payload-live-preview 2.2.2 → 2.3.1
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 +35 -30
- package/dist/adapters/astro/PreviewBoundary.astro +17 -4
- package/dist/adapters/astro/RichText.astro +13 -2
- package/dist/adapters/astro/index.d.ts +7 -7
- package/dist/adapters/astro/index.js +1 -1
- package/dist/adapters/astro/index.js.map +1 -1
- package/dist/adapters/astro/middleware-entry.d.ts +3 -3
- package/dist/adapters/astro/middleware-entry.js +1 -1
- package/dist/adapters/astro/middleware-entry.js.map +1 -1
- package/dist/adapters/nextjs/index.d.ts +2 -2
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/adapters/nextjs/index.js.map +1 -1
- package/dist/adapters/nuxt/index.d.ts +4 -4
- package/dist/adapters/nuxt/index.js +1 -1
- package/dist/adapters/nuxt/index.js.map +1 -1
- package/dist/adapters/nuxt/module.d.ts +1 -1
- package/dist/adapters/react/index.d.ts +2 -2
- package/dist/adapters/react/index.js +1 -1
- package/dist/adapters/react/index.js.map +1 -1
- package/dist/adapters/sveltekit/index.d.ts +5 -5
- package/dist/adapters/sveltekit/index.js +1 -1
- package/dist/adapters/sveltekit/index.js.map +1 -1
- package/dist/adapters/vue/index.d.ts +2 -2
- package/dist/adapters/vue/index.js +1 -1
- package/dist/adapters/vue/index.js.map +1 -1
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +15 -3
- package/dist/client.d.ts +15 -3
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/codegen-astro.js +1 -1
- package/dist/codegen-astro.js.map +1 -1
- package/dist/codegen-cli.js +1 -1
- package/dist/codegen-cli.js.map +1 -1
- package/dist/codegen.cjs +1 -1
- package/dist/codegen.cjs.map +1 -1
- package/dist/codegen.js +1 -1
- package/dist/codegen.js.map +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +139 -4
- package/dist/core.d.ts +139 -4
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/doctor-cli.d.ts +1 -1
- package/dist/doctor-cli.js +1 -1
- package/dist/doctor-cli.js.map +1 -1
- package/dist/doctor.d.ts +2 -2
- package/dist/doctor.js +1 -1
- package/dist/doctor.js.map +1 -1
- package/dist/{document-session-Bkd181PV.d.ts → document-session-BuYuO3ae.d.ts} +27 -2
- package/dist/{fragment-endpoint-CLRpNQ3n.d.ts → fragment-endpoint-CQE_7MKi.d.ts} +1 -1
- package/dist/fragment.cjs +1 -1
- package/dist/fragment.cjs.map +1 -1
- package/dist/fragment.d.cts +6 -2
- package/dist/fragment.d.ts +6 -2
- package/dist/fragment.js +1 -1
- package/dist/fragment.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +73 -12
- package/dist/index.d.ts +73 -12
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lean.cjs +1 -1
- package/dist/lean.cjs.map +1 -1
- package/dist/lean.js +1 -1
- package/dist/lean.js.map +1 -1
- package/dist/lexical.cjs +1 -1
- package/dist/lexical.cjs.map +1 -1
- package/dist/lexical.d.cts +16 -4
- package/dist/lexical.d.ts +16 -4
- package/dist/lexical.js +1 -1
- package/dist/lexical.js.map +1 -1
- package/dist/{locals-zz2gi9dj.d.ts → locals-CyzDKfKU.d.ts} +7 -1
- package/dist/{middleware-CI-UTf6R.d.ts → middleware-Dnt6u4nF.d.ts} +2 -2
- package/dist/{options-CnYybG51.d.ts → options-DTzhFVJ4.d.ts} +13 -1
- package/dist/plugin.cjs +1 -1
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +15 -9
- package/dist/plugin.d.ts +15 -9
- package/dist/plugin.js +1 -1
- package/dist/plugin.js.map +1 -1
- package/dist/plugins.cjs +1 -1
- package/dist/plugins.cjs.map +1 -1
- package/dist/plugins.d.cts +8 -2
- package/dist/plugins.d.ts +8 -2
- package/dist/plugins.js +1 -1
- package/dist/plugins.js.map +1 -1
- package/dist/{probe-D-IHg9dF.d.ts → probe-afwdYebU.d.ts} +6 -2
- package/dist/server.cjs +1 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +19 -1
- package/dist/server.d.ts +19 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/structural.d.cts +2 -0
- package/dist/structural.d.ts +2 -0
- package/package.json +2 -1
package/dist/plugin.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs","names":["findResolverBySlug","options","collectionSlug","globalSlug","collections","Object","hasOwn","globals","assertNoEntityUrl","entities","selectedSlugs","kind","Array","isArray","length","selected","Set","candidate","entity","record","slug","has","livePreviewConfig","Error","stableUnion","existing","additions","values","seen","candidates","value","add","push","resolveUrl","base","baseUrl","replace","fallback","previewParam","args","locale","code","normaliseLocale","context","data","entry","collectionConfig","globalConfig","documentInfo","collection","global","findResolver","path","resolved","startsWith","name","hashAt","indexOf","hash","slice","beforeHash","queryAt","query","URLSearchParams","getAll","endsWith","encodeURIComponent","withPreviewParam","buildLivePreviewUrl","collectionSlugs","keys","globalSlugs","config","root","admin","current","currentUrl","configured","url","breakpoints","map","breakpoint","livePreview"],"sources":["../src/payload/index.ts","../src/payload/plugin.ts"],"sourcesContent":["/**\n * `payload-live-preview/payload` — helpers for `payload.config.ts`. It never\n * imports `payload`, only produces the callback `admin.livePreview.url` expects.\n */\n\n/** Arguments Payload passes to `admin.livePreview.url`. */\nexport interface LivePreviewUrlArgs {\n readonly data: Record<string, unknown>;\n readonly locale?: string | { readonly code?: string | null; readonly [extra: string]: unknown };\n readonly collectionConfig?: { readonly slug: string };\n readonly globalConfig?: { readonly slug: string };\n /** Payload 2 identifies the edited entity here instead of through the top-level configs. */\n readonly documentInfo?: {\n readonly collection?: {\n /** Payload 2 inherits this runtime value through a mapped config type. */\n readonly slug?: string;\n /** Structural anchor for Payload 2's published sanitized config type. */\n readonly fields?: unknown;\n };\n readonly global?: {\n /** Payload 2 inherits this runtime value through a mapped config type. */\n readonly slug?: string;\n /** Structural anchor for Payload 2's published sanitized config type. */\n readonly fields?: unknown;\n };\n };\n readonly [extra: string]: unknown;\n}\n\n/** Context handed to per-slug path resolvers. */\nexport interface PathResolverContext {\n readonly data: Record<string, unknown>;\n /** Normalised locale code, or `undefined`. */\n readonly locale: string | undefined;\n}\n\nexport type PathResolver = string | ((context: PathResolverContext) => string);\n\n/** A resolver that may decline a document: `null` means no preview target; `''` falls back. */\nexport type NullablePathResolver =\n string | null | ((context: PathResolverContext) => string | null);\n\nexport interface BuildLivePreviewUrlOptions {\n /** Frontend origin, e.g. `https://site.example`. */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. */\n readonly collections?: Readonly<Record<string, PathResolver>>;\n /** Per-global path resolvers keyed by global slug. */\n readonly globals?: Readonly<Record<string, PathResolver>>;\n /** Path when no resolver matches or one returns `''` (a draft without a slug). Default `/`. */\n readonly fallback?: string;\n /** Query parameter signalling preview intent; keep it in the adapter's `previewQueryParams`. Client-controlled, so it authorizes nothing. Default `'preview'`, `null` disables it. */\n readonly previewParam?: string | null;\n}\n\n/**\n * Like {@link BuildLivePreviewUrlOptions} with nullable resolvers: the callback\n * may return `null`, and no iframe beats one pointing at a public page.\n */\nexport interface BuildLivePreviewUrlNullableOptions {\n readonly baseUrl: string;\n readonly collections?: Readonly<Record<string, NullablePathResolver>>;\n readonly globals?: Readonly<Record<string, NullablePathResolver>>;\n /** `null` declines every unmapped document. Default `/`. */\n readonly fallback?: string | null;\n /** See {@link BuildLivePreviewUrlOptions.previewParam}. */\n readonly previewParam?: string | null;\n}\n\n/** Build an `admin.livePreview.url` callback from slug → path mappings. */\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlOptions,\n): (args: LivePreviewUrlArgs) => string;\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlNullableOptions,\n): (args: LivePreviewUrlArgs) => string | null;\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlNullableOptions,\n): (args: LivePreviewUrlArgs) => string | null {\n const base = options.baseUrl.replace(/\\/+$/, '');\n // `??` would swallow an explicit `null`, which is the whole point of the nullable form.\n const fallback = options.fallback === undefined ? '/' : options.fallback;\n const previewParam = options.previewParam === undefined ? 'preview' : options.previewParam;\n\n return (args) => {\n const locale = normaliseLocale(args.locale);\n const context: PathResolverContext = { data: args.data, locale };\n const entry = findResolver(options, args);\n\n let path: string | null = fallback;\n if (entry !== undefined) {\n const resolved = typeof entry === 'function' ? entry(context) : entry;\n if (resolved === null) return null;\n if (resolved.length > 0) path = resolved;\n }\n if (path === null) return null;\n if (!path.startsWith('/')) path = `/${path}`;\n return `${base}${previewParam === null ? path : withPreviewParam(path, previewParam)}`;\n };\n}\n\n/** `path` with `<name>=true` in its query — ahead of any `#fragment`, and not twice. */\nfunction withPreviewParam(path: string, name: string): string {\n const hashAt = path.indexOf('#');\n const hash = hashAt === -1 ? '' : path.slice(hashAt);\n const beforeHash = hashAt === -1 ? path : path.slice(0, hashAt);\n const queryAt = beforeHash.indexOf('?');\n const query = queryAt === -1 ? '' : beforeHash.slice(queryAt + 1);\n const values = new URLSearchParams(query).getAll(name);\n if (values[values.length - 1] === 'true') return path;\n const separator = queryAt === -1 ? '?' : query.length === 0 || query.endsWith('&') ? '' : '&';\n return `${beforeHash}${separator}${encodeURIComponent(name)}=true${hash}`;\n}\n\n/** The mapped resolver, or `undefined` when the slug is not mapped; a mapped `null` is a resolver in its own right. */\nfunction findResolver(\n options: BuildLivePreviewUrlNullableOptions,\n args: LivePreviewUrlArgs,\n): NullablePathResolver | undefined {\n // Payload 3's explicit callback arguments win as a pair. Looking through a\n // stale `documentInfo` when either is present could select the wrong entity.\n if (args.collectionConfig !== undefined || args.globalConfig !== undefined) {\n return findResolverBySlug(options, args.collectionConfig?.slug, args.globalConfig?.slug);\n }\n return findResolverBySlug(\n options,\n args.documentInfo?.collection?.slug,\n args.documentInfo?.global?.slug,\n );\n}\n\nfunction findResolverBySlug(\n options: BuildLivePreviewUrlNullableOptions,\n collectionSlug: string | undefined,\n globalSlug: string | undefined,\n): NullablePathResolver | undefined {\n if (\n collectionSlug !== undefined &&\n options.collections !== undefined &&\n Object.hasOwn(options.collections, collectionSlug)\n ) {\n return options.collections[collectionSlug];\n }\n if (\n globalSlug !== undefined &&\n options.globals !== undefined &&\n Object.hasOwn(options.globals, globalSlug)\n ) {\n return options.globals[globalSlug];\n }\n return undefined;\n}\n\nfunction normaliseLocale(locale: LivePreviewUrlArgs['locale']): string | undefined {\n if (locale === undefined) return undefined;\n if (typeof locale === 'string') return locale.length > 0 ? locale : undefined;\n return typeof locale.code === 'string' && locale.code.length > 0 ? locale.code : undefined;\n}\n","/**\n * `payload-live-preview/plugin` configures Payload 2 or 3 without importing\n * either version. It owns URL selection and root preview metadata, while\n * authentication remains an explicit server-side integration.\n */\nimport { buildLivePreviewUrl, type LivePreviewUrlArgs } from './index';\n\nexport interface LivePreviewBreakpoint {\n readonly name: string;\n readonly label: string;\n readonly width: number | string;\n readonly height: number | string;\n}\n\nexport interface LivePreviewPluginOptions {\n /** Frontend origin, e.g. `https://site.example`. */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. */\n readonly collections?: Readonly<\n Record<\n string,\n | string\n | ((context: {\n readonly data: Record<string, unknown>;\n readonly locale: string | undefined;\n }) => string)\n >\n >;\n /** Per-global path resolvers keyed by global slug. */\n readonly globals?: Readonly<\n Record<\n string,\n | string\n | ((context: {\n readonly data: Record<string, unknown>;\n readonly locale: string | undefined;\n }) => string)\n >\n >;\n /** Path used when no resolver matches or one returns `''`. Default `/`. */\n readonly fallback?: string;\n /** Preview-intent query parameter. Keep it in the frontend adapter's `previewQueryParams`; `null` needs another intent signal. */\n readonly previewParam?: string | null;\n /** Device sizes displayed by Payload's live-preview toolbar. */\n readonly breakpoints?: readonly LivePreviewBreakpoint[];\n}\n\ntype UnknownRecord = Record<string, unknown>;\n\n/** Configure mapped entities and one shared live-preview URL callback. */\nexport function livePreview(\n options: LivePreviewPluginOptions,\n): <TConfig extends object>(config: TConfig) => TConfig {\n const resolveUrl = buildLivePreviewUrl(options);\n const collectionSlugs = Object.keys(options.collections ?? {});\n const globalSlugs = Object.keys(options.globals ?? {});\n\n return <TConfig extends object>(config: TConfig): TConfig => {\n const root = config as UnknownRecord;\n const admin = record(root['admin']);\n const current = record(admin['livePreview']);\n const currentUrl = current['url'];\n\n if (Object.hasOwn(current, 'url') && currentUrl !== resolveUrl) {\n throw new Error(\n 'payload-live-preview/plugin cannot replace an existing admin.livePreview.url',\n );\n }\n\n assertNoEntityUrl(root['collections'], collectionSlugs, 'collection');\n assertNoEntityUrl(root['globals'], globalSlugs, 'global');\n\n const configured: UnknownRecord = {\n ...current,\n collections: stableUnion(current['collections'], collectionSlugs),\n globals: stableUnion(current['globals'], globalSlugs),\n url: resolveUrl satisfies (args: LivePreviewUrlArgs) => string,\n };\n if (options.breakpoints !== undefined) {\n configured['breakpoints'] = options.breakpoints.map((breakpoint) => ({ ...breakpoint }));\n }\n\n return {\n ...root,\n admin: {\n ...admin,\n livePreview: configured,\n },\n } as TConfig;\n };\n}\n\nfunction assertNoEntityUrl(\n entities: unknown,\n selectedSlugs: readonly string[],\n kind: 'collection' | 'global',\n): void {\n if (!Array.isArray(entities) || selectedSlugs.length === 0) return;\n const selected = new Set(selectedSlugs);\n for (const candidate of entities) {\n const entity = record(candidate);\n const slug = entity['slug'];\n if (typeof slug !== 'string' || !selected.has(slug)) continue;\n const livePreviewConfig = record(record(entity['admin'])['livePreview']);\n if (Object.hasOwn(livePreviewConfig, 'url')) {\n throw new Error(\n `payload-live-preview/plugin cannot configure ${kind} \"${slug}\" because it already has admin.livePreview.url`,\n );\n }\n }\n}\n\nfunction stableUnion(existing: unknown, additions: readonly string[]): string[] {\n const values: string[] = [];\n const seen = new Set<string>();\n const current: readonly unknown[] = Array.isArray(existing)\n ? (existing as readonly unknown[])\n : [];\n const candidates: readonly unknown[] = [...current, ...additions];\n for (const value of candidates) {\n if (typeof value !== 'string') continue;\n if (seen.has(value)) continue;\n seen.add(value);\n values.push(value);\n }\n return values;\n}\n\nfunction record(value: unknown): UnknownRecord {\n return typeof value === 'object' && value !== null ? (value as UnknownRecord) : {};\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"plugin.cjs","names":["findResolverBySlug","options","collectionSlug","globalSlug","collections","Object","hasOwn","globals","assertNoEntityUrl","entities","selectedSlugs","kind","Array","isArray","length","selected","Set","candidate","entity","record","slug","has","livePreviewConfig","Error","stableUnion","existing","additions","values","seen","candidates","value","add","push","resolveUrl","base","baseUrl","replace","fallback","previewParam","args","locale","code","normaliseLocale","context","data","entry","collectionConfig","globalConfig","documentInfo","collection","global","findResolver","path","resolved","startsWith","name","hashAt","indexOf","hash","slice","beforeHash","queryAt","query","URLSearchParams","getAll","endsWith","encodeURIComponent","withPreviewParam","buildLivePreviewUrl","collectionSlugs","keys","globalSlugs","identity","order","assign","config","root","admin","current","currentUrl","configured","url","breakpoints","map","breakpoint","livePreview"],"sources":["../src/payload/index.ts","../src/payload/plugin.ts"],"sourcesContent":["/**\n * `payload-live-preview/payload` — helpers for `payload.config.ts`. It never\n * imports `payload`, only produces the callback `admin.livePreview.url` expects.\n */\n\n/** Arguments Payload passes to `admin.livePreview.url`. */\nexport interface LivePreviewUrlArgs {\n readonly data: Record<string, unknown>;\n readonly locale?: string | { readonly code?: string | null; readonly [extra: string]: unknown };\n readonly collectionConfig?: { readonly slug: string };\n readonly globalConfig?: { readonly slug: string };\n /** Payload 2 identifies the edited entity here instead of through the top-level configs. */\n readonly documentInfo?: {\n readonly collection?: {\n /** Payload 2 inherits this runtime value through a mapped config type. */\n readonly slug?: string;\n /** Structural anchor for Payload 2's published sanitized config type. */\n readonly fields?: unknown;\n };\n readonly global?: {\n /** Payload 2 inherits this runtime value through a mapped config type. */\n readonly slug?: string;\n /** Structural anchor for Payload 2's published sanitized config type. */\n readonly fields?: unknown;\n };\n };\n readonly [extra: string]: unknown;\n}\n\n/** Context handed to per-slug path resolvers. */\nexport interface PathResolverContext {\n readonly data: Record<string, unknown>;\n /** Normalised locale code, or `undefined`. */\n readonly locale: string | undefined;\n}\n\nexport type PathResolver = string | ((context: PathResolverContext) => string);\n\n/** A resolver that may decline a document: `null` means no preview target; `''` falls back. */\nexport type NullablePathResolver =\n string | null | ((context: PathResolverContext) => string | null);\n\nexport interface BuildLivePreviewUrlOptions {\n /** Frontend origin, e.g. `https://site.example`. */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. */\n readonly collections?: Readonly<Record<string, PathResolver>>;\n /** Per-global path resolvers keyed by global slug. */\n readonly globals?: Readonly<Record<string, PathResolver>>;\n /** Path when no resolver matches or one returns `''` (a draft without a slug). Default `/`. */\n readonly fallback?: string;\n /** Query parameter signalling preview intent; keep it in the adapter's `previewQueryParams`. Client-controlled, so it authorizes nothing. Default `'preview'`, `null` disables it. */\n readonly previewParam?: string | null;\n}\n\n/**\n * Like {@link BuildLivePreviewUrlOptions} with nullable resolvers: the callback\n * may return `null`, and no iframe beats one pointing at a public page.\n */\nexport interface BuildLivePreviewUrlNullableOptions {\n readonly baseUrl: string;\n readonly collections?: Readonly<Record<string, NullablePathResolver>>;\n readonly globals?: Readonly<Record<string, NullablePathResolver>>;\n /** `null` declines every unmapped document. Default `/`. */\n readonly fallback?: string | null;\n /** See {@link BuildLivePreviewUrlOptions.previewParam}. */\n readonly previewParam?: string | null;\n}\n\n/** Build an `admin.livePreview.url` callback from slug → path mappings. */\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlOptions,\n): (args: LivePreviewUrlArgs) => string;\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlNullableOptions,\n): (args: LivePreviewUrlArgs) => string | null;\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlNullableOptions,\n): (args: LivePreviewUrlArgs) => string | null {\n const base = options.baseUrl.replace(/\\/+$/, '');\n // `??` would swallow an explicit `null`, which is the whole point of the nullable form.\n const fallback = options.fallback === undefined ? '/' : options.fallback;\n const previewParam = options.previewParam === undefined ? 'preview' : options.previewParam;\n\n return (args) => {\n const locale = normaliseLocale(args.locale);\n const context: PathResolverContext = { data: args.data, locale };\n const entry = findResolver(options, args);\n\n let path: string | null = fallback;\n if (entry !== undefined) {\n const resolved = typeof entry === 'function' ? entry(context) : entry;\n if (resolved === null) return null;\n if (resolved.length > 0) path = resolved;\n }\n if (path === null) return null;\n if (!path.startsWith('/')) path = `/${path}`;\n return `${base}${previewParam === null ? path : withPreviewParam(path, previewParam)}`;\n };\n}\n\n/** `path` with `<name>=true` in its query — ahead of any `#fragment`, and not twice. */\nfunction withPreviewParam(path: string, name: string): string {\n const hashAt = path.indexOf('#');\n const hash = hashAt === -1 ? '' : path.slice(hashAt);\n const beforeHash = hashAt === -1 ? path : path.slice(0, hashAt);\n const queryAt = beforeHash.indexOf('?');\n const query = queryAt === -1 ? '' : beforeHash.slice(queryAt + 1);\n const values = new URLSearchParams(query).getAll(name);\n if (values[values.length - 1] === 'true') return path;\n const separator = queryAt === -1 ? '?' : query.length === 0 || query.endsWith('&') ? '' : '&';\n return `${beforeHash}${separator}${encodeURIComponent(name)}=true${hash}`;\n}\n\n/** The mapped resolver, or `undefined` when the slug is not mapped; a mapped `null` is a resolver in its own right. */\nfunction findResolver(\n options: BuildLivePreviewUrlNullableOptions,\n args: LivePreviewUrlArgs,\n): NullablePathResolver | undefined {\n // Payload 3's explicit callback arguments win as a pair. Looking through a\n // stale `documentInfo` when either is present could select the wrong entity.\n if (args.collectionConfig !== undefined || args.globalConfig !== undefined) {\n return findResolverBySlug(options, args.collectionConfig?.slug, args.globalConfig?.slug);\n }\n return findResolverBySlug(\n options,\n args.documentInfo?.collection?.slug,\n args.documentInfo?.global?.slug,\n );\n}\n\nfunction findResolverBySlug(\n options: BuildLivePreviewUrlNullableOptions,\n collectionSlug: string | undefined,\n globalSlug: string | undefined,\n): NullablePathResolver | undefined {\n if (\n collectionSlug !== undefined &&\n options.collections !== undefined &&\n Object.hasOwn(options.collections, collectionSlug)\n ) {\n return options.collections[collectionSlug];\n }\n if (\n globalSlug !== undefined &&\n options.globals !== undefined &&\n Object.hasOwn(options.globals, globalSlug)\n ) {\n return options.globals[globalSlug];\n }\n return undefined;\n}\n\nfunction normaliseLocale(locale: LivePreviewUrlArgs['locale']): string | undefined {\n if (locale === undefined) return undefined;\n if (typeof locale === 'string') return locale.length > 0 ? locale : undefined;\n return typeof locale.code === 'string' && locale.code.length > 0 ? locale.code : undefined;\n}\n","/**\n * `payload-live-preview/plugin` configures Payload 2, 3 or 4 without importing\n * any of them. It owns URL selection and root preview metadata, while\n * authentication remains an explicit server-side integration.\n */\nimport { buildLivePreviewUrl, type LivePreviewUrlArgs } from './index';\n\nexport interface LivePreviewBreakpoint {\n readonly name: string;\n readonly label: string;\n readonly width: number | string;\n readonly height: number | string;\n}\n\nexport interface LivePreviewPluginOptions {\n /** Frontend origin, e.g. `https://site.example`. */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. `null` means this document has no preview. */\n readonly collections?: Readonly<\n Record<\n string,\n | string\n | null\n | ((context: {\n readonly data: Record<string, unknown>;\n readonly locale: string | undefined;\n }) => string | null)\n >\n >;\n /** Per-global path resolvers keyed by global slug. `null` means this document has no preview. */\n readonly globals?: Readonly<\n Record<\n string,\n | string\n | null\n | ((context: {\n readonly data: Record<string, unknown>;\n readonly locale: string | undefined;\n }) => string | null)\n >\n >;\n /** Path used when no resolver matches or one returns `''`; `null` declines those documents. Default `/`. */\n readonly fallback?: string | null;\n /** Preview-intent query parameter. Keep it in the frontend adapter's `previewQueryParams`; `null` needs another intent signal. */\n readonly previewParam?: string | null;\n /** Device sizes displayed by Payload's live-preview toolbar. */\n readonly breakpoints?: readonly LivePreviewBreakpoint[];\n /** Where this plugin runs: Payload 3 and 4 sort plugins by ascending `order`, `0` when unset. Payload 2 keeps list order. */\n readonly order?: number;\n}\n\ntype UnknownRecord = Record<string, unknown>;\n\n/** Configure mapped entities and one shared live-preview URL callback. */\nexport function livePreview(options: LivePreviewPluginOptions): (<TConfig extends object>(\n config: TConfig,\n) => TConfig) & {\n /** Payload reads this name when another plugin looks this one up in `config.plugins`. */\n readonly slug: string;\n readonly order?: number;\n} {\n const resolveUrl = buildLivePreviewUrl(options);\n const collectionSlugs = Object.keys(options.collections ?? {});\n const globalSlugs = Object.keys(options.globals ?? {});\n\n const transform = <TConfig extends object>(config: TConfig): TConfig => {\n const root = config as UnknownRecord;\n const admin = record(root['admin']);\n const current = record(admin['livePreview']);\n const currentUrl = current['url'];\n\n if (Object.hasOwn(current, 'url') && currentUrl !== resolveUrl) {\n throw new Error(\n 'payload-live-preview/plugin cannot replace an existing admin.livePreview.url',\n );\n }\n\n assertNoEntityUrl(root['collections'], collectionSlugs, 'collection');\n assertNoEntityUrl(root['globals'], globalSlugs, 'global');\n\n const configured: UnknownRecord = {\n ...current,\n collections: stableUnion(current['collections'], collectionSlugs),\n globals: stableUnion(current['globals'], globalSlugs),\n url: resolveUrl satisfies (args: LivePreviewUrlArgs) => string | null,\n };\n if (options.breakpoints !== undefined) {\n configured['breakpoints'] = options.breakpoints.map((breakpoint) => ({ ...breakpoint }));\n }\n\n return {\n ...root,\n admin: {\n ...admin,\n livePreview: configured,\n },\n } as TConfig;\n };\n\n const identity: { slug: string; order?: number } = { slug: 'payload-live-preview' };\n if (options.order !== undefined) identity.order = options.order;\n return Object.assign(transform, identity);\n}\n\nfunction assertNoEntityUrl(\n entities: unknown,\n selectedSlugs: readonly string[],\n kind: 'collection' | 'global',\n): void {\n if (!Array.isArray(entities) || selectedSlugs.length === 0) return;\n const selected = new Set(selectedSlugs);\n for (const candidate of entities) {\n const entity = record(candidate);\n const slug = entity['slug'];\n if (typeof slug !== 'string' || !selected.has(slug)) continue;\n const livePreviewConfig = record(record(entity['admin'])['livePreview']);\n if (Object.hasOwn(livePreviewConfig, 'url')) {\n throw new Error(\n `payload-live-preview/plugin cannot configure ${kind} \"${slug}\" because it already has admin.livePreview.url`,\n );\n }\n }\n}\n\nfunction stableUnion(existing: unknown, additions: readonly string[]): string[] {\n const values: string[] = [];\n const seen = new Set<string>();\n const current: readonly unknown[] = Array.isArray(existing)\n ? (existing as readonly unknown[])\n : [];\n const candidates: readonly unknown[] = [...current, ...additions];\n for (const value of candidates) {\n if (typeof value !== 'string') continue;\n if (seen.has(value)) continue;\n seen.add(value);\n values.push(value);\n }\n return values;\n}\n\nfunction record(value: unknown): UnknownRecord {\n return typeof value === 'object' && value !== null ? (value as UnknownRecord) : {};\n}\n"],"mappings":"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","ignoreList":[]}
|
package/dist/plugin.d.cts
CHANGED
|
@@ -7,24 +7,30 @@ interface LivePreviewBreakpoint {
|
|
|
7
7
|
interface LivePreviewPluginOptions {
|
|
8
8
|
/** Frontend origin, e.g. `https://site.example`. */
|
|
9
9
|
readonly baseUrl: string;
|
|
10
|
-
/** Per-collection path resolvers keyed by collection slug. */
|
|
11
|
-
readonly collections?: Readonly<Record<string, string | ((context: {
|
|
10
|
+
/** Per-collection path resolvers keyed by collection slug. `null` means this document has no preview. */
|
|
11
|
+
readonly collections?: Readonly<Record<string, string | null | ((context: {
|
|
12
12
|
readonly data: Record<string, unknown>;
|
|
13
13
|
readonly locale: string | undefined;
|
|
14
|
-
}) => string)>>;
|
|
15
|
-
/** Per-global path resolvers keyed by global slug. */
|
|
16
|
-
readonly globals?: Readonly<Record<string, string | ((context: {
|
|
14
|
+
}) => string | null)>>;
|
|
15
|
+
/** Per-global path resolvers keyed by global slug. `null` means this document has no preview. */
|
|
16
|
+
readonly globals?: Readonly<Record<string, string | null | ((context: {
|
|
17
17
|
readonly data: Record<string, unknown>;
|
|
18
18
|
readonly locale: string | undefined;
|
|
19
|
-
}) => string)>>;
|
|
20
|
-
/** Path used when no resolver matches or one returns `''
|
|
21
|
-
readonly fallback?: string;
|
|
19
|
+
}) => string | null)>>;
|
|
20
|
+
/** Path used when no resolver matches or one returns `''`; `null` declines those documents. Default `/`. */
|
|
21
|
+
readonly fallback?: string | null;
|
|
22
22
|
/** Preview-intent query parameter. Keep it in the frontend adapter's `previewQueryParams`; `null` needs another intent signal. */
|
|
23
23
|
readonly previewParam?: string | null;
|
|
24
24
|
/** Device sizes displayed by Payload's live-preview toolbar. */
|
|
25
25
|
readonly breakpoints?: readonly LivePreviewBreakpoint[];
|
|
26
|
+
/** Where this plugin runs: Payload 3 and 4 sort plugins by ascending `order`, `0` when unset. Payload 2 keeps list order. */
|
|
27
|
+
readonly order?: number;
|
|
26
28
|
}
|
|
27
29
|
/** Configure mapped entities and one shared live-preview URL callback. */
|
|
28
|
-
declare function livePreview(options: LivePreviewPluginOptions): <TConfig extends object>(config: TConfig) => TConfig
|
|
30
|
+
declare function livePreview(options: LivePreviewPluginOptions): (<TConfig extends object>(config: TConfig) => TConfig) & {
|
|
31
|
+
/** Payload reads this name when another plugin looks this one up in `config.plugins`. */
|
|
32
|
+
readonly slug: string;
|
|
33
|
+
readonly order?: number;
|
|
34
|
+
};
|
|
29
35
|
|
|
30
36
|
export { type LivePreviewBreakpoint, type LivePreviewPluginOptions, livePreview };
|
package/dist/plugin.d.ts
CHANGED
|
@@ -7,24 +7,30 @@ interface LivePreviewBreakpoint {
|
|
|
7
7
|
interface LivePreviewPluginOptions {
|
|
8
8
|
/** Frontend origin, e.g. `https://site.example`. */
|
|
9
9
|
readonly baseUrl: string;
|
|
10
|
-
/** Per-collection path resolvers keyed by collection slug. */
|
|
11
|
-
readonly collections?: Readonly<Record<string, string | ((context: {
|
|
10
|
+
/** Per-collection path resolvers keyed by collection slug. `null` means this document has no preview. */
|
|
11
|
+
readonly collections?: Readonly<Record<string, string | null | ((context: {
|
|
12
12
|
readonly data: Record<string, unknown>;
|
|
13
13
|
readonly locale: string | undefined;
|
|
14
|
-
}) => string)>>;
|
|
15
|
-
/** Per-global path resolvers keyed by global slug. */
|
|
16
|
-
readonly globals?: Readonly<Record<string, string | ((context: {
|
|
14
|
+
}) => string | null)>>;
|
|
15
|
+
/** Per-global path resolvers keyed by global slug. `null` means this document has no preview. */
|
|
16
|
+
readonly globals?: Readonly<Record<string, string | null | ((context: {
|
|
17
17
|
readonly data: Record<string, unknown>;
|
|
18
18
|
readonly locale: string | undefined;
|
|
19
|
-
}) => string)>>;
|
|
20
|
-
/** Path used when no resolver matches or one returns `''
|
|
21
|
-
readonly fallback?: string;
|
|
19
|
+
}) => string | null)>>;
|
|
20
|
+
/** Path used when no resolver matches or one returns `''`; `null` declines those documents. Default `/`. */
|
|
21
|
+
readonly fallback?: string | null;
|
|
22
22
|
/** Preview-intent query parameter. Keep it in the frontend adapter's `previewQueryParams`; `null` needs another intent signal. */
|
|
23
23
|
readonly previewParam?: string | null;
|
|
24
24
|
/** Device sizes displayed by Payload's live-preview toolbar. */
|
|
25
25
|
readonly breakpoints?: readonly LivePreviewBreakpoint[];
|
|
26
|
+
/** Where this plugin runs: Payload 3 and 4 sort plugins by ascending `order`, `0` when unset. Payload 2 keeps list order. */
|
|
27
|
+
readonly order?: number;
|
|
26
28
|
}
|
|
27
29
|
/** Configure mapped entities and one shared live-preview URL callback. */
|
|
28
|
-
declare function livePreview(options: LivePreviewPluginOptions): <TConfig extends object>(config: TConfig) => TConfig
|
|
30
|
+
declare function livePreview(options: LivePreviewPluginOptions): (<TConfig extends object>(config: TConfig) => TConfig) & {
|
|
31
|
+
/** Payload reads this name when another plugin looks this one up in `config.plugins`. */
|
|
32
|
+
readonly slug: string;
|
|
33
|
+
readonly order?: number;
|
|
34
|
+
};
|
|
29
35
|
|
|
30
36
|
export { type LivePreviewBreakpoint, type LivePreviewPluginOptions, livePreview };
|
package/dist/plugin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function e(e,n
|
|
1
|
+
function e(e,o,n){return void 0!==o&&void 0!==e.collections&&Object.hasOwn(e.collections,o)?e.collections[o]:void 0!==n&&void 0!==e.globals&&Object.hasOwn(e.globals,n)?e.globals[n]:void 0}function o(o){const i=function(o){const n=o.baseUrl.replace(/\/+$/,""),l=void 0===o.fallback?"/":o.fallback,t=void 0===o.previewParam?"preview":o.previewParam;return i=>{const r=function(e){return void 0===e?void 0:"string"==typeof e?e.length>0?e:void 0:"string"==typeof e.code&&e.code.length>0?e.code:void 0}(i.locale),c={data:i.data,locale:r},a=function(o,n){return void 0!==n.collectionConfig||void 0!==n.globalConfig?e(o,n.collectionConfig?.slug,n.globalConfig?.slug):e(o,n.documentInfo?.collection?.slug,n.documentInfo?.global?.slug)}(o,i);let s=l;if(void 0!==a){const e="function"==typeof a?a(c):a;if(null===e)return null;e.length>0&&(s=e)}return null===s?null:(s.startsWith("/")||(s=`/${s}`),`${n}${null===t?s:function(e,o){const n=e.indexOf("#"),l=-1===n?"":e.slice(n),t=-1===n?e:e.slice(0,n),i=t.indexOf("?"),r=-1===i?"":t.slice(i+1),c=new URLSearchParams(r).getAll(o);return"true"===c[c.length-1]?e:`${t}${-1===i?"?":0===r.length||r.endsWith("&")?"":"&"}${encodeURIComponent(o)}=true${l}`}(s,t)}`)}}(o),r=Object.keys(o.collections??{}),c=Object.keys(o.globals??{}),a={slug:"payload-live-preview"};return void 0!==o.order&&(a.order=o.order),Object.assign(e=>{const a=e,s=t(a.admin),u=t(s.livePreview),d=u.url;if(Object.hasOwn(u,"url")&&d!==i)throw new Error("payload-live-preview/plugin cannot replace an existing admin.livePreview.url");n(a.collections,r,"collection"),n(a.globals,c,"global");const f={...u,collections:l(u.collections,r),globals:l(u.globals,c),url:i};return void 0!==o.breakpoints&&(f.breakpoints=o.breakpoints.map(e=>({...e}))),{...a,admin:{...s,livePreview:f}}},a)}function n(e,o,n){if(!Array.isArray(e)||0===o.length)return;const l=new Set(o);for(const o of e){const e=t(o),i=e.slug;if("string"!=typeof i||!l.has(i))continue;const r=t(t(e.admin).livePreview);if(Object.hasOwn(r,"url"))throw new Error(`payload-live-preview/plugin cannot configure ${n} "${i}" because it already has admin.livePreview.url`)}}function l(e,o){const n=[],l=/* @__PURE__ */new Set,t=[...Array.isArray(e)?e:[],...o];for(const e of t)"string"==typeof e&&(l.has(e)||(l.add(e),n.push(e)));return n}function t(e){return"object"==typeof e&&null!==e?e:{}}export{o as livePreview};
|
|
2
2
|
//# sourceMappingURL=plugin.js.map
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":["findResolverBySlug","options","collectionSlug","globalSlug","collections","Object","hasOwn","globals","livePreview","resolveUrl","base","baseUrl","replace","fallback","previewParam","args","locale","length","code","normaliseLocale","context","data","entry","collectionConfig","globalConfig","slug","documentInfo","collection","global","findResolver","path","resolved","startsWith","name","hashAt","indexOf","hash","slice","beforeHash","queryAt","query","values","URLSearchParams","getAll","endsWith","encodeURIComponent","withPreviewParam","buildLivePreviewUrl","collectionSlugs","keys","globalSlugs","config","root","admin","record","current","currentUrl","Error","assertNoEntityUrl","configured","stableUnion","url","breakpoints","map","breakpoint","entities","selectedSlugs","kind","Array","isArray","selected","Set","candidate","entity","has","livePreviewConfig","existing","additions","seen","candidates","value","add","push"],"sources":["../src/payload/index.ts","../src/payload/plugin.ts"],"sourcesContent":["/**\n * `payload-live-preview/payload` — helpers for `payload.config.ts`. It never\n * imports `payload`, only produces the callback `admin.livePreview.url` expects.\n */\n\n/** Arguments Payload passes to `admin.livePreview.url`. */\nexport interface LivePreviewUrlArgs {\n readonly data: Record<string, unknown>;\n readonly locale?: string | { readonly code?: string | null; readonly [extra: string]: unknown };\n readonly collectionConfig?: { readonly slug: string };\n readonly globalConfig?: { readonly slug: string };\n /** Payload 2 identifies the edited entity here instead of through the top-level configs. */\n readonly documentInfo?: {\n readonly collection?: {\n /** Payload 2 inherits this runtime value through a mapped config type. */\n readonly slug?: string;\n /** Structural anchor for Payload 2's published sanitized config type. */\n readonly fields?: unknown;\n };\n readonly global?: {\n /** Payload 2 inherits this runtime value through a mapped config type. */\n readonly slug?: string;\n /** Structural anchor for Payload 2's published sanitized config type. */\n readonly fields?: unknown;\n };\n };\n readonly [extra: string]: unknown;\n}\n\n/** Context handed to per-slug path resolvers. */\nexport interface PathResolverContext {\n readonly data: Record<string, unknown>;\n /** Normalised locale code, or `undefined`. */\n readonly locale: string | undefined;\n}\n\nexport type PathResolver = string | ((context: PathResolverContext) => string);\n\n/** A resolver that may decline a document: `null` means no preview target; `''` falls back. */\nexport type NullablePathResolver =\n string | null | ((context: PathResolverContext) => string | null);\n\nexport interface BuildLivePreviewUrlOptions {\n /** Frontend origin, e.g. `https://site.example`. */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. */\n readonly collections?: Readonly<Record<string, PathResolver>>;\n /** Per-global path resolvers keyed by global slug. */\n readonly globals?: Readonly<Record<string, PathResolver>>;\n /** Path when no resolver matches or one returns `''` (a draft without a slug). Default `/`. */\n readonly fallback?: string;\n /** Query parameter signalling preview intent; keep it in the adapter's `previewQueryParams`. Client-controlled, so it authorizes nothing. Default `'preview'`, `null` disables it. */\n readonly previewParam?: string | null;\n}\n\n/**\n * Like {@link BuildLivePreviewUrlOptions} with nullable resolvers: the callback\n * may return `null`, and no iframe beats one pointing at a public page.\n */\nexport interface BuildLivePreviewUrlNullableOptions {\n readonly baseUrl: string;\n readonly collections?: Readonly<Record<string, NullablePathResolver>>;\n readonly globals?: Readonly<Record<string, NullablePathResolver>>;\n /** `null` declines every unmapped document. Default `/`. */\n readonly fallback?: string | null;\n /** See {@link BuildLivePreviewUrlOptions.previewParam}. */\n readonly previewParam?: string | null;\n}\n\n/** Build an `admin.livePreview.url` callback from slug → path mappings. */\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlOptions,\n): (args: LivePreviewUrlArgs) => string;\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlNullableOptions,\n): (args: LivePreviewUrlArgs) => string | null;\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlNullableOptions,\n): (args: LivePreviewUrlArgs) => string | null {\n const base = options.baseUrl.replace(/\\/+$/, '');\n // `??` would swallow an explicit `null`, which is the whole point of the nullable form.\n const fallback = options.fallback === undefined ? '/' : options.fallback;\n const previewParam = options.previewParam === undefined ? 'preview' : options.previewParam;\n\n return (args) => {\n const locale = normaliseLocale(args.locale);\n const context: PathResolverContext = { data: args.data, locale };\n const entry = findResolver(options, args);\n\n let path: string | null = fallback;\n if (entry !== undefined) {\n const resolved = typeof entry === 'function' ? entry(context) : entry;\n if (resolved === null) return null;\n if (resolved.length > 0) path = resolved;\n }\n if (path === null) return null;\n if (!path.startsWith('/')) path = `/${path}`;\n return `${base}${previewParam === null ? path : withPreviewParam(path, previewParam)}`;\n };\n}\n\n/** `path` with `<name>=true` in its query — ahead of any `#fragment`, and not twice. */\nfunction withPreviewParam(path: string, name: string): string {\n const hashAt = path.indexOf('#');\n const hash = hashAt === -1 ? '' : path.slice(hashAt);\n const beforeHash = hashAt === -1 ? path : path.slice(0, hashAt);\n const queryAt = beforeHash.indexOf('?');\n const query = queryAt === -1 ? '' : beforeHash.slice(queryAt + 1);\n const values = new URLSearchParams(query).getAll(name);\n if (values[values.length - 1] === 'true') return path;\n const separator = queryAt === -1 ? '?' : query.length === 0 || query.endsWith('&') ? '' : '&';\n return `${beforeHash}${separator}${encodeURIComponent(name)}=true${hash}`;\n}\n\n/** The mapped resolver, or `undefined` when the slug is not mapped; a mapped `null` is a resolver in its own right. */\nfunction findResolver(\n options: BuildLivePreviewUrlNullableOptions,\n args: LivePreviewUrlArgs,\n): NullablePathResolver | undefined {\n // Payload 3's explicit callback arguments win as a pair. Looking through a\n // stale `documentInfo` when either is present could select the wrong entity.\n if (args.collectionConfig !== undefined || args.globalConfig !== undefined) {\n return findResolverBySlug(options, args.collectionConfig?.slug, args.globalConfig?.slug);\n }\n return findResolverBySlug(\n options,\n args.documentInfo?.collection?.slug,\n args.documentInfo?.global?.slug,\n );\n}\n\nfunction findResolverBySlug(\n options: BuildLivePreviewUrlNullableOptions,\n collectionSlug: string | undefined,\n globalSlug: string | undefined,\n): NullablePathResolver | undefined {\n if (\n collectionSlug !== undefined &&\n options.collections !== undefined &&\n Object.hasOwn(options.collections, collectionSlug)\n ) {\n return options.collections[collectionSlug];\n }\n if (\n globalSlug !== undefined &&\n options.globals !== undefined &&\n Object.hasOwn(options.globals, globalSlug)\n ) {\n return options.globals[globalSlug];\n }\n return undefined;\n}\n\nfunction normaliseLocale(locale: LivePreviewUrlArgs['locale']): string | undefined {\n if (locale === undefined) return undefined;\n if (typeof locale === 'string') return locale.length > 0 ? locale : undefined;\n return typeof locale.code === 'string' && locale.code.length > 0 ? locale.code : undefined;\n}\n","/**\n * `payload-live-preview/plugin` configures Payload 2 or 3 without importing\n * either version. It owns URL selection and root preview metadata, while\n * authentication remains an explicit server-side integration.\n */\nimport { buildLivePreviewUrl, type LivePreviewUrlArgs } from './index';\n\nexport interface LivePreviewBreakpoint {\n readonly name: string;\n readonly label: string;\n readonly width: number | string;\n readonly height: number | string;\n}\n\nexport interface LivePreviewPluginOptions {\n /** Frontend origin, e.g. `https://site.example`. */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. */\n readonly collections?: Readonly<\n Record<\n string,\n | string\n | ((context: {\n readonly data: Record<string, unknown>;\n readonly locale: string | undefined;\n }) => string)\n >\n >;\n /** Per-global path resolvers keyed by global slug. */\n readonly globals?: Readonly<\n Record<\n string,\n | string\n | ((context: {\n readonly data: Record<string, unknown>;\n readonly locale: string | undefined;\n }) => string)\n >\n >;\n /** Path used when no resolver matches or one returns `''`. Default `/`. */\n readonly fallback?: string;\n /** Preview-intent query parameter. Keep it in the frontend adapter's `previewQueryParams`; `null` needs another intent signal. */\n readonly previewParam?: string | null;\n /** Device sizes displayed by Payload's live-preview toolbar. */\n readonly breakpoints?: readonly LivePreviewBreakpoint[];\n}\n\ntype UnknownRecord = Record<string, unknown>;\n\n/** Configure mapped entities and one shared live-preview URL callback. */\nexport function livePreview(\n options: LivePreviewPluginOptions,\n): <TConfig extends object>(config: TConfig) => TConfig {\n const resolveUrl = buildLivePreviewUrl(options);\n const collectionSlugs = Object.keys(options.collections ?? {});\n const globalSlugs = Object.keys(options.globals ?? {});\n\n return <TConfig extends object>(config: TConfig): TConfig => {\n const root = config as UnknownRecord;\n const admin = record(root['admin']);\n const current = record(admin['livePreview']);\n const currentUrl = current['url'];\n\n if (Object.hasOwn(current, 'url') && currentUrl !== resolveUrl) {\n throw new Error(\n 'payload-live-preview/plugin cannot replace an existing admin.livePreview.url',\n );\n }\n\n assertNoEntityUrl(root['collections'], collectionSlugs, 'collection');\n assertNoEntityUrl(root['globals'], globalSlugs, 'global');\n\n const configured: UnknownRecord = {\n ...current,\n collections: stableUnion(current['collections'], collectionSlugs),\n globals: stableUnion(current['globals'], globalSlugs),\n url: resolveUrl satisfies (args: LivePreviewUrlArgs) => string,\n };\n if (options.breakpoints !== undefined) {\n configured['breakpoints'] = options.breakpoints.map((breakpoint) => ({ ...breakpoint }));\n }\n\n return {\n ...root,\n admin: {\n ...admin,\n livePreview: configured,\n },\n } as TConfig;\n };\n}\n\nfunction assertNoEntityUrl(\n entities: unknown,\n selectedSlugs: readonly string[],\n kind: 'collection' | 'global',\n): void {\n if (!Array.isArray(entities) || selectedSlugs.length === 0) return;\n const selected = new Set(selectedSlugs);\n for (const candidate of entities) {\n const entity = record(candidate);\n const slug = entity['slug'];\n if (typeof slug !== 'string' || !selected.has(slug)) continue;\n const livePreviewConfig = record(record(entity['admin'])['livePreview']);\n if (Object.hasOwn(livePreviewConfig, 'url')) {\n throw new Error(\n `payload-live-preview/plugin cannot configure ${kind} \"${slug}\" because it already has admin.livePreview.url`,\n );\n }\n }\n}\n\nfunction stableUnion(existing: unknown, additions: readonly string[]): string[] {\n const values: string[] = [];\n const seen = new Set<string>();\n const current: readonly unknown[] = Array.isArray(existing)\n ? (existing as readonly unknown[])\n : [];\n const candidates: readonly unknown[] = [...current, ...additions];\n for (const value of candidates) {\n if (typeof value !== 'string') continue;\n if (seen.has(value)) continue;\n seen.add(value);\n values.push(value);\n }\n return values;\n}\n\nfunction record(value: unknown): UnknownRecord {\n return typeof value === 'object' && value !== null ? (value as UnknownRecord) : {};\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"plugin.js","names":["findResolverBySlug","options","collectionSlug","globalSlug","collections","Object","hasOwn","globals","livePreview","resolveUrl","base","baseUrl","replace","fallback","previewParam","args","locale","length","code","normaliseLocale","context","data","entry","collectionConfig","globalConfig","slug","documentInfo","collection","global","findResolver","path","resolved","startsWith","name","hashAt","indexOf","hash","slice","beforeHash","queryAt","query","values","URLSearchParams","getAll","endsWith","encodeURIComponent","withPreviewParam","buildLivePreviewUrl","collectionSlugs","keys","globalSlugs","identity","order","assign","config","root","admin","record","current","currentUrl","Error","assertNoEntityUrl","configured","stableUnion","url","breakpoints","map","breakpoint","entities","selectedSlugs","kind","Array","isArray","selected","Set","candidate","entity","has","livePreviewConfig","existing","additions","seen","candidates","value","add","push"],"sources":["../src/payload/index.ts","../src/payload/plugin.ts"],"sourcesContent":["/**\n * `payload-live-preview/payload` — helpers for `payload.config.ts`. It never\n * imports `payload`, only produces the callback `admin.livePreview.url` expects.\n */\n\n/** Arguments Payload passes to `admin.livePreview.url`. */\nexport interface LivePreviewUrlArgs {\n readonly data: Record<string, unknown>;\n readonly locale?: string | { readonly code?: string | null; readonly [extra: string]: unknown };\n readonly collectionConfig?: { readonly slug: string };\n readonly globalConfig?: { readonly slug: string };\n /** Payload 2 identifies the edited entity here instead of through the top-level configs. */\n readonly documentInfo?: {\n readonly collection?: {\n /** Payload 2 inherits this runtime value through a mapped config type. */\n readonly slug?: string;\n /** Structural anchor for Payload 2's published sanitized config type. */\n readonly fields?: unknown;\n };\n readonly global?: {\n /** Payload 2 inherits this runtime value through a mapped config type. */\n readonly slug?: string;\n /** Structural anchor for Payload 2's published sanitized config type. */\n readonly fields?: unknown;\n };\n };\n readonly [extra: string]: unknown;\n}\n\n/** Context handed to per-slug path resolvers. */\nexport interface PathResolverContext {\n readonly data: Record<string, unknown>;\n /** Normalised locale code, or `undefined`. */\n readonly locale: string | undefined;\n}\n\nexport type PathResolver = string | ((context: PathResolverContext) => string);\n\n/** A resolver that may decline a document: `null` means no preview target; `''` falls back. */\nexport type NullablePathResolver =\n string | null | ((context: PathResolverContext) => string | null);\n\nexport interface BuildLivePreviewUrlOptions {\n /** Frontend origin, e.g. `https://site.example`. */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. */\n readonly collections?: Readonly<Record<string, PathResolver>>;\n /** Per-global path resolvers keyed by global slug. */\n readonly globals?: Readonly<Record<string, PathResolver>>;\n /** Path when no resolver matches or one returns `''` (a draft without a slug). Default `/`. */\n readonly fallback?: string;\n /** Query parameter signalling preview intent; keep it in the adapter's `previewQueryParams`. Client-controlled, so it authorizes nothing. Default `'preview'`, `null` disables it. */\n readonly previewParam?: string | null;\n}\n\n/**\n * Like {@link BuildLivePreviewUrlOptions} with nullable resolvers: the callback\n * may return `null`, and no iframe beats one pointing at a public page.\n */\nexport interface BuildLivePreviewUrlNullableOptions {\n readonly baseUrl: string;\n readonly collections?: Readonly<Record<string, NullablePathResolver>>;\n readonly globals?: Readonly<Record<string, NullablePathResolver>>;\n /** `null` declines every unmapped document. Default `/`. */\n readonly fallback?: string | null;\n /** See {@link BuildLivePreviewUrlOptions.previewParam}. */\n readonly previewParam?: string | null;\n}\n\n/** Build an `admin.livePreview.url` callback from slug → path mappings. */\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlOptions,\n): (args: LivePreviewUrlArgs) => string;\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlNullableOptions,\n): (args: LivePreviewUrlArgs) => string | null;\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlNullableOptions,\n): (args: LivePreviewUrlArgs) => string | null {\n const base = options.baseUrl.replace(/\\/+$/, '');\n // `??` would swallow an explicit `null`, which is the whole point of the nullable form.\n const fallback = options.fallback === undefined ? '/' : options.fallback;\n const previewParam = options.previewParam === undefined ? 'preview' : options.previewParam;\n\n return (args) => {\n const locale = normaliseLocale(args.locale);\n const context: PathResolverContext = { data: args.data, locale };\n const entry = findResolver(options, args);\n\n let path: string | null = fallback;\n if (entry !== undefined) {\n const resolved = typeof entry === 'function' ? entry(context) : entry;\n if (resolved === null) return null;\n if (resolved.length > 0) path = resolved;\n }\n if (path === null) return null;\n if (!path.startsWith('/')) path = `/${path}`;\n return `${base}${previewParam === null ? path : withPreviewParam(path, previewParam)}`;\n };\n}\n\n/** `path` with `<name>=true` in its query — ahead of any `#fragment`, and not twice. */\nfunction withPreviewParam(path: string, name: string): string {\n const hashAt = path.indexOf('#');\n const hash = hashAt === -1 ? '' : path.slice(hashAt);\n const beforeHash = hashAt === -1 ? path : path.slice(0, hashAt);\n const queryAt = beforeHash.indexOf('?');\n const query = queryAt === -1 ? '' : beforeHash.slice(queryAt + 1);\n const values = new URLSearchParams(query).getAll(name);\n if (values[values.length - 1] === 'true') return path;\n const separator = queryAt === -1 ? '?' : query.length === 0 || query.endsWith('&') ? '' : '&';\n return `${beforeHash}${separator}${encodeURIComponent(name)}=true${hash}`;\n}\n\n/** The mapped resolver, or `undefined` when the slug is not mapped; a mapped `null` is a resolver in its own right. */\nfunction findResolver(\n options: BuildLivePreviewUrlNullableOptions,\n args: LivePreviewUrlArgs,\n): NullablePathResolver | undefined {\n // Payload 3's explicit callback arguments win as a pair. Looking through a\n // stale `documentInfo` when either is present could select the wrong entity.\n if (args.collectionConfig !== undefined || args.globalConfig !== undefined) {\n return findResolverBySlug(options, args.collectionConfig?.slug, args.globalConfig?.slug);\n }\n return findResolverBySlug(\n options,\n args.documentInfo?.collection?.slug,\n args.documentInfo?.global?.slug,\n );\n}\n\nfunction findResolverBySlug(\n options: BuildLivePreviewUrlNullableOptions,\n collectionSlug: string | undefined,\n globalSlug: string | undefined,\n): NullablePathResolver | undefined {\n if (\n collectionSlug !== undefined &&\n options.collections !== undefined &&\n Object.hasOwn(options.collections, collectionSlug)\n ) {\n return options.collections[collectionSlug];\n }\n if (\n globalSlug !== undefined &&\n options.globals !== undefined &&\n Object.hasOwn(options.globals, globalSlug)\n ) {\n return options.globals[globalSlug];\n }\n return undefined;\n}\n\nfunction normaliseLocale(locale: LivePreviewUrlArgs['locale']): string | undefined {\n if (locale === undefined) return undefined;\n if (typeof locale === 'string') return locale.length > 0 ? locale : undefined;\n return typeof locale.code === 'string' && locale.code.length > 0 ? locale.code : undefined;\n}\n","/**\n * `payload-live-preview/plugin` configures Payload 2, 3 or 4 without importing\n * any of them. It owns URL selection and root preview metadata, while\n * authentication remains an explicit server-side integration.\n */\nimport { buildLivePreviewUrl, type LivePreviewUrlArgs } from './index';\n\nexport interface LivePreviewBreakpoint {\n readonly name: string;\n readonly label: string;\n readonly width: number | string;\n readonly height: number | string;\n}\n\nexport interface LivePreviewPluginOptions {\n /** Frontend origin, e.g. `https://site.example`. */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. `null` means this document has no preview. */\n readonly collections?: Readonly<\n Record<\n string,\n | string\n | null\n | ((context: {\n readonly data: Record<string, unknown>;\n readonly locale: string | undefined;\n }) => string | null)\n >\n >;\n /** Per-global path resolvers keyed by global slug. `null` means this document has no preview. */\n readonly globals?: Readonly<\n Record<\n string,\n | string\n | null\n | ((context: {\n readonly data: Record<string, unknown>;\n readonly locale: string | undefined;\n }) => string | null)\n >\n >;\n /** Path used when no resolver matches or one returns `''`; `null` declines those documents. Default `/`. */\n readonly fallback?: string | null;\n /** Preview-intent query parameter. Keep it in the frontend adapter's `previewQueryParams`; `null` needs another intent signal. */\n readonly previewParam?: string | null;\n /** Device sizes displayed by Payload's live-preview toolbar. */\n readonly breakpoints?: readonly LivePreviewBreakpoint[];\n /** Where this plugin runs: Payload 3 and 4 sort plugins by ascending `order`, `0` when unset. Payload 2 keeps list order. */\n readonly order?: number;\n}\n\ntype UnknownRecord = Record<string, unknown>;\n\n/** Configure mapped entities and one shared live-preview URL callback. */\nexport function livePreview(options: LivePreviewPluginOptions): (<TConfig extends object>(\n config: TConfig,\n) => TConfig) & {\n /** Payload reads this name when another plugin looks this one up in `config.plugins`. */\n readonly slug: string;\n readonly order?: number;\n} {\n const resolveUrl = buildLivePreviewUrl(options);\n const collectionSlugs = Object.keys(options.collections ?? {});\n const globalSlugs = Object.keys(options.globals ?? {});\n\n const transform = <TConfig extends object>(config: TConfig): TConfig => {\n const root = config as UnknownRecord;\n const admin = record(root['admin']);\n const current = record(admin['livePreview']);\n const currentUrl = current['url'];\n\n if (Object.hasOwn(current, 'url') && currentUrl !== resolveUrl) {\n throw new Error(\n 'payload-live-preview/plugin cannot replace an existing admin.livePreview.url',\n );\n }\n\n assertNoEntityUrl(root['collections'], collectionSlugs, 'collection');\n assertNoEntityUrl(root['globals'], globalSlugs, 'global');\n\n const configured: UnknownRecord = {\n ...current,\n collections: stableUnion(current['collections'], collectionSlugs),\n globals: stableUnion(current['globals'], globalSlugs),\n url: resolveUrl satisfies (args: LivePreviewUrlArgs) => string | null,\n };\n if (options.breakpoints !== undefined) {\n configured['breakpoints'] = options.breakpoints.map((breakpoint) => ({ ...breakpoint }));\n }\n\n return {\n ...root,\n admin: {\n ...admin,\n livePreview: configured,\n },\n } as TConfig;\n };\n\n const identity: { slug: string; order?: number } = { slug: 'payload-live-preview' };\n if (options.order !== undefined) identity.order = options.order;\n return Object.assign(transform, identity);\n}\n\nfunction assertNoEntityUrl(\n entities: unknown,\n selectedSlugs: readonly string[],\n kind: 'collection' | 'global',\n): void {\n if (!Array.isArray(entities) || selectedSlugs.length === 0) return;\n const selected = new Set(selectedSlugs);\n for (const candidate of entities) {\n const entity = record(candidate);\n const slug = entity['slug'];\n if (typeof slug !== 'string' || !selected.has(slug)) continue;\n const livePreviewConfig = record(record(entity['admin'])['livePreview']);\n if (Object.hasOwn(livePreviewConfig, 'url')) {\n throw new Error(\n `payload-live-preview/plugin cannot configure ${kind} \"${slug}\" because it already has admin.livePreview.url`,\n );\n }\n }\n}\n\nfunction stableUnion(existing: unknown, additions: readonly string[]): string[] {\n const values: string[] = [];\n const seen = new Set<string>();\n const current: readonly unknown[] = Array.isArray(existing)\n ? (existing as readonly unknown[])\n : [];\n const candidates: readonly unknown[] = [...current, ...additions];\n for (const value of candidates) {\n if (typeof value !== 'string') continue;\n if (seen.has(value)) continue;\n seen.add(value);\n values.push(value);\n }\n return values;\n}\n\nfunction record(value: unknown): UnknownRecord {\n return typeof value === 'object' && value !== null ? (value as UnknownRecord) : {};\n}\n"],"mappings":"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","ignoreList":[]}
|
package/dist/plugins.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";function e(e){return("object"==typeof e&&null!==e||"function"==typeof e)&&"function"==typeof e.then&&(Promise.resolve(e).catch(()=>{}),!0)}function t(t){return(...n)=>{try{e(t(...n))}catch{}}}var n=t((...e)=>console.error(...e)),r=()=>{},i=class{#e;#t;#n=/* @__PURE__ */new Set;#r="staging";constructor(e,t){this.#e=e,this.#t=t}assertOpen(){if("closed"===this.#r)throw new Error(`Plugin context for "${this.#e}" is no longer active`)}get active(){return"active"===this.#r}eligible(){return"closed"!==this.#r}own(e){return this.assertOpen(),this.#i({kind:"cleanup",acquire:void 0,finalize:void 0,cleanup:e,disposed:!1})}stage(e,t,n){this.assertOpen();const r={kind:e,acquire:t,finalize:n,cleanup:void 0,disposed:!1},i=this.#i(r);if("active"===this.#r)try{this.#o(r)}catch(e){throw this.#s(r),e}return i}counts(){const e={transform:0,renderer:0,subscription:0,cleanup:0};for(const t of this.#n)e[t.kind]+=1;return e}commit(){if("staging"!==this.#r)throw new Error(`Plugin context for "${this.#e}" cannot be committed`);this.#r="committing";try{for(const e of this.#n)this.#o(e);this.#r="active"}catch(e){throw this.close(),e}}close(){if("closed"!==this.#r){this.#r="closed";for(const e of[...this.#n].reverse())this.#s(e);this.#n.clear()}}#i(e){return this.#n.add(e),()=>{this.#s(e)}}#o(e){if(e.disposed||void 0!==e.cleanup||void 0===e.acquire)return;const t=e.acquire();e.cleanup=t??r}#s(t){if(t.disposed)return;t.disposed=!0,this.#n.delete(t);const n=t.cleanup;if(t.cleanup=void 0,void 0!==n)try{e(n())&&this.#t(`plugin "${this.#e}" cleanup returned a Promise/thenable; cleanups must be synchronous`)}catch(e){this.#t(`plugin "${this.#e}" cleanup failed:`,e)}try{t.finalize?.()}catch(e){this.#t(`plugin "${this.#e}" cleanup failed:`,e)}}},o=class{#a;#c;#l=/* @__PURE__ */new Set;constructor(e,t){this.#a=e,this.#c=t}on(e,t){return this.#u("on",e,t)}once(e,t){return this.#u("once",e,t)}off(e,t){const n=t;for(const t of[...this.#l])t.event===e&&t.handler===n&&t.dispose()}emit(e,t){return this.#c.assertOpen(),this.#a.emit(e,t)}emitWhile(e,t,n){return this.#c.assertOpen(),this.#a.emitWhile(e,t,()=>{if(!this.#c.eligible())return!1;const e=n();return!!this.#c.eligible()&&e})}listenerCount(e){let t=0;for(const n of this.#l)n.event===e&&(t+=1);return t}removeAllListeners(e){for(const t of[...this.#l])void 0!==e&&t.event!==e||t.dispose()}eventNames(){const e=/* @__PURE__ */new Set;for(const t of this.#l)e.add(t.event);return[...e]}#u(e,t,n){this.#c.assertOpen();const i=n,o=[...this.#l].find(n=>n.kind===e&&n.event===t&&n.handler===i);if(void 0!==o)return o.dispose;let s=r,a=!0;const c=async t=>{this.#c.active&&a&&("once"===e&&s(),await n(t))},l={kind:e,event:t,handler:i,dispose:r};return s=this.#c.stage("subscription",()=>this.#a[e](t,c),()=>{a=!1,this.#l.delete(l)}),l.dispose=s,this.#l.add(l),s}},s="payload-live-preview-highlight",a=/* @__PURE__ */new WeakMap,c=/* @__PURE__ */new WeakMap,l={name:"highlight",version:"1.0.0",init:e=>{if("undefined"==typeof document||"undefined"==typeof window)return;const t="function"==typeof window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,n=function(e,t){let n=a.get(e);void 0===n||n.connected()||(a.delete(e),n=void 0),void 0===n&&(n=function(e,t){const n=e.getElementById(s);if(n instanceof HTMLStyleElement)return{pluginOwned:!1,connected:()=>n.isConnected,remove:()=>{},owners:0};const r=function(e,t){try{if(!Array.isArray(e.adoptedStyleSheets)||"function"!=typeof CSSStyleSheet)return;const n=new CSSStyleSheet;if("function"!=typeof n.replaceSync)return;return n.replaceSync(t),e.adoptedStyleSheets=[...e.adoptedStyleSheets,n],n}catch{return}}(e,t);if(void 0!==r)return{pluginOwned:!0,connected:()=>e.adoptedStyleSheets.includes(r),remove:()=>{e.adoptedStyleSheets=e.adoptedStyleSheets.filter(e=>e!==r)},owners:0};const i=e.createElement("style");return i.id=s,i.textContent=t,e.head.appendChild(i),{pluginOwned:!0,connected:()=>i.isConnected,remove:()=>{i.remove()},owners:0}}(e,t?".lp-highlight{outline:2px solid rgba(0,102,204,0.85);outline-offset:2px;}":"@keyframes lp-highlight{0%{outline:2px solid rgba(0,102,204,0.85);outline-offset:2px}100%{outline:2px solid transparent;outline-offset:2px}}.lp-highlight{animation:lp-highlight 0.6s ease-out;}"),a.set(e,n));const r=n;r.owners+=1;let i=!0;return()=>{i&&(i=!1,r.owners-=1,r.owners>0||(a.get(e)===r&&a.delete(e),r.pluginOwned&&r.remove()))}}(document,t),r=t?1e3:600,i=/* @__PURE__ */new WeakMap,o=/* @__PURE__ */new Set;e.registerCleanup?.(()=>{for(const e of[...o])e();n()}),e.events.on("elementUpdate",e=>{const t=e.element;i.get(t)?.();const n=function(e){let t=c.get(e);void 0===t&&(t={owners:0,pluginAdded:!e.classList.contains("lp-highlight")},c.set(e,t));const n=t;n.owners+=1,e.classList.add("lp-highlight");let r=!0;return()=>{r&&(r=!1,n.owners-=1,n.owners>0||(c.delete(e),n.pluginAdded&&e.classList.remove("lp-highlight")))}}(t);let s=!1;const a=()=>{s||(s=!0,window.clearTimeout(l),i.get(t)===a&&i.delete(t),o.delete(a),n())},l=window.setTimeout(a,r);o.add(a),i.set(t,a)})}},u={name:"debug",version:"1.0.0",init:e=>{e.events.on("init",()=>{e.log("init")}),e.events.on("connect",t=>{e.log("connect ←",t.origin)}),e.events.on("disconnect",t=>{e.log("disconnect (",t.reason,")")}),e.events.on("cacheRefresh",t=>{e.log("cacheRefresh",t.elementCount,"elements,",t.fieldCount,"fields")}),e.events.on("beforeUpdate",t=>{e.log("beforeUpdate",Object.keys(t.data.fields).length,"fields")}),e.events.on("afterUpdate",t=>{e.log("afterUpdate",t.updatedCount,"in",t.durationMs.toFixed(2),"ms")}),e.events.on("error",t=>{e.log("error in",t.context,":",t.error.message)})}},d="payload-live-preview:scroll";function h(){"undefined"!=typeof window&&(function(){if("undefined"!=typeof window)try{sessionStorage.setItem(d,JSON.stringify({href:window.location.href,x:window.scrollX,y:window.scrollY}))}catch{}}(),window.location.reload())}function f(e){if(null==e)return[];const t=/* @__PURE__ */new Set,n=[];for(const r of e.split(/[\s,]+/)){const e=r.trim();0===e.length||t.has(e)||(t.add(e),n.push(e))}return n}var p="data-payload-island";function g(e){return function(e){return"astro-island"===e.tagName.toLowerCase()||e.hasAttribute(p)}(e)&&!("patch"===e.getAttribute(p))}function isInsideIsland(e){let t=e;for(;null!==t;){if(g(t))return!0;t=t.parentElement}return!1}var m="data-payload-field",v="data-payload-depends",y="data-payload-guessed",w="data-payload-covers";function b(e){if((e.getAttribute("data-payload-fragment")??"").length>0)return"fragment";const t=e.getAttribute("data-payload-strategy");return null!==t?"route"===t?"route":void 0:e.hasAttribute(m)&&null!==e.closest("head")?"route":void 0}function P(e){switch(typeof e){case"string":return e.length>65536?void 0:`s:${e}`;case"number":return`n:${Object.is(e,-0)?"-0":String(e)}`;case"boolean":return"b:"+(e?"1":"0");case"bigint":return`i:${String(e)}`;case"undefined":return"u";case"object":{if(null===e)return"z";let t;try{t=JSON.stringify(e)}catch{return}return t.length>65536?void 0:`o:${t}`}case"symbol":case"function":return}}function S(e){return"object"==typeof e&&null!==e}function x(e){return Array.isArray(e)?"array":S(e)?"object":"scalar"}function L(e,t){return S(e)?e[t]:void 0}function A(e,t){return("string"==typeof t||"number"==typeof t)&&S(e)&&!Array.isArray(e)&&e.id===t}function k(e,t){if(!S(e)||!S(t))return A(e,t)||A(t,e)||P(e)===P(t);if(Array.isArray(e)!==Array.isArray(t))return!1;const n=Object.keys(t);return n.length===Object.keys(e).length&&n.every(n=>Object.hasOwn(e,n)&&k(L(e,n),L(t,n)))}function $(e,t){const n=P(t),r=P(e);return void 0!==n&&n===r||!(!A(e,t)&&!A(t,e))||void 0!==n&&void 0!==r&&k(e,t)}function C(e,t,n,r){const i=[];let o=0;const s=(e,t,n,a)=>{if(o+=1,r.covers(e)||$(t,n))return;if(!((void 0===t||x(t)===x(n))&&S(n)&&r.reachesBelow(e)&&a<8))return void i.push({path:e,value:n});const c=function(e,t){const n=new Set(Object.keys(t));if(S(e))for(const t of Object.keys(e))n.add(t);return[...n]}(t,n);0===c.length&&i.push({path:e,value:n});for(const r of c){if(o>=1024)return void i.push({path:e,value:n});s(`${e}.${r}`,L(t,r),L(n,r),a+1)}};return s(e,t,n,0),i}var N=/* @__PURE__ */new Set(["id","_id","createdAt","updatedAt","createdBy","updatedBy","_status","globalType","collection","locale","localized"]);function O(e,t){if(void 0===t||0===t.length)return e;const n=`_${t}`;return e.endsWith(n)?e.slice(0,-n.length):e}function T(e,t){const n=new Set(e),r=[...t],i=(e,t)=>{const n=`${t}.`;for(const t of e)if(t.startsWith(n))return!0;return!1};return{covers:e=>n.has(e)||r.some(t=>t===e||e.startsWith(`${t}.`)),reachesBelow:e=>i(n,e)||i(r,e)}}var E="payload-live-preview-unbound",U={"bottom-right":"bottom:12px;right:12px;","bottom-left":"bottom:12px;left:12px;","top-right":"top:12px;right:12px;","top-left":"top:12px;left:12px;"};function R(e,t,n,r=[],i="descendant"){const o=[...t],s=function(e,t,n){const r=T(e,n),i=e=>r.covers(e)||r.reachesBelow(e);return e=>{if(i(e))return!0;const n=O(e,t);return n!==e&&i(n)}}(o,n,r),a=Object.keys(e).filter(e=>!N.has(e)&&!s(e));return"declared"===i&&a.push(...function(e,t,n,r){const i=T(t,r),o=[];for(const[t,r]of Object.entries(e)){if(N.has(t))continue;const e=O(t,n);if(!i.covers(e)&&i.reachesBelow(e))for(const{path:t}of C(e,void 0,r,i))o.push(t)}return o}(e,o,n,r)),[...new Set(a)].sort((e,t)=>e.localeCompare(t))}function z(e,t){const n=e.createElement("textarea");n.value=t,n.setAttribute("readonly",""),n.style.cssText="position:fixed;opacity:0;pointer-events:none;",e.body.append(n),n.select(),n.remove()}function F(e,t,n){const r=e.createElement("button");return r.type="button",r.textContent=n,r.style.cssText="display:block;width:100%;text-align:left;margin:2px 0;padding:2px 4px;border:0;border-radius:3px;background:#222;color:#7fd1ff;font:inherit;cursor:pointer;",r.title=`Copy ${m}="${t}"`,r.addEventListener("click",()=>{!function(e,t){const n=e.defaultView?.navigator.clipboard;null==n?z(e,t):n.writeText(t).catch(()=>{z(e,t)})}(e,`${m}="${t}"`),r.textContent=`${n} ✓`}),r}var q=Object.freeze({NoTrustedOrigin:"LP0101",ReferrerOnlyTrust:"LP0102",PluginIncompatible:"LP0103",ProfileFeatureOmitted:"LP0104",OrphanField:"LP0201",UnattributableUpdate:"LP0202",UnboundField:"LP0203",VisibilityGateDeferred:"LP0301",UnsafeAttributeWrite:"LP0401",TextTargetHasChildren:"LP0402",MissingArrayTemplate:"LP0403",StructuralItemUnkeyed:"LP0404",StructuralDuplicateKey:"LP0405",StructuralUnstableKeys:"LP0406",UnsupportedStrategy:"LP0407",UnknownValueFormat:"LP0408",SanitizerDroppedAttribute:"LP0409",UnrenderedBlockKept:"LP0410",UnfaithfulPatch:"LP0411",ServerFormatReplaced:"LP0412",UnrenderedBlockLost:"LP0413",MessageRejected:"LP0501",TokenRejected:"LP0502",ProtocolShapeUnknown:"LP0503",HandlerThrew:"LP0601",TransformThrew:"LP0602",RendererThrew:"LP0603",StartupFailed:"LP0605",ReadyFailed:"LP0606",HydrationWaitTimedOut:"LP0607",AuditRuntimeMissing:"LP0701",AuditNoFrameAncestors:"LP0702",AuditFrameOptionsBlocks:"LP0703",AuditBindingsExposed:"LP0704",AuditGateThresholdExceeded:"LP0705",AuditUnownedBindings:"LP0706",AuditNoBindings:"LP0707",AuditNotAPage:"LP0708",FragmentRequestFailed:"LP0801",FragmentResponseInvalid:"LP0802",FragmentUnauthorized:"LP0803",FragmentSuperseded:"LP0804",RouteRefreshLoop:"LP0805",FragmentStrategyUnavailable:"LP0806",UnboundChangeRefresh:"LP0807",EscalationUnavailable:"LP0808",IslandStartUnavailable:"LP0809",RouteRefreshUnconfirmed:"LP0810",V2ReadinessGap:"LP0709",RuntimeOnPublicPage:"LP0710"});exports.DIAGNOSTIC_CODES=q,exports.EventEmitter=class{#d=/* @__PURE__ */new Map;#h=/* @__PURE__ */new Map;on(e,t){return this.#f(this.#d,e,t)}once(e,t){return this.#f(this.#h,e,t)}off(e,t){this.#p(this.#d,e,t),this.#p(this.#h,e,t)}async emit(e,t){await this.#g(e,t)}async emitWhile(e,t,n){return this.#g(e,t,n)}async#g(e,t,n){const r=()=>n?.()??!0;if(!r())return!1;const i=this.#d.get(e);if(i)for(const n of[...i]){if(!r())return!1;if(await this.#m(n,t,e),!r())return!1}if(!r())return!1;const o=this.#h.get(e);if(o&&o.size>0){const n=[...o];this.#h.delete(e);for(const i of n){if(!r())return!1;if(await this.#m(i,t,e),!r())return!1}}return r()}listenerCount(e){return(this.#d.get(e)?.size??0)+(this.#h.get(e)?.size??0)}removeAllListeners(e){if(void 0===e)return this.#d.clear(),void this.#h.clear();this.#d.delete(e),this.#h.delete(e)}eventNames(){const e=/* @__PURE__ */new Set;for(const t of this.#d.keys())e.add(t);for(const t of this.#h.keys())e.add(t);return[...e]}#f(e,t,n){let r=e.get(t);return r||(r=/* @__PURE__ */new Set,e.set(t,r)),r.add(n),()=>{this.#p(e,t,n)}}#p(e,t,n){const r=e.get(t);void 0!==r&&(r.delete(n),0===r.size&&e.delete(t))}async#m(e,t,r){try{await e(t)}catch(e){const t="string"==typeof r||"number"==typeof r?String(r):"<event>";n(`[live-preview] LP0601: handler for "${t}" threw:`,e)}}},exports.PluginManager=class{#a;#v;#y;#w;#t;#b=/* @__PURE__ */new Map;#P=/* @__PURE__ */new Map;#S=/* @__PURE__ */new Map;#x=/* @__PURE__ */new Set;#L=/* @__PURE__ */new Map;#A=Promise.resolve();#k=0;constructor(e){this.#a=e.events,this.#v=e.config,this.#y=e.registerFieldRenderer,this.#t=t(e.log);const n=e.onTransformError;this.#w=void 0===n?void 0:t((...e)=>{const t=e[0];try{return n(t)}catch(e){return void this.#t("transform error reporter failed:",e)}})}register(e){return this.#k>0?this.#$(e,!1):this.#C(()=>this.#$(e,!0))}unregister(e){return this.#k>0?this.#N(e,!1):this.#C(async()=>{await this.#N(e,!0)})}destroyAll(){return this.#k>0?this.#O(!1):this.#C(async()=>{await this.#O(!0)})}applyTransforms(t,n,r,i){const o=this.#L.get(t);if(void 0===o||0===o.length)return n;let s=n;for(const a of[...o]){if(!a.active)continue;const{transform:o}=a;if(!1===i?.())return n;try{s=o(s,{fieldName:t,element:r.element,allFields:r.allFields});const a=e(s);if(!1===i?.())return n;if(a)throw new TypeError(`Transform for "${t}" returned a Promise/thenable; transforms must be synchronous`)}catch(e){if(!1===i?.())return n;const r=e instanceof Error?e:new Error(String(e));return this.#t(`transform for "${t}" failed:`,r),this.#w?.(r),n}}return s}list(){return[...this.#b.keys()]}snapshot(){const e=[],t=(e,t,n,r)=>{const i=r.counts();return{name:e,version:t,state:n,registrations:{transforms:i.transform,renderers:i.renderer,subscriptions:i.subscription,cleanups:i.cleanup}}};for(const[n,r]of this.#P)e.push(t(n,void 0,"initializing",r.scope));for(const[n,r]of this.#b)e.push(t(n,r.plugin.version,"active",r.scope));for(const t of this.#S.keys())e.push({name:t,version:void 0,state:"tearing-down",registrations:{transforms:0,renderers:0,subscriptions:0,cleanups:0}});return e}get size(){return this.#b.size}async#$(e,t){if(this.#b.has(e.name)||this.#P.has(e.name)||this.#S.has(e.name))return void this.#t(`plugin "${e.name}" already registered`);const n=function(e,t){if(void 0!==e){if(void 0!==e.runtime&&!function(e,t){const n=function(e){const t=/^v?(\d+)\.(\d+)\.(\d+)/.exec(e.trim());if(null!==t)return[Number(t[1]),Number(t[2]),Number(t[3])]}(e);return void 0!==n&&t.split("||").some(e=>{const r=e.trim().split(/\s+/).filter(e=>e.length>0);return 0===r.length?""===e.trim()&&""===t.trim():r.every(e=>function(e,t){const n=t.trim();if(""===n||"*"===n)return!0;const r=/^(\^|~|>=|<=|>|<|=)?\s*v?(\d+)\.(\d+)\.(\d+)/.exec(n);if(null===r)return!1;const i=r[1]??"=",o=[Number(r[2]),Number(r[3]),Number(r[4])],s=function(e,t){for(let n=0;n<3;n+=1){const r=(e[n]??0)-(t[n]??0);if(0!==r)return r}return 0}(e,o);switch(i){case"=":return 0===s;case">":return s>0;case">=":return s>=0;case"<":return s<0;case"<=":return s<=0;case"~":return s>=0&&e[0]===o[0]&&e[1]===o[1];case"^":return!(s<0)&&(o[0]>0?e[0]===o[0]:o[1]>0?0===e[0]&&e[1]===o[1]:0===e[0]&&0===e[1]&&e[2]===o[2]);default:return!1}}(n,e))})}(t,e.runtime))return`declares runtime ${e.runtime}, this runtime is ${t}`;if(void 0!==e.protocol){if(!Number.isInteger(e.protocol)||e.protocol<1)return`declares an invalid protocol version ${String(e.protocol)}`;if(e.protocol<4)return`declares protocol ${String(e.protocol)}, this runtime speaks ${String(4)}`}}}(e.compat,"2.2.2");if(void 0!==n)return void this.#T(e.name,n);const r=new i(e.name,this.#t),o=this.#E(e.name,r),s={scope:r,cancelled:!1};this.#P.set(e.name,s);try{if(await this.#U(()=>e.init(o),t),s.cancelled)return;r.commit()}catch(t){return r.close(),void(s.cancelled||this.#t(`plugin "${e.name}" init failed:`,t))}finally{this.#P.get(e.name)===s&&this.#P.delete(e.name)}this.#b.set(e.name,{plugin:e,scope:r}),this.#t(`plugin "${e.name}" registered`)}#T(e,t){const n=`plugin "${e}" refused: ${t}`;this.#t(n),this.#a.emit("error",{error:new Error(n),context:"plugin",code:"LP0103"})}#E(e,t){return{events:new o(this.#a,t),registerFieldRenderer:e=>{t.stage("renderer",()=>{const t=this.#y(e);return"function"==typeof t?t:void 0})},registerTransform:(e,n)=>{const r={transform:n,active:!1};t.stage("transform",()=>{r.active=!0;const t=this.#L.get(e);return void 0===t?this.#L.set(e,[r]):t.push(r),()=>{r.active=!1;const t=this.#L.get(e);if(void 0===t)return;const n=t.indexOf(r);n>=0&&t.splice(n,1),0===t.length&&this.#L.delete(e)}})},registerCleanup:e=>{t.own(e)},getConfig:()=>this.#v,log:(...t)=>{this.#t(`[${e}]`,...t)}}}#N(e,t){const n=this.#P.get(e);if(void 0!==n)return n.cancelled=!0,n.scope.close(),Promise.resolve();const r=this.#S.get(e);if(void 0!==r)return this.#x.has(e)?Promise.resolve():t?this.#R(r):r;const i=this.#b.get(e);if(void 0===i)return Promise.resolve();this.#b.delete(e),i.scope.close();const o=Promise.resolve().then(()=>this.#z(e,i.plugin,t));return this.#S.set(e,o),o.then(()=>{this.#S.get(e)===o&&this.#S.delete(e)}),o}async#z(e,t,n){if(void 0!==t.destroy){this.#x.add(e);try{await this.#U(()=>t.destroy?.(),n)}catch(t){this.#t(`plugin "${e}" destroy failed:`,t)}finally{this.#x.delete(e)}}}async#O(e){for(const e of this.#P.values())e.cancelled=!0,e.scope.close();const t=[...this.#b.keys()];for(const n of t)await this.#N(n,e)}async#U(e,t){t?await this.#R(Promise.resolve().then(e)):await e()}async#R(e){this.#k+=1;try{await e}finally{this.#k-=1}}#C(e){const t=this.#A.then(e);return this.#A=t.catch(e=>{this.#t("plugin manager mutation failed:",e)}),t}},exports.createAnalyticsPlugin=function(){let e=0,t=0,n=0;return{name:"analytics",version:"1.0.0",init:r=>{r.events.on("afterUpdate",r=>{e+=1,t+=r.updatedCount,n+=r.durationMs})},getStats:()=>({updateCount:e,totalElements:t,totalDurationMs:n,averageDurationMs:0===e?0:n/e})}},exports.createUnboundFieldsOverlayPlugin=function(e={}){return{name:"unbound-fields",version:"1.0.0",init:t=>{const n=e.root??("undefined"==typeof document?void 0:document);if(void 0===n)return;if((e.onlyWithDebug??1)&&!0!==t.getConfig().debug)return void t.log("not mounted: the client runs without `debug: true`");const r=function(e,t){const n=function(e){return 9===e.nodeType?e:e.ownerDocument}(e);if(null==n?.body)return null;const r=n.createElement("aside");r.id=E,r.style.cssText="position:fixed;z-index:2147483646;max-width:280px;max-height:40vh;overflow:auto;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;background:#111;color:#eee;border:1px solid #333;border-radius:6px;padding:8px 10px;box-shadow:0 4px 16px rgba(0,0,0,0.4);"+t,r.setAttribute("aria-hidden","true"),r.hidden=!0;const i=e=>{const t=n.createElement("div");return t.textContent=e,t.style.cssText="font-weight:600;margin-bottom:4px;",t},o=i("Unbound fields"),s=n.createElement("div"),a=i("Guessed bindings");a.setAttribute("data-testid","guessed-bindings");const c=n.createElement("div");return r.append(o,s,a,c),n.body.append(r),{update:(e,t)=>{r.isConnected||(n.getElementById(E)?.remove(),n.body.append(r)),r.hidden=0===e.length&&0===t.length,o.hidden=0===e.length,s.replaceChildren(...e.map(e=>F(n,e,e))),a.hidden=0===t.length,c.replaceChildren(...t.map(({field:e,matched:t})=>F(n,e,`${e} ← ${JSON.stringify(t)}`)))},destroy:()=>{r.remove()}}}(n,U[e.position??"bottom-right"]);if(null===r)return;t.registerCleanup?.(r.destroy);const i="declared"===t.getConfig().subfieldCoverage?"declared":"descendant",o=t.getConfig().strategies??{};t.events.on("afterUpdate",e=>{const s=R(e.data.fields,function(e){const t=[];for(const n of e.querySelectorAll(`[${m}]`)){const e=n.getAttribute(m);null!==e&&e.length>0&&t.push(e)}return t}(n),e.data.locale,function(e,t){const n=[];for(const t of e.querySelectorAll(`[${w}]`))n.push(...f(t.getAttribute(w)));for(const r of e.querySelectorAll(`[${v}]`)){const e=b(r);void 0!==e&&void 0!==t[e]&&(isInsideIsland(r)||n.push(...f(r.getAttribute(v))))}return n}(n,o),i),a=function(e){const t=[];for(const n of e.querySelectorAll(`[${y}]`)){const e=n.getAttribute(m);null!==e&&0!==e.length&&t.push({field:e,matched:n.getAttribute(y)??""})}return t}(n);r.update(s,a),s.length>0&&t.log("unbound:",s.join(", ")),a.length>0&&t.log("guessed:",a.map(e=>e.field).join(", "))})}}},exports.debugPlugin=u,exports.documentSavePlugin=function(e={}){const t=e.strategy??"silent";return{name:"document-save",version:"1.1.0",init:n=>{let r=!0;const i=/* @__PURE__ */new Set;n.registerCleanup?.(()=>{r=!1;for(const e of i)e.abort();i.clear()}),function(){if("undefined"!=typeof window)try{const e=sessionStorage.getItem(d);if(null===e)return;sessionStorage.removeItem(d);const t=JSON.parse(e);if(t.href!==window.location.href)return;window.scrollTo(t.x??0,t.y??0)}catch{}}(),n.events.on("documentSave",()=>{if(!r)return;if("silent"===t)return;if("reload"===t)return void h();const o=new AbortController;i.add(o);const s="fetch"===t?async function(e,t,n){if(e.handler)try{await e.handler(n)}catch(e){if(!r||n.aborted)return;t("document-save handler threw:",e)}else t("document-save: fetch strategy selected but no handler supplied")}(e,n.log,o.signal):async function(e,t,n,r){if("undefined"==typeof fetch)return void t("document-save: revalidate strategy needs fetch — not available");const i=e.revalidateUrl??"/api/revalidate";let o=!1;try{const s=await fetch(i,{method:"POST",signal:n,headers:{"Content-Type":"application/json",...e.revalidateHeaders??{}},body:JSON.stringify({source:"payload-live-preview"})});if(!r()||n.aborted)return;o=s.ok,o||t("document-save revalidate non-2xx:",s.status)}catch(e){if(!r()||n.aborted)return;t("document-save revalidate failed:",e)}o||"reload"!==e.onRevalidateFailure||h()}(e,n.log,o.signal,()=>r);s.finally(()=>{i.delete(o)})})}}},exports.highlightPlugin=l,exports.unboundFieldNames=R;
|
|
1
|
+
"use strict";function e(e){return("object"==typeof e&&null!==e||"function"==typeof e)&&"function"==typeof e.then&&(Promise.resolve(e).catch(()=>{}),!0)}function t(t){return(...n)=>{try{e(t(...n))}catch{}}}var n=t((...e)=>console.error(...e)),r=()=>{},i=class{#e;#t;#n=/* @__PURE__ */new Set;#r="staging";constructor(e,t){this.#e=e,this.#t=t}assertOpen(){if("closed"===this.#r)throw new Error(`Plugin context for "${this.#e}" is no longer active`)}get active(){return"active"===this.#r}eligible(){return"closed"!==this.#r}own(e){return this.assertOpen(),this.#i({kind:"cleanup",acquire:void 0,finalize:void 0,cleanup:e,disposed:!1})}stage(e,t,n){this.assertOpen();const r={kind:e,acquire:t,finalize:n,cleanup:void 0,disposed:!1},i=this.#i(r);if("active"===this.#r)try{this.#o(r)}catch(e){throw this.#s(r),e}return i}counts(){const e={transform:0,renderer:0,subscription:0,cleanup:0};for(const t of this.#n)e[t.kind]+=1;return e}commit(){if("staging"!==this.#r)throw new Error(`Plugin context for "${this.#e}" cannot be committed`);this.#r="committing";try{for(const e of this.#n)this.#o(e);this.#r="active"}catch(e){throw this.close(),e}}close(){if("closed"!==this.#r){this.#r="closed";for(const e of[...this.#n].reverse())this.#s(e);this.#n.clear()}}#i(e){return this.#n.add(e),()=>{this.#s(e)}}#o(e){if(e.disposed||void 0!==e.cleanup||void 0===e.acquire)return;const t=e.acquire();e.cleanup=t??r}#s(t){if(t.disposed)return;t.disposed=!0,this.#n.delete(t);const n=t.cleanup;if(t.cleanup=void 0,void 0!==n)try{e(n())&&this.#t(`plugin "${this.#e}" cleanup returned a Promise/thenable; cleanups must be synchronous`)}catch(e){this.#t(`plugin "${this.#e}" cleanup failed:`,e)}try{t.finalize?.()}catch(e){this.#t(`plugin "${this.#e}" cleanup failed:`,e)}}},o=class{#a;#u;#l=/* @__PURE__ */new Set;constructor(e,t){this.#a=e,this.#u=t}on(e,t){return this.#c("on",e,t)}once(e,t){return this.#c("once",e,t)}off(e,t){const n=t;for(const t of[...this.#l])t.event===e&&t.handler===n&&t.dispose()}emit(e,t){return this.#u.assertOpen(),this.#a.emit(e,t)}emitWhile(e,t,n){return this.#u.assertOpen(),this.#a.emitWhile(e,t,()=>{if(!this.#u.eligible())return!1;const e=n();return!!this.#u.eligible()&&e})}listenerCount(e){let t=0;for(const n of this.#l)n.event===e&&(t+=1);return t}removeAllListeners(e){for(const t of[...this.#l])void 0!==e&&t.event!==e||t.dispose()}eventNames(){const e=/* @__PURE__ */new Set;for(const t of this.#l)e.add(t.event);return[...e]}#c(e,t,n){this.#u.assertOpen();const i=n,o=[...this.#l].find(n=>n.kind===e&&n.event===t&&n.handler===i);if(void 0!==o)return o.dispose;let s=r,a=!0;const u=async t=>{this.#u.active&&a&&("once"===e&&s(),await n(t))},l={kind:e,event:t,handler:i,dispose:r};return s=this.#u.stage("subscription",()=>this.#a[e](t,u),()=>{a=!1,this.#l.delete(l)}),l.dispose=s,this.#l.add(l),s}},s="payload-live-preview-highlight",a=/* @__PURE__ */new WeakMap,u=/* @__PURE__ */new WeakMap,l={name:"highlight",version:"1.0.0",init:e=>{if("undefined"==typeof document||"undefined"==typeof window)return;const t="function"==typeof window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,n=function(e,t){let n=a.get(e);void 0===n||n.connected()||(a.delete(e),n=void 0),void 0===n&&(n=function(e,t){const n=e.getElementById(s);if(n instanceof HTMLStyleElement)return{pluginOwned:!1,connected:()=>n.isConnected,remove:()=>{},owners:0};const r=function(e,t){try{if(!Array.isArray(e.adoptedStyleSheets)||"function"!=typeof CSSStyleSheet)return;const n=new CSSStyleSheet;if("function"!=typeof n.replaceSync)return;return n.replaceSync(t),e.adoptedStyleSheets=[...e.adoptedStyleSheets,n],n}catch{return}}(e,t);if(void 0!==r)return{pluginOwned:!0,connected:()=>e.adoptedStyleSheets.includes(r),remove:()=>{e.adoptedStyleSheets=e.adoptedStyleSheets.filter(e=>e!==r)},owners:0};const i=e.createElement("style");return i.id=s,i.textContent=t,e.head.appendChild(i),{pluginOwned:!0,connected:()=>i.isConnected,remove:()=>{i.remove()},owners:0}}(e,t?".lp-highlight{outline:2px solid rgba(0,102,204,0.85);outline-offset:2px;}":"@keyframes lp-highlight{0%{outline:2px solid rgba(0,102,204,0.85);outline-offset:2px}100%{outline:2px solid transparent;outline-offset:2px}}.lp-highlight{animation:lp-highlight 0.6s ease-out;}"),a.set(e,n));const r=n;r.owners+=1;let i=!0;return()=>{i&&(i=!1,r.owners-=1,r.owners>0||(a.get(e)===r&&a.delete(e),r.pluginOwned&&r.remove()))}}(document,t),r=t?1e3:600,i=/* @__PURE__ */new WeakMap,o=/* @__PURE__ */new Set;e.registerCleanup?.(()=>{for(const e of[...o])e();n()}),e.events.on("elementUpdate",e=>{const t=e.element;i.get(t)?.();const n=function(e){let t=u.get(e);void 0===t&&(t={owners:0,pluginAdded:!e.classList.contains("lp-highlight")},u.set(e,t));const n=t;n.owners+=1,e.classList.add("lp-highlight");let r=!0;return()=>{r&&(r=!1,n.owners-=1,n.owners>0||(u.delete(e),n.pluginAdded&&e.classList.remove("lp-highlight")))}}(t);let s=!1;const a=()=>{s||(s=!0,window.clearTimeout(l),i.get(t)===a&&i.delete(t),o.delete(a),n())},l=window.setTimeout(a,r);o.add(a),i.set(t,a)})}},c={name:"debug",version:"1.0.0",init:e=>{e.events.on("init",()=>{e.log("init")}),e.events.on("connect",t=>{e.log("connect ←",t.origin)}),e.events.on("disconnect",t=>{e.log("disconnect (",t.reason,")")}),e.events.on("cacheRefresh",t=>{e.log("cacheRefresh",t.elementCount,"elements,",t.fieldCount,"fields")}),e.events.on("beforeUpdate",t=>{e.log("beforeUpdate",Object.keys(t.data.fields).length,"fields")}),e.events.on("afterUpdate",t=>{e.log("afterUpdate",t.updatedCount,"in",t.durationMs.toFixed(2),"ms")}),e.events.on("error",t=>{e.log("error in",t.context,":",t.error.message)})}},d="payload-live-preview:scroll";function h(){"undefined"!=typeof window&&(function(){if("undefined"!=typeof window)try{sessionStorage.setItem(d,JSON.stringify({href:window.location.href,x:window.scrollX,y:window.scrollY}))}catch{}}(),window.location.reload())}function f(e){if(null==e)return[];const t=/* @__PURE__ */new Set,n=[];for(const r of e.split(/[\s,]+/)){const e=r.trim();0===e.length||t.has(e)||(t.add(e),n.push(e))}return n}var p="data-payload-island";function g(e){return function(e){return"astro-island"===e.tagName.toLowerCase()||e.hasAttribute(p)}(e)&&!("patch"===e.getAttribute(p))}function isInsideIsland(e){let t=e;for(;null!==t;){if(g(t))return!0;t=t.parentElement}return!1}var m="data-payload-field",v="data-payload-depends",y="data-payload-guessed",w="data-payload-covers";function b(e){if((e.getAttribute("data-payload-fragment")??"").length>0)return"fragment";const t=e.getAttribute("data-payload-strategy");return null!==t?"route"===t?"route":void 0:e.hasAttribute(m)&&null!==e.closest("head")?"route":void 0}function P(e){switch(typeof e){case"string":return e.length>65536?void 0:`s:${e}`;case"number":return`n:${Object.is(e,-0)?"-0":String(e)}`;case"boolean":return"b:"+(e?"1":"0");case"bigint":return`i:${String(e)}`;case"undefined":return"u";case"object":{if(null===e)return"z";let t;try{t=JSON.stringify(e)}catch{return}return t.length>65536?void 0:`o:${t}`}case"symbol":case"function":return}}function S(e){return"object"==typeof e&&null!==e}function x(e){return Array.isArray(e)?"array":S(e)?"object":"scalar"}function L(e,t){return S(e)?e[t]:void 0}function A(e,t){return("string"==typeof t||"number"==typeof t)&&S(e)&&!Array.isArray(e)&&e.id===t}function k(e,t){if(!S(e)||!S(t))return A(e,t)||A(t,e)||P(e)===P(t);if(Array.isArray(e)!==Array.isArray(t))return!1;const n=Object.keys(t);return n.length===Object.keys(e).length&&n.every(n=>Object.hasOwn(e,n)&&k(L(e,n),L(t,n)))}function C(e,t){const n=P(t),r=P(e);return void 0!==n&&n===r||!(!A(e,t)&&!A(t,e))||void 0!==n&&void 0!==r&&k(e,t)}function $(e,t,n,r){const i=[];let o=0;const s=(e,t,n,a)=>{if(o+=1,r.covers(e)||C(t,n))return;if(!((void 0===t||x(t)===x(n))&&S(n)&&r.reachesBelow(e)&&a<8))return void i.push({path:e,value:n});const u=function(e,t){const n=new Set(Object.keys(t));if(S(e))for(const t of Object.keys(e))n.add(t);return[...n]}(t,n);0===u.length&&i.push({path:e,value:n});for(const r of u){if(o>=1024)return void i.push({path:e,value:n});s(`${e}.${r}`,L(t,r),L(n,r),a+1)}};return s(e,t,n,0),i}var N=/* @__PURE__ */new Set(["id","_id","createdAt","updatedAt","createdBy","updatedBy","_status","globalType","collection","locale","localized"]);function O(e,t){if(void 0===t||0===t.length)return e;const n=`_${t}`;return e.endsWith(n)?e.slice(0,-n.length):e}function T(e,t){const n=new Set(e),r=[...t],i=(e,t)=>{const n=`${t}.`;for(const t of e)if(t.startsWith(n))return!0;return!1};return{covers:e=>n.has(e)||r.some(t=>t===e||e.startsWith(`${t}.`)),reachesBelow:e=>i(n,e)||i(r,e)}}var E="payload-live-preview-unbound",U={"bottom-right":"bottom:12px;right:12px;","bottom-left":"bottom:12px;left:12px;","top-right":"top:12px;right:12px;","top-left":"top:12px;left:12px;"};function F(e,t,n,r=[],i="descendant"){const o=[...t],s=function(e,t,n){const r=T(e,n),i=e=>r.covers(e)||r.reachesBelow(e);return e=>{if(i(e))return!0;const n=O(e,t);return n!==e&&i(n)}}(o,n,r),a=Object.keys(e).filter(e=>!N.has(e)&&!s(e));return"declared"===i&&a.push(...function(e,t,n,r){const i=T(t,r),o=[];for(const[t,r]of Object.entries(e)){if(N.has(t))continue;const e=O(t,n);if(!i.covers(e)&&i.reachesBelow(e))for(const{path:t}of $(e,void 0,r,i))o.push(t)}return o}(e,o,n,r)),[...new Set(a)].sort((e,t)=>e.localeCompare(t))}function R(e,t){const n=e.createElement("textarea");n.value=t,n.setAttribute("readonly",""),n.style.cssText="position:fixed;opacity:0;pointer-events:none;",e.body.append(n),n.select(),n.remove()}function z(e,t,n){const r=e.createElement("button");return r.type="button",r.textContent=n,r.style.cssText="display:block;width:100%;text-align:left;margin:2px 0;padding:2px 4px;border:0;border-radius:3px;background:#222;color:#7fd1ff;font:inherit;cursor:pointer;",r.title=`Copy ${m}="${t}"`,r.addEventListener("click",()=>{!function(e,t){const n=e.defaultView?.navigator.clipboard;null==n?R(e,t):n.writeText(t).catch(()=>{R(e,t)})}(e,`${m}="${t}"`),r.textContent=`${n} ✓`}),r}var M=Object.freeze({NoTrustedOrigin:"LP0101",ReferrerOnlyTrust:"LP0102",PluginIncompatible:"LP0103",ProfileFeatureOmitted:"LP0104",OrphanField:"LP0201",UnattributableUpdate:"LP0202",UnboundField:"LP0203",CoverageDefaultChanges:"LP0204",VisibilityGateDeferred:"LP0301",UnsafeAttributeWrite:"LP0401",TextTargetHasChildren:"LP0402",MissingArrayTemplate:"LP0403",StructuralItemUnkeyed:"LP0404",StructuralDuplicateKey:"LP0405",StructuralUnstableKeys:"LP0406",UnsupportedStrategy:"LP0407",UnknownValueFormat:"LP0408",SanitizerDroppedAttribute:"LP0409",UnrenderedBlockKept:"LP0410",UnfaithfulPatch:"LP0411",ServerFormatReplaced:"LP0412",UnrenderedBlockLost:"LP0413",MessageRejected:"LP0501",TokenRejected:"LP0502",ProtocolShapeUnknown:"LP0503",HandlerThrew:"LP0601",TransformThrew:"LP0602",RendererThrew:"LP0603",StartupFailed:"LP0605",ReadyFailed:"LP0606",HydrationWaitTimedOut:"LP0607",AuditRuntimeMissing:"LP0701",AuditNoFrameAncestors:"LP0702",AuditFrameOptionsBlocks:"LP0703",AuditBindingsExposed:"LP0704",AuditGateThresholdExceeded:"LP0705",AuditUnownedBindings:"LP0706",AuditNoBindings:"LP0707",AuditNotAPage:"LP0708",FragmentRequestFailed:"LP0801",FragmentResponseInvalid:"LP0802",FragmentUnauthorized:"LP0803",FragmentSuperseded:"LP0804",RouteRefreshLoop:"LP0805",FragmentStrategyUnavailable:"LP0806",UnboundChangeRefresh:"LP0807",EscalationUnavailable:"LP0808",IslandStartUnavailable:"LP0809",RouteRefreshUnconfirmed:"LP0810",V2ReadinessGap:"LP0709",RuntimeOnPublicPage:"LP0710",AuditModifierWithoutField:"LP0711"});exports.DIAGNOSTIC_CODES=M,exports.EventEmitter=class{#d=/* @__PURE__ */new Map;#h=/* @__PURE__ */new Map;on(e,t){return this.#f(this.#d,e,t)}once(e,t){return this.#f(this.#h,e,t)}off(e,t){this.#p(this.#d,e,t),this.#p(this.#h,e,t)}async emit(e,t){await this.#g(e,t)}async emitWhile(e,t,n){return this.#g(e,t,n)}async#g(e,t,n){const r=()=>n?.()??!0;if(!r())return!1;const i=this.#d.get(e);if(i)for(const n of[...i]){if(!r())return!1;if(await this.#m(n,t,e),!r())return!1}if(!r())return!1;const o=this.#h.get(e);if(o&&o.size>0){const n=[...o];this.#h.delete(e);for(const i of n){if(!r())return!1;if(await this.#m(i,t,e),!r())return!1}}return r()}listenerCount(e){return(this.#d.get(e)?.size??0)+(this.#h.get(e)?.size??0)}removeAllListeners(e){if(void 0===e)return this.#d.clear(),void this.#h.clear();this.#d.delete(e),this.#h.delete(e)}eventNames(){const e=/* @__PURE__ */new Set;for(const t of this.#d.keys())e.add(t);for(const t of this.#h.keys())e.add(t);return[...e]}#f(e,t,n){let r=e.get(t);return r||(r=/* @__PURE__ */new Set,e.set(t,r)),r.add(n),()=>{this.#p(e,t,n)}}#p(e,t,n){const r=e.get(t);void 0!==r&&(r.delete(n),0===r.size&&e.delete(t))}async#m(e,t,r){try{await e(t)}catch(e){const t="string"==typeof r||"number"==typeof r?String(r):"<event>";n(`[live-preview] LP0601: handler for "${t}" threw:`,e)}}},exports.PluginManager=class{#a;#v;#y;#w;#t;#b=/* @__PURE__ */new Map;#P=/* @__PURE__ */new Map;#S=/* @__PURE__ */new Map;#x=/* @__PURE__ */new Set;#L=/* @__PURE__ */new Map;#A=Promise.resolve();#k=0;constructor(e){this.#a=e.events,this.#v=e.config,this.#y=e.registerFieldRenderer,this.#t=t(e.log);const n=e.onTransformError;this.#w=void 0===n?void 0:t((...e)=>{const t=e[0];try{return n(t)}catch(e){return void this.#t("transform error reporter failed:",e)}})}register(e){return this.#k>0?this.#C(e,!1):this.#$(()=>this.#C(e,!0))}unregister(e){return this.#k>0?this.#N(e,!1):this.#$(async()=>{await this.#N(e,!0)})}destroyAll(){return this.#k>0?this.#O(!1):this.#$(async()=>{await this.#O(!0)})}applyTransforms(t,n,r,i){const o=this.#L.get(t);if(void 0===o||0===o.length)return n;let s=n;for(const a of[...o]){if(!a.active)continue;const{transform:o}=a;if(!1===i?.())return n;try{s=o(s,{fieldName:t,element:r.element,allFields:r.allFields});const a=e(s);if(!1===i?.())return n;if(a)throw new TypeError(`Transform for "${t}" returned a Promise/thenable; transforms must be synchronous`)}catch(e){if(!1===i?.())return n;const r=e instanceof Error?e:new Error(String(e));return this.#t(`transform for "${t}" failed:`,r),this.#w?.(r),n}}return s}list(){return[...this.#b.keys()]}snapshot(){const e=[],t=(e,t,n,r)=>{const i=r.counts();return{name:e,version:t,state:n,registrations:{transforms:i.transform,renderers:i.renderer,subscriptions:i.subscription,cleanups:i.cleanup}}};for(const[n,r]of this.#P)e.push(t(n,void 0,"initializing",r.scope));for(const[n,r]of this.#b)e.push(t(n,r.plugin.version,"active",r.scope));for(const t of this.#S.keys())e.push({name:t,version:void 0,state:"tearing-down",registrations:{transforms:0,renderers:0,subscriptions:0,cleanups:0}});return e}get size(){return this.#b.size}async#C(e,t){if(this.#b.has(e.name)||this.#P.has(e.name)||this.#S.has(e.name))return void this.#t(`plugin "${e.name}" already registered`);const n=function(e,t){if(void 0!==e){if(void 0!==e.runtime&&!function(e,t){const n=function(e){const t=/^v?(\d+)\.(\d+)\.(\d+)/.exec(e.trim());if(null!==t)return[Number(t[1]),Number(t[2]),Number(t[3])]}(e);return void 0!==n&&t.split("||").some(e=>{const r=e.trim().split(/\s+/).filter(e=>e.length>0);return 0===r.length?""===e.trim()&&""===t.trim():r.every(e=>function(e,t){const n=t.trim();if(""===n||"*"===n)return!0;const r=/^(\^|~|>=|<=|>|<|=)?\s*v?(\d+)\.(\d+)\.(\d+)/.exec(n);if(null===r)return!1;const i=r[1]??"=",o=[Number(r[2]),Number(r[3]),Number(r[4])],s=function(e,t){for(let n=0;n<3;n+=1){const r=(e[n]??0)-(t[n]??0);if(0!==r)return r}return 0}(e,o);switch(i){case"=":return 0===s;case">":return s>0;case">=":return s>=0;case"<":return s<0;case"<=":return s<=0;case"~":return s>=0&&e[0]===o[0]&&e[1]===o[1];case"^":return!(s<0)&&(o[0]>0?e[0]===o[0]:o[1]>0?0===e[0]&&e[1]===o[1]:0===e[0]&&0===e[1]&&e[2]===o[2]);default:return!1}}(n,e))})}(t,e.runtime))return`declares runtime ${e.runtime}, this runtime is ${t}`;if(void 0!==e.protocol){if(!Number.isInteger(e.protocol)||e.protocol<1)return`declares an invalid protocol version ${String(e.protocol)}`;if(e.protocol<4)return`declares protocol ${String(e.protocol)}, this runtime speaks ${String(4)}`}}}(e.compat,"2.3.1");if(void 0!==n)return void this.#T(e.name,n);const r=new i(e.name,this.#t),o=this.#E(e.name,r),s={scope:r,cancelled:!1};this.#P.set(e.name,s);try{if(await this.#U(()=>e.init(o),t),s.cancelled)return;r.commit()}catch(t){return r.close(),void(s.cancelled||this.#t(`plugin "${e.name}" init failed:`,t))}finally{this.#P.get(e.name)===s&&this.#P.delete(e.name)}this.#b.set(e.name,{plugin:e,scope:r}),this.#t(`plugin "${e.name}" registered`)}#T(e,t){const n=`plugin "${e}" refused: ${t}`;this.#t(n),this.#a.emit("error",{error:new Error(n),context:"plugin",code:"LP0103"})}#E(e,t){return{events:new o(this.#a,t),registerFieldRenderer:e=>{t.stage("renderer",()=>{const t=this.#y(e);return"function"==typeof t?t:void 0})},registerTransform:(e,n)=>{const r={transform:n,active:!1};t.stage("transform",()=>{r.active=!0;const t=this.#L.get(e);return void 0===t?this.#L.set(e,[r]):t.push(r),()=>{r.active=!1;const t=this.#L.get(e);if(void 0===t)return;const n=t.indexOf(r);n>=0&&t.splice(n,1),0===t.length&&this.#L.delete(e)}})},registerCleanup:e=>{t.own(e)},getConfig:()=>this.#v,log:(...t)=>{this.#t(`[${e}]`,...t)}}}#N(e,t){const n=this.#P.get(e);if(void 0!==n)return n.cancelled=!0,n.scope.close(),Promise.resolve();const r=this.#S.get(e);if(void 0!==r)return this.#x.has(e)?Promise.resolve():t?this.#F(r):r;const i=this.#b.get(e);if(void 0===i)return Promise.resolve();this.#b.delete(e),i.scope.close();const o=Promise.resolve().then(()=>this.#R(e,i.plugin,t));return this.#S.set(e,o),o.then(()=>{this.#S.get(e)===o&&this.#S.delete(e)}),o}async#R(e,t,n){if(void 0!==t.destroy){this.#x.add(e);try{await this.#U(()=>t.destroy?.(),n)}catch(t){this.#t(`plugin "${e}" destroy failed:`,t)}finally{this.#x.delete(e)}}}async#O(e){for(const e of this.#P.values())e.cancelled=!0,e.scope.close();const t=[...this.#b.keys()];for(const n of t)await this.#N(n,e)}async#U(e,t){t?await this.#F(Promise.resolve().then(e)):await e()}async#F(e){this.#k+=1;try{await e}finally{this.#k-=1}}#$(e){const t=this.#A.then(e);return this.#A=t.catch(e=>{this.#t("plugin manager mutation failed:",e)}),t}},exports.createAnalyticsPlugin=function(){let e=0,t=0,n=0;return{name:"analytics",version:"1.0.0",init:r=>{r.events.on("afterUpdate",r=>{e+=1,t+=r.updatedCount,n+=r.durationMs})},getStats:()=>({updateCount:e,totalElements:t,totalDurationMs:n,averageDurationMs:0===e?0:n/e})}},exports.createUnboundFieldsOverlayPlugin=function(e={}){return{name:"unbound-fields",version:"1.0.0",init:t=>{const n=e.root??("undefined"==typeof document?void 0:document);if(void 0===n)return;if((e.onlyWithDebug??1)&&!0!==t.getConfig().debug)return void t.log("not mounted: the client runs without `debug: true`");const r=function(e,t){const n=function(e){return 9===e.nodeType?e:e.ownerDocument}(e);if(null==n?.body)return null;const r=n.createElement("aside");r.id=E,r.style.cssText="position:fixed;z-index:2147483646;max-width:280px;max-height:40vh;overflow:auto;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;background:#111;color:#eee;border:1px solid #333;border-radius:6px;padding:8px 10px;box-shadow:0 4px 16px rgba(0,0,0,0.4);"+t,r.setAttribute("aria-hidden","true"),r.hidden=!0;const i=e=>{const t=n.createElement("div");return t.textContent=e,t.style.cssText="font-weight:600;margin-bottom:4px;",t},o=i("Unbound fields"),s=n.createElement("div"),a=i("Guessed bindings");a.setAttribute("data-testid","guessed-bindings");const u=n.createElement("div");return r.append(o,s,a,u),n.body.append(r),{update:(e,t)=>{r.isConnected||(n.getElementById(E)?.remove(),n.body.append(r)),r.hidden=0===e.length&&0===t.length,o.hidden=0===e.length,s.replaceChildren(...e.map(e=>z(n,e,e))),a.hidden=0===t.length,u.replaceChildren(...t.map(({field:e,matched:t})=>z(n,e,`${e} ← ${JSON.stringify(t)}`)))},destroy:()=>{r.remove()}}}(n,U[e.position??"bottom-right"]);if(null===r)return;t.registerCleanup?.(r.destroy);const i="declared"===t.getConfig().subfieldCoverage?"declared":"descendant",o=t.getConfig().strategies??{};t.events.on("afterUpdate",e=>{const s=F(e.data.fields,function(e){const t=[];for(const n of e.querySelectorAll(`[${m}]`)){const e=n.getAttribute(m);null!==e&&e.length>0&&t.push(e)}return t}(n),e.data.locale,function(e,t){const n=[];for(const t of e.querySelectorAll(`[${w}]`))n.push(...f(t.getAttribute(w)));for(const r of e.querySelectorAll(`[${v}]`)){const e=b(r);void 0!==e&&void 0!==t[e]&&(isInsideIsland(r)||n.push(...f(r.getAttribute(v))))}return n}(n,o),i),a=function(e){const t=[];for(const n of e.querySelectorAll(`[${y}]`)){const e=n.getAttribute(m);null!==e&&0!==e.length&&t.push({field:e,matched:n.getAttribute(y)??""})}return t}(n);r.update(s,a),s.length>0&&t.log("unbound:",s.join(", ")),a.length>0&&t.log("guessed:",a.map(e=>e.field).join(", "))})}}},exports.debugPlugin=c,exports.documentSavePlugin=function(e={}){const t=e.strategy??"silent";return{name:"document-save",version:"1.1.0",init:n=>{let r=!0;const i=/* @__PURE__ */new Set;n.registerCleanup?.(()=>{r=!1;for(const e of i)e.abort();i.clear()}),function(){if("undefined"!=typeof window)try{const e=sessionStorage.getItem(d);if(null===e)return;sessionStorage.removeItem(d);const t=JSON.parse(e);if(t.href!==window.location.href)return;window.scrollTo(t.x??0,t.y??0)}catch{}}(),n.events.on("documentSave",()=>{if(!r)return;if("silent"===t)return;if("reload"===t)return void h();const o=new AbortController;i.add(o);const s="fetch"===t?async function(e,t,n){if(e.handler)try{await e.handler(n)}catch(e){if(!r||n.aborted)return;t("document-save handler threw:",e)}else t("document-save: fetch strategy selected but no handler supplied")}(e,n.log,o.signal):async function(e,t,n,r){if("undefined"==typeof fetch)return void t("document-save: revalidate strategy needs fetch — not available");const i=e.revalidateUrl??"/api/revalidate";let o=!1;try{const s=await fetch(i,{method:"POST",signal:n,headers:{"Content-Type":"application/json",...e.revalidateHeaders??{}},body:JSON.stringify({source:"payload-live-preview"})});if(!r()||n.aborted)return;o=s.ok,o||t("document-save revalidate non-2xx:",s.status)}catch(e){if(!r()||n.aborted)return;t("document-save revalidate failed:",e)}o||"reload"!==e.onRevalidateFailure||h()}(e,n.log,o.signal,()=>r);s.finally(()=>{i.delete(o)})})}}},exports.highlightPlugin=l,exports.unboundFieldNames=F;
|
|
2
2
|
//# sourceMappingURL=plugins.cjs.map
|