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.
- package/README.md +134 -61
- package/dist/global.d.ts +4 -0
- package/dist/global.d.ts.map +1 -0
- package/dist/index.cjs +13 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -7
- package/dist/index.js.map +1 -1
- package/dist/lexical.d.ts +28 -4
- package/dist/lexical.d.ts.map +1 -1
- package/dist/llms-lexical.d.ts +4 -0
- package/dist/llms-lexical.d.ts.map +1 -0
- package/dist/llms-txt.d.ts +48 -7
- package/dist/llms-txt.d.ts.map +1 -1
- package/dist/next/headers.d.ts +0 -1
- package/dist/next/headers.d.ts.map +1 -1
- package/dist/next/index.cjs +1 -2
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.ts +3 -5
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +1 -1
- package/dist/next/index.js.map +1 -1
- package/dist/next/llms-txt-response.d.ts +7 -0
- package/dist/next/llms-txt-response.d.ts.map +1 -0
- package/dist/next/markdown-response.d.ts +4 -0
- package/dist/next/markdown-response.d.ts.map +1 -0
- package/dist/next/rewrites.d.ts +32 -7
- package/dist/next/rewrites.d.ts.map +1 -1
- package/dist/next/types.d.ts +2 -0
- package/dist/next/types.d.ts.map +1 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/types.d.ts +42 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -5
- package/dist/chunk-B5YH4Y5S.js +0 -3
- package/dist/chunk-B5YH4Y5S.js.map +0 -1
- package/dist/next/llms-route.d.ts +0 -12
- package/dist/next/llms-route.d.ts.map +0 -1
- package/dist/next/markdown-route.d.ts +0 -34
- 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
|
-
|
|
3
|
+
Helpers for `llms.txt` / `llms-full.txt` content stored in a Payload **global**, Lexical → Markdown
|
|
4
|
+
conversion, and Next.js utilities for markdown responses and Accept-based rewrites.
|
|
4
5
|
|
|
5
|
-
##
|
|
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
|
-
|
|
46
|
+
`normalizeOptions(options)` returns defaults including `global`:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { normalizeOptions } from "payload-plugin-llms"
|
|
24
50
|
|
|
25
|
-
|
|
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 {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
|
|
125
|
+
### Lexical → Markdown
|
|
54
126
|
|
|
55
127
|
```ts
|
|
56
|
-
import {
|
|
57
|
-
import { createMarkdownRoute } from "payload-plugin-llms/next"
|
|
128
|
+
import { lexicalToMarkdown, lexicalToMarkdownAsync } from "payload-plugin-llms"
|
|
58
129
|
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
143
|
+
Types include `LlmsTxtContent`, `LlmsTxtSection`, `LlmsTxtLink`, `BuildLlmsTxtFromGlobalOptions`,
|
|
144
|
+
`LexicalToMarkdownOptions`, `LexicalToMarkdownAsyncOptions`, `SerializedLexicalNode`.
|
|
71
145
|
|
|
72
|
-
##
|
|
146
|
+
## Next.js (`payload-plugin-llms/next`)
|
|
73
147
|
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
156
|
+
### Rewrites for clients that prefer Markdown
|
|
88
157
|
|
|
89
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
##
|
|
178
|
+
## License
|
|
106
179
|
|
|
107
|
-
|
|
180
|
+
Apache-2.0 (see repository root).
|
package/dist/global.d.ts
ADDED
|
@@ -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
|
|
2
|
-
|
|
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
|
|
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
|
|
6
|
+
`}function C(e,n){return`${d(e,n).trim()}
|
|
8
7
|
|
|
9
|
-
`}function
|
|
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
|
|
11
|
+
`}function v(e,n){return`${d(e,n).trim().split(`
|
|
13
12
|
`).map(i=>`> ${i}`).join(`
|
|
14
13
|
`)}
|
|
15
14
|
|
|
16
|
-
`}function
|
|
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
|
package/dist/index.cjs.map
CHANGED
|
@@ -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":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,kBAAAE,EAAA,YAAAC,EAAA,sBAAAC,EAAA,sBAAAC,EAAA,qBAAAC,EAAA,sBAAAH,IAAA,eAAAI,EAAAP,GCoBO,SAASQ,EAAkBC,EAA2B,CAC3D,IAAMC,EAAO,MAAMD,EAAK,KAAK,KAAKA,EAAK,GAAG,IAC1C,OAAOA,EAAK,YAAc,GAAGC,CAAI,KAAKD,EAAK,WAAW,GAAKC,CAC7D,CAEO,SAASC,EAAaC,EAAiC,CAC5D,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,CAEA,SAASC,EACPD,EACAI,EACAC,EAAuC,CAAC,EACxC,CACA,IAAMC,EAAS,MAAM,QAAQF,CAAK,EAAIA,EAAQA,EAAQ,CAACA,CAAK,EAAI,CAAC,EACjE,GAAIE,EAAO,SAAW,EAEtB,IAAID,EAAQ,eAAiB,GAAM,CACjC,QAAWE,KAAQD,EACjBN,EAAM,KAAKO,EAAM,EAAE,EAErB,MACF,CAEA,QAAWA,KAAQD,EACjBN,EAAM,KAAKO,CAAI,EAEnB,CAEA,SAASJ,EAAeH,EAAiB,CACvC,IAAMQ,EAAU,CAAC,GAAGR,CAAK,EACzB,KAAOQ,EAAQ,CAAC,IAAM,IAAIA,EAAQ,MAAM,EACxC,KAAOA,EAAQ,GAAG,EAAE,IAAM,IAAIA,EAAQ,IAAI,EAC1C,OAAOA,CACT,CCnCO,SAASC,EACdC,EACAC,EAAoC,CAAC,EAC7B,CAER,OADiBD,EAAK,MAAM,UAAY,CAAC,GACzB,IAAKE,GAASC,EAAeD,EAAMD,CAAO,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,CAC7E,CAEA,SAASE,EAAeD,EAA6BD,EAA2C,CAC9F,OAAQC,EAAK,KAAM,CACjB,IAAK,OACH,OAAOE,EAAYF,EAA4B,MAAQ,GAAKA,EAA4B,MAAM,EAChG,IAAK,YACH,MAAO;AAAA,EACT,IAAK,MACH,MAAO,IACT,IAAK,UACH,OAAOG,EAAkBH,EAA+BD,CAAO,EACjE,IAAK,YACH,OAAOK,EAAoBJ,EAA+BD,CAAO,EACnE,IAAK,OACL,IAAK,WACH,OAAOM,EAAeL,EAA4BD,CAAO,EAC3D,IAAK,OACH,OAAOO,EAAeN,EAAuDD,CAAO,EACtF,IAAK,WACH,OAAOQ,EAAmBP,EAA+BD,CAAO,EAAE,KAAK,EACzE,IAAK,QACL,IAAK,aACH,OAAOS,EAAgBR,EAA+BD,CAAO,EAC/D,IAAK,iBACH,MAAO;AAAA;AAAA,EACT,IAAK,OACH,OAAOQ,EAAmBP,EAA+BD,CAAO,EAAE,KAAK,EACzE,QACE,OAAOQ,EAAmBP,EAA+BD,CAAO,CACpE,CACF,CAEA,SAASQ,EACPP,EACAD,EACQ,CACR,OAAQC,EAAK,UAAY,CAAC,GAAG,IAAKS,GAAUR,EAAeQ,EAAOV,CAAO,CAAC,EAAE,KAAK,EAAE,CACrF,CAEA,SAASG,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,EACPH,EACAD,EACQ,CAER,IAAMgB,GADQ,OAAOf,EAAK,KAAQ,SAAW,aAAa,KAAKA,EAAK,GAAG,EAAI,QACrD,CAAC,GAAK,IACtBgB,EAAUT,EAAmBP,EAAMD,CAAO,EAAE,KAAK,EAEvD,MAAO,GAAG,IAAI,OAAO,OAAOgB,CAAK,CAAC,CAAC,IAAIC,CAAO;AAAA;AAAA,CAChD,CAEA,SAASZ,EACPJ,EACAD,EACQ,CACR,MAAO,GAAGQ,EAAmBP,EAAMD,CAAO,EAAE,KAAK,CAAC;AAAA;AAAA,CACpD,CAEA,SAASM,EAAeL,EAA0BD,EAA2C,CAC3F,IAAMW,EAAOH,EAAmBP,EAAMD,CAAO,EAAE,KAAK,EAC9CkB,EAAOC,EAAYlB,EAAMD,CAAO,EAEtC,MAAO,IAAIW,CAAI,KAAKO,CAAI,GAC1B,CAEA,SAASC,EAAYlB,EAA0BD,EAA2C,CACxF,IAAMoB,EAASnB,EAAK,OACdoB,EAAcD,GAAQ,KAAOnB,EAAK,IAExC,OAAImB,GAAQ,WAAa,WACNpB,EAAQ,sBAAsB,CAC7C,WAAYoB,EAAO,KAAK,WACxB,MAAOA,EAAO,KAAK,MACnB,IAAKC,CACP,CAAC,GAEkBA,GAAe,IAG7BA,GAAe,GACxB,CAEA,SAASd,EACPN,EACAD,EACQ,CACR,IAAMsB,EAAarB,EAAK,WAAa,UAAYA,EAAK,WAAa,UAMnE,MAAO,IALQA,EAAK,UAAY,CAAC,GAAG,IAAI,CAACS,EAAOa,IAEvC,GADQD,EAAa,GAAGC,EAAQ,CAAC,KAAO,IAC/B,GAAGrB,EAAeQ,EAAOV,CAAO,EAAE,KAAK,CAAC,EACzD,EAEe,KAAK;AAAA,CAAI,CAAC;AAAA;AAAA,CAC5B,CAEA,SAASS,EAAgBR,EAA6BD,EAA2C,CAO/F,MAAO,GANSQ,EAAmBP,EAAMD,CAAO,EAC7C,KAAK,EACL,MAAM;AAAA,CAAI,EACV,IAAKwB,GAAS,KAAKA,CAAI,EAAE,EACzB,KAAK;AAAA,CAAI,CAEK;AAAA;AAAA,CACnB,CChLO,SAASC,EACdC,EAAoC,CAAC,EACD,CACpC,MAAO,CACL,QAASA,EAAQ,SAAW,GAC5B,OAAQ,CACN,QAASA,EAAQ,QAAQ,SAAW,YACpC,gBAAiBA,EAAQ,QAAQ,iBAAmB,IACtD,CACF,CACF,CCRO,IAAMC,EAAqBC,IAChCC,EAAiBD,CAAO,EAEhBE,GAAWA","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 {
|
|
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
|
|
6
|
-
export type {
|
|
7
|
-
export type {
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
-
|
|
2
|
-
`;case"tab":return" ";case"heading":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
|
|
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
|
|
6
|
+
`}function S(e,n){return`${s(e,n).trim()}
|
|
7
7
|
|
|
8
|
-
`}function
|
|
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
|
|
11
|
+
`}function N(e,n){return`${s(e,n).trim().split(`
|
|
12
12
|
`).map(i=>`> ${i}`).join(`
|
|
13
13
|
`)}
|
|
14
14
|
|
|
15
|
-
`}function
|
|
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"]}
|