@rcarls/rc-textarea-plugin-markdown 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 CHANGED
@@ -1,5 +1,68 @@
1
1
  # @rcarls/rc-textarea-plugin-markdown
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 54d9ead: Localize every component's built-in text. Button names, role
8
+ descriptions, announcements, and default labels now resolve per key from
9
+ the element's `messages` property, then from text registered with
10
+ `registerMessages(locale, catalog)` in `@rcarls/rc-common`, then from the
11
+ English defaults. The locale is the element's own `lang`, else
12
+ `<html lang>`; an ancestor's `lang` is ignored, because it usually marks
13
+ content rather than the interface. Components re-render when that locale
14
+ changes or new text is registered. `RcMessageCatalog` types the catalog,
15
+ and each package adds its scope to it.
16
+
17
+ Numbers a component formats as text follow the same locale:
18
+ `rc-progress`'s default percentage and `rc-splitter`'s `aria-valuetext`
19
+ use `Intl.NumberFormat`. `TypeaheadController` matches prefixes with an
20
+ `Intl.Collator`, so case and accents are ignored the way the locale
21
+ ignores them, and takes a `locale` option. `ItemsCollectionController`'s
22
+ `setCreateOption(text, label?)` takes the option's visible text from its
23
+ caller.
24
+
25
+ `rc-transfer-list`'s direction arrows are now decorative: screen readers
26
+ read only the action name, and the arrows turn over in RTL.
27
+
28
+ **Breaking:** chrome-text properties are replaced by `messages`. Migrate:
29
+
30
+ - `rc-search-bar` `clear-label` / `clearLabel` → `messages.clear`
31
+ - `rc-adaptive-menu` `overflow-label` / `overflowLabel` → `messages.overflow`
32
+ - `rc-chip-group` `show-all-label` / `showAllLabel` and `show-less-label` /
33
+ `showLessLabel` → `messages.showAll` and `messages.showLess`
34
+ - `rc-select` and `rc-combobox` `dialog-confirm-label` /
35
+ `dialogConfirmLabel` and `dialog-cancel-label` / `dialogCancelLabel` →
36
+ `messages.done` and `messages.cancel`
37
+ - `rc-editor-toolbar` `label` → `messages.toolbar`
38
+
39
+ Per-instance names stay attributes, but now default to `undefined` and fall
40
+ back to a message: `label` on `rc-adaptive-menu`, `rc-chip-group`,
41
+ `rc-menubar`, and `rc-splitter`; `available-label` and `selected-label`
42
+ on `rc-transfer-list`; `low-label` and `high-label` on `rc-range-slider`.
43
+ Read the resolved name from the rendered `aria-label` instead of the
44
+ property.
45
+
46
+ - 253ba66: Correct package dependency declarations and prevent bundled Markdown implementation types from
47
+ leaking into the editor declarations.
48
+
49
+ BREAKING CHANGE: `@rcarls/rc-textarea-adapters` now treats `@rcarls/rc-textarea` as a peer instead
50
+ of installing it as a runtime dependency. Both textarea extension packages require a compatible
51
+ pre-1 `@rcarls/rc-textarea` release; install it alongside either extension package when upgrading.
52
+
53
+ - 6b99ced: **Breaking:** replace `LineDisclosureController` with `FoldingActionController`.
54
+ Pass a caller-owned panel as `target` and render it through a block widget, or pass
55
+ `{ fromLine, toLine }` to fold source lines. Panel creation and content revision now
56
+ belong to the plugin. Set `initiallyExpanded: false` to retain the old diagnostic
57
+ panel default; call `clear()` when document identity changes.
58
+
59
+ Folding actions keep source text, form values, and undo history intact. The Markdown
60
+ plugin adds gutter folds for heading sections, lists, code blocks, block quotes,
61
+ and GFM tables. The base gutter has a 24px minimum width; Material uses 48px.
62
+ Folding buttons expose `fold-trigger` and `fold-icon` CSS parts, and
63
+ `createMarkdownPlugin({ folding: { createTriggerIcon } })` lets consumers choose
64
+ the Markdown fold icon.
65
+
3
66
  ## 0.6.0
4
67
 
5
68
  ## 0.5.0
package/README.md CHANGED
@@ -1,11 +1,21 @@
1
1
  # @rcarls/rc-textarea-plugin-markdown
2
2
 
