The Website
This website is hosted through GitHub pages and thus can't run any server side code, meaning: everything you see here was made using html, css and javascript! Even the syntax highlighting is generated on the fly using javascript without any library. I found this blog describing how the author created a simple syntax highlighting logic using nothing but css and javascript. I've copied and modified the code to work for any width and length and worked with the <code> tag instead of the <pre> tag.
It's actually quite simple: You take a list of objects containing a regex, color and ident like this:
const cRegex = [
{
regex: /"(.*?)"/g, // strings
val: '#FFD658',
code: 'A'
},
{
regex: /(\d+\.?)/g, // numbers
val: ' #A7C',
code: 'B'
},
{
regex: /\b(char|short|int|long|float|double|unsigned|void|const|static|typedef|struct|[^\s]+_t)\b/g, // keywords and types
val: '#78dce8',
code: 'C'
},
{
regex: /(\w[A-Za-z0-9_]*)(?=\()/g, // functions
val: '#a6e22e',
code: 'D'
},
{
regex: /\b(sizeof|delete|switch|case|if|else|extern|return|for|while|break|continue|include)\b/g, // commands
val: '#E68',
code: 'E'
},
{
regex: /\b(true|false|NULL|\$)(?=[^\w])/g, // constants
val: '#ae81ff',
code: 'F'
},
{
regex: /([\b\s])([!=]=|[!=]==|\+\+|--|&&|\|\|<=|>=|>>|<<|\.\.\.)(?!span)([\b\s\w])/g, // operators
val: '#f92672',
code: 'G'
},
{
regex: /(\/\/.*)/g, // single line comment
val: 'gray',
code: 'H'
},
];
Then you just tokenize the input based on these regex expressions and parse them into a linear gradient using the index, length and color value given to the code:
function findTokens(line, regexObjs){
var rtrnText = '0'.repeat(line.length); // This string will hold the required information once tokenized
for(x = 0; x < regexObjs.length; x++){
let matches = [...line.matchAll(regexObjs[x].regex)];
matches.forEach((match) => {
// the <code> tag doesn't reconize '\n' symbols as characters when drawing the linear-gradient and thus we'll need to exclude them when writing the character index
rtrnText = rtrnText.replaceAt(match.index-(match.index-line.slice(0, match.index).replaceAll('\n', '').length), match[0].length, regexObjs[x].code);
});
}
return rtrnText;
}
function convertToCSS(line, regexObjs){
let rtrnString = 'linear-gradient(to right, ';
let previousChar = '';
let previousColour = 'white';
for(z = 0; z < line.length; z++){
if(line[z] != previousChar){
if(line[z] == 0){
rtrnString += previousColour + ' ' + z + 'ch, white ' + z + 'ch, ';
previousChar = '0';
previousColour = 'white';
}else{
for(a = 0; a < regexObjs.length; a++){
if(line[z] == regexObjs[a].code){
rtrnString += previousColour + ' ' + z + 'ch, ' + regexObjs[a].val + ' ' + z + 'ch, ';
previousChar = line[z];
previousColour = regexObjs[a].val;
}
}
}
}
}
rtrnString += 'white ' + line.replaceAll('\n', '').length + 'ch)';
return rtrnString;
}
console.log(convertToCSS(findTokens('char *str = "Hello world!";\nint main(int argc, char **argv)\n{\n printf("%s\n", str);\n return 0;\n}', cRegex), cRegex));