@nubisco/docs-sdk 0.0.0-stage → 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nubisco
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to use,
8
+ copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
9
+ Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,102 @@
1
- # Temporary Holding Version
1
+ <p align="center">
2
+ <img src="fixture/docs/public/logo.svg" alt="Nubisco" width="96" />
3
+ </p>
2
4
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
5
+ <h1 align="center">@nubisco/docs-sdk</h1>
6
+
7
+ <p align="center">The Nubisco documentation design as one package: VitePress, the theme, the plugins and a config helper. A product supplies its content and a small config.</p>
8
+
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/@nubisco/docs-sdk"><img src="https://img.shields.io/npm/v/@nubisco/docs-sdk" alt="npm" /></a>
11
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/@nubisco/docs-sdk" alt="license" /></a>
12
+ </p>
13
+
14
+ ## What it gives you
15
+
16
+ - **The design.** Neutral layer colours, a page header that is an inset card and closes
17
+ into a bar as you scroll, tabs that are pages, a left navigation with a filter, and
18
+ "On this page" on the right. Light, dark and auto.
19
+ - **VitePress, bundled.** Your project depends on this package, not on VitePress. One
20
+ version of VitePress across every site.
21
+ - **The plugins.** Tabs, mermaid diagrams and grouped code icons, already wired.
22
+ - **A config helper.** `defineNubiscoDocs` sets everything the design fixes. You state
23
+ your name, address, repository, navigation and footer.
24
+ - **A CLI.** `nubisco-docs dev | build | preview`.
25
+
26
+ ## Install
27
+
28
+ ```sh
29
+ pnpm add -D @nubisco/docs-sdk @nubisco/ui vue
30
+ ```
31
+
32
+ `@nubisco/ui` and `vue` are peer dependencies: the theme is built from the library's
33
+ components and tokens, and there must be one copy of each.
34
+
35
+ ## Use
36
+
37
+ ```ts
38
+ // docs/.vitepress/config.ts
39
+ import { defineNubiscoDocs } from '@nubisco/docs-sdk'
40
+
41
+ export default defineNubiscoDocs({
42
+ title: 'Acta',
43
+ description: 'What Acta is, in one sentence.',
44
+ base: '/acta/',
45
+ hostname: 'https://docs.nubisco.io/acta/',
46
+ repo: 'nubisco/acta',
47
+ nav: [
48
+ { text: 'Users', link: '/users/' },
49
+ { text: 'Developers', link: '/developers/' },
50
+ ],
51
+ sidebar: {
52
+ '/users/': [
53
+ { text: 'Start', items: [{ text: 'Welcome', link: '/users/' }] },
54
+ ],
55
+ },
56
+ footer: {
57
+ copyright: 'Copyright © 2026 <a href="https://nubisco.io">Nubisco</a>',
58
+ },
59
+ })
60
+ ```
61
+
62
+ ```ts
63
+ // docs/.vitepress/theme/index.ts
64
+ import theme from '@nubisco/docs-sdk/theme'
65
+ export default theme
66
+ ```
67
+
68
+ ```json
69
+ {
70
+ "scripts": {
71
+ "docs:dev": "nubisco-docs dev",
72
+ "docs:build": "nubisco-docs build"
73
+ }
74
+ }
75
+ ```
76
+
77
+ Pages opt in with `layout: nubisco` in frontmatter. The fields the layout reads are
78
+ `title`, `intro` (one paragraph of inline Markdown), `status` (`stable`, `beta`, `labs`...),
79
+ `source` (a path in the repository, for the source link) and, for a page with facets,
80
+ `pageTabs` plus `tab`.
81
+
82
+ The `fixture/` folder is a complete small site that uses the package exactly as above. It is
83
+ built in CI on every change.
84
+
85
+ ## Contributing
86
+
87
+ See [CONTRIBUTING.md](CONTRIBUTING.md). Contributions are made under the
88
+ [Contributor License Agreement](docs/CLA-INDIVIDUAL.md). Security reports: see
89
+ [SECURITY.md](SECURITY.md).
90
+
91
+ ## Acknowledgements
92
+
93
+ The layout draws inspiration from [IBM Carbon Design System](https://carbondesignsystem.com)
94
+ documentation structure. Carbon is the work of IBM and its contributors, licensed under Apache 2.0.
95
+ The tabs and mermaid plugins are adapted from `vitepress-plugin-tabs` and
96
+ `vitepress-plugin-mermaid`, both MIT. See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
97
+
98
+ ---
99
+
100
+ ## License
101
+
102
+ [MIT](LICENSE)
@@ -0,0 +1,100 @@
1
+ # Third-party notices
2
+
3
+ `@nubisco/docs-sdk` is released under the MIT License (see `LICENSE`). It contains code
4
+ adapted from the projects below, and it is used with the fonts and libraries listed at
5
+ the end. Each keeps its own licence and copyright, reproduced here as those licences
6
+ require.
7
+
8
+ ## Code adapted into this package
9
+
10
+ ### vitepress-plugin-tabs
11
+
12
+ Adapted into `src/plugins/tabs/` (the tabs markdown rule and the tab components).
13
+ Source: https://github.com/sapphi-red/vitepress-plugins (package `vitepress-plugin-tabs`, MIT).
14
+
15
+ ```
16
+ MIT License
17
+
18
+ Copyright (c) 2022 sapphi-red
19
+
20
+ Permission is hereby granted, free of charge, to any person obtaining a copy
21
+ of this software and associated documentation files (the "Software"), to deal
22
+ in the Software without restriction, including without limitation the rights
23
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24
+ copies of the Software, and to permit persons to whom the Software is
25
+ furnished to do so, subject to the following conditions:
26
+
27
+ The above copyright notice and this permission notice shall be included in all
28
+ copies or substantial portions of the Software.
29
+
30
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36
+ SOFTWARE.
37
+ ```
38
+
39
+ ### vitepress-plugin-mermaid
40
+
41
+ Adapted into `src/plugins/mermaid/` (the mermaid markdown rule, the Vite plugin and the
42
+ diagram component). Source: https://github.com/emersonbottero/vitepress-plugin-mermaid
43
+ (package `vitepress-plugin-mermaid`, MIT).
44
+
45
+ ```
46
+ MIT License
47
+
48
+ Copyright (c) 2022 emersonbottero
49
+
50
+ Permission is hereby granted, free of charge, to any person obtaining a copy
51
+ of this software and associated documentation files (the "Software"), to deal
52
+ in the Software without restriction, including without limitation the rights
53
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
54
+ copies of the Software, and to permit persons to whom the Software is
55
+ furnished to do so, subject to the following conditions:
56
+
57
+ The above copyright notice and this permission notice shall be included in all
58
+ copies or substantial portions of the Software.
59
+
60
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
65
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
66
+ SOFTWARE.
67
+ ```
68
+
69
+ ## Design reference (no code taken)
70
+
71
+ The layout draws on the structure of the documentation of IBM's Carbon Design System
72
+ (https://carbondesignsystem.com), which is the work of IBM and its contributors and is
73
+ licensed under Apache 2.0. This package contains none of Carbon's code, assets or marks.
74
+ "Carbon" and "IBM" are trademarks of International Business Machines Corporation.
75
+
76
+ ## Dependencies
77
+
78
+ Installed with this package, not copied into it. Their licences travel with them.
79
+
80
+ | Package | Licence |
81
+ | --- | --- |
82
+ | `vitepress`, `vue`, `vite`, `mermaid`, `vite-svg-loader`, `vitepress-plugin-group-icons`, `markdown-it-container`, `sass-embedded` | MIT |
83
+ | `@nubisco/ui` (peer dependency) | MIT |
84
+ | `@fontsource/plus-jakarta-sans` (Plus Jakarta Sans) | SIL Open Font License 1.1 |
85
+ | `@fontsource/fira-code` (Fira Code) | SIL Open Font License 1.1 |
86
+
87
+ ### Fonts
88
+
89
+ The sites this package builds serve Plus Jakarta Sans (Copyright 2020 The Plus Jakarta
90
+ Sans Project Authors, https://github.com/tokotype/PlusJakartaSans) and Fira Code
91
+ (Copyright 2014-2020 The Fira Code Project Authors, https://github.com/tonsky/FiraCode),
92
+ both under the SIL Open Font License, Version 1.1
93
+ (https://openfontlicense.org). The fonts are not part of this package's own files: they
94
+ come from the `@fontsource` packages, which carry the full licence text. A site that
95
+ republishes the font files keeps that licence file with them.
96
+
97
+ ### Icons
98
+
99
+ The icons the theme draws come from `@nubisco/ui`, which builds them from Phosphor Icons
100
+ (https://phosphoricons.com, MIT, Copyright (c) 2023 Phosphor Icons).
package/dist/cli.js ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/node/cli.ts
4
+ import { build, createServer, serve } from "vitepress";
5
+ var USAGE = `nubisco-docs <command> [root] [--port <n>]
6
+
7
+ dev start the dev server
8
+ build build the static site
9
+ preview serve a built site
10
+
11
+ root is the docs folder, "docs" by default.`;
12
+ var [command, ...rest] = process.argv.slice(2);
13
+ var flagAt = rest.indexOf("--port");
14
+ var port = flagAt === -1 ? void 0 : Number(rest[flagAt + 1]);
15
+ var root = rest.find((arg, i) => !arg.startsWith("--") && rest[i - 1] !== "--port") ?? "docs";
16
+ async function main() {
17
+ if (command === "dev") {
18
+ const server = await createServer(root, { port });
19
+ await server.listen();
20
+ server.printUrls();
21
+ } else if (command === "build") {
22
+ await build(root);
23
+ } else if (command === "preview") {
24
+ await serve({ root, port });
25
+ } else {
26
+ console.error(USAGE);
27
+ process.exit(command ? 1 : 0);
28
+ }
29
+ }
30
+ main().catch((error) => {
31
+ console.error(error);
32
+ process.exit(1);
33
+ });
@@ -0,0 +1,78 @@
1
+ import { DefaultTheme, UserConfig } from 'vitepress';
2
+
3
+ /** What the Nubisco theme reads from `themeConfig.nubisco`. */
4
+ interface INubiscoDocsThemeConfig {
5
+ /** `owner/name` on GitHub. Drives the source and issue links in the page header. */
6
+ repo?: string;
7
+ /** The branch the source links point at. Defaults to `master`. */
8
+ branch?: string;
9
+ /**
10
+ * Show the Square and Round switch beside the colour mode. It belongs to the
11
+ * component library's own docs and is off everywhere else.
12
+ */
13
+ appearanceControl?: boolean;
14
+ }
15
+ interface INubiscoDocsOptions {
16
+ /** The product's name, shown in the top bar and the page header. */
17
+ title: string;
18
+ /** One sentence, for search engines and link previews. */
19
+ description: string;
20
+ /** URL prefix the site is served under, with both slashes: `/acta/`. */
21
+ base: string;
22
+ /** The public address of the site, for the sitemap: `https://docs.nubisco.io/acta/`. */
23
+ hostname: string;
24
+ /** `owner/name` on GitHub: `nubisco/acta`. */
25
+ repo: string;
26
+ /** Branch the edit and source links point at. Defaults to `master`. */
27
+ branch?: string;
28
+ /** Folder of the docs inside the repository, for the edit link. Defaults to `docs/`. */
29
+ docsDir?: string;
30
+ /** Path of the product's mark under `public/`. Defaults to `/logo.svg`. */
31
+ logo?: string;
32
+ /** Browser chrome colour. Defaults to the dark ground. */
33
+ themeColor?: string;
34
+ /** The top bar's links, in the order the standard sets (see the docs standard). */
35
+ nav: DefaultTheme.NavItem[];
36
+ /** The left navigation. Keyed by path prefix, or one list. */
37
+ sidebar: DefaultTheme.Sidebar;
38
+ /** HTML for the two footer lines. Links are allowed. */
39
+ footer?: {
40
+ message?: string;
41
+ copyright?: string;
42
+ };
43
+ /** Analytics script. Nubisco's by default, `false` for none. */
44
+ analytics?: string | false;
45
+ /** Show the Square and Round switch. Component library only. */
46
+ appearanceControl?: boolean;
47
+ /**
48
+ * Anything else VitePress accepts, merged over the defaults. `vite` and
49
+ * `themeConfig` are merged one level deep, `head` is appended, and a
50
+ * `markdown.config` is called after the SDK's own.
51
+ */
52
+ vitepress?: UserConfig<DefaultTheme.Config>;
53
+ }
54
+
55
+ /**
56
+ * The VitePress config for a Nubisco product's documentation.
57
+ *
58
+ * ```ts
59
+ * // docs/.vitepress/config.ts
60
+ * import { defineNubiscoDocs } from '@nubisco/docs-sdk'
61
+ *
62
+ * export default defineNubiscoDocs({
63
+ * title: 'Acta',
64
+ * description: '…',
65
+ * base: '/acta/',
66
+ * hostname: 'https://docs.nubisco.io/acta/',
67
+ * repo: 'nubisco/acta',
68
+ * nav: [...],
69
+ * sidebar: { ... },
70
+ * })
71
+ * ```
72
+ *
73
+ * Everything the design standard fixes is set here, so a product states only
74
+ * what is its own: its name, its address, its navigation and its footer.
75
+ */
76
+ declare function defineNubiscoDocs(options: INubiscoDocsOptions): UserConfig<DefaultTheme.Config>;
77
+
78
+ export { type INubiscoDocsOptions, type INubiscoDocsThemeConfig, defineNubiscoDocs };
package/dist/index.js ADDED
@@ -0,0 +1,361 @@
1
+ // src/node/index.ts
2
+ import { defineConfig } from "vitepress";
3
+ import svgLoader from "vite-svg-loader";
4
+ import {
5
+ groupIconMdPlugin,
6
+ groupIconVitePlugin
7
+ } from "vitepress-plugin-group-icons";
8
+ import { nubiscoUI } from "@nubisco/ui/vite";
9
+ import { fonts } from "@nubisco/ui/plugins/fonts";
10
+
11
+ // src/plugins/tabs/markdown/markdownPlugin.ts
12
+ import container from "markdown-it-container";
13
+
14
+ // src/plugins/tabs/markdown/ruleBlockTab.ts
15
+ var tabMarker = "=";
16
+ var tabMarkerCode = tabMarker.charCodeAt(0);
17
+ var minTabMarkerLen = 2;
18
+ var ruleBlockTab = (state, startLine, endLine, silent) => {
19
+ let pos = state.bMarks[startLine] + state.tShift[startLine];
20
+ const max = state.eMarks[startLine];
21
+ if (state.parentType !== "container") {
22
+ return false;
23
+ }
24
+ if (pos + minTabMarkerLen > max) {
25
+ return false;
26
+ }
27
+ const marker = state.src.charCodeAt(pos);
28
+ if (marker !== tabMarkerCode) {
29
+ return false;
30
+ }
31
+ const mem = pos;
32
+ pos = state.skipChars(pos + 1, marker);
33
+ const tabMarkerLen = pos - mem;
34
+ if (tabMarkerLen < minTabMarkerLen - 1) {
35
+ return false;
36
+ }
37
+ if (silent) {
38
+ return true;
39
+ }
40
+ let nextLine = startLine;
41
+ let endStart = mem;
42
+ let endPos = pos;
43
+ for (; ; ) {
44
+ nextLine++;
45
+ if (nextLine >= endLine) {
46
+ break;
47
+ }
48
+ endStart = state.bMarks[nextLine] + state.tShift[nextLine];
49
+ const max2 = state.eMarks[nextLine];
50
+ if (endStart < max2 && state.sCount[nextLine] < state.blkIndent) {
51
+ break;
52
+ }
53
+ const startCharCode = state.src.charCodeAt(endStart);
54
+ if (startCharCode !== tabMarkerCode) {
55
+ continue;
56
+ }
57
+ const p = state.skipChars(endStart + 1, marker);
58
+ if (p - endStart !== tabMarkerLen) {
59
+ continue;
60
+ }
61
+ endPos = p;
62
+ break;
63
+ }
64
+ const oldParent = state.parentType;
65
+ const oldLineMax = state.lineMax;
66
+ state.parentType = "tab";
67
+ state.lineMax = nextLine;
68
+ const startToken = state.push("tab_open", "div", 1);
69
+ startToken.markup = state.src.slice(mem, pos);
70
+ startToken.block = true;
71
+ startToken.info = state.src.slice(pos, max).trimStart();
72
+ startToken.map = [startLine, nextLine - 1];
73
+ state.md.block.tokenize(state, startLine + 1, nextLine);
74
+ const endToken = state.push("tab_close", "div", -1);
75
+ endToken.markup = state.src.slice(endStart, endPos);
76
+ endToken.block = true;
77
+ state.parentType = oldParent;
78
+ state.lineMax = oldLineMax;
79
+ state.line = nextLine;
80
+ return true;
81
+ };
82
+
83
+ // src/plugins/tabs/markdown/markdownPlugin.ts
84
+ var parseTabsParams = (input) => {
85
+ const match = input.match(/key:(\S+)/);
86
+ return {
87
+ shareStateKey: match?.[1]
88
+ };
89
+ };
90
+ var tabsPlugin = (md) => {
91
+ md.use(container, "tabs", {
92
+ render(tokens, index) {
93
+ const token = tokens[index];
94
+ if (token.nesting === 1) {
95
+ const params = parseTabsParams(token.info);
96
+ const shareStateKeyProp = params.shareStateKey ? `sharedStateKey="${md.utils.escapeHtml(params.shareStateKey)}"` : "";
97
+ return `<ContentTabs ${shareStateKeyProp}>
98
+ `;
99
+ } else {
100
+ return `</ContentTabs>
101
+ `;
102
+ }
103
+ }
104
+ });
105
+ md.block.ruler.after("container_tabs", "tab", ruleBlockTab);
106
+ const renderTab = (tokens, index) => {
107
+ const token = tokens[index];
108
+ if (token.nesting === 1) {
109
+ const label = token.info;
110
+ const labelProp = `label="${md.utils.escapeHtml(label)}"`;
111
+ return `<ContentTab ${labelProp}>
112
+ `;
113
+ } else {
114
+ return `</ContentTab>
115
+ `;
116
+ }
117
+ };
118
+ md.renderer.rules["tab_open"] = renderTab;
119
+ md.renderer.rules["tab_close"] = renderTab;
120
+ };
121
+
122
+ // src/plugins/mermaid/mermaid-markdown.ts
123
+ var MermaidMarkdown = (md, pluginOptions) => {
124
+ const fence = md.renderer.rules.fence.bind(md.renderer.rules);
125
+ md.renderer.rules.fence = (tokens, index, options, env, slf) => {
126
+ const token = tokens[index];
127
+ if (token.info.trim() === "mermaid") {
128
+ try {
129
+ const key = index;
130
+ const cssClass = pluginOptions?.class || "mermaid";
131
+ return `
132
+ <Suspense>
133
+ <template #default>
134
+ <Mermaid id="mermaid-${key}" class="${cssClass}" graph="${encodeURIComponent(token.content)}"></Mermaid>
135
+ </template>
136
+ <!-- loading state via #fallback slot -->
137
+ <template #fallback>
138
+ Loading...
139
+ </template>
140
+ </Suspense>`;
141
+ } catch (err) {
142
+ return `<pre>${err}</pre>`;
143
+ }
144
+ }
145
+ if (token.info.trim() === "mmd") {
146
+ tokens[index].info = "mermaid";
147
+ }
148
+ return fence(tokens, index, options, env, slf);
149
+ };
150
+ };
151
+
152
+ // src/plugins/mermaid/mermaid-plugin.ts
153
+ var DEFAULT_OPTIONS = {
154
+ // we set loose as default here because is needed to load images
155
+ securityLevel: "loose",
156
+ startOnLoad: false
157
+ };
158
+ function MermaidPlugin(inlineOptions) {
159
+ const options = {
160
+ ...DEFAULT_OPTIONS,
161
+ ...inlineOptions
162
+ };
163
+ const virtualModuleId = "virtual:mermaid-config";
164
+ const resolvedVirtualModuleId = "\0" + virtualModuleId;
165
+ return {
166
+ name: "vite-plugin-mermaid",
167
+ // The component is registered by the theme (`src/theme/index.ts`), not
168
+ // injected into VitePress's client entry by a path in the consumer's tree.
169
+ async resolveId(id) {
170
+ if (id === virtualModuleId) {
171
+ return resolvedVirtualModuleId;
172
+ }
173
+ },
174
+ async load(id) {
175
+ if (id === resolvedVirtualModuleId) {
176
+ return `export default ${JSON.stringify(options)};`;
177
+ }
178
+ }
179
+ };
180
+ }
181
+
182
+ // src/plugins/mermaid/index.ts
183
+ var withMermaid = (config) => {
184
+ if (!config.markdown) config.markdown = {};
185
+ const markdownConfigOriginal = config.markdown.config || (() => {
186
+ });
187
+ config.markdown.config = (...args) => {
188
+ MermaidMarkdown(...args, config.mermaidPlugin);
189
+ markdownConfigOriginal(...args);
190
+ };
191
+ if (!config.vite) config.vite = {};
192
+ if (!config.vite.plugins) config.vite.plugins = [];
193
+ config.vite.plugins.push(MermaidPlugin(config.mermaid));
194
+ if (!config.vite.optimizeDeps) config.vite.optimizeDeps = {};
195
+ if (!config.vite.optimizeDeps.include) config.vite.optimizeDeps.include = [];
196
+ config.vite.optimizeDeps.include = [
197
+ ...config.vite.optimizeDeps.include,
198
+ "@braintree/sanitize-url",
199
+ "dayjs",
200
+ "debug",
201
+ "cytoscape-cose-bilkent",
202
+ "cytoscape"
203
+ ];
204
+ if (!config.vite.resolve) config.vite.resolve = {};
205
+ const mermaidPluginAlias = {
206
+ "dayjs/plugin/advancedFormat.js": "dayjs/esm/plugin/advancedFormat",
207
+ "dayjs/plugin/customParseFormat.js": "dayjs/esm/plugin/customParseFormat",
208
+ "dayjs/plugin/isoWeek.js": "dayjs/esm/plugin/isoWeek",
209
+ "cytoscape/dist/cytoscape.umd.js": "cytoscape/dist/cytoscape.esm.js"
210
+ };
211
+ if (!config.vite.resolve.alias) config.vite.resolve.alias = mermaidPluginAlias;
212
+ else if (Array.isArray(config.vite.resolve.alias)) {
213
+ config.vite.resolve.alias = [
214
+ ...config.vite.resolve.alias,
215
+ ...Object.entries(mermaidPluginAlias).map(([find, replacement]) => ({
216
+ find,
217
+ replacement
218
+ }))
219
+ ];
220
+ } else {
221
+ config.vite.resolve.alias = {
222
+ ...config.vite.resolve.alias,
223
+ ...mermaidPluginAlias
224
+ };
225
+ }
226
+ return config;
227
+ };
228
+
229
+ // src/node/index.ts
230
+ var ANALYTICS = "https://analytics.nubisco.io/script.js";
231
+ function defineNubiscoDocs(options) {
232
+ const base = options.base;
233
+ const logo = options.logo ?? "/logo.svg";
234
+ const extra = options.vitepress ?? {};
235
+ const analytics = options.analytics ?? ANALYTICS;
236
+ const docsDir = options.docsDir ?? "docs/";
237
+ const branch = options.branch ?? "master";
238
+ const config = defineConfig({
239
+ ...extra,
240
+ title: options.title,
241
+ description: options.description,
242
+ base,
243
+ // The theme owns light and dark (`useTheme()` sets `.dark`), so VitePress's
244
+ // own appearance switch stays off.
245
+ appearance: false,
246
+ // `_shared.md` fragments are included by tab pages. They are not pages.
247
+ srcExclude: ["**/_*.md", ...extra.srcExclude ?? []],
248
+ lastUpdated: true,
249
+ head: [
250
+ ["link", { rel: "icon", href: `${base}favicon.ico`, sizes: "any" }],
251
+ [
252
+ "link",
253
+ {
254
+ rel: "icon",
255
+ type: "image/png",
256
+ sizes: "32x32",
257
+ href: `${base}favicon-32x32.png`
258
+ }
259
+ ],
260
+ [
261
+ "link",
262
+ {
263
+ rel: "icon",
264
+ type: "image/png",
265
+ sizes: "16x16",
266
+ href: `${base}favicon-16x16.png`
267
+ }
268
+ ],
269
+ [
270
+ "link",
271
+ {
272
+ rel: "apple-touch-icon",
273
+ sizes: "180x180",
274
+ href: `${base}apple-touch-icon.png`
275
+ }
276
+ ],
277
+ ["link", { rel: "manifest", href: `${base}site.webmanifest` }],
278
+ [
279
+ "meta",
280
+ { name: "theme-color", content: options.themeColor ?? "#0d0d0f" }
281
+ ],
282
+ ...analytics ? [
283
+ ["script", { defer: "", src: analytics }]
284
+ ] : [],
285
+ ...extra.head ?? []
286
+ ],
287
+ markdown: {
288
+ ...extra.markdown,
289
+ config(md) {
290
+ md.use(tabsPlugin);
291
+ md.use(groupIconMdPlugin);
292
+ extra.markdown?.config?.(md);
293
+ }
294
+ },
295
+ sitemap: { hostname: options.hostname, ...extra.sitemap },
296
+ vite: {
297
+ ...extra.vite,
298
+ plugins: [
299
+ svgLoader(),
300
+ groupIconVitePlugin(),
301
+ // The theme passes icon modules to NbIcon at run time, which the glyph
302
+ // transform cannot see through. They need no catalogue.
303
+ nubiscoUI({ glyphs: { catalog: "off", warnUnresolved: false } }),
304
+ fonts(),
305
+ ...extra.vite?.plugins ?? []
306
+ ],
307
+ ssr: {
308
+ ...extra.vite?.ssr,
309
+ // The theme and the library ship Vue sources and ESM, which VitePress
310
+ // must compile with the page, not load from node_modules as is.
311
+ noExternal: [
312
+ "@nubisco/docs-sdk",
313
+ "@nubisco/ui",
314
+ "vue",
315
+ ...extra.vite?.ssr?.noExternal ?? []
316
+ ]
317
+ },
318
+ optimizeDeps: {
319
+ ...extra.vite?.optimizeDeps,
320
+ exclude: [
321
+ "@nubisco/docs-sdk",
322
+ ...extra.vite?.optimizeDeps?.exclude ?? []
323
+ ]
324
+ },
325
+ css: {
326
+ ...extra.vite?.css,
327
+ preprocessorOptions: {
328
+ scss: { api: "modern-compiler" },
329
+ ...extra.vite?.css?.preprocessorOptions
330
+ }
331
+ }
332
+ },
333
+ themeConfig: {
334
+ siteTitle: options.title,
335
+ logo: { src: logo, width: 24, height: 24 },
336
+ nav: options.nav,
337
+ sidebar: options.sidebar,
338
+ socialLinks: [
339
+ { icon: "github", link: `https://github.com/${options.repo}` }
340
+ ],
341
+ editLink: {
342
+ pattern: `https://github.com/${options.repo}/edit/${branch}/${docsDir}:path`,
343
+ text: "Edit this page on GitHub"
344
+ },
345
+ search: { provider: "local" },
346
+ lastUpdated: { text: "Last updated" },
347
+ footer: options.footer,
348
+ ...extra.themeConfig,
349
+ // Read by the theme. Typed in `INubiscoDocsThemeConfig`.
350
+ nubisco: {
351
+ repo: options.repo,
352
+ branch,
353
+ appearanceControl: options.appearanceControl ?? false
354
+ }
355
+ }
356
+ });
357
+ return withMermaid(config);
358
+ }
359
+ export {
360
+ defineNubiscoDocs
361
+ };