payload-plugin-llms 0.9.0 → 0.9.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.
Files changed (42) hide show
  1. package/README.md +134 -61
  2. package/dist/global.d.ts +4 -0
  3. package/dist/global.d.ts.map +1 -0
  4. package/dist/index.cjs +13 -8
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.ts +7 -5
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +13 -7
  9. package/dist/index.js.map +1 -1
  10. package/dist/lexical.d.ts +28 -4
  11. package/dist/lexical.d.ts.map +1 -1
  12. package/dist/llms-lexical.d.ts +4 -0
  13. package/dist/llms-lexical.d.ts.map +1 -0
  14. package/dist/llms-txt.d.ts +48 -7
  15. package/dist/llms-txt.d.ts.map +1 -1
  16. package/dist/next/headers.d.ts +0 -1
  17. package/dist/next/headers.d.ts.map +1 -1
  18. package/dist/next/index.cjs +1 -2
  19. package/dist/next/index.cjs.map +1 -1
  20. package/dist/next/index.d.ts +3 -5
  21. package/dist/next/index.d.ts.map +1 -1
  22. package/dist/next/index.js +1 -1
  23. package/dist/next/index.js.map +1 -1
  24. package/dist/next/llms-txt-response.d.ts +7 -0
  25. package/dist/next/llms-txt-response.d.ts.map +1 -0
  26. package/dist/next/markdown-response.d.ts +4 -0
  27. package/dist/next/markdown-response.d.ts.map +1 -0
  28. package/dist/next/rewrites.d.ts +32 -7
  29. package/dist/next/rewrites.d.ts.map +1 -1
  30. package/dist/next/types.d.ts +2 -0
  31. package/dist/next/types.d.ts.map +1 -1
  32. package/dist/options.d.ts.map +1 -1
  33. package/dist/plugin.d.ts.map +1 -1
  34. package/dist/types.d.ts +42 -9
  35. package/dist/types.d.ts.map +1 -1
  36. package/package.json +12 -5
  37. package/dist/chunk-B5YH4Y5S.js +0 -3
  38. package/dist/chunk-B5YH4Y5S.js.map +0 -1
  39. package/dist/next/llms-route.d.ts +0 -12
  40. package/dist/next/llms-route.d.ts.map +0 -1
  41. package/dist/next/markdown-route.d.ts +0 -34
  42. package/dist/next/markdown-route.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,8 +1,25 @@
1
1
  # payload-plugin-llms
2
2
 
3
- Payload CMS plugin and Next.js helpers for `llms.txt`, markdown page responses, markdown rewrites, and Lexical-to-Markdown conversion.
3
+ Helpers for `llms.txt` / `llms-full.txt` content stored in a Payload **global**, LexicalMarkdown
4
+ conversion, and Next.js utilities for markdown responses and Accept-based rewrites.
4
5
 
5
- ## Usage
6
+ ## Install
7
+
8
+ ```bash
9
+ pnpm add payload-plugin-llms
10
+ ```
11
+
12
+ ```bash
13
+ npm install payload-plugin-llms
14
+ ```
15
+
16
+ ### Peer dependencies
17
+
18
+ - `payload` `^3.80.0`
19
+ - `@payloadcms/richtext-lexical` `^3.80.0`
20
+ - `next` `^15.0.0 || ^16.0.0` — optional; required for `payload-plugin-llms/next`
21
+
22
+ ## `payload.config.ts`
6
23
 
7
24
  ```ts
8
25
  import { buildConfig } from "payload"
@@ -11,97 +28,153 @@ import { payloadPluginLlms } from "payload-plugin-llms"
11
28
  export default buildConfig({
12
29
  plugins: [
13
30
  payloadPluginLlms({
31
+ enabled: true,
14
32
  routes: {
15
33
  llmsTxt: "/llms.txt",
16
34
  markdownSegment: "md",
17
35
  },
36
+ global: {
37
+ slug: "llms",
38
+ label: "LLMs",
39
+ localized: false,
40
+ },
18
41
  }),
19
42
  ],
20
43
  })
21
44
  ```
22
45
 
23
- The Payload plugin entrypoint keeps this package visible in Payload config and normalizes shared options. Next.js routes still live in your app route files.
46
+ `normalizeOptions(options)` returns defaults including `global`:
47
+
48
+ ```ts
49
+ import { normalizeOptions } from "payload-plugin-llms"
24
50
 
25
- ## llms.txt Route
51
+ const normalized = normalizeOptions({})
52
+ ```
53
+
54
+ ### Options (`PayloadPluginLlmsOptions`)
55
+
56
+ | Option | Default | Purpose |
57
+ | ------------------------ | ------------- | -------------------------------------------------------- |
58
+ | `enabled` | `true` | Toggle plugin |
59
+ | `routes.llmsTxt` | `"/llms.txt"` | Documented path for `llms.txt` in your app |
60
+ | `routes.markdownSegment` | `"md"` | Segment name for markdown URLs (rewrites) |
61
+ | `global.slug` | `"llms"` | Global slug |
62
+ | `global.label` | `"LLMs"` | Admin label |
63
+ | `global.localized` | `false` | Localize tab fields |
64
+ | `global.overrides` | — | `Partial<GlobalConfig>` merged into the generated global |
65
+
66
+ If a global with the same slug already exists in config, the plugin does not add another.
67
+
68
+ ## Core helpers (`payload-plugin-llms`)
69
+
70
+ - `buildLlmsTxt({ payload, locale?, draft?, depth?, globalSlug?, lexical? })` — reads the
71
+ **llms.txt** tab and returns markdown text (`lexical.resolveLexicalBlock` handles top-level
72
+ serialized `block` nodes)
73
+ - `buildLlmsFullTxt({ … })` — same for the **llms-full.txt** tab
74
+ - `buildLlmsTxtFromStructured(content)` — legacy structured `LlmsTxtContent` → `llms.txt` lines (no
75
+ Lexical)
76
+ - `formatLlmsTxtLink(link)`
77
+ - `lexicalToMarkdown(root, options?)` — sync Lexical JSON → Markdown (`block` nodes are omitted)
78
+ - `lexicalToMarkdownAsync(root, options?)` — async; optional `resolveLexicalBlock` for custom
79
+ Lexical blocks
80
+ - `createLlmsGlobal(normalizeOptions())` — use the generated global config directly if you are not
81
+ using the plugin
82
+ - `createLlmsLexicalEditor()` — Lexical adapter for custom fields that should match the llms editor
83
+
84
+ ### Example: Next.js `llms.txt` route
26
85
 
27
86
  ```ts
28
- import { createLlmsTxtRoute } from "payload-plugin-llms/next"
29
-
30
- export const GET = createLlmsTxtRoute({
31
- loadContent: async () => ({
32
- title: "Acme",
33
- description: "Useful website content.",
34
- intro: "This website is built with Next.js and Payload CMS.",
35
- sections: [
36
- {
37
- title: "Pages",
38
- links: [
39
- {
40
- title: "Home",
41
- url: "https://example.com",
42
- description: "Start here.",
43
- },
44
- ],
87
+ import { cacheLife } from "next/cache"
88
+ import { getPayload } from "payload"
89
+ import { buildLlmsTxt } from "payload-plugin-llms"
90
+ import { LlmsResponse } from "payload-plugin-llms/next"
91
+ import config from "@payload-config"
92
+
93
+ export async function GET() {
94
+ "use cache"
95
+ cacheLife("days")
96
+
97
+ const payload = await getPayload({ config })
98
+
99
+ const body = await buildLlmsTxt({
100
+ payload,
101
+ locale: "en",
102
+ depth: 2,
103
+ lexical: {
104
+ resolveInternalLink: ({ relationTo, value }) =>
105
+ relationTo && value && typeof value === "object" && value !== null && "slug" in value
106
+ ? `/${String((value as { slug?: string }).slug)}`
107
+ : null,
108
+ resolveLexicalBlock: async (fields) => {
109
+ if (fields.blockType === "my-custom-block") {
110
+ // Load data, format markdown, etc.
111
+ return "\n---\n\n"
112
+ }
113
+ return ""
45
114
  },
46
- ],
47
- }),
48
- })
115
+ },
116
+ })
117
+
118
+ return new LlmsResponse(body)
119
+ }
49
120
  ```
50
121
 
51
- Place this in a route such as `src/app/(meta)/llms.txt/route.ts`.
122
+ `lexical.resolveLexicalBlock` runs only for Lexical nodes with `type: "block"` that are **direct
123
+ children of the field’s `root`**; omit it if you do not use custom blocks in llms rich text.
52
124
 
53
- ## Markdown Page Route
125
+ ### Lexical Markdown
54
126
 
55
127
  ```ts
56
- import { draftMode } from "next/headers"
57
- import { createMarkdownRoute } from "payload-plugin-llms/next"
128
+ import { lexicalToMarkdown, lexicalToMarkdownAsync } from "payload-plugin-llms"
58
129
 
59
- import { LOCALES } from "@/payload.i18n"
60
- import { getCachedPageMarkdown } from "@/server/queries/get-cached-page-markdown"
130
+ lexicalToMarkdown(payloadLexicalRoot, {
131
+ resolveInternalLink: (reference) =>
132
+ reference.relationTo && reference.value
133
+ ? `/${reference.relationTo}/${String(reference.value)}`
134
+ : (reference.url ?? null),
135
+ })
61
136
 
62
- export const GET = createMarkdownRoute({
63
- locales: LOCALES,
64
- draftMode,
65
- searchParams: ["q", "collection"],
66
- getMarkdown: getCachedPageMarkdown,
137
+ await lexicalToMarkdownAsync(payloadLexicalRoot, {
138
+ resolveInternalLink: (reference) => reference.url ?? null,
139
+ resolveLexicalBlock: async (fields) => (fields.blockType === "my-block" ? "custom output\n" : ""),
67
140
  })
68
141
  ```
69
142
 
70
- Place this in a route such as `src/app/(frontend)/[locale]/md/[[...slug]]/route.ts`.
143
+ Types include `LlmsTxtContent`, `LlmsTxtSection`, `LlmsTxtLink`, `BuildLlmsTxtFromGlobalOptions`,
144
+ `LexicalToMarkdownOptions`, `LexicalToMarkdownAsyncOptions`, `SerializedLexicalNode`.
71
145
 
72
- ## Markdown Rewrites
146
+ ## Next.js (`payload-plugin-llms/next`)
73
147
 
74
- ```ts
75
- import { createMarkdownRewrites } from "payload-plugin-llms/next"
76
-
77
- import { LOCALES } from "@/payload.i18n"
148
+ Use your own App Router handlers and choose caching (`dynamic`, `revalidate`, `unstable_cache`,
149
+ etc.). This entry exports small helpers only:
78
150
 
79
- export async function rewrites() {
80
- return createMarkdownRewrites({
81
- locales: LOCALES,
82
- markdownSegment: "md",
83
- })
84
- }
85
- ```
151
+ - `LlmsResponse` subclass of `Response`; constructor merges `DEFAULT_LLMS_TXT_HEADERS` with optional `init.headers` and forwards other `ResponseInit` fields
152
+ - `createMarkdownResponse(markdown, { headers? })`
153
+ - `createMarkdownRewrites(...)` — Accept: `text/markdown` rewrites
154
+ - `DEFAULT_LLMS_TXT_HEADERS`, `DEFAULT_MARKDOWN_HEADERS`, `mergeHeaders`, `isMarkdownAccepted`
86
155
 
87
- Requests with an `Accept` header containing `text/markdown` are rewritten to the localized markdown route.
156
+ ### Rewrites for clients that prefer Markdown
88
157
 
89
- ## Lexical Utility
158
+ `CreateMarkdownRewritesOptions`: either `{ locales, localizedRoutes?: true, ... }` for
159
+ `/:locale/...` routes, or `{ localizedRoutes: false, ... }` when there is no locale prefix. Optional
160
+ fields: `markdownSegment`, `acceptHeaderPattern`, `includeIndexRewrite`, `has`.
90
161
 
91
162
  ```ts
92
- import { lexicalToMarkdown } from "payload-plugin-llms"
93
-
94
- const markdown = lexicalToMarkdown(doc.content, {
95
- resolveInternalLink: ({ relationTo, value }) => {
96
- if (relationTo === "pages" && typeof value === "object" && value !== null && "slug" in value) {
97
- return `/${String(value.slug)}`
98
- }
163
+ import type { NextConfig } from "next"
164
+ import { createMarkdownRewrites } from "payload-plugin-llms/next"
99
165
 
100
- return null
166
+ const nextConfig: NextConfig = {
167
+ async rewrites() {
168
+ return createMarkdownRewrites({
169
+ locales: ["en", "de"],
170
+ markdownSegment: "md",
171
+ })
101
172
  },
102
- })
173
+ }
174
+
175
+ export default nextConfig
103
176
  ```
104
177
 
105
- ## App-Owned Rendering
178
+ ## License
106
179
 
