@contraagent/elements 0.1.0 → 0.2.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.
Files changed (61) hide show
  1. package/README.md +16 -5
  2. package/custom-elements.json +1107 -345
  3. package/dist/code/code.d.ts +83 -0
  4. package/dist/code/code.d.ts.map +1 -0
  5. package/dist/code/code.js +206 -0
  6. package/dist/code/code.js.map +1 -0
  7. package/dist/code/highlight.d.ts +25 -0
  8. package/dist/code/highlight.d.ts.map +1 -0
  9. package/dist/code/highlight.js +312 -0
  10. package/dist/code/highlight.js.map +1 -0
  11. package/dist/code/index.d.ts +3 -0
  12. package/dist/code/index.d.ts.map +1 -0
  13. package/dist/code/index.js +5 -0
  14. package/dist/code/index.js.map +1 -0
  15. package/dist/define/all.d.ts +2 -0
  16. package/dist/define/all.d.ts.map +1 -1
  17. package/dist/define/all.js +2 -0
  18. package/dist/define/all.js.map +1 -1
  19. package/dist/define/code.d.ts +4 -0
  20. package/dist/define/code.d.ts.map +1 -0
  21. package/dist/define/code.js +7 -0
  22. package/dist/define/code.js.map +1 -0
  23. package/dist/define/tree.d.ts +4 -0
  24. package/dist/define/tree.d.ts.map +1 -0
  25. package/dist/define/tree.js +7 -0
  26. package/dist/define/tree.js.map +1 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +2 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/markdown/highlight.d.ts +1 -4
  32. package/dist/markdown/highlight.d.ts.map +1 -1
  33. package/dist/markdown/highlight.js +2 -85
  34. package/dist/markdown/highlight.js.map +1 -1
  35. package/dist/styles/prose.d.ts.map +1 -1
  36. package/dist/styles/prose.js +5 -0
  37. package/dist/styles/prose.js.map +1 -1
  38. package/dist/tree/index.d.ts +2 -0
  39. package/dist/tree/index.d.ts.map +1 -0
  40. package/dist/tree/index.js +4 -0
  41. package/dist/tree/index.js.map +1 -0
  42. package/dist/tree/tree.d.ts +83 -0
  43. package/dist/tree/tree.d.ts.map +1 -0
  44. package/dist/tree/tree.js +251 -0
  45. package/dist/tree/tree.js.map +1 -0
  46. package/docs/code.md +55 -0
  47. package/docs/examples/code.ts +28 -0
  48. package/docs/examples/tree.ts +44 -0
  49. package/docs/tree.md +44 -0
  50. package/package.json +19 -3
  51. package/src/code/code.ts +199 -0
  52. package/src/code/highlight.ts +378 -0
  53. package/src/code/index.ts +4 -0
  54. package/src/define/all.ts +2 -0
  55. package/src/define/code.ts +9 -0
  56. package/src/define/tree.ts +9 -0
  57. package/src/index.ts +2 -0
  58. package/src/markdown/highlight.ts +2 -94
  59. package/src/styles/prose.ts +5 -0
  60. package/src/tree/index.ts +3 -0
  61. package/src/tree/tree.ts +263 -0
