From 90fa46372f09a465c127c9209fbcea922bfa17a9 Mon Sep 17 00:00:00 2001 From: 222448082Ashen <167728161+222448082Ashen@users.noreply.github.com> Date: Sun, 21 Dec 2025 15:33:48 +0530 Subject: [PATCH 1/3] Update PR template and improve example validator script Revamps the pull request template for clarity and geometry example validation instructions. Adds single-example validation mode to usage-examples-testing-script.cjs, enabling reliable checks for flat-file usage example layouts. --- .github/pull_request_template.md | 69 ++++++++---------- scripts/usage-examples-testing-script.cjs | 88 +++++++++++++++++++++++ 2 files changed, 117 insertions(+), 40 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a7b68a73a..20c9c6668 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,62 +1,51 @@ # Description -_Please include a summary of the changes and the related issue. Please also include relevant -motivation and context. List any dependencies that are required for this change._ +**Category:** geometry -## Type of change +**What this PR adds:** + +- Ensures the Geometry usage examples are complete and validate cleanly. +- Improves the usage-example validator script so individual examples can be validated reliably with the repo's flat-file usage-example layout. -_Please delete options that are not relevant._ +## Type of change +- [x] Documentation / examples (usage examples and supporting assets) +- [x] Tooling / scripts (validation improvements) - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as - expected) -- [ ] Documentation (update or new) +- [ ] Breaking change ## How Has This Been Tested? -_Please describe the tests that you ran to verify your changes. Provide instructions so we can -reproduce. Please also list any relevant details for your test configuration._ +- `npm run build` +- Validated a full pass over Geometry usage examples (27 example keys) using the validator script in single-example mode. -## Testing Checklist +## Testing Commands -- [ ] Tested in latest Chrome -- [ ] Tested in latest Firefox -- [ ] npm run build -- [ ] npm run preview +**Single example** -## Checklist +```sh +node ./scripts/usage-examples-testing-script.cjs center_point-1-example +``` -_Please delete options that are not relevant._ +**All Geometry examples (PowerShell)** -### If involving code +```powershell +$dir = "public/usage-examples/geometry"; $examples = Get-ChildItem -Path $dir -Filter "*-example.txt" | Select-Object -ExpandProperty BaseName | Sort-Object -Unique; if (-not $examples) { Write-Error "No *-example.txt files found in $dir"; exit 1 }; $failed = @(); foreach ($ex in $examples) { Write-Host "`n=== Validating $ex ==="; node .\scripts\usage-examples-testing-script.cjs $ex; if ($LASTEXITCODE -ne 0) { $failed += $ex } }; if ($failed.Count -gt 0) { Write-Host "`nFAILED examples:"; $failed | ForEach-Object { Write-Host " - $_" }; exit 1 } else { Write-Host "`nAll Geometry examples validated successfully: $($examples.Count)" } +``` -- [ ] My code follows the style guidelines of this project -- [ ] I have performed a self-review of my own code -- [ ] I have commented my code in hard-to-understand areas -- [ ] I have made corresponding changes to the documentation -- [ ] My changes generate no new warnings - -### If modified config files - -- [ ] I have checked the following files for changes: - - [ ] package.json - - [ ] astro.config.mjs - - [ ] netlify.toml - - [ ] docker-compose.yml - - [ ] custom.css +## Checklist -## Folders and Files Added/Modified +- [x] I have performed a self-review of my changes +- [x] `npm run build` completes successfully +- [x] Usage examples follow repo conventions (C++, C# top-level, C# OOP, Python, .txt, and output image/gif) +- [x] My changes generate no new warnings -_Please list the folders and files added/modified with this pull request and delete options that are not relevant._ +## Files Modified/Added -- Added: - - [ ] folder/folder - - [ ] folder/folder -- Modified: - - [ ] folder/file - - [ ] folder/file +- `public/usage-examples/geometry/` (validated example sets) +- `scripts/usage-examples-testing-script.cjs` (single-example validation mode) ## Additional Notes -_Please add any additional information that might be useful for the reviewers._ +- This PR uses the validator's single-example mode to avoid assumptions about nested example folders. diff --git a/scripts/usage-examples-testing-script.cjs b/scripts/usage-examples-testing-script.cjs index 978b54d95..4d4925fad 100644 --- a/scripts/usage-examples-testing-script.cjs +++ b/scripts/usage-examples-testing-script.cjs @@ -169,6 +169,94 @@ if (process.argv[2] != null) { testing = true; } +// =============================================================================== +// Single-example validation mode +// =============================================================================== +// Many categories store usage examples as flat files directly under: +// public/usage-examples//.* +// The page-generation logic below expects an older nested folder structure. +// When an example key is provided, validate only that example and exit early. +if (testing) { + const usageExamplesRoot = path.join(__dirname, "..", "public", "usage-examples"); + const categoriesOnDisk = fs + .readdirSync(usageExamplesRoot, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name); + + let exampleDir = ""; + for (const category of categoriesOnDisk) { + const candidateDir = path.join(usageExamplesRoot, category); + const candidateTxt = path.join(candidateDir, `${fileNameToCheck}.txt`); + if (fs.existsSync(candidateTxt)) { + exampleDir = candidateDir; + break; + } + } + + let output = "\n------------------------------------------------\n\n"; + output += kleur.magenta("Testing") + kleur.cyan(" -> " + fileNameToCheck) + "\n\n"; + + if (!exampleDir) { + output += kleur.red("\u274C Not Found\t\t -> ") + kleur.white(fileNameToCheck + ".txt\n"); + output += "\nCould not find a matching .txt file under public/usage-examples//.\n"; + output += "Make sure the example files exist and are named correctly.\n"; + output += "\n------------------------------------------------\n"; + console.log(output); + process.exit(1); + } + + const filesInDir = fs.readdirSync(exampleDir); + let ok = true; + + // Text file + if (filesInDir.includes(fileNameToCheck + ".txt")) { + output += kleur.green("\u2705 Text Description\t -> ") + kleur.white(fileNameToCheck + ".txt\n"); + } else { + output += kleur.red("\u274C Text Description\t -> ") + kleur.white(fileNameToCheck + ".txt\n"); + ok = false; + } + + // Output file (.png or .gif) + if (filesInDir.includes(fileNameToCheck + ".png")) { + output += kleur.green("\u2705 Image\t\t -> ") + kleur.white(fileNameToCheck + ".png\n"); + } else if (filesInDir.includes(fileNameToCheck + ".gif")) { + output += kleur.green("\u2705 Image (Gif)\t\t -> ") + kleur.white(fileNameToCheck + ".gif\n"); + } else { + output += kleur.red("\u274C Image/Gif\t\t -> ") + kleur.white(fileNameToCheck + " .png or .gif file\n"); + ok = false; + } + + // Required code files + const requiredCodeFiles = { + ".cpp": "C++\t\t", + "-top-level.cs": "C# (Top-Level)", + "-oop.cs": "C# (Object-Oriented)", + ".py": "Python\t", + }; + + Object.keys(requiredCodeFiles).forEach((extension) => { + if (filesInDir.includes(fileNameToCheck + extension)) { + output += + kleur.green("\u2705 " + requiredCodeFiles[extension] + "\t -> ") + + kleur.white(fileNameToCheck + extension + "\n"); + } else { + output += + kleur.red("\u274C " + requiredCodeFiles[extension] + "\t -> ") + + kleur.white(fileNameToCheck + extension + "\n"); + ok = false; + } + }); + + if (!ok) { + output += "\nSome files missing or incorrectly named (shown in red above).\n"; + output += "Please update the example set and try again.\n"; + } + + output += "\n------------------------------------------------\n"; + console.log(output); + process.exit(ok ? 0 : 1); +} + let apiJsonData = getJsonData(); let categories = getApiCategories(apiJsonData); From 3a46daf3aafa7b34d6a987a7b887474bdfd61d96 Mon Sep 17 00:00:00 2001 From: dilankakasun <167728161+222448082Ashen@users.noreply.github.com> Date: Wed, 21 Jan 2026 10:24:05 +0530 Subject: [PATCH 2/3] Update PR template and remove test output from script Revised the pull request template for clarity, expanded checklists, and improved instructions. Removed the single-example validation output and related logic from usage-examples-testing-script.cjs to streamline the script and reduce console clutter. --- .github/pull_request_template.md | 83 +++++++++++++---------- scripts/usage-examples-testing-script.cjs | 67 ++---------------- 2 files changed, 52 insertions(+), 98 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 20c9c6668..4ca36209e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,51 +1,62 @@ # Description - -**Category:** geometry - -**What this PR adds:** - -- Ensures the Geometry usage examples are complete and validate cleanly. -- Improves the usage-example validator script so individual examples can be validated reliably with the repo's flat-file usage-example layout. +Please include a summary of the changes and the related issue. Please also include relevant motivation and context. List any dependencies that are required for this change. ## Type of change +Please delete options that are not relevant. -- [x] Documentation / examples (usage examples and supporting assets) -- [x] Tooling / scripts (validation improvements) - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Documentation (update or new) ## How Has This Been Tested? +Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration. -- `npm run build` -- Validated a full pass over Geometry usage examples (27 example keys) using the validator script in single-example mode. - -## Testing Commands - -**Single example** - -```sh -node ./scripts/usage-examples-testing-script.cjs center_point-1-example -``` - -**All Geometry examples (PowerShell)** - -```powershell -$dir = "public/usage-examples/geometry"; $examples = Get-ChildItem -Path $dir -Filter "*-example.txt" | Select-Object -ExpandProperty BaseName | Sort-Object -Unique; if (-not $examples) { Write-Error "No *-example.txt files found in $dir"; exit 1 }; $failed = @(); foreach ($ex in $examples) { Write-Host "`n=== Validating $ex ==="; node .\scripts\usage-examples-testing-script.cjs $ex; if ($LASTEXITCODE -ne 0) { $failed += $ex } }; if ($failed.Count -gt 0) { Write-Host "`nFAILED examples:"; $failed | ForEach-Object { Write-Host " - $_" }; exit 1 } else { Write-Host "`nAll Geometry examples validated successfully: $($examples.Count)" } -``` +### Testing Checklist +- [ ] Tested in latest Chrome +- [ ] Tested in latest Firefox +- [ ] `npm run build` +- [ ] `npm run preview` ## Checklist +Please delete options that are not relevant. + +### If involving code +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings + +### If modified config files +- [ ] I have checked the following files for changes: + - [ ] package.json + - [ ] astro.config.mjs + - [ ] netlify.toml + - [ ] docker-compose.yml + - [ ] custom.css + +## Folders and Files Added/Modified +Please list the folders and files added/modified with this pull request and delete options that are not relevant. + +### Added: +- folder/folder +- folder/folder + +### Modified: +- folder/file +- folder/file -- [x] I have performed a self-review of my changes -- [x] `npm run build` completes successfully -- [x] Usage examples follow repo conventions (C++, C# top-level, C# OOP, Python, .txt, and output image/gif) -- [x] My changes generate no new warnings - -## Files Modified/Added +## Additional Notes +Please add any additional information that might be useful for the reviewers. -- `public/usage-examples/geometry/` (validated example sets) -- `scripts/usage-examples-testing-script.cjs` (single-example validation mode) +--- -## Additional Notes +### Geometry Example Validation (Optional) + diff --git a/scripts/usage-examples-testing-script.cjs b/scripts/usage-examples-testing-script.cjs index 4d4925fad..7e4346b69 100644 --- a/scripts/usage-examples-testing-script.cjs +++ b/scripts/usage-examples-testing-script.cjs @@ -159,10 +159,7 @@ console.log("\nGenerating MDX files for Usage Examples pages...\n"); let name; let success = true; let testing = false; -let testingSuccess = true; -let testingOutput = ""; let fileNameToCheck = ""; -// let simpleExample = false; if (process.argv[2] != null) { fileNameToCheck = process.argv[2]; @@ -394,56 +391,6 @@ categories.forEach((categoryKey) => { functionExampleFiles.forEach((exampleTxtKey) => { let exampleKey = exampleTxtKey.replaceAll(".txt", ""); - // ----------------------------------- - // ========= TESTING ================= - // ----------------------------------- - // Testing that all files are included for filename (terminal argument) - if (fileNameToCheck == exampleKey) { - - // Define required code files - const requiredCodeFiles = { - ".cpp": "C++\t\t", - "-top-level.cs": "C# (Top-Level)", - "-oop.cs": "C# (Object-Oriented)", - ".py": "Python\t", - // ".pas": "Pascal", - }; - - let exampleFiles = categoryFiles.filter(file => file.startsWith(exampleKey)); - - testingOutput += "\n------------------------------------------------\n\n"; - testingOutput += kleur.magenta("Testing") + kleur.cyan(" -> " + fileNameToCheck) + "\n\n"; - - // Text file - check already done above - testingOutput += kleur.green("\u2705 Text Description\t -> ") + kleur.white(fileNameToCheck + ".txt\n"); - - // Check for output file (.png or .gif) - if (exampleFiles.includes(fileNameToCheck + ".png")) { - testingOutput += kleur.green("\u2705 Image\t\t -> ") + kleur.white(fileNameToCheck + ".png\n"); - } else if (exampleFiles.includes(fileNameToCheck + ".gif")) { - testingOutput += kleur.green("\u2705 Image (Gif)\t\t -> ") + kleur.white(fileNameToCheck + ".gif\n"); - } else { - testingOutput += kleur.red("\u274C Image/Gif\t\t -> ") + kleur.white(fileNameToCheck + " .png or .gif file\n"); - testingSuccess = false; - } - - // Check code files - Object.keys(requiredCodeFiles).forEach(function (extension) { - if (exampleFiles.includes(fileNameToCheck + extension)) { - testingOutput += kleur.green("\u2705 " + requiredCodeFiles[extension] + "\t -> ") + kleur.white(fileNameToCheck + extension + "\n"); - } else { - testingOutput += kleur.red("\u274C " + requiredCodeFiles[extension] + "\t -> ") + kleur.white(fileNameToCheck + extension + "\n"); - testingSuccess = false; - } - }); - - if (!testingSuccess) { - testingOutput += "\nSome files missing or incorrectly named (shown in red above).\nPlease update to make sure you have all files listed above and try again.\n" - } - - testingOutput += "\n------------------------------------------------\n"; - } - // ----------------------------------- // Description let txtFilePath = categoryFilePath + "/" + functionKey + "/" + exampleTxtKey; @@ -489,16 +436,16 @@ categories.forEach((categoryKey) => { } // Check for cpp files for standard SK and Beyond SK else if (lang == "cpp" && cppFiles.length > 0) { cppFiles.forEach(file => { - if (file.includes(exampleKey)){ - if (file.includes("-sk")){ + if (file.includes(exampleKey)) { + if (file.includes("-sk")) { mdxContent += `import ${importTitle}_sk_${lang} from '${codeFilePath.replaceAll(".cpp", "-sk.cpp").replaceAll("/usage", "/public/usage")}?raw';\n`; } - if (file.includes("-beyond")){ + if (file.includes("-beyond")) { mdxContent += `import ${importTitle}_beyond_${lang} from '${codeFilePath.replaceAll(".cpp", "-beyond.cpp").replaceAll("/usage", "/public/usage")}?raw';\n`; } } - }); - } + }); + } else { mdxContent += `import ${importTitle}_${lang} from '${codeFilePath.replaceAll("/usage", "/public/usage")}?raw';\n`; } @@ -633,7 +580,3 @@ categories.forEach((categoryKey) => { if (success) { console.log(kleur.green("\nAll Usage Example MDX files generated successfully.")); } -// Output information when checking filename -if (testing) { - console.log(testingOutput); -} From 147ffd566775d9b36523f562a8553264919387b9 Mon Sep 17 00:00:00 2001 From: dilankakasun <167728161+222448082Ashen@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:37:44 +0530 Subject: [PATCH 3/3] Improve function linking and update usage examples Enhanced the API documentation script to better handle overloaded function links and example references, including correct anchor generation for functions with multiple overloads. Updated usage-example-references.json to add new examples, fix duplicate entries, and adjust titles and formatting for consistency. --- scripts/api-pages-script.cjs | 89 ++++++++-- .../json-files/usage-example-references.json | 157 +++++++++++++----- 2 files changed, 185 insertions(+), 61 deletions(-) diff --git a/scripts/api-pages-script.cjs b/scripts/api-pages-script.cjs index 45dbc63fd..16d231840 100644 --- a/scripts/api-pages-script.cjs +++ b/scripts/api-pages-script.cjs @@ -134,6 +134,8 @@ function getAllFinishedExamples() { // ------------------------------------------------------------------------------ // Type Mappings // ------------------------------------------------------------------------------ +const globalFunctionGroups = {}; + function Mappings(jsonData) { //generate mappings from API for (const categoryKey in jsonData) { @@ -312,10 +314,11 @@ function getGroupName(jsonData, uniqueName) { const category = jsonData[categoryKey]; const categoryFunctions = category.functions; categoryFunctions.forEach((func) => { - if (func.unique_global_name == uniqueName) { - funcGroupName = func.name.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");; + if (func.unique_global_name == uniqueName || func.name == uniqueName) { + funcGroupName = func.name.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" "); } }); + if (funcGroupName) break; } return funcGroupName; } @@ -480,6 +483,18 @@ let mdxContent = ""; let success = true; const jsonData = getJsonData("api.json"); const jsonColors = getJsonData("colors.json"); + +// Pre-calculate global function counts after jsonData is loaded +for (const categoryKey in jsonData) { + if (categoryKey !== "types") { + jsonData[categoryKey].functions.forEach((f) => { + if (!globalFunctionGroups[f.name]) { + globalFunctionGroups[f.name] = 0; + } + globalFunctionGroups[f.name]++; + }); + } +} let guidesJson = getJsonData("guides.json"); let usageExamplesJson = getJsonData("usage-example-references.json"); let guidesCategories = getApiCategories(guidesJson); @@ -642,7 +657,7 @@ for (const categoryKey in jsonData) { // Put {} symbol at the end of headers of overloaded functions with usage example or else just keep empty const formattedName = isOverloaded ? `\n#### [${functionName2}](#${formattedUniqueLink})${hasSymbol} \\{#${formattedUniqueLink}\\}` - : `\n### [${functionName2}](#${formattedLink})${hasSymbol}`; + : `\n### [${functionName2}](#${formattedLink})${hasSymbol} \\{#${formattedLink}\\}`; // Replace type names in the description with formatted versions let description = func.description || ""; @@ -672,8 +687,11 @@ for (const categoryKey in jsonData) { .split("_") .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(" "); - const formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); - const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})` + let formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); + if (functionGroups[names] && functionGroups[names].length > 1) { + formattedLink += "-functions"; + } + const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})`; description = description.replace(new RegExp(`\`\\b${names}\\b\``, "g"), link); description = description.replaceAll("\n", " "); } @@ -709,8 +727,11 @@ for (const categoryKey in jsonData) { .split("_") .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(" "); - const formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); - const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})` + let formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); + if (functionGroups[names] && functionGroups[names].length > 1) { + formattedLink += "-functions"; + } + const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})`; description2 = description2.replace(new RegExp(`\`\\b${names}\\b\``, "g"), link); description2 = description2.replaceAll("\n", " "); } @@ -738,6 +759,20 @@ for (const categoryKey in jsonData) { ); } + for (const names of functionNames) { + const normalName = names + .split("_") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(" "); + let formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); + if (functionGroups[names] && functionGroups[names].length > 1) { + formattedLink += "-functions"; + } + const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})`; + returnDescription = returnDescription.replace(new RegExp(`\`\\b${names}\\b\``, "g"), link); + returnDescription = returnDescription.replaceAll("\n", " "); + } + mdxContent += `${returnDescription}\n\n`; } @@ -785,7 +820,7 @@ for (const categoryKey in jsonData) { example.functions.forEach((used) => { if (func.unique_global_name == used && limit < 4) { allExamples.push({ - name: example.funcKey, + funcKey: example.funcKey, title: example.title, url: example.url }) @@ -814,8 +849,19 @@ for (const categoryKey in jsonData) { if (allExamples.length > 0) { mdxContent += `**API Documentation Code Examples**:\n\n` allExamples.forEach((example) => { - const exampleName = getGroupName(jsonData, example.name); - mdxContent += `- [${exampleName}](${example.url}): ${example.title}\n` + let exampleName = getGroupName(jsonData, example.funcKey); + if (exampleName == "" && example.funcKey) { + exampleName = example.funcKey.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" "); + } + if (exampleName == "") exampleName = "Example"; + + let exampleUrl = example.url; + if (example.funcKey && globalFunctionGroups[example.funcKey] > 1) { + const hash = example.funcKey.toLowerCase().replace(/_/g, "-"); + exampleUrl = exampleUrl.replace(/#.*$/, `#${hash}-functions`); + } + + mdxContent += `- [${exampleName}](${exampleUrl}): ${example.title}\n` }) } @@ -887,8 +933,11 @@ for (const categoryKey in jsonData) { .split("_") .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(" "); - const formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); - const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})` + let formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); + if (functionGroups[names] && functionGroups[names].length > 1) { + formattedLink += "-functions"; + } + const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})`; description = description.replace(new RegExp(`\`\\b${names}\\b\``, "g"), link); } @@ -917,9 +966,12 @@ for (const categoryKey in jsonData) { .split("_") .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(" "); - const formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); - const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})` - description = description.replace(new RegExp(`\`\\b${names}\\b\``, "g"), link); + let formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); + if (functionGroups[names] && functionGroups[names].length > 1) { + formattedLink += "-functions"; + } + const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})`; + fieldDescription = fieldDescription.replace(new RegExp(`\`\\b${names}\\b\``, "g"), link); } mdxContent += `| ${fieldName} | ${fieldType} | ${fieldDescription.replace(/\n/g, '')} |\n`; @@ -937,8 +989,11 @@ for (const categoryKey in jsonData) { .split("_") .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(" "); - const formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); - const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})` + let formattedLink = normalName.toLowerCase().replace(/\s+/g, "-"); + if (functionGroups[names] && functionGroups[names].length > 1) { + formattedLink += "-functions"; + } + const link = `[\`${normalName}\`](/api/${input}/#${formattedLink})`; description = description.replace(new RegExp(`\`\\b${names}\\b\``, "g"), link); } description = description.replaceAll("\n\n\n", "\n\n"); diff --git a/scripts/json-files/usage-example-references.json b/scripts/json-files/usage-example-references.json index c41688ec6..554152979 100644 --- a/scripts/json-files/usage-example-references.json +++ b/scripts/json-files/usage-example-references.json @@ -2,7 +2,7 @@ "audio": [ { "funcKey": "play_music_named", - "title": "Music Playback", + "title": "Music Playback\r", "url": "/api/audio/#play-music-named", "functions": [ "audio_ready", @@ -14,7 +14,7 @@ }, { "funcKey": "resume_music", - "title": "Pausing and Resuming Game Music", + "title": "Pausing and Resuming Game Music\r", "url": "/api/audio/#resume-music", "functions": [ "audio_ready", @@ -142,7 +142,7 @@ }, { "funcKey": "closest_point_on_circle", - "title": "Closest Point to Mouse on Circle", + "title": "Closest Point to Mouse on Circle\r", "url": "/api/geometry/#closest-point-on-circle", "functions": [ "open_window", @@ -161,6 +161,25 @@ "close_all_windows" ] }, + { + "funcKey": "lines_intersect", + "title": "Simple Line Intersect Check", + "url": "/api/geometry/#lines-intersect", + "functions": [ + "open_window", + "Point2D", + "line_from_point_to_point", + "draw_line_record", + "color_red", + "draw_text_no_font_no_size", + "color_black", + "color_blue", + "color_green", + "refresh_screen", + "delay", + "close_all_windows" + ] + }, { "funcKey": "line_intersects_rect", "title": "Avoid the Rectangle", @@ -256,25 +275,6 @@ "close_all_windows" ] }, - { - "funcKey": "lines_intersect", - "title": "Simple Line Intersect Check", - "url": "/api/geometry/#lines-intersect", - "functions": [ - "open_window", - "Point2D", - "line_from_point_to_point", - "draw_line_record", - "color_red", - "draw_text_no_font_no_size", - "color_black", - "color_blue", - "color_green", - "refresh_screen", - "delay", - "close_all_windows" - ] - }, { "funcKey": "point_at", "title": "Flower Grid", @@ -508,7 +508,7 @@ }, { "funcKey": "random_window_point", - "title": "Random Portals", + "title": "Random Portals\r", "url": "/api/geometry/#random-window-point", "functions": [ "open_window", @@ -524,6 +524,32 @@ "close_window" ] }, + { + "funcKey": "rectangle_around", + "title": "A perpetually moving circle which increases and decreases in size, surrounded by a rectangle shape", + "url": "/api/geometry/#rectangle-around", + "functions": [ + "open_window", + "create_timer", + "start_timer", + "quit_requested", + "point_at", + "cosine", + "sine", + "circle_at", + "timer_ticks", + "reset_timer", + "process_events", + "clear_screen_to_white", + "draw_rectangle_record", + "color_black", + "rectangle_around_circle", + "fill_circle_record", + "color_red", + "refresh_screen", + "close_all_windows" + ] + }, { "funcKey": "same_point", "title": "Point 2D Guessing Game", @@ -561,6 +587,24 @@ "close_all_windows" ] }, + { + "funcKey": "bitmap_center", + "title": "Draw a bitmap with a red dot at its center\r", + "url": "/api/graphics/#bitmap-center", + "functions": [ + "open_window", + "load_bitmap", + "clear_screen", + "color_white", + "draw_bitmap", + "fill_circle_record", + "color_red", + "circle_at", + "refresh_screen", + "delay", + "close_all_windows" + ] + }, { "funcKey": "clear_screen", "title": "Background Color", @@ -575,7 +619,7 @@ }, { "funcKey": "draw_bitmap_named", - "title": "SplashKit Logo", + "title": "SplashKit Logo\r", "url": "/api/graphics/#draw-bitmap-named", "functions": [ "open_window", @@ -1041,7 +1085,7 @@ }, { "funcKey": "fill_rectangle_on_bitmap", - "title": "Cityscape", + "title": "Cityscape\r", "url": "/api/graphics/#fill-rectangle-on-bitmap", "functions": [ "open_window", @@ -1112,7 +1156,7 @@ }, { "funcKey": "fill_triangle_on_bitmap", - "title": "Hooray! A Red Hat", + "title": "Hooray! A Red Hat\r", "url": "/api/graphics/#fill-triangle-on-bitmap", "functions": [ "open_window", @@ -1172,7 +1216,7 @@ }, { "funcKey": "free_font", - "title": "Freeing Fonts", + "title": "Freeing Fonts\r", "url": "/api/graphics/#free-font", "functions": [ "open_window", @@ -1211,7 +1255,7 @@ }, { "funcKey": "load_font", - "title": "Using Fonts", + "title": "Using Fonts\r", "url": "/api/graphics/#load-font", "functions": [ "open_window", @@ -1242,7 +1286,7 @@ }, { "funcKey": "text_width_font_named", - "title": "Underline Text using Text Width", + "title": "Underline Text using Text Width\r", "url": "/api/graphics/#text-width-font-named", "functions": [ "open_window", @@ -1303,7 +1347,7 @@ "physics": [ { "funcKey": "sprite_bitmap_collision", - "title": "Does SplashKit have bugs?", + "title": "Does SplashKit have bugs?\r", "url": "/api/physics/#sprite-bitmap-collision", "functions": [ "open_window", @@ -1323,7 +1367,7 @@ }, { "funcKey": "sprite_collision", - "title": "Colliding Sprites", + "title": "Colliding Sprites\r", "url": "/api/physics/#sprite-collision", "functions": [ "open_window", @@ -1342,7 +1386,7 @@ }, { "funcKey": "sprite_point_collision", - "title": "Determine Sprite Collisions with Points", + "title": "Determine Sprite Collisions with Points\r", "url": "/api/physics/#sprite-point-collision", "functions": [ "open_window", @@ -1365,7 +1409,7 @@ }, { "funcKey": "sprite_rectangle_collision", - "title": "Detect Sprite Collisions with Rectangles", + "title": "Detect Sprite Collisions with Rectangles\r", "url": "/api/physics/#sprite-rectangle-collision", "functions": [ "open_window", @@ -1390,7 +1434,7 @@ "raspberry": [ { "funcKey": "raspi_i2c_write_data", - "title": "LED Text Scrolling", + "title": "LED Text Scrolling\r", "url": "/api/raspberry/#raspi-i2c-write-data", "functions": [ "write_line", @@ -1407,7 +1451,7 @@ "sprites": [ { "funcKey": "create_sprite", - "title": "Creating a Player Sprite", + "title": "Creating a Player Sprite\r", "url": "/api/sprites/#create-sprite", "functions": [ "open_window", @@ -1425,7 +1469,7 @@ }, { "funcKey": "draw_sprite", - "title": "Drawing a Player Sprite", + "title": "Drawing a Player Sprite\r", "url": "/api/sprites/#draw-sprite", "functions": [ "open_window", @@ -1443,7 +1487,7 @@ }, { "funcKey": "free_sprite", - "title": "Freeing a Sprite", + "title": "Freeing a Sprite\r", "url": "/api/sprites/#free-sprite", "functions": [ "open_window", @@ -1465,7 +1509,7 @@ }, { "funcKey": "sprite_set_position", - "title": "Setting Sprite Position", + "title": "Setting Sprite Position\r", "url": "/api/sprites/#sprite-set-position", "functions": [ "open_window", @@ -1485,7 +1529,7 @@ }, { "funcKey": "sprite_set_velocity", - "title": "Setting Velocity of Sprite", + "title": "Setting Velocity of Sprite\r", "url": "/api/sprites/#sprite-set-velocity", "functions": [ "open_window", @@ -1507,7 +1551,7 @@ }, { "funcKey": "sprite_set_x", - "title": "Setting Sprite X-coordinate", + "title": "Setting Sprite X-coordinate\r", "url": "/api/sprites/#sprite-set-x", "functions": [ "open_window", @@ -1524,7 +1568,7 @@ }, { "funcKey": "sprite_set_y", - "title": "Setting Sprite Y-coordinate", + "title": "Setting Sprite Y-coordinate\r", "url": "/api/sprites/#sprite-set-y", "functions": [ "open_window", @@ -1541,7 +1585,7 @@ }, { "funcKey": "sprite_x", - "title": "Sprite x-coordinate", + "title": "Sprite x-coordinate\r", "url": "/api/sprites/#sprite-x", "functions": [ "open_window", @@ -1561,7 +1605,7 @@ }, { "funcKey": "sprite_y", - "title": "Sprite y-coordinate", + "title": "Sprite y-coordinate\r", "url": "/api/sprites/#sprite-y", "functions": [ "open_window", @@ -1673,7 +1717,7 @@ }, { "funcKey": "current_ticks", - "title": "How many ticks?", + "title": "How many ticks?\r", "url": "/api/utilities/#current-ticks", "functions": [ "write_line", @@ -1790,5 +1834,30 @@ "write_line" ] } + ], + "windows": [ + { + "funcKey": "close_window", + "title": "Starts a countdown to close the window at the push of a button.", + "url": "/api/windows/#close-window", + "functions": [ + "open_window", + "create_timer", + "quit_requested", + "process_events", + "clear_window", + "color_white", + "button_at_position", + "rectangle_from", + "start_timer", + "draw_text_font_as_string", + "color_black", + "timer_ticks", + "reset_timer", + "draw_interface", + "refresh_window", + "close_all_windows" + ] + } ] } \ No newline at end of file