@artinstack/migrator 0.1.0 → 0.1.2
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 +66 -9
- package/dist/{bundle-BfZqiKV_.d.ts → bundle-DfM_jKbq.d.ts} +2 -2
- package/dist/chunk-2PNSVE5Y.js +67 -0
- package/dist/chunk-2PNSVE5Y.js.map +1 -0
- package/dist/chunk-3YJFSTYR.js +147 -0
- package/dist/chunk-3YJFSTYR.js.map +1 -0
- package/dist/{chunk-LKNIQQJO.js → chunk-HH7666MQ.js} +13 -65
- package/dist/chunk-HH7666MQ.js.map +1 -0
- package/dist/{chunk-JKDRTL24.js → chunk-HI7JHWZU.js} +1 -1
- package/dist/chunk-HI7JHWZU.js.map +1 -0
- package/dist/chunk-VXEHAQKK.js +2290 -0
- package/dist/chunk-VXEHAQKK.js.map +1 -0
- package/dist/cli/index.js +23 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/{index-DQNzrygx.d.ts → index-D88mjcF5.d.ts} +1 -1
- package/dist/index.d.ts +259 -5
- package/dist/index.js +127 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/index.d.ts +16 -0
- package/dist/lib/index.js +15 -0
- package/dist/normalizer/index.d.ts +837 -3
- package/dist/normalizer/index.js +36 -3
- package/dist/sinks/index.d.ts +2 -2
- package/dist/sinks/index.js +3 -2
- package/package.json +5 -1
- package/dist/chunk-2RWAXT6O.js +0 -1
- package/dist/chunk-FXXKLYO5.js +0 -1076
- package/dist/chunk-FXXKLYO5.js.map +0 -1
- package/dist/chunk-JKDRTL24.js.map +0 -1
- package/dist/chunk-LKNIQQJO.js.map +0 -1
- /package/dist/{chunk-2RWAXT6O.js.map → lib/index.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { M as MigrationAdapter, a as MigrationPlatform } from './bundle-
|
|
2
|
-
export { A as AdapterContext, B as BundleCounts, E as EntityBundle, b as EntityKey, c as EntityType, d as MigrationCursor, N as NormalizedAsset, e as NormalizedAssetExif, f as NormalizedCategory, g as NormalizedEntity, h as NormalizedPage, i as NormalizedPortfolio, j as NormalizedPost, k as NormalizedTag, P as PortfolioMediaLink, l as PublishStatus, S as SourceMetadata,
|
|
3
|
-
export { EntityState, MigrationCheckpoint, TrackedEntity, buildPortfolioMediaLinks, isTerminalState, shouldProcessEntity } from './normalizer/index.js';
|
|
4
|
-
export { C as ConflictReport, D as DryRunOptions, a as DryRunResult, F as FALLBACK_ASSET_BYTES, b as FilesystemMigrationSink, M as MIGRATION_WRITE_STAGES, c as MigrationRedirect, d as MigrationReport, e as MigrationRunMode, f as MigrationRunOptions, g as MigrationRunResult, h as MigrationSink, i as MigrationWriteStage, R as RewriteInlineImageRef, j as RewriteInlineImagesOptions, k as RewriteInlineImagesResult, S as StorageEstimate, U as UploadAssetInput, l as UploadAssetResult, m as UploadedAssetRef, W as WriteFilesystemOptions, n as analyzeConflicts, o as buildMigrationReport, p as buildRedirectMap, q as bundleToCombinedJson, r as createFilesystemMigrationSink, s as detectRedirectLoops, t as emptyConflictReport, u as estimateStorage, v as hasBlockingConflicts, w as hasWarnings, x as portfolioMediaMatchesBundle, y as rewriteInlineImages, z as runDryRun, A as runMigration, B as runMigrationFromBundle, E as staleUrlsFromEstimate, G as writeFilesystemExport } from './index-
|
|
1
|
+
import { M as MigrationAdapter, a as MigrationPlatform, V as ValidationResult } from './bundle-DfM_jKbq.js';
|
|
2
|
+
export { A as AdapterContext, B as BundleCounts, E as EntityBundle, b as EntityKey, c as EntityType, d as MigrationCursor, N as NormalizedAsset, e as NormalizedAssetExif, f as NormalizedCategory, g as NormalizedEntity, h as NormalizedPage, i as NormalizedPortfolio, j as NormalizedPost, k as NormalizedTag, P as PortfolioMediaLink, l as PublishStatus, S as SourceMetadata, m as ValidationIssue, n as bundleCounts, o as collectEntities, p as emptyBundle, q as entityKey } from './bundle-DfM_jKbq.js';
|
|
3
|
+
export { EntityState, MigrationCheckpoint, TrackedEntity, buildPortfolioMediaLinks, isTerminalState, normalizedAssetExifSchema, normalizedAssetSchema, normalizedCategorySchema, normalizedEntitySchema, normalizedPageSchema, normalizedPortfolioSchema, normalizedPostSchema, normalizedTagSchema, shouldProcessEntity, sourceMetadataSchema, validateNormalizedAsset, validateNormalizedCategory, validateNormalizedEntity, validateNormalizedPage, validateNormalizedPortfolio, validateNormalizedPost, validateNormalizedTag } from './normalizer/index.js';
|
|
4
|
+
export { C as ConflictReport, D as DryRunOptions, a as DryRunResult, F as FALLBACK_ASSET_BYTES, b as FilesystemMigrationSink, M as MIGRATION_WRITE_STAGES, c as MigrationRedirect, d as MigrationReport, e as MigrationRunMode, f as MigrationRunOptions, g as MigrationRunResult, h as MigrationSink, i as MigrationWriteStage, R as RewriteInlineImageRef, j as RewriteInlineImagesOptions, k as RewriteInlineImagesResult, S as StorageEstimate, U as UploadAssetInput, l as UploadAssetResult, m as UploadedAssetRef, W as WriteFilesystemOptions, n as analyzeConflicts, o as buildMigrationReport, p as buildRedirectMap, q as bundleToCombinedJson, r as createFilesystemMigrationSink, s as detectRedirectLoops, t as emptyConflictReport, u as estimateStorage, v as hasBlockingConflicts, w as hasWarnings, x as portfolioMediaMatchesBundle, y as rewriteInlineImages, z as runDryRun, A as runMigration, B as runMigrationFromBundle, E as staleUrlsFromEstimate, G as writeFilesystemExport } from './index-D88mjcF5.js';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
+
export { discoverContentAssetUrls, discoverRawImgSrcs, extractInlineImageSrcs, isLikelyImageUrl, normalizeAssetUrl } from './lib/index.js';
|
|
6
7
|
import 'node:stream';
|
|
7
8
|
|
|
8
9
|
declare const wordpressAdapter: MigrationAdapter;
|
|
@@ -301,6 +302,207 @@ declare class SquarespaceCollectionClient {
|
|
|
301
302
|
|
|
302
303
|
declare const squarespaceAdapter: MigrationAdapter;
|
|
303
304
|
|
|
305
|
+
interface WixPost {
|
|
306
|
+
id: string;
|
|
307
|
+
title: string;
|
|
308
|
+
slug: string;
|
|
309
|
+
url?: string;
|
|
310
|
+
excerpt?: string;
|
|
311
|
+
contentHtml: string;
|
|
312
|
+
publishedAt?: string;
|
|
313
|
+
status?: "draft" | "published" | "archived";
|
|
314
|
+
categorySlugs?: string[];
|
|
315
|
+
tagSlugs?: string[];
|
|
316
|
+
featuredImageUrl?: string;
|
|
317
|
+
seoTitle?: string;
|
|
318
|
+
seoDescription?: string;
|
|
319
|
+
}
|
|
320
|
+
interface WixPage {
|
|
321
|
+
id: string;
|
|
322
|
+
title: string;
|
|
323
|
+
slug: string;
|
|
324
|
+
url?: string;
|
|
325
|
+
contentHtml: string;
|
|
326
|
+
isHomePage?: boolean;
|
|
327
|
+
status?: "draft" | "published" | "archived";
|
|
328
|
+
seoTitle?: string;
|
|
329
|
+
seoDescription?: string;
|
|
330
|
+
}
|
|
331
|
+
interface WixCategory {
|
|
332
|
+
id: string;
|
|
333
|
+
name: string;
|
|
334
|
+
slug: string;
|
|
335
|
+
}
|
|
336
|
+
interface WixTag {
|
|
337
|
+
id: string;
|
|
338
|
+
name: string;
|
|
339
|
+
slug: string;
|
|
340
|
+
}
|
|
341
|
+
/** Canonical collected document shared by W0 JSON fixtures, W1 API, and W2 snapshots. */
|
|
342
|
+
interface WixExport {
|
|
343
|
+
exportVersion: 1;
|
|
344
|
+
exportedAt?: string;
|
|
345
|
+
site?: {
|
|
346
|
+
url?: string;
|
|
347
|
+
siteId?: string;
|
|
348
|
+
title?: string;
|
|
349
|
+
};
|
|
350
|
+
posts?: WixPost[];
|
|
351
|
+
pages?: WixPage[];
|
|
352
|
+
categories?: WixCategory[];
|
|
353
|
+
tags?: WixTag[];
|
|
354
|
+
}
|
|
355
|
+
interface WixSnapshotTarget {
|
|
356
|
+
url: string;
|
|
357
|
+
isHomePage?: boolean;
|
|
358
|
+
title?: string;
|
|
359
|
+
slug?: string;
|
|
360
|
+
/** Offline/test hook — use fixture HTML instead of fetching `url`. */
|
|
361
|
+
html?: string;
|
|
362
|
+
}
|
|
363
|
+
interface WixSnapshotGap {
|
|
364
|
+
url: string;
|
|
365
|
+
code: "empty_extract" | "login_wall" | "fetch_failed";
|
|
366
|
+
message: string;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
declare const wixAuthContextSchema: z.ZodObject<{
|
|
370
|
+
/** Full Authorization header value (API key or Bearer token). */
|
|
371
|
+
authorization: z.ZodString;
|
|
372
|
+
siteId: z.ZodString;
|
|
373
|
+
accountId: z.ZodOptional<z.ZodString>;
|
|
374
|
+
extraHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
375
|
+
}, "strip", z.ZodTypeAny, {
|
|
376
|
+
authorization: string;
|
|
377
|
+
siteId: string;
|
|
378
|
+
accountId?: string | undefined;
|
|
379
|
+
extraHeaders?: Record<string, string> | undefined;
|
|
380
|
+
}, {
|
|
381
|
+
authorization: string;
|
|
382
|
+
siteId: string;
|
|
383
|
+
accountId?: string | undefined;
|
|
384
|
+
extraHeaders?: Record<string, string> | undefined;
|
|
385
|
+
}>;
|
|
386
|
+
type WixAuthContext = z.infer<typeof wixAuthContextSchema>;
|
|
387
|
+
declare const wixClientOptionsSchema: z.ZodObject<{
|
|
388
|
+
auth: z.ZodObject<{
|
|
389
|
+
/** Full Authorization header value (API key or Bearer token). */
|
|
390
|
+
authorization: z.ZodString;
|
|
391
|
+
siteId: z.ZodString;
|
|
392
|
+
accountId: z.ZodOptional<z.ZodString>;
|
|
393
|
+
extraHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
394
|
+
}, "strip", z.ZodTypeAny, {
|
|
395
|
+
authorization: string;
|
|
396
|
+
siteId: string;
|
|
397
|
+
accountId?: string | undefined;
|
|
398
|
+
extraHeaders?: Record<string, string> | undefined;
|
|
399
|
+
}, {
|
|
400
|
+
authorization: string;
|
|
401
|
+
siteId: string;
|
|
402
|
+
accountId?: string | undefined;
|
|
403
|
+
extraHeaders?: Record<string, string> | undefined;
|
|
404
|
+
}>;
|
|
405
|
+
pageSize: z.ZodDefault<z.ZodNumber>;
|
|
406
|
+
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
407
|
+
retryBaseDelayMs: z.ZodDefault<z.ZodNumber>;
|
|
408
|
+
maxRetryDelayMs: z.ZodDefault<z.ZodNumber>;
|
|
409
|
+
requestIntervalMs: z.ZodDefault<z.ZodNumber>;
|
|
410
|
+
fetchImpl: z.ZodOptional<z.ZodType<typeof fetch, z.ZodTypeDef, typeof fetch>>;
|
|
411
|
+
/** Include draft posts when the API key has permission. */
|
|
412
|
+
includeDrafts: z.ZodDefault<z.ZodBoolean>;
|
|
413
|
+
}, "strip", z.ZodTypeAny, {
|
|
414
|
+
maxRetries: number;
|
|
415
|
+
retryBaseDelayMs: number;
|
|
416
|
+
maxRetryDelayMs: number;
|
|
417
|
+
requestIntervalMs: number;
|
|
418
|
+
pageSize: number;
|
|
419
|
+
auth: {
|
|
420
|
+
authorization: string;
|
|
421
|
+
siteId: string;
|
|
422
|
+
accountId?: string | undefined;
|
|
423
|
+
extraHeaders?: Record<string, string> | undefined;
|
|
424
|
+
};
|
|
425
|
+
includeDrafts: boolean;
|
|
426
|
+
fetchImpl?: typeof fetch | undefined;
|
|
427
|
+
}, {
|
|
428
|
+
auth: {
|
|
429
|
+
authorization: string;
|
|
430
|
+
siteId: string;
|
|
431
|
+
accountId?: string | undefined;
|
|
432
|
+
extraHeaders?: Record<string, string> | undefined;
|
|
433
|
+
};
|
|
434
|
+
maxRetries?: number | undefined;
|
|
435
|
+
retryBaseDelayMs?: number | undefined;
|
|
436
|
+
maxRetryDelayMs?: number | undefined;
|
|
437
|
+
requestIntervalMs?: number | undefined;
|
|
438
|
+
fetchImpl?: typeof fetch | undefined;
|
|
439
|
+
pageSize?: number | undefined;
|
|
440
|
+
includeDrafts?: boolean | undefined;
|
|
441
|
+
}>;
|
|
442
|
+
type WixClientOptions = z.input<typeof wixClientOptionsSchema>;
|
|
443
|
+
/** Fetch blog posts, categories, and tags via injected `fetch` + vault auth headers. */
|
|
444
|
+
declare class WixCollectionClient {
|
|
445
|
+
readonly auth: WixAuthContext;
|
|
446
|
+
readonly pageSize: number;
|
|
447
|
+
readonly maxRetries: number;
|
|
448
|
+
readonly retryBaseDelayMs: number;
|
|
449
|
+
readonly maxRetryDelayMs: number;
|
|
450
|
+
readonly requestIntervalMs: number;
|
|
451
|
+
readonly fetchImpl: typeof fetch;
|
|
452
|
+
readonly includeDrafts: boolean;
|
|
453
|
+
private lastRequestAt;
|
|
454
|
+
constructor(options: WixClientOptions);
|
|
455
|
+
buildUrl(path: string, query?: Record<string, string | number | undefined>): string;
|
|
456
|
+
fetchJson<T = unknown>(path: string, query?: Record<string, string | number | undefined>): Promise<T>;
|
|
457
|
+
listAllCategories(): Promise<WixCategory[]>;
|
|
458
|
+
listAllTags(): Promise<WixTag[]>;
|
|
459
|
+
listAllPosts(lookup: {
|
|
460
|
+
categorySlugsById: Map<string, string>;
|
|
461
|
+
tagSlugsById: Map<string, string>;
|
|
462
|
+
}): Promise<WixPost[]>;
|
|
463
|
+
private listDraftPosts;
|
|
464
|
+
collectExport(): Promise<WixExport>;
|
|
465
|
+
private buildHeaders;
|
|
466
|
+
private requestWithRetry;
|
|
467
|
+
private throttle;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
declare const wixSnapshotClientOptionsSchema: z.ZodObject<{
|
|
471
|
+
fetchImpl: z.ZodOptional<z.ZodType<typeof fetch, z.ZodTypeDef, typeof fetch>>;
|
|
472
|
+
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
473
|
+
retryBaseDelayMs: z.ZodDefault<z.ZodNumber>;
|
|
474
|
+
requestIntervalMs: z.ZodDefault<z.ZodNumber>;
|
|
475
|
+
}, "strip", z.ZodTypeAny, {
|
|
476
|
+
maxRetries: number;
|
|
477
|
+
retryBaseDelayMs: number;
|
|
478
|
+
requestIntervalMs: number;
|
|
479
|
+
fetchImpl?: typeof fetch | undefined;
|
|
480
|
+
}, {
|
|
481
|
+
maxRetries?: number | undefined;
|
|
482
|
+
retryBaseDelayMs?: number | undefined;
|
|
483
|
+
requestIntervalMs?: number | undefined;
|
|
484
|
+
fetchImpl?: typeof fetch | undefined;
|
|
485
|
+
}>;
|
|
486
|
+
type WixSnapshotClientOptions = z.input<typeof wixSnapshotClientOptionsSchema>;
|
|
487
|
+
interface WixSnapshotResult {
|
|
488
|
+
pages: WixPage[];
|
|
489
|
+
gaps: WixSnapshotGap[];
|
|
490
|
+
}
|
|
491
|
+
declare class WixPageSnapshotCollector {
|
|
492
|
+
readonly fetchImpl: typeof fetch;
|
|
493
|
+
readonly maxRetries: number;
|
|
494
|
+
readonly retryBaseDelayMs: number;
|
|
495
|
+
readonly requestIntervalMs: number;
|
|
496
|
+
private lastRequestAt;
|
|
497
|
+
constructor(options?: WixSnapshotClientOptions);
|
|
498
|
+
collectPages(targets: WixSnapshotTarget[]): Promise<WixSnapshotResult>;
|
|
499
|
+
collectFromUrlList(urls: string[]): Promise<WixSnapshotResult>;
|
|
500
|
+
private fetchHtml;
|
|
501
|
+
private throttle;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
declare const wixAdapter: MigrationAdapter;
|
|
505
|
+
|
|
304
506
|
declare function getAdapter(platform: MigrationPlatform): MigrationAdapter;
|
|
305
507
|
|
|
306
508
|
interface HtmlToGrapesOptions {
|
|
@@ -333,4 +535,56 @@ declare function htmlToGrapes(html: string, options?: HtmlToGrapesOptions): Grap
|
|
|
333
535
|
/** Parse `<style>` blocks and class rules into Grapes root `styles[]`. */
|
|
334
536
|
declare function cssToStyles(css: string): GrapesStyleRule[];
|
|
335
537
|
|
|
336
|
-
|
|
538
|
+
declare const grapesStyleRuleSchema: z.ZodObject<{
|
|
539
|
+
selectors: z.ZodArray<z.ZodString, "many">;
|
|
540
|
+
style: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
541
|
+
}, "strip", z.ZodTypeAny, {
|
|
542
|
+
style: Record<string, string>;
|
|
543
|
+
selectors: string[];
|
|
544
|
+
}, {
|
|
545
|
+
style: Record<string, string>;
|
|
546
|
+
selectors: string[];
|
|
547
|
+
}>;
|
|
548
|
+
declare const grapesComponentSchema: z.ZodType<GrapesComponent>;
|
|
549
|
+
declare const grapesProjectSnapshotSchema: z.ZodObject<{
|
|
550
|
+
content: z.ZodArray<z.ZodType<GrapesComponent, z.ZodTypeDef, GrapesComponent>, "many">;
|
|
551
|
+
styles: z.ZodArray<z.ZodObject<{
|
|
552
|
+
selectors: z.ZodArray<z.ZodString, "many">;
|
|
553
|
+
style: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
554
|
+
}, "strip", z.ZodTypeAny, {
|
|
555
|
+
style: Record<string, string>;
|
|
556
|
+
selectors: string[];
|
|
557
|
+
}, {
|
|
558
|
+
style: Record<string, string>;
|
|
559
|
+
selectors: string[];
|
|
560
|
+
}>, "many">;
|
|
561
|
+
contentHtml: z.ZodOptional<z.ZodString>;
|
|
562
|
+
contentCss: z.ZodOptional<z.ZodString>;
|
|
563
|
+
}, "strip", z.ZodTypeAny, {
|
|
564
|
+
content: GrapesComponent[];
|
|
565
|
+
styles: {
|
|
566
|
+
style: Record<string, string>;
|
|
567
|
+
selectors: string[];
|
|
568
|
+
}[];
|
|
569
|
+
contentHtml?: string | undefined;
|
|
570
|
+
contentCss?: string | undefined;
|
|
571
|
+
}, {
|
|
572
|
+
content: GrapesComponent[];
|
|
573
|
+
styles: {
|
|
574
|
+
style: Record<string, string>;
|
|
575
|
+
selectors: string[];
|
|
576
|
+
}[];
|
|
577
|
+
contentHtml?: string | undefined;
|
|
578
|
+
contentCss?: string | undefined;
|
|
579
|
+
}>;
|
|
580
|
+
interface ValidateGrapesProjectSnapshotOptions {
|
|
581
|
+
/** When set, every component `type` in the tree must be in this allowlist. */
|
|
582
|
+
allowedComponentTypes?: string[];
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Opt-in structural check for a Grapes project snapshot (not a full Grapes editor project file).
|
|
586
|
+
* Does not validate host-specific component registries unless `allowedComponentTypes` is passed.
|
|
587
|
+
*/
|
|
588
|
+
declare function validateGrapesProjectSnapshot(snapshot: unknown, options?: ValidateGrapesProjectSnapshotOptions): ValidationResult;
|
|
589
|
+
|
|
590
|
+
export { type GrapesComponent, type GrapesProjectSnapshot, type GrapesStyleRule, type HtmlToGrapesOptions, MigrationAdapter, MigrationPlatform, SMUGMUG_API_BASE, SMUGMUG_OAUTH_ENDPOINTS, SQUARESPACE_JSON_FORMAT, SmugMugApiClient, type SmugMugClientOptions, type SmugMugCredentials, type SquarespaceClientOptions, type SquarespaceCollectTarget, SquarespaceCollectionClient, type ValidateGrapesProjectSnapshotOptions, ValidationResult, WixCollectionClient, WixPageSnapshotCollector, buildJsonPrettyUrl, buildSmugMugAuthorizationHeader, cssToStyles, getAdapter, grapesComponentSchema, grapesProjectSnapshotSchema, grapesStyleRuleSchema, htmlToGrapes, mapJsonPrettyWire, readSmugMugCredentialsFromEnv, signSmugMugOAuthRequest, smugMugCredentialsSchema, smugmugAdapter, squarespaceAdapter, validateGrapesProjectSnapshot, wixAdapter, wordpressAdapter };
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,8 @@ import {
|
|
|
2
2
|
SMUGMUG_API_BASE,
|
|
3
3
|
SMUGMUG_OAUTH_ENDPOINTS,
|
|
4
4
|
SmugMugApiClient,
|
|
5
|
+
WixCollectionClient,
|
|
6
|
+
WixPageSnapshotCollector,
|
|
5
7
|
buildSmugMugAuthorizationHeader,
|
|
6
8
|
getAdapter,
|
|
7
9
|
readSmugMugCredentialsFromEnv,
|
|
@@ -9,9 +11,27 @@ import {
|
|
|
9
11
|
smugMugCredentialsSchema,
|
|
10
12
|
smugmugAdapter,
|
|
11
13
|
squarespaceAdapter,
|
|
14
|
+
wixAdapter,
|
|
12
15
|
wordpressAdapter
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import
|
|
16
|
+
} from "./chunk-VXEHAQKK.js";
|
|
17
|
+
import {
|
|
18
|
+
normalizedAssetExifSchema,
|
|
19
|
+
normalizedAssetSchema,
|
|
20
|
+
normalizedCategorySchema,
|
|
21
|
+
normalizedEntitySchema,
|
|
22
|
+
normalizedPageSchema,
|
|
23
|
+
normalizedPortfolioSchema,
|
|
24
|
+
normalizedPostSchema,
|
|
25
|
+
normalizedTagSchema,
|
|
26
|
+
sourceMetadataSchema,
|
|
27
|
+
validateNormalizedAsset,
|
|
28
|
+
validateNormalizedCategory,
|
|
29
|
+
validateNormalizedEntity,
|
|
30
|
+
validateNormalizedPage,
|
|
31
|
+
validateNormalizedPortfolio,
|
|
32
|
+
validateNormalizedPost,
|
|
33
|
+
validateNormalizedTag
|
|
34
|
+
} from "./chunk-3YJFSTYR.js";
|
|
15
35
|
import {
|
|
16
36
|
FALLBACK_ASSET_BYTES,
|
|
17
37
|
FilesystemMigrationSink,
|
|
@@ -37,7 +57,7 @@ import {
|
|
|
37
57
|
runMigrationFromBundle,
|
|
38
58
|
staleUrlsFromEstimate,
|
|
39
59
|
writeFilesystemExport
|
|
40
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-HH7666MQ.js";
|
|
41
61
|
import {
|
|
42
62
|
buildPortfolioMediaLinks,
|
|
43
63
|
bundleCounts,
|
|
@@ -46,7 +66,14 @@ import {
|
|
|
46
66
|
entityKey,
|
|
47
67
|
isTerminalState,
|
|
48
68
|
shouldProcessEntity
|
|
49
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-HI7JHWZU.js";
|
|
70
|
+
import {
|
|
71
|
+
discoverContentAssetUrls,
|
|
72
|
+
discoverRawImgSrcs,
|
|
73
|
+
extractInlineImageSrcs,
|
|
74
|
+
isLikelyImageUrl,
|
|
75
|
+
normalizeAssetUrl
|
|
76
|
+
} from "./chunk-2PNSVE5Y.js";
|
|
50
77
|
|
|
51
78
|
// src/transformers/html-to-grapes/index.ts
|
|
52
79
|
import * as cheerio from "cheerio";
|
|
@@ -327,6 +354,74 @@ function serializeContentHtml($) {
|
|
|
327
354
|
const rootHtml = $.root().html()?.trim();
|
|
328
355
|
return rootHtml || void 0;
|
|
329
356
|
}
|
|
357
|
+
|
|
358
|
+
// src/transformers/validate-snapshot.ts
|
|
359
|
+
import { z } from "zod";
|
|
360
|
+
var grapesStyleRuleSchema = z.object({
|
|
361
|
+
selectors: z.array(z.string().min(1)).min(1),
|
|
362
|
+
style: z.record(z.string(), z.string())
|
|
363
|
+
});
|
|
364
|
+
var grapesComponentSchema = z.lazy(
|
|
365
|
+
() => z.object({
|
|
366
|
+
type: z.string().min(1),
|
|
367
|
+
tagName: z.string().optional(),
|
|
368
|
+
attributes: z.record(z.string(), z.string()).optional(),
|
|
369
|
+
classes: z.array(z.string()).optional(),
|
|
370
|
+
components: z.array(grapesComponentSchema).optional(),
|
|
371
|
+
content: z.string().optional(),
|
|
372
|
+
void: z.boolean().optional()
|
|
373
|
+
})
|
|
374
|
+
);
|
|
375
|
+
var grapesProjectSnapshotSchema = z.object({
|
|
376
|
+
content: z.array(grapesComponentSchema),
|
|
377
|
+
styles: z.array(grapesStyleRuleSchema),
|
|
378
|
+
contentHtml: z.string().optional(),
|
|
379
|
+
contentCss: z.string().optional()
|
|
380
|
+
});
|
|
381
|
+
function zodIssuesToValidationIssues(issues) {
|
|
382
|
+
return issues.map((issue) => ({
|
|
383
|
+
code: issue.code,
|
|
384
|
+
message: issue.message,
|
|
385
|
+
path: issue.path.length > 0 ? issue.path.join(".") : void 0
|
|
386
|
+
}));
|
|
387
|
+
}
|
|
388
|
+
function collectComponentTypes(components) {
|
|
389
|
+
const types = [];
|
|
390
|
+
for (const component of components) {
|
|
391
|
+
types.push(component.type);
|
|
392
|
+
if (component.components?.length) {
|
|
393
|
+
types.push(...collectComponentTypes(component.components));
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return types;
|
|
397
|
+
}
|
|
398
|
+
function validateAllowedComponentTypes(snapshot, allowedComponentTypes) {
|
|
399
|
+
const allowlist = new Set(allowedComponentTypes);
|
|
400
|
+
const issues = [];
|
|
401
|
+
for (const componentType of collectComponentTypes(snapshot.content)) {
|
|
402
|
+
if (!allowlist.has(componentType)) {
|
|
403
|
+
issues.push({
|
|
404
|
+
code: "invalid_component_type",
|
|
405
|
+
message: `Component type "${componentType}" is not in allowedComponentTypes`,
|
|
406
|
+
path: "content"
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return issues;
|
|
411
|
+
}
|
|
412
|
+
function validateGrapesProjectSnapshot(snapshot, options = {}) {
|
|
413
|
+
const result = grapesProjectSnapshotSchema.safeParse(snapshot);
|
|
414
|
+
if (!result.success) {
|
|
415
|
+
return { ok: false, issues: zodIssuesToValidationIssues(result.error.issues) };
|
|
416
|
+
}
|
|
417
|
+
if (options.allowedComponentTypes?.length) {
|
|
418
|
+
const typeIssues = validateAllowedComponentTypes(result.data, options.allowedComponentTypes);
|
|
419
|
+
if (typeIssues.length > 0) {
|
|
420
|
+
return { ok: false, issues: typeIssues };
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return { ok: true, issues: [] };
|
|
424
|
+
}
|
|
330
425
|
export {
|
|
331
426
|
FALLBACK_ASSET_BYTES,
|
|
332
427
|
FilesystemMigrationSink,
|
|
@@ -336,6 +431,8 @@ export {
|
|
|
336
431
|
SQUARESPACE_JSON_FORMAT,
|
|
337
432
|
SmugMugApiClient,
|
|
338
433
|
SquarespaceCollectionClient,
|
|
434
|
+
WixCollectionClient,
|
|
435
|
+
WixPageSnapshotCollector,
|
|
339
436
|
analyzeConflicts,
|
|
340
437
|
buildJsonPrettyUrl,
|
|
341
438
|
buildMigrationReport,
|
|
@@ -348,16 +445,32 @@ export {
|
|
|
348
445
|
createFilesystemMigrationSink,
|
|
349
446
|
cssToStyles,
|
|
350
447
|
detectRedirectLoops,
|
|
448
|
+
discoverContentAssetUrls,
|
|
449
|
+
discoverRawImgSrcs,
|
|
351
450
|
emptyBundle,
|
|
352
451
|
emptyConflictReport,
|
|
353
452
|
entityKey,
|
|
354
453
|
estimateStorage,
|
|
454
|
+
extractInlineImageSrcs,
|
|
355
455
|
getAdapter,
|
|
456
|
+
grapesComponentSchema,
|
|
457
|
+
grapesProjectSnapshotSchema,
|
|
458
|
+
grapesStyleRuleSchema,
|
|
356
459
|
hasBlockingConflicts,
|
|
357
460
|
hasWarnings,
|
|
358
461
|
htmlToGrapes,
|
|
462
|
+
isLikelyImageUrl,
|
|
359
463
|
isTerminalState,
|
|
360
464
|
mapJsonPrettyWire,
|
|
465
|
+
normalizeAssetUrl,
|
|
466
|
+
normalizedAssetExifSchema,
|
|
467
|
+
normalizedAssetSchema,
|
|
468
|
+
normalizedCategorySchema,
|
|
469
|
+
normalizedEntitySchema,
|
|
470
|
+
normalizedPageSchema,
|
|
471
|
+
normalizedPortfolioSchema,
|
|
472
|
+
normalizedPostSchema,
|
|
473
|
+
normalizedTagSchema,
|
|
361
474
|
portfolioMediaMatchesBundle,
|
|
362
475
|
readSmugMugCredentialsFromEnv,
|
|
363
476
|
rewriteInlineImages,
|
|
@@ -368,8 +481,18 @@ export {
|
|
|
368
481
|
signSmugMugOAuthRequest,
|
|
369
482
|
smugMugCredentialsSchema,
|
|
370
483
|
smugmugAdapter,
|
|
484
|
+
sourceMetadataSchema,
|
|
371
485
|
squarespaceAdapter,
|
|
372
486
|
staleUrlsFromEstimate,
|
|
487
|
+
validateGrapesProjectSnapshot,
|
|
488
|
+
validateNormalizedAsset,
|
|
489
|
+
validateNormalizedCategory,
|
|
490
|
+
validateNormalizedEntity,
|
|
491
|
+
validateNormalizedPage,
|
|
492
|
+
validateNormalizedPortfolio,
|
|
493
|
+
validateNormalizedPost,
|
|
494
|
+
validateNormalizedTag,
|
|
495
|
+
wixAdapter,
|
|
373
496
|
wordpressAdapter,
|
|
374
497
|
writeFilesystemExport
|
|
375
498
|
};
|
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"],"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"],"mappings":"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","names":[]}
|
|
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":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** All `<img src>` values (including those not ingested as vault assets). */
|
|
2
|
+
declare function discoverRawImgSrcs(content: string): string[];
|
|
3
|
+
/** Normalize protocol-relative and trim; skip data URIs. */
|
|
4
|
+
declare function normalizeAssetUrl(raw: string): string | undefined;
|
|
5
|
+
/** Heuristic: URL likely points at a raster/vector image asset, not a page link. */
|
|
6
|
+
declare function isLikelyImageUrl(url: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Generic content-discovery pass: collect image URLs from HTML `<img>` tags and
|
|
9
|
+
* common shortcode/builder attributes (`src=`, `image=`, `url=`) without parsing
|
|
10
|
+
* builder-specific structure (Tatsu, Elementor, etc.).
|
|
11
|
+
*/
|
|
12
|
+
declare function discoverContentAssetUrls(content: string): string[];
|
|
13
|
+
/** @deprecated Use discoverContentAssetUrls — kept for call-site clarity during transition. */
|
|
14
|
+
declare function extractInlineImageSrcs(content: string): string[];
|
|
15
|
+
|
|
16
|
+
export { discoverContentAssetUrls, discoverRawImgSrcs, extractInlineImageSrcs, isLikelyImageUrl, normalizeAssetUrl };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
discoverContentAssetUrls,
|
|
3
|
+
discoverRawImgSrcs,
|
|
4
|
+
extractInlineImageSrcs,
|
|
5
|
+
isLikelyImageUrl,
|
|
6
|
+
normalizeAssetUrl
|
|
7
|
+
} from "../chunk-2PNSVE5Y.js";
|
|
8
|
+
export {
|
|
9
|
+
discoverContentAssetUrls,
|
|
10
|
+
discoverRawImgSrcs,
|
|
11
|
+
extractInlineImageSrcs,
|
|
12
|
+
isLikelyImageUrl,
|
|
13
|
+
normalizeAssetUrl
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=index.js.map
|