doccupine 0.0.24 β 0.0.26
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/dist/index.js +90 -2
- package/dist/templates/app/layout.d.ts +1 -1
- package/dist/templates/app/layout.js +10 -4
- package/dist/templates/components/MDXComponents.d.ts +1 -1
- package/dist/templates/components/MDXComponents.js +2 -0
- package/dist/templates/components/layout/ActionBar.d.ts +1 -1
- package/dist/templates/components/layout/ActionBar.js +1 -1
- package/dist/templates/components/layout/GlobalStyles.d.ts +1 -1
- package/dist/templates/components/layout/GlobalStyles.js +4 -0
- package/dist/templates/mdx/deployment.mdx.d.ts +1 -1
- package/dist/templates/mdx/deployment.mdx.js +1 -1
- package/dist/templates/mdx/fonts.mdx.d.ts +1 -0
- package/dist/templates/mdx/fonts.mdx.js +121 -0
- package/dist/templates/mdx/index.mdx.d.ts +1 -1
- package/dist/templates/mdx/index.mdx.js +24 -8
- package/dist/templates/mdx/navigation.mdx.d.ts +1 -1
- package/dist/templates/mdx/navigation.mdx.js +1 -0
- package/dist/templates/mdx/steps.mdx.d.ts +1 -1
- package/dist/templates/mdx/steps.mdx.js +0 -1
- package/dist/templates/package.js +7 -7
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -55,6 +55,7 @@ import { columnsMdxTemplate } from "./templates/mdx/columns.mdx.js";
|
|
|
55
55
|
import { commandsMdxTemplate } from "./templates/mdx/commands.mdx.js";
|
|
56
56
|
import { deploymentMdxTemplate } from "./templates/mdx/deployment.mdx.js";
|
|
57
57
|
import { fieldsMdxTemplate } from "./templates/mdx/fields.mdx.js";
|
|
58
|
+
import { fontsMdxTemplate } from "./templates/mdx/fonts.mdx.js";
|
|
58
59
|
import { globalsMdxTemplate } from "./templates/mdx/globals.mdx.js";
|
|
59
60
|
import { headersAndTextMdxTemplate } from "./templates/mdx/headers-and-text.mdx.js";
|
|
60
61
|
import { iconsMdxTemplate } from "./templates/mdx/icons.mdx.js";
|
|
@@ -139,7 +140,9 @@ class MDXToNextJSGenerator {
|
|
|
139
140
|
rootDir;
|
|
140
141
|
watcher = null;
|
|
141
142
|
configWatcher = null;
|
|
143
|
+
fontWatcher = null;
|
|
142
144
|
configFiles = ["theme.json", "navigation.json", "config.json"];
|
|
145
|
+
fontConfigFile = "fonts.json";
|
|
143
146
|
constructor(watchDir, outputDir) {
|
|
144
147
|
this.watchDir = path.resolve(watchDir);
|
|
145
148
|
this.outputDir = path.resolve(outputDir);
|
|
@@ -152,6 +155,7 @@ class MDXToNextJSGenerator {
|
|
|
152
155
|
await this.createNextJSStructure();
|
|
153
156
|
await this.createStartingDocs();
|
|
154
157
|
await this.copyCustomConfigFiles();
|
|
158
|
+
await this.copyFontConfig();
|
|
155
159
|
await this.processAllMDXFiles();
|
|
156
160
|
console.log(chalk.green("β
Initial setup complete!"));
|
|
157
161
|
console.log(chalk.cyan("π‘ To start the Next.js dev server:"));
|
|
@@ -221,6 +225,7 @@ class MDXToNextJSGenerator {
|
|
|
221
225
|
"commands.mdx": this.generateCommandsMdx(),
|
|
222
226
|
"deployment.mdx": this.generateDeploymentMdx(),
|
|
223
227
|
"fields.mdx": this.generateFieldsMdx(),
|
|
228
|
+
"fonts.mdx": this.generateFontsMdx(),
|
|
224
229
|
"globals.mdx": this.generateGlobalsMdx(),
|
|
225
230
|
"headers-and-text.mdx": this.generateHeadersAndTextMdx(),
|
|
226
231
|
"icons.mdx": this.generateIconsMdx(),
|
|
@@ -257,6 +262,31 @@ class MDXToNextJSGenerator {
|
|
|
257
262
|
}
|
|
258
263
|
}
|
|
259
264
|
}
|
|
265
|
+
async copyFontConfig() {
|
|
266
|
+
console.log(chalk.blue(`π Checking for font configuration...`));
|
|
267
|
+
const sourcePath = path.join(this.rootDir, this.fontConfigFile);
|
|
268
|
+
const destPath = path.join(this.outputDir, this.fontConfigFile);
|
|
269
|
+
if (await fs.pathExists(sourcePath)) {
|
|
270
|
+
await fs.copy(sourcePath, destPath);
|
|
271
|
+
console.log(chalk.green(` β Copied ${this.fontConfigFile} to Next.js app`));
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
console.log(chalk.gray(` β ${this.fontConfigFile} not found, skipping`));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
async loadFontConfig() {
|
|
278
|
+
const fontPath = path.join(this.rootDir, this.fontConfigFile);
|
|
279
|
+
try {
|
|
280
|
+
if (await fs.pathExists(fontPath)) {
|
|
281
|
+
const fontContent = await fs.readFile(fontPath, "utf8");
|
|
282
|
+
return JSON.parse(fontContent);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
console.warn(chalk.yellow(`β οΈ Error reading ${this.fontConfigFile}`), error);
|
|
287
|
+
}
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
260
290
|
async handleConfigFileChange(filePath) {
|
|
261
291
|
const fileName = path.basename(filePath);
|
|
262
292
|
if (this.configFiles.includes(fileName)) {
|
|
@@ -286,6 +316,37 @@ class MDXToNextJSGenerator {
|
|
|
286
316
|
}
|
|
287
317
|
}
|
|
288
318
|
}
|
|
319
|
+
async handleFontConfigChange() {
|
|
320
|
+
console.log(chalk.cyan(`π€ Font configuration changed`));
|
|
321
|
+
const sourcePath = path.join(this.rootDir, this.fontConfigFile);
|
|
322
|
+
const destPath = path.join(this.outputDir, this.fontConfigFile);
|
|
323
|
+
try {
|
|
324
|
+
await fs.copy(sourcePath, destPath);
|
|
325
|
+
console.log(chalk.green(`π Updated ${this.fontConfigFile} in Next.js app`));
|
|
326
|
+
// Update the layout template with new font config
|
|
327
|
+
await this.updateRootLayout();
|
|
328
|
+
console.log(chalk.green(`β
Layout updated with new font configuration`));
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
console.error(chalk.red(`β Error updating font configuration:`), error);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
async handleFontConfigDelete() {
|
|
335
|
+
console.log(chalk.red(`ποΈ Font configuration deleted`));
|
|
336
|
+
const destPath = path.join(this.outputDir, this.fontConfigFile);
|
|
337
|
+
try {
|
|
338
|
+
if (await fs.pathExists(destPath)) {
|
|
339
|
+
await fs.remove(destPath);
|
|
340
|
+
console.log(chalk.yellow(`ποΈ Removed ${this.fontConfigFile} from Next.js app`));
|
|
341
|
+
// Update the layout template without font config
|
|
342
|
+
await this.updateRootLayout();
|
|
343
|
+
console.log(chalk.green(`β
Layout updated without font configuration`));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
console.error(chalk.red(`β Error removing font configuration:`), error);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
289
350
|
async startWatching() {
|
|
290
351
|
console.log(chalk.yellow(`π Watching for changes in: ${this.watchDir}`));
|
|
291
352
|
this.watcher = chokidar.watch(this.watchDir, {
|
|
@@ -343,6 +404,25 @@ class MDXToNextJSGenerator {
|
|
|
343
404
|
.on("error", (error) => {
|
|
344
405
|
console.error(chalk.red("β Config watcher error:"), error);
|
|
345
406
|
});
|
|
407
|
+
const fontPath = path.join(this.rootDir, this.fontConfigFile);
|
|
408
|
+
this.fontWatcher = chokidar.watch(fontPath, {
|
|
409
|
+
persistent: true,
|
|
410
|
+
ignoreInitial: true,
|
|
411
|
+
});
|
|
412
|
+
this.fontWatcher
|
|
413
|
+
.on("add", () => {
|
|
414
|
+
console.log(chalk.cyan(`π€ Font configuration added`));
|
|
415
|
+
this.handleFontConfigChange();
|
|
416
|
+
})
|
|
417
|
+
.on("change", () => {
|
|
418
|
+
this.handleFontConfigChange();
|
|
419
|
+
})
|
|
420
|
+
.on("unlink", () => {
|
|
421
|
+
this.handleFontConfigDelete();
|
|
422
|
+
})
|
|
423
|
+
.on("error", (error) => {
|
|
424
|
+
console.error(chalk.red("β Font watcher error:"), error);
|
|
425
|
+
});
|
|
346
426
|
}
|
|
347
427
|
async handleFileChange(action, filePath) {
|
|
348
428
|
console.log(chalk.cyan(`π File ${action}: ${filePath}`));
|
|
@@ -469,7 +549,8 @@ class MDXToNextJSGenerator {
|
|
|
469
549
|
order: frontmatter.order || 0,
|
|
470
550
|
});
|
|
471
551
|
}
|
|
472
|
-
|
|
552
|
+
const fontConfig = await this.loadFontConfig();
|
|
553
|
+
return layoutTemplate(pages, fontConfig);
|
|
473
554
|
}
|
|
474
555
|
generateNotFoundPage() {
|
|
475
556
|
return notFoundTemplate;
|
|
@@ -702,6 +783,9 @@ export default function Home() {
|
|
|
702
783
|
generateFieldsMdx() {
|
|
703
784
|
return fieldsMdxTemplate;
|
|
704
785
|
}
|
|
786
|
+
generateFontsMdx() {
|
|
787
|
+
return fontsMdxTemplate;
|
|
788
|
+
}
|
|
705
789
|
generateGlobalsMdx() {
|
|
706
790
|
return globalsMdxTemplate;
|
|
707
791
|
}
|
|
@@ -744,12 +828,16 @@ export default function Home() {
|
|
|
744
828
|
await this.configWatcher.close();
|
|
745
829
|
console.log(chalk.yellow("π Stopped watching for config changes"));
|
|
746
830
|
}
|
|
831
|
+
if (this.fontWatcher) {
|
|
832
|
+
await this.fontWatcher.close();
|
|
833
|
+
console.log(chalk.yellow("π Stopped watching for font config changes"));
|
|
834
|
+
}
|
|
747
835
|
}
|
|
748
836
|
}
|
|
749
837
|
program
|
|
750
838
|
.name("doccupine")
|
|
751
839
|
.description("Watch MDX files and generate Next.js documentation pages automatically")
|
|
752
|
-
.version("0.0.
|
|
840
|
+
.version("0.0.26");
|
|
753
841
|
program
|
|
754
842
|
.command("watch", { isDefault: true })
|
|
755
843
|
.description("Watch a directory for MDX changes and generate Next.js app")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const layoutTemplate: (pages: any[]) => string;
|
|
1
|
+
export declare const layoutTemplate: (pages: any[], fontConfig: any) => string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export const layoutTemplate = (pages) => `import type { Metadata } from "next";
|
|
2
|
-
import { Inter } from "next/font/google";
|
|
1
|
+
export const layoutTemplate = (pages, fontConfig) => `import type { Metadata } from "next";
|
|
2
|
+
${fontConfig?.googleFont?.fontName?.length ? `import { ${fontConfig.googleFont.fontName} } from "next/font/google";` : fontConfig?.localFonts?.length || fontConfig?.localFonts?.src?.length ? 'import localFont from "next/font/local";' : 'import { Inter } from "next/font/google";'}
|
|
3
3
|
import { StyledComponentsRegistry } from "cherry-styled-components/src/lib";
|
|
4
4
|
import { theme, themeDark } from "@/app/theme";
|
|
5
5
|
import { CherryThemeProvider } from "@/components/layout/CherryThemeProvider";
|
|
@@ -11,7 +11,13 @@ import { DocsNavigation } from "@/components/layout/DocsNavigation";
|
|
|
11
11
|
import { transformPagesToGroupedStructure } from "@/utils/orderNavItems";
|
|
12
12
|
import navigation from "@/navigation.json";
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
${fontConfig?.googleFont?.fontName?.length
|
|
15
|
+
? `const font = ${fontConfig.googleFont.fontName}({ subsets: ${fontConfig?.googleFont?.subsets?.length ? JSON.stringify(fontConfig?.googleFont?.subsets, null, 2) : '["latin"]'}, ${fontConfig.googleFont?.weight.length ? `weight: "${fontConfig.googleFont.weight}"` : ""} });`
|
|
16
|
+
: fontConfig?.localFonts?.length || fontConfig?.localFonts?.src?.length
|
|
17
|
+
? `const font = localFont({
|
|
18
|
+
src: ${fontConfig.localFonts?.src?.length ? JSON.stringify(fontConfig?.localFonts.src, null, 2).replace(/"([^"]+)":/g, "$1:") : `"${fontConfig?.localFonts}"`},
|
|
19
|
+
});`
|
|
20
|
+
: 'const font = Inter({ subsets: ["latin"] });'}
|
|
15
21
|
|
|
16
22
|
export const metadata: Metadata = {
|
|
17
23
|
title: "Doccupine",
|
|
@@ -47,7 +53,7 @@ export default async function RootLayout({
|
|
|
47
53
|
|
|
48
54
|
return (
|
|
49
55
|
<html lang="en">
|
|
50
|
-
<body className={
|
|
56
|
+
<body className={font.className}>
|
|
51
57
|
<StyledComponentsRegistry>
|
|
52
58
|
<CherryThemeProvider theme={theme} themeDark={themeDark}>
|
|
53
59
|
<Header />
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const mdxComponentsTemplate = "import React from \"react\";\ntype MDXComponents = Record<string, React.ComponentType<any>>;\nimport { Code as CodeBlock } from \"@/components/layout/Code\";\nimport { Card } from \"@/components/layout/Card\";\nimport { Accordion } from \"@/components/layout/Accordion\";\nimport { Tabs, TabContent } from \"@/components/layout/Tabs\";\nimport { Callout } from \"@/components/layout/Callout\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport { Columns } from \"@/components/layout/Columns\";\nimport { Field } from \"@/components/layout/Field\";\nimport { Update } from \"@/components/layout/Update\";\nimport { Steps, Step } from \"@/components/layout/Steps\";\nimport { Button } from \"@/components/layout/Button\";\nimport { DemoTheme } from \"@/components/layout/DemoTheme\";\n\nfunction extractAllTextFromChildren(children: React.ReactNode): string {\n if (children == null) return \"\";\n if (typeof children === \"string\") return children;\n if (typeof children === \"number\") return String(children);\n if (typeof children === \"boolean\") return \"\";\n if (Array.isArray(children))\n return children.map(extractAllTextFromChildren).join(\"\");\n if (React.isValidElement(children)) {\n const element = children as React.ReactElement<any>;\n return extractAllTextFromChildren(element.props.children);\n }\n return \"\";\n}\n\nfunction generateId(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\")\n .trim();\n}\n\n// Map <pre><code class=\"language-xyz\"> to our <Code /> component\nfunction Pre(props: any) {\n const child = React.Children.only(\n props.children,\n ) as React.ReactElement<any> | null;\n if (child && child.type === \"code\") {\n const className = child.props.className || \"\";\n const match = /language-(\\w+)/.exec(className);\n const language = match ? match[1] : undefined;\n const code =\n typeof child.props.children === \"string\"\n ? child.props.children.replace(/\\n$/, \"\")\n : String(child.props.children ?? \"\");\n if (language) {\n return (\n <CodeBlock className={className} code={code} language={language} />\n );\n }\n }\n return <pre {...props} />;\n}\n\nexport function useMDXComponents(components: MDXComponents): MDXComponents {\n return {\n // Headings with auto-generated ids for TOC and deep links\n h1: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h1 id={id} {...props}>\n {children}\n </h1>\n );\n },\n h2: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h2 id={id} {...props}>\n {children}\n </h2>\n );\n },\n h3: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h3 id={id} {...props}>\n {children}\n </h3>\n );\n },\n h4: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h4 id={id} {...props}>\n {children}\n </h4>\n );\n },\n h5: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h5 id={id} {...props}>\n {children}\n </h5>\n );\n },\n h6: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h6 id={id} {...props}>\n {children}\n </h6>\n );\n },\n\n // Code blocks\n pre: Pre,\n\n // Expose your custom components for MDX usage\n Card,\n Accordion,\n Tabs,\n TabContent,\n Callout,\n Icon,\n Columns,\n Field,\n Update,\n Steps,\n Step,\n Button,\n DemoTheme,\n ...components,\n };\n}\n";
|
|
1
|
+
export declare const mdxComponentsTemplate = "import React from \"react\";\ntype MDXComponents = Record<string, React.ComponentType<any>>;\nimport { Space } from \"cherry-styled-components/src/lib\";\nimport { Code as CodeBlock } from \"@/components/layout/Code\";\nimport { Card } from \"@/components/layout/Card\";\nimport { Accordion } from \"@/components/layout/Accordion\";\nimport { Tabs, TabContent } from \"@/components/layout/Tabs\";\nimport { Callout } from \"@/components/layout/Callout\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport { Columns } from \"@/components/layout/Columns\";\nimport { Field } from \"@/components/layout/Field\";\nimport { Update } from \"@/components/layout/Update\";\nimport { Steps, Step } from \"@/components/layout/Steps\";\nimport { Button } from \"@/components/layout/Button\";\nimport { DemoTheme } from \"@/components/layout/DemoTheme\";\n\nfunction extractAllTextFromChildren(children: React.ReactNode): string {\n if (children == null) return \"\";\n if (typeof children === \"string\") return children;\n if (typeof children === \"number\") return String(children);\n if (typeof children === \"boolean\") return \"\";\n if (Array.isArray(children))\n return children.map(extractAllTextFromChildren).join(\"\");\n if (React.isValidElement(children)) {\n const element = children as React.ReactElement<any>;\n return extractAllTextFromChildren(element.props.children);\n }\n return \"\";\n}\n\nfunction generateId(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\")\n .trim();\n}\n\n// Map <pre><code class=\"language-xyz\"> to our <Code /> component\nfunction Pre(props: any) {\n const child = React.Children.only(\n props.children,\n ) as React.ReactElement<any> | null;\n if (child && child.type === \"code\") {\n const className = child.props.className || \"\";\n const match = /language-(\\w+)/.exec(className);\n const language = match ? match[1] : undefined;\n const code =\n typeof child.props.children === \"string\"\n ? child.props.children.replace(/\\n$/, \"\")\n : String(child.props.children ?? \"\");\n if (language) {\n return (\n <CodeBlock className={className} code={code} language={language} />\n );\n }\n }\n return <pre {...props} />;\n}\n\nexport function useMDXComponents(components: MDXComponents): MDXComponents {\n return {\n // Headings with auto-generated ids for TOC and deep links\n h1: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h1 id={id} {...props}>\n {children}\n </h1>\n );\n },\n h2: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h2 id={id} {...props}>\n {children}\n </h2>\n );\n },\n h3: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h3 id={id} {...props}>\n {children}\n </h3>\n );\n },\n h4: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h4 id={id} {...props}>\n {children}\n </h4>\n );\n },\n h5: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h5 id={id} {...props}>\n {children}\n </h5>\n );\n },\n h6: ({ children, ...props }: any) => {\n const id = generateId(extractAllTextFromChildren(children));\n return (\n <h6 id={id} {...props}>\n {children}\n </h6>\n );\n },\n\n // Code blocks\n pre: Pre,\n\n // Expose your custom components for MDX usage\n Card,\n Accordion,\n Tabs,\n TabContent,\n Callout,\n Icon,\n Columns,\n Field,\n Update,\n Steps,\n Step,\n Button,\n DemoTheme,\n Space,\n ...components,\n };\n}\n";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const mdxComponentsTemplate = `import React from "react";
|
|
2
2
|
type MDXComponents = Record<string, React.ComponentType<any>>;
|
|
3
|
+
import { Space } from "cherry-styled-components/src/lib";
|
|
3
4
|
import { Code as CodeBlock } from "@/components/layout/Code";
|
|
4
5
|
import { Card } from "@/components/layout/Card";
|
|
5
6
|
import { Accordion } from "@/components/layout/Accordion";
|
|
@@ -126,6 +127,7 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
|
|
|
126
127
|
Step,
|
|
127
128
|
Button,
|
|
128
129
|
DemoTheme,
|
|
130
|
+
Space,
|
|
129
131
|
...components,
|
|
130
132
|
};
|
|
131
133
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const actionBarTemplate = "\"use client\";\nimport { useState } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { rgba } from \"polished\";\nimport { resetButton, Textarea } from \"cherry-styled-components/src/lib\";\n\ninterface ActionBarProps {\n children: React.ReactNode;\n content: string;\n}\n\nconst StyledActionBar = styled.div<{ theme: Theme }>`\n position: absolute;\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n left: 0;\n padding: 70px 20px 20px 20px;\n display: flex;\n justify-content: space-between;\n width: 100%;\n\n ${mq(\"lg\")} {\n left: 50%;\n transform: translateX(-50%);\n max-width: calc(100vw - 640px);\n width: 100%;\n padding: 0 20px 20px 20px;\n margin: 0;\n }\n`;\n\nconst StyledActionBarContent = styled.div`\n margin: auto 0;\n`;\n\nconst StyledCopyButton = styled.button<{ theme: Theme; $copied: boolean }>`\n background: transparent;\n border: solid 1px\n ${({ theme, $copied }) =>\n $copied ? theme.colors.success : theme.colors.grayLight};\n color: ${({ theme, $copied }) =>\n $copied ? theme.colors.success : theme.colors.primary};\n border-radius: ${({ theme }) => theme.spacing.radius.xs};\n padding: 6px 8px;\n font-size: 12px;\n font-family:
|
|
1
|
+
export declare const actionBarTemplate = "\"use client\";\nimport { useState } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { rgba } from \"polished\";\nimport { resetButton, Textarea } from \"cherry-styled-components/src/lib\";\n\ninterface ActionBarProps {\n children: React.ReactNode;\n content: string;\n}\n\nconst StyledActionBar = styled.div<{ theme: Theme }>`\n position: absolute;\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n left: 0;\n padding: 70px 20px 20px 20px;\n display: flex;\n justify-content: space-between;\n width: 100%;\n\n ${mq(\"lg\")} {\n left: 50%;\n transform: translateX(-50%);\n max-width: calc(100vw - 640px);\n width: 100%;\n padding: 0 20px 20px 20px;\n margin: 0;\n }\n`;\n\nconst StyledActionBarContent = styled.div`\n margin: auto 0;\n`;\n\nconst StyledCopyButton = styled.button<{ theme: Theme; $copied: boolean }>`\n background: transparent;\n border: solid 1px\n ${({ theme, $copied }) =>\n $copied ? theme.colors.success : theme.colors.grayLight};\n color: ${({ theme, $copied }) =>\n $copied ? theme.colors.success : theme.colors.primary};\n border-radius: ${({ theme }) => theme.spacing.radius.xs};\n padding: 6px 8px;\n font-size: 12px;\n font-family: inherit;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 6px;\n margin-right: -6px;\n\n & svg.lucide {\n color: ${({ theme, $copied }) =>\n $copied ? theme.colors.success : theme.colors.primary};\n }\n\n &:hover {\n border-color: ${({ theme, $copied }) =>\n $copied ? theme.colors.success : theme.colors.primary};\n }\n\n &:active {\n transform: scale(0.95);\n }\n`;\n\nconst StyledToggle = styled.button<{ theme: Theme; $isActive?: boolean }>`\n ${resetButton}\n width: 56px;\n height: 32px;\n border-radius: 30px;\n display: flex;\n position: relative;\n margin: auto 0;\n transform: scale(1);\n background: ${({ theme }) => theme.colors.light};\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n\n &::after {\n content: \"\";\n position: absolute;\n top: 3px;\n left: 3px;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.2)};\n transition: all 0.3s ease;\n z-index: 1;\n ${({ $isActive }) =>\n !$isActive &&\n css`\n transform: translateX(24px);\n `}\n }\n\n & svg {\n width: 16px;\n height: 16px;\n object-fit: contain;\n margin: auto;\n transition: all 0.3s ease;\n position: relative;\n z-index: 2;\n }\n\n & .lucide-eye {\n transform: translateX(1px);\n }\n\n & .lucide-code-xml {\n transform: translateX(-1px);\n }\n\n & svg[stroke] {\n stroke: ${({ theme }) => theme.colors.primary};\n }\n\n @media (hover: hover) {\n &:hover {\n transform: scale(1.05);\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n Toggle & svg[stroke] {\n stroke: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n }\n }\n }\n\n &:active {\n transform: scale(0.97);\n }\n`;\n\nconst StyledContent = styled.div`\n padding-top: 140px;\n\n ${mq(\"lg\")} {\n padding-top: 70px;\n }\n\n & textarea {\n max-width: 640px;\n margin: auto;\n width: 100%;\n height: 100%;\n min-height: calc(100vh - 180px);\n\n ${mq(\"lg\")} {\n min-height: calc(100vh - 110px);\n }\n }\n`;\n\nfunction ActionBar({ children, content }: ActionBarProps) {\n const [isView, setIsView] = useState(true);\n const [copied, setCopied] = useState(false);\n\n const handleCopyContent = async () => {\n try {\n await navigator.clipboard.writeText(content);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error(\"Failed to copy:\", err);\n }\n };\n\n return (\n <>\n <StyledActionBar>\n <StyledCopyButton onClick={handleCopyContent} $copied={copied}>\n {copied ? (\n <>\n <Icon name=\"check\" size={16} />\n <span>Copied!</span>\n </>\n ) : (\n <>\n <Icon name=\"copy\" size={16} />\n <span>Copy Content</span>\n </>\n )}\n </StyledCopyButton>\n <StyledActionBarContent>\n {\" \"}\n <StyledToggle\n onClick={() => setIsView(!isView)}\n aria-label=\"Toggle Theme\"\n $isActive={isView}\n >\n <Icon name=\"Eye\" />\n <Icon name=\"CodeXml\" />\n </StyledToggle>\n </StyledActionBarContent>\n </StyledActionBar>\n {isView && <StyledContent>{children}</StyledContent>}\n {!isView && (\n <StyledContent>\n <Textarea defaultValue={content} $fullWidth />\n </StyledContent>\n )}\n </>\n );\n}\n\nexport { ActionBar };";
|
|
@@ -44,7 +44,7 @@ const StyledCopyButton = styled.button<{ theme: Theme; $copied: boolean }>\`
|
|
|
44
44
|
border-radius: \${({ theme }) => theme.spacing.radius.xs};
|
|
45
45
|
padding: 6px 8px;
|
|
46
46
|
font-size: 12px;
|
|
47
|
-
font-family:
|
|
47
|
+
font-family: inherit;
|
|
48
48
|
font-weight: 600;
|
|
49
49
|
cursor: pointer;
|
|
50
50
|
transition: all 0.2s ease;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const globalStylesTemplate = "\"use client\";\nimport { createGlobalStyle } from \"styled-components\";\n\nconst GlobalStyles = createGlobalStyle`\nhtml,\nbody {\n margin: 0;\n padding: 0;\n min-height: 100%;\n scroll-behavior: smooth;\n background-color: ${({ theme }) => theme.colors.light};\n scroll-padding-top: 20px;\n}\n\nbody {\n font-family: \"Inter\", sans-serif;\n -moz-osx-font-smoothing: grayscale;\n -webkit-text-size-adjust: 100%;\n -webkit-font-smoothing: antialiased;\n}\n\n:root {\n interpolate-size: allow-keywords;\n}\n\n* {\n box-sizing: border-box;\n min-width: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace;\n}\n\npre,\ncode,\nkbd,\nsamp,\nblockquote,\np,\na,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nul li,\nol li {\n margin: 0;\n padding: 0;\n color: ${({ theme }) => theme.colors.dark};\n}\n\na {\n color: ${({ theme }) => (theme.isDark ? theme.colors.dark : theme.colors.primary)};\n}\n\nol,\nul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\nfigure {\n margin: 0;\n}\n\nfieldset {\n appearance: none;\n border: none;\n}\n\nbutton,\ninput,\na,\nimg,\nsvg,\nsvg * {\n transition: all 0.3s ease;\n}\n\nstrong,\nb {\n font-weight: 700;\n}`;\n\nexport { GlobalStyles };";
|
|
1
|
+
export declare const globalStylesTemplate = "\"use client\";\nimport { createGlobalStyle } from \"styled-components\";\n\nconst GlobalStyles = createGlobalStyle`\nhtml,\nbody {\n margin: 0;\n padding: 0;\n min-height: 100%;\n scroll-behavior: smooth;\n background-color: ${({ theme }) => theme.colors.light};\n scroll-padding-top: 20px;\n}\n\nbody {\n font-family: \"Inter\", sans-serif;\n -moz-osx-font-smoothing: grayscale;\n -webkit-text-size-adjust: 100%;\n -webkit-font-smoothing: antialiased;\n}\n\n:root {\n interpolate-size: allow-keywords;\n}\n\n* {\n box-sizing: border-box;\n min-width: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace;\n}\n\npre,\ncode,\nkbd,\nsamp,\nblockquote,\np,\na,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nul li,\nol li {\n margin: 0;\n padding: 0;\n color: ${({ theme }) => theme.colors.dark};\n}\n\na {\n color: ${({ theme }) => (theme.isDark ? theme.colors.dark : theme.colors.primary)};\n}\n\nol,\nul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\nfigure {\n margin: 0;\n}\n\nfieldset {\n appearance: none;\n border: none;\n}\n\nbutton,\ninput,\na,\nimg,\nsvg,\nsvg * {\n transition: all 0.3s ease;\n}\n\nstrong,\nb {\n font-weight: 700;\n}\n\n.full-width {\n width: 100%;\n}`;\n\nexport { GlobalStyles };";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const deploymentMdxTemplate = "---\ntitle: \"Deployment\"\ndescription: \"Deploy your Doccupine Next.js app to Vercel.\"\ndate: \"2025-01-15\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder:
|
|
1
|
+
export declare const deploymentMdxTemplate = "---\ntitle: \"Deployment\"\ndescription: \"Deploy your Doccupine Next.js app to Vercel.\"\ndate: \"2025-01-15\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 5\n---\n# Deployment\nDeploy your Doccupine site as a Next.js application on Vercel. You can connect a Git repository for automatic deployments or use the Vercel CLI for manual control.\n\n<Callout type=\"warning\">\n Only deploy the generated website directory produced by Doccupine (the Next.js app). Do not deploy your MDX source folder. If your repo contains multiple folders, set the Vercel project <strong>Root Directory</strong> to the generated site folder.\n</Callout>\n\n## Prerequisites\n- **Vercel account**: https://vercel.com/signup\n- **Git repository**: GitHub, GitLab, or Bitbucket with your Next.js app\n- **Node.js**: Use an LTS version\n\n## Option 1: Deploy via Git (recommended)\n1. **Push the generated site folder** to a Git repository (or ensure the repo\u2019s root is the generated website directory).\n2. **Import to Vercel**: Go to https://vercel.com/new and select your repository.\n3. If your repo is a monorepo, set the project **Root Directory** to the generated website folder (Project \u2192 Settings \u2192 General \u2192 Root Directory).\n4. **Framework preset**: Vercel auto-detects Next.js.\n5. **Build settings** (defaults are fine):\n - Install Command: `pnpm i`, `yarn`, or `npm i` (Vercel auto-detects)\n - Build Command: `next build`\n - Output: handled automatically by Vercel for Next.js\n6. **Environment Variables**: Add any values required by your docs (see below).\n7. **Deploy**: Vercel creates a Preview deployment per branch. Merge to your main branch to promote to Production.\n\n## Option 2: Deploy with Vercel CLI\n1. Install the CLI:\n ```bash\n npm i -g vercel\n ```\n2. From the generated website directory, run:\n ```bash\n vercel\n ```\n Follow the prompts to link or create a project.\n3. When ready for production:\n ```bash\n vercel --prod\n ```\n\n## Environment variables\nIf your documentation or site behavior depends on environment variables, define them in Vercel:\n- In the Vercel dashboard: Project \u2192 Settings \u2192 Environment Variables.\n- Or via CLI:\n ```bash\n vercel env add NAME\n ```\n\nFor Next.js, make sure variables needed on the client are prefixed with `NEXT_PUBLIC_`.\n\n## Next.js configuration notes\n- Ensure a valid `next.config.js` if you customize images, basePath, or MDX handling.\n- If you use MDX, include the necessary plugins/config in your project.\n- Vercel automatically enables Image Optimization and Edge/CDN features for Next.js.\n\n## Custom domains\n- Add a domain in Vercel: Project \u2192 Settings \u2192 Domains.\n- Point DNS to Vercel as instructed. Changes can take a few minutes to propagate.\n\n## Troubleshooting\n- **Build failed**: Check the Vercel build logs. Confirm Node version and lockfile are present.\n- **Missing content**: Ensure your MDX directory and any assets are included in the repository.\n- **Env not applied**: Add variables for the correct environment (Preview vs Production) and redeploy.\n- **Images not loading**: Configure `images.domains` in `next.config.js` if using remote images.\n\n## Tips\n- **Preview first**: Use Preview deployments to validate docs before merging to Production.\n- **Cache and performance**: Leverage ISR or static generation where applicable for faster loads.\n- **Consistent tooling**: Keep a single package manager and lockfile in the repo (npm, pnpm, or yarn).";
|
|
@@ -4,7 +4,7 @@ description: "Deploy your Doccupine Next.js app to Vercel."
|
|
|
4
4
|
date: "2025-01-15"
|
|
5
5
|
category: "Configuration"
|
|
6
6
|
categoryOrder: 3
|
|
7
|
-
order:
|
|
7
|
+
order: 5
|
|
8
8
|
---
|
|
9
9
|
# Deployment
|
|
10
10
|
Deploy your Doccupine site as a Next.js application on Vercel. You can connect a Git repository for automatic deployments or use the Vercel CLI for manual control.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const fontsMdxTemplate = "---\ntitle: \"Fonts\"\ndescription: \"Customize the documentation typography with a fonts.json file (Google Fonts or local custom fonts).\"\ndate: \"2025-01-15\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 4\n---\n# Fonts\nDefine your site\u2019s typography with a `fonts.json` file. You can load fonts from Google Fonts or from local font files bundled with your project.\n\n## fonts.json\nPlace a `fonts.json` at your project root (the same folder where you execute `npx doccupine`). Choose one of the following configurations depending on the source of your fonts.\n\n## Google Fonts\nUse this when your font is hosted by Google Fonts.\n\n```json\n{\n \"googleFont\": {\n \"fontName\": \"Work_Sans\",\n \"subsets\": [\"latin\"],\n \"weight\": \"400\"\n }\n}\n```\n\n### Rules\n- **fontName**: Capitalize each word. If the name contains spaces, replace them with `_`.\n - Example: \"Work Sans\" \u2192 `Work_Sans`\n- **subsets**: Pick the subsets you need (for example, `latin`).\n- **weight**: The font weight to load (for example, `\"400\"`).\n\n### Tips\n- **One primary family**: Start with a single family and weight, then add more if needed.\n- **Readability**: Choose readable body fonts; reserve display fonts for headings.\n\n## Local custom fonts\nUse this when you want to ship your own font files. Upload your font files to the Next.js `public` directory, then reference them with relative paths.\n\n```json\n{\n \"localFonts\": {\n \"src\": [\n {\n \"path\": \"../public/font.woff\",\n \"weight\": \"400\",\n \"style\": \"normal\"\n },\n {\n \"path\": \"../public/font.woff\",\n \"weight\": \"400\",\n \"style\": \"italic\"\n },\n {\n \"path\": \"../public/font.woff\",\n \"weight\": \"700\",\n \"style\": \"normal\"\n },\n {\n \"path\": \"../public/font.woff\",\n \"weight\": \"700\",\n \"style\": \"italic\"\n }\n ]\n }\n}\n```\n\n### Single file shorthand\nIf you have only one file, you can use:\n\n```json\n{\n \"localFonts\": \"../public/font.woff\"\n}\n```\n\n### Rules\n- **Upload files**: Place `font.woff` (and any additional weights/styles) in your Next.js `public` directory.\n- **path**: Use a relative path to the file from where it is consumed by your build tooling; the example above uses `../public/font.woff`.\n- **weight**: String value of the font weight (for example, `\"400\"`, `\"700\"`).\n- **style**: `\"normal\"` or `\"italic\"`.\n\n### Tips\n- **Provide only what you need**: Include the minimal set of weights/styles to keep bundle size small.\n- **File formats**: `.woff` is broadly supported and recommended for the web.\n\n## Behavior\n- **Placement**: Put `fonts.json` in the project root alongside `config.json` and (optionally) `theme.json`.\n- **Validation**: Follow the naming rule for `googleFont.fontName` (capitalize, replace spaces with `_`).\n- **Local files**: Ensure the referenced files exist under the Next.js `public` directory.\n\n## Examples\n- **Google Fonts (Work Sans)**\n\n```json\n{\n \"googleFont\": {\n \"fontName\": \"Work_Sans\",\n \"subsets\": [\"latin\"],\n \"weight\": \"400\"\n }\n}\n```\n\n- **Local fonts (multiple weights/styles)**\n\n```json\n{\n \"localFonts\": {\n \"src\": [\n { \"path\": \"../public/font.woff\", \"weight\": \"400\", \"style\": \"normal\" },\n { \"path\": \"../public/font.woff\", \"weight\": \"400\", \"style\": \"italic\" },\n { \"path\": \"../public/font.woff\", \"weight\": \"700\", \"style\": \"normal\" },\n { \"path\": \"../public/font.woff\", \"weight\": \"700\", \"style\": \"italic\" }\n ]\n }\n}\n```\n";
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export const fontsMdxTemplate = `---
|
|
2
|
+
title: "Fonts"
|
|
3
|
+
description: "Customize the documentation typography with a fonts.json file (Google Fonts or local custom fonts)."
|
|
4
|
+
date: "2025-01-15"
|
|
5
|
+
category: "Configuration"
|
|
6
|
+
categoryOrder: 3
|
|
7
|
+
order: 4
|
|
8
|
+
---
|
|
9
|
+
# Fonts
|
|
10
|
+
Define your siteβs typography with a \`fonts.json\` file. You can load fonts from Google Fonts or from local font files bundled with your project.
|
|
11
|
+
|
|
12
|
+
## fonts.json
|
|
13
|
+
Place a \`fonts.json\` at your project root (the same folder where you execute \`npx doccupine\`). Choose one of the following configurations depending on the source of your fonts.
|
|
14
|
+
|
|
15
|
+
## Google Fonts
|
|
16
|
+
Use this when your font is hosted by Google Fonts.
|
|
17
|
+
|
|
18
|
+
\`\`\`json
|
|
19
|
+
{
|
|
20
|
+
"googleFont": {
|
|
21
|
+
"fontName": "Work_Sans",
|
|
22
|
+
"subsets": ["latin"],
|
|
23
|
+
"weight": "400"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
\`\`\`
|
|
27
|
+
|
|
28
|
+
### Rules
|
|
29
|
+
- **fontName**: Capitalize each word. If the name contains spaces, replace them with \`_\`.
|
|
30
|
+
- Example: "Work Sans" β \`Work_Sans\`
|
|
31
|
+
- **subsets**: Pick the subsets you need (for example, \`latin\`).
|
|
32
|
+
- **weight**: The font weight to load (for example, \`"400"\`).
|
|
33
|
+
|
|
34
|
+
### Tips
|
|
35
|
+
- **One primary family**: Start with a single family and weight, then add more if needed.
|
|
36
|
+
- **Readability**: Choose readable body fonts; reserve display fonts for headings.
|
|
37
|
+
|
|
38
|
+
## Local custom fonts
|
|
39
|
+
Use this when you want to ship your own font files. Upload your font files to the Next.js \`public\` directory, then reference them with relative paths.
|
|
40
|
+
|
|
41
|
+
\`\`\`json
|
|
42
|
+
{
|
|
43
|
+
"localFonts": {
|
|
44
|
+
"src": [
|
|
45
|
+
{
|
|
46
|
+
"path": "../public/font.woff",
|
|
47
|
+
"weight": "400",
|
|
48
|
+
"style": "normal"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"path": "../public/font.woff",
|
|
52
|
+
"weight": "400",
|
|
53
|
+
"style": "italic"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"path": "../public/font.woff",
|
|
57
|
+
"weight": "700",
|
|
58
|
+
"style": "normal"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"path": "../public/font.woff",
|
|
62
|
+
"weight": "700",
|
|
63
|
+
"style": "italic"
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
\`\`\`
|
|
69
|
+
|
|
70
|
+
### Single file shorthand
|
|
71
|
+
If you have only one file, you can use:
|
|
72
|
+
|
|
73
|
+
\`\`\`json
|
|
74
|
+
{
|
|
75
|
+
"localFonts": "../public/font.woff"
|
|
76
|
+
}
|
|
77
|
+
\`\`\`
|
|
78
|
+
|
|
79
|
+
### Rules
|
|
80
|
+
- **Upload files**: Place \`font.woff\` (and any additional weights/styles) in your Next.js \`public\` directory.
|
|
81
|
+
- **path**: Use a relative path to the file from where it is consumed by your build tooling; the example above uses \`../public/font.woff\`.
|
|
82
|
+
- **weight**: String value of the font weight (for example, \`"400"\`, \`"700"\`).
|
|
83
|
+
- **style**: \`"normal"\` or \`"italic"\`.
|
|
84
|
+
|
|
85
|
+
### Tips
|
|
86
|
+
- **Provide only what you need**: Include the minimal set of weights/styles to keep bundle size small.
|
|
87
|
+
- **File formats**: \`.woff\` is broadly supported and recommended for the web.
|
|
88
|
+
|
|
89
|
+
## Behavior
|
|
90
|
+
- **Placement**: Put \`fonts.json\` in the project root alongside \`config.json\` and (optionally) \`theme.json\`.
|
|
91
|
+
- **Validation**: Follow the naming rule for \`googleFont.fontName\` (capitalize, replace spaces with \`_\`).
|
|
92
|
+
- **Local files**: Ensure the referenced files exist under the Next.js \`public\` directory.
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
- **Google Fonts (Work Sans)**
|
|
96
|
+
|
|
97
|
+
\`\`\`json
|
|
98
|
+
{
|
|
99
|
+
"googleFont": {
|
|
100
|
+
"fontName": "Work_Sans",
|
|
101
|
+
"subsets": ["latin"],
|
|
102
|
+
"weight": "400"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
\`\`\`
|
|
106
|
+
|
|
107
|
+
- **Local fonts (multiple weights/styles)**
|
|
108
|
+
|
|
109
|
+
\`\`\`json
|
|
110
|
+
{
|
|
111
|
+
"localFonts": {
|
|
112
|
+
"src": [
|
|
113
|
+
{ "path": "../public/font.woff", "weight": "400", "style": "normal" },
|
|
114
|
+
{ "path": "../public/font.woff", "weight": "400", "style": "italic" },
|
|
115
|
+
{ "path": "../public/font.woff", "weight": "700", "style": "normal" },
|
|
116
|
+
{ "path": "../public/font.woff", "weight": "700", "style": "italic" }
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
\`\`\`
|
|
121
|
+
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const indexMdxTemplate = "---\ntitle: \"Getting Started\"\ndescription: \"Doccupine is a free and open-source document management system that allows you to store, organize, and share your documentation with ease.\"\ndate: \"2025-01-15\"\ncategory: \"General\"\ncategoryOrder: 0\norder: 0\n---\n# Welcome to Doccupine\
|
|
1
|
+
export declare const indexMdxTemplate = "---\ntitle: \"Getting Started\"\ndescription: \"Doccupine is a free and open-source document management system that allows you to store, organize, and share your documentation with ease.\"\ndate: \"2025-01-15\"\ncategory: \"General\"\ncategoryOrder: 0\norder: 0\n---\n# Welcome to Doccupine\nUsing Doccupine, you simply create your documentation in MDX files with traditional Markdown syntax, Doccupine monitors your changes automatically generating a beautiful, modern documentation website.\n\n## Features\n\n<Columns cols={2}>\n <Card>\n <img src=\"https://doccupine.com/mdx.svg\" alt=\"Markdown-based content\" className=\"full-width\" />\n <Space $size={12} />\n Markdown-based content\n </Card>\n <Card>\n <img src=\"https://doccupine.com/structure.svg\" alt=\"Built-in file structure\" className=\"full-width\" />\n <Space $size={12} />\n Built-in file structure\n </Card>\n <Card>\n <img src=\"https://doccupine.com/live-reload.svg\" alt=\"Live Preview & Auto-Update\" className=\"full-width\" />\n <Space $size={12} />\n Live Preview & Auto-Update\n </Card>\n <Card>\n <img src=\"https://doccupine.com/deployment.svg\" alt=\"Easy Deployment\" className=\"full-width\" />\n <Space $size={12} />\n Easy Deployment\n </Card>\n</Columns>\n\n## Getting Started\n\nTo get started with Doccupine, make sure you have [Node.js](https://nodejs.org) and npm installed on your machine. Then, follow these steps:\n\n- **Run Doccupine CLI:**\n\nCreate a new directory for your project and navigate to it in your terminal. Run the following command to create a new Doccupine project:\n\n```bash\nnpx doccupine\n```\n\nOnce you run the command, Doccupine will ask you to select a directory to store your MDX files. Choose the directory where you want to create your documentation files.\nAfter selecting the directory, Doccupine will ask you to enter the name of the directory for the generated website. Enter the name of the directory where you want to create your website.\n\nThis will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.\n\n## Start documenting\nStart documenting your project by editing the **index.mdx** file in the choosen MDX directory.\n\nIn your MDX directory, you can structure your content using folders and files. Doccupine will automatically generate a navigation menu based on the configured categories and order.\n";
|
|
@@ -7,16 +7,32 @@ categoryOrder: 0
|
|
|
7
7
|
order: 0
|
|
8
8
|
---
|
|
9
9
|
# Welcome to Doccupine
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## Open Source and Extensible
|
|
13
|
-
Doccupine is built on open standards, enabling customization and extensibility for different documentation needs. You stay in control of your content, with the option to host docs yourself and tailor the websiteβs look and features to match your organizationβs requirements.
|
|
10
|
+
Using Doccupine, you simply create your documentation in MDX files with traditional Markdown syntax, Doccupine monitors your changes automatically generating a beautiful, modern documentation website.
|
|
14
11
|
|
|
15
12
|
## Features
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
13
|
+
|
|
14
|
+
<Columns cols={2}>
|
|
15
|
+
<Card>
|
|
16
|
+
<img src="https://doccupine.com/mdx.svg" alt="Markdown-based content" className="full-width" />
|
|
17
|
+
<Space $size={12} />
|
|
18
|
+
Markdown-based content
|
|
19
|
+
</Card>
|
|
20
|
+
<Card>
|
|
21
|
+
<img src="https://doccupine.com/structure.svg" alt="Built-in file structure" className="full-width" />
|
|
22
|
+
<Space $size={12} />
|
|
23
|
+
Built-in file structure
|
|
24
|
+
</Card>
|
|
25
|
+
<Card>
|
|
26
|
+
<img src="https://doccupine.com/live-reload.svg" alt="Live Preview & Auto-Update" className="full-width" />
|
|
27
|
+
<Space $size={12} />
|
|
28
|
+
Live Preview & Auto-Update
|
|
29
|
+
</Card>
|
|
30
|
+
<Card>
|
|
31
|
+
<img src="https://doccupine.com/deployment.svg" alt="Easy Deployment" className="full-width" />
|
|
32
|
+
<Space $size={12} />
|
|
33
|
+
Easy Deployment
|
|
34
|
+
</Card>
|
|
35
|
+
</Columns>
|
|
20
36
|
|
|
21
37
|
## Getting Started
|
|
22
38
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const navigationMdxTemplate = "---\ntitle: \"Navigation\"\ndescription: \"Organize and structure your navigation.\"\ndate: \"2025-01-15\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 2\n---\n# Navigation\nDoccupine builds your sidebar automatically from your MDX pages. By default, it reads the page frontmatter and groups pages into categories in the order you define. For larger docs, you can take full control with a `navigation.json` file.\n\n## Automatic navigation (default)\nWhen no custom navigation is provided, Doccupine generates a structure based on each page\u2019s frontmatter.\n\n### Frontmatter fields\n- **category**: The category name that groups the page in the sidebar.\n- **categoryOrder**: The position of the category within the sidebar. Lower numbers appear first.\n- **order**: The position of the page within its category. Lower numbers appear first.\n\n### Example frontmatter\n\n```text\n---\ntitle: \"Navigation\"\ndescription: \"Organize and structure your navigation.\"\ndate: \"2025-01-15\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 2\n---\n```\n\nThis approach is great for small sets of documents. For larger projects, setting these fields on every page can become repetitive.\n\n## Custom navigation with navigation.json\nTo centrally define the entire sidebar, create a `navigation.json` at your project root (the same folder where you execute `npx doccupine`). When present, it takes priority over page frontmatter and fully controls the navigation structure.\n\n### Example navigation.json\n\n```json\n[\n {\n \"label\": \"General\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Getting Started\" },\n { \"slug\": \"commands\", \"title\": \"Commands\" }\n ]\n },\n {\n \"label\": \"Components\",\n \"links\": [\n { \"slug\": \"headers-and-text\", \"title\": \"Headers and Text\" },\n { \"slug\": \"lists-and-tables\", \"title\": \"Lists and tables\" },\n { \"slug\": \"code\", \"title\": \"Code\" },\n { \"slug\": \"accordion\", \"title\": \"Accordion\" },\n { \"slug\": \"tabs\", \"title\": \"Tabs\" },\n { \"slug\": \"cards\", \"title\": \"Cards\" },\n { \"slug\": \"callouts\", \"title\": \"Callouts\" },\n { \"slug\": \"images-and-embeds\", \"title\": \"Images and embeds\" },\n { \"slug\": \"icons\", \"title\": \"Icons\" },\n { \"slug\": \"fields\", \"title\": \"Fields\" },\n { \"slug\": \"update\", \"title\": \"Update\" },\n { \"slug\": \"columns\", \"title\": \"Columns\" },\n { \"slug\": \"steps\", \"title\": \"Steps\" }\n ]\n },\n {\n \"label\": \"Configuration\",\n \"links\": [\n { \"slug\": \"globals\", \"title\": \"Globals\" },\n { \"slug\": \"navigation\", \"title\": \"Navigation\" },\n { \"slug\": \"theme\", \"title\": \"Theme\" },\n { \"slug\": \"deployment\", \"title\": \"Deployment\" }\n ]\n }\n]\n```\n\n### Fields\n- **label**: The section header shown in the sidebar.\n- **links**: An array of page entries for that section.\n - **slug**: The MDX file slug (filename without extension). Use an empty string `\"\"` for `index.mdx`.\n - **title**: The display title in the navigation. This can differ from the page\u2019s `title` frontmatter.\n\n## Precedence and behavior\n- **navigation.json takes priority**. If present, it defines the entire sidebar structure.\n- Without `navigation.json`, the sidebar is built from page frontmatter: `category` \u2192 grouped; `categoryOrder` \u2192 category position; `order` \u2192 page position.\n- Pages without a `category` appear at the top level.\n\n## Tips\n- **Start simple**: Use frontmatter for small docs. Switch to `navigation.json` as the structure grows.\n- **Keep slugs consistent**: `slug` must match the MDX filename (e.g., `text.mdx` \u2192 `text`).\n- **Control titles**: Use `title` in `navigation.json` to customize sidebar labels without changing page frontmatter.";
|
|
1
|
+
export declare const navigationMdxTemplate = "---\ntitle: \"Navigation\"\ndescription: \"Organize and structure your navigation.\"\ndate: \"2025-01-15\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 2\n---\n# Navigation\nDoccupine builds your sidebar automatically from your MDX pages. By default, it reads the page frontmatter and groups pages into categories in the order you define. For larger docs, you can take full control with a `navigation.json` file.\n\n## Automatic navigation (default)\nWhen no custom navigation is provided, Doccupine generates a structure based on each page\u2019s frontmatter.\n\n### Frontmatter fields\n- **category**: The category name that groups the page in the sidebar.\n- **categoryOrder**: The position of the category within the sidebar. Lower numbers appear first.\n- **order**: The position of the page within its category. Lower numbers appear first.\n\n### Example frontmatter\n\n```text\n---\ntitle: \"Navigation\"\ndescription: \"Organize and structure your navigation.\"\ndate: \"2025-01-15\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 2\n---\n```\n\nThis approach is great for small sets of documents. For larger projects, setting these fields on every page can become repetitive.\n\n## Custom navigation with navigation.json\nTo centrally define the entire sidebar, create a `navigation.json` at your project root (the same folder where you execute `npx doccupine`). When present, it takes priority over page frontmatter and fully controls the navigation structure.\n\n### Example navigation.json\n\n```json\n[\n {\n \"label\": \"General\",\n \"links\": [\n { \"slug\": \"\", \"title\": \"Getting Started\" },\n { \"slug\": \"commands\", \"title\": \"Commands\" }\n ]\n },\n {\n \"label\": \"Components\",\n \"links\": [\n { \"slug\": \"headers-and-text\", \"title\": \"Headers and Text\" },\n { \"slug\": \"lists-and-tables\", \"title\": \"Lists and tables\" },\n { \"slug\": \"code\", \"title\": \"Code\" },\n { \"slug\": \"accordion\", \"title\": \"Accordion\" },\n { \"slug\": \"tabs\", \"title\": \"Tabs\" },\n { \"slug\": \"cards\", \"title\": \"Cards\" },\n { \"slug\": \"callouts\", \"title\": \"Callouts\" },\n { \"slug\": \"images-and-embeds\", \"title\": \"Images and embeds\" },\n { \"slug\": \"icons\", \"title\": \"Icons\" },\n { \"slug\": \"fields\", \"title\": \"Fields\" },\n { \"slug\": \"update\", \"title\": \"Update\" },\n { \"slug\": \"columns\", \"title\": \"Columns\" },\n { \"slug\": \"steps\", \"title\": \"Steps\" }\n ]\n },\n {\n \"label\": \"Configuration\",\n \"links\": [\n { \"slug\": \"globals\", \"title\": \"Globals\" },\n { \"slug\": \"navigation\", \"title\": \"Navigation\" },\n { \"slug\": \"theme\", \"title\": \"Theme\" },\n { \"slug\": \"fonts\", \"title\": \"Fonts\" },\n { \"slug\": \"deployment\", \"title\": \"Deployment\" }\n ]\n }\n]\n```\n\n### Fields\n- **label**: The section header shown in the sidebar.\n- **links**: An array of page entries for that section.\n - **slug**: The MDX file slug (filename without extension). Use an empty string `\"\"` for `index.mdx`.\n - **title**: The display title in the navigation. This can differ from the page\u2019s `title` frontmatter.\n\n## Precedence and behavior\n- **navigation.json takes priority**. If present, it defines the entire sidebar structure.\n- Without `navigation.json`, the sidebar is built from page frontmatter: `category` \u2192 grouped; `categoryOrder` \u2192 category position; `order` \u2192 page position.\n- Pages without a `category` appear at the top level.\n\n## Tips\n- **Start simple**: Use frontmatter for small docs. Switch to `navigation.json` as the structure grows.\n- **Keep slugs consistent**: `slug` must match the MDX filename (e.g., `text.mdx` \u2192 `text`).\n- **Control titles**: Use `title` in `navigation.json` to customize sidebar labels without changing page frontmatter.";
|
|
@@ -70,6 +70,7 @@ To centrally define the entire sidebar, create a \`navigation.json\` at your pro
|
|
|
70
70
|
{ "slug": "globals", "title": "Globals" },
|
|
71
71
|
{ "slug": "navigation", "title": "Navigation" },
|
|
72
72
|
{ "slug": "theme", "title": "Theme" },
|
|
73
|
+
{ "slug": "fonts", "title": "Fonts" },
|
|
73
74
|
{ "slug": "deployment", "title": "Deployment" }
|
|
74
75
|
]
|
|
75
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const stepsMdxTemplate = "---\ntitle: \"Steps\"\ndescription: \"Guide readers step-by-step using the Steps component.\"\ndate: \"2025-01-15\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 13\n---\n# Steps\nGuide readers step-by-step using the Steps component.\n\nThe Steps component is perfect for organizing procedures or workflows in a clear sequence. Include as many individual steps as necessary to outline your process.\n\n## Steps Usage\nYou can use the `Steps` component to create a step-by-step guide. Each step is represented by a `Step` component, which includes a title and content.\n\n```mdx\n<Steps>\n <Step title=\"Step 1\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 2\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 3\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n</Steps>\n```\n\n<Steps>\n <Step title=\"Step 1\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 2\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 3\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n</Steps>\n\n
|
|
1
|
+
export declare const stepsMdxTemplate = "---\ntitle: \"Steps\"\ndescription: \"Guide readers step-by-step using the Steps component.\"\ndate: \"2025-01-15\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 13\n---\n# Steps\nGuide readers step-by-step using the Steps component.\n\nThe Steps component is perfect for organizing procedures or workflows in a clear sequence. Include as many individual steps as necessary to outline your process.\n\n## Steps Usage\nYou can use the `Steps` component to create a step-by-step guide. Each step is represented by a `Step` component, which includes a title and content.\n\n```mdx\n<Steps>\n <Step title=\"Step 1\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 2\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 3\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n</Steps>\n```\n\n<Steps>\n <Step title=\"Step 1\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 2\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n\n <Step title=\"Step 3\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n </Step>\n</Steps>\n\n## Properties\n\n<Field value=\"title\" type=\"string\" required>\n The title of the step.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the step.\n</Field>\n";
|
|
@@ -9,22 +9,22 @@ export const packageJsonTemplate = JSON.stringify({
|
|
|
9
9
|
lint: "next lint",
|
|
10
10
|
},
|
|
11
11
|
dependencies: {
|
|
12
|
-
next: "16.0.
|
|
13
|
-
react: "19.2.
|
|
14
|
-
"react-dom": "19.2.
|
|
12
|
+
next: "16.0.8",
|
|
13
|
+
react: "19.2.1",
|
|
14
|
+
"react-dom": "19.2.1",
|
|
15
15
|
},
|
|
16
16
|
devDependencies: {
|
|
17
17
|
"@mdx-js/react": "^3.1.1",
|
|
18
|
-
"@types/node": "^
|
|
18
|
+
"@types/node": "^25",
|
|
19
19
|
"@types/react": "^19",
|
|
20
20
|
"@types/react-dom": "^19",
|
|
21
21
|
"cherry-styled-components": "^0.1.0-43",
|
|
22
22
|
eslint: "^9",
|
|
23
|
-
"eslint-config-next": "16.0.
|
|
24
|
-
"lucide-react": "^0.
|
|
23
|
+
"eslint-config-next": "16.0.8",
|
|
24
|
+
"lucide-react": "^0.559.0",
|
|
25
25
|
"next-mdx-remote": "^5.0.0",
|
|
26
26
|
polished: "^4.3.1",
|
|
27
|
-
prettier: "^3.
|
|
27
|
+
prettier: "^3.7.4",
|
|
28
28
|
"rehype-highlight": "^7.0.2",
|
|
29
29
|
"rehype-parse": "^9.0.1",
|
|
30
30
|
"rehype-stringify": "^10.0.1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doccupine",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"description": "Generate beautiful, ready-to-use documentation with just one CLI command β fast, simple, and open source.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"chalk": "^5.6.2",
|
|
33
|
-
"chokidar": "^
|
|
33
|
+
"chokidar": "^5.0.0",
|
|
34
34
|
"commander": "^14.0.2",
|
|
35
35
|
"fs-extra": "^11.3.2",
|
|
36
36
|
"gray-matter": "^4.0.3",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/chokidar": "^2.1.7",
|
|
41
41
|
"@types/fs-extra": "^11.0.4",
|
|
42
|
-
"@types/node": "^
|
|
42
|
+
"@types/node": "^25.0.0",
|
|
43
43
|
"@types/prompts": "^2.4.9",
|
|
44
44
|
"typescript": "^5.9.3"
|
|
45
45
|
},
|