Files
upstream-tldraw/apps/docs/scripts/lib/generateLllmsTxt.ts
upstream-mirror a774ac673a
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
2026-09-23 16:12:52 +05:00

140 lines
4.5 KiB
TypeScript

import fs from 'fs'
import path from 'path'
import { Database } from 'sqlite'
import sqlite3 from 'sqlite3'
import { EXAMPLES_CATEGORIES } from './generateExamplesContent'
import { PUBLIC_DIR } from './utils'
type DbType = Database<sqlite3.Database, sqlite3.Statement>
export async function generateLlmsTxt(db: DbType) {
const overviewMarkdown = await getMarkdownForOverview(db)
const examplesMarkdown = await getMarkdownForExamples(db)
const docsMarkdown = await getMarkdownForDocs(db)
const releasesMarkdown = await getMarkdownForReleases(db)
fs.writeFileSync(path.join(PUBLIC_DIR, 'llms.txt'), overviewMarkdown)
fs.writeFileSync(
path.join(PUBLIC_DIR, 'llms-full.txt'),
`${docsMarkdown}\n--------------------------------\n\n${releasesMarkdown}\n--------------------------------\n\n${examplesMarkdown}`
)
fs.writeFileSync(path.join(PUBLIC_DIR, 'llms-examples.txt'), examplesMarkdown)
fs.writeFileSync(path.join(PUBLIC_DIR, 'llms-docs.txt'), docsMarkdown)
fs.writeFileSync(path.join(PUBLIC_DIR, 'llms-releases.txt'), releasesMarkdown)
}
async function getMarkdownForOverview(db: DbType) {
let result = `# tldraw SDK\n\n`
const features = await db.all('SELECT * FROM articles WHERE sectionId = "sdk-features"')
// sectionIndex carries the version order generateSection worked out for the sidebar; sorting
// by id would be a string sort that puts v3.9.0 above v3.10.0
const releases = await db.all(
`SELECT * FROM articles WHERE sectionId = "releases" AND id NOT LIKE '%/next' ORDER BY sectionIndex ASC`
)
const examples = await db.all('SELECT * FROM articles WHERE sectionId = "examples"')
result += `## SDK features\n\n`
for (const feature of features) {
result += `- [${feature.title}](https://tldraw.dev${feature.path})\n`
}
result += `\n## Releases\n\n`
for (const release of releases) {
result += `- [${release.title}](https://tldraw.dev${release.path})\n`
}
result += `\n## Examples\n\n`
for (const example of examples) {
result += `- [${example.title}](https://tldraw.dev${example.path})\n`
}
result += `\n## Markdown exports of resources\n`
result += `\n- [All SDK features, releases, and examples](https://tldraw.dev/llms-full.txt)`
result += `\n- [SDK features only](https://tldraw.dev/llms-docs.txt)`
result += `\n- [Releases only](https://tldraw.dev/llms-releases.txt)`
result += `\n- [Examples only](https://tldraw.dev/llms-examples.txt)`
return result
}
async function getMarkdownForDocs(db: DbType) {
let result = `# tldraw SDK features\n`
const features = await db.all('SELECT * FROM articles WHERE sectionId = "sdk-features"')
for (const feature of features) {
result += `\n--------\n`
result += `\n# ${feature.title}\n\n${feature.content.trim()}\n`
}
return result
}
async function getMarkdownForReleases(db: DbType) {
let result = `# tldraw SDK releases\n`
const releases = await db.all(
`SELECT * FROM articles WHERE sectionId = "releases" AND id NOT LIKE '%/next' ORDER BY sectionIndex ASC`
)
for (const release of releases) {
result += `\n--------\n`
result += `\n# ${release.title}\n\n${release.content.trim()}\n`
}
return result
}
async function getMarkdownForExamples(db: DbType) {
const examples = await db.all('SELECT * FROM articles WHERE sectionId = "examples"')
// Sort examples by category
const categories = EXAMPLES_CATEGORIES.map((category) => {
return {
id: category.id,
title: category.title,
examples: examples.filter((example) => example.categoryId === category.id),
}
})
let result = `# tldraw SDK Examples`
for (const category of categories) {
for (const example of category.examples) {
result += `\n\n--------`
result += `\n\n# ${example.title}`
result += `\n\nCategory: ${category.title}`
result += `\n\nKeywords: ${example.keywords.trim()}`
if (example.description?.trim()) {
result += `\n\n${example.description.trim()}`
}
result += `\n\n${example.content.trim()}`
result += getMarkdownForFile('App.tsx', example.componentCode)
const files = JSON.parse(example.componentCodeFiles)
for (const name in files) {
result += getMarkdownForFile(name, files[name])
}
}
}
return result
}
const ALLOWED_FILE_TYPES = ['tsx', 'ts', 'js', 'jsx', 'md', 'css', 'html']
function getMarkdownForFile(fileName: string, fileContent: string) {
const type = fileName.split('.').pop()
// Skip non-code files, eg: PDFs, PNGs, SVGs (which generateSection does collect)
if (!ALLOWED_FILE_TYPES.includes(type ?? '')) {
return ''
}
let result = `\n\n## ${fileName}`
result += `\n\n\`\`\`${type}`
result += `\n${fileContent.trim()}`
result += `\n\`\`\``
return result
}