payload-plugin-urls 0.9.1 → 0.9.3
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 +389 -11
- package/dist/chunk-OKNQKSNQ.js +2 -0
- package/dist/chunk-OKNQKSNQ.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/next/cms-link.d.ts +32 -0
- package/dist/next/cms-link.d.ts.map +1 -0
- package/dist/next/index.cjs +2 -0
- package/dist/next/index.cjs.map +1 -0
- package/dist/next/index.d.ts +3 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +2 -0
- package/dist/next/index.js.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/types.d.ts +87 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +30 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/index.ts","../../src/next/cms-link.tsx","../../src/options.ts","../../src/utils.ts","../../src/link.ts"],"sourcesContent":["export { CmsLink } from \"./cms-link\"\n\nexport type { CmsLinkProps, CmsLinkUrlsContext } from \"./cms-link\"\n","\"use client\"\n\nimport Link from \"next/link\"\nimport { usePathname } from \"next/navigation\"\n\nimport { getDocumentLink } from \"../link\"\n\nimport type { GetDocumentLinkArgs, GetDocumentLinkContext } from \"../types\"\nimport type { LinkProps } from \"next/link\"\nimport type { ComponentProps, MouseEvent } from \"react\"\n\nfunction coerceToLocationString(href: LinkProps[\"href\"] | string | undefined | null): string {\n if (href == null) return \"\"\n if (typeof href === \"string\") return href.trim()\n if (typeof href === \"object\") {\n const o = href as { pathname?: string; search?: string; hash?: string }\n return `${o.pathname ?? \"\"}${o.search ?? \"\"}${o.hash ?? \"\"}`\n }\n return String(href).trim()\n}\n\nfunction sameSitePathnameForActiveMatch(href: string, siteUrl: string): string | null {\n try {\n const trimmed = href.trim()\n if (!trimmed) return null\n\n const resolved = new URL(trimmed, siteUrl)\n if (resolved.protocol !== \"http:\" && resolved.protocol !== \"https:\") return null\n\n const siteOrigin = new URL(siteUrl).origin\n if (resolved.origin !== siteOrigin) return null\n\n return resolved.pathname === \"\" ? \"/\" : resolved.pathname\n } catch {\n return null\n }\n}\n\nfunction isActivePathname(\n pathname: string,\n activePathname: string | null,\n matchType: \"exact\" | \"partial\",\n): boolean {\n if (activePathname == null) return false\n if (matchType === \"exact\") return pathname === activePathname\n\n if (activePathname === \"/\") return pathname === \"/\"\n\n return pathname.startsWith(activePathname)\n}\n\nexport interface CmsLinkUrlsContext {\n locale: GetDocumentLinkContext[\"locale\"]\n options: GetDocumentLinkContext[\"options\"]\n baseUrl?: GetDocumentLinkContext[\"baseUrl\"]\n urlPrefixStrategy?: GetDocumentLinkContext[\"urlPrefixStrategy\"]\n}\n\nexport interface CmsLinkProps extends Omit<ComponentProps<typeof Link>, \"href\" | \"type\"> {\n /** When true, renders a non-interactive `span` (Payload link blocks often expose this flag). */\n disabled?: boolean\n /** Absolute site base URL (origin is enough, e.g. `https://example.com`) for resolving relative links and active-state matching. */\n siteUrl: string\n /** Locale and plugin options passed to `getDocumentLink` for internal references. */\n context: CmsLinkUrlsContext\n /** Link type from the CMS; internal resolution uses `reference` unless this is `\"custom\"`. */\n type?: string | null\n /** Relationship value for internal links. */\n reference?: GetDocumentLinkArgs | null\n /** Custom URL when `type` is `\"custom\"`. */\n url?: string | null\n /** Explicit `href` overrides resolved relation and `url`. */\n href?: LinkProps[\"href\"]\n newTab?: boolean | null\n matchType?: \"exact\" | \"partial\"\n /** Extra pixels subtracted from the `#hash` target scroll offset (default `16`). */\n hashScrollYOffset?: number\n}\n\nexport function CmsLink({\n siteUrl,\n context,\n children,\n className,\n href,\n type,\n url,\n newTab,\n target,\n reference,\n disabled,\n matchType = \"exact\",\n hashScrollYOffset = 16,\n onClick,\n ...props\n}: CmsLinkProps) {\n const pathname = usePathname()\n\n if (disabled === true) {\n return <span className={className}>{children}</span>\n }\n\n const relationHref =\n type !== \"custom\" && reference && typeof reference.value === \"object\"\n ? getDocumentLink(reference, context)\n : null\n\n const shouldOpenNewTab = Boolean(newTab || target === \"_blank\")\n const newTabProps = shouldOpenNewTab\n ? { rel: \"noopener noreferrer\" as const, target: \"_blank\" as const }\n : {}\n\n const linkHrefResolved: LinkProps[\"href\"] =\n href != null && href !== \"\"\n ? typeof href === \"string\"\n ? href.replace(\"/#\", \"#\")\n : href\n : (relationHref || url || \"\").replace(\"/#\", \"#\").trim()\n\n const hrefString = coerceToLocationString(linkHrefResolved)\n\n const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {\n const link = hrefString.replace(\"/#\", \"#\")\n\n const linkUrl = new URL(link, window.location.href)\n\n if (linkUrl.hash && linkUrl.pathname === window.location.pathname && !shouldOpenNewTab) {\n e.preventDefault()\n\n const hashTarget = document.querySelector<HTMLElement>(linkUrl.hash)\n\n if (!hashTarget) return\n\n const y = hashTarget.getBoundingClientRect().top + window.scrollY - hashScrollYOffset\n\n window.scrollTo({ top: y, behavior: \"smooth\" })\n } else if (!shouldOpenNewTab && !e.metaKey) {\n window.scrollTo({ top: 0, behavior: \"instant\" })\n }\n\n onClick?.(e)\n }\n\n const activePathname = sameSitePathnameForActiveMatch(hrefString, siteUrl)\n const isActiveLink = isActivePathname(pathname, activePathname, matchType)\n\n return (\n <Link\n {...props}\n {...newTabProps}\n className={className}\n href={linkHrefResolved}\n onClick={handleClick}\n data-state={isActiveLink ? \"active\" : undefined}\n data-active={isActiveLink || undefined}\n >\n {children}\n </Link>\n )\n}\n","import type {\n PayloadPluginConfig,\n PayloadPluginUrlsOptions,\n RootPageFieldOptions,\n UrlCollectionOptions,\n} from \"./types\"\n\nexport type NormalizedPayloadPluginUrlsOptions = PayloadPluginUrlsOptions & {\n collections: Record<string, UrlCollectionOptions>\n locales: {\n defaultLocale: string\n locales: string[]\n }\n rootPages: {\n slug: string\n label?: unknown\n fields: Record<string, RootPageFieldOptions>\n }\n}\n\nexport function normalizeOptions(\n options: PayloadPluginUrlsOptions,\n config?: PayloadPluginConfig,\n): NormalizedPayloadPluginUrlsOptions {\n const configLocales = getConfigLocales(config)\n const fallbackLocales = configLocales ?? { defaultLocale: \"en\", locales: [\"en\"] }\n const locales = {\n ...fallbackLocales,\n ...options.locales,\n }\n\n return {\n ...options,\n field: {\n name: \"populatedUrl\",\n ...options.field,\n },\n locales: {\n defaultLocale: locales.defaultLocale ?? locales.locales[0] ?? \"en\",\n locales: locales.locales.length ? locales.locales : [locales.defaultLocale ?? \"en\"],\n },\n rootPages: {\n slug: \"root-pages\",\n ...options.rootPages,\n fields: options.rootPages?.fields ?? {\n indexPage: {\n isHomepage: true,\n relationTo: \"pages\",\n },\n },\n },\n }\n}\n\nexport function getCollectionOptions(options: PayloadPluginUrlsOptions, collection: string) {\n return options.collections[collection]\n}\n\nexport function getCollectionEntries(options: PayloadPluginUrlsOptions) {\n return Object.entries(options.collections)\n}\n\nexport function getCollectionsForCategory(\n options: PayloadPluginUrlsOptions,\n categoryCollection: string,\n) {\n return getCollectionEntries(options)\n .filter(\n ([, collectionOptions]) => collectionOptions.category?.collection === categoryCollection,\n )\n .map(([collection]) => collection)\n}\n\nexport function getRootPageFieldNames(options: PayloadPluginUrlsOptions) {\n const normalizedOptions = normalizeOptions(options)\n return Object.keys(normalizedOptions.rootPages.fields)\n}\n\nexport function getHomepageRootPageField(options: PayloadPluginUrlsOptions) {\n const fields = normalizeOptions(options).rootPages.fields\n const homepageEntry =\n Object.entries(fields).find(([, field]) => field.isHomepage) ??\n Object.entries(fields).find(([fieldName]) => fieldName === \"indexPage\")\n\n return homepageEntry?.[0] ?? Object.keys(fields)[0] ?? \"indexPage\"\n}\n\nexport function getRootPageFieldOptions(options: PayloadPluginUrlsOptions, fieldName: string) {\n return normalizeOptions(options).rootPages.fields[fieldName]\n}\n\nfunction getConfigLocales(config: PayloadPluginConfig | undefined) {\n const localization = config?.localization || undefined\n const locales = localization?.locales\n ?.map((locale) => (typeof locale === \"string\" ? locale : locale.code))\n .filter((locale): locale is string => Boolean(locale))\n\n if (!locales?.length) {\n return undefined\n }\n\n return {\n defaultLocale: localization?.defaultLocale ?? locales[0] ?? \"en\",\n locales,\n }\n}\n","import type { Breadcrumb, UrlDoc, UrlUpdateSource } from \"./types\"\n\nconst withoutTrailingSlash = (path: string) => path.replace(/\\/$/, \"\").replace(/^\\/?/, \"/\")\n\nfunction getBreadcrumbsUrl(breadcrumbs: Breadcrumb[] | null | undefined) {\n const lastItem = breadcrumbs?.at(-1)\n const url = lastItem?.url ?? \"\"\n return url.replace(/(^\\/)|(\\/$)/g, \"\")\n}\n\nfunction mergeDoc<T extends object>(data: Partial<T>, originalDoc?: Partial<T>) {\n return {\n ...(originalDoc || {}),\n ...withoutUndefinedValues(data),\n } as T\n}\n\nfunction withoutPopulatedUrl<T extends object>(doc: T) {\n const { populatedUrl: _populatedUrl, ...rest } = doc as T & { populatedUrl?: unknown }\n return rest\n}\n\nfunction getDocumentId(doc: unknown) {\n if (!doc || typeof doc !== \"object\" || !(\"id\" in doc)) {\n return undefined\n }\n\n return typeof doc.id === \"string\" ? doc.id : undefined\n}\n\nfunction getRelationId(value: unknown) {\n if (typeof value === \"string\") {\n return value\n }\n\n if (!value || typeof value !== \"object\" || !(\"id\" in value)) {\n return undefined\n }\n\n return typeof value.id === \"string\" ? value.id : undefined\n}\n\nfunction normalizePath(path: string | undefined) {\n return withoutTrailingSlash(`/${path ?? \"\"}`.replace(/\\/+/g, \"/\"))\n}\n\nfunction getStringValue(value: unknown, key: \"populatedUrl\" | \"slug\") {\n if (!value || typeof value !== \"object\" || !(key in value)) {\n return undefined\n }\n\n const record = value as Record<\"populatedUrl\" | \"slug\", unknown>\n return typeof record[key] === \"string\" ? record[key] : undefined\n}\n\nfunction isDraftDoc(doc: UrlDoc) {\n return doc._status === \"draft\"\n}\n\nfunction getRecord(value: unknown) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\nfunction dedupeSources<T extends UrlUpdateSource>(sources: T[]) {\n const seen = new Set<string>()\n\n return sources.filter((source) => {\n const key = sourceKey(source)\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\nfunction sourceKey(source: UrlUpdateSource) {\n switch (source.type) {\n case \"category\":\n case \"collection\":\n case \"page\":\n return `${source.type}:${source.collection}:${source.id ?? \"\"}`\n case \"rootPages\":\n return `rootPages:${JSON.stringify(source.current)}:${JSON.stringify(source.previous)}`\n }\n}\n\nfunction withoutUndefinedValues<T extends object>(value: Partial<T>) {\n return Object.fromEntries(\n Object.entries(value).filter(([, entry]) => entry !== undefined),\n ) as Partial<T>\n}\n\nexport {\n getBreadcrumbsUrl,\n getRecord,\n dedupeSources,\n isDraftDoc,\n getStringValue,\n normalizePath,\n getRelationId,\n getDocumentId,\n withoutPopulatedUrl,\n mergeDoc,\n withoutTrailingSlash,\n}\n","import { getCollectionOptions, normalizeOptions } from \"./options\"\nimport { getBreadcrumbsUrl, withoutTrailingSlash } from \"./utils\"\n\nimport type {\n GetDocumentLinkArgs,\n GetDocumentLinkContext,\n Locale,\n PayloadPluginUrlsOptions,\n UrlCollectionOptions,\n UrlDoc,\n UrlPrefixStrategy,\n} from \"./types\"\n\nexport function getDocumentLink(\n reference: GetDocumentLinkArgs,\n { baseUrl, locale, options, urlPrefixStrategy }: GetDocumentLinkContext,\n) {\n if (typeof reference.value === \"string\") {\n throw new Error(\"Reference value is a string\")\n }\n\n if (reference.value.populatedUrl) {\n return withoutTrailingSlash(reference.value.populatedUrl)\n }\n\n const normalizedOptions = normalizeOptions(options)\n const collectionOptions = getCollectionOptions(normalizedOptions, reference.relationTo)\n const routeCollection = collectionOptions?.routeCollection ?? reference.relationTo\n const slugs = getSlugsForCollection(\n collectionOptions,\n reference.value,\n urlPrefixStrategy ?? collectionOptions?.prefixStrategy,\n )\n\n return getDocumentLinkBySlugs(slugs, {\n baseUrl,\n collection: routeCollection,\n locale,\n options: normalizedOptions,\n })\n}\n\nexport function getDocumentLinkBySlugs(\n slugs: string[],\n {\n baseUrl,\n locale,\n options,\n }: {\n baseUrl?: string\n collection: string\n locale: Locale\n options: PayloadPluginUrlsOptions\n },\n) {\n const normalizedOptions = normalizeOptions(options)\n const prefix = baseUrl || (locale === normalizedOptions.locales?.defaultLocale ? \"\" : locale)\n const segments = [...prefix.split(\"/\"), ...slugs].filter(Boolean)\n return withoutTrailingSlash(`/${segments.join(\"/\")}`)\n}\n\nexport function withLocalePrefix(path: string, locale: Locale, options: PayloadPluginUrlsOptions) {\n const defaultLocale = normalizeOptions(options).locales?.defaultLocale\n if (locale === defaultLocale) {\n return withoutTrailingSlash(path)\n }\n return withoutTrailingSlash(`/${locale}${path}`)\n}\n\nfunction getSlugsForCollection(\n collectionOptions: UrlCollectionOptions | undefined,\n doc: UrlDoc,\n strategy?: UrlPrefixStrategy,\n) {\n if (collectionOptions?.category) {\n return strategy === \"rootPage\"\n ? [doc.slug ?? \"\"]\n : [firstRelatedCategoryPath(doc), doc.slug ?? \"\"]\n }\n\n if (collectionOptions?.breadcrumbs) {\n return [getBreadcrumbsUrl(doc.breadcrumbs) || doc.slug || \"\"]\n }\n\n return [doc.slug ?? \"\"]\n}\n\nfunction firstRelatedCategoryPath(doc: UrlDoc) {\n const categories = doc.categories\n if (!Array.isArray(categories) || categories.length === 0) {\n return \"\"\n }\n\n const categoryItems = categories as unknown[]\n const first = categoryItems[0]\n if (!first || typeof first !== \"object\" || typeof first === \"string\") {\n return \"\"\n }\n\n const categoryDoc = first as UrlDoc\n return (\n getBreadcrumbsUrl(categoryDoc.breadcrumbs) ||\n (categoryDoc.slug ?? \"\").replace(/(^\\/)|(\\/$)/g, \"\")\n )\n}\n"],"mappings":"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","names":["next_exports","__export","CmsLink","__toCommonJS","import_link","import_navigation","normalizeOptions","options","config","locales","getConfigLocales","getCollectionOptions","collection","getConfigLocales","config","localization","locales","locale","withoutTrailingSlash","path","getBreadcrumbsUrl","breadcrumbs","getDocumentLink","reference","baseUrl","locale","options","urlPrefixStrategy","withoutTrailingSlash","normalizedOptions","normalizeOptions","collectionOptions","getCollectionOptions","routeCollection","slugs","getSlugsForCollection","getDocumentLinkBySlugs","segments","getSlugsForCollection","collectionOptions","doc","strategy","firstRelatedCategoryPath","getBreadcrumbsUrl","categories","first","categoryDoc","import_jsx_runtime","coerceToLocationString","href","o","sameSitePathnameForActiveMatch","siteUrl","trimmed","resolved","siteOrigin","isActivePathname","pathname","activePathname","matchType","CmsLink","context","children","className","type","url","newTab","target","reference","disabled","hashScrollYOffset","onClick","props","relationHref","getDocumentLink","shouldOpenNewTab","newTabProps","linkHrefResolved","hrefString","handleClick","e","link","linkUrl","hashTarget","y","isActiveLink","Link"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEpC,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{s as f}from"../chunk-OKNQKSNQ.js";import A from"next/link";import{usePathname as M}from"next/navigation";import{jsx as k}from"react/jsx-runtime";function R(t){if(t==null)return"";if(typeof t=="string")return t.trim();if(typeof t=="object"){let n=t;return`${n.pathname??""}${n.search??""}${n.hash??""}`}return String(t).trim()}function E(t,n){try{let o=t.trim();if(!o)return null;let e=new URL(o,n);if(e.protocol!=="http:"&&e.protocol!=="https:")return null;let r=new URL(n).origin;return e.origin!==r?null:e.pathname===""?"/":e.pathname}catch{return null}}function H(t,n,o){return n==null?!1:o==="exact"?t===n:n==="/"?t==="/":t.startsWith(n)}function O({siteUrl:t,context:n,children:o,className:e,href:r,type:g,url:h,newTab:L,target:d,reference:i,disabled:x,matchType:C="exact",hashScrollYOffset:y=16,onClick:b,...w}){let P=M();if(x===!0)return k("span",{className:e,children:o});let v=g!=="custom"&&i&&typeof i.value=="object"?f(i,n):null,s=!!(L||d==="_blank"),T=s?{rel:"noopener noreferrer",target:"_blank"}:{},c=r!=null&&r!==""?typeof r=="string"?r.replace("/#","#"):r:(v||h||"").replace("/#","#").trim(),u=R(c),D=l=>{let S=u.replace("/#","#"),a=new URL(S,window.location.href);if(a.hash&&a.pathname===window.location.pathname&&!s){l.preventDefault();let m=document.querySelector(a.hash);if(!m)return;let G=m.getBoundingClientRect().top+window.scrollY-y;window.scrollTo({top:G,behavior:"smooth"})}else!s&&!l.metaKey&&window.scrollTo({top:0,behavior:"instant"});b?.(l)},U=E(u,t),p=H(P,U,C);return k(A,{...w,...T,className:e,href:c,onClick:D,"data-state":p?"active":void 0,"data-active":p||void 0,children:o})}export{O as CmsLink};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/cms-link.tsx"],"sourcesContent":["\"use client\"\n\nimport Link from \"next/link\"\nimport { usePathname } from \"next/navigation\"\n\nimport { getDocumentLink } from \"../link\"\n\nimport type { GetDocumentLinkArgs, GetDocumentLinkContext } from \"../types\"\nimport type { LinkProps } from \"next/link\"\nimport type { ComponentProps, MouseEvent } from \"react\"\n\nfunction coerceToLocationString(href: LinkProps[\"href\"] | string | undefined | null): string {\n if (href == null) return \"\"\n if (typeof href === \"string\") return href.trim()\n if (typeof href === \"object\") {\n const o = href as { pathname?: string; search?: string; hash?: string }\n return `${o.pathname ?? \"\"}${o.search ?? \"\"}${o.hash ?? \"\"}`\n }\n return String(href).trim()\n}\n\nfunction sameSitePathnameForActiveMatch(href: string, siteUrl: string): string | null {\n try {\n const trimmed = href.trim()\n if (!trimmed) return null\n\n const resolved = new URL(trimmed, siteUrl)\n if (resolved.protocol !== \"http:\" && resolved.protocol !== \"https:\") return null\n\n const siteOrigin = new URL(siteUrl).origin\n if (resolved.origin !== siteOrigin) return null\n\n return resolved.pathname === \"\" ? \"/\" : resolved.pathname\n } catch {\n return null\n }\n}\n\nfunction isActivePathname(\n pathname: string,\n activePathname: string | null,\n matchType: \"exact\" | \"partial\",\n): boolean {\n if (activePathname == null) return false\n if (matchType === \"exact\") return pathname === activePathname\n\n if (activePathname === \"/\") return pathname === \"/\"\n\n return pathname.startsWith(activePathname)\n}\n\nexport interface CmsLinkUrlsContext {\n locale: GetDocumentLinkContext[\"locale\"]\n options: GetDocumentLinkContext[\"options\"]\n baseUrl?: GetDocumentLinkContext[\"baseUrl\"]\n urlPrefixStrategy?: GetDocumentLinkContext[\"urlPrefixStrategy\"]\n}\n\nexport interface CmsLinkProps extends Omit<ComponentProps<typeof Link>, \"href\" | \"type\"> {\n /** When true, renders a non-interactive `span` (Payload link blocks often expose this flag). */\n disabled?: boolean\n /** Absolute site base URL (origin is enough, e.g. `https://example.com`) for resolving relative links and active-state matching. */\n siteUrl: string\n /** Locale and plugin options passed to `getDocumentLink` for internal references. */\n context: CmsLinkUrlsContext\n /** Link type from the CMS; internal resolution uses `reference` unless this is `\"custom\"`. */\n type?: string | null\n /** Relationship value for internal links. */\n reference?: GetDocumentLinkArgs | null\n /** Custom URL when `type` is `\"custom\"`. */\n url?: string | null\n /** Explicit `href` overrides resolved relation and `url`. */\n href?: LinkProps[\"href\"]\n newTab?: boolean | null\n matchType?: \"exact\" | \"partial\"\n /** Extra pixels subtracted from the `#hash` target scroll offset (default `16`). */\n hashScrollYOffset?: number\n}\n\nexport function CmsLink({\n siteUrl,\n context,\n children,\n className,\n href,\n type,\n url,\n newTab,\n target,\n reference,\n disabled,\n matchType = \"exact\",\n hashScrollYOffset = 16,\n onClick,\n ...props\n}: CmsLinkProps) {\n const pathname = usePathname()\n\n if (disabled === true) {\n return <span className={className}>{children}</span>\n }\n\n const relationHref =\n type !== \"custom\" && reference && typeof reference.value === \"object\"\n ? getDocumentLink(reference, context)\n : null\n\n const shouldOpenNewTab = Boolean(newTab || target === \"_blank\")\n const newTabProps = shouldOpenNewTab\n ? { rel: \"noopener noreferrer\" as const, target: \"_blank\" as const }\n : {}\n\n const linkHrefResolved: LinkProps[\"href\"] =\n href != null && href !== \"\"\n ? typeof href === \"string\"\n ? href.replace(\"/#\", \"#\")\n : href\n : (relationHref || url || \"\").replace(\"/#\", \"#\").trim()\n\n const hrefString = coerceToLocationString(linkHrefResolved)\n\n const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {\n const link = hrefString.replace(\"/#\", \"#\")\n\n const linkUrl = new URL(link, window.location.href)\n\n if (linkUrl.hash && linkUrl.pathname === window.location.pathname && !shouldOpenNewTab) {\n e.preventDefault()\n\n const hashTarget = document.querySelector<HTMLElement>(linkUrl.hash)\n\n if (!hashTarget) return\n\n const y = hashTarget.getBoundingClientRect().top + window.scrollY - hashScrollYOffset\n\n window.scrollTo({ top: y, behavior: \"smooth\" })\n } else if (!shouldOpenNewTab && !e.metaKey) {\n window.scrollTo({ top: 0, behavior: \"instant\" })\n }\n\n onClick?.(e)\n }\n\n const activePathname = sameSitePathnameForActiveMatch(hrefString, siteUrl)\n const isActiveLink = isActivePathname(pathname, activePathname, matchType)\n\n return (\n <Link\n {...props}\n {...newTabProps}\n className={className}\n href={linkHrefResolved}\n onClick={handleClick}\n data-state={isActiveLink ? \"active\" : undefined}\n data-active={isActiveLink || undefined}\n >\n {children}\n </Link>\n )\n}\n"],"mappings":"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","names":["Link","usePathname","jsx","coerceToLocationString","href","o","sameSitePathnameForActiveMatch","siteUrl","trimmed","resolved","siteOrigin","isActivePathname","pathname","activePathname","matchType","CmsLink","context","children","className","type","url","newTab","target","reference","disabled","hashScrollYOffset","onClick","props","usePathname","relationHref","getDocumentLink","shouldOpenNewTab","newTabProps","linkHrefResolved","hrefString","handleClick","e","link","linkUrl","hashTarget","y","isActiveLink","Link"]}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAIV,aAAa,EACb,wBAAwB,EAEzB,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAIV,aAAa,EACb,wBAAwB,EAEzB,MAAM,SAAS,CAAA;AAGhB,eAAO,MAAM,iBAAiB,GAAI,UAAU,wBAAwB,KAAG,aA2BtE,CAAA"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,102 +1,189 @@
|
|
|
1
1
|
import type { CollectionAfterChangeHook, CollectionBeforeChangeHook, CollectionConfig, Field, GlobalAfterChangeHook, GlobalConfig, LabelFunction, Payload, Plugin, StaticLabel, WorkflowConfig } from "payload";
|
|
2
|
+
/** Locale code used when resolving localized URLs. */
|
|
2
3
|
export type Locale = string;
|
|
4
|
+
/** Strategy used to prefix generated URLs for documents. */
|
|
3
5
|
export type UrlPrefixStrategy = "category" | "rootPage";
|
|
6
|
+
/** Breadcrumb entry used to derive a document URL path. */
|
|
4
7
|
export interface Breadcrumb {
|
|
8
|
+
/** Breadcrumb URL segment or full path supplied by Payload. */
|
|
5
9
|
url?: string | null;
|
|
6
10
|
}
|
|
11
|
+
/** Minimal document shape used by URL resolution helpers. */
|
|
7
12
|
export interface UrlDoc {
|
|
13
|
+
/** Document id used for relationship values. */
|
|
8
14
|
id?: string | number | null;
|
|
15
|
+
/** Slug used as the final URL segment. */
|
|
9
16
|
slug?: string | null;
|
|
17
|
+
/** URL calculated by the plugin. */
|
|
10
18
|
populatedUrl?: string | null;
|
|
19
|
+
/** Breadcrumbs used to derive a URL when breadcrumb mode is enabled. */
|
|
11
20
|
breadcrumbs?: Breadcrumb[] | null;
|
|
21
|
+
/** Optional category relationship data used by category prefixing. */
|
|
12
22
|
categories?: unknown;
|
|
23
|
+
/** Draft/published status used when deciding whether URL updates should cascade. */
|
|
13
24
|
_status?: "draft" | "published" | null;
|
|
14
25
|
[key: string]: unknown;
|
|
15
26
|
}
|
|
27
|
+
/** Stored root-pages global data keyed by configured root page field names. */
|
|
16
28
|
export interface RootPagesDoc {
|
|
29
|
+
/** Root-pages global id. */
|
|
17
30
|
id?: string | null;
|
|
31
|
+
/** Relationship fields keyed by configured root page field name. */
|
|
18
32
|
[field: string]: string | UrlDoc | null | undefined;
|
|
19
33
|
}
|
|
34
|
+
/** URL plugin options for a single Payload collection. */
|
|
20
35
|
export interface UrlCollectionOptions {
|
|
36
|
+
/** Whether to derive URLs from Payload breadcrumbs. */
|
|
21
37
|
breadcrumbs?: boolean;
|
|
38
|
+
/** Prefixing strategy used for generated URLs. */
|
|
22
39
|
prefixStrategy?: UrlPrefixStrategy;
|
|
40
|
+
/** Root page field name used when `prefixStrategy` is `"rootPage"`. */
|
|
23
41
|
rootPage?: string;
|
|
42
|
+
/** Category relationship config used when `prefixStrategy` is `"category"`. */
|
|
24
43
|
category?: {
|
|
44
|
+
/** Collection slug for related category documents. */
|
|
25
45
|
collection: string;
|
|
46
|
+
/** Field name on the document that stores category relationships. */
|
|
26
47
|
field?: string;
|
|
27
48
|
};
|
|
49
|
+
/** Collection whose URL changes should trigger updates for this collection. */
|
|
28
50
|
routeCollection?: string;
|
|
29
51
|
}
|
|
52
|
+
/** Options for a generated root-pages relationship field. */
|
|
30
53
|
export interface RootPageFieldOptions {
|
|
54
|
+
/** Marks this root page as the site homepage. */
|
|
31
55
|
isHomepage?: boolean;
|
|
56
|
+
/** Collection slug used by the generated relationship field. */
|
|
32
57
|
relationTo?: string;
|
|
58
|
+
/** Payload field config overrides for the generated relationship field. */
|
|
33
59
|
overrides?: Partial<Field>;
|
|
34
60
|
}
|
|
61
|
+
/** Options for configuring the Payload URLs plugin. */
|
|
35
62
|
export interface PayloadPluginUrlsOptions {
|
|
63
|
+
/** URL options keyed by collection slug. */
|
|
36
64
|
collections: Record<string, UrlCollectionOptions>;
|
|
65
|
+
/**
|
|
66
|
+
* Merged into the root-pages global after plugin defaults. Hook arrays are concatenated
|
|
67
|
+
* (plugin hooks first, then yours). `fields` is ignored; use `rootPages.fields[field].overrides`
|
|
68
|
+
* for relationship field tweaks.
|
|
69
|
+
*/
|
|
70
|
+
overrides?: Partial<GlobalConfig>;
|
|
71
|
+
/** Config for the generated populated URL field. */
|
|
37
72
|
field?: {
|
|
73
|
+
/** Field name for the generated populated URL field. */
|
|
38
74
|
name?: string;
|
|
75
|
+
/** Field config overrides for the generated populated URL field. */
|
|
39
76
|
overrides?: Record<string, unknown>;
|
|
40
77
|
};
|
|
78
|
+
/** Locale config used when resolving URLs outside a localized request. */
|
|
41
79
|
locales?: {
|
|
80
|
+
/** Fallback locale used when a request locale is missing. */
|
|
42
81
|
defaultLocale?: Locale;
|
|
82
|
+
/** Supported locale codes for URL updates. */
|
|
43
83
|
locales?: Locale[];
|
|
44
84
|
};
|
|
85
|
+
/** Config for the root-pages global and its generated relationship fields. */
|
|
45
86
|
rootPages?: {
|
|
87
|
+
/** Slug for the generated root-pages global. */
|
|
46
88
|
slug?: string;
|
|
89
|
+
/** Admin label for the generated root-pages global. */
|
|
47
90
|
label?: LabelFunction | StaticLabel;
|
|
91
|
+
/** Root page fields keyed by field name. */
|
|
48
92
|
fields?: Record<string, RootPageFieldOptions>;
|
|
49
93
|
};
|
|
50
94
|
}
|
|
95
|
+
/** Payload instance type used by URL helpers. */
|
|
51
96
|
export type PayloadLike = Payload;
|
|
97
|
+
/** Shared hook argument shape consumed by URL plugin hook utilities. */
|
|
52
98
|
export interface HookArgs {
|
|
99
|
+
/** Collection metadata from the running Payload hook. */
|
|
53
100
|
collection?: {
|
|
101
|
+
/** Collection slug for the hook document. */
|
|
54
102
|
slug?: string;
|
|
55
103
|
};
|
|
104
|
+
/** Payload request context object. */
|
|
56
105
|
context?: Record<string, unknown>;
|
|
106
|
+
/** Incoming data in before-change hooks. */
|
|
57
107
|
data?: UrlDoc;
|
|
108
|
+
/** Current document in after-change hooks. */
|
|
58
109
|
doc?: UrlDoc;
|
|
110
|
+
/** Previous document state when Payload provides one. */
|
|
59
111
|
previousDoc?: UrlDoc;
|
|
112
|
+
/** Original document state when Payload provides one. */
|
|
60
113
|
originalDoc?: UrlDoc;
|
|
114
|
+
/** Payload request object. */
|
|
61
115
|
req: {
|
|
116
|
+
/** Active request locale. */
|
|
62
117
|
locale?: string;
|
|
118
|
+
/** Mutable request context shared across hooks. */
|
|
63
119
|
context?: Record<string, unknown>;
|
|
120
|
+
/** Payload instance for querying related documents. */
|
|
64
121
|
payload: PayloadLike;
|
|
65
122
|
};
|
|
66
123
|
}
|
|
124
|
+
/** Payload hook types used by the URL plugin. */
|
|
67
125
|
export type Hook = CollectionBeforeChangeHook | CollectionAfterChangeHook | GlobalAfterChangeHook;
|
|
126
|
+
/** Payload config type accepted by plugin functions. */
|
|
68
127
|
export type PayloadPluginConfig = Parameters<Plugin>[0];
|
|
128
|
+
/** Payload collection config type used by URL plugin helpers. */
|
|
69
129
|
export type CollectionConfigLike = CollectionConfig;
|
|
130
|
+
/** Payload global config type used by URL plugin helpers. */
|
|
70
131
|
export type GlobalConfigLike = GlobalConfig;
|
|
132
|
+
/** Payload field config type used by URL plugin helpers. */
|
|
71
133
|
export type FieldLike = Field;
|
|
134
|
+
/** Payload workflow config type used by URL plugin helpers. */
|
|
72
135
|
export type WorkflowLike = WorkflowConfig;
|
|
136
|
+
/** Payload plugin function type returned by this package. */
|
|
73
137
|
export type PayloadPlugin = Plugin;
|
|
138
|
+
/** Arguments for resolving and assigning a document's populated URL. */
|
|
74
139
|
export interface ResolvePopulatedUrlArgs {
|
|
140
|
+
/** Collection slug for the document being resolved. */
|
|
75
141
|
collection: string;
|
|
142
|
+
/** Document data used to build the URL. */
|
|
76
143
|
data: Partial<UrlDoc>;
|
|
144
|
+
/** Locale used for the generated URL. */
|
|
77
145
|
locale: Locale;
|
|
146
|
+
/** Plugin options that describe collection and root page behavior. */
|
|
78
147
|
options: PayloadPluginUrlsOptions;
|
|
148
|
+
/** Previous document state used to preserve unchanged values when needed. */
|
|
79
149
|
originalDoc?: Partial<UrlDoc>;
|
|
150
|
+
/** Payload instance for resolving related category/root page documents. */
|
|
80
151
|
payload?: PayloadLike;
|
|
152
|
+
/** Current root-pages global data. */
|
|
81
153
|
rootPages: RootPagesDoc;
|
|
82
154
|
}
|
|
155
|
+
/** Arguments for converting a relationship value into a document link. */
|
|
83
156
|
export interface GetDocumentLinkArgs {
|
|
157
|
+
/** Collection slug for the relationship value. */
|
|
84
158
|
relationTo: string;
|
|
159
|
+
/** Relationship value as an id or populated URL document. */
|
|
85
160
|
value: string | UrlDoc;
|
|
86
161
|
}
|
|
162
|
+
/** Context used when formatting a document link for a locale and URL strategy. */
|
|
87
163
|
export interface GetDocumentLinkContext {
|
|
164
|
+
/** Optional base URL prepended to generated links. */
|
|
88
165
|
baseUrl?: string;
|
|
166
|
+
/** Locale used for the generated link. */
|
|
89
167
|
locale: Locale;
|
|
168
|
+
/** Plugin options used to determine URL structure. */
|
|
90
169
|
options: PayloadPluginUrlsOptions;
|
|
170
|
+
/** Prefix strategy override for this link. */
|
|
91
171
|
urlPrefixStrategy?: UrlPrefixStrategy;
|
|
92
172
|
}
|
|
173
|
+
/** Source of a URL update triggered by a document or root-pages change. */
|
|
93
174
|
export type UrlUpdateSource = {
|
|
175
|
+
/** Collection slug whose document changed. */
|
|
94
176
|
collection: string;
|
|
177
|
+
/** Changed document id, when available. */
|
|
95
178
|
id?: string | null;
|
|
179
|
+
/** Kind of document change that triggered URL updates. */
|
|
96
180
|
type: "category" | "collection" | "page";
|
|
97
181
|
} | {
|
|
182
|
+
/** Current root-pages global data. */
|
|
98
183
|
current: RootPagesDoc;
|
|
184
|
+
/** Previous root-pages global data, when available. */
|
|
99
185
|
previous?: RootPagesDoc;
|
|
186
|
+
/** Identifies a root-pages global update source. */
|
|
100
187
|
type: "rootPages";
|
|
101
188
|
};
|
|
102
189
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload-plugin-urls",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
4
4
|
"description": "Payload CMS plugin for URL utilities.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -28,6 +28,11 @@
|
|
|
28
28
|
"types": "./dist/index.d.ts",
|
|
29
29
|
"import": "./dist/index.js",
|
|
30
30
|
"require": "./dist/index.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./next": {
|
|
33
|
+
"types": "./dist/next/index.d.ts",
|
|
34
|
+
"import": "./dist/next/index.js",
|
|
35
|
+
"require": "./dist/next/index.cjs"
|
|
31
36
|
}
|
|
32
37
|
},
|
|
33
38
|
"files": [
|
|
@@ -38,10 +43,32 @@
|
|
|
38
43
|
"build": "tsup --config tsup.config.ts --minify && tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
39
44
|
"dev": "tsup --config tsup.config.ts --watch",
|
|
40
45
|
"test": "vitest run tests/index.test.ts",
|
|
41
|
-
"typecheck": "tsc --noEmit"
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"lint": "pnpm -w exec oxlint \"packages/${npm_package_name}\"",
|
|
48
|
+
"format": "pnpm exec oxfmt .",
|
|
49
|
+
"format:check": "pnpm exec oxfmt --check ."
|
|
42
50
|
},
|
|
43
51
|
"peerDependencies": {
|
|
44
|
-
"
|
|
52
|
+
"next": "^15.0.0 || ^16.0.0",
|
|
53
|
+
"payload": "^3.80.0",
|
|
54
|
+
"react": ">=18.0.0",
|
|
55
|
+
"react-dom": ">=18.0.0"
|
|
56
|
+
},
|
|
57
|
+
"peerDependenciesMeta": {
|
|
58
|
+
"next": {
|
|
59
|
+
"optional": true
|
|
60
|
+
},
|
|
61
|
+
"react": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"react-dom": {
|
|
65
|
+
"optional": true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"next": "^16.2.5",
|
|
70
|
+
"react": "^19.2.6",
|
|
71
|
+
"react-dom": "^19.2.6"
|
|
45
72
|
},
|
|
46
73
|
"publishConfig": {
|
|
47
74
|
"access": "public"
|