@localess/richtext 3.4.1 → 4.0.0-dev.20260905083404

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.
@@ -1 +1,204 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=(...e)=>({type:`doc`,content:e}),t=(...e)=>({type:`paragraph`,content:e}),n=(e,t)=>({type:`text`,text:e,...t?{marks:t}:{}}),r=(...e)=>({type:`listItem`,content:e}),i={type:`link`,attrs:{href:`https://example.com`,target:`_blank`,rel:`noopener noreferrer nofollow`,class:null}},a=[{title:`empty doc`,input:e(),expected:``,parity:!0},{title:`null input`,input:null,expected:``,parity:!1},{title:`plain paragraph`,input:e(t(n(`Hello world`))),expected:`<p>Hello world</p>`,parity:!0},{title:`two paragraphs`,input:e(t(n(`One`)),t(n(`Two`))),expected:`<p>One</p><p>Two</p>`,parity:!0},{title:`all six heading levels`,input:e(...[1,2,3,4,5,6].map(e=>({type:`heading`,attrs:{level:e},content:[n(`H${e}`)]}))),expected:`<h1>H1</h1><h2>H2</h2><h3>H3</h3><h4>H4</h4><h5>H5</h5><h6>H6</h6>`,parity:!0},{title:`invalid heading level falls back to h1`,input:e({type:`heading`,attrs:{level:9},content:[n(`Big`)]}),expected:`<h1>Big</h1>`,parity:!0},{title:`every simple mark`,input:e(t(n(`b`,[{type:`bold`}]),n(`i`,[{type:`italic`}]),n(`s`,[{type:`strike`}]),n(`u`,[{type:`underline`}]),n(`c`,[{type:`code`}]))),expected:`<p><strong>b</strong><em>i</em><s>s</s><u>u</u><code>c</code></p>`,parity:!0},{title:`nested marks fold with marks[0] outermost`,input:e(t(n(`x`,[{type:`bold`},{type:`italic`}]))),expected:`<p><strong><em>x</em></strong></p>`,parity:!0},{title:`adjacent nodes sharing an outer mark merge into one wrapper`,input:e(t(n(`a`,[{type:`bold`}]),n(`b`,[{type:`bold`},{type:`italic`}]))),expected:`<p><strong>a<em>b</em></strong></p>`,parity:!0},{title:`bullet list with paragraphs in items`,input:e({type:`bulletList`,content:[r(t(n(`One`))),r(t(n(`Two`)))]}),expected:`<ul><li><p>One</p></li><li><p>Two</p></li></ul>`,parity:!0},{title:`ordered list omits start=1`,input:e({type:`orderedList`,attrs:{start:1},content:[r(t(n(`One`)))]}),expected:`<ol><li><p>One</p></li></ol>`,parity:!0},{title:`ordered list emits start=3`,input:e({type:`orderedList`,attrs:{start:3},content:[r(t(n(`Three`)))]}),expected:`<ol start="3"><li><p>Three</p></li></ol>`,parity:!0},{title:`nested bullet list inside a list item`,input:e({type:`bulletList`,content:[r(t(n(`Outer`)),{type:`bulletList`,content:[r(t(n(`Inner`)))]})]}),expected:`<ul><li><p>Outer</p><ul><li><p>Inner</p></li></ul></li></ul>`,parity:!0},{title:`code block without language`,input:e({type:`codeBlock`,attrs:{language:null},content:[n(`const x = 1;`)]}),expected:`<pre><code>const x = 1;</code></pre>`,parity:!0},{title:`code block with language class`,input:e({type:`codeBlock`,attrs:{language:`js`},content:[n(`const x = 1;`)]}),expected:`<pre><code class="language-js">const x = 1;</code></pre>`,parity:!0},{title:`link with editor-default attrs`,input:e(t(n(`Visit`,[i]))),expected:`<p><a target="_blank" rel="noopener noreferrer nofollow" href="https://example.com">Visit</a></p>`,parity:!0},{title:`link spanning differently-marked text renders one anchor`,input:e(t(n(`go `,[i]),n(`bold`,[i,{type:`bold`}]),n(` now`,[i]))),expected:`<p><a target="_blank" rel="noopener noreferrer nofollow" href="https://example.com">go <strong>bold</strong> now</a></p>`,parity:!0},{title:`text escaping of angle brackets and ampersands`,input:e(t(n(`a < b & c > d`))),expected:`<p>a &lt; b &amp; c &gt; d</p>`,parity:!0},{title:`javascript: href is sanitized to empty (intentionally stricter than TipTap)`,input:e(t(n(`x`,[{type:`link`,attrs:{href:`javascript:alert(1)`}}]))),expected:`<p><a href="">x</a></p>`,parity:!1},{title:`unknown node types are skipped`,input:e({type:`schema`,attrs:{data:{}}},t(n(`kept`))),expected:`<p>kept</p>`,parity:!1}];exports.richTextFixtures=a;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/test-utils/fixtures.ts
3
+ var doc = (...content) => ({
4
+ type: "doc",
5
+ content
6
+ });
7
+ var p = (...content) => ({
8
+ type: "paragraph",
9
+ content
10
+ });
11
+ var t = (text, marks) => ({
12
+ type: "text",
13
+ text,
14
+ ...marks ? { marks } : {}
15
+ });
16
+ var li = (...content) => ({
17
+ type: "listItem",
18
+ content
19
+ });
20
+ var link = {
21
+ type: "link",
22
+ attrs: {
23
+ href: "https://example.com",
24
+ target: "_blank",
25
+ rel: "noopener noreferrer nofollow",
26
+ class: null
27
+ }
28
+ };
29
+ /**
30
+ * Shared correctness corpus. Every renderer in every framework package must
31
+ * produce exactly these strings (DOM-roundtrip-normalized where the framework
32
+ * renders through a real DOM). `parity: true` fixtures are additionally
33
+ * asserted byte-identical to TipTap's `generateHTML`.
34
+ */
35
+ var richTextFixtures = [
36
+ {
37
+ title: "empty doc",
38
+ input: doc(),
39
+ expected: "",
40
+ parity: true
41
+ },
42
+ {
43
+ title: "null input",
44
+ input: null,
45
+ expected: "",
46
+ parity: false
47
+ },
48
+ {
49
+ title: "plain paragraph",
50
+ input: doc(p(t("Hello world"))),
51
+ expected: "<p>Hello world</p>",
52
+ parity: true
53
+ },
54
+ {
55
+ title: "two paragraphs",
56
+ input: doc(p(t("One")), p(t("Two"))),
57
+ expected: "<p>One</p><p>Two</p>",
58
+ parity: true
59
+ },
60
+ {
61
+ title: "all six heading levels",
62
+ input: doc(...[
63
+ 1,
64
+ 2,
65
+ 3,
66
+ 4,
67
+ 5,
68
+ 6
69
+ ].map((level) => ({
70
+ type: "heading",
71
+ attrs: { level },
72
+ content: [t(`H${level}`)]
73
+ }))),
74
+ expected: "<h1>H1</h1><h2>H2</h2><h3>H3</h3><h4>H4</h4><h5>H5</h5><h6>H6</h6>",
75
+ parity: true
76
+ },
77
+ {
78
+ title: "invalid heading level falls back to h1",
79
+ input: doc({
80
+ type: "heading",
81
+ attrs: { level: 9 },
82
+ content: [t("Big")]
83
+ }),
84
+ expected: "<h1>Big</h1>",
85
+ parity: true
86
+ },
87
+ {
88
+ title: "every simple mark",
89
+ input: doc(p(t("b", [{ type: "bold" }]), t("i", [{ type: "italic" }]), t("s", [{ type: "strike" }]), t("u", [{ type: "underline" }]), t("c", [{ type: "code" }]))),
90
+ expected: "<p><strong>b</strong><em>i</em><s>s</s><u>u</u><code>c</code></p>",
91
+ parity: true
92
+ },
93
+ {
94
+ title: "nested marks fold with marks[0] outermost",
95
+ input: doc(p(t("x", [{ type: "bold" }, { type: "italic" }]))),
96
+ expected: "<p><strong><em>x</em></strong></p>",
97
+ parity: true
98
+ },
99
+ {
100
+ title: "adjacent nodes sharing an outer mark merge into one wrapper",
101
+ input: doc(p(t("a", [{ type: "bold" }]), t("b", [{ type: "bold" }, { type: "italic" }]))),
102
+ expected: "<p><strong>a<em>b</em></strong></p>",
103
+ parity: true
104
+ },
105
+ {
106
+ title: "bullet list with paragraphs in items",
107
+ input: doc({
108
+ type: "bulletList",
109
+ content: [li(p(t("One"))), li(p(t("Two")))]
110
+ }),
111
+ expected: "<ul><li><p>One</p></li><li><p>Two</p></li></ul>",
112
+ parity: true
113
+ },
114
+ {
115
+ title: "ordered list omits start=1",
116
+ input: doc({
117
+ type: "orderedList",
118
+ attrs: { start: 1 },
119
+ content: [li(p(t("One")))]
120
+ }),
121
+ expected: "<ol><li><p>One</p></li></ol>",
122
+ parity: true
123
+ },
124
+ {
125
+ title: "ordered list emits start=3",
126
+ input: doc({
127
+ type: "orderedList",
128
+ attrs: { start: 3 },
129
+ content: [li(p(t("Three")))]
130
+ }),
131
+ expected: "<ol start=\"3\"><li><p>Three</p></li></ol>",
132
+ parity: true
133
+ },
134
+ {
135
+ title: "nested bullet list inside a list item",
136
+ input: doc({
137
+ type: "bulletList",
138
+ content: [li(p(t("Outer")), {
139
+ type: "bulletList",
140
+ content: [li(p(t("Inner")))]
141
+ })]
142
+ }),
143
+ expected: "<ul><li><p>Outer</p><ul><li><p>Inner</p></li></ul></li></ul>",
144
+ parity: true
145
+ },
146
+ {
147
+ title: "code block without language",
148
+ input: doc({
149
+ type: "codeBlock",
150
+ attrs: { language: null },
151
+ content: [t("const x = 1;")]
152
+ }),
153
+ expected: "<pre><code>const x = 1;</code></pre>",
154
+ parity: true
155
+ },
156
+ {
157
+ title: "code block with language class",
158
+ input: doc({
159
+ type: "codeBlock",
160
+ attrs: { language: "js" },
161
+ content: [t("const x = 1;")]
162
+ }),
163
+ expected: "<pre><code class=\"language-js\">const x = 1;</code></pre>",
164
+ parity: true
165
+ },
166
+ {
167
+ title: "link with editor-default attrs",
168
+ input: doc(p(t("Visit", [link]))),
169
+ expected: "<p><a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://example.com\">Visit</a></p>",
170
+ parity: true
171
+ },
172
+ {
173
+ title: "link spanning differently-marked text renders one anchor",
174
+ input: doc(p(t("go ", [link]), t("bold", [link, { type: "bold" }]), t(" now", [link]))),
175
+ expected: "<p><a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://example.com\">go <strong>bold</strong> now</a></p>",
176
+ parity: true
177
+ },
178
+ {
179
+ title: "text escaping of angle brackets and ampersands",
180
+ input: doc(p(t("a < b & c > d"))),
181
+ expected: "<p>a &lt; b &amp; c &gt; d</p>",
182
+ parity: true
183
+ },
184
+ {
185
+ title: "javascript: href is sanitized to empty (intentionally stricter than TipTap)",
186
+ input: doc(p(t("x", [{
187
+ type: "link",
188
+ attrs: { href: "javascript:alert(1)" }
189
+ }]))),
190
+ expected: "<p><a href=\"\">x</a></p>",
191
+ parity: false
192
+ },
193
+ {
194
+ title: "unknown node types are skipped",
195
+ input: doc({
196
+ type: "schema",
197
+ attrs: { data: {} }
198
+ }, p(t("kept"))),
199
+ expected: "<p>kept</p>",
200
+ parity: false
201
+ }
202
+ ];
203
+ //#endregion
204
+ exports.richTextFixtures = richTextFixtures;
@@ -1,18 +1,22 @@
1
1
  //#region src/test-utils/fixtures.ts
