diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 31070574..cf12605d 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -1,13 +1,13 @@ import { URL, fileURLToPath } from 'node:url' import { resolve } from 'path' import { defineConfig } from 'vitepress' +import { getSidebarItemsFromMdFiles } from './utils.mts' // https://vitepress.dev/reference/site-config export default defineConfig({ appearance: 'force-dark', srcDir: 'src', title: 'KitOps', - titleTemplate: 'KitOps', description: 'Documentation for KitOps', head: [ @@ -51,7 +51,6 @@ export default defineConfig({ text: 'Getting started', items: [ { text: 'Overview', link: '/docs/overview' }, - { text: 'Installation', link: '/docs/cli/installation' }, { text: 'Use Cases', link: '/docs/use-cases' }, { text: 'Why KitOps?', link: '/docs/why-kitops' }, ] @@ -72,10 +71,13 @@ export default defineConfig({ }, { text: 'CLI', - items: [ - { text: 'Download & Install', link: '/docs/cli/installation' }, - { text: 'Command Reference', link: '/docs/cli/kit' }, - ] + items: getSidebarItemsFromMdFiles('docs/cli', { + replacements: { + 'cli-reference': 'Command Reference' , + 'installation': 'Download & Install' + }, + textFormat: (text) => text.replaceAll('cli-', '') + }) }, { text: 'MLOps with Kitfile', diff --git a/docs/.vitepress/theme/components/Home.vue b/docs/.vitepress/theme/components/Home.vue index 6271647b..a6a1a474 100644 --- a/docs/.vitepress/theme/components/Home.vue +++ b/docs/.vitepress/theme/components/Home.vue @@ -8,7 +8,7 @@ import { VueMarqueeSlider } from 'vue3-marquee-slider'

Share and run your models anywhere

Bridge the gap between ML and Application teams

- Install + Install
@@ -83,7 +83,7 @@ import { VueMarqueeSlider } from 'vue3-marquee-slider'
1

Download and install Kit CLI.

- Install the CLI + Install the CLI
@@ -91,7 +91,7 @@ import { VueMarqueeSlider } from 'vue3-marquee-slider'
2

Create a simple manifest file called a Kitfile with your model, dataset and code. Then build and push the ModelKit to a registry for sharing.

- LEARN MORE + LEARN MORE
@@ -99,7 +99,7 @@ import { VueMarqueeSlider } from 'vue3-marquee-slider'
3

Pull the ModelKit into your pipeline, or use kit dev to start working with the model.

