diff --git a/apps/docs/e2e/Navigation.cy.res b/apps/docs/e2e/Navigation.cy.res index 5bb185a91..674e4a751 100644 --- a/apps/docs/e2e/Navigation.cy.res +++ b/apps/docs/e2e/Navigation.cy.res @@ -15,15 +15,21 @@ let waitForHydration = () => { // re-query from the DOM root on each retry. let clickNavLink = (~testId, ~text) => { - get(`[data-testid="${testId}"] a:visible`) - ->containsChainable(text) + getByTestId(testId) + ->should("be.visible") + ->containsSelectorChainable("a", text) + ->scrollIntoView + ->should("be.visible") ->click ->ignore } let clickMobileNavLink = text => { - get(`[data-testid="mobile-nav"] a:visible`) - ->containsChainable(text) + getByTestId("mobile-nav") + ->should("be.visible") + ->containsSelectorChainable("a", text) + ->scrollIntoView + ->should("be.visible") ->click ->ignore } diff --git a/apps/docs/markdown-pages/docs/manual/llms.mdx b/apps/docs/markdown-pages/docs/manual/llms.mdx index df59645c2..687827fc9 100644 --- a/apps/docs/markdown-pages/docs/manual/llms.mdx +++ b/apps/docs/markdown-pages/docs/manual/llms.mdx @@ -10,15 +10,15 @@ order: 4 We adhere to the [llms.txt convention](https://llmstxt.org/) to make documentation accessible to large language models and their applications. -This ReScript manual major version: `v12 (current version)`. +## Files -The root `/llms.txt` file is the default entry point and always describes the current stable manual. Use the files under `/llms/manual/v13/` (pre-release version) or `/llms/manual/v12/` (current version) when you want an explicit major-version path. These major-version paths use the latest generated documentation for that major version and avoid full patch numbers in the URL. - -## Default Current Files - -- [/llms.txt](/llms.txt) - a list of the available files for the current ReScript language manual. -- [/llms/manual/llm-full.txt](/llms/manual/llm-full.txt) - complete current documentation for the ReScript language. -- [/llms/manual/llm-small.txt](/llms/manual/llm-small.txt) - abridged current documentation without detailed examples. +- [/llms.txt](/llms.txt) - a list of the available files for the ReScript language manual. +- [/llms/manual/llm-full.txt](/llms/manual/llm-full.txt) - complete documentation for the ReScript language. +- [/llms/manual/llm-small.txt](/llms/manual/llm-small.txt) - abridged documentation without detailed examples. +- [/llms/manual/language-overview/llm.txt](/llms/manual/language-overview/llm.txt) - focused documentation for ReScript syntax and core language features. +- [/llms/manual/javascript-interop/llm.txt](/llms/manual/javascript-interop/llm.txt) - focused documentation for binding to JavaScript and TypeScript code. +- [/llms/manual/build-system/llm.txt](/llms/manual/build-system/llm.txt) - focused documentation for build configuration, project structure, and build-tool integration. +- [/llms/manual/getting-started/llm.txt](/llms/manual/getting-started/llm.txt) - focused documentation for installation, editor setup, migrations, and JavaScript onboarding. ## Package Documentation @@ -27,12 +27,3 @@ The root `/llms.txt` file is the default entry point and always describes the cu ## Notes - The content is automatically generated from the same source as the official documentation for the specific version. - -## Major Version Files - -- [v13 pre-release LLMs index](/llms/manual/v13/llms.txt) - a list of the available files for the latest ReScript v13 pre-release documentation. -- [v13 pre-release complete documentation](/llms/manual/v13/llm-full.txt) - complete latest ReScript v13 pre-release documentation. -- [v13 pre-release abridged documentation](/llms/manual/v13/llm-small.txt) - abridged latest ReScript v13 pre-release documentation. -- [v12 current LLMs index](/llms/manual/v12/llms.txt) - a list of the available files for the current ReScript v12 documentation. -- [v12 current complete documentation](/llms/manual/v12/llm-full.txt) - complete current ReScript v12 documentation. -- [v12 current abridged documentation](/llms/manual/v12/llm-small.txt) - abridged current ReScript v12 documentation. diff --git a/apps/docs/markdown-pages/docs/react/llms.mdx b/apps/docs/markdown-pages/docs/react/llms.mdx index 1183e93b3..09ed75a2f 100644 --- a/apps/docs/markdown-pages/docs/react/llms.mdx +++ b/apps/docs/markdown-pages/docs/react/llms.mdx @@ -9,23 +9,11 @@ section: "Overview" We adhere to the [llms.txt convention](https://llmstxt.org/) to make documentation accessible to large language models and their applications. -Current ReScript React documentation version: `v0.14.2`. -ReScript React package version: `v0.14.2`. -React version: `v19.2.4`. +## Files -The unversioned files under `/llms/react/` are the default entry points and always describe the current ReScript React docs. Use the versioned files under `/llms/react/v0.14.2/` when you want a stable path for this ReScript React documentation version. - -## Default Current Files - -- [/llms/react/llms.txt](/llms/react/llms.txt) - a list of the available files for the current ReScript React docs. -- [/llms/react/llm-full.txt](/llms/react/llm-full.txt) - complete current documentation for ReScript React. -- [/llms/react/llm-small.txt](/llms/react/llm-small.txt) - abridged current documentation without detailed examples. - -## Versioned Files - -- [/llms/react/v0.14.2/llms.txt](/llms/react/v0.14.2/llms.txt) - a list of the available files for ReScript React `v0.14.2`. -- [/llms/react/v0.14.2/llm-full.txt](/llms/react/v0.14.2/llm-full.txt) - complete documentation for ReScript React `v0.14.2`. -- [/llms/react/v0.14.2/llm-small.txt](/llms/react/v0.14.2/llm-small.txt) - abridged documentation for ReScript React `v0.14.2`. +- [/llms/react/llms.txt](/llms/react/llms.txt) - a list of the available files for ReScript React docs. +- [/llms/react/llm-full.txt](/llms/react/llm-full.txt) - complete documentation for ReScript React. +- [/llms/react/llm-small.txt](/llms/react/llm-small.txt) - abridged documentation without detailed examples. ## Language Documentation diff --git a/apps/docs/public/llms/manual/template.mdx b/apps/docs/public/llms/manual/template.mdx index 389404f95..687827fc9 100644 --- a/apps/docs/public/llms/manual/template.mdx +++ b/apps/docs/public/llms/manual/template.mdx @@ -10,15 +10,15 @@ order: 4 We adhere to the [llms.txt convention](https://llmstxt.org/) to make documentation accessible to large language models and their applications. -This ReScript manual major version: ``. +## Files -The root `/llms.txt` file is the default entry point and always describes the current stable manual. Use the files under `/llms/manual/v13/` (pre-release version) or `/llms/manual/v12/` (current version) when you want an explicit major-version path. These major-version paths use the latest generated documentation for that major version and avoid full patch numbers in the URL. - -## Default Current Files - -- [/llms.txt](/llms.txt) - a list of the available files for the current ReScript language manual. -- [/llms/manual/llm-full.txt](/llms/manual/llm-full.txt) - complete current documentation for the ReScript language. -- [/llms/manual/llm-small.txt](/llms/manual/llm-small.txt) - abridged current documentation without detailed examples. +- [/llms.txt](/llms.txt) - a list of the available files for the ReScript language manual. +- [/llms/manual/llm-full.txt](/llms/manual/llm-full.txt) - complete documentation for the ReScript language. +- [/llms/manual/llm-small.txt](/llms/manual/llm-small.txt) - abridged documentation without detailed examples. +- [/llms/manual/language-overview/llm.txt](/llms/manual/language-overview/llm.txt) - focused documentation for ReScript syntax and core language features. +- [/llms/manual/javascript-interop/llm.txt](/llms/manual/javascript-interop/llm.txt) - focused documentation for binding to JavaScript and TypeScript code. +- [/llms/manual/build-system/llm.txt](/llms/manual/build-system/llm.txt) - focused documentation for build configuration, project structure, and build-tool integration. +- [/llms/manual/getting-started/llm.txt](/llms/manual/getting-started/llm.txt) - focused documentation for installation, editor setup, migrations, and JavaScript onboarding. ## Package Documentation @@ -27,12 +27,3 @@ The root `/llms.txt` file is the default entry point and always describes the cu ## Notes - The content is automatically generated from the same source as the official documentation for the specific version. - -## Major Version Files - -- [v13 pre-release LLMs index](/llms/manual/v13/llms.txt) - a list of the available files for the latest ReScript v13 pre-release documentation. -- [v13 pre-release complete documentation](/llms/manual/v13/llm-full.txt) - complete latest ReScript v13 pre-release documentation. -- [v13 pre-release abridged documentation](/llms/manual/v13/llm-small.txt) - abridged latest ReScript v13 pre-release documentation. -- [v12 current LLMs index](/llms/manual/v12/llms.txt) - a list of the available files for the current ReScript v12 documentation. -- [v12 current complete documentation](/llms/manual/v12/llm-full.txt) - complete current ReScript v12 documentation. -- [v12 current abridged documentation](/llms/manual/v12/llm-small.txt) - abridged current ReScript v12 documentation. diff --git a/apps/docs/public/llms/manual/template.txt b/apps/docs/public/llms/manual/template.txt index c6b24ac7f..e91b13e35 100644 --- a/apps/docs/public/llms/manual/template.txt +++ b/apps/docs/public/llms/manual/template.txt @@ -2,19 +2,17 @@ > ReScript is a robustly typed language that compiles to efficient and human-readable JavaScript. It comes with a lightning fast compiler toolchain that scales to any codebase size. -## Documentation Sets - -This ReScript manual major version: . - -The root `/llms.txt` file is the default entry point and always describes the current stable manual. Use the files under `/llms/manual/v13/` (pre-release version) or `/llms/manual/v12/` (current version) when you want an explicit major-version path. These major-version paths use the latest generated documentation for that major version and avoid full patch numbers in the URL. - -### Default Current Files +## Files - [LLMs index](https://rescript-lang.org/llms.txt): This file -- [Complete current documentation](https://rescript-lang.org/llms/manual/llm-full.txt): The complete current ReScript documentation including all examples and additional content -- [Abridged current documentation](https://rescript-lang.org/llms/manual/llm-small.txt): A minimal current version of the ReScript documentation, with the essential content for quick reference +- [Complete documentation](https://rescript-lang.org/llms/manual/llm-full.txt): The complete ReScript documentation including all examples and additional content +- [Abridged documentation](https://rescript-lang.org/llms/manual/llm-small.txt): A minimal ReScript documentation file with the essential content for quick reference +- [Language overview](https://rescript-lang.org/llms/manual/language-overview/llm.txt): Focused documentation for ReScript syntax and core language features +- [JavaScript interop](https://rescript-lang.org/llms/manual/javascript-interop/llm.txt): Focused documentation for binding to JavaScript and TypeScript code +- [Build system](https://rescript-lang.org/llms/manual/build-system/llm.txt): Focused documentation for build configuration, project structure, and build-tool integration +- [Getting started](https://rescript-lang.org/llms/manual/getting-started/llm.txt): Focused documentation for installation, editor setup, migrations, and JavaScript onboarding -## Individual Package Documentation +## Package Documentation - [ReScript React documentation](https://rescript-lang.org/llms/react/llms.txt): This is the developer documentation for ReScript React. @@ -24,7 +22,3 @@ The root `/llms.txt` file is the default entry point and always describes the cu - The complete documentation includes all content from the official documentation - Package-specific documentation files contain only the content relevant to that package - The content is automatically generated from the same source as the official documentation for the specific version - -### Major Version Files - - diff --git a/apps/docs/public/llms/react/template.mdx b/apps/docs/public/llms/react/template.mdx index ba61e3f05..09ed75a2f 100644 --- a/apps/docs/public/llms/react/template.mdx +++ b/apps/docs/public/llms/react/template.mdx @@ -9,23 +9,11 @@ section: "Overview" We adhere to the [llms.txt convention](https://llmstxt.org/) to make documentation accessible to large language models and their applications. -Current ReScript React documentation version: ``. -ReScript React package version: ``. -React version: ``. +## Files -The unversioned files under `/llms/react/` are the default entry points and always describe the current ReScript React docs. Use the versioned files under `/llms/react//` when you want a stable path for this ReScript React documentation version. - -## Default Current Files - -- [/llms/react/llms.txt](/llms/react/llms.txt) - a list of the available files for the current ReScript React docs. -- [/llms/react/llm-full.txt](/llms/react/llm-full.txt) - complete current documentation for ReScript React. -- [/llms/react/llm-small.txt](/llms/react/llm-small.txt) - abridged current documentation without detailed examples. - -## Versioned Files - -- [/llms/react//llms.txt](/llms/react//llms.txt) - a list of the available files for ReScript React ``. -- [/llms/react//llm-full.txt](/llms/react//llm-full.txt) - complete documentation for ReScript React ``. -- [/llms/react//llm-small.txt](/llms/react//llm-small.txt) - abridged documentation for ReScript React ``. +- [/llms/react/llms.txt](/llms/react/llms.txt) - a list of the available files for ReScript React docs. +- [/llms/react/llm-full.txt](/llms/react/llm-full.txt) - complete documentation for ReScript React. +- [/llms/react/llm-small.txt](/llms/react/llm-small.txt) - abridged documentation without detailed examples. ## Language Documentation diff --git a/apps/docs/public/llms/react/template.txt b/apps/docs/public/llms/react/template.txt index 8da45a75d..d6c06b45e 100644 --- a/apps/docs/public/llms/react/template.txt +++ b/apps/docs/public/llms/react/template.txt @@ -2,25 +2,11 @@ > ReScript React is a strongly typed interface for React, designed to integrate seamlessly with modern React (>= v18.0) while compiling to idiomatic JavaScript, enabling robust and scalable React applications. -## ReScript React Documentation - -Current ReScript React documentation version: . -ReScript React package version: . -React version: . - -The unversioned files under `/llms/react/` are the default entry points and always describe the current ReScript React docs. Use the versioned files under `/llms/react//` when you want a stable path for this ReScript React documentation version. - -### Default Current Files +## Files - [LLMs index](https://rescript-lang.org/llms/react/llms.txt): This file -- [Complete current documentation](https://rescript-lang.org/llms/react/llm-full.txt): The complete current ReScript React documentation including all examples and additional content -- [Abridged current documentation](https://rescript-lang.org/llms/react/llm-small.txt): A minimal current version of the ReScript React documentation, with the essential content for quick reference - -### Versioned Files - -- [ LLMs index](https://rescript-lang.org/llms/react//llms.txt): This file for ReScript React -- [ complete documentation](https://rescript-lang.org/llms/react//llm-full.txt): The complete ReScript React documentation including all examples and additional content -- [ abridged documentation](https://rescript-lang.org/llms/react//llm-small.txt): A minimal ReScript React reference with the essential content +- [Complete documentation](https://rescript-lang.org/llms/react/llm-full.txt): The complete ReScript React documentation including all examples and additional content +- [Abridged documentation](https://rescript-lang.org/llms/react/llm-small.txt): A minimal ReScript React documentation file with the essential content for quick reference ## Language Documentation diff --git a/apps/docs/scripts/__tests__/generate-llms.test.mjs b/apps/docs/scripts/__tests__/generate-llms.test.mjs index 3b6b22c6c..a945479cd 100644 --- a/apps/docs/scripts/__tests__/generate-llms.test.mjs +++ b/apps/docs/scripts/__tests__/generate-llms.test.mjs @@ -25,6 +25,8 @@ let makeWorkspace = () => { "markdown-pages/docs/manual/introduction.mdx", `--- title: "Introduction" +section: "Overview" +order: 1 --- # Manual Introduction @@ -35,6 +37,51 @@ let answer = 42 `, ); + writeFile( + root, + "markdown-pages/docs/manual/overview.mdx", + `--- +title: "Language Overview" +section: "Language Features" +order: 1 +--- + +# Language Overview + +Language feature content. +`, + ); + + writeFile( + root, + "markdown-pages/docs/manual/bind-to-js-function.mdx", + `--- +title: "Bind to JS Function" +section: "JavaScript Interop" +order: 1 +--- + +# Bind to JS Function + +JavaScript interop content. +`, + ); + + writeFile( + root, + "markdown-pages/docs/manual/build-overview.mdx", + `--- +title: "Build Overview" +section: "Build System" +order: 1 +--- + +# Build Overview + +Build system content. +`, + ); + writeFile( root, "markdown-pages/docs/react/introduction.mdx", @@ -51,12 +98,14 @@ title: "React Introduction" "public/llms/manual/template.txt", `# Manual LLMs -Current version: -Version label: +## Files -- [Complete documentation](https://rescript-lang.org/llms/manual//llm-full.txt) -- [Abridged documentation](https://rescript-lang.org/llms/manual//llm-small.txt) - +- [Complete documentation](https://rescript-lang.org/llms/manual/llm-full.txt) +- [Abridged documentation](https://rescript-lang.org/llms/manual/llm-small.txt) +- [Language overview](https://rescript-lang.org/llms/manual/language-overview/llm.txt) +- [JavaScript interop](https://rescript-lang.org/llms/manual/javascript-interop/llm.txt) +- [Build system](https://rescript-lang.org/llms/manual/build-system/llm.txt) +- [Getting started](https://rescript-lang.org/llms/manual/getting-started/llm.txt) `, ); writeFile(root, "public/llms/manual/llms.txt", "stale manual index"); @@ -66,14 +115,42 @@ Version label: writeFile(root, "public/llms/manual/v11/llms.txt", "stale v11 index"); writeFile(root, "public/llms/manual/v11/llm-full.txt", "stale v11 full"); writeFile(root, "public/llms/manual/v11/llm-small.txt", "stale v11 small"); + writeFile(root, "public/llms/manual/v12/llms.txt", "stale v12 index"); + writeFile(root, "public/llms/manual/v12/llm-full.txt", "stale v12 full"); + writeFile(root, "public/llms/manual/v12/llm-small.txt", "stale v12 small"); + writeFile( + root, + "public/llms/manual/v12/language-overview/llm.txt", + "stale v12 language overview", + ); + writeFile(root, "public/llms/manual/v13/llms.txt", "stale v13 index"); + writeFile(root, "public/llms/manual/v13/llm-full.txt", "stale v13 full"); + writeFile(root, "public/llms/manual/v13/llm-small.txt", "stale v13 small"); + writeFile( + root, + "public/llms/manual/v13/language-overview/llm.txt", + "stale v13 language overview", + ); writeFile( root, "public/llms/manual/template.mdx", - `# Manual LLMs + `--- +title: "LLMs" +section: "Overview" +order: 4 +--- -- [/llms/manual//llm-full.txt](/llms/manual//llm-full.txt) -- [/llms/manual//llm-small.txt](/llms/manual//llm-small.txt) +# Manual LLMs + +## Files + +- [/llms/manual/llm-full.txt](/llms/manual/llm-full.txt) +- [/llms/manual/llm-small.txt](/llms/manual/llm-small.txt) +- [/llms/manual/language-overview/llm.txt](/llms/manual/language-overview/llm.txt) +- [/llms/manual/javascript-interop/llm.txt](/llms/manual/javascript-interop/llm.txt) +- [/llms/manual/build-system/llm.txt](/llms/manual/build-system/llm.txt) +- [/llms/manual/getting-started/llm.txt](/llms/manual/getting-started/llm.txt) `, ); @@ -82,12 +159,10 @@ Version label: "public/llms/react/template.txt", `# React LLMs -Current version: -ReScript React package version: -React version: +## Files -- [Complete documentation](https://rescript-lang.org/llms/react//llm-full.txt) -- [Abridged documentation](https://rescript-lang.org/llms/react//llm-small.txt) +- [Complete documentation](https://rescript-lang.org/llms/react/llm-full.txt) +- [Abridged documentation](https://rescript-lang.org/llms/react/llm-small.txt) `, ); @@ -96,10 +171,34 @@ React version: "public/llms/react/template.mdx", `# React LLMs -- [/llms/react//llm-full.txt](/llms/react//llm-full.txt) -- [/llms/react//llm-small.txt](/llms/react//llm-small.txt) +## Files + +- [/llms/react/llm-full.txt](/llms/react/llm-full.txt) +- [/llms/react/llm-small.txt](/llms/react/llm-small.txt) `, ); + writeFile( + root, + "public/llms/react/v0.14.2/llms.txt", + "stale react versioned index", + ); + writeFile( + root, + "public/llms/react/v0.14.2/llm-full.txt", + "stale react versioned full", + ); + writeFile( + root, + "public/llms/react/v0.14.2/llm-small.txt", + "stale react versioned small", + ); + writeFile(root, "public/llms/react/latest/llms.txt", "stale latest index"); + writeFile(root, "public/llms/react/latest/llm-full.txt", "stale latest full"); + writeFile( + root, + "public/llms/react/latest/llm-small.txt", + "stale latest small", + ); return root; }; @@ -107,17 +206,6 @@ React version: let readFile = (root, filePath) => fs.readFileSync(path.join(root, filePath), "utf8"); -let assertOccursInOrder = (content, parts) => { - let lastIndex = -1; - - for (let part of parts) { - let index = content.indexOf(part); - assert.notEqual(index, -1); - assert.ok(index > lastIndex); - lastIndex = index; - } -}; - test("generate_llms writes the default manual index at the site root", () => { let root = makeWorkspace(); @@ -127,26 +215,75 @@ test("generate_llms writes the default manual index at the site root", () => { }); let currentLlms = readFile(root, "public/llms.txt"); - let versionedLlms = readFile(root, "public/llms/manual/v12/llms.txt"); - let preReleaseLlms = readFile(root, "public/llms/manual/v13/llms.txt"); - let manualVersions = ["v12", "v13"]; + let humanLlmsPage = readFile(root, "markdown-pages/docs/manual/llms.mdx"); + let languageOverview = readFile( + root, + "public/llms/manual/language-overview/llm.txt", + ); + let javascriptInterop = readFile( + root, + "public/llms/manual/javascript-interop/llm.txt", + ); + let buildSystem = readFile(root, "public/llms/manual/build-system/llm.txt"); + let gettingStarted = readFile( + root, + "public/llms/manual/getting-started/llm.txt", + ); assert.doesNotMatch(currentLlms, //); assert.doesNotMatch(currentLlms, //); - assert.match(currentLlms, /Current version: v12/); - assert.match(currentLlms, /Version label: v12 \(current version\)/); - assert.match(currentLlms, /v12 current/i); - assert.match(currentLlms, /v13 pre-release/i); + assert.doesNotMatch(currentLlms, /Current version/i); + assert.doesNotMatch(currentLlms, /Version label/i); + assert.doesNotMatch(currentLlms, /Default Current Files/i); + assert.doesNotMatch(currentLlms, /default entry point/i); + assert.doesNotMatch(humanLlmsPage, /This ReScript manual major version/i); + assert.doesNotMatch(humanLlmsPage, /Default Current Files/i); + assert.doesNotMatch(humanLlmsPage, /default entry point/i); + assert.doesNotMatch(humanLlmsPage, /## Versioned Files/); + assert.match( + currentLlms, + /https:\/\/rescript-lang\.org\/llms\/manual\/llm-full\.txt/, + ); + assert.match( + currentLlms, + /https:\/\/rescript-lang\.org\/llms\/manual\/llm-small\.txt/, + ); + assert.match( + currentLlms, + /https:\/\/rescript-lang\.org\/llms\/manual\/language-overview\/llm\.txt/, + ); assert.match( currentLlms, - /https:\/\/rescript-lang\.org\/llms\/manual\/v12\/llm-full\.txt/, + /https:\/\/rescript-lang\.org\/llms\/manual\/javascript-interop\/llm\.txt/, ); assert.match( currentLlms, - /https:\/\/rescript-lang\.org\/llms\/manual\/v12\/llm-small\.txt/, + /https:\/\/rescript-lang\.org\/llms\/manual\/build-system\/llm\.txt/, ); + assert.match( + currentLlms, + /https:\/\/rescript-lang\.org\/llms\/manual\/getting-started\/llm\.txt/, + ); + assert.doesNotMatch(currentLlms, /\/llms\/manual\/v12\//); + assert.doesNotMatch(currentLlms, /\/llms\/manual\/v13\//); assert.doesNotMatch(currentLlms, /\/llms\/manual\/v10\//); assert.doesNotMatch(currentLlms, /\/llms\/manual\/v11\//); + assert.doesNotMatch(humanLlmsPage, /\/llms\/manual\/v13\//); + assert.doesNotMatch(humanLlmsPage, /\/llms\/manual\/v12\//); + assert.match(languageOverview, /# ReScript Language Overview/); + assert.match(languageOverview, /Language feature content/); + assert.doesNotMatch(languageOverview, /JavaScript interop content/); + assert.doesNotMatch(languageOverview, /Manual Introduction/); + assert.match(javascriptInterop, /# ReScript JavaScript Interop/); + assert.match(javascriptInterop, /JavaScript interop content/); + assert.doesNotMatch(javascriptInterop, /Language feature content/); + assert.match(buildSystem, /# ReScript Build System/); + assert.match(buildSystem, /Build system content/); + assert.doesNotMatch(buildSystem, /Manual Introduction/); + assert.match(gettingStarted, /# ReScript Getting Started/); + assert.match(gettingStarted, /Manual Introduction/); + assert.doesNotMatch(gettingStarted, /Manual LLMs/); + assert.doesNotMatch(gettingStarted, /Build system content/); assert.equal( fs.existsSync(path.join(root, "public/llms/manual/llms.txt")), @@ -176,41 +313,38 @@ test("generate_llms writes the default manual index at the site root", () => { fs.existsSync(path.join(root, "public/llms/manual/v11/llm-small.txt")), false, ); - assert.equal(versionedLlms, currentLlms); - assert.match(preReleaseLlms, /Version label: v13 \(pre-release version\)/); - - for (let version of manualVersions) { - assert.match( - currentLlms, - new RegExp( - `https://rescript-lang\\.org/llms/manual/${version}/llm-full\\.txt`, - ), + for (let version of ["v12", "v13"]) { + assert.equal( + fs.existsSync(path.join(root, `public/llms/manual/${version}/llms.txt`)), + false, ); assert.equal( - readFile(root, `public/llms/manual/${version}/llm-full.txt`), - readFile(root, "public/llms/manual/llm-full.txt"), + fs.existsSync( + path.join(root, `public/llms/manual/${version}/llm-full.txt`), + ), + false, ); assert.equal( - readFile(root, `public/llms/manual/${version}/llm-small.txt`), - readFile(root, "public/llms/manual/llm-small.txt"), + fs.existsSync( + path.join(root, `public/llms/manual/${version}/llm-small.txt`), + ), + false, ); - assert.match( - readFile(root, `public/llms/manual/${version}/llms.txt`), - new RegExp(`Current version: ${version}`), + assert.equal( + fs.existsSync( + path.join( + root, + `public/llms/manual/${version}/language-overview/llm.txt`, + ), + ), + false, ); } assert.doesNotMatch(currentLlms, /v10\.|v11\.|v12\.|v13\./); - let majorVersionLinks = currentLlms.slice( - currentLlms.indexOf("v13 pre-release LLMs index"), - ); - assertOccursInOrder(majorVersionLinks, [ - "/llms/manual/v13/llm-full.txt", - "/llms/manual/v12/llm-full.txt", - ]); }); -test("generate_llms writes versioned ReScript React files", () => { +test("generate_llms writes ReScript React files", () => { let root = makeWorkspace(); child_process.execFileSync(process.execPath, [generatorPath], { @@ -219,33 +353,55 @@ test("generate_llms writes versioned ReScript React files", () => { }); let currentLlms = readFile(root, "public/llms/react/llms.txt"); - let versionedLlms = readFile(root, "public/llms/react/v0.14.2/llms.txt"); + let humanLlmsPage = readFile(root, "markdown-pages/docs/react/llms.mdx"); assert.doesNotMatch(currentLlms, //); assert.doesNotMatch(currentLlms, /|/); - assert.match(currentLlms, /Current version: v0\.14\.2/); - assert.match(currentLlms, /ReScript React package version: v0\.14\.2/); - assert.match(currentLlms, /React version: v19\.2\.4/); + assert.doesNotMatch(currentLlms, /Current version/i); + assert.doesNotMatch(currentLlms, /ReScript React package version/i); + assert.doesNotMatch(currentLlms, /React version/i); + assert.doesNotMatch(currentLlms, /Default Current Files/i); + assert.doesNotMatch(currentLlms, /default entry point/i); + assert.doesNotMatch( + humanLlmsPage, + /Current ReScript React documentation version/i, + ); + assert.doesNotMatch(humanLlmsPage, /Default Current Files/i); + assert.doesNotMatch(humanLlmsPage, /default entry point/i); + assert.doesNotMatch(humanLlmsPage, /## Versioned Files/); assert.match( currentLlms, - /https:\/\/rescript-lang\.org\/llms\/react\/v0\.14\.2\/llm-full\.txt/, + /https:\/\/rescript-lang\.org\/llms\/react\/llm-full\.txt/, ); assert.match( currentLlms, - /https:\/\/rescript-lang\.org\/llms\/react\/v0\.14\.2\/llm-small\.txt/, + /https:\/\/rescript-lang\.org\/llms\/react\/llm-small\.txt/, ); + assert.doesNotMatch(currentLlms, /\/llms\/react\/v0\.14\.2\//); + assert.doesNotMatch(humanLlmsPage, /\/llms\/react\/v0\.14\.2\//); assert.equal( fs.existsSync(path.join(root, "public/llms/react/latest/llms.txt")), false, ); - assert.equal(versionedLlms, currentLlms); assert.equal( - readFile(root, "public/llms/react/v0.14.2/llm-full.txt"), - readFile(root, "public/llms/react/llm-full.txt"), + fs.existsSync(path.join(root, "public/llms/react/latest/llm-full.txt")), + false, + ); + assert.equal( + fs.existsSync(path.join(root, "public/llms/react/latest/llm-small.txt")), + false, ); assert.equal( - readFile(root, "public/llms/react/v0.14.2/llm-small.txt"), - readFile(root, "public/llms/react/llm-small.txt"), + fs.existsSync(path.join(root, "public/llms/react/v0.14.2/llms.txt")), + false, + ); + assert.equal( + fs.existsSync(path.join(root, "public/llms/react/v0.14.2/llm-full.txt")), + false, + ); + assert.equal( + fs.existsSync(path.join(root, "public/llms/react/v0.14.2/llm-small.txt")), + false, ); }); diff --git a/apps/docs/scripts/generate_llms.res b/apps/docs/scripts/generate_llms.res index f88cb5cf2..0278caff0 100644 --- a/apps/docs/scripts/generate_llms.res +++ b/apps/docs/scripts/generate_llms.res @@ -32,22 +32,133 @@ let writeTextFile = (filePath: string, content: string): unit => { Node.Fs.writeFileSync(filePath, content, ~encoding="utf8") } -let copyFile = (sourcePath: string, targetPath: string): unit => { - writeTextFile(targetPath, readMarkdownFile(sourcePath)) -} - let removeLlmsTextFiles = (~llmsDirectory: string): unit => { removeFileIfExists(llmsDirectory->Node.Path.join2("llms.txt")) removeFileIfExists(llmsDirectory->Node.Path.join2("llm-full.txt")) removeFileIfExists(llmsDirectory->Node.Path.join2("llm-small.txt")) } -let createDirectoryIfNotExists = (dirPath: string): unit => { +let rec createDirectoryIfNotExists = (dirPath: string): unit => { if !Node.Fs.existsSync(dirPath) { + let parentPath = Node.Path.dirname(dirPath) + if parentPath !== "" && parentPath !== dirPath { + createDirectoryIfNotExists(parentPath) + } Node.Fs.mkdirSync(dirPath) } } +type sectionLlmFile = { + title: string, + slug: string, + section: string, + description: string, + excludedSlugs: array, +} + +type mdxDocument = { + title: string, + slug: string, + section: string, + order: option, + content: string, +} + +let getFrontmatterString = (frontmatter: JSON.t, fieldName: string): string => { + switch frontmatter { + | Object(dict) => + switch dict->Dict.get(fieldName) { + | Some(String(value)) => value + | _ => "" + } + | _ => "" + } +} + +let getFrontmatterNumber = (frontmatter: JSON.t, fieldName: string): option => { + switch frontmatter { + | Object(dict) => + switch dict->Dict.get(fieldName) { + | Some(Number(value)) => Some(value) + | _ => None + } + | _ => None + } +} + +let removeFrontmatter = (content: string): string => { + let regex = RegExp.fromString("^---[\\s\\S]*?---\\s*", ~flags="") + String.replaceRegExp(content, regex, "") +} + +let readMdxDocument = (filePath: string): mdxDocument => { + let rawContent = filePath->readMarkdownFile + let {frontmatter}: MarkdownParser.result = rawContent->MarkdownParser.parseSync + { + title: frontmatter->getFrontmatterString("title"), + slug: filePath->Node.Path.basename->String.replace(".mdx", ""), + section: frontmatter->getFrontmatterString("section"), + order: frontmatter->getFrontmatterNumber("order"), + content: rawContent->removeFrontmatter->String.trim, + } +} + +let compareMdxDocuments = (a: mdxDocument, b: mdxDocument): float => { + switch (a.order, b.order) { + | (Some(orderA), Some(orderB)) => + switch Float.compare(orderA, orderB) { + | 0. => String.compare(a.title, b.title) + | result => result + } + | (Some(_), None) => -1.0 + | (None, Some(_)) => 1.0 + | (None, None) => String.compare(a.title, b.title) + } +} + +let sectionLlmFilePath = (~llmsDirectory: string, sectionFile: sectionLlmFile): string => + llmsDirectory->Node.Path.join2(sectionFile.slug)->Node.Path.join2("llm.txt") + +let createSectionLlmFiles = ( + ~llmsDirectory: string, + ~sectionFiles: array, + ~documents: array, +): unit => { + sectionFiles->Array.forEach(sectionFile => { + let sectionDocuments = + documents->Array.filter(document => + document.section === sectionFile.section && + !(sectionFile.excludedSlugs->Array.some(excludedSlug => excludedSlug === document.slug)) + ) + let content = + sectionDocuments + ->Array.map(document => document.content) + ->Array.join("\n") + ->String.trim + + let filePath = sectionLlmFilePath(~llmsDirectory, sectionFile) + createDirectoryIfNotExists(Node.Path.dirname(filePath)) + writeTextFile( + filePath, + `# ${sectionFile.title} + +${sectionFile.description} + +${content} +`, + ) + }) +} + +let removeSectionLlmFiles = ( + ~llmsDirectory: string, + ~sectionFiles: array, +): unit => { + sectionFiles->Array.forEach(sectionFile => + removeFileIfExists(sectionLlmFilePath(~llmsDirectory, sectionFile)) + ) +} + let removeCodeTabTags = (content: string): string => { let regex = RegExp.fromString("[\\s\\S]*?", ~flags="g") String.replaceRegExp(content, regex, "") @@ -93,32 +204,20 @@ let replacePlaceholder = (content: string, placeholder: string, value: string): String.replaceRegExp(content, regex, value) } -let manualVersionLabel = (version: string): string => { - switch version { - | "v12" => "v12 (current version)" - | "v13" => "v13 (pre-release version)" - | version => version - } -} - let renderTemplate = ( content: string, ~version: string, - ~manualVersionLinks: string, ~rescriptReactVersion: string, ~reactVersion: string, ): string => { content ->replacePlaceholder("", version) - ->replacePlaceholder("", version->manualVersionLabel) - ->replacePlaceholder("", manualVersionLinks) ->replacePlaceholder("", rescriptReactVersion) ->replacePlaceholder("", reactVersion) } let createLlmsFiles = ( ~version: string, - ~manualVersionLinks: string, ~rescriptReactVersion: string, ~reactVersion: string, ~txtFilePath: string, @@ -135,7 +234,6 @@ let createLlmsFiles = ( mdxFilePath, readMarkdownFile(mdxFileTemplatePath)->renderTemplate( ~version, - ~manualVersionLinks, ~rescriptReactVersion, ~reactVersion, ), @@ -145,48 +243,20 @@ let createLlmsFiles = ( txtFilePath, readMarkdownFile(txtFileTemplatePath)->renderTemplate( ~version, - ~manualVersionLinks, ~rescriptReactVersion, ~reactVersion, ), ) } -let copyCurrentFilesToVersion = ( - ~version: string, - ~llmsDirectory: string, - ~fullFilePath: string, - ~smallFilePath: string, - ~manualVersionLinks: string, - ~rescriptReactVersion: string, - ~reactVersion: string, -): unit => { - let versionedLlmsDirectory = llmsDirectory->Node.Path.join2(version) - let txtFileTemplatePath = llmsDirectory->Node.Path.join2("template.txt") - - createDirectoryIfNotExists(versionedLlmsDirectory) - writeTextFile( - versionedLlmsDirectory->Node.Path.join2("llms.txt"), - readMarkdownFile(txtFileTemplatePath)->renderTemplate( - ~version, - ~manualVersionLinks, - ~rescriptReactVersion, - ~reactVersion, - ), - ) - copyFile(fullFilePath, versionedLlmsDirectory->Node.Path.join2("llm-full.txt")) - copyFile(smallFilePath, versionedLlmsDirectory->Node.Path.join2("llm-small.txt")) -} - let generateFile = ( ~currentVersion: string, - ~copyVersions: array, - ~manualVersionLinks: string, ~rescriptReactVersion: string, ~reactVersion: string, ~txtFilePath: string, ~staleTxtFilePath: option=?, ~staleVersions: array, + ~sectionFiles: array=[], docsDirectory: string, llmsDirectory: string, ): unit => { @@ -206,13 +276,14 @@ let generateFile = ( | None => () } - staleVersions->Array.forEach(version => - removeLlmsTextFiles(~llmsDirectory=llmsDirectory->Node.Path.join2(version)) - ) + staleVersions->Array.forEach(version => { + let versionedLlmsDirectory = llmsDirectory->Node.Path.join2(version) + removeLlmsTextFiles(~llmsDirectory=versionedLlmsDirectory) + removeSectionLlmFiles(~llmsDirectory=versionedLlmsDirectory, ~sectionFiles) + }) createLlmsFiles( ~version=currentVersion, - ~manualVersionLinks, ~rescriptReactVersion, ~reactVersion, ~txtFilePath, @@ -220,9 +291,10 @@ let generateFile = ( llmsDirectory, ) - docsDirectory - ->collectFiles - ->Array.forEach(filePath => { + let mdxFilePaths = + docsDirectory->collectFiles->Array.filter(filePath => String.endsWith(filePath, ".mdx")) + + mdxFilePaths->Array.forEach(filePath => { if String.endsWith(filePath, ".mdx") { let content = readMarkdownFile(filePath) @@ -232,31 +304,46 @@ let generateFile = ( } }) - copyVersions->Array.forEach(version => - copyCurrentFilesToVersion( - ~version, - ~llmsDirectory, - ~fullFilePath, - ~smallFilePath, - ~manualVersionLinks, - ~rescriptReactVersion, - ~reactVersion, - ) - ) + let documents = mdxFilePaths->Array.map(readMdxDocument)->Array.toSorted(compareMdxDocuments) + + createSectionLlmFiles(~llmsDirectory, ~sectionFiles, ~documents) } let currentManualVersion = "v12" -let manualMajorVersions = ["v12", "v13"] let currentReactVersion = "v0.14.2" let currentReactRuntimeVersion = "v19.2.4" -let manualVersionLinks = `- [v13 pre-release LLMs index](https://rescript-lang.org/llms/manual/v13/llms.txt): The LLM file list for the latest ReScript v13 pre-release documentation -- [v13 pre-release complete documentation](https://rescript-lang.org/llms/manual/v13/llm-full.txt): The complete latest ReScript v13 pre-release documentation -- [v13 pre-release abridged documentation](https://rescript-lang.org/llms/manual/v13/llm-small.txt): A minimal latest ReScript v13 pre-release reference -- [v12 current LLMs index](https://rescript-lang.org/llms/manual/v12/llms.txt): The LLM file list for the current ReScript v12 documentation -- [v12 current complete documentation](https://rescript-lang.org/llms/manual/v12/llm-full.txt): The complete current ReScript v12 documentation -- [v12 current abridged documentation](https://rescript-lang.org/llms/manual/v12/llm-small.txt): A minimal current ReScript v12 reference` +let manualSectionLlmFiles = [ + { + title: "ReScript Language Overview", + slug: "language-overview", + section: "Language Features", + description: "Focused documentation for ReScript syntax, data types, control flow, modules, and core language features.", + excludedSlugs: [], + }, + { + title: "ReScript JavaScript Interop", + slug: "javascript-interop", + section: "JavaScript Interop", + description: "Focused documentation for binding to JavaScript values, modules, functions, objects, JSON, TypeScript, and other runtime interop patterns.", + excludedSlugs: [], + }, + { + title: "ReScript Build System", + slug: "build-system", + section: "Build System", + description: "Focused documentation for ReScript build configuration, project structure, monorepo setup, compiler performance, and build-tool integration.", + excludedSlugs: [], + }, + { + title: "ReScript Getting Started", + slug: "getting-started", + section: "Overview", + description: "Focused documentation for installing ReScript, editor setup, migration notes, and onboarding from JavaScript.", + excludedSlugs: ["llms"], + }, +] let manualDocsDirectory = "markdown-pages/docs/manual" let reactDocsDirectory = "markdown-pages/docs/react" @@ -266,24 +353,21 @@ let reactLlmsDirectory = "public/llms/react" generateFile( ~currentVersion=currentManualVersion, - ~copyVersions=manualMajorVersions, - ~manualVersionLinks, ~rescriptReactVersion="", ~reactVersion="", ~txtFilePath="public/llms.txt", ~staleTxtFilePath="public/llms/manual/llms.txt", - ~staleVersions=["v10", "v11"], + ~staleVersions=["v10", "v11", "v12", "v13"], + ~sectionFiles=manualSectionLlmFiles, manualDocsDirectory, manualLlmsDirectory, ) generateFile( ~currentVersion=currentReactVersion, - ~copyVersions=[currentReactVersion], - ~manualVersionLinks="", ~rescriptReactVersion=currentReactVersion, ~reactVersion=currentReactRuntimeVersion, ~txtFilePath=reactLlmsDirectory->Node.Path.join2("llms.txt"), - ~staleVersions=["latest"], + ~staleVersions=["latest", currentReactVersion], reactDocsDirectory, reactLlmsDirectory, )