Mistake 4:
The lack of 'stricness' disturbed some people.
And it is a good point!
Now, 'use strict';
is present in the code.
The individual results for each element are returned in the form of an array.
Change 4:
@Mast pointed out something very simple and small.
The initialization had the following line:
var f=window.highlight = function(element, lang){//...
At first, it is completely unclear what f
is doing.
I've changed it's name to fn
, and added a description of what that variable is doing there.
(function(window){
'use strict';
//fn keeps an internal reference to avoid problems with rewritting the window.highlight
var f=windowfn = window.highlight = function(element, lang){
'use strict';
if(element instanceof NodeList || element instanceof HTMLCollection)
{
for(var i = 0, l = element.length;length, results = []; i<l; i++)
{
try
{
fresults[i] = fn( element[i], lang );
}
catch(e)
{
//welogs wantthe message, to give a chance to all the other elements
(console.error || console.log).call( console, e.message );
results[i] = false;
}
}
return true;results;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 1st parameter must be an Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang');
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = ffn.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflowreflows
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
ffn.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
ffn.langs = {};
})(Function('return this')());//just be sure that we have the real window
//main file, containing the main function
(function(window){
'use strict';
//fn keeps an internal reference to avoid problems with rewritting the window.highlight
var fn = window.highlight = function(element, lang){
var'use f=window.highlightstrict';
= function
if(element, lang){
instanceof NodeList || element instanceof HTMLCollection)
{
iffor(elementvar instanceofi NodeList= ||0, l = element.length, instanceofresults HTMLCollection= []; i<l; i++)
{
for(var i = 0, l = element.length; i<l; i++)try
{
try
{
results[i] = ffn( element[i], lang );
}
catch(e)
{
//we want to give a chance to all the other elements
(console.error || console.log).call( console, e.message );
}
}
return true;
}
if(!catch(element instanceof Element)e)
{
{
throw new TypeError( 'The 1st parameter must be an Element or NodeList' );
//logs the message, to give a chance to all the other }elements
lang =( langconsole.error || elementconsole.getAttribute('data-lang');
log if(!lang)
{
throw new TypeError.call( 'Missing languageconsole, definitione. Set the 2nd parameter or the attribute data-lang'message );
}
var lang_defsresults[i] = f.langs[lang];
if(!lang_defs)
{false;
throw new TypeError( 'The language "' + lang + '" was not yet defined' );}
}
return results;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 1st parameter must be an Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang');
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = fn.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var ij = 0, lk = lang_defsdiv.childNodes.length; i<l;j<k; i++j++)
{
var html = '';
forif(var j = 0, k = div.childNodeschildNodes[j].length;nodeType j<k;=== j++3)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
html += div.innerHTML = returned;
}childNodes[j].outerHTML;
}
}
//only change atrefreshes the endHTML, to avoid unnecessary reflow
element.className += ' highlightbefore 'doing +anything lang;else
elementdiv.innerHTML = div.innerHTML;html;
returnif('function' true;=== typeof lang_defs[i].patch)
} {
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
//default replace object {
f div.default_replaceinnerHTML = {'tag':returned;
'span', 'text': '1ドル'};
}
}
//allonly change at the languagesend, willto beavoid addedunnecessary herereflows
felement.langsclassName += ' highlight ' + lang;
element.innerHTML = {div.innerHTML;
return true;
};
})(Function('return//default this')())replace object
fn.default_replace = {'tag': 'span', 'text': '1ドル'};//justall the languages will be sureadded thathere
we have the realfn.langs window= {};
})(Function('return this')());//==========================================================just be sure that we have the real window
// sql syntax highlight, anothed different file
(function(window){//==========================================================
// sql syntax highlight, anothed different file
(function(window){
'use strict';
if('function' === typeof window.highlight)
{
window.highlight.langs.sql=[
{
'class':'string',
'match':/([bn]?"(?:[^"]|[\\"]")*"|[bn]?'(?:[^']|[\\']')*')(?=[\b\s\(\),;\$#\+\-\*\/]|$)/g,
'replace':window.highlight.default_replace
},
{
'class':'comment',
'match':/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'replace':window.highlight.default_replace,
'patch':function(){
'use strict';
return this.innerHTML.replace(
/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'1ドル</span>'
).replace(//matches single-line comments
/<span class="comment">((?:#|-- |\/\/)(?:.|<\/span><span class="[^"]+">([^<])<\/span>)*)([\r\n]|$)/g,
function(_,part1,part2,part3){
return '<span class="comment">'+
//cleans up all spans
((part1||'')+(part2||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>'+
(part3||'');
}
).replace(//matches multi-line comments
/<span class="comment">(\/\*(?:[^*]|\*[^\/])+(?:\*\/(?:<\/span>)?|$))/g,
function(_,part1){
return '<span class="comment">'+
//cleans up all spans
((part1||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>';
}
);
}
},
{
/*
* numbers aren't that 'regular' and many edge-cases were left behind
* with the help of @MLM (http://stackoverflow.com/users/796832/mlm),
* we were able to make this work.
* he took over the regex and patched it all up, I did the replace string
*/
'match':/((?:^|\b|\(|\s|,))(?![a-z_]+)([+\-]?\d+(?:\.\d+)?(?:[eE]-?\d+)?)((?=$|\b|\s|\(|\)|,|;))/g,
'replace':'1ドル<span class="number">2ドル</span>3ドル'
},
{
'class':'name',
'match':/(`[^`]+`)/g,
'replace':window.highlight.default_replace
},
{
'class':'var',
'match':/(@@?[a-z_][a-z_\d]*)/g,
'replace':window.highlight.default_replace
},
{
'class':'keyword',
//the keyword replace must have an aditional check (`(?!\()` after the name), due to the function replace()
'match':/\b(accessible|add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|false|fetch|float|float4|float8|for|force|foreign|from|fulltext|generated|get|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|io_after_gtids|io_before_gtids|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|linear|lines|load|localtime|localtimestamp|lock|long|longblob|longtext|loop|low_priority|master_bind|master_ssl_verify_server_cert|match|maxvalue|mediumblob|mediumint|mediumtext|middleint|minute_microsecond|minute_second|mod|modifies|natural|nonblocking|not|no_write_to_binlog|null|numeric|on|optimize|optimizer_costs|option|optionally|or|order|out|outer|outfile|parse_gcol_expr|partition|precision|primary|procedure|purge|range|read|reads|read_write|real|references|regexp|release|rename|repeat|replace(?!\()|require|resignal|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|signal|smallint|spatial|specific|sql|sqlexception|sqlstate|sqlwarning|sql_big_result|sql_calc_found_rows|sql_small_result|ssl|starting|stored|straight_join|table|terminated|then|tinyblob|tinyint|tinytext|to|trailing|trigger|true|undo|union|unique|unlock|unsigned|update|usage|use|using|utc_date|utc_time|utc_timestamp|values|varbinary|varchar|varcharacter|varying|virtual|when|where|while|with|write|xor|year_month|zerofill)\b/gi,
'replace':window.highlight.default_replace
},
{
'class':'func',
'match':/\b([a-z_][a-z_\d]*)\b(?=\()/gi,
'replace':window.highlight.default_replace
},
{
'class':'name',
'match':/\b([a-z\_][a-z_\d]*)\b/gi,
'replace':window.highlight.default_replace
}
];},
{
/*
* numbers aren't that 'regular' and many edge-cases were left behind
* with the help of @MLM (http://stackoverflow.com/users/796832/mlm),
* we were able to make this work.
* he took over the regex and patched it all up, I did the replace string
*/
'match':/((?:^|\b|\(|\s|,))(?![a-z_]+)([+\-]?\d+(?:\.\d+)?(?:[eE]-?\d+)?)((?=$|\b|\s|\(|\)|,|;))/g,
'replace':'1ドル<span class="number">2ドル</span>3ドル'
},
{
'class':'name',
'match':/(`[^`]+`)/g,
'replace':window.highlight.default_replace
},
{
'class':'var',
'match':/(@@?[a-z_][a-z_\d]*)/g,
'replace':window.highlight.default_replace
},
{
'class':'keyword',
//the keyword replace must have an aditional check (`(?!\()` after the name), due to the function replace()
'match':/\b(accessible|add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|false|fetch|float|float4|float8|for|force|foreign|from|fulltext|generated|get|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|io_after_gtids|io_before_gtids|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|linear|lines|load|localtime|localtimestamp|lock|long|longblob|longtext|loop|low_priority|master_bind|master_ssl_verify_server_cert|match|maxvalue|mediumblob|mediumint|mediumtext|middleint|minute_microsecond|minute_second|mod|modifies|natural|nonblocking|not|no_write_to_binlog|null|numeric|on|optimize|optimizer_costs|option|optionally|or|order|out|outer|outfile|parse_gcol_expr|partition|precision|primary|procedure|purge|range|read|reads|read_write|real|references|regexp|release|rename|repeat|replace(?!\()|require|resignal|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|signal|smallint|spatial|specific|sql|sqlexception|sqlstate|sqlwarning|sql_big_result|sql_calc_found_rows|sql_small_result|ssl|starting|stored|straight_join|table|terminated|then|tinyblob|tinyint|tinytext|to|trailing|trigger|true|undo|union|unique|unlock|unsigned|update|usage|use|using|utc_date|utc_time|utc_timestamp|values|varbinary|varchar|varcharacter|varying|virtual|when|where|while|with|write|xor|year_month|zerofill)\b/gi,
'replace':window.highlight.default_replace
},
{
'class':'func',
'match':/\b([a-z_][a-z_\d]*)\b(?=\()/gi,
'replace':window.highlight.default_replace
},
{
'class':'name',
'match':/\b([a-z\_][a-z_\d]*)\b/gi,
'replace':window.highlight.default_replace
}
];
}
})(Function('return this')());
//=========================================================
// execution example:
window.onload = function(){
highlight(document.getElementsByTagName('pre')[0]);
}
/*styling for this example only*/
p {
font-family:sans-serif;
margin-bottom: 0px;
}
pre {margin-top:5px;}
/*console theme, main file*/
.highlight, .highlight *{
background:black;
color:white;
font-family:'Consolas',monospace;
font-size:16px;
word-wrap: break-word;
white-space: pre;
}
/*sql style, different file*/
.highlight.sql .keyword{color:teal;}
.highlight.sql .string{color:red;}
.highlight.sql .func{color:purple;}
.highlight.sql .number{color:#0F0;}
.highlight.sql .name{color:olive;}
.highlight.sql .var{color:green;}
.highlight.sql .comment{color:gray;}
<p>Simple example:</p>
<pre data-lang="sql">
insert into `table` select * from `_copy` where id < 55;
</pre>
<p>Simple example, without language defined:</p>
<pre>
select "This will be 'unhighlighted'";
</pre>
<p>Complex example:</p>
<pre data-lang="sql">
CREATE TABLE `shop` (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT '' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
(3,'C',1.69),(3,'D',-1.25),(4,'D',19.95);
#This is an example of sql a = 'b', 'c'
SELECT MAX(article) AS article FROM shop;
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.price < s2.price
WHERE s2.article IS NULL;
SELECT article, MAX(price) AS price
FROM shop
GROUP BY article;
SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);
SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
/*
a string =' ',
*/
select '1'#comment
/*''*/ or 2;
select "Also has support for "" <-- that style of quotes",
'''Like this as well!''';
</pre>
(function(window){
var f=window.highlight = function(element, lang){
if(element instanceof NodeList || element instanceof HTMLCollection)
{
for(var i = 0, l = element.length; i<l; i++)
{
try
{
f( element[i], lang );
}
catch(e)
{
//we want to give a chance to all the other elements
(console.error || console.log).call( console, e.message );
}
}
return true;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 1st parameter must be an Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang');
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = f.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflow
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
f.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
f.langs = {};
})(Function('return this')());//just be sure that we have the real window
(function(window){
var f=window.highlight = function(element, lang){
if(element instanceof NodeList || element instanceof HTMLCollection)
{
for(var i = 0, l = element.length; i<l; i++)
{
try
{
f( element[i], lang );
}
catch(e)
{
//we want to give a chance to all the other elements
(console.error || console.log).call( console, e.message );
}
}
return true;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 1st parameter must be an Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang');
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = f.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflow
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
f.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
f.langs = {};
})(Function('return this')());//just be sure that we have the real window
//==========================================================
// sql syntax highlight, anothed different file
(function(window){
if('function' === typeof window.highlight)
{
window.highlight.langs.sql=[
{
'class':'string',
'match':/([bn]?"(?:[^"]|[\\"]")*"|[bn]?'(?:[^']|[\\']')*')(?=[\b\s\(\),;\$#\+\-\*\/]|$)/g,
'replace':window.highlight.default_replace
},
{
'class':'comment',
'match':/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'replace':window.highlight.default_replace,
'patch':function(){
return this.innerHTML.replace(
/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'1ドル</span>'
).replace(//matches single-line comments
/<span class="comment">((?:#|-- |\/\/)(?:.|<\/span><span class="[^"]+">([^<])<\/span>)*)([\r\n]|$)/g,
function(_,part1,part2,part3){
return '<span class="comment">'+
//cleans up all spans
((part1||'')+(part2||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>'+
(part3||'');
}
).replace(//matches multi-line comments
/<span class="comment">(\/\*(?:[^*]|\*[^\/])+(?:\*\/(?:<\/span>)?|$))/g,
function(_,part1){
return '<span class="comment">'+
//cleans up all spans
((part1||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>';
}
);
}
},
{
/*
* numbers aren't that 'regular' and many edge-cases were left behind
* with the help of @MLM (http://stackoverflow.com/users/796832/mlm),
* we were able to make this work.
* he took over the regex and patched it all up, I did the replace string
*/
'match':/((?:^|\b|\(|\s|,))(?![a-z_]+)([+\-]?\d+(?:\.\d+)?(?:[eE]-?\d+)?)((?=$|\b|\s|\(|\)|,|;))/g,
'replace':'1ドル<span class="number">2ドル</span>3ドル'
},
{
'class':'name',
'match':/(`[^`]+`)/g,
'replace':window.highlight.default_replace
},
{
'class':'var',
'match':/(@@?[a-z_][a-z_\d]*)/g,
'replace':window.highlight.default_replace
},
{
'class':'keyword',
//the keyword replace must have an aditional check (`(?!\()` after the name), due to the function replace()
'match':/\b(accessible|add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|false|fetch|float|float4|float8|for|force|foreign|from|fulltext|generated|get|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|io_after_gtids|io_before_gtids|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|linear|lines|load|localtime|localtimestamp|lock|long|longblob|longtext|loop|low_priority|master_bind|master_ssl_verify_server_cert|match|maxvalue|mediumblob|mediumint|mediumtext|middleint|minute_microsecond|minute_second|mod|modifies|natural|nonblocking|not|no_write_to_binlog|null|numeric|on|optimize|optimizer_costs|option|optionally|or|order|out|outer|outfile|parse_gcol_expr|partition|precision|primary|procedure|purge|range|read|reads|read_write|real|references|regexp|release|rename|repeat|replace(?!\()|require|resignal|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|signal|smallint|spatial|specific|sql|sqlexception|sqlstate|sqlwarning|sql_big_result|sql_calc_found_rows|sql_small_result|ssl|starting|stored|straight_join|table|terminated|then|tinyblob|tinyint|tinytext|to|trailing|trigger|true|undo|union|unique|unlock|unsigned|update|usage|use|using|utc_date|utc_time|utc_timestamp|values|varbinary|varchar|varcharacter|varying|virtual|when|where|while|with|write|xor|year_month|zerofill)\b/gi,
'replace':window.highlight.default_replace
},
{
'class':'func',
'match':/\b([a-z_][a-z_\d]*)\b(?=\()/gi,
'replace':window.highlight.default_replace
},
{
'class':'name',
'match':/\b([a-z\_][a-z_\d]*)\b/gi,
'replace':window.highlight.default_replace
}
];
}
})(Function('return this')());
//=========================================================
// execution example:
window.onload = function(){
highlight(document.getElementsByTagName('pre')[0]);
}
/*console theme, main file*/
.highlight, .highlight *{
background:black;
color:white;
font-family:'Consolas',monospace;
font-size:16px;
word-wrap: break-word;
white-space: pre;
}
/*sql style, different file*/
.highlight.sql .keyword{color:teal;}
.highlight.sql .string{color:red;}
.highlight.sql .func{color:purple;}
.highlight.sql .number{color:#0F0;}
.highlight.sql .name{color:olive;}
.highlight.sql .var{color:green;}
.highlight.sql .comment{color:gray;}
<pre data-lang="sql">
CREATE TABLE `shop` (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT '' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
(3,'C',1.69),(3,'D',-1.25),(4,'D',19.95);
#This is an example of sql a = 'b', 'c'
SELECT MAX(article) AS article FROM shop;
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.price < s2.price
WHERE s2.article IS NULL;
SELECT article, MAX(price) AS price
FROM shop
GROUP BY article;
SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);
SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
/*
a string =' ',
*/
select '1'#comment
/*''*/ or 2;
</pre>
Mistake 4:
The lack of 'stricness' disturbed some people.
And it is a good point!
Now, 'use strict';
is present in the code.
The individual results for each element are returned in the form of an array.
Change 4:
@Mast pointed out something very simple and small.
The initialization had the following line:
var f=window.highlight = function(element, lang){//...
At first, it is completely unclear what f
is doing.
I've changed it's name to fn
, and added a description of what that variable is doing there.
(function(window){
'use strict';
//fn keeps an internal reference to avoid problems with rewritting the window.highlight
var fn = window.highlight = function(element, lang){
'use strict';
if(element instanceof NodeList || element instanceof HTMLCollection)
{
for(var i = 0, l = element.length, results = []; i<l; i++)
{
try
{
results[i] = fn( element[i], lang );
}
catch(e)
{
//logs the message, to give a chance to all the other elements
(console.error || console.log).call( console, e.message );
results[i] = false;
}
}
return results;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 1st parameter must be an Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang');
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = fn.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflows
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
fn.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
fn.langs = {};
})(Function('return this')());//just be sure that we have the real window
//main file, containing the main function
(function(window){
'use strict';
//fn keeps an internal reference to avoid problems with rewritting the window.highlight
var fn = window.highlight = function(element, lang){
'use strict';
if(element instanceof NodeList || element instanceof HTMLCollection)
{
for(var i = 0, l = element.length, results = []; i<l; i++)
{
try
{
results[i] = fn( element[i], lang );
}
catch(e)
{
//logs the message, to give a chance to all the other elements
( console.error || console.log ).call( console, e.message );
results[i] = false;
}
}
return results;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 1st parameter must be an Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang');
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = fn.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflows
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
fn.default_replace = {'tag': 'span', 'text': '1ドル'};//all the languages will be added here
fn.langs = {};
})(Function('return this')());//just be sure that we have the real window
//==========================================================
// sql syntax highlight, anothed different file
(function(window){
'use strict';
if('function' === typeof window.highlight)
{
window.highlight.langs.sql=[
{
'class':'string',
'match':/([bn]?"(?:[^"]|[\\"]")*"|[bn]?'(?:[^']|[\\']')*')(?=[\b\s\(\),;\$#\+\-\*\/]|$)/g,
'replace':window.highlight.default_replace
},
{
'class':'comment',
'match':/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'replace':window.highlight.default_replace,
'patch':function(){
'use strict';
return this.innerHTML.replace(
/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'1ドル</span>'
).replace(//matches single-line comments
/<span class="comment">((?:#|-- |\/\/)(?:.|<\/span><span class="[^"]+">([^<])<\/span>)*)([\r\n]|$)/g,
function(_,part1,part2,part3){
return '<span class="comment">'+
//cleans up all spans
((part1||'')+(part2||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>'+
(part3||'');
}
).replace(//matches multi-line comments
/<span class="comment">(\/\*(?:[^*]|\*[^\/])+(?:\*\/(?:<\/span>)?|$))/g,
function(_,part1){
return '<span class="comment">'+
//cleans up all spans
((part1||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>';
}
);
}
},
{
/*
* numbers aren't that 'regular' and many edge-cases were left behind
* with the help of @MLM (http://stackoverflow.com/users/796832/mlm),
* we were able to make this work.
* he took over the regex and patched it all up, I did the replace string
*/
'match':/((?:^|\b|\(|\s|,))(?![a-z_]+)([+\-]?\d+(?:\.\d+)?(?:[eE]-?\d+)?)((?=$|\b|\s|\(|\)|,|;))/g,
'replace':'1ドル<span class="number">2ドル</span>3ドル'
},
{
'class':'name',
'match':/(`[^`]+`)/g,
'replace':window.highlight.default_replace
},
{
'class':'var',
'match':/(@@?[a-z_][a-z_\d]*)/g,
'replace':window.highlight.default_replace
},
{
'class':'keyword',
//the keyword replace must have an aditional check (`(?!\()` after the name), due to the function replace()
'match':/\b(accessible|add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|false|fetch|float|float4|float8|for|force|foreign|from|fulltext|generated|get|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|io_after_gtids|io_before_gtids|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|linear|lines|load|localtime|localtimestamp|lock|long|longblob|longtext|loop|low_priority|master_bind|master_ssl_verify_server_cert|match|maxvalue|mediumblob|mediumint|mediumtext|middleint|minute_microsecond|minute_second|mod|modifies|natural|nonblocking|not|no_write_to_binlog|null|numeric|on|optimize|optimizer_costs|option|optionally|or|order|out|outer|outfile|parse_gcol_expr|partition|precision|primary|procedure|purge|range|read|reads|read_write|real|references|regexp|release|rename|repeat|replace(?!\()|require|resignal|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|signal|smallint|spatial|specific|sql|sqlexception|sqlstate|sqlwarning|sql_big_result|sql_calc_found_rows|sql_small_result|ssl|starting|stored|straight_join|table|terminated|then|tinyblob|tinyint|tinytext|to|trailing|trigger|true|undo|union|unique|unlock|unsigned|update|usage|use|using|utc_date|utc_time|utc_timestamp|values|varbinary|varchar|varcharacter|varying|virtual|when|where|while|with|write|xor|year_month|zerofill)\b/gi,
'replace':window.highlight.default_replace
},
{
'class':'func',
'match':/\b([a-z_][a-z_\d]*)\b(?=\()/gi,
'replace':window.highlight.default_replace
},
{
'class':'name',
'match':/\b([a-z\_][a-z_\d]*)\b/gi,
'replace':window.highlight.default_replace
}
];
}
})(Function('return this')());
//=========================================================
// execution example:
window.onload = function(){
highlight(document.getElementsByTagName('pre'));
}
/*styling for this example only*/
p {
font-family:sans-serif;
margin-bottom: 0px;
}
pre {margin-top:5px;}
/*console theme, main file*/
.highlight, .highlight *{
background:black;
color:white;
font-family:'Consolas',monospace;
font-size:16px;
word-wrap: break-word;
white-space: pre;
}
/*sql style, different file*/
.highlight.sql .keyword{color:teal;}
.highlight.sql .string{color:red;}
.highlight.sql .func{color:purple;}
.highlight.sql .number{color:#0F0;}
.highlight.sql .name{color:olive;}
.highlight.sql .var{color:green;}
.highlight.sql .comment{color:gray;}
<p>Simple example:</p>
<pre data-lang="sql">
insert into `table` select * from `_copy` where id < 55;
</pre>
<p>Simple example, without language defined:</p>
<pre>
select "This will be 'unhighlighted'";
</pre>
<p>Complex example:</p>
<pre data-lang="sql">
CREATE TABLE `shop` (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT '' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
(3,'C',1.69),(3,'D',-1.25),(4,'D',19.95);
#This is an example of sql a = 'b', 'c'
SELECT MAX(article) AS article FROM shop;
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.price < s2.price
WHERE s2.article IS NULL;
SELECT article, MAX(price) AS price
FROM shop
GROUP BY article;
SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);
SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
/*
a string =' ',
*/
select '1'#comment
/*''*/ or 2;
select "Also has support for "" <-- that style of quotes",
'''Like this as well!''';
</pre>
Also, the exception about the language being missing was adjusted.
Change 3:
You can now pass a set of elements (NodeList
or HTMLCollection
) and the elements will be highlighted.
The exceptions that are thrown will be handled differently, giving the other elements a chance.
(function(window){
var f=window.highlight = function(element, lang){
if(element instanceof NodeList || element instanceof HTMLCollection)
{
for(var i = 0, l = element.length; i<l; i++)
{
try
{
f( element[i], lang );
}
catch(e)
{
//we want to give a chance to all the other elements
(console.error || console.log).call( console, e.message );
}
}
return true;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 2nd1st parameter must be an Element'Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang') || '';;
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = f.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflow
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
f.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
f.langs = {};
})(Function('return this')());//just be sure that we have the real window
// highlight function, separated file
(function(window){
var f=window.highlight = function(element, lang){
if(element instanceof NodeList || element instanceof HTMLCollection)
{
for(var i = 0, l = element.length; i<l; i++)
{
try
{
f( element[i], lang );
}
catch(e)
{
//we want to give a chance to all the other elements
(console.error || console.log).call( console, e.message );
}
}
return true;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 2nd1st parameter must be an Element'Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang') || '';;
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = f.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflow
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
f.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
f.langs = {};
})(Function('return this')());//just be sure that we have the real window
//==========================================================
// sql syntax highlight, anothed different file
(function(window){
if('function' === typeof window.highlight)
{
window.highlight.langs.sql=[
{
'class':'string',
'match':/([bn]?"(?:[^"]|[\\"]")*"|[bn]?'(?:[^']|[\\']')*')(?=[\b\s\(\),;\$#\+\-\*\/]|$)/g,
'replace':window.highlight.default_replace
},
{
'class':'comment',
'match':/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'replace':window.highlight.default_replace,
'patch':function(){
return this.innerHTML.replace(
/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'1ドル</span>'
).replace(//matches single-line comments
/<span class="comment">((?:#|-- |\/\/)(?:.|<\/span><span class="[^"]+">([^<])<\/span>)*)([\r\n]|$)/g,
function(_,part1,part2,part3){
return '<span class="comment">'+
//cleans up all spans
((part1||'')+(part2||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>'+
(part3||'');
}
).replace(//matches multi-line comments
/<span class="comment">(\/\*(?:[^*]|\*[^\/])+(?:\*\/(?:<\/span>)?|$))/g,
function(_,part1){
return '<span class="comment">'+
//cleans up all spans
((part1||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>';
}
);
}
},
{
/*
* numbers aren't that 'regular' and many edge-cases were left behind
* with the help of @MLM (http://stackoverflow.com/users/796832/mlm),
* we were able to make this work.
* he took over the regex and patched it all up, I did the replace string
*/
'match':/((?:^|\b|\(|\s|,))(?![a-z_]+)([+\-]?\d+(?:\.\d+)?(?:[eE]-?\d+)?)((?=$|\b|\s|\(|\)|,|;))/g,
'replace':'1ドル<span class="number">2ドル</span>3ドル'
},
{
'class':'name',
'match':/(`[^`]+`)/g,
'replace':window.highlight.default_replace
},
{
'class':'var',
'match':/(@@?[a-z_][a-z_\d]*)/g,
'replace':window.highlight.default_replace
},
{
'class':'keyword',
//the keyword replace must have an aditional check (`(?!\()` after the name), due to the function replace()
'match':/\b(accessible|add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|false|fetch|float|float4|float8|for|force|foreign|from|fulltext|generated|get|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|io_after_gtids|io_before_gtids|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|linear|lines|load|localtime|localtimestamp|lock|long|longblob|longtext|loop|low_priority|master_bind|master_ssl_verify_server_cert|match|maxvalue|mediumblob|mediumint|mediumtext|middleint|minute_microsecond|minute_second|mod|modifies|natural|nonblocking|not|no_write_to_binlog|null|numeric|on|optimize|optimizer_costs|option|optionally|or|order|out|outer|outfile|parse_gcol_expr|partition|precision|primary|procedure|purge|range|read|reads|read_write|real|references|regexp|release|rename|repeat|replace(?!\()|require|resignal|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|signal|smallint|spatial|specific|sql|sqlexception|sqlstate|sqlwarning|sql_big_result|sql_calc_found_rows|sql_small_result|ssl|starting|stored|straight_join|table|terminated|then|tinyblob|tinyint|tinytext|to|trailing|trigger|true|undo|union|unique|unlock|unsigned|update|usage|use|using|utc_date|utc_time|utc_timestamp|values|varbinary|varchar|varcharacter|varying|virtual|when|where|while|with|write|xor|year_month|zerofill)\b/gi,
'replace':window.highlight.default_replace
},
{
'class':'func',
'match':/\b([a-z_][a-z_\d]*)\b(?=\()/gi,
'replace':window.highlight.default_replace
},
{
'class':'name',
'match':/\b([a-z\_][a-z_\d]*)\b/gi,
'replace':window.highlight.default_replace
}
];
}
})(Function('return this')());
//=========================================================
// execution example:
window.onload = function(){
highlight(document.getElementsByTagName('pre')[0]);
}
/*console theme, main file*/
.highlight, .highlight *{
background:black;
color:white;
font-family:'Consolas',monospace;
font-size:16px;
word-wrap: break-word;
white-space: pre;
}
/*sql style, different file*/
.highlight.sql .keyword{color:teal;}
.highlight.sql .string{color:red;}
.highlight.sql .func{color:purple;}
.highlight.sql .number{color:#0F0;}
.highlight.sql .name{color:olive;}
.highlight.sql .var{color:green;}
.highlight.sql .comment{color:gray;}
<pre data-lang="sql">
CREATE TABLE `shop` (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT '' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
(3,'C',1.69),(3,'D',-1.25),(4,'D',19.95);
#This is an example of sql a = 'b', 'c'
SELECT MAX(article) AS article FROM shop;
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.price < s2.price
WHERE s2.article IS NULL;
SELECT article, MAX(price) AS price
FROM shop
GROUP BY article;
SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);
SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
/*
a string =' ',
*/
select '1'#comment
/*''*/ or 2;
</pre>
(function(window){
var f=window.highlight = function(element, lang){
if(!(element instanceof Element))
{
throw new TypeError( 'The 2nd parameter must be an Element' );
}
lang = lang || element.getAttribute('data-lang') || '';
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = f.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflow
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
f.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
f.langs = {};
})(Function('return this')());//just be sure that we have the real window
// highlight function, separated file
(function(window){
var f=window.highlight = function(element, lang){
if(!(element instanceof Element))
{
throw new TypeError( 'The 2nd parameter must be an Element' );
}
lang = lang || element.getAttribute('data-lang') || '';
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = f.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflow
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
f.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
f.langs = {};
})(Function('return this')());//just be sure that we have the real window
//==========================================================
// sql syntax highlight, anothed different file
(function(window){
if('function' === typeof window.highlight)
{
window.highlight.langs.sql=[
{
'class':'string',
'match':/([bn]?"(?:[^"]|[\\"]")*"|[bn]?'(?:[^']|[\\']')*')(?=[\b\s\(\),;\$#\+\-\*\/]|$)/g,
'replace':window.highlight.default_replace
},
{
'class':'comment',
'match':/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'replace':window.highlight.default_replace,
'patch':function(){
return this.innerHTML.replace(
/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'1ドル</span>'
).replace(//matches single-line comments
/<span class="comment">((?:#|-- |\/\/)(?:.|<\/span><span class="[^"]+">([^<])<\/span>)*)([\r\n]|$)/g,
function(_,part1,part2,part3){
return '<span class="comment">'+
//cleans up all spans
((part1||'')+(part2||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>'+
(part3||'');
}
).replace(//matches multi-line comments
/<span class="comment">(\/\*(?:[^*]|\*[^\/])+(?:\*\/(?:<\/span>)?|$))/g,
function(_,part1){
return '<span class="comment">'+
//cleans up all spans
((part1||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>';
}
);
}
},
{
/*
* numbers aren't that 'regular' and many edge-cases were left behind
* with the help of @MLM (http://stackoverflow.com/users/796832/mlm),
* we were able to make this work.
* he took over the regex and patched it all up, I did the replace string
*/
'match':/((?:^|\b|\(|\s|,))(?![a-z_]+)([+\-]?\d+(?:\.\d+)?(?:[eE]-?\d+)?)((?=$|\b|\s|\(|\)|,|;))/g,
'replace':'1ドル<span class="number">2ドル</span>3ドル'
},
{
'class':'name',
'match':/(`[^`]+`)/g,
'replace':window.highlight.default_replace
},
{
'class':'var',
'match':/(@@?[a-z_][a-z_\d]*)/g,
'replace':window.highlight.default_replace
},
{
'class':'keyword',
//the keyword replace must have an aditional check (`(?!\()` after the name), due to the function replace()
'match':/\b(accessible|add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|false|fetch|float|float4|float8|for|force|foreign|from|fulltext|generated|get|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|io_after_gtids|io_before_gtids|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|linear|lines|load|localtime|localtimestamp|lock|long|longblob|longtext|loop|low_priority|master_bind|master_ssl_verify_server_cert|match|maxvalue|mediumblob|mediumint|mediumtext|middleint|minute_microsecond|minute_second|mod|modifies|natural|nonblocking|not|no_write_to_binlog|null|numeric|on|optimize|optimizer_costs|option|optionally|or|order|out|outer|outfile|parse_gcol_expr|partition|precision|primary|procedure|purge|range|read|reads|read_write|real|references|regexp|release|rename|repeat|replace(?!\()|require|resignal|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|signal|smallint|spatial|specific|sql|sqlexception|sqlstate|sqlwarning|sql_big_result|sql_calc_found_rows|sql_small_result|ssl|starting|stored|straight_join|table|terminated|then|tinyblob|tinyint|tinytext|to|trailing|trigger|true|undo|union|unique|unlock|unsigned|update|usage|use|using|utc_date|utc_time|utc_timestamp|values|varbinary|varchar|varcharacter|varying|virtual|when|where|while|with|write|xor|year_month|zerofill)\b/gi,
'replace':window.highlight.default_replace
},
{
'class':'func',
'match':/\b([a-z_][a-z_\d]*)\b(?=\()/gi,
'replace':window.highlight.default_replace
},
{
'class':'name',
'match':/\b([a-z\_][a-z_\d]*)\b/gi,
'replace':window.highlight.default_replace
}
];
}
})(Function('return this')());
//=========================================================
// execution example:
window.onload = function(){
highlight(document.getElementsByTagName('pre')[0]);
}
/*console theme, main file*/
.highlight, .highlight *{
background:black;
color:white;
font-family:'Consolas',monospace;
font-size:16px;
word-wrap: break-word;
white-space: pre;
}
/*sql style, different file*/
.highlight.sql .keyword{color:teal;}
.highlight.sql .string{color:red;}
.highlight.sql .func{color:purple;}
.highlight.sql .number{color:#0F0;}
.highlight.sql .name{color:olive;}
.highlight.sql .var{color:green;}
.highlight.sql .comment{color:gray;}
<pre data-lang="sql">
CREATE TABLE `shop` (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT '' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
(3,'C',1.69),(3,'D',-1.25),(4,'D',19.95);
#This is an example of sql a = 'b', 'c'
SELECT MAX(article) AS article FROM shop;
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.price < s2.price
WHERE s2.article IS NULL;
SELECT article, MAX(price) AS price
FROM shop
GROUP BY article;
SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);
SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
/*
a string =' ',
*/
select '1'#comment
/*''*/ or 2;
</pre>
Also, the exception about the language being missing was adjusted.
Change 3:
You can now pass a set of elements (NodeList
or HTMLCollection
) and the elements will be highlighted.
The exceptions that are thrown will be handled differently, giving the other elements a chance.
(function(window){
var f=window.highlight = function(element, lang){
if(element instanceof NodeList || element instanceof HTMLCollection)
{
for(var i = 0, l = element.length; i<l; i++)
{
try
{
f( element[i], lang );
}
catch(e)
{
//we want to give a chance to all the other elements
(console.error || console.log).call( console, e.message );
}
}
return true;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 1st parameter must be an Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang');
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = f.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflow
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
f.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
f.langs = {};
})(Function('return this')());//just be sure that we have the real window
(function(window){
var f=window.highlight = function(element, lang){
if(element instanceof NodeList || element instanceof HTMLCollection)
{
for(var i = 0, l = element.length; i<l; i++)
{
try
{
f( element[i], lang );
}
catch(e)
{
//we want to give a chance to all the other elements
(console.error || console.log).call( console, e.message );
}
}
return true;
}
if(!(element instanceof Element))
{
throw new TypeError( 'The 1st parameter must be an Element or NodeList' );
}
lang = lang || element.getAttribute('data-lang');
if(!lang)
{
throw new TypeError( 'Missing language definition. Set the 2nd parameter or the attribute data-lang' );
}
var lang_defs = f.langs[lang];
if(!lang_defs)
{
throw new TypeError( 'The language "' + lang + '" was not yet defined' );
}
//create a document fragment, to avoid reflow and increase performance
var fragment = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = element.innerHTML;
fragment.appendChild(div);
for(var i = 0, l = lang_defs.length; i<l; i++)
{
var html = '';
for(var j = 0, k = div.childNodes.length; j<k; j++)
{
if(div.childNodes[j].nodeType === 3)
{
html += div.childNodes[j].nodeValue
.replace(
lang_defs[i].match,
/*shortcut to decide if the lang_defs[i].replace is one of those types
*if so, passes it directly
*otherwise, makes a string matching based on the object
*/
{'string':1, 'function':1}[ typeof lang_defs[i].replace ]
? lang_defs[i].replace
: '<' + lang_defs[i].replace.tag +
' class="' + lang_defs[i]['class'] + '">' +
lang_defs[i].replace.text +
'</' + lang_defs[i].replace.tag + '>'
);
}
else
{
html += div.childNodes[j].outerHTML;
}
}
//refreshes the HTML, before doing anything else
div.innerHTML = html;
if('function' === typeof lang_defs[i].patch)
{
var returned = lang_defs[i].patch.call( div );
if('string' === typeof returned)
{
div.innerHTML = returned;
}
}
}
//only change at the end, to avoid unnecessary reflow
element.className += ' highlight ' + lang;
element.innerHTML = div.innerHTML;
return true;
};
//default replace object
f.default_replace = {'tag': 'span', 'text': '1ドル'};
//all the languages will be added here
f.langs = {};
})(Function('return this')());//just be sure that we have the real window
//==========================================================
// sql syntax highlight, anothed different file
(function(window){
if('function' === typeof window.highlight)
{
window.highlight.langs.sql=[
{
'class':'string',
'match':/([bn]?"(?:[^"]|[\\"]")*"|[bn]?'(?:[^']|[\\']')*')(?=[\b\s\(\),;\$#\+\-\*\/]|$)/g,
'replace':window.highlight.default_replace
},
{
'class':'comment',
'match':/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'replace':window.highlight.default_replace,
'patch':function(){
return this.innerHTML.replace(
/((?:\/\/|\-\-\s|#)[^\r\n]*|\/\*(?:[^*]|\*[^\/])*(?:\*\/|$))/g,
'1ドル</span>'
).replace(//matches single-line comments
/<span class="comment">((?:#|-- |\/\/)(?:.|<\/span><span class="[^"]+">([^<])<\/span>)*)([\r\n]|$)/g,
function(_,part1,part2,part3){
return '<span class="comment">'+
//cleans up all spans
((part1||'')+(part2||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>'+
(part3||'');
}
).replace(//matches multi-line comments
/<span class="comment">(\/\*(?:[^*]|\*[^\/])+(?:\*\/(?:<\/span>)?|$))/g,
function(_,part1){
return '<span class="comment">'+
//cleans up all spans
((part1||'')).replace(/<\/?span(?: class="[^"]+")?>/g,'')+
'</span>';
}
);
}
},
{
/*
* numbers aren't that 'regular' and many edge-cases were left behind
* with the help of @MLM (http://stackoverflow.com/users/796832/mlm),
* we were able to make this work.
* he took over the regex and patched it all up, I did the replace string
*/
'match':/((?:^|\b|\(|\s|,))(?![a-z_]+)([+\-]?\d+(?:\.\d+)?(?:[eE]-?\d+)?)((?=$|\b|\s|\(|\)|,|;))/g,
'replace':'1ドル<span class="number">2ドル</span>3ドル'
},
{
'class':'name',
'match':/(`[^`]+`)/g,
'replace':window.highlight.default_replace
},
{
'class':'var',
'match':/(@@?[a-z_][a-z_\d]*)/g,
'replace':window.highlight.default_replace
},
{
'class':'keyword',
//the keyword replace must have an aditional check (`(?!\()` after the name), due to the function replace()
'match':/\b(accessible|add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|false|fetch|float|float4|float8|for|force|foreign|from|fulltext|generated|get|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|io_after_gtids|io_before_gtids|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|linear|lines|load|localtime|localtimestamp|lock|long|longblob|longtext|loop|low_priority|master_bind|master_ssl_verify_server_cert|match|maxvalue|mediumblob|mediumint|mediumtext|middleint|minute_microsecond|minute_second|mod|modifies|natural|nonblocking|not|no_write_to_binlog|null|numeric|on|optimize|optimizer_costs|option|optionally|or|order|out|outer|outfile|parse_gcol_expr|partition|precision|primary|procedure|purge|range|read|reads|read_write|real|references|regexp|release|rename|repeat|replace(?!\()|require|resignal|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|signal|smallint|spatial|specific|sql|sqlexception|sqlstate|sqlwarning|sql_big_result|sql_calc_found_rows|sql_small_result|ssl|starting|stored|straight_join|table|terminated|then|tinyblob|tinyint|tinytext|to|trailing|trigger|true|undo|union|unique|unlock|unsigned|update|usage|use|using|utc_date|utc_time|utc_timestamp|values|varbinary|varchar|varcharacter|varying|virtual|when|where|while|with|write|xor|year_month|zerofill)\b/gi,
'replace':window.highlight.default_replace
},
{
'class':'func',
'match':/\b([a-z_][a-z_\d]*)\b(?=\()/gi,
'replace':window.highlight.default_replace
},
{
'class':'name',
'match':/\b([a-z\_][a-z_\d]*)\b/gi,
'replace':window.highlight.default_replace
}
];
}
})(Function('return this')());
//=========================================================
// execution example:
window.onload = function(){
highlight(document.getElementsByTagName('pre')[0]);
}
/*console theme, main file*/
.highlight, .highlight *{
background:black;
color:white;
font-family:'Consolas',monospace;
font-size:16px;
word-wrap: break-word;
white-space: pre;
}
/*sql style, different file*/
.highlight.sql .keyword{color:teal;}
.highlight.sql .string{color:red;}
.highlight.sql .func{color:purple;}
.highlight.sql .number{color:#0F0;}
.highlight.sql .name{color:olive;}
.highlight.sql .var{color:green;}
.highlight.sql .comment{color:gray;}
<pre data-lang="sql">
CREATE TABLE `shop` (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT '' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
(3,'C',1.69),(3,'D',-1.25),(4,'D',19.95);
#This is an example of sql a = 'b', 'c'
SELECT MAX(article) AS article FROM shop;
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.price < s2.price
WHERE s2.article IS NULL;
SELECT article, MAX(price) AS price
FROM shop
GROUP BY article;
SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);
SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
/*
a string =' ',
*/
select '1'#comment
/*''*/ or 2;
</pre>