@@ -0,0 +1,83 @@
1
+ import { LitElement, type PropertyValues } from 'lit';
2
+ /** A line marked in a text: its number, or the first and the last of a range, both included. */
3
+ export type LineMark = number | readonly [number, number];
4
+ export interface CodeStrings {
5
+ /** The button that copies the whole text. */
6
+ copy: string;
7
+ /** What the copy button says for a moment after the text was copied. */
8
+ copied: string;
9
+ /** The switch between long lines wrapped and scrolled sideways. */
10
+ wrap: string;
11
+ /** What a text with no characters shows. */
12
+ empty: string;
13
+ /** The note under a text cut short: the lines shown of all its lines. */
14
+ cut: (shown: number, total: number) => string;
15
+ }
16
+ export declare const DEFAULT_CODE_STRINGS: Readonly<CodeStrings>;
17
+ /** What of a text is shown. */
18
+ export interface ShownText {
19
+ /** The text shown: its first lines. */
20
+ shown: string;
21
+ /** The number of lines shown. */
22
+ lines: number;
23
+ /** The number of lines of the whole text (a last line break ends the last line). */
24
+ total: number;
25
+ /** Less than the whole text is shown. */
26
+ cut: boolean;
27
+ }
28
+ /**
29
+ * The first lines of `text`: at most `maxLines` lines and `maxCharacters` characters, cut
30
+ * at the end of a line (a first line longer than that is cut inside it).
31
+ */
32
+ export declare function shownText(text: string, maxLines: number, maxCharacters: number): ShownText;
33
+ /** Whether line `n` is in one of `marks`. */
34
+ export declare function isMarked(marks: readonly LineMark[], n: number): boolean;
35
+ /**
36
+ * A text shown as code: highlighted by its `language` (`LANGUAGES`, another name of one
37
+ * or a file name; anything else is plain), each line numbered from `start`, the lines of
38
+ * `highlight` marked (a bar beside the number and a tint). Long lines scroll sideways,
39
+ * or wrap with `wrap` or the reader's switch. A text of more than `maxLines` lines or
40
+ * `maxCharacters` characters shows its first lines and says how many it has; the copy
41
+ * button copies the whole text. The line numbers are not part of a selection.
42
+ *
43
+ * @tagname cae-code
44
+ * @csspart header - the path, the language and the buttons
45
+ * @csspart code - the lines, which scroll
46
+ * @csspart cut - the note under a text cut short
47
+ */
48
+ export declare class CaeCode extends LitElement {
49
+ static styles: (import("lit").CSSResult | import("lit").CSSResult[])[];
50
+ /** The text. */
51
+ code: string;
52
+ /** Its language: a name of `LANGUAGES`, another name of one, or a file name; anything else is plain text. */
53
+ language: string;
54
+ /** The number of the first line. */
55
+ start: number;
56
+ /** The lines marked, in the numbers shown. */
57
+ highlight: readonly LineMark[];
58
+ /** The file the text is, named over it. */
59
+ path: string;
60
+ /** What the lines are named to a screen reader (default: the path). */
61
+ label: string;
62
+ /** Long lines wrap at first; the reader's switch changes it. */
63
+ wrap: boolean;
64
+ /** The most lines shown. */
65
+ maxLines: number;
66
+ /** The most characters shown, at the end of a line. */
67
+ maxCharacters: number;
68
+ /** The visible words; English by default. */
69
+ strings: Partial<CodeStrings>;
70
+ private wrapped;
71
+ private copied;
72
+ private copiedTimer;
73
+ willUpdate(changed: PropertyValues<this>): void;
74
+ disconnectedCallback(): void;
75
+ private copy;
76
+ render(): import("lit").TemplateResult<1>;
77
+ }
78
+ declare global {
79
+ interface HTMLElementTagNameMap {
80
+ 'cae-code': CaeCode;
81
+ }
82
+ }
83
+ //# sourceMappingURL=code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../src/code/code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAO1E,gGAAgG;AAChG,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/C;AAED,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,WAAW,CAMtD,CAAC;AAEF,+BAA+B;AAC/B,MAAM,WAAW,SAAS;IACxB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,GAAG,EAAE,OAAO,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,SAAS,CAoB1F;AAED,6CAA6C;AAC7C,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,OAAQ,SAAQ,UAAU;IACrC,OAAgB,MAAM,0DA2BpB;IAEF,gBAAgB;IACJ,IAAI,SAAM;IACtB,6GAA6G;IACjG,QAAQ,SAAM;IAC1B,oCAAoC;IACR,KAAK,SAAK;IACtC,8CAA8C;IACd,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAM;IACpE,2CAA2C;IAC/B,IAAI,SAAM;IACtB,uEAAuE;IAC3D,KAAK,SAAM;IACvB,gEAAgE;IACnC,IAAI,UAAS;IAC1C,4BAA4B;IACA,QAAQ,SAAQ;IAC5C,uDAAuD;IAC3B,aAAa,SAAW;IACpD,6CAA6C;IACb,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,CAAM;IAE1D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,WAAW,CAA4C;IAEtD,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAK/C,oBAAoB,IAAI,IAAI;YAKvB,IAAI;IAWT,MAAM;CA6BhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,UAAU,EAAE,OAAO,CAAC;KACrB;CACF"}
@@ -0,0 +1,206 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement, css, html, nothing } from 'lit';
8
+ import { property, state } from 'lit/decorators.js';
9
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
10
+ import { withDefaults } from '../core/strings.js';
11
+ import { base, prose } from '../styles/index.js';
12
+ import { languageOf, tokenLines, tokenize, tokensHtml } from './highlight.js';
13
+ export const DEFAULT_CODE_STRINGS = {
14
+ copy: 'Copy',
15
+ copied: 'Copied',
16
+ wrap: 'Wrap lines',
17
+ empty: 'No text',
18
+ cut: (shown, total) => `First ${shown.toLocaleString('en')} of ${total.toLocaleString('en')} lines`,
19
+ };
20
+ /**
21
+ * The first lines of `text`: at most `maxLines` lines and `maxCharacters` characters, cut
22
+ * at the end of a line (a first line longer than that is cut inside it).
23
+ */
24
+ export function shownText(text, maxLines, maxCharacters) {
25
+ const all = text.endsWith('\n') ? text.slice(0, -1) : text;
26
+ let total = all || text ? 1 : 0;
27
+ for (let i = all.indexOf('\n'); i >= 0; i = all.indexOf('\n', i + 1))
28
+ total++;
29
+ let end = 0;
30
+ let lines = 0;
31
+ while (lines < Math.max(1, maxLines)) {
32
+ const next = all.indexOf('\n', end);
33
+ const stop = next < 0 ? all.length : next;
34
+ if (lines > 0 && stop > maxCharacters)
35
+ break;
36
+ lines++;
37
+ if (next < 0) {
38
+ end = all.length;
39
+ break;
40
+ }
41
+ end = next + 1;
42
+ }
43
+ let shown = lines >= total ? all : all.slice(0, end - 1);
44
+ if (shown.length > maxCharacters)
45
+ shown = shown.slice(0, maxCharacters);
46
+ return { shown, lines: total ? lines : 0, total, cut: shown.length < all.length };
47
+ }
48
+ /** Whether line `n` is in one of `marks`. */
49
+ export function isMarked(marks, n) {
50
+ return marks.some((m) => (typeof m === 'number' ? m === n : n >= m[0] && n <= m[1]));
51
+ }
52
+ /**
53
+ * A text shown as code: highlighted by its `language` (`LANGUAGES`, another name of one
54
+ * or a file name; anything else is plain), each line numbered from `start`, the lines of
55
+ * `highlight` marked (a bar beside the number and a tint). Long lines scroll sideways,
56
+ * or wrap with `wrap` or the reader's switch. A text of more than `maxLines` lines or
57
+ * `maxCharacters` characters shows its first lines and says how many it has; the copy
58
+ * button copies the whole text. The line numbers are not part of a selection.
59
+ *
60
+ * @tagname cae-code
61
+ * @csspart header - the path, the language and the buttons
62
+ * @csspart code - the lines, which scroll
63
+ * @csspart cut - the note under a text cut short
64
+ */
65
+ export class CaeCode extends LitElement {
66
+ constructor() {
67
+ super(...arguments);
68
+ /** The text. */
69
+ this.code = '';
70
+ /** Its language: a name of `LANGUAGES`, another name of one, or a file name; anything else is plain text. */
71
+ this.language = '';
72
+ /** The number of the first line. */
73
+ this.start = 1;
74
+ /** The lines marked, in the numbers shown. */
75
+ this.highlight = [];
76
+ /** The file the text is, named over it. */
77
+ this.path = '';
78
+ /** What the lines are named to a screen reader (default: the path). */
79
+ this.label = '';
80
+ /** Long lines wrap at first; the reader's switch changes it. */
81
+ this.wrap = false;
82
+ /** The most lines shown. */
83
+ this.maxLines = 5000;
84
+ /** The most characters shown, at the end of a line. */
85
+ this.maxCharacters = 500_000;
86
+ /** The visible words; English by default. */
87
+ this.strings = {};
88
+ this.wrapped = false;
89
+ this.copied = false;
90
+ }
91
+ static { this.styles = [
92
+ base,
93
+ prose,
94
+ css `
95
+ :host { display: block; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--well); overflow: hidden; }
96
+ .head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding: 4px 6px 4px 10px; border-bottom: 1px solid var(--line); font-size: var(--font-size-sm); color: var(--text-2); }
97
+ .path { font-family: var(--mono); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
98
+ .lang { color: var(--text-muted); }
99
+ .tools { margin-left: auto; display: flex; gap: 4px; flex: none; }
100
+ .tools button { font-size: var(--font-size-sm); color: var(--text-2); border: 1px solid var(--line2); border-radius: var(--radius-pill); padding: 0 9px; cursor: pointer; background: none; }
101
+ .tools button[aria-pressed='true'] { background: var(--raise); color: var(--text); }
102
+ .scroll { overflow: auto; max-height: var(--cae-code-max-height, 70vh); font-family: var(--mono); font-size: var(--font-size-md); line-height: 1.5; }
103
+ .lines { display: block; min-width: max-content; padding: 4px 0; }
104
+ .wrap .lines { min-width: 0; }
105
+ .ln { display: flex; }
106
+ /* the number is the line's own: drawn by CSS, so a selection of lines copies no numbers */
107
+ .ln::before { content: attr(data-n); position: sticky; left: 0; flex: none; box-sizing: border-box; width: calc(var(--digits) * 1ch + 22px);
108
+ padding: 0 10px 0 8px; text-align: right; color: var(--text-muted); background: var(--well); border-left: 3px solid transparent; }
109
+ .t { flex: 1; white-space: pre; padding-right: 12px; }
110
+ .t:empty::after { content: ' '; }
111
+ .wrap .t { white-space: pre-wrap; overflow-wrap: anywhere; }
112
+ .ln[data-mark] { background: color-mix(in srgb, var(--accent) 6%, transparent); }
113
+ .hl-doc { opacity: 1; }
114
+ .ln[data-mark]::before { border-left-color: var(--accent); color: var(--text); background: color-mix(in srgb, var(--accent) 14%, var(--well)); }
115
+ .cut, .empty { padding: 4px 10px; font-size: var(--font-size-sm); color: var(--text-muted); border-top: 1px solid var(--line); }
116
+ .empty { border-top: 0; }
117
+ `,
118
+ ]; }
119
+ willUpdate(changed) {
120
+ if (changed.has('wrap'))
121
+ this.wrapped = this.wrap;
122
+ if (changed.has('code'))
123
+ this.copied = false;
124
+ }
125
+ disconnectedCallback() {
126
+ super.disconnectedCallback();
127
+ clearTimeout(this.copiedTimer);
128
+ }
129
+ async copy() {
130
+ try {
131
+ await navigator.clipboard.writeText(this.code);
132
+ }
133
+ catch {
134
+ return;
135
+ }
136
+ this.copied = true;
137
+ clearTimeout(this.copiedTimer);
138
+ this.copiedTimer = setTimeout(() => (this.copied = false), 1500);
139
+ }
140
+ render() {
141
+ const s = withDefaults(DEFAULT_CODE_STRINGS, this.strings);
142
+ const lang = languageOf(this.language);
143
+ const { shown, lines, total, cut } = shownText(this.code, this.maxLines, this.maxCharacters);
144
+ const last = this.start + Math.max(lines, 1) - 1;
145
+ const rows = tokenLines(tokenize(shown, lang))
146
+ .map((line, i) => {
147
+ const n = this.start + i;
148
+ return `<div class="ln" data-n="${n}"${isMarked(this.highlight, n) ? ' data-mark=""' : ''}><span class="t">${tokensHtml(line)}</span></div>`;
149
+ })
150
+ .join('');
151
+ return html `<div class="head" part="header">
152
+ ${this.path ? html `<span class="path" title=${this.path}>${this.path}</span>` : nothing}
153
+ ${lang ? html `<span class="lang">${lang}</span>` : nothing}
154
+ <span class="tools">
155
+ <button type="button" aria-pressed=${this.wrapped ? 'true' : 'false'} @click=${() => (this.wrapped = !this.wrapped)}>${s.wrap}</button>
156
+ <button type="button" ?disabled=${!this.code} @click=${() => void this.copy()}>${this.copied ? s.copied : s.copy}</button>
157
+ </span>
158
+ <span class="sr" role="status">${this.copied ? s.copied : ''}</span>
159
+ </div>
160
+ ${this.code
161
+ ? html `<div class="scroll ${this.wrapped ? 'wrap' : ''}" part="code" data-scroll=${this.wrapped ? 'y' : 'x'} tabindex="0" role=${this.label || this.path ? 'region' : nothing}
162
+ aria-label=${this.label || this.path || nothing}
163
+ style="--digits: ${String(last).length}">
164
+ <code class="lines hl">${unsafeHTML(rows)}</code>
165
+ </div>
166
+ ${cut ? html `<div class="cut" part="cut">${s.cut(lines, total)}</div>` : nothing}`
167
+ : html `<div class="empty">${s.empty}</div>`}`;
168
+ }
169
+ }
170
+ __decorate([
171
+ property()
172
+ ], CaeCode.prototype, "code", void 0);
173
+ __decorate([
174
+ property()
175
+ ], CaeCode.prototype, "language", void 0);
176
+ __decorate([
177
+ property({ type: Number })
178
+ ], CaeCode.prototype, "start", void 0);
179
+ __decorate([
180
+ property({ attribute: false })
181
+ ], CaeCode.prototype, "highlight", void 0);
182
+ __decorate([
183
+ property()
184
+ ], CaeCode.prototype, "path", void 0);
185
+ __decorate([
186
+ property()
187
+ ], CaeCode.prototype, "label", void 0);
188
+ __decorate([
189
+ property({ type: Boolean })
190
+ ], CaeCode.prototype, "wrap", void 0);
191
+ __decorate([
192
+ property({ type: Number })
193
+ ], CaeCode.prototype, "maxLines", void 0);
194
+ __decorate([
195
+ property({ type: Number })
196
+ ], CaeCode.prototype, "maxCharacters", void 0);
197
+ __decorate([
198
+ property({ attribute: false })
199
+ ], CaeCode.prototype, "strings", void 0);
200
+ __decorate([
201
+ state()
202
+ ], CaeCode.prototype, "wrapped", void 0);
203
+ __decorate([
204
+ state()
205
+ ], CaeCode.prototype, "copied", void 0);
206
+ //# sourceMappingURL=code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/code/code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /** What a token is; '' for text of no colour. */
2
+ export type TokenType = 'comment' | 'doc' | 'string' | 'number' | 'keyword' | 'constant' | 'builtin' | 'type' | 'function' | 'class' | 'decorator' | 'key' | 'tag' | 'attribute' | 'inserted' | 'deleted' | 'meta' | '';
3
+ /** A piece of the text and what it is. */
4
+ export interface CodeToken {
5
+ text: string;
6
+ type: TokenType;
7
+ }
8
+ /** The languages highlighted, by name; `languageOf` reads their other names and file extensions. */
9
+ export declare const LANGUAGES: readonly ["python", "json", "javascript", "typescript", "c", "cpp", "java", "go", "rust", "shell", "toml", "yaml", "sql", "xml", "diff"];
10
+ export type Language = (typeof LANGUAGES)[number];
11
+ /** The language `hint` names: a language's name, another name of it, a file name or its extension; '' for any other. */
12
+ export declare function languageOf(hint: string | null | undefined): Language | '';
13
+ /** `code` as tokens of `hint`'s language (`languageOf`); the whole text as one plain token for any other. */
14
+ export declare function tokenize(code: string, hint?: string | null): CodeToken[];
15
+ /** Tokens as escaped HTML, each but plain text in a `<span>` of its type's class. */
16
+ export declare function tokensHtml(tokens: readonly CodeToken[]): string;
17
+ /** Tokens split into lines at each line break: a token across lines becomes one piece per line. */
18
+ export declare function tokenLines(tokens: readonly CodeToken[]): CodeToken[][];
19
+ /** Highlighted, escaped HTML. `hint` is a language (`python`), another name of it, or a file name (`schema.py`); anything unknown is plain. */
20
+ export declare function highlight(code: string, hint?: string | null): string;
21
+ /** Python as highlighted, escaped HTML. */
22
+ export declare const hlPython: (src: string) => string;
23
+ /** JSON as highlighted, escaped HTML. */
24
+ export declare const hlJson: (src: string) => string;
25
+ //# sourceMappingURL=highlight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"highlight.d.ts","sourceRoot":"","sources":["../../src/code/highlight.ts"],"names":[],"mappings":"AAMA,iDAAiD;AACjD,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,KAAK,GACL,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,UAAU,GACV,SAAS,GACT,MAAM,GACN,UAAU,GACV,OAAO,GACP,WAAW,GACX,KAAK,GACL,KAAK,GACL,WAAW,GACX,UAAU,GACV,SAAS,GACT,MAAM,GACN,EAAE,CAAC;AAEP,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,oGAAoG;AACpG,eAAO,MAAM,SAAS,0IAA2I,CAAC;AAClK,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AA8NlD,wHAAwH;AACxH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,GAAG,EAAE,CAIzE;AA6BD,6GAA6G;AAC7G,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,CAmCxE;AAuBD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAE/D;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,EAAE,EAAE,CAUtE;AAED,+IAA+I;AAC/I,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAEpE;AAED,2CAA2C;AAC3C,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,KAAG,MAAkC,CAAC;AAE1E,yCAAyC;AACzC,eAAO,MAAM,MAAM,GAAI,KAAK,MAAM,KAAG,MAAgC,CAAC"}
@@ -0,0 +1,312 @@
1
+ // Syntax highlighting: a small tokenizer for a fixed set of languages, no library.
2
+ // Each language is a few regular expressions and its words; a token is a piece of
3
+ // the text and what it is. `highlight` returns escaped HTML: every token is escaped
4
+ // before it is wrapped, so no input can inject markup.
5
+ import { esc } from '../core/format.js';
6
+ /** The languages highlighted, by name; `languageOf` reads their other names and file extensions. */
7
+ export const LANGUAGES = ['python', 'json', 'javascript', 'typescript', 'c', 'cpp', 'java', 'go', 'rust', 'shell', 'toml', 'yaml', 'sql', 'xml', 'diff'];
8
+ const words = (s) => new Set(s.split(' '));
9
+ const LINE_C = ['comment', '//[^\\n]*|/\\*[\\s\\S]*?\\*/'];
10
+ const DQ = '"(?:[^"\\\\\\n]|\\\\.)*"';
11
+ const SQ = "'(?:[^'\\\\\\n]|\\\\.)*'";
12
+ const CHAR = "'(?:[^'\\\\\\n]|\\\\.)'";
13
+ const NUMBER = ['number', "\\b(?:0[xX][\\da-fA-F_']+|0[bB][01_]+|\\d[\\d_']*(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)[uUlLfFn]*\\b"];
14
+ const NAME = '[A-Za-z_$][\\w$]*';
15
+ const JS_KW = 'break case catch class const continue debugger default delete do else export extends finally for from function if import in instanceof let new of return static super switch throw try typeof var void while with yield async await as';
16
+ const C_KW = 'auto break case char const continue default do double else enum extern float for goto if inline int long register restrict return short signed sizeof static struct switch typedef union unsigned void volatile while bool';
17
+ const C_DEFINES = { struct: 'class', class: 'class', enum: 'class', union: 'class' };
18
+ const GRAMMARS = {
19
+ python: {
20
+ rules: [
21
+ ['comment', '#[^\\n]*'],
22
+ ['doc', '(?:[rRbBfFuU]{0,2})(?:"""[\\s\\S]*?"""|\'\'\'[\\s\\S]*?\'\'\')'],
23
+ ['string', `(?:[rRbBfFuU]{0,2})(?:${DQ}|${SQ})`],
24
+ ['decorator', '@[A-Za-z_][\\w.]*'],
25
+ ['number', '\\b\\d[\\d_]*(?:\\.\\d+)?(?:[eE][+-]?\\d+)?\\b'],
26
+ ],
27
+ keywords: words('and as assert async await break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield match case'),
28
+ constants: words('None True False self cls'),
29
+ builtins: words('str int float bool list dict set tuple bytes object type len range print isinstance super Optional Literal Any Union Path'),
30
+ defines: { def: 'function', class: 'class' },
31
+ types: true,
32
+ name: '[A-Za-z_]\\w*',
33
+ },
34
+ json: {
35
+ rules: [
36
+ ['key', `${DQ}(?=\\s*:)`],
37
+ ['string', DQ],
38
+ ['comment', '//[^\\n]*|/\\*[\\s\\S]*?\\*/'],
39
+ ['number', '-?\\b\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?\\b'],
40
+ ],
41
+ constants: words('true false null'),
42
+ name: '[A-Za-z_]\\w*',
43
+ },
44
+ javascript: {
45
+ rules: [LINE_C, ['string', `${DQ}|${SQ}|\`(?:[^\`\\\\]|\\\\.)*\``], ['decorator', '@[A-Za-z_$][\\w$.]*'], NUMBER],
46
+ keywords: words(JS_KW),
47
+ constants: words('true false null undefined this NaN Infinity'),
48
+ builtins: words('console Math JSON Promise Array Object String Number Boolean Map Set WeakMap Symbol Error Date RegExp BigInt globalThis window document'),
49
+ defines: { function: 'function', class: 'class' },
50
+ types: true,
51
+ },
52
+ typescript: {
53
+ rules: [LINE_C, ['string', `${DQ}|${SQ}|\`(?:[^\`\\\\]|\\\\.)*\``], ['decorator', '@[A-Za-z_$][\\w$.]*'], NUMBER],
54
+ keywords: words(`${JS_KW} interface type enum implements namespace declare abstract private protected public readonly keyof infer is satisfies module override`),
55
+ constants: words('true false null undefined this NaN Infinity'),
56
+ builtins: words('console Math JSON Promise Array Object String Number Boolean Map Set WeakMap Symbol Error Date RegExp BigInt globalThis string number boolean unknown never any void Record Partial Readonly'),
57
+ defines: { function: 'function', class: 'class', interface: 'class', type: 'class', enum: 'class' },
58
+ types: true,
59
+ },
60
+ c: {
61
+ rules: [['meta', '^[ \\t]*#[ \\t]*\\w+'], LINE_C, ['string', `${DQ}|${CHAR}`], NUMBER],
62
+ keywords: words(C_KW),
63
+ constants: words('NULL true false'),
64
+ builtins: words('printf fprintf malloc calloc realloc free size_t memcpy memset strlen strcmp FILE'),
65
+ defines: C_DEFINES,
66
+ types: true,
67
+ },
68
+ cpp: {
69
+ rules: [['meta', '^[ \\t]*#[ \\t]*\\w+'], LINE_C, ['string', `${DQ}|${CHAR}`], NUMBER],
70
+ keywords: words(`${C_KW} alignas alignof catch class constexpr consteval const_cast decltype delete dynamic_cast explicit export friend mutable namespace new noexcept operator private protected public reinterpret_cast static_assert static_cast template this thread_local throw try typeid typename using virtual co_await co_return co_yield concept requires override final`),
71
+ constants: words('nullptr NULL true false'),
72
+ builtins: words('std string vector map set unordered_map array optional cout cerr endl unique_ptr shared_ptr make_unique make_shared size_t'),
73
+ defines: C_DEFINES,
74
+ types: true,
75
+ },
76
+ java: {
77
+ rules: [LINE_C, ['string', `"""[\\s\\S]*?"""|${DQ}|${CHAR}`], ['decorator', '@[A-Za-z_][\\w.]*'], NUMBER],
78
+ keywords: words('abstract assert boolean break byte case catch char class continue default do double else enum extends final finally float for if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while var record yield sealed permits'),
79
+ constants: words('true false null'),
80
+ builtins: words('String System Object Integer Long Double Boolean List Map Set Optional Exception RuntimeException'),
81
+ defines: { class: 'class', interface: 'class', enum: 'class', record: 'class' },
82
+ types: true,
83
+ },
84
+ go: {
85
+ rules: [LINE_C, ['string', `${DQ}|\`[^\`]*\`|${CHAR}`], NUMBER],
86
+ keywords: words('break case chan const continue default defer else fallthrough for func go goto if import interface map package range return select struct switch type var'),
87
+ constants: words('true false nil iota'),
88
+ builtins: words('append cap close complex copy delete imag len make new panic print println real recover string int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 byte rune error bool float32 float64 any'),
89
+ defines: { func: 'function', type: 'class' },
90
+ types: true,
91
+ },
92
+ rust: {
93
+ rules: [
94
+ LINE_C,
95
+ ['string', 'b?r#*"[\\s\\S]*?"#*|b?"(?:[^"\\\\]|\\\\.)*"'],
96
+ ['string', `b?${CHAR}`],
97
+ ['type', "'[A-Za-z_]\\w*\\b(?!')"],
98
+ ['decorator', '#!?\\[[^\\]\\n]*\\]'],
99
+ ['builtin', '\\b[A-Za-z_]\\w*!(?=\\s*[\\[({])'],
100
+ NUMBER,
101
+ ],
102
+ keywords: words('as async await break const continue crate dyn else enum extern fn for if impl in let loop match mod move mut pub ref return self Self static struct super trait type unsafe use where while'),
103
+ constants: words('true false None Some Ok Err'),
104
+ builtins: words('Vec String Option Result Box Rc Arc HashMap str usize isize u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 bool char'),
105
+ defines: { fn: 'function', struct: 'class', enum: 'class', trait: 'class', type: 'class' },
106
+ types: true,
107
+ },
108
+ shell: {
109
+ rules: [
110
+ ['comment', '(?:^|(?<=\\s))#[^\\n]*'],
111
+ ['string', `"(?:[^"\\\\]|\\\\.)*"|'[^']*'`],
112
+ ['builtin', '\\$(?:\\{[^}\\n]*\\}|\\w+|[@*#?$!0-9-])'],
113
+ ['number', '\\b\\d+\\b'],
114
+ ],
115
+ keywords: words('if then else elif fi for while until do done case esac in function select return local export readonly declare set unset shift break continue exit source alias'),
116
+ builtins: words('echo cd printf read test eval exec trap pwd'),
117
+ name: '[A-Za-z_][\\w-]*',
118
+ },
119
+ toml: {
120
+ rules: [
121
+ ['comment', '#[^\\n]*'],
122
+ ['class', '^[ \\t]*\\[\\[?[^\\]\\n]*\\]\\]?'],
123
+ ['key', '^[ \\t]*[A-Za-z0-9_.\\-"\']+(?=[ \\t]*=)'],
124
+ ['string', `"""[\\s\\S]*?"""|'''[\\s\\S]*?'''|${DQ}|'[^'\\n]*'`],
125
+ ['number', '\\d{4}-\\d{2}-\\d{2}(?:[T ]\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(?:Z|[+-]\\d{2}:\\d{2})?)?'],
126
+ ['number', '[+-]?\\b\\d[\\d_]*(?:\\.\\d+)?(?:[eE][+-]?\\d+)?\\b'],
127
+ ],
128
+ constants: words('true false inf nan'),
129
+ name: '[A-Za-z_]\\w*',
130
+ },
131
+ yaml: {
132
+ rules: [
133
+ ['comment', '(?:^|(?<=\\s))#[^\\n]*'],
134
+ ['meta', '^(?:---|\\.\\.\\.)(?=\\s|$)'],
135
+ ['key', '[A-Za-z0-9_.\\-/]+(?=:(?:[ \\t]|$))'],
136
+ ['string', `${DQ}|'(?:[^'\\n]|'')*'`],
137
+ ['decorator', '[&*][\\w-]+'],
138
+ ['number', '[+-]?\\b\\d[\\d_]*(?:\\.\\d+)?(?:[eE][+-]?\\d+)?\\b'],
139
+ ],
140
+ constants: words('true false null yes no on off True False Null'),
141
+ name: '[A-Za-z_]\\w*',
142
+ },
143
+ sql: {
144
+ rules: [['comment', '--[^\\n]*|/\\*[\\s\\S]*?\\*/'], ['string', "'(?:[^']|'')*'"], ['key', '"(?:[^"]|"")*"'], ['number', '\\b\\d+(?:\\.\\d+)?\\b']],
145
+ keywords: words('select from where and or not insert into values update set delete create table drop alter add column index primary key foreign references join left right inner outer full cross on as group by order having limit offset union all distinct case when then else end is in exists between like returning with view default unique constraint if begin commit rollback transaction asc desc'),
146
+ constants: words('true false null'),
147
+ builtins: words('count sum avg min max coalesce cast lower upper now integer int text varchar char boolean date timestamp real numeric bigint serial float double'),
148
+ caseless: true,
149
+ name: '[A-Za-z_]\\w*',
150
+ },
151
+ xml: {
152
+ rules: [
153
+ ['comment', '<!--[\\s\\S]*?-->'],
154
+ ['meta', '<\\?[\\s\\S]*?\\?>|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|<![A-Za-z][^>]*>'],
155
+ ['tag', '</?[A-Za-z_][\\w:.-]*|/?>'],
156
+ ['attribute', '[A-Za-z_:][\\w:.-]*(?=\\s*=\\s*["\'])'],
157
+ ['string', '(?<==\\s*)(?:"[^"]*"|\'[^\']*\')'],
158
+ ['constant', '&#?\\w+;'],
159
+ ],
160
+ name: null,
161
+ },
162
+ diff: {
163
+ rules: [
164
+ ['meta', '^(?:diff |index |--- |\\+\\+\\+ |@@)[^\\n]*'],
165
+ ['inserted', '^\\+[^\\n]*'],
166
+ ['deleted', '^-[^\\n]*'],
167
+ ],
168
+ name: null,
169
+ },
170
+ };
171
+ /** The other names and the file extensions of each language. */
172
+ const ALIASES = {
173
+ py: 'python', python3: 'python', pyi: 'python', pyw: 'python',
174
+ jsonc: 'json', jsonl: 'json', json5: 'json', geojson: 'json',
175
+ js: 'javascript', mjs: 'javascript', cjs: 'javascript', jsx: 'javascript', node: 'javascript',
176
+ ts: 'typescript', tsx: 'typescript', mts: 'typescript', cts: 'typescript',
177
+ h: 'c',
178
+ 'c++': 'cpp', cc: 'cpp', cxx: 'cpp', hpp: 'cpp', hh: 'cpp', hxx: 'cpp',
179
+ golang: 'go',
180
+ rs: 'rust',
181
+ sh: 'shell', bash: 'shell', zsh: 'shell', ksh: 'shell', shellscript: 'shell',
182
+ ini: 'toml', cfg: 'toml',
183
+ yml: 'yaml',
184
+ html: 'xml', htm: 'xml', xhtml: 'xml', svg: 'xml', plist: 'xml', xsd: 'xml', xsl: 'xml',
185
+ patch: 'diff',
186
+ };
187
+ /** The language `hint` names: a language's name, another name of it, a file name or its extension; '' for any other. */
188
+ export function languageOf(hint) {
189
+ const h = String(hint || '').trim().toLowerCase().replace(/^.*\//, '');
190
+ const known = (s) => (LANGUAGES.includes(s) ? s : (ALIASES[s] ?? ''));
191
+ return known(h) || (h.includes('.') ? known(h.replace(/^.*\./, '')) : '');
192
+ }
193
+ const compiled = new Map();
194
+ function patternOf(lang) {
195
+ let re = compiled.get(lang);
196
+ if (!re) {
197
+ const g = GRAMMARS[lang];
198
+ const parts = g.rules.map(([, src]) => `(${src})`);
199
+ const name = g.name === undefined ? NAME : g.name;
200
+ if (name)
201
+ parts.push(`(${name})`);
202
+ re = new RegExp(parts.join('|'), 'gm');
203
+ compiled.set(lang, re);
204
+ }
205
+ return re;
206
+ }
207
+ /** The type of a name: a keyword, a constant, a function's or a type's own name, a built-in or a type; '' for any other. */
208
+ function nameType(g, word, prev) {
209
+ const w = g.caseless ? word.toLowerCase() : word;
210
+ if (g.keywords?.has(w))
211
+ return 'keyword';
212
+ if (g.constants?.has(w))
213
+ return 'constant';
214
+ const defined = g.defines?.[prev];
215
+ if (defined)
216
+ return defined;
217
+ if (g.builtins?.has(w))
218
+ return 'builtin';
219
+ if (g.types && /^[A-Z]\w*$/.test(word) && word.length > 1 && /[a-z]/.test(word))
220
+ return 'type';
221
+ return '';
222
+ }
223
+ /** `code` as tokens of `hint`'s language (`languageOf`); the whole text as one plain token for any other. */
224
+ export function tokenize(code, hint) {
225
+ const lang = languageOf(hint);
226
+ if (!lang || !code)
227
+ return code ? [{ text: code, type: '' }] : [];
228
+ const g = GRAMMARS[lang];
229
+ const re = patternOf(lang);
230
+ const out = [];
231
+ const push = (text, type) => {
232
+ if (!text)
233
+ return;
234
+ const last = out[out.length - 1];
235
+ if (last && last.type === type)
236
+ last.text += text;
237
+ else
238
+ out.push({ text, type });
239
+ };
240
+ let at = 0;
241
+ let prev = '';
242
+ re.lastIndex = 0;
243
+ for (let m = re.exec(code); m; m = re.exec(code)) {
244
+ if (!m[0]) {
245
+ re.lastIndex++;
246
+ continue;
247
+ }
248
+ const gap = code.slice(at, m.index);
249
+ if (/\S/.test(gap))
250
+ prev = '';
251
+ push(gap, '');
252
+ at = re.lastIndex;
253
+ const rule = m.findIndex((x, i) => i > 0 && x !== undefined) - 1;
254
+ if (rule < g.rules.length) {
255
+ push(m[0], g.rules[rule][0]);
256
+ prev = '';
257
+ }
258
+ else {
259
+ push(m[0], nameType(g, m[0], prev));
260
+ prev = m[0];
261
+ }
262
+ }
263
+ push(code.slice(at), '');
264
+ return out;
265
+ }
266
+ /** The classes of a token's type in the markup (`prose` colours them). */
267
+ const CLASS = {
268
+ comment: 'hl-c',
269
+ doc: 'hl-s hl-doc',
270
+ string: 'hl-s',
271
+ number: 'hl-n',
272
+ keyword: 'hl-k',
273
+ constant: 'hl-k hl-const',
274
+ builtin: 'hl-b',
275
+ type: 'hl-t',
276
+ function: 'hl-f',
277
+ class: 'hl-cls',
278
+ decorator: 'hl-d',
279
+ key: 'hl-key',
280
+ tag: 'hl-tag',
281
+ attribute: 'hl-attr',
282
+ inserted: 'hl-ins',
283
+ deleted: 'hl-del',
284
+ meta: 'hl-meta',
285
+ };
286
+ /** Tokens as escaped HTML, each but plain text in a `<span>` of its type's class. */
287
+ export function tokensHtml(tokens) {
288
+ return tokens.map((t) => (t.type ? `<span class="${CLASS[t.type]}">${esc(t.text)}</span>` : esc(t.text))).join('');
289
+ }
290
+ /** Tokens split into lines at each line break: a token across lines becomes one piece per line. */
291
+ export function tokenLines(tokens) {
292
+ const lines = [[]];
293
+ for (const t of tokens) {
294
+ const parts = t.text.split('\n');
295
+ parts.forEach((text, i) => {
296
+ if (i > 0)
297
+ lines.push([]);
298
+ if (text)
299
+ lines[lines.length - 1].push({ text, type: t.type });
300
+ });
301
+ }
302
+ return lines;
303
+ }
304
+ /** Highlighted, escaped HTML. `hint` is a language (`python`), another name of it, or a file name (`schema.py`); anything unknown is plain. */
305
+ export function highlight(code, hint) {
306
+ return tokensHtml(tokenize(code, hint));
307
+ }
308
+ /** Python as highlighted, escaped HTML. */
309
+ export const hlPython = (src) => highlight(src, 'python');
310
+ /** JSON as highlighted, escaped HTML. */
311
+ export const hlJson = (src) => highlight(src, 'json');
312
+ //# sourceMappingURL=highlight.js.map