├── .gitignore ├── changes.txt ├── compile.php ├── composer.json ├── demo-dark.css ├── demo.html ├── demo.js ├── jquery.jush.js ├── json.php ├── jush-api.js ├── jush-dark.css ├── jush-help.wsf ├── jush.css ├── modules ├── jush-autocomplete-sql.js ├── jush-cnf.js ├── jush-css.js ├── jush-htm.js ├── jush-http.js ├── jush-js.js ├── jush-mssql.js ├── jush-oracle.js ├── jush-pgsql.js ├── jush-php.js ├── jush-simpledb.js ├── jush-sql.js ├── jush-sqlite.js ├── jush-textarea.js ├── jush-txt.js └── jush.js ├── readme.html ├── sql.html ├── tests.html ├── tests.js └── textarea.html /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | jush.js 3 | -------------------------------------------------------------------------------- /changes.txt: -------------------------------------------------------------------------------- 1 | JUSH 2.2.0-dev: 2 | Add textarea autocomplete 3 | Add autocomplete for SQL 4 | 5 | JUSH 2.1.3: 6 | Split dark mode 7 | 8 | JUSH 2.1.2: 9 | Textarea: Open help on Ctrl+click 10 | 11 | JUSH 2.1.1: 12 | Add support for dark mode 13 | Add support for IME composition 14 | PostgreSQL: Fix dollar-quoted strings 15 | MySQL: Fix doc links 16 | MySQL: Lowercase sqlstatus link in MariaDB 17 | 18 | JUSH 2.0.0: 19 | Add highlighted textarea 20 | Allow using tags in highlighted source 21 | Highlight PHP 5.5 22 | Highlight HTML5 23 | Highlight CSS 3 24 | Highlight SimpleDB 25 | Highlight keys in JavaScript objects 26 | Highlight hexadecimal numbers 27 | Link Suhosin in php.ini 28 | Link MySQL geometry 29 | Unlink PECL 30 | Help cursor for documentation links 31 | Match regular expressions only once (performance) 32 | 33 | JUSH 1.11.0: 34 | Fix jQuery plugin (thanks to Daniel Kouba) 35 | 36 | JUSH 1.10.0: 37 | Highlight Oracle 38 | Highlight jsDoc 39 | Highlight text with PHP (e.g. command line scripts) 40 | Highlight MySQL 5.5 41 | Link PHP methods 42 | Link PHP callbacks 43 | Link SQLite PRAGMA 44 | Link PostgreSQL variables 45 | Allow specifying language through class="language-*" 46 | Optionally display title with function summary and parameters 47 | Ability to link custom words (e.g. function or table names) 48 | Highlight tags in 1 second chunks (let browser live) 49 | Fix highlighting in Chrome 50 | 51 | JUSH 1.9.0: 52 | Link PHP classes and special functions 53 | Improve performance on multiple calls 54 | Windows command line interface for context help 55 | 56 | JUSH 1.8.0: 57 | Highlight MS SQL 58 | Link mail headers 59 | 60 | JUSH 1.7.0: 61 | Highlight XML 62 | Highlight phpDoc 63 | Highlight MySQL code comments /*! */ 64 | 65 | JUSH 1.6.0: 66 | Remove Python (orthogonal) 67 | Option to customize links - e.g. jush.create_links = ' target="_blank"' 68 | Option to highlight only part of document - jush.highlight_tag(dom_elements) 69 | 70 | JUSH 1.5.0: 71 | Performance optimizations 72 | Link HTTP headers 73 | Highlight variables inside heredoc 74 | Parse nowdoc (PHP 5.3) 75 | Parse JS regexp only after operator 76 | Highlight
77 | Option to not create links - jush.create_links 78 | Fix CSS comments 79 | 80 | JUSH 1.4.0: 81 | Highlighting of Apache config 82 | 83 | JUSH 1.3.1: 84 | Highlight MySQL keywords 85 | Link PHP 5.3 keywords 86 | 87 | JUSH 1.3.0: 88 | Highlight numbers 89 | JavaScript built-in functions 90 | 91 | JUSH 1.2.4: 92 | Links to HTML attributes (lowercase, aliases) 93 | Escape from php_echo by ?> 94 | 95 | JUSH 1.2.3: 96 | Bug fixes from Kajman 97 | 98 | JUSH 1.2.2: 99 | Highlight Python 100 | Added jush.style() 101 | Highlight HTML in document.write 102 | 103 | JUSH 1.2.1: 104 | php.ini highlighting 105 | MySQL data types, missing functions 106 | Don't highlight PHP functions after new 107 | Improve links to PHP keywords 108 | Treat print as echo 109 | JavaScript keywords 110 | SQL variables 111 | 112 | JUSH 1.2.0: 113 | PostgreSQL 114 | SQL strings accept '' 115 | SQLite strings not accept \' 116 | Highlight inside sqlite_exec 117 | Document jush.urls 118 | 119 | JUSH 1.1.0: 120 | Highlight SQLite 121 | Links to undocumented PgSQL and Socket PHP aliases 122 | 123 | JUSH 1.0.4: 124 | Highlight SQL functions and PHP keywords 125 | Jush in class='jush jush-php' not necessary anymore 126 | Remove SET from SQL links (colide with UPDATE SET) 127 | Add jush- prefix to styles 128 | Change to 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 |
9 |
10 |
11 | Language: 29 |
30 |
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 |
9 |

14 |

15 |

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 --> &amp;'], 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 | --------------------------------------------------------------------------------