129 | Change A to A:link
130 | Highlight nearly all links
131 |
132 | JUSH 1.0.3:
133 | Highlight PHP also in 'tag'
134 | Decode & as last
135 | Customizable tab width
136 | Preserve tabs in IE
137 | Allow short_open_tag
138 | Add for IE
139 |
140 | JUSH 1.0.2:
141 | Recognize functions in mysql_query()
142 | Recognize PHP function language constructs without parentheses
143 | Add style for backticks
144 |
145 | JUSH 1.0.1:
146 | Fixes highlight_tag with jush-lang
147 | Uses
in highlight_tag
148 | More MySQL commands, links CSS at-rules
149 | Adds A:hover style
150 | Updates installation instructions
151 |
152 | JUSH 1.0.0:
153 | Highlight HTML, CSS, JS, PHP and SQL code embedded into each other
154 | Provide links to the documentation for all supported languages
155 |
--------------------------------------------------------------------------------
/compile.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JUSH - Demo
5 |
6 |
7 |
8 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/demo.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | jush.style('jush.css');
3 | jush.style('jush-dark.css', '(prefers-color-scheme: dark)');
4 | jush.create_links = 'target="_blank"';
5 | var source = document.getElementById('source');
6 | var value = '';
7 | if (!source.value && location.hash) {
8 | source.value = location.hash.substr(1);
9 | }
10 | source.oninput = function highlight() {
11 | if (value == source.value) {
12 | return;
13 | }
14 | value = source.value;
15 | var result = document.getElementById('result');
16 | var language = source.form['language'].value;
17 | result.className = 'jush-' + language;
18 | result.innerHTML = jush.highlight(language, source.value);
19 | };
20 | source.form['language'].onchange = function () {
21 | value = '';
22 | source.oninput();
23 | }
24 | source.oninput();
25 | })();
26 |
--------------------------------------------------------------------------------
/jquery.jush.js:
--------------------------------------------------------------------------------
1 | (function ($) {
2 |
3 | // include jush.js here
4 |
5 | $.jush = jush;
6 |
7 | /** Highlight element content
8 | * @param [string]
9 | * @return jQuery
10 | * @this jQuery
11 | */
12 | $.fn.jush = function (language) {
13 | return this.each(function () {
14 | var lang = language;
15 | var $this = $(this);
16 | if (!lang) {
17 | var match = /(^|\s)(?:jush-|language-)(\S+)/.exec($this.attr('class'));
18 | lang = (match ? match[2] : 'htm');
19 | }
20 | $this.html(jush.highlight(lang, $this.text()));
21 | });
22 | }
23 |
24 | })(jQuery);
25 |
--------------------------------------------------------------------------------
/json.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JSON
5 |
6 |
7 |
8 |
16 |
17 |
22 |
23 |
24 |
29 |
--------------------------------------------------------------------------------
/jush-dark.css:
--------------------------------------------------------------------------------
1 | .jush {
2 | --text-color: #ccc;
3 | --bg-color: #111;
4 | --php-color: #cc9;
5 | --string-color: #e6e;
6 | --string-plain-color: #e6e;
7 | --keyword-color: #acf;
8 | --identifier-color: #f88;
9 | --value-color: #e6e;
10 | --number-color: #0c0;
11 | --attribute-color: #3cc;
12 | --js-bg-color: #036;
13 | --css-bg-color: #404000;
14 | --php-bg-color: #520;
15 | --php-sql-bg-color: #404000;
16 | }
17 |
--------------------------------------------------------------------------------
/jush-help.wsf:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
71 |
72 |
--------------------------------------------------------------------------------
/jush.css:
--------------------------------------------------------------------------------
1 | .jush {
2 | --text-color: #000;
3 | --bg-color: #fff;
4 | --php-color: #003;
5 | --string-color: green;
6 | --string-plain-color: #009F00;
7 | --keyword-color: navy;
8 | --identifier-color: red;
9 | --value-color: purple;
10 | --number-color: #007F7F;
11 | --attribute-color: teal;
12 | --js-bg-color: #f0f0ff;
13 | --css-bg-color: #ffffe0;
14 | --php-bg-color: #fff0f0;
15 | --php-sql-bg-color: #ffbbb0;
16 | }
17 |
18 | .jush { color: var(--text-color); }
19 | .jush-htm_com, .jush-com, .jush-com_code, .jush-one, .jush-php_doc, .jush-php_com, .jush-php_one, .jush-js_one, .jush-js_doc { color: gray; }
20 | .jush-php, .jush-php_new, .jush-php_fun { color: var(--php-color); background-color: var(--php-bg-color); }
21 | .jush-php_quo, .jush-php_eot, .jush-js_bac { color: var(--string-color); }
22 | .jush-php_apo, .jush-quo, .jush-quo_one, .jush-apo, .jush-sql_apo, .jush-sqlite_apo, .jush-sql_quo, .jush-sql_eot { color: var(--string-plain-color); }
23 | .jush-php_quo_var, .jush-php_var, .jush-sql_var, .jush-js_bac .jush-js { font-style: italic; }
24 | .jush-php_apo .jush-php_quo_var, .jush-php_apo .jush-php_var { font-style: normal; }
25 | .jush-php_halt2 { background-color: var(--bg-color); color: var(--text-color); }
26 | .jush-tag_css, .jush-att_css .jush-att_quo, .jush-att_css .jush-att_apo, .jush-att_css .jush-att_val { color: var(--text-color); background-color: var(--css-bg-color); }
27 | .jush-tag_js, .jush-att_js .jush-att_quo, .jush-att_js .jush-att_apo, .jush-att_js .jush-att_val, .jush-css_js { color: var(--text-color); background-color: var(--js-bg-color); }
28 | .jush-tag, .jush-xml_tag { color: var(--keyword-color); }
29 | .jush-att, .jush-xml_att, .jush-att_js, .jush-att_css, .jush-att_http { color: var(--attribute-color); }
30 | .jush-att_quo, .jush-att_apo, .jush-att_val { color: var(--value-color); }
31 | .jush-ent { color: var(--value-color); }
32 | .jush-js_key, .jush-js_key .jush-quo, .jush-js_key .jush-apo { color: var(--value-color); }
33 | .jush-js_reg { color: var(--keyword-color); }
34 | .jush-php_sql .jush-php_quo, .jush-php_sql .jush-php_apo,
35 | .jush-php_sqlite .jush-php_quo, .jush-php_sqlite .jush-php_apo,
36 | .jush-php_pgsql .jush-php_quo, .jush-php_pgsql .jush-php_apo,
37 | .jush-php_mssql .jush-php_quo, .jush-php_mssql .jush-php_apo,
38 | .jush-php_oracle .jush-php_quo, .jush-php_oracle .jush-php_apo { background-color: var(--php-sql-bg-color); }
39 | .jush-bac, .jush-php_bac, .jush-bra, .jush-mssql_bra, .jush-sqlite_quo { color: var(--identifier-color); }
40 | .jush-num, .jush-clr { color: var(--number-color); }
41 |
42 | .jush a { color: var(--keyword-color); }
43 | .jush a.jush-help { cursor: help; }
44 | .jush-sql a, .jush-sql_code a, .jush-sqlite a, .jush-pgsql a, .jush-mssql a, .jush-oracle a, .jush-simpledb a { font-weight: bold; }
45 | .jush-php_sql .jush-php_quo a, .jush-php_sql .jush-php_apo a { font-weight: normal; }
46 | .jush-tag a, .jush-att a, .jush-apo a, .jush-quo a, .jush-php_apo a, .jush-php_quo a, .jush-php_eot2 a { color: inherit; }
47 | a.jush-custom:link, a.jush-custom:visited { font-weight: normal; color: inherit; }
48 |
49 | .jush p { margin: 0; }
50 |
--------------------------------------------------------------------------------
/modules/jush-autocomplete-sql.js:
--------------------------------------------------------------------------------
1 | /** Get callback for autocompletition
2 | * @param string escaped empty identifier, e.g. `` for MySQL or [] for MS SQL
3 | * @param Object> keys are table names, values are lists of columns
4 | * @return Function see autocomplete()
5 | */
6 | jush.autocompleteSql = function (esc, tablesColumns) {
7 | /**
8 | * key: regular expression; ' ' will be expanded to '\\s+', '\\w' to esc[0]+'?\\w'+esc[1]+'?', '$' will be appended
9 | * value: list of autocomplete words; '?' means to not use the word if it's already in the current query
10 | */
11 | const keywordsDefault = {
12 | '^': ['SELECT', 'INSERT INTO', 'UPDATE', 'DELETE FROM', 'EXPLAIN'],
13 | '^EXPLAIN ': ['SELECT'],
14 | '^INSERT ': ['IGNORE'],
15 | '^INSERT .+\\) ': ['?VALUES', 'ON DUPLICATE KEY UPDATE'],
16 | '^UPDATE \\w+ ': ['SET'],
17 | '^UPDATE \\w+ SET .+ ': ['?WHERE'],
18 | '^DELETE FROM \\w+ ': ['WHERE'],
19 | ' JOIN \\w+ ': ['ON', 'USING'],
20 | '\\bSELECT ': ['*', 'DISTINCT'],
21 | '\\bSELECT .+ ': ['?FROM'],
22 | '\\bSELECT (?!.* (WHERE|GROUP BY|HAVING|ORDER BY|LIMIT) ).+ FROM .+ ': ['INNER JOIN', 'LEFT JOIN', '?WHERE'],
23 | '\\bSELECT (?!.* (HAVING|ORDER BY|LIMIT|OFFSET) ).+ FROM .+ ': ['?GROUP BY'],
24 | '\\bSELECT (?!.* (ORDER BY|LIMIT|OFFSET) ).+ FROM .+ ': ['?HAVING'],
25 | '\\bSELECT (?!.* (LIMIT|OFFSET) ).+ FROM .+ ': ['?ORDER BY'], // this matches prefixes without LIMIT|OFFSET and offers ORDER BY if it's not already used in prefix or suffix
26 | '\\bSELECT (?!.* (OFFSET) ).+ FROM .+ ': ['?LIMIT', '?OFFSET'],
27 | ' ORDER BY (?!.* (LIMIT|OFFSET) ).+ ': ['DESC'],
28 | };
29 |
30 | /** Get list of strings for autocompletion
31 | * @param string
32 | * @param string
33 | * @param string
34 | * @return Object keys are words, values are offsets
35 | */
36 | function autocomplete(state, before, after) {
37 | if (/^(one|com|sql_apo|sqlite_apo)$/.test(state)) {
38 | return {};
39 | }
40 | before = before
41 | .replace(/\/\*.*?\*\/|\s--[^\n]*|'[^']+'/s, '') // strip comments and strings
42 | .replace(/.*;/s, '') // strip previous query
43 | .trimStart()
44 | ;
45 | after = after.replace(/;.*/s, ''); // strip next query
46 | const query = before + after;
47 | const allTables = Object.keys(tablesColumns);
48 | const usedTables = findTables(query); // tables used by the current query
49 | const uniqueColumns = {};
50 | for (const table of Object.values(usedTables)) {
51 | for (const column of tablesColumns[table]) {
52 | uniqueColumns[column] = 0;
53 | }
54 | }
55 | const columns = Object.keys(uniqueColumns);
56 | if (columns.length > 50) {
57 | columns.length = 0;
58 | }
59 | if (Object.keys(usedTables).length > 1) {
60 | for (const alias in usedTables) {
61 | columns.push(alias + '.');
62 | }
63 | }
64 |
65 | const preferred = {
66 | '\\b(FROM|INTO|^UPDATE|JOIN) ': allTables, // all tables including the current ones (self-join)
67 | '\\b(^INSERT|USING) [^(]*\\(([^)]+, )?': columns, // offer columns right after '(' or after ','
68 | '(^UPDATE .+ SET| DUPLICATE KEY UPDATE| BY) (.+, )?': columns,
69 | ' (WHERE|HAVING|AND|OR|ON|=) ': columns,
70 | };
71 | keywordsDefault['\\bSELECT( DISTINCT)? (?!.* FROM )(.+, )?'] = columns; // this is not in preferred because we prefer '*'
72 |
73 | const context = before.replace(escRe('[\\w`]+$'), ''); // in 'UPDATE tab.`co', context is 'UPDATE tab.'
74 | before = before.replace(escRe('.*[^\\w`]', 's'), ''); // in 'UPDATE tab.`co', before is '`co'
75 |
76 | const thisColumns = []; // columns in the current table ('table.')
77 | const match = context.match(escRe('`?(\\w+)`?\\.$'));
78 | if (match) {
79 | let table = match[1];
80 | if (!tablesColumns[table]) {
81 | table = usedTables[table];
82 | }
83 | if (tablesColumns[table]) {
84 | thisColumns.push(...tablesColumns[table]);
85 | preferred['\\.'] = thisColumns;
86 | }
87 | }
88 |
89 | if (query.includes(esc[0]) && !/^\w/.test(before)) { // if there's any ` in the query, use ` everywhere unless the user starts typing letters
90 | allTables.forEach(addEsc);
91 | columns.forEach(addEsc);
92 | thisColumns.forEach(addEsc);
93 | }
94 |
95 | const ac = {};
96 | for (const keywords of [preferred, keywordsDefault]) {
97 | for (const re in keywords) {
98 | if (context.match(escRe(re.replace(/ /g, '\\s+').replace(/\\w\+/g, '`?\\w+`?') + '$', 'is'))) {
99 | for (let keyword of keywords[re]) {
100 | if (keyword[0] == '?') {
101 | keyword = keyword.substring(1);
102 | if (query.match(new RegExp('\\s+' + keyword + '\\s+', 'i'))) {
103 | continue;
104 | }
105 | }
106 | if (keyword.length != before.length && keyword.substring(0, before.length).toUpperCase() == before.toUpperCase()) {
107 | const isCol = (keywords[re] == columns || keywords[re] == thisColumns);
108 | ac[keyword + (isCol ? '' : ' ')] = before.length;
109 | }
110 | }
111 | }
112 | }
113 | }
114 |
115 | return ac;
116 | }
117 |
118 | function addEsc(val, key, array) {
119 | array[key] = esc[0] + val.replace(/\.?$/, esc[1] + '$&');
120 | }
121 |
122 | /** Change odd ` to esc[0], even to esc[1] */
123 | function escRe(re, flags) {
124 | let i = 0;
125 | return new RegExp(re.replace(/`/g, () => (esc[0] == '[' ? '\\' : '') + esc[i++ % 2]), flags);
126 | }
127 |
128 | /** @return Object key is alias, value is actual table */
129 | function findTables(query) {
130 | const matches = query.matchAll(escRe('\\b(FROM|JOIN|INTO|UPDATE)\\s+(\\w+|`.+?`)((\\s+AS)?\\s+((?!(LEFT|INNER|JOIN|ON|USING|WHERE|GROUP|HAVING|ORDER|LIMIT)\\b)\\w+|`.+?`))?', 'gi')); //! handle `abc``def`
131 | const result = {};
132 | for (const match of matches) {
133 | const table = match[2].replace(escRe('^`|`$', 'g'), '');
134 | const alias = (match[5] ? match[5].replace(escRe('^`|`$', 'g'), '') : table);
135 | if (tablesColumns[table]) {
136 | result[alias] = table;
137 | }
138 | }
139 | if (!Object.keys(result).length) {
140 | for (const table in tablesColumns) {
141 | result[table] = table;
142 | }
143 | }
144 | return result;
145 | }
146 |
147 | // we open the autocomplete on word character, space, '(', '.' and '`'; textarea also triggers it on Backspace and Ctrl+Space
148 | autocomplete.openBy = escRe('^[\\w`(. ]$'); //! ignore . in 1.23
149 |
150 | return autocomplete;
151 | };
152 |
--------------------------------------------------------------------------------
/modules/jush-cnf.js:
--------------------------------------------------------------------------------
1 | jush.tr.cnf = { quo_one: /"/, one: /#/, cnf_http: /((?:^|\n)\s*)(RequestHeader|Header|CacheIgnoreHeaders)([ \t]+|$)/i, cnf_php: /((?:^|\n)\s*)(PHPIniDir)([ \t]+|$)/i, cnf_phpini: /((?:^|\n)\s*)(php_value|php_flag|php_admin_value|php_admin_flag)([ \t]+|$)/i };
2 | jush.tr.quo_one = { esc: /\\/, _1: /"|(?=\n)/ };
3 | jush.tr.cnf_http = { apo: /'/, quo: /"/, _1: /(?=\n)/ };
4 | jush.tr.cnf_php = { _1: /()/ };
5 | jush.tr.cnf_phpini = { cnf_phpini_val: /[ \t]/ };
6 | jush.tr.cnf_phpini_val = { apo: /'/, quo: /"/, _2: /(?=\n)/ };
7 |
8 | jush.urls.cnf_http = 'https://httpd.apache.org/docs/current/mod/$key.html#$val';
9 | jush.urls.cnf_php = 'https://www.php.net/$key';
10 | jush.urls.cnf_phpini = 'https://www.php.net/configuration.changes#$key';
11 | jush.urls.cnf = ['https://httpd.apache.org/docs/current/mod/$key.html#$1',
12 | 'beos', 'core', 'mod_actions', 'mod_alias', 'mod_auth_basic', 'mod_auth_digest', 'mod_authn_alias', 'mod_authn_anon', 'mod_authn_dbd', 'mod_authn_dbm', 'mod_authn_default', 'mod_authn_file', 'mod_authnz_ldap', 'mod_authz_dbm', 'mod_authz_default', 'mod_authz_groupfile', 'mod_authz_host', 'mod_authz_owner', 'mod_authz_user', 'mod_autoindex', 'mod_cache', 'mod_cern_meta', 'mod_cgi', 'mod_cgid', 'mod_dav', 'mod_dav_fs', 'mod_dav_lock', 'mod_dbd', 'mod_deflate', 'mod_dir', 'mod_disk_cache', 'mod_dumpio', 'mod_echo', 'mod_env', 'mod_example', 'mod_expires', 'mod_ext_filter', 'mod_file_cache', 'mod_filter', 'mod_charset_lite', 'mod_ident', 'mod_imagemap', 'mod_include', 'mod_info', 'mod_isapi', 'mod_ldap', 'mod_log_config', 'mod_log_forensic', 'mod_mem_cache', 'mod_mime', 'mod_mime_magic', 'mod_negotiation', 'mod_nw_ssl', 'mod_proxy', 'mod_rewrite', 'mod_setenvif', 'mod_so', 'mod_speling', 'mod_ssl', 'mod_status', 'mod_substitute', 'mod_suexec', 'mod_userdir', 'mod_usertrack', 'mod_version', 'mod_vhost_alias', 'mpm_common', 'mpm_netware', 'mpm_winnt', 'prefork'
13 | ];
14 |
15 | jush.links.cnf_http = { 'mod_cache': /CacheIgnoreHeaders/i, 'mod_headers': /.+/ };
16 | jush.links.cnf_php = { 'configuration.file': /.+/ };
17 | jush.links.cnf_phpini = { 'configuration.changes.apache': /.+/ };
18 |
19 | jush.links2.cnf = /((?:^|\n)\s*(?:<)?)(MaxRequestsPerThread|(AcceptFilter|AcceptPathInfo|AccessFileName|AddDefaultCharset|AddOutputFilterByType|AllowEncodedSlashes|AllowOverride|AuthName|AuthType|CGIMapExtension|ContentDigest|DefaultType|Directory|DirectoryMatch|DocumentRoot|EnableMMAP|EnableSendfile|ErrorDocument|ErrorLog|FileETag|Files|FilesMatch|ForceType|HostnameLookups|IfDefine|IfModule|Include|KeepAlive|KeepAliveTimeout|Limit|LimitExcept|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine|LimitXMLRequestBody|Location|LocationMatch|LogLevel|MaxKeepAliveRequests|NameVirtualHost|Options|Require|RLimitCPU|RLimitMEM|RLimitNPROC|Satisfy|ScriptInterpreterSource|ServerAdmin|ServerAlias|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|SetHandler|SetInputFilter|SetOutputFilter|TimeOut|TraceEnable|UseCanonicalName|UseCanonicalPhysicalPort|VirtualHost)|(Action|Script)|(Alias|AliasMatch|Redirect|RedirectMatch|RedirectPermanent|RedirectTemp|ScriptAlias|ScriptAliasMatch)|(AuthBasicAuthoritative|AuthBasicProvider)|(AuthDigestAlgorithm|AuthDigestDomain|AuthDigestNcCheck|AuthDigestNonceFormat|AuthDigestNonceLifetime|AuthDigestProvider|AuthDigestQop|AuthDigestShmemSize)|(AuthnProviderAlias)|(Anonymous|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID|Anonymous_VerifyEmail)|(AuthDBDUserPWQuery|AuthDBDUserRealmQuery)|(AuthDBMType|AuthDBMUserFile)|(AuthDefaultAuthoritative)|(AuthUserFile)|(AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPRemoteUserAttribute|AuthLDAPRemoteUserIsDN|AuthLDAPUrl|AuthzLDAPAuthoritative)|(AuthDBMGroupFile|AuthzDBMAuthoritative|AuthzDBMType)|(AuthzDefaultAuthoritative)|(AuthGroupFile|AuthzGroupFileAuthoritative)|(Allow|Deny|Order)|(AuthzOwnerAuthoritative)|(AuthzUserAuthoritative)|(AddAlt|AddAltByEncoding|AddAltByType|AddDescription|AddIcon|AddIconByEncoding|AddIconByType|DefaultIcon|HeaderName|IndexHeadInsert|IndexIgnore|IndexOptions|IndexOrderDefault|IndexStyleSheet|ReadmeName)|(CacheDefaultExpire|CacheDisable|CacheEnable|CacheIgnoreCacheControl|CacheIgnoreNoLastMod|CacheIgnoreQueryString|CacheLastModifiedFactor|CacheMaxExpire|CacheStoreNoStore|CacheStorePrivate)|(MetaDir|MetaFiles|MetaSuffix)|(ScriptLog|ScriptLogBuffer|ScriptLogLength)|(ScriptSock)|(Dav|DavDepthInfinity|DavMinTimeout)|(DavLockDB)|(DavGenericLockDB)|(DBDExptime|DBDKeep|DBDMax|DBDMin|DBDParams|DBDPersist|DBDPrepareSQL|DBDriver)|(DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateMemLevel|DeflateWindowSize)|(DirectoryIndex|DirectorySlash)|(CacheDirLength|CacheDirLevels|CacheMaxFileSize|CacheMinFileSize|CacheRoot)|(DumpIOInput|DumpIOLogLevel|DumpIOOutput)|(ProtocolEcho)|(PassEnv|SetEnv|UnsetEnv)|(Example)|(ExpiresActive|ExpiresByType|ExpiresDefault)|(ExtFilterDefine|ExtFilterOptions)|(CacheFile|MMapFile)|(FilterChain|FilterDeclare|FilterProtocol|FilterProvider|FilterTrace)|(CharsetDefault|CharsetOptions|CharsetSourceEnc)|(IdentityCheck|IdentityCheckTimeout)|(ImapBase|ImapDefault|ImapMenu)|(SSIEnableAccess|SSIEndTag|SSIErrorMsg|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|XBitHack)|(AddModuleInfo)|(ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer)|(LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionTimeout|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPSharedCacheFile|LDAPSharedCacheSize|LDAPTrustedClientCert|LDAPTrustedGlobalCert|LDAPTrustedMode|LDAPVerifyServerCert)|(BufferedLogs|CookieLog|CustomLog|LogFormat|TransferLog)|(ForensicLog)|(MCacheMaxObjectCount|MCacheMaxObjectSize|MCacheMaxStreamingBuffer|MCacheMinObjectSize|MCacheRemovalAlgorithm|MCacheSize)|(AddCharset|AddEncoding|AddHandler|AddInputFilter|AddLanguage|AddOutputFilter|AddType|DefaultLanguage|ModMimeUsePathInfo|MultiviewsMatch|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|TypesConfig)|(MimeMagicFile)|(CacheNegotiatedDocs|ForceLanguagePriority|LanguagePriority)|(NWSSLTrustedCerts|NWSSLUpgradeable|SecureListen)|(AllowCONNECT|BalancerMember|NoProxy|Proxy|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyFtpDirCharset|ProxyIOBufferSize|ProxyMatch|ProxyMaxForwards|ProxyPass|ProxyPassInterpolateEnv|ProxyPassMatch|ProxyPassReverse|ProxyPassReverseCookieDomain|ProxyPassReverseCookiePath|ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxySet|ProxyStatus|ProxyTimeout|ProxyVia)|(RewriteBase|RewriteCond|RewriteEngine|RewriteLock|RewriteLog|RewriteLogLevel|RewriteMap|RewriteOptions|RewriteRule)|(BrowserMatch|BrowserMatchNoCase|SetEnvIf|SetEnvIfNoCase)|(LoadFile|LoadModule)|(CheckCaseOnly|CheckSpelling)|(SSLCACertificateFile|SSLCACertificatePath|SSLCADNRequestFile|SSLCADNRequestPath|SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLCryptoDevice|SSLEngine|SSLHonorCipherOrder|SSLMutex|SSLOptions|SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCipherSuite|SSLProxyEngine|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRequire|SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLUserName|SSLVerifyClient|SSLVerifyDepth)|(ExtendedStatus|SeeRequestTail)|(Substitute)|(SuexecUserGroup)|(UserDir)|(CookieDomain|CookieExpires|CookieName|CookieStyle|CookieTracking)|(IfVersion)|(VirtualDocumentRoot|VirtualDocumentRootIP|VirtualScriptAlias|VirtualScriptAliasIP)|(AcceptMutex|ChrootDir|CoreDumpDirectory|EnableExceptionHook|GracefulShutdownTimeout|Group|Listen|ListenBackLog|LockFile|MaxClients|MaxMemFree|MaxRequestsPerChild|MaxSpareThreads|MinSpareThreads|PidFile|ReceiveBufferSize|ScoreBoardFile|SendBufferSize|ServerLimit|StartServers|StartThreads|ThreadLimit|ThreadsPerChild|ThreadStackSize|User)|(MaxThreads)|(Win32DisableAcceptEx)|(MaxSpareServers|MinSpareServers))(\b)/gi;
20 |
--------------------------------------------------------------------------------
/modules/jush-css.js:
--------------------------------------------------------------------------------
1 | jush.tr.css = { php: jush.php, quo: /"/, apo: /'/, com: /\/\*/, css_at: /(@)([^;\s{]+)/, css_pro: /\{/, _2: /(<)(\/style)(>)/i };
2 | jush.tr.css_at = { php: jush.php, quo: /"/, apo: /'/, com: /\/\*/, css_at2: /\{/, _1: /;/ };
3 | jush.tr.css_at2 = { php: jush.php, quo: /"/, apo: /'/, com: /\/\*/, css_at: /@/, css_pro: /\{/, _2: /}/ };
4 | jush.tr.css_pro = { php: jush.php, com: /\/\*/, css_val: /(\s*)([-\w]+)(\s*:)/, _1: /}/ }; //! misses e.g. margin/*-left*/:
5 | jush.tr.css_val = { php: jush.php, quo: /"/, apo: /'/, css_js: /expression\s*\(/i, com: /\/\*/, clr: /#/, num: /[-+]?[0-9]*\.?[0-9]+(?:em|ex|px|in|cm|mm|pt|pc|%)?/, _2: /}/, _1: /;|$/ };
6 | jush.tr.css_js = { php: jush.php, css_js: /\(/, _1: /\)/ };
7 | jush.tr.clr = { _1: /(?=[^a-fA-F0-9])/ };
8 |
9 | jush.urls.css_at = 'https://developer.mozilla.org/en-US/docs/Web/CSS/$key';
10 | jush.urls.css_val = jush.urls.css_at;
11 | jush.urls.css = [jush.urls.css_at,
12 | '_colon_$1', '_doublecolon_$1'
13 | ];
14 |
15 | jush.links.css_at = {
16 | '@$val': /^(charset|color-profile|container|counter-style|document|font-face|font-feature-values|font-palette-values|import|keyframes|layer|media|namespace|page|position-try|property|scope|starting-style|supports|view-transition)$/i
17 | };
18 | jush.links.css_val = {
19 | '$val': /^(accent-color|align-(content|items|self)|alignment-baseline|all|anchor-name|animation(-composition|-delay|-direction|-duration|-fill-mode|-iteration-count|-name|-play-state|-range(-end|-start)?|-timeline|-timing-function)?|appearance|aspect-ratio|backdrop-filter|backface-visibility|background(-attachment|-blend-mode|-clip|-color|-image|-origin|-position(-x|-y)?|-repeat|-size)?|block-size|border(-block(-color|-end(-color|-style|-width)?|-start(-color|-style|-width)?|-style|-width)?|-bottom(-color|-left-radius|-right-radius|-style|-width)?|-collapse|-color|-end-end-radius|-end-start-radius|-image(-outset|-repeat|-slice|-source|-width)?|-inline(-color|-end(-color|-style|-width)?|-start(-color|-style|-width)?|-style|-width)?|-left(-color|-style|-width)?|-radius|-right(-color|-style|-width)?|-spacing|-start-end-radius|-start-start-radius|-style|-top(-color|-left-radius|-right-radius|-style|-width)?|-width)?|bottom|box-(align|decoration-break|direction|flex(-group)?|lines|ordinal-group|orient|pack|shadow|sizing)|break-(after|before|inside)|caption-side|caret-color|clear|clip(-path|-rule)?|color(-interpolation(-filters)?|-scheme)?|column-(count|fill|gap|rule(-color|-style|-width)?|span|width)|columns|contain(-intrinsic-block-size|-intrinsic-height|-intrinsic-inline-size|-intrinsic-size|-intrinsic-width)?|container(-name|-type)?|content(-visibility)?|counter-(increment|reset|set)|cursor|cx|cy|d|direction|display|dominant-baseline|empty-cells|field-sizing|fill(-opacity|-rule)?|filter|flex(-basis|-direction|-flow|-grow|-shrink|-wrap)?|float|flood-(color|opacity)|font(-family|-feature-settings|-kerning|-language-override|-optical-sizing|-palette|-size(-adjust)?|-smooth|-stretch|-style|-synthesis(-position|-small-caps|-style|-weight)?|-variant(-alternates|-caps|-east-asian|-emoji|-ligatures|-numeric|-position)?|-variation-settings|-weight)?|forced-color-adjust|gap|grid(-area|-auto-columns|-auto-flow|-auto-rows|-column(-end|-start)?|-row(-end|-start)?|-template(-areas|-columns|-rows)?)?|hanging-punctuation|height|hyphenate-(character|limit-chars)|hyphens|image-(orientation|rendering|resolution)|initial-letter|inline-size|inset(-block(-end|-start)?|-inline(-end|-start)?)?|interpolate-size|isolation|justify-(content|items|self)|left|letter-spacing|lighting-color|line-(break|clamp|height(-step)?)|list-style(-image|-position|-type)?|margin(-block(-end|-start)?|-bottom|-inline(-end|-start)?|-left|-right|-top|-trim)?|marker(-end|-mid|-start)?|mask(-border(-mode|-outset|-repeat|-slice|-source|-width)?|-clip|-composite|-image|-mode|-origin|-position|-repeat|-size|-type)?|math-(depth|shift|style)|max-(block-size|height|inline-size|width)|min-(block-size|height|inline-size|width)|mix-blend-mode|object-(fit|position)|offset(-anchor|-distance|-path|-position|-rotate)?|opacity|order|orphans|outline(-color|-offset|-style|-width)?|overflow(-anchor|-block|-clip-margin|-inline|-wrap|-x|-y)?|overlay|overscroll-behavior(-block|-inline|-x|-y)?|padding(-block(-end|-start)?|-bottom|-inline(-end|-start)?|-left|-right|-top)?|page(-break-after|-break-before|-break-inside)?|paint-order|perspective(-origin)?|place-(content|items|self)|pointer-events|position(-anchor|-area|-try(-fallbacks|-order)?|-visibility)?|print-color-adjust|quotes|r|resize|right|rotate|row-gap|ruby-(align|position)|rx|ry|scale|scroll-(behavior|margin(-block(-end|-start)?|-bottom|-inline(-end|-start)?|-left|-right|-top)?|marker-group|padding(-block(-end|-start)?|-bottom|-inline(-end|-start)?|-left|-right|-top)?|snap-(align|stop|type)|timeline(-axis|-name)?)|scrollbar-(color|gutter|width)|shape-(image-threshold|margin|outside|rendering)|speak-as|stop-(color|opacity)|stroke(-dasharray|-dashoffset|-linecap|-linejoin|-miterlimit|-opacity|-width)?|tab-size|table-layout|text-(align(-last)?|anchor|box(-edge|-trim)?|combine-upright|decoration(-color|-line|-skip(-ink)?|-style|-thickness)?|emphasis(-color|-position|-style)?|indent|justify|orientation|overflow|rendering|shadow|size-adjust|spacing-trim|transform|underline-(offset|position)|wrap(-mode|-style)?)|timeline-scope|top|touch-action|transform(-box|-origin|-style)?|transition(-behavior|-delay|-duration|-property|-timing-function)?|translate|unicode-bidi|user-(modify|select)|vector-effect|vertical-align|view-(timeline(-axis|-inset|-name)?|transition-name)|visibility|white-space(-collapse)?|widows|width|will-change|word-(break|spacing)|writing-mode|x|y|z-index|zoom)$/i
20 | };
21 |
22 | jush.links2.css = /(:)(?/ };
3 | jush.tr.ent = { php: jush.php, _1: /[;\s]/ };
4 | jush.tr.tag = { php: jush.php, att_css: /(\s*)(style)(\s*=\s*|$)/i, att_js: /(\s*)(on[-\w]+)(\s*=\s*|$)/i, att_http: /(\s*)(http-equiv)(\s*=\s*|$)/i, att: /(\s*)([-\w]+)()/, _1: />/ };
5 | jush.tr.tag_css = { php: jush.php, att: /(\s*)([-\w]+)()/, css: />/ };
6 | jush.tr.tag_js = { php: jush.php, att: /(\s*)([-\w]+)()/, js: />/ };
7 | jush.tr.att = { php: jush.php, att_quo: /\s*=\s*"/, att_apo: /\s*=\s*'/, att_val: /\s*=\s*/, _1: /()/ };
8 | jush.tr.att_css = { php: jush.php, att_quo: /"/, att_apo: /'/, att_val: /\s*/ };
9 | jush.tr.att_js = { php: jush.php, att_quo: /"/, att_apo: /'/, att_val: /\s*/ };
10 | jush.tr.att_http = { php: jush.php, att_quo: /"/, att_apo: /'/, att_val: /\s*/ };
11 | jush.tr.att_quo = { php: jush.php, _2: /"/ };
12 | jush.tr.att_apo = { php: jush.php, _2: /'/ };
13 | jush.tr.att_val = { php: jush.php, _2: /(?=>|\s)/ };
14 | jush.tr.xml = { php: jush.php, htm_com: / &', '<a href="">HTML</a> <!-- comment --> &'],
4 | ['htm', '', '<a href="" onclick="alert(\'\');">'],
5 | ['htm', '', '<a href="" style="color: red;">'],
6 | ['htm', ' SCRIPT', '<script type="text/javascript">alert("");</script> SCRIPT'],
7 | ['htm', ' STYLE', '<style type="text/css">a { color: red; }</style> STYLE'],
8 | ['htm', '', '<a href=index.php title=\'Quoting\'>'],
9 | ['htm', '', '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'],
10 |
11 | ['tag', 'title=""', 'title=""'],
12 |
13 | ['xml', '', '<rss version="0.91">'],
14 |
15 | ['css', 'a { color: red } /* comment */ b { font-weight: bold; color: black; }', 'a { color: red } /* </style> comment */ b { font-weight: bold; color: black; }'],
16 |
17 | ['js', 'if (/.+@.+/.test(email)) { /* */ alert(email); }', 'if (/.+@.+/.test(email)) { /* </script> */ alert(email); }'],
18 | ['js', '/[/\\]]/.test("/");', '/[/\\]]/.test("/");'],
19 | ['js', '{ a: [ 1, { "b": "c" }, 3 ], \'d\': 4 }', '{ a: [ 1, { "b": "c" }, 3 ], \'d\': 4 }'],
20 |
21 | ['htm', '";', '<?php echo "<a href=\'$href\'>";'],
22 | ['htm', '="";log()?>', '<?="<a>";log()?><b>'],
23 | ['php', 'echo "Test" . $_SERVER["PHP_SELF"]; /* ?> comment */ mysql_free_result($result);', 'echo "Test" . $_SERVER["PHP_SELF"]; /* ?> comment */ mysql_free_result($result);'],
24 | ['php', 'mysql_query("SELECT 1");', 'mysql_query("SELECT 1");'],
25 | ['php', '/** @return bool */ ini_set("display_errors", true);', '/** @return bool */ ini_set("display_errors", true);'],
26 | ['php', 'header("HTTP/1.1 404 Not Found");', 'header("HTTP/1.1 404 Not Found");'],
27 | ['php', 'header("Content-Type: text/html; charset=utf-8");', 'header("Content-Type: text/html; charset=utf-8");'],
28 | ['php', 'mail("", "", "", "From: info@example.com\\nMIME-Version: 1.0");', 'mail("", "", "", "From: info@example.com\\nMIME-Version: 1.0");'],
29 |
30 | ['sql', 'SELECT 1, \'MySQL\'', 'SELECT 1, \'MySQL\''],
31 | ['sqlite', 'SELECT 1, \'SQLite\'', 'SELECT 1, \'SQLite\''],
32 | ['pgsql', 'SELECT 1, \'PostgreSQL\'', 'SELECT 1, \'PostgreSQL\''],
33 | ['mssql', 'SELECT 1, \'MS SQL\'', 'SELECT 1, \'MS SQL\''],
34 | ['oracle', 'SELECT 1, \'Oracle\'', 'SELECT 1, \'Oracle\''],
35 |
36 | ['sql', 'SET foreign_key_checks = 0', 'SET foreign_key_checks = 0'],
37 | ['sqlstatus', 'Qcache_hits', 'Qcache_hits'],
38 |
39 | ['cnf', 'Listen 80\nphp_flag display_errors On', 'Listen 80\nphp_flag display_errors On']
40 | ];
41 |
42 | tests.highlight_html = [
43 | ['htm', '<area href="">', '<area href="">']
44 | ];
45 |
46 | var html = [];
47 |
48 | for (var callback in tests) {
49 | for (var i = 0; i < tests[callback].length; i++) {
50 | var test = tests[callback][i];
51 | var highlighted = jush[callback](test[0], test[1]);
52 | if (highlighted !== test[2]) {
53 | console.log(highlighted.replace(/['\\]/g, '\\$&'));
54 | html.push('error:');
55 | }
56 | html.push('' + highlighted + '
');
57 | }
58 | }
59 |
60 | document.getElementById('result').innerHTML = html.join('\n');
61 |
--------------------------------------------------------------------------------
/textarea.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JUSH textarea
5 |
6 |
7 |
8 | SQL
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
25 |
--------------------------------------------------------------------------------