@knitli/astro-docs-template 0.1.2 → 0.2.1

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.
@@ -1,46 +1,89 @@
1
- import { existsSync, statSync, mkdirSync, readdirSync, readFileSync, writeFileSync, cpSync } from 'node:fs';
2
- import { dirname, resolve, join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- export { default as createConfig } from './config.js';
5
-
6
- const __dirname$1 = dirname(fileURLToPath(import.meta.url));
7
- const SCAFFOLDING_DIR = resolve(__dirname$1, "../scaffolding");
8
- const PIECES = {
1
+ // SPDX-FileCopyrightText: 2026 Knitli Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ import {
6
+ cpSync,
7
+ existsSync,
8
+ mkdirSync,
9
+ readdirSync,
10
+ readFileSync,
11
+ statSync,
12
+ writeFileSync,
13
+ } from "node:fs";
14
+ import { dirname, join, resolve } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+
17
+ export { type DocsTemplateOptions, default as createConfig } from "./config.js";
18
+
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const SCAFFOLDING_DIR = resolve(__dirname, "../scaffolding");
21
+
22
+ // ── Options ──
23
+
24
+ export interface InitOptions {
25
+ /** Display name for the product (e.g. "Recoco", "CodeWeaver") */
26
+ appName: string;
27
+ /** npm package name (e.g. "@knitli-site/recoco-docs") */
28
+ name: string;
29
+ /** Short product description */
30
+ description: string;
31
+ /** Cloudflare Worker name (e.g. "recoco-docs") */
32
+ workerName?: string;
33
+ /** Whether this is a CodeWeaver-branded site */
34
+ is_codeweaver?: boolean;
35
+ }
36
+
37
+ export interface AddPiecesOptions extends InitOptions {
38
+ pieces: PieceName[];
39
+ /** Overwrite existing files (default: false — skips with a warning) */
40
+ force?: boolean;
41
+ }
42
+
43
+ // ── Piece definitions ──
44
+
45
+ export const PIECES = {
9
46
  config: {
10
47
  description: "Astro config using createConfig()",
11
- paths: ["astro.config.ts"]
48
+ paths: ["astro.config.ts"],
12
49
  },
13
50
  wrangler: {
14
51
  description: "Cloudflare Worker deployment config",
15
- paths: ["wrangler.jsonc"]
52
+ paths: ["wrangler.jsonc"],
16
53
  },
17
54
  tsconfig: {
18
55
  description: "TypeScript config extending shared base",
19
- paths: ["tsconfig.json"]
56
+ paths: ["tsconfig.json"],
20
57
  },
21
58
  content: {
22
59
  description: "Content collections, env types, and tags",
23
- paths: ["src/content.config.ts", "src/env.d.ts", "tags.yml"]
60
+ paths: ["src/content.config.ts", "src/env.d.ts", "tags.yml"],
24
61
  },
25
62
  mise: {
26
63
  description: "mise dev tasks (build, deploy, clean, etc.)",
27
- paths: ["mise.toml"]
64
+ paths: ["mise.toml"],
28
65
  },
29
66
  styles: {
30
67
  description: "Custom CSS hook for site-specific styles",
31
- paths: ["src/styles/custom.css"]
68
+ paths: ["src/styles/custom.css"],
32
69
  },
33
70
  deps: {
34
71
  description: "package.json with template dependencies",
35
- paths: ["package.json"]
72
+ paths: ["package.json"],
36
73
  },
37
74
  "starter-content": {
38
75
  description: "Example documentation pages",
39
- paths: ["src/content/docs"]
40
- }
41
- };
42
- const PIECE_NAMES = Object.keys(PIECES);
43
- const TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
76
+ paths: ["src/content/docs"],
77
+ },
78
+ } as const;
79
+
80
+ export type PieceName = keyof typeof PIECES;
81
+ export const PIECE_NAMES = Object.keys(PIECES) as PieceName[];
82
+
83
+ // ── Shared helpers ──
84
+
85
+ /** File extensions that should have placeholder substitution applied */
86
+ const TEXT_EXTENSIONS = new Set([
44
87
  ".ts",
45
88
  ".js",
46
89
  ".mjs",
@@ -53,28 +96,42 @@ const TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
53
96
  ".css",
54
97
  ".html",
55
98
  ".astro",
56
- ".toml"
99
+ ".toml",
57
100
  ]);
58
- function isTextFile(filePath) {
101
+
102
+ function isTextFile(filePath: string): boolean {
59
103
  return TEXT_EXTENSIONS.has(filePath.slice(filePath.lastIndexOf(".")));
60
104
  }
61
- function buildReplacements(options) {
105
+
106
+ function buildReplacements(options: InitOptions): Record<string, string> {
62
107
  return {
63
108
  "{{appName}}": options.appName,
64
109
  "{{appNameLower}}": options.appName.toLowerCase(),
65
110
  "{{name}}": options.name,
66
111
  "{{description}}": options.description,
67
- "{{workerName}}": options.workerName ?? `${options.appName.toLowerCase()}-docs`
112
+ "{{workerName}}":
113
+ options.workerName ?? `${options.appName.toLowerCase()}-docs`,
68
114
  };
69
115
  }
70
- function applyReplacements(content, replacements) {
116
+
117
+ function applyReplacements(
118
+ content: string,
119
+ replacements: Record<string, string>,
120
+ ): string {
71
121
  let result = content;
72
122
  for (const [placeholder, value] of Object.entries(replacements)) {
73
123
  result = result.replaceAll(placeholder, value);
74
124
  }
75
125
  return result;
76
126
  }
77
- function copyFile(srcPath, destPath, replacements, created, force) {
127
+
128
+ function copyFile(
129
+ srcPath: string,
130
+ destPath: string,
131
+ replacements: Record<string, string>,
132
+ created: string[],
133
+ force?: boolean,
134
+ ): void {
78
135
  if (!force && existsSync(destPath)) {
79
136
  console.log(` skip ${destPath} (exists, use --force to overwrite)`);
80
137
  return;
@@ -88,7 +145,14 @@ function copyFile(srcPath, destPath, replacements, created, force) {
88
145
  }
89
146
  created.push(destPath);
90
147
  }
91
- function copyDirRecursive(srcDir, destDir, replacements, created, force) {
148
+
149
+ function copyDirRecursive(
150
+ srcDir: string,
151
+ destDir: string,
152
+ replacements: Record<string, string>,
153
+ created: string[],
154
+ force?: boolean,
155
+ ): void {
92
156
  mkdirSync(destDir, { recursive: true });
93
157
  for (const entry of readdirSync(srcDir)) {
94
158
  const srcPath = join(srcDir, entry);
@@ -100,51 +164,79 @@ function copyDirRecursive(srcDir, destDir, replacements, created, force) {
100
164
  }
101
165
  }
102
166
  }
103
- function initDocsTemplate(targetPath, options) {
167
+
168
+ // ── Public API ──
169
+
170
+ /**
171
+ * Initialize a new Knitli docs site from the template scaffolding.
172
+ *
173
+ * Copies all files from the scaffolding directory to the target path,
174
+ * applying placeholder substitution to text files.
175
+ */
176
+ export function initDocsTemplate(
177
+ targetPath: string,
178
+ options: InitOptions,
179
+ ): string[] {
104
180
  const target = resolve(targetPath);
105
181
  const replacements = buildReplacements(options);
106
- const created = [];
182
+ const created: string[] = [];
183
+
107
184
  if (!existsSync(SCAFFOLDING_DIR)) {
108
185
  throw new Error(`Scaffolding directory not found at ${SCAFFOLDING_DIR}`);
109
186
  }
187
+
110
188
  copyDirRecursive(SCAFFOLDING_DIR, target, replacements, created, true);
111
189
  return created;
112
190
  }
113
- function addPieces(targetPath, options) {
191
+
192
+ /**
193
+ * Add specific pieces from the template scaffolding to an existing project.
194
+ *
195
+ * Unlike initDocsTemplate, this only copies the files belonging to the
196
+ * requested pieces and skips existing files unless force is set.
197
+ */
198
+ export function addPieces(
199
+ targetPath: string,
200
+ options: AddPiecesOptions,
201
+ ): string[] {
114
202
  const target = resolve(targetPath);
115
203
  const replacements = buildReplacements(options);
116
- const created = [];
204
+ const created: string[] = [];
205
+
117
206
  if (!existsSync(SCAFFOLDING_DIR)) {
118
207
  throw new Error(`Scaffolding directory not found at ${SCAFFOLDING_DIR}`);
119
208
  }
209
+
120
210
  for (const piece of options.pieces) {
121
211
  const pieceDef = PIECES[piece];
122
212
  if (!pieceDef) {
123
213
  throw new Error(
124
- `Unknown piece: ${piece}. Available: ${PIECE_NAMES.join(", ")}`
214
+ `Unknown piece: ${piece}. Available: ${PIECE_NAMES.join(", ")}`,
125
215
  );
126
216
  }
217
+
127
218
  for (const relPath of pieceDef.paths) {
128
219
  const srcPath = join(SCAFFOLDING_DIR, relPath);
129
220
  const destPath = join(target, relPath);
221
+
130
222
  if (!existsSync(srcPath)) {
131
223
  console.warn(` warn: ${relPath} not found in scaffolding, skipping`);
132
224
  continue;
133
225
  }
226
+
134
227
  if (statSync(srcPath).isDirectory()) {
135
228
  copyDirRecursive(
136
229
  srcPath,
137
230
  destPath,
138
231
  replacements,
139
232
  created,
140
- options.force
233
+ options.force,
141
234
  );
142
235
  } else {
143
236
  copyFile(srcPath, destPath, replacements, created, options.force);
144
237
  }
145
238
  }
146
239
  }
240
+
147
241
  return created;
148
242
  }
149
-
150
- export { PIECES, PIECE_NAMES, addPieces, initDocsTemplate };
package/dist/cli.d.ts DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env bun
2
- export {};
3
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/config.d.ts DELETED
@@ -1,59 +0,0 @@
1
- import type { OutgoingHttpHeaders } from "node:http2";
2
- type defaultIntegration = "sitemap" | "astroD2" | "markdoc" | "mdx" | "favicons" | "cloudflare-pages-headers";
3
- export declare const headlineLogoDark: string, headlineLogoLight: string, variables: string, docsStyle: string, faviconIco: string, faviconSvg: string;
4
- declare const shikiCfg: {
5
- themes: {
6
- light: "catppuccin-latte";
7
- dark: "catppuccin-mocha";
8
- };
9
- bundledLangs: string[];
10
- langAlias: {
11
- js: string;
12
- md: string;
13
- py: string;
14
- rs: string;
15
- sh: string;
16
- yml: string;
17
- };
18
- };
19
- declare const imgDomains: {
20
- protocol: string;
21
- hostname: string;
22
- }[];
23
- export interface DocsTemplateOptions {
24
- appName: string;
25
- description: string;
26
- llmConfig: {
27
- llmDescription: string;
28
- promotePatterns: string[];
29
- demotePatterns: string[];
30
- };
31
- rootDir: string;
32
- shikiConfig?: typeof shikiCfg;
33
- logoDark?: string;
34
- logoLight?: string;
35
- imageDomains?: typeof imgDomains;
36
- is_codeweaver?: boolean;
37
- sitemapFilter?: (page: string) => boolean;
38
- linkValidationConfig?: Record<string, unknown>;
39
- sidebarConfig?: {
40
- label: string;
41
- autogenerate: {
42
- directory: string;
43
- };
44
- }[];
45
- unwantedPlugins?: string[];
46
- pluginConfigs?: Record<string, any>;
47
- unwantedIntegrations?: defaultIntegration[];
48
- integrationConfigs?: Record<string, any>;
49
- headersConfig?: OutgoingHttpHeaders;
50
- }
51
- export type IntegrationOptions = Pick<DocsTemplateOptions, "appName" | "sitemapFilter" | "integrationConfigs"> & {
52
- unwantedIntegrations?: defaultIntegration[];
53
- };
54
- export type PluginOptions = Pick<DocsTemplateOptions, "appName" | "llmConfig" | "pluginConfigs"> & {
55
- unwantedPlugins?: string[];
56
- };
57
- export default function createConfig(options: DocsTemplateOptions): import("astro").AstroUserConfig<never, never, never>;
58
- export {};
59
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AA6BtD,KAAK,kBAAkB,GACnB,SAAS,GACT,SAAS,GACT,SAAS,GACT,KAAK,GACL,UAAU,GACV,0BAA0B,CAAC;AAQ/B,eAAO,MACL,gBAAgB,UAChB,iBAAiB,UACjB,SAAS,UACT,SAAS,UACT,UAAU,UACV,UAAU,QACE,CAAC;AAEf,QAAA,MAAM,QAAQ;;;;;;;;;;;;;;CAyBb,CAAC;AAEF,QAAA,MAAM,UAAU;;;GAMf,CAAC;AA8DF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACT,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,QAAQ,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,UAAU,CAAC;IACjC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1C,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE;QACd,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE;YAAE,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;KACrC,EAAE,CAAC;IACJ,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACpC,oBAAoB,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAE5C,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACzC,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACrC;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,mBAAmB,EACnB,SAAS,GAAG,eAAe,GAAG,oBAAoB,CACnD,GAAG;IAAE,oBAAoB,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAAE,CAAC;AA+DpD,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,mBAAmB,EACnB,SAAS,GAAG,WAAW,GAAG,eAAe,CAC1C,GAAG;IAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAoEnC,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,OAAO,EAAE,mBAAmB,wDAuOhE"}
package/dist/index.d.ts DELETED
@@ -1,69 +0,0 @@
1
- export { type DocsTemplateOptions, default as createConfig } from "./config.js";
2
- export interface InitOptions {
3
- /** Display name for the product (e.g. "Recoco", "CodeWeaver") */
4
- appName: string;
5
- /** npm package name (e.g. "@knitli-site/recoco-docs") */
6
- name: string;
7
- /** Short product description */
8
- description: string;
9
- /** Cloudflare Worker name (e.g. "recoco-docs") */
10
- workerName?: string;
11
- /** Whether this is a CodeWeaver-branded site */
12
- is_codeweaver?: boolean;
13
- }
14
- export interface AddPiecesOptions extends InitOptions {
15
- pieces: PieceName[];
16
- /** Overwrite existing files (default: false — skips with a warning) */
17
- force?: boolean;
18
- }
19
- export declare const PIECES: {
20
- readonly config: {
21
- readonly description: "Astro config using createConfig()";
22
- readonly paths: readonly ["astro.config.ts"];
23
- };
24
- readonly wrangler: {
25
- readonly description: "Cloudflare Worker deployment config";
26
- readonly paths: readonly ["wrangler.jsonc"];
27
- };
28
- readonly tsconfig: {
29
- readonly description: "TypeScript config extending shared base";
30
- readonly paths: readonly ["tsconfig.json"];
31
- };
32
- readonly content: {
33
- readonly description: "Content collections, env types, and tags";
34
- readonly paths: readonly ["src/content.config.ts", "src/env.d.ts", "tags.yml"];
35
- };
36
- readonly mise: {
37
- readonly description: "mise dev tasks (build, deploy, clean, etc.)";
38
- readonly paths: readonly ["mise.toml"];
39
- };
40
- readonly styles: {
41
- readonly description: "Custom CSS hook for site-specific styles";
42
- readonly paths: readonly ["src/styles/custom.css"];
43
- };
44
- readonly deps: {
45
- readonly description: "package.json with template dependencies";
46
- readonly paths: readonly ["package.json"];
47
- };
48
- readonly "starter-content": {
49
- readonly description: "Example documentation pages";
50
- readonly paths: readonly ["src/content/docs"];
51
- };
52
- };
53
- export type PieceName = keyof typeof PIECES;
54
- export declare const PIECE_NAMES: PieceName[];
55
- /**
56
- * Initialize a new Knitli docs site from the template scaffolding.
57
- *
58
- * Copies all files from the scaffolding directory to the target path,
59
- * applying placeholder substitution to text files.
60
- */
61
- export declare function initDocsTemplate(targetPath: string, options: InitOptions): string[];
62
- /**
63
- * Add specific pieces from the template scaffolding to an existing project.
64
- *
65
- * Unlike initDocsTemplate, this only copies the files belonging to the
66
- * requested pieces and skips existing files unless force is set.
67
- */
68
- export declare function addPieces(targetPath: string, options: AddPiecesOptions): string[];
69
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,KAAK,mBAAmB,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,aAAa,CAAC;AAOhF,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAID,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCT,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,MAAM,CAAC;AAC5C,eAAO,MAAM,WAAW,EAA0B,SAAS,EAAE,CAAC;AAyF9D;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,MAAM,EAAE,CAWV;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,GACxB,MAAM,EAAE,CAyCV"}