mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 12:46:31 +00:00
add syntax highlighting
This commit is contained in:
parent
77c01e12a5
commit
fee5666971
@ -40,6 +40,200 @@ async function checkStatus(): Promise<"running" | "done"> {
|
||||
return "done";
|
||||
}
|
||||
|
||||
function syntaxHighlight(code: string): string {
|
||||
const colors = {
|
||||
colorBackground: "#282828",
|
||||
colorForeground: "#fbf1c7",
|
||||
colorKeyword: "#fb4934",
|
||||
colorIdentifier: "#83a598",
|
||||
colorOperator: "#fe8019",
|
||||
colorSpecial: "#fe8019",
|
||||
colorType: "#fabd2f",
|
||||
colorBoolean: "#d3869b",
|
||||
colorNumber: "#d3869b",
|
||||
colorString: "#b8bb26",
|
||||
colorComment: "#928374",
|
||||
colorFunction: "#b8bb26",
|
||||
colorLineNumber: "#7c6f64",
|
||||
} as const;
|
||||
|
||||
/*
|
||||
Keyword = { link = "GruvboxRed" },
|
||||
Identifier = { link = "GruvboxBlue" },
|
||||
Operator = { fg = colors.orange, italic = config.italic.operators },
|
||||
Special = { link = "GruvboxOrange" },
|
||||
Type = { link = "GruvboxYellow" },
|
||||
Boolean = { link = "GruvboxPurple" },
|
||||
Number = { link = "GruvboxPurple" },
|
||||
String = { fg = colors.green, italic = config.italic.strings },
|
||||
Comment = { fg = colors.gray, italic = config.italic.comments },
|
||||
Function = { link = "GruvboxGreenBold" },
|
||||
*/
|
||||
|
||||
let matches: {
|
||||
index: number;
|
||||
length: number;
|
||||
color: string;
|
||||
extra: string;
|
||||
}[] = [];
|
||||
|
||||
function addMatches(color: string, re: RegExp, extra = "") {
|
||||
for (const match of code.matchAll(re)) {
|
||||
matches.push({
|
||||
index: match.index,
|
||||
length: match[1].length,
|
||||
color,
|
||||
extra,
|
||||
});
|
||||
}
|
||||
}
|
||||
function addKeywordMatches(color: string, keywords: string[]) {
|
||||
addMatches(
|
||||
color,
|
||||
new RegExp(
|
||||
`(?<!\\w)(${
|
||||
keywords.map((kw) => `(?:${kw})`).join("|")
|
||||
})(?!\\w)`,
|
||||
"g",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
for (let i = 0; i < code.length; ++i) {
|
||||
if (code[i] !== '"') {
|
||||
continue;
|
||||
}
|
||||
let last = code[i];
|
||||
const index = i;
|
||||
i += 1;
|
||||
while (i < code.length && !(code[i] === '"' && last !== "\\")) {
|
||||
last = code[i];
|
||||
i += 1;
|
||||
}
|
||||
if (i < code.length) {
|
||||
i += 1;
|
||||
}
|
||||
matches.push({
|
||||
index,
|
||||
length: i - index,
|
||||
color: colors.colorString,
|
||||
extra: "font-style: italic;",
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let last = "";
|
||||
for (let i = 0; i < code.length; ++i) {
|
||||
if (last === "/" && code[i] === "/") {
|
||||
const index = i - 1;
|
||||
while (i < code.length && code[i] !== "\n") {
|
||||
i += 1;
|
||||
}
|
||||
matches.push({
|
||||
index,
|
||||
length: i - index,
|
||||
color: colors.colorComment,
|
||||
extra: "font-style: italic;",
|
||||
});
|
||||
}
|
||||
last = code[i];
|
||||
}
|
||||
}
|
||||
|
||||
addKeywordMatches(
|
||||
colors.colorKeyword,
|
||||
[
|
||||
"break",
|
||||
"return",
|
||||
"let",
|
||||
"fn",
|
||||
"if",
|
||||
"else",
|
||||
"struct",
|
||||
"import",
|
||||
"or",
|
||||
"and",
|
||||
"not",
|
||||
"while",
|
||||
"for",
|
||||
"in",
|
||||
],
|
||||
);
|
||||
addKeywordMatches(colors.colorSpecial, ["null"]);
|
||||
addKeywordMatches(colors.colorType, ["int", "string", "bool"]);
|
||||
addKeywordMatches(colors.colorBoolean, ["false", "true"]);
|
||||
addMatches(
|
||||
colors.colorOperator,
|
||||
new RegExp(
|
||||
`(${
|
||||
[
|
||||
"\\+=",
|
||||
"\\-=",
|
||||
"\\+",
|
||||
"\\->",
|
||||
"\\-",
|
||||
"\\*",
|
||||
"/",
|
||||
"==",
|
||||
"!=",
|
||||
"<=",
|
||||
">=",
|
||||
"=",
|
||||
"<",
|
||||
">",
|
||||
"\\.",
|
||||
"::<",
|
||||
"::",
|
||||
":",
|
||||
].map((kw) => `(?:${kw})`).join("|")
|
||||
})`,
|
||||
"g",
|
||||
),
|
||||
);
|
||||
addMatches(
|
||||
colors.colorNumber,
|
||||
/(0|(?:[1-9][0-9]*)|(?:0[0-7]+)|(?:0x[0-9a-fA-F]+)|(?:0b[01]+))/g,
|
||||
);
|
||||
addMatches(
|
||||
colors.colorFunction,
|
||||
/([a-zA-Z_]\w*(?=\())/g,
|
||||
"font-weight: 700;",
|
||||
);
|
||||
addMatches(colors.colorIdentifier, /([a-z_]\w*)/g);
|
||||
addMatches(colors.colorType, /([A-Z_]\w*)/g);
|
||||
|
||||
matches = matches.reduce<typeof matches>(
|
||||
(acc, match) =>
|
||||
acc.find((m) => m.index === match.index) === undefined
|
||||
? (acc.push(match), acc)
|
||||
: acc,
|
||||
[],
|
||||
);
|
||||
matches.sort((a, b) => a.index - b.index);
|
||||
|
||||
let highlighted = "";
|
||||
let i = 0;
|
||||
for (const match of matches) {
|
||||
if (match.index < i) {
|
||||
continue;
|
||||
}
|
||||
while (i < match.index) {
|
||||
highlighted += code[i];
|
||||
i += 1;
|
||||
}
|
||||
const section = code.slice(match.index, match.index + match.length);
|
||||
highlighted +=
|
||||
`<span style="color: ${match.color};${match.extra}">${section}</span>`;
|
||||
i += section.length;
|
||||
}
|
||||
while (i < code.length) {
|
||||
highlighted += code[i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return highlighted;
|
||||
}
|
||||
|
||||
function sourceCode(view: Element, codeData: string) {
|
||||
const outerContainer = document.createElement("div");
|
||||
outerContainer.classList.add("code-container");
|
||||
@ -51,7 +245,7 @@ function sourceCode(view: Element, codeData: string) {
|
||||
const code = document.createElement("pre");
|
||||
|
||||
code.classList.add("code-source");
|
||||
code.innerText = codeData;
|
||||
code.innerHTML = syntaxHighlight(codeData);
|
||||
innerContainer.append(lines, code);
|
||||
outerContainer.append(innerContainer);
|
||||
view.replaceChildren(outerContainer);
|
||||
|
@ -11,6 +11,10 @@
|
||||
--white: #ecebe9;
|
||||
--white-transparent: #ecebe9aa;
|
||||
--code-status: var(--white);
|
||||
|
||||
--code-bg: #282828;
|
||||
--code-fg: #fbf1c7;
|
||||
--code-linenr: #7c6f64;
|
||||
}
|
||||
|
||||
* {
|
||||
@ -99,14 +103,19 @@ main #cover {
|
||||
#view .code-container {
|
||||
max-height: 100%;
|
||||
overflow: scroll;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
background-color: var(--code-bg);
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
#view .code-container pre {
|
||||
font-family: "Roboto Mono", monospace;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
color: var(--code-fg);
|
||||
}
|
||||
|
||||
#view .code-container pre.code-lines {
|
||||
color: var(--code-linenr);
|
||||
}
|
||||
|
||||
#view .code-container.code-coverage {
|
||||
@ -121,7 +130,6 @@ main #cover {
|
||||
}
|
||||
|
||||
#view .code-lines {
|
||||
color: var(--white-transparent);
|
||||
border-right: 1px solid currentcolor;
|
||||
padding-right: 0.5rem;
|
||||
margin: 0;
|
||||
|
Loading…
Reference in New Issue
Block a user