@shadow-shard-tools/docs-core 1.0.18 → 1.0.19
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 +57 -0
- package/dist/cjs/configs/clientConfig.js +28 -112
- package/dist/cjs/configs/index.browser.js +16 -0
- package/dist/cjs/configs/sstDocsConfigShared.js +159 -101
- package/dist/cjs/data/buildTree.js +48 -10
- package/dist/cjs/data/fsDataProvider.browser.js +10 -0
- package/dist/cjs/data/index.browser.js +17 -0
- package/dist/cjs/data/index.js +4 -1
- package/dist/cjs/data/loadAllCategories.js +15 -5
- package/dist/cjs/data/loadAllItems.js +19 -7
- package/dist/cjs/data/loadVersionData.fs.js +29 -0
- package/dist/cjs/data/loadVersionData.js +69 -7
- package/dist/cjs/index.browser.js +22 -0
- package/dist/cjs/themes/index.js +5 -1
- package/dist/cjs/themes/styleThemeSchema.js +36 -0
- package/dist/cjs/types/DataDiagnostic.js +2 -0
- package/dist/cjs/utilities/index.browser.js +53 -0
- package/dist/cjs/utilities/path/pathExists.browser.js +6 -0
- package/dist/cjs/utilities/path/pathExists.js +1 -1
- package/dist/cjs/utilities/path/resolveAgainstProjectRoot.browser.js +6 -0
- package/dist/cjs/utilities/path/resolveDataPath.browser.js +6 -0
- package/dist/cjs/utilities/path/resolveDataPath.js +1 -1
- package/dist/cjs/utilities/string/withBasePath.js +37 -9
- package/dist/cjs/utilities/system/logger.browser.js +39 -0
- package/dist/cjs/utilities/system/logger.js +26 -6
- package/dist/configs/clientConfig.d.ts.map +1 -1
- package/dist/configs/clientConfig.js +28 -112
- package/dist/configs/clientConfig.js.map +1 -1
- package/dist/configs/index.browser.d.ts +4 -0
- package/dist/configs/index.browser.d.ts.map +1 -0
- package/dist/configs/index.browser.js +4 -0
- package/dist/configs/index.browser.js.map +1 -0
- package/dist/configs/sstDocsConfig.browser.d.ts.map +1 -1
- package/dist/configs/sstDocsConfig.browser.js.map +1 -1
- package/dist/configs/sstDocsConfig.d.ts.map +1 -1
- package/dist/configs/sstDocsConfig.js.map +1 -1
- package/dist/configs/sstDocsConfigShared.d.ts +8 -0
- package/dist/configs/sstDocsConfigShared.d.ts.map +1 -1
- package/dist/configs/sstDocsConfigShared.js +158 -97
- package/dist/configs/sstDocsConfigShared.js.map +1 -1
- package/dist/data/buildTree.d.ts +10 -2
- package/dist/data/buildTree.d.ts.map +1 -1
- package/dist/data/buildTree.js +48 -10
- package/dist/data/buildTree.js.map +1 -1
- package/dist/data/fsDataProvider.browser.d.ts +6 -0
- package/dist/data/fsDataProvider.browser.d.ts.map +1 -0
- package/dist/data/fsDataProvider.browser.js +7 -0
- package/dist/data/fsDataProvider.browser.js.map +1 -0
- package/dist/data/fsDataProvider.d.ts.map +1 -1
- package/dist/data/fsDataProvider.js.map +1 -1
- package/dist/data/index.browser.d.ts +7 -0
- package/dist/data/index.browser.d.ts.map +1 -0
- package/dist/data/index.browser.js +7 -0
- package/dist/data/index.browser.js.map +1 -0
- package/dist/data/index.d.ts +2 -1
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +2 -1
- package/dist/data/index.js.map +1 -1
- package/dist/data/loadAllCategories.d.ts +10 -1
- package/dist/data/loadAllCategories.d.ts.map +1 -1
- package/dist/data/loadAllCategories.js +15 -5
- package/dist/data/loadAllCategories.js.map +1 -1
- package/dist/data/loadAllItems.d.ts +10 -1
- package/dist/data/loadAllItems.d.ts.map +1 -1
- package/dist/data/loadAllItems.js +19 -7
- package/dist/data/loadAllItems.js.map +1 -1
- package/dist/data/loadVersionData.d.ts +22 -1
- package/dist/data/loadVersionData.d.ts.map +1 -1
- package/dist/data/loadVersionData.fs.d.ts +3 -0
- package/dist/data/loadVersionData.fs.d.ts.map +1 -0
- package/dist/data/loadVersionData.fs.js +24 -0
- package/dist/data/loadVersionData.fs.js.map +1 -0
- package/dist/data/loadVersionData.js +67 -7
- package/dist/data/loadVersionData.js.map +1 -1
- package/dist/index.browser.d.ts +7 -0
- package/dist/index.browser.d.ts.map +1 -0
- package/dist/index.browser.js +7 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/themes/index.d.ts +1 -0
- package/dist/themes/index.d.ts.map +1 -1
- package/dist/themes/index.js +1 -0
- package/dist/themes/index.js.map +1 -1
- package/dist/themes/styleThemeSchema.d.ts +6 -0
- package/dist/themes/styleThemeSchema.d.ts.map +1 -0
- package/dist/themes/styleThemeSchema.js +32 -0
- package/dist/themes/styleThemeSchema.js.map +1 -0
- package/dist/themes/themeRegistry.d.ts.map +1 -1
- package/dist/themes/themeRegistry.js.map +1 -1
- package/dist/types/DataDiagnostic.d.ts +8 -0
- package/dist/types/DataDiagnostic.d.ts.map +1 -0
- package/dist/types/DataDiagnostic.js +2 -0
- package/dist/types/DataDiagnostic.js.map +1 -0
- package/dist/types/HtmlGeneratorSettings.d.ts +1 -1
- package/dist/types/HtmlGeneratorSettings.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utilities/index.browser.d.ts +23 -0
- package/dist/utilities/index.browser.d.ts.map +1 -0
- package/dist/utilities/index.browser.js +29 -0
- package/dist/utilities/index.browser.js.map +1 -0
- package/dist/utilities/path/pathExists.browser.d.ts +2 -0
- package/dist/utilities/path/pathExists.browser.d.ts.map +1 -0
- package/dist/utilities/path/pathExists.browser.js +4 -0
- package/dist/utilities/path/pathExists.browser.js.map +1 -0
- package/dist/utilities/path/pathExists.js +1 -1
- package/dist/utilities/path/pathExists.js.map +1 -1
- package/dist/utilities/path/resolveAgainstProjectRoot.browser.d.ts +2 -0
- package/dist/utilities/path/resolveAgainstProjectRoot.browser.d.ts.map +1 -0
- package/dist/utilities/path/resolveAgainstProjectRoot.browser.js +4 -0
- package/dist/utilities/path/resolveAgainstProjectRoot.browser.js.map +1 -0
- package/dist/utilities/path/resolveAgainstProjectRoot.d.ts.map +1 -1
- package/dist/utilities/path/resolveAgainstProjectRoot.js.map +1 -1
- package/dist/utilities/path/resolveDataPath.browser.d.ts +2 -0
- package/dist/utilities/path/resolveDataPath.browser.d.ts.map +1 -0
- package/dist/utilities/path/resolveDataPath.browser.js +4 -0
- package/dist/utilities/path/resolveDataPath.browser.js.map +1 -0
- package/dist/utilities/path/resolveDataPath.d.ts.map +1 -1
- package/dist/utilities/path/resolveDataPath.js +1 -1
- package/dist/utilities/path/resolveDataPath.js.map +1 -1
- package/dist/utilities/string/withBasePath.d.ts.map +1 -1
- package/dist/utilities/string/withBasePath.js +37 -6
- package/dist/utilities/string/withBasePath.js.map +1 -1
- package/dist/utilities/system/logger.browser.d.ts +3 -0
- package/dist/utilities/system/logger.browser.d.ts.map +1 -0
- package/dist/utilities/system/logger.browser.js +36 -0
- package/dist/utilities/system/logger.browser.js.map +1 -0
- package/dist/utilities/system/logger.d.ts.map +1 -1
- package/dist/utilities/system/logger.js +26 -6
- package/dist/utilities/system/logger.js.map +1 -1
- package/package.json +181 -9
package/README.md
CHANGED
|
@@ -25,6 +25,63 @@ import { CODE_LANGUAGE_CONFIG } from "@shadow-shard-tools/docs-core/configs/inde
|
|
|
25
25
|
Everything ships as native ESM with TypeScript declarations in `dist/`. Install with `npm install @shadow-shard-tools/docs-core` (or link locally) and cherry-pick the helpers and contracts you need.
|
|
26
26
|
CommonJS consumers can `require` the same subpaths via the conditional exports (built into `dist/cjs`).
|
|
27
27
|
|
|
28
|
+
## API map (common imports)
|
|
29
|
+
| Domain | Import from | Common exports |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| Configs | `@shadow-shard-tools/docs-core/configs` | `loadSstDocsConfig`, `buildClientVisibleConfig`, `serializeClientConfigForBrowser`, `exposeClientConfig`, `readClientConfig`, `CODE_LANGUAGE_CONFIG` |
|
|
32
|
+
| Data | `@shadow-shard-tools/docs-core/data` | `loadVersions`, `loadVersionData`, `buildTree`, `FsDataProvider`, `HttpDataProvider` |
|
|
33
|
+
| Themes | `@shadow-shard-tools/docs-core/themes` | `defaultTheme`, `getThemePreset`, `AVAILABLE_THEME_PRESET_NAMES`, `StyleTheme` |
|
|
34
|
+
| Utilities | `@shadow-shard-tools/docs-core/utilities` | `slugify`, `withBasePath`, `normalizeSystemPath`, `isValidImageUrl`, `createLogger` |
|
|
35
|
+
| Types | `@shadow-shard-tools/docs-core/types` | `Content`, `Version`, `StyleTheme`, `SstDocsConfigFile`, `ResolvedSstDocsConfig`, `ClientVisibleSstDocsConfig` |
|
|
36
|
+
|
|
37
|
+
## Quickstart recipes
|
|
38
|
+
### Load config and expose client config
|
|
39
|
+
```ts
|
|
40
|
+
import {
|
|
41
|
+
buildClientVisibleConfig,
|
|
42
|
+
exposeClientConfig,
|
|
43
|
+
loadSstDocsConfig,
|
|
44
|
+
readClientConfig,
|
|
45
|
+
serializeClientConfigForBrowser,
|
|
46
|
+
} from "@shadow-shard-tools/docs-core/configs";
|
|
47
|
+
|
|
48
|
+
const config = await loadSstDocsConfig();
|
|
49
|
+
const clientConfig = buildClientVisibleConfig(config);
|
|
50
|
+
|
|
51
|
+
// Server-side: embed into HTML (pretty for readability while debugging)
|
|
52
|
+
const clientScript = serializeClientConfigForBrowser(clientConfig, { pretty: true });
|
|
53
|
+
// -> <script>{clientScript}</script>
|
|
54
|
+
|
|
55
|
+
// Browser-side: attach and read from the global name (__SST_DOCS_CONFIG__ by default)
|
|
56
|
+
exposeClientConfig(clientConfig);
|
|
57
|
+
const cfg = readClientConfig();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Load docs from FS/HTTP and build a tree
|
|
61
|
+
```ts
|
|
62
|
+
import path from "node:path";
|
|
63
|
+
import {
|
|
64
|
+
FsDataProvider,
|
|
65
|
+
HttpDataProvider,
|
|
66
|
+
loadVersionData,
|
|
67
|
+
loadVersions,
|
|
68
|
+
} from "@shadow-shard-tools/docs-core/data";
|
|
69
|
+
|
|
70
|
+
// Local filesystem
|
|
71
|
+
const fsProvider = new FsDataProvider();
|
|
72
|
+
const dataRoot = path.resolve("./public/SST-Docs/data");
|
|
73
|
+
const versions = await loadVersions(fsProvider, dataRoot);
|
|
74
|
+
const versionRoot = `${dataRoot}/${versions[0]?.version ?? "current"}`;
|
|
75
|
+
const { tree, items, standaloneDocs } = await loadVersionData(fsProvider, versionRoot);
|
|
76
|
+
|
|
77
|
+
// Remote HTTP (e.g., CDN-hosted data)
|
|
78
|
+
const httpProvider = new HttpDataProvider();
|
|
79
|
+
const remoteRoot = "https://cdn.example.com/SST-Docs/data";
|
|
80
|
+
const remoteVersions = await loadVersions(httpProvider, remoteRoot);
|
|
81
|
+
const remoteVersionRoot = `${remoteRoot}/${remoteVersions[0]?.version ?? "current"}`;
|
|
82
|
+
const { tree: remoteTree } = await loadVersionData(httpProvider, remoteVersionRoot);
|
|
83
|
+
```
|
|
84
|
+
|
|
28
85
|
### Config example
|
|
29
86
|
Create `sst-docs.config.json` in your project root:
|
|
30
87
|
```json
|
|
@@ -5,7 +5,25 @@ exports.buildClientVisibleConfig = buildClientVisibleConfig;
|
|
|
5
5
|
exports.serializeClientConfigForBrowser = serializeClientConfigForBrowser;
|
|
6
6
|
exports.exposeClientConfig = exposeClientConfig;
|
|
7
7
|
exports.readClientConfig = readClientConfig;
|
|
8
|
+
const zod_1 = require("zod");
|
|
9
|
+
const styleThemeSchema_js_1 = require("../themes/styleThemeSchema.js");
|
|
8
10
|
exports.DEFAULT_CLIENT_CONFIG_GLOBAL = "__SST_DOCS_CONFIG__";
|
|
11
|
+
const headerBrandingSchema = zod_1.z
|
|
12
|
+
.object({
|
|
13
|
+
logoSrc: zod_1.z.string().optional(),
|
|
14
|
+
logoAlt: zod_1.z.string().optional(),
|
|
15
|
+
logoText: zod_1.z.string().optional(),
|
|
16
|
+
})
|
|
17
|
+
.strict()
|
|
18
|
+
.optional()
|
|
19
|
+
.default({});
|
|
20
|
+
const clientConfigSchema = zod_1.z
|
|
21
|
+
.object({
|
|
22
|
+
PUBLIC_DATA_PATH: zod_1.z.string(),
|
|
23
|
+
HEADER_BRANDING: headerBrandingSchema,
|
|
24
|
+
HTML_GENERATOR_THEME: styleThemeSchema_js_1.styleThemeSchema.optional(),
|
|
25
|
+
})
|
|
26
|
+
.strict();
|
|
9
27
|
function buildClientVisibleConfig(config) {
|
|
10
28
|
return {
|
|
11
29
|
PUBLIC_DATA_PATH: config.PUBLIC_DATA_PATH,
|
|
@@ -39,124 +57,22 @@ function readClientConfig(globalName = exports.DEFAULT_CLIENT_CONFIG_GLOBAL) {
|
|
|
39
57
|
return assertClientConfig(value, globalName);
|
|
40
58
|
}
|
|
41
59
|
function normalizeAndValidateClientConfigSource(source) {
|
|
42
|
-
const normalized =
|
|
60
|
+
const normalized = isClientConfigShape(source)
|
|
43
61
|
? source
|
|
44
62
|
: buildClientVisibleConfig(source);
|
|
45
63
|
return assertClientConfig(normalized);
|
|
46
64
|
}
|
|
47
65
|
function assertClientConfig(value, globalName = exports.DEFAULT_CLIENT_CONFIG_GLOBAL) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
const candidate = value;
|
|
58
|
-
const hasPublicPath = typeof candidate.PUBLIC_DATA_PATH === "string";
|
|
59
|
-
const hasBranding = isHeaderBranding(candidate.HEADER_BRANDING);
|
|
60
|
-
const hasTheme = candidate.HTML_GENERATOR_THEME === undefined ||
|
|
61
|
-
isStyleTheme(candidate.HTML_GENERATOR_THEME);
|
|
62
|
-
return hasPublicPath && hasBranding && hasTheme;
|
|
63
|
-
}
|
|
64
|
-
function isHeaderBranding(value) {
|
|
65
|
-
if (value === undefined)
|
|
66
|
-
return true;
|
|
67
|
-
if (!value || typeof value !== "object")
|
|
68
|
-
return false;
|
|
69
|
-
const record = value;
|
|
70
|
-
return (["logoSrc", "logoAlt", "logoText"].every((key) => key in record ? typeof record[key] === "string" || record[key] === undefined : true));
|
|
66
|
+
const parsed = clientConfigSchema.safeParse(value);
|
|
67
|
+
if (parsed.success)
|
|
68
|
+
return parsed.data;
|
|
69
|
+
const message = parsed.error.issues
|
|
70
|
+
.map((issue) => `${issue.path.join(".") || "config"}: ${issue.message}`)
|
|
71
|
+
.join("; ");
|
|
72
|
+
throw new Error(`Client config "${globalName}" is missing or malformed on globalThis. ${message}`);
|
|
71
73
|
}
|
|
72
|
-
function
|
|
74
|
+
function isClientConfigShape(value) {
|
|
73
75
|
if (!value || typeof value !== "object")
|
|
74
76
|
return false;
|
|
75
|
-
|
|
76
|
-
const stringProps = (obj, keys) => !!obj &&
|
|
77
|
-
typeof obj === "object" &&
|
|
78
|
-
keys.every((k) => typeof obj[k] === "string");
|
|
79
|
-
return (typeof theme.input === "string" &&
|
|
80
|
-
stringProps(theme.text, [
|
|
81
|
-
"logoText",
|
|
82
|
-
"documentTitle",
|
|
83
|
-
"breadcrumb",
|
|
84
|
-
"titleLevel1",
|
|
85
|
-
"titleLevel2",
|
|
86
|
-
"titleLevel3",
|
|
87
|
-
"titleAnchor",
|
|
88
|
-
"general",
|
|
89
|
-
"alternative",
|
|
90
|
-
"list",
|
|
91
|
-
"math",
|
|
92
|
-
]) &&
|
|
93
|
-
stringProps(theme.hints, ["text", "key"]) &&
|
|
94
|
-
stringProps(theme.divider, ["border", "gradient", "text"]) &&
|
|
95
|
-
stringProps(theme.buttons, ["common", "small", "tabSmall", "tabSmallActive"]) &&
|
|
96
|
-
stringProps(theme.dropdown, ["container", "item", "itemActive"]) &&
|
|
97
|
-
stringProps(theme.messageBox, [
|
|
98
|
-
"info",
|
|
99
|
-
"warning",
|
|
100
|
-
"error",
|
|
101
|
-
"success",
|
|
102
|
-
"neutral",
|
|
103
|
-
"quote",
|
|
104
|
-
]) &&
|
|
105
|
-
stringProps(theme.table, ["cornerCell", "headers", "rows", "border", "empty"]) &&
|
|
106
|
-
stringProps(theme.code, ["header", "language", "lines", "empty"]) &&
|
|
107
|
-
stringProps(theme.audioPlayer, [
|
|
108
|
-
"container",
|
|
109
|
-
"playButton",
|
|
110
|
-
"time",
|
|
111
|
-
"slider",
|
|
112
|
-
"sliderThumb",
|
|
113
|
-
"sliderTrackColor",
|
|
114
|
-
"sliderFillColor",
|
|
115
|
-
]) &&
|
|
116
|
-
stringProps(theme.chart, [
|
|
117
|
-
"legendLabelColor",
|
|
118
|
-
"tooltipBg",
|
|
119
|
-
"tooltipTitleColor",
|
|
120
|
-
"tooltipBodyColor",
|
|
121
|
-
"tooltipBorderColor",
|
|
122
|
-
"axisTickColor",
|
|
123
|
-
"gridLineColor",
|
|
124
|
-
]) &&
|
|
125
|
-
stringProps(theme.graph, ["background", "defaultCurve"]) &&
|
|
126
|
-
stringProps(theme.searchModal, [
|
|
127
|
-
"resultBackground",
|
|
128
|
-
"resultEmptyInputText",
|
|
129
|
-
"resultNoResultText",
|
|
130
|
-
"header",
|
|
131
|
-
"footer",
|
|
132
|
-
"borders",
|
|
133
|
-
"item",
|
|
134
|
-
"selectedItem",
|
|
135
|
-
"itemHeaderText",
|
|
136
|
-
"itemFoundSectionText",
|
|
137
|
-
"itemTags",
|
|
138
|
-
]) &&
|
|
139
|
-
stringProps(theme.navigation, [
|
|
140
|
-
"row",
|
|
141
|
-
"rowActive",
|
|
142
|
-
"rowFocused",
|
|
143
|
-
"rowHover",
|
|
144
|
-
"hideOrShowHintsText",
|
|
145
|
-
]) &&
|
|
146
|
-
stringProps(theme.category, [
|
|
147
|
-
"empty",
|
|
148
|
-
"cardBody",
|
|
149
|
-
"cardHeaderText",
|
|
150
|
-
"cardDescriptionText",
|
|
151
|
-
]) &&
|
|
152
|
-
stringProps(theme.sections, [
|
|
153
|
-
"siteBackground",
|
|
154
|
-
"siteBorders",
|
|
155
|
-
"headerBackground",
|
|
156
|
-
"headerMobileBackground",
|
|
157
|
-
"sidebarBackground",
|
|
158
|
-
"documentHeaderBackground",
|
|
159
|
-
"contentBackground",
|
|
160
|
-
]) &&
|
|
161
|
-
stringProps(theme.header, ["mobileNavigationToggle", "mobileMenuToggle"]));
|
|
77
|
+
return clientConfigSchema.safeParse(value).success;
|
|
162
78
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serializeClientConfigForBrowser = exports.readClientConfig = exports.exposeClientConfig = exports.DEFAULT_CLIENT_CONFIG_GLOBAL = exports.buildClientVisibleConfig = exports.SST_DOCS_CONFIG_FILENAME = exports.SstDocsConfigError = exports.resolvePublicDataPath = exports.derivePublicDataPath = exports.CODE_LANGUAGE_CONFIG = void 0;
|
|
4
|
+
var codeLanguagesConfig_js_1 = require("./codeLanguagesConfig.js");
|
|
5
|
+
Object.defineProperty(exports, "CODE_LANGUAGE_CONFIG", { enumerable: true, get: function () { return codeLanguagesConfig_js_1.CODE_LANGUAGE_CONFIG; } });
|
|
6
|
+
var sstDocsConfigShared_js_1 = require("./sstDocsConfigShared.js");
|
|
7
|
+
Object.defineProperty(exports, "derivePublicDataPath", { enumerable: true, get: function () { return sstDocsConfigShared_js_1.derivePublicDataPath; } });
|
|
8
|
+
Object.defineProperty(exports, "resolvePublicDataPath", { enumerable: true, get: function () { return sstDocsConfigShared_js_1.resolvePublicDataPath; } });
|
|
9
|
+
Object.defineProperty(exports, "SstDocsConfigError", { enumerable: true, get: function () { return sstDocsConfigShared_js_1.SstDocsConfigError; } });
|
|
10
|
+
Object.defineProperty(exports, "SST_DOCS_CONFIG_FILENAME", { enumerable: true, get: function () { return sstDocsConfigShared_js_1.SST_DOCS_CONFIG_FILENAME; } });
|
|
11
|
+
var clientConfig_js_1 = require("./clientConfig.js");
|
|
12
|
+
Object.defineProperty(exports, "buildClientVisibleConfig", { enumerable: true, get: function () { return clientConfig_js_1.buildClientVisibleConfig; } });
|
|
13
|
+
Object.defineProperty(exports, "DEFAULT_CLIENT_CONFIG_GLOBAL", { enumerable: true, get: function () { return clientConfig_js_1.DEFAULT_CLIENT_CONFIG_GLOBAL; } });
|
|
14
|
+
Object.defineProperty(exports, "exposeClientConfig", { enumerable: true, get: function () { return clientConfig_js_1.exposeClientConfig; } });
|
|
15
|
+
Object.defineProperty(exports, "readClientConfig", { enumerable: true, get: function () { return clientConfig_js_1.readClientConfig; } });
|
|
16
|
+
Object.defineProperty(exports, "serializeClientConfigForBrowser", { enumerable: true, get: function () { return clientConfig_js_1.serializeClientConfigForBrowser; } });
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SstDocsConfigError = exports.SST_DOCS_CONFIG_FILENAME = void 0;
|
|
3
|
+
exports.SST_DOCS_CONFIG_REFERENCE = exports.SstDocsConfigError = exports.SST_DOCS_CONFIG_FILENAME = void 0;
|
|
7
4
|
exports.parseConfigContents = parseConfigContents;
|
|
8
5
|
exports.derivePublicDataPath = derivePublicDataPath;
|
|
9
6
|
exports.resolvePublicDataPath = resolvePublicDataPath;
|
|
10
7
|
const themeRegistry_js_1 = require("../themes/themeRegistry.js");
|
|
11
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
12
8
|
const normalizeSystemPath_js_1 = require("../utilities/string/normalizeSystemPath.js");
|
|
9
|
+
const zod_1 = require("zod");
|
|
13
10
|
exports.SST_DOCS_CONFIG_FILENAME = "sst-docs.config.json";
|
|
11
|
+
const DEFAULT_FS_DATA_PATH = "./public/SST-Docs/data";
|
|
12
|
+
const DEFAULT_OUTPUT_DIRECTORY = "./dist/html";
|
|
14
13
|
class SstDocsConfigError extends Error {
|
|
15
14
|
constructor(message) {
|
|
16
15
|
super(message);
|
|
@@ -18,6 +17,111 @@ class SstDocsConfigError extends Error {
|
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
exports.SstDocsConfigError = SstDocsConfigError;
|
|
20
|
+
exports.SST_DOCS_CONFIG_REFERENCE = [
|
|
21
|
+
{
|
|
22
|
+
key: "FS_DATA_PATH",
|
|
23
|
+
type: "string",
|
|
24
|
+
required: true,
|
|
25
|
+
default: DEFAULT_FS_DATA_PATH,
|
|
26
|
+
description: "Absolute or project-relative path to the docs data root (contains versions.json).",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
key: "HEADER_BRANDING.logoSrc",
|
|
30
|
+
type: "string",
|
|
31
|
+
required: false,
|
|
32
|
+
description: "Optional logo image path/URL shown in the header.",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
key: "HEADER_BRANDING.logoAlt",
|
|
36
|
+
type: "string",
|
|
37
|
+
required: false,
|
|
38
|
+
description: "Optional alt text for the logo image.",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
key: "HEADER_BRANDING.logoText",
|
|
42
|
+
type: "string",
|
|
43
|
+
required: false,
|
|
44
|
+
description: "Optional text fallback when no logo image is provided.",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
key: "HTML_GENERATOR_SETTINGS.OUTPUT_DIRECTORY",
|
|
48
|
+
type: "string",
|
|
49
|
+
required: true,
|
|
50
|
+
default: DEFAULT_OUTPUT_DIRECTORY,
|
|
51
|
+
description: "Where the HTML generator writes the output bundle.",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
key: "HTML_GENERATOR_SETTINGS.THEME",
|
|
55
|
+
type: "string",
|
|
56
|
+
required: true,
|
|
57
|
+
default: themeRegistry_js_1.DEFAULT_THEME_PRESET,
|
|
58
|
+
description: `Theme preset name. Options: ${themeRegistry_js_1.AVAILABLE_THEME_PRESET_NAMES.join(", ")}.`,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
key: "HTML_GENERATOR_SETTINGS.SEPARATE_BUILD_FOR_HTML_GENERATOR",
|
|
62
|
+
type: "boolean",
|
|
63
|
+
required: false,
|
|
64
|
+
default: "false",
|
|
65
|
+
description: "Whether to run a separate build for the HTML generator.",
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
const optionalTrimmedString = zod_1.z
|
|
69
|
+
.string()
|
|
70
|
+
.trim()
|
|
71
|
+
.transform((value) => (value.length > 0 ? value : undefined))
|
|
72
|
+
.optional();
|
|
73
|
+
const HeaderBrandingSchema = zod_1.z
|
|
74
|
+
.object({
|
|
75
|
+
logoSrc: optionalTrimmedString,
|
|
76
|
+
logoAlt: optionalTrimmedString,
|
|
77
|
+
logoText: optionalTrimmedString,
|
|
78
|
+
})
|
|
79
|
+
.strict()
|
|
80
|
+
.transform((value) => value);
|
|
81
|
+
const HtmlGeneratorSettingsSchema = zod_1.z
|
|
82
|
+
.object({
|
|
83
|
+
OUTPUT_DIRECTORY: zod_1.z
|
|
84
|
+
.string()
|
|
85
|
+
.trim()
|
|
86
|
+
.min(1, {
|
|
87
|
+
message: `Set HTML_GENERATOR_SETTINGS.OUTPUT_DIRECTORY (default: "${DEFAULT_OUTPUT_DIRECTORY}")`,
|
|
88
|
+
})
|
|
89
|
+
.transform((val) => (0, normalizeSystemPath_js_1.normalizeSystemPath)(val)),
|
|
90
|
+
THEME: zod_1.z
|
|
91
|
+
.string()
|
|
92
|
+
.trim()
|
|
93
|
+
.min(1, {
|
|
94
|
+
message: `Set HTML_GENERATOR_SETTINGS.THEME (default: "${themeRegistry_js_1.DEFAULT_THEME_PRESET}")`,
|
|
95
|
+
})
|
|
96
|
+
.transform((value, ctx) => {
|
|
97
|
+
const normalized = value.toLowerCase();
|
|
98
|
+
if (!(0, themeRegistry_js_1.isThemePresetName)(normalized)) {
|
|
99
|
+
const options = themeRegistry_js_1.AVAILABLE_THEME_PRESET_NAMES.join(", ");
|
|
100
|
+
ctx.addIssue({
|
|
101
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
102
|
+
message: `HTML_GENERATOR_SETTINGS.THEME must be one of: ${options} (default: "${themeRegistry_js_1.DEFAULT_THEME_PRESET}")`,
|
|
103
|
+
});
|
|
104
|
+
return zod_1.z.NEVER;
|
|
105
|
+
}
|
|
106
|
+
return cloneTheme((0, themeRegistry_js_1.getThemePreset)(normalized));
|
|
107
|
+
}),
|
|
108
|
+
SEPARATE_BUILD_FOR_HTML_GENERATOR: zod_1.z.boolean().default(false),
|
|
109
|
+
})
|
|
110
|
+
.strict()
|
|
111
|
+
.transform((value) => value);
|
|
112
|
+
const ConfigSchema = zod_1.z
|
|
113
|
+
.object({
|
|
114
|
+
FS_DATA_PATH: zod_1.z
|
|
115
|
+
.string()
|
|
116
|
+
.trim()
|
|
117
|
+
.min(1, {
|
|
118
|
+
message: `Provide FS_DATA_PATH (default: "${DEFAULT_FS_DATA_PATH}")`,
|
|
119
|
+
})
|
|
120
|
+
.transform((val) => (0, normalizeSystemPath_js_1.normalizeSystemPath)(val)),
|
|
121
|
+
HEADER_BRANDING: HeaderBrandingSchema.optional().transform((value) => value ?? {}),
|
|
122
|
+
HTML_GENERATOR_SETTINGS: HtmlGeneratorSettingsSchema.optional(),
|
|
123
|
+
})
|
|
124
|
+
.strict();
|
|
21
125
|
function parseConfigContents(contents, sourcePath) {
|
|
22
126
|
let parsed;
|
|
23
127
|
try {
|
|
@@ -26,11 +130,21 @@ function parseConfigContents(contents, sourcePath) {
|
|
|
26
130
|
catch (error) {
|
|
27
131
|
throw new SstDocsConfigError(`Failed to parse ${exports.SST_DOCS_CONFIG_FILENAME}: ${error.message}`);
|
|
28
132
|
}
|
|
29
|
-
|
|
133
|
+
const result = ConfigSchema.safeParse(parsed);
|
|
134
|
+
if (!result.success) {
|
|
135
|
+
throw new SstDocsConfigError(formatConfigValidationError(sourcePath, result.error));
|
|
136
|
+
}
|
|
137
|
+
const resolved = result.data;
|
|
138
|
+
return {
|
|
139
|
+
FS_DATA_PATH: resolved.FS_DATA_PATH,
|
|
140
|
+
PUBLIC_DATA_PATH: derivePublicDataPath(resolved.FS_DATA_PATH),
|
|
141
|
+
HEADER_BRANDING: resolved.HEADER_BRANDING,
|
|
142
|
+
HTML_GENERATOR_SETTINGS: resolved.HTML_GENERATOR_SETTINGS,
|
|
143
|
+
};
|
|
30
144
|
}
|
|
31
145
|
function derivePublicDataPath(fsDataPath) {
|
|
32
146
|
const normalizedFsPath = (0, normalizeSystemPath_js_1.normalizeSystemPath)(fsDataPath.trim());
|
|
33
|
-
const posixPath =
|
|
147
|
+
const posixPath = normalizePosixPath(normalizedFsPath || "/");
|
|
34
148
|
const segments = posixPath.split("/").filter(Boolean);
|
|
35
149
|
const publicIndex = segments.indexOf("public");
|
|
36
150
|
const publicSegments = publicIndex >= 0 ? segments.slice(publicIndex + 1) : segments;
|
|
@@ -57,14 +171,14 @@ function resolvePublicDataPath(baseUrl, config) {
|
|
|
57
171
|
}
|
|
58
172
|
function normalizePublicPath(value) {
|
|
59
173
|
const normalized = (0, normalizeSystemPath_js_1.normalizeSystemPath)(value.trim());
|
|
60
|
-
const posixPath =
|
|
174
|
+
const posixPath = normalizePosixPath(normalized || "/");
|
|
61
175
|
const withLeading = posixPath.startsWith("/") ? posixPath : `/${posixPath}`;
|
|
62
176
|
return withLeading.endsWith("/") ? withLeading : `${withLeading}/`;
|
|
63
177
|
}
|
|
64
178
|
function joinUrlPaths(base, child) {
|
|
65
179
|
const normalizedBase = normalizePublicPath(base);
|
|
66
180
|
const normalizedChild = normalizePublicPath(child).replace(/^\/+/, "");
|
|
67
|
-
const joined =
|
|
181
|
+
const joined = normalizePosixPath(`${normalizedBase}${normalizedChild ? `/${normalizedChild}` : ""}`);
|
|
68
182
|
return joined.endsWith("/") ? joined : `${joined}/`;
|
|
69
183
|
}
|
|
70
184
|
function isAbsoluteUrl(value) {
|
|
@@ -76,99 +190,43 @@ function isAbsoluteUrl(value) {
|
|
|
76
190
|
return false;
|
|
77
191
|
}
|
|
78
192
|
}
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
throw new SstDocsConfigError(`Invalid configuration in ${sourcePath}: expected an object`);
|
|
82
|
-
}
|
|
83
|
-
const raw = value;
|
|
84
|
-
if (typeof raw.FS_DATA_PATH !== "string") {
|
|
85
|
-
throw new SstDocsConfigError(`Missing or invalid FS_DATA_PATH in ${sourcePath}`);
|
|
86
|
-
}
|
|
87
|
-
const fsDataPath = (0, normalizeSystemPath_js_1.normalizeSystemPath)(raw.FS_DATA_PATH.trim());
|
|
88
|
-
if (fsDataPath.length === 0) {
|
|
89
|
-
throw new SstDocsConfigError(`FS_DATA_PATH cannot be empty in ${sourcePath}`);
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
FS_DATA_PATH: fsDataPath,
|
|
93
|
-
PUBLIC_DATA_PATH: derivePublicDataPath(fsDataPath),
|
|
94
|
-
HEADER_BRANDING: normalizeHeaderBranding(raw.HEADER_BRANDING, sourcePath),
|
|
95
|
-
HTML_GENERATOR_SETTINGS: normalizeHtmlGeneratorSettings(raw.HTML_GENERATOR_SETTINGS, sourcePath),
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
function normalizeHeaderBranding(value, sourcePath) {
|
|
99
|
-
if (value === undefined) {
|
|
100
|
-
return {};
|
|
101
|
-
}
|
|
102
|
-
if (!value || typeof value !== "object") {
|
|
103
|
-
throw new SstDocsConfigError(`HEADER_BRANDING must be an object in ${sourcePath}`);
|
|
104
|
-
}
|
|
105
|
-
const { logoSrc, logoAlt, logoText } = value;
|
|
106
|
-
return {
|
|
107
|
-
logoSrc: normalizeOptionalString(logoSrc, "logoSrc", sourcePath),
|
|
108
|
-
logoAlt: normalizeOptionalString(logoAlt, "logoAlt", sourcePath),
|
|
109
|
-
logoText: normalizeOptionalString(logoText, "logoText", sourcePath),
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
function normalizeOptionalString(value, key, sourcePath) {
|
|
113
|
-
if (value === undefined || value === null)
|
|
114
|
-
return undefined;
|
|
115
|
-
if (typeof value !== "string") {
|
|
116
|
-
throw new SstDocsConfigError(`HEADER_BRANDING.${key} must be a string in ${sourcePath}`);
|
|
117
|
-
}
|
|
118
|
-
const trimmed = value.trim();
|
|
119
|
-
return trimmed.length > 0 ? trimmed : undefined;
|
|
120
|
-
}
|
|
121
|
-
function normalizeHtmlGeneratorSettings(value, sourcePath) {
|
|
122
|
-
if (value === undefined) {
|
|
123
|
-
return undefined;
|
|
124
|
-
}
|
|
125
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
126
|
-
throw new SstDocsConfigError(`HTML_GENERATOR_SETTINGS must be an object in ${sourcePath}`);
|
|
127
|
-
}
|
|
128
|
-
const { OUTPUT_DIRECTORY, THEME, SEPARATE_BUILD_FOR_HTML_GENERATOR, } = value;
|
|
129
|
-
if (typeof OUTPUT_DIRECTORY !== "string") {
|
|
130
|
-
throw new SstDocsConfigError(`HTML_GENERATOR_SETTINGS.OUTPUT_DIRECTORY must be a string in ${sourcePath}`);
|
|
131
|
-
}
|
|
132
|
-
const outputDirectory = (0, normalizeSystemPath_js_1.normalizeSystemPath)(OUTPUT_DIRECTORY.trim());
|
|
133
|
-
if (outputDirectory.length === 0) {
|
|
134
|
-
throw new SstDocsConfigError(`HTML_GENERATOR_SETTINGS.OUTPUT_DIRECTORY cannot be empty in ${sourcePath}`);
|
|
135
|
-
}
|
|
136
|
-
if (THEME === undefined) {
|
|
137
|
-
throw new SstDocsConfigError(`HTML_GENERATOR_SETTINGS.THEME must be provided in ${sourcePath}`);
|
|
138
|
-
}
|
|
139
|
-
if (SEPARATE_BUILD_FOR_HTML_GENERATOR !== undefined &&
|
|
140
|
-
typeof SEPARATE_BUILD_FOR_HTML_GENERATOR !== "boolean") {
|
|
141
|
-
throw new SstDocsConfigError(`HTML_GENERATOR_SETTINGS.SEPARATE_BUILD_FOR_HTML_GENERATOR must be a boolean in ${sourcePath}`);
|
|
142
|
-
}
|
|
143
|
-
const resolvedTheme = resolveThemeConfiguration(THEME, sourcePath);
|
|
144
|
-
return {
|
|
145
|
-
OUTPUT_DIRECTORY: outputDirectory,
|
|
146
|
-
THEME: resolvedTheme,
|
|
147
|
-
SEPARATE_BUILD_FOR_HTML_GENERATOR: SEPARATE_BUILD_FOR_HTML_GENERATOR ?? false,
|
|
148
|
-
};
|
|
193
|
+
function cloneTheme(theme) {
|
|
194
|
+
return JSON.parse(JSON.stringify(theme));
|
|
149
195
|
}
|
|
150
|
-
function
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
196
|
+
function formatConfigValidationError(sourcePath, error) {
|
|
197
|
+
const lines = error.issues.map((issue) => {
|
|
198
|
+
const path = issue.path.join(".") || "config";
|
|
199
|
+
const defaultValue = defaultValueFor(path);
|
|
200
|
+
const hint = defaultValue ? ` (default: ${defaultValue})` : "";
|
|
201
|
+
return `${path}: ${issue.message}${hint}`;
|
|
202
|
+
});
|
|
203
|
+
return `Invalid configuration in ${sourcePath}:\n- ${lines.join("\n- ")}`;
|
|
156
204
|
}
|
|
157
|
-
function
|
|
158
|
-
|
|
159
|
-
return themeRegistry_js_1.DEFAULT_THEME_PRESET;
|
|
160
|
-
}
|
|
161
|
-
if (typeof raw !== "string") {
|
|
162
|
-
const options = themeRegistry_js_1.AVAILABLE_THEME_PRESET_NAMES.join(", ");
|
|
163
|
-
throw new SstDocsConfigError(`${propertyPath} must be one of: ${options} in ${sourcePath}`);
|
|
164
|
-
}
|
|
165
|
-
const normalized = raw.trim().toLowerCase();
|
|
166
|
-
if (!(0, themeRegistry_js_1.isThemePresetName)(normalized)) {
|
|
167
|
-
const options = themeRegistry_js_1.AVAILABLE_THEME_PRESET_NAMES.join(", ");
|
|
168
|
-
throw new SstDocsConfigError(`Unknown ${propertyPath} "${raw}" in ${sourcePath}. Supported presets: ${options}`);
|
|
169
|
-
}
|
|
170
|
-
return normalized;
|
|
205
|
+
function defaultValueFor(path) {
|
|
206
|
+
return exports.SST_DOCS_CONFIG_REFERENCE.find((entry) => entry.key === path)?.default;
|
|
171
207
|
}
|
|
172
|
-
function
|
|
173
|
-
|
|
208
|
+
function normalizePosixPath(value) {
|
|
209
|
+
const sanitized = value.replace(/\\/g, "/");
|
|
210
|
+
const hasLeadingSlash = sanitized.startsWith("/");
|
|
211
|
+
const parts = sanitized.split("/");
|
|
212
|
+
const stack = [];
|
|
213
|
+
for (const part of parts) {
|
|
214
|
+
if (!part || part === ".")
|
|
215
|
+
continue;
|
|
216
|
+
if (part === "..") {
|
|
217
|
+
if (stack.length > 0 && stack[stack.length - 1] !== "..") {
|
|
218
|
+
stack.pop();
|
|
219
|
+
}
|
|
220
|
+
else if (!hasLeadingSlash) {
|
|
221
|
+
stack.push("..");
|
|
222
|
+
}
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
stack.push(part);
|
|
226
|
+
}
|
|
227
|
+
const normalized = stack.join("/");
|
|
228
|
+
if (hasLeadingSlash) {
|
|
229
|
+
return `/${normalized}`;
|
|
230
|
+
}
|
|
231
|
+
return normalized || ".";
|
|
174
232
|
}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildTree = buildTree;
|
|
4
|
-
|
|
4
|
+
const logger_js_1 = require("../utilities/system/logger.js");
|
|
5
|
+
function convertCategory(raw, rawMap, docLookup, usedDocIds, included, visiting, diagnostics, logger) {
|
|
5
6
|
if (visiting.has(raw.id)) {
|
|
6
|
-
|
|
7
|
+
const message = `Detected circular category reference at ${raw.id}.`;
|
|
8
|
+
diagnostics.push({
|
|
9
|
+
code: "circular-category",
|
|
10
|
+
level: "warn",
|
|
11
|
+
message,
|
|
12
|
+
context: { categoryId: raw.id },
|
|
13
|
+
});
|
|
14
|
+
logger.warn(message);
|
|
7
15
|
return null;
|
|
8
16
|
}
|
|
9
17
|
visiting.add(raw.id);
|
|
@@ -13,12 +21,26 @@ function convertCategory(raw, rawMap, docLookup, usedDocIds, included, visiting)
|
|
|
13
21
|
const validDocs = docIds
|
|
14
22
|
.map((rawId) => {
|
|
15
23
|
if (typeof rawId !== "string" || rawId.length === 0) {
|
|
16
|
-
|
|
24
|
+
const message = `Invalid doc id in category ${raw.id}.`;
|
|
25
|
+
diagnostics.push({
|
|
26
|
+
code: "invalid-doc-ref",
|
|
27
|
+
level: "warn",
|
|
28
|
+
message,
|
|
29
|
+
context: { categoryId: raw.id, docId: rawId },
|
|
30
|
+
});
|
|
31
|
+
logger.warn(message);
|
|
17
32
|
return null;
|
|
18
33
|
}
|
|
19
34
|
const doc = docLookup.get(rawId);
|
|
20
35
|
if (!doc) {
|
|
21
|
-
|
|
36
|
+
const message = `Doc id ${rawId} referenced in category ${raw.id} not found.`;
|
|
37
|
+
diagnostics.push({
|
|
38
|
+
code: "missing-doc-ref",
|
|
39
|
+
level: "warn",
|
|
40
|
+
message,
|
|
41
|
+
context: { categoryId: raw.id, docId: rawId },
|
|
42
|
+
});
|
|
43
|
+
logger.warn(message);
|
|
22
44
|
return null;
|
|
23
45
|
}
|
|
24
46
|
usedDocIds.add(rawId);
|
|
@@ -35,15 +57,29 @@ function convertCategory(raw, rawMap, docLookup, usedDocIds, included, visiting)
|
|
|
35
57
|
const validChildren = childIds
|
|
36
58
|
.map((rawChildId) => {
|
|
37
59
|
if (typeof rawChildId !== "string" || rawChildId.length === 0) {
|
|
38
|
-
|
|
60
|
+
const message = `Invalid child category id in ${raw.id}.`;
|
|
61
|
+
diagnostics.push({
|
|
62
|
+
code: "invalid-child-ref",
|
|
63
|
+
level: "warn",
|
|
64
|
+
message,
|
|
65
|
+
context: { categoryId: raw.id, childId: rawChildId },
|
|
66
|
+
});
|
|
67
|
+
logger.warn(message);
|
|
39
68
|
return null;
|
|
40
69
|
}
|
|
41
70
|
const childRaw = rawMap[rawChildId];
|
|
42
71
|
if (!childRaw) {
|
|
43
|
-
|
|
72
|
+
const message = `Child category ${rawChildId} referenced in ${raw.id} not found.`;
|
|
73
|
+
diagnostics.push({
|
|
74
|
+
code: "missing-child-ref",
|
|
75
|
+
level: "warn",
|
|
76
|
+
message,
|
|
77
|
+
context: { categoryId: raw.id, childId: rawChildId },
|
|
78
|
+
});
|
|
79
|
+
logger.warn(message);
|
|
44
80
|
return null;
|
|
45
81
|
}
|
|
46
|
-
return convertCategory(childRaw, rawMap, docLookup, usedDocIds, included, visiting);
|
|
82
|
+
return convertCategory(childRaw, rawMap, docLookup, usedDocIds, included, visiting, diagnostics, logger);
|
|
47
83
|
})
|
|
48
84
|
.filter((child) => child !== null);
|
|
49
85
|
if (validChildren.length > 0) {
|
|
@@ -61,10 +97,12 @@ function convertCategory(raw, rawMap, docLookup, usedDocIds, included, visiting)
|
|
|
61
97
|
children,
|
|
62
98
|
};
|
|
63
99
|
}
|
|
64
|
-
function buildTree(rawMap, allDocs) {
|
|
100
|
+
function buildTree(rawMap, allDocs, options) {
|
|
65
101
|
const docLookup = new Map(allDocs.map((d) => [d.id, d]));
|
|
66
102
|
const usedDocIds = new Set();
|
|
67
103
|
const includedIds = new Set();
|
|
104
|
+
const diagnostics = [];
|
|
105
|
+
const logger = options?.logger ?? (0, logger_js_1.createLogger)("data:buildTree");
|
|
68
106
|
const childCategoryIds = new Set();
|
|
69
107
|
Object.values(rawMap).forEach((category) => {
|
|
70
108
|
if (Array.isArray(category?.children)) {
|
|
@@ -86,8 +124,8 @@ function buildTree(rawMap, allDocs) {
|
|
|
86
124
|
.map((rootCategory) => {
|
|
87
125
|
if (includedIds.has(rootCategory.id))
|
|
88
126
|
return null;
|
|
89
|
-
return convertCategory(rootCategory, rawMap, docLookup, usedDocIds, includedIds, new Set());
|
|
127
|
+
return convertCategory(rootCategory, rawMap, docLookup, usedDocIds, includedIds, new Set(), diagnostics, logger);
|
|
90
128
|
})
|
|
91
129
|
.filter((category) => category !== null);
|
|
92
|
-
return { tree, usedDocIds };
|
|
130
|
+
return { tree, usedDocIds, diagnostics };
|
|
93
131
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fsDataProvider = exports.FsDataProvider = void 0;
|
|
4
|
+
class FsDataProvider {
|
|
5
|
+
async readJson(_absPath) {
|
|
6
|
+
throw new Error("FsDataProvider is only available in Node.js environments where the file system can be read.");
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
exports.FsDataProvider = FsDataProvider;
|
|
10
|
+
exports.fsDataProvider = FsDataProvider;
|