2
- var e = (...e) => ({
2
+ var doc = (...content) => ({
3
3
  type: "doc",
4
- content: e
5
- }), t = (...e) => ({
4
+ content
5
+ });
6
+ var p = (...content) => ({
6
7
  type: "paragraph",
7
- content: e
8
- }), n = (e, t) => ({
8
+ content
9
+ });
10
+ var t = (text, marks) => ({
9
11
  type: "text",
10
- text: e,
11
- ...t ? { marks: t } : {}
12
- }), r = (...e) => ({
12
+ text,
13
+ ...marks ? { marks } : {}
14
+ });
15
+ var li = (...content) => ({
13
16
  type: "listItem",
14
- content: e
15
- }), i = {
17
+ content
18
+ });
19
+ var link = {
16
20
  type: "link",
17
21
  attrs: {
18
22
  href: "https://example.com",
@@ -20,173 +24,180 @@ var e = (...e) => ({
20
24
  rel: "noopener noreferrer nofollow",
21
25
  class: null
22
26
  }
23
- }, a = [
27
+ };
28
+ /**
29
+ * Shared correctness corpus. Every renderer in every framework package must
30
+ * produce exactly these strings (DOM-roundtrip-normalized where the framework
31
+ * renders through a real DOM). `parity: true` fixtures are additionally
32
+ * asserted byte-identical to TipTap's `generateHTML`.
33
+ */
34
+ var richTextFixtures = [
24
35
  {
25
36
  title: "empty doc",
26
- input: e(),
37
+ input: doc(),
27
38
  expected: "",
28
- parity: !0
39
+ parity: true
29
40
  },
30
41
  {
31
42
  title: "null input",
32
43
  input: null,
33
44
  expected: "",
34
- parity: !1
45
+ parity: false
35
46
  },
36
47
  {
37
48
  title: "plain paragraph",
38
- input: e(t(n("Hello world"))),
49
+ input: doc(p(t("Hello world"))),
39
50
  expected: "<p>Hello world</p>",
40
- parity: !0
51
+ parity: true
41
52
  },
42
53
  {
43
54
  title: "two paragraphs",
44
- input: e(t(n("One")), t(n("Two"))),
55
+ input: doc(p(t("One")), p(t("Two"))),
45
56
  expected: "<p>One</p><p>Two</p>",
46
- parity: !0
57
+ parity: true
47
58
  },
48
59
  {
49
60
  title: "all six heading levels",
50
- input: e(...[
61
+ input: doc(...[
51
62
  1,
52
63
  2,
53
64
  3,
54
65
  4,
55
66
  5,
56
67
  6
57
- ].map((e) => ({
68
+ ].map((level) => ({
58
69
  type: "heading",
59
- attrs: { level: e },
60
- content: [n(`H${e}`)]
70
+ attrs: { level },
71
+ content: [t(`H${level}`)]
61
72
  }))),
62
73
  expected: "<h1>H1</h1><h2>H2</h2><h3>H3</h3><h4>H4</h4><h5>H5</h5><h6>H6</h6>",
63
- parity: !0
74
+ parity: true
64
75
  },
65
76
  {
66
77
  title: "invalid heading level falls back to h1",
67
- input: e({
78
+ input: doc({
68
79
  type: "heading",
69
80
  attrs: { level: 9 },
70
- content: [n("Big")]
81
+ content: [t("Big")]
71
82
  }),
72
83
  expected: "<h1>Big</h1>",
73
- parity: !0
84
+ parity: true
74
85
  },
75
86
  {
76
87
  title: "every simple mark",
77
- input: e(t(n("b", [{ type: "bold" }]), n("i", [{ type: "italic" }]), n("s", [{ type: "strike" }]), n("u", [{ type: "underline" }]), n("c", [{ type: "code" }]))),
88
+ input: doc(p(t("b", [{ type: "bold" }]), t("i", [{ type: "italic" }]), t("s", [{ type: "strike" }]), t("u", [{ type: "underline" }]), t("c", [{ type: "code" }]))),
78
89
  expected: "<p><strong>b</strong><em>i</em><s>s</s><u>u</u><code>c</code></p>",
79
- parity: !0
90
+ parity: true
80
91
  },
81
92
  {
82
93
  title: "nested marks fold with marks[0] outermost",
83
- input: e(t(n("x", [{ type: "bold" }, { type: "italic" }]))),
94
+ input: doc(p(t("x", [{ type: "bold" }, { type: "italic" }]))),
84
95
  expected: "<p><strong><em>x</em></strong></p>",
85
- parity: !0
96
+ parity: true
86
97
  },
87
98
  {
88
99
  title: "adjacent nodes sharing an outer mark merge into one wrapper",
89
- input: e(t(n("a", [{ type: "bold" }]), n("b", [{ type: "bold" }, { type: "italic" }]))),
100
+ input: doc(p(t("a", [{ type: "bold" }]), t("b", [{ type: "bold" }, { type: "italic" }]))),
90
101
  expected: "<p><strong>a<em>b</em></strong></p>",
91
- parity: !0
102
+ parity: true
92
103
  },
93
104
  {
94
105
  title: "bullet list with paragraphs in items",
95
- input: e({
106
+ input: doc({
96
107
  type: "bulletList",
97
- content: [r(t(n("One"))), r(t(n("Two")))]
108
+ content: [li(p(t("One"))), li(p(t("Two")))]
98
109
  }),
99
110
  expected: "<ul><li><p>One</p></li><li><p>Two</p></li></ul>",
100
- parity: !0
111
+ parity: true
101
112
  },
102
113
  {
103
114
  title: "ordered list omits start=1",
104
- input: e({
115
+ input: doc({
105
116
  type: "orderedList",
106
117
  attrs: { start: 1 },
107
- content: [r(t(n("One")))]
118
+ content: [li(p(t("One")))]
108
119
  }),
109
120
  expected: "<ol><li><p>One</p></li></ol>",
110
- parity: !0
121
+ parity: true
111
122
  },
112
123
  {
113
124
  title: "ordered list emits start=3",
114
- input: e({
125
+ input: doc({
115
126
  type: "orderedList",
116
127
  attrs: { start: 3 },
117
- content: [r(t(n("Three")))]
128
+ content: [li(p(t("Three")))]
118
129
  }),
119
130
  expected: "<ol start=\"3\"><li><p>Three</p></li></ol>",
120
- parity: !0
131
+ parity: true
121
132
  },
122
133
  {
123
134
  title: "nested bullet list inside a list item",
124
- input: e({
135
+ input: doc({
125
136
  type: "bulletList",
126
- content: [r(t(n("Outer")), {
137
+ content: [li(p(t("Outer")), {
127
138
  type: "bulletList",
128
- content: [r(t(n("Inner")))]
139
+ content: [li(p(t("Inner")))]
129
140
  })]
130
141
  }),
131
142
  expected: "<ul><li><p>Outer</p><ul><li><p>Inner</p></li></ul></li></ul>",
132
- parity: !0
143
+ parity: true
133
144
  },
134
145
  {
135
146
  title: "code block without language",
136
- input: e({
147
+ input: doc({
137
148
  type: "codeBlock",
138
149
  attrs: { language: null },
139
- content: [n("const x = 1;")]
150
+ content: [t("const x = 1;")]
140
151
  }),
141
152
  expected: "<pre><code>const x = 1;</code></pre>",
142
- parity: !0
153
+ parity: true
143
154
  },
144
155
  {
145
156
  title: "code block with language class",
146
- input: e({
157
+ input: doc({
147
158
  type: "codeBlock",
148
159
  attrs: { language: "js" },
149
- content: [n("const x = 1;")]
160
+ content: [t("const x = 1;")]
150
161
  }),
151
162
  expected: "<pre><code class=\"language-js\">const x = 1;</code></pre>",
152
- parity: !0
163
+ parity: true
153
164
  },
154
165
  {
155
166
  title: "link with editor-default attrs",
156
- input: e(t(n("Visit", [i]))),
167
+ input: doc(p(t("Visit", [link]))),
157
168
  expected: "<p><a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://example.com\">Visit</a></p>",
158
- parity: !0
169
+ parity: true
159
170
  },
160
171
  {
161
172
  title: "link spanning differently-marked text renders one anchor",
162
- input: e(t(n("go ", [i]), n("bold", [i, { type: "bold" }]), n(" now", [i]))),
173
+ input: doc(p(t("go ", [link]), t("bold", [link, { type: "bold" }]), t(" now", [link]))),
163
174
  expected: "<p><a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://example.com\">go <strong>bold</strong> now</a></p>",
164
- parity: !0
175
+ parity: true
165
176
  },
166
177
  {
167
178
  title: "text escaping of angle brackets and ampersands",
168
- input: e(t(n("a < b & c > d"))),
179
+ input: doc(p(t("a < b & c > d"))),
169
180
  expected: "<p>a &lt; b &amp; c &gt; d</p>",
170
- parity: !0
181
+ parity: true
171
182
  },
172
183
  {
173
184
  title: "javascript: href is sanitized to empty (intentionally stricter than TipTap)",
174
- input: e(t(n("x", [{
185
+ input: doc(p(t("x", [{
175
186
  type: "link",
176
187
  attrs: { href: "javascript:alert(1)" }
177
188
  }]))),
178
189
  expected: "<p><a href=\"\">x</a></p>",
179
- parity: !1
190
+ parity: false
180
191
  },
181
192
  {
182
193
  title: "unknown node types are skipped",
183
- input: e({
194
+ input: doc({
184
195
  type: "schema",
185
196
  attrs: { data: {} }
186
- }, t(n("kept"))),
197
+ }, p(t("kept"))),
187
198
  expected: "<p>kept</p>",
188
- parity: !1
199
+ parity: false
189
200
  }
190
201
  ];
191
202
  //#endregion
192
- export { a as richTextFixtures };
203
+ export { richTextFixtures };
package/package.json CHANGED
@@ -1,75 +1,78 @@
1
- {
2
- "name": "@localess/richtext",
3
- "version": "3.4.1",
4
- "description": "Framework-neutral rich text model and renderer for Localess's TipTap JSON content.",
5
- "keywords": [
6
- "localess",
7
- "sdk",
8
- "richtext",
9
- "tiptap",
10
- "javascript",
11
- "typescript"
12
- ],
13
- "author": "Lessify",
14
- "homepage": "https://github.com/Lessify/localess-js",
15
- "sideEffects": false,
16
- "files": [
17
- "dist",
18
- "SKILL.md"
19
- ],
20
- "main": "dist/index.js",
21
- "module": "dist/index.mjs",
22
- "types": "dist/index.d.ts",
23
- "exports": {
24
- ".": {
25
- "types": "./dist/index.d.ts",
26
- "import": "./dist/index.mjs",
27
- "require": "./dist/index.js"
28
- },
29
- "./test-utils": {
30
- "types": "./dist/test-utils/index.d.ts",
31
- "import": "./dist/test-utils/index.mjs",
32
- "require": "./dist/test-utils/index.js"
33
- }
34
- },
35
- "repository": {
36
- "type": "git",
37
- "url": "git+https://github.com/Lessify/localess-js.git",
38
- "directory": "packages/richtext"
39
- },
40
- "bugs": {
41
- "url": "https://github.com/Lessify/localess-js/issues"
42
- },
43
- "scripts": {
44
- "build": "vite build",
45
- "test": "vitest run",
46
- "test:watch": "vitest",
47
- "test:coverage": "vitest run --coverage"
48
- },
49
- "license": "MIT",
50
- "devDependencies": {
51
- "@tiptap/extension-bold": "^3.22.5",
52
- "@tiptap/extension-bullet-list": "^3.22.5",
53
- "@tiptap/extension-code": "^3.22.5",
54
- "@tiptap/extension-code-block-lowlight": "^3.22.5",
55
- "@tiptap/extension-document": "^3.22.5",
56
- "@tiptap/extension-heading": "^3.22.5",
57
- "@tiptap/extension-history": "^3.22.5",
58
- "@tiptap/extension-italic": "^3.22.5",
59
- "@tiptap/extension-link": "^3.22.5",
60
- "@tiptap/extension-list-item": "^3.22.5",
61
- "@tiptap/extension-ordered-list": "^3.22.5",
62
- "@tiptap/extension-paragraph": "^3.22.5",
63
- "@tiptap/extension-strike": "^3.22.5",
64
- "@tiptap/extension-text": "^3.22.5",
65
- "@tiptap/extension-underline": "^3.22.5",
66
- "@tiptap/html": "^3.22.5",
67
- "@types/node": "^24",
68
- "typescript": "^5.9.3",
69
- "vite": "^8.0.16",
70
- "vite-plugin-dts": "^5.0.0"
71
- },
72
- "engines": {
73
- "node": ">= 24.0.0"
74
- }
75
- }
1
+ {
2
+ "name": "@localess/richtext",
3
+ "version": "4.0.0-dev.20260905083404",
4
+ "description": "Framework-neutral rich text model and renderer for Localess's TipTap JSON content.",
5
+ "keywords": [
6
+ "localess",
7
+ "sdk",
8
+ "richtext",
9
+ "tiptap",
10
+ "javascript",
11
+ "typescript"
12
+ ],
13
+ "author": "Lessify",
14
+ "homepage": "https://github.com/Lessify/localess-js",
15
+ "sideEffects": false,
16
+ "files": [
17
+ "dist",
18
+ "SKILL.md"
19
+ ],
20
+ "main": "dist/index.js",
21
+ "module": "dist/index.mjs",
22
+ "types": "dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.mjs",
27
+ "require": "./dist/index.js"
28
+ },
29
+ "./test-utils": {
30
+ "types": "./dist/test-utils/index.d.ts",
31
+ "import": "./dist/test-utils/index.mjs",
32
+ "require": "./dist/test-utils/index.js"
33
+ }
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/Lessify/localess-js.git",
38
+ "directory": "packages/richtext"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/Lessify/localess-js/issues"
42
+ },
43
+ "scripts": {
44
+ "build": "vite build",
45
+ "test": "vitest run",
46
+ "test:watch": "vitest",
47
+ "test:coverage": "vitest run --coverage"
48
+ },
49
+ "license": "MIT",
50
+ "dependencies": {
51
+ "@localess/model": "4.0.0-dev.20260905083404"
52
+ },
53
+ "devDependencies": {
54
+ "@tiptap/extension-bold": "^3.22.5",
55
+ "@tiptap/extension-bullet-list": "^3.22.5",
56
+ "@tiptap/extension-code": "^3.22.5",
57
+ "@tiptap/extension-code-block-lowlight": "^3.22.5",
58
+ "@tiptap/extension-document": "^3.22.5",
59
+ "@tiptap/extension-heading": "^3.22.5",
60
+ "@tiptap/extension-history": "^3.22.5",
61
+ "@tiptap/extension-italic": "^3.22.5",
62
+ "@tiptap/extension-link": "^3.22.5",
63
+ "@tiptap/extension-list-item": "^3.22.5",
64
+ "@tiptap/extension-ordered-list": "^3.22.5",
65
+ "@tiptap/extension-paragraph": "^3.22.5",
66
+ "@tiptap/extension-strike": "^3.22.5",
67
+ "@tiptap/extension-text": "^3.22.5",
68
+ "@tiptap/extension-underline": "^3.22.5",
69
+ "@tiptap/html": "^3.22.5",
70
+ "@types/node": "^24",
71
+ "typescript": "^5.9.3",
72
+ "vite": "^8.0.16",
73
+ "vite-plugin-dts": "^5.0.0"
74
+ },
75
+ "engines": {
76
+ "node": ">= 24.0.0"
77
+ }
78
+ }