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
@@ -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