Ship file viewer, editor improvements, and private package releases
This commit is contained in:
1 parent
645914955c
commit
a4a31032b9
158 files changed
+10523
-137
No files matched your search
@@ -1,37 +1,90 @@
|
||||
/** Read-only derived output. Loading this entry does not load CodeMirror until opened. */
|
||||
export async function mountBuilderSourceEditor(parent: HTMLElement, language: "text" | "xml", content: string) {
|
||||
const [{ EditorView, basicSetup }, { EditorState, Compartment }, { xml }, { HighlightStyle, syntaxHighlighting }, { tags }] = await Promise.all([
|
||||
import("codemirror"), import("@codemirror/state"), import("@codemirror/lang-xml"),
|
||||
import("@codemirror/language"), import("@lezer/highlight"),
|
||||
export async function mountBuilderSourceEditor(
|
||||
parent: HTMLElement,
|
||||
language: "text" | "xml",
|
||||
content: string,
|
||||
options: { label?: string; theme?: "tokens" } = {},
|
||||
) {
|
||||
const [
|
||||
{ EditorView, basicSetup },
|
||||
{ EditorState, Compartment },
|
||||
{ xml },
|
||||
{ HighlightStyle, syntaxHighlighting },
|
||||
{ tags },
|
||||
] = await Promise.all([
|
||||
import("codemirror"),
|
||||
import("@codemirror/state"),
|
||||
import("@codemirror/lang-xml"),
|
||||
import("@codemirror/language"),
|
||||
import("@lezer/highlight"),
|
||||
]);
|
||||
if (!parent.isConnected) return null;
|
||||
const stopShortcut = (event: KeyboardEvent) => event.stopPropagation();
|
||||
parent.addEventListener("keydown", stopShortcut);
|
||||
const wrapping = new Compartment();
|
||||
const view = new EditorView({ parent, doc: content, extensions: [
|
||||
basicSetup, EditorState.readOnly.of(true), EditorView.editable.of(false),
|
||||
EditorView.contentAttributes.of({ tabindex: "0", "aria-label": "Generated email source" }),
|
||||
language === "xml" ? xml() : [], wrapping.of([]),
|
||||
syntaxHighlighting(HighlightStyle.define([
|
||||
{ tag: tags.tagName, color: "#7dd3fc" }, { tag: tags.attributeName, color: "#c4b5fd" },
|
||||
{ tag: tags.attributeValue, color: "#a7f3d0" }, { tag: tags.angleBracket, color: "#94a3b8" },
|
||||
{ tag: tags.comment, color: "#94a3b8" },
|
||||
])),
|
||||
EditorView.theme({
|
||||
"&": { height: "100%", fontSize: "12px", backgroundColor: "#111827", color: "#e5e7eb" },
|
||||
".cm-scroller": { overflow: "auto", fontFamily: "ui-monospace, Consolas, monospace" },
|
||||
".cm-gutters": { backgroundColor: "#111827", color: "#94a3b8", borderColor: "#334155" },
|
||||
".cm-activeLine, .cm-activeLineGutter": { backgroundColor: "transparent" },
|
||||
"&.cm-focused": { outline: "2px solid var(--wrn-color-primary)", outlineOffset: "-2px" },
|
||||
}),
|
||||
] });
|
||||
const color = (token: string, legacy: string) =>
|
||||
options.theme === "tokens" ? `var(--wrn-color-${token})` : legacy;
|
||||
const view = new EditorView({
|
||||
parent,
|
||||
doc: content,
|
||||
extensions: [
|
||||
basicSetup,
|
||||
EditorState.readOnly.of(true),
|
||||
EditorView.editable.of(false),
|
||||
EditorView.contentAttributes.of({
|
||||
tabindex: "0",
|
||||
"aria-label": options.label ?? "Generated email source",
|
||||
}),
|
||||
language === "xml" ? xml() : [],
|
||||
wrapping.of([]),
|
||||
syntaxHighlighting(
|
||||
HighlightStyle.define([
|
||||
{ tag: tags.tagName, color: color("primary", "#7dd3fc") },
|
||||
{ tag: tags.attributeName, color: color("text", "#c4b5fd") },
|
||||
{ tag: tags.attributeValue, color: color("primary", "#a7f3d0") },
|
||||
{ tag: tags.angleBracket, color: color("muted", "#94a3b8") },
|
||||
{ tag: tags.comment, color: color("muted", "#94a3b8") },
|
||||
]),
|
||||
),
|
||||
EditorView.theme({
|
||||
"&": {
|
||||
height: "100%",
|
||||
fontSize: "12px",
|
||||
backgroundColor: color("surface", "#111827"),
|
||||
color: color("text", "#e5e7eb"),
|
||||
},
|
||||
".cm-scroller": { overflow: "auto", fontFamily: "ui-monospace, Consolas, monospace" },
|
||||
".cm-gutters": {
|
||||
backgroundColor: color("surface", "#111827"),
|
||||
color: color("muted", "#94a3b8"),
|
||||
borderColor: color("border", "#334155"),
|
||||
},
|
||||
".cm-activeLine, .cm-activeLineGutter": { backgroundColor: "transparent" },
|
||||
"&.cm-focused": { outline: "2px solid var(--wrn-color-primary)", outlineOffset: "-2px" },
|
||||
}),
|
||||
],
|
||||
});
|
||||
let destroyed = false;
|
||||
const observer = new MutationObserver(() => { if (!parent.isConnected) destroy(); });
|
||||
function destroy() { if (destroyed) return; destroyed = true; observer.disconnect(); parent.removeEventListener("keydown", stopShortcut); view.destroy(); }
|
||||
const observer = new MutationObserver(() => {
|
||||
if (!parent.isConnected) destroy();
|
||||
});
|
||||
function destroy() {
|
||||
if (destroyed) return;
|
||||
destroyed = true;
|
||||
observer.disconnect();
|
||||
parent.removeEventListener("keydown", stopShortcut);
|
||||
view.destroy();
|
||||
}
|
||||
observer.observe(parent.ownerDocument.documentElement, { childList: true, subtree: true });
|
||||
return {
|
||||
update(value: string) { if (!destroyed && view.state.doc.toString() !== value) view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: value } }); },
|
||||
wrap(enabled: boolean) { if (!destroyed) view.dispatch({ effects: wrapping.reconfigure(enabled ? EditorView.lineWrapping : []) }); },
|
||||
update(value: string) {
|
||||
if (!destroyed && view.state.doc.toString() !== value)
|
||||
view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: value } });
|
||||
},
|
||||
wrap(enabled: boolean) {
|
||||
if (!destroyed)
|
||||
view.dispatch({ effects: wrapping.reconfigure(enabled ? EditorView.lineWrapping : []) });
|
||||
},
|
||||
destroy,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user