@rcarls/rc-textarea-adapters 0.6.0 → 0.7.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/CHANGELOG.md +11 -0
- package/README.md +2 -1
- package/dist/rc-textarea-adapters.js +2 -1
- package/dist/rc-textarea-adapters.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @rcarls/rc-textarea-adapters
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 253ba66: Correct package dependency declarations and prevent bundled Markdown implementation types from
|
|
8
|
+
leaking into the editor declarations.
|
|
9
|
+
|
|
10
|
+
BREAKING CHANGE: `@rcarls/rc-textarea-adapters` now treats `@rcarls/rc-textarea` as a peer instead
|
|
11
|
+
of installing it as a runtime dependency. Both textarea extension packages require a compatible
|
|
12
|
+
pre-1 `@rcarls/rc-textarea` release; install it alongside either extension package when upgrading.
|
|
13
|
+
|
|
3
14
|
## 0.6.0
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -13,7 +13,8 @@ Full API, usage examples, and keyboard/accessibility notes are on the
|
|
|
13
13
|
|
|
14
14
|
## Peer dependencies
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Install `@rcarls/rc-textarea` alongside this package. The tokenizer integrations
|
|
17
|
+
are optional, so install only the additional peer used by your chosen adapter:
|
|
17
18
|
|
|
18
19
|
| Adapter | Peer dependency |
|
|
19
20
|
| ------- | --------------- |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rc-textarea-adapters.js","sources":["../src/lezer.ts","../src/unified.ts","../src/shiki.ts"],"sourcesContent":["import type { RCTextareaPlugin, MarkDecoration, DecorationInput } from '@rcarls/rc-textarea';\n\n/** Minimal structural shape of a lezer `Parser` / language's `.parser`. */\ninterface LezerParser {\n parse(input: string): {\n cursor(): LezerCursor;\n };\n}\n\ninterface LezerCursor {\n type: { name: string };\n from: number;\n to: number;\n next(): boolean;\n}\n\n/**\n * Create an `rc-textarea` plugin that uses a lezer parser (e.g. any `@codemirror/lang-*` package)\n * to produce syntax decorations.\n *\n * Lezer node offsets (`.from` / `.to`) are already absolute character offsets, identical to\n * rc-textarea's coordinate space — no conversion is needed.\n *\n * ```ts\n * import { javascript } from '@codemirror/lang-javascript';\n * import { createLezerPlugin } from '@rcarls/rc-textarea-adapters';\n *\n * editor.usePlugin(createLezerPlugin(javascript().language.parser, {\n * VariableDeclaration: { color: 'var(--color-keyword)' },\n * String: { color: 'var(--color-string)' },\n * LineComment: { italic: true, color: 'var(--color-comment)' },\n * }));\n * ```\n */\nexport function createLezerPlugin(\n parser: LezerParser,\n nodeTypeToStyle: Record<string, Omit<MarkDecoration, 'id' | 'type' | 'from' | 'to'>>,\n): RCTextareaPlugin {\n return {\n update(value, api) {\n const tree = parser.parse(value);\n const cursor = tree.cursor();\n const decorations: DecorationInput[] = [];\n do {\n const style = nodeTypeToStyle[cursor.type.name];\n if (style) {\n decorations.push({ type: 'mark', from: cursor.from, to: cursor.to, ...style });\n }\n } while (cursor.next());\n api.setDecorations(decorations);\n },\n };\n}\n","import type { RCTextareaPlugin, MarkDecoration, DecorationInput } from '@rcarls/rc-textarea';\n\n/** Minimal structural shape of a unist `Node` (shared by mdast, hast, etc.). */\ninterface UnistNode {\n type: string;\n position?: {\n start: { offset?: number };\n end: { offset?: number };\n };\n children?: UnistNode[];\n}\n\n/** Minimal structural shape of a unified `Processor`. */\ninterface UnifiedProcessor {\n parse(value: string): UnistNode;\n}\n\nfunction visit(node: UnistNode, visitor: (n: UnistNode) => void): void {\n visitor(node);\n if (node.children) {\n for (const child of node.children) visit(child, visitor);\n }\n}\n\n/**\n * Create an `rc-textarea` plugin that uses a unified processor (e.g. `remark-parse` for\n * Markdown, `rehype-parse` for HTML) to produce syntax decorations.\n *\n * Node `position.start.offset` / `position.end.offset` values are absolute character offsets,\n * identical to rc-textarea's coordinate space — no conversion is needed.\n *\n * ```ts\n * import { unified } from 'unified';\n * import remarkParse from 'remark-parse';\n * import { createUnifiedPlugin } from '@rcarls/rc-textarea-adapters';\n *\n * const processor = unified().use(remarkParse);\n *\n * editor.usePlugin(createUnifiedPlugin(processor, {\n * strong: { bold: true },\n * emphasis: { italic: true },\n * inlineCode: { className: 'md-inline-code' },\n * heading: { bold: true, color: 'var(--color-heading)' },\n * }));\n * ```\n */\nexport function createUnifiedPlugin(\n processor: UnifiedProcessor,\n nodeTypeToStyle: Record<string, Omit<MarkDecoration, 'id' | 'type' | 'from' | 'to'>>,\n): RCTextareaPlugin {\n return {\n update(value, api) {\n const tree = processor.parse(value);\n const decorations: DecorationInput[] = [];\n visit(tree, (node) => {\n const style = nodeTypeToStyle[node.type];\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n if (style && start !== undefined && end !== undefined) {\n decorations.push({ type: 'mark', from: start, to: end, ...style });\n }\n });\n api.setDecorations(decorations);\n },\n };\n}\n","import type { RCTextareaPlugin, DecorationInput } from '@rcarls/rc-textarea';\n\ninterface ShikiToken {\n content: string;\n color?: string;\n}\n\n/** Minimal structural shape of a shiki `Highlighter`. */\ninterface ShikiHighlighter {\n codeToTokens(\n code: string,\n opts: { lang: string; theme?: string },\n ): Promise<{ tokens: ShikiToken[][] }>;\n}\n\n/**\n * Create an `rc-textarea` plugin that uses a [shiki](https://shiki.style/) `Highlighter`\n * to produce syntax decorations.\n *\n * Shiki tokens carry line-relative offsets; this adapter converts them to the absolute\n * character offsets that rc-textarea expects by tracking position across lines.\n *\n * ```ts\n * import { createHighlighter } from 'shiki';\n * import { createShikiPlugin } from '@rcarls/rc-textarea-adapters';\n *\n * const highlighter = await createHighlighter({\n * themes: ['github-dark'],\n * langs: ['typescript'],\n * });\n *\n * editor.usePlugin(createShikiPlugin(highlighter, 'typescript', 'github-dark'));\n * ```\n */\nexport function createShikiPlugin(\n highlighter: ShikiHighlighter,\n lang: string,\n theme?: string,\n): RCTextareaPlugin {\n return {\n async update(value, api) {\n const result = await highlighter.codeToTokens(value, {\n lang,\n ...(theme ? { theme } : {}),\n });\n\n const decorations: DecorationInput[] = [];\n let offset = 0;\n\n for (const line of result.tokens) {\n for (const token of line) {\n const len = token.content.length;\n if (token.color) {\n decorations.push({\n type: 'mark',\n from: offset,\n to: offset + len,\n color: token.color,\n });\n }\n offset += len;\n }\n offset += 1; // '\\n'\n }\n\n api.setDecorations(decorations);\n },\n };\n}\n"],"names":["createLezerPlugin","parser","nodeTypeToStyle","value","api","cursor","decorations","style","visit","node","visitor","child","createUnifiedPlugin","processor","tree","start","end","createShikiPlugin","highlighter","lang","theme","result","offset","line","token","len"],"mappings":"AAkCO,SAASA,EACdC,GACAC,GACkB;AAClB,SAAO;AAAA,IACL,OAAOC,GAAOC,GAAK;AAEjB,YAAMC,IADOJ,EAAO,MAAME,CAAK,EACX,OAAA,GACdG,IAAiC,CAAA;
|
|
1
|
+
{"version":3,"file":"rc-textarea-adapters.js","sources":["../src/lezer.ts","../src/unified.ts","../src/shiki.ts"],"sourcesContent":["import type { RCTextareaPlugin, MarkDecoration, DecorationInput } from '@rcarls/rc-textarea';\n\n/** Minimal structural shape of a lezer `Parser` / language's `.parser`. */\ninterface LezerParser {\n parse(input: string): {\n cursor(): LezerCursor;\n };\n}\n\ninterface LezerCursor {\n type: { name: string };\n from: number;\n to: number;\n next(): boolean;\n}\n\n/**\n * Create an `rc-textarea` plugin that uses a lezer parser (e.g. any `@codemirror/lang-*` package)\n * to produce syntax decorations.\n *\n * Lezer node offsets (`.from` / `.to`) are already absolute character offsets, identical to\n * rc-textarea's coordinate space — no conversion is needed.\n *\n * ```ts\n * import { javascript } from '@codemirror/lang-javascript';\n * import { createLezerPlugin } from '@rcarls/rc-textarea-adapters';\n *\n * editor.usePlugin(createLezerPlugin(javascript().language.parser, {\n * VariableDeclaration: { color: 'var(--color-keyword)' },\n * String: { color: 'var(--color-string)' },\n * LineComment: { italic: true, color: 'var(--color-comment)' },\n * }));\n * ```\n */\nexport function createLezerPlugin(\n parser: LezerParser,\n nodeTypeToStyle: Record<string, Omit<MarkDecoration, 'id' | 'type' | 'from' | 'to'>>,\n): RCTextareaPlugin {\n return {\n update(value, api) {\n const tree = parser.parse(value);\n const cursor = tree.cursor();\n const decorations: DecorationInput[] = [];\n\n do {\n const style = nodeTypeToStyle[cursor.type.name];\n\n if (style) {\n decorations.push({ type: 'mark', from: cursor.from, to: cursor.to, ...style });\n }\n } while (cursor.next());\n\n api.setDecorations(decorations);\n },\n };\n}\n","import type { RCTextareaPlugin, MarkDecoration, DecorationInput } from '@rcarls/rc-textarea';\n\n/** Minimal structural shape of a unist `Node` (shared by mdast, hast, etc.). */\ninterface UnistNode {\n type: string;\n position?: {\n start: { offset?: number };\n end: { offset?: number };\n };\n children?: UnistNode[];\n}\n\n/** Minimal structural shape of a unified `Processor`. */\ninterface UnifiedProcessor {\n parse(value: string): UnistNode;\n}\n\nfunction visit(node: UnistNode, visitor: (n: UnistNode) => void): void {\n visitor(node);\n\n if (node.children) {\n for (const child of node.children) {\n visit(child, visitor);\n }\n }\n}\n\n/**\n * Create an `rc-textarea` plugin that uses a unified processor (e.g. `remark-parse` for\n * Markdown, `rehype-parse` for HTML) to produce syntax decorations.\n *\n * Node `position.start.offset` / `position.end.offset` values are absolute character offsets,\n * identical to rc-textarea's coordinate space — no conversion is needed.\n *\n * ```ts\n * import { unified } from 'unified';\n * import remarkParse from 'remark-parse';\n * import { createUnifiedPlugin } from '@rcarls/rc-textarea-adapters';\n *\n * const processor = unified().use(remarkParse);\n *\n * editor.usePlugin(createUnifiedPlugin(processor, {\n * strong: { bold: true },\n * emphasis: { italic: true },\n * inlineCode: { className: 'md-inline-code' },\n * heading: { bold: true, color: 'var(--color-heading)' },\n * }));\n * ```\n */\nexport function createUnifiedPlugin(\n processor: UnifiedProcessor,\n nodeTypeToStyle: Record<string, Omit<MarkDecoration, 'id' | 'type' | 'from' | 'to'>>,\n): RCTextareaPlugin {\n return {\n update(value, api) {\n const tree = processor.parse(value);\n const decorations: DecorationInput[] = [];\n\n visit(tree, (node) => {\n const style = nodeTypeToStyle[node.type];\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n\n if (style && start !== undefined && end !== undefined) {\n decorations.push({ type: 'mark', from: start, to: end, ...style });\n }\n });\n\n api.setDecorations(decorations);\n },\n };\n}\n","import type { RCTextareaPlugin, DecorationInput } from '@rcarls/rc-textarea';\n\ninterface ShikiToken {\n content: string;\n color?: string;\n}\n\n/** Minimal structural shape of a shiki `Highlighter`. */\ninterface ShikiHighlighter {\n codeToTokens(\n code: string,\n opts: { lang: string; theme?: string },\n ): Promise<{ tokens: ShikiToken[][] }>;\n}\n\n/**\n * Create an `rc-textarea` plugin that uses a [shiki](https://shiki.style/) `Highlighter`\n * to produce syntax decorations.\n *\n * Shiki tokens carry line-relative offsets; this adapter converts them to the absolute\n * character offsets that rc-textarea expects by tracking position across lines.\n *\n * ```ts\n * import { createHighlighter } from 'shiki';\n * import { createShikiPlugin } from '@rcarls/rc-textarea-adapters';\n *\n * const highlighter = await createHighlighter({\n * themes: ['github-dark'],\n * langs: ['typescript'],\n * });\n *\n * editor.usePlugin(createShikiPlugin(highlighter, 'typescript', 'github-dark'));\n * ```\n */\nexport function createShikiPlugin(\n highlighter: ShikiHighlighter,\n lang: string,\n theme?: string,\n): RCTextareaPlugin {\n return {\n async update(value, api) {\n const result = await highlighter.codeToTokens(value, {\n lang,\n ...(theme ? { theme } : {}),\n });\n\n const decorations: DecorationInput[] = [];\n let offset = 0;\n\n for (const line of result.tokens) {\n for (const token of line) {\n const len = token.content.length;\n\n if (token.color) {\n decorations.push({\n type: 'mark',\n from: offset,\n to: offset + len,\n color: token.color,\n });\n }\n\n offset += len;\n }\n\n offset += 1; // '\\n'\n }\n\n api.setDecorations(decorations);\n },\n };\n}\n"],"names":["createLezerPlugin","parser","nodeTypeToStyle","value","api","cursor","decorations","style","visit","node","visitor","child","createUnifiedPlugin","processor","tree","start","end","createShikiPlugin","highlighter","lang","theme","result","offset","line","token","len"],"mappings":"AAkCO,SAASA,EACdC,GACAC,GACkB;AAClB,SAAO;AAAA,IACL,OAAOC,GAAOC,GAAK;AAEjB,YAAMC,IADOJ,EAAO,MAAME,CAAK,EACX,OAAA,GACdG,IAAiC,CAAA;AAEvC,SAAG;AACD,cAAMC,IAAQL,EAAgBG,EAAO,KAAK,IAAI;AAE9C,QAAIE,KACFD,EAAY,KAAK,EAAE,MAAM,QAAQ,MAAMD,EAAO,MAAM,IAAIA,EAAO,IAAI,GAAGE,EAAA,CAAO;AAAA,MAEjF,SAASF,EAAO,KAAA;AAEhB,MAAAD,EAAI,eAAeE,CAAW;AAAA,IAChC;AAAA,EAAA;AAEJ;ACtCA,SAASE,EAAMC,GAAiBC,GAAuC;AAGrE,MAFAA,EAAQD,CAAI,GAERA,EAAK;AACP,eAAWE,KAASF,EAAK;AACvB,MAAAD,EAAMG,GAAOD,CAAO;AAG1B;AAwBO,SAASE,EACdC,GACAX,GACkB;AAClB,SAAO;AAAA,IACL,OAAOC,GAAOC,GAAK;AACjB,YAAMU,IAAOD,EAAU,MAAMV,CAAK,GAC5BG,IAAiC,CAAA;AAEvC,MAAAE,EAAMM,GAAM,CAACL,MAAS;AACpB,cAAMF,IAAQL,EAAgBO,EAAK,IAAI,GACjCM,IAAQN,EAAK,UAAU,MAAM,QAC7BO,IAAMP,EAAK,UAAU,IAAI;AAE/B,QAAIF,KAASQ,MAAU,UAAaC,MAAQ,UAC1CV,EAAY,KAAK,EAAE,MAAM,QAAQ,MAAMS,GAAO,IAAIC,GAAK,GAAGT,GAAO;AAAA,MAErE,CAAC,GAEDH,EAAI,eAAeE,CAAW;AAAA,IAChC;AAAA,EAAA;AAEJ;ACrCO,SAASW,EACdC,GACAC,GACAC,GACkB;AAClB,SAAO;AAAA,IACL,MAAM,OAAOjB,GAAOC,GAAK;AACvB,YAAMiB,IAAS,MAAMH,EAAY,aAAaf,GAAO;AAAA,QACnD,MAAAgB;AAAA,QACA,GAAIC,IAAQ,EAAE,OAAAA,MAAU,CAAA;AAAA,MAAC,CAC1B,GAEKd,IAAiC,CAAA;AACvC,UAAIgB,IAAS;AAEb,iBAAWC,KAAQF,EAAO,QAAQ;AAChC,mBAAWG,KAASD,GAAM;AACxB,gBAAME,IAAMD,EAAM,QAAQ;AAE1B,UAAIA,EAAM,SACRlB,EAAY,KAAK;AAAA,YACf,MAAM;AAAA,YACN,MAAMgB;AAAA,YACN,IAAIA,IAASG;AAAA,YACb,OAAOD,EAAM;AAAA,UAAA,CACd,GAGHF,KAAUG;AAAA,QACZ;AAEA,QAAAH,KAAU;AAAA,MACZ;AAEA,MAAAlB,EAAI,eAAeE,CAAW;AAAA,IAChC;AAAA,EAAA;AAEJ;"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.7.0",
|
|
7
7
|
"description": "Adapter factories that connect Lezer, unified, and Shiki tokenizers to rc-textarea.",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -30,11 +30,9 @@
|
|
|
30
30
|
"scripts": {
|
|
31
31
|
"build": "tsc && vite build"
|
|
32
32
|
},
|
|
33
|
-
"dependencies": {
|
|
34
|
-
"@rcarls/rc-textarea": "0.6.0"
|
|
35
|
-
},
|
|
36
33
|
"peerDependencies": {
|
|
37
34
|
"@lezer/common": ">=1.0.0",
|
|
35
|
+
"@rcarls/rc-textarea": ">=0.2.0 <1.0.0",
|
|
38
36
|
"shiki": ">=1.0.0",
|
|
39
37
|
"unified": ">=11.0.0"
|
|
40
38
|
},
|
|
@@ -50,6 +48,8 @@
|
|
|
50
48
|
}
|
|
51
49
|
},
|
|
52
50
|
"devDependencies": {
|
|
51
|
+
"@rcarls/rc-textarea": "0.7.0",
|
|
52
|
+
"lit": "^3.0.0",
|
|
53
53
|
"typescript": "~5.9.3",
|
|
54
54
|
"vite": "^7.1.7",
|
|
55
55
|
"vite-plugin-dts": "^4.5.4"
|