prosemirror-highlight 0.13.0 → 0.14.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/README.md +44 -20
- package/dist/hast-Cn9tqyqN.js +35 -0
- package/dist/hast-Cn9tqyqN.js.map +1 -0
- package/dist/index.d.ts +71 -64
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +181 -183
- package/dist/index.js.map +1 -0
- package/dist/lowlight.d.ts +8 -8
- package/dist/lowlight.d.ts.map +1 -0
- package/dist/lowlight.js +12 -14
- package/dist/lowlight.js.map +1 -0
- package/dist/refractor.d.ts +6 -6
- package/dist/refractor.d.ts.map +1 -0
- package/dist/refractor.js +12 -14
- package/dist/refractor.js.map +1 -0
- package/dist/shiki.d.ts +6 -6
- package/dist/shiki.d.ts.map +1 -0
- package/dist/shiki.js +39 -39
- package/dist/shiki.js.map +1 -0
- package/dist/sugar-high.d.ts +5 -5
- package/dist/sugar-high.d.ts.map +1 -0
- package/dist/sugar-high.js +23 -21
- package/dist/sugar-high.js.map +1 -0
- package/dist/types-DCbyVqHc.d.ts +35 -0
- package/dist/types-DCbyVqHc.d.ts.map +1 -0
- package/package.json +25 -31
- package/dist/chunk-ZZGBRRBM.js +0 -46
- package/dist/types-BIUZQh-P.d.ts +0 -33
package/README.md
CHANGED
|
@@ -12,10 +12,9 @@ Highlight your [ProseMirror] code blocks with any syntax highlighter you like!
|
|
|
12
12
|
<summary>Static loading of a fixed set of languages</summary>
|
|
13
13
|
|
|
14
14
|
```ts
|
|
15
|
-
import { getSingletonHighlighter } from 'shiki'
|
|
16
|
-
|
|
17
15
|
import { createHighlightPlugin } from 'prosemirror-highlight'
|
|
18
16
|
import { createParser } from 'prosemirror-highlight/shiki'
|
|
17
|
+
import { getSingletonHighlighter } from 'shiki'
|
|
19
18
|
|
|
20
19
|
const highlighter = await getSingletonHighlighter({
|
|
21
20
|
themes: ['github-light'],
|
|
@@ -31,17 +30,42 @@ export const shikiPlugin = createHighlightPlugin({ parser })
|
|
|
31
30
|
<summary>Dynamic loading of arbitrary languages</summary>
|
|
32
31
|
|
|
33
32
|
```ts
|
|
33
|
+
import { createHighlightPlugin } from 'prosemirror-highlight'
|
|
34
|
+
import { createParser, type Parser } from 'prosemirror-highlight/shiki'
|
|
35
|
+
import type { Decoration } from 'prosemirror-view'
|
|
34
36
|
import {
|
|
35
|
-
|
|
37
|
+
createHighlighter,
|
|
36
38
|
type BuiltinLanguage,
|
|
37
39
|
type Highlighter,
|
|
38
40
|
} from 'shiki'
|
|
39
41
|
|
|
40
|
-
import { createHighlightPlugin } from 'prosemirror-highlight'
|
|
41
|
-
import { createParser, type Parser } from 'prosemirror-highlight/shiki'
|
|
42
|
-
|
|
43
42
|
let highlighter: Highlighter | undefined
|
|
43
|
+
let highlighterPromise: Promise<void> | undefined
|
|
44
44
|
let parser: Parser | undefined
|
|
45
|
+
const loadedLanguages = new Set<string>()
|
|
46
|
+
|
|
47
|
+
function loadHighlighter(): Promise<void> {
|
|
48
|
+
if (!highlighterPromise) {
|
|
49
|
+
highlighterPromise = createHighlighter({
|
|
50
|
+
themes: ['github-light', 'github-dark', 'github-dark-dimmed'],
|
|
51
|
+
langs: [],
|
|
52
|
+
}).then((h) => {
|
|
53
|
+
highlighter = h
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
return highlighterPromise
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function loadLanguage(
|
|
60
|
+
highlighter: Highlighter,
|
|
61
|
+
language: string,
|
|
62
|
+
): Promise<void> {
|
|
63
|
+
try {
|
|
64
|
+
return await highlighter.loadLanguage(language as BuiltinLanguage)
|
|
65
|
+
} finally {
|
|
66
|
+
loadedLanguages.add(language)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
45
69
|
|
|
46
70
|
/**
|
|
47
71
|
* Lazy load highlighter and highlighter languages.
|
|
@@ -50,23 +74,25 @@ let parser: Parser | undefined
|
|
|
50
74
|
* promise that resolves when the highlighter or the language is loaded.
|
|
51
75
|
* Otherwise, it returns an array of decorations.
|
|
52
76
|
*/
|
|
53
|
-
const lazyParser: Parser = (options) => {
|
|
77
|
+
const lazyParser: Parser = (options): Promise<void> | Decoration[] => {
|
|
54
78
|
if (!highlighter) {
|
|
55
|
-
return
|
|
56
|
-
themes: ['github-light'],
|
|
57
|
-
langs: [],
|
|
58
|
-
}).then((h) => {
|
|
59
|
-
highlighter = h
|
|
60
|
-
})
|
|
79
|
+
return loadHighlighter()
|
|
61
80
|
}
|
|
62
81
|
|
|
63
|
-
const language = options.language
|
|
64
|
-
if (language && !
|
|
65
|
-
return
|
|
82
|
+
const language = options.language
|
|
83
|
+
if (language && !loadedLanguages.has(language)) {
|
|
84
|
+
return loadLanguage(highlighter, language)
|
|
66
85
|
}
|
|
67
86
|
|
|
68
87
|
if (!parser) {
|
|
69
|
-
parser = createParser(highlighter
|
|
88
|
+
parser = createParser(highlighter, {
|
|
89
|
+
themes: {
|
|
90
|
+
light: 'github-light',
|
|
91
|
+
dark: 'github-dark',
|
|
92
|
+
dim: 'github-dark-dimmed',
|
|
93
|
+
},
|
|
94
|
+
defaultColor: 'dim',
|
|
95
|
+
})
|
|
70
96
|
}
|
|
71
97
|
|
|
72
98
|
return parser(options)
|
|
@@ -105,7 +131,6 @@ You can use these variables to set the background color and text color of the co
|
|
|
105
131
|
import 'highlight.js/styles/default.css'
|
|
106
132
|
|
|
107
133
|
import { common, createLowlight } from 'lowlight'
|
|
108
|
-
|
|
109
134
|
import { createHighlightPlugin } from 'prosemirror-highlight'
|
|
110
135
|
import { createParser } from 'prosemirror-highlight/lowlight'
|
|
111
136
|
|
|
@@ -122,10 +147,9 @@ export const lowlightPlugin = createHighlightPlugin({ parser })
|
|
|
122
147
|
<summary>Static loading of all languages</summary>
|
|
123
148
|
|
|
124
149
|
```ts
|
|
125
|
-
import { refractor } from 'refractor/all'
|
|
126
|
-
|
|
127
150
|
import { createHighlightPlugin } from 'prosemirror-highlight'
|
|
128
151
|
import { createParser } from 'prosemirror-highlight/refractor'
|
|
152
|
+
import { refractor } from 'refractor/all'
|
|
129
153
|
|
|
130
154
|
const parser = createParser(refractor)
|
|
131
155
|
export const refractorPlugin = createHighlightPlugin({ parser })
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Decoration } from "prosemirror-view";
|
|
2
|
+
|
|
3
|
+
//#region src/hast.ts
|
|
4
|
+
function fillFromRoot(decorations, node, from) {
|
|
5
|
+
for (const child of node.children) from = fillFromRootContent(decorations, child, from);
|
|
6
|
+
}
|
|
7
|
+
function fillFromRootContent(decorations, node, from) {
|
|
8
|
+
if (node.type === "element") {
|
|
9
|
+
const to = from + getElementSize(node);
|
|
10
|
+
const { className, ...rest } = node.properties || {};
|
|
11
|
+
decorations.push(Decoration.inline(from, to, {
|
|
12
|
+
class: className ? Array.isArray(className) ? className.join(" ") : String(className) : void 0,
|
|
13
|
+
...rest,
|
|
14
|
+
nodeName: node.tagName
|
|
15
|
+
}));
|
|
16
|
+
return to;
|
|
17
|
+
} else if (node.type === "text") return from + node.value.length;
|
|
18
|
+
else return from;
|
|
19
|
+
}
|
|
20
|
+
function getElementSize(node) {
|
|
21
|
+
let size = 0;
|
|
22
|
+
for (const child of node.children) size += getElementContentSize(child);
|
|
23
|
+
return size;
|
|
24
|
+
}
|
|
25
|
+
function getElementContentSize(node) {
|
|
26
|
+
switch (node.type) {
|
|
27
|
+
case "element": return getElementSize(node);
|
|
28
|
+
case "text": return node.value.length;
|
|
29
|
+
default: return 0;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { fillFromRoot as t };
|
|
35
|
+
//# sourceMappingURL=hast-Cn9tqyqN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hast-Cn9tqyqN.js","names":[],"sources":["../src/hast.ts"],"sourcesContent":["import type { Element, ElementContent, Root, RootContent } from 'hast'\nimport { Decoration } from 'prosemirror-view'\n\nexport function fillFromRoot(\n decorations: Decoration[],\n node: Root,\n from: number,\n) {\n for (const child of node.children) {\n from = fillFromRootContent(decorations, child, from)\n }\n}\n\nfunction fillFromRootContent(\n decorations: Decoration[],\n node: RootContent,\n from: number,\n): number {\n if (node.type === 'element') {\n const to = from + getElementSize(node)\n const { className, ...rest } = node.properties || {}\n decorations.push(\n Decoration.inline(from, to, {\n class: className\n ? Array.isArray(className)\n ? className.join(' ')\n : String(className)\n : undefined,\n ...rest,\n nodeName: node.tagName,\n }),\n )\n return to\n } else if (node.type === 'text') {\n return from + node.value.length\n } else {\n return from\n }\n}\n\nfunction getElementSize(node: Element): number {\n let size = 0\n\n for (const child of node.children) {\n size += getElementContentSize(child)\n }\n\n return size\n}\n\nfunction getElementContentSize(node: ElementContent): number {\n switch (node.type) {\n case 'element':\n return getElementSize(node)\n case 'text':\n return node.value.length\n default:\n return 0\n }\n}\n"],"mappings":";;;AAGA,SAAgB,aACd,aACA,MACA,MACA;AACA,MAAK,MAAM,SAAS,KAAK,SACvB,QAAO,oBAAoB,aAAa,OAAO,KAAK;;AAIxD,SAAS,oBACP,aACA,MACA,MACQ;AACR,KAAI,KAAK,SAAS,WAAW;EAC3B,MAAM,KAAK,OAAO,eAAe,KAAK;EACtC,MAAM,EAAE,WAAW,GAAG,SAAS,KAAK,cAAc,EAAE;AACpD,cAAY,KACV,WAAW,OAAO,MAAM,IAAI;GAC1B,OAAO,YACH,MAAM,QAAQ,UAAU,GACtB,UAAU,KAAK,IAAI,GACnB,OAAO,UAAU,GACnB;GACJ,GAAG;GACH,UAAU,KAAK;GAChB,CAAC,CACH;AACD,SAAO;YACE,KAAK,SAAS,OACvB,QAAO,OAAO,KAAK,MAAM;KAEzB,QAAO;;AAIX,SAAS,eAAe,MAAuB;CAC7C,IAAI,OAAO;AAEX,MAAK,MAAM,SAAS,KAAK,SACvB,SAAQ,sBAAsB,MAAM;AAGtC,QAAO;;AAGT,SAAS,sBAAsB,MAA8B;AAC3D,SAAQ,KAAK,MAAb;EACE,KAAK,UACH,QAAO,eAAe,KAAK;EAC7B,KAAK,OACH,QAAO,KAAK,MAAM;EACpB,QACE,QAAO"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,80 +1,87 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Decoration, DecorationSet } from
|
|
4
|
-
import {
|
|
1
|
+
import { n as Parser, t as LanguageExtractor } from "./types-DCbyVqHc.js";
|
|
2
|
+
import { Plugin, Transaction } from "prosemirror-state";
|
|
3
|
+
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
4
|
+
import { Node } from "prosemirror-model";
|
|
5
5
|
|
|
6
|
+
//#region src/cache.d.ts
|
|
6
7
|
/**
|
|
7
8
|
* Represents a cache of doc positions to the node and decorations at that position
|
|
8
9
|
*/
|
|
9
10
|
declare class DecorationCache {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
11
|
+
private cache;
|
|
12
|
+
constructor(cache?: Map<number, [node: Node, decorations: Decoration[]]>);
|
|
13
|
+
/**
|
|
14
|
+
* Gets the cache entry at the given doc position, or null if it doesn't exist
|
|
15
|
+
* @param pos The doc position of the node you want the cache for
|
|
16
|
+
*/
|
|
17
|
+
get(pos: number): [node: Node, decorations: Decoration[]] | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Sets the cache entry at the given position with the give node/decoration
|
|
20
|
+
* values
|
|
21
|
+
* @param pos The doc position of the node to set the cache for
|
|
22
|
+
* @param node The node to place in cache
|
|
23
|
+
* @param decorations The decorations to place in cache
|
|
24
|
+
*/
|
|
25
|
+
set(pos: number, node: Node, decorations: Decoration[]): void;
|
|
26
|
+
/**
|
|
27
|
+
* Removes the value at the oldPos (if it exists) and sets the new position to
|
|
28
|
+
* the given values
|
|
29
|
+
* @param oldPos The old node position to overwrite
|
|
30
|
+
* @param newPos The new node position to set the cache for
|
|
31
|
+
* @param node The new node to place in cache
|
|
32
|
+
* @param decorations The new decorations to place in cache
|
|
33
|
+
*/
|
|
34
|
+
private replace;
|
|
35
|
+
/**
|
|
36
|
+
* Removes the cache entry at the given position
|
|
37
|
+
* @param pos The doc position to remove from cache
|
|
38
|
+
*/
|
|
39
|
+
remove(pos: number): void;
|
|
40
|
+
/**
|
|
41
|
+
* Invalidates the cache by removing all decoration entries on nodes that have
|
|
42
|
+
* changed, updating the positions of the nodes that haven't and removing all
|
|
43
|
+
* the entries that have been deleted; NOTE: this does not affect the current
|
|
44
|
+
* cache, but returns an entirely new one
|
|
45
|
+
* @param tr A transaction to map the current cache to
|
|
46
|
+
*/
|
|
47
|
+
invalidate(tr: Transaction): DecorationCache;
|
|
47
48
|
}
|
|
48
|
-
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/plugin.d.ts
|
|
49
51
|
/**
|
|
50
52
|
* Describes the current state of the highlightPlugin
|
|
51
53
|
*/
|
|
52
54
|
interface HighlightPluginState {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
cache: DecorationCache;
|
|
56
|
+
decorations: DecorationSet | undefined;
|
|
57
|
+
promises: Promise<void>[];
|
|
56
58
|
}
|
|
57
59
|
/**
|
|
58
60
|
* Creates a plugin that highlights the contents of all nodes (via Decorations)
|
|
59
61
|
* with a type passed in blockTypes
|
|
60
62
|
*/
|
|
61
|
-
declare function createHighlightPlugin({
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
63
|
+
declare function createHighlightPlugin({
|
|
64
|
+
parser,
|
|
65
|
+
nodeTypes,
|
|
66
|
+
languageExtractor
|
|
67
|
+
}: {
|
|
68
|
+
/**
|
|
69
|
+
* A function that returns an array of decorations for the given node text
|
|
70
|
+
* content, language, and position.
|
|
71
|
+
*/
|
|
72
|
+
parser: Parser;
|
|
73
|
+
/**
|
|
74
|
+
* An array containing all the node type name to target for highlighting.
|
|
75
|
+
*
|
|
76
|
+
* @default ['code_block', 'codeBlock']
|
|
77
|
+
*/
|
|
78
|
+
nodeTypes?: string[];
|
|
79
|
+
/**
|
|
80
|
+
* A function that returns the language string to use when highlighting that
|
|
81
|
+
* node. By default, it returns `node.attrs.language`.
|
|
82
|
+
*/
|
|
83
|
+
languageExtractor?: LanguageExtractor;
|
|
78
84
|
}): Plugin<HighlightPluginState>;
|
|
79
|
-
|
|
80
|
-
export { DecorationCache, type HighlightPluginState, LanguageExtractor, Parser, createHighlightPlugin };
|
|
85
|
+
//#endregion
|
|
86
|
+
export { DecorationCache, type HighlightPluginState, type LanguageExtractor, type Parser, createHighlightPlugin };
|
|
87
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/cache.ts","../src/plugin.ts"],"mappings":";;;;;;;;;cAOa,eAAA;EAAA,QACH,KAAA;cAGN,KAAA,GAAQ,GAAA,UAAa,IAAA,EAAM,IAAA,EAAiB,WAAA,EAAa,UAAA;EAA9B;;;;EAS7B,GAAA,CAAI,GAAA,YAAW,IAAA,EAAA,IAAA,EAAA,WAAA,EAAA,UAAA;EAWQ;;;;;;;EAAvB,GAAA,CAAI,GAAA,UAAa,IAAA,EAAM,IAAA,EAAiB,WAAA,EAAa,UAAA;EApB3C;;;;;;;;EAAA,QAoCF,OAAA;EA3BO;;;;EAyCf,MAAA,CAAO,GAAA;EA9BgB;;;;;;;EAyCvB,UAAA,CAAW,EAAA,EAAI,WAAA,GAAc,eAAA;AAAA;;;;;AAjE/B;UCGiB,oBAAA;EACf,KAAA,EAAO,eAAA;EACP,WAAA,EAAa,aAAA;EACb,QAAA,EAAU,OAAA;AAAA;;;;;iBAOI,qBAAA,CAAA;EACd,MAAA;EACA,SAAA;EACA;AAAA;EDiD6B;;;;EC3C7B,MAAA,EAAQ,MAAA;EDlBE;;;;;ECyBV,SAAA;EDhBA;;;;ECsBA,iBAAA,GAAoB,iBAAA;AAAA,IAClB,MAAA,CAAO,oBAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,188 +1,186 @@
|
|
|
1
|
-
// src/cache.ts
|
|
2
|
-
var DecorationCache = class _DecorationCache {
|
|
3
|
-
constructor(cache) {
|
|
4
|
-
this.cache = new Map(cache);
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Gets the cache entry at the given doc position, or null if it doesn't exist
|
|
8
|
-
* @param pos The doc position of the node you want the cache for
|
|
9
|
-
*/
|
|
10
|
-
get(pos) {
|
|
11
|
-
return this.cache.get(pos);
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Sets the cache entry at the given position with the give node/decoration
|
|
15
|
-
* values
|
|
16
|
-
* @param pos The doc position of the node to set the cache for
|
|
17
|
-
* @param node The node to place in cache
|
|
18
|
-
* @param decorations The decorations to place in cache
|
|
19
|
-
*/
|
|
20
|
-
set(pos, node, decorations) {
|
|
21
|
-
if (pos < 0) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
this.cache.set(pos, [node, decorations]);
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Removes the value at the oldPos (if it exists) and sets the new position to
|
|
28
|
-
* the given values
|
|
29
|
-
* @param oldPos The old node position to overwrite
|
|
30
|
-
* @param newPos The new node position to set the cache for
|
|
31
|
-
* @param node The new node to place in cache
|
|
32
|
-
* @param decorations The new decorations to place in cache
|
|
33
|
-
*/
|
|
34
|
-
replace(oldPos, newPos, node, decorations) {
|
|
35
|
-
this.remove(oldPos);
|
|
36
|
-
this.set(newPos, node, decorations);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Removes the cache entry at the given position
|
|
40
|
-
* @param pos The doc position to remove from cache
|
|
41
|
-
*/
|
|
42
|
-
remove(pos) {
|
|
43
|
-
this.cache.delete(pos);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Invalidates the cache by removing all decoration entries on nodes that have
|
|
47
|
-
* changed, updating the positions of the nodes that haven't and removing all
|
|
48
|
-
* the entries that have been deleted; NOTE: this does not affect the current
|
|
49
|
-
* cache, but returns an entirely new one
|
|
50
|
-
* @param tr A transaction to map the current cache to
|
|
51
|
-
*/
|
|
52
|
-
invalidate(tr) {
|
|
53
|
-
const returnCache = new _DecorationCache(this.cache);
|
|
54
|
-
const mapping = tr.mapping;
|
|
55
|
-
this.cache.forEach(([node, decorations], pos) => {
|
|
56
|
-
if (pos < 0) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
const result = mapping.mapResult(pos);
|
|
60
|
-
const mappedNode = tr.doc.nodeAt(result.pos);
|
|
61
|
-
if (result.deleted || !(mappedNode == null ? void 0 : mappedNode.eq(node))) {
|
|
62
|
-
returnCache.remove(pos);
|
|
63
|
-
} else if (pos !== result.pos) {
|
|
64
|
-
const updatedDecorations = decorations.map((d) => {
|
|
65
|
-
return d.map(mapping, 0, 0);
|
|
66
|
-
}).filter((d) => d != null);
|
|
67
|
-
returnCache.replace(pos, result.pos, mappedNode, updatedDecorations);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
return returnCache;
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// src/plugin.ts
|
|
75
1
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
76
2
|
import { DecorationSet } from "prosemirror-view";
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
3
|
+
|
|
4
|
+
//#region src/cache.ts
|
|
5
|
+
/**
|
|
6
|
+
* Represents a cache of doc positions to the node and decorations at that position
|
|
7
|
+
*/
|
|
8
|
+
var DecorationCache = class DecorationCache {
|
|
9
|
+
constructor(cache) {
|
|
10
|
+
this.cache = new Map(cache);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Gets the cache entry at the given doc position, or null if it doesn't exist
|
|
14
|
+
* @param pos The doc position of the node you want the cache for
|
|
15
|
+
*/
|
|
16
|
+
get(pos) {
|
|
17
|
+
return this.cache.get(pos);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Sets the cache entry at the given position with the give node/decoration
|
|
21
|
+
* values
|
|
22
|
+
* @param pos The doc position of the node to set the cache for
|
|
23
|
+
* @param node The node to place in cache
|
|
24
|
+
* @param decorations The decorations to place in cache
|
|
25
|
+
*/
|
|
26
|
+
set(pos, node, decorations) {
|
|
27
|
+
if (pos < 0) return;
|
|
28
|
+
this.cache.set(pos, [node, decorations]);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Removes the value at the oldPos (if it exists) and sets the new position to
|
|
32
|
+
* the given values
|
|
33
|
+
* @param oldPos The old node position to overwrite
|
|
34
|
+
* @param newPos The new node position to set the cache for
|
|
35
|
+
* @param node The new node to place in cache
|
|
36
|
+
* @param decorations The new decorations to place in cache
|
|
37
|
+
*/
|
|
38
|
+
replace(oldPos, newPos, node, decorations) {
|
|
39
|
+
this.remove(oldPos);
|
|
40
|
+
this.set(newPos, node, decorations);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Removes the cache entry at the given position
|
|
44
|
+
* @param pos The doc position to remove from cache
|
|
45
|
+
*/
|
|
46
|
+
remove(pos) {
|
|
47
|
+
this.cache.delete(pos);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Invalidates the cache by removing all decoration entries on nodes that have
|
|
51
|
+
* changed, updating the positions of the nodes that haven't and removing all
|
|
52
|
+
* the entries that have been deleted; NOTE: this does not affect the current
|
|
53
|
+
* cache, but returns an entirely new one
|
|
54
|
+
* @param tr A transaction to map the current cache to
|
|
55
|
+
*/
|
|
56
|
+
invalidate(tr) {
|
|
57
|
+
const returnCache = new DecorationCache(this.cache);
|
|
58
|
+
const mapping = tr.mapping;
|
|
59
|
+
this.cache.forEach(([node, decorations], pos) => {
|
|
60
|
+
if (pos < 0) return;
|
|
61
|
+
const result = mapping.mapResult(pos);
|
|
62
|
+
const mappedNode = tr.doc.nodeAt(result.pos);
|
|
63
|
+
if (result.deleted || !mappedNode?.eq(node)) returnCache.remove(pos);
|
|
64
|
+
else if (pos !== result.pos) {
|
|
65
|
+
const updatedDecorations = decorations.map((d) => {
|
|
66
|
+
return d.map(mapping, 0, 0);
|
|
67
|
+
}).filter((d) => d != null);
|
|
68
|
+
returnCache.replace(pos, result.pos, mappedNode, updatedDecorations);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return returnCache;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/plugin.ts
|
|
77
|
+
/**
|
|
78
|
+
* Creates a plugin that highlights the contents of all nodes (via Decorations)
|
|
79
|
+
* with a type passed in blockTypes
|
|
80
|
+
*/
|
|
81
|
+
function createHighlightPlugin({ parser, nodeTypes = ["code_block", "codeBlock"], languageExtractor = (node) => node.attrs.language }) {
|
|
82
|
+
const key = new PluginKey("prosemirror-highlight");
|
|
83
|
+
return new Plugin({
|
|
84
|
+
key,
|
|
85
|
+
state: {
|
|
86
|
+
init(_, instance) {
|
|
87
|
+
const cache = new DecorationCache();
|
|
88
|
+
const [decorations, promises] = calculateDecoration(instance.doc, parser, nodeTypes, languageExtractor, cache);
|
|
89
|
+
return {
|
|
90
|
+
cache,
|
|
91
|
+
decorations,
|
|
92
|
+
promises
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
apply: (tr, data) => {
|
|
96
|
+
const cache = data.cache.invalidate(tr);
|
|
97
|
+
const refresh = !!tr.getMeta("prosemirror-highlight-refresh");
|
|
98
|
+
if (!tr.docChanged && !refresh) return {
|
|
99
|
+
cache,
|
|
100
|
+
decorations: data.decorations?.map(tr.mapping, tr.doc),
|
|
101
|
+
promises: data.promises
|
|
102
|
+
};
|
|
103
|
+
const [decorations, promises] = calculateDecoration(tr.doc, parser, nodeTypes, languageExtractor, cache);
|
|
104
|
+
return {
|
|
105
|
+
cache,
|
|
106
|
+
decorations,
|
|
107
|
+
promises
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
view: (view) => {
|
|
112
|
+
const promises = /* @__PURE__ */ new Set();
|
|
113
|
+
const refresh = () => {
|
|
114
|
+
if (promises.size > 0) return;
|
|
115
|
+
const tr = view.state.tr.setMeta("prosemirror-highlight-refresh", true);
|
|
116
|
+
view.dispatch(tr);
|
|
117
|
+
};
|
|
118
|
+
const check = () => {
|
|
119
|
+
const state = key.getState(view.state);
|
|
120
|
+
for (const promise of state?.promises ?? []) {
|
|
121
|
+
promises.add(promise);
|
|
122
|
+
promise.then(() => {
|
|
123
|
+
promises.delete(promise);
|
|
124
|
+
refresh();
|
|
125
|
+
}).catch((error) => {
|
|
126
|
+
console.error("[prosemirror-highlight] Error resolving parser:", error);
|
|
127
|
+
promises.delete(promise);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
check();
|
|
132
|
+
return { update: () => {
|
|
133
|
+
check();
|
|
134
|
+
} };
|
|
135
|
+
},
|
|
136
|
+
props: { decorations(state) {
|
|
137
|
+
return this.getState(state)?.decorations;
|
|
138
|
+
} }
|
|
139
|
+
});
|
|
151
140
|
}
|
|
152
141
|
function calculateDecoration(doc, parser, nodeTypes, languageExtractor, cache) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return [DecorationSet.create(doc, result), promises];
|
|
142
|
+
const allDecorations = [];
|
|
143
|
+
const promises = [];
|
|
144
|
+
const nodes = collectCodeBlocks(doc, nodeTypes);
|
|
145
|
+
try {
|
|
146
|
+
for (const [node, pos] of nodes) {
|
|
147
|
+
const language = languageExtractor(node);
|
|
148
|
+
const cached = cache.get(pos);
|
|
149
|
+
if (cached) {
|
|
150
|
+
const [_, decorations] = cached;
|
|
151
|
+
if (decorations.length > 0) allDecorations.push(decorations);
|
|
152
|
+
} else {
|
|
153
|
+
const parsed = parser({
|
|
154
|
+
content: node.textContent,
|
|
155
|
+
language: language || void 0,
|
|
156
|
+
pos,
|
|
157
|
+
size: node.nodeSize
|
|
158
|
+
});
|
|
159
|
+
if (parsed && Array.isArray(parsed)) {
|
|
160
|
+
cache.set(pos, node, parsed);
|
|
161
|
+
if (parsed.length > 0) allDecorations.push(parsed);
|
|
162
|
+
} else if (parsed instanceof Promise) {
|
|
163
|
+
cache.remove(pos);
|
|
164
|
+
promises.push(parsed);
|
|
165
|
+
} else console.error(`[prosemirror-highlight] Invalid parser result:`, parsed);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error(`[prosemirror-highlight] Error parsing code blocks:`, error);
|
|
170
|
+
}
|
|
171
|
+
return [allDecorations.length > 0 ? DecorationSet.create(doc, allDecorations.flat()) : void 0, promises];
|
|
184
172
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
173
|
+
function collectCodeBlocks(doc, nodeTypes) {
|
|
174
|
+
const nodes = [];
|
|
175
|
+
doc.descendants((node, pos) => {
|
|
176
|
+
if (node.type.isTextblock && nodeTypes.includes(node.type.name)) {
|
|
177
|
+
nodes.push([node, pos]);
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
return nodes;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
//#endregion
|
|
185
|
+
export { DecorationCache, createHighlightPlugin };
|
|
186
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/cache.ts","../src/plugin.ts"],"sourcesContent":["import type { Node as ProseMirrorNode } from 'prosemirror-model'\nimport type { Transaction } from 'prosemirror-state'\nimport type { Decoration } from 'prosemirror-view'\n\n/**\n * Represents a cache of doc positions to the node and decorations at that position\n */\nexport class DecorationCache {\n private cache: Map<number, [node: ProseMirrorNode, decorations: Decoration[]]>\n\n constructor(\n cache?: Map<number, [node: ProseMirrorNode, decorations: Decoration[]]>,\n ) {\n this.cache = new Map(cache)\n }\n\n /**\n * Gets the cache entry at the given doc position, or null if it doesn't exist\n * @param pos The doc position of the node you want the cache for\n */\n get(pos: number) {\n return this.cache.get(pos)\n }\n\n /**\n * Sets the cache entry at the given position with the give node/decoration\n * values\n * @param pos The doc position of the node to set the cache for\n * @param node The node to place in cache\n * @param decorations The decorations to place in cache\n */\n set(pos: number, node: ProseMirrorNode, decorations: Decoration[]): void {\n if (pos < 0) {\n return\n }\n\n this.cache.set(pos, [node, decorations])\n }\n\n /**\n * Removes the value at the oldPos (if it exists) and sets the new position to\n * the given values\n * @param oldPos The old node position to overwrite\n * @param newPos The new node position to set the cache for\n * @param node The new node to place in cache\n * @param decorations The new decorations to place in cache\n */\n private replace(\n oldPos: number,\n newPos: number,\n node: ProseMirrorNode,\n decorations: Decoration[],\n ): void {\n this.remove(oldPos)\n this.set(newPos, node, decorations)\n }\n\n /**\n * Removes the cache entry at the given position\n * @param pos The doc position to remove from cache\n */\n remove(pos: number): void {\n this.cache.delete(pos)\n }\n\n /**\n * Invalidates the cache by removing all decoration entries on nodes that have\n * changed, updating the positions of the nodes that haven't and removing all\n * the entries that have been deleted; NOTE: this does not affect the current\n * cache, but returns an entirely new one\n * @param tr A transaction to map the current cache to\n */\n invalidate(tr: Transaction): DecorationCache {\n const returnCache = new DecorationCache(this.cache)\n const mapping = tr.mapping\n\n this.cache.forEach(([node, decorations], pos) => {\n if (pos < 0) {\n return\n }\n\n const result = mapping.mapResult(pos)\n const mappedNode = tr.doc.nodeAt(result.pos)\n\n if (result.deleted || !mappedNode?.eq(node)) {\n returnCache.remove(pos)\n } else if (pos !== result.pos) {\n // update the decorations' from/to values to match the new node position\n const updatedDecorations = decorations\n .map((d): Decoration | null => {\n // @ts-expect-error: internal api\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n return d.map(mapping, 0, 0) as Decoration | null\n })\n .filter((d): d is Decoration => d != null)\n returnCache.replace(pos, result.pos, mappedNode, updatedDecorations)\n }\n })\n\n return returnCache\n }\n}\n","import type { Node as ProseMirrorNode } from 'prosemirror-model'\nimport { Plugin, PluginKey } from 'prosemirror-state'\nimport { type Decoration, DecorationSet } from 'prosemirror-view'\n\nimport { DecorationCache } from './cache'\nimport type { LanguageExtractor, Parser } from './types'\n\n/**\n * Describes the current state of the highlightPlugin\n */\nexport interface HighlightPluginState {\n cache: DecorationCache\n decorations: DecorationSet | undefined\n promises: Promise<void>[]\n}\n\n/**\n * Creates a plugin that highlights the contents of all nodes (via Decorations)\n * with a type passed in blockTypes\n */\nexport function createHighlightPlugin({\n parser,\n nodeTypes = ['code_block', 'codeBlock'],\n languageExtractor = (node) => node.attrs.language as string | undefined,\n}: {\n /**\n * A function that returns an array of decorations for the given node text\n * content, language, and position.\n */\n parser: Parser\n\n /**\n * An array containing all the node type name to target for highlighting.\n *\n * @default ['code_block', 'codeBlock']\n */\n nodeTypes?: string[]\n\n /**\n * A function that returns the language string to use when highlighting that\n * node. By default, it returns `node.attrs.language`.\n */\n languageExtractor?: LanguageExtractor\n}): Plugin<HighlightPluginState> {\n const key = new PluginKey<HighlightPluginState>('prosemirror-highlight')\n\n return new Plugin<HighlightPluginState>({\n key,\n state: {\n init(_, instance) {\n const cache = new DecorationCache()\n const [decorations, promises] = calculateDecoration(\n instance.doc,\n parser,\n nodeTypes,\n languageExtractor,\n cache,\n )\n\n return { cache, decorations, promises }\n },\n apply: (tr, data) => {\n const cache = data.cache.invalidate(tr)\n const refresh = !!tr.getMeta('prosemirror-highlight-refresh')\n\n if (!tr.docChanged && !refresh) {\n const decorations = data.decorations?.map(tr.mapping, tr.doc)\n const promises = data.promises\n return { cache, decorations, promises }\n }\n\n const [decorations, promises] = calculateDecoration(\n tr.doc,\n parser,\n nodeTypes,\n languageExtractor,\n cache,\n )\n return { cache, decorations, promises }\n },\n },\n view: (view) => {\n const promises = new Set<Promise<void>>()\n\n // Refresh the decorations when all promises resolve\n const refresh = () => {\n if (promises.size > 0) {\n return\n }\n const tr = view.state.tr.setMeta('prosemirror-highlight-refresh', true)\n view.dispatch(tr)\n }\n\n const check = () => {\n const state = key.getState(view.state)\n\n for (const promise of state?.promises ?? []) {\n promises.add(promise)\n promise\n .then(() => {\n promises.delete(promise)\n refresh()\n })\n .catch((error) => {\n console.error(\n '[prosemirror-highlight] Error resolving parser:',\n error,\n )\n promises.delete(promise)\n })\n }\n }\n\n check()\n\n return {\n update: () => {\n check()\n },\n }\n },\n props: {\n decorations(this, state) {\n return this.getState(state)?.decorations\n },\n },\n })\n}\n\nfunction calculateDecoration(\n doc: ProseMirrorNode,\n parser: Parser,\n nodeTypes: string[],\n languageExtractor: LanguageExtractor,\n cache: DecorationCache,\n): [DecorationSet | undefined, Promise<void>[]] {\n const allDecorations: Decoration[][] = []\n const promises: Promise<void>[] = []\n const nodes = collectCodeBlocks(doc, nodeTypes)\n\n try {\n for (const [node, pos] of nodes) {\n const language = languageExtractor(node)\n const cached = cache.get(pos)\n\n if (cached) {\n const [_, decorations] = cached\n if (decorations.length > 0) {\n allDecorations.push(decorations)\n }\n } else {\n const parsed = parser({\n content: node.textContent,\n language: language || undefined,\n pos,\n size: node.nodeSize,\n })\n if (parsed && Array.isArray(parsed)) {\n cache.set(pos, node, parsed)\n if (parsed.length > 0) {\n allDecorations.push(parsed)\n }\n } else if (parsed instanceof Promise) {\n cache.remove(pos)\n promises.push(parsed)\n } else {\n console.error(\n `[prosemirror-highlight] Invalid parser result:`,\n parsed,\n )\n }\n }\n }\n } catch (error) {\n console.error(`[prosemirror-highlight] Error parsing code blocks:`, error)\n }\n\n const decorationSet =\n allDecorations.length > 0\n ? DecorationSet.create(doc, allDecorations.flat())\n : undefined\n return [decorationSet, promises]\n}\n\nfunction collectCodeBlocks(\n doc: ProseMirrorNode,\n nodeTypes: string[],\n): Array<[node: ProseMirrorNode, pos: number]> {\n const nodes: Array<[node: ProseMirrorNode, pos: number]> = []\n doc.descendants((node, pos) => {\n if (node.type.isTextblock && nodeTypes.includes(node.type.name)) {\n nodes.push([node, pos])\n return false\n }\n })\n return nodes\n}\n"],"mappings":";;;;;;;AAOA,IAAa,kBAAb,MAAa,gBAAgB;CAG3B,YACE,OACA;AACA,OAAK,QAAQ,IAAI,IAAI,MAAM;;;;;;CAO7B,IAAI,KAAa;AACf,SAAO,KAAK,MAAM,IAAI,IAAI;;;;;;;;;CAU5B,IAAI,KAAa,MAAuB,aAAiC;AACvE,MAAI,MAAM,EACR;AAGF,OAAK,MAAM,IAAI,KAAK,CAAC,MAAM,YAAY,CAAC;;;;;;;;;;CAW1C,AAAQ,QACN,QACA,QACA,MACA,aACM;AACN,OAAK,OAAO,OAAO;AACnB,OAAK,IAAI,QAAQ,MAAM,YAAY;;;;;;CAOrC,OAAO,KAAmB;AACxB,OAAK,MAAM,OAAO,IAAI;;;;;;;;;CAUxB,WAAW,IAAkC;EAC3C,MAAM,cAAc,IAAI,gBAAgB,KAAK,MAAM;EACnD,MAAM,UAAU,GAAG;AAEnB,OAAK,MAAM,SAAS,CAAC,MAAM,cAAc,QAAQ;AAC/C,OAAI,MAAM,EACR;GAGF,MAAM,SAAS,QAAQ,UAAU,IAAI;GACrC,MAAM,aAAa,GAAG,IAAI,OAAO,OAAO,IAAI;AAE5C,OAAI,OAAO,WAAW,CAAC,YAAY,GAAG,KAAK,CACzC,aAAY,OAAO,IAAI;YACd,QAAQ,OAAO,KAAK;IAE7B,MAAM,qBAAqB,YACxB,KAAK,MAAyB;AAG7B,YAAO,EAAE,IAAI,SAAS,GAAG,EAAE;MAC3B,CACD,QAAQ,MAAuB,KAAK,KAAK;AAC5C,gBAAY,QAAQ,KAAK,OAAO,KAAK,YAAY,mBAAmB;;IAEtE;AAEF,SAAO;;;;;;;;;;AC/EX,SAAgB,sBAAsB,EACpC,QACA,YAAY,CAAC,cAAc,YAAY,EACvC,qBAAqB,SAAS,KAAK,MAAM,YAoBV;CAC/B,MAAM,MAAM,IAAI,UAAgC,wBAAwB;AAExE,QAAO,IAAI,OAA6B;EACtC;EACA,OAAO;GACL,KAAK,GAAG,UAAU;IAChB,MAAM,QAAQ,IAAI,iBAAiB;IACnC,MAAM,CAAC,aAAa,YAAY,oBAC9B,SAAS,KACT,QACA,WACA,mBACA,MACD;AAED,WAAO;KAAE;KAAO;KAAa;KAAU;;GAEzC,QAAQ,IAAI,SAAS;IACnB,MAAM,QAAQ,KAAK,MAAM,WAAW,GAAG;IACvC,MAAM,UAAU,CAAC,CAAC,GAAG,QAAQ,gCAAgC;AAE7D,QAAI,CAAC,GAAG,cAAc,CAAC,QAGrB,QAAO;KAAE;KAAO,aAFI,KAAK,aAAa,IAAI,GAAG,SAAS,GAAG,IAAI;KAEhC,UADZ,KAAK;KACiB;IAGzC,MAAM,CAAC,aAAa,YAAY,oBAC9B,GAAG,KACH,QACA,WACA,mBACA,MACD;AACD,WAAO;KAAE;KAAO;KAAa;KAAU;;GAE1C;EACD,OAAO,SAAS;GACd,MAAM,2BAAW,IAAI,KAAoB;GAGzC,MAAM,gBAAgB;AACpB,QAAI,SAAS,OAAO,EAClB;IAEF,MAAM,KAAK,KAAK,MAAM,GAAG,QAAQ,iCAAiC,KAAK;AACvE,SAAK,SAAS,GAAG;;GAGnB,MAAM,cAAc;IAClB,MAAM,QAAQ,IAAI,SAAS,KAAK,MAAM;AAEtC,SAAK,MAAM,WAAW,OAAO,YAAY,EAAE,EAAE;AAC3C,cAAS,IAAI,QAAQ;AACrB,aACG,WAAW;AACV,eAAS,OAAO,QAAQ;AACxB,eAAS;OACT,CACD,OAAO,UAAU;AAChB,cAAQ,MACN,mDACA,MACD;AACD,eAAS,OAAO,QAAQ;OACxB;;;AAIR,UAAO;AAEP,UAAO,EACL,cAAc;AACZ,WAAO;MAEV;;EAEH,OAAO,EACL,YAAkB,OAAO;AACvB,UAAO,KAAK,SAAS,MAAM,EAAE;KAEhC;EACF,CAAC;;AAGJ,SAAS,oBACP,KACA,QACA,WACA,mBACA,OAC8C;CAC9C,MAAM,iBAAiC,EAAE;CACzC,MAAM,WAA4B,EAAE;CACpC,MAAM,QAAQ,kBAAkB,KAAK,UAAU;AAE/C,KAAI;AACF,OAAK,MAAM,CAAC,MAAM,QAAQ,OAAO;GAC/B,MAAM,WAAW,kBAAkB,KAAK;GACxC,MAAM,SAAS,MAAM,IAAI,IAAI;AAE7B,OAAI,QAAQ;IACV,MAAM,CAAC,GAAG,eAAe;AACzB,QAAI,YAAY,SAAS,EACvB,gBAAe,KAAK,YAAY;UAE7B;IACL,MAAM,SAAS,OAAO;KACpB,SAAS,KAAK;KACd,UAAU,YAAY;KACtB;KACA,MAAM,KAAK;KACZ,CAAC;AACF,QAAI,UAAU,MAAM,QAAQ,OAAO,EAAE;AACnC,WAAM,IAAI,KAAK,MAAM,OAAO;AAC5B,SAAI,OAAO,SAAS,EAClB,gBAAe,KAAK,OAAO;eAEpB,kBAAkB,SAAS;AACpC,WAAM,OAAO,IAAI;AACjB,cAAS,KAAK,OAAO;UAErB,SAAQ,MACN,kDACA,OACD;;;UAIA,OAAO;AACd,UAAQ,MAAM,sDAAsD,MAAM;;AAO5E,QAAO,CAHL,eAAe,SAAS,IACpB,cAAc,OAAO,KAAK,eAAe,MAAM,CAAC,GAChD,QACiB,SAAS;;AAGlC,SAAS,kBACP,KACA,WAC6C;CAC7C,MAAM,QAAqD,EAAE;AAC7D,KAAI,aAAa,MAAM,QAAQ;AAC7B,MAAI,KAAK,KAAK,eAAe,UAAU,SAAS,KAAK,KAAK,KAAK,EAAE;AAC/D,SAAM,KAAK,CAAC,MAAM,IAAI,CAAC;AACvB,UAAO;;GAET;AACF,QAAO"}
|
package/dist/lowlight.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import 'prosemirror-model';
|
|
4
|
-
import 'prosemirror-view';
|
|
1
|
+
import { n as Parser } from "./types-DCbyVqHc.js";
|
|
2
|
+
import { Root } from "hast";
|
|
5
3
|
|
|
4
|
+
//#region src/lowlight.d.ts
|
|
6
5
|
type Lowlight = {
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
highlight: (language: string, value: string) => Root;
|
|
7
|
+
highlightAuto: (value: string) => Root;
|
|
9
8
|
};
|
|
10
9
|
declare function createParser(lowlight: Lowlight): Parser;
|
|
11
|
-
|
|
12
|
-
export {
|
|
10
|
+
//#endregion
|
|
11
|
+
export { Lowlight, type Parser, createParser };
|
|
12
|
+
//# sourceMappingURL=lowlight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lowlight.d.ts","names":[],"sources":["../src/lowlight.ts"],"mappings":";;;;KAQY,QAAA;EACV,SAAA,GAAY,QAAA,UAAkB,KAAA,aAAkB,IAAA;EAChD,aAAA,GAAgB,KAAA,aAAkB,IAAA;AAAA;AAAA,iBAGpB,YAAA,CAAa,QAAA,EAAU,QAAA,GAAW,MAAA"}
|
package/dist/lowlight.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
fillFromRoot
|
|
3
|
-
} from "./chunk-ZZGBRRBM.js";
|
|
1
|
+
import { t as fillFromRoot } from "./hast-Cn9tqyqN.js";
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
//#region src/lowlight.ts
|
|
6
4
|
function createParser(lowlight) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
5
|
+
return function highlighter({ content, language, pos }) {
|
|
6
|
+
const root = language ? lowlight.highlight(language, content) : lowlight.highlightAuto(content);
|
|
7
|
+
const decorations = [];
|
|
8
|
+
fillFromRoot(decorations, root, pos + 1);
|
|
9
|
+
return decorations;
|
|
10
|
+
};
|
|
14
11
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
};
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { createParser };
|
|
15
|
+
//# sourceMappingURL=lowlight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lowlight.js","names":[],"sources":["../src/lowlight.ts"],"sourcesContent":["import type { Root } from 'hast'\nimport type { Decoration } from 'prosemirror-view'\n\nimport { fillFromRoot } from './hast'\nimport type { Parser } from './types'\n\nexport type { Parser }\n\nexport type Lowlight = {\n highlight: (language: string, value: string) => Root\n highlightAuto: (value: string) => Root\n}\n\nexport function createParser(lowlight: Lowlight): Parser {\n return function highlighter({ content, language, pos }) {\n const root = language\n ? lowlight.highlight(language, content)\n : lowlight.highlightAuto(content)\n\n const decorations: Decoration[] = []\n const from = pos + 1\n fillFromRoot(decorations, root, from)\n return decorations\n }\n}\n"],"mappings":";;;AAaA,SAAgB,aAAa,UAA4B;AACvD,QAAO,SAAS,YAAY,EAAE,SAAS,UAAU,OAAO;EACtD,MAAM,OAAO,WACT,SAAS,UAAU,UAAU,QAAQ,GACrC,SAAS,cAAc,QAAQ;EAEnC,MAAM,cAA4B,EAAE;AAEpC,eAAa,aAAa,MADb,MAAM,EACkB;AACrC,SAAO"}
|
package/dist/refractor.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import 'prosemirror-model';
|
|
4
|
-
import 'prosemirror-view';
|
|
1
|
+
import { n as Parser } from "./types-DCbyVqHc.js";
|
|
2
|
+
import { Refractor } from "refractor/core";
|
|
5
3
|
|
|
4
|
+
//#region src/refractor.d.ts
|
|
6
5
|
declare function createParser(refractor: Refractor): Parser;
|
|
7
|
-
|
|
8
|
-
export { Parser, createParser };
|
|
6
|
+
//#endregion
|
|
7
|
+
export { type Parser, createParser };
|
|
8
|
+
//# sourceMappingURL=refractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refractor.d.ts","names":[],"sources":["../src/refractor.ts"],"mappings":";;;;iBASgB,YAAA,CAAa,SAAA,EAAW,SAAA,GAAY,MAAA"}
|
package/dist/refractor.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
fillFromRoot
|
|
3
|
-
} from "./chunk-ZZGBRRBM.js";
|
|
1
|
+
import { t as fillFromRoot } from "./hast-Cn9tqyqN.js";
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
//#region src/refractor.ts
|
|
6
4
|
function createParser(refractor) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
5
|
+
return function highlighter({ content, language, pos }) {
|
|
6
|
+
const root = refractor.highlight(content, language || "");
|
|
7
|
+
const decorations = [];
|
|
8
|
+
fillFromRoot(decorations, root, pos + 1);
|
|
9
|
+
return decorations;
|
|
10
|
+
};
|
|
14
11
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
};
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { createParser };
|
|
15
|
+
//# sourceMappingURL=refractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refractor.js","names":[],"sources":["../src/refractor.ts"],"sourcesContent":["import type { Root } from 'hast'\nimport type { Decoration } from 'prosemirror-view'\nimport type { Refractor } from 'refractor/core'\n\nimport { fillFromRoot } from './hast'\nimport type { Parser } from './types'\n\nexport type { Parser }\n\nexport function createParser(refractor: Refractor): Parser {\n return function highlighter({ content, language, pos }) {\n const root: Root = refractor.highlight(content, language || '')\n\n const decorations: Decoration[] = []\n const from = pos + 1\n\n fillFromRoot(decorations, root, from)\n return decorations\n }\n}\n"],"mappings":";;;AASA,SAAgB,aAAa,WAA8B;AACzD,QAAO,SAAS,YAAY,EAAE,SAAS,UAAU,OAAO;EACtD,MAAM,OAAa,UAAU,UAAU,SAAS,YAAY,GAAG;EAE/D,MAAM,cAA4B,EAAE;AAGpC,eAAa,aAAa,MAFb,MAAM,EAEkB;AACrC,SAAO"}
|
package/dist/shiki.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import 'prosemirror-model';
|
|
4
|
-
import 'prosemirror-view';
|
|
1
|
+
import { n as Parser } from "./types-DCbyVqHc.js";
|
|
2
|
+
import { CodeToTokensOptions, HighlighterGeneric } from "@shikijs/types";
|
|
5
3
|
|
|
4
|
+
//#region src/shiki.d.ts
|
|
6
5
|
declare function createParser<Language extends string = string, Theme extends string = string>(highlighter: HighlighterGeneric<Language, Theme>, options?: CodeToTokensOptions<Language, Theme>): Parser;
|
|
7
|
-
|
|
8
|
-
export { Parser, createParser };
|
|
6
|
+
//#endregion
|
|
7
|
+
export { type Parser, createParser };
|
|
8
|
+
//# sourceMappingURL=shiki.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shiki.d.ts","names":[],"sources":["../src/shiki.ts"],"mappings":";;;;iBAOgB,YAAA,iEAAA,CAId,WAAA,EAAa,kBAAA,CAAmB,QAAA,EAAU,KAAA,GAC1C,OAAA,GAAU,mBAAA,CAAoB,QAAA,EAAU,KAAA,IACvC,MAAA"}
|
package/dist/shiki.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
// src/shiki.ts
|
|
2
1
|
import { Decoration } from "prosemirror-view";
|
|
2
|
+
|
|
3
|
+
//#region src/shiki.ts
|
|
3
4
|
function createParser(highlighter, options) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
decorations.push(decoration);
|
|
31
|
-
from = to;
|
|
32
|
-
}
|
|
33
|
-
from += 1;
|
|
34
|
-
}
|
|
35
|
-
return decorations;
|
|
36
|
-
};
|
|
5
|
+
return function parser({ content, language, pos, size }) {
|
|
6
|
+
const decorations = [];
|
|
7
|
+
const { tokens, fg, bg, rootStyle } = highlighter.codeToTokens(content, {
|
|
8
|
+
lang: language,
|
|
9
|
+
...options ?? { theme: highlighter.getLoadedThemes()[0] }
|
|
10
|
+
});
|
|
11
|
+
const style = rootStyle || (fg && bg ? `--prosemirror-highlight:${fg};--prosemirror-highlight-bg:${bg}` : "");
|
|
12
|
+
if (style) {
|
|
13
|
+
const decoration = Decoration.node(pos, pos + size, { style });
|
|
14
|
+
decorations.push(decoration);
|
|
15
|
+
}
|
|
16
|
+
let from = pos + 1;
|
|
17
|
+
for (const line of tokens) {
|
|
18
|
+
for (const token of line) {
|
|
19
|
+
const to = from + token.content.length;
|
|
20
|
+
const decoration = Decoration.inline(from, to, {
|
|
21
|
+
style: stringifyTokenStyle(token.htmlStyle ?? `color: ${token.color}`),
|
|
22
|
+
class: "shiki"
|
|
23
|
+
});
|
|
24
|
+
decorations.push(decoration);
|
|
25
|
+
from = to;
|
|
26
|
+
}
|
|
27
|
+
from += 1;
|
|
28
|
+
}
|
|
29
|
+
return decorations;
|
|
30
|
+
};
|
|
37
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Copied from https://github.com/shikijs/shiki/blob/f76a371dbc2752cba341023df00ebfe9b66cb3f6/packages/core/src/utils.ts#L213
|
|
34
|
+
*
|
|
35
|
+
* Copy instead of import it from `shiki` to avoid importing the `shiki` package in this file.
|
|
36
|
+
*/
|
|
38
37
|
function stringifyTokenStyle(token) {
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
if (typeof token === "string") return token;
|
|
39
|
+
return Object.entries(token).map(([key, value]) => `${key}:${value}`).join(";");
|
|
41
40
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { createParser };
|
|
44
|
+
//# sourceMappingURL=shiki.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shiki.js","names":[],"sources":["../src/shiki.ts"],"sourcesContent":["import type { CodeToTokensOptions, HighlighterGeneric } from '@shikijs/types'\nimport { Decoration } from 'prosemirror-view'\n\nimport type { Parser } from './types'\n\nexport type { Parser }\n\nexport function createParser<\n Language extends string = string,\n Theme extends string = string,\n>(\n highlighter: HighlighterGeneric<Language, Theme>,\n options?: CodeToTokensOptions<Language, Theme>,\n): Parser {\n return function parser({ content, language, pos, size }) {\n const decorations: Decoration[] = []\n\n const { tokens, fg, bg, rootStyle } = highlighter.codeToTokens(content, {\n lang: language as Language | undefined,\n\n // Use provided options for themes or just use first loaded theme\n ...(options ?? {\n theme: highlighter.getLoadedThemes()[0],\n }),\n })\n\n const style =\n rootStyle ||\n (fg && bg\n ? `--prosemirror-highlight:${fg};--prosemirror-highlight-bg:${bg}`\n : '')\n\n if (style) {\n const decoration = Decoration.node(pos, pos + size, { style })\n decorations.push(decoration)\n }\n\n let from = pos + 1\n\n for (const line of tokens) {\n for (const token of line) {\n const to = from + token.content.length\n\n const decoration = Decoration.inline(from, to, {\n // When using `options.themes` the `htmlStyle` field will be set, otherwise `color` will be set\n style: stringifyTokenStyle(\n token.htmlStyle ?? `color: ${token.color}`,\n ),\n class: 'shiki',\n })\n\n decorations.push(decoration)\n\n from = to\n }\n\n from += 1\n }\n\n return decorations\n }\n}\n\n/**\n * Copied from https://github.com/shikijs/shiki/blob/f76a371dbc2752cba341023df00ebfe9b66cb3f6/packages/core/src/utils.ts#L213\n *\n * Copy instead of import it from `shiki` to avoid importing the `shiki` package in this file.\n */\nfunction stringifyTokenStyle(token: string | Record<string, string>): string {\n if (typeof token === 'string') return token\n return Object.entries(token)\n .map(([key, value]) => `${key}:${value}`)\n .join(';')\n}\n"],"mappings":";;;AAOA,SAAgB,aAId,aACA,SACQ;AACR,QAAO,SAAS,OAAO,EAAE,SAAS,UAAU,KAAK,QAAQ;EACvD,MAAM,cAA4B,EAAE;EAEpC,MAAM,EAAE,QAAQ,IAAI,IAAI,cAAc,YAAY,aAAa,SAAS;GACtE,MAAM;GAGN,GAAI,WAAW,EACb,OAAO,YAAY,iBAAiB,CAAC,IACtC;GACF,CAAC;EAEF,MAAM,QACJ,cACC,MAAM,KACH,2BAA2B,GAAG,8BAA8B,OAC5D;AAEN,MAAI,OAAO;GACT,MAAM,aAAa,WAAW,KAAK,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AAC9D,eAAY,KAAK,WAAW;;EAG9B,IAAI,OAAO,MAAM;AAEjB,OAAK,MAAM,QAAQ,QAAQ;AACzB,QAAK,MAAM,SAAS,MAAM;IACxB,MAAM,KAAK,OAAO,MAAM,QAAQ;IAEhC,MAAM,aAAa,WAAW,OAAO,MAAM,IAAI;KAE7C,OAAO,oBACL,MAAM,aAAa,UAAU,MAAM,QACpC;KACD,OAAO;KACR,CAAC;AAEF,gBAAY,KAAK,WAAW;AAE5B,WAAO;;AAGT,WAAQ;;AAGV,SAAO;;;;;;;;AASX,SAAS,oBAAoB,OAAgD;AAC3E,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAO,OAAO,QAAQ,MAAM,CACzB,KAAK,CAAC,KAAK,WAAW,GAAG,IAAI,GAAG,QAAQ,CACxC,KAAK,IAAI"}
|
package/dist/sugar-high.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import 'prosemirror-model';
|
|
3
|
-
import 'prosemirror-view';
|
|
1
|
+
import { n as Parser } from "./types-DCbyVqHc.js";
|
|
4
2
|
|
|
3
|
+
//#region src/sugar-high.d.ts
|
|
5
4
|
declare function createParser(): Parser;
|
|
6
|
-
|
|
7
|
-
export { Parser, createParser };
|
|
5
|
+
//#endregion
|
|
6
|
+
export { type Parser, createParser };
|
|
7
|
+
//# sourceMappingURL=sugar-high.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sugar-high.d.ts","names":[],"sources":["../src/sugar-high.ts"],"mappings":";;;iBASgB,YAAA,CAAA,GAAgB,MAAA"}
|
package/dist/sugar-high.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
// src/sugar-high.ts
|
|
2
1
|
import { Decoration } from "prosemirror-view";
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { SugarHigh, tokenize } from "sugar-high";
|
|
3
|
+
|
|
4
|
+
//#region src/sugar-high.ts
|
|
5
|
+
const types = SugarHigh.TokenTypes;
|
|
5
6
|
function createParser() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
return function parser({ content, pos }) {
|
|
8
|
+
const decorations = [];
|
|
9
|
+
const tokens = tokenize(content);
|
|
10
|
+
let from = pos + 1;
|
|
11
|
+
for (const [type, content] of tokens) {
|
|
12
|
+
const to = from + content.length;
|
|
13
|
+
const decoration = Decoration.inline(from, to, {
|
|
14
|
+
class: `sh__token--${types[type]}`,
|
|
15
|
+
style: `color: var(--sh-${types[type]})`
|
|
16
|
+
});
|
|
17
|
+
decorations.push(decoration);
|
|
18
|
+
from = to;
|
|
19
|
+
}
|
|
20
|
+
return decorations;
|
|
21
|
+
};
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { createParser };
|
|
26
|
+
//# sourceMappingURL=sugar-high.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sugar-high.js","names":[],"sources":["../src/sugar-high.ts"],"sourcesContent":["import { Decoration } from 'prosemirror-view'\nimport { tokenize, SugarHigh } from 'sugar-high'\n\nimport type { Parser } from './types'\n\nexport type { Parser }\n\nconst types = SugarHigh.TokenTypes\n\nexport function createParser(): Parser {\n return function parser({ content, pos }) {\n const decorations: Decoration[] = []\n\n const tokens = tokenize(content)\n\n let from = pos + 1\n\n for (const [type, content] of tokens) {\n const to = from + content.length\n\n const decoration = Decoration.inline(from, to, {\n class: `sh__token--${types[type]}`,\n style: `color: var(--sh-${types[type]})`,\n })\n\n decorations.push(decoration)\n\n from = to\n }\n\n return decorations\n }\n}\n"],"mappings":";;;;AAOA,MAAM,QAAQ,UAAU;AAExB,SAAgB,eAAuB;AACrC,QAAO,SAAS,OAAO,EAAE,SAAS,OAAO;EACvC,MAAM,cAA4B,EAAE;EAEpC,MAAM,SAAS,SAAS,QAAQ;EAEhC,IAAI,OAAO,MAAM;AAEjB,OAAK,MAAM,CAAC,MAAM,YAAY,QAAQ;GACpC,MAAM,KAAK,OAAO,QAAQ;GAE1B,MAAM,aAAa,WAAW,OAAO,MAAM,IAAI;IAC7C,OAAO,cAAc,MAAM;IAC3B,OAAO,mBAAmB,MAAM,MAAM;IACvC,CAAC;AAEF,eAAY,KAAK,WAAW;AAE5B,UAAO;;AAGT,SAAO"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Decoration } from "prosemirror-view";
|
|
2
|
+
import { Node } from "prosemirror-model";
|
|
3
|
+
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* A function that parses the text content of a code block node and returns an
|
|
7
|
+
* array of ProseMirror decorations. If the underlying syntax highlighter is
|
|
8
|
+
* still loading, you can return a promise that will be resolved when the
|
|
9
|
+
* highlighter is ready.
|
|
10
|
+
*/
|
|
11
|
+
type Parser = (options: {
|
|
12
|
+
/**
|
|
13
|
+
* The text content of the code block node.
|
|
14
|
+
*/
|
|
15
|
+
content: string;
|
|
16
|
+
/**
|
|
17
|
+
* The start position of the code block node.
|
|
18
|
+
*/
|
|
19
|
+
pos: number;
|
|
20
|
+
/**
|
|
21
|
+
* The language of the code block node.
|
|
22
|
+
*/
|
|
23
|
+
language?: string;
|
|
24
|
+
/**
|
|
25
|
+
* The size of the code block node.
|
|
26
|
+
*/
|
|
27
|
+
size: number;
|
|
28
|
+
}) => Decoration[] | Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* A function that extracts the language of a code block node.
|
|
31
|
+
*/
|
|
32
|
+
type LanguageExtractor = (node: Node) => string | undefined;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { Parser as n, LanguageExtractor as t };
|
|
35
|
+
//# sourceMappingURL=types-DCbyVqHc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-DCbyVqHc.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;AASA;;;;KAAY,MAAA,IAAU,OAAA;EASpB;;;EALA,OAAA;EAgBI;;;EAXJ,GAAA;EAgBU;;;EAXV,QAAA;EAWoD;;;EANpD,IAAA;AAAA,MACI,UAAA,KAAe,OAAA;;;;KAKT,iBAAA,IAAqB,IAAA,EAAM,IAAA"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prosemirror-highlight",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.0",
|
|
5
5
|
"description": "A ProseMirror plugin to highlight code blocks",
|
|
6
6
|
"author": "ocavue <ocavue@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -63,6 +63,9 @@
|
|
|
63
63
|
"sugar-high": "^0.6.1 || ^0.7.0 || ^0.8.0 || ^0.9.0"
|
|
64
64
|
},
|
|
65
65
|
"peerDependenciesMeta": {
|
|
66
|
+
"@shikijs/types": {
|
|
67
|
+
"optional": true
|
|
68
|
+
},
|
|
66
69
|
"@types/hast": {
|
|
67
70
|
"optional": true
|
|
68
71
|
},
|
|
@@ -87,53 +90,44 @@
|
|
|
87
90
|
"refractor": {
|
|
88
91
|
"optional": true
|
|
89
92
|
},
|
|
90
|
-
"@shikijs/types": {
|
|
91
|
-
"optional": true
|
|
92
|
-
},
|
|
93
93
|
"sugar-high": {
|
|
94
94
|
"optional": true
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
97
|
"devDependencies": {
|
|
98
|
-
"@
|
|
99
|
-
"@ocavue/
|
|
98
|
+
"@ocavue/eslint-config": "^3.11.2",
|
|
99
|
+
"@ocavue/tsconfig": "^0.6.3",
|
|
100
|
+
"@shikijs/types": "^3.22.0",
|
|
100
101
|
"@types/hast": "^3.0.4",
|
|
101
|
-
"@types/node": "^
|
|
102
|
-
"eslint": "^9.
|
|
102
|
+
"@types/node": "^24.0.0",
|
|
103
|
+
"eslint": "^9.39.2",
|
|
103
104
|
"highlight.js": "^11.11.1",
|
|
104
|
-
"jsdom": "^
|
|
105
|
+
"jsdom": "^28.0.0",
|
|
105
106
|
"lowlight": "^3.3.0",
|
|
106
|
-
"pkg-pr-new": "^0.0.
|
|
107
|
-
"prettier": "^3.
|
|
107
|
+
"pkg-pr-new": "^0.0.63",
|
|
108
|
+
"prettier": "^3.8.1",
|
|
108
109
|
"prosemirror-example-setup": "^1.2.3",
|
|
109
|
-
"prosemirror-model": "^1.
|
|
110
|
-
"prosemirror-schema-basic": "^1.2.
|
|
111
|
-
"prosemirror-state": "^1.4.
|
|
112
|
-
"prosemirror-transform": "^1.
|
|
113
|
-
"prosemirror-view": "^1.
|
|
110
|
+
"prosemirror-model": "^1.25.4",
|
|
111
|
+
"prosemirror-schema-basic": "^1.2.4",
|
|
112
|
+
"prosemirror-state": "^1.4.4",
|
|
113
|
+
"prosemirror-transform": "^1.11.0",
|
|
114
|
+
"prosemirror-view": "^1.41.6",
|
|
114
115
|
"refractor": "^5.0.0",
|
|
115
|
-
"shiki": "^3.
|
|
116
|
-
"sugar-high": "^0.9.
|
|
117
|
-
"
|
|
118
|
-
"typescript": "^5.
|
|
119
|
-
"vite": "^
|
|
120
|
-
"vitest": "^
|
|
121
|
-
},
|
|
122
|
-
"renovate": {
|
|
123
|
-
"dependencyDashboard": true,
|
|
124
|
-
"extends": [
|
|
125
|
-
"github>ocavue/config-renovate"
|
|
126
|
-
]
|
|
116
|
+
"shiki": "^3.22.0",
|
|
117
|
+
"sugar-high": "^0.9.5",
|
|
118
|
+
"tsdown": "^0.20.3",
|
|
119
|
+
"typescript": "^5.9.3",
|
|
120
|
+
"vite": "^7.3.1",
|
|
121
|
+
"vitest": "^4.0.18"
|
|
127
122
|
},
|
|
128
123
|
"scripts": {
|
|
129
124
|
"dev": "vite",
|
|
130
|
-
"build": "
|
|
125
|
+
"build": "tsdown",
|
|
131
126
|
"build:playground": "vite build",
|
|
132
127
|
"lint": "eslint .",
|
|
133
128
|
"fix": "eslint --fix . && prettier --write .",
|
|
134
|
-
"start": "esno src/index.ts",
|
|
135
129
|
"test": "vitest",
|
|
136
|
-
"typecheck": "tsc
|
|
130
|
+
"typecheck": "tsc -b"
|
|
137
131
|
},
|
|
138
132
|
"typesVersions": {
|
|
139
133
|
"*": {
|
package/dist/chunk-ZZGBRRBM.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// src/hast.ts
|
|
2
|
-
import { Decoration } from "prosemirror-view";
|
|
3
|
-
function fillFromRoot(decorations, node, from) {
|
|
4
|
-
for (const child of node.children) {
|
|
5
|
-
from = fillFromRootContent(decorations, child, from);
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
function fillFromRootContent(decorations, node, from) {
|
|
9
|
-
if (node.type === "element") {
|
|
10
|
-
const to = from + getElementSize(node);
|
|
11
|
-
const { className, ...rest } = node.properties || {};
|
|
12
|
-
decorations.push(
|
|
13
|
-
Decoration.inline(from, to, {
|
|
14
|
-
class: className ? Array.isArray(className) ? className.join(" ") : String(className) : void 0,
|
|
15
|
-
...rest,
|
|
16
|
-
nodeName: node.tagName
|
|
17
|
-
})
|
|
18
|
-
);
|
|
19
|
-
return to;
|
|
20
|
-
} else if (node.type === "text") {
|
|
21
|
-
return from + node.value.length;
|
|
22
|
-
} else {
|
|
23
|
-
return from;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function getElementSize(node) {
|
|
27
|
-
let size = 0;
|
|
28
|
-
for (const child of node.children) {
|
|
29
|
-
size += getElementContentSize(child);
|
|
30
|
-
}
|
|
31
|
-
return size;
|
|
32
|
-
}
|
|
33
|
-
function getElementContentSize(node) {
|
|
34
|
-
switch (node.type) {
|
|
35
|
-
case "element":
|
|
36
|
-
return getElementSize(node);
|
|
37
|
-
case "text":
|
|
38
|
-
return node.value.length;
|
|
39
|
-
default:
|
|
40
|
-
return 0;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export {
|
|
45
|
-
fillFromRoot
|
|
46
|
-
};
|
package/dist/types-BIUZQh-P.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Node } from 'prosemirror-model';
|
|
2
|
-
import { Decoration } from 'prosemirror-view';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A function that parses the text content of a code block node and returns an
|
|
6
|
-
* array of ProseMirror decorations. If the underlying syntax highlighter is
|
|
7
|
-
* still loading, you can return a promise that will be resolved when the
|
|
8
|
-
* highlighter is ready.
|
|
9
|
-
*/
|
|
10
|
-
type Parser = (options: {
|
|
11
|
-
/**
|
|
12
|
-
* The text content of the code block node.
|
|
13
|
-
*/
|
|
14
|
-
content: string;
|
|
15
|
-
/**
|
|
16
|
-
* The start position of the code block node.
|
|
17
|
-
*/
|
|
18
|
-
pos: number;
|
|
19
|
-
/**
|
|
20
|
-
* The language of the code block node.
|
|
21
|
-
*/
|
|
22
|
-
language?: string;
|
|
23
|
-
/**
|
|
24
|
-
* The size of the code block node.
|
|
25
|
-
*/
|
|
26
|
-
size: number;
|
|
27
|
-
}) => Decoration[] | Promise<void>;
|
|
28
|
-
/**
|
|
29
|
-
* A function that extracts the language of a code block node.
|
|
30
|
-
*/
|
|
31
|
-
type LanguageExtractor = (node: Node) => string | undefined;
|
|
32
|
-
|
|
33
|
-
export type { LanguageExtractor as L, Parser as P };
|