@tenphi/docs 0.15.0 → 0.17.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 +1 -1
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/schema.json +342 -8
- package/dist/{config-DoR8g9IM.js → config-Ci9Nv0wQ.js} +285 -13
- package/dist/config-Ci9Nv0wQ.js.map +1 -0
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.js +1 -1
- package/dist/{content-BIpXueW7.js → content-XLQlJDnf.js} +232 -16
- package/dist/content-XLQlJDnf.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/markdown/index.d.ts +1 -1
- package/dist/{types-B-msp1dH.d.ts → types-C-AgUcAb.d.ts} +87 -21
- package/dist/{types-B-msp1dH.d.ts.map → types-C-AgUcAb.d.ts.map} +1 -1
- package/package.json +2 -2
- package/dist/config-DoR8g9IM.js.map +0 -1
- package/dist/content-BIpXueW7.js.map +0 -1
|
@@ -9,6 +9,12 @@ const COOKBOOK_COMPONENT_NAMES = [
|
|
|
9
9
|
"Tab",
|
|
10
10
|
"Footer",
|
|
11
11
|
"Hero",
|
|
12
|
+
"PageFrame",
|
|
13
|
+
"HeaderFrame",
|
|
14
|
+
"HeaderLinks",
|
|
15
|
+
"Layout",
|
|
16
|
+
"SearchButton",
|
|
17
|
+
"TableOfContentsLayout",
|
|
12
18
|
"LanguageSelect",
|
|
13
19
|
"Logo",
|
|
14
20
|
"MarkdownCodeBlock",
|
|
@@ -21,6 +27,7 @@ const COOKBOOK_COMPONENT_NAMES = [
|
|
|
21
27
|
"MobileNavigationTabs",
|
|
22
28
|
"MobileTableOfContents",
|
|
23
29
|
"PackageVersion",
|
|
30
|
+
"VersionSwitcher",
|
|
24
31
|
"Preview",
|
|
25
32
|
"Sidebar",
|
|
26
33
|
"SocialIcons",
|
|
@@ -33,6 +40,37 @@ const COOKBOOK_COMPONENT_NAMES = [
|
|
|
33
40
|
];
|
|
34
41
|
/** Named Tasty sub-elements available on each configurable Cookbook surface. */
|
|
35
42
|
const COOKBOOK_COMPONENT_SUB_ELEMENTS = {
|
|
43
|
+
PageFrame: [
|
|
44
|
+
"MainFrame",
|
|
45
|
+
"SidebarFrame",
|
|
46
|
+
"Columns"
|
|
47
|
+
],
|
|
48
|
+
HeaderFrame: [],
|
|
49
|
+
HeaderLinks: [
|
|
50
|
+
"Desktop",
|
|
51
|
+
"Link",
|
|
52
|
+
"HoverLink",
|
|
53
|
+
"PrimaryLink",
|
|
54
|
+
"HoverPrimaryLink",
|
|
55
|
+
"Trigger",
|
|
56
|
+
"HoverTrigger",
|
|
57
|
+
"Panel",
|
|
58
|
+
"PanelNavigation",
|
|
59
|
+
"PanelLink",
|
|
60
|
+
"FirstPanelLink",
|
|
61
|
+
"Close",
|
|
62
|
+
"HoverClose"
|
|
63
|
+
],
|
|
64
|
+
Layout: ["LockedPage"],
|
|
65
|
+
SearchButton: [
|
|
66
|
+
"Label",
|
|
67
|
+
"Shortcut",
|
|
68
|
+
"Hover",
|
|
69
|
+
"Active",
|
|
70
|
+
"NativeIcon",
|
|
71
|
+
"Icon"
|
|
72
|
+
],
|
|
73
|
+
TableOfContentsLayout: ["Content"],
|
|
36
74
|
Card: [
|
|
37
75
|
"Heading2",
|
|
38
76
|
"Heading3",
|
|
@@ -104,8 +142,12 @@ const COOKBOOK_COMPONENT_SUB_ELEMENTS = {
|
|
|
104
142
|
"Heading5",
|
|
105
143
|
"Heading6",
|
|
106
144
|
"Link",
|
|
145
|
+
"RevealedLink",
|
|
107
146
|
"HoverLink",
|
|
108
|
-
"LinkIcon"
|
|
147
|
+
"LinkIcon",
|
|
148
|
+
"CopiedLink",
|
|
149
|
+
"CopiedLinkIcon",
|
|
150
|
+
"CopiedIcon"
|
|
109
151
|
],
|
|
110
152
|
MarkdownTable: [
|
|
111
153
|
"Table",
|
|
@@ -123,10 +165,16 @@ const COOKBOOK_COMPONENT_SUB_ELEMENTS = {
|
|
|
123
165
|
MobileMenuToggle: [
|
|
124
166
|
"Control",
|
|
125
167
|
"Icon",
|
|
168
|
+
"Section",
|
|
169
|
+
"Page",
|
|
126
170
|
"HoverControl",
|
|
127
171
|
"ActiveControl"
|
|
128
172
|
],
|
|
129
173
|
MobileNavigationTabs: [
|
|
174
|
+
"Trigger",
|
|
175
|
+
"Marker",
|
|
176
|
+
"Caret",
|
|
177
|
+
"ExpandedCaret",
|
|
130
178
|
"Label",
|
|
131
179
|
"List",
|
|
132
180
|
"Item",
|
|
@@ -143,6 +191,13 @@ const COOKBOOK_COMPONENT_SUB_ELEMENTS = {
|
|
|
143
191
|
"CurrentIndicator"
|
|
144
192
|
],
|
|
145
193
|
PackageVersion: [],
|
|
194
|
+
VersionSwitcher: [
|
|
195
|
+
"Trigger",
|
|
196
|
+
"Panel",
|
|
197
|
+
"OpenPanel",
|
|
198
|
+
"Link",
|
|
199
|
+
"CurrentLink"
|
|
200
|
+
],
|
|
146
201
|
Preview: [
|
|
147
202
|
"Caption",
|
|
148
203
|
"Stage",
|
|
@@ -152,14 +207,25 @@ const COOKBOOK_COMPONENT_SUB_ELEMENTS = {
|
|
|
152
207
|
"Pre"
|
|
153
208
|
],
|
|
154
209
|
Sidebar: [
|
|
210
|
+
"Backdrop",
|
|
211
|
+
"OpenBackdrop",
|
|
212
|
+
"MobileHeading",
|
|
213
|
+
"HomeLink",
|
|
214
|
+
"HomeLogo",
|
|
215
|
+
"HomeLabel",
|
|
216
|
+
"Close",
|
|
217
|
+
"HoverClose",
|
|
218
|
+
"CloseIcon",
|
|
155
219
|
"CurrentLink",
|
|
156
220
|
"OpenPane",
|
|
157
221
|
"Content",
|
|
222
|
+
"Tree",
|
|
158
223
|
"List",
|
|
159
224
|
"Item",
|
|
160
225
|
"TopLevelSpacing",
|
|
161
226
|
"GroupSpacing",
|
|
162
227
|
"NestedItem",
|
|
228
|
+
"SectionHeading",
|
|
163
229
|
"Control",
|
|
164
230
|
"Summary",
|
|
165
231
|
"GroupLabel",
|
|
@@ -168,6 +234,13 @@ const COOKBOOK_COMPONENT_SUB_ELEMENTS = {
|
|
|
168
234
|
"LinkLabel",
|
|
169
235
|
"InteractiveControl",
|
|
170
236
|
"SummaryMarker",
|
|
237
|
+
"Caret",
|
|
238
|
+
"ExpandedCaret",
|
|
239
|
+
"LinkedSummary",
|
|
240
|
+
"GroupLink",
|
|
241
|
+
"LinkedSectionHeading",
|
|
242
|
+
"SectionLink",
|
|
243
|
+
"Badge",
|
|
171
244
|
"TopLevelLink"
|
|
172
245
|
],
|
|
173
246
|
Steps: ["Item", "Marker"],
|
|
@@ -194,8 +267,10 @@ const COOKBOOK_COMPONENT_SUB_ELEMENTS = {
|
|
|
194
267
|
ThemeSelect: [
|
|
195
268
|
"Trigger",
|
|
196
269
|
"HoverTrigger",
|
|
270
|
+
"ActiveTrigger",
|
|
197
271
|
"Icon",
|
|
198
272
|
"Panel",
|
|
273
|
+
"OpenPanel",
|
|
199
274
|
"Section",
|
|
200
275
|
"SectionSpacing",
|
|
201
276
|
"SectionLabel",
|
|
@@ -219,6 +294,7 @@ const COOKBOOK_COMPONENT_SUB_ELEMENTS = {
|
|
|
219
294
|
"Primary",
|
|
220
295
|
"TitleAndSearch",
|
|
221
296
|
"Title",
|
|
297
|
+
"LogoLink",
|
|
222
298
|
"Logo",
|
|
223
299
|
"SiteTitle",
|
|
224
300
|
"Search",
|
|
@@ -231,13 +307,29 @@ const COOKBOOK_COMPONENT_SUB_ELEMENTS = {
|
|
|
231
307
|
};
|
|
232
308
|
//#endregion
|
|
233
309
|
//#region src/config/index.ts
|
|
234
|
-
const DEFAULT_BRAND = "
|
|
310
|
+
const DEFAULT_BRAND = "okhsl(266 68% 48%)";
|
|
235
311
|
const HEAD_KEYS = /* @__PURE__ */ new Set([
|
|
236
312
|
"tag",
|
|
237
313
|
"attrs",
|
|
238
314
|
"content"
|
|
239
315
|
]);
|
|
240
316
|
const SITE_ICON_KEYS = /* @__PURE__ */ new Set(["source", "background"]);
|
|
317
|
+
const COLOR_DECLARATION_KEYS = /* @__PURE__ */ new Set([
|
|
318
|
+
"from",
|
|
319
|
+
"tone",
|
|
320
|
+
"saturation",
|
|
321
|
+
"hue",
|
|
322
|
+
"darkHue",
|
|
323
|
+
"darkSaturation",
|
|
324
|
+
"base",
|
|
325
|
+
"contrast",
|
|
326
|
+
"mode",
|
|
327
|
+
"autoFlip",
|
|
328
|
+
"opacity",
|
|
329
|
+
"pastel",
|
|
330
|
+
"role",
|
|
331
|
+
"inherit"
|
|
332
|
+
]);
|
|
241
333
|
const ROOT_KEYS = /* @__PURE__ */ new Set([
|
|
242
334
|
"root",
|
|
243
335
|
"redirects",
|
|
@@ -259,10 +351,12 @@ const OBJECT_KEYS = {
|
|
|
259
351
|
site: /* @__PURE__ */ new Set([
|
|
260
352
|
"title",
|
|
261
353
|
"version",
|
|
354
|
+
"versions",
|
|
262
355
|
"description",
|
|
263
356
|
"url",
|
|
264
357
|
"repository",
|
|
265
|
-
"favicon"
|
|
358
|
+
"favicon",
|
|
359
|
+
"headerLinks"
|
|
266
360
|
]),
|
|
267
361
|
content: /* @__PURE__ */ new Set([
|
|
268
362
|
"sources",
|
|
@@ -276,6 +370,7 @@ const OBJECT_KEYS = {
|
|
|
276
370
|
theme: /* @__PURE__ */ new Set([
|
|
277
371
|
"brand",
|
|
278
372
|
"palette",
|
|
373
|
+
"fonts",
|
|
279
374
|
"states",
|
|
280
375
|
"tokens",
|
|
281
376
|
"presets",
|
|
@@ -319,6 +414,45 @@ function validateConfig(config) {
|
|
|
319
414
|
}
|
|
320
415
|
for (const key of Object.keys(value)) if (!keys.has(key)) unknown(diagnostics, `${section}.${key}`);
|
|
321
416
|
}
|
|
417
|
+
if (isRecord(config.site) && config.site.versions !== void 0) {
|
|
418
|
+
if (!Array.isArray(config.site.versions) || config.site.versions.length < 2) invalid(diagnostics, "site.versions must contain at least two versions.");
|
|
419
|
+
else {
|
|
420
|
+
const bases = /* @__PURE__ */ new Set();
|
|
421
|
+
for (const [index, version] of config.site.versions.entries()) {
|
|
422
|
+
const path = `site.versions[${index}]`;
|
|
423
|
+
if (!isRecord(version)) {
|
|
424
|
+
invalid(diagnostics, `${path} must be an object.`);
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
for (const key of Object.keys(version)) if (key !== "label" && key !== "routeBase") unknown(diagnostics, `${path}.${key}`);
|
|
428
|
+
if (typeof version.label !== "string" || !version.label.trim()) invalid(diagnostics, `${path}.label must be a non-empty string.`);
|
|
429
|
+
const base = version.routeBase;
|
|
430
|
+
if (typeof base !== "string" || !base.startsWith("/") || base !== "/" && base.endsWith("/") || base.includes("//") || /[?#\\\s]/.test(base) || base.split("/").some((segment) => segment === "." || segment === "..")) invalid(diagnostics, `${path}.routeBase must be a root-relative route without a trailing slash.`);
|
|
431
|
+
else if (bases.has(base)) invalid(diagnostics, `${path}.routeBase duplicates ${base}.`);
|
|
432
|
+
else bases.add(base);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (isRecord(config.site) && config.site.headerLinks !== void 0) {
|
|
437
|
+
if (!Array.isArray(config.site.headerLinks)) invalid(diagnostics, "site.headerLinks must be an array.");
|
|
438
|
+
else config.site.headerLinks.forEach((item, index) => {
|
|
439
|
+
const path = `site.headerLinks[${index}]`;
|
|
440
|
+
if (!isRecord(item)) {
|
|
441
|
+
invalid(diagnostics, `${path} must be an object.`);
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
for (const key of Object.keys(item)) if (![
|
|
445
|
+
"label",
|
|
446
|
+
"link",
|
|
447
|
+
"variant",
|
|
448
|
+
"newTab"
|
|
449
|
+
].includes(key)) unknown(diagnostics, `${path}.${key}`);
|
|
450
|
+
if (typeof item.label !== "string" || !item.label.trim()) invalid(diagnostics, `${path}.label must be a non-empty string.`);
|
|
451
|
+
if (typeof item.link !== "string" || /[\\\s]/.test(item.link) || !(/^(?:\/(?!\/)|#)/.test(item.link) || isHttpUrl(item.link))) invalid(diagnostics, `${path}.link must be an HTTP(S) URL, root-relative route, or fragment.`);
|
|
452
|
+
if (item.variant !== void 0 && !["default", "primary"].includes(item.variant)) invalid(diagnostics, `${path}.variant must be "default" or "primary".`);
|
|
453
|
+
if (item.newTab !== void 0 && typeof item.newTab !== "boolean") invalid(diagnostics, `${path}.newTab must be a boolean.`);
|
|
454
|
+
});
|
|
455
|
+
}
|
|
322
456
|
if (config.navigation !== void 0 && !Array.isArray(config.navigation)) {
|
|
323
457
|
if (!isRecord(config.navigation)) invalid(diagnostics, "navigation must be an array or object.");
|
|
324
458
|
else {
|
|
@@ -327,6 +461,15 @@ function validateConfig(config) {
|
|
|
327
461
|
if (config.navigation.tabs !== void 0 && !Array.isArray(config.navigation.tabs)) invalid(diagnostics, "navigation.tabs must be an array.");
|
|
328
462
|
}
|
|
329
463
|
}
|
|
464
|
+
if (Array.isArray(config.navigation)) validateNavigationItems(config.navigation, "navigation", diagnostics);
|
|
465
|
+
else if (isRecord(config.navigation)) {
|
|
466
|
+
if (Array.isArray(config.navigation.items)) validateNavigationItems(config.navigation.items, "navigation.items", diagnostics);
|
|
467
|
+
if (Array.isArray(config.navigation.tabs)) for (const [index, tab] of config.navigation.tabs.entries()) {
|
|
468
|
+
const path = `navigation.tabs[${index}]`;
|
|
469
|
+
if (!isRecord(tab) || typeof tab.label !== "string" || typeof tab.link !== "string") invalid(diagnostics, `${path} must have a label and link.`);
|
|
470
|
+
else if (tab.items !== void 0) validateNavigationItems(tab.items, `${path}.items`, diagnostics);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
330
473
|
if (config.redirects !== void 0 && (!isRecord(config.redirects) || Object.values(config.redirects).some((value) => typeof value !== "string"))) invalid(diagnostics, "redirects must map old routes to document routes.");
|
|
331
474
|
const head = config.head;
|
|
332
475
|
if (head !== void 0 && !Array.isArray(head)) invalid(diagnostics, "head must be an array.");
|
|
@@ -397,13 +540,14 @@ function validateConfig(config) {
|
|
|
397
540
|
const variants = [
|
|
398
541
|
"file",
|
|
399
542
|
"glob",
|
|
400
|
-
"package"
|
|
543
|
+
"package",
|
|
544
|
+
"openapi"
|
|
401
545
|
].filter((key) => key in source);
|
|
402
546
|
if (variants.length !== 1) {
|
|
403
547
|
diagnostics.push({
|
|
404
548
|
code: "DOCS_CONFIG_INVALID",
|
|
405
549
|
severity: "error",
|
|
406
|
-
message: `content.sources[${index}] must select exactly one of file, glob, or
|
|
550
|
+
message: `content.sources[${index}] must select exactly one of file, glob, package, or openapi.`
|
|
407
551
|
});
|
|
408
552
|
continue;
|
|
409
553
|
}
|
|
@@ -437,6 +581,12 @@ function validateConfig(config) {
|
|
|
437
581
|
"index",
|
|
438
582
|
"routeBase",
|
|
439
583
|
"trust"
|
|
584
|
+
]),
|
|
585
|
+
openapi: /* @__PURE__ */ new Set([
|
|
586
|
+
"id",
|
|
587
|
+
"root",
|
|
588
|
+
"routeBase",
|
|
589
|
+
"openapi"
|
|
440
590
|
])
|
|
441
591
|
}[variant];
|
|
442
592
|
for (const key of Object.keys(source)) if (!allowed.has(key)) unknown(diagnostics, `content.sources[${index}].${key}`);
|
|
@@ -499,10 +649,58 @@ function validateConfig(config) {
|
|
|
499
649
|
"styles",
|
|
500
650
|
"customStyles",
|
|
501
651
|
"palette",
|
|
652
|
+
"fonts",
|
|
502
653
|
"tokens",
|
|
503
654
|
"states",
|
|
504
655
|
"presets"
|
|
505
656
|
]) if (config.theme?.[field] !== void 0 && !isRecord(config.theme[field])) invalid(diagnostics, `theme.${field} must be an object.`);
|
|
657
|
+
if (isRecord(config.theme?.fonts)) for (const [role, font] of Object.entries(config.theme.fonts)) {
|
|
658
|
+
const path = `theme.fonts.${role}`;
|
|
659
|
+
if (![
|
|
660
|
+
"body",
|
|
661
|
+
"heading",
|
|
662
|
+
"code"
|
|
663
|
+
].includes(role)) {
|
|
664
|
+
unknown(diagnostics, path);
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
if (font === void 0) continue;
|
|
668
|
+
if (typeof font === "string") {
|
|
669
|
+
if (!validFontFamily(font)) invalid(diagnostics, `${path} must name a Google Fonts family.`);
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
if (!isRecord(font)) {
|
|
673
|
+
invalid(diagnostics, `${path} must be a Google Fonts name or font definition.`);
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
if ("google" in font) {
|
|
677
|
+
for (const key of Object.keys(font)) if (!["google", "weights"].includes(key)) unknown(diagnostics, `${path}.${key}`);
|
|
678
|
+
if (!validFontFamily(font.google)) invalid(diagnostics, `${path}.google must name a Google Fonts family.`);
|
|
679
|
+
if (font.weights !== void 0 && (!Array.isArray(font.weights) || font.weights.length === 0 || font.weights.some((weight) => !Number.isInteger(weight) || weight < 1 || weight > 1e3))) invalid(diagnostics, `${path}.weights must be a non-empty array of font weights from 1 to 1000.`);
|
|
680
|
+
} else {
|
|
681
|
+
for (const key of Object.keys(font)) if (!["family", "files"].includes(key)) unknown(diagnostics, `${path}.${key}`);
|
|
682
|
+
if (!validFontFamily(font.family)) invalid(diagnostics, `${path}.family must be a font family name.`);
|
|
683
|
+
if (!Array.isArray(font.files) || font.files.length === 0) {
|
|
684
|
+
invalid(diagnostics, `${path}.files must contain at least one font file.`);
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
font.files.forEach((file, index) => {
|
|
688
|
+
const filePath = `${path}.files[${index}]`;
|
|
689
|
+
if (!isRecord(file)) {
|
|
690
|
+
invalid(diagnostics, `${filePath} must be an object.`);
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
for (const key of Object.keys(file)) if (![
|
|
694
|
+
"src",
|
|
695
|
+
"weight",
|
|
696
|
+
"style"
|
|
697
|
+
].includes(key)) unknown(diagnostics, `${filePath}.${key}`);
|
|
698
|
+
if (typeof file.src !== "string" || !/^\/(?!\/)[^\s"'()\\?#]+\.(?:woff2?|ttf|otf)$/.test(file.src) || file.src.split("/").some((segment) => segment === "." || segment === "..")) invalid(diagnostics, `${filePath}.src must be a root-relative .woff2, .woff, .ttf, or .otf public path.`);
|
|
699
|
+
if (file.weight !== void 0 && !(typeof file.weight === "number" && Number.isInteger(file.weight) && file.weight >= 1 && file.weight <= 1e3) && !(typeof file.weight === "string" && /^(?:[1-9]\d{0,2}|1000) (?:[1-9]\d{0,2}|1000)$/.test(file.weight) && Number(file.weight.split(" ")[0]) < Number(file.weight.split(" ")[1]))) invalid(diagnostics, `${filePath}.weight must be a weight from 1 to 1000 or an ascending range.`);
|
|
700
|
+
if (file.style !== void 0 && !["normal", "italic"].includes(file.style)) invalid(diagnostics, `${filePath}.style must be normal or italic.`);
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
506
704
|
for (const [name, entry] of Object.entries(config.theme?.styles ?? {})) {
|
|
507
705
|
if (!COOKBOOK_COMPONENT_NAMES.includes(name)) {
|
|
508
706
|
unknown(diagnostics, `theme.styles.${name}; register custom components under theme.customStyles`);
|
|
@@ -522,6 +720,8 @@ function validateConfig(config) {
|
|
|
522
720
|
for (const [name, value] of Object.entries(config.theme?.palette ?? {})) {
|
|
523
721
|
if (![
|
|
524
722
|
"surface",
|
|
723
|
+
"header",
|
|
724
|
+
"overlay",
|
|
525
725
|
"text",
|
|
526
726
|
"textSoft",
|
|
527
727
|
"info",
|
|
@@ -529,14 +729,15 @@ function validateConfig(config) {
|
|
|
529
729
|
"warning",
|
|
530
730
|
"danger"
|
|
531
731
|
].includes(name)) unknown(diagnostics, `theme.palette.${name}`);
|
|
532
|
-
|
|
533
|
-
glaze.color({ from: value }).resolve();
|
|
534
|
-
} catch (error) {
|
|
535
|
-
invalid(diagnostics, `theme.palette.${name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
536
|
-
}
|
|
732
|
+
validatePaletteColor(name, value, diagnostics);
|
|
537
733
|
}
|
|
538
734
|
if (brand !== void 0) try {
|
|
539
|
-
glaze.color({
|
|
735
|
+
if (isBrandDeclaration(brand)) glaze.color({
|
|
736
|
+
hue: brand.hue,
|
|
737
|
+
saturation: brand.saturation,
|
|
738
|
+
tone: brand.tone
|
|
739
|
+
}).resolve();
|
|
740
|
+
else glaze.color({ from: typeof brand === "object" && brand !== null && "from" in brand ? brand.from : brand }).resolve();
|
|
540
741
|
} catch (error) {
|
|
541
742
|
invalid(diagnostics, `theme.brand: ${error instanceof Error ? error.message : String(error)}`);
|
|
542
743
|
}
|
|
@@ -551,6 +752,46 @@ function validateConfig(config) {
|
|
|
551
752
|
}
|
|
552
753
|
return diagnostics;
|
|
553
754
|
}
|
|
755
|
+
function validatePaletteColor(name, value, diagnostics) {
|
|
756
|
+
try {
|
|
757
|
+
if (!isPaletteDeclaration(value)) {
|
|
758
|
+
glaze.color({ from: value }).resolve();
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
for (const key of Object.keys(value)) if (!COLOR_DECLARATION_KEYS.has(key)) unknown(diagnostics, `theme.palette.${name}.${key}`);
|
|
762
|
+
const colorName = name === "textSoft" ? "text-soft" : name;
|
|
763
|
+
const theme = glaze(266, 68);
|
|
764
|
+
theme.colors({
|
|
765
|
+
surface: { tone: 98 },
|
|
766
|
+
"surface-2": {
|
|
767
|
+
base: "surface",
|
|
768
|
+
tone: "-2"
|
|
769
|
+
},
|
|
770
|
+
"accent-surface": { tone: 48 },
|
|
771
|
+
text: {
|
|
772
|
+
base: "surface",
|
|
773
|
+
contrast: { apca: 75 }
|
|
774
|
+
},
|
|
775
|
+
"text-soft": {
|
|
776
|
+
base: "surface",
|
|
777
|
+
contrast: { apca: 60 }
|
|
778
|
+
},
|
|
779
|
+
[colorName]: {
|
|
780
|
+
tone: colorName === "surface" ? 98 : 50,
|
|
781
|
+
...value
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
theme.resolve();
|
|
785
|
+
} catch (error) {
|
|
786
|
+
invalid(diagnostics, `theme.palette.${name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
function isPaletteDeclaration(value) {
|
|
790
|
+
return typeof value === "object" && value !== null && !("h" in value || "r" in value || "c" in value);
|
|
791
|
+
}
|
|
792
|
+
function isBrandDeclaration(value) {
|
|
793
|
+
return isRecord(value) && "hue" in value && "saturation" in value && "tone" in value;
|
|
794
|
+
}
|
|
554
795
|
function unknown(diagnostics, path) {
|
|
555
796
|
diagnostics.push({
|
|
556
797
|
code: "DOCS_CONFIG_UNKNOWN_KEY",
|
|
@@ -568,6 +809,9 @@ function invalid(diagnostics, message) {
|
|
|
568
809
|
function isRecord(value) {
|
|
569
810
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
570
811
|
}
|
|
812
|
+
function validFontFamily(value) {
|
|
813
|
+
return typeof value === "string" && value.length <= 100 && /^[\p{L}\p{N} ._-]+$/u.test(value) && value.trim() === value && value.length > 0;
|
|
814
|
+
}
|
|
571
815
|
function isHttpUrl(value) {
|
|
572
816
|
try {
|
|
573
817
|
return ["http:", "https:"].includes(new URL(value).protocol);
|
|
@@ -575,6 +819,25 @@ function isHttpUrl(value) {
|
|
|
575
819
|
return false;
|
|
576
820
|
}
|
|
577
821
|
}
|
|
822
|
+
function validateNavigationItems(items, path, diagnostics) {
|
|
823
|
+
if (!Array.isArray(items)) {
|
|
824
|
+
invalid(diagnostics, `${path} must be an array.`);
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
for (const [index, item] of items.entries()) {
|
|
828
|
+
const itemPath = `${path}[${index}]`;
|
|
829
|
+
if (typeof item === "string") continue;
|
|
830
|
+
if (!isRecord(item) || typeof item.label !== "string") {
|
|
831
|
+
invalid(diagnostics, `${itemPath} must be a route or a labeled navigation item.`);
|
|
832
|
+
continue;
|
|
833
|
+
}
|
|
834
|
+
if (("items" in item || "autogenerate" in item) && item.link !== void 0 && (typeof item.link !== "string" || !/^\/(?!\/)[^?#\\\s]*$/.test(item.link) || item.link.includes("//") || item.link.split("/").some((segment) => segment === "." || segment === ".."))) invalid(diagnostics, `${itemPath}.link must be a root-relative page route without a query or fragment.`);
|
|
835
|
+
if ("items" in item) validateNavigationItems(item.items, `${itemPath}.items`, diagnostics);
|
|
836
|
+
else if ("autogenerate" in item) {
|
|
837
|
+
if (!isRecord(item.autogenerate) || typeof item.autogenerate.directory !== "string") invalid(diagnostics, `${itemPath}.autogenerate.directory must be a directory path.`);
|
|
838
|
+
} else if (typeof item.link !== "string") invalid(diagnostics, `${itemPath}.link must be a URL or route.`);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
578
841
|
function normalizeDocsConfig(config = {}) {
|
|
579
842
|
const diagnostics = validateConfig(config);
|
|
580
843
|
if (diagnostics.length > 0) throw new DocsConfigError(diagnostics);
|
|
@@ -626,7 +889,7 @@ function defineDocsConfig(config) {
|
|
|
626
889
|
if (diagnostics.length > 0) throw new DocsConfigError(diagnostics);
|
|
627
890
|
return config;
|
|
628
891
|
}
|
|
629
|
-
/** Compose presets.
|
|
892
|
+
/** Compose presets. Color roles and fonts replace, other objects merge, and styles use Tasty semantics. */
|
|
630
893
|
function mergeDocsConfig(...configs) {
|
|
631
894
|
const merge = (base, next) => {
|
|
632
895
|
const result = { ...base };
|
|
@@ -640,6 +903,15 @@ function mergeDocsConfig(...configs) {
|
|
|
640
903
|
const diagnostics = validateConfig(next);
|
|
641
904
|
if (diagnostics.length) throw new DocsConfigError(diagnostics);
|
|
642
905
|
const result = merge(base, next);
|
|
906
|
+
if (next.theme?.brand !== void 0) result.theme.brand = next.theme.brand;
|
|
907
|
+
if (next.theme?.palette) result.theme.palette = {
|
|
908
|
+
...base.theme?.palette,
|
|
909
|
+
...Object.fromEntries(Object.entries(next.theme.palette).filter(([, color]) => color !== void 0))
|
|
910
|
+
};
|
|
911
|
+
if (next.theme?.fonts) result.theme.fonts = {
|
|
912
|
+
...base.theme?.fonts,
|
|
913
|
+
...Object.fromEntries(Object.entries(next.theme.fonts).filter(([, font]) => font !== void 0))
|
|
914
|
+
};
|
|
643
915
|
for (const field of ["styles", "customStyles"]) {
|
|
644
916
|
if (!next.theme?.[field]) continue;
|
|
645
917
|
const styles = { ...base.theme?.[field] };
|
|
@@ -652,4 +924,4 @@ function mergeDocsConfig(...configs) {
|
|
|
652
924
|
//#endregion
|
|
653
925
|
export { validateConfig as a, normalizeDocsConfig as i, defineDocsConfig as n, COOKBOOK_COMPONENT_NAMES as o, mergeDocsConfig as r, COOKBOOK_COMPONENT_SUB_ELEMENTS as s, DocsConfigError as t };
|
|
654
926
|
|
|
655
|
-
//# sourceMappingURL=config-
|
|
927
|
+
//# sourceMappingURL=config-Ci9Nv0wQ.js.map
|