feat: gaps in tailwind migration closed
This commit is contained in:
145
assets/js/monaco/languages.js
Normal file
145
assets/js/monaco/languages.js
Normal file
@@ -0,0 +1,145 @@
|
||||
let liquidLanguageRegistered = false;
|
||||
let markdownWithMacrosRegistered = false;
|
||||
|
||||
export const registerLiquidLanguage = (monaco) => {
|
||||
if (liquidLanguageRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
monaco.languages.register({ id: "liquid" });
|
||||
monaco.languages.setLanguageConfiguration("liquid", {
|
||||
comments: {
|
||||
blockComment: ["{% comment %}", "{% endcomment %}"]
|
||||
},
|
||||
brackets: [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
],
|
||||
autoClosingPairs: [
|
||||
{ open: "{", close: "}" },
|
||||
{ open: "[", close: "]" },
|
||||
{ open: "(", close: ")" },
|
||||
{ open: '"', close: '"' },
|
||||
{ open: "'", close: "'" }
|
||||
],
|
||||
surroundingPairs: [
|
||||
{ open: "{", close: "}" },
|
||||
{ open: "[", close: "]" },
|
||||
{ open: "(", close: ")" },
|
||||
{ open: '"', close: '"' },
|
||||
{ open: "'", close: "'" }
|
||||
]
|
||||
});
|
||||
|
||||
monaco.languages.setMonarchTokensProvider("liquid", {
|
||||
defaultToken: "",
|
||||
tokenizer: {
|
||||
root: [
|
||||
[/\{\{-?/, { token: "delimiter.output", next: "@liquidOutput" }],
|
||||
[/\{%-?\s*comment\b[^%]*-?%\}/, { token: "comment.block", next: "@liquidComment" }],
|
||||
[/\{%-?/, { token: "delimiter.tag", next: "@liquidTag" }],
|
||||
[/<!DOCTYPE/i, "metatag"],
|
||||
[/<!--/, { token: "comment", next: "@htmlComment" }],
|
||||
[/(<)(script)/i, ["delimiter.html", "tag.html"], "@scriptTag"],
|
||||
[/(<)(style)/i, ["delimiter.html", "tag.html"], "@styleTag"],
|
||||
[/(<\/)([\w:-]+)/, ["delimiter.html", "tag.html"]],
|
||||
[/(<)([\w:-]+)/, ["delimiter.html", "tag.html"], "@htmlTag"],
|
||||
[/[^<{]+/, ""],
|
||||
[/./, ""]
|
||||
],
|
||||
liquidOutput: [
|
||||
[/-?\}\}/, { token: "delimiter.output", next: "@pop" }],
|
||||
[/\|\s*[a-zA-Z_][\w-]*/, "keyword"],
|
||||
[/\b(?:true|false|nil|blank|empty)\b/, "keyword"],
|
||||
[/\b\d+(?:\.\d+)?\b/, "number"],
|
||||
[/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/, "string"],
|
||||
[/[a-zA-Z_][\w.-]*/, "identifier"],
|
||||
[/[,:()[\]]/, "delimiter"]
|
||||
],
|
||||
liquidTag: [
|
||||
[/-?%\}/, { token: "delimiter.tag", next: "@pop" }],
|
||||
[/\b(?:assign|capture|case|comment|cycle|decrement|echo|elsif|else|endcase|endcapture|endif|endfor|endunless|endcomment|for|if|include|increment|liquid|paginate|raw|render|tablerow|unless|when)\b/, "keyword"],
|
||||
[/\|\s*[a-zA-Z_][\w-]*/, "keyword"],
|
||||
[/\b(?:true|false|nil|blank|empty|contains)\b/, "keyword"],
|
||||
[/\b\d+(?:\.\d+)?\b/, "number"],
|
||||
[/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/, "string"],
|
||||
[/[><=!]=?|\.|:/, "operator"],
|
||||
[/[a-zA-Z_][\w.-]*/, "identifier"],
|
||||
[/[,:()[\]]/, "delimiter"]
|
||||
],
|
||||
liquidComment: [
|
||||
[/\{%-?\s*endcomment\s*-?%\}/, { token: "comment.block", next: "@pop" }],
|
||||
[/./, "comment.block"]
|
||||
],
|
||||
htmlComment: [
|
||||
[/-->/, { token: "comment", next: "@pop" }],
|
||||
[/./, "comment"]
|
||||
],
|
||||
htmlTag: [
|
||||
[/\/>/, { token: "delimiter.html", next: "@pop" }],
|
||||
[/>/, { token: "delimiter.html", next: "@pop" }],
|
||||
[/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/, "attribute.value"],
|
||||
[/[\w:-]+/, "attribute.name"],
|
||||
[/=/, "delimiter"]
|
||||
],
|
||||
scriptTag: [
|
||||
[/>/, { token: "delimiter.html", next: "@pop" }],
|
||||
[/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/, "attribute.value"],
|
||||
[/[\w:-]+/, "attribute.name"],
|
||||
[/=/, "delimiter"]
|
||||
],
|
||||
styleTag: [
|
||||
[/>/, { token: "delimiter.html", next: "@pop" }],
|
||||
[/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/, "attribute.value"],
|
||||
[/[\w:-]+/, "attribute.name"],
|
||||
[/=/, "delimiter"]
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
liquidLanguageRegistered = true;
|
||||
};
|
||||
|
||||
export const registerMarkdownWithMacrosLanguage = (monaco) => {
|
||||
if (markdownWithMacrosRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
monaco.languages.register({ id: "markdown-with-macros" });
|
||||
monaco.languages.setMonarchTokensProvider("markdown-with-macros", {
|
||||
defaultToken: "",
|
||||
tokenPostfix: ".md",
|
||||
tokenizer: {
|
||||
root: [
|
||||
[/\[\[[a-zA-Z][\w-]*/, { token: "keyword.macro", next: "@macroParams" }],
|
||||
[/^#{1,6}\s.*$/, "keyword.header"],
|
||||
[/^\s*>+/, "string.quote"],
|
||||
[/^\s*[-+*]\s/, "keyword"],
|
||||
[/^\s*\d+\.\s/, "keyword"],
|
||||
[/^\s*```\w*/, { token: "string.code", next: "@codeblock" }],
|
||||
[/\*\*[^*]+\*\*/, "strong"],
|
||||
[/\*[^*]+\*/, "emphasis"],
|
||||
[/__[^_]+__/, "strong"],
|
||||
[/_[^_]+_/, "emphasis"],
|
||||
[/`[^`]+`/, "variable"],
|
||||
[/!?\[[^\]]*\]\([^)]*\)/, "string.link"],
|
||||
[/!?\[[^\]]*\]\[[^\]]*\]/, "string.link"]
|
||||
],
|
||||
macroParams: [
|
||||
[/\]\]/, { token: "keyword.macro", next: "@root" }],
|
||||
[/[a-zA-Z][\w-]*(?=\s*=)/, "attribute.name"],
|
||||
[/=/, "delimiter"],
|
||||
[/"[^"]*"/, "string"],
|
||||
[/\s+/, "white"],
|
||||
[/[^\]"=\s]+/, "attribute.value"]
|
||||
],
|
||||
codeblock: [
|
||||
[/^\s*```\s*$/, { token: "string.code", next: "@root" }],
|
||||
[/.*$/, "variable.source"]
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
markdownWithMacrosRegistered = true;
|
||||
};
|
||||
@@ -1 +1,88 @@
|
||||
export const createMonacoServices = (services) => services;
|
||||
import { loadScript } from "../utils/script_loader.js";
|
||||
import { ensureMonacoTheme } from "./theme.js";
|
||||
import { registerLiquidLanguage, registerMarkdownWithMacrosLanguage } from "./languages.js";
|
||||
|
||||
let monacoLoaderPromise;
|
||||
const monacoEditors = new Map();
|
||||
|
||||
export const loadMonaco = () => {
|
||||
if (window.monaco?.editor) {
|
||||
ensureMonacoTheme(window.monaco);
|
||||
registerLiquidLanguage(window.monaco);
|
||||
registerMarkdownWithMacrosLanguage(window.monaco);
|
||||
return Promise.resolve(window.monaco);
|
||||
}
|
||||
|
||||
if (monacoLoaderPromise) {
|
||||
return monacoLoaderPromise;
|
||||
}
|
||||
|
||||
monacoLoaderPromise = loadScript("/monaco/vs/loader.js")
|
||||
.then(
|
||||
() =>
|
||||
new Promise((resolve, reject) => {
|
||||
window.require.config({ paths: { vs: "/monaco/vs" } });
|
||||
window.require(["vs/editor/editor.main"], () => {
|
||||
ensureMonacoTheme(window.monaco);
|
||||
registerLiquidLanguage(window.monaco);
|
||||
registerMarkdownWithMacrosLanguage(window.monaco);
|
||||
resolve(window.monaco);
|
||||
}, reject);
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
monacoLoaderPromise = null;
|
||||
throw error;
|
||||
});
|
||||
|
||||
return monacoLoaderPromise;
|
||||
};
|
||||
|
||||
export const registerMonacoEditor = (key, editor) => {
|
||||
if (key) {
|
||||
monacoEditors.set(key, editor);
|
||||
}
|
||||
};
|
||||
|
||||
export const unregisterMonacoEditor = (key) => {
|
||||
if (key) {
|
||||
monacoEditors.delete(key);
|
||||
}
|
||||
};
|
||||
|
||||
export const activeMonacoEditor = () => {
|
||||
for (const editor of monacoEditors.values()) {
|
||||
if (typeof editor?.hasTextFocus === "function" && editor.hasTextFocus()) {
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const runMonacoEditorAction = (editor, actionId, triggerId = actionId) => {
|
||||
if (!editor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const action = typeof editor.getAction === "function" ? editor.getAction(actionId) : null;
|
||||
|
||||
if (action && typeof action.run === "function") {
|
||||
action.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof editor.trigger === "function") {
|
||||
editor.trigger("bds-menu", triggerId, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
export const diffModelPath = (filePath, side) => {
|
||||
const normalized = String(filePath || "working-tree").replace(/^\/+/, "");
|
||||
return `inmemory://model/git-diff/${side}/${normalized}`;
|
||||
};
|
||||
|
||||
export { ensureMonacoTheme };
|
||||
|
||||
62
assets/js/monaco/theme.js
Normal file
62
assets/js/monaco/theme.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import { cssVar, normalizeMonacoColor } from "../utils/color.js";
|
||||
|
||||
let monacoThemeSignature = null;
|
||||
|
||||
export const ensureMonacoTheme = (monaco) => {
|
||||
const background = normalizeMonacoColor(
|
||||
cssVar("--vscode-editor-background", cssVar("--vscode-input-background", "#1e1e1e")),
|
||||
"#1e1e1e"
|
||||
);
|
||||
const foreground = normalizeMonacoColor(cssVar("--vscode-editor-foreground", "#d4d4d4"), "#d4d4d4");
|
||||
const lineNumber = normalizeMonacoColor(cssVar("--vscode-editorLineNumber-foreground", "#858585"), "#858585");
|
||||
const activeLineNumber = normalizeMonacoColor(
|
||||
cssVar("--vscode-editorLineNumber-activeForeground", foreground),
|
||||
foreground
|
||||
);
|
||||
const selection = normalizeMonacoColor(cssVar("--vscode-editor-selectionBackground", "#264f78"), "#264f78");
|
||||
const inactiveSelection = normalizeMonacoColor(
|
||||
cssVar("--vscode-editor-inactiveSelectionBackground", "#3a3d41"),
|
||||
"#3a3d41"
|
||||
);
|
||||
const cursor = normalizeMonacoColor(cssVar("--vscode-editorCursor-foreground", foreground), foreground);
|
||||
const border = normalizeMonacoColor(cssVar("--vscode-panel-border", "#3c3c3c"), "#3c3c3c");
|
||||
const lineHighlight = normalizeMonacoColor(
|
||||
cssVar("--vscode-editor-lineHighlightBackground", background),
|
||||
background
|
||||
);
|
||||
const signature = [background, foreground, lineNumber, activeLineNumber, selection, inactiveSelection, cursor, border].join("|");
|
||||
|
||||
if (signature === monacoThemeSignature) {
|
||||
monaco.editor.setTheme("bds-theme");
|
||||
return;
|
||||
}
|
||||
|
||||
monaco.editor.defineTheme("bds-theme", {
|
||||
base: "vs-dark",
|
||||
inherit: true,
|
||||
rules: [
|
||||
{ token: "keyword.macro", foreground: "C586C0", fontStyle: "bold" },
|
||||
{ token: "attribute.name", foreground: "9CDCFE" },
|
||||
{ token: "attribute.value", foreground: "CE9178" }
|
||||
],
|
||||
colors: {
|
||||
"editor.background": background,
|
||||
"editor.foreground": foreground,
|
||||
"editor.lineHighlightBackground": lineHighlight,
|
||||
"editorCursor.foreground": cursor,
|
||||
"editor.selectionBackground": selection,
|
||||
"editor.inactiveSelectionBackground": inactiveSelection,
|
||||
"editorLineNumber.foreground": lineNumber,
|
||||
"editorLineNumber.activeForeground": activeLineNumber,
|
||||
"editorIndentGuide.background1": border,
|
||||
"editorIndentGuide.activeBackground1": foreground,
|
||||
"editorWidget.border": border,
|
||||
"editorGutter.background": background,
|
||||
"focusBorder": border,
|
||||
"input.border": border
|
||||
}
|
||||
});
|
||||
|
||||
monacoThemeSignature = signature;
|
||||
monaco.editor.setTheme("bds-theme");
|
||||
};
|
||||
Reference in New Issue
Block a user