3
- Markdown decoration plugin for `rc-textarea`.
3
+ Markdown decoration and folding plugin for `rc-textarea`. Its gutter actions fold heading
4
+ sections, multiline lists, code blocks, block quotes, and GFM tables while preserving source text.
5
+
6
+ Use `createMarkdownPlugin({ folding: { createTriggerIcon } })` to choose its
7
+ folding icon. Style the button and icon through `rc-textarea::part(fold-trigger)`
8
+ and `rc-textarea::part(fold-icon)`.
4
9
 
5
10
  Docs: [https://richardcarls.github.io/rc-webcomponents/components/rc-textarea](https://richardcarls.github.io/rc-webcomponents/components/rc-textarea).
6
11
 
7
12
  Part of the [rc-webcomponents](https://github.com/richardcarls/rc-webcomponents) library.
8
13
 
14
+ ## Localization
15
+
16
+ The plugin has no element of its own, so it reads no `lang` and no registered messages. Pass
17
+ fold toggle text in `createMarkdownPlugin({ messages: { block, fold } })`.
18
+
9
19
  ## Documentation
10
20
 
11
21
  Full API, usage examples, and keyboard/accessibility notes are on the
@@ -1,7 +1,14 @@
1
- import { fromMarkdown as l } from "mdast-util-from-markdown";
2
- import { visit as m } from "unist-util-visit";
3
- import { micromark as d } from "micromark";
4
- const u = {
1
+ import { fromMarkdown as E } from "mdast-util-from-markdown";
2
+ import { gfmTableFromMarkdown as M } from "mdast-util-gfm-table";
3
+ import { visit as v } from "unist-util-visit";
4
+ import { micromark as P } from "micromark";
5
+ import { gfmTable as x, gfmTableHtml as _ } from "micromark-extension-gfm-table";
6
+ import "@rcarls/rc-textarea";
7
+ import { FoldingActionController as D } from "@rcarls/rc-textarea/folding";
8
+ const L = Object.freeze({
9
+ block: (e, i) => e === "heading" ? `Heading level ${i}` : e,
10
+ fold: (e, i, c) => `${e} at line ${i}: ${c}`
11
+ }), $ = x(), S = M(), C = {
5
12
  heading: { bold: !0, className: "rte-heading" },
6
13
  emphasis: { italic: !0 },
7
14
  strong: { bold: !0 },
@@ -9,28 +16,69 @@ const u = {
9
16
  link: { underline: "solid", className: "rte-link" },
10
17
  blockquote: { className: "rte-blockquote" }
11
18
  };
12
- function f(t) {
13
- return d(t);
19
+ function F(e) {
20
+ return P(e, {
21
+ extensions: [$],
22
+ htmlExtensions: [_()]
23
+ });
14
24
  }
15
- function s() {
25
+ function w(e = {}) {
26
+ const i = { ...L, ...e.messages };
27
+ let c = null, s = null, d = !1;
16
28
  return {
17
- getPreviewHtml: f,
18
- update(t, a) {
19
- const c = l(t), e = [];
20
- m(c, (o) => {
21
- const r = u[o.type], i = o.position?.start.offset, n = o.position?.end.offset;
22
- r !== void 0 && i !== void 0 && n !== void 0 && e.push({ type: "mark", from: i, to: n, ...r });
23
- }), a.setDecorations(e);
29
+ getPreviewHtml: F,
30
+ mount(a) {
31
+ s = a.host, d = !s.gutter && !s.lineNumbers, d && (s.gutter = !0), c = new D(a, e.folding);
32
+ },
33
+ destroy() {
34
+ c?.clear(), c = null, s && d && (s.gutter = !1), s = null, d = !1;
35
+ },
36
+ update(a, N) {
37
+ const f = E(a, {
38
+ extensions: [$],
39
+ mdastExtensions: [S]
40
+ }), u = [], p = [], g = a.split(`
41
+ `), h = /* @__PURE__ */ new Map(), b = (t, o, l, n) => {
42
+ const r = t.position?.start.line;
43
+ if (r === void 0 || l > n)
44
+ return;
45
+ const y = g[r - 1]?.trim() ?? "", T = "depth" in t ? `${t.depth}` : "", m = `${t.type}${T}:${y}`, A = h.get(m) ?? 0;
46
+ h.set(m, A + 1), p.push({
47
+ key: `${m}:${A}`,
48
+ gutterLine: r,
49
+ label: i.fold(o, r, y),
50
+ target: { fromLine: l, toLine: n }
51
+ });
52
+ }, k = f.children.filter((t) => t.type === "heading");
53
+ for (const [t, o] of k.entries()) {
54
+ const l = (o.position?.end.line ?? 0) + 1;
55
+ let n = g.length;
56
+ for (const r of k.slice(t + 1))
57
+ if (r.depth <= o.depth) {
58
+ n = (r.position?.start.line ?? n + 1) - 1;
59
+ break;
60
+ }
61
+ b(o, i.block("heading", o.depth), l, n);
62
+ }
63
+ v(f, (t) => {
64
+ const o = C[t.type], l = t.position?.start.offset, n = t.position?.end.offset;
65
+ o !== void 0 && l !== void 0 && n !== void 0 && u.push({ type: "mark", from: l, to: n, ...o }), t.position && ["list", "code", "blockquote", "table"].includes(t.type) && b(
66
+ t,
67
+ i.block(t.type),
68
+ t.position.start.line + 1,
69
+ t.position.end.line
70
+ );
71
+ }), N.setDecorations([...u, ...c?.getDecorations(p) ?? []]);
24
72
  }
25
73
  };
26
74
  }
27
- const v = s();
28
- function w() {
29
- return s();
75
+ const R = w();
76
+ function U(e = {}) {
77
+ return w(e);
30
78
  }
31
79
  export {
32
- w as createMarkdownPlugin,
33
- f as getMarkdownPreviewHtml,
34
- v as markdownPlugin
80
+ U as createMarkdownPlugin,
81
+ F as getMarkdownPreviewHtml,
82
+ R as markdownPlugin
35
83
  };
36
84
  //# sourceMappingURL=rc-textarea-plugin-markdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rc-textarea-plugin-markdown.js","sources":["../src/markdown-plugin.ts"],"sourcesContent":["import { fromMarkdown } from 'mdast-util-from-markdown';\nimport { visit } from 'unist-util-visit';\nimport { micromark } from 'micromark';\n\nimport type { RCTextareaPlugin, RCTextareaPluginAPI, DecorationInput } from '@rcarls/rc-textarea';\n\n/** Minimal shape of a unist node as used by visit(). */\ninterface VisitNode {\n type: string;\n position?: {\n start: { offset?: number };\n end: { offset?: number };\n };\n}\n\n/** Decoration styles applied per MDAST node type. */\nconst DECORATION_MAP: Record<string, Partial<Omit<DecorationInput, 'type' | 'from' | 'to'>>> = {\n heading: { bold: true, className: 'rte-heading' },\n emphasis: { italic: true },\n strong: { bold: true },\n inlineCode: { className: 'rte-code' },\n link: { underline: 'solid', className: 'rte-link' },\n blockquote: { className: 'rte-blockquote' },\n};\n\n/** Render a markdown string to safe HTML using micromark (no raw HTML passthrough). */\nexport function getMarkdownPreviewHtml(value: string): string {\n return micromark(value);\n}\n\nfunction buildPlugin(): RCTextareaPlugin & { getPreviewHtml(value: string): string } {\n return {\n getPreviewHtml: getMarkdownPreviewHtml,\n\n update(value: string, api: RCTextareaPluginAPI): void {\n const tree = fromMarkdown(value);\n const decorations: DecorationInput[] = [];\n\n visit(tree, (node: VisitNode) => {\n const style = DECORATION_MAP[node.type];\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n\n if (style !== undefined && start !== undefined && end !== undefined) {\n decorations.push({ type: 'mark', from: start, to: end, ...style } as DecorationInput);\n }\n });\n\n api.setDecorations(decorations);\n },\n };\n}\n\n/** Singleton markdown plugin. Use when a single instance is sufficient. */\nexport const markdownPlugin = buildPlugin();\n\n/** Factory for cases where multiple independent instances are needed. */\nexport function createMarkdownPlugin(): RCTextareaPlugin & {\n getPreviewHtml(value: string): string;\n} {\n return buildPlugin();\n}\n"],"names":["DECORATION_MAP","getMarkdownPreviewHtml","value","micromark","buildPlugin","api","tree","fromMarkdown","decorations","visit","node","style","start","end","markdownPlugin","createMarkdownPlugin"],"mappings":";;;AAgBA,MAAMA,IAAyF;AAAA,EAC7F,SAAS,EAAE,MAAM,IAAM,WAAW,cAAA;AAAA,EAClC,UAAU,EAAE,QAAQ,GAAA;AAAA,EACpB,QAAQ,EAAE,MAAM,GAAA;AAAA,EAChB,YAAY,EAAE,WAAW,WAAA;AAAA,EACzB,MAAM,EAAE,WAAW,SAAS,WAAW,WAAA;AAAA,EACvC,YAAY,EAAE,WAAW,iBAAA;AAC3B;AAGO,SAASC,EAAuBC,GAAuB;AAC5D,SAAOC,EAAUD,CAAK;AACxB;AAEA,SAASE,IAA4E;AACnF,SAAO;AAAA,IACL,gBAAgBH;AAAA,IAEhB,OAAOC,GAAeG,GAAgC;AACpD,YAAMC,IAAOC,EAAaL,CAAK,GACzBM,IAAiC,CAAA;AAEvC,MAAAC,EAAMH,GAAM,CAACI,MAAoB;AAC/B,cAAMC,IAAQX,EAAeU,EAAK,IAAI,GAChCE,IAAQF,EAAK,UAAU,MAAM,QAC7BG,IAAMH,EAAK,UAAU,IAAI;AAE/B,QAAIC,MAAU,UAAaC,MAAU,UAAaC,MAAQ,UACxDL,EAAY,KAAK,EAAE,MAAM,QAAQ,MAAMI,GAAO,IAAIC,GAAK,GAAGF,GAA0B;AAAA,MAExF,CAAC,GAEDN,EAAI,eAAeG,CAAW;AAAA,IAChC;AAAA,EAAA;AAEJ;AAGO,MAAMM,IAAiBV,EAAA;AAGvB,SAASW,IAEd;AACA,SAAOX,EAAA;AACT;"}
1
+ {"version":3,"file":"rc-textarea-plugin-markdown.js","sources":["../src/markdown-plugin.ts"],"sourcesContent":["import { fromMarkdown } from 'mdast-util-from-markdown';\nimport { gfmTableFromMarkdown } from 'mdast-util-gfm-table';\nimport { visit } from 'unist-util-visit';\nimport { micromark } from 'micromark';\nimport { gfmTable, gfmTableHtml } from 'micromark-extension-gfm-table';\n\nimport {\n type RCTextarea,\n type RCTextareaPlugin,\n type RCTextareaPluginAPI,\n type DecorationInput,\n} from '@rcarls/rc-textarea';\nimport {\n FoldingActionController,\n type FoldingAction,\n type FoldingActionControllerOptions,\n} from '@rcarls/rc-textarea/folding';\n\n/** Text of the Markdown plugin's fold toggles. */\nexport interface MarkdownPluginMessages {\n /** Name of a foldable block from its MDAST type, such as `Heading level 2` or `code`. */\n block: (type: string, depth?: number) => string;\n /** Accessible name of a fold toggle. */\n fold: (block: string, line: number, title: string) => string;\n}\n\nexport const DEFAULT_MARKDOWN_PLUGIN_MESSAGES: Readonly<MarkdownPluginMessages> = Object.freeze({\n block: (type: string, depth?: number) => (type === 'heading' ? `Heading level ${depth}` : type),\n fold: (block: string, line: number, title: string) => `${block} at line ${line}: ${title}`,\n});\n\n/** Options for the Markdown plugin. */\nexport interface MarkdownPluginOptions {\n /** Visual options for the folding actions. */\n folding?: FoldingActionControllerOptions;\n /**\n * Fold toggle text overrides, for a non-English interface. The plugin has no\n * element of its own, so it reads no `lang` and no registered messages.\n */\n messages?: Partial<MarkdownPluginMessages>;\n}\n\n/** Minimal shape of a unist node as used by visit(). */\ninterface VisitNode {\n type: string;\n position?: {\n start: { offset?: number; line: number };\n end: { offset?: number; line: number };\n };\n}\n\nconst TABLE_SYNTAX = gfmTable();\nconst TABLE_AST = gfmTableFromMarkdown();\n\n/** Decoration styles applied per MDAST node type. */\nconst DECORATION_MAP: Record<string, Partial<Omit<DecorationInput, 'type' | 'from' | 'to'>>> = {\n heading: { bold: true, className: 'rte-heading' },\n emphasis: { italic: true },\n strong: { bold: true },\n inlineCode: { className: 'rte-code' },\n link: { underline: 'solid', className: 'rte-link' },\n blockquote: { className: 'rte-blockquote' },\n};\n\n/** Render a markdown string to safe HTML using micromark (no raw HTML passthrough). */\nexport function getMarkdownPreviewHtml(value: string): string {\n return micromark(value, {\n extensions: [TABLE_SYNTAX],\n htmlExtensions: [gfmTableHtml()],\n });\n}\n\nfunction buildPlugin(options: MarkdownPluginOptions = {}): RCTextareaPlugin & {\n getPreviewHtml(value: string): string;\n} {\n const messages = { ...DEFAULT_MARKDOWN_PLUGIN_MESSAGES, ...options.messages };\n let folding: FoldingActionController | null = null;\n let host: RCTextarea | null = null;\n let enabledGutter = false;\n\n return {\n getPreviewHtml: getMarkdownPreviewHtml,\n\n mount(api: RCTextareaPluginAPI): void {\n host = api.host as RCTextarea;\n enabledGutter = !host.gutter && !host.lineNumbers;\n\n if (enabledGutter) {\n host.gutter = true;\n }\n\n folding = new FoldingActionController(api, options.folding);\n },\n\n destroy(): void {\n folding?.clear();\n folding = null;\n\n if (host && enabledGutter) {\n host.gutter = false;\n }\n\n host = null;\n enabledGutter = false;\n },\n\n update(value: string, api: RCTextareaPluginAPI): void {\n const tree = fromMarkdown(value, {\n extensions: [TABLE_SYNTAX],\n mdastExtensions: [TABLE_AST],\n });\n const decorations: DecorationInput[] = [];\n const actions: FoldingAction[] = [];\n const lines = value.split('\\n');\n const keyCounts = new Map<string, number>();\n\n const addFold = (node: VisitNode, block: string, fromLine: number, toLine: number): void => {\n const line = node.position?.start.line;\n\n if (line === undefined || fromLine > toLine) {\n return;\n }\n\n const title = lines[line - 1]?.trim() ?? '';\n // Keys stay in English-free MDAST terms so a fold survives a locale change.\n const depth = 'depth' in node ? `${node.depth as number}` : '';\n const baseKey = `${node.type}${depth}:${title}`;\n const occurrence = keyCounts.get(baseKey) ?? 0;\n\n keyCounts.set(baseKey, occurrence + 1);\n\n actions.push({\n key: `${baseKey}:${occurrence}`,\n gutterLine: line,\n label: messages.fold(block, line, title),\n target: { fromLine, toLine },\n });\n };\n\n const headings = tree.children.filter((node) => node.type === 'heading');\n\n for (const [index, heading] of headings.entries()) {\n const fromLine = (heading.position?.end.line ?? 0) + 1;\n let toLine = lines.length;\n\n for (const later of headings.slice(index + 1)) {\n if (later.depth <= heading.depth) {\n toLine = (later.position?.start.line ?? toLine + 1) - 1;\n\n break;\n }\n }\n\n addFold(heading, messages.block('heading', heading.depth), fromLine, toLine);\n }\n\n visit(tree, (node: VisitNode) => {\n const style = DECORATION_MAP[node.type];\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n\n if (style !== undefined && start !== undefined && end !== undefined) {\n decorations.push({ type: 'mark', from: start, to: end, ...style } as DecorationInput);\n }\n\n if (node.position && ['list', 'code', 'blockquote', 'table'].includes(node.type)) {\n addFold(\n node,\n messages.block(node.type),\n node.position.start.line + 1,\n node.position.end.line,\n );\n }\n });\n\n api.setDecorations([...decorations, ...(folding?.getDecorations(actions) ?? [])]);\n },\n };\n}\n\n/** Singleton markdown plugin. Use when a single instance is sufficient. */\nexport const markdownPlugin = buildPlugin();\n\n/** Factory for cases where multiple independent instances are needed. */\nexport function createMarkdownPlugin(options: MarkdownPluginOptions = {}): RCTextareaPlugin & {\n getPreviewHtml(value: string): string;\n} {\n return buildPlugin(options);\n}\n"],"names":["DEFAULT_MARKDOWN_PLUGIN_MESSAGES","type","depth","block","line","title","TABLE_SYNTAX","gfmTable","TABLE_AST","gfmTableFromMarkdown","DECORATION_MAP","getMarkdownPreviewHtml","value","micromark","gfmTableHtml","buildPlugin","options","messages","folding","host","enabledGutter","api","FoldingActionController","tree","fromMarkdown","decorations","actions","lines","keyCounts","addFold","node","fromLine","toLine","baseKey","occurrence","headings","index","heading","later","visit","style","start","end","markdownPlugin","createMarkdownPlugin"],"mappings":"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"}
@@ -1 +1,2 @@
1
1
  export { markdownPlugin, createMarkdownPlugin, getMarkdownPreviewHtml } from './markdown-plugin.js';
2
+ export type { MarkdownPluginOptions } from './markdown-plugin.js';
@@ -1,4 +1,23 @@
1
1
  import { RCTextareaPlugin } from '@rcarls/rc-textarea';
2
+ import { FoldingActionControllerOptions } from '@rcarls/rc-textarea/folding';
3
+ /** Text of the Markdown plugin's fold toggles. */
4
+ export interface MarkdownPluginMessages {
5
+ /** Name of a foldable block from its MDAST type, such as `Heading level 2` or `code`. */
6
+ block: (type: string, depth?: number) => string;
7
+ /** Accessible name of a fold toggle. */
8
+ fold: (block: string, line: number, title: string) => string;
9
+ }
10
+ export declare const DEFAULT_MARKDOWN_PLUGIN_MESSAGES: Readonly<MarkdownPluginMessages>;
11
+ /** Options for the Markdown plugin. */
12
+ export interface MarkdownPluginOptions {
13
+ /** Visual options for the folding actions. */
14
+ folding?: FoldingActionControllerOptions;
15
+ /**
16
+ * Fold toggle text overrides, for a non-English interface. The plugin has no
17
+ * element of its own, so it reads no `lang` and no registered messages.
18
+ */
19
+ messages?: Partial<MarkdownPluginMessages>;
20
+ }
2
21
  /** Render a markdown string to safe HTML using micromark (no raw HTML passthrough). */
3
22
  export declare function getMarkdownPreviewHtml(value: string): string;
4
23
  /** Singleton markdown plugin. Use when a single instance is sufficient. */
@@ -6,6 +25,6 @@ export declare const markdownPlugin: RCTextareaPlugin & {
6
25
  getPreviewHtml(value: string): string;
7
26
  };
8
27
  /** Factory for cases where multiple independent instances are needed. */
9
- export declare function createMarkdownPlugin(): RCTextareaPlugin & {
28
+ export declare function createMarkdownPlugin(options?: MarkdownPluginOptions): RCTextareaPlugin & {
10
29
  getPreviewHtml(value: string): string;
11
30
  };
package/package.json CHANGED
@@ -3,8 +3,8 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.6.0",
7
- "description": "Markdown decoration plugin for rc-textarea.",
6
+ "version": "0.7.0",
7
+ "description": "Markdown decoration and folding plugin for rc-textarea.",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "git+https://github.com/richardcarls/rc-webcomponents.git",
@@ -28,21 +28,31 @@
28
28
  "types": "./dist/types/index.d.ts",
29
29
  "sideEffects": false,
30
30
  "scripts": {
31
- "build": "tsc && vite build"
31
+ "build": "tsc && vite build",
32
+ "test:browser": "vitest --run"
32
33
  },
33
34
  "devDependencies": {
34
- "@rcarls/rc-textarea": "0.6.0",
35
+ "@rcarls/rc-textarea": "0.7.0",
36
+ "@vitest/browser-playwright": "4.1.5",
37
+ "lit": "^3.0.0",
35
38
  "mdast-util-from-markdown": "^2.0.2",
39
+ "mdast-util-gfm-table": "^2.0.0",
36
40
  "micromark": "^4.0.2",
41
+ "micromark-extension-gfm-table": "^2.0.0",
42
+ "playwright": "^1.56.0",
37
43
  "typescript": "~5.9.3",
38
44
  "unist-util-visit": "^5.0.0",
39
45
  "vite": "^7.1.7",
40
- "vite-plugin-dts": "^4.5.4"
46
+ "vite-plugin-dts": "^4.5.4",
47
+ "vitest": "^4.0.6",
48
+ "vitest-browser-lit": "^1.0.1"
41
49
  },
42
50
  "peerDependencies": {
43
51
  "@rcarls/rc-textarea": ">=0.2.0 <1.0.0",
44
52
  "mdast-util-from-markdown": ">=2.0.0",
53
+ "mdast-util-gfm-table": ">=2.0.0",
45
54
  "micromark": ">=4.0.0",
55
+ "micromark-extension-gfm-table": ">=2.0.0",
46
56
  "unist-util-visit": ">=5.0.0"
47
57
  }
48
58
  }