@sdboyer/thema-ui 0.0.0-bootstrap.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +24 -1
- package/dist/Diagnostics.d.ts +8 -0
- package/dist/Diagnostics.js +14 -0
- package/dist/Editor.d.ts +12 -0
- package/dist/Editor.js +95 -0
- package/dist/OpBar.d.ts +14 -0
- package/dist/OpBar.js +15 -0
- package/dist/Output.d.ts +20 -0
- package/dist/Output.js +56 -0
- package/dist/Tabs.d.ts +15 -0
- package/dist/Tabs.js +23 -0
- package/dist/cue-lang.d.ts +8 -0
- package/dist/cue-lang.js +82 -0
- package/dist/docs.d.ts +64 -0
- package/dist/docs.js +42 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +18 -0
- package/dist/markers.d.ts +11 -0
- package/dist/markers.js +45 -0
- package/dist/ops.d.ts +13 -0
- package/dist/ops.js +22 -0
- package/dist/positions.d.ts +7 -0
- package/dist/positions.js +40 -0
- package/dist/theme.d.ts +16 -0
- package/dist/theme.js +55 -0
- package/dist/types.d.ts +580 -0
- package/dist/types.js +85 -0
- package/errors/E0101.md +43 -0
- package/errors/E0102.md +34 -0
- package/errors/E0103.md +41 -0
- package/errors/E0104.md +5 -0
- package/errors/E0105.md +62 -0
- package/errors/E0106.md +46 -0
- package/errors/E0107.md +48 -0
- package/errors/E0108.md +45 -0
- package/errors/E0109.md +37 -0
- package/errors/E0110.md +17 -0
- package/errors/E0111.md +55 -0
- package/errors/E0112.md +40 -0
- package/errors/E0120.md +34 -0
- package/errors/E0121.md +34 -0
- package/errors/E0122.md +26 -0
- package/errors/E0123.md +37 -0
- package/errors/E0124.md +36 -0
- package/errors/E0125.md +43 -0
- package/errors/E0126.md +38 -0
- package/errors/E0128.md +34 -0
- package/errors/E0129.md +42 -0
- package/errors/E0130.md +43 -0
- package/errors/E0131.md +42 -0
- package/errors/E0132.md +40 -0
- package/errors/E0133.md +46 -0
- package/errors/E0134.md +36 -0
- package/errors/E0135.md +109 -0
- package/errors/E0137.md +37 -0
- package/errors/E0140.md +46 -0
- package/errors/E0141.md +35 -0
- package/errors/E0142.md +38 -0
- package/errors/E0143.md +62 -0
- package/errors/E0144.md +49 -0
- package/errors/E0145.md +48 -0
- package/errors/E0146.md +38 -0
- package/errors/E0147.md +57 -0
- package/errors/E0148.md +42 -0
- package/errors/E0149.md +27 -0
- package/errors/E0150.md +77 -0
- package/errors/E0151.md +47 -0
- package/errors/E0152.md +35 -0
- package/errors/E0201.md +35 -0
- package/errors/E0202.md +42 -0
- package/errors/E0203.md +37 -0
- package/errors/E0204.md +46 -0
- package/errors/E0205.md +47 -0
- package/errors/E0206.md +47 -0
- package/errors/E0208.md +59 -0
- package/errors/E0210.md +44 -0
- package/errors/E0211.md +43 -0
- package/errors/E0212.md +41 -0
- package/errors/E0213.md +42 -0
- package/errors/E0214.md +42 -0
- package/errors/E0215.md +44 -0
- package/errors/E0216.md +41 -0
- package/errors/E0217.md +43 -0
- package/errors/E0218.md +44 -0
- package/errors/E0230.md +46 -0
- package/errors/E0232.md +42 -0
- package/errors/E0233.md +42 -0
- package/errors/E0234.md +43 -0
- package/errors/E0240.md +31 -0
- package/errors/E0242.md +5 -0
- package/errors/E0243.md +5 -0
- package/errors/E0250.md +39 -0
- package/errors/E0251.md +83 -0
- package/errors/E0252.md +42 -0
- package/errors/E0253.md +142 -0
- package/errors/E0254.md +38 -0
- package/errors/E0301.md +43 -0
- package/errors/E0302.md +58 -0
- package/errors/E0303.md +57 -0
- package/errors/E0304.md +9 -0
- package/errors/E0305.md +55 -0
- package/errors/E0307.md +9 -0
- package/errors/E0308.md +9 -0
- package/errors/E0310.md +46 -0
- package/errors/E0311.md +46 -0
- package/errors/E0330.md +67 -0
- package/errors/E0331.md +64 -0
- package/errors/E0332.md +52 -0
- package/errors/E0333.md +61 -0
- package/errors/E0334.md +61 -0
- package/errors/E0335.md +57 -0
- package/errors/E0336.md +50 -0
- package/errors/E0337.md +54 -0
- package/errors/E0338.md +62 -0
- package/errors/E0340.md +57 -0
- package/errors/E0341.md +51 -0
- package/errors/E0342.md +53 -0
- package/errors/E0343.md +56 -0
- package/errors/E0344.md +58 -0
- package/errors/E0345.md +51 -0
- package/errors/E0346.md +45 -0
- package/errors/E0347.md +53 -0
- package/errors/E0348.md +50 -0
- package/errors/E0349.md +52 -0
- package/errors/E0350.md +54 -0
- package/errors/E0351.md +54 -0
- package/errors/E0352.md +60 -0
- package/errors/E0353.md +53 -0
- package/errors/E0354.md +43 -0
- package/errors/E0355.md +55 -0
- package/errors/E0356.md +65 -0
- package/errors/E0357.md +68 -0
- package/errors/E0358.md +50 -0
- package/errors/E0359.md +53 -0
- package/errors/E0360.md +59 -0
- package/errors/E0361.md +59 -0
- package/errors/E0362.md +56 -0
- package/errors/E0364.md +58 -0
- package/errors/E0365.md +58 -0
- package/errors/E0366.md +56 -0
- package/errors/E0367.md +57 -0
- package/errors/E0368.md +58 -0
- package/errors/E0369.md +60 -0
- package/errors/E0370.md +59 -0
- package/errors/E0371.md +59 -0
- package/errors/E0372.md +57 -0
- package/errors/E0380.md +71 -0
- package/errors/E0381.md +61 -0
- package/errors/E0382.md +64 -0
- package/errors/E0383.md +61 -0
- package/errors/E0384.md +63 -0
- package/errors/E0385.md +61 -0
- package/errors/E0386.md +59 -0
- package/errors/E0387.md +59 -0
- package/errors/E0388.md +60 -0
- package/errors/E0389.md +59 -0
- package/errors/E0390.md +59 -0
- package/errors/E0401.md +56 -0
- package/errors/E0402.md +51 -0
- package/errors/E0403.md +51 -0
- package/errors/E0404.md +57 -0
- package/errors/E0405.md +56 -0
- package/errors/E0406.md +53 -0
- package/errors/E0407.md +54 -0
- package/errors/E0410.md +56 -0
- package/errors/E0411.md +59 -0
- package/errors/E0412.md +59 -0
- package/errors/E0413.md +74 -0
- package/errors/E0414.md +53 -0
- package/errors/E0415.md +72 -0
- package/errors/E0416.md +67 -0
- package/errors/E0418.md +59 -0
- package/errors/E0420.md +71 -0
- package/errors/E0421.md +82 -0
- package/errors/E0422.md +82 -0
- package/errors/E0423.md +83 -0
- package/errors/E0501.md +51 -0
- package/errors/E0502.md +50 -0
- package/errors/E0503.md +52 -0
- package/errors/E0504.md +64 -0
- package/errors/E0505.md +51 -0
- package/errors/E0506.md +48 -0
- package/errors/E0507.md +41 -0
- package/errors/E0508.md +39 -0
- package/errors/E0601.md +22 -0
- package/errors/E0602.md +28 -0
- package/errors/E0603.md +65 -0
- package/errors/E0604.md +37 -0
- package/errors/E0605.md +36 -0
- package/errors/E0606.md +44 -0
- package/errors/E0607.md +57 -0
- package/errors/E0608.md +37 -0
- package/errors/E0609.md +33 -0
- package/errors/E0611.md +37 -0
- package/errors/E0612.md +34 -0
- package/errors/E0613.md +30 -0
- package/errors/E0614.md +36 -0
- package/errors/E0616.md +33 -0
- package/errors/E0617.md +15 -0
- package/errors/E0618.md +16 -0
- package/errors/E0620.md +37 -0
- package/errors/E0621.md +45 -0
- package/errors/E0622.md +34 -0
- package/errors/E0623.md +33 -0
- package/errors/E0624.md +34 -0
- package/errors/E0625.md +28 -0
- package/errors/E0626.md +54 -0
- package/errors/E0627.md +27 -0
- package/errors/E0628.md +63 -0
- package/errors/E0701.md +25 -0
- package/errors/E0801.md +23 -0
- package/errors/E0802.md +22 -0
- package/errors/E0803.md +22 -0
- package/errors/E0804.md +25 -0
- package/errors/E0805.md +26 -0
- package/errors/E0901.md +27 -0
- package/errors/E0902.md +40 -0
- package/errors/E0903.md +23 -0
- package/errors/E1001.md +53 -0
- package/errors/E1002.md +43 -0
- package/errors/E1003.md +40 -0
- package/errors/E1004.md +44 -0
- package/errors/README.md +215 -0
- package/package.json +29 -3
package/dist/docs.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export declare const docsBase = "https://github.com/sdboyer/thema/blob/main/docs/";
|
|
2
|
+
export declare function themaDoc(path: string): string;
|
|
3
|
+
export interface Doc {
|
|
4
|
+
href: string;
|
|
5
|
+
title: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const docs: {
|
|
8
|
+
lineage: {
|
|
9
|
+
href: string;
|
|
10
|
+
title: string;
|
|
11
|
+
};
|
|
12
|
+
versions: {
|
|
13
|
+
href: string;
|
|
14
|
+
title: string;
|
|
15
|
+
};
|
|
16
|
+
forms: {
|
|
17
|
+
href: string;
|
|
18
|
+
title: string;
|
|
19
|
+
};
|
|
20
|
+
bind: {
|
|
21
|
+
href: string;
|
|
22
|
+
title: string;
|
|
23
|
+
};
|
|
24
|
+
validate: {
|
|
25
|
+
href: string;
|
|
26
|
+
title: string;
|
|
27
|
+
};
|
|
28
|
+
"validate-any": {
|
|
29
|
+
href: string;
|
|
30
|
+
title: string;
|
|
31
|
+
};
|
|
32
|
+
translate: {
|
|
33
|
+
href: string;
|
|
34
|
+
title: string;
|
|
35
|
+
};
|
|
36
|
+
openapi: {
|
|
37
|
+
href: string;
|
|
38
|
+
title: string;
|
|
39
|
+
};
|
|
40
|
+
jsonschema: {
|
|
41
|
+
href: string;
|
|
42
|
+
title: string;
|
|
43
|
+
};
|
|
44
|
+
typescript: {
|
|
45
|
+
href: string;
|
|
46
|
+
title: string;
|
|
47
|
+
};
|
|
48
|
+
lacunas: {
|
|
49
|
+
href: string;
|
|
50
|
+
title: string;
|
|
51
|
+
};
|
|
52
|
+
diagnostics: {
|
|
53
|
+
href: string;
|
|
54
|
+
title: string;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
export type Topic = keyof typeof docs;
|
|
58
|
+
export declare function hasDoc(name: string): name is Topic;
|
|
59
|
+
export declare function lacunaTypeDoc(type: string): Doc;
|
|
60
|
+
export declare function DocLink(props: {
|
|
61
|
+
topic: Topic;
|
|
62
|
+
} | {
|
|
63
|
+
doc: Doc;
|
|
64
|
+
}): import("preact").JSX.Element;
|
package/dist/docs.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
// Where the page points for what thema's terms mean: thema's own docs, which
|
|
3
|
+
// live in this tree beside the playground, and pkg.go.dev for what only the
|
|
4
|
+
// Go API documents.
|
|
5
|
+
// docsBase is where thema's docs/ is published.
|
|
6
|
+
export const docsBase = "https://github.com/sdboyer/thema/blob/main/docs/";
|
|
7
|
+
// themaDoc is the URL of a file under thema's docs/.
|
|
8
|
+
export function themaDoc(path) {
|
|
9
|
+
return docsBase + path;
|
|
10
|
+
}
|
|
11
|
+
// ref is the URL of an entry in thema's reference docs, docs/reference/.
|
|
12
|
+
function ref(page, anchor = "") {
|
|
13
|
+
return themaDoc(`reference/${page}${anchor ? "#" + anchor : ""}`);
|
|
14
|
+
}
|
|
15
|
+
// docs are the terms the page links to their reference entries. Operations
|
|
16
|
+
// are keyed by their names.
|
|
17
|
+
export const docs = {
|
|
18
|
+
lineage: { href: ref("lineage.md"), title: "Lineages" },
|
|
19
|
+
versions: { href: ref("lineage.md", "versions"), title: "Versions, minor and major" },
|
|
20
|
+
forms: { href: ref("lineage.md", "forms"), title: "The normal form and the authoring form" },
|
|
21
|
+
bind: { href: ref("lineage.md", "binding"), title: "Binding: what thema checks of a lineage" },
|
|
22
|
+
validate: { href: ref("operations.md", "validate"), title: "validate" },
|
|
23
|
+
"validate-any": { href: ref("operations.md", "validate-any"), title: "validate-any" },
|
|
24
|
+
translate: { href: ref("operations.md", "translate"), title: "translate" },
|
|
25
|
+
openapi: { href: ref("codegen.md", "openapi"), title: "Generating OpenAPI" },
|
|
26
|
+
jsonschema: { href: ref("codegen.md", "json-schema"), title: "Generating JSON Schema" },
|
|
27
|
+
typescript: { href: ref("codegen.md", "typescript"), title: "Generating TypeScript" },
|
|
28
|
+
lacunas: { href: ref("lacunas.md"), title: "Lacunas" },
|
|
29
|
+
diagnostics: { href: themaDoc("errors/README.md"), title: "Diagnostic codes" },
|
|
30
|
+
};
|
|
31
|
+
export function hasDoc(name) {
|
|
32
|
+
return Object.hasOwn(docs, name);
|
|
33
|
+
}
|
|
34
|
+
// lacunaTypeDoc is the reference entry for a lacuna type.
|
|
35
|
+
export function lacunaTypeDoc(type) {
|
|
36
|
+
return { href: ref("lacunas.md", type.toLowerCase()), title: `The ${type} lacuna type` };
|
|
37
|
+
}
|
|
38
|
+
// DocLink is the small ? beside a term, opening its reference entry.
|
|
39
|
+
export function DocLink(props) {
|
|
40
|
+
const d = "doc" in props ? props.doc : docs[props.topic];
|
|
41
|
+
return (_jsx("a", { class: "doc-link", href: d.href, target: "_blank", rel: "noreferrer", title: d.title, "aria-label": `Reference: ${d.title}`, children: "?" }));
|
|
42
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./cue-lang";
|
|
2
|
+
export * from "./Diagnostics";
|
|
3
|
+
export * from "./docs";
|
|
4
|
+
export * from "./Editor";
|
|
5
|
+
export * from "./markers";
|
|
6
|
+
export * from "./OpBar";
|
|
7
|
+
export * from "./ops";
|
|
8
|
+
export * from "./Output";
|
|
9
|
+
export * from "./positions";
|
|
10
|
+
export * from "./Tabs";
|
|
11
|
+
export * from "./theme";
|
|
12
|
+
export * from "./types";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// The pieces of the thema playground's frontend that other tools build on:
|
|
2
|
+
// the CUE language mode, the editor and its theme, diagnostics shown in place,
|
|
3
|
+
// the operations bar, tabs and an operation's output, and the wire types of
|
|
4
|
+
// thema's diagnostics and session API. The playground
|
|
5
|
+
// itself imports everything it shares from here, so this is exactly what it
|
|
6
|
+
// uses.
|
|
7
|
+
export * from "./cue-lang";
|
|
8
|
+
export * from "./Diagnostics";
|
|
9
|
+
export * from "./docs";
|
|
10
|
+
export * from "./Editor";
|
|
11
|
+
export * from "./markers";
|
|
12
|
+
export * from "./OpBar";
|
|
13
|
+
export * from "./ops";
|
|
14
|
+
export * from "./Output";
|
|
15
|
+
export * from "./positions";
|
|
16
|
+
export * from "./Tabs";
|
|
17
|
+
export * from "./theme";
|
|
18
|
+
export * from "./types";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Diagnostic } from "./types";
|
|
2
|
+
export interface Marker {
|
|
3
|
+
from: number;
|
|
4
|
+
to: number;
|
|
5
|
+
severity: "error" | "warning" | "info";
|
|
6
|
+
message: string;
|
|
7
|
+
code: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function markersFor(ds: readonly Diagnostic[], file: string, text: string): Marker[];
|
|
10
|
+
export declare function docsURL(code: string): string;
|
|
11
|
+
export declare function filesOf(ds: readonly Diagnostic[]): Set<string>;
|
package/dist/markers.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { themaDoc } from "./docs";
|
|
2
|
+
import { offsetOf, spanAt } from "./positions";
|
|
3
|
+
export function markersFor(ds, file, text) {
|
|
4
|
+
const out = [];
|
|
5
|
+
const at = (p) => {
|
|
6
|
+
if (!p || p.file !== file || p.origin === "thema")
|
|
7
|
+
return null;
|
|
8
|
+
const off = offsetOf(text, p);
|
|
9
|
+
return off === null ? null : spanAt(text, off);
|
|
10
|
+
};
|
|
11
|
+
for (const d of ds) {
|
|
12
|
+
const primary = at(d.primary);
|
|
13
|
+
if (primary) {
|
|
14
|
+
const extra = [...(d.help ?? []).map((h) => `help: ${h}`)];
|
|
15
|
+
out.push({
|
|
16
|
+
...primary,
|
|
17
|
+
severity: d.severity === "warning" ? "warning" : d.severity === "note" ? "info" : "error",
|
|
18
|
+
message: [`${d.code}: ${d.headline}`, ...extra].join("\n"),
|
|
19
|
+
code: d.code,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
for (const n of d.notes ?? []) {
|
|
23
|
+
const span = at(n.pos);
|
|
24
|
+
if (span) {
|
|
25
|
+
out.push({ ...span, severity: "info", message: `${d.code}: ${n.label}`, code: d.code });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
// docsURL is where a code is explained, in the docs of the thema the page
|
|
32
|
+
// runs.
|
|
33
|
+
export function docsURL(code) {
|
|
34
|
+
return themaDoc(`errors/${encodeURIComponent(code)}.md`);
|
|
35
|
+
}
|
|
36
|
+
// filesOf lists the files diagnostics point into, so a file tab can say it
|
|
37
|
+
// has problems without being open.
|
|
38
|
+
export function filesOf(ds) {
|
|
39
|
+
const s = new Set();
|
|
40
|
+
for (const d of ds) {
|
|
41
|
+
if (d.primary && d.primary.origin !== "thema")
|
|
42
|
+
s.add(d.primary.file);
|
|
43
|
+
}
|
|
44
|
+
return s;
|
|
45
|
+
}
|
package/dist/ops.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type DataOp = "validate" | "validate-any" | "translate";
|
|
2
|
+
export type CodegenOp = "openapi" | "jsonschema" | "typescript";
|
|
3
|
+
export type UserOp = DataOp | CodegenOp;
|
|
4
|
+
export declare const dataOps: readonly DataOp[];
|
|
5
|
+
export declare const codegenOps: readonly CodegenOp[];
|
|
6
|
+
export interface OpArgs {
|
|
7
|
+
version: string;
|
|
8
|
+
from: string;
|
|
9
|
+
to: string;
|
|
10
|
+
format: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function isCodegen(op: string): op is CodegenOp;
|
|
13
|
+
export declare function argsOf(op: UserOp): ReadonlyArray<"version" | "from" | "to" | "format">;
|
package/dist/ops.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// The operations a user runs on data or on a lineage, and the arguments each
|
|
2
|
+
// takes: what OpBar offers and Output renders the result of.
|
|
3
|
+
export const dataOps = ["validate", "validate-any", "translate"];
|
|
4
|
+
export const codegenOps = ["openapi", "jsonschema", "typescript"];
|
|
5
|
+
export function isCodegen(op) {
|
|
6
|
+
return op === "openapi" || op === "jsonschema" || op === "typescript";
|
|
7
|
+
}
|
|
8
|
+
// The arguments each operation takes, for the panel to offer.
|
|
9
|
+
export function argsOf(op) {
|
|
10
|
+
switch (op) {
|
|
11
|
+
case "validate":
|
|
12
|
+
case "typescript":
|
|
13
|
+
return ["version"];
|
|
14
|
+
case "validate-any":
|
|
15
|
+
return [];
|
|
16
|
+
case "translate":
|
|
17
|
+
return ["from", "to"];
|
|
18
|
+
case "openapi":
|
|
19
|
+
case "jsonschema":
|
|
20
|
+
return ["version", "format"];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Pos } from "./types";
|
|
2
|
+
export declare function offsetOf(text: string, pos: Pick<Pos, "line" | "col">): number | null;
|
|
3
|
+
export declare function charIndexOfByte(s: string, b: number): number;
|
|
4
|
+
export declare function spanAt(text: string, from: number): {
|
|
5
|
+
from: number;
|
|
6
|
+
to: number;
|
|
7
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// offsetOf is pos as an offset into text, or null when text has no such
|
|
2
|
+
// line. A column past the line's end is clamped to it.
|
|
3
|
+
export function offsetOf(text, pos) {
|
|
4
|
+
if (pos.line < 1)
|
|
5
|
+
return null;
|
|
6
|
+
let start = 0;
|
|
7
|
+
for (let l = 1; l < pos.line; l++) {
|
|
8
|
+
const nl = text.indexOf("\n", start);
|
|
9
|
+
if (nl < 0)
|
|
10
|
+
return null;
|
|
11
|
+
start = nl + 1;
|
|
12
|
+
}
|
|
13
|
+
let end = text.indexOf("\n", start);
|
|
14
|
+
if (end < 0)
|
|
15
|
+
end = text.length;
|
|
16
|
+
const line = text.slice(start, end);
|
|
17
|
+
return start + charIndexOfByte(line, Math.max(0, pos.col - 1));
|
|
18
|
+
}
|
|
19
|
+
// charIndexOfByte is the index of the character that starts at byte b of
|
|
20
|
+
// s's UTF-8 encoding.
|
|
21
|
+
export function charIndexOfByte(s, b) {
|
|
22
|
+
let bytes = 0;
|
|
23
|
+
let i = 0;
|
|
24
|
+
while (i < s.length && bytes < b) {
|
|
25
|
+
const cp = s.codePointAt(i);
|
|
26
|
+
bytes += cp < 0x80 ? 1 : cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4;
|
|
27
|
+
i += cp > 0xffff ? 2 : 1;
|
|
28
|
+
}
|
|
29
|
+
return i;
|
|
30
|
+
}
|
|
31
|
+
// spanAt is the range to underline for a position: the word or quoted string
|
|
32
|
+
// that starts there, or one character.
|
|
33
|
+
export function spanAt(text, from) {
|
|
34
|
+
if (from >= text.length)
|
|
35
|
+
return { from: Math.max(0, text.length - 1), to: text.length };
|
|
36
|
+
const rest = text.slice(from);
|
|
37
|
+
const m = /^("(?:[^"\\\n]|\\.)*"|#?[\w$.]+)/.exec(rest);
|
|
38
|
+
const len = m ? m[0].length : 1;
|
|
39
|
+
return { from, to: from + Math.max(1, len) };
|
|
40
|
+
}
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { HighlightStyle } from "@codemirror/language";
|
|
2
|
+
export declare const tokenColors: {
|
|
3
|
+
readonly keyword: readonly [import("@lezer/highlight").Tag, import("@lezer/highlight").Tag, import("@lezer/highlight").Tag, import("@lezer/highlight").Tag];
|
|
4
|
+
readonly string: readonly [import("@lezer/highlight").Tag, import("@lezer/highlight").Tag, import("@lezer/highlight").Tag, import("@lezer/highlight").Tag];
|
|
5
|
+
readonly literal: readonly [import("@lezer/highlight").Tag, import("@lezer/highlight").Tag, import("@lezer/highlight").Tag, import("@lezer/highlight").Tag];
|
|
6
|
+
readonly type: readonly [import("@lezer/highlight").Tag, import("@lezer/highlight").Tag];
|
|
7
|
+
readonly definition: readonly [import("@lezer/highlight").Tag, import("@lezer/highlight").Tag];
|
|
8
|
+
readonly property: readonly [import("@lezer/highlight").Tag, import("@lezer/highlight").Tag];
|
|
9
|
+
readonly comment: readonly [import("@lezer/highlight").Tag, import("@lezer/highlight").Tag, import("@lezer/highlight").Tag];
|
|
10
|
+
readonly meta: readonly [import("@lezer/highlight").Tag, import("@lezer/highlight").Tag];
|
|
11
|
+
readonly punctuation: readonly [import("@lezer/highlight").Tag, import("@lezer/highlight").Tag, import("@lezer/highlight").Tag, import("@lezer/highlight").Tag];
|
|
12
|
+
};
|
|
13
|
+
export declare const highlight: HighlightStyle;
|
|
14
|
+
export declare const lightTheme: import("@codemirror/state").Extension;
|
|
15
|
+
export declare const darkTheme: import("@codemirror/state").Extension;
|
|
16
|
+
export declare function darkScheme(): MediaQueryList | null;
|
package/dist/theme.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// The editors' look. Colors come from the page's stylesheet, as CSS
|
|
2
|
+
// variables with a light and a dark value each, so the editors follow the
|
|
3
|
+
// system's color scheme with the rest of the page. CodeMirror's own
|
|
4
|
+
// light/dark rules (caret, search panel, bracket matching) key off whether
|
|
5
|
+
// the editor theme says it is dark, so the editor also needs telling.
|
|
6
|
+
import { HighlightStyle } from "@codemirror/language";
|
|
7
|
+
import { EditorView } from "@codemirror/view";
|
|
8
|
+
import { tags as t } from "@lezer/highlight";
|
|
9
|
+
// The token colors, each a --syn-* variable in style.css. A test holds every
|
|
10
|
+
// one to readable contrast against the editor's background in both schemes.
|
|
11
|
+
export const tokenColors = {
|
|
12
|
+
keyword: [t.keyword, t.controlKeyword, t.moduleKeyword, t.operatorKeyword],
|
|
13
|
+
string: [t.string, t.special(t.string), t.regexp, t.escape],
|
|
14
|
+
literal: [t.number, t.bool, t.null, t.atom],
|
|
15
|
+
type: [t.typeName, t.standard(t.typeName)],
|
|
16
|
+
definition: [t.className, t.definition(t.typeName)],
|
|
17
|
+
property: [t.propertyName, t.definition(t.propertyName)],
|
|
18
|
+
comment: [t.comment, t.lineComment, t.blockComment],
|
|
19
|
+
meta: [t.meta, t.annotation],
|
|
20
|
+
punctuation: [t.punctuation, t.bracket, t.separator, t.operator],
|
|
21
|
+
};
|
|
22
|
+
// One rule per tag: a later rule naming the same tag replaces an earlier one
|
|
23
|
+
// rather than adding to it, so a comment's italics ride with its color.
|
|
24
|
+
export const highlight = HighlightStyle.define([
|
|
25
|
+
...Object.entries(tokenColors).map(([name, tag]) => ({
|
|
26
|
+
tag: [...tag],
|
|
27
|
+
color: `var(--syn-${name})`,
|
|
28
|
+
...(name === "comment" ? { fontStyle: "italic" } : {}),
|
|
29
|
+
})),
|
|
30
|
+
{ tag: t.invalid, color: "var(--error)" },
|
|
31
|
+
]);
|
|
32
|
+
const spec = {
|
|
33
|
+
"&": { height: "100%", fontSize: "var(--code-size)", color: "var(--text)", backgroundColor: "var(--bg)" },
|
|
34
|
+
".cm-scroller": { fontFamily: "var(--mono)", lineHeight: "1.5" },
|
|
35
|
+
".cm-content": { caretColor: "var(--text)" },
|
|
36
|
+
".cm-cursor, .cm-dropCursor": { borderLeftColor: "var(--text)" },
|
|
37
|
+
".cm-gutters": { background: "var(--panel)", color: "var(--muted)", border: "none" },
|
|
38
|
+
".cm-activeLine": { background: "var(--active-line)" },
|
|
39
|
+
".cm-activeLineGutter": { background: "var(--active-line)", color: "var(--text)" },
|
|
40
|
+
".cm-selectionBackground, &.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
41
|
+
background: "var(--selection)",
|
|
42
|
+
},
|
|
43
|
+
".cm-tooltip": { background: "var(--panel)", color: "var(--text)", border: "1px solid var(--border)" },
|
|
44
|
+
".cm-tooltip-lint": { fontFamily: "var(--mono)", fontSize: "var(--code-size)" },
|
|
45
|
+
".cm-diagnostic": { whiteSpace: "pre-wrap" },
|
|
46
|
+
".cm-diagnosticSource": { color: "var(--muted)" },
|
|
47
|
+
"&.cm-focused": { outline: "none" },
|
|
48
|
+
};
|
|
49
|
+
export const lightTheme = EditorView.theme(spec, { dark: false });
|
|
50
|
+
export const darkTheme = EditorView.theme(spec, { dark: true });
|
|
51
|
+
// darkScheme is the system's color-scheme preference, or null where there is
|
|
52
|
+
// no way to ask (jsdom).
|
|
53
|
+
export function darkScheme() {
|
|
54
|
+
return typeof matchMedia === "function" ? matchMedia("(prefers-color-scheme: dark)") : null;
|
|
55
|
+
}
|