107
- The plugin does not ship project-specific document lookup, block rendering, cache tags, or URL building. Keep functions such as `getCachedPageMarkdown`, `docResultToMarkdown`, and `blocksToMarkdown` in your app and pass them to the route factories.
180
+ Apache-2.0 (see repository root).
@@ -0,0 +1,4 @@
1
+ import type { NormalizedPayloadPluginLlmsOptions } from "./types";
2
+ import type { GlobalConfig } from "payload";
3
+ export declare function createLlmsGlobal(normalized: NormalizedPayloadPluginLlmsOptions): GlobalConfig;
4
+ //# sourceMappingURL=global.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global.d.ts","sourceRoot":"","sources":["../src/global.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,SAAS,CAAA;AACjE,OAAO,KAAK,EAAS,YAAY,EAAE,MAAM,SAAS,CAAA;AA4HlD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,kCAAkC,GAAG,YAAY,CA2B7F"}
package/dist/index.cjs CHANGED
@@ -1,17 +1,22 @@
1
- "use strict";var s=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var T=(e,t)=>{for(var n in t)s(e,n,{get:t[n],enumerable:!0})},k=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of f(t))!L.call(e,r)&&r!==n&&s(e,r,{get:()=>t[r],enumerable:!(i=x(t,r))||i.enumerable});return e};var S=e=>k(s({},"__esModule",{value:!0}),e);var P={};T(P,{buildLlmsTxt:()=>m,default:()=>u,formatLlmsTxtLink:()=>d,lexicalToMarkdown:()=>p,normalizeOptions:()=>l,payloadPluginLlms:()=>u});module.exports=S(P);function d(e){let t=`- [${e.title}](${e.url})`;return e.description?`${t}: ${e.description}`:t}function m(e){let t=[];e.title&&t.push(`# ${e.title}`,""),e.description&&t.push(`> ${e.description}`,""),a(t,e.intro);for(let n of e.sections??[]){t.push(`## ${n.title}`,""),a(t,n.content,{trailingBlank:!1});for(let i of n.links??[])t.push(d(i));t.push("")}return a(t,e.footer,{trailingBlank:!1}),y(t).join(`
2
- `)}function a(e,t,n={}){let i=Array.isArray(t)?t:t?[t]:[];if(i.length!==0){if(n.trailingBlank??!0){for(let r of i)e.push(r,"");return}for(let r of i)e.push(r)}}function y(e){let t=[...e];for(;t[0]==="";)t.shift();for(;t.at(-1)==="";)t.pop();return t}function p(e,t={}){return(e.root?.children??[]).map(i=>c(i,t)).join("").trim()}function c(e,t){switch(e.type){case"text":return N(e.text??"",e.format);case"linebreak":return`
3
- `;case"tab":return" ";case"heading":return z(e,t);case"paragraph":return O(e,t);case"link":case"autolink":return w(e,t);case"list":return h(e,t);case"listitem":return o(e,t).trim();case"quote":case"blockquote":return E(e,t);case"horizontalrule":return`---
1
+ "use strict";var g=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var E=(e,n)=>{for(var t in n)g(e,t,{get:n[t],enumerable:!0})},G=(e,n,t,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of N(n))!P.call(e,r)&&r!==t&&g(e,r,{get:()=>n[r],enumerable:!(i=z(n,r))||i.enumerable});return e};var M=e=>G(g({},"__esModule",{value:!0}),e);var U={};E(U,{buildLlmsFullTxt:()=>w,buildLlmsTxt:()=>b,buildLlmsTxtFromStructured:()=>T,createLlmsGlobal:()=>f,createLlmsLexicalEditor:()=>m,default:()=>y,formatLlmsTxtLink:()=>L,lexicalToMarkdown:()=>k,lexicalToMarkdownAsync:()=>c,normalizeOptions:()=>p,payloadPluginLlms:()=>y});module.exports=M(U);function k(e,n={}){return(e.root?.children??[]).map(i=>u(i,n)).join("").trim()}async function c(e,n={}){let t=e?.root?.children??[];return(await Promise.all(t.map(async r=>{if(r.type==="block"){let l=r.fields;return l&&n.resolveLexicalBlock?await n.resolveLexicalBlock(l):""}return u(r,n)}))).join("").trim()}function u(e,n){switch(e.type){case"block":return"";case"text":return I(e.text??"",e.format);case"linebreak":return`
2
+ `;case"tab":return" ";case"heading":return R(e,n);case"paragraph":return C(e,n);case"link":case"autolink":return $(e,n);case"list":return A(e,n);case"listitem":return d(e,n).trim();case"quote":case"blockquote":return v(e,n);case"horizontalrule":return`---
4
3
 
5
- `;case"root":return o(e,t).trim();default:return o(e,t)}}function o(e,t){return(e.children??[]).map(n=>c(n,t)).join("")}function N(e,t=0){if((t&16)===16)return`\`${e}\``;let n=e,i=(t&1)===1,r=(t&2)===2;return i&&r?n=`***${n}***`:i?n=`**${n}**`:r&&(n=`_${n}_`),(t&4)===4&&(n=`~~${n}~~`),(t&8)===8&&(n=`<u>${n}</u>`),n}function z(e,t){let i=(typeof e.tag=="string"?/^h([1-6])$/.exec(e.tag):null)?.[1]??"2",r=o(e,t).trim();return`${"#".repeat(Number(i))} ${r}
4
+ `;case"root":return d(e,n).trim();default:return d(e,n)}}function d(e,n){return(e.children??[]).map(t=>u(t,n)).join("")}function I(e,n=0){if((n&16)===16)return`\`${e}\``;let t=e,i=(n&1)===1,r=(n&2)===2;return i&&r?t=`***${t}***`:i?t=`**${t}**`:r&&(t=`_${t}_`),(n&4)===4&&(t=`~~${t}~~`),(n&8)===8&&(t=`<u>${t}</u>`),t}function R(e,n){let i=(typeof e.tag=="string"?/^h([1-6])$/.exec(e.tag):null)?.[1]??"2",r=d(e,n).trim();return`${"#".repeat(Number(i))} ${r}
6
5
 
7
- `}function O(e,t){return`${o(e,t).trim()}
6
+ `}function C(e,n){return`${d(e,n).trim()}
8
7
 
9
- `}function w(e,t){let n=o(e,t).trim(),i=I(e,t);return`[${n}](${i})`}function I(e,t){let n=e.fields,i=n?.url??e.url;return n?.linkType==="internal"?t.resolveInternalLink?.({relationTo:n.doc?.relationTo,value:n.doc?.value,url:i})??i??"#":i??"#"}function h(e,t){let n=e.listType==="number"||e.listType==="ordered";return`${(e.children??[]).map((r,g)=>`${n?`${g+1}. `:"- "}${c(r,t).trim()}`).join(`
8
+ `}function $(e,n){let t=d(e,n).trim(),i=F(e,n);return`[${t}](${i})`}function F(e,n){let t=e.fields,i=t?.url??e.url;return t?.linkType==="internal"?n.resolveInternalLink?.({relationTo:t.doc?.relationTo,value:t.doc?.value,url:i})??i??"#":i??"#"}function A(e,n){let t=e.listType==="number"||e.listType==="ordered";return`${(e.children??[]).map((r,l)=>`${t?`${l+1}. `:"- "}${u(r,n).trim()}`).join(`
10
9
  `)}
11
10
 
12
- `}function E(e,t){return`${o(e,t).trim().split(`
11
+ `}function v(e,n){return`${d(e,n).trim().split(`
13
12
  `).map(i=>`> ${i}`).join(`
14
13
  `)}
15
14
 
16
- `}function l(e={}){return{enabled:e.enabled??!0,routes:{llmsTxt:e.routes?.llmsTxt??"/llms.txt",markdownSegment:e.routes?.markdownSegment??"md"}}}var u=e=>(l(e),t=>t);0&&(module.exports={buildLlmsTxt,formatLlmsTxtLink,lexicalToMarkdown,normalizeOptions,payloadPluginLlms});
15
+ `}function L(e){let n=`- [${e.title}](${e.url})`;return e.description?`${n}: ${e.description}`:n}function T(e){let n=[];e.title&&n.push(`# ${e.title}`,""),e.description&&n.push(`> ${e.description}`,""),x(n,e.intro);for(let t of e.sections??[]){n.push(`## ${t.title}`,""),x(n,t.content,{trailingBlank:!1});for(let i of t.links??[])n.push(L(i));n.push("")}return x(n,e.footer,{trailingBlank:!1}),H(n).join(`
16
+ `)}async function b(e){return S(e,"llmsTxt")}async function w(e){return S(e,"llmsFullTxt")}async function S(e,n){let t=e.globalSlug??"llms",r=(await e.payload.findGlobal({slug:t,locale:e.locale,draft:e.draft,depth:e.depth??2,req:e.req}))?.[n];return B(r,e)}async function B(e,n){if(!e)return"";let t=n.lexical??{},i=[];e.openingContent&&i.push(await c(e.openingContent,t));for(let r of e.sections??[]){let l=r.content?await c(r.content,t):"",a=r.title?.trim()??"";!a&&!l.trim()||(i.push(`
17
+ ---
18
+ `),a&&i.push(`
19
+ ## ${a}
20
+
21
+ `),l.trim()&&i.push(l))}return i.join("").trim()}function x(e,n,t={}){let i=Array.isArray(n)?n:n?[n]:[];if(i.length!==0){if(t.trailingBlank??!0){for(let r of i)e.push(r,"");return}for(let r of i)e.push(r)}}function H(e){let n=[...e];for(;n[0]==="";)n.shift();for(;n.at(-1)==="";)n.pop();return n}var o=require("@payloadcms/richtext-lexical");function m(){return(0,o.lexicalEditor)({features:({defaultFeatures:e})=>[(0,o.HeadingFeature)({enabledHeadingSizes:["h1","h2","h3","h4"]}),(0,o.BlockquoteFeature)(),(0,o.HorizontalRuleFeature)(),(0,o.OrderedListFeature)(),(0,o.UnorderedListFeature)(),...e]})}function h(e,n){return[{name:"openingContent",type:"richText",localized:n,label:"Opening content",admin:{description:"Rendered at the top of the file (headings, lists, formatting, quotes, horizontal rules). Use an H1 for a title if you want one."},editor:e},{name:"sections",type:"array",localized:n,label:"Sections",admin:{description:"Each section is separated by a horizontal rule in the output.",initCollapsed:!0},fields:[{name:"title",type:"text",localized:n,label:"Section title"},{name:"content",type:"richText",localized:n,label:"Content",required:!0,editor:e}]}]}function O(e){if(!Array.isArray(e))return[];let n=[];for(let t of e)n.push(t);return n}function _(e,n){if(!n)return e;if(!e)return n;let t=e,i=n,r={...t};for(let l of Object.keys(i)){let a=t[l],s=i[l];Array.isArray(a)||Array.isArray(s)?r[l]=[...O(a),...O(s)]:s!==void 0&&(r[l]=s)}return r}function D(e,n){if(!n)return e;let{hooks:t,access:i,admin:r,fields:l,...a}=n,s={...e,...a};return i&&(s.access={...e.access,...i}),r&&(s.admin={...e.admin,...r}),(t||e.hooks)&&(s.hooks=_(e.hooks,t)),s}function f(e){let n=m(),{slug:t,label:i,localized:r,overrides:l}=e.global,a={slug:t,label:i,fields:[{type:"tabs",tabs:[{name:"llmsTxt",label:"llms.txt",fields:h(n,r)},{name:"llmsFullTxt",label:"llms-full.txt",fields:h(n,r)}]}]};return D(a,l)}function q(e={}){return{slug:e.global?.slug??"llms",label:e.global?.label??"LLMs",localized:e.global?.localized??!1,overrides:e.global?.overrides}}function p(e={}){return{enabled:e.enabled??!0,routes:{llmsTxt:e.routes?.llmsTxt??"/llms.txt",markdownSegment:e.routes?.markdownSegment??"md"},global:q(e)}}var y=e=>{let n=p(e);return n.enabled?t=>(t.globals??[]).some(i=>i.slug===n.global.slug)?t:{...t,globals:[...t.globals??[],f(n)]}:t=>t};0&&(module.exports={buildLlmsFullTxt,buildLlmsTxt,buildLlmsTxtFromStructured,createLlmsGlobal,createLlmsLexicalEditor,formatLlmsTxtLink,lexicalToMarkdown,lexicalToMarkdownAsync,normalizeOptions,payloadPluginLlms});
17
22
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/llms-txt.ts","../src/lexical.ts","../src/options.ts","../src/plugin.ts"],"sourcesContent":["export { buildLlmsTxt, formatLlmsTxtLink } from \"./llms-txt\"\nexport { lexicalToMarkdown } from \"./lexical\"\nexport { normalizeOptions } from \"./options\"\nexport { payloadPluginLlms } from \"./plugin\"\n\nexport type { LexicalToMarkdownOptions, SerializedLexicalNode } from \"./lexical\"\nexport type { LlmsTxtContent, LlmsTxtLink, LlmsTxtSection } from \"./llms-txt\"\nexport type {\n NormalizedPayloadPluginLlmsOptions,\n PayloadPlugin,\n PayloadPluginConfig,\n PayloadPluginLlmsOptions,\n} from \"./types\"\n\nexport { payloadPluginLlms as default } from \"./plugin\"\n","export type LlmsTxtLink = {\n title: string\n url: string\n description?: string | null\n}\n\nexport type LlmsTxtSection = {\n title: string\n content?: string | string[]\n links?: LlmsTxtLink[]\n}\n\nexport type LlmsTxtContent = {\n title?: string\n description?: string\n intro?: string | string[]\n sections?: LlmsTxtSection[]\n footer?: string | string[]\n}\n\nexport function formatLlmsTxtLink(link: LlmsTxtLink): string {\n const line = `- [${link.title}](${link.url})`\n return link.description ? `${line}: ${link.description}` : line\n}\n\nexport function buildLlmsTxt(content: LlmsTxtContent): string {\n const lines: string[] = []\n\n if (content.title) {\n lines.push(`# ${content.title}`, \"\")\n }\n if (content.description) {\n lines.push(`> ${content.description}`, \"\")\n }\n\n appendLines(lines, content.intro)\n\n for (const section of content.sections ?? []) {\n lines.push(`## ${section.title}`, \"\")\n appendLines(lines, section.content, { trailingBlank: false })\n for (const link of section.links ?? []) {\n lines.push(formatLlmsTxtLink(link))\n }\n lines.push(\"\")\n }\n\n appendLines(lines, content.footer, { trailingBlank: false })\n\n return trimBlankEdges(lines).join(\"\\n\")\n}\n\nfunction appendLines(\n lines: string[],\n value: string | string[] | undefined,\n options: { trailingBlank?: boolean } = {},\n) {\n const values = Array.isArray(value) ? value : value ? [value] : []\n if (values.length === 0) return\n\n if (options.trailingBlank ?? true) {\n for (const item of values) {\n lines.push(item, \"\")\n }\n return\n }\n\n for (const item of values) {\n lines.push(item)\n }\n}\n\nfunction trimBlankEdges(lines: string[]) {\n const trimmed = [...lines]\n while (trimmed[0] === \"\") trimmed.shift()\n while (trimmed.at(-1) === \"\") trimmed.pop()\n return trimmed\n}\n","export type SerializedLexicalNode = {\n type?: string\n [key: string]: unknown\n}\n\ntype SerializedElementNode = SerializedLexicalNode & {\n children?: SerializedLexicalNode[]\n}\n\ntype SerializedTextNode = SerializedLexicalNode & {\n type: \"text\"\n text?: string\n format?: number\n}\n\ntype SerializedLinkNode = SerializedElementNode & {\n url?: string\n fields?: {\n linkType?: string\n url?: string\n doc?: {\n relationTo?: string\n value?: unknown\n }\n }\n}\n\nexport type LexicalToMarkdownOptions = {\n resolveInternalLink?: (reference: {\n relationTo?: string\n value?: unknown\n url?: string\n }) => string | null | undefined\n}\n\nconst IS_BOLD = 1\nconst IS_ITALIC = 2\nconst IS_STRIKETHROUGH = 4\nconst IS_UNDERLINE = 8\nconst IS_CODE = 16\n\nexport function lexicalToMarkdown(\n data: { root?: { children?: SerializedLexicalNode[] } },\n options: LexicalToMarkdownOptions = {},\n): string {\n const children = data.root?.children ?? []\n return children.map((node) => nodeToMarkdown(node, options)).join(\"\").trim()\n}\n\nfunction nodeToMarkdown(node: SerializedLexicalNode, options: LexicalToMarkdownOptions): string {\n switch (node.type) {\n case \"text\":\n return formatText((node as SerializedTextNode).text ?? \"\", (node as SerializedTextNode).format)\n case \"linebreak\":\n return \"\\n\"\n case \"tab\":\n return \"\\t\"\n case \"heading\":\n return headingToMarkdown(node as SerializedElementNode, options)\n case \"paragraph\":\n return paragraphToMarkdown(node as SerializedElementNode, options)\n case \"link\":\n case \"autolink\":\n return linkToMarkdown(node as SerializedLinkNode, options)\n case \"list\":\n return listToMarkdown(node as SerializedElementNode & { listType?: string }, options)\n case \"listitem\":\n return childrenToMarkdown(node as SerializedElementNode, options).trim()\n case \"quote\":\n case \"blockquote\":\n return quoteToMarkdown(node as SerializedElementNode, options)\n case \"horizontalrule\":\n return \"---\\n\\n\"\n case \"root\":\n return childrenToMarkdown(node as SerializedElementNode, options).trim()\n default:\n return childrenToMarkdown(node as SerializedElementNode, options)\n }\n}\n\nfunction childrenToMarkdown(\n node: SerializedElementNode,\n options: LexicalToMarkdownOptions,\n): string {\n return (node.children ?? []).map((child) => nodeToMarkdown(child, options)).join(\"\")\n}\n\nfunction formatText(text: string, format = 0): string {\n if ((format & IS_CODE) === IS_CODE) {\n return `\\`${text}\\``\n }\n\n let markdown = text\n const isBold = (format & IS_BOLD) === IS_BOLD\n const isItalic = (format & IS_ITALIC) === IS_ITALIC\n\n if (isBold && isItalic) {\n markdown = `***${markdown}***`\n } else if (isBold) {\n markdown = `**${markdown}**`\n } else if (isItalic) {\n markdown = `_${markdown}_`\n }\n\n if ((format & IS_STRIKETHROUGH) === IS_STRIKETHROUGH) {\n markdown = `~~${markdown}~~`\n }\n\n if ((format & IS_UNDERLINE) === IS_UNDERLINE) {\n markdown = `<u>${markdown}</u>`\n }\n\n return markdown\n}\n\nfunction headingToMarkdown(\n node: SerializedElementNode & { tag?: unknown },\n options: LexicalToMarkdownOptions,\n): string {\n const match = typeof node.tag === \"string\" ? /^h([1-6])$/.exec(node.tag) : null\n const level = match?.[1] ?? \"2\"\n const content = childrenToMarkdown(node, options).trim()\n\n return `${\"#\".repeat(Number(level))} ${content}\\n\\n`\n}\n\nfunction paragraphToMarkdown(\n node: SerializedElementNode,\n options: LexicalToMarkdownOptions,\n): string {\n return `${childrenToMarkdown(node, options).trim()}\\n\\n`\n}\n\nfunction linkToMarkdown(node: SerializedLinkNode, options: LexicalToMarkdownOptions): string {\n const text = childrenToMarkdown(node, options).trim()\n const href = getLinkHref(node, options)\n\n return `[${text}](${href})`\n}\n\nfunction getLinkHref(node: SerializedLinkNode, options: LexicalToMarkdownOptions): string {\n const fields = node.fields\n const fallbackUrl = fields?.url ?? node.url\n\n if (fields?.linkType === \"internal\") {\n const resolved = options.resolveInternalLink?.({\n relationTo: fields.doc?.relationTo,\n value: fields.doc?.value,\n url: fallbackUrl,\n })\n\n return resolved ?? fallbackUrl ?? \"#\"\n }\n\n return fallbackUrl ?? \"#\"\n}\n\nfunction listToMarkdown(\n node: SerializedElementNode & { listType?: string },\n options: LexicalToMarkdownOptions,\n): string {\n const isNumbered = node.listType === \"number\" || node.listType === \"ordered\"\n const items = (node.children ?? []).map((child, index) => {\n const prefix = isNumbered ? `${index + 1}. ` : \"- \"\n return `${prefix}${nodeToMarkdown(child, options).trim()}`\n })\n\n return `${items.join(\"\\n\")}\\n\\n`\n}\n\nfunction quoteToMarkdown(node: SerializedElementNode, options: LexicalToMarkdownOptions): string {\n const content = childrenToMarkdown(node, options)\n .trim()\n .split(\"\\n\")\n .map((line) => `> ${line}`)\n .join(\"\\n\")\n\n return `${content}\\n\\n`\n}\n","import type { NormalizedPayloadPluginLlmsOptions, PayloadPluginLlmsOptions } from \"./types\"\n\nexport function normalizeOptions(\n options: PayloadPluginLlmsOptions = {},\n): NormalizedPayloadPluginLlmsOptions {\n return {\n enabled: options.enabled ?? true,\n routes: {\n llmsTxt: options.routes?.llmsTxt ?? \"/llms.txt\",\n markdownSegment: options.routes?.markdownSegment ?? \"md\",\n },\n }\n}\n","import { normalizeOptions } from \"./options\"\n\nimport type { PayloadPlugin, PayloadPluginLlmsOptions } from \"./types\"\n\nexport const payloadPluginLlms = (options?: PayloadPluginLlmsOptions): PayloadPlugin => {\n normalizeOptions(options)\n\n return (config) => config\n}\n"],"mappings":"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","names":["index_exports","__export","buildLlmsTxt","payloadPluginLlms","formatLlmsTxtLink","lexicalToMarkdown","normalizeOptions","__toCommonJS","formatLlmsTxtLink","link","line","buildLlmsTxt","content","lines","appendLines","section","trimBlankEdges","value","options","values","item","trimmed","lexicalToMarkdown","data","options","node","nodeToMarkdown","formatText","headingToMarkdown","paragraphToMarkdown","linkToMarkdown","listToMarkdown","childrenToMarkdown","quoteToMarkdown","child","text","format","markdown","isBold","isItalic","level","content","href","getLinkHref","fields","fallbackUrl","isNumbered","index","line","normalizeOptions","options","payloadPluginLlms","options","normalizeOptions","config"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/lexical.ts","../src/llms-txt.ts","../src/llms-lexical.ts","../src/global.ts","../src/options.ts","../src/plugin.ts"],"sourcesContent":["export { buildLlmsFullTxt, buildLlmsTxtFromStructured, buildLlmsTxt, formatLlmsTxtLink } from \"./llms-txt\"\nexport { createLlmsGlobal } from \"./global\"\nexport { lexicalToMarkdown, lexicalToMarkdownAsync } from \"./lexical\"\nexport { normalizeOptions } from \"./options\"\nexport { payloadPluginLlms } from \"./plugin\"\nexport { createLlmsLexicalEditor } from \"./llms-lexical\"\n\nexport type {\n LexicalToMarkdownAsyncOptions,\n LexicalToMarkdownOptions,\n SerializedLexicalNode,\n} from \"./lexical\"\nexport type {\n BuildLlmsTxtFromGlobalOptions,\n LlmsTxtContent,\n LlmsTxtLink,\n LlmsTxtSection,\n} from \"./llms-txt\"\nexport type {\n LlmsGlobalTabKey,\n NormalizedLlmsGlobalOptions,\n NormalizedPayloadPluginLlmsOptions,\n PayloadPlugin,\n PayloadPluginConfig,\n PayloadPluginLlmsGlobalOptions,\n PayloadPluginLlmsOptions,\n} from \"./types\"\n\nexport { payloadPluginLlms as default } from \"./plugin\"\n","/** Minimal serialized Lexical node shape accepted by the markdown converter. */\nexport interface SerializedLexicalNode {\n /** Lexical node type, such as `paragraph`, `heading`, `text`, or `link`. */\n type?: string\n [key: string]: unknown\n}\n\ntype SerializedElementNode = SerializedLexicalNode & {\n children?: SerializedLexicalNode[]\n}\n\ntype SerializedTextNode = SerializedLexicalNode & {\n type: \"text\"\n text?: string\n format?: number\n}\n\ntype SerializedLinkNode = SerializedElementNode & {\n url?: string\n fields?: {\n linkType?: string\n url?: string\n doc?: {\n relationTo?: string\n value?: unknown\n }\n }\n}\n\n/** Options for converting serialized Lexical content to markdown. */\nexport interface LexicalToMarkdownOptions {\n /** Resolves Payload/Lexical internal link references to public URLs. */\n resolveInternalLink?: (reference: {\n /** Collection slug for the linked document. */\n relationTo?: string\n /** Linked document id or populated document value. */\n value?: unknown\n /** Fallback URL stored on the Lexical link node. */\n url?: string\n }) => string | null | undefined\n}\n\n/** Options for async Lexical → markdown conversion (includes serialized block nodes). */\nexport interface LexicalToMarkdownAsyncOptions extends LexicalToMarkdownOptions {\n /**\n * When a serialized `block` node is encountered, returns markdown for that block’s `fields`.\n * If omitted, block nodes produce no output.\n */\n resolveLexicalBlock?: (fields: Record<string, unknown>) => Promise<string> | string\n}\n\nconst IS_BOLD = 1\nconst IS_ITALIC = 2\nconst IS_STRIKETHROUGH = 4\nconst IS_UNDERLINE = 8\nconst IS_CODE = 16\n\nexport function lexicalToMarkdown(\n data: { root?: { children?: SerializedLexicalNode[] } },\n options: LexicalToMarkdownOptions = {},\n): string {\n const children = data.root?.children ?? []\n return children\n .map((node) => nodeToMarkdown(node, options))\n .join(\"\")\n .trim()\n}\n\n/**\n * Like {@link lexicalToMarkdown}, but resolves top-level serialized `block` nodes via\n * `resolveLexicalBlock`.\n */\nexport async function lexicalToMarkdownAsync(\n data: { root?: { children?: SerializedLexicalNode[] } } | null | undefined,\n options: LexicalToMarkdownAsyncOptions = {},\n): Promise<string> {\n const children = data?.root?.children ?? []\n const segments = await Promise.all(\n children.map(async (node) => {\n if (node.type === \"block\") {\n const fields = (node as SerializedLexicalNode & { fields?: Record<string, unknown> }).fields\n if (fields && options.resolveLexicalBlock) {\n return await options.resolveLexicalBlock(fields)\n }\n return \"\"\n }\n return nodeToMarkdown(node, options)\n }),\n )\n return segments.join(\"\").trim()\n}\n\nfunction nodeToMarkdown(node: SerializedLexicalNode, options: LexicalToMarkdownOptions): string {\n switch (node.type) {\n case \"block\":\n return \"\"\n case \"text\":\n return formatText(\n (node as SerializedTextNode).text ?? \"\",\n (node as SerializedTextNode).format,\n )\n case \"linebreak\":\n return \"\\n\"\n case \"tab\":\n return \"\\t\"\n case \"heading\":\n return headingToMarkdown(node as SerializedElementNode, options)\n case \"paragraph\":\n return paragraphToMarkdown(node as SerializedElementNode, options)\n case \"link\":\n case \"autolink\":\n return linkToMarkdown(node as SerializedLinkNode, options)\n case \"list\":\n return listToMarkdown(node as SerializedElementNode & { listType?: string }, options)\n case \"listitem\":\n return childrenToMarkdown(node as SerializedElementNode, options).trim()\n case \"quote\":\n case \"blockquote\":\n return quoteToMarkdown(node as SerializedElementNode, options)\n case \"horizontalrule\":\n return \"---\\n\\n\"\n case \"root\":\n return childrenToMarkdown(node as SerializedElementNode, options).trim()\n default:\n return childrenToMarkdown(node as SerializedElementNode, options)\n }\n}\n\nfunction childrenToMarkdown(\n node: SerializedElementNode,\n options: LexicalToMarkdownOptions,\n): string {\n return (node.children ?? []).map((child) => nodeToMarkdown(child, options)).join(\"\")\n}\n\nfunction formatText(text: string, format = 0): string {\n if ((format & IS_CODE) === IS_CODE) {\n return `\\`${text}\\``\n }\n\n let markdown = text\n const isBold = (format & IS_BOLD) === IS_BOLD\n const isItalic = (format & IS_ITALIC) === IS_ITALIC\n\n if (isBold && isItalic) {\n markdown = `***${markdown}***`\n } else if (isBold) {\n markdown = `**${markdown}**`\n } else if (isItalic) {\n markdown = `_${markdown}_`\n }\n\n if ((format & IS_STRIKETHROUGH) === IS_STRIKETHROUGH) {\n markdown = `~~${markdown}~~`\n }\n\n if ((format & IS_UNDERLINE) === IS_UNDERLINE) {\n markdown = `<u>${markdown}</u>`\n }\n\n return markdown\n}\n\nfunction headingToMarkdown(\n node: SerializedElementNode & { tag?: unknown },\n options: LexicalToMarkdownOptions,\n): string {\n const match = typeof node.tag === \"string\" ? /^h([1-6])$/.exec(node.tag) : null\n const level = match?.[1] ?? \"2\"\n const content = childrenToMarkdown(node, options).trim()\n\n return `${\"#\".repeat(Number(level))} ${content}\\n\\n`\n}\n\nfunction paragraphToMarkdown(\n node: SerializedElementNode,\n options: LexicalToMarkdownOptions,\n): string {\n return `${childrenToMarkdown(node, options).trim()}\\n\\n`\n}\n\nfunction linkToMarkdown(node: SerializedLinkNode, options: LexicalToMarkdownOptions): string {\n const text = childrenToMarkdown(node, options).trim()\n const href = getLinkHref(node, options)\n\n return `[${text}](${href})`\n}\n\nfunction getLinkHref(node: SerializedLinkNode, options: LexicalToMarkdownOptions): string {\n const fields = node.fields\n const fallbackUrl = fields?.url ?? node.url\n\n if (fields?.linkType === \"internal\") {\n const resolved = options.resolveInternalLink?.({\n relationTo: fields.doc?.relationTo,\n value: fields.doc?.value,\n url: fallbackUrl,\n })\n\n return resolved ?? fallbackUrl ?? \"#\"\n }\n\n return fallbackUrl ?? \"#\"\n}\n\nfunction listToMarkdown(\n node: SerializedElementNode & { listType?: string },\n options: LexicalToMarkdownOptions,\n): string {\n const isNumbered = node.listType === \"number\" || node.listType === \"ordered\"\n const items = (node.children ?? []).map((child, index) => {\n const prefix = isNumbered ? `${index + 1}. ` : \"- \"\n return `${prefix}${nodeToMarkdown(child, options).trim()}`\n })\n\n return `${items.join(\"\\n\")}\\n\\n`\n}\n\nfunction quoteToMarkdown(node: SerializedElementNode, options: LexicalToMarkdownOptions): string {\n const content = childrenToMarkdown(node, options)\n .trim()\n .split(\"\\n\")\n .map((line) => `> ${line}`)\n .join(\"\\n\")\n\n return `${content}\\n\\n`\n}\n","import {\n lexicalToMarkdownAsync,\n type LexicalToMarkdownAsyncOptions,\n type SerializedLexicalNode,\n} from \"./lexical\"\n\nimport type { Payload, PayloadRequest } from \"payload\"\n\n/** Link entry rendered inside a structured llms.txt section (legacy builder). */\nexport interface LlmsTxtLink {\n /** Link label rendered inside the markdown link. */\n title: string\n /** Link destination URL. */\n url: string\n /** Optional text appended after the link. */\n description?: string | null\n}\n\n/** Section rendered in a structured llms.txt document (legacy builder). */\nexport interface LlmsTxtSection {\n /** Section heading. */\n title: string\n /** Paragraph content rendered before section links. */\n content?: string | string[]\n /** Links rendered in the section. */\n links?: LlmsTxtLink[]\n}\n\n/** Structured content used to build an llms.txt document without Lexical (legacy builder). */\nexport interface LlmsTxtContent {\n /** Optional document title rendered as the top-level heading. */\n title?: string\n /** Optional blockquote description rendered below the title. */\n description?: string\n /** Intro paragraphs rendered before sections. */\n intro?: string | string[]\n /** Sections rendered in order. */\n sections?: LlmsTxtSection[]\n /** Footer paragraphs rendered after sections. */\n footer?: string | string[]\n}\n\nexport interface BuildLlmsTxtFromGlobalOptions {\n /** Payload instance (Local API). */\n payload: Payload\n /** Passed to `findGlobal` when the llms global uses localized fields. */\n locale?: string\n draft?: boolean\n depth?: number\n /** Express / Payload request for nested operations; recommended inside hooks. */\n req?: PayloadRequest\n /**\n * Global slug; defaults to `\"llms\"`.\n * Should match the `global.slug` option passed to `payloadPluginLlms` when overridden.\n */\n globalSlug?: string\n /**\n * Options passed to markdown conversion. Use `resolveLexicalBlock` if you need custom\n * Lexical block serialization.\n */\n lexical?: LexicalToMarkdownAsyncOptions\n}\n\ninterface LlmsTabDoc {\n openingContent?: unknown\n sections?: Array<{ title?: string | null; content?: unknown }> | null\n}\n\nexport function formatLlmsTxtLink(link: LlmsTxtLink): string {\n const line = `- [${link.title}](${link.url})`\n return link.description ? `${line}: ${link.description}` : line\n}\n\n/** Build llms.txt-style plain text from structured sections and links (no Lexical). */\nexport function buildLlmsTxtFromStructured(content: LlmsTxtContent): string {\n const lines: string[] = []\n\n if (content.title) {\n lines.push(`# ${content.title}`, \"\")\n }\n if (content.description) {\n lines.push(`> ${content.description}`, \"\")\n }\n\n appendLines(lines, content.intro)\n\n for (const section of content.sections ?? []) {\n lines.push(`## ${section.title}`, \"\")\n appendLines(lines, section.content, { trailingBlank: false })\n for (const link of section.links ?? []) {\n lines.push(formatLlmsTxtLink(link))\n }\n lines.push(\"\")\n }\n\n appendLines(lines, content.footer, { trailingBlank: false })\n\n return trimBlankEdges(lines).join(\"\\n\")\n}\n\n/** Load the `llms.txt` tab from the `llms` global and render markdown. */\nexport async function buildLlmsTxt(options: BuildLlmsTxtFromGlobalOptions): Promise<string> {\n return loadLlmsGlobalTab(options, \"llmsTxt\")\n}\n\n/** Load the `llms-full.txt` tab from the `llms` global and render markdown. */\nexport async function buildLlmsFullTxt(options: BuildLlmsTxtFromGlobalOptions): Promise<string> {\n return loadLlmsGlobalTab(options, \"llmsFullTxt\")\n}\n\nasync function loadLlmsGlobalTab(\n options: BuildLlmsTxtFromGlobalOptions,\n tabKey: \"llmsTxt\" | \"llmsFullTxt\",\n): Promise<string> {\n const slug = options.globalSlug ?? \"llms\"\n const doc = (await options.payload.findGlobal({\n slug,\n locale: options.locale,\n draft: options.draft,\n depth: options.depth ?? 2,\n req: options.req,\n })) as Record<string, unknown> | null\n\n const tab = doc?.[tabKey] as LlmsTabDoc | undefined\n return assembleLlmsMarkdownFromTab(tab, options)\n}\n\nasync function assembleLlmsMarkdownFromTab(\n tab: LlmsTabDoc | null | undefined,\n options: BuildLlmsTxtFromGlobalOptions,\n): Promise<string> {\n if (!tab) {\n return \"\"\n }\n\n const lexicalOpts = options.lexical ?? {}\n\n const parts: string[] = []\n\n if (tab.openingContent) {\n parts.push(\n await lexicalToMarkdownAsync(\n tab.openingContent as { root?: { children?: SerializedLexicalNode[] } },\n lexicalOpts,\n ),\n )\n }\n\n for (const section of tab.sections ?? []) {\n const body = section.content\n ? await lexicalToMarkdownAsync(\n section.content as { root?: { children?: SerializedLexicalNode[] } },\n lexicalOpts,\n )\n : \"\"\n const title = section.title?.trim() ?? \"\"\n if (!title && !body.trim()) {\n continue\n }\n parts.push(\"\\n---\\n\")\n if (title) {\n parts.push(`\\n## ${title}\\n\\n`)\n }\n if (body.trim()) {\n parts.push(body)\n }\n }\n\n return parts.join(\"\").trim()\n}\n\nfunction appendLines(\n lines: string[],\n value: string | string[] | undefined,\n options: { trailingBlank?: boolean } = {},\n) {\n const values = Array.isArray(value) ? value : value ? [value] : []\n if (values.length === 0) return\n\n if (options.trailingBlank ?? true) {\n for (const item of values) {\n lines.push(item, \"\")\n }\n return\n }\n\n for (const item of values) {\n lines.push(item)\n }\n}\n\nfunction trimBlankEdges(lines: string[]) {\n const trimmed = [...lines]\n while (trimmed[0] === \"\") trimmed.shift()\n while (trimmed.at(-1) === \"\") trimmed.pop()\n return trimmed\n}\n","import type { RichTextField } from \"payload\"\n\nimport {\n BlockquoteFeature,\n HeadingFeature,\n HorizontalRuleFeature,\n lexicalEditor,\n OrderedListFeature,\n UnorderedListFeature,\n} from \"@payloadcms/richtext-lexical\"\n\n/** Lexical editor for llms opening content and section bodies (headings, lists, quotes, rules, default rich-text features). */\nexport function createLlmsLexicalEditor(): NonNullable<RichTextField[\"editor\"]> {\n return lexicalEditor({\n features: ({ defaultFeatures }) => [\n HeadingFeature({ enabledHeadingSizes: [\"h1\", \"h2\", \"h3\", \"h4\"] }),\n BlockquoteFeature(),\n HorizontalRuleFeature(),\n OrderedListFeature(),\n UnorderedListFeature(),\n ...defaultFeatures,\n ],\n })\n}\n","import { createLlmsLexicalEditor } from \"./llms-lexical\"\n\nimport type { NormalizedPayloadPluginLlmsOptions } from \"./types\"\nimport type { Field, GlobalConfig } from \"payload\"\n\ntype LexicalEditorProvider = ReturnType<typeof createLlmsLexicalEditor>\n\nfunction llmsTabFields(editor: LexicalEditorProvider, localized: boolean): Field[] {\n return [\n {\n name: \"openingContent\",\n type: \"richText\",\n localized,\n label: \"Opening content\",\n admin: {\n description:\n \"Rendered at the top of the file (headings, lists, formatting, quotes, horizontal rules). Use an H1 for a title if you want one.\",\n },\n editor,\n },\n {\n name: \"sections\",\n type: \"array\",\n localized,\n label: \"Sections\",\n admin: {\n description: \"Each section is separated by a horizontal rule in the output.\",\n initCollapsed: true,\n },\n fields: [\n {\n name: \"title\",\n type: \"text\",\n localized,\n label: \"Section title\",\n },\n {\n name: \"content\",\n type: \"richText\",\n localized,\n label: \"Content\",\n required: true,\n editor,\n },\n ],\n },\n ]\n}\n\nfunction unknownArrayFrom(value: unknown): unknown[] {\n if (!Array.isArray(value)) {\n return []\n }\n const out: unknown[] = []\n for (const item of value) {\n out.push(item)\n }\n return out\n}\n\nfunction mergeHooks<H extends Record<string, unknown> | undefined>(base: H, extra: H): H {\n if (!extra) {\n return base\n }\n if (!base) {\n return extra\n }\n const a = base\n const b = extra\n const out: Record<string, unknown> = { ...a }\n for (const key of Object.keys(b)) {\n const av = a[key]\n const bv = b[key]\n if (Array.isArray(av) || Array.isArray(bv)) {\n out[key] = [...unknownArrayFrom(av), ...unknownArrayFrom(bv)]\n } else if (bv !== undefined) {\n out[key] = bv\n }\n }\n return out as H\n}\n\nfunction mergeGlobalOverride(\n base: GlobalConfig,\n override: Partial<GlobalConfig> | undefined,\n): GlobalConfig {\n if (!override) {\n return base\n }\n\n const {\n hooks: overrideHooks,\n access: overrideAccess,\n admin: overrideAdmin,\n fields: _fields,\n ...rest\n } = override\n\n const merged: GlobalConfig = {\n ...base,\n ...rest,\n }\n\n if (overrideAccess) {\n merged.access = {\n ...(base.access as Record<string, unknown> | undefined),\n ...(overrideAccess as Record<string, unknown>),\n } as GlobalConfig[\"access\"]\n }\n\n if (overrideAdmin) {\n merged.admin = {\n ...(base.admin as Record<string, unknown> | undefined),\n ...(overrideAdmin as Record<string, unknown>),\n } as GlobalConfig[\"admin\"]\n }\n\n if (overrideHooks || base.hooks) {\n merged.hooks = mergeHooks(\n base.hooks as Record<string, unknown> | undefined,\n overrideHooks as Record<string, unknown> | undefined,\n ) as GlobalConfig[\"hooks\"]\n }\n\n return merged\n}\n\nexport function createLlmsGlobal(normalized: NormalizedPayloadPluginLlmsOptions): GlobalConfig {\n const editor = createLlmsLexicalEditor()\n const { slug, label, localized, overrides } = normalized.global\n\n const base = {\n slug,\n label,\n fields: [\n {\n type: \"tabs\",\n tabs: [\n {\n name: \"llmsTxt\",\n label: \"llms.txt\",\n fields: llmsTabFields(editor, localized),\n },\n {\n name: \"llmsFullTxt\",\n label: \"llms-full.txt\",\n fields: llmsTabFields(editor, localized),\n },\n ],\n },\n ],\n } satisfies GlobalConfig\n\n return mergeGlobalOverride(base, overrides)\n}\n","import type {\n NormalizedLlmsGlobalOptions,\n NormalizedPayloadPluginLlmsOptions,\n PayloadPluginLlmsOptions,\n} from \"./types\"\n\nfunction normalizeGlobalOptions(options: PayloadPluginLlmsOptions = {}): NormalizedLlmsGlobalOptions {\n return {\n slug: options.global?.slug ?? \"llms\",\n label: options.global?.label ?? \"LLMs\",\n localized: options.global?.localized ?? false,\n overrides: options.global?.overrides,\n }\n}\n\nexport function normalizeOptions(\n options: PayloadPluginLlmsOptions = {},\n): NormalizedPayloadPluginLlmsOptions {\n return {\n enabled: options.enabled ?? true,\n routes: {\n llmsTxt: options.routes?.llmsTxt ?? \"/llms.txt\",\n markdownSegment: options.routes?.markdownSegment ?? \"md\",\n },\n global: normalizeGlobalOptions(options),\n }\n}\n","import { createLlmsGlobal } from \"./global\"\nimport { normalizeOptions } from \"./options\"\n\nimport type { PayloadPlugin, PayloadPluginLlmsOptions } from \"./types\"\n\nexport const payloadPluginLlms = (options?: PayloadPluginLlmsOptions): PayloadPlugin => {\n const normalized = normalizeOptions(options)\n\n if (!normalized.enabled) {\n return (config) => config\n }\n\n return (config) => {\n if ((config.globals ?? []).some((global_) => global_.slug === normalized.global.slug)) {\n return config\n }\n\n return {\n ...config,\n globals: [...(config.globals ?? []), createLlmsGlobal(normalized)],\n }\n }\n}\n"],"mappings":"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","names":["index_exports","__export","buildLlmsFullTxt","buildLlmsTxt","buildLlmsTxtFromStructured","createLlmsGlobal","createLlmsLexicalEditor","payloadPluginLlms","formatLlmsTxtLink","lexicalToMarkdown","lexicalToMarkdownAsync","normalizeOptions","__toCommonJS","lexicalToMarkdown","data","options","node","nodeToMarkdown","lexicalToMarkdownAsync","children","fields","formatText","headingToMarkdown","paragraphToMarkdown","linkToMarkdown","listToMarkdown","childrenToMarkdown","quoteToMarkdown","child","text","format","markdown","isBold","isItalic","level","content","href","getLinkHref","fallbackUrl","isNumbered","index","line","formatLlmsTxtLink","link","line","buildLlmsTxtFromStructured","content","lines","appendLines","section","trimBlankEdges","buildLlmsTxt","options","loadLlmsGlobalTab","buildLlmsFullTxt","tabKey","slug","tab","assembleLlmsMarkdownFromTab","lexicalOpts","parts","lexicalToMarkdownAsync","body","title","value","values","item","trimmed","import_richtext_lexical","createLlmsLexicalEditor","defaultFeatures","llmsTabFields","editor","localized","unknownArrayFrom","value","out","item","mergeHooks","base","extra","a","b","key","av","bv","mergeGlobalOverride","override","overrideHooks","overrideAccess","overrideAdmin","_fields","rest","merged","createLlmsGlobal","normalized","createLlmsLexicalEditor","slug","label","overrides","normalizeGlobalOptions","options","normalizeOptions","payloadPluginLlms","options","normalized","normalizeOptions","config","global_","createLlmsGlobal"]}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
- export { buildLlmsTxt, formatLlmsTxtLink } from "./llms-txt";
2
- export { lexicalToMarkdown } from "./lexical";
1
+ export { buildLlmsFullTxt, buildLlmsTxtFromStructured, buildLlmsTxt, formatLlmsTxtLink } from "./llms-txt";
2
+ export { createLlmsGlobal } from "./global";
3
+ export { lexicalToMarkdown, lexicalToMarkdownAsync } from "./lexical";
3
4
  export { normalizeOptions } from "./options";
4
5
  export { payloadPluginLlms } from "./plugin";
5
- export type { LexicalToMarkdownOptions, SerializedLexicalNode } from "./lexical";
6
- export type { LlmsTxtContent, LlmsTxtLink, LlmsTxtSection } from "./llms-txt";
7
- export type { NormalizedPayloadPluginLlmsOptions, PayloadPlugin, PayloadPluginConfig, PayloadPluginLlmsOptions, } from "./types";
6
+ export { createLlmsLexicalEditor } from "./llms-lexical";
7
+ export type { LexicalToMarkdownAsyncOptions, LexicalToMarkdownOptions, SerializedLexicalNode, } from "./lexical";
8
+ export type { BuildLlmsTxtFromGlobalOptions, LlmsTxtContent, LlmsTxtLink, LlmsTxtSection, } from "./llms-txt";
9
+ export type { LlmsGlobalTabKey, NormalizedLlmsGlobalOptions, NormalizedPayloadPluginLlmsOptions, PayloadPlugin, PayloadPluginConfig, PayloadPluginLlmsGlobalOptions, PayloadPluginLlmsOptions, } from "./types";
8
10
  export { payloadPluginLlms as default } from "./plugin";
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAE5C,YAAY,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AAChF,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC7E,YAAY,EACV,kCAAkC,EAClC,aAAa,EACb,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,iBAAiB,IAAI,OAAO,EAAE,MAAM,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC1G,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAExD,YAAY,EACV,6BAA6B,EAC7B,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,6BAA6B,EAC7B,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,gBAAgB,EAChB,2BAA2B,EAC3B,kCAAkC,EAClC,aAAa,EACb,mBAAmB,EACnB,8BAA8B,EAC9B,wBAAwB,GACzB,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,iBAAiB,IAAI,OAAO,EAAE,MAAM,UAAU,CAAA"}
package/dist/index.js CHANGED
@@ -1,16 +1,22 @@
1
- import{a as c,b as u}from"./chunk-B5YH4Y5S.js";function m(e,n={}){return(e.root?.children??[]).map(i=>o(i,n)).join("").trim()}function o(e,n){switch(e.type){case"text":return p(e.text??"",e.format);case"linebreak":return`
2
- `;case"tab":return" ";case"heading":return x(e,n);case"paragraph":return L(e,n);case"link":case"autolink":return g(e,n);case"list":return S(e,n);case"listitem":return l(e,n).trim();case"quote":case"blockquote":return k(e,n);case"horizontalrule":return`---
1
+ function T(e,n={}){return(e.root?.children??[]).map(i=>c(i,n)).join("").trim()}async function d(e,n={}){let t=e?.root?.children??[];return(await Promise.all(t.map(async r=>{if(r.type==="block"){let l=r.fields;return l&&n.resolveLexicalBlock?await n.resolveLexicalBlock(l):""}return c(r,n)}))).join("").trim()}function c(e,n){switch(e.type){case"block":return"";case"text":return b(e.text??"",e.format);case"linebreak":return`
2
+ `;case"tab":return" ";case"heading":return w(e,n);case"paragraph":return S(e,n);case"link":case"autolink":return h(e,n);case"list":return z(e,n);case"listitem":return s(e,n).trim();case"quote":case"blockquote":return N(e,n);case"horizontalrule":return`---
3
3
 
4
- `;case"root":return l(e,n).trim();default:return l(e,n)}}function l(e,n){return(e.children??[]).map(t=>o(t,n)).join("")}function p(e,n=0){if((n&16)===16)return`\`${e}\``;let t=e,i=(n&1)===1,r=(n&2)===2;return i&&r?t=`***${t}***`:i?t=`**${t}**`:r&&(t=`_${t}_`),(n&4)===4&&(t=`~~${t}~~`),(n&8)===8&&(t=`<u>${t}</u>`),t}function x(e,n){let i=(typeof e.tag=="string"?/^h([1-6])$/.exec(e.tag):null)?.[1]??"2",r=l(e,n).trim();return`${"#".repeat(Number(i))} ${r}
4
+ `;case"root":return s(e,n).trim();default:return s(e,n)}}function s(e,n){return(e.children??[]).map(t=>c(t,n)).join("")}function b(e,n=0){if((n&16)===16)return`\`${e}\``;let t=e,i=(n&1)===1,r=(n&2)===2;return i&&r?t=`***${t}***`:i?t=`**${t}**`:r&&(t=`_${t}_`),(n&4)===4&&(t=`~~${t}~~`),(n&8)===8&&(t=`<u>${t}</u>`),t}function w(e,n){let i=(typeof e.tag=="string"?/^h([1-6])$/.exec(e.tag):null)?.[1]??"2",r=s(e,n).trim();return`${"#".repeat(Number(i))} ${r}
5
5
 
6
- `}function L(e,n){return`${l(e,n).trim()}
6
+ `}function S(e,n){return`${s(e,n).trim()}
7
7
 
8
- `}function g(e,n){let t=l(e,n).trim(),i=T(e,n);return`[${t}](${i})`}function T(e,n){let t=e.fields,i=t?.url??e.url;return t?.linkType==="internal"?n.resolveInternalLink?.({relationTo:t.doc?.relationTo,value:t.doc?.value,url:i})??i??"#":i??"#"}function S(e,n){let t=e.listType==="number"||e.listType==="ordered";return`${(e.children??[]).map((r,d)=>`${t?`${d+1}. `:"- "}${o(r,n).trim()}`).join(`
8
+ `}function h(e,n){let t=s(e,n).trim(),i=O(e,n);return`[${t}](${i})`}function O(e,n){let t=e.fields,i=t?.url??e.url;return t?.linkType==="internal"?n.resolveInternalLink?.({relationTo:t.doc?.relationTo,value:t.doc?.value,url:i})??i??"#":i??"#"}function z(e,n){let t=e.listType==="number"||e.listType==="ordered";return`${(e.children??[]).map((r,l)=>`${t?`${l+1}. `:"- "}${c(r,n).trim()}`).join(`
9
9
  `)}
10
10
 
11
- `}function k(e,n){return`${l(e,n).trim().split(`
11
+ `}function N(e,n){return`${s(e,n).trim().split(`
12
12
  `).map(i=>`> ${i}`).join(`
13
13
  `)}
14
14
 
15
- `}function a(e={}){return{enabled:e.enabled??!0,routes:{llmsTxt:e.routes?.llmsTxt??"/llms.txt",markdownSegment:e.routes?.markdownSegment??"md"}}}var s=e=>(a(e),n=>n);export{u as buildLlmsTxt,s as default,c as formatLlmsTxtLink,m as lexicalToMarkdown,a as normalizeOptions,s as payloadPluginLlms};
15
+ `}function g(e){let n=`- [${e.title}](${e.url})`;return e.description?`${n}: ${e.description}`:n}function P(e){let n=[];e.title&&n.push(`# ${e.title}`,""),e.description&&n.push(`> ${e.description}`,""),u(n,e.intro);for(let t of e.sections??[]){n.push(`## ${t.title}`,""),u(n,t.content,{trailingBlank:!1});for(let i of t.links??[])n.push(g(i));n.push("")}return u(n,e.footer,{trailingBlank:!1}),I(n).join(`
16
+ `)}async function E(e){return x(e,"llmsTxt")}async function G(e){return x(e,"llmsFullTxt")}async function x(e,n){let t=e.globalSlug??"llms",r=(await e.payload.findGlobal({slug:t,locale:e.locale,draft:e.draft,depth:e.depth??2,req:e.req}))?.[n];return M(r,e)}async function M(e,n){if(!e)return"";let t=n.lexical??{},i=[];e.openingContent&&i.push(await d(e.openingContent,t));for(let r of e.sections??[]){let l=r.content?await d(r.content,t):"",o=r.title?.trim()??"";!o&&!l.trim()||(i.push(`
17
+ ---
18
+ `),o&&i.push(`
19
+ ## ${o}
20
+
21
+ `),l.trim()&&i.push(l))}return i.join("").trim()}function u(e,n,t={}){let i=Array.isArray(n)?n:n?[n]:[];if(i.length!==0){if(t.trailingBlank??!0){for(let r of i)e.push(r,"");return}for(let r of i)e.push(r)}}function I(e){let n=[...e];for(;n[0]==="";)n.shift();for(;n.at(-1)==="";)n.pop();return n}import{BlockquoteFeature as R,HeadingFeature as C,HorizontalRuleFeature as $,lexicalEditor as F,OrderedListFeature as A,UnorderedListFeature as v}from"@payloadcms/richtext-lexical";function m(){return F({features:({defaultFeatures:e})=>[C({enabledHeadingSizes:["h1","h2","h3","h4"]}),R(),$(),A(),v(),...e]})}function L(e,n){return[{name:"openingContent",type:"richText",localized:n,label:"Opening content",admin:{description:"Rendered at the top of the file (headings, lists, formatting, quotes, horizontal rules). Use an H1 for a title if you want one."},editor:e},{name:"sections",type:"array",localized:n,label:"Sections",admin:{description:"Each section is separated by a horizontal rule in the output.",initCollapsed:!0},fields:[{name:"title",type:"text",localized:n,label:"Section title"},{name:"content",type:"richText",localized:n,label:"Content",required:!0,editor:e}]}]}function y(e){if(!Array.isArray(e))return[];let n=[];for(let t of e)n.push(t);return n}function B(e,n){if(!n)return e;if(!e)return n;let t=e,i=n,r={...t};for(let l of Object.keys(i)){let o=t[l],a=i[l];Array.isArray(o)||Array.isArray(a)?r[l]=[...y(o),...y(a)]:a!==void 0&&(r[l]=a)}return r}function H(e,n){if(!n)return e;let{hooks:t,access:i,admin:r,fields:l,...o}=n,a={...e,...o};return i&&(a.access={...e.access,...i}),r&&(a.admin={...e.admin,...r}),(t||e.hooks)&&(a.hooks=B(e.hooks,t)),a}function f(e){let n=m(),{slug:t,label:i,localized:r,overrides:l}=e.global,o={slug:t,label:i,fields:[{type:"tabs",tabs:[{name:"llmsTxt",label:"llms.txt",fields:L(n,r)},{name:"llmsFullTxt",label:"llms-full.txt",fields:L(n,r)}]}]};return H(o,l)}function _(e={}){return{slug:e.global?.slug??"llms",label:e.global?.label??"LLMs",localized:e.global?.localized??!1,overrides:e.global?.overrides}}function p(e={}){return{enabled:e.enabled??!0,routes:{llmsTxt:e.routes?.llmsTxt??"/llms.txt",markdownSegment:e.routes?.markdownSegment??"md"},global:_(e)}}var k=e=>{let n=p(e);return n.enabled?t=>(t.globals??[]).some(i=>i.slug===n.global.slug)?t:{...t,globals:[...t.globals??[],f(n)]}:t=>t};export{G as buildLlmsFullTxt,E as buildLlmsTxt,P as buildLlmsTxtFromStructured,f as createLlmsGlobal,m as createLlmsLexicalEditor,k as default,g as formatLlmsTxtLink,T as lexicalToMarkdown,d as lexicalToMarkdownAsync,p as normalizeOptions,k as payloadPluginLlms};
16
22
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lexical.ts","../src/options.ts","../src/plugin.ts"],"sourcesContent":["export type SerializedLexicalNode = {\n type?: string\n [key: string]: unknown\n}\n\ntype SerializedElementNode = SerializedLexicalNode & {\n children?: SerializedLexicalNode[]\n}\n\ntype SerializedTextNode = SerializedLexicalNode & {\n type: \"text\"\n text?: string\n format?: number\n}\n\ntype SerializedLinkNode = SerializedElementNode & {\n url?: string\n fields?: {\n linkType?: string\n url?: string\n doc?: {\n relationTo?: string\n value?: unknown\n }\n }\n}\n\nexport type LexicalToMarkdownOptions = {\n resolveInternalLink?: (reference: {\n relationTo?: string\n value?: unknown\n url?: string\n }) => string | null | undefined\n}\n\nconst IS_BOLD = 1\nconst IS_ITALIC = 2\nconst IS_STRIKETHROUGH = 4\nconst IS_UNDERLINE = 8\nconst IS_CODE = 16\n\nexport function lexicalToMarkdown(\n data: { root?: { children?: SerializedLexicalNode[] } },\n options: LexicalToMarkdownOptions = {},\n): string {\n const children = data.root?.children ?? []\n return children.map((node) => nodeToMarkdown(node, options)).join(\"\").trim()\n}\n\nfunction nodeToMarkdown(node: SerializedLexicalNode, options: LexicalToMarkdownOptions): string {\n switch (node.type) {\n case \"text\":\n return formatText((node as SerializedTextNode).text ?? \"\", (node as SerializedTextNode).format)\n case \"linebreak\":\n return \"\\n\"\n case \"tab\":\n return \"\\t\"\n case \"heading\":\n return headingToMarkdown(node as SerializedElementNode, options)\n case \"paragraph\":\n return paragraphToMarkdown(node as SerializedElementNode, options)\n case \"link\":\n case \"autolink\":\n return linkToMarkdown(node as SerializedLinkNode, options)\n case \"list\":\n return listToMarkdown(node as SerializedElementNode & { listType?: string }, options)\n case \"listitem\":\n return childrenToMarkdown(node as SerializedElementNode, options).trim()\n case \"quote\":\n case \"blockquote\":\n return quoteToMarkdown(node as SerializedElementNode, options)\n case \"horizontalrule\":\n return \"---\\n\\n\"\n case \"root\":\n return childrenToMarkdown(node as SerializedElementNode, options).trim()\n default:\n return childrenToMarkdown(node as SerializedElementNode, options)\n }\n}\n\nfunction childrenToMarkdown(\n node: SerializedElementNode,\n options: LexicalToMarkdownOptions,\n): string {\n return (node.children ?? []).map((child) => nodeToMarkdown(child, options)).join(\"\")\n}\n\nfunction formatText(text: string, format = 0): string {\n if ((format & IS_CODE) === IS_CODE) {\n return `\\`${text}\\``\n }\n\n let markdown = text\n const isBold = (format & IS_BOLD) === IS_BOLD\n const isItalic = (format & IS_ITALIC) === IS_ITALIC\n\n if (isBold && isItalic) {\n markdown = `***${markdown}***`\n } else if (isBold) {\n markdown = `**${markdown}**`\n } else if (isItalic) {\n markdown = `_${markdown}_`\n }\n\n if ((format & IS_STRIKETHROUGH) === IS_STRIKETHROUGH) {\n markdown = `~~${markdown}~~`\n }\n\n if ((format & IS_UNDERLINE) === IS_UNDERLINE) {\n markdown = `<u>${markdown}</u>`\n }\n\n return markdown\n}\n\nfunction headingToMarkdown(\n node: SerializedElementNode & { tag?: unknown },\n options: LexicalToMarkdownOptions,\n): string {\n const match = typeof node.tag === \"string\" ? /^h([1-6])$/.exec(node.tag) : null\n const level = match?.[1] ?? \"2\"\n const content = childrenToMarkdown(node, options).trim()\n\n return `${\"#\".repeat(Number(level))} ${content}\\n\\n`\n}\n\nfunction paragraphToMarkdown(\n node: SerializedElementNode,\n options: LexicalToMarkdownOptions,\n): string {\n return `${childrenToMarkdown(node, options).trim()}\\n\\n`\n}\n\nfunction linkToMarkdown(node: SerializedLinkNode, options: LexicalToMarkdownOptions): string {\n const text = childrenToMarkdown(node, options).trim()\n const href = getLinkHref(node, options)\n\n return `[${text}](${href})`\n}\n\nfunction getLinkHref(node: SerializedLinkNode, options: LexicalToMarkdownOptions): string {\n const fields = node.fields\n const fallbackUrl = fields?.url ?? node.url\n\n if (fields?.linkType === \"internal\") {\n const resolved = options.resolveInternalLink?.({\n relationTo: fields.doc?.relationTo,\n value: fields.doc?.value,\n url: fallbackUrl,\n })\n\n return resolved ?? fallbackUrl ?? \"#\"\n }\n\n return fallbackUrl ?? \"#\"\n}\n\nfunction listToMarkdown(\n node: SerializedElementNode & { listType?: string },\n options: LexicalToMarkdownOptions,\n): string {\n const isNumbered = node.listType === \"number\" || node.listType === \"ordered\"\n const items = (node.children ?? []).map((child, index) => {\n const prefix = isNumbered ? `${index + 1}. ` : \"- \"\n return `${prefix}${nodeToMarkdown(child, options).trim()}`\n })\n\n return `${items.join(\"\\n\")}\\n\\n`\n}\n\nfunction quoteToMarkdown(node: SerializedElementNode, options: LexicalToMarkdownOptions): string {\n const content = childrenToMarkdown(node, options)\n .trim()\n .split(\"\\n\")\n .map((line) => `> ${line}`)\n .join(\"\\n\")\n\n return `${content}\\n\\n`\n}\n","import type { NormalizedPayloadPluginLlmsOptions, PayloadPluginLlmsOptions } from \"./types\"\n\nexport function normalizeOptions(\n options: PayloadPluginLlmsOptions = {},\n): NormalizedPayloadPluginLlmsOptions {\n return {\n enabled: options.enabled ?? true,\n routes: {\n llmsTxt: options.routes?.llmsTxt ?? \"/llms.txt\",\n markdownSegment: options.routes?.markdownSegment ?? \"md\",\n },\n }\n}\n","import { normalizeOptions } from \"./options\"\n\nimport type { PayloadPlugin, PayloadPluginLlmsOptions } from \"./types\"\n\nexport const payloadPluginLlms = (options?: PayloadPluginLlmsOptions): PayloadPlugin => {\n normalizeOptions(options)\n\n return (config) => config\n}\n"],"mappings":"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","names":["lexicalToMarkdown","data","options","node","nodeToMarkdown","formatText","headingToMarkdown","paragraphToMarkdown","linkToMarkdown","listToMarkdown","childrenToMarkdown","quoteToMarkdown","child","text","format","markdown","isBold","isItalic","level","content","href","getLinkHref","fields","fallbackUrl","isNumbered","index","line","normalizeOptions","options","payloadPluginLlms","options","normalizeOptions","config"]}
1
+ {"version":3,"sources":["../src/lexical.ts","../src/llms-txt.ts","../src/llms-lexical.ts","../src/global.ts","../src/options.ts","../src/plugin.ts"],"sourcesContent":["/** Minimal serialized Lexical node shape accepted by the markdown converter. */\nexport interface SerializedLexicalNode {\n /** Lexical node type, such as `paragraph`, `heading`, `text`, or `link`. */\n type?: string\n [key: string]: unknown\n}\n\ntype SerializedElementNode = SerializedLexicalNode & {\n children?: SerializedLexicalNode[]\n}\n\ntype SerializedTextNode = SerializedLexicalNode & {\n type: \"text\"\n text?: string\n format?: number\n}\n\ntype SerializedLinkNode = SerializedElementNode & {\n url?: string\n fields?: {\n linkType?: string\n url?: string\n doc?: {\n relationTo?: string\n value?: unknown\n }\n }\n}\n\n/** Options for converting serialized Lexical content to markdown. */\nexport interface LexicalToMarkdownOptions {\n /** Resolves Payload/Lexical internal link references to public URLs. */\n resolveInternalLink?: (reference: {\n /** Collection slug for the linked document. */\n relationTo?: string\n /** Linked document id or populated document value. */\n value?: unknown\n /** Fallback URL stored on the Lexical link node. */\n url?: string\n }) => string | null | undefined\n}\n\n/** Options for async Lexical → markdown conversion (includes serialized block nodes). */\nexport interface LexicalToMarkdownAsyncOptions extends LexicalToMarkdownOptions {\n /**\n * When a serialized `block` node is encountered, returns markdown for that block’s `fields`.\n * If omitted, block nodes produce no output.\n */\n resolveLexicalBlock?: (fields: Record<string, unknown>) => Promise<string> | string\n}\n\nconst IS_BOLD = 1\nconst IS_ITALIC = 2\nconst IS_STRIKETHROUGH = 4\nconst IS_UNDERLINE = 8\nconst IS_CODE = 16\n\nexport function lexicalToMarkdown(\n data: { root?: { children?: SerializedLexicalNode[] } },\n options: LexicalToMarkdownOptions = {},\n): string {\n const children = data.root?.children ?? []\n return children\n .map((node) => nodeToMarkdown(node, options))\n .join(\"\")\n .trim()\n}\n\n/**\n * Like {@link lexicalToMarkdown}, but resolves top-level serialized `block` nodes via\n * `resolveLexicalBlock`.\n */\nexport async function lexicalToMarkdownAsync(\n data: { root?: { children?: SerializedLexicalNode[] } } | null | undefined,\n options: LexicalToMarkdownAsyncOptions = {},\n): Promise<string> {\n const children = data?.root?.children ?? []\n const segments = await Promise.all(\n children.map(async (node) => {\n if (node.type === \"block\") {\n const fields = (node as SerializedLexicalNode & { fields?: Record<string, unknown> }).fields\n if (fields && options.resolveLexicalBlock) {\n return await options.resolveLexicalBlock(fields)\n }\n return \"\"\n }\n return nodeToMarkdown(node, options)\n }),\n )\n return segments.join(\"\").trim()\n}\n\nfunction nodeToMarkdown(node: SerializedLexicalNode, options: LexicalToMarkdownOptions): string {\n switch (node.type) {\n case \"block\":\n return \"\"\n case \"text\":\n return formatText(\n (node as SerializedTextNode).text ?? \"\",\n (node as SerializedTextNode).format,\n )\n case \"linebreak\":\n return \"\\n\"\n case \"tab\":\n return \"\\t\"\n case \"heading\":\n return headingToMarkdown(node as SerializedElementNode, options)\n case \"paragraph\":\n return paragraphToMarkdown(node as SerializedElementNode, options)\n case \"link\":\n case \"autolink\":\n return linkToMarkdown(node as SerializedLinkNode, options)\n case \"list\":\n return listToMarkdown(node as SerializedElementNode & { listType?: string }, options)\n case \"listitem\":\n return childrenToMarkdown(node as SerializedElementNode, options).trim()\n case \"quote\":\n case \"blockquote\":\n return quoteToMarkdown(node as SerializedElementNode, options)\n case \"horizontalrule\":\n return \"---\\n\\n\"\n case \"root\":\n return childrenToMarkdown(node as SerializedElementNode, options).trim()\n default:\n return childrenToMarkdown(node as SerializedElementNode, options)\n }\n}\n\nfunction childrenToMarkdown(\n node: SerializedElementNode,\n options: LexicalToMarkdownOptions,\n): string {\n return (node.children ?? []).map((child) => nodeToMarkdown(child, options)).join(\"\")\n}\n\nfunction formatText(text: string, format = 0): string {\n if ((format & IS_CODE) === IS_CODE) {\n return `\\`${text}\\``\n }\n\n let markdown = text\n const isBold = (format & IS_BOLD) === IS_BOLD\n const isItalic = (format & IS_ITALIC) === IS_ITALIC\n\n if (isBold && isItalic) {\n markdown = `***${markdown}***`\n } else if (isBold) {\n markdown = `**${markdown}**`\n } else if (isItalic) {\n markdown = `_${markdown}_`\n }\n\n if ((format & IS_STRIKETHROUGH) === IS_STRIKETHROUGH) {\n markdown = `~~${markdown}~~`\n }\n\n if ((format & IS_UNDERLINE) === IS_UNDERLINE) {\n markdown = `<u>${markdown}</u>`\n }\n\n return markdown\n}\n\nfunction headingToMarkdown(\n node: SerializedElementNode & { tag?: unknown },\n options: LexicalToMarkdownOptions,\n): string {\n const match = typeof node.tag === \"string\" ? /^h([1-6])$/.exec(node.tag) : null\n const level = match?.[1] ?? \"2\"\n const content = childrenToMarkdown(node, options).trim()\n\n return `${\"#\".repeat(Number(level))} ${content}\\n\\n`\n}\n\nfunction paragraphToMarkdown(\n node: SerializedElementNode,\n options: LexicalToMarkdownOptions,\n): string {\n return `${childrenToMarkdown(node, options).trim()}\\n\\n`\n}\n\nfunction linkToMarkdown(node: SerializedLinkNode, options: LexicalToMarkdownOptions): string {\n const text = childrenToMarkdown(node, options).trim()\n const href = getLinkHref(node, options)\n\n return `[${text}](${href})`\n}\n\nfunction getLinkHref(node: SerializedLinkNode, options: LexicalToMarkdownOptions): string {\n const fields = node.fields\n const fallbackUrl = fields?.url ?? node.url\n\n if (fields?.linkType === \"internal\") {\n const resolved = options.resolveInternalLink?.({\n relationTo: fields.doc?.relationTo,\n value: fields.doc?.value,\n url: fallbackUrl,\n })\n\n return resolved ?? fallbackUrl ?? \"#\"\n }\n\n return fallbackUrl ?? \"#\"\n}\n\nfunction listToMarkdown(\n node: SerializedElementNode & { listType?: string },\n options: LexicalToMarkdownOptions,\n): string {\n const isNumbered = node.listType === \"number\" || node.listType === \"ordered\"\n const items = (node.children ?? []).map((child, index) => {\n const prefix = isNumbered ? `${index + 1}. ` : \"- \"\n return `${prefix}${nodeToMarkdown(child, options).trim()}`\n })\n\n return `${items.join(\"\\n\")}\\n\\n`\n}\n\nfunction quoteToMarkdown(node: SerializedElementNode, options: LexicalToMarkdownOptions): string {\n const content = childrenToMarkdown(node, options)\n .trim()\n .split(\"\\n\")\n .map((line) => `> ${line}`)\n .join(\"\\n\")\n\n return `${content}\\n\\n`\n}\n","import {\n lexicalToMarkdownAsync,\n type LexicalToMarkdownAsyncOptions,\n type SerializedLexicalNode,\n} from \"./lexical\"\n\nimport type { Payload, PayloadRequest } from \"payload\"\n\n/** Link entry rendered inside a structured llms.txt section (legacy builder). */\nexport interface LlmsTxtLink {\n /** Link label rendered inside the markdown link. */\n title: string\n /** Link destination URL. */\n url: string\n /** Optional text appended after the link. */\n description?: string | null\n}\n\n/** Section rendered in a structured llms.txt document (legacy builder). */\nexport interface LlmsTxtSection {\n /** Section heading. */\n title: string\n /** Paragraph content rendered before section links. */\n content?: string | string[]\n /** Links rendered in the section. */\n links?: LlmsTxtLink[]\n}\n\n/** Structured content used to build an llms.txt document without Lexical (legacy builder). */\nexport interface LlmsTxtContent {\n /** Optional document title rendered as the top-level heading. */\n title?: string\n /** Optional blockquote description rendered below the title. */\n description?: string\n /** Intro paragraphs rendered before sections. */\n intro?: string | string[]\n /** Sections rendered in order. */\n sections?: LlmsTxtSection[]\n /** Footer paragraphs rendered after sections. */\n footer?: string | string[]\n}\n\nexport interface BuildLlmsTxtFromGlobalOptions {\n /** Payload instance (Local API). */\n payload: Payload\n /** Passed to `findGlobal` when the llms global uses localized fields. */\n locale?: string\n draft?: boolean\n depth?: number\n /** Express / Payload request for nested operations; recommended inside hooks. */\n req?: PayloadRequest\n /**\n * Global slug; defaults to `\"llms\"`.\n * Should match the `global.slug` option passed to `payloadPluginLlms` when overridden.\n */\n globalSlug?: string\n /**\n * Options passed to markdown conversion. Use `resolveLexicalBlock` if you need custom\n * Lexical block serialization.\n */\n lexical?: LexicalToMarkdownAsyncOptions\n}\n\ninterface LlmsTabDoc {\n openingContent?: unknown\n sections?: Array<{ title?: string | null; content?: unknown }> | null\n}\n\nexport function formatLlmsTxtLink(link: LlmsTxtLink): string {\n const line = `- [${link.title}](${link.url})`\n return link.description ? `${line}: ${link.description}` : line\n}\n\n/** Build llms.txt-style plain text from structured sections and links (no Lexical). */\nexport function buildLlmsTxtFromStructured(content: LlmsTxtContent): string {\n const lines: string[] = []\n\n if (content.title) {\n lines.push(`# ${content.title}`, \"\")\n }\n if (content.description) {\n lines.push(`> ${content.description}`, \"\")\n }\n\n appendLines(lines, content.intro)\n\n for (const section of content.sections ?? []) {\n lines.push(`## ${section.title}`, \"\")\n appendLines(lines, section.content, { trailingBlank: false })\n for (const link of section.links ?? []) {\n lines.push(formatLlmsTxtLink(link))\n }\n lines.push(\"\")\n }\n\n appendLines(lines, content.footer, { trailingBlank: false })\n\n return trimBlankEdges(lines).join(\"\\n\")\n}\n\n/** Load the `llms.txt` tab from the `llms` global and render markdown. */\nexport async function buildLlmsTxt(options: BuildLlmsTxtFromGlobalOptions): Promise<string> {\n return loadLlmsGlobalTab(options, \"llmsTxt\")\n}\n\n/** Load the `llms-full.txt` tab from the `llms` global and render markdown. */\nexport async function buildLlmsFullTxt(options: BuildLlmsTxtFromGlobalOptions): Promise<string> {\n return loadLlmsGlobalTab(options, \"llmsFullTxt\")\n}\n\nasync function loadLlmsGlobalTab(\n options: BuildLlmsTxtFromGlobalOptions,\n tabKey: \"llmsTxt\" | \"llmsFullTxt\",\n): Promise<string> {\n const slug = options.globalSlug ?? \"llms\"\n const doc = (await options.payload.findGlobal({\n slug,\n locale: options.locale,\n draft: options.draft,\n depth: options.depth ?? 2,\n req: options.req,\n })) as Record<string, unknown> | null\n\n const tab = doc?.[tabKey] as LlmsTabDoc | undefined\n return assembleLlmsMarkdownFromTab(tab, options)\n}\n\nasync function assembleLlmsMarkdownFromTab(\n tab: LlmsTabDoc | null | undefined,\n options: BuildLlmsTxtFromGlobalOptions,\n): Promise<string> {\n if (!tab) {\n return \"\"\n }\n\n const lexicalOpts = options.lexical ?? {}\n\n const parts: string[] = []\n\n if (tab.openingContent) {\n parts.push(\n await lexicalToMarkdownAsync(\n tab.openingContent as { root?: { children?: SerializedLexicalNode[] } },\n lexicalOpts,\n ),\n )\n }\n\n for (const section of tab.sections ?? []) {\n const body = section.content\n ? await lexicalToMarkdownAsync(\n section.content as { root?: { children?: SerializedLexicalNode[] } },\n lexicalOpts,\n )\n : \"\"\n const title = section.title?.trim() ?? \"\"\n if (!title && !body.trim()) {\n continue\n }\n parts.push(\"\\n---\\n\")\n if (title) {\n parts.push(`\\n## ${title}\\n\\n`)\n }\n if (body.trim()) {\n parts.push(body)\n }\n }\n\n return parts.join(\"\").trim()\n}\n\nfunction appendLines(\n lines: string[],\n value: string | string[] | undefined,\n options: { trailingBlank?: boolean } = {},\n) {\n const values = Array.isArray(value) ? value : value ? [value] : []\n if (values.length === 0) return\n\n if (options.trailingBlank ?? true) {\n for (const item of values) {\n lines.push(item, \"\")\n }\n return\n }\n\n for (const item of values) {\n lines.push(item)\n }\n}\n\nfunction trimBlankEdges(lines: string[]) {\n const trimmed = [...lines]\n while (trimmed[0] === \"\") trimmed.shift()\n while (trimmed.at(-1) === \"\") trimmed.pop()\n return trimmed\n}\n","import type { RichTextField } from \"payload\"\n\nimport {\n BlockquoteFeature,\n HeadingFeature,\n HorizontalRuleFeature,\n lexicalEditor,\n OrderedListFeature,\n UnorderedListFeature,\n} from \"@payloadcms/richtext-lexical\"\n\n/** Lexical editor for llms opening content and section bodies (headings, lists, quotes, rules, default rich-text features). */\nexport function createLlmsLexicalEditor(): NonNullable<RichTextField[\"editor\"]> {\n return lexicalEditor({\n features: ({ defaultFeatures }) => [\n HeadingFeature({ enabledHeadingSizes: [\"h1\", \"h2\", \"h3\", \"h4\"] }),\n BlockquoteFeature(),\n HorizontalRuleFeature(),\n OrderedListFeature(),\n UnorderedListFeature(),\n ...defaultFeatures,\n ],\n })\n}\n","import { createLlmsLexicalEditor } from \"./llms-lexical\"\n\nimport type { NormalizedPayloadPluginLlmsOptions } from \"./types\"\nimport type { Field, GlobalConfig } from \"payload\"\n\ntype LexicalEditorProvider = ReturnType<typeof createLlmsLexicalEditor>\n\nfunction llmsTabFields(editor: LexicalEditorProvider, localized: boolean): Field[] {\n return [\n {\n name: \"openingContent\",\n type: \"richText\",\n localized,\n label: \"Opening content\",\n admin: {\n description:\n \"Rendered at the top of the file (headings, lists, formatting, quotes, horizontal rules). Use an H1 for a title if you want one.\",\n },\n editor,\n },\n {\n name: \"sections\",\n type: \"array\",\n localized,\n label: \"Sections\",\n admin: {\n description: \"Each section is separated by a horizontal rule in the output.\",\n initCollapsed: true,\n },\n fields: [\n {\n name: \"title\",\n type: \"text\",\n localized,\n label: \"Section title\",\n },\n {\n name: \"content\",\n type: \"richText\",\n localized,\n label: \"Content\",\n required: true,\n editor,\n },\n ],\n },\n ]\n}\n\nfunction unknownArrayFrom(value: unknown): unknown[] {\n if (!Array.isArray(value)) {\n return []\n }\n const out: unknown[] = []\n for (const item of value) {\n out.push(item)\n }\n return out\n}\n\nfunction mergeHooks<H extends Record<string, unknown> | undefined>(base: H, extra: H): H {\n if (!extra) {\n return base\n }\n if (!base) {\n return extra\n }\n const a = base\n const b = extra\n const out: Record<string, unknown> = { ...a }\n for (const key of Object.keys(b)) {\n const av = a[key]\n const bv = b[key]\n if (Array.isArray(av) || Array.isArray(bv)) {\n out[key] = [...unknownArrayFrom(av), ...unknownArrayFrom(bv)]\n } else if (bv !== undefined) {\n out[key] = bv\n }\n }\n return out as H\n}\n\nfunction mergeGlobalOverride(\n base: GlobalConfig,\n override: Partial<GlobalConfig> | undefined,\n): GlobalConfig {\n if (!override) {\n return base\n }\n\n const {\n hooks: overrideHooks,\n access: overrideAccess,\n admin: overrideAdmin,\n fields: _fields,\n ...rest\n } = override\n\n const merged: GlobalConfig = {\n ...base,\n ...rest,\n }\n\n if (overrideAccess) {\n merged.access = {\n ...(base.access as Record<string, unknown> | undefined),\n ...(overrideAccess as Record<string, unknown>),\n } as GlobalConfig[\"access\"]\n }\n\n if (overrideAdmin) {\n merged.admin = {\n ...(base.admin as Record<string, unknown> | undefined),\n ...(overrideAdmin as Record<string, unknown>),\n } as GlobalConfig[\"admin\"]\n }\n\n if (overrideHooks || base.hooks) {\n merged.hooks = mergeHooks(\n base.hooks as Record<string, unknown> | undefined,\n overrideHooks as Record<string, unknown> | undefined,\n ) as GlobalConfig[\"hooks\"]\n }\n\n return merged\n}\n\nexport function createLlmsGlobal(normalized: NormalizedPayloadPluginLlmsOptions): GlobalConfig {\n const editor = createLlmsLexicalEditor()\n const { slug, label, localized, overrides } = normalized.global\n\n const base = {\n slug,\n label,\n fields: [\n {\n type: \"tabs\",\n tabs: [\n {\n name: \"llmsTxt\",\n label: \"llms.txt\",\n fields: llmsTabFields(editor, localized),\n },\n {\n name: \"llmsFullTxt\",\n label: \"llms-full.txt\",\n fields: llmsTabFields(editor, localized),\n },\n ],\n },\n ],\n } satisfies GlobalConfig\n\n return mergeGlobalOverride(base, overrides)\n}\n","import type {\n NormalizedLlmsGlobalOptions,\n NormalizedPayloadPluginLlmsOptions,\n PayloadPluginLlmsOptions,\n} from \"./types\"\n\nfunction normalizeGlobalOptions(options: PayloadPluginLlmsOptions = {}): NormalizedLlmsGlobalOptions {\n return {\n slug: options.global?.slug ?? \"llms\",\n label: options.global?.label ?? \"LLMs\",\n localized: options.global?.localized ?? false,\n overrides: options.global?.overrides,\n }\n}\n\nexport function normalizeOptions(\n options: PayloadPluginLlmsOptions = {},\n): NormalizedPayloadPluginLlmsOptions {\n return {\n enabled: options.enabled ?? true,\n routes: {\n llmsTxt: options.routes?.llmsTxt ?? \"/llms.txt\",\n markdownSegment: options.routes?.markdownSegment ?? \"md\",\n },\n global: normalizeGlobalOptions(options),\n }\n}\n","import { createLlmsGlobal } from \"./global\"\nimport { normalizeOptions } from \"./options\"\n\nimport type { PayloadPlugin, PayloadPluginLlmsOptions } from \"./types\"\n\nexport const payloadPluginLlms = (options?: PayloadPluginLlmsOptions): PayloadPlugin => {\n const normalized = normalizeOptions(options)\n\n if (!normalized.enabled) {\n return (config) => config\n }\n\n return (config) => {\n if ((config.globals ?? []).some((global_) => global_.slug === normalized.global.slug)) {\n return config\n }\n\n return {\n ...config,\n globals: [...(config.globals ?? []), createLlmsGlobal(normalized)],\n }\n }\n}\n"],"mappings":"AAyDO,SAASA,EACdC,EACAC,EAAoC,CAAC,EAC7B,CAER,OADiBD,EAAK,MAAM,UAAY,CAAC,GAEtC,IAAKE,GAASC,EAAeD,EAAMD,CAAO,CAAC,EAC3C,KAAK,EAAE,EACP,KAAK,CACV,CAMA,eAAsBG,EACpBJ,EACAC,EAAyC,CAAC,EACzB,CACjB,IAAMI,EAAWL,GAAM,MAAM,UAAY,CAAC,EAa1C,OAZiB,MAAM,QAAQ,IAC7BK,EAAS,IAAI,MAAOH,GAAS,CAC3B,GAAIA,EAAK,OAAS,QAAS,CACzB,IAAMI,EAAUJ,EAAsE,OACtF,OAAII,GAAUL,EAAQ,oBACb,MAAMA,EAAQ,oBAAoBK,CAAM,EAE1C,EACT,CACA,OAAOH,EAAeD,EAAMD,CAAO,CACrC,CAAC,CACH,GACgB,KAAK,EAAE,EAAE,KAAK,CAChC,CAEA,SAASE,EAAeD,EAA6BD,EAA2C,CAC9F,OAAQC,EAAK,KAAM,CACjB,IAAK,QACH,MAAO,GACT,IAAK,OACH,OAAOK,EACJL,EAA4B,MAAQ,GACpCA,EAA4B,MAC/B,EACF,IAAK,YACH,MAAO;AAAA,EACT,IAAK,MACH,MAAO,IACT,IAAK,UACH,OAAOM,EAAkBN,EAA+BD,CAAO,EACjE,IAAK,YACH,OAAOQ,EAAoBP,EAA+BD,CAAO,EACnE,IAAK,OACL,IAAK,WACH,OAAOS,EAAeR,EAA4BD,CAAO,EAC3D,IAAK,OACH,OAAOU,EAAeT,EAAuDD,CAAO,EACtF,IAAK,WACH,OAAOW,EAAmBV,EAA+BD,CAAO,EAAE,KAAK,EACzE,IAAK,QACL,IAAK,aACH,OAAOY,EAAgBX,EAA+BD,CAAO,EAC/D,IAAK,iBACH,MAAO;AAAA;AAAA,EACT,IAAK,OACH,OAAOW,EAAmBV,EAA+BD,CAAO,EAAE,KAAK,EACzE,QACE,OAAOW,EAAmBV,EAA+BD,CAAO,CACpE,CACF,CAEA,SAASW,EACPV,EACAD,EACQ,CACR,OAAQC,EAAK,UAAY,CAAC,GAAG,IAAKY,GAAUX,EAAeW,EAAOb,CAAO,CAAC,EAAE,KAAK,EAAE,CACrF,CAEA,SAASM,EAAWQ,EAAcC,EAAS,EAAW,CACpD,IAAKA,EAAS,MAAa,GACzB,MAAO,KAAKD,CAAI,KAGlB,IAAIE,EAAWF,EACTG,GAAUF,EAAS,KAAa,EAChCG,GAAYH,EAAS,KAAe,EAE1C,OAAIE,GAAUC,EACZF,EAAW,MAAMA,CAAQ,MAChBC,EACTD,EAAW,KAAKA,CAAQ,KACfE,IACTF,EAAW,IAAIA,CAAQ,MAGpBD,EAAS,KAAsB,IAClCC,EAAW,KAAKA,CAAQ,OAGrBD,EAAS,KAAkB,IAC9BC,EAAW,MAAMA,CAAQ,QAGpBA,CACT,CAEA,SAAST,EACPN,EACAD,EACQ,CAER,IAAMmB,GADQ,OAAOlB,EAAK,KAAQ,SAAW,aAAa,KAAKA,EAAK,GAAG,EAAI,QACrD,CAAC,GAAK,IACtBmB,EAAUT,EAAmBV,EAAMD,CAAO,EAAE,KAAK,EAEvD,MAAO,GAAG,IAAI,OAAO,OAAOmB,CAAK,CAAC,CAAC,IAAIC,CAAO;AAAA;AAAA,CAChD,CAEA,SAASZ,EACPP,EACAD,EACQ,CACR,MAAO,GAAGW,EAAmBV,EAAMD,CAAO,EAAE,KAAK,CAAC;AAAA;AAAA,CACpD,CAEA,SAASS,EAAeR,EAA0BD,EAA2C,CAC3F,IAAMc,EAAOH,EAAmBV,EAAMD,CAAO,EAAE,KAAK,EAC9CqB,EAAOC,EAAYrB,EAAMD,CAAO,EAEtC,MAAO,IAAIc,CAAI,KAAKO,CAAI,GAC1B,CAEA,SAASC,EAAYrB,EAA0BD,EAA2C,CACxF,IAAMK,EAASJ,EAAK,OACdsB,EAAclB,GAAQ,KAAOJ,EAAK,IAExC,OAAII,GAAQ,WAAa,WACNL,EAAQ,sBAAsB,CAC7C,WAAYK,EAAO,KAAK,WACxB,MAAOA,EAAO,KAAK,MACnB,IAAKkB,CACP,CAAC,GAEkBA,GAAe,IAG7BA,GAAe,GACxB,CAEA,SAASb,EACPT,EACAD,EACQ,CACR,IAAMwB,EAAavB,EAAK,WAAa,UAAYA,EAAK,WAAa,UAMnE,MAAO,IALQA,EAAK,UAAY,CAAC,GAAG,IAAI,CAACY,EAAOY,IAEvC,GADQD,EAAa,GAAGC,EAAQ,CAAC,KAAO,IAC/B,GAAGvB,EAAeW,EAAOb,CAAO,EAAE,KAAK,CAAC,EACzD,EAEe,KAAK;AAAA,CAAI,CAAC;AAAA;AAAA,CAC5B,CAEA,SAASY,EAAgBX,EAA6BD,EAA2C,CAO/F,MAAO,GANSW,EAAmBV,EAAMD,CAAO,EAC7C,KAAK,EACL,MAAM;AAAA,CAAI,EACV,IAAK0B,GAAS,KAAKA,CAAI,EAAE,EACzB,KAAK;AAAA,CAAI,CAEK;AAAA;AAAA,CACnB,CC9JO,SAASC,EAAkBC,EAA2B,CAC3D,IAAMC,EAAO,MAAMD,EAAK,KAAK,KAAKA,EAAK,GAAG,IAC1C,OAAOA,EAAK,YAAc,GAAGC,CAAI,KAAKD,EAAK,WAAW,GAAKC,CAC7D,CAGO,SAASC,EAA2BC,EAAiC,CAC1E,IAAMC,EAAkB,CAAC,EAErBD,EAAQ,OACVC,EAAM,KAAK,KAAKD,EAAQ,KAAK,GAAI,EAAE,EAEjCA,EAAQ,aACVC,EAAM,KAAK,KAAKD,EAAQ,WAAW,GAAI,EAAE,EAG3CE,EAAYD,EAAOD,EAAQ,KAAK,EAEhC,QAAWG,KAAWH,EAAQ,UAAY,CAAC,EAAG,CAC5CC,EAAM,KAAK,MAAME,EAAQ,KAAK,GAAI,EAAE,EACpCD,EAAYD,EAAOE,EAAQ,QAAS,CAAE,cAAe,EAAM,CAAC,EAC5D,QAAWN,KAAQM,EAAQ,OAAS,CAAC,EACnCF,EAAM,KAAKL,EAAkBC,CAAI,CAAC,EAEpCI,EAAM,KAAK,EAAE,CACf,CAEA,OAAAC,EAAYD,EAAOD,EAAQ,OAAQ,CAAE,cAAe,EAAM,CAAC,EAEpDI,EAAeH,CAAK,EAAE,KAAK;AAAA,CAAI,CACxC,CAGA,eAAsBI,EAAaC,EAAyD,CAC1F,OAAOC,EAAkBD,EAAS,SAAS,CAC7C,CAGA,eAAsBE,EAAiBF,EAAyD,CAC9F,OAAOC,EAAkBD,EAAS,aAAa,CACjD,CAEA,eAAeC,EACbD,EACAG,EACiB,CACjB,IAAMC,EAAOJ,EAAQ,YAAc,OAS7BK,GARO,MAAML,EAAQ,QAAQ,WAAW,CAC5C,KAAAI,EACA,OAAQJ,EAAQ,OAChB,MAAOA,EAAQ,MACf,MAAOA,EAAQ,OAAS,EACxB,IAAKA,EAAQ,GACf,CAAC,KAEiBG,CAAM,EACxB,OAAOG,EAA4BD,EAAKL,CAAO,CACjD,CAEA,eAAeM,EACbD,EACAL,EACiB,CACjB,GAAI,CAACK,EACH,MAAO,GAGT,IAAME,EAAcP,EAAQ,SAAW,CAAC,EAElCQ,EAAkB,CAAC,EAErBH,EAAI,gBACNG,EAAM,KACJ,MAAMC,EACJJ,EAAI,eACJE,CACF,CACF,EAGF,QAAWV,KAAWQ,EAAI,UAAY,CAAC,EAAG,CACxC,IAAMK,EAAOb,EAAQ,QACjB,MAAMY,EACJZ,EAAQ,QACRU,CACF,EACA,GACEI,EAAQd,EAAQ,OAAO,KAAK,GAAK,GACnC,CAACc,GAAS,CAACD,EAAK,KAAK,IAGzBF,EAAM,KAAK;AAAA;AAAA,CAAS,EAChBG,GACFH,EAAM,KAAK;AAAA,KAAQG,CAAK;AAAA;AAAA,CAAM,EAE5BD,EAAK,KAAK,GACZF,EAAM,KAAKE,CAAI,EAEnB,CAEA,OAAOF,EAAM,KAAK,EAAE,EAAE,KAAK,CAC7B,CAEA,SAASZ,EACPD,EACAiB,EACAZ,EAAuC,CAAC,EACxC,CACA,IAAMa,EAAS,MAAM,QAAQD,CAAK,EAAIA,EAAQA,EAAQ,CAACA,CAAK,EAAI,CAAC,EACjE,GAAIC,EAAO,SAAW,EAEtB,IAAIb,EAAQ,eAAiB,GAAM,CACjC,QAAWc,KAAQD,EACjBlB,EAAM,KAAKmB,EAAM,EAAE,EAErB,MACF,CAEA,QAAWA,KAAQD,EACjBlB,EAAM,KAAKmB,CAAI,EAEnB,CAEA,SAAShB,EAAeH,EAAiB,CACvC,IAAMoB,EAAU,CAAC,GAAGpB,CAAK,EACzB,KAAOoB,EAAQ,CAAC,IAAM,IAAIA,EAAQ,MAAM,EACxC,KAAOA,EAAQ,GAAG,EAAE,IAAM,IAAIA,EAAQ,IAAI,EAC1C,OAAOA,CACT,CClMA,OACE,qBAAAC,EACA,kBAAAC,EACA,yBAAAC,EACA,iBAAAC,EACA,sBAAAC,EACA,wBAAAC,MACK,+BAGA,SAASC,GAAgE,CAC9E,OAAOH,EAAc,CACnB,SAAU,CAAC,CAAE,gBAAAI,CAAgB,IAAM,CACjCN,EAAe,CAAE,oBAAqB,CAAC,KAAM,KAAM,KAAM,IAAI,CAAE,CAAC,EAChED,EAAkB,EAClBE,EAAsB,EACtBE,EAAmB,EACnBC,EAAqB,EACrB,GAAGE,CACL,CACF,CAAC,CACH,CChBA,SAASC,EAAcC,EAA+BC,EAA6B,CACjF,MAAO,CACL,CACE,KAAM,iBACN,KAAM,WACN,UAAAA,EACA,MAAO,kBACP,MAAO,CACL,YACE,iIACJ,EACA,OAAAD,CACF,EACA,CACE,KAAM,WACN,KAAM,QACN,UAAAC,EACA,MAAO,WACP,MAAO,CACL,YAAa,gEACb,cAAe,EACjB,EACA,OAAQ,CACN,CACE,KAAM,QACN,KAAM,OACN,UAAAA,EACA,MAAO,eACT,EACA,CACE,KAAM,UACN,KAAM,WACN,UAAAA,EACA,MAAO,UACP,SAAU,GACV,OAAAD,CACF,CACF,CACF,CACF,CACF,CAEA,SAASE,EAAiBC,EAA2B,CACnD,GAAI,CAAC,MAAM,QAAQA,CAAK,EACtB,MAAO,CAAC,EAEV,IAAMC,EAAiB,CAAC,EACxB,QAAWC,KAAQF,EACjBC,EAAI,KAAKC,CAAI,EAEf,OAAOD,CACT,CAEA,SAASE,EAA0DC,EAASC,EAAa,CACvF,GAAI,CAACA,EACH,OAAOD,EAET,GAAI,CAACA,EACH,OAAOC,EAET,IAAMC,EAAIF,EACJG,EAAIF,EACJJ,EAA+B,CAAE,GAAGK,CAAE,EAC5C,QAAWE,KAAO,OAAO,KAAKD,CAAC,EAAG,CAChC,IAAME,EAAKH,EAAEE,CAAG,EACVE,EAAKH,EAAEC,CAAG,EACZ,MAAM,QAAQC,CAAE,GAAK,MAAM,QAAQC,CAAE,EACvCT,EAAIO,CAAG,EAAI,CAAC,GAAGT,EAAiBU,CAAE,EAAG,GAAGV,EAAiBW,CAAE,CAAC,EACnDA,IAAO,SAChBT,EAAIO,CAAG,EAAIE,EAEf,CACA,OAAOT,CACT,CAEA,SAASU,EACPP,EACAQ,EACc,CACd,GAAI,CAACA,EACH,OAAOR,EAGT,GAAM,CACJ,MAAOS,EACP,OAAQC,EACR,MAAOC,EACP,OAAQC,EACR,GAAGC,CACL,EAAIL,EAEEM,EAAuB,CAC3B,GAAGd,EACH,GAAGa,CACL,EAEA,OAAIH,IACFI,EAAO,OAAS,CACd,GAAId,EAAK,OACT,GAAIU,CACN,GAGEC,IACFG,EAAO,MAAQ,CACb,GAAId,EAAK,MACT,GAAIW,CACN,IAGEF,GAAiBT,EAAK,SACxBc,EAAO,MAAQf,EACbC,EAAK,MACLS,CACF,GAGKK,CACT,CAEO,SAASC,EAAiBC,EAA8D,CAC7F,IAAMvB,EAASwB,EAAwB,EACjC,CAAE,KAAAC,EAAM,MAAAC,EAAO,UAAAzB,EAAW,UAAA0B,CAAU,EAAIJ,EAAW,OAEnDhB,EAAO,CACX,KAAAkB,EACA,MAAAC,EACA,OAAQ,CACN,CACE,KAAM,OACN,KAAM,CACJ,CACE,KAAM,UACN,MAAO,WACP,OAAQ3B,EAAcC,EAAQC,CAAS,CACzC,EACA,CACE,KAAM,cACN,MAAO,gBACP,OAAQF,EAAcC,EAAQC,CAAS,CACzC,CACF,CACF,CACF,CACF,EAEA,OAAOa,EAAoBP,EAAMoB,CAAS,CAC5C,CCpJA,SAASC,EAAuBC,EAAoC,CAAC,EAAgC,CACnG,MAAO,CACL,KAAMA,EAAQ,QAAQ,MAAQ,OAC9B,MAAOA,EAAQ,QAAQ,OAAS,OAChC,UAAWA,EAAQ,QAAQ,WAAa,GACxC,UAAWA,EAAQ,QAAQ,SAC7B,CACF,CAEO,SAASC,EACdD,EAAoC,CAAC,EACD,CACpC,MAAO,CACL,QAASA,EAAQ,SAAW,GAC5B,OAAQ,CACN,QAASA,EAAQ,QAAQ,SAAW,YACpC,gBAAiBA,EAAQ,QAAQ,iBAAmB,IACtD,EACA,OAAQD,EAAuBC,CAAO,CACxC,CACF,CCrBO,IAAME,EAAqBC,GAAsD,CACtF,IAAMC,EAAaC,EAAiBF,CAAO,EAE3C,OAAKC,EAAW,QAIRE,IACDA,EAAO,SAAW,CAAC,GAAG,KAAMC,GAAYA,EAAQ,OAASH,EAAW,OAAO,IAAI,EAC3EE,EAGF,CACL,GAAGA,EACH,QAAS,CAAC,GAAIA,EAAO,SAAW,CAAC,EAAIE,EAAiBJ,CAAU,CAAC,CACnE,EAXQE,GAAWA,CAavB","names":["lexicalToMarkdown","data","options","node","nodeToMarkdown","lexicalToMarkdownAsync","children","fields","formatText","headingToMarkdown","paragraphToMarkdown","linkToMarkdown","listToMarkdown","childrenToMarkdown","quoteToMarkdown","child","text","format","markdown","isBold","isItalic","level","content","href","getLinkHref","fallbackUrl","isNumbered","index","line","formatLlmsTxtLink","link","line","buildLlmsTxtFromStructured","content","lines","appendLines","section","trimBlankEdges","buildLlmsTxt","options","loadLlmsGlobalTab","buildLlmsFullTxt","tabKey","slug","tab","assembleLlmsMarkdownFromTab","lexicalOpts","parts","lexicalToMarkdownAsync","body","title","value","values","item","trimmed","BlockquoteFeature","HeadingFeature","HorizontalRuleFeature","lexicalEditor","OrderedListFeature","UnorderedListFeature","createLlmsLexicalEditor","defaultFeatures","llmsTabFields","editor","localized","unknownArrayFrom","value","out","item","mergeHooks","base","extra","a","b","key","av","bv","mergeGlobalOverride","override","overrideHooks","overrideAccess","overrideAdmin","_fields","rest","merged","createLlmsGlobal","normalized","createLlmsLexicalEditor","slug","label","overrides","normalizeGlobalOptions","options","normalizeOptions","payloadPluginLlms","options","normalized","normalizeOptions","config","global_","createLlmsGlobal"]}