@nextblock-cms/cortex 0.13.3 → 0.13.6

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.
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),I={b:"bold",code:"code",del:"strike",em:"italic",i:"italic",mark:"highlight",s:"strike",strike:"strike",strong:"bold",sub:"subscript",sup:"superscript"},S=new Set(["article","aside","body","div","footer","header","html","main","nav","section"]),h=new Set(["script","style","noscript","svg","template","iframe","form"]),b=12;function u(i){return i.replace(/&nbsp;/gi," ").replace(/&lt;/gi,"<").replace(/&gt;/gi,">").replace(/&quot;/gi,'"').replace(/&#0?39;/g,"'").replace(/&apos;/gi,"'").replace(/&#(\d+);/g,(e,t)=>String.fromCodePoint(Number(t))).replace(/&#x([0-9a-f]+);/gi,(e,t)=>String.fromCodePoint(Number.parseInt(t,16))).replace(/&amp;/gi,"&")}function T(i,e){const t=i.match(new RegExp(`\\b${e}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`,"i"));return t?u(t[1]??t[2]??t[3]??""):null}function A(i,e,t){const n=new RegExp(`<${t}\\b`,"gi"),o=new RegExp(`</${t}\\s*>`,"gi");let r=1,a=e;for(;r>0;){o.lastIndex=a;const c=o.exec(i);if(!c)return{end:i.length,inner:i.slice(e)};n.lastIndex=a;const s=n.exec(i);if(s&&s.index<c.index){r+=1,a=s.index+s[0].length;continue}if(r-=1,a=c.index+c[0].length,r===0)return{end:a,inner:i.slice(e,c.index)}}return{end:a,inner:i.slice(e)}}function d(i){const e=[];let t=0;for(;t<i.length;){const n=i.indexOf("<",t);if(n===-1){e.push({text:i.slice(t),type:"text"});break}n>t&&e.push({text:i.slice(t,n),type:"text"});const o=i.indexOf(">",n);if(o===-1){e.push({text:i.slice(n),type:"text"});break}const r=i.slice(n+1,o);if(r.startsWith("!")||r.startsWith("/")||r.startsWith("?")){t=o+1;continue}const a=r.match(/^([a-zA-Z][a-zA-Z0-9-]*)/);if(!a){t=o+1;continue}const c=a[1].toLowerCase();if(w.has(c)||r.trimEnd().endsWith("/")){e.push({attrs:r,inner:"",tag:c,type:"element"}),t=o+1;continue}const s=A(i,o+1,c);e.push({attrs:r,inner:s.inner,tag:c,type:"element"}),t=s.end}return e}function g(i,e,t){if(!e)return;const n=i[i.length-1];if(n&&n.type==="text"&&JSON.stringify(n.marks??[])===JSON.stringify(t)){n.text+=e;return}i.push(t.length>0?{marks:t,text:e,type:"text"}:{text:e,type:"text"})}function p(i,e,t){const n=[];if(t>b)return g(n,u(i.replace(/<[^>]*>/g,"")).replace(/\s+/g," "),e),n;for(const o of d(i)){if(o.type==="text"){g(n,u(o.text).replace(/\s+/g," "),e);continue}if(h.has(o.tag))continue;if(o.tag==="br"){n.push({type:"hardBreak"});continue}if(o.tag==="a"){const a=T(o.attrs,"href"),c=a?[...e,{attrs:{href:a,target:"_blank"},type:"link"}]:e;n.push(...p(o.inner,c,t+1));continue}const r=I[o.tag];if(r){const a=e.some(c=>c.type===r)?e:[...e,{type:r}];n.push(...p(o.inner,a,t+1));continue}n.push(...p(o.inner,e,t+1))}return n}function k(i){const e=[...i];for(;e.length>0;){const t=e[0];if(t.type==="hardBreak"){e.shift();continue}const n=t.text.replace(/^\s+/,"");if(!n){e.shift();continue}e[0]={...t,text:n};break}for(;e.length>0;){const t=e[e.length-1];if(t.type==="hardBreak"){e.pop();continue}const n=t.text.replace(/\s+$/,"");if(!n){e.pop();continue}e[e.length-1]={...t,text:n};break}return e}function y(i){const e=k(i);return e.length>0?{content:e,type:"paragraph"}:null}function $(i,e){const t=[];for(const n of d(i)){if(n.type!=="element"||n.tag!=="li")continue;const o=f(n.inner,e+1);t.push({content:o.length>0?o:[{type:"paragraph"}],type:"listItem"})}return t}function f(i,e){const t=[];if(e>b)return t;let n=[];const o=()=>{const r=y(n);r&&t.push(r),n=[]};for(const r of d(i)){if(r.type==="text"){g(n,u(r.text).replace(/\s+/g," "),[]);continue}const{attrs:a,inner:c,tag:s}=r;if(h.has(s))continue;const x=s.match(/^h([1-6])$/);if(x){o();const l=k(p(c,[],e+1));l.length>0&&t.push({attrs:{level:Number(x[1])},content:l,type:"heading"});continue}if(s==="p"){o();const l=y(p(c,[],e+1));l&&t.push(l);continue}if(s==="ul"||s==="ol"){o();const l=$(c,e);l.length>0&&t.push({content:l,type:s==="ul"?"bulletList":"orderedList"});continue}if(s==="blockquote"){o();const l=f(c,e+1);l.length>0&&t.push({content:l,type:"blockquote"});continue}if(s==="pre"){o();const l=u(c.replace(/<[^>]*>/g,"")).replace(/^\n+|\n+$/g,"");l&&t.push({content:[{text:l,type:"text"}],type:"codeBlock"});continue}if(s==="hr"){o(),t.push({type:"horizontalRule"});continue}if(s==="br"){n.push({type:"hardBreak"});continue}if(S.has(s)||s==="li"||s==="table"){o(),t.push(...f(c,e+1));continue}n.push(...p(`<${a}>${c}</${s}>`,[],e+1))}return o(),t}function m(i){return i.split(/\n\s*\n/).map(e=>e.trim()).filter(Boolean).map(e=>({content:[{text:e.replace(/\s*\n\s*/g," "),type:"text"}],type:"paragraph"}))}function E(i){const e=(typeof i=="string"?i:"").trim().replace(/^```(?:html|xml)?\s*\n?/i,"").replace(/\n?```$/,"").trim();if(!e)return null;const t=[...h].reduce((r,a)=>r.replace(new RegExp(`<${a}\\b[\\s\\S]*?</${a}\\s*>`,"gi")," "),e).trim();if(!t)return null;const o=/<[a-zA-Z!/]/.test(t)?f(t,0):m(t);if(o.length===0){const r=m(u(t.replace(/<[^>]*>/g," ")).replace(/[ \t]+/g," "));return r.length>0?{content:r,type:"doc"}:null}return{content:o,type:"doc"}}exports.editorDocumentFromHtml=E;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Convert an HTML fragment (or plain text) into a Tiptap/editor document.
3
+ *
4
+ * Cortex asks models for HTML rather than nested editor JSON — the same choice
5
+ * `ai-block-generation.ts` already makes for the inline assistant — because even
6
+ * small models emit correct HTML reliably while deeply nested node JSON is a
7
+ * common failure mode. Products store their body as `description_json`, so that
8
+ * HTML has to become editor JSON on the server, with no DOM available.
9
+ *
10
+ * Deliberately dependency-free: `@tiptap/html`'s `generateJSON` needs both a DOM
11
+ * shim and the full client-side extension list, and `libs/editor` is a client
12
+ * bundle that cannot be imported from a server tool.
13
+ */
14
+ type EditorBlockNode = {
15
+ attrs?: Record<string, unknown>;
16
+ content?: unknown[];
17
+ type: string;
18
+ };
19
+ export type EditorDocument = {
20
+ content: EditorBlockNode[];
21
+ type: 'doc';
22
+ };
23
+ /**
24
+ * Build an editor document from an HTML fragment or plain text. Returns null
25
+ * when there is no usable content, so callers can omit the field entirely
26
+ * rather than storing an empty body.
27
+ */
28
+ export declare function editorDocumentFromHtml(value: string): EditorDocument | null;
29
+ export {};
@@ -0,0 +1,290 @@
1
+ const w = /* @__PURE__ */ new Set([
2
+ "area",
3
+ "base",
4
+ "br",
5
+ "col",
6
+ "embed",
7
+ "hr",
8
+ "img",
9
+ "input",
10
+ "link",
11
+ "meta",
12
+ "param",
13
+ "source",
14
+ "track",
15
+ "wbr"
16
+ ]), I = {
17
+ b: "bold",
18
+ code: "code",
19
+ del: "strike",
20
+ em: "italic",
21
+ i: "italic",
22
+ mark: "highlight",
23
+ s: "strike",
24
+ strike: "strike",
25
+ strong: "bold",
26
+ sub: "subscript",
27
+ sup: "superscript"
28
+ }, S = /* @__PURE__ */ new Set([
29
+ "article",
30
+ "aside",
31
+ "body",
32
+ "div",
33
+ "footer",
34
+ "header",
35
+ "html",
36
+ "main",
37
+ "nav",
38
+ "section"
39
+ ]), h = /* @__PURE__ */ new Set(["script", "style", "noscript", "svg", "template", "iframe", "form"]), b = 12;
40
+ function u(i) {
41
+ return i.replace(/&nbsp;/gi, " ").replace(/&lt;/gi, "<").replace(/&gt;/gi, ">").replace(/&quot;/gi, '"').replace(/&#0?39;/g, "'").replace(/&apos;/gi, "'").replace(/&#(\d+);/g, (e, t) => String.fromCodePoint(Number(t))).replace(/&#x([0-9a-f]+);/gi, (e, t) => String.fromCodePoint(Number.parseInt(t, 16))).replace(/&amp;/gi, "&");
42
+ }
43
+ function A(i, e) {
44
+ const t = i.match(
45
+ new RegExp(`\\b${e}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`, "i")
46
+ );
47
+ return t ? u(t[1] ?? t[2] ?? t[3] ?? "") : null;
48
+ }
49
+ function T(i, e, t) {
50
+ const n = new RegExp(`<${t}\\b`, "gi"), o = new RegExp(`</${t}\\s*>`, "gi");
51
+ let r = 1, a = e;
52
+ for (; r > 0; ) {
53
+ o.lastIndex = a;
54
+ const c = o.exec(i);
55
+ if (!c)
56
+ return { end: i.length, inner: i.slice(e) };
57
+ n.lastIndex = a;
58
+ const s = n.exec(i);
59
+ if (s && s.index < c.index) {
60
+ r += 1, a = s.index + s[0].length;
61
+ continue;
62
+ }
63
+ if (r -= 1, a = c.index + c[0].length, r === 0)
64
+ return { end: a, inner: i.slice(e, c.index) };
65
+ }
66
+ return { end: a, inner: i.slice(e) };
67
+ }
68
+ function d(i) {
69
+ const e = [];
70
+ let t = 0;
71
+ for (; t < i.length; ) {
72
+ const n = i.indexOf("<", t);
73
+ if (n === -1) {
74
+ e.push({ text: i.slice(t), type: "text" });
75
+ break;
76
+ }
77
+ n > t && e.push({ text: i.slice(t, n), type: "text" });
78
+ const o = i.indexOf(">", n);
79
+ if (o === -1) {
80
+ e.push({ text: i.slice(n), type: "text" });
81
+ break;
82
+ }
83
+ const r = i.slice(n + 1, o);
84
+ if (r.startsWith("!") || r.startsWith("/") || r.startsWith("?")) {
85
+ t = o + 1;
86
+ continue;
87
+ }
88
+ const a = r.match(/^([a-zA-Z][a-zA-Z0-9-]*)/);
89
+ if (!a) {
90
+ t = o + 1;
91
+ continue;
92
+ }
93
+ const c = a[1].toLowerCase();
94
+ if (w.has(c) || r.trimEnd().endsWith("/")) {
95
+ e.push({ attrs: r, inner: "", tag: c, type: "element" }), t = o + 1;
96
+ continue;
97
+ }
98
+ const s = T(i, o + 1, c);
99
+ e.push({ attrs: r, inner: s.inner, tag: c, type: "element" }), t = s.end;
100
+ }
101
+ return e;
102
+ }
103
+ function g(i, e, t) {
104
+ if (!e)
105
+ return;
106
+ const n = i[i.length - 1];
107
+ if (n && n.type === "text" && JSON.stringify(n.marks ?? []) === JSON.stringify(t)) {
108
+ n.text += e;
109
+ return;
110
+ }
111
+ i.push(t.length > 0 ? { marks: t, text: e, type: "text" } : { text: e, type: "text" });
112
+ }
113
+ function l(i, e, t) {
114
+ const n = [];
115
+ if (t > b)
116
+ return g(n, u(i.replace(/<[^>]*>/g, "")).replace(/\s+/g, " "), e), n;
117
+ for (const o of d(i)) {
118
+ if (o.type === "text") {
119
+ g(n, u(o.text).replace(/\s+/g, " "), e);
120
+ continue;
121
+ }
122
+ if (h.has(o.tag))
123
+ continue;
124
+ if (o.tag === "br") {
125
+ n.push({ type: "hardBreak" });
126
+ continue;
127
+ }
128
+ if (o.tag === "a") {
129
+ const a = A(o.attrs, "href"), c = a ? [...e, { attrs: { href: a, target: "_blank" }, type: "link" }] : e;
130
+ n.push(...l(o.inner, c, t + 1));
131
+ continue;
132
+ }
133
+ const r = I[o.tag];
134
+ if (r) {
135
+ const a = e.some((c) => c.type === r) ? e : [...e, { type: r }];
136
+ n.push(...l(o.inner, a, t + 1));
137
+ continue;
138
+ }
139
+ n.push(...l(o.inner, e, t + 1));
140
+ }
141
+ return n;
142
+ }
143
+ function k(i) {
144
+ const e = [...i];
145
+ for (; e.length > 0; ) {
146
+ const t = e[0];
147
+ if (t.type === "hardBreak") {
148
+ e.shift();
149
+ continue;
150
+ }
151
+ const n = t.text.replace(/^\s+/, "");
152
+ if (!n) {
153
+ e.shift();
154
+ continue;
155
+ }
156
+ e[0] = { ...t, text: n };
157
+ break;
158
+ }
159
+ for (; e.length > 0; ) {
160
+ const t = e[e.length - 1];
161
+ if (t.type === "hardBreak") {
162
+ e.pop();
163
+ continue;
164
+ }
165
+ const n = t.text.replace(/\s+$/, "");
166
+ if (!n) {
167
+ e.pop();
168
+ continue;
169
+ }
170
+ e[e.length - 1] = { ...t, text: n };
171
+ break;
172
+ }
173
+ return e;
174
+ }
175
+ function y(i) {
176
+ const e = k(i);
177
+ return e.length > 0 ? { content: e, type: "paragraph" } : null;
178
+ }
179
+ function $(i, e) {
180
+ const t = [];
181
+ for (const n of d(i)) {
182
+ if (n.type !== "element" || n.tag !== "li")
183
+ continue;
184
+ const o = f(n.inner, e + 1);
185
+ t.push({
186
+ content: o.length > 0 ? o : [{ type: "paragraph" }],
187
+ type: "listItem"
188
+ });
189
+ }
190
+ return t;
191
+ }
192
+ function f(i, e) {
193
+ const t = [];
194
+ if (e > b)
195
+ return t;
196
+ let n = [];
197
+ const o = () => {
198
+ const r = y(n);
199
+ r && t.push(r), n = [];
200
+ };
201
+ for (const r of d(i)) {
202
+ if (r.type === "text") {
203
+ g(n, u(r.text).replace(/\s+/g, " "), []);
204
+ continue;
205
+ }
206
+ const { attrs: a, inner: c, tag: s } = r;
207
+ if (h.has(s))
208
+ continue;
209
+ const x = s.match(/^h([1-6])$/);
210
+ if (x) {
211
+ o();
212
+ const p = k(l(c, [], e + 1));
213
+ p.length > 0 && t.push({
214
+ attrs: { level: Number(x[1]) },
215
+ content: p,
216
+ type: "heading"
217
+ });
218
+ continue;
219
+ }
220
+ if (s === "p") {
221
+ o();
222
+ const p = y(l(c, [], e + 1));
223
+ p && t.push(p);
224
+ continue;
225
+ }
226
+ if (s === "ul" || s === "ol") {
227
+ o();
228
+ const p = $(c, e);
229
+ p.length > 0 && t.push({
230
+ content: p,
231
+ type: s === "ul" ? "bulletList" : "orderedList"
232
+ });
233
+ continue;
234
+ }
235
+ if (s === "blockquote") {
236
+ o();
237
+ const p = f(c, e + 1);
238
+ p.length > 0 && t.push({ content: p, type: "blockquote" });
239
+ continue;
240
+ }
241
+ if (s === "pre") {
242
+ o();
243
+ const p = u(c.replace(/<[^>]*>/g, "")).replace(/^\n+|\n+$/g, "");
244
+ p && t.push({ content: [{ text: p, type: "text" }], type: "codeBlock" });
245
+ continue;
246
+ }
247
+ if (s === "hr") {
248
+ o(), t.push({ type: "horizontalRule" });
249
+ continue;
250
+ }
251
+ if (s === "br") {
252
+ n.push({ type: "hardBreak" });
253
+ continue;
254
+ }
255
+ if (S.has(s) || s === "li" || s === "table") {
256
+ o(), t.push(...f(c, e + 1));
257
+ continue;
258
+ }
259
+ n.push(...l(`<${a}>${c}</${s}>`, [], e + 1));
260
+ }
261
+ return o(), t;
262
+ }
263
+ function m(i) {
264
+ return i.split(/\n\s*\n/).map((e) => e.trim()).filter(Boolean).map((e) => ({
265
+ content: [{ text: e.replace(/\s*\n\s*/g, " "), type: "text" }],
266
+ type: "paragraph"
267
+ }));
268
+ }
269
+ function E(i) {
270
+ const e = (typeof i == "string" ? i : "").trim().replace(/^```(?:html|xml)?\s*\n?/i, "").replace(/\n?```$/, "").trim();
271
+ if (!e)
272
+ return null;
273
+ const t = [...h].reduce(
274
+ (r, a) => r.replace(new RegExp(`<${a}\\b[\\s\\S]*?</${a}\\s*>`, "gi"), " "),
275
+ e
276
+ ).trim();
277
+ if (!t)
278
+ return null;
279
+ const o = /<[a-zA-Z!/]/.test(t) ? f(t, 0) : m(t);
280
+ if (o.length === 0) {
281
+ const r = m(
282
+ u(t.replace(/<[^>]*>/g, " ")).replace(/[ \t]+/g, " ")
283
+ );
284
+ return r.length > 0 ? { content: r, type: "doc" } : null;
285
+ }
286
+ return { content: o, type: "doc" };
287
+ }
288
+ export {
289
+ E as editorDocumentFromHtml
290
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextblock-cms/cortex",
3
- "version": "0.13.3",
3
+ "version": "0.13.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -27,9 +27,9 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@ai-sdk/openai-compatible": "^2.0.42",
30
- "@nextblock-cms/db": "^0.13.3",
31
- "@nextblock-cms/ecommerce": "npm:@nextblock-cms/ecom@^0.13.3",
32
- "@nextblock-cms/utils": "^0.13.3",
30
+ "@nextblock-cms/db": "^0.13.6",
31
+ "@nextblock-cms/ecommerce": "npm:@nextblock-cms/ecom@^0.13.6",
32
+ "@nextblock-cms/utils": "^0.13.6",
33
33
  "ai": "^6.0.170",
34
34
  "zod": "^4.3.6"
35
35
  },