@artinstack/migrator 0.1.3 → 0.1.5
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/README.md +11 -0
- package/dist/bundle-uAAHehbv.d.ts +23 -0
- package/dist/chunk-CIOYDRY5.js +851 -0
- package/dist/chunk-CIOYDRY5.js.map +1 -0
- package/dist/chunk-S7TRWILI.js +71 -0
- package/dist/chunk-S7TRWILI.js.map +1 -0
- package/dist/{chunk-QEXTXHFG.js → chunk-XUBCG3IA.js} +221 -41
- package/dist/{chunk-QEXTXHFG.js.map → chunk-XUBCG3IA.js.map} +1 -1
- package/dist/{chunk-HH7666MQ.js → chunk-YLFVYPB3.js} +207 -75
- package/dist/chunk-YLFVYPB3.js.map +1 -0
- package/dist/cli/index.js +42 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +8 -87
- package/dist/index.js +23 -351
- package/dist/index.js.map +1 -1
- package/dist/normalizer/index.d.ts +4 -2
- package/dist/rewrite-inline-images-BckVKPbh.d.ts +21 -0
- package/dist/sinks/index.d.ts +262 -3
- package/dist/sinks/index.js +4 -2
- package/dist/transformers/index.d.ts +157 -0
- package/dist/transformers/index.js +32 -0
- package/dist/transformers/index.js.map +1 -0
- package/dist/{bundle-DfM_jKbq.d.ts → types-DWOP8Dcy.d.ts} +1 -21
- package/package.json +5 -1
- package/dist/chunk-HH7666MQ.js.map +0 -1
- package/dist/index-D88mjcF5.d.ts +0 -279
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
squarespaceAdapter,
|
|
16
16
|
wixAdapter,
|
|
17
17
|
wordpressAdapter
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-XUBCG3IA.js";
|
|
19
19
|
import {
|
|
20
20
|
normalizedAssetExifSchema,
|
|
21
21
|
normalizedAssetSchema,
|
|
@@ -53,13 +53,12 @@ import {
|
|
|
53
53
|
hasWarnings,
|
|
54
54
|
mapJsonPrettyWire,
|
|
55
55
|
portfolioMediaMatchesBundle,
|
|
56
|
-
rewriteInlineImages,
|
|
57
56
|
runDryRun,
|
|
58
57
|
runMigration,
|
|
59
58
|
runMigrationFromBundle,
|
|
60
59
|
staleUrlsFromEstimate,
|
|
61
60
|
writeFilesystemExport
|
|
62
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-YLFVYPB3.js";
|
|
63
62
|
import {
|
|
64
63
|
buildPortfolioMediaLinks,
|
|
65
64
|
bundleCounts,
|
|
@@ -69,6 +68,22 @@ import {
|
|
|
69
68
|
isTerminalState,
|
|
70
69
|
shouldProcessEntity
|
|
71
70
|
} from "./chunk-HI7JHWZU.js";
|
|
71
|
+
import {
|
|
72
|
+
cssToStyles,
|
|
73
|
+
grapesComponentSchema,
|
|
74
|
+
grapesProjectSnapshotSchema,
|
|
75
|
+
grapesStyleRuleSchema,
|
|
76
|
+
htmlToGrapes,
|
|
77
|
+
htmlToTiptap,
|
|
78
|
+
tiptapDocSchema,
|
|
79
|
+
tiptapMarkSchema,
|
|
80
|
+
tiptapNodeSchema,
|
|
81
|
+
validateGrapesProjectSnapshot,
|
|
82
|
+
validateTiptapDoc
|
|
83
|
+
} from "./chunk-CIOYDRY5.js";
|
|
84
|
+
import {
|
|
85
|
+
rewriteInlineImages
|
|
86
|
+
} from "./chunk-S7TRWILI.js";
|
|
72
87
|
import {
|
|
73
88
|
discoverContentAssetUrls,
|
|
74
89
|
discoverRawImgSrcs,
|
|
@@ -76,354 +91,6 @@ import {
|
|
|
76
91
|
isLikelyImageUrl,
|
|
77
92
|
normalizeAssetUrl
|
|
78
93
|
} from "./chunk-2PNSVE5Y.js";
|
|
79
|
-
|
|
80
|
-
// src/transformers/html-to-grapes/index.ts
|
|
81
|
-
import * as cheerio from "cheerio";
|
|
82
|
-
|
|
83
|
-
// src/transformers/css-to-styles/index.ts
|
|
84
|
-
function stripCssComments(css) {
|
|
85
|
-
return css.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
86
|
-
}
|
|
87
|
-
function parseDeclarations(block) {
|
|
88
|
-
const style = {};
|
|
89
|
-
for (const declaration of block.split(";")) {
|
|
90
|
-
const trimmed = declaration.trim();
|
|
91
|
-
if (!trimmed) continue;
|
|
92
|
-
const separator = trimmed.indexOf(":");
|
|
93
|
-
if (separator === -1) continue;
|
|
94
|
-
const property = trimmed.slice(0, separator).trim();
|
|
95
|
-
const value = trimmed.slice(separator + 1).trim();
|
|
96
|
-
if (!property || !value) continue;
|
|
97
|
-
style[property] = value;
|
|
98
|
-
}
|
|
99
|
-
return style;
|
|
100
|
-
}
|
|
101
|
-
function cssToStyles(css) {
|
|
102
|
-
const cleaned = stripCssComments(css);
|
|
103
|
-
const rules = [];
|
|
104
|
-
const rulePattern = /([^{]+)\{([^}]*)\}/g;
|
|
105
|
-
for (const match of cleaned.matchAll(rulePattern)) {
|
|
106
|
-
const selectorText = match[1]?.trim() ?? "";
|
|
107
|
-
const declarationBlock = match[2] ?? "";
|
|
108
|
-
if (!selectorText || selectorText.startsWith("@")) continue;
|
|
109
|
-
const style = parseDeclarations(declarationBlock);
|
|
110
|
-
if (Object.keys(style).length === 0) continue;
|
|
111
|
-
const selectors = selectorText.split(",").map((selector) => selector.trim()).filter(Boolean);
|
|
112
|
-
if (selectors.length === 0) continue;
|
|
113
|
-
rules.push({ selectors, style });
|
|
114
|
-
}
|
|
115
|
-
return rules;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// src/transformers/html-to-grapes/walk.ts
|
|
119
|
-
var INLINE_TAGS = /* @__PURE__ */ new Set([
|
|
120
|
-
"a",
|
|
121
|
-
"abbr",
|
|
122
|
-
"b",
|
|
123
|
-
"br",
|
|
124
|
-
"cite",
|
|
125
|
-
"code",
|
|
126
|
-
"del",
|
|
127
|
-
"em",
|
|
128
|
-
"i",
|
|
129
|
-
"img",
|
|
130
|
-
"ins",
|
|
131
|
-
"mark",
|
|
132
|
-
"q",
|
|
133
|
-
"s",
|
|
134
|
-
"small",
|
|
135
|
-
"span",
|
|
136
|
-
"strong",
|
|
137
|
-
"sub",
|
|
138
|
-
"sup",
|
|
139
|
-
"u",
|
|
140
|
-
"wbr"
|
|
141
|
-
]);
|
|
142
|
-
var VOID_TAGS = /* @__PURE__ */ new Set([
|
|
143
|
-
"area",
|
|
144
|
-
"base",
|
|
145
|
-
"br",
|
|
146
|
-
"col",
|
|
147
|
-
"embed",
|
|
148
|
-
"hr",
|
|
149
|
-
"img",
|
|
150
|
-
"input",
|
|
151
|
-
"link",
|
|
152
|
-
"meta",
|
|
153
|
-
"param",
|
|
154
|
-
"source",
|
|
155
|
-
"track",
|
|
156
|
-
"wbr"
|
|
157
|
-
]);
|
|
158
|
-
var TEXT_CONTAINER_TAGS = /* @__PURE__ */ new Set([
|
|
159
|
-
"blockquote",
|
|
160
|
-
"figcaption",
|
|
161
|
-
"h1",
|
|
162
|
-
"h2",
|
|
163
|
-
"h3",
|
|
164
|
-
"h4",
|
|
165
|
-
"h5",
|
|
166
|
-
"h6",
|
|
167
|
-
"label",
|
|
168
|
-
"li",
|
|
169
|
-
"p",
|
|
170
|
-
"pre",
|
|
171
|
-
"td",
|
|
172
|
-
"th"
|
|
173
|
-
]);
|
|
174
|
-
var SKIP_TAGS = /* @__PURE__ */ new Set(["script", "style", "noscript", "template"]);
|
|
175
|
-
var DEFAULT_TYPES = {
|
|
176
|
-
a: "link",
|
|
177
|
-
img: "image"
|
|
178
|
-
};
|
|
179
|
-
function tagNameOf($el) {
|
|
180
|
-
const raw = $el.prop("tagName");
|
|
181
|
-
return typeof raw === "string" ? raw.toLowerCase() : void 0;
|
|
182
|
-
}
|
|
183
|
-
function applyElementMeta(component, meta) {
|
|
184
|
-
if (meta.attributes) component.attributes = meta.attributes;
|
|
185
|
-
if (meta.classes) component.classes = meta.classes;
|
|
186
|
-
return component;
|
|
187
|
-
}
|
|
188
|
-
function pickElementMeta($el) {
|
|
189
|
-
const attributes = {};
|
|
190
|
-
const classes = [];
|
|
191
|
-
if (typeof $el.attr() === "object") {
|
|
192
|
-
for (const [key, value] of Object.entries($el.attr() ?? {})) {
|
|
193
|
-
if (key === "class") {
|
|
194
|
-
classes.push(...value.split(/\s+/).filter(Boolean));
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
attributes[key] = value;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return {
|
|
201
|
-
attributes: Object.keys(attributes).length > 0 ? attributes : void 0,
|
|
202
|
-
classes: classes.length > 0 ? classes : void 0
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
function resolveComponentType(tagName, classes, options) {
|
|
206
|
-
if (options.componentMap && classes) {
|
|
207
|
-
for (const className of classes) {
|
|
208
|
-
const mapped = options.componentMap[className];
|
|
209
|
-
if (mapped) return mapped;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
return DEFAULT_TYPES[tagName] ?? "default";
|
|
213
|
-
}
|
|
214
|
-
function hasOnlyInlineContent($, $el) {
|
|
215
|
-
let inlineOnly = true;
|
|
216
|
-
$el.contents().each((_, node) => {
|
|
217
|
-
if (!inlineOnly) return;
|
|
218
|
-
const $child = $(node);
|
|
219
|
-
if ($child.get(0)?.type === "text") return;
|
|
220
|
-
const childTag = tagNameOf($child);
|
|
221
|
-
if (!childTag || !INLINE_TAGS.has(childTag)) {
|
|
222
|
-
inlineOnly = false;
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
if (!hasOnlyInlineContent($, $child)) {
|
|
226
|
-
inlineOnly = false;
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
return inlineOnly;
|
|
230
|
-
}
|
|
231
|
-
function walkChildren($, $el, options) {
|
|
232
|
-
const components = [];
|
|
233
|
-
$el.contents().each((_, node) => {
|
|
234
|
-
const walked = walkNode($, $(node), options);
|
|
235
|
-
if (!walked) return;
|
|
236
|
-
if (Array.isArray(walked)) {
|
|
237
|
-
components.push(...walked);
|
|
238
|
-
} else {
|
|
239
|
-
components.push(walked);
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
return components;
|
|
243
|
-
}
|
|
244
|
-
function walkNode($, $el, options) {
|
|
245
|
-
const node = $el.get(0);
|
|
246
|
-
if (!node) return null;
|
|
247
|
-
if (node.type === "text") {
|
|
248
|
-
const text = "data" in node ? String(node.data ?? "") : "";
|
|
249
|
-
if (!text.trim()) return null;
|
|
250
|
-
return { type: "textnode", content: text };
|
|
251
|
-
}
|
|
252
|
-
if (node.type !== "tag") return null;
|
|
253
|
-
const tagName = tagNameOf($el);
|
|
254
|
-
if (!tagName || SKIP_TAGS.has(tagName)) return null;
|
|
255
|
-
const meta = pickElementMeta($el);
|
|
256
|
-
if (VOID_TAGS.has(tagName)) {
|
|
257
|
-
return applyElementMeta(
|
|
258
|
-
{
|
|
259
|
-
type: resolveComponentType(tagName, meta.classes, options),
|
|
260
|
-
tagName,
|
|
261
|
-
void: true
|
|
262
|
-
},
|
|
263
|
-
meta
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
if (TEXT_CONTAINER_TAGS.has(tagName) && hasOnlyInlineContent($, $el)) {
|
|
267
|
-
return applyElementMeta(
|
|
268
|
-
{
|
|
269
|
-
type: "text",
|
|
270
|
-
tagName,
|
|
271
|
-
content: $el.html() ?? ""
|
|
272
|
-
},
|
|
273
|
-
meta
|
|
274
|
-
);
|
|
275
|
-
}
|
|
276
|
-
if (INLINE_TAGS.has(tagName)) {
|
|
277
|
-
return applyElementMeta(
|
|
278
|
-
{
|
|
279
|
-
type: "text",
|
|
280
|
-
content: $.html($el) ?? ""
|
|
281
|
-
},
|
|
282
|
-
meta
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
const components = walkChildren($, $el, options);
|
|
286
|
-
const component = applyElementMeta(
|
|
287
|
-
{
|
|
288
|
-
type: resolveComponentType(tagName, meta.classes, options),
|
|
289
|
-
tagName
|
|
290
|
-
},
|
|
291
|
-
meta
|
|
292
|
-
);
|
|
293
|
-
if (components.length > 0) {
|
|
294
|
-
component.components = components;
|
|
295
|
-
}
|
|
296
|
-
return component;
|
|
297
|
-
}
|
|
298
|
-
function appendWalked(content, walked) {
|
|
299
|
-
if (!walked) return;
|
|
300
|
-
if (Array.isArray(walked)) {
|
|
301
|
-
content.push(...walked);
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
content.push(walked);
|
|
305
|
-
}
|
|
306
|
-
function walkNodes($, $nodes, content, options) {
|
|
307
|
-
$nodes.each((_, node) => {
|
|
308
|
-
appendWalked(content, walkNode($, $(node), options));
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
function walkHtmlToComponents($, options = {}) {
|
|
312
|
-
const content = [];
|
|
313
|
-
const body = $("body");
|
|
314
|
-
if (body.length) {
|
|
315
|
-
walkNodes($, body.contents(), content, options);
|
|
316
|
-
return content;
|
|
317
|
-
}
|
|
318
|
-
const children = $.root().children();
|
|
319
|
-
if (children.length) {
|
|
320
|
-
walkNodes($, children, content, options);
|
|
321
|
-
} else {
|
|
322
|
-
walkNodes($, $.root().contents(), content, options);
|
|
323
|
-
}
|
|
324
|
-
return content;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// src/transformers/html-to-grapes/index.ts
|
|
328
|
-
function htmlToGrapes(html, options = {}) {
|
|
329
|
-
const trimmed = html.trim();
|
|
330
|
-
if (!trimmed) {
|
|
331
|
-
return { content: [], styles: [] };
|
|
332
|
-
}
|
|
333
|
-
const $ = cheerio.load(trimmed, { xml: false });
|
|
334
|
-
const styleBlocks = [];
|
|
335
|
-
$("style").each((_, element) => {
|
|
336
|
-
styleBlocks.push($(element).html() ?? "");
|
|
337
|
-
$(element).remove();
|
|
338
|
-
});
|
|
339
|
-
const contentCss = styleBlocks.join("\n").trim();
|
|
340
|
-
const styles = cssToStyles(contentCss);
|
|
341
|
-
const content = walkHtmlToComponents($, options);
|
|
342
|
-
const contentHtml = serializeContentHtml($);
|
|
343
|
-
return {
|
|
344
|
-
content,
|
|
345
|
-
styles,
|
|
346
|
-
...contentHtml ? { contentHtml } : {},
|
|
347
|
-
...contentCss ? { contentCss } : {}
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
function serializeContentHtml($) {
|
|
351
|
-
const body = $("body");
|
|
352
|
-
if (body.length) {
|
|
353
|
-
const html = body.html()?.trim();
|
|
354
|
-
return html || void 0;
|
|
355
|
-
}
|
|
356
|
-
const rootHtml = $.root().html()?.trim();
|
|
357
|
-
return rootHtml || void 0;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// src/transformers/validate-snapshot.ts
|
|
361
|
-
import { z } from "zod";
|
|
362
|
-
var grapesStyleRuleSchema = z.object({
|
|
363
|
-
selectors: z.array(z.string().min(1)).min(1),
|
|
364
|
-
style: z.record(z.string(), z.string())
|
|
365
|
-
});
|
|
366
|
-
var grapesComponentSchema = z.lazy(
|
|
367
|
-
() => z.object({
|
|
368
|
-
type: z.string().min(1),
|
|
369
|
-
tagName: z.string().optional(),
|
|
370
|
-
attributes: z.record(z.string(), z.string()).optional(),
|
|
371
|
-
classes: z.array(z.string()).optional(),
|
|
372
|
-
components: z.array(grapesComponentSchema).optional(),
|
|
373
|
-
content: z.string().optional(),
|
|
374
|
-
void: z.boolean().optional()
|
|
375
|
-
})
|
|
376
|
-
);
|
|
377
|
-
var grapesProjectSnapshotSchema = z.object({
|
|
378
|
-
content: z.array(grapesComponentSchema),
|
|
379
|
-
styles: z.array(grapesStyleRuleSchema),
|
|
380
|
-
contentHtml: z.string().optional(),
|
|
381
|
-
contentCss: z.string().optional()
|
|
382
|
-
});
|
|
383
|
-
function zodIssuesToValidationIssues(issues) {
|
|
384
|
-
return issues.map((issue) => ({
|
|
385
|
-
code: issue.code,
|
|
386
|
-
message: issue.message,
|
|
387
|
-
path: issue.path.length > 0 ? issue.path.join(".") : void 0
|
|
388
|
-
}));
|
|
389
|
-
}
|
|
390
|
-
function collectComponentTypes(components) {
|
|
391
|
-
const types = [];
|
|
392
|
-
for (const component of components) {
|
|
393
|
-
types.push(component.type);
|
|
394
|
-
if (component.components?.length) {
|
|
395
|
-
types.push(...collectComponentTypes(component.components));
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
return types;
|
|
399
|
-
}
|
|
400
|
-
function validateAllowedComponentTypes(snapshot, allowedComponentTypes) {
|
|
401
|
-
const allowlist = new Set(allowedComponentTypes);
|
|
402
|
-
const issues = [];
|
|
403
|
-
for (const componentType of collectComponentTypes(snapshot.content)) {
|
|
404
|
-
if (!allowlist.has(componentType)) {
|
|
405
|
-
issues.push({
|
|
406
|
-
code: "invalid_component_type",
|
|
407
|
-
message: `Component type "${componentType}" is not in allowedComponentTypes`,
|
|
408
|
-
path: "content"
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
return issues;
|
|
413
|
-
}
|
|
414
|
-
function validateGrapesProjectSnapshot(snapshot, options = {}) {
|
|
415
|
-
const result = grapesProjectSnapshotSchema.safeParse(snapshot);
|
|
416
|
-
if (!result.success) {
|
|
417
|
-
return { ok: false, issues: zodIssuesToValidationIssues(result.error.issues) };
|
|
418
|
-
}
|
|
419
|
-
if (options.allowedComponentTypes?.length) {
|
|
420
|
-
const typeIssues = validateAllowedComponentTypes(result.data, options.allowedComponentTypes);
|
|
421
|
-
if (typeIssues.length > 0) {
|
|
422
|
-
return { ok: false, issues: typeIssues };
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
return { ok: true, issues: [] };
|
|
426
|
-
}
|
|
427
94
|
export {
|
|
428
95
|
FALLBACK_ASSET_BYTES,
|
|
429
96
|
FilesystemMigrationSink,
|
|
@@ -462,6 +129,7 @@ export {
|
|
|
462
129
|
hasBlockingConflicts,
|
|
463
130
|
hasWarnings,
|
|
464
131
|
htmlToGrapes,
|
|
132
|
+
htmlToTiptap,
|
|
465
133
|
isLikelyImageUrl,
|
|
466
134
|
isTerminalState,
|
|
467
135
|
mapJsonPrettyWire,
|
|
@@ -488,6 +156,9 @@ export {
|
|
|
488
156
|
sourceMetadataSchema,
|
|
489
157
|
squarespaceAdapter,
|
|
490
158
|
staleUrlsFromEstimate,
|
|
159
|
+
tiptapDocSchema,
|
|
160
|
+
tiptapMarkSchema,
|
|
161
|
+
tiptapNodeSchema,
|
|
491
162
|
validateGrapesProjectSnapshot,
|
|
492
163
|
validateNormalizedAsset,
|
|
493
164
|
validateNormalizedCategory,
|
|
@@ -496,6 +167,7 @@ export {
|
|
|
496
167
|
validateNormalizedPortfolio,
|
|
497
168
|
validateNormalizedPost,
|
|
498
169
|
validateNormalizedTag,
|
|
170
|
+
validateTiptapDoc,
|
|
499
171
|
wixAdapter,
|
|
500
172
|
wordpressAdapter,
|
|
501
173
|
writeFilesystemExport
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transformers/html-to-grapes/index.ts","../src/transformers/css-to-styles/index.ts","../src/transformers/html-to-grapes/walk.ts","../src/transformers/validate-snapshot.ts"],"sourcesContent":["import * as cheerio from \"cheerio\";\n\nimport { cssToStyles } from \"../css-to-styles/index.js\";\nimport type { GrapesProjectSnapshot, HtmlToGrapesOptions } from \"./types.js\";\nimport { walkHtmlToComponents } from \"./walk.js\";\n\nexport type {\n GrapesComponent,\n GrapesProjectSnapshot,\n GrapesStyleRule,\n HtmlToGrapesOptions,\n} from \"./types.js\";\n\n/** Cheerio HTML walk → Grapes `content` + root `styles`. */\nexport function htmlToGrapes(html: string, options: HtmlToGrapesOptions = {}): GrapesProjectSnapshot {\n const trimmed = html.trim();\n if (!trimmed) {\n return { content: [], styles: [] };\n }\n\n const $ = cheerio.load(trimmed, { xml: false });\n const styleBlocks: string[] = [];\n\n $(\"style\").each((_, element) => {\n styleBlocks.push($(element).html() ?? \"\");\n $(element).remove();\n });\n\n const contentCss = styleBlocks.join(\"\\n\").trim();\n const styles = cssToStyles(contentCss);\n const content = walkHtmlToComponents($, options);\n const contentHtml = serializeContentHtml($);\n\n return {\n content,\n styles,\n ...(contentHtml ? { contentHtml } : {}),\n ...(contentCss ? { contentCss } : {}),\n };\n}\n\nfunction serializeContentHtml($: cheerio.CheerioAPI): string | undefined {\n const body = $(\"body\");\n if (body.length) {\n const html = body.html()?.trim();\n return html || undefined;\n }\n\n const rootHtml = $.root().html()?.trim();\n return rootHtml || undefined;\n}\n","import type { GrapesStyleRule } from \"../html-to-grapes/types.js\";\n\nfunction stripCssComments(css: string): string {\n return css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n}\n\nfunction parseDeclarations(block: string): Record<string, string> {\n const style: Record<string, string> = {};\n for (const declaration of block.split(\";\")) {\n const trimmed = declaration.trim();\n if (!trimmed) continue;\n const separator = trimmed.indexOf(\":\");\n if (separator === -1) continue;\n const property = trimmed.slice(0, separator).trim();\n const value = trimmed.slice(separator + 1).trim();\n if (!property || !value) continue;\n style[property] = value;\n }\n return style;\n}\n\n/** Parse `<style>` blocks and class rules into Grapes root `styles[]`. */\nexport function cssToStyles(css: string): GrapesStyleRule[] {\n const cleaned = stripCssComments(css);\n const rules: GrapesStyleRule[] = [];\n const rulePattern = /([^{]+)\\{([^}]*)\\}/g;\n\n for (const match of cleaned.matchAll(rulePattern)) {\n const selectorText = match[1]?.trim() ?? \"\";\n const declarationBlock = match[2] ?? \"\";\n if (!selectorText || selectorText.startsWith(\"@\")) continue;\n\n const style = parseDeclarations(declarationBlock);\n if (Object.keys(style).length === 0) continue;\n\n const selectors = selectorText\n .split(\",\")\n .map((selector) => selector.trim())\n .filter(Boolean);\n\n if (selectors.length === 0) continue;\n rules.push({ selectors, style });\n }\n\n return rules;\n}\n","import type { Cheerio, CheerioAPI } from \"cheerio\";\nimport type { AnyNode } from \"domhandler\";\n\nimport type { GrapesComponent, HtmlToGrapesOptions } from \"./types.js\";\n\ntype CheerioSelection = Cheerio<AnyNode>;\n\nconst INLINE_TAGS = new Set([\n \"a\",\n \"abbr\",\n \"b\",\n \"br\",\n \"cite\",\n \"code\",\n \"del\",\n \"em\",\n \"i\",\n \"img\",\n \"ins\",\n \"mark\",\n \"q\",\n \"s\",\n \"small\",\n \"span\",\n \"strong\",\n \"sub\",\n \"sup\",\n \"u\",\n \"wbr\",\n]);\n\nconst VOID_TAGS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"param\",\n \"source\",\n \"track\",\n \"wbr\",\n]);\n\nconst TEXT_CONTAINER_TAGS = new Set([\n \"blockquote\",\n \"figcaption\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"label\",\n \"li\",\n \"p\",\n \"pre\",\n \"td\",\n \"th\",\n]);\n\nconst SKIP_TAGS = new Set([\"script\", \"style\", \"noscript\", \"template\"]);\n\nconst DEFAULT_TYPES: Record<string, string> = {\n a: \"link\",\n img: \"image\",\n};\n\nfunction tagNameOf($el: CheerioSelection): string | undefined {\n const raw = $el.prop(\"tagName\");\n return typeof raw === \"string\" ? raw.toLowerCase() : undefined;\n}\n\nfunction applyElementMeta(\n component: GrapesComponent,\n meta: Pick<GrapesComponent, \"attributes\" | \"classes\">,\n): GrapesComponent {\n if (meta.attributes) component.attributes = meta.attributes;\n if (meta.classes) component.classes = meta.classes;\n return component;\n}\n\nfunction pickElementMeta($el: CheerioSelection): Pick<GrapesComponent, \"attributes\" | \"classes\"> {\n const attributes: Record<string, string> = {};\n const classes: string[] = [];\n\n if (typeof $el.attr() === \"object\") {\n for (const [key, value] of Object.entries($el.attr() ?? {})) {\n if (key === \"class\") {\n classes.push(...value.split(/\\s+/).filter(Boolean));\n continue;\n }\n attributes[key] = value;\n }\n }\n\n return {\n attributes: Object.keys(attributes).length > 0 ? attributes : undefined,\n classes: classes.length > 0 ? classes : undefined,\n };\n}\n\nfunction resolveComponentType(\n tagName: string,\n classes: string[] | undefined,\n options: HtmlToGrapesOptions,\n): string {\n if (options.componentMap && classes) {\n for (const className of classes) {\n const mapped = options.componentMap[className];\n if (mapped) return mapped;\n }\n }\n return DEFAULT_TYPES[tagName] ?? \"default\";\n}\n\nfunction hasOnlyInlineContent($: CheerioAPI, $el: CheerioSelection): boolean {\n let inlineOnly = true;\n\n $el.contents().each((_, node) => {\n if (!inlineOnly) return;\n const $child = $(node);\n if ($child.get(0)?.type === \"text\") return;\n const childTag = tagNameOf($child);\n if (!childTag || !INLINE_TAGS.has(childTag)) {\n inlineOnly = false;\n return;\n }\n if (!hasOnlyInlineContent($, $child)) {\n inlineOnly = false;\n }\n });\n\n return inlineOnly;\n}\n\nfunction walkChildren(\n $: CheerioAPI,\n $el: CheerioSelection,\n options: HtmlToGrapesOptions,\n): GrapesComponent[] {\n const components: GrapesComponent[] = [];\n\n $el.contents().each((_, node) => {\n const walked = walkNode($, $(node), options);\n if (!walked) return;\n if (Array.isArray(walked)) {\n components.push(...walked);\n } else {\n components.push(walked);\n }\n });\n\n return components;\n}\n\nfunction walkNode(\n $: CheerioAPI,\n $el: CheerioSelection,\n options: HtmlToGrapesOptions,\n): GrapesComponent | GrapesComponent[] | null {\n const node = $el.get(0);\n if (!node) return null;\n\n if (node.type === \"text\") {\n const text = \"data\" in node ? String(node.data ?? \"\") : \"\";\n if (!text.trim()) return null;\n return { type: \"textnode\", content: text };\n }\n\n if (node.type !== \"tag\") return null;\n\n const tagName = tagNameOf($el);\n if (!tagName || SKIP_TAGS.has(tagName)) return null;\n\n const meta = pickElementMeta($el);\n\n if (VOID_TAGS.has(tagName)) {\n return applyElementMeta(\n {\n type: resolveComponentType(tagName, meta.classes, options),\n tagName,\n void: true,\n },\n meta,\n );\n }\n\n if (TEXT_CONTAINER_TAGS.has(tagName) && hasOnlyInlineContent($, $el)) {\n return applyElementMeta(\n {\n type: \"text\",\n tagName,\n content: $el.html() ?? \"\",\n },\n meta,\n );\n }\n\n if (INLINE_TAGS.has(tagName)) {\n return applyElementMeta(\n {\n type: \"text\",\n content: $.html($el) ?? \"\",\n },\n meta,\n );\n }\n\n const components = walkChildren($, $el, options);\n const component = applyElementMeta(\n {\n type: resolveComponentType(tagName, meta.classes, options),\n tagName,\n },\n meta,\n );\n\n if (components.length > 0) {\n component.components = components;\n }\n\n return component;\n}\n\nfunction appendWalked(\n content: GrapesComponent[],\n walked: GrapesComponent | GrapesComponent[] | null,\n): void {\n if (!walked) return;\n if (Array.isArray(walked)) {\n content.push(...walked);\n return;\n }\n content.push(walked);\n}\n\nfunction walkNodes(\n $: CheerioAPI,\n $nodes: CheerioSelection,\n content: GrapesComponent[],\n options: HtmlToGrapesOptions,\n): void {\n $nodes.each((_, node) => {\n appendWalked(content, walkNode($, $(node), options));\n });\n}\n\nexport function walkHtmlToComponents(\n $: CheerioAPI,\n options: HtmlToGrapesOptions = {},\n): GrapesComponent[] {\n const content: GrapesComponent[] = [];\n const body = $(\"body\");\n\n if (body.length) {\n walkNodes($, body.contents(), content, options);\n return content;\n }\n\n const children = $.root().children();\n if (children.length) {\n walkNodes($, children, content, options);\n } else {\n walkNodes($, $.root().contents(), content, options);\n }\n\n return content;\n}\n","import { z } from \"zod\";\n\nimport type { ValidationIssue, ValidationResult } from \"../normalizer/types.js\";\nimport type { GrapesComponent, GrapesProjectSnapshot } from \"./html-to-grapes/types.js\";\n\nexport const grapesStyleRuleSchema = z.object({\n selectors: z.array(z.string().min(1)).min(1),\n style: z.record(z.string(), z.string()),\n});\n\nexport const grapesComponentSchema: z.ZodType<GrapesComponent> = z.lazy(() =>\n z.object({\n type: z.string().min(1),\n tagName: z.string().optional(),\n attributes: z.record(z.string(), z.string()).optional(),\n classes: z.array(z.string()).optional(),\n components: z.array(grapesComponentSchema).optional(),\n content: z.string().optional(),\n void: z.boolean().optional(),\n }),\n);\n\nexport const grapesProjectSnapshotSchema = z.object({\n content: z.array(grapesComponentSchema),\n styles: z.array(grapesStyleRuleSchema),\n contentHtml: z.string().optional(),\n contentCss: z.string().optional(),\n});\n\nexport interface ValidateGrapesProjectSnapshotOptions {\n /** When set, every component `type` in the tree must be in this allowlist. */\n allowedComponentTypes?: string[];\n}\n\nfunction zodIssuesToValidationIssues(issues: z.ZodIssue[]): ValidationIssue[] {\n return issues.map((issue) => ({\n code: issue.code,\n message: issue.message,\n path: issue.path.length > 0 ? issue.path.join(\".\") : undefined,\n }));\n}\n\nfunction collectComponentTypes(components: GrapesComponent[]): string[] {\n const types: string[] = [];\n for (const component of components) {\n types.push(component.type);\n if (component.components?.length) {\n types.push(...collectComponentTypes(component.components));\n }\n }\n return types;\n}\n\nfunction validateAllowedComponentTypes(\n snapshot: GrapesProjectSnapshot,\n allowedComponentTypes: string[],\n): ValidationIssue[] {\n const allowlist = new Set(allowedComponentTypes);\n const issues: ValidationIssue[] = [];\n\n for (const componentType of collectComponentTypes(snapshot.content)) {\n if (!allowlist.has(componentType)) {\n issues.push({\n code: \"invalid_component_type\",\n message: `Component type \"${componentType}\" is not in allowedComponentTypes`,\n path: \"content\",\n });\n }\n }\n\n return issues;\n}\n\n/**\n * Opt-in structural check for a Grapes project snapshot (not a full Grapes editor project file).\n * Does not validate host-specific component registries unless `allowedComponentTypes` is passed.\n */\nexport function validateGrapesProjectSnapshot(\n snapshot: unknown,\n options: ValidateGrapesProjectSnapshotOptions = {},\n): ValidationResult {\n const result = grapesProjectSnapshotSchema.safeParse(snapshot);\n if (!result.success) {\n return { ok: false, issues: zodIssuesToValidationIssues(result.error.issues) };\n }\n\n if (options.allowedComponentTypes?.length) {\n const typeIssues = validateAllowedComponentTypes(result.data, options.allowedComponentTypes);\n if (typeIssues.length > 0) {\n return { ok: false, issues: typeIssues };\n }\n }\n\n return { ok: true, issues: [] };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { A as AdapterContext,
|
|
1
|
+
import { i as MigrationCursor, E as EntityKey, P as PortfolioMediaLink, l as ValidationResult } from '../types-DWOP8Dcy.js';
|
|
2
|
+
export { A as AdapterContext, h as EntityType, M as MigrationAdapter, g as MigrationPlatform, b as NormalizedAsset, j as NormalizedAssetExif, d as NormalizedCategory, f as NormalizedEntity, a as NormalizedPage, c as NormalizedPortfolio, N as NormalizedPost, e as NormalizedTag, k as PublishStatus, S as SourceMetadata, V as ValidationIssue, m as entityKey } from '../types-DWOP8Dcy.js';
|
|
3
|
+
import { E as EntityBundle } from '../bundle-uAAHehbv.js';
|
|
4
|
+
export { B as BundleCounts, b as bundleCounts, c as collectEntities, e as emptyBundle } from '../bundle-uAAHehbv.js';
|
|
3
5
|
import { z } from 'zod';
|
|
4
6
|
|
|
5
7
|
/** Portable entity state for resume / idempotency (not Directus field names). */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface RewriteInlineImageRef {
|
|
2
|
+
originalSrc: string;
|
|
3
|
+
sourceAssetId?: string;
|
|
4
|
+
}
|
|
5
|
+
interface UploadedAssetRef {
|
|
6
|
+
targetId: string;
|
|
7
|
+
publicUrl?: string;
|
|
8
|
+
}
|
|
9
|
+
interface RewriteInlineImagesOptions {
|
|
10
|
+
resolveAsset: (src: string) => RewriteInlineImageRef | undefined;
|
|
11
|
+
replaceWith: (ref: RewriteInlineImageRef, uploaded: UploadedAssetRef) => string;
|
|
12
|
+
}
|
|
13
|
+
interface RewriteInlineImagesResult {
|
|
14
|
+
html: string;
|
|
15
|
+
referencedSources: string[];
|
|
16
|
+
unresolved: string[];
|
|
17
|
+
}
|
|
18
|
+
/** Rewrite `<img src>` / `srcset` using uploaded asset targets supplied by the host sink. */
|
|
19
|
+
declare function rewriteInlineImages(html: string, options: RewriteInlineImagesOptions, uploadedBySourceId: Map<string, UploadedAssetRef>): RewriteInlineImagesResult;
|
|
20
|
+
|
|
21
|
+
export { type RewriteInlineImageRef as R, type UploadedAssetRef as U, type RewriteInlineImagesOptions as a, type RewriteInlineImagesResult as b, rewriteInlineImages as r };
|