@particle-academy/fancy-code 0.8.0 → 0.9.1
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/README.md +9 -0
- package/dist/index.cjs +39 -221
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -36
- package/dist/index.d.ts +3 -36
- package/dist/index.js +30 -212
- package/dist/index.js.map +1 -1
- package/package.json +10 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,34 +1,9 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { RefObject, ReactNode, CSSProperties } from 'react';
|
|
3
|
-
import { DiffAnnotations, LineChangeType } from '@particle-academy/fancy-file-commons';
|
|
4
|
-
export { languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
3
|
+
import { ThemeColors, DiffAnnotations, LineChangeType, Token, Tokenizer } from '@particle-academy/fancy-file-commons';
|
|
4
|
+
export { ThemeColors, Token, TokenType, Tokenizer, languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
5
5
|
import { MediaKind, MediaViewerProps, InputTagProps, InputTagTriggers, InputTagAdapter } from '@particle-academy/react-fancy';
|
|
6
6
|
|
|
7
|
-
interface ThemeColors {
|
|
8
|
-
background: string;
|
|
9
|
-
foreground: string;
|
|
10
|
-
gutterBackground: string;
|
|
11
|
-
gutterForeground: string;
|
|
12
|
-
gutterBorder: string;
|
|
13
|
-
activeLineBackground: string;
|
|
14
|
-
selectionBackground: string;
|
|
15
|
-
cursorColor: string;
|
|
16
|
-
diffAdded?: string;
|
|
17
|
-
diffModified?: string;
|
|
18
|
-
diffRemoved?: string;
|
|
19
|
-
keyword: string;
|
|
20
|
-
string: string;
|
|
21
|
-
comment: string;
|
|
22
|
-
number: string;
|
|
23
|
-
operator: string;
|
|
24
|
-
function: string;
|
|
25
|
-
type: string;
|
|
26
|
-
tag: string;
|
|
27
|
-
attribute: string;
|
|
28
|
-
attributeValue: string;
|
|
29
|
-
punctuation: string;
|
|
30
|
-
variable: string;
|
|
31
|
-
}
|
|
32
7
|
interface ThemeDefinition {
|
|
33
8
|
/** Unique theme name */
|
|
34
9
|
name: string;
|
|
@@ -407,14 +382,6 @@ declare function diffRemovedColor(colors: ThemeColors): string;
|
|
|
407
382
|
*/
|
|
408
383
|
declare function renderMarkdown(markdown: string): string;
|
|
409
384
|
|
|
410
|
-
type TokenType = "keyword" | "string" | "comment" | "number" | "operator" | "tag" | "attribute" | "attributeValue" | "punctuation" | "function" | "type" | "variable" | "plain";
|
|
411
|
-
interface Token {
|
|
412
|
-
type: TokenType;
|
|
413
|
-
start: number;
|
|
414
|
-
end: number;
|
|
415
|
-
}
|
|
416
|
-
type Tokenizer = (source: string) => Token[];
|
|
417
|
-
|
|
418
385
|
/**
|
|
419
386
|
* Minimal, dependency-free Markdown tokenizer for editor highlighting. Line-based
|
|
420
387
|
* for block constructs (fences, headings, blockquotes, list markers) plus a few
|
|
@@ -481,4 +448,4 @@ interface CodeEditorInputTagProps extends Omit<InputTagProps, "adapter"> {
|
|
|
481
448
|
*/
|
|
482
449
|
declare function CodeEditorInputTag(props: CodeEditorInputTagProps): react.JSX.Element;
|
|
483
450
|
|
|
484
|
-
export { CodeEditor, type CodeEditorContextValue, CodeEditorInputTag, type CodeEditorInputTagProps, type CodeEditorPanelProps, type CodeEditorProps, type CodeEditorStatusBarProps, type CodeEditorToolbarProps, type FileKind, FileViewer, type FileViewerProps, type GutterDiffMark, type LanguageDefinition, MarkdownEditor, type MarkdownEditorMode, type MarkdownEditorProps, type ResolveFileKindInput, type
|
|
451
|
+
export { CodeEditor, type CodeEditorContextValue, CodeEditorInputTag, type CodeEditorInputTagProps, type CodeEditorPanelProps, type CodeEditorProps, type CodeEditorStatusBarProps, type CodeEditorToolbarProps, type FileKind, FileViewer, type FileViewerProps, type GutterDiffMark, type LanguageDefinition, MarkdownEditor, type MarkdownEditorMode, type MarkdownEditorProps, type ResolveFileKindInput, type ThemeDefinition, diffMarkColor, diffRemovedColor, getLanguage, getRegisteredLanguages, getRegisteredThemes, getTheme, gutterDiffMark, hasDeletedAtEnd, registerLanguage, registerTheme, renderMarkdown, resolveFileKind, tokenizeMarkdown, useCodeEditor, useCodeEditorInputTagAdapter };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,34 +1,9 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { RefObject, ReactNode, CSSProperties } from 'react';
|
|
3
|
-
import { DiffAnnotations, LineChangeType } from '@particle-academy/fancy-file-commons';
|
|
4
|
-
export { languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
3
|
+
import { ThemeColors, DiffAnnotations, LineChangeType, Token, Tokenizer } from '@particle-academy/fancy-file-commons';
|
|
4
|
+
export { ThemeColors, Token, TokenType, Tokenizer, languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
5
5
|
import { MediaKind, MediaViewerProps, InputTagProps, InputTagTriggers, InputTagAdapter } from '@particle-academy/react-fancy';
|
|
6
6
|
|
|
7
|
-
interface ThemeColors {
|
|
8
|
-
background: string;
|
|
9
|
-
foreground: string;
|
|
10
|
-
gutterBackground: string;
|
|
11
|
-
gutterForeground: string;
|
|
12
|
-
gutterBorder: string;
|
|
13
|
-
activeLineBackground: string;
|
|
14
|
-
selectionBackground: string;
|
|
15
|
-
cursorColor: string;
|
|
16
|
-
diffAdded?: string;
|
|
17
|
-
diffModified?: string;
|
|
18
|
-
diffRemoved?: string;
|
|
19
|
-
keyword: string;
|
|
20
|
-
string: string;
|
|
21
|
-
comment: string;
|
|
22
|
-
number: string;
|
|
23
|
-
operator: string;
|
|
24
|
-
function: string;
|
|
25
|
-
type: string;
|
|
26
|
-
tag: string;
|
|
27
|
-
attribute: string;
|
|
28
|
-
attributeValue: string;
|
|
29
|
-
punctuation: string;
|
|
30
|
-
variable: string;
|
|
31
|
-
}
|
|
32
7
|
interface ThemeDefinition {
|
|
33
8
|
/** Unique theme name */
|
|
34
9
|
name: string;
|
|
@@ -407,14 +382,6 @@ declare function diffRemovedColor(colors: ThemeColors): string;
|
|
|
407
382
|
*/
|
|
408
383
|
declare function renderMarkdown(markdown: string): string;
|
|
409
384
|
|
|
410
|
-
type TokenType = "keyword" | "string" | "comment" | "number" | "operator" | "tag" | "attribute" | "attributeValue" | "punctuation" | "function" | "type" | "variable" | "plain";
|
|
411
|
-
interface Token {
|
|
412
|
-
type: TokenType;
|
|
413
|
-
start: number;
|
|
414
|
-
end: number;
|
|
415
|
-
}
|
|
416
|
-
type Tokenizer = (source: string) => Token[];
|
|
417
|
-
|
|
418
385
|
/**
|
|
419
386
|
* Minimal, dependency-free Markdown tokenizer for editor highlighting. Line-based
|
|
420
387
|
* for block constructs (fences, headings, blockquotes, list markers) plus a few
|
|
@@ -481,4 +448,4 @@ interface CodeEditorInputTagProps extends Omit<InputTagProps, "adapter"> {
|
|
|
481
448
|
*/
|
|
482
449
|
declare function CodeEditorInputTag(props: CodeEditorInputTagProps): react.JSX.Element;
|
|
483
450
|
|
|
484
|
-
export { CodeEditor, type CodeEditorContextValue, CodeEditorInputTag, type CodeEditorInputTagProps, type CodeEditorPanelProps, type CodeEditorProps, type CodeEditorStatusBarProps, type CodeEditorToolbarProps, type FileKind, FileViewer, type FileViewerProps, type GutterDiffMark, type LanguageDefinition, MarkdownEditor, type MarkdownEditorMode, type MarkdownEditorProps, type ResolveFileKindInput, type
|
|
451
|
+
export { CodeEditor, type CodeEditorContextValue, CodeEditorInputTag, type CodeEditorInputTagProps, type CodeEditorPanelProps, type CodeEditorProps, type CodeEditorStatusBarProps, type CodeEditorToolbarProps, type FileKind, FileViewer, type FileViewerProps, type GutterDiffMark, type LanguageDefinition, MarkdownEditor, type MarkdownEditorMode, type MarkdownEditorProps, type ResolveFileKindInput, type ThemeDefinition, diffMarkColor, diffRemovedColor, getLanguage, getRegisteredLanguages, getRegisteredThemes, getTheme, gutterDiffMark, hasDeletedAtEnd, registerLanguage, registerTheme, renderMarkdown, resolveFileKind, tokenizeMarkdown, useCodeEditor, useCodeEditorInputTagAdapter };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createContext, useMemo, useState, useCallback, useRef, useEffect, useSyncExternalStore, useContext } from 'react';
|
|
2
2
|
import { cn, useControllableState, resolveMediaType, MediaViewer, textareaAdapter, InputTag } from '@particle-academy/react-fancy';
|
|
3
|
-
import { annotateLines, languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
3
|
+
import { annotateLines, highlightCode, tok, tokenizeHtml, LIGHT_COLORS, DARK_COLORS, languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
4
4
|
export { languageFromFilename } from '@particle-academy/fancy-file-commons';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
@@ -42,26 +42,12 @@ function CodeEditorPanel({ className }) {
|
|
|
42
42
|
_maxHeight,
|
|
43
43
|
_minHeight
|
|
44
44
|
} = useCodeEditor();
|
|
45
|
-
if (!engine) return null;
|
|
46
|
-
const {
|
|
47
|
-
textareaRef,
|
|
48
|
-
highlightedHtml,
|
|
49
|
-
lineCount,
|
|
50
|
-
activeLine,
|
|
51
|
-
themeColors,
|
|
52
|
-
handleKeyDown,
|
|
53
|
-
handleInput,
|
|
54
|
-
handleScroll,
|
|
55
|
-
handleSelect,
|
|
56
|
-
scrollTop,
|
|
57
|
-
scrollLeft
|
|
58
|
-
} = engine;
|
|
59
|
-
const gutterWidth = lineNumbers ? `${Math.max(String(lineCount).length, 2) * 0.75 + 1.5}em` : "0";
|
|
60
45
|
const lineNumberElements = useMemo(() => {
|
|
61
|
-
if (!lineNumbers) return null;
|
|
62
|
-
const
|
|
46
|
+
if (!engine || !lineNumbers) return null;
|
|
47
|
+
const { themeColors: themeColors2, lineCount: lineCount2, activeLine: activeLine2 } = engine;
|
|
48
|
+
const removed = diffRemovedColor(themeColors2);
|
|
63
49
|
const lines = [];
|
|
64
|
-
for (let i = 1; i <=
|
|
50
|
+
for (let i = 1; i <= lineCount2; i++) {
|
|
65
51
|
const mark = gutterDiffMark(diffAnnotations, i);
|
|
66
52
|
lines.push(
|
|
67
53
|
/* @__PURE__ */ jsxs(
|
|
@@ -71,8 +57,8 @@ function CodeEditorPanel({ className }) {
|
|
|
71
57
|
"data-diff-deleted-above": mark?.deletedAbove ? "" : void 0,
|
|
72
58
|
style: {
|
|
73
59
|
position: "relative",
|
|
74
|
-
color: i ===
|
|
75
|
-
backgroundColor: i ===
|
|
60
|
+
color: i === activeLine2 ? themeColors2.foreground : themeColors2.gutterForeground,
|
|
61
|
+
backgroundColor: i === activeLine2 ? themeColors2.activeLineBackground : void 0
|
|
76
62
|
},
|
|
77
63
|
className: "pr-3 text-right text-[13px] leading-[1.5] select-none",
|
|
78
64
|
children: [
|
|
@@ -87,7 +73,7 @@ function CodeEditorPanel({ className }) {
|
|
|
87
73
|
bottom: 0,
|
|
88
74
|
width: 3,
|
|
89
75
|
borderRadius: 2,
|
|
90
|
-
backgroundColor: diffMarkColor(mark.type,
|
|
76
|
+
backgroundColor: diffMarkColor(mark.type, themeColors2)
|
|
91
77
|
}
|
|
92
78
|
}
|
|
93
79
|
),
|
|
@@ -108,7 +94,7 @@ function CodeEditorPanel({ className }) {
|
|
|
108
94
|
}
|
|
109
95
|
),
|
|
110
96
|
i,
|
|
111
|
-
i ===
|
|
97
|
+
i === lineCount2 && hasDeletedAtEnd(diffAnnotations) && /* @__PURE__ */ jsx(
|
|
112
98
|
"span",
|
|
113
99
|
{
|
|
114
100
|
"aria-hidden": "true",
|
|
@@ -132,7 +118,22 @@ function CodeEditorPanel({ className }) {
|
|
|
132
118
|
);
|
|
133
119
|
}
|
|
134
120
|
return lines;
|
|
135
|
-
}, [
|
|
121
|
+
}, [engine, lineNumbers, diffAnnotations]);
|
|
122
|
+
if (!engine) return null;
|
|
123
|
+
const {
|
|
124
|
+
textareaRef,
|
|
125
|
+
highlightedHtml,
|
|
126
|
+
lineCount,
|
|
127
|
+
activeLine,
|
|
128
|
+
themeColors,
|
|
129
|
+
handleKeyDown,
|
|
130
|
+
handleInput,
|
|
131
|
+
handleScroll,
|
|
132
|
+
handleSelect,
|
|
133
|
+
scrollTop,
|
|
134
|
+
scrollLeft
|
|
135
|
+
} = engine;
|
|
136
|
+
const gutterWidth = lineNumbers ? `${Math.max(String(lineCount).length, 2) * 0.75 + 1.5}em` : "0";
|
|
136
137
|
const containerStyle = {
|
|
137
138
|
backgroundColor: themeColors.background,
|
|
138
139
|
color: themeColors.foreground,
|
|
@@ -445,89 +446,6 @@ var tokenizeJavaScript = (source) => {
|
|
|
445
446
|
return tokens;
|
|
446
447
|
};
|
|
447
448
|
|
|
448
|
-
// src/engine/tokenizers/html.ts
|
|
449
|
-
var tokenizeHtml = (source) => {
|
|
450
|
-
const tokens = [];
|
|
451
|
-
const len = source.length;
|
|
452
|
-
let i = 0;
|
|
453
|
-
while (i < len) {
|
|
454
|
-
if (source[i] === "<" && source.slice(i, i + 4) === "<!--") {
|
|
455
|
-
const pos2 = i;
|
|
456
|
-
i += 4;
|
|
457
|
-
while (i < len && source.slice(i, i + 3) !== "-->") i++;
|
|
458
|
-
i += 3;
|
|
459
|
-
tokens.push({ type: "comment", start: pos2, end: i });
|
|
460
|
-
continue;
|
|
461
|
-
}
|
|
462
|
-
if (source[i] === "<" && source.slice(i, i + 9).toUpperCase() === "<!DOCTYPE") {
|
|
463
|
-
const pos2 = i;
|
|
464
|
-
while (i < len && source[i] !== ">") i++;
|
|
465
|
-
i++;
|
|
466
|
-
tokens.push({ type: "keyword", start: pos2, end: i });
|
|
467
|
-
continue;
|
|
468
|
-
}
|
|
469
|
-
if (source[i] === "<") {
|
|
470
|
-
tokens.push({ type: "punctuation", start: i, end: i + 1 });
|
|
471
|
-
i++;
|
|
472
|
-
if (i < len && source[i] === "/") {
|
|
473
|
-
tokens.push({ type: "punctuation", start: i, end: i + 1 });
|
|
474
|
-
i++;
|
|
475
|
-
}
|
|
476
|
-
if (i < len && /[a-zA-Z]/.test(source[i])) {
|
|
477
|
-
const pos2 = i;
|
|
478
|
-
while (i < len && /[a-zA-Z0-9-]/.test(source[i])) i++;
|
|
479
|
-
tokens.push({ type: "tag", start: pos2, end: i });
|
|
480
|
-
}
|
|
481
|
-
while (i < len && source[i] !== ">" && !(source[i] === "/" && source[i + 1] === ">")) {
|
|
482
|
-
if (source[i] === " " || source[i] === " " || source[i] === "\n" || source[i] === "\r") {
|
|
483
|
-
i++;
|
|
484
|
-
continue;
|
|
485
|
-
}
|
|
486
|
-
if (/[a-zA-Z_@:]/.test(source[i])) {
|
|
487
|
-
const pos2 = i;
|
|
488
|
-
while (i < len && /[a-zA-Z0-9_\-:.]/.test(source[i])) i++;
|
|
489
|
-
tokens.push({ type: "attribute", start: pos2, end: i });
|
|
490
|
-
while (i < len && (source[i] === " " || source[i] === " ")) i++;
|
|
491
|
-
if (i < len && source[i] === "=") {
|
|
492
|
-
tokens.push({ type: "operator", start: i, end: i + 1 });
|
|
493
|
-
i++;
|
|
494
|
-
while (i < len && (source[i] === " " || source[i] === " ")) i++;
|
|
495
|
-
if (i < len && (source[i] === '"' || source[i] === "'")) {
|
|
496
|
-
const quote = source[i];
|
|
497
|
-
const pos3 = i;
|
|
498
|
-
i++;
|
|
499
|
-
while (i < len && source[i] !== quote) i++;
|
|
500
|
-
i++;
|
|
501
|
-
tokens.push({ type: "attributeValue", start: pos3, end: i });
|
|
502
|
-
} else if (i < len && /[^\s>]/.test(source[i])) {
|
|
503
|
-
const pos3 = i;
|
|
504
|
-
while (i < len && /[^\s>]/.test(source[i])) i++;
|
|
505
|
-
tokens.push({ type: "attributeValue", start: pos3, end: i });
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
continue;
|
|
509
|
-
}
|
|
510
|
-
i++;
|
|
511
|
-
}
|
|
512
|
-
if (i < len && source[i] === "/") {
|
|
513
|
-
tokens.push({ type: "punctuation", start: i, end: i + 1 });
|
|
514
|
-
i++;
|
|
515
|
-
}
|
|
516
|
-
if (i < len && source[i] === ">") {
|
|
517
|
-
tokens.push({ type: "punctuation", start: i, end: i + 1 });
|
|
518
|
-
i++;
|
|
519
|
-
}
|
|
520
|
-
continue;
|
|
521
|
-
}
|
|
522
|
-
const pos = i;
|
|
523
|
-
while (i < len && source[i] !== "<") i++;
|
|
524
|
-
if (i > pos) {
|
|
525
|
-
tokens.push({ type: "plain", start: pos, end: i });
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
return tokens;
|
|
529
|
-
};
|
|
530
|
-
|
|
531
449
|
// src/engine/tokenizers/php.ts
|
|
532
450
|
var PHP_KEYWORDS = /* @__PURE__ */ new Set([
|
|
533
451
|
"abstract",
|
|
@@ -1111,11 +1029,6 @@ var tokenizeGo = (source) => {
|
|
|
1111
1029
|
return tokens;
|
|
1112
1030
|
};
|
|
1113
1031
|
|
|
1114
|
-
// src/engine/tokenizer.ts
|
|
1115
|
-
function tok(type, s, e) {
|
|
1116
|
-
return { type, start: s, end: e };
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
1032
|
// src/engine/tokenizers/markdown.ts
|
|
1120
1033
|
function tokenizeMarkdown(source) {
|
|
1121
1034
|
const tokens = [];
|
|
@@ -1320,112 +1233,17 @@ function getTheme(name) {
|
|
|
1320
1233
|
function getRegisteredThemes() {
|
|
1321
1234
|
return Array.from(themeRegistry.keys());
|
|
1322
1235
|
}
|
|
1323
|
-
|
|
1324
|
-
// src/themes/light.ts
|
|
1325
1236
|
registerTheme({
|
|
1326
1237
|
name: "light",
|
|
1327
1238
|
variant: "light",
|
|
1328
|
-
colors:
|
|
1329
|
-
background: "#ffffff",
|
|
1330
|
-
foreground: "#1e1e2e",
|
|
1331
|
-
gutterBackground: "#f8fafc",
|
|
1332
|
-
gutterForeground: "#94a3b8",
|
|
1333
|
-
gutterBorder: "#e2e8f0",
|
|
1334
|
-
activeLineBackground: "#f8fafc",
|
|
1335
|
-
selectionBackground: "#dbeafe",
|
|
1336
|
-
cursorColor: "#3b82f6",
|
|
1337
|
-
diffAdded: "#1a7f37",
|
|
1338
|
-
diffModified: "#0969da",
|
|
1339
|
-
diffRemoved: "#cf222e",
|
|
1340
|
-
keyword: "#8b5cf6",
|
|
1341
|
-
string: "#059669",
|
|
1342
|
-
comment: "#94a3b8",
|
|
1343
|
-
number: "#d97706",
|
|
1344
|
-
operator: "#0891b2",
|
|
1345
|
-
function: "#2563eb",
|
|
1346
|
-
type: "#d97706",
|
|
1347
|
-
tag: "#dc2626",
|
|
1348
|
-
attribute: "#d97706",
|
|
1349
|
-
attributeValue: "#059669",
|
|
1350
|
-
punctuation: "#64748b",
|
|
1351
|
-
variable: "#1e1e2e"
|
|
1352
|
-
}
|
|
1239
|
+
colors: LIGHT_COLORS
|
|
1353
1240
|
});
|
|
1354
|
-
|
|
1355
|
-
// src/themes/dark.ts
|
|
1356
1241
|
registerTheme({
|
|
1357
1242
|
name: "dark",
|
|
1358
1243
|
variant: "dark",
|
|
1359
|
-
colors:
|
|
1360
|
-
background: "#18181b",
|
|
1361
|
-
foreground: "#e4e4e7",
|
|
1362
|
-
gutterBackground: "#18181b",
|
|
1363
|
-
gutterForeground: "#52525b",
|
|
1364
|
-
gutterBorder: "#27272a",
|
|
1365
|
-
activeLineBackground: "#27272a",
|
|
1366
|
-
selectionBackground: "#1e3a5f",
|
|
1367
|
-
cursorColor: "#60a5fa",
|
|
1368
|
-
diffAdded: "#3fb950",
|
|
1369
|
-
diffModified: "#4184e4",
|
|
1370
|
-
diffRemoved: "#f85149",
|
|
1371
|
-
keyword: "#c084fc",
|
|
1372
|
-
string: "#34d399",
|
|
1373
|
-
comment: "#71717a",
|
|
1374
|
-
number: "#fbbf24",
|
|
1375
|
-
operator: "#22d3ee",
|
|
1376
|
-
function: "#60a5fa",
|
|
1377
|
-
type: "#fbbf24",
|
|
1378
|
-
tag: "#f87171",
|
|
1379
|
-
attribute: "#fbbf24",
|
|
1380
|
-
attributeValue: "#34d399",
|
|
1381
|
-
punctuation: "#a1a1aa",
|
|
1382
|
-
variable: "#e4e4e7"
|
|
1383
|
-
}
|
|
1244
|
+
colors: DARK_COLORS
|
|
1384
1245
|
});
|
|
1385
1246
|
|
|
1386
|
-
// src/engine/highlight.ts
|
|
1387
|
-
function escapeHtml(text) {
|
|
1388
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1389
|
-
}
|
|
1390
|
-
var COLOR_RE = /^(#[0-9a-fA-F]{3,8}|(?:rgb|rgba|hsl|hsla)\([\d\s,.%/-]+\)|[a-zA-Z]+)$/;
|
|
1391
|
-
function safeColor(value) {
|
|
1392
|
-
return typeof value === "string" && COLOR_RE.test(value.trim()) ? value.trim() : "inherit";
|
|
1393
|
-
}
|
|
1394
|
-
function highlightCode(source, tokens, colors) {
|
|
1395
|
-
if (tokens.length === 0) return escapeHtml(source);
|
|
1396
|
-
const colorMap = {
|
|
1397
|
-
keyword: colors.keyword,
|
|
1398
|
-
string: colors.string,
|
|
1399
|
-
comment: colors.comment,
|
|
1400
|
-
number: colors.number,
|
|
1401
|
-
operator: colors.operator,
|
|
1402
|
-
function: colors.function,
|
|
1403
|
-
type: colors.type,
|
|
1404
|
-
tag: colors.tag,
|
|
1405
|
-
attribute: colors.attribute,
|
|
1406
|
-
attributeValue: colors.attributeValue,
|
|
1407
|
-
punctuation: colors.punctuation,
|
|
1408
|
-
variable: colors.variable,
|
|
1409
|
-
plain: colors.foreground
|
|
1410
|
-
};
|
|
1411
|
-
const parts = [];
|
|
1412
|
-
let pos = 0;
|
|
1413
|
-
for (const token of tokens) {
|
|
1414
|
-
if (token.start > pos) {
|
|
1415
|
-
parts.push(escapeHtml(source.slice(pos, token.start)));
|
|
1416
|
-
}
|
|
1417
|
-
const text = escapeHtml(source.slice(token.start, token.end));
|
|
1418
|
-
const color = safeColor(colorMap[token.type]);
|
|
1419
|
-
const style = token.type === "comment" ? `color:${color};font-style:italic` : `color:${color}`;
|
|
1420
|
-
parts.push(`<span style="${style}">${text}</span>`);
|
|
1421
|
-
pos = token.end;
|
|
1422
|
-
}
|
|
1423
|
-
if (pos < source.length) {
|
|
1424
|
-
parts.push(escapeHtml(source.slice(pos)));
|
|
1425
|
-
}
|
|
1426
|
-
return parts.join("");
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
1247
|
// src/engine/position.ts
|
|
1430
1248
|
function lineColumnToOffset(text, line, column = 1) {
|
|
1431
1249
|
const lines = text.split("\n");
|
|
@@ -1818,7 +1636,7 @@ var CodeEditor = Object.assign(CodeEditorRoot, {
|
|
|
1818
1636
|
});
|
|
1819
1637
|
|
|
1820
1638
|
// src/engine/markdown-render.ts
|
|
1821
|
-
function
|
|
1639
|
+
function escapeHtml(s) {
|
|
1822
1640
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1823
1641
|
}
|
|
1824
1642
|
function escapeAttr(s) {
|
|
@@ -1859,10 +1677,10 @@ function renderMarkdown(markdown) {
|
|
|
1859
1677
|
i++;
|
|
1860
1678
|
}
|
|
1861
1679
|
i++;
|
|
1862
|
-
out.push(`<pre><code${lang ? ` class="language-${escapeAttr(
|
|
1680
|
+
out.push(`<pre><code${lang ? ` class="language-${escapeAttr(escapeHtml(lang))}"` : ""}>${escapeHtml(body.join("\n"))}</code></pre>`);
|
|
1863
1681
|
continue;
|
|
1864
1682
|
}
|
|
1865
|
-
const esc =
|
|
1683
|
+
const esc = escapeHtml(line);
|
|
1866
1684
|
if (/^\s*$/.test(line)) {
|
|
1867
1685
|
flushPara();
|
|
1868
1686
|
closeList();
|