@seoengine.ai/next-llm-ready 1.0.0

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.
@@ -0,0 +1,398 @@
1
+ 'use strict';
2
+
3
+ // src/utils/html-to-markdown.ts
4
+ var defaultOptions = {
5
+ preserveLineBreaks: true,
6
+ convertImages: true,
7
+ convertLinks: true,
8
+ stripScripts: true,
9
+ customHandlers: {}
10
+ };
11
+ function htmlToMarkdown(html, options = {}) {
12
+ const opts = { ...defaultOptions, ...options };
13
+ if (typeof window === "undefined") {
14
+ return serverSideConvert(html, opts);
15
+ }
16
+ const doc = new DOMParser().parseFromString(html, "text/html");
17
+ return convertNode(doc.body, opts);
18
+ }
19
+ function serverSideConvert(html, opts) {
20
+ let markdown = html;
21
+ if (opts.stripScripts) {
22
+ markdown = markdown.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "");
23
+ markdown = markdown.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, "");
24
+ }
25
+ markdown = markdown.replace(/<h1[^>]*>(.*?)<\/h1>/gi, "\n# $1\n");
26
+ markdown = markdown.replace(/<h2[^>]*>(.*?)<\/h2>/gi, "\n## $1\n");
27
+ markdown = markdown.replace(/<h3[^>]*>(.*?)<\/h3>/gi, "\n### $1\n");
28
+ markdown = markdown.replace(/<h4[^>]*>(.*?)<\/h4>/gi, "\n#### $1\n");
29
+ markdown = markdown.replace(/<h5[^>]*>(.*?)<\/h5>/gi, "\n##### $1\n");
30
+ markdown = markdown.replace(/<h6[^>]*>(.*?)<\/h6>/gi, "\n###### $1\n");
31
+ markdown = markdown.replace(/<(strong|b)[^>]*>(.*?)<\/\1>/gi, "**$2**");
32
+ markdown = markdown.replace(/<(em|i)[^>]*>(.*?)<\/\1>/gi, "*$2*");
33
+ if (opts.convertLinks) {
34
+ markdown = markdown.replace(/<a[^>]*href=["']([^"']*)["'][^>]*>(.*?)<\/a>/gi, "[$2]($1)");
35
+ }
36
+ if (opts.convertImages) {
37
+ markdown = markdown.replace(
38
+ /<img[^>]*src=["']([^"']*)["'][^>]*alt=["']([^"']*)["'][^>]*\/?>/gi,
39
+ "![$2]($1)"
40
+ );
41
+ markdown = markdown.replace(
42
+ /<img[^>]*alt=["']([^"']*)["'][^>]*src=["']([^"']*)["'][^>]*\/?>/gi,
43
+ "![$1]($2)"
44
+ );
45
+ markdown = markdown.replace(/<img[^>]*src=["']([^"']*)["'][^>]*\/?>/gi, "![]($1)");
46
+ }
47
+ markdown = markdown.replace(/<ul[^>]*>/gi, "\n");
48
+ markdown = markdown.replace(/<\/ul>/gi, "\n");
49
+ markdown = markdown.replace(/<ol[^>]*>/gi, "\n");
50
+ markdown = markdown.replace(/<\/ol>/gi, "\n");
51
+ markdown = markdown.replace(/<li[^>]*>(.*?)<\/li>/gi, "- $1\n");
52
+ markdown = markdown.replace(/<blockquote[^>]*>(.*?)<\/blockquote>/gis, (_, content) => {
53
+ return "\n> " + content.trim().replace(/\n/g, "\n> ") + "\n";
54
+ });
55
+ markdown = markdown.replace(/<pre[^>]*><code[^>]*>(.*?)<\/code><\/pre>/gis, "\n```\n$1\n```\n");
56
+ markdown = markdown.replace(/<code[^>]*>(.*?)<\/code>/gi, "`$1`");
57
+ markdown = markdown.replace(/<p[^>]*>(.*?)<\/p>/gis, "\n$1\n");
58
+ markdown = markdown.replace(/<br\s*\/?>/gi, "\n");
59
+ markdown = markdown.replace(/<hr[^>]*\/?>/gi, "\n---\n");
60
+ markdown = markdown.replace(/<[^>]+>/g, "");
61
+ markdown = decodeHTMLEntities(markdown);
62
+ markdown = markdown.replace(/\n{3,}/g, "\n\n");
63
+ markdown = markdown.trim();
64
+ return markdown;
65
+ }
66
+ function convertNode(node, opts) {
67
+ if (node.nodeType === Node.TEXT_NODE) {
68
+ return node.textContent || "";
69
+ }
70
+ if (node.nodeType !== Node.ELEMENT_NODE) {
71
+ return "";
72
+ }
73
+ const element = node;
74
+ const tagName = element.tagName.toLowerCase();
75
+ if (opts.customHandlers?.[tagName]) {
76
+ return opts.customHandlers[tagName](element);
77
+ }
78
+ if (opts.stripScripts && (tagName === "script" || tagName === "style")) {
79
+ return "";
80
+ }
81
+ const childContent = Array.from(element.childNodes).map((child) => convertNode(child, opts)).join("");
82
+ switch (tagName) {
83
+ case "h1":
84
+ return `
85
+ # ${childContent.trim()}
86
+ `;
87
+ case "h2":
88
+ return `
89
+ ## ${childContent.trim()}
90
+ `;
91
+ case "h3":
92
+ return `
93
+ ### ${childContent.trim()}
94
+ `;
95
+ case "h4":
96
+ return `
97
+ #### ${childContent.trim()}
98
+ `;
99
+ case "h5":
100
+ return `
101
+ ##### ${childContent.trim()}
102
+ `;
103
+ case "h6":
104
+ return `
105
+ ###### ${childContent.trim()}
106
+ `;
107
+ case "p":
108
+ return `
109
+ ${childContent.trim()}
110
+ `;
111
+ case "br":
112
+ return opts.preserveLineBreaks ? "\n" : " ";
113
+ case "strong":
114
+ case "b":
115
+ return `**${childContent}**`;
116
+ case "em":
117
+ case "i":
118
+ return `*${childContent}*`;
119
+ case "u":
120
+ return `_${childContent}_`;
121
+ case "s":
122
+ case "strike":
123
+ case "del":
124
+ return `~~${childContent}~~`;
125
+ case "a":
126
+ if (opts.convertLinks) {
127
+ const href = element.getAttribute("href") || "";
128
+ return `[${childContent}](${href})`;
129
+ }
130
+ return childContent;
131
+ case "img":
132
+ if (opts.convertImages) {
133
+ const src = element.getAttribute("src") || "";
134
+ const alt = element.getAttribute("alt") || "";
135
+ return `![${alt}](${src})`;
136
+ }
137
+ return "";
138
+ case "ul":
139
+ return `
140
+ ${childContent}
141
+ `;
142
+ case "ol":
143
+ return `
144
+ ${childContent}
145
+ `;
146
+ case "li":
147
+ return `- ${childContent.trim()}
148
+ `;
149
+ case "blockquote":
150
+ return `
151
+ > ${childContent.trim().replace(/\n/g, "\n> ")}
152
+ `;
153
+ case "pre":
154
+ const codeElement = element.querySelector("code");
155
+ const lang = codeElement?.className.match(/language-(\w+)/)?.[1] || "";
156
+ const code = codeElement?.textContent || childContent;
157
+ return `
158
+ \`\`\`${lang}
159
+ ${code.trim()}
160
+ \`\`\`
161
+ `;
162
+ case "code":
163
+ if (element.parentElement?.tagName.toLowerCase() === "pre") {
164
+ return childContent;
165
+ }
166
+ return `\`${childContent}\``;
167
+ case "hr":
168
+ return "\n---\n";
169
+ case "table":
170
+ return convertTable(element);
171
+ case "div":
172
+ case "section":
173
+ case "article":
174
+ case "main":
175
+ case "aside":
176
+ case "header":
177
+ case "footer":
178
+ case "nav":
179
+ return childContent;
180
+ default:
181
+ return childContent;
182
+ }
183
+ }
184
+ function convertTable(table) {
185
+ const rows = table.querySelectorAll("tr");
186
+ if (rows.length === 0) return "";
187
+ let markdown = "\n";
188
+ let headerProcessed = false;
189
+ rows.forEach((row, index) => {
190
+ const cells = row.querySelectorAll("th, td");
191
+ const rowContent = Array.from(cells).map((cell) => cell.textContent?.trim() || "").join(" | ");
192
+ markdown += `| ${rowContent} |
193
+ `;
194
+ if (!headerProcessed && (row.querySelector("th") || index === 0)) {
195
+ const separator = Array.from(cells).map(() => "---").join(" | ");
196
+ markdown += `| ${separator} |
197
+ `;
198
+ headerProcessed = true;
199
+ }
200
+ });
201
+ return markdown + "\n";
202
+ }
203
+ function decodeHTMLEntities(text) {
204
+ const entities = {
205
+ "&amp;": "&",
206
+ "&lt;": "<",
207
+ "&gt;": ">",
208
+ "&quot;": '"',
209
+ "&#39;": "'",
210
+ "&apos;": "'",
211
+ "&nbsp;": " ",
212
+ "&mdash;": "\u2014",
213
+ "&ndash;": "\u2013",
214
+ "&hellip;": "\u2026",
215
+ "&copy;": "\xA9",
216
+ "&reg;": "\xAE",
217
+ "&trade;": "\u2122"
218
+ };
219
+ let result = text;
220
+ for (const [entity, char] of Object.entries(entities)) {
221
+ result = result.replace(new RegExp(entity, "g"), char);
222
+ }
223
+ result = result.replace(/&#(\d+);/g, (_, num) => String.fromCharCode(parseInt(num, 10)));
224
+ result = result.replace(
225
+ /&#x([0-9a-f]+);/gi,
226
+ (_, hex) => String.fromCharCode(parseInt(hex, 16))
227
+ );
228
+ return result;
229
+ }
230
+ function countWords(text) {
231
+ return text.replace(/[^\w\s]/g, "").split(/\s+/).filter((word) => word.length > 0).length;
232
+ }
233
+ function calculateReadingTime(text, wordsPerMinute = 200) {
234
+ const words = countWords(text);
235
+ return Math.ceil(words / wordsPerMinute);
236
+ }
237
+
238
+ // src/server/generate-markdown.ts
239
+ function generateMarkdown(content) {
240
+ const parts = [];
241
+ if (content.promptPrefix?.trim()) {
242
+ parts.push(content.promptPrefix.trim());
243
+ parts.push("");
244
+ }
245
+ parts.push(`# ${content.title}`);
246
+ parts.push("");
247
+ if (content.excerpt) {
248
+ parts.push(`> ${content.excerpt}`);
249
+ parts.push("");
250
+ }
251
+ parts.push("---");
252
+ parts.push(`- **Source**: ${content.url}`);
253
+ if (content.date) {
254
+ parts.push(`- **Date**: ${content.date}`);
255
+ }
256
+ if (content.modifiedDate) {
257
+ parts.push(`- **Modified**: ${content.modifiedDate}`);
258
+ }
259
+ if (content.author) {
260
+ parts.push(`- **Author**: ${content.author}`);
261
+ }
262
+ if (content.categories?.length) {
263
+ parts.push(`- **Categories**: ${content.categories.join(", ")}`);
264
+ }
265
+ if (content.tags?.length) {
266
+ parts.push(`- **Tags**: ${content.tags.join(", ")}`);
267
+ }
268
+ if (content.readingTime) {
269
+ parts.push(`- **Reading Time**: ${content.readingTime} min`);
270
+ }
271
+ parts.push("---");
272
+ parts.push("");
273
+ if (content.content) {
274
+ const contentMarkdown = isHTML(content.content) ? htmlToMarkdown(content.content) : content.content;
275
+ parts.push(contentMarkdown);
276
+ }
277
+ const markdown = parts.join("\n").trim();
278
+ const wordCount = countWords(markdown);
279
+ const readingTime = calculateReadingTime(markdown);
280
+ const headings = extractMarkdownHeadings(markdown);
281
+ return {
282
+ markdown,
283
+ wordCount,
284
+ readingTime,
285
+ headings
286
+ };
287
+ }
288
+ function generateMarkdownString(content) {
289
+ return generateMarkdown(content).markdown;
290
+ }
291
+ function isHTML(str) {
292
+ return /<[a-z][\s\S]*>/i.test(str);
293
+ }
294
+ function extractMarkdownHeadings(markdown) {
295
+ const headings = [];
296
+ const lines = markdown.split("\n");
297
+ let index = 0;
298
+ for (const line of lines) {
299
+ const match = line.match(/^(#{1,6})\s+(.+)$/);
300
+ if (match) {
301
+ const level = match[1].length;
302
+ const text = match[2].trim();
303
+ const id = generateSlug(text, index);
304
+ headings.push({ id, text, level });
305
+ index++;
306
+ }
307
+ }
308
+ return headings;
309
+ }
310
+ function generateSlug(text, index) {
311
+ const slug = text.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
312
+ return slug || `heading-${index}`;
313
+ }
314
+ function contentToPlainText(content) {
315
+ const markdown = generateMarkdownString(content);
316
+ return markdown.replace(/^#+\s+/gm, "").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "").replace(/^[-*+]\s+/gm, "").replace(/^>\s+/gm, "").replace(/^---$/gm, "").replace(/\n{2,}/g, "\n\n").trim();
317
+ }
318
+
319
+ // src/server/generate-llms-txt.ts
320
+ function generateLLMsTxt(config) {
321
+ const parts = [];
322
+ parts.push(`# ${config.siteName}`);
323
+ parts.push("");
324
+ if (config.siteDescription) {
325
+ parts.push(`> ${config.siteDescription}`);
326
+ parts.push("");
327
+ }
328
+ if (config.headerText) {
329
+ parts.push(config.headerText);
330
+ } else {
331
+ parts.push("This file provides LLM-friendly access to the content on this website.");
332
+ }
333
+ parts.push("");
334
+ parts.push("---");
335
+ parts.push(`- **Site URL**: ${config.siteUrl}`);
336
+ parts.push("- **Format**: Append `?llm=1` to any page URL to get markdown");
337
+ parts.push("---");
338
+ parts.push("");
339
+ if (config.content.length > 0) {
340
+ parts.push("## Available Content");
341
+ parts.push("");
342
+ for (const item of config.content) {
343
+ const llmUrl = appendQueryParam(item.url, "llm", "1");
344
+ parts.push(`### [${item.title}](${llmUrl})`);
345
+ if (item.type) {
346
+ parts.push(`- **Type**: ${item.type}`);
347
+ }
348
+ if (item.date) {
349
+ parts.push(`- **Date**: ${item.date}`);
350
+ }
351
+ if (item.description) {
352
+ parts.push(`- **Description**: ${item.description}`);
353
+ }
354
+ parts.push(`- **Markdown URL**: ${llmUrl}`);
355
+ parts.push("");
356
+ }
357
+ }
358
+ parts.push("---");
359
+ parts.push("");
360
+ if (config.footerText) {
361
+ parts.push(config.footerText);
362
+ } else {
363
+ parts.push("*Generated by [next-llm-ready](https://seoengine.ai) - Make your content AI-ready*");
364
+ }
365
+ return parts.join("\n");
366
+ }
367
+ function appendQueryParam(url, key, value) {
368
+ const separator = url.includes("?") ? "&" : "?";
369
+ return `${url}${separator}${key}=${value}`;
370
+ }
371
+ function sortByDate(items) {
372
+ return [...items].sort((a, b) => {
373
+ if (!a.date) return 1;
374
+ if (!b.date) return -1;
375
+ return new Date(b.date).getTime() - new Date(a.date).getTime();
376
+ });
377
+ }
378
+ function filterByType(items, types) {
379
+ const typeSet = new Set(types.map((t) => t.toLowerCase()));
380
+ return items.filter((item) => !item.type || typeSet.has(item.type.toLowerCase()));
381
+ }
382
+ function createLLMsTxtItem(title, url, options) {
383
+ return {
384
+ title,
385
+ url,
386
+ ...options
387
+ };
388
+ }
389
+
390
+ exports.contentToPlainText = contentToPlainText;
391
+ exports.createLLMsTxtItem = createLLMsTxtItem;
392
+ exports.filterByType = filterByType;
393
+ exports.generateLLMsTxt = generateLLMsTxt;
394
+ exports.generateMarkdown = generateMarkdown;
395
+ exports.generateMarkdownString = generateMarkdownString;
396
+ exports.sortByDate = sortByDate;
397
+ //# sourceMappingURL=index.cjs.map
398
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/html-to-markdown.ts","../../src/server/generate-markdown.ts","../../src/server/generate-llms-txt.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * HTML to Markdown Converter\n * Converts HTML content to clean markdown format\n */\n\nimport type { HTMLToMarkdownOptions } from '../types';\n\nconst defaultOptions: HTMLToMarkdownOptions = {\n preserveLineBreaks: true,\n convertImages: true,\n convertLinks: true,\n stripScripts: true,\n customHandlers: {},\n};\n\n/**\n * Convert HTML string to Markdown\n */\nexport function htmlToMarkdown(\n html: string,\n options: HTMLToMarkdownOptions = {}\n): string {\n const opts = { ...defaultOptions, ...options };\n\n // Create a temporary DOM element to parse HTML\n if (typeof window === 'undefined') {\n // Server-side: use basic regex conversion\n return serverSideConvert(html, opts);\n }\n\n // Client-side: use DOM parsing\n const doc = new DOMParser().parseFromString(html, 'text/html');\n return convertNode(doc.body, opts);\n}\n\n/**\n * Server-side HTML to Markdown conversion (regex-based)\n */\nfunction serverSideConvert(html: string, opts: HTMLToMarkdownOptions): string {\n let markdown = html;\n\n // Strip scripts and styles\n if (opts.stripScripts) {\n markdown = markdown.replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '');\n markdown = markdown.replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, '');\n }\n\n // Headings\n markdown = markdown.replace(/<h1[^>]*>(.*?)<\\/h1>/gi, '\\n# $1\\n');\n markdown = markdown.replace(/<h2[^>]*>(.*?)<\\/h2>/gi, '\\n## $1\\n');\n markdown = markdown.replace(/<h3[^>]*>(.*?)<\\/h3>/gi, '\\n### $1\\n');\n markdown = markdown.replace(/<h4[^>]*>(.*?)<\\/h4>/gi, '\\n#### $1\\n');\n markdown = markdown.replace(/<h5[^>]*>(.*?)<\\/h5>/gi, '\\n##### $1\\n');\n markdown = markdown.replace(/<h6[^>]*>(.*?)<\\/h6>/gi, '\\n###### $1\\n');\n\n // Bold and italic\n markdown = markdown.replace(/<(strong|b)[^>]*>(.*?)<\\/\\1>/gi, '**$2**');\n markdown = markdown.replace(/<(em|i)[^>]*>(.*?)<\\/\\1>/gi, '*$2*');\n\n // Links\n if (opts.convertLinks) {\n markdown = markdown.replace(/<a[^>]*href=[\"']([^\"']*)[\"'][^>]*>(.*?)<\\/a>/gi, '[$2]($1)');\n }\n\n // Images\n if (opts.convertImages) {\n markdown = markdown.replace(\n /<img[^>]*src=[\"']([^\"']*)[\"'][^>]*alt=[\"']([^\"']*)[\"'][^>]*\\/?>/gi,\n '![$2]($1)'\n );\n markdown = markdown.replace(\n /<img[^>]*alt=[\"']([^\"']*)[\"'][^>]*src=[\"']([^\"']*)[\"'][^>]*\\/?>/gi,\n '![$1]($2)'\n );\n markdown = markdown.replace(/<img[^>]*src=[\"']([^\"']*)[\"'][^>]*\\/?>/gi, '![]($1)');\n }\n\n // Lists\n markdown = markdown.replace(/<ul[^>]*>/gi, '\\n');\n markdown = markdown.replace(/<\\/ul>/gi, '\\n');\n markdown = markdown.replace(/<ol[^>]*>/gi, '\\n');\n markdown = markdown.replace(/<\\/ol>/gi, '\\n');\n markdown = markdown.replace(/<li[^>]*>(.*?)<\\/li>/gi, '- $1\\n');\n\n // Blockquotes\n markdown = markdown.replace(/<blockquote[^>]*>(.*?)<\\/blockquote>/gis, (_, content) => {\n return '\\n> ' + content.trim().replace(/\\n/g, '\\n> ') + '\\n';\n });\n\n // Code blocks\n markdown = markdown.replace(/<pre[^>]*><code[^>]*>(.*?)<\\/code><\\/pre>/gis, '\\n```\\n$1\\n```\\n');\n markdown = markdown.replace(/<code[^>]*>(.*?)<\\/code>/gi, '`$1`');\n\n // Paragraphs and line breaks\n markdown = markdown.replace(/<p[^>]*>(.*?)<\\/p>/gis, '\\n$1\\n');\n markdown = markdown.replace(/<br\\s*\\/?>/gi, '\\n');\n\n // Horizontal rules\n markdown = markdown.replace(/<hr[^>]*\\/?>/gi, '\\n---\\n');\n\n // Strip remaining HTML tags\n markdown = markdown.replace(/<[^>]+>/g, '');\n\n // Decode HTML entities\n markdown = decodeHTMLEntities(markdown);\n\n // Clean up whitespace\n markdown = markdown.replace(/\\n{3,}/g, '\\n\\n');\n markdown = markdown.trim();\n\n return markdown;\n}\n\n/**\n * Client-side DOM-based conversion\n */\nfunction convertNode(node: Node, opts: HTMLToMarkdownOptions): string {\n if (node.nodeType === Node.TEXT_NODE) {\n return node.textContent || '';\n }\n\n if (node.nodeType !== Node.ELEMENT_NODE) {\n return '';\n }\n\n const element = node as Element;\n const tagName = element.tagName.toLowerCase();\n\n // Check for custom handler\n if (opts.customHandlers?.[tagName]) {\n return opts.customHandlers[tagName](element);\n }\n\n // Skip scripts and styles\n if (opts.stripScripts && (tagName === 'script' || tagName === 'style')) {\n return '';\n }\n\n const childContent = Array.from(element.childNodes)\n .map((child) => convertNode(child, opts))\n .join('');\n\n switch (tagName) {\n case 'h1':\n return `\\n# ${childContent.trim()}\\n`;\n case 'h2':\n return `\\n## ${childContent.trim()}\\n`;\n case 'h3':\n return `\\n### ${childContent.trim()}\\n`;\n case 'h4':\n return `\\n#### ${childContent.trim()}\\n`;\n case 'h5':\n return `\\n##### ${childContent.trim()}\\n`;\n case 'h6':\n return `\\n###### ${childContent.trim()}\\n`;\n case 'p':\n return `\\n${childContent.trim()}\\n`;\n case 'br':\n return opts.preserveLineBreaks ? '\\n' : ' ';\n case 'strong':\n case 'b':\n return `**${childContent}**`;\n case 'em':\n case 'i':\n return `*${childContent}*`;\n case 'u':\n return `_${childContent}_`;\n case 's':\n case 'strike':\n case 'del':\n return `~~${childContent}~~`;\n case 'a':\n if (opts.convertLinks) {\n const href = element.getAttribute('href') || '';\n return `[${childContent}](${href})`;\n }\n return childContent;\n case 'img':\n if (opts.convertImages) {\n const src = element.getAttribute('src') || '';\n const alt = element.getAttribute('alt') || '';\n return `![${alt}](${src})`;\n }\n return '';\n case 'ul':\n return `\\n${childContent}\\n`;\n case 'ol':\n return `\\n${childContent}\\n`;\n case 'li':\n return `- ${childContent.trim()}\\n`;\n case 'blockquote':\n return `\\n> ${childContent.trim().replace(/\\n/g, '\\n> ')}\\n`;\n case 'pre':\n const codeElement = element.querySelector('code');\n const lang = codeElement?.className.match(/language-(\\w+)/)?.[1] || '';\n const code = codeElement?.textContent || childContent;\n return `\\n\\`\\`\\`${lang}\\n${code.trim()}\\n\\`\\`\\`\\n`;\n case 'code':\n // Check if inside pre\n if (element.parentElement?.tagName.toLowerCase() === 'pre') {\n return childContent;\n }\n return `\\`${childContent}\\``;\n case 'hr':\n return '\\n---\\n';\n case 'table':\n return convertTable(element);\n case 'div':\n case 'section':\n case 'article':\n case 'main':\n case 'aside':\n case 'header':\n case 'footer':\n case 'nav':\n return childContent;\n default:\n return childContent;\n }\n}\n\n/**\n * Convert HTML table to Markdown table\n */\nfunction convertTable(table: Element): string {\n const rows = table.querySelectorAll('tr');\n if (rows.length === 0) return '';\n\n let markdown = '\\n';\n let headerProcessed = false;\n\n rows.forEach((row, index) => {\n const cells = row.querySelectorAll('th, td');\n const rowContent = Array.from(cells)\n .map((cell) => cell.textContent?.trim() || '')\n .join(' | ');\n\n markdown += `| ${rowContent} |\\n`;\n\n // Add separator after header row\n if (!headerProcessed && (row.querySelector('th') || index === 0)) {\n const separator = Array.from(cells)\n .map(() => '---')\n .join(' | ');\n markdown += `| ${separator} |\\n`;\n headerProcessed = true;\n }\n });\n\n return markdown + '\\n';\n}\n\n/**\n * Decode HTML entities\n */\nfunction decodeHTMLEntities(text: string): string {\n const entities: Record<string, string> = {\n '&amp;': '&',\n '&lt;': '<',\n '&gt;': '>',\n '&quot;': '\"',\n '&#39;': \"'\",\n '&apos;': \"'\",\n '&nbsp;': ' ',\n '&mdash;': '—',\n '&ndash;': '–',\n '&hellip;': '…',\n '&copy;': '©',\n '&reg;': '®',\n '&trade;': '™',\n };\n\n let result = text;\n for (const [entity, char] of Object.entries(entities)) {\n result = result.replace(new RegExp(entity, 'g'), char);\n }\n\n // Decode numeric entities\n result = result.replace(/&#(\\d+);/g, (_, num) => String.fromCharCode(parseInt(num, 10)));\n result = result.replace(/&#x([0-9a-f]+);/gi, (_, hex) =>\n String.fromCharCode(parseInt(hex, 16))\n );\n\n return result;\n}\n\n/**\n * Calculate word count from text\n */\nexport function countWords(text: string): number {\n return text\n .replace(/[^\\w\\s]/g, '')\n .split(/\\s+/)\n .filter((word) => word.length > 0).length;\n}\n\n/**\n * Calculate reading time in minutes\n */\nexport function calculateReadingTime(text: string, wordsPerMinute = 200): number {\n const words = countWords(text);\n return Math.ceil(words / wordsPerMinute);\n}\n\n/**\n * Extract headings from HTML for TOC\n */\nexport function extractHeadings(\n html: string,\n levels: string[] = ['h2', 'h3', 'h4']\n): Array<{ id: string; text: string; level: number }> {\n const headings: Array<{ id: string; text: string; level: number }> = [];\n const levelPattern = levels.join('|');\n const regex = new RegExp(\n `<(${levelPattern})[^>]*(?:id=[\"']([^\"']*)[\"'])?[^>]*>(.*?)<\\\\/\\\\1>`,\n 'gi'\n );\n\n let match;\n let index = 0;\n while ((match = regex.exec(html)) !== null) {\n const level = parseInt(match[1].charAt(1), 10);\n const id = match[2] || `heading-${index}`;\n const text = match[3].replace(/<[^>]+>/g, '').trim();\n\n headings.push({ id, text, level });\n index++;\n }\n\n return headings;\n}\n","/**\n * Server-side Markdown Generation\n * Generate LLM-ready markdown from content\n */\n\nimport type { LLMContent, MarkdownOutput, TOCHeading } from '../types';\nimport { htmlToMarkdown, countWords, calculateReadingTime } from '../utils/html-to-markdown';\n\n/**\n * Generate complete markdown output from LLM content\n */\nexport function generateMarkdown(content: LLMContent): MarkdownOutput {\n const parts: string[] = [];\n\n // Add custom prompt prefix if set\n if (content.promptPrefix?.trim()) {\n parts.push(content.promptPrefix.trim());\n parts.push('');\n }\n\n // Title\n parts.push(`# ${content.title}`);\n parts.push('');\n\n // Excerpt as blockquote\n if (content.excerpt) {\n parts.push(`> ${content.excerpt}`);\n parts.push('');\n }\n\n // Metadata section\n parts.push('---');\n parts.push(`- **Source**: ${content.url}`);\n\n if (content.date) {\n parts.push(`- **Date**: ${content.date}`);\n }\n\n if (content.modifiedDate) {\n parts.push(`- **Modified**: ${content.modifiedDate}`);\n }\n\n if (content.author) {\n parts.push(`- **Author**: ${content.author}`);\n }\n\n if (content.categories?.length) {\n parts.push(`- **Categories**: ${content.categories.join(', ')}`);\n }\n\n if (content.tags?.length) {\n parts.push(`- **Tags**: ${content.tags.join(', ')}`);\n }\n\n if (content.readingTime) {\n parts.push(`- **Reading Time**: ${content.readingTime} min`);\n }\n\n parts.push('---');\n parts.push('');\n\n // Main content (convert HTML to markdown if needed)\n if (content.content) {\n const contentMarkdown = isHTML(content.content)\n ? htmlToMarkdown(content.content)\n : content.content;\n parts.push(contentMarkdown);\n }\n\n const markdown = parts.join('\\n').trim();\n const wordCount = countWords(markdown);\n const readingTime = calculateReadingTime(markdown);\n const headings = extractMarkdownHeadings(markdown);\n\n return {\n markdown,\n wordCount,\n readingTime,\n headings,\n };\n}\n\n/**\n * Generate markdown string only (without metadata)\n */\nexport function generateMarkdownString(content: LLMContent): string {\n return generateMarkdown(content).markdown;\n}\n\n/**\n * Check if string contains HTML\n */\nfunction isHTML(str: string): boolean {\n return /<[a-z][\\s\\S]*>/i.test(str);\n}\n\n/**\n * Extract headings from markdown for TOC\n */\nfunction extractMarkdownHeadings(markdown: string): TOCHeading[] {\n const headings: TOCHeading[] = [];\n const lines = markdown.split('\\n');\n let index = 0;\n\n for (const line of lines) {\n const match = line.match(/^(#{1,6})\\s+(.+)$/);\n if (match) {\n const level = match[1].length;\n const text = match[2].trim();\n const id = generateSlug(text, index);\n\n headings.push({ id, text, level });\n index++;\n }\n }\n\n return headings;\n}\n\n/**\n * Generate URL-friendly slug from text\n */\nfunction generateSlug(text: string, index: number): string {\n const slug = text\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n return slug || `heading-${index}`;\n}\n\n/**\n * Convert LLMContent to plain text (for previews, etc.)\n */\nexport function contentToPlainText(content: LLMContent): string {\n const markdown = generateMarkdownString(content);\n return markdown\n .replace(/^#+\\s+/gm, '') // Remove headings\n .replace(/\\*\\*([^*]+)\\*\\*/g, '$1') // Remove bold\n .replace(/\\*([^*]+)\\*/g, '$1') // Remove italic\n .replace(/`([^`]+)`/g, '$1') // Remove inline code\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1') // Remove links\n .replace(/!\\[([^\\]]*)\\]\\([^)]+\\)/g, '') // Remove images\n .replace(/^[-*+]\\s+/gm, '') // Remove list markers\n .replace(/^>\\s+/gm, '') // Remove blockquotes\n .replace(/^---$/gm, '') // Remove horizontal rules\n .replace(/\\n{2,}/g, '\\n\\n') // Normalize line breaks\n .trim();\n}\n","/**\n * LLMs.txt Generator\n * Generate sitemap-style content listing for AI crawlers\n * Follows the llms.txt specification\n */\n\nimport type { LLMsTxtConfig, LLMsTxtItem } from '../types';\n\n/**\n * Generate llms.txt content\n */\nexport function generateLLMsTxt(config: LLMsTxtConfig): string {\n const parts: string[] = [];\n\n // Header\n parts.push(`# ${config.siteName}`);\n parts.push('');\n\n if (config.siteDescription) {\n parts.push(`> ${config.siteDescription}`);\n parts.push('');\n }\n\n // Custom header text or default\n if (config.headerText) {\n parts.push(config.headerText);\n } else {\n parts.push('This file provides LLM-friendly access to the content on this website.');\n }\n parts.push('');\n\n // Site info\n parts.push('---');\n parts.push(`- **Site URL**: ${config.siteUrl}`);\n parts.push('- **Format**: Append `?llm=1` to any page URL to get markdown');\n parts.push('---');\n parts.push('');\n\n // Content listing\n if (config.content.length > 0) {\n parts.push('## Available Content');\n parts.push('');\n\n for (const item of config.content) {\n const llmUrl = appendQueryParam(item.url, 'llm', '1');\n\n parts.push(`### [${item.title}](${llmUrl})`);\n\n if (item.type) {\n parts.push(`- **Type**: ${item.type}`);\n }\n\n if (item.date) {\n parts.push(`- **Date**: ${item.date}`);\n }\n\n if (item.description) {\n parts.push(`- **Description**: ${item.description}`);\n }\n\n parts.push(`- **Markdown URL**: ${llmUrl}`);\n parts.push('');\n }\n }\n\n // Footer\n parts.push('---');\n parts.push('');\n\n if (config.footerText) {\n parts.push(config.footerText);\n } else {\n parts.push('*Generated by [next-llm-ready](https://seoengine.ai) - Make your content AI-ready*');\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Append query parameter to URL\n */\nfunction appendQueryParam(url: string, key: string, value: string): string {\n const separator = url.includes('?') ? '&' : '?';\n return `${url}${separator}${key}=${value}`;\n}\n\n/**\n * Sort content items by date (newest first)\n */\nexport function sortByDate(items: LLMsTxtItem[]): LLMsTxtItem[] {\n return [...items].sort((a, b) => {\n if (!a.date) return 1;\n if (!b.date) return -1;\n return new Date(b.date).getTime() - new Date(a.date).getTime();\n });\n}\n\n/**\n * Filter content by type\n */\nexport function filterByType(items: LLMsTxtItem[], types: string[]): LLMsTxtItem[] {\n const typeSet = new Set(types.map((t) => t.toLowerCase()));\n return items.filter((item) => !item.type || typeSet.has(item.type.toLowerCase()));\n}\n\n/**\n * Create LLMsTxtItem from minimal data\n */\nexport function createLLMsTxtItem(\n title: string,\n url: string,\n options?: Partial<Omit<LLMsTxtItem, 'title' | 'url'>>\n): LLMsTxtItem {\n return {\n title,\n url,\n ...options,\n };\n}\n"]}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * next-llm-ready - TypeScript Type Definitions
3
+ * Make your Next.js content AI-ready
4
+ */
5
+ /**
6
+ * Content metadata for LLM-ready output
7
+ */
8
+ interface LLMContent {
9
+ /** Page/post title */
10
+ title: string;
11
+ /** Main content (HTML or Markdown) */
12
+ content: string;
13
+ /** Short description/excerpt */
14
+ excerpt?: string;
15
+ /** Canonical URL */
16
+ url: string;
17
+ /** Publication date (ISO 8601) */
18
+ date?: string;
19
+ /** Last modified date (ISO 8601) */
20
+ modifiedDate?: string;
21
+ /** Author name */
22
+ author?: string;
23
+ /** Categories/sections */
24
+ categories?: string[];
25
+ /** Tags/keywords */
26
+ tags?: string[];
27
+ /** Custom prompt prefix for AI context */
28
+ promptPrefix?: string;
29
+ /** Featured image URL */
30
+ image?: string;
31
+ /** Reading time in minutes */
32
+ readingTime?: number;
33
+ }
34
+ /**
35
+ * Generated markdown output
36
+ */
37
+ interface MarkdownOutput {
38
+ /** Raw markdown string */
39
+ markdown: string;
40
+ /** Word count */
41
+ wordCount: number;
42
+ /** Estimated reading time */
43
+ readingTime: number;
44
+ /** Extracted headings for TOC */
45
+ headings: TOCHeading[];
46
+ }
47
+ /**
48
+ * Single TOC heading item
49
+ */
50
+ interface TOCHeading {
51
+ /** Heading ID (for anchor links) */
52
+ id: string;
53
+ /** Heading text content */
54
+ text: string;
55
+ /** Heading level (1-6) */
56
+ level: number;
57
+ /** Child headings (for nested structure) */
58
+ children?: TOCHeading[];
59
+ }
60
+ /**
61
+ * LLMs.txt endpoint configuration
62
+ */
63
+ interface LLMsTxtConfig {
64
+ /** Site name */
65
+ siteName: string;
66
+ /** Site description */
67
+ siteDescription?: string;
68
+ /** Site URL */
69
+ siteUrl: string;
70
+ /** Content items to include */
71
+ content: LLMsTxtItem[];
72
+ /** Custom header text */
73
+ headerText?: string;
74
+ /** Custom footer text */
75
+ footerText?: string;
76
+ }
77
+ /**
78
+ * Single item in LLMs.txt listing
79
+ */
80
+ interface LLMsTxtItem {
81
+ /** Content title */
82
+ title: string;
83
+ /** Page URL */
84
+ url: string;
85
+ /** Content type (post, page, etc.) */
86
+ type?: string;
87
+ /** Publication date */
88
+ date?: string;
89
+ /** Short description */
90
+ description?: string;
91
+ }
92
+
93
+ /**
94
+ * Server-side Markdown Generation
95
+ * Generate LLM-ready markdown from content
96
+ */
97
+
98
+ /**
99
+ * Generate complete markdown output from LLM content
100
+ */
101
+ declare function generateMarkdown(content: LLMContent): MarkdownOutput;
102
+ /**
103
+ * Generate markdown string only (without metadata)
104
+ */
105
+ declare function generateMarkdownString(content: LLMContent): string;
106
+ /**
107
+ * Convert LLMContent to plain text (for previews, etc.)
108
+ */
109
+ declare function contentToPlainText(content: LLMContent): string;
110
+
111
+ /**
112
+ * LLMs.txt Generator
113
+ * Generate sitemap-style content listing for AI crawlers
114
+ * Follows the llms.txt specification
115
+ */
116
+
117
+ /**
118
+ * Generate llms.txt content
119
+ */
120
+ declare function generateLLMsTxt(config: LLMsTxtConfig): string;
121
+ /**
122
+ * Sort content items by date (newest first)
123
+ */
124
+ declare function sortByDate(items: LLMsTxtItem[]): LLMsTxtItem[];
125
+ /**
126
+ * Filter content by type
127
+ */
128
+ declare function filterByType(items: LLMsTxtItem[], types: string[]): LLMsTxtItem[];
129
+ /**
130
+ * Create LLMsTxtItem from minimal data
131
+ */
132
+ declare function createLLMsTxtItem(title: string, url: string, options?: Partial<Omit<LLMsTxtItem, 'title' | 'url'>>): LLMsTxtItem;
133
+
134
+ export { type LLMContent, type LLMsTxtConfig, type LLMsTxtItem, type MarkdownOutput, contentToPlainText, createLLMsTxtItem, filterByType, generateLLMsTxt, generateMarkdown, generateMarkdownString, sortByDate };