Created
May 17, 2023 14:06
-
-
Save howiemnet/6052587a1a6f574dfa4927125420520e to your computer and use it in GitHub Desktop.
Hacky JS file hilighter - takes a URL to a JS file (in the querystring - add ?file=https://url.to/my/javascript/file.js) and renders it nicely... -ish.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<body> | |
<div style="font-family: sans-serif; font-size: large; width: 100%; padding: 10px; margin:0 0 30px 0; border: 2px solid black;" id="titlebar"></div> | |
<div id="myDiv"> | |
</div> | |
<script> | |
// h quick util: takes a querystring URL - ?file=URL_to_JS_file and renders out as hilighted JS | |
const params = new Proxy(new URLSearchParams(window.location.search), { get: (searchParams, prop) => searchParams.get(prop), }); | |
function getText(){ | |
// read text from URL location | |
var request = new XMLHttpRequest(); | |
var sourceURL = params.file; | |
document.getElementById("titlebar").innerHTML = "h's hacky syntax hilighter - file: <strong>"+sourceURL+"</strong>"; | |
request.open('GET', sourceURL, true); | |
request.send(null); | |
request.onreadystatechange = function () { | |
if (request.readyState === 4 && request.status === 200) { | |
var type = request.getResponseHeader('Content-Type'); | |
if (type.indexOf("javascript") !== 1) { | |
var str = request.responseText; | |
// quick replacements to fix JS file formatting when thrown into | |
// an HTML renderer. | |
// | |
// In order, replace tabs, spaces (so they don't get collapsed), angle brackets, newlines: | |
str = str.replace(/\t/g, ' ').replace(/ /g, ' ').replace(/</g, "<").replace(/>/g, ">").replace(/(?:\r\n|\r|\n)/g, '<br>'); | |
var el = document.getElementById("myDiv"); | |
el.innerHTML = str; | |
w3CodeColor(el,"js"); | |
} | |
} | |
} | |
} | |
getText(); | |
function w3CodeColor(elmnt, mode) { | |
var lang = (mode || "html"); | |
var elmntObj = (document.getElementById(elmnt) || elmnt); | |
var elmntTxt = elmntObj.innerHTML; | |
var tagcolor = "mediumblue"; | |
var tagnamecolor = "brown"; | |
var attributecolor = "red"; | |
var attributevaluecolor = "mediumblue"; | |
var commentcolor = "green"; | |
var cssselectorcolor = "brown"; | |
var csspropertycolor = "red"; | |
var csspropertyvaluecolor = "mediumblue"; | |
var cssdelimitercolor = "black"; | |
var cssimportantcolor = "red"; | |
var jscolor = "black"; | |
var jskeywordcolor = "mediumblue"; | |
var jsstringcolor = "brown"; | |
var jsnumbercolor = "red"; | |
var jspropertycolor = "black"; | |
elmntObj.style.fontFamily = "Consolas,'Courier New', monospace"; | |
if (!lang) {lang = "html"; } | |
if (lang == "html") {elmntTxt = htmlMode(elmntTxt);} | |
if (lang == "css") {elmntTxt = cssMode(elmntTxt);} | |
if (lang == "js") {elmntTxt = jsMode(elmntTxt);} | |
elmntObj.innerHTML = elmntTxt; | |
function extract(str, start, end, func, repl) { | |
var s, e, d = "", a = []; | |
while (str.search(start) > -1) { | |
s = str.search(start); | |
e = str.indexOf(end, s); | |
if (e == -1) {e = str.length;} | |
if (repl) { | |
a.push(func(str.substring(s, e + (end.length)))); | |
str = str.substring(0, s) + repl + str.substr(e + (end.length)); | |
} else { | |
d += str.substring(0, s); | |
d += func(str.substring(s, e + (end.length))); | |
str = str.substr(e + (end.length)); | |
} | |
} | |
this.rest = d + str; | |
this.arr = a; | |
} | |
function htmlMode(txt) { | |
var rest = txt, done = "", php, comment, angular, startpos, endpos, note, i; | |
comment = new extract(rest, "<!--", "-->", commentMode, "W3HTMLCOMMENTPOS"); | |
rest = comment.rest; | |
while (rest.indexOf("<") > -1) { | |
note = ""; | |
startpos = rest.indexOf("<"); | |
if (rest.substr(startpos, 9).toUpperCase() == "<STYLE") {note = "css";} | |
if (rest.substr(startpos, 10).toUpperCase() == "<SCRIPT") {note = "javascript";} | |
endpos = rest.indexOf(">", startpos); | |
if (endpos == -1) {endpos = rest.length;} | |
done += rest.substring(0, startpos); | |
done += tagMode(rest.substring(startpos, endpos + 4)); | |
rest = rest.substr(endpos + 4); | |
if (note == "css") { | |
endpos = rest.indexOf("</style>"); | |
if (endpos > -1) { | |
done += cssMode(rest.substring(0, endpos)); | |
rest = rest.substr(endpos); | |
} | |
} | |
if (note == "javascript") { | |
endpos = rest.indexOf("</script>"); | |
if (endpos > -1) { | |
done += jsMode(rest.substring(0, endpos)); | |
rest = rest.substr(endpos); | |
} | |
} | |
} | |
rest = done + rest; | |
for (i = 0; i < comment.arr.length; i++) { | |
rest = rest.replace("W3HTMLCOMMENTPOS", comment.arr[i]); | |
} | |
return rest; | |
} | |
function tagMode(txt) { | |
var rest = txt, done = "", startpos, endpos, result; | |
while (rest.search(/(\s|<br>)/) > -1) { | |
startpos = rest.search(/(\s|<br>)/); | |
endpos = rest.indexOf(">"); | |
if (endpos == -1) {endpos = rest.length;} | |
done += rest.substring(0, startpos); | |
done += attributeMode(rest.substring(startpos, endpos)); | |
rest = rest.substr(endpos); | |
} | |
result = done + rest; | |
result = "<span style=color:" + tagcolor + "><</span>" + result.substring(4); | |
if (result.substr(result.length - 4, 4) == ">") { | |
result = result.substring(0, result.length - 4) + "<span style=color:" + tagcolor + ">></span>"; | |
} | |
return "<span style=color:" + tagnamecolor + ">" + result + "</span>"; | |
} | |
function attributeMode(txt) { | |
var rest = txt, done = "", startpos, endpos, singlefnuttpos, doublefnuttpos, spacepos; | |
while (rest.indexOf("=") > -1) { | |
endpos = -1; | |
startpos = rest.indexOf("="); | |
singlefnuttpos = rest.indexOf("'", startpos); | |
doublefnuttpos = rest.indexOf('"', startpos); | |
spacepos = rest.indexOf(" ", startpos + 2); | |
if (spacepos > -1 && (spacepos < singlefnuttpos || singlefnuttpos == -1) && (spacepos < doublefnuttpos || doublefnuttpos == -1)) { | |
endpos = rest.indexOf(" ", startpos); | |
} else if (doublefnuttpos > -1 && (doublefnuttpos < singlefnuttpos || singlefnuttpos == -1) && (doublefnuttpos < spacepos || spacepos == -1)) { | |
endpos = rest.indexOf('"', rest.indexOf('"', startpos) + 1); | |
} else if (singlefnuttpos > -1 && (singlefnuttpos < doublefnuttpos || doublefnuttpos == -1) && (singlefnuttpos < spacepos || spacepos == -1)) { | |
endpos = rest.indexOf("'", rest.indexOf("'", startpos) + 1); | |
} | |
if (!endpos || endpos == -1 || endpos < startpos) {endpos = rest.length;} | |
done += rest.substring(0, startpos); | |
done += attributeValueMode(rest.substring(startpos, endpos + 1)); | |
rest = rest.substr(endpos + 1); | |
} | |
return "<span style=color:" + attributecolor + ">" + done + rest + "</span>"; | |
} | |
function attributeValueMode(txt) { | |
return "<span style=color:" + attributevaluecolor + ">" + txt + "</span>"; | |
} | |
function commentMode(txt) { | |
return "<span style=color:" + commentcolor + ">" + txt + "</span>"; | |
} | |
function cssMode(txt) { | |
var rest = txt, done = "", s, e, comment, i, midz, c, cc; | |
comment = new extract(rest, /\/\*/, "*/", commentMode, "W3CSSCOMMENTPOS"); | |
rest = comment.rest; | |
while (rest.search("{") > -1) { | |
s = rest.search("{"); | |
midz = rest.substr(s + 1); | |
cc = 1; | |
c = 0; | |
for (i = 0; i < midz.length; i++) { | |
if (midz.substr(i, 1) == "{") {cc++; c++} | |
if (midz.substr(i, 1) == "}") {cc--;} | |
if (cc == 0) {break;} | |
} | |
if (cc != 0) {c = 0;} | |
e = s; | |
for (i = 0; i <= c; i++) { | |
e = rest.indexOf("}", e + 1); | |
} | |
if (e == -1) {e = rest.length;} | |
done += rest.substring(0, s + 1); | |
done += cssPropertyMode(rest.substring(s + 1, e)); | |
rest = rest.substr(e); | |
} | |
rest = done + rest; | |
rest = rest.replace(/{/g, "<span style=color:" + cssdelimitercolor + ">{</span>"); | |
rest = rest.replace(/}/g, "<span style=color:" + cssdelimitercolor + ">}</span>"); | |
for (i = 0; i < comment.arr.length; i++) { | |
rest = rest.replace("W3CSSCOMMENTPOS", comment.arr[i]); | |
} | |
return "<span style=color:" + cssselectorcolor + ">" + rest + "</span>"; | |
} | |
function cssPropertyMode(txt) { | |
var rest = txt, done = "", s, e, n, loop; | |
if (rest.indexOf("{") > -1 ) { return cssMode(rest); } | |
while (rest.search(":") > -1) { | |
s = rest.search(":"); | |
loop = true; | |
n = s; | |
while (loop == true) { | |
loop = false; | |
e = rest.indexOf(";", n); | |
if (rest.substring(e - 5, e + 1) == " ") { | |
loop = true; | |
n = e + 1; | |
} | |
} | |
if (e == -1) {e = rest.length;} | |
done += rest.substring(0, s); | |
done += cssPropertyValueMode(rest.substring(s, e + 1)); | |
rest = rest.substr(e + 1); | |
} | |
return "<span style=color:" + csspropertycolor + ">" + done + rest + "</span>"; | |
} | |
function cssPropertyValueMode(txt) { | |
var rest = txt, done = "", s; | |
rest = "<span style=color:" + cssdelimitercolor + ">:</span>" + rest.substring(1); | |
while (rest.search(/!important/i) > -1) { | |
s = rest.search(/!important/i); | |
done += rest.substring(0, s); | |
done += cssImportantMode(rest.substring(s, s + 10)); | |
rest = rest.substr(s + 10); | |
} | |
result = done + rest; | |
if (result.substr(result.length - 1, 1) == ";" && result.substr(result.length - 6, 6) != " " && result.substr(result.length - 4, 4) != "<" && result.substr(result.length - 4, 4) != ">" && result.substr(result.length - 5, 5) != "&") { | |
result = result.substring(0, result.length - 1) + "<span style=color:" + cssdelimitercolor + ">;</span>"; | |
} | |
return "<span style=color:" + csspropertyvaluecolor + ">" + result + "</span>"; | |
} | |
function cssImportantMode(txt) { | |
return "<span style=color:" + cssimportantcolor + ";font-weight:bold;>" + txt + "</span>"; | |
} | |
function jsMode(txt) { | |
var rest = txt, done = "", esc = [], i, cc, tt = "", sfnuttpos, dfnuttpos, compos, comlinepos, keywordpos, numpos, mypos, dotpos, y; | |
for (i = 0; i < rest.length; i++) { | |
cc = rest.substr(i, 1); | |
if (cc == "\\") { | |
esc.push(rest.substr(i, 2)); | |
cc = "W3JSESCAPE"; | |
i++; | |
} | |
tt += cc; | |
} | |
rest = tt; | |
y = 1; | |
while (y == 1) { | |
sfnuttpos = getPos(rest, "'", "'", jsStringMode); | |
dfnuttpos = getPos(rest, '"', '"', jsStringMode); | |
compos = getPos(rest, /\/\*/, "*/", commentMode); | |
comlinepos = getPos(rest, /\/\//, "<br>", commentMode); | |
numpos = getNumPos(rest, jsNumberMode); | |
keywordpos = getKeywordPos("js", rest, jsKeywordMode); | |
dotpos = getDotPos(rest, jsPropertyMode); | |
if (Math.max(numpos[0], sfnuttpos[0], dfnuttpos[0], compos[0], comlinepos[0], keywordpos[0], dotpos[0]) == -1) {break;} | |
mypos = getMinPos(numpos, sfnuttpos, dfnuttpos, compos, comlinepos, keywordpos, dotpos); | |
if (mypos[0] == -1) {break;} | |
if (mypos[0] > -1) { | |
done += rest.substring(0, mypos[0]); | |
done += mypos[2](rest.substring(mypos[0], mypos[1])); | |
rest = rest.substr(mypos[1]); | |
} | |
} | |
rest = done + rest; | |
for (i = 0; i < esc.length; i++) { | |
rest = rest.replace("W3JSESCAPE", esc[i]); | |
} | |
return "<span style=color:" + jscolor + ">" + rest + "</span>"; | |
} | |
function jsStringMode(txt) { | |
return "<span style=color:" + jsstringcolor + ">" + txt + "</span>"; | |
} | |
function jsKeywordMode(txt) { | |
return "<span style=color:" + jskeywordcolor + ">" + txt + "</span>"; | |
} | |
function jsNumberMode(txt) { | |
return "<span style=color:" + jsnumbercolor + ">" + txt + "</span>"; | |
} | |
function jsPropertyMode(txt) { | |
return "<span style=color:" + jspropertycolor + ">" + txt + "</span>"; | |
} | |
function getDotPos(txt, func) { | |
var x, i, j, s, e, arr = [".","<", " ", ";", "(", "+", ")", "[", "]", ",", "&", ":", "{", "}", "/" ,"-", "*", "|", "%"]; | |
s = txt.indexOf("."); | |
if (s > -1) { | |
x = txt.substr(s + 1); | |
for (j = 0; j < x.length; j++) { | |
cc = x[j]; | |
for (i = 0; i < arr.length; i++) { | |
if (cc.indexOf(arr[i]) > -1) { | |
e = j; | |
return [s + 1, e + s + 1, func]; | |
} | |
} | |
} | |
} | |
return [-1, -1, func]; | |
} | |
function getMinPos() { | |
var i, arr = []; | |
for (i = 0; i < arguments.length; i++) { | |
if (arguments[i][0] > -1) { | |
if (arr.length == 0 || arguments[i][0] < arr[0]) {arr = arguments[i];} | |
} | |
} | |
if (arr.length == 0) {arr = arguments[i];} | |
return arr; | |
} | |
function getKeywordPos(typ, txt, func) { | |
var words, i, pos, rpos = -1, rpos2 = -1, patt; | |
if (typ == "js") { | |
words = ["abstract","arguments","boolean","break","byte","case","catch","char","class","const","continue","debugger","default","delete", | |
"do","double","else","enum","eval","export","extends","false","final","finally","float","for","function","goto","if","implements","import", | |
"in","instanceof","int","interface","let","long","NaN","native","new","null","package","private","protected","public","return","short","static", | |
"super","switch","synchronized","this","throw","throws","transient","true","try","typeof","var","void","volatile","while","with","yield"]; | |
} | |
for (i = 0; i < words.length; i++) { | |
pos = txt.indexOf(words[i]); | |
if (pos > -1) { | |
patt = /\W/g; | |
if (txt.substr(pos + words[i].length,1).match(patt) && txt.substr(pos - 1,1).match(patt)) { | |
if (pos > -1 && (rpos == -1 || pos < rpos)) { | |
rpos = pos; | |
rpos2 = rpos + words[i].length; | |
} | |
} | |
} | |
} | |
return [rpos, rpos2, func]; | |
} | |
function getPos(txt, start, end, func) { | |
var s, e; | |
s = txt.search(start); | |
e = txt.indexOf(end, s + (end.length)); | |
if (e == -1) {e = txt.length;} | |
return [s, e + (end.length), func]; | |
} | |
function getNumPos(txt, func) { | |
var arr = ["<br>", " ", ";", "(", "+", ")", "[", "]", ",", "&", ":", "{", "}", "/" ,"-", "*", "|", "%", "="], i, j, c, startpos = 0, endpos, word; | |
for (i = 0; i < txt.length; i++) { | |
for (j = 0; j < arr.length; j++) { | |
c = txt.substr(i, arr[j].length); | |
if (c == arr[j]) { | |
if (c == "-" && (txt.substr(i - 1, 1) == "e" || txt.substr(i - 1, 1) == "E")) { | |
continue; | |
} | |
endpos = i; | |
if (startpos < endpos) { | |
word = txt.substring(startpos, endpos); | |
if (!isNaN(word)) {return [startpos, endpos, func];} | |
} | |
i += arr[j].length; | |
startpos = i; | |
i -= 1; | |
break; | |
} | |
} | |
} | |
return [-1, -1, func]; | |
} | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment