|
1 | | -import { dev } from '$app/environment'; |
2 | 1 | import { read } from '$app/server'; |
3 | 2 | import type { Document } from '@sveltejs/site-kit'; |
4 | 3 | import { create_index } from '@sveltejs/site-kit/server/content'; |
5 | | -import { minimatch } from 'minimatch'; |
6 | 4 |
|
7 | 5 | const documents = import.meta.glob<string>('../../../content/**/*.md', { |
8 | 6 | eager: true, |
@@ -127,191 +125,3 @@ function create_docs() { |
127 | 125 |
|
128 | 126 | export const docs = create_docs(); |
129 | 127 | export const examples = index.examples.children; |
130 | | - |
131 | | -export const packages = Object.keys(docs.topics).map((topic) => topic.split('/')[1]); |
132 | | - |
133 | | -export const DOCUMENTATION_NAMES: Record<string, string> = { |
134 | | - svelte: 'Svelte', |
135 | | - kit: 'SvelteKit', |
136 | | - cli: 'Svelte CLI' |
137 | | -}; |
138 | | - |
139 | | -export function get_documentation_title(type: string): string { |
140 | | - return `This is the developer documentation for ${DOCUMENTATION_NAMES[type]}.`; |
141 | | -} |
142 | | - |
143 | | -export function get_documentation_start_title(type: string): string { |
144 | | - return `# Start of ${DOCUMENTATION_NAMES[type]} documentation`; |
145 | | -} |
146 | | - |
147 | | -interface MinimizeOptions { |
148 | | - removeLegacy: boolean; |
149 | | - removeNoteBlocks: boolean; |
150 | | - removeDetailsBlocks: boolean; |
151 | | - removePlaygroundLinks: boolean; |
152 | | - removePrettierIgnore: boolean; |
153 | | - normalizeWhitespace: boolean; |
154 | | -} |
155 | | - |
156 | | -const defaultOptions: MinimizeOptions = { |
157 | | - removeLegacy: false, |
158 | | - removeNoteBlocks: false, |
159 | | - removeDetailsBlocks: false, |
160 | | - removePlaygroundLinks: false, |
161 | | - removePrettierIgnore: false, |
162 | | - normalizeWhitespace: false |
163 | | -}; |
164 | | - |
165 | | -function remove_quote_blocks(content: string, blockType: string): string { |
166 | | - return content |
167 | | - .split('\n') |
168 | | - .reduce((acc: string[], line: string, index: number, lines: string[]) => { |
169 | | - // If we find a block (with or without additional text), skip it and all subsequent blockquote lines |
170 | | - if (line.trim().startsWith(`> [!${blockType}]`)) { |
171 | | - // Skip all subsequent lines that are part of the blockquote |
172 | | - let i = index; |
173 | | - while (i < lines.length && (lines[i].startsWith('>') || lines[i].trim() === '')) { |
174 | | - i++; |
175 | | - } |
176 | | - // Update the index to skip all these lines |
177 | | - index = i - 1; |
178 | | - return acc; |
179 | | - } |
180 | | - |
181 | | - // Only add the line if it's not being skipped |
182 | | - acc.push(line); |
183 | | - return acc; |
184 | | - }, []) |
185 | | - .join('\n'); |
186 | | -} |
187 | | - |
188 | | -function minimize_content(content: string, options?: Partial<MinimizeOptions>): string { |
189 | | - // Merge with defaults, but only for properties that are defined |
190 | | - const settings: MinimizeOptions = options ? { ...defaultOptions, ...options } : defaultOptions; |
191 | | - |
192 | | - let minimized = content; |
193 | | - |
194 | | - if (settings.removeLegacy) { |
195 | | - minimized = remove_quote_blocks(minimized, 'LEGACY'); |
196 | | - } |
197 | | - |
198 | | - if (settings.removeNoteBlocks) { |
199 | | - minimized = remove_quote_blocks(minimized, 'NOTE'); |
200 | | - } |
201 | | - |
202 | | - if (settings.removeDetailsBlocks) { |
203 | | - minimized = remove_quote_blocks(minimized, 'DETAILS'); |
204 | | - } |
205 | | - |
206 | | - if (settings.removePlaygroundLinks) { |
207 | | - // Replace playground URLs with /[link] but keep the original link text |
208 | | - minimized = minimized.replace(/\[([^\]]+)\]\(\/playground[^)]+\)/g, '[$1](/REMOVED)'); |
209 | | - } |
210 | | - |
211 | | - if (settings.removePrettierIgnore) { |
212 | | - minimized = minimized |
213 | | - .split('\n') |
214 | | - .filter((line) => line.trim() !== '<!-- prettier-ignore -->') |
215 | | - .join('\n'); |
216 | | - } |
217 | | - |
218 | | - if (settings.normalizeWhitespace) { |
219 | | - minimized = minimized.replace(/\s+/g, ' '); |
220 | | - } |
221 | | - |
222 | | - minimized = minimized.trim(); |
223 | | - |
224 | | - return minimized; |
225 | | -} |
226 | | - |
227 | | -function should_include_file_llm_docs(filename: string, ignore: string[] = []): boolean { |
228 | | - const shouldIgnore = ignore.some((pattern) => minimatch(filename, pattern)); |
229 | | - if (shouldIgnore) { |
230 | | - if (dev) console.log(`❌ Ignored by pattern: ${filename}`); |
231 | | - return false; |
232 | | - } |
233 | | - |
234 | | - return true; |
235 | | -} |
236 | | - |
237 | | -interface GenerateLlmContentOptions { |
238 | | - prefix?: string; |
239 | | - ignore?: string[]; |
240 | | - minimize?: Partial<MinimizeOptions>; |
241 | | - package?: string; |
242 | | -} |
243 | | - |
244 | | -export function generate_llm_content(options: GenerateLlmContentOptions = {}): string { |
245 | | - const { prefix, ignore = [], minimize: minimizeOptions, package: pkg } = options; |
246 | | - |
247 | | - let content = ''; |
248 | | - if (prefix) { |
249 | | - content = `${prefix}\n\n`; |
250 | | - } |
251 | | - |
252 | | - let current_section = ''; |
253 | | - const paths = sort_documentation_paths(); |
254 | | - |
255 | | - for (const path of paths) { |
256 | | - if (!should_include_file_llm_docs(path, ignore)) continue; |
257 | | - |
258 | | - // If a specific package is provided, only include its docs |
259 | | - if (pkg) { |
260 | | - if (!path.includes(`docs/${pkg}/`)) continue; |
261 | | - } else { |
262 | | - // For combined content, only include paths that match any package |
263 | | - const doc_type = packages.find((p) => path.includes(`docs/${p}/`)); |
264 | | - if (!doc_type) continue; |
265 | | - |
266 | | - const section = get_documentation_start_title(doc_type); |
267 | | - if (section !== current_section) { |
268 | | - if (current_section) content += '\n'; |
269 | | - content += `${section}\n\n`; |
270 | | - current_section = section; |
271 | | - } |
272 | | - } |
273 | | - |
274 | | - const docContent = minimizeOptions |
275 | | - ? minimize_content(index[path].body, minimizeOptions) |
276 | | - : index[path].body; |
277 | | - if (docContent.trim() === '') continue; |
278 | | - |
279 | | - content += `\n# ${index[path].metadata.title}\n\n`; |
280 | | - content += docContent; |
281 | | - content += '\n'; |
282 | | - } |
283 | | - |
284 | | - return content; |
285 | | -} |
286 | | - |
287 | | -function get_documentation_section_priority(path: string): number { |
288 | | - if (path.includes('docs/svelte/')) return 0; |
289 | | - if (path.includes('docs/kit/')) return 1; |
290 | | - if (path.includes('docs/cli/')) return 2; |
291 | | - return 3; |
292 | | -} |
293 | | - |
294 | | -function sort_documentation_paths(): string[] { |
295 | | - return Object.keys(index).sort((a, b) => { |
296 | | - a = index[a].file; |
297 | | - b = index[b].file; |
298 | | - // First compare by section priority |
299 | | - const priorityA = get_documentation_section_priority(a); |
300 | | - const priorityB = get_documentation_section_priority(b); |
301 | | - if (priorityA !== priorityB) return priorityA - priorityB; |
302 | | - |
303 | | - // Get directory paths |
304 | | - const dirA = a.split('/').slice(0, -1).join('/'); |
305 | | - const dirB = b.split('/').slice(0, -1).join('/'); |
306 | | - |
307 | | - // If in the same directory, prioritize index.md |
308 | | - if (dirA === dirB) { |
309 | | - if (a.endsWith('index.md')) return -1; |
310 | | - if (b.endsWith('index.md')) return 1; |
311 | | - return a.localeCompare(b); |
312 | | - } |
313 | | - |
314 | | - // Otherwise sort by directory path |
315 | | - return dirA.localeCompare(dirB); |
316 | | - }); |
317 | | -} |
0 commit comments