@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.
- package/LICENSE +21 -0
- package/README.md +858 -0
- package/dist/api/index.cjs +624 -0
- package/dist/api/index.cjs.map +1 -0
- package/dist/api/index.d.cts +295 -0
- package/dist/api/index.d.ts +295 -0
- package/dist/api/index.js +613 -0
- package/dist/api/index.js.map +1 -0
- package/dist/hooks/index.cjs +619 -0
- package/dist/hooks/index.cjs.map +1 -0
- package/dist/hooks/index.d.cts +257 -0
- package/dist/hooks/index.d.ts +257 -0
- package/dist/hooks/index.js +611 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.cjs +1609 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +850 -0
- package/dist/index.d.ts +850 -0
- package/dist/index.js +1576 -0
- package/dist/index.js.map +1 -0
- package/dist/server/index.cjs +398 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +134 -0
- package/dist/server/index.d.ts +134 -0
- package/dist/server/index.js +390 -0
- package/dist/server/index.js.map +1 -0
- package/dist/styles.css +855 -0
- package/package.json +118 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,850 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* next-llm-ready - TypeScript Type Definitions
|
|
6
|
+
* Make your Next.js content AI-ready
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Content metadata for LLM-ready output
|
|
10
|
+
*/
|
|
11
|
+
interface LLMContent {
|
|
12
|
+
/** Page/post title */
|
|
13
|
+
title: string;
|
|
14
|
+
/** Main content (HTML or Markdown) */
|
|
15
|
+
content: string;
|
|
16
|
+
/** Short description/excerpt */
|
|
17
|
+
excerpt?: string;
|
|
18
|
+
/** Canonical URL */
|
|
19
|
+
url: string;
|
|
20
|
+
/** Publication date (ISO 8601) */
|
|
21
|
+
date?: string;
|
|
22
|
+
/** Last modified date (ISO 8601) */
|
|
23
|
+
modifiedDate?: string;
|
|
24
|
+
/** Author name */
|
|
25
|
+
author?: string;
|
|
26
|
+
/** Categories/sections */
|
|
27
|
+
categories?: string[];
|
|
28
|
+
/** Tags/keywords */
|
|
29
|
+
tags?: string[];
|
|
30
|
+
/** Custom prompt prefix for AI context */
|
|
31
|
+
promptPrefix?: string;
|
|
32
|
+
/** Featured image URL */
|
|
33
|
+
image?: string;
|
|
34
|
+
/** Reading time in minutes */
|
|
35
|
+
readingTime?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Generated markdown output
|
|
39
|
+
*/
|
|
40
|
+
interface MarkdownOutput {
|
|
41
|
+
/** Raw markdown string */
|
|
42
|
+
markdown: string;
|
|
43
|
+
/** Word count */
|
|
44
|
+
wordCount: number;
|
|
45
|
+
/** Estimated reading time */
|
|
46
|
+
readingTime: number;
|
|
47
|
+
/** Extracted headings for TOC */
|
|
48
|
+
headings: TOCHeading[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Position options for UI elements
|
|
52
|
+
*/
|
|
53
|
+
type ButtonPosition = 'floating' | 'inline' | 'next-to-heading' | 'below-heading';
|
|
54
|
+
/**
|
|
55
|
+
* TOC position options
|
|
56
|
+
*/
|
|
57
|
+
type TOCPosition = 'left' | 'right' | 'inline-start' | 'inline-end';
|
|
58
|
+
/**
|
|
59
|
+
* Heading levels to include in TOC
|
|
60
|
+
*/
|
|
61
|
+
type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
62
|
+
/**
|
|
63
|
+
* Copy action types for analytics
|
|
64
|
+
*/
|
|
65
|
+
type CopyAction = 'copy' | 'view' | 'download';
|
|
66
|
+
/**
|
|
67
|
+
* CopyButton component props
|
|
68
|
+
*/
|
|
69
|
+
interface CopyButtonProps {
|
|
70
|
+
/** Content to copy (LLMContent object or markdown string) */
|
|
71
|
+
content: LLMContent | string;
|
|
72
|
+
/** Button text */
|
|
73
|
+
text?: string;
|
|
74
|
+
/** Show dropdown with additional options */
|
|
75
|
+
showDropdown?: boolean;
|
|
76
|
+
/** Button position */
|
|
77
|
+
position?: ButtonPosition;
|
|
78
|
+
/** Enable keyboard shortcut (Ctrl+Shift+C / Cmd+Shift+C) */
|
|
79
|
+
keyboardShortcut?: boolean;
|
|
80
|
+
/** Custom class name */
|
|
81
|
+
className?: string;
|
|
82
|
+
/** Toast message on copy */
|
|
83
|
+
toastMessage?: string;
|
|
84
|
+
/** Toast duration in ms */
|
|
85
|
+
toastDuration?: number;
|
|
86
|
+
/** Callback on successful copy */
|
|
87
|
+
onCopy?: (action: CopyAction) => void;
|
|
88
|
+
/** Callback on error */
|
|
89
|
+
onError?: (error: Error) => void;
|
|
90
|
+
/** Analytics tracking function */
|
|
91
|
+
onAnalytics?: (event: AnalyticsEvent) => void;
|
|
92
|
+
/** Custom styles */
|
|
93
|
+
style?: React.CSSProperties;
|
|
94
|
+
/** Disable the button */
|
|
95
|
+
disabled?: boolean;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* CopyDropdown component props (split button with menu)
|
|
99
|
+
*/
|
|
100
|
+
interface CopyDropdownProps extends Omit<CopyButtonProps, 'showDropdown'> {
|
|
101
|
+
/** Dropdown menu items */
|
|
102
|
+
menuItems?: DropdownMenuItem[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Dropdown menu item
|
|
106
|
+
*/
|
|
107
|
+
interface DropdownMenuItem {
|
|
108
|
+
/** Unique identifier */
|
|
109
|
+
id: string;
|
|
110
|
+
/** Display label */
|
|
111
|
+
label: string;
|
|
112
|
+
/** Icon component */
|
|
113
|
+
icon?: React.ReactNode;
|
|
114
|
+
/** Action to perform */
|
|
115
|
+
action: CopyAction | (() => void);
|
|
116
|
+
/** Keyboard shortcut hint */
|
|
117
|
+
shortcut?: string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* TOC (Table of Contents) component props
|
|
121
|
+
*/
|
|
122
|
+
interface TOCProps {
|
|
123
|
+
/** Content to extract headings from (HTML string or ref to content element) */
|
|
124
|
+
content?: string;
|
|
125
|
+
/** Reference to content container element */
|
|
126
|
+
contentRef?: React.RefObject<HTMLElement>;
|
|
127
|
+
/** Manually provided headings */
|
|
128
|
+
headings?: TOCHeading[];
|
|
129
|
+
/** Position of TOC */
|
|
130
|
+
position?: TOCPosition;
|
|
131
|
+
/** Heading levels to include */
|
|
132
|
+
levels?: HeadingLevel[];
|
|
133
|
+
/** Title for TOC section */
|
|
134
|
+
title?: string;
|
|
135
|
+
/** Sticky behavior */
|
|
136
|
+
sticky?: boolean;
|
|
137
|
+
/** Sticky offset from top (px) */
|
|
138
|
+
stickyOffset?: number;
|
|
139
|
+
/** Custom class name */
|
|
140
|
+
className?: string;
|
|
141
|
+
/** Smooth scroll behavior */
|
|
142
|
+
smoothScroll?: boolean;
|
|
143
|
+
/** Highlight active heading */
|
|
144
|
+
highlightActive?: boolean;
|
|
145
|
+
/** Collapsible on mobile */
|
|
146
|
+
collapsible?: boolean;
|
|
147
|
+
/** Initially collapsed */
|
|
148
|
+
defaultCollapsed?: boolean;
|
|
149
|
+
/** Custom styles */
|
|
150
|
+
style?: React.CSSProperties;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Single TOC heading item
|
|
154
|
+
*/
|
|
155
|
+
interface TOCHeading {
|
|
156
|
+
/** Heading ID (for anchor links) */
|
|
157
|
+
id: string;
|
|
158
|
+
/** Heading text content */
|
|
159
|
+
text: string;
|
|
160
|
+
/** Heading level (1-6) */
|
|
161
|
+
level: number;
|
|
162
|
+
/** Child headings (for nested structure) */
|
|
163
|
+
children?: TOCHeading[];
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* LLMBadge component props (shows AI-ready indicator)
|
|
167
|
+
*/
|
|
168
|
+
interface LLMBadgeProps {
|
|
169
|
+
/** Badge text */
|
|
170
|
+
text?: string;
|
|
171
|
+
/** Show tooltip with info */
|
|
172
|
+
showTooltip?: boolean;
|
|
173
|
+
/** Tooltip content */
|
|
174
|
+
tooltipContent?: string;
|
|
175
|
+
/** Badge size */
|
|
176
|
+
size?: 'sm' | 'md' | 'lg';
|
|
177
|
+
/** Custom class name */
|
|
178
|
+
className?: string;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* useLLMCopy hook options
|
|
182
|
+
*/
|
|
183
|
+
interface UseLLMCopyOptions {
|
|
184
|
+
/** Content to copy */
|
|
185
|
+
content: LLMContent | string;
|
|
186
|
+
/** Success callback */
|
|
187
|
+
onSuccess?: (action: CopyAction) => void;
|
|
188
|
+
/** Error callback */
|
|
189
|
+
onError?: (error: Error) => void;
|
|
190
|
+
/** Analytics callback */
|
|
191
|
+
onAnalytics?: (event: AnalyticsEvent) => void;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* useLLMCopy hook return value
|
|
195
|
+
*/
|
|
196
|
+
interface UseLLMCopyReturn {
|
|
197
|
+
/** Copy to clipboard function */
|
|
198
|
+
copy: () => Promise<boolean>;
|
|
199
|
+
/** View markdown function (returns markdown string) */
|
|
200
|
+
view: () => string;
|
|
201
|
+
/** Download markdown function */
|
|
202
|
+
download: (filename?: string) => void;
|
|
203
|
+
/** Generated markdown */
|
|
204
|
+
markdown: string;
|
|
205
|
+
/** Copy in progress */
|
|
206
|
+
isCopying: boolean;
|
|
207
|
+
/** Last copy was successful */
|
|
208
|
+
isSuccess: boolean;
|
|
209
|
+
/** Last error */
|
|
210
|
+
error: Error | null;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* useTOC hook options
|
|
214
|
+
*/
|
|
215
|
+
interface UseTOCOptions {
|
|
216
|
+
/** Content container ref */
|
|
217
|
+
contentRef: React.RefObject<HTMLElement>;
|
|
218
|
+
/** Heading levels to track */
|
|
219
|
+
levels?: HeadingLevel[];
|
|
220
|
+
/** Root margin for intersection observer */
|
|
221
|
+
rootMargin?: string;
|
|
222
|
+
/** Threshold for intersection observer */
|
|
223
|
+
threshold?: number | number[];
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* useTOC hook return value
|
|
227
|
+
*/
|
|
228
|
+
interface UseTOCReturn {
|
|
229
|
+
/** Extracted headings */
|
|
230
|
+
headings: TOCHeading[];
|
|
231
|
+
/** Currently active heading ID */
|
|
232
|
+
activeId: string | null;
|
|
233
|
+
/** Scroll to heading function */
|
|
234
|
+
scrollTo: (id: string) => void;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* useAnalytics hook options
|
|
238
|
+
*/
|
|
239
|
+
interface UseAnalyticsOptions {
|
|
240
|
+
/** API endpoint for tracking */
|
|
241
|
+
endpoint?: string;
|
|
242
|
+
/** Include page URL */
|
|
243
|
+
includeUrl?: boolean;
|
|
244
|
+
/** Include timestamp */
|
|
245
|
+
includeTimestamp?: boolean;
|
|
246
|
+
/** Custom metadata */
|
|
247
|
+
metadata?: Record<string, unknown>;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* useAnalytics hook return value
|
|
251
|
+
*/
|
|
252
|
+
interface UseAnalyticsReturn {
|
|
253
|
+
/** Track an event */
|
|
254
|
+
track: (event: AnalyticsEvent) => Promise<void>;
|
|
255
|
+
/** Track copy action */
|
|
256
|
+
trackCopy: () => Promise<void>;
|
|
257
|
+
/** Track view action */
|
|
258
|
+
trackView: () => Promise<void>;
|
|
259
|
+
/** Track download action */
|
|
260
|
+
trackDownload: () => Promise<void>;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Analytics event
|
|
264
|
+
*/
|
|
265
|
+
interface AnalyticsEvent {
|
|
266
|
+
/** Event type */
|
|
267
|
+
action: CopyAction;
|
|
268
|
+
/** Page/content identifier */
|
|
269
|
+
contentId?: string;
|
|
270
|
+
/** Page URL */
|
|
271
|
+
url?: string;
|
|
272
|
+
/** Timestamp */
|
|
273
|
+
timestamp?: string;
|
|
274
|
+
/** Additional metadata */
|
|
275
|
+
metadata?: Record<string, unknown>;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Analytics handler config
|
|
279
|
+
*/
|
|
280
|
+
interface AnalyticsConfig {
|
|
281
|
+
/** Enable analytics */
|
|
282
|
+
enabled?: boolean;
|
|
283
|
+
/** API endpoint */
|
|
284
|
+
endpoint?: string;
|
|
285
|
+
/** Storage type */
|
|
286
|
+
storage?: 'memory' | 'localStorage' | 'custom';
|
|
287
|
+
/** Custom storage adapter */
|
|
288
|
+
storageAdapter?: AnalyticsStorageAdapter;
|
|
289
|
+
/** Batch events before sending */
|
|
290
|
+
batchSize?: number;
|
|
291
|
+
/** Flush interval in ms */
|
|
292
|
+
flushInterval?: number;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Custom analytics storage adapter
|
|
296
|
+
*/
|
|
297
|
+
interface AnalyticsStorageAdapter {
|
|
298
|
+
/** Save event */
|
|
299
|
+
save: (event: AnalyticsEvent) => Promise<void>;
|
|
300
|
+
/** Get all events */
|
|
301
|
+
getAll: () => Promise<AnalyticsEvent[]>;
|
|
302
|
+
/** Clear events */
|
|
303
|
+
clear: () => Promise<void>;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* LLMs.txt endpoint configuration
|
|
307
|
+
*/
|
|
308
|
+
interface LLMsTxtConfig {
|
|
309
|
+
/** Site name */
|
|
310
|
+
siteName: string;
|
|
311
|
+
/** Site description */
|
|
312
|
+
siteDescription?: string;
|
|
313
|
+
/** Site URL */
|
|
314
|
+
siteUrl: string;
|
|
315
|
+
/** Content items to include */
|
|
316
|
+
content: LLMsTxtItem[];
|
|
317
|
+
/** Custom header text */
|
|
318
|
+
headerText?: string;
|
|
319
|
+
/** Custom footer text */
|
|
320
|
+
footerText?: string;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Single item in LLMs.txt listing
|
|
324
|
+
*/
|
|
325
|
+
interface LLMsTxtItem {
|
|
326
|
+
/** Content title */
|
|
327
|
+
title: string;
|
|
328
|
+
/** Page URL */
|
|
329
|
+
url: string;
|
|
330
|
+
/** Content type (post, page, etc.) */
|
|
331
|
+
type?: string;
|
|
332
|
+
/** Publication date */
|
|
333
|
+
date?: string;
|
|
334
|
+
/** Short description */
|
|
335
|
+
description?: string;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Markdown API handler options
|
|
339
|
+
*/
|
|
340
|
+
interface MarkdownHandlerOptions {
|
|
341
|
+
/** Function to fetch content by slug/id */
|
|
342
|
+
getContent: (slug: string) => Promise<LLMContent | null>;
|
|
343
|
+
/** Cache control header value */
|
|
344
|
+
cacheControl?: string;
|
|
345
|
+
/** Enable CORS */
|
|
346
|
+
cors?: boolean;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Analytics API handler options
|
|
350
|
+
*/
|
|
351
|
+
interface AnalyticsHandlerOptions {
|
|
352
|
+
/** Storage adapter */
|
|
353
|
+
storage: AnalyticsStorageAdapter;
|
|
354
|
+
/** Rate limiting (requests per minute) */
|
|
355
|
+
rateLimit?: number;
|
|
356
|
+
/** Enable CORS */
|
|
357
|
+
cors?: boolean;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Global LLM Ready configuration
|
|
361
|
+
*/
|
|
362
|
+
interface LLMReadyConfig {
|
|
363
|
+
/** Default button position */
|
|
364
|
+
defaultPosition?: ButtonPosition;
|
|
365
|
+
/** Default TOC position */
|
|
366
|
+
defaultTOCPosition?: TOCPosition;
|
|
367
|
+
/** Enable keyboard shortcuts globally */
|
|
368
|
+
keyboardShortcuts?: boolean;
|
|
369
|
+
/** Default prompt prefix */
|
|
370
|
+
promptPrefix?: string;
|
|
371
|
+
/** Analytics configuration */
|
|
372
|
+
analytics?: AnalyticsConfig;
|
|
373
|
+
/** Custom theme variables */
|
|
374
|
+
theme?: ThemeConfig;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Theme configuration (CSS variables)
|
|
378
|
+
*/
|
|
379
|
+
interface ThemeConfig {
|
|
380
|
+
/** Primary color */
|
|
381
|
+
primaryColor?: string;
|
|
382
|
+
/** Primary hover color */
|
|
383
|
+
primaryHover?: string;
|
|
384
|
+
/** Text color */
|
|
385
|
+
textColor?: string;
|
|
386
|
+
/** Background color */
|
|
387
|
+
backgroundColor?: string;
|
|
388
|
+
/** Border color */
|
|
389
|
+
borderColor?: string;
|
|
390
|
+
/** Border radius */
|
|
391
|
+
borderRadius?: string;
|
|
392
|
+
/** Font family */
|
|
393
|
+
fontFamily?: string;
|
|
394
|
+
/** Shadow */
|
|
395
|
+
shadow?: string;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* HTML to Markdown conversion options
|
|
399
|
+
*/
|
|
400
|
+
interface HTMLToMarkdownOptions {
|
|
401
|
+
/** Preserve line breaks */
|
|
402
|
+
preserveLineBreaks?: boolean;
|
|
403
|
+
/** Convert images to markdown */
|
|
404
|
+
convertImages?: boolean;
|
|
405
|
+
/** Convert links to markdown */
|
|
406
|
+
convertLinks?: boolean;
|
|
407
|
+
/** Strip scripts and styles */
|
|
408
|
+
stripScripts?: boolean;
|
|
409
|
+
/** Custom element handlers */
|
|
410
|
+
customHandlers?: Record<string, (element: Element) => string>;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Download options
|
|
414
|
+
*/
|
|
415
|
+
interface DownloadOptions {
|
|
416
|
+
/** Filename (without extension) */
|
|
417
|
+
filename?: string;
|
|
418
|
+
/** File extension */
|
|
419
|
+
extension?: 'md' | 'txt';
|
|
420
|
+
/** Include metadata header */
|
|
421
|
+
includeMetadata?: boolean;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Simple copy button component
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* ```tsx
|
|
429
|
+
* <CopyButton
|
|
430
|
+
* content={{
|
|
431
|
+
* title: "My Article",
|
|
432
|
+
* content: "<p>Article content...</p>",
|
|
433
|
+
* url: "https://example.com/article",
|
|
434
|
+
* }}
|
|
435
|
+
* text="Copy for AI"
|
|
436
|
+
* />
|
|
437
|
+
* ```
|
|
438
|
+
*/
|
|
439
|
+
declare function CopyButton({ content, text, position, keyboardShortcut, className, toastMessage, toastDuration, onCopy, onError, onAnalytics, style, disabled, }: CopyButtonProps): react_jsx_runtime.JSX.Element;
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Split button with dropdown for copy/view/download actions
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```tsx
|
|
446
|
+
* <CopyDropdown
|
|
447
|
+
* content={{
|
|
448
|
+
* title: "My Article",
|
|
449
|
+
* content: "<p>Article content...</p>",
|
|
450
|
+
* url: "https://example.com/article",
|
|
451
|
+
* }}
|
|
452
|
+
* text="Copy for AI"
|
|
453
|
+
* />
|
|
454
|
+
* ```
|
|
455
|
+
*/
|
|
456
|
+
declare function CopyDropdown({ content, text, menuItems, position, keyboardShortcut, className, toastMessage, toastDuration, onCopy, onError, onAnalytics, style, disabled, }: CopyDropdownProps): react_jsx_runtime.JSX.Element;
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Table of Contents component
|
|
460
|
+
*
|
|
461
|
+
* @example
|
|
462
|
+
* ```tsx
|
|
463
|
+
* function Article() {
|
|
464
|
+
* const contentRef = useRef<HTMLDivElement>(null);
|
|
465
|
+
*
|
|
466
|
+
* return (
|
|
467
|
+
* <div className="article-layout">
|
|
468
|
+
* <TOC
|
|
469
|
+
* contentRef={contentRef}
|
|
470
|
+
* position="right"
|
|
471
|
+
* levels={['h2', 'h3']}
|
|
472
|
+
* sticky
|
|
473
|
+
* />
|
|
474
|
+
* <article ref={contentRef}>
|
|
475
|
+
* <h2 id="intro">Introduction</h2>
|
|
476
|
+
* <p>Content...</p>
|
|
477
|
+
* </article>
|
|
478
|
+
* </div>
|
|
479
|
+
* );
|
|
480
|
+
* }
|
|
481
|
+
* ```
|
|
482
|
+
*/
|
|
483
|
+
declare function TOC({ content, contentRef, headings: providedHeadings, position, levels, title, sticky, stickyOffset, className, smoothScroll, highlightActive, collapsible, defaultCollapsed, style, }: TOCProps): react_jsx_runtime.JSX.Element | null;
|
|
484
|
+
/**
|
|
485
|
+
* Mobile TOC with slide-up panel
|
|
486
|
+
*/
|
|
487
|
+
declare function TOCMobile(props: TOCProps): react_jsx_runtime.JSX.Element;
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Badge showing content is LLM-ready
|
|
491
|
+
*
|
|
492
|
+
* @example
|
|
493
|
+
* ```tsx
|
|
494
|
+
* <LLMBadge
|
|
495
|
+
* text="AI Ready"
|
|
496
|
+
* showTooltip
|
|
497
|
+
* size="sm"
|
|
498
|
+
* />
|
|
499
|
+
* ```
|
|
500
|
+
*/
|
|
501
|
+
declare function LLMBadge({ text, showTooltip, tooltipContent, size, className, }: LLMBadgeProps): react_jsx_runtime.JSX.Element;
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Hook for LLM copy/view/download operations
|
|
505
|
+
*
|
|
506
|
+
* @example
|
|
507
|
+
* ```tsx
|
|
508
|
+
* function MyComponent() {
|
|
509
|
+
* const { copy, view, download, markdown, isCopying, isSuccess } = useLLMCopy({
|
|
510
|
+
* content: {
|
|
511
|
+
* title: 'My Article',
|
|
512
|
+
* content: '<p>Article content...</p>',
|
|
513
|
+
* url: 'https://example.com/article',
|
|
514
|
+
* },
|
|
515
|
+
* onSuccess: () => console.log('Copied!'),
|
|
516
|
+
* });
|
|
517
|
+
*
|
|
518
|
+
* return (
|
|
519
|
+
* <div>
|
|
520
|
+
* <button onClick={copy} disabled={isCopying}>
|
|
521
|
+
* {isSuccess ? 'Copied!' : 'Copy'}
|
|
522
|
+
* </button>
|
|
523
|
+
* <button onClick={download}>Download</button>
|
|
524
|
+
* <pre>{view()}</pre>
|
|
525
|
+
* </div>
|
|
526
|
+
* );
|
|
527
|
+
* }
|
|
528
|
+
* ```
|
|
529
|
+
*/
|
|
530
|
+
declare function useLLMCopy(options: UseLLMCopyOptions): UseLLMCopyReturn;
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Hook for Table of Contents functionality
|
|
534
|
+
*
|
|
535
|
+
* @example
|
|
536
|
+
* ```tsx
|
|
537
|
+
* function ArticlePage() {
|
|
538
|
+
* const contentRef = useRef<HTMLDivElement>(null);
|
|
539
|
+
* const { headings, activeId, scrollTo } = useTOC({
|
|
540
|
+
* contentRef,
|
|
541
|
+
* levels: ['h2', 'h3'],
|
|
542
|
+
* });
|
|
543
|
+
*
|
|
544
|
+
* return (
|
|
545
|
+
* <div>
|
|
546
|
+
* <nav>
|
|
547
|
+
* {headings.map(h => (
|
|
548
|
+
* <a
|
|
549
|
+
* key={h.id}
|
|
550
|
+
* href={`#${h.id}`}
|
|
551
|
+
* onClick={(e) => { e.preventDefault(); scrollTo(h.id); }}
|
|
552
|
+
* className={activeId === h.id ? 'active' : ''}
|
|
553
|
+
* >
|
|
554
|
+
* {h.text}
|
|
555
|
+
* </a>
|
|
556
|
+
* ))}
|
|
557
|
+
* </nav>
|
|
558
|
+
* <div ref={contentRef}>
|
|
559
|
+
* <h2 id="intro">Introduction</h2>
|
|
560
|
+
* <p>Content...</p>
|
|
561
|
+
* </div>
|
|
562
|
+
* </div>
|
|
563
|
+
* );
|
|
564
|
+
* }
|
|
565
|
+
* ```
|
|
566
|
+
*/
|
|
567
|
+
declare function useTOC(options: UseTOCOptions): UseTOCReturn;
|
|
568
|
+
/**
|
|
569
|
+
* Build nested TOC structure from flat headings
|
|
570
|
+
*/
|
|
571
|
+
declare function buildNestedTOC(headings: TOCHeading[]): TOCHeading[];
|
|
572
|
+
/**
|
|
573
|
+
* Hook for keyboard navigation in TOC
|
|
574
|
+
*/
|
|
575
|
+
declare function useTOCKeyboard(headings: TOCHeading[], activeId: string | null, scrollTo: (id: string) => void): void;
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Hook for analytics tracking
|
|
579
|
+
*
|
|
580
|
+
* @example
|
|
581
|
+
* ```tsx
|
|
582
|
+
* function MyComponent() {
|
|
583
|
+
* const { track, trackCopy, trackView, trackDownload } = useAnalytics({
|
|
584
|
+
* endpoint: '/api/analytics',
|
|
585
|
+
* metadata: { contentId: 'article-123' },
|
|
586
|
+
* });
|
|
587
|
+
*
|
|
588
|
+
* return (
|
|
589
|
+
* <button onClick={trackCopy}>Copy</button>
|
|
590
|
+
* );
|
|
591
|
+
* }
|
|
592
|
+
* ```
|
|
593
|
+
*/
|
|
594
|
+
declare function useAnalytics(options?: UseAnalyticsOptions): UseAnalyticsReturn;
|
|
595
|
+
/**
|
|
596
|
+
* Create a simple analytics tracker function (non-hook version)
|
|
597
|
+
*/
|
|
598
|
+
declare function createAnalyticsTracker(endpoint: string): (action: CopyAction, contentId?: string, metadata?: Record<string, unknown>) => Promise<void>;
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* HTML to Markdown Converter
|
|
602
|
+
* Converts HTML content to clean markdown format
|
|
603
|
+
*/
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Convert HTML string to Markdown
|
|
607
|
+
*/
|
|
608
|
+
declare function htmlToMarkdown(html: string, options?: HTMLToMarkdownOptions): string;
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Clipboard Utilities
|
|
612
|
+
* Cross-browser clipboard operations
|
|
613
|
+
*/
|
|
614
|
+
/**
|
|
615
|
+
* Copy text to clipboard
|
|
616
|
+
* Uses modern Clipboard API with fallback for older browsers
|
|
617
|
+
*/
|
|
618
|
+
declare function copyToClipboard(text: string): Promise<boolean>;
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Download Utilities
|
|
622
|
+
* File download functionality
|
|
623
|
+
*/
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Download content as a file
|
|
627
|
+
*/
|
|
628
|
+
declare function downloadAsFile(content: string, options?: DownloadOptions): void;
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Server-side Markdown Generation
|
|
632
|
+
* Generate LLM-ready markdown from content
|
|
633
|
+
*/
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Generate complete markdown output from LLM content
|
|
637
|
+
*/
|
|
638
|
+
declare function generateMarkdown(content: LLMContent): MarkdownOutput;
|
|
639
|
+
/**
|
|
640
|
+
* Generate markdown string only (without metadata)
|
|
641
|
+
*/
|
|
642
|
+
declare function generateMarkdownString(content: LLMContent): string;
|
|
643
|
+
/**
|
|
644
|
+
* Convert LLMContent to plain text (for previews, etc.)
|
|
645
|
+
*/
|
|
646
|
+
declare function contentToPlainText(content: LLMContent): string;
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* LLMs.txt Generator
|
|
650
|
+
* Generate sitemap-style content listing for AI crawlers
|
|
651
|
+
* Follows the llms.txt specification
|
|
652
|
+
*/
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Generate llms.txt content
|
|
656
|
+
*/
|
|
657
|
+
declare function generateLLMsTxt(config: LLMsTxtConfig): string;
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* LLMs.txt API Route Handler
|
|
661
|
+
* Creates an API route handler for serving /llms.txt
|
|
662
|
+
*/
|
|
663
|
+
|
|
664
|
+
interface LLMsTxtHandlerOptions {
|
|
665
|
+
/** Function to get site configuration */
|
|
666
|
+
getSiteConfig: () => Promise<{
|
|
667
|
+
siteName: string;
|
|
668
|
+
siteDescription?: string;
|
|
669
|
+
siteUrl: string;
|
|
670
|
+
}>;
|
|
671
|
+
/** Function to get all content items */
|
|
672
|
+
getContent: () => Promise<LLMsTxtItem[]>;
|
|
673
|
+
/** Cache control header (default: 1 hour) */
|
|
674
|
+
cacheControl?: string;
|
|
675
|
+
/** Custom header text */
|
|
676
|
+
headerText?: string;
|
|
677
|
+
/** Custom footer text */
|
|
678
|
+
footerText?: string;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Create an API route handler for /llms.txt
|
|
682
|
+
*
|
|
683
|
+
* @example
|
|
684
|
+
* ```ts
|
|
685
|
+
* // app/llms.txt/route.ts
|
|
686
|
+
* import { createLLMsTxtHandler } from 'next-llm-ready/api';
|
|
687
|
+
*
|
|
688
|
+
* export const GET = createLLMsTxtHandler({
|
|
689
|
+
* getSiteConfig: async () => ({
|
|
690
|
+
* siteName: 'My Site',
|
|
691
|
+
* siteDescription: 'A great website',
|
|
692
|
+
* siteUrl: 'https://example.com',
|
|
693
|
+
* }),
|
|
694
|
+
* getContent: async () => {
|
|
695
|
+
* const posts = await getAllPosts();
|
|
696
|
+
* return posts.map(post => ({
|
|
697
|
+
* title: post.title,
|
|
698
|
+
* url: `https://example.com/blog/${post.slug}`,
|
|
699
|
+
* type: 'post',
|
|
700
|
+
* date: post.date,
|
|
701
|
+
* }));
|
|
702
|
+
* },
|
|
703
|
+
* });
|
|
704
|
+
* ```
|
|
705
|
+
*/
|
|
706
|
+
declare function createLLMsTxtHandler(options: LLMsTxtHandlerOptions): (request: NextRequest) => Promise<NextResponse>;
|
|
707
|
+
/**
|
|
708
|
+
* Create a Pages Router API handler for /api/llms.txt
|
|
709
|
+
*
|
|
710
|
+
* @example
|
|
711
|
+
* ```ts
|
|
712
|
+
* // pages/api/llms.txt.ts
|
|
713
|
+
* import { createLLMsTxtPageHandler } from 'next-llm-ready/api';
|
|
714
|
+
*
|
|
715
|
+
* export default createLLMsTxtPageHandler({
|
|
716
|
+
* getSiteConfig: async () => ({ ... }),
|
|
717
|
+
* getContent: async () => { ... },
|
|
718
|
+
* });
|
|
719
|
+
* ```
|
|
720
|
+
*/
|
|
721
|
+
declare function createLLMsTxtPageHandler(options: LLMsTxtHandlerOptions): (req: {
|
|
722
|
+
method?: string;
|
|
723
|
+
}, res: {
|
|
724
|
+
status: (code: number) => {
|
|
725
|
+
end: (body?: string) => void;
|
|
726
|
+
json: (body: unknown) => void;
|
|
727
|
+
};
|
|
728
|
+
setHeader: (name: string, value: string) => void;
|
|
729
|
+
}) => Promise<void>;
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Markdown API Route Handler
|
|
733
|
+
* Serves markdown content for ?llm=1 requests
|
|
734
|
+
*/
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Create middleware to handle ?llm=1 query parameter
|
|
738
|
+
*
|
|
739
|
+
* @example
|
|
740
|
+
* ```ts
|
|
741
|
+
* // middleware.ts
|
|
742
|
+
* import { withLLMParam } from 'next-llm-ready/api';
|
|
743
|
+
*
|
|
744
|
+
* export default withLLMParam({
|
|
745
|
+
* getContent: async (pathname) => {
|
|
746
|
+
* // Extract slug and fetch content
|
|
747
|
+
* const slug = pathname.split('/').pop();
|
|
748
|
+
* const post = await getPostBySlug(slug);
|
|
749
|
+
* if (!post) return null;
|
|
750
|
+
* return {
|
|
751
|
+
* title: post.title,
|
|
752
|
+
* content: post.content,
|
|
753
|
+
* url: `https://example.com${pathname}`,
|
|
754
|
+
* date: post.date,
|
|
755
|
+
* };
|
|
756
|
+
* },
|
|
757
|
+
* });
|
|
758
|
+
* ```
|
|
759
|
+
*/
|
|
760
|
+
declare function withLLMParam(options: MarkdownHandlerOptions): (request: NextRequest) => Promise<NextResponse | undefined>;
|
|
761
|
+
/**
|
|
762
|
+
* Create an API route handler for markdown endpoints
|
|
763
|
+
*
|
|
764
|
+
* @example
|
|
765
|
+
* ```ts
|
|
766
|
+
* // app/api/content/[slug]/route.ts
|
|
767
|
+
* import { createMarkdownHandler } from 'next-llm-ready/api';
|
|
768
|
+
*
|
|
769
|
+
* export const GET = createMarkdownHandler({
|
|
770
|
+
* getContent: async (slug) => {
|
|
771
|
+
* const post = await getPostBySlug(slug);
|
|
772
|
+
* if (!post) return null;
|
|
773
|
+
* return {
|
|
774
|
+
* title: post.title,
|
|
775
|
+
* content: post.content,
|
|
776
|
+
* url: `https://example.com/blog/${slug}`,
|
|
777
|
+
* };
|
|
778
|
+
* },
|
|
779
|
+
* });
|
|
780
|
+
* ```
|
|
781
|
+
*/
|
|
782
|
+
declare function createMarkdownHandler(options: Omit<MarkdownHandlerOptions, 'getContent'> & {
|
|
783
|
+
getContent: (slug: string) => Promise<LLMContent | null>;
|
|
784
|
+
}): (request: NextRequest, { params }: {
|
|
785
|
+
params: {
|
|
786
|
+
slug?: string;
|
|
787
|
+
};
|
|
788
|
+
}) => Promise<NextResponse>;
|
|
789
|
+
/**
|
|
790
|
+
* Helper to check if request has ?llm=1 parameter
|
|
791
|
+
*/
|
|
792
|
+
declare function hasLLMParam(request: NextRequest): boolean;
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Analytics API Route Handler
|
|
796
|
+
* Tracks copy/view/download events
|
|
797
|
+
*/
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* In-memory analytics storage (for development/testing)
|
|
801
|
+
*/
|
|
802
|
+
declare function createInMemoryStorage(): AnalyticsStorageAdapter;
|
|
803
|
+
/**
|
|
804
|
+
* Create an API route handler for analytics tracking
|
|
805
|
+
*
|
|
806
|
+
* @example
|
|
807
|
+
* ```ts
|
|
808
|
+
* // app/api/analytics/route.ts
|
|
809
|
+
* import { createAnalyticsHandler, createInMemoryStorage } from 'next-llm-ready/api';
|
|
810
|
+
*
|
|
811
|
+
* const storage = createInMemoryStorage();
|
|
812
|
+
*
|
|
813
|
+
* export const POST = createAnalyticsHandler({
|
|
814
|
+
* storage,
|
|
815
|
+
* rateLimit: 100,
|
|
816
|
+
* });
|
|
817
|
+
*
|
|
818
|
+
* export const GET = async () => {
|
|
819
|
+
* const events = await storage.getAll();
|
|
820
|
+
* return NextResponse.json({ events });
|
|
821
|
+
* };
|
|
822
|
+
* ```
|
|
823
|
+
*/
|
|
824
|
+
declare function createAnalyticsHandler(options: AnalyticsHandlerOptions): (request: NextRequest) => Promise<NextResponse>;
|
|
825
|
+
/**
|
|
826
|
+
* Create a Pages Router API handler for analytics
|
|
827
|
+
*/
|
|
828
|
+
declare function createAnalyticsPageHandler(options: AnalyticsHandlerOptions): (req: {
|
|
829
|
+
method?: string;
|
|
830
|
+
body?: unknown;
|
|
831
|
+
headers?: {
|
|
832
|
+
[key: string]: string | string[] | undefined;
|
|
833
|
+
};
|
|
834
|
+
}, res: {
|
|
835
|
+
status: (code: number) => {
|
|
836
|
+
end: (body?: string) => void;
|
|
837
|
+
json: (body: unknown) => void;
|
|
838
|
+
};
|
|
839
|
+
setHeader: (name: string, value: string) => void;
|
|
840
|
+
}) => Promise<void>;
|
|
841
|
+
/**
|
|
842
|
+
* Aggregate analytics events by action type
|
|
843
|
+
*/
|
|
844
|
+
declare function aggregateEvents(storage: AnalyticsStorageAdapter): Promise<Record<string, number>>;
|
|
845
|
+
/**
|
|
846
|
+
* Get events for a specific content ID
|
|
847
|
+
*/
|
|
848
|
+
declare function getEventsForContent(storage: AnalyticsStorageAdapter, contentId: string): Promise<AnalyticsEvent[]>;
|
|
849
|
+
|
|
850
|
+
export { type AnalyticsConfig, type AnalyticsEvent, type AnalyticsHandlerOptions, type AnalyticsStorageAdapter, type CopyAction, CopyButton, type CopyButtonProps, CopyDropdown, type CopyDropdownProps, type DownloadOptions, type DropdownMenuItem, type HTMLToMarkdownOptions, LLMBadge, type LLMBadgeProps, type LLMContent, type LLMReadyConfig, type LLMsTxtConfig, type LLMsTxtHandlerOptions, type LLMsTxtItem, type MarkdownHandlerOptions, type MarkdownOutput, TOC, type TOCHeading, TOCMobile, type TOCProps, type ThemeConfig, type UseAnalyticsOptions, type UseAnalyticsReturn, type UseLLMCopyOptions, type UseLLMCopyReturn, type UseTOCOptions, type UseTOCReturn, aggregateEvents, buildNestedTOC, contentToPlainText, copyToClipboard, createAnalyticsHandler, createAnalyticsPageHandler, createAnalyticsTracker, createInMemoryStorage, createLLMsTxtHandler, createLLMsTxtPageHandler, createMarkdownHandler, downloadAsFile, generateLLMsTxt, generateMarkdown, generateMarkdownString, getEventsForContent, hasLLMParam, htmlToMarkdown, useAnalytics, useLLMCopy, useTOC, useTOCKeyboard, withLLMParam };
|