@tenphi/docs 0.12.0 → 0.15.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/README.md CHANGED
@@ -5,4 +5,26 @@ graph construction, Markdown reference rewriting, and diagnostics for Cookbook.
5
5
 
6
6
  ```ts
7
7
  import { createDocsGraph, defineDocsConfig } from "@tenphi/docs";
8
+
9
+ const config = defineDocsConfig({
10
+ content: {
11
+ localizeRepositoryLinks: true,
12
+ sources: [
13
+ { file: "README.md", route: "/" },
14
+ { glob: "docs/**/*.{md,mdx}", base: "docs" },
15
+ ],
16
+ },
17
+ });
18
+
19
+ const graph = await createDocsGraph({ root: process.cwd(), config });
8
20
  ```
21
+
22
+ The graph validates routes, fragments, navigation, raw HTML policy, and assets
23
+ without mutating source files. It rewrites inline, reference-style, and matched
24
+ absolute repository links; hashes and collects local images/downloads;
25
+ understands trusted MDX syntax; and confines locked npm artifacts to their
26
+ extraction root.
27
+
28
+ Most applications should install `@tenphi/cookbook`, which combines this engine
29
+ with the supported Astro/Starlight renderer. This package is useful for custom
30
+ tooling, validation, and alternate renderers. Node.js 22.14 or newer is required.
@@ -1,4 +1,4 @@
1
- import { A as NavigationConfig, B as SiteIconConfig, D as HeadConfig, E as EditLinkConfig, G as TypographyPreset, H as ThemePaletteConfig, K as TypographyPresets, N as NavigationTab, O as LocaleConfig, P as NormalizedDocsConfig, R as SearchConfig, T as DocsSource, U as ThemeTokenValue, V as ThemeConfig, W as ThemeTokens, _ as DocsConfig, a as ComponentStyleConfig, c as ComponentsConfig, j as NavigationItem, k as MarkdownConfig, l as ContentConfig, n as BuildConfig, o as ComponentStyles, s as ComponentStylesConfig, t as BrandConfig, u as CookbookComponentName, v as DocsDiagnostic, z as SiteConfig } from "../types-m7SvwRsi.js";
1
+ import { A as NavigationConfig, B as SiteIconConfig, D as HeadConfig, E as EditLinkConfig, G as TypographyPreset, H as ThemePaletteConfig, K as TypographyPresets, M as NavigationPlacement, N as NavigationTab, O as LocaleConfig, P as NormalizedDocsConfig, R as SearchConfig, T as DocsSource, U as ThemeTokenValue, V as ThemeConfig, W as ThemeTokens, _ as DocsConfig, a as ComponentStyleConfig, c as ComponentsConfig, i as COOKBOOK_COMPONENT_SUB_ELEMENTS, j as NavigationItem, k as MarkdownConfig, l as ContentConfig, n as BuildConfig, o as ComponentStyles, r as COOKBOOK_COMPONENT_NAMES, s as ComponentStylesConfig, t as BrandConfig, u as CookbookComponentName, v as DocsDiagnostic, z as SiteConfig } from "../types-B-msp1dH.js";
2
2
  //#region src/config/index.d.ts
