diff --git a/README.md b/README.md
index 6b1e52e94..6b6877faa 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,31 @@
-#
-
+
-
-
-
+
+
+
-
-[![Homepage](https://img.shields.io/badge/Homepage-8A2BE2)](https://nativelink.com)
-[![GitHub stars](https://img.shields.io/github/stars/tracemachina/nativelink?style=social)](https://github.com/TraceMachina/nativelink)
-[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/TraceMachina/nativelink/badge)](https://securityscorecards.dev/viewer/?uri=github.com/TraceMachina/nativelink)
-[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8050/badge)](https://www.bestpractices.dev/projects/8050)
-[![Slack](https://img.shields.io/badge/slack--channel-blue?logo=slack)](https://nativelink.slack.com/join/shared_invite/zt-281qk1ho0-krT7HfTUIYfQMdwflRuq7A#/shared-invite/email)
-[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
+
+
+
+
+ enter the shipstorm
+
+
+
+
+
+
+
+ [![Homepage](https://img.shields.io/badge/Homepage-8A2BE2)](https://nativelink.com)
+ [![GitHub stars](https://img.shields.io/github/stars/tracemachina/nativelink?style=social)](https://github.com/TraceMachina/nativelink)
+ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/TraceMachina/nativelink/badge)](https://securityscorecards.dev/viewer/?uri=github.com/TraceMachina/nativelink)
+ [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8050/badge)](https://www.bestpractices.dev/projects/8050)
+ [![Slack](https://img.shields.io/badge/slack--channel-blue?logo=slack)](https://nativelink.slack.com/join/shared_invite/zt-281qk1ho0-krT7HfTUIYfQMdwflRuq7A#/shared-invite/email)
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
+
## What's NativeLink?
@@ -22,9 +33,11 @@ NativeLink is an efficient, high-performance build cache and remote execution sy
NativeLink is trusted in production environments to reduce costs and developer iteration times--handling over **one billion requests** per month for its customers, including large corporations such as **Samsung**.
-
-
-
+
+
+
+
+
## 🔑 Key Features
diff --git a/docs/astro.config.ts b/docs/astro.config.ts
index 9421b984f..c642809b9 100644
--- a/docs/astro.config.ts
+++ b/docs/astro.config.ts
@@ -4,14 +4,14 @@ import mdx from "@astrojs/mdx";
import sitemap from "@astrojs/sitemap";
import starlight from "@astrojs/starlight";
import deno from "@deno/astro-adapter";
+import tailwindcss from "@tailwindcss/vite";
// import partytown from "@astrojs/partytown";
import { rehypeHeadingIds } from "@astrojs/markdown-remark";
import { rehypeMermaid } from "@beoe/rehype-mermaid"; // "rehype-mermaid";
-import tailwindcss from "@tailwindcss/vite";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
-import { starlightConfig } from "./starlight.conf.ts";
-// import { default as playformCompress } from "@playform/compress";
+
+import { starlightConfig } from "./starlight.conf";
// https://astro.build/config
export default defineConfig({
diff --git a/docs/biome.json b/docs/biome.json
index eb2cdb535..91bc63dc9 100644
--- a/docs/biome.json
+++ b/docs/biome.json
@@ -14,8 +14,11 @@
"rules": {
"all": true,
"style": {
- "useNamingConvention": "off",
- "noDefaultExport": "off"
+ "useBlockStatements": "error",
+ "useShorthandArrayType": "error",
+ "noShoutyConstants": "warn",
+ "noDefaultExport": "off",
+ "useNamingConvention": "off"
}
}
},
diff --git a/docs/bun.lockb b/docs/bun.lockb
index b37cfb40f..7b76508d1 100755
Binary files a/docs/bun.lockb and b/docs/bun.lockb differ
diff --git a/docs/deno.lock b/docs/deno.lock
index 885f5082d..028687487 100644
--- a/docs/deno.lock
+++ b/docs/deno.lock
@@ -58,25 +58,25 @@
"workspace": {
"packageJson": {
"dependencies": [
- "npm:@astrojs/check@^0.7.0",
+ "npm:@astrojs/check@0.9.3",
"npm:@astrojs/deno@5.0.1",
- "npm:@astrojs/markdown-remark@^5.1.0",
- "npm:@astrojs/partytown@^2.1.1",
+ "npm:@astrojs/markdown-remark@5.2.0",
+ "npm:@astrojs/partytown@2.1.2",
"npm:@astrojs/sitemap@^3.1.6",
- "npm:@astrojs/starlight@^0.25.5",
+ "npm:@astrojs/starlight@0.27.0",
"npm:@bazel/bazelisk@^1.19.0",
"npm:@beoe/pan-zoom@^0.0.3",
"npm:@beoe/rehype-mermaid@^0.0.1",
"npm:@biomejs/biome@^1.8.1",
"npm:@deno/astro-adapter@^0.1.3",
"npm:@lorenzo_lewis/starlight-utils@^0.1.1",
- "npm:@tailwindcss/vite@^4.0.0-alpha.19",
+ "npm:@tailwindcss/vite@^4.0.0-alpha.23",
"npm:@types/bun@latest",
- "npm:astro@^4.5.12",
+ "npm:astro@4.15.4",
"npm:rehype-autolink-headings@^7.1.0",
"npm:rehype-mermaid@^2.1.0",
"npm:remark@^15.0.1",
- "npm:tailwindcss@^4.0.0-alpha.19",
+ "npm:tailwindcss@^4.0.0-alpha.23",
"npm:typescript@^5.4.5"
]
}
diff --git a/docs/package.json b/docs/package.json
index 27492dd68..9cac9ff5f 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -6,9 +6,9 @@
"sync": "astro sync",
"astro": "astro",
"biome": "biome",
- "docs": "bun run docs.build && bun run docs.generate",
- "docs.build": "cd .. && unset TMPDIR TMP; bazelisk build nativelink-config:docs_json && cd docs && bun run src/utils/metaphase_aot.ts",
- "docs.generate": "bun run src/utils/md_to_mdx_aot.ts",
+ "docs": "bun run build.docs && bun run generate.docs",
+ "build.docs": "cd .. && unset TMPDIR TMP; bazelisk build nativelink-config:docs_json && cd docs && bun run src/utils/metaphase_aot.ts",
+ "generate.docs": "bun run src/utils/md_to_mdx_aot.ts",
"build": "bun fix && astro build",
"check": "biome ci . && astro check",
"dev": "astro dev",
@@ -24,19 +24,19 @@
"setup": "bun install && bun run deno install -Arf jsr:@deno/deployctl@1.12.0"
},
"dependencies": {
- "@astrojs/check": "^0.7.0",
+ "@astrojs/check": "0.9.3",
"@astrojs/deno": "5.0.1",
- "@astrojs/markdown-remark": "^5.1.0",
- "@astrojs/partytown": "^2.1.1",
+ "@astrojs/markdown-remark": "5.2.0",
+ "@astrojs/partytown": "2.1.2",
"@astrojs/sitemap": "^3.1.6",
- "@astrojs/starlight": "^0.25.5",
+ "@astrojs/starlight": "0.27.0",
"@beoe/pan-zoom": "^0.0.3",
"@beoe/rehype-mermaid": "^0.0.1",
"@deno/astro-adapter": "^0.1.3",
- "@tailwindcss/vite": "^4.0.0-alpha.19",
- "astro": "^4.5.12",
+ "@tailwindcss/vite": "^4.0.0-alpha.23",
+ "astro": "4.15.4",
"rehype-mermaid": "^2.1.0",
- "tailwindcss": "^4.0.0-alpha.19"
+ "tailwindcss": "^4.0.0-alpha.23"
},
"devDependencies": {
"@bazel/bazelisk": "^1.19.0",
diff --git a/docs/src/styles/custom.css b/docs/src/styles/custom.css
index 18debe3f9..458d4ab9c 100644
--- a/docs/src/styles/custom.css
+++ b/docs/src/styles/custom.css
@@ -18,3 +18,52 @@ html[data-theme="dark"] .beoe-light {
html {
scroll-behavior: smooth;
}
+
+.buttons {
+ display: flex;
+ justify-content: center;
+ gap: 10px;
+ margin-top: 20px;
+}
+
+.buttons button {
+ background-color: #4A90E2; /* A nice blue color */
+ color: white;
+ font-size: 18px;
+ font-weight: bold;
+ border: none;
+ border-radius: 50%;
+ width: 50px;
+ height: 50px;
+ cursor: pointer;
+ transition: transform 0.2s ease, background-color 0.2s ease;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.buttons button:hover {
+ background-color: #357ABD; /* Darker blue on hover */
+ transform: scale(1.1);
+}
+
+.buttons button:active {
+ background-color: #2C6BA1; /* Even darker blue on active */
+ transform: scale(1.05);
+}
+
+.buttons button:focus {
+ outline: none;
+ box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.5);
+}
+
+.buttons button:disabled {
+ background-color: #B0BEC5; /* Grey color for disabled state */
+ cursor: not-allowed;
+ transform: none;
+}
+
+.buttons button:disabled:hover {
+ transform: none;
+}
diff --git a/docs/src/styles/tailwind.css b/docs/src/styles/tailwind.css
index b398a123f..ec72093a1 100644
--- a/docs/src/styles/tailwind.css
+++ b/docs/src/styles/tailwind.css
@@ -1,4 +1,26 @@
-/* @import "tailwindcss"; */
+@import "tailwindcss";
+
+a {
+ @apply underline;
+}
+
+ /* Header Links and Sidebar classes generated by astro */
+a.astro-3ii7xxms,
+a.astro-vtgkq7vy {
+ @apply no-underline;
+}
+
+#logo {
+ @apply flex justify-center items-center;
+}
+
+#description {
+ @apply text-lg font-semibold;
+}
+
+#badges {
+ @apply flex-wrap gap-0.5 md:px-20;
+}
/* @theme {
--color-primaryColor: rgb(99, 102, 241);
diff --git a/docs/src/utils/md_to_mdx.ts b/docs/src/utils/md_to_mdx.ts
index 9d3ec52ed..84ba1bace 100644
--- a/docs/src/utils/md_to_mdx.ts
+++ b/docs/src/utils/md_to_mdx.ts
@@ -2,19 +2,28 @@ import type {
Blockquote,
Code,
Heading,
+ Image,
InlineCode,
Paragraph,
+ PhrasingContent,
Root,
RootContent,
Text,
} from "mdast";
+
import { remark } from "remark";
import remarkMdx from "remark-mdx";
import remarkParse from "remark-parse";
import remarkStringify from "remark-stringify";
import { visit } from "unist-util-visit";
-const DEFAULT_TITLE = "Default Title";
+export type MarkdownProps = {
+ title: string;
+ description: string;
+ pagefind?: boolean;
+ assets?: string[];
+};
+
const BLOCK_TYPES = ["caution", "note", "tip"];
export function parseMarkdown(markdown: string): Root {
@@ -34,7 +43,7 @@ function extractTitleFromTree(tree: Root): {
title: string;
index: number;
} {
- let title = DEFAULT_TITLE;
+ let title = "Default Title";
let titleIndex = -1;
for (let i = 0; i < tree.children.length; i++) {
@@ -66,12 +75,12 @@ function extractTextFromNode(node: Heading | Paragraph): string {
export function generateFrontMatter(
title: string,
description: string,
- pagefind: boolean,
+ pagefind = true,
): string {
return `---
title: "${title}"
description: "${description}"
-pagefind: ${pagefind}
+pagefind: ${pagefind ? "true" : "false"}
---
`;
}
@@ -183,55 +192,109 @@ function removeValeAndGitCliffComments(markdown: string): string {
function processLines(lines: string[]): string[] {
const processedLines = [];
- let inMermaidBlock = false;
- let inCodeBlock = false;
+ const block = {
+ code: false,
+ list: false,
+ };
for (const line of lines) {
- if (isMermaidBlockStart(line)) {
- inMermaidBlock = true;
- processedLines.push(line);
- continue;
- }
- if (isBlockEnd(line, inMermaidBlock)) {
- inMermaidBlock = false;
- processedLines.push(line);
+ if (processCodeBlock(line, block.code, processedLines)) {
+ block.code = !block.code;
continue;
}
- if (isCodeBlock(line, inMermaidBlock)) {
- inCodeBlock = !inCodeBlock;
- processedLines.push(line);
+ block.list = processListBlock(line, block.list, processedLines);
+ if (block.list) {
continue;
}
- if (inMermaidBlock || inCodeBlock || isSpecialLine(line)) {
- processedLines.push(line);
+ if (processSpecialLine(line, processedLines)) {
continue;
}
processedLines.push(escapeHtml(line));
}
+ // Ensure any unclosed list is closed
+ closeList(block.list, processedLines);
+
return processedLines;
}
-function isMermaidBlockStart(line: string): boolean {
- return line.trim().startsWith("```mermaid");
+// Utility to escape HTML entities
+function replaceHtml(unsafe: string): string {
+ return unsafe
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+}
+
+function processCodeBlock(
+ line: string,
+ codeBlock: boolean,
+ processedLines: string[],
+ // languages: string[],
+): boolean {
+ if (isCodeBlock(line)) {
+ processedLines.push(line);
+ return true;
+ }
+
+ if (codeBlock) {
+ processedLines.push(line);
+ return true;
+ }
+
+ return false;
}
-function isBlockEnd(line: string, inMermaidBlock: boolean): boolean {
- return inMermaidBlock && line.trim() === "```";
+function isCodeBlock(line: string): boolean {
+ const trimmedLine = line.trim();
+ return trimmedLine.startsWith("```");
}
-function isCodeBlock(line: string, inMermaidBlock: boolean): boolean {
- return line.trim().startsWith("```") && !inMermaidBlock;
+function processListBlock(
+ line: string,
+ listBlock: boolean,
+ processedLines: string[],
+): boolean {
+ let isListBlock = listBlock;
+
+ if (/^\d+\.\s+\*\*(.+)\*\*:/.test(line)) {
+ isListBlock = closeList(isListBlock, processedLines);
+ processedLines.push(line);
+ processedLines.push('');
+ return true;
+ }
+
+ if (isListBlock && /^\s*-\s+(.+)/.test(line)) {
+ processedLines.push(line.replace(/^\s*-\s+(.+)/, "$1 "));
+ return true;
+ }
+
+ return closeList(isListBlock, processedLines);
}
-function isSpecialLine(line: string): boolean {
- return (
+function processSpecialLine(line: string, processedLines: string[]): boolean {
+ if (
line.trim().startsWith(">") ||
/^\[!(TIP|NOTE|WARNING|IMPORTANT|CAUTION)\]/.test(line)
- );
+ ) {
+ processedLines.push(line);
+ return true;
+ }
+
+ return false;
+}
+
+function closeList(inList: boolean, processedLines: string[]): boolean {
+ if (inList) {
+ processedLines.push(" ");
+ return false;
+ }
+ return inList;
}
function escapeHtml(line: string): string {
@@ -242,27 +305,246 @@ function escapeHtml(line: string): string {
}
export async function transformMarkdownToMdx(
- markdown: string,
- description: string,
- pagefind = true,
+ input: string,
+ docs: MarkdownProps,
+ // languages: string[],
): Promise {
- const preprocessedMarkdown = preProcessMarkdown(markdown);
+ const preprocessedMarkdown = preProcessMarkdown(input);
const tree = parseMarkdown(preprocessedMarkdown);
- const { title, content } = extractTitle(tree);
- let transformedContent = transformGitHubMarkdown(content);
+ // Extract title and content
+ const { content } = extractTitle(tree);
+
+ // Apply transformations in sequence
+ // Prepend the import statements to the content
+ let transformedContent = docs.assets
+ ? [...generateAssetImports(docs.assets), ...content]
+ : [...content];
+
+ // Apply transformations for target IDs
+ const targetIds = ["logo", "description", "badges"];
+ for (const targetId of targetIds) {
+ transformedContent = processTarget(transformedContent, targetId);
+ }
+
+ // GitHub Markdown specific transformations
+ transformedContent = transformGitHubMarkdown(transformedContent);
+
+ // Preserve inline code
transformedContent = preserveInlineCode(transformedContent);
- const modifiedMarkdown = remark()
- .use(remarkStringify)
- .stringify({ type: "root", children: transformedContent });
+ // Reassemble the tree with the transformed content
+ tree.children = transformedContent;
+ // Convert the transformed tree back to Markdown
+ const modifiedMarkdown = remark().use(remarkStringify).stringify(tree);
+
+ // Convert Markdown to MDX
const processedMdx = await remark()
.use(remarkParse)
.use(remarkMdx)
.use(remarkStringify)
.process(modifiedMarkdown);
- const frontMatter = generateFrontMatter(title, description, pagefind);
+ // Generate front matter
+ const frontMatter = generateFrontMatter(
+ docs.title,
+ docs.description,
+ docs.pagefind,
+ );
+
+ // Return the final MDX content
return frontMatter + String(processedMdx);
}
+
+// Function to generate asset import statements
+export function generateAssetImports(assets: string[]): RootContent[] {
+ return assets.map((asset) => {
+ const assetName = transformToPascalCase(asset);
+ return {
+ type: "html",
+ value: `import ${assetName} from '${asset}';\n`,
+ };
+ });
+}
+
+// Helper function to convert file paths to PascalCase
+function transformToPascalCase(filePath: string): string {
+ const fileName = filePath.split("/").pop()?.split(".")[0];
+ if (!fileName) {
+ throw new Error("Invalid file path");
+ }
+
+ return fileName
+ .split(/[^a-zA-Z0-9]/)
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
+ .join("");
+}
+
+export function processTarget(
+ tree: RootContent[],
+ targetId: string,
+): RootContent[] {
+ const alignRegex = /align=["'](center|left|right)["']/i;
+
+ const content = tree.map((node, index, children) => {
+ if (isMatchingTargetNode(node, targetId)) {
+ replaceAlignAttributeInNode(node, alignRegex);
+ if (targetId === "logo") {
+ transformImgSrc(node);
+ }
+ if (targetId === "badges") {
+ ensureBadgeClasses(node);
+ processAndWrapNextBlock(children, index);
+ }
+ }
+ return node;
+ });
+
+ return content;
+}
+
+function ensureBadgeClasses(node: RootContent): void {
+ if (isHtmlNode(node)) {
+ // Replace the class="" attribute directly in node.value
+ node.value = node.value.replace(/class="([^"]*)"/g, (_, classes) => {
+ // Ensure the required classes are present
+ const requiredClasses = [
+ "flex",
+ "justify-center",
+ "items-center",
+ "flex-wrap",
+ "gap-0.5",
+ ];
+
+ // Split the existing classes into an array
+ const existingClasses = classes.trim().split(/\s+/);
+
+ // Add any missing required classes
+ for (const requiredClass of requiredClasses) {
+ if (!existingClasses.includes(requiredClass)) {
+ existingClasses.push(requiredClass);
+ }
+ }
+
+ // Return the updated class attribute
+ return `class="${existingClasses.join(" ")}"`;
+ });
+ }
+}
+
+// Helper function to check if a node matches the target ID
+function isMatchingTargetNode(node: RootContent, targetId: string): boolean {
+ if (node.type === "html" && typeof node.value === "string") {
+ const idRegex = new RegExp(`id=["']${targetId}["']`, "i");
+ return idRegex.test(node.value);
+ }
+ return false;
+}
+
+// Function to replace the align attribute with a CSS class
+function replaceAlignAttributeInNode(
+ node: RootContent,
+ alignRegex: RegExp,
+): void {
+ if (node.type === "html" && typeof node.value === "string") {
+ const newValue = node.value.replace(alignRegex, (_, p1) => {
+ const alignment = p1.toLowerCase() as keyof typeof alignToClassMap;
+ return `class="${alignToClassMap[alignment]}"`;
+ });
+ node.value = newValue;
+ }
+}
+
+function transformImgSrc(node: RootContent): void {
+ if (isHtmlNode(node)) {
+ node.value = node.value
+ // Remove the entire tag and replace it with the two tags
+ .replace(
+ /[\s\S]*?]*>\s*]*>\s* ]*src="[^"]*"[^>]*>\s*<\/picture>/g,
+ `
+
+
+ `,
+ );
+ }
+}
+
+// Type guard to check if a node is an HTML node with a value property
+function isHtmlNode(
+ node: RootContent,
+): node is RootContent & { value: string } {
+ return node.type === "html" && typeof node.value === "string";
+}
+
+function wrapLinksInBlocks(blockNode: RootContent): RootContent[] {
+ if (blockNode.type !== "paragraph") {
+ return [blockNode];
+ }
+
+ const block = blockNode as Paragraph;
+ let modified = false;
+
+ const newChildren = block.children.map((child) => {
+ if (
+ child.type === "link" &&
+ child.children.some((c) => c.type === "image")
+ ) {
+ const image = child.children.find((c) => c.type === "image") as Image;
+ if (image) {
+ modified = true;
+ const altText = replaceHtml(image.alt || "");
+ const imageUrl = replaceHtml(image.url || "");
+ const linkUrl = replaceHtml(child.url || "");
+
+ return {
+ type: "html",
+ value: `\n[![${altText}](${imageUrl})](${linkUrl})\n
`,
+ } as RootContent;
+ }
+ }
+ return child;
+ });
+
+ if (modified) {
+ return [
+ {
+ type: "paragraph",
+ children: newChildren.filter((node): node is PhrasingContent => !!node),
+ },
+ ];
+ }
+ return [blockNode];
+}
+
+// Function to process and wrap the next block in the children array
+function processAndWrapNextBlock(
+ children: RootContent[],
+ index: number,
+): Paragraph | null {
+ const nextNode = children[index + 1];
+
+ // Ensure the next node exists and is a paragraph
+ if (nextNode && nextNode.type === "paragraph") {
+ // console.log(nextNode)
+ // Wrap links in blocks if applicable
+ const wrappedParagraphs = wrapLinksInBlocks(nextNode);
+
+ // If the paragraph has been modified, replace it in the children array
+ if (wrappedParagraphs.length > 0) {
+ children.splice(index + 1, 1, ...wrappedParagraphs);
+ return wrappedParagraphs[0] as Paragraph;
+ }
+ }
+
+ // If no wrapping was done, return null to signal no changes
+ return null;
+}
+
+// Alignments to CSS class mapping
+type Alignments = "center" | "left" | "right";
+const alignToClassMap: Record = {
+ center: "flex justify-center items-center",
+ left: "flex justify-start items-center",
+ right: "flex justify-end items-center",
+};
diff --git a/docs/src/utils/md_to_mdx_aot.ts b/docs/src/utils/md_to_mdx_aot.ts
index a59fc69cf..89df7c049 100644
--- a/docs/src/utils/md_to_mdx_aot.ts
+++ b/docs/src/utils/md_to_mdx_aot.ts
@@ -22,65 +22,103 @@ async function writeMdxFile(
}
}
-async function convertMarkdownToMdx(
- filePath: string,
- outputFilePath: string,
- description: string,
- pagefind = true,
-): Promise {
+async function convertMarkdownToMdx(file: ConvertFileType): Promise {
try {
- const markdown = await readMarkdownFile(filePath);
- const mdxContent = await transformMarkdownToMdx(
- markdown,
- description,
- pagefind,
- );
- await writeMdxFile(outputFilePath, mdxContent);
+ const markdown = await readMarkdownFile(file.input);
+ const mdxContent = await transformMarkdownToMdx(markdown, file.docs);
+ await writeMdxFile(file.output, mdxContent);
} catch (err) {
console.error(`Error during conversion: ${err}`);
throw err;
}
}
-// Convert the actual files.
-convertMarkdownToMdx(
- "../local-remote-execution/README.md",
- "src/content/docs/explanations/lre.mdx",
- "Local Remote Execution architecture",
-);
-convertMarkdownToMdx(
- "../CONTRIBUTING.md",
- "src/content/docs/contribute/guidelines.mdx",
- "NativeLink contribution guidelines",
-);
-convertMarkdownToMdx(
- "README.md",
- "src/content/docs/contribute/docs.mdx",
- "Working on documentation",
-);
-convertMarkdownToMdx(
- "../nativelink-config/README.md",
- "src/content/docs/config/configuration-intro.mdx",
- "NativeLink configuration guide",
-);
-convertMarkdownToMdx(
- "../deployment-examples/chromium/README.md",
- "src/content/docs/deployment-examples/chromium.mdx",
- "NativeLink deployment example for Chromium",
-);
-convertMarkdownToMdx(
- "../deployment-examples/kubernetes/README.md",
- "src/content/docs/deployment-examples/kubernetes.mdx",
- "NativeLink deployment example for Kubernetes",
-);
-convertMarkdownToMdx(
- "../CHANGELOG.md",
- "src/content/docs/reference/changelog.mdx",
- "NativeLink's Changelog",
- false, // Set pagefind to false for changelog
-);
-convertMarkdownToMdx(
- "../README.md",
- "src/content/docs/introduction/setup.mdx",
- "Get started with NativeLink",
-);
+export type ConvertFileType = {
+ input: string;
+ output: string;
+ docs: {
+ title: string;
+ description: string;
+ pagefind?: boolean;
+ assets?: string[];
+ };
+};
+
+// Directories
+const rootDir = "../";
+const docsDir = "src/content/docs";
+const assetsDir = "@assets";
+
+const filesToConvert: ConvertFileType[] = [
+ {
+ input: `${rootDir}/local-remote-execution/README.md`,
+ output: `${docsDir}/explanations/lre.mdx`,
+ docs: {
+ title: "Local Remote Execution",
+ description: "Local Remote Execution architecture",
+ },
+ },
+ {
+ input: `${rootDir}/CONTRIBUTING.md`,
+ output: `${docsDir}/contribute/guidelines.mdx`,
+ docs: {
+ title: "NativeLink contribution guidelines",
+ description: "Contribution Guidelines",
+ },
+ },
+ {
+ input: "README.md",
+ output: `${docsDir}/contribute/docs.mdx`,
+ docs: {
+ title: "The NativeLink documentation",
+ description: "Working on documentation",
+ },
+ },
+ {
+ input: `${rootDir}/nativelink-config/README.md`,
+ output: `${docsDir}/config/configuration-intro.mdx`,
+ docs: {
+ title: "NativeLink configuration guide",
+ description: "NativeLink configuration guide",
+ },
+ },
+ {
+ input: `${rootDir}/deployment-examples/chromium/README.md`,
+ output: `${docsDir}/deployment-examples/chromium.mdx`,
+ docs: {
+ title: "NativeLink deployment example for Chromium",
+ description: "NativeLink deployment example for Chromium",
+ },
+ },
+ {
+ input: `${rootDir}/deployment-examples/kubernetes/README.md`,
+ output: `${docsDir}/deployment-examples/kubernetes.mdx`,
+ docs: {
+ title: "Local Remote Execution architecture",
+ description: "Local Remote Execution architecture",
+ },
+ },
+ {
+ input: `${rootDir}/CHANGELOG.md`,
+ output: `${docsDir}/reference/changelog.mdx`,
+ docs: {
+ title: "Changelog",
+ description: "NativeLink's Changelog",
+ pagefind: false, // Set pagefind to false for changelog
+ },
+ },
+ {
+ input: `${rootDir}/README.md`,
+ output: `${docsDir}/introduction/setup.mdx`,
+ docs: {
+ title: "Introduction",
+ description: "Get started with NativeLink",
+ pagefind: true,
+ assets: [`${assetsDir}/logo-dark.svg`, `${assetsDir}/logo-light.svg`],
+ },
+ },
+];
+
+filesToConvert.map((file) => {
+ convertMarkdownToMdx(file);
+});
diff --git a/docs/starlight.conf.ts b/docs/starlight.conf.ts
index dcda3f7a1..0bc84bc04 100644
--- a/docs/starlight.conf.ts
+++ b/docs/starlight.conf.ts
@@ -34,7 +34,7 @@ export const starlightConfig = {
// See https://diataxis.fr/ for details.
{
label: "Getting Started",
- collapsed: false,
+ collapsed: true,
items: [
{
label: "Introduction",
@@ -55,7 +55,7 @@ export const starlightConfig = {
// content without elaborate explanations. Tutorials should have a
// clear goal and a straightforward "follow-these-commands" structure.
label: "NativeLink Cloud",
- collapsed: false,
+ collapsed: true,
items: [
{
label: "Bazel",
@@ -84,7 +84,7 @@ export const starlightConfig = {
// need to be "complete". They should provide practical guidance for
// real-world use-cases.
label: "Configuring NativeLink",
- collapsed: false,
+ collapsed: true,
items: [
{
label: "Configuration Introduction",
@@ -105,7 +105,7 @@ export const starlightConfig = {
// need to be "complete". They should provide practical guidance for
// real-world use-cases.
label: "On-Prem Examples",
- collapsed: false,
+ collapsed: true,
items: [
{
label: "On-Prem Overview",
@@ -126,7 +126,7 @@ export const starlightConfig = {
// internal functionality and design concepts. Explanations should
// explain design decisions, constraints, etc.
label: "Understanding NativeLink",
- collapsed: false,
+ collapsed: true,
items: [
{
label: "Architecture",
@@ -147,7 +147,7 @@ export const starlightConfig = {
// common questions and confusions about esoteric tooling and
// concepts. It aims to help new users feel more at ease and
label: "FAQ",
- collapsed: false,
+ collapsed: true,
items: [
{
label: "Is NativeLink Free?",
@@ -188,7 +188,7 @@ export const starlightConfig = {
// contributors. They should provide practical guidance for
// real-world use-cases.
label: "For Contributors",
- collapsed: false,
+ collapsed: true,
items: [
{
label: "Contribution Guidelines",
@@ -217,7 +217,7 @@ export const starlightConfig = {
// descriptions with the intent to be used as consulting material.
// Mostly autogenerated to stay in sync with the codebase.
label: "Reference",
- collapsed: false,
+ collapsed: true,
items: [
{
label: "Glossary",
diff --git a/docs/tsconfig.json b/docs/tsconfig.json
index 1057e7cab..4da5cd7af 100644
--- a/docs/tsconfig.json
+++ b/docs/tsconfig.json
@@ -3,7 +3,8 @@
"compilerOptions": {
"baseUrl": ".",
"paths": {
- "@components/*": ["./src/components/*"]
+ "@components/*": ["./src/components/*"],
+ "@assets/*": ["./src/assets/*"]
}
}
}