prosemirror-highlight 0.15.1 → 0.15.2
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/dist/{hast-Cn9tqyqN.js → hast-CWvQRbqI.js} +2 -3
- package/dist/{hast-Cn9tqyqN.js.map → hast-CWvQRbqI.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -5
- package/dist/index.js.map +1 -1
- package/dist/lezer.d.ts +1 -1
- package/dist/lezer.js +1 -2
- package/dist/lezer.js.map +1 -1
- package/dist/lowlight.d.ts +1 -1
- package/dist/lowlight.js +2 -3
- package/dist/lowlight.js.map +1 -1
- package/dist/refractor.d.ts +1 -1
- package/dist/refractor.js +2 -3
- package/dist/refractor.js.map +1 -1
- package/dist/shiki.d.ts +1 -1
- package/dist/shiki.js +1 -2
- package/dist/shiki.js.map +1 -1
- package/dist/sugar-high.d.ts +1 -1
- package/dist/sugar-high.js +1 -2
- package/dist/sugar-high.js.map +1 -1
- package/dist/{types-jXJYKXGQ.d.ts → types-LIvFgazU.d.ts} +1 -1
- package/dist/{types-jXJYKXGQ.d.ts.map → types-LIvFgazU.d.ts.map} +1 -1
- package/package.json +19 -19
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Decoration } from "prosemirror-view";
|
|
2
|
-
|
|
3
2
|
//#region src/hast.ts
|
|
4
3
|
function fillFromRoot(decorations, node, from) {
|
|
5
4
|
for (const child of node.children) from = fillFromRootContent(decorations, child, from);
|
|
@@ -29,7 +28,7 @@ function getElementContentSize(node) {
|
|
|
29
28
|
default: return 0;
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
|
-
|
|
33
31
|
//#endregion
|
|
34
32
|
export { fillFromRoot as t };
|
|
35
|
-
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=hast-CWvQRbqI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hast-
|
|
1
|
+
{"version":3,"file":"hast-CWvQRbqI.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,KAAA;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,4 +1,4 @@
|
|
|
1
|
-
import { n as Parser, r as ParserOptions, t as LanguageExtractor } from "./types-
|
|
1
|
+
import { n as Parser, r as ParserOptions, t as LanguageExtractor } from "./types-LIvFgazU.js";
|
|
2
2
|
import { Plugin, Transaction } from "prosemirror-state";
|
|
3
3
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
4
4
|
import { Node } from "prosemirror-model";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2
2
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
3
|
-
|
|
4
3
|
//#region src/cache.ts
|
|
5
4
|
/**
|
|
6
5
|
* Represents a cache of doc positions to the node and decorations at that position
|
|
@@ -71,7 +70,6 @@ var DecorationCache = class DecorationCache {
|
|
|
71
70
|
return returnCache;
|
|
72
71
|
}
|
|
73
72
|
};
|
|
74
|
-
|
|
75
73
|
//#endregion
|
|
76
74
|
//#region src/plugin.ts
|
|
77
75
|
/**
|
|
@@ -111,7 +109,7 @@ function createHighlightPlugin({ parser, nodeTypes = ["code_block", "codeBlock"]
|
|
|
111
109
|
view: (view) => {
|
|
112
110
|
const promises = /* @__PURE__ */ new Set();
|
|
113
111
|
const refresh = () => {
|
|
114
|
-
if (promises.size > 0) return;
|
|
112
|
+
if (promises.size > 0 || view.isDestroyed) return;
|
|
115
113
|
const tr = view.state.tr.setMeta("prosemirror-highlight-refresh", true);
|
|
116
114
|
view.dispatch(tr);
|
|
117
115
|
};
|
|
@@ -180,7 +178,6 @@ function collectCodeBlocks(doc, nodeTypes) {
|
|
|
180
178
|
});
|
|
181
179
|
return nodes;
|
|
182
180
|
}
|
|
183
|
-
|
|
184
181
|
//#endregion
|
|
185
182
|
//#region src/line-number.ts
|
|
186
183
|
/**
|
|
@@ -216,7 +213,7 @@ function createLineStartSpan(lineNumber) {
|
|
|
216
213
|
span.textContent = lineNumber.toString();
|
|
217
214
|
return span;
|
|
218
215
|
}
|
|
219
|
-
|
|
220
216
|
//#endregion
|
|
221
217
|
export { DecorationCache, createHighlightPlugin, withLineNumbers };
|
|
218
|
+
|
|
222
219
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/cache.ts","../src/plugin.ts","../src/line-number.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","import { Decoration } from 'prosemirror-view'\n\nimport type { Parser, ParserOptions } from './types'\n\n/**\n * Returns a new parser that adds line numbers to the parsed decorations.\n *\n * Line numbers are added as `<span class=\"line-number\">` elements with\n * the line number as the text content.\n */\nexport function withLineNumbers(parser: Parser): Parser {\n return function parserWithLineNumbers(options: ParserOptions) {\n const parsed = parser(options)\n if (parsed && Array.isArray(parsed)) {\n const { pos, content } = options\n const start = pos + 1\n const lineStarts = [start]\n for (const match of content.matchAll(/(?:\\r?\\n)/g)) {\n lineStarts.push(start + match.index + match[0].length)\n }\n const decorations: Decoration[] = []\n for (const [index, lineStart] of lineStarts.entries()) {\n decorations.push(createLineStartWidget(lineStart, index + 1))\n }\n return [...decorations, ...parsed]\n }\n return parsed\n }\n}\n\nexport function createLineStartWidget(\n from: number,\n lineNumber: number,\n): Decoration {\n return Decoration.widget(from, () => createLineStartSpan(lineNumber), {\n key: 'line-number',\n side: -20,\n })\n}\n\nfunction createLineStartSpan(lineNumber: number) {\n const span = document.createElement('span')\n span.className = 'line-number'\n span.textContent = lineNumber.toString()\n return span\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/cache.ts","../src/plugin.ts","../src/line-number.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 || view.isDestroyed) {\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","import { Decoration } from 'prosemirror-view'\n\nimport type { Parser, ParserOptions } from './types'\n\n/**\n * Returns a new parser that adds line numbers to the parsed decorations.\n *\n * Line numbers are added as `<span class=\"line-number\">` elements with\n * the line number as the text content.\n */\nexport function withLineNumbers(parser: Parser): Parser {\n return function parserWithLineNumbers(options: ParserOptions) {\n const parsed = parser(options)\n if (parsed && Array.isArray(parsed)) {\n const { pos, content } = options\n const start = pos + 1\n const lineStarts = [start]\n for (const match of content.matchAll(/(?:\\r?\\n)/g)) {\n lineStarts.push(start + match.index + match[0].length)\n }\n const decorations: Decoration[] = []\n for (const [index, lineStart] of lineStarts.entries()) {\n decorations.push(createLineStartWidget(lineStart, index + 1))\n }\n return [...decorations, ...parsed]\n }\n return parsed\n }\n}\n\nexport function createLineStartWidget(\n from: number,\n lineNumber: number,\n): Decoration {\n return Decoration.widget(from, () => createLineStartSpan(lineNumber), {\n key: 'line-number',\n side: -20,\n })\n}\n\nfunction createLineStartSpan(lineNumber: number) {\n const span = document.createElement('span')\n span.className = 'line-number'\n span.textContent = lineNumber.toString()\n return span\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,QACE,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,KAAK,KAAK,YAC5B;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,KAAA;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,KAAA,GACiB,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;;;;;;;;;;ACzLT,SAAgB,gBAAgB,QAAwB;AACtD,QAAO,SAAS,sBAAsB,SAAwB;EAC5D,MAAM,SAAS,OAAO,QAAQ;AAC9B,MAAI,UAAU,MAAM,QAAQ,OAAO,EAAE;GACnC,MAAM,EAAE,KAAK,YAAY;GACzB,MAAM,QAAQ,MAAM;GACpB,MAAM,aAAa,CAAC,MAAM;AAC1B,QAAK,MAAM,SAAS,QAAQ,SAAS,aAAa,CAChD,YAAW,KAAK,QAAQ,MAAM,QAAQ,MAAM,GAAG,OAAO;GAExD,MAAM,cAA4B,EAAE;AACpC,QAAK,MAAM,CAAC,OAAO,cAAc,WAAW,SAAS,CACnD,aAAY,KAAK,sBAAsB,WAAW,QAAQ,EAAE,CAAC;AAE/D,UAAO,CAAC,GAAG,aAAa,GAAG,OAAO;;AAEpC,SAAO;;;AAIX,SAAgB,sBACd,MACA,YACY;AACZ,QAAO,WAAW,OAAO,YAAY,oBAAoB,WAAW,EAAE;EACpE,KAAK;EACL,MAAM;EACP,CAAC;;AAGJ,SAAS,oBAAoB,YAAoB;CAC/C,MAAM,OAAO,SAAS,cAAc,OAAO;AAC3C,MAAK,YAAY;AACjB,MAAK,cAAc,WAAW,UAAU;AACxC,QAAO"}
|
package/dist/lezer.d.ts
CHANGED
package/dist/lezer.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Decoration } from "prosemirror-view";
|
|
2
2
|
import { highlightTree } from "@lezer/highlight";
|
|
3
|
-
|
|
4
3
|
//#region src/lezer.ts
|
|
5
4
|
function createParser({ parse, highlighter }) {
|
|
6
5
|
return function lezerParser(options) {
|
|
@@ -14,7 +13,7 @@ function createParser({ parse, highlighter }) {
|
|
|
14
13
|
return decorations;
|
|
15
14
|
};
|
|
16
15
|
}
|
|
17
|
-
|
|
18
16
|
//#endregion
|
|
19
17
|
export { createParser };
|
|
18
|
+
|
|
20
19
|
//# sourceMappingURL=lezer.js.map
|
package/dist/lezer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lezer.js","names":[],"sources":["../src/lezer.ts"],"sourcesContent":["import type { Tree } from '@lezer/common'\nimport type { Highlighter } from '@lezer/highlight'\nimport { highlightTree } from '@lezer/highlight'\nimport { Decoration } from 'prosemirror-view'\n\nimport type { Parser, ParserOptions } from './types'\n\nexport type { Parser, ParserOptions }\n\nexport function createParser({\n parse,\n highlighter,\n}: {\n parse: (options: ParserOptions) => Tree | undefined\n highlighter: Highlighter | readonly Highlighter[]\n}): Parser {\n return function lezerParser(options) {\n const tree = parse(options)\n\n if (!tree) {\n return []\n }\n\n const decorations: Decoration[] = []\n const offset = options.pos + 1\n highlightTree(tree, highlighter, (from, to, classes) => {\n if (classes && from < to) {\n decorations.push(\n Decoration.inline(offset + from, offset + to, { class: classes }),\n )\n }\n })\n\n return decorations\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"lezer.js","names":[],"sources":["../src/lezer.ts"],"sourcesContent":["import type { Tree } from '@lezer/common'\nimport type { Highlighter } from '@lezer/highlight'\nimport { highlightTree } from '@lezer/highlight'\nimport { Decoration } from 'prosemirror-view'\n\nimport type { Parser, ParserOptions } from './types'\n\nexport type { Parser, ParserOptions }\n\nexport function createParser({\n parse,\n highlighter,\n}: {\n parse: (options: ParserOptions) => Tree | undefined\n highlighter: Highlighter | readonly Highlighter[]\n}): Parser {\n return function lezerParser(options) {\n const tree = parse(options)\n\n if (!tree) {\n return []\n }\n\n const decorations: Decoration[] = []\n const offset = options.pos + 1\n highlightTree(tree, highlighter, (from, to, classes) => {\n if (classes && from < to) {\n decorations.push(\n Decoration.inline(offset + from, offset + to, { class: classes }),\n )\n }\n })\n\n return decorations\n }\n}\n"],"mappings":";;;AASA,SAAgB,aAAa,EAC3B,OACA,eAIS;AACT,QAAO,SAAS,YAAY,SAAS;EACnC,MAAM,OAAO,MAAM,QAAQ;AAE3B,MAAI,CAAC,KACH,QAAO,EAAE;EAGX,MAAM,cAA4B,EAAE;EACpC,MAAM,SAAS,QAAQ,MAAM;AAC7B,gBAAc,MAAM,cAAc,MAAM,IAAI,YAAY;AACtD,OAAI,WAAW,OAAO,GACpB,aAAY,KACV,WAAW,OAAO,SAAS,MAAM,SAAS,IAAI,EAAE,OAAO,SAAS,CAAC,CAClE;IAEH;AAEF,SAAO"}
|
package/dist/lowlight.d.ts
CHANGED
package/dist/lowlight.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { t as fillFromRoot } from "./hast-
|
|
2
|
-
|
|
1
|
+
import { t as fillFromRoot } from "./hast-CWvQRbqI.js";
|
|
3
2
|
//#region src/lowlight.ts
|
|
4
3
|
function createParser(lowlight) {
|
|
5
4
|
return function highlighter({ content, language, pos }) {
|
|
@@ -9,7 +8,7 @@ function createParser(lowlight) {
|
|
|
9
8
|
return decorations;
|
|
10
9
|
};
|
|
11
10
|
}
|
|
12
|
-
|
|
13
11
|
//#endregion
|
|
14
12
|
export { createParser };
|
|
13
|
+
|
|
15
14
|
//# sourceMappingURL=lowlight.js.map
|
package/dist/lowlight.js.map
CHANGED
|
@@ -1 +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":"
|
|
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
package/dist/refractor.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { t as fillFromRoot } from "./hast-
|
|
2
|
-
|
|
1
|
+
import { t as fillFromRoot } from "./hast-CWvQRbqI.js";
|
|
3
2
|
//#region src/refractor.ts
|
|
4
3
|
function createParser(refractor) {
|
|
5
4
|
return function highlighter({ content, language, pos }) {
|
|
@@ -9,7 +8,7 @@ function createParser(refractor) {
|
|
|
9
8
|
return decorations;
|
|
10
9
|
};
|
|
11
10
|
}
|
|
12
|
-
|
|
13
11
|
//#endregion
|
|
14
12
|
export { createParser };
|
|
13
|
+
|
|
15
14
|
//# sourceMappingURL=refractor.js.map
|
package/dist/refractor.js.map
CHANGED
|
@@ -1 +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":"
|
|
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
package/dist/shiki.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Decoration } from "prosemirror-view";
|
|
2
|
-
|
|
3
2
|
//#region src/shiki.ts
|
|
4
3
|
function createParser(highlighter, options) {
|
|
5
4
|
return function parser({ content, language, pos, size }) {
|
|
@@ -38,7 +37,7 @@ function stringifyTokenStyle(token) {
|
|
|
38
37
|
if (typeof token === "string") return token;
|
|
39
38
|
return Object.entries(token).map(([key, value]) => `${key}:${value}`).join(";");
|
|
40
39
|
}
|
|
41
|
-
|
|
42
40
|
//#endregion
|
|
43
41
|
export { createParser };
|
|
42
|
+
|
|
44
43
|
//# sourceMappingURL=shiki.js.map
|
package/dist/shiki.js.map
CHANGED
|
@@ -1 +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/v3.22.0/packages/core/src/utils/tokens.ts#L151\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":"
|
|
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/v3.22.0/packages/core/src/utils/tokens.ts#L151\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
package/dist/sugar-high.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Decoration } from "prosemirror-view";
|
|
2
2
|
import { SugarHigh, tokenize } from "sugar-high";
|
|
3
|
-
|
|
4
3
|
//#region src/sugar-high.ts
|
|
5
4
|
const types = SugarHigh.TokenTypes;
|
|
6
5
|
function createParser() {
|
|
@@ -20,7 +19,7 @@ function createParser() {
|
|
|
20
19
|
return decorations;
|
|
21
20
|
};
|
|
22
21
|
}
|
|
23
|
-
|
|
24
22
|
//#endregion
|
|
25
23
|
export { createParser };
|
|
24
|
+
|
|
26
25
|
//# sourceMappingURL=sugar-high.js.map
|
package/dist/sugar-high.js.map
CHANGED
|
@@ -1 +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":"
|
|
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"}
|
|
@@ -33,4 +33,4 @@ type Parser = (options: ParserOptions) => Decoration[] | Promise<void>;
|
|
|
33
33
|
type LanguageExtractor = (node: Node) => string | undefined;
|
|
34
34
|
//#endregion
|
|
35
35
|
export { Parser as n, ParserOptions as r, LanguageExtractor as t };
|
|
36
|
-
//# sourceMappingURL=types-
|
|
36
|
+
//# sourceMappingURL=types-LIvFgazU.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-
|
|
1
|
+
{"version":3,"file":"types-LIvFgazU.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;;UAGiB,aAAA;;AAAjB;;EAIE,OAAA;EAJ4B;;;EAS5B,GAAA;EAUA;;;EALA,QAAA;EAcgB;;;EAThB,IAAA;AAAA;;;;;;;KASU,MAAA,IAAU,OAAA,EAAS,aAAA,KAAkB,UAAA,KAAe,OAAA;;AAKhE;;KAAY,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.15.
|
|
4
|
+
"version": "0.15.2",
|
|
5
5
|
"description": "A ProseMirror plugin to highlight code blocks",
|
|
6
6
|
"author": "ocavue <ocavue@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -108,35 +108,35 @@
|
|
|
108
108
|
}
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
|
-
"@lezer/common": "^1.5.
|
|
112
|
-
"@lezer/css": "^1.3.
|
|
111
|
+
"@lezer/common": "^1.5.2",
|
|
112
|
+
"@lezer/css": "^1.3.3",
|
|
113
113
|
"@lezer/highlight": "^1.2.3",
|
|
114
114
|
"@lezer/javascript": "^1.5.4",
|
|
115
|
-
"@ocavue/eslint-config": "^4.
|
|
116
|
-
"@ocavue/tsconfig": "^0.
|
|
117
|
-
"@shikijs/types": "^4.
|
|
115
|
+
"@ocavue/eslint-config": "^4.5.9",
|
|
116
|
+
"@ocavue/tsconfig": "^0.7.1",
|
|
117
|
+
"@shikijs/types": "^4.1.0",
|
|
118
118
|
"@types/hast": "^3.0.4",
|
|
119
119
|
"@types/node": "^24.0.0",
|
|
120
120
|
"diffable-html-snapshot": "^0.2.0",
|
|
121
|
-
"eslint": "^10.0
|
|
121
|
+
"eslint": "^10.4.0",
|
|
122
122
|
"highlight.js": "^11.11.1",
|
|
123
|
-
"jsdom": "^
|
|
123
|
+
"jsdom": "^29.1.1",
|
|
124
124
|
"lowlight": "^3.3.0",
|
|
125
|
-
"pkg-pr-new": "^0.0.
|
|
126
|
-
"prettier": "^3.8.
|
|
125
|
+
"pkg-pr-new": "^0.0.75",
|
|
126
|
+
"prettier": "^3.8.3",
|
|
127
127
|
"prosemirror-example-setup": "^1.2.3",
|
|
128
|
-
"prosemirror-model": "^1.25.
|
|
128
|
+
"prosemirror-model": "^1.25.7",
|
|
129
129
|
"prosemirror-schema-basic": "^1.2.4",
|
|
130
130
|
"prosemirror-state": "^1.4.4",
|
|
131
|
-
"prosemirror-transform": "^1.
|
|
132
|
-
"prosemirror-view": "^1.41.
|
|
131
|
+
"prosemirror-transform": "^1.12.0",
|
|
132
|
+
"prosemirror-view": "^1.41.8",
|
|
133
133
|
"refractor": "^5.0.0",
|
|
134
|
-
"shiki": "^4.
|
|
135
|
-
"sugar-high": "^
|
|
136
|
-
"tsdown": "^0.
|
|
137
|
-
"typescript": "^
|
|
138
|
-
"vite": "^
|
|
139
|
-
"vitest": "^4.
|
|
134
|
+
"shiki": "^4.1.0",
|
|
135
|
+
"sugar-high": "^1.2.0",
|
|
136
|
+
"tsdown": "^0.21.10",
|
|
137
|
+
"typescript": "^6.0.3",
|
|
138
|
+
"vite": "^8.0.14",
|
|
139
|
+
"vitest": "^4.1.7"
|
|
140
140
|
},
|
|
141
141
|
"scripts": {
|
|
142
142
|
"dev": "vite",
|