- USE CASES + USE CASES
diff --git a/docs/.vitepress/utils.mts b/docs/.vitepress/utils.mts new file mode 100644 index 00000000..26179c7f --- /dev/null +++ b/docs/.vitepress/utils.mts @@ -0,0 +1,106 @@ +// Adapted from https://github.com/vuejs/vitepress/issues/1737#issuecomment-1372010207 +import * as fs from 'fs' +import { resolve } from 'path' + +type ScanOptions = { + capitalize?: boolean, + replacements?: Record, + textFormat: (text: string) => string +} + +// Path where our docs are living. +const BASE_PATH = resolve(__dirname, '../src/') + +/** + * Capitalize a given text. + * @param {string} text - text to capitalize + * @returns {string} + */ +function capitalize(text: string) { + return text[0].toUpperCase() + text.slice(1) +} + +/** + * Given a folder path and an optional set of options, deep scan the folder for *.md files and return an array of items. + * @param pathName The path to the folder with the *.md files to scan + * @param options The options + * @returns {Array} + */ +export function getSidebarItemsFromMdFiles(pathName: string, options: Partial) { + const defaults: ScanOptions = { + capitalize: true, + textFormat: (text) => text.replace(/[-_]/g, ' ') + } + + const path = resolve(BASE_PATH, `../src/${pathName}`) + + return getItems(path, { + ...defaults, + ...options + }) +} + +// Read the folder and return the `{ text, items }` array. +function getItems(path: string, options: Partial) { + let content = fs.readdirSync(path).filter(item => !item.startsWith('.')) + + if (!content) { + return; + } + + const getFormattedText = (text: string) => { + let formattedText = options.textFormat(text) + + // If a custom label was provided, use that as-is and don't capitalize it to respect custom values. + if (options.replacements && options.replacements[text]) { + formattedText = options.replacements[text] + } else + // Otherwise, just check the `capitalize` flag. + if (options.capitalize) { + formattedText = capitalize(formattedText) + } + + return formattedText; + } + + let arr = content.map((item) => { + const text = getFormattedText(item.split('.')[0]) + + // If is content, just resolve it. + if (item.endsWith('.md')) { + return { + text, + link: resolve(path.replace(BASE_PATH, ''), item), + } + } else { + const newPath = resolve(path, item) + const isFolder = fs.lstatSync(newPath).isDirectory() + + if (!isFolder) { + return + } + + // If is a folder, recursively handle it. + return { + text, + items: getItems(newPath, options), + collapsible: true, + } + } + }) + + arr = arr.flatMap((item) => { + if (item?.link) { + item.link = normalizeLink(item.link) + } + + return item + }) + + return arr +} + +// Normalize a given path and return the `link` value in a standard, normalized format. +function normalizeLink(path) { + return path.replace(/\\/g, '/').split('.')[0] +} diff --git a/docs/src/docs/cli/cli-reference.md b/docs/src/docs/cli/cli-reference.md index 87769342..d6cf617e 100644 --- a/docs/src/docs/cli/cli-reference.md +++ b/docs/src/docs/cli/cli-reference.md @@ -340,7 +340,7 @@ Create a tag that refers to a modelkit ### Synopsis -Create or update a tag that refers to +Create or update a tag {target-modelkit} that refers to {source-modelkit} This command assigns a new tag to an existing modelkit (source-modelkit) or updates an existing tag, effectively renaming or categorizing modelkits for diff --git a/docs/src/docs/cli/usage.md b/docs/src/docs/cli/usage.md index 7ae30b85..00010f48 100644 --- a/docs/src/docs/cli/usage.md +++ b/docs/src/docs/cli/usage.md @@ -48,7 +48,7 @@ Then you can push it to your registry: $ ./kit push localhost:5050/example-repo:example-tag --http ``` -After you finish calling all your friends and telling them about Kit, they will want to fetch your ModelKit and run it. The `fetch` command is used to bring everything in the ModelKit to your local machine - the model, dataset(s), code, and the [Kitfile](../kitfile/overview.md) manifest. +After you finish calling all your friends and telling them about Kit, they will want to fetch your ModelKit and run it. The `fetch` command is used to bring everything in the ModelKit to your local machine - the model, dataset(s), code, and the [Kitfile](../kitfile/kf-overview.md) manifest. ```sh $ ./kit fetch localhost:5050/test-repo:test-tag --http @@ -74,4 +74,4 @@ The `dev` command will automatically generate a RESTful API for the model and th $ ./kit dev ``` -So with a few easy commands you've been able to package up a model, share it with others, and run it locally...and you never needed to learn Dockerfile syntax or how to deal with a Helm chart or other proprietary packaging method. \ No newline at end of file +So with a few easy commands you've been able to package up a model, share it with others, and run it locally...and you never needed to learn Dockerfile syntax or how to deal with a Helm chart or other proprietary packaging method. diff --git a/pkg/cmd/tag/cmd.go b/pkg/cmd/tag/cmd.go index 857722c2..c7aab233 100644 --- a/pkg/cmd/tag/cmd.go +++ b/pkg/cmd/tag/cmd.go @@ -13,7 +13,7 @@ import ( const ( shortDesc = "Create a tag that refers to a modelkit" - longDesc = `Create or update a tag that refers to + longDesc = `Create or update a tag {target-modelkit} that refers to {source-modelkit} This command assigns a new tag to an existing modelkit (source-modelkit) or updates an existing tag, effectively renaming or categorizing modelkits for