3
3
  declare class DocsConfigError extends Error {
4
4
  readonly diagnostics: DocsDiagnostic[];
@@ -6,7 +6,9 @@ declare class DocsConfigError extends Error {
6
6
  }
7
7
  declare function validateConfig(config: DocsConfig): DocsDiagnostic[];
8
8
  declare function normalizeDocsConfig(config?: DocsConfig): NormalizedDocsConfig;
9
- declare function defineDocsConfig<const T extends DocsConfig>(config: T): T;
9
+ declare function defineDocsConfig(config: DocsConfig): DocsConfig;
10
+ /** Compose presets. Objects merge, arrays replace, and styles use Tasty semantics. */
11
+ declare function mergeDocsConfig(...configs: DocsConfig[]): DocsConfig;
10
12
  //#endregion
11
- export { type BrandConfig, type BuildConfig, type ComponentStyleConfig, type ComponentStyles, type ComponentStylesConfig, type ComponentsConfig, type ContentConfig, type CookbookComponentName, type DocsConfig, DocsConfigError, type DocsSource, type EditLinkConfig, type HeadConfig, type LocaleConfig, type MarkdownConfig, type NavigationConfig, type NavigationItem, type NavigationTab, type NormalizedDocsConfig, type SearchConfig, type SiteConfig, type SiteIconConfig, type ThemeConfig, type ThemePaletteConfig, type ThemeTokenValue, type ThemeTokens, type TypographyPreset, type TypographyPresets, defineDocsConfig, normalizeDocsConfig, validateConfig };
13
+ export { type BrandConfig, type BuildConfig, COOKBOOK_COMPONENT_NAMES, COOKBOOK_COMPONENT_SUB_ELEMENTS, type ComponentStyleConfig, type ComponentStyles, type ComponentStylesConfig, type ComponentsConfig, type ContentConfig, type CookbookComponentName, type DocsConfig, DocsConfigError, type DocsSource, type EditLinkConfig, type HeadConfig, type LocaleConfig, type MarkdownConfig, type NavigationConfig, type NavigationItem, type NavigationPlacement, type NavigationTab, type NormalizedDocsConfig, type SearchConfig, type SiteConfig, type SiteIconConfig, type ThemeConfig, type ThemePaletteConfig, type ThemeTokenValue, type ThemeTokens, type TypographyPreset, type TypographyPresets, defineDocsConfig, mergeDocsConfig, normalizeDocsConfig, validateConfig };
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/config/index.ts"],"mappings":";;cAoEa,wBAAwB;WAC1B,aAAa;EAEtB,YAAY,aAAa;;iBAOX,eAAe,QAAQ,aAAa;iBA0OpC,oBACd,SAAQ,aACP;iBA6Ca,uBAAuB,UAAU,YAAY,QAAQ,IAAI"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/config/index.ts"],"mappings":";;cAyEa,wBAAwB;WAC1B,aAAa;EAEtB,YAAY,aAAa;;iBAOX,eAAe,QAAQ,aAAa;iBA4iBpC,oBACd,SAAQ,aACP;iBA4Ca,iBAAiB,QAAQ,aAAa;;iBAOtC,mBAAmB,SAAS,eAAe"}
@@ -1,240 +1,2 @@
1
- //#region src/config/index.ts
2
- const DEFAULT_BRAND = "#315efb";
3
- const HEAD_KEYS = /* @__PURE__ */ new Set([
4
- "tag",
5
- "attrs",
6
- "content"
7
- ]);
8
- const SITE_ICON_KEYS = /* @__PURE__ */ new Set(["source", "background"]);
9
- const ROOT_KEYS = /* @__PURE__ */ new Set([
10
- "site",
11
- "head",
12
- "editLink",
13
- "lastUpdated",
14
- "locales",
15
- "defaultLocale",
16
- "content",
17
- "navigation",
18
- "theme",
19
- "markdown",
20
- "search",
21
- "components",
22
- "build"
23
- ]);
24
- const OBJECT_KEYS = {
25
- site: /* @__PURE__ */ new Set([
26
- "title",
27
- "version",
28
- "description",
29
- "url",
30
- "repository",
31
- "favicon"
32
- ]),
33
- content: /* @__PURE__ */ new Set([
34
- "sources",
35
- "allowOutsideRoot",
36
- "localizeRepositoryLinks"
37
- ]),
38
- markdown: /* @__PURE__ */ new Set([
39
- "stripLeadingBadges",
40
- "rawHtml",
41
- "strictLanguages",
42
- "executablePreviews",
43
- "remarkPlugins",
44
- "rehypePlugins"
45
- ]),
46
- search: /* @__PURE__ */ new Set(["enabled"]),
47
- components: /* @__PURE__ */ new Set(["overrides"]),
48
- theme: /* @__PURE__ */ new Set([
49
- "variant",
50
- "brand",
51
- "palette",
52
- "states",
53
- "tokens",
54
- "presets",
55
- "styles",
56
- "contrastLevel"
57
- ]),
58
- build: /* @__PURE__ */ new Set([
59
- "strict",
60
- "ci",
61
- "base",
62
- "cacheDir",
63
- "maxArtifactBytes",
64
- "maxUnpackedBytes",
65
- "maxFiles",
66
- "maxPathDepth",
67
- "maxAssetBytes"
68
- ])
69
- };
70
- var DocsConfigError = class extends Error {
71
- diagnostics;
72
- constructor(diagnostics) {
73
- super(diagnostics.map((diagnostic) => diagnostic.message).join("\n"));
74
- this.name = "DocsConfigError";
75
- this.diagnostics = diagnostics;
76
- }
77
- };
78
- function validateConfig(config) {
79
- const diagnostics = [];
80
- for (const key of Object.keys(config)) if (!ROOT_KEYS.has(key)) unknown(diagnostics, key);
81
- for (const [section, keys] of Object.entries(OBJECT_KEYS)) {
82
- const value = config[section];
83
- if (value === void 0 || Array.isArray(value) || typeof value !== "object") continue;
84
- for (const key of Object.keys(value)) if (!keys.has(key)) unknown(diagnostics, `${section}.${key}`);
85
- }
86
- const head = config.head;
87
- if (head !== void 0 && !Array.isArray(head)) invalid(diagnostics, "head must be an array.");
88
- else for (const [index, entry] of (head ?? []).entries()) {
89
- if (!isRecord(entry)) {
90
- invalid(diagnostics, `head[${index}] must be an object.`);
91
- continue;
92
- }
93
- for (const key of Object.keys(entry)) if (!HEAD_KEYS.has(key)) unknown(diagnostics, `head[${index}].${key}`);
94
- if (typeof entry.tag !== "string") invalid(diagnostics, `head[${index}].tag must be a string.`);
95
- if (entry.attrs !== void 0 && !isRecord(entry.attrs)) invalid(diagnostics, `head[${index}].attrs must be an object.`);
96
- else for (const [name, value] of Object.entries(entry.attrs ?? {})) if (value !== void 0 && typeof value !== "string" && typeof value !== "boolean") invalid(diagnostics, `head[${index}].attrs.${name} must be a string or boolean.`);
97
- if (entry.content !== void 0 && typeof entry.content !== "string") invalid(diagnostics, `head[${index}].content must be a string.`);
98
- }
99
- const favicon = config.site?.favicon;
100
- if (favicon !== void 0) {
101
- if (typeof favicon === "string") {
102
- if (favicon.trim() === "") invalid(diagnostics, "site.favicon must be a non-empty local path.");
103
- } else if (!isRecord(favicon)) invalid(diagnostics, "site.favicon must be a local path or an object with a source path.");
104
- else {
105
- for (const key of Object.keys(favicon)) if (!SITE_ICON_KEYS.has(key)) unknown(diagnostics, `site.favicon.${key}`);
106
- if (typeof favicon.source !== "string" || favicon.source.trim() === "") invalid(diagnostics, "site.favicon.source must be a non-empty string.");
107
- if (favicon.background !== void 0 && (typeof favicon.background !== "string" || favicon.background.trim() === "")) invalid(diagnostics, "site.favicon.background must be a non-empty color string.");
108
- }
109
- }
110
- if (config.editLink !== void 0 && (!isRecord(config.editLink) || typeof config.editLink.baseUrl !== "string")) invalid(diagnostics, "editLink must contain a string baseUrl.");
111
- else if (config.editLink !== void 0) {
112
- for (const key of Object.keys(config.editLink)) if (key !== "baseUrl") unknown(diagnostics, `editLink.${key}`);
113
- try {
114
- new URL(config.editLink.baseUrl);
115
- } catch {
116
- invalid(diagnostics, "editLink.baseUrl must be an absolute URL.");
117
- }
118
- }
119
- if (config.lastUpdated !== void 0 && typeof config.lastUpdated !== "boolean") invalid(diagnostics, "lastUpdated must be a boolean.");
120
- if (config.locales !== void 0 && !isRecord(config.locales)) invalid(diagnostics, "locales must be an object.");
121
- else for (const [key, locale] of Object.entries(config.locales ?? {})) {
122
- if (!isRecord(locale) || typeof locale.label !== "string") {
123
- invalid(diagnostics, `locales.${key} must contain a string label.`);
124
- continue;
125
- }
126
- for (const property of Object.keys(locale)) if (![
127
- "label",
128
- "lang",
129
- "dir"
130
- ].includes(property)) unknown(diagnostics, `locales.${key}.${property}`);
131
- if (locale.lang !== void 0 && typeof locale.lang !== "string") invalid(diagnostics, `locales.${key}.lang must be a string.`);
132
- if (locale.dir !== void 0 && locale.dir !== "ltr" && locale.dir !== "rtl") invalid(diagnostics, `locales.${key}.dir must be "ltr" or "rtl".`);
133
- }
134
- if (config.defaultLocale !== void 0 && typeof config.defaultLocale !== "string") invalid(diagnostics, "defaultLocale must be a string.");
135
- else if (config.defaultLocale !== void 0 && (config.locales === void 0 || !(config.defaultLocale in config.locales))) invalid(diagnostics, `defaultLocale must match a key in locales; received "${config.defaultLocale}".`);
136
- const sources = config.content?.sources ?? [];
137
- for (const [index, source] of sources.entries()) if ([
138
- "file",
139
- "glob",
140
- "package"
141
- ].filter((key) => key in source).length !== 1) diagnostics.push({
142
- code: "DOCS_CONFIG_INVALID",
143
- severity: "error",
144
- message: `content.sources[${index}] must select exactly one of file, glob, or package.`
145
- });
146
- const brand = config.theme?.brand;
147
- if (typeof brand === "object" && brand !== null && "contrast" in brand && !brand.unsafeContrast) {
148
- const target = brand.contrast?.apca;
149
- const normal = Array.isArray(target) ? target[0] : target;
150
- if (typeof normal === "number" && normal < 45) diagnostics.push({
151
- code: "DOCS_CONFIG_INVALID",
152
- severity: "error",
153
- message: "theme.brand.contrast.apca cannot be below 45 without unsafeContrast.",
154
- hint: "Remove the override, use 45 or higher, or explicitly set unsafeContrast: true."
155
- });
156
- }
157
- for (const [name, entry] of Object.entries(config.theme?.styles ?? {})) if (!isRecord(entry)) invalid(diagnostics, `theme.styles.${name} must be a Tasty style object.`);
158
- else if ("mode" in entry) invalid(diagnostics, `theme.styles.${name} must contain only the Tasty style properties to override, without a mode wrapper.`);
159
- const componentOverrides = config.components?.overrides;
160
- if (componentOverrides !== void 0 && !isRecord(componentOverrides)) invalid(diagnostics, "components.overrides must be an object.");
161
- else for (const [name, override] of Object.entries(componentOverrides ?? {})) {
162
- if (typeof override === "string") continue;
163
- if (name === "Footer" && override === false) continue;
164
- invalid(diagnostics, `components.overrides.${name} must be an Astro component path${name === "Footer" ? " or false" : ""}.`);
165
- }
166
- return diagnostics;
167
- }
168
- function unknown(diagnostics, path) {
169
- diagnostics.push({
170
- code: "DOCS_CONFIG_UNKNOWN_KEY",
171
- severity: "error",
172
- message: `Unknown configuration key "${path}".`
173
- });
174
- }
175
- function invalid(diagnostics, message) {
176
- diagnostics.push({
177
- code: "DOCS_CONFIG_INVALID",
178
- severity: "error",
179
- message
180
- });
181
- }
182
- function isRecord(value) {
183
- return typeof value === "object" && value !== null && !Array.isArray(value);
184
- }
185
- function normalizeDocsConfig(config = {}) {
186
- const diagnostics = validateConfig(config);
187
- if (diagnostics.length > 0) throw new DocsConfigError(diagnostics);
188
- const navigation = Array.isArray(config.navigation) ? { items: config.navigation } : config.navigation ?? {};
189
- return {
190
- site: { ...config.site },
191
- head: [...config.head ?? []],
192
- ...config.editLink ? { editLink: { ...config.editLink } } : {},
193
- lastUpdated: config.lastUpdated ?? false,
194
- ...config.locales ? { locales: { ...config.locales } } : {},
195
- ...config.defaultLocale ? { defaultLocale: config.defaultLocale } : {},
196
- content: {
197
- allowOutsideRoot: false,
198
- localizeRepositoryLinks: false,
199
- ...config.content
200
- },
201
- navigation,
202
- theme: {
203
- ...config.theme,
204
- brand: config.theme?.brand ?? DEFAULT_BRAND
205
- },
206
- markdown: {
207
- stripLeadingBadges: true,
208
- rawHtml: "sanitize",
209
- strictLanguages: false,
210
- executablePreviews: true,
211
- ...config.markdown
212
- },
213
- search: {
214
- enabled: true,
215
- ...config.search
216
- },
217
- components: { ...config.components },
218
- build: {
219
- strict: true,
220
- ci: process.env.CI === "true",
221
- base: "/",
222
- cacheDir: "",
223
- maxArtifactBytes: 26214400,
224
- maxUnpackedBytes: 104857600,
225
- maxFiles: 1e4,
226
- maxPathDepth: 24,
227
- maxAssetBytes: 20971520,
228
- ...config.build
229
- }
230
- };
231
- }
232
- function defineDocsConfig(config) {
233
- const diagnostics = validateConfig(config);
234
- if (diagnostics.length > 0) throw new DocsConfigError(diagnostics);
235
- return config;
236
- }
237
- //#endregion
238
- export { DocsConfigError, defineDocsConfig, normalizeDocsConfig, validateConfig };
239
-
240
- //# sourceMappingURL=index.js.map
1
+ import { a as validateConfig, i as normalizeDocsConfig, n as defineDocsConfig, o as COOKBOOK_COMPONENT_NAMES, r as mergeDocsConfig, s as COOKBOOK_COMPONENT_SUB_ELEMENTS, t as DocsConfigError } from "../config-DoR8g9IM.js";
2
+ export { COOKBOOK_COMPONENT_NAMES, COOKBOOK_COMPONENT_SUB_ELEMENTS, DocsConfigError, defineDocsConfig, mergeDocsConfig, normalizeDocsConfig, validateConfig };