@specglass/core 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/defaults.js +5 -1
- package/dist/config/schema.d.ts +44 -0
- package/dist/config/schema.js +14 -0
- package/dist/content/rehype-code-blocks.js +91 -10
- package/dist/navigation/builder.js +3 -0
- package/dist/navigation/meta-parser.js +1 -0
- package/dist/navigation/meta-schema.d.ts +16 -7
- package/dist/navigation/meta-schema.js +2 -1
- package/dist/types/navigation.d.ts +5 -0
- package/package.json +1 -1
package/dist/config/defaults.js
CHANGED
|
@@ -21,8 +21,12 @@ export const DEFAULT_CONFIG = {
|
|
|
21
21
|
footer: undefined,
|
|
22
22
|
favicon: undefined,
|
|
23
23
|
socialImage: undefined,
|
|
24
|
-
headerLinks:
|
|
24
|
+
headerLinks: [
|
|
25
|
+
{ label: "Documentation", href: "/" },
|
|
26
|
+
{ label: "API Reference", href: "/api-reference" },
|
|
27
|
+
],
|
|
25
28
|
colors: undefined,
|
|
29
|
+
socialLinks: undefined,
|
|
26
30
|
},
|
|
27
31
|
build: {
|
|
28
32
|
outDir: "dist",
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -180,6 +180,26 @@ export declare const configSchema: z.ZodObject<{
|
|
|
180
180
|
dark?: string | undefined;
|
|
181
181
|
} | undefined;
|
|
182
182
|
}>>;
|
|
183
|
+
/** Social/external links shown in the footer */
|
|
184
|
+
socialLinks: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
185
|
+
/** Display label for the link */
|
|
186
|
+
label: z.ZodString;
|
|
187
|
+
/** URL the link navigates to */
|
|
188
|
+
href: z.ZodString;
|
|
189
|
+
/** Optional icon identifier (e.g., 'github', 'twitter', 'discord') */
|
|
190
|
+
icon: z.ZodOptional<z.ZodString>;
|
|
191
|
+
}, "strip", z.ZodTypeAny, {
|
|
192
|
+
label: string;
|
|
193
|
+
href: string;
|
|
194
|
+
icon?: string | undefined;
|
|
195
|
+
}, {
|
|
196
|
+
label: string;
|
|
197
|
+
href: string;
|
|
198
|
+
icon?: string | undefined;
|
|
199
|
+
}>, "many">>;
|
|
200
|
+
/** Base URL for "Edit on GitHub" links. File path will be appended.
|
|
201
|
+
* Example: "https://github.com/org/repo/edit/main/docs" */
|
|
202
|
+
editUrl: z.ZodOptional<z.ZodString>;
|
|
183
203
|
}, "strip", z.ZodTypeAny, {
|
|
184
204
|
logo?: string | undefined;
|
|
185
205
|
primaryColor?: string | undefined;
|
|
@@ -213,6 +233,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
213
233
|
dark?: string | undefined;
|
|
214
234
|
} | undefined;
|
|
215
235
|
} | undefined;
|
|
236
|
+
socialLinks?: {
|
|
237
|
+
label: string;
|
|
238
|
+
href: string;
|
|
239
|
+
icon?: string | undefined;
|
|
240
|
+
}[] | undefined;
|
|
241
|
+
editUrl?: string | undefined;
|
|
216
242
|
}, {
|
|
217
243
|
logo?: string | undefined;
|
|
218
244
|
primaryColor?: string | undefined;
|
|
@@ -246,6 +272,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
246
272
|
dark?: string | undefined;
|
|
247
273
|
} | undefined;
|
|
248
274
|
} | undefined;
|
|
275
|
+
socialLinks?: {
|
|
276
|
+
label: string;
|
|
277
|
+
href: string;
|
|
278
|
+
icon?: string | undefined;
|
|
279
|
+
}[] | undefined;
|
|
280
|
+
editUrl?: string | undefined;
|
|
249
281
|
}>>;
|
|
250
282
|
/** Build output configuration */
|
|
251
283
|
build: z.ZodOptional<z.ZodObject<{
|
|
@@ -305,6 +337,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
305
337
|
dark?: string | undefined;
|
|
306
338
|
} | undefined;
|
|
307
339
|
} | undefined;
|
|
340
|
+
socialLinks?: {
|
|
341
|
+
label: string;
|
|
342
|
+
href: string;
|
|
343
|
+
icon?: string | undefined;
|
|
344
|
+
}[] | undefined;
|
|
345
|
+
editUrl?: string | undefined;
|
|
308
346
|
} | undefined;
|
|
309
347
|
build?: {
|
|
310
348
|
outDir?: string | undefined;
|
|
@@ -358,6 +396,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
358
396
|
dark?: string | undefined;
|
|
359
397
|
} | undefined;
|
|
360
398
|
} | undefined;
|
|
399
|
+
socialLinks?: {
|
|
400
|
+
label: string;
|
|
401
|
+
href: string;
|
|
402
|
+
icon?: string | undefined;
|
|
403
|
+
}[] | undefined;
|
|
404
|
+
editUrl?: string | undefined;
|
|
361
405
|
} | undefined;
|
|
362
406
|
build?: {
|
|
363
407
|
outDir?: string | undefined;
|
package/dist/config/schema.js
CHANGED
|
@@ -20,6 +20,15 @@ const headerLinkSchema = z.object({
|
|
|
20
20
|
/** URL the link navigates to */
|
|
21
21
|
href: z.string(),
|
|
22
22
|
});
|
|
23
|
+
/** Schema for a social/external link shown in the footer */
|
|
24
|
+
const socialLinkSchema = z.object({
|
|
25
|
+
/** Display label for the link */
|
|
26
|
+
label: z.string(),
|
|
27
|
+
/** URL the link navigates to */
|
|
28
|
+
href: z.string(),
|
|
29
|
+
/** Optional icon identifier (e.g., 'github', 'twitter', 'discord') */
|
|
30
|
+
icon: z.string().optional(),
|
|
31
|
+
});
|
|
23
32
|
/**
|
|
24
33
|
* A color value that supports both light and dark modes.
|
|
25
34
|
*
|
|
@@ -70,6 +79,11 @@ const themeSchema = z.object({
|
|
|
70
79
|
headerLinks: z.array(headerLinkSchema).optional(),
|
|
71
80
|
/** Semantic color tokens for CSS custom property theming */
|
|
72
81
|
colors: colorsSchema.optional(),
|
|
82
|
+
/** Social/external links shown in the footer */
|
|
83
|
+
socialLinks: z.array(socialLinkSchema).optional(),
|
|
84
|
+
/** Base URL for "Edit on GitHub" links. File path will be appended.
|
|
85
|
+
* Example: "https://github.com/org/repo/edit/main/docs" */
|
|
86
|
+
editUrl: z.string().url().optional(),
|
|
73
87
|
});
|
|
74
88
|
/** Schema for OpenAPI configuration */
|
|
75
89
|
const openApiSchema = z.object({
|
|
@@ -37,6 +37,45 @@ function isAlreadyWrapped(parent) {
|
|
|
37
37
|
return true;
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
|
+
function parseMeta(meta, lang) {
|
|
41
|
+
const result = {
|
|
42
|
+
showLineNumbers: false,
|
|
43
|
+
isDiff: lang === "diff",
|
|
44
|
+
highlightLines: [],
|
|
45
|
+
};
|
|
46
|
+
if (!meta)
|
|
47
|
+
return result;
|
|
48
|
+
// Extract filename="..." or title="..."
|
|
49
|
+
const filenameMatch = meta.match(/(?:filename|title)=["']([^"']+)["']/);
|
|
50
|
+
if (filenameMatch) {
|
|
51
|
+
result.filename = filenameMatch[1];
|
|
52
|
+
}
|
|
53
|
+
// Check for showLineNumbers flag
|
|
54
|
+
if (/\bshowLineNumbers\b/.test(meta)) {
|
|
55
|
+
result.showLineNumbers = true;
|
|
56
|
+
}
|
|
57
|
+
// Check for diff flag
|
|
58
|
+
if (/\bdiff\b/.test(meta)) {
|
|
59
|
+
result.isDiff = true;
|
|
60
|
+
}
|
|
61
|
+
// Parse highlight ranges: {1,3-5,8}
|
|
62
|
+
const highlightMatch = meta.match(/\{([\d,\s-]+)\}/);
|
|
63
|
+
if (highlightMatch) {
|
|
64
|
+
const ranges = highlightMatch[1].split(",").map((s) => s.trim());
|
|
65
|
+
for (const range of ranges) {
|
|
66
|
+
if (range.includes("-")) {
|
|
67
|
+
const [start, end] = range.split("-").map(Number);
|
|
68
|
+
for (let i = start; i <= end; i++) {
|
|
69
|
+
result.highlightLines.push(i);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
result.highlightLines.push(Number(range));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
40
79
|
export function rehypeCodeBlocks() {
|
|
41
80
|
return (tree) => {
|
|
42
81
|
// Process in reverse to avoid index shifts when splicing
|
|
@@ -55,22 +94,64 @@ export function rehypeCodeBlocks() {
|
|
|
55
94
|
return;
|
|
56
95
|
// Extract raw text for clipboard
|
|
57
96
|
const rawCode = extractText(codeEl).trimEnd();
|
|
58
|
-
//
|
|
97
|
+
// Get language from class="language-xxx"
|
|
98
|
+
const codeClasses = Array.isArray(codeEl.properties?.className)
|
|
99
|
+
? codeEl.properties.className
|
|
100
|
+
: [];
|
|
101
|
+
const langClass = codeClasses.find((c) => typeof c === "string" && c.startsWith("language-"));
|
|
102
|
+
const lang = langClass ? langClass.replace("language-", "") : "text";
|
|
103
|
+
// Parse meta string from Astro/Shiki
|
|
104
|
+
const meta = (node.properties?.["data-meta"] ??
|
|
105
|
+
codeEl.properties?.["data-meta"] ??
|
|
106
|
+
node.data?.meta);
|
|
107
|
+
const parsed = parseMeta(meta, lang);
|
|
108
|
+
// Build CSS classes for the wrapper
|
|
109
|
+
const wrapperClasses = ["code-block", "code-block--fenced"];
|
|
110
|
+
if (parsed.showLineNumbers)
|
|
111
|
+
wrapperClasses.push("code-block--line-numbers");
|
|
112
|
+
if (parsed.isDiff)
|
|
113
|
+
wrapperClasses.push("code-block--diff");
|
|
114
|
+
if (parsed.highlightLines.length > 0)
|
|
115
|
+
wrapperClasses.push("code-block--has-highlights");
|
|
116
|
+
// Build children: optional header + body
|
|
117
|
+
const children = [];
|
|
118
|
+
// Add filename header if present
|
|
119
|
+
if (parsed.filename) {
|
|
120
|
+
children.push({
|
|
121
|
+
type: "element",
|
|
122
|
+
tagName: "div",
|
|
123
|
+
properties: { className: ["code-block-header"] },
|
|
124
|
+
children: [
|
|
125
|
+
{
|
|
126
|
+
type: "element",
|
|
127
|
+
tagName: "span",
|
|
128
|
+
properties: { className: ["code-block-title"] },
|
|
129
|
+
children: [{ type: "text", value: parsed.filename }],
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
// Body
|
|
135
|
+
children.push({
|
|
136
|
+
type: "element",
|
|
137
|
+
tagName: "div",
|
|
138
|
+
properties: { className: ["code-block-body"] },
|
|
139
|
+
children: [node],
|
|
140
|
+
});
|
|
141
|
+
// Build wrapper div
|
|
59
142
|
const wrapper = {
|
|
60
143
|
type: "element",
|
|
61
144
|
tagName: "div",
|
|
62
145
|
properties: {
|
|
63
|
-
className:
|
|
146
|
+
className: wrapperClasses,
|
|
64
147
|
"data-code": rawCode,
|
|
148
|
+
...(parsed.filename ? { "data-filename": parsed.filename } : {}),
|
|
149
|
+
...(parsed.showLineNumbers ? { "data-line-numbers": "" } : {}),
|
|
150
|
+
...(parsed.highlightLines.length > 0
|
|
151
|
+
? { "data-highlight": parsed.highlightLines.join(",") }
|
|
152
|
+
: {}),
|
|
65
153
|
},
|
|
66
|
-
children
|
|
67
|
-
{
|
|
68
|
-
type: "element",
|
|
69
|
-
tagName: "div",
|
|
70
|
-
properties: { className: ["code-block-body"] },
|
|
71
|
-
children: [node],
|
|
72
|
-
},
|
|
73
|
-
],
|
|
154
|
+
children,
|
|
74
155
|
};
|
|
75
156
|
replacements.push({ parent: parent, index, wrapper });
|
|
76
157
|
});
|
|
@@ -97,6 +97,7 @@ async function buildItems(dirPath, slugPrefix) {
|
|
|
97
97
|
type: "external-link",
|
|
98
98
|
href: entry.href,
|
|
99
99
|
...(entry.icon !== undefined && { icon: entry.icon }),
|
|
100
|
+
...(entry.badge !== undefined && { badge: entry.badge }),
|
|
100
101
|
});
|
|
101
102
|
continue;
|
|
102
103
|
}
|
|
@@ -112,6 +113,7 @@ async function buildItems(dirPath, slugPrefix) {
|
|
|
112
113
|
children,
|
|
113
114
|
...(entry.collapsed !== undefined && { collapsed: entry.collapsed }),
|
|
114
115
|
...(entry.icon !== undefined && { icon: entry.icon }),
|
|
116
|
+
...(entry.badge !== undefined && { badge: entry.badge }),
|
|
115
117
|
});
|
|
116
118
|
continue;
|
|
117
119
|
}
|
|
@@ -124,6 +126,7 @@ async function buildItems(dirPath, slugPrefix) {
|
|
|
124
126
|
slug: slugPrefix ? `${slugPrefix}/${fileSlug}` : fileSlug,
|
|
125
127
|
type: "page",
|
|
126
128
|
...(entry.icon !== undefined && { icon: entry.icon }),
|
|
129
|
+
...(entry.badge !== undefined && { badge: entry.badge }),
|
|
127
130
|
});
|
|
128
131
|
}
|
|
129
132
|
// If no file or directory matches, skip silently (meta references a non-existent item)
|
|
@@ -17,6 +17,7 @@ function normalizeEntry(key, value) {
|
|
|
17
17
|
...(value.icon !== undefined && { icon: value.icon }),
|
|
18
18
|
...(value.href !== undefined && { href: value.href }),
|
|
19
19
|
...(value.hidden !== undefined && { hidden: value.hidden }),
|
|
20
|
+
...(value.badge !== undefined && { badge: value.badge }),
|
|
20
21
|
};
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
/**
|
|
3
3
|
* Zod schema for the object form of a `_meta.json` entry value.
|
|
4
4
|
*
|
|
5
|
-
* Supports: `title` (required), `collapsed`, `icon`, `href`, `hidden`.
|
|
5
|
+
* Supports: `title` (required), `collapsed`, `icon`, `href`, `hidden`, `badge`.
|
|
6
6
|
*/
|
|
7
7
|
export declare const metaJsonEntryObjectSchema: z.ZodObject<{
|
|
8
8
|
title: z.ZodString;
|
|
@@ -10,18 +10,21 @@ export declare const metaJsonEntryObjectSchema: z.ZodObject<{
|
|
|
10
10
|
icon: z.ZodOptional<z.ZodString>;
|
|
11
11
|
href: z.ZodOptional<z.ZodString>;
|
|
12
12
|
hidden: z.ZodOptional<z.ZodBoolean>;
|
|
13
|
+
badge: z.ZodOptional<z.ZodString>;
|
|
13
14
|
}, "strip", z.ZodTypeAny, {
|
|
14
15
|
title: string;
|
|
15
16
|
href?: string | undefined;
|
|
16
|
-
collapsed?: boolean | undefined;
|
|
17
17
|
icon?: string | undefined;
|
|
18
|
+
collapsed?: boolean | undefined;
|
|
18
19
|
hidden?: boolean | undefined;
|
|
20
|
+
badge?: string | undefined;
|
|
19
21
|
}, {
|
|
20
22
|
title: string;
|
|
21
23
|
href?: string | undefined;
|
|
22
|
-
collapsed?: boolean | undefined;
|
|
23
24
|
icon?: string | undefined;
|
|
25
|
+
collapsed?: boolean | undefined;
|
|
24
26
|
hidden?: boolean | undefined;
|
|
27
|
+
badge?: string | undefined;
|
|
25
28
|
}>;
|
|
26
29
|
/**
|
|
27
30
|
* Zod schema for a single `_meta.json` entry value.
|
|
@@ -35,18 +38,21 @@ export declare const metaJsonEntryValueSchema: z.ZodUnion<[z.ZodString, z.ZodObj
|
|
|
35
38
|
icon: z.ZodOptional<z.ZodString>;
|
|
36
39
|
href: z.ZodOptional<z.ZodString>;
|
|
37
40
|
hidden: z.ZodOptional<z.ZodBoolean>;
|
|
41
|
+
badge: z.ZodOptional<z.ZodString>;
|
|
38
42
|
}, "strip", z.ZodTypeAny, {
|
|
39
43
|
title: string;
|
|
40
44
|
href?: string | undefined;
|
|
41
|
-
collapsed?: boolean | undefined;
|
|
42
45
|
icon?: string | undefined;
|
|
46
|
+
collapsed?: boolean | undefined;
|
|
43
47
|
hidden?: boolean | undefined;
|
|
48
|
+
badge?: string | undefined;
|
|
44
49
|
}, {
|
|
45
50
|
title: string;
|
|
46
51
|
href?: string | undefined;
|
|
47
|
-
collapsed?: boolean | undefined;
|
|
48
52
|
icon?: string | undefined;
|
|
53
|
+
collapsed?: boolean | undefined;
|
|
49
54
|
hidden?: boolean | undefined;
|
|
55
|
+
badge?: string | undefined;
|
|
50
56
|
}>]>;
|
|
51
57
|
/**
|
|
52
58
|
* Zod schema for a complete `_meta.json` file.
|
|
@@ -60,17 +66,20 @@ export declare const metaJsonSchema: z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodS
|
|
|
60
66
|
icon: z.ZodOptional<z.ZodString>;
|
|
61
67
|
href: z.ZodOptional<z.ZodString>;
|
|
62
68
|
hidden: z.ZodOptional<z.ZodBoolean>;
|
|
69
|
+
badge: z.ZodOptional<z.ZodString>;
|
|
63
70
|
}, "strip", z.ZodTypeAny, {
|
|
64
71
|
title: string;
|
|
65
72
|
href?: string | undefined;
|
|
66
|
-
collapsed?: boolean | undefined;
|
|
67
73
|
icon?: string | undefined;
|
|
74
|
+
collapsed?: boolean | undefined;
|
|
68
75
|
hidden?: boolean | undefined;
|
|
76
|
+
badge?: string | undefined;
|
|
69
77
|
}, {
|
|
70
78
|
title: string;
|
|
71
79
|
href?: string | undefined;
|
|
72
|
-
collapsed?: boolean | undefined;
|
|
73
80
|
icon?: string | undefined;
|
|
81
|
+
collapsed?: boolean | undefined;
|
|
74
82
|
hidden?: boolean | undefined;
|
|
83
|
+
badge?: string | undefined;
|
|
75
84
|
}>]>>;
|
|
76
85
|
export type MetaJsonSchemaInput = z.input<typeof metaJsonSchema>;
|
|
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
/**
|
|
3
3
|
* Zod schema for the object form of a `_meta.json` entry value.
|
|
4
4
|
*
|
|
5
|
-
* Supports: `title` (required), `collapsed`, `icon`, `href`, `hidden`.
|
|
5
|
+
* Supports: `title` (required), `collapsed`, `icon`, `href`, `hidden`, `badge`.
|
|
6
6
|
*/
|
|
7
7
|
export const metaJsonEntryObjectSchema = z.object({
|
|
8
8
|
title: z.string(),
|
|
@@ -10,6 +10,7 @@ export const metaJsonEntryObjectSchema = z.object({
|
|
|
10
10
|
icon: z.string().optional(),
|
|
11
11
|
href: z.string().optional(),
|
|
12
12
|
hidden: z.boolean().optional(),
|
|
13
|
+
badge: z.string().optional(),
|
|
13
14
|
});
|
|
14
15
|
/**
|
|
15
16
|
* Zod schema for a single `_meta.json` entry value.
|
|
@@ -22,6 +22,8 @@ export interface NavItem {
|
|
|
22
22
|
href?: string;
|
|
23
23
|
/** If true, item is excluded from the rendered tree */
|
|
24
24
|
hidden?: boolean;
|
|
25
|
+
/** Optional badge label ("New", "Beta", "Deprecated", or custom string) */
|
|
26
|
+
badge?: string;
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* The complete sidebar navigation tree.
|
|
@@ -41,6 +43,7 @@ export type MetaJsonEntryValue = string | {
|
|
|
41
43
|
icon?: string;
|
|
42
44
|
href?: string;
|
|
43
45
|
hidden?: boolean;
|
|
46
|
+
badge?: string;
|
|
44
47
|
};
|
|
45
48
|
/**
|
|
46
49
|
* A single parsed entry from `_meta.json`, preserving key order.
|
|
@@ -58,4 +61,6 @@ export interface MetaJsonEntry {
|
|
|
58
61
|
href?: string;
|
|
59
62
|
/** Whether to hide from navigation */
|
|
60
63
|
hidden?: boolean;
|
|
64
|
+
/** Optional badge label */
|
|
65
|
+
badge?: string;
|
|
61
66
|
}
|