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";
|
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) {
|
function sourceCode(view: Element, codeData: string) {
|
||||||
const outerContainer = document.createElement("div");
|
const outerContainer = document.createElement("div");
|
||||||
outerContainer.classList.add("code-container");
|
outerContainer.classList.add("code-container");
|
||||||
@ -51,7 +245,7 @@ function sourceCode(view: Element, codeData: string) {
|
|||||||
const code = document.createElement("pre");
|
const code = document.createElement("pre");
|
||||||
|
|
||||||
code.classList.add("code-source");
|
code.classList.add("code-source");
|
||||||
code.innerText = codeData;
|
code.innerHTML = syntaxHighlight(codeData);
|
||||||
innerContainer.append(lines, code);
|
innerContainer.append(lines, code);
|
||||||
outerContainer.append(innerContainer);
|
outerContainer.append(innerContainer);
|
||||||
view.replaceChildren(outerContainer);
|
view.replaceChildren(outerContainer);
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
--white: #ecebe9;
|
--white: #ecebe9;
|
||||||
--white-transparent: #ecebe9aa;
|
--white-transparent: #ecebe9aa;
|
||||||
--code-status: var(--white);
|
--code-status: var(--white);
|
||||||
|
|
||||||
|
--code-bg: #282828;
|
||||||
|
--code-fg: #fbf1c7;
|
||||||
|
--code-linenr: #7c6f64;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@ -99,14 +103,19 @@ main #cover {
|
|||||||
#view .code-container {
|
#view .code-container {
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
background-color: var(--code-bg);
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#view .code-container pre {
|
#view .code-container pre {
|
||||||
font-family: "Roboto Mono", monospace;
|
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 {
|
#view .code-container.code-coverage {
|
||||||
@ -121,7 +130,6 @@ main #cover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#view .code-lines {
|
#view .code-lines {
|
||||||
color: var(--white-transparent);
|
|
||||||
border-right: 1px solid currentcolor;
|
border-right: 1px solid currentcolor;
|
||||||
padding-right: 0.5rem;
|
padding-right: 0.5rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user