* Parse llms.txt to get documentation entries.
(llmsTxtPath)
| 250 | * Parse llms.txt to get documentation entries. |
| 251 | */ |
| 252 | function parseLlmsTxt(llmsTxtPath) { |
| 253 | const content = fs.readFileSync(llmsTxtPath, 'utf8'); |
| 254 | const entries = []; |
| 255 | const tree = unified().use(remarkParse).parse(content); |
| 256 | |
| 257 | const toText = node => { |
| 258 | if (!node) { |
| 259 | return ''; |
| 260 | } |
| 261 | if (node.type === 'text') { |
| 262 | return node.value; |
| 263 | } |
| 264 | if (node.type === 'inlineCode') { |
| 265 | return '`' + node.value + '`'; |
| 266 | } |
| 267 | if (Array.isArray(node.children)) { |
| 268 | return node.children.map(toText).join(''); |
| 269 | } |
| 270 | return ''; |
| 271 | }; |
| 272 | |
| 273 | const extractEntry = listItem => { |
| 274 | const paragraph = listItem.children?.find(child => child.type === 'paragraph'); |
| 275 | if (!paragraph || !Array.isArray(paragraph.children)) { |
| 276 | return null; |
| 277 | } |
| 278 | |
| 279 | const linkIndex = paragraph.children.findIndex(child => child.type === 'link'); |
| 280 | if (linkIndex === -1) { |
| 281 | return null; |
| 282 | } |
| 283 | |
| 284 | const link = paragraph.children[linkIndex]; |
| 285 | const title = toText(link).trim(); |
| 286 | const entryPath = link.url; |
| 287 | if (!title || !entryPath) { |
| 288 | return null; |
| 289 | } |
| 290 | |
| 291 | let description = paragraph.children |
| 292 | .slice(linkIndex + 1) |
| 293 | .map(toText) |
| 294 | .join('') |
| 295 | .trim(); |
| 296 | |
| 297 | if (description.startsWith(':')) { |
| 298 | description = description.slice(1).trim(); |
| 299 | } |
| 300 | |
| 301 | return { |
| 302 | title, |
| 303 | path: entryPath, |
| 304 | description |
| 305 | }; |
| 306 | }; |
| 307 | |
| 308 | const walk = node => { |
| 309 | if (!node || !Array.isArray(node.children)) { |
no test coverage detected