@topik/core 0.1.0-alpha.6 → 0.1.0-alpha.7
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/{course-navigation-CWlVc0a0.mjs → course-navigation-h54ccuqO.mjs} +7 -13
- package/dist/course-navigation.d.mts +1 -3
- package/dist/course-navigation.mjs +1 -1
- package/dist/{folder-links-DI4xfipU.mjs → folder-links-jLZaG6xi.mjs} +3 -3
- package/dist/index.d.mts +1 -57
- package/dist/index.mjs +96 -96
- package/dist/{preview-C_3OnNUi.d.mts → preview-DfACgOEg.d.mts} +0 -14
- package/dist/preview.d.mts +1 -1
- package/dist/preview.mjs +1 -2
- package/dist/wiki-navigation.d.mts +1 -3
- package/dist/wiki-navigation.mjs +2 -3
- package/package.json +7 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as resolveDeclaredSourcePage, i as resolveDeclaredPublicRoute, n as hasDeclaredFolder, o as resolveNavigationPath, r as isFolderHref } from "./folder-links-
|
|
1
|
+
import { a as resolveDeclaredSourcePage, i as resolveDeclaredPublicRoute, n as hasDeclaredFolder, o as resolveNavigationPath, r as isFolderHref } from "./folder-links-jLZaG6xi.mjs";
|
|
2
2
|
import { parseTopikResourceReference } from "@topik/content";
|
|
3
|
-
|
|
3
|
+
// src/assets/constants.ts
|
|
4
4
|
const ASSET_API_VERSION = "v1";
|
|
5
5
|
const ASSET_TYPE = "Asset";
|
|
6
6
|
const ASSET_SCHEMA_ID = "https://topik.dev/schemas/asset/v1.json";
|
|
@@ -30,8 +30,7 @@ const TOPIK_ASSET_LIMITS = {
|
|
|
30
30
|
maxComponents: 64,
|
|
31
31
|
maxRepositoryPathUtf8Bytes: 768
|
|
32
32
|
};
|
|
33
|
-
|
|
34
|
-
//#region src/assets/nfkc-casefold-v17.ts
|
|
33
|
+
// src/assets/nfkc-casefold-v17.ts
|
|
35
34
|
/** Unicode 17.0.0 NFKC_CF data from DerivedNormalizationProps.txt.
|
|
36
35
|
* Source SHA-256: 71fd6a206a2c0cdd41feb6b7f656aa31091db45e9cedc926985d718397f9e488
|
|
37
36
|
*/
|
|
@@ -112,8 +111,7 @@ const NFKC_CASEFOLD_V17_DATA = [
|
|
|
112
111
|
"13e;2f986=5ab5;2f987=267a7;2f988=267b5;2f989=23393;2f98a=2339c;2f98b=8201;2f98c=8204;2f98d=8f9e;2f98e=446b;2f98f=8291;2f990=828b;2f991=829d;2f992=52b3;2f993=82b1;2f994=82b3;2f995=82bd;2f996=82e6;2f997=26b3c;2f998=82e5;2f999=831d;2f99a=8363;2f99b=83ad;2f99c=8323;2f99d=83bd;2f99e=83e7;2f99f=8457;2f9a0=8353;2f9a1=83ca;2f9a2=83cc;2f9a3=83dc;2f9a4=26c36;2f9a5=26d6b;2f9a6=26cd5;2f9a7=452b;2f9a8=84f1;2f9a9=84f3;2f9aa=8516;2f9ab=273ca;2f9ac=8564;2f9ad=26f2c;2f9ae=455d;2f9af=4561;2f9b0=26fb1;2f9b1=270d2;2f9b2=456b;2f9b3=8650;2f9b4=865c;2f9b5=8667;2f9b6=8669;2f9b7=86a9;2f9b8=8688;2f9b9=870e;2f9ba=86e2;2f9bb=8779;2f9bc=8728;2f9bd=876b;2f9be=8786;2f9bf=45d7;2f9c0=87e1;2f9c1=8801;2f9c2=45f9;2f9c3=8860;2f9c4=8863;2f9c5=27667;2f9c6=88d7;2f9c7=88de;2f9c8=4635;2f9c9=88fa;2f9ca=34bb;2f9cb=278ae;2f9cc=27966;2f9cd=46be;2f9ce=46c7;2f9cf=8aa0;2f9d0=8aed;2f9d1=8b8a;2f9d2=8c55;2f9d3=27ca8;2f9d4=8cab;2f9d5=8cc1;2f9d6=8d1b;2f9d7=8d77;2f9d8=27f2f;2f9d9=20804;2f9da=8dcb;2f9db=8dbc;2f9dc=8df0;2f9dd=208de;2f9de=8ed",
|
|
113
112
|
"4;2f9df=8f38;2f9e0=285d2;2f9e1=285ed;2f9e2=9094;2f9e3=90f1;2f9e4=9111;2f9e5=2872e;2f9e6=911b;2f9e7=9238;2f9e8=92d7;2f9e9=92d8;2f9ea=927c;2f9eb=93f9;2f9ec=9415;2f9ed=28bfa;2f9ee=958b;2f9ef=4995;2f9f0=95b7;2f9f1=28d77;2f9f2=49e6;2f9f3=96c3;2f9f4=5db2;2f9f5=9723;2f9f6=29145;2f9f7=2921a;2f9f8=4a6e;2f9f9=4a76;2f9fa=97e0;2f9fb=2940a;2f9fc=4ab2;2f9fd=29496;2f9fe..2f9ff=980b;2fa00=9829;2fa01=295b6;2fa02=98e2;2fa03=4b33;2fa04=9929;2fa05=99a7;2fa06=99c2;2fa07=99fe;2fa08=4bce;2fa09=29b30;2fa0a=9b12;2fa0b=9c40;2fa0c=9cfd;2fa0d=4cce;2fa0e=4ced;2fa0f=9d67;2fa10=2a0ce;2fa11=4cf8;2fa12=2a105;2fa13=2a20e;2fa14=2a291;2fa15=9ebb;2fa16=4d56;2fa17=9ef9;2fa18=9efe;2fa19=9f05;2fa1a=9f0f;2fa1b=9f16;2fa1c=9f3b;2fa1d=2a600;e0000=;e0001=;e0002..e001f=;e0020..e007f=;e0080..e00ff=;e0100..e01ef=;e01f0..e0fff="
|
|
114
113
|
].join("");
|
|
115
|
-
|
|
116
|
-
//#region src/assets/path-unicode-v17.ts
|
|
114
|
+
// src/assets/path-unicode-v17.ts
|
|
117
115
|
/**
|
|
118
116
|
* Unicode 17 path-forbidden code points, encoded as inclusive hexadecimal ranges.
|
|
119
117
|
*
|
|
@@ -175,8 +173,7 @@ function isCodePointInRanges(codePoint, ranges) {
|
|
|
175
173
|
}
|
|
176
174
|
return false;
|
|
177
175
|
}
|
|
178
|
-
|
|
179
|
-
//#region src/assets/diagnostics.ts
|
|
176
|
+
// src/assets/diagnostics.ts
|
|
180
177
|
const TOPIK_ASSET_DIAGNOSTIC_IDS = [
|
|
181
178
|
"TOPIK_ASSET_UNSUPPORTED_VERSION",
|
|
182
179
|
"TOPIK_ASSET_DUPLICATE_MEMBER",
|
|
@@ -289,8 +286,7 @@ function containsUnsafeDiagnosticUnicode(value) {
|
|
|
289
286
|
}
|
|
290
287
|
return false;
|
|
291
288
|
}
|
|
292
|
-
|
|
293
|
-
//#region src/assets/path.ts
|
|
289
|
+
// src/assets/path.ts
|
|
294
290
|
const encoder = new TextEncoder();
|
|
295
291
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
296
292
|
const FORBIDDEN_ASCII = /[\\%<>:"|?*]/u;
|
|
@@ -436,8 +432,7 @@ function parseNfkcCasefoldData(source) {
|
|
|
436
432
|
}
|
|
437
433
|
return mapping;
|
|
438
434
|
}
|
|
439
|
-
|
|
440
|
-
//#region src/course-navigation.ts
|
|
435
|
+
// src/course-navigation.ts
|
|
441
436
|
const INTERNAL_COURSE_ORIGIN = "https://topik.invalid";
|
|
442
437
|
const RESOURCE_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
443
438
|
function isName(value) {
|
|
@@ -554,5 +549,4 @@ function resolveCourseContentHref(href, currentPageName, resolved) {
|
|
|
554
549
|
search: url.search
|
|
555
550
|
} : null;
|
|
556
551
|
}
|
|
557
|
-
//#endregion
|
|
558
552
|
export { TOPIK_JSON_VERSION as C, TOPIK_PATH_VERSION as E, TOPIK_BLOB_OUTPUT_PREFIX as S, TOPIK_PATH_V1_DESCRIPTOR as T, ASSET_SCHEMA_ID as _, computeTopikPathCollisionKey as a, TOPIK_ASSET_NAME_VERSION as b, validateTopikPathSet as c, TOPIK_ASSET_DIAGNOSTIC_IDS as d, correlateTopikAssetResult as f, ASSET_API_VERSION as g, isTopikPathNormalizationSensitiveV17 as h, validateCoursePageSources as i, TOPIK_ASSET_CORRELATION_ID_PATTERN as l, isTopikPathCodePointForbiddenV17 as m, resolveCourseContentReference as n, toNfkcCasefold as o, topikAssetDiagnostic as p, resolveCourseNavigation as r, validateTopikPath as s, resolveCourseContentHref as t, TOPIK_ASSET_DEFAULT_CORRELATION_ID as u, ASSET_TYPE as v, TOPIK_MATERIALIZATION_VERSION as w, TOPIK_ASSET_REFERENCE_VERSION as x, TOPIK_ASSET_LIMITS as y };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//#region src/course-navigation.d.ts
|
|
2
1
|
/** @internal Logical page sources become Markdown files and must agree on directory spelling. */
|
|
3
2
|
export declare function validateCoursePageSources(paths: readonly string[]): boolean;
|
|
4
3
|
/** Portable reference context for one Course, independent of filesystem access. */
|
|
@@ -48,5 +47,4 @@ export type ResolvedCourseContentReference = {
|
|
|
48
47
|
export declare function resolveCourseNavigation(context: CourseReferenceContext): ResolvedCourseNavigation;
|
|
49
48
|
export declare function resolveCourseContentReference(href: string, currentPageName: string, resolved: ResolvedCourseNavigation): ResolvedCourseContentReference;
|
|
50
49
|
/** Resolve relative source references or root-relative public routes without guessing files. */
|
|
51
|
-
export declare function resolveCourseContentHref(href: string, currentPageName: string, resolved: ResolvedCourseNavigation): ResolvedCourseContentLink | null;
|
|
52
|
-
//#endregion
|
|
50
|
+
export declare function resolveCourseContentHref(href: string, currentPageName: string, resolved: ResolvedCourseNavigation): ResolvedCourseContentLink | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as resolveCourseContentHref, n as resolveCourseContentReference, r as resolveCourseNavigation, i as validateCoursePageSources } from "./course-navigation-
|
|
1
|
+
export { t as resolveCourseContentHref, n as resolveCourseContentReference, r as resolveCourseNavigation, i as validateCoursePageSources } from "./course-navigation-h54ccuqO.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/folder-links.ts
|
|
2
2
|
/** Resolve decoded source paths consistently without URL root-clamping or Node-only APIs. */
|
|
3
3
|
function resolveNavigationPath(href, sourcePath, directory = "") {
|
|
4
4
|
if (/^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//")) return void 0;
|
|
@@ -45,13 +45,13 @@ function resolveDeclaredSourcePage(path, pages, folder = false) {
|
|
|
45
45
|
const candidates = folderLandingCandidates(path, pages);
|
|
46
46
|
return candidates.length === 1 ? candidates[0] : void 0;
|
|
47
47
|
}
|
|
48
|
-
/**
|
|
48
|
+
/** Exact public routes take precedence over Wiki's fallback index aliases. */
|
|
49
49
|
function resolveDeclaredPublicRoute(href, pages, wiki = false) {
|
|
50
50
|
if (!href.startsWith("/") || isFolderHref(href)) return void 0;
|
|
51
51
|
const path = resolveNavigationPath(href, "");
|
|
52
52
|
if (path === void 0 || /\.(?:mdx?|markdown)$/i.test(path)) return void 0;
|
|
53
|
+
if (pages.has(path)) return pages.get(path);
|
|
53
54
|
const route = wiki ? path === "index" ? "" : path.replace(/\/index$/, "") : path;
|
|
54
55
|
return pages.get(route);
|
|
55
56
|
}
|
|
56
|
-
//#endregion
|
|
57
57
|
export { resolveDeclaredSourcePage as a, resolveDeclaredPublicRoute as i, hasDeclaredFolder as n, resolveNavigationPath as o, isFolderHref as r, folderLandingCandidates as t };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CourseReferenceContext, ResolvedCourseContentLink, ResolvedCourseContentReference, ResolvedCourseNavigation, ResolvedCoursePage, resolveCourseContentHref, resolveCourseContentReference, resolveCourseNavigation } from "./course-navigation.mjs";
|
|
2
|
-
import { $ as TopikAssetPathDiagnosticReason, A as AssetBlobUri, B as parseGeneratedAssetName, C as TopikMaterializationResourceV1, D as digestTopikAssetSemanticRecord, E as createTopikMaterializationRecord, F as generateAutomaticAssetName, G as validateProjectNamespace, H as topikAssetNameDescriptor, I as isAssetBlobUri, J as TOPIK_ASSET_DIAGNOSTIC_IDS, K as TOPIK_ASSET_CORRELATION_ID_PATTERN, L as isGeneratedAssetName, M as GenerateAutomaticAssetNameOptions, N as GeneratedAssetName, O as digestTopikMaterializationRecord, P as ParsedAsset, Q as TopikAssetDiagnosticLocation, R as parseAsset, S as TopikMaterializationResourceInput, T as createTopikAssetSemanticRecord, U as validateAssetBlobUri, V as serializeAsset, W as validateAssetValue, X as TopikAssetDiagnostic, Y as TopikAssetCorrelationId, Z as TopikAssetDiagnosticId, _ as TopikAssetReferenceMappingV1, a as PreviewState, at as ASSET_TYPE, b as TopikMaterializationPayloadV1, c as AssetCompilationOptions, ct as TOPIK_ASSET_REFERENCE_VERSION, d as AssetNameInput, dt as TOPIK_MATERIALIZATION_VERSION, et as TopikAssetRecoveryCategory, f as AssetPayload, ft as TOPIK_PATH_V1_DESCRIPTOR, g as compileAssetResources, gt as SourceResource, h as ContentBearingResource, ht as ResourceType, i as PreviewPayloadDescriptor, it as ASSET_SCHEMA_ID, j as CompiledAsset, k as validateTopikMaterializationRecord, l as AssetCompilationResult, lt as TOPIK_BLOB_OUTPUT_PREFIX, m as CompiledResource, mt as Resource, n as CourseNavigationModule, nt as correlateTopikAssetResult, o as TOPIK_PREVIEW_PROTOCOL, ot as TOPIK_ASSET_LIMITS, p as CompileAssetResourcesInput, pt as TOPIK_PATH_VERSION, q as TOPIK_ASSET_DEFAULT_CORRELATION_ID, r as PreviewDiagnostic, rt as ASSET_API_VERSION, s as AssetCompilationError, st as TOPIK_ASSET_NAME_VERSION, t as CourseNavigationIndex, tt as TopikAssetResult, u as AssetNameGenerator, ut as TOPIK_JSON_VERSION, v as TopikAssetSemanticRecordV1, w as compareTopikAssetIdentities, x as TopikMaterializationRecordV1, y as TopikMaterializationPayloadInput, z as parseAssetBlobUri } from "./preview-
|
|
2
|
+
import { $ as TopikAssetPathDiagnosticReason, A as AssetBlobUri, B as parseGeneratedAssetName, C as TopikMaterializationResourceV1, D as digestTopikAssetSemanticRecord, E as createTopikMaterializationRecord, F as generateAutomaticAssetName, G as validateProjectNamespace, H as topikAssetNameDescriptor, I as isAssetBlobUri, J as TOPIK_ASSET_DIAGNOSTIC_IDS, K as TOPIK_ASSET_CORRELATION_ID_PATTERN, L as isGeneratedAssetName, M as GenerateAutomaticAssetNameOptions, N as GeneratedAssetName, O as digestTopikMaterializationRecord, P as ParsedAsset, Q as TopikAssetDiagnosticLocation, R as parseAsset, S as TopikMaterializationResourceInput, T as createTopikAssetSemanticRecord, U as validateAssetBlobUri, V as serializeAsset, W as validateAssetValue, X as TopikAssetDiagnostic, Y as TopikAssetCorrelationId, Z as TopikAssetDiagnosticId, _ as TopikAssetReferenceMappingV1, a as PreviewState, at as ASSET_TYPE, b as TopikMaterializationPayloadV1, c as AssetCompilationOptions, ct as TOPIK_ASSET_REFERENCE_VERSION, d as AssetNameInput, dt as TOPIK_MATERIALIZATION_VERSION, et as TopikAssetRecoveryCategory, f as AssetPayload, ft as TOPIK_PATH_V1_DESCRIPTOR, g as compileAssetResources, gt as SourceResource, h as ContentBearingResource, ht as ResourceType, i as PreviewPayloadDescriptor, it as ASSET_SCHEMA_ID, j as CompiledAsset, k as validateTopikMaterializationRecord, l as AssetCompilationResult, lt as TOPIK_BLOB_OUTPUT_PREFIX, m as CompiledResource, mt as Resource, n as CourseNavigationModule, nt as correlateTopikAssetResult, o as TOPIK_PREVIEW_PROTOCOL, ot as TOPIK_ASSET_LIMITS, p as CompileAssetResourcesInput, pt as TOPIK_PATH_VERSION, q as TOPIK_ASSET_DEFAULT_CORRELATION_ID, r as PreviewDiagnostic, rt as ASSET_API_VERSION, s as AssetCompilationError, st as TOPIK_ASSET_NAME_VERSION, t as CourseNavigationIndex, tt as TopikAssetResult, u as AssetNameGenerator, ut as TOPIK_JSON_VERSION, v as TopikAssetSemanticRecordV1, w as compareTopikAssetIdentities, x as TopikMaterializationRecordV1, y as TopikMaterializationPayloadInput, z as parseAssetBlobUri } from "./preview-DfACgOEg.mjs";
|
|
3
3
|
import { ExternalWikiDropdown, ExternalWikiTab, InternalWikiDropdown, InternalWikiTab, ResolvedWikiContentLink, ResolvedWikiContentReference, ResolvedWikiNavigation, ResolvedWikiPage, WikiSwitcherNode, findFirstWikiPage, findWikiPageAncestors, hasWikiNavChildren, isExternalWikiDropdown, isExternalWikiTab, isInternalWikiDropdown, isInternalWikiTab, joinWikiPath, resolveWikiContentHref, resolveWikiContentReference, resolveWikiNavigation } from "./wiki-navigation.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { TopikContentDiagnostic, TopikNavigationReference, TopikResourceReference } from "@topik/content";
|
|
@@ -9,11 +9,8 @@ import { CoursePage } from "@topik/schema/course-page/v1";
|
|
|
9
9
|
import { Guide } from "@topik/schema/guide/v1";
|
|
10
10
|
import { Wiki, WikiNavNode } from "@topik/schema/wiki/v1";
|
|
11
11
|
import { WikiPage } from "@topik/schema/wiki-page/v1";
|
|
12
|
-
//#region src/config/source-version.d.ts
|
|
13
12
|
/** The public resource validator owns Person fields, including future schema additions. */
|
|
14
13
|
declare function parseSourcePersons(value: unknown): Person[];
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region src/config/collection.d.ts
|
|
17
14
|
declare const collectionConfigSchema: z.ZodObject<{
|
|
18
15
|
id: z.ZodString;
|
|
19
16
|
title: z.ZodString;
|
|
@@ -28,8 +25,6 @@ type CollectionConfig = Omit<z.infer<typeof collectionConfigSchema>, "persons">
|
|
|
28
25
|
persons?: ReturnType<typeof parseSourcePersons>;
|
|
29
26
|
};
|
|
30
27
|
export declare function parseCollectionConfig(raw: unknown): CollectionConfig;
|
|
31
|
-
//#endregion
|
|
32
|
-
//#region src/config/wiki.d.ts
|
|
33
28
|
type WikiPageNavNode$1 = {
|
|
34
29
|
type: "page";
|
|
35
30
|
slug: string;
|
|
@@ -98,8 +93,6 @@ type WikiConfig = Omit<z.infer<typeof wikiConfigSchema>, "labels"> & {
|
|
|
98
93
|
labels?: Record<string, string>;
|
|
99
94
|
};
|
|
100
95
|
export declare function parseWikiConfig(raw: unknown): WikiConfig;
|
|
101
|
-
//#endregion
|
|
102
|
-
//#region src/config/course.d.ts
|
|
103
96
|
declare const moduleSchema: z.ZodObject<{
|
|
104
97
|
id: z.ZodString;
|
|
105
98
|
title: z.ZodString;
|
|
@@ -136,8 +129,6 @@ type CourseConfig = Omit<z.infer<typeof courseConfigSchema>, "persons"> & {
|
|
|
136
129
|
};
|
|
137
130
|
type CourseModuleConfig = z.infer<typeof moduleSchema>;
|
|
138
131
|
export declare function parseCourseConfig(raw: unknown): CourseConfig;
|
|
139
|
-
//#endregion
|
|
140
|
-
//#region src/config/manifest.d.ts
|
|
141
132
|
export declare const TOPIK_MANIFEST_FILENAME = ".topik.yaml";
|
|
142
133
|
export declare const TOPIK_MANIFEST_LIMITS: {
|
|
143
134
|
readonly maxBytes: 1048576;
|
|
@@ -167,16 +158,12 @@ export declare const topikManifestSchema: z.ZodObject<{
|
|
|
167
158
|
type TopikManifest = z.infer<typeof topikManifestSchema>;
|
|
168
159
|
type TopikManifestSource = z.infer<typeof topikManifestSourceSchema>;
|
|
169
160
|
export declare function parseTopikManifest(raw: unknown): TopikManifest;
|
|
170
|
-
//#endregion
|
|
171
|
-
//#region src/config/assets.d.ts
|
|
172
161
|
export declare const DEFAULT_ASSET_DIRECTORY = "_assets";
|
|
173
162
|
/** Source-local destination for new synced media; not an input scan or compiler output path. */
|
|
174
163
|
export declare const sourceAssetsConfigSchema: z.ZodObject<{
|
|
175
164
|
directory: z.ZodDefault<z.ZodString>;
|
|
176
165
|
}, z.core.$strict>;
|
|
177
166
|
type SourceAssetsConfig = z.infer<typeof sourceAssetsConfigSchema>;
|
|
178
|
-
//#endregion
|
|
179
|
-
//#region src/compile/public-errors.d.ts
|
|
180
167
|
declare const PUBLIC_COMPILE_ERROR_MESSAGES: {
|
|
181
168
|
readonly "manifest-required": 'Project compilation requires .topik.yaml in the selected directory. Add a manifest such as: {"version":1,"namespace":"owner/project","sources":[{"kind":"wiki","config":"wiki.yaml"}]}';
|
|
182
169
|
readonly "manifest-invalid": "Root manifest is invalid.";
|
|
@@ -207,8 +194,6 @@ export declare class PublicCompileError extends Error {
|
|
|
207
194
|
readonly location?: string;
|
|
208
195
|
constructor(id: PublicCompileErrorId, location?: string);
|
|
209
196
|
}
|
|
210
|
-
//#endregion
|
|
211
|
-
//#region src/compile/manifest.d.ts
|
|
212
197
|
interface ManifestSourceDescriptor extends TopikManifestSource {
|
|
213
198
|
/** Zero-based declaration index, used only for provenance and diagnostics. */
|
|
214
199
|
sourceIndex: number;
|
|
@@ -236,8 +221,6 @@ export declare function loadTopikManifest(dir: string): Promise<TopikManifest>;
|
|
|
236
221
|
export declare function discoverManifestSources(options: CompileOptions): Promise<ManifestSourceDescriptor[]>;
|
|
237
222
|
/** Compile only declared sources, sharing the existing local compiler and Asset pipeline. */
|
|
238
223
|
export declare function compileManifest(options: CompileOptions): Promise<ManifestCompileResult>;
|
|
239
|
-
//#endregion
|
|
240
|
-
//#region src/compile/shared.d.ts
|
|
241
224
|
interface CompileResult {
|
|
242
225
|
courseNavigation: CourseNavigationIndex;
|
|
243
226
|
/** Present for manifest compilation, in declaration order. */
|
|
@@ -260,8 +243,6 @@ export declare class CompileError extends Error {
|
|
|
260
243
|
constructor(diagnostics: TopikContentDiagnostic[]);
|
|
261
244
|
}
|
|
262
245
|
export declare function isErrorDiagnostic(diagnostic: TopikContentDiagnostic): boolean;
|
|
263
|
-
//#endregion
|
|
264
|
-
//#region src/compile/links.d.ts
|
|
265
246
|
/** Optional application-provided catalogue; Topik never fetches targets. */
|
|
266
247
|
interface CompileResourceReferenceTarget {
|
|
267
248
|
type: TopikResourceReference["type"];
|
|
@@ -295,8 +276,6 @@ export declare function compileResourceLinks(input: CompileResourceLinksInput):
|
|
|
295
276
|
diagnostics: TopikContentDiagnostic[];
|
|
296
277
|
references: CompiledResourceReference[];
|
|
297
278
|
}>;
|
|
298
|
-
//#endregion
|
|
299
|
-
//#region src/compile/guide.d.ts
|
|
300
279
|
interface CompileGuidesOptions {
|
|
301
280
|
dir: string;
|
|
302
281
|
/** Exact config path relative to dir; content is relative to the config directory. */
|
|
@@ -316,8 +295,6 @@ interface CompileResourceDiscovery {
|
|
|
316
295
|
consumedSourcePaths: string[];
|
|
317
296
|
}
|
|
318
297
|
export declare function compileGuides(options: CompileGuidesOptions): Promise<CompileResult>;
|
|
319
|
-
//#endregion
|
|
320
|
-
//#region src/compile/discovery.d.ts
|
|
321
298
|
interface DiscoverResourceOptions {
|
|
322
299
|
dir: string;
|
|
323
300
|
/** Exact config path relative to dir; content is relative to its directory. */
|
|
@@ -330,8 +307,6 @@ export declare function discoverGuideResources(options: DiscoverResourceOptions)
|
|
|
330
307
|
export declare function discoverWikiResources(options: DiscoverResourceOptions): Promise<SourceResourceDiscovery>;
|
|
331
308
|
/** Read Course membership, metadata and paths without compiling links or Assets. */
|
|
332
309
|
export declare function discoverCourseResources(options: DiscoverResourceOptions): Promise<SourceResourceDiscovery>;
|
|
333
|
-
//#endregion
|
|
334
|
-
//#region src/compile/wiki.d.ts
|
|
335
310
|
interface CompileWikiOptions {
|
|
336
311
|
dir: string;
|
|
337
312
|
/** Exact config path relative to dir; content is relative to the config directory. */
|
|
@@ -342,8 +317,6 @@ interface CompileWikiOptions {
|
|
|
342
317
|
}
|
|
343
318
|
export declare function compileWiki(options: CompileWikiOptions): Promise<CompileResult>;
|
|
344
319
|
export declare function pagePathToName(wikiId: string, pagePath: string): string;
|
|
345
|
-
//#endregion
|
|
346
|
-
//#region src/compile/course.d.ts
|
|
347
320
|
interface CompileCourseOptions {
|
|
348
321
|
dir: string;
|
|
349
322
|
/** Exact configuration path relative to dir; page sources are relative to its directory. */
|
|
@@ -353,8 +326,6 @@ interface CompileCourseOptions {
|
|
|
353
326
|
referenceTargets?: readonly CompileResourceReferenceTarget[];
|
|
354
327
|
}
|
|
355
328
|
export declare function compileCourse(options: CompileCourseOptions): Promise<CompileResult>;
|
|
356
|
-
//#endregion
|
|
357
|
-
//#region src/compile/asset-names.d.ts
|
|
358
329
|
interface ProjectAssetNameOptions {
|
|
359
330
|
/** Directory containing the manifest, or an explicitly chosen root for standalone use. */
|
|
360
331
|
projectRoot: string;
|
|
@@ -362,8 +333,6 @@ interface ProjectAssetNameOptions {
|
|
|
362
333
|
}
|
|
363
334
|
/** Create the project's naming policy without reading or requiring a manifest. */
|
|
364
335
|
export declare function createProjectAssetNameGenerator(options: ProjectAssetNameOptions): AssetNameGenerator;
|
|
365
|
-
//#endregion
|
|
366
|
-
//#region src/compile/index.d.ts
|
|
367
336
|
interface CompileOptions {
|
|
368
337
|
dir: string;
|
|
369
338
|
validation?: CompileValidationOptions;
|
|
@@ -376,8 +345,6 @@ interface LintResult {
|
|
|
376
345
|
diagnostics: CompileResult["diagnostics"];
|
|
377
346
|
}
|
|
378
347
|
export declare function lint(options: CompileOptions): Promise<LintResult>;
|
|
379
|
-
//#endregion
|
|
380
|
-
//#region src/validate.d.ts
|
|
381
348
|
interface ValidationError {
|
|
382
349
|
id?: "resource-invalid" | "resource-unsupported-type" | "resource-unsupported-version" | TopikAssetDiagnosticId;
|
|
383
350
|
resource: string;
|
|
@@ -390,8 +357,6 @@ interface ValidationResult {
|
|
|
390
357
|
}
|
|
391
358
|
/** Validate the resources produced by `compile` and the CLI export. */
|
|
392
359
|
export declare function validateResources(resources: readonly unknown[]): ValidationResult;
|
|
393
|
-
//#endregion
|
|
394
|
-
//#region src/watch.d.ts
|
|
395
360
|
interface WatchOptions {
|
|
396
361
|
dir: string;
|
|
397
362
|
signal?: AbortSignal;
|
|
@@ -414,8 +379,6 @@ interface Watcher {
|
|
|
414
379
|
close(): Promise<void>;
|
|
415
380
|
}
|
|
416
381
|
export declare function watch(options: WatchOptions): Promise<Watcher>;
|
|
417
|
-
//#endregion
|
|
418
|
-
//#region src/assets/path.d.ts
|
|
419
382
|
interface ValidateTopikPathOptions {
|
|
420
383
|
bindingRoot?: string;
|
|
421
384
|
capabilities?: {
|
|
@@ -434,8 +397,6 @@ export declare function computeTopikPathCollisionKey(path: string, options?: Val
|
|
|
434
397
|
export declare function validateTopikPathSet(paths: readonly string[], options?: ValidateTopikPathOptions): TopikAssetResult<Map<string, string>>;
|
|
435
398
|
/** Unicode 17 NFKC casefold for topik-path-v1-admitted input. */
|
|
436
399
|
export declare function toNfkcCasefold(value: string): string;
|
|
437
|
-
//#endregion
|
|
438
|
-
//#region src/assets/json.d.ts
|
|
439
400
|
export declare class TopikJsonSyntaxError extends SyntaxError {
|
|
440
401
|
readonly offset: number;
|
|
441
402
|
readonly duplicatePointer?: string | undefined;
|
|
@@ -447,8 +408,6 @@ export declare function serializeTopikJson(value: unknown): string;
|
|
|
447
408
|
export declare function topikJsonDescriptor(): {
|
|
448
409
|
id: typeof TOPIK_JSON_VERSION;
|
|
449
410
|
};
|
|
450
|
-
//#endregion
|
|
451
|
-
//#region src/assets/files.d.ts
|
|
452
411
|
type PortableAssetFileType = "regular" | "symlink" | "hardlink" | "gitlink" | "device" | "fifo" | "socket" | "special" | "sparse" | "archive-link";
|
|
453
412
|
interface PortableAssetFileDescriptor {
|
|
454
413
|
path: string;
|
|
@@ -473,15 +432,11 @@ interface ReadPortableAssetFileOptions {
|
|
|
473
432
|
/** Filesystem reader using no-follow traversal and stable same-handle identity checks. */
|
|
474
433
|
export declare function readPortableAssetFile(options: ReadPortableAssetFileOptions): Promise<TopikAssetResult<PortableAssetFileDescriptor>>;
|
|
475
434
|
export declare function looksLikeGitLfsPointer(bytes: Uint8Array): boolean;
|
|
476
|
-
//#endregion
|
|
477
|
-
//#region src/assets/media.d.ts
|
|
478
435
|
export declare const TOPIK_UNRESOLVED_ACTIVE_CONTENT_TYPE: "application/x-topik-active-content";
|
|
479
436
|
/** Sniff exact bytes conservatively. Unknown safe bytes remain opaque downloads. */
|
|
480
437
|
export declare function sniffPortableMediaType(bytes: Uint8Array): string;
|
|
481
438
|
export declare function isTopikActiveMediaType(mediaType: string): boolean;
|
|
482
439
|
export declare function isInlineMediaCompatible(mediaType: string, role: string): boolean;
|
|
483
|
-
//#endregion
|
|
484
|
-
//#region src/source/syntax.d.ts
|
|
485
440
|
interface SourceByteRange {
|
|
486
441
|
start: number;
|
|
487
442
|
end: number;
|
|
@@ -497,8 +452,6 @@ interface SourceByteEdit extends SourceByteRange {
|
|
|
497
452
|
oldSha256: string;
|
|
498
453
|
replacement: Uint8Array;
|
|
499
454
|
}
|
|
500
|
-
//#endregion
|
|
501
|
-
//#region src/source/project.d.ts
|
|
502
455
|
export declare const SOURCE_WRITER_VERSION: "topik-source-writer-v1";
|
|
503
456
|
export declare const SOURCE_PROJECT_LIMITS: {
|
|
504
457
|
readonly maxFiles: 10000;
|
|
@@ -590,11 +543,7 @@ export declare function digestSourceResourceGraph(resources: readonly Resource[]
|
|
|
590
543
|
export declare function readSourceProject(input: {
|
|
591
544
|
tree: readonly SourceTreeFile[];
|
|
592
545
|
}): Promise<SourceProject>;
|
|
593
|
-
//#endregion
|
|
594
|
-
//#region src/source/asset-context.d.ts
|
|
595
546
|
type SourceAssetReferenceContexts = Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
596
|
-
//#endregion
|
|
597
|
-
//#region src/source/initialize.d.ts
|
|
598
547
|
interface SourceInitializationIntent {
|
|
599
548
|
namespace: string;
|
|
600
549
|
source: TopikManifestSource & {
|
|
@@ -645,8 +594,6 @@ interface AddSourceToProjectInput {
|
|
|
645
594
|
}
|
|
646
595
|
/** Adding a declaration preserves the existing namespace, order and every original source. */
|
|
647
596
|
export declare function addSourceToProject(input: AddSourceToProjectInput): Promise<SourcePlanResult>;
|
|
648
|
-
//#endregion
|
|
649
|
-
//#region src/source/diagnostics.d.ts
|
|
650
597
|
interface SourcePlanDiagnostic {
|
|
651
598
|
code: string;
|
|
652
599
|
message: string;
|
|
@@ -658,8 +605,6 @@ interface SourcePlanDiagnostic {
|
|
|
658
605
|
kind?: "wiki" | "collection" | "course";
|
|
659
606
|
config?: string;
|
|
660
607
|
}
|
|
661
|
-
//#endregion
|
|
662
|
-
//#region src/source/plan.d.ts
|
|
663
608
|
type SourceResourceOperation = {
|
|
664
609
|
kind: "update" | "delete";
|
|
665
610
|
resource: string;
|
|
@@ -754,5 +699,4 @@ interface PlanSourceUpdatesInput {
|
|
|
754
699
|
}
|
|
755
700
|
/** The complete candidate is compiled before any applicable file changes are returned. */
|
|
756
701
|
export declare function planSourceUpdates(input: PlanSourceUpdatesInput): Promise<SourcePlanResult>;
|
|
757
|
-
//#endregion
|
|
758
702
|
export { ASSET_API_VERSION, ASSET_SCHEMA_ID, ASSET_TYPE, type AddSourceToProjectInput, type AssetBlobUri, AssetCompilationError, type AssetCompilationOptions, type AssetCompilationResult, type AssetNameGenerator, type AssetNameInput, type AssetPayload, type CollectionConfig, type CompileAssetResourcesInput, type CompileCourseOptions, type CompileGuidesOptions, type CompileOptions, type CompileResourceLinksInput, type CompileResourceReferenceTarget, type CompileResult, type CompileValidationOptions, type CompileWikiOptions, type CompiledAsset, type CompiledResource, type CompiledResourceReference, type ContentBearingResource, type CourseConfig, type CourseModuleConfig, CourseNavigationIndex, CourseNavigationModule, type CourseReferenceContext, type DiscoverResourceOptions, type ExternalWikiDropdown, type ExternalWikiTab, type GenerateAutomaticAssetNameOptions, type GeneratedAssetName, type InitializeSourceProjectInput, type InternalWikiDropdown, type InternalWikiTab, type LinkValidationPolicy, type LintResult, type ManifestCompileResult, type ManifestSourceDescriptor, type ManifestSourceProvenance, type ParsedAsset, type PlanSourceUpdatesInput, type PortableAssetFileDescriptor, type PortableAssetFileType, PreviewDiagnostic, PreviewPayloadDescriptor, PreviewState, type ProjectAssetNameOptions, type PublicCompileErrorId, type ReadPortableAssetFileOptions, type ResolvedCourseContentLink, type ResolvedCourseContentReference, type ResolvedCourseNavigation, type ResolvedCoursePage, type ResolvedWikiContentLink, type ResolvedWikiContentReference, type ResolvedWikiNavigation, type ResolvedWikiPage, type Resource, type ResourceType, type SourceAssetsConfig, type SourceByteEdit, type SourceByteRange, type SourceConfigurationProvenance, type SourceDocumentProvenance, type SourceExclusiveAuthority, type SourceFieldEvidence, type SourceFieldOrigin, type SourceFileChange, type SourceInitializationIntent, type SourceMediaSelection, type SourcePlanDiagnostic, type SourcePlanResult, type SourceProject, type SourceResource, type SourceResourceDiscovery, type SourceResourceOperation, type SourceSharedAuthority, type SourceTreeFile, type SourceUpdatePlan, type SourceWriteAuthority, TOPIK_ASSET_CORRELATION_ID_PATTERN, TOPIK_ASSET_DEFAULT_CORRELATION_ID, TOPIK_ASSET_DIAGNOSTIC_IDS, TOPIK_ASSET_LIMITS, TOPIK_ASSET_NAME_VERSION, TOPIK_ASSET_REFERENCE_VERSION, TOPIK_BLOB_OUTPUT_PREFIX, TOPIK_JSON_VERSION, TOPIK_MATERIALIZATION_VERSION, TOPIK_PATH_V1_DESCRIPTOR, TOPIK_PATH_VERSION, TOPIK_PREVIEW_PROTOCOL, type TopikAssetCorrelationId, type TopikAssetDiagnostic, type TopikAssetDiagnosticId, type TopikAssetDiagnosticLocation, type TopikAssetPathDiagnosticReason, type TopikAssetRecoveryCategory, type TopikAssetReferenceMappingV1, type TopikAssetResult, type TopikAssetSemanticRecordV1, type TopikManifest, type TopikManifestSource, type TopikMaterializationPayloadInput, type TopikMaterializationPayloadV1, type TopikMaterializationRecordV1, type TopikMaterializationResourceInput, type TopikMaterializationResourceV1, type ValidTopikPath, type ValidateTopikPathOptions, type ValidationError, type ValidationResult, type WatchOptions, type Watcher, type WikiConfig, type WikiSwitcherNode, compareTopikAssetIdentities, compileAssetResources, correlateTopikAssetResult, createTopikAssetSemanticRecord, createTopikMaterializationRecord, digestTopikAssetSemanticRecord, digestTopikMaterializationRecord, findFirstWikiPage, findWikiPageAncestors, generateAutomaticAssetName, hasWikiNavChildren, isAssetBlobUri, isExternalWikiDropdown, isExternalWikiTab, isGeneratedAssetName, isInternalWikiDropdown, isInternalWikiTab, joinWikiPath, parseAsset, parseAssetBlobUri, parseGeneratedAssetName, resolveCourseContentHref, resolveCourseContentReference, resolveCourseNavigation, resolveWikiContentHref, resolveWikiContentReference, resolveWikiNavigation, serializeAsset, topikAssetNameDescriptor, validateAssetBlobUri, validateAssetValue, validateProjectNamespace, validateTopikMaterializationRecord };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as TOPIK_JSON_VERSION, E as TOPIK_PATH_VERSION, S as TOPIK_BLOB_OUTPUT_PREFIX, T as TOPIK_PATH_V1_DESCRIPTOR, _ as ASSET_SCHEMA_ID, a as computeTopikPathCollisionKey, b as TOPIK_ASSET_NAME_VERSION, c as validateTopikPathSet, d as TOPIK_ASSET_DIAGNOSTIC_IDS, f as correlateTopikAssetResult, g as ASSET_API_VERSION, h as isTopikPathNormalizationSensitiveV17, i as validateCoursePageSources, l as TOPIK_ASSET_CORRELATION_ID_PATTERN, m as isTopikPathCodePointForbiddenV17, n as resolveCourseContentReference, o as toNfkcCasefold, p as topikAssetDiagnostic, r as resolveCourseNavigation, s as validateTopikPath, t as resolveCourseContentHref, u as TOPIK_ASSET_DEFAULT_CORRELATION_ID, v as ASSET_TYPE, w as TOPIK_MATERIALIZATION_VERSION, x as TOPIK_ASSET_REFERENCE_VERSION, y as TOPIK_ASSET_LIMITS } from "./course-navigation-
|
|
2
|
-
import { i as resolveDeclaredPublicRoute, o as resolveNavigationPath, r as isFolderHref, t as folderLandingCandidates } from "./folder-links-
|
|
1
|
+
import { C as TOPIK_JSON_VERSION, E as TOPIK_PATH_VERSION, S as TOPIK_BLOB_OUTPUT_PREFIX, T as TOPIK_PATH_V1_DESCRIPTOR, _ as ASSET_SCHEMA_ID, a as computeTopikPathCollisionKey, b as TOPIK_ASSET_NAME_VERSION, c as validateTopikPathSet, d as TOPIK_ASSET_DIAGNOSTIC_IDS, f as correlateTopikAssetResult, g as ASSET_API_VERSION, h as isTopikPathNormalizationSensitiveV17, i as validateCoursePageSources, l as TOPIK_ASSET_CORRELATION_ID_PATTERN, m as isTopikPathCodePointForbiddenV17, n as resolveCourseContentReference, o as toNfkcCasefold, p as topikAssetDiagnostic, r as resolveCourseNavigation, s as validateTopikPath, t as resolveCourseContentHref, u as TOPIK_ASSET_DEFAULT_CORRELATION_ID, v as ASSET_TYPE, w as TOPIK_MATERIALIZATION_VERSION, x as TOPIK_ASSET_REFERENCE_VERSION, y as TOPIK_ASSET_LIMITS } from "./course-navigation-h54ccuqO.mjs";
|
|
2
|
+
import { i as resolveDeclaredPublicRoute, o as resolveNavigationPath, r as isFolderHref, t as folderLandingCandidates } from "./folder-links-jLZaG6xi.mjs";
|
|
3
3
|
import { findFirstWikiPage, findWikiPageAncestors, hasWikiNavChildren, isExternalWikiDropdown, isExternalWikiTab, isInternalWikiDropdown, isInternalWikiTab, joinWikiPath, resolveWikiContentHref, resolveWikiContentReference, resolveWikiNavigation } from "./wiki-navigation.mjs";
|
|
4
4
|
import { TOPIK_PREVIEW_PROTOCOL } from "./preview.mjs";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -24,12 +24,11 @@ import { isAlias, isMap, isNode, isScalar, isSeq, parse as parse$1, parseDocumen
|
|
|
24
24
|
import { EventEmitter } from "node:events";
|
|
25
25
|
import { watch as watch$1 } from "chokidar";
|
|
26
26
|
import { tmpdir } from "node:os";
|
|
27
|
-
|
|
27
|
+
// src/config/assets.ts
|
|
28
28
|
const DEFAULT_ASSET_DIRECTORY = "_assets";
|
|
29
29
|
/** Source-local destination for new synced media; not an input scan or compiler output path. */
|
|
30
30
|
const sourceAssetsConfigSchema = z.strictObject({ directory: z.string().refine((directory) => validateTopikPath(directory).ok, "Expected a portable relative directory").default(DEFAULT_ASSET_DIRECTORY) });
|
|
31
|
-
|
|
32
|
-
//#region src/assets/json.ts
|
|
31
|
+
// src/assets/json.ts
|
|
33
32
|
var TopikJsonSyntaxError = class extends SyntaxError {
|
|
34
33
|
offset;
|
|
35
34
|
duplicatePointer;
|
|
@@ -253,8 +252,7 @@ function escapePointer(value) {
|
|
|
253
252
|
function isJsonWhitespace(code) {
|
|
254
253
|
return code === 9 || code === 10 || code === 13 || code === 32;
|
|
255
254
|
}
|
|
256
|
-
|
|
257
|
-
//#region src/assets/asset.ts
|
|
255
|
+
// src/assets/asset.ts
|
|
258
256
|
const encoder = new TextEncoder();
|
|
259
257
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
260
258
|
const ASSET_BLOB_URI_VALIDATOR = /^blobs\/[0-9a-f]{64}$/u;
|
|
@@ -472,8 +470,7 @@ function base32(bytes) {
|
|
|
472
470
|
if (bits > 0) result += alphabet[accumulator << 5 - bits & 31];
|
|
473
471
|
return result;
|
|
474
472
|
}
|
|
475
|
-
|
|
476
|
-
//#region src/validate.ts
|
|
473
|
+
// src/validate.ts
|
|
477
474
|
const ajv = new Ajv2020({
|
|
478
475
|
strict: true,
|
|
479
476
|
discriminator: true,
|
|
@@ -571,8 +568,7 @@ function validateResources(resources) {
|
|
|
571
568
|
errors
|
|
572
569
|
};
|
|
573
570
|
}
|
|
574
|
-
|
|
575
|
-
//#region src/config/source-version.ts
|
|
571
|
+
// src/config/source-version.ts
|
|
576
572
|
const sourceVersionSchema = z.literal(1).optional();
|
|
577
573
|
const sourceLabelsSchema = z.record(z.string(), z.string());
|
|
578
574
|
const name$1 = z.string().min(1).max(63).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
|
|
@@ -616,8 +612,7 @@ function parseSourcePersons(value) {
|
|
|
616
612
|
if (new Set(persons.map((person) => person.name)).size !== persons.length || !validateResources(persons).valid) throw new TypeError("Invalid or duplicate Person resource");
|
|
617
613
|
return persons;
|
|
618
614
|
}
|
|
619
|
-
|
|
620
|
-
//#region src/config/collection.ts
|
|
615
|
+
// src/config/collection.ts
|
|
621
616
|
const collectionConfigSchema = z.object({
|
|
622
617
|
id: z.string().min(1).max(63).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
|
|
623
618
|
title: z.string().min(1).max(256),
|
|
@@ -633,8 +628,7 @@ function parseCollectionConfig(raw) {
|
|
|
633
628
|
...config.sourceVersion === 1 && persons !== void 0 ? { persons: parseSourcePersons(persons) } : {}
|
|
634
629
|
};
|
|
635
630
|
}
|
|
636
|
-
|
|
637
|
-
//#region src/config/wiki.ts
|
|
631
|
+
// src/config/wiki.ts
|
|
638
632
|
const wikiNavIconPattern = new RegExp(wikiV1Schema.$defs.groupNode.properties.icon.pattern);
|
|
639
633
|
const wikiExternalHrefPattern = new RegExp(wikiV1Schema.$defs.externalTabNode.properties.href.pattern);
|
|
640
634
|
const pathSegment = z.string().min(1).max(256).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Slugs must be lowercase DNS-style segments");
|
|
@@ -812,8 +806,7 @@ function parseWikiConfig(raw) {
|
|
|
812
806
|
...config.sourceVersion === 1 && labels !== void 0 ? { labels: sourceLabelsSchema.parse(labels) } : {}
|
|
813
807
|
};
|
|
814
808
|
}
|
|
815
|
-
|
|
816
|
-
//#region src/config/course.ts
|
|
809
|
+
// src/config/course.ts
|
|
817
810
|
const name = z.string().min(1).max(63).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
|
|
818
811
|
const slug = z.string().min(1).max(256).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
|
|
819
812
|
const title = z.string().min(1).max(256);
|
|
@@ -865,8 +858,7 @@ function parseCourseConfig(raw) {
|
|
|
865
858
|
function parseCoursePageMetadata(raw) {
|
|
866
859
|
return coursePageMetadataSchema.parse(raw);
|
|
867
860
|
}
|
|
868
|
-
|
|
869
|
-
//#region src/config/manifest.ts
|
|
861
|
+
// src/config/manifest.ts
|
|
870
862
|
const TOPIK_MANIFEST_FILENAME = ".topik.yaml";
|
|
871
863
|
const TOPIK_MANIFEST_LIMITS = {
|
|
872
864
|
maxBytes: 1048576,
|
|
@@ -933,8 +925,7 @@ function findConfigurationPathConflict(paths) {
|
|
|
933
925
|
}
|
|
934
926
|
}
|
|
935
927
|
}
|
|
936
|
-
|
|
937
|
-
//#region src/assets/files.ts
|
|
928
|
+
// src/assets/files.ts
|
|
938
929
|
const execFileAsync = promisify(execFile);
|
|
939
930
|
function validatePortableAssetFile(file) {
|
|
940
931
|
const diagnostics = [];
|
|
@@ -1124,7 +1115,7 @@ async function readPortableAssetFileAnchored(options, afterDirectoryOpened, afte
|
|
|
1124
1115
|
const bytes = buffer.subarray(0, length);
|
|
1125
1116
|
await afterFileRead?.();
|
|
1126
1117
|
const after = await fileHandle.stat({ bigint: true });
|
|
1127
|
-
if (before
|
|
1118
|
+
if (!hasStableFileIdentity(before, after)) return {
|
|
1128
1119
|
ok: false,
|
|
1129
1120
|
diagnostics: [unsupportedPath(options.path, "File identity changed while hashing")]
|
|
1130
1121
|
};
|
|
@@ -1248,7 +1239,7 @@ async function anchoredGitBoundaryFingerprint(directory) {
|
|
|
1248
1239
|
failure: "Git boundary is not a regular file or directory"
|
|
1249
1240
|
};
|
|
1250
1241
|
const after = await handle.stat({ bigint: true });
|
|
1251
|
-
if (before
|
|
1242
|
+
if (!hasStableFileIdentity(before, after)) return {
|
|
1252
1243
|
ok: false,
|
|
1253
1244
|
failure: "Git boundary identity changed while it was inspected"
|
|
1254
1245
|
};
|
|
@@ -1374,8 +1365,7 @@ async function applyGitAttributes(directory, relativePath, state) {
|
|
|
1374
1365
|
const before = await handle.stat({ bigint: true });
|
|
1375
1366
|
if (!before.isFile() || before.nlink !== 1n) return "Git attribute evidence is not a stable regular file";
|
|
1376
1367
|
const bytes = await handle.readFile();
|
|
1377
|
-
|
|
1378
|
-
if (before.dev !== after.dev || before.ino !== after.ino || before.mode !== after.mode || before.nlink !== after.nlink || before.size !== after.size || before.ctimeNs !== after.ctimeNs || before.mtimeNs !== after.mtimeNs) return "Git attribute evidence changed while it was evaluated";
|
|
1368
|
+
if (!hasStableFileIdentity(before, await handle.stat({ bigint: true }))) return "Git attribute evidence changed while it was evaluated";
|
|
1379
1369
|
let source;
|
|
1380
1370
|
try {
|
|
1381
1371
|
source = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
@@ -1456,8 +1446,11 @@ function unsupportedPath(path, message) {
|
|
|
1456
1446
|
recovery: "preserve-read-only"
|
|
1457
1447
|
});
|
|
1458
1448
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1449
|
+
/** Keep the mutation evidence identical for bytes, Git boundaries, and Git attributes. */
|
|
1450
|
+
function hasStableFileIdentity(before, after) {
|
|
1451
|
+
return before.dev === after.dev && before.ino === after.ino && before.mode === after.mode && before.nlink === after.nlink && before.size === after.size && before.ctimeNs === after.ctimeNs && before.mtimeNs === after.mtimeNs;
|
|
1452
|
+
}
|
|
1453
|
+
// src/assets/identity.ts
|
|
1461
1454
|
function createTopikAssetSemanticRecord(assets, references) {
|
|
1462
1455
|
return {
|
|
1463
1456
|
descriptor: "topik-asset-semantic-v1",
|
|
@@ -1669,8 +1662,7 @@ function sha256$1(bytes) {
|
|
|
1669
1662
|
function compareUtf8$1(left, right) {
|
|
1670
1663
|
return Buffer.compare(Buffer.from(left), Buffer.from(right));
|
|
1671
1664
|
}
|
|
1672
|
-
|
|
1673
|
-
//#region src/assets/media.ts
|
|
1665
|
+
// src/assets/media.ts
|
|
1674
1666
|
const MARKUP_INSPECTION_LIMIT = 65536;
|
|
1675
1667
|
const TOPIK_UNRESOLVED_ACTIVE_CONTENT_TYPE = "application/x-topik-active-content";
|
|
1676
1668
|
/** Sniff exact bytes conservatively. Unknown safe bytes remain opaque downloads. */
|
|
@@ -1774,8 +1766,7 @@ function skipMarkupWhitespace(value, start) {
|
|
|
1774
1766
|
function ascii(bytes, start, length) {
|
|
1775
1767
|
return String.fromCharCode(...bytes.slice(start, start + length));
|
|
1776
1768
|
}
|
|
1777
|
-
|
|
1778
|
-
//#region src/compile/assets.ts
|
|
1769
|
+
// src/compile/assets.ts
|
|
1779
1770
|
var AssetCompilationError = class extends Error {
|
|
1780
1771
|
diagnostics;
|
|
1781
1772
|
constructor(message, diagnostics = []) {
|
|
@@ -2128,8 +2119,7 @@ function compareResources(left, right) {
|
|
|
2128
2119
|
function compareUtf8(left, right) {
|
|
2129
2120
|
return Buffer.compare(Buffer.from(left), Buffer.from(right));
|
|
2130
2121
|
}
|
|
2131
|
-
|
|
2132
|
-
//#region src/compile/asset-names.ts
|
|
2122
|
+
// src/compile/asset-names.ts
|
|
2133
2123
|
/** Create the project's naming policy without reading or requiring a manifest. */
|
|
2134
2124
|
function createProjectAssetNameGenerator(options) {
|
|
2135
2125
|
const root = resolve(options.projectRoot);
|
|
@@ -2146,8 +2136,7 @@ function createProjectAssetNameGenerator(options) {
|
|
|
2146
2136
|
return generated.value;
|
|
2147
2137
|
};
|
|
2148
2138
|
}
|
|
2149
|
-
|
|
2150
|
-
//#region src/compile/public-errors.ts
|
|
2139
|
+
// src/compile/public-errors.ts
|
|
2151
2140
|
const PUBLIC_COMPILE_ERROR_MESSAGES = {
|
|
2152
2141
|
"manifest-required": "Project compilation requires .topik.yaml in the selected directory. Add a manifest such as: {\"version\":1,\"namespace\":\"owner/project\",\"sources\":[{\"kind\":\"wiki\",\"config\":\"wiki.yaml\"}]}",
|
|
2153
2142
|
"manifest-invalid": "Root manifest is invalid.",
|
|
@@ -2196,8 +2185,7 @@ function containsForbiddenCodePoint(value) {
|
|
|
2196
2185
|
for (const character of value) if (isTopikPathCodePointForbiddenV17(character.codePointAt(0) ?? 0)) return true;
|
|
2197
2186
|
return false;
|
|
2198
2187
|
}
|
|
2199
|
-
|
|
2200
|
-
//#region src/compile/files.ts
|
|
2188
|
+
// src/compile/files.ts
|
|
2201
2189
|
const LINUX_O_PATH = 2097152;
|
|
2202
2190
|
const SAFE_READ_FLAGS = constants.O_RDONLY | (typeof constants.O_NOFOLLOW === "number" ? constants.O_NOFOLLOW : 0) | (typeof constants.O_NONBLOCK === "number" ? constants.O_NONBLOCK : 0);
|
|
2203
2191
|
var FileOutsideCompilationRootError = class extends PublicCompileError {
|
|
@@ -2287,8 +2275,7 @@ function safeRelativePath(filePath, rootDir) {
|
|
|
2287
2275
|
const location = relative(resolve(rootDir), resolve(filePath)).split(sep).join("/");
|
|
2288
2276
|
return location.length > 0 && !location.startsWith("../") && location !== ".." ? location : void 0;
|
|
2289
2277
|
}
|
|
2290
|
-
|
|
2291
|
-
//#region src/compile/config.ts
|
|
2278
|
+
// src/compile/config.ts
|
|
2292
2279
|
async function readOptionalConfigFileWithPath(dir, candidates) {
|
|
2293
2280
|
for (const name of candidates) {
|
|
2294
2281
|
const filePath = join(dir, name);
|
|
@@ -2382,8 +2369,7 @@ function parseSafeConfigurationYaml(raw) {
|
|
|
2382
2369
|
}
|
|
2383
2370
|
return document.toJS({ maxAliasCount: 0 });
|
|
2384
2371
|
}
|
|
2385
|
-
|
|
2386
|
-
//#region src/compile/frontmatter.ts
|
|
2372
|
+
// src/compile/frontmatter.ts
|
|
2387
2373
|
/** Find the same Markdown header boundary for compilation and source byte inspection. */
|
|
2388
2374
|
function markdownFrontmatter(raw) {
|
|
2389
2375
|
const match = raw.match(/^\uFEFF?---[ \t]*\r?\n(?:---[ \t]*(?:\r?\n|$)|([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$))/);
|
|
@@ -2398,8 +2384,7 @@ function markdownFrontmatter(raw) {
|
|
|
2398
2384
|
bodyStart: match[0].length
|
|
2399
2385
|
};
|
|
2400
2386
|
}
|
|
2401
|
-
|
|
2402
|
-
//#region src/compile/shared.ts
|
|
2387
|
+
// src/compile/shared.ts
|
|
2403
2388
|
var CompileError = class extends Error {
|
|
2404
2389
|
diagnostics;
|
|
2405
2390
|
constructor(diagnostics) {
|
|
@@ -2463,8 +2448,7 @@ function parseReferenceList(value, _fieldName, filePath) {
|
|
|
2463
2448
|
});
|
|
2464
2449
|
return references.length > 0 ? references : void 0;
|
|
2465
2450
|
}
|
|
2466
|
-
|
|
2467
|
-
//#region src/reference-paths.ts
|
|
2451
|
+
// src/reference-paths.ts
|
|
2468
2452
|
/** Physical source paths also satisfy the portable filesystem contract. */
|
|
2469
2453
|
function resolveSourceReferencePath(href, sourcePath, directory) {
|
|
2470
2454
|
const path = resolveNavigationPath(href, sourcePath, directory);
|
|
@@ -2505,8 +2489,7 @@ function sourceNonMarkdownLinkPath(reference, sourcePath, directory) {
|
|
|
2505
2489
|
const path = resolveSourceReferencePath(reference.href, sourcePath, directory);
|
|
2506
2490
|
return path !== void 0 && !/\.(?:mdx?|markdown)$/i.test(path) ? path : void 0;
|
|
2507
2491
|
}
|
|
2508
|
-
|
|
2509
|
-
//#region src/compile/links.ts
|
|
2492
|
+
// src/compile/links.ts
|
|
2510
2493
|
/** Resolve document identity after all declared sources have been discovered, before Assets. */
|
|
2511
2494
|
async function compileResourceLinks(input) {
|
|
2512
2495
|
const policy = linkValidationPolicy(input.validation);
|
|
@@ -2652,10 +2635,10 @@ async function compileResourceLinks(input) {
|
|
|
2652
2635
|
const candidates = path === void 0 || link.href.startsWith("/") && !markdown ? void 0 : markdown ? targetsByPath.get(path) : extensionless ? targetsByExtensionlessPath.get(path) : void 0;
|
|
2653
2636
|
let target = routeTarget ? localTargets.get(`${resource.type}/${routeTarget.page}`) : folder ? landingPages[0] : candidates?.length === 1 ? candidates[0] : void 0;
|
|
2654
2637
|
const rootRoute = link.href.split(/[?#]/, 1)[0] === "/";
|
|
2655
|
-
if (!target && (
|
|
2638
|
+
if (!target && (rootRoute || path !== void 0 && !markdown) && resource.type === "WikiPage") {
|
|
2656
2639
|
const resolved = navigation.get(resource.spec.wiki);
|
|
2657
2640
|
const wikiTarget = resolved && resolveWikiContentHref(link.href, resource.name, resolved);
|
|
2658
|
-
if (wikiTarget) target = localTargets.get(`WikiPage/${wikiTarget.page.page}`);
|
|
2641
|
+
if (wikiTarget && (rootRoute || extensionless || link.kind === "card" || path !== void 0 && !await hasNonPageFile(path))) target = localTargets.get(`WikiPage/${wikiTarget.page.page}`);
|
|
2659
2642
|
}
|
|
2660
2643
|
if (!target && path !== void 0 && !markdown && resource.type === "CoursePage") {
|
|
2661
2644
|
const resolved = courseNavigationByPage.get(resource.name);
|
|
@@ -2773,8 +2756,7 @@ function linkDiagnostic(id, level, link) {
|
|
|
2773
2756
|
...link.file ? { file: link.file } : {}
|
|
2774
2757
|
};
|
|
2775
2758
|
}
|
|
2776
|
-
|
|
2777
|
-
//#region src/compile/guide.ts
|
|
2759
|
+
// src/compile/guide.ts
|
|
2778
2760
|
async function compileGuides(options) {
|
|
2779
2761
|
const result = await inspectGuides(options);
|
|
2780
2762
|
throwOnCompileErrors(result.diagnostics);
|
|
@@ -2922,8 +2904,7 @@ function mergeTags(collectionTags, frontmatterTags) {
|
|
|
2922
2904
|
}
|
|
2923
2905
|
return [...tags];
|
|
2924
2906
|
}
|
|
2925
|
-
|
|
2926
|
-
//#region src/compile/wiki.ts
|
|
2907
|
+
// src/compile/wiki.ts
|
|
2927
2908
|
async function compileWiki(options) {
|
|
2928
2909
|
const result = await inspectWiki(options);
|
|
2929
2910
|
throwOnCompileErrors(result.diagnostics);
|
|
@@ -3160,8 +3141,7 @@ function normalizePagePath(pagePath) {
|
|
|
3160
3141
|
function pagePathToTitleFallback(pagePath) {
|
|
3161
3142
|
return normalizePagePath(pagePath).replaceAll("/", "-");
|
|
3162
3143
|
}
|
|
3163
|
-
|
|
3164
|
-
//#region src/compile/course.ts
|
|
3144
|
+
// src/compile/course.ts
|
|
3165
3145
|
async function compileCourse(options) {
|
|
3166
3146
|
const result = await inspectCourse(options);
|
|
3167
3147
|
throwOnCompileErrors(result.diagnostics);
|
|
@@ -3351,8 +3331,7 @@ function validateCourseAuthors(resources, paths) {
|
|
|
3351
3331
|
const persons = new Set(resources.filter((resource) => resource.type === "Person").map((resource) => resource.name));
|
|
3352
3332
|
for (const resource of resources) if ((resource.type === "Course" || resource.type === "CoursePage") && resource.spec.authors?.some((author) => !persons.has(author))) throw new PublicCompileError("author-not-found", paths[`${resource.type}/${resource.name}`]);
|
|
3353
3333
|
}
|
|
3354
|
-
|
|
3355
|
-
//#region src/compile/manifest.ts
|
|
3334
|
+
// src/compile/manifest.ts
|
|
3356
3335
|
var ManifestSourceError = class extends PublicCompileError {
|
|
3357
3336
|
sourceIndex;
|
|
3358
3337
|
kind;
|
|
@@ -3489,8 +3468,7 @@ async function compileManifest(options) {
|
|
|
3489
3468
|
...compiled
|
|
3490
3469
|
};
|
|
3491
3470
|
}
|
|
3492
|
-
|
|
3493
|
-
//#region src/compile/discovery.ts
|
|
3471
|
+
// src/compile/discovery.ts
|
|
3494
3472
|
/** Read authoring metadata and paths before combining a caller-owned source inventory. */
|
|
3495
3473
|
async function discoverGuideResources(options) {
|
|
3496
3474
|
return discoverGuides(options);
|
|
@@ -3503,8 +3481,7 @@ async function discoverWikiResources(options) {
|
|
|
3503
3481
|
async function discoverCourseResources(options) {
|
|
3504
3482
|
return discoverCourse(options);
|
|
3505
3483
|
}
|
|
3506
|
-
|
|
3507
|
-
//#region src/compile/index.ts
|
|
3484
|
+
// src/compile/index.ts
|
|
3508
3485
|
/** Compile exactly the project declared by .topik.yaml in dir. */
|
|
3509
3486
|
async function compile(options) {
|
|
3510
3487
|
return compileManifest(options);
|
|
@@ -3517,8 +3494,7 @@ async function lint(options) {
|
|
|
3517
3494
|
throw error;
|
|
3518
3495
|
}
|
|
3519
3496
|
}
|
|
3520
|
-
|
|
3521
|
-
//#region src/watch.ts
|
|
3497
|
+
// src/watch.ts
|
|
3522
3498
|
function freeze(value) {
|
|
3523
3499
|
if (value && typeof value === "object") {
|
|
3524
3500
|
for (const child of Object.values(value)) freeze(child);
|
|
@@ -3545,6 +3521,7 @@ async function watch(options) {
|
|
|
3545
3521
|
let materializationDigest;
|
|
3546
3522
|
let requested = 0;
|
|
3547
3523
|
let closed = false;
|
|
3524
|
+
let watchFailed = false;
|
|
3548
3525
|
let running;
|
|
3549
3526
|
let debounceTimer;
|
|
3550
3527
|
function publish(patch) {
|
|
@@ -3564,7 +3541,7 @@ async function watch(options) {
|
|
|
3564
3541
|
});
|
|
3565
3542
|
try {
|
|
3566
3543
|
const result = await compile({ dir });
|
|
3567
|
-
if (closed) return;
|
|
3544
|
+
if (closed || watchFailed) return;
|
|
3568
3545
|
if (revision !== requested) continue;
|
|
3569
3546
|
const nextDigest = digestTopikMaterializationRecord(result.materialization);
|
|
3570
3547
|
const updates = result.resources.filter((resource) => {
|
|
@@ -3586,7 +3563,7 @@ async function watch(options) {
|
|
|
3586
3563
|
});
|
|
3587
3564
|
for (const resource of updates) emitter.emit("update", `${resource.type}/${resource.name}`, resource);
|
|
3588
3565
|
} catch (error) {
|
|
3589
|
-
if (closed) return;
|
|
3566
|
+
if (closed || watchFailed) return;
|
|
3590
3567
|
if (revision !== requested) continue;
|
|
3591
3568
|
const id = error instanceof PublicCompileError ? error.id : "compilation-failed";
|
|
3592
3569
|
publish({
|
|
@@ -3599,17 +3576,17 @@ async function watch(options) {
|
|
|
3599
3576
|
if (emitter.listenerCount("error") > 0) emitter.emit("error", error instanceof Error ? error : /* @__PURE__ */ new Error("Compilation failed"));
|
|
3600
3577
|
}
|
|
3601
3578
|
if (revision === requested) return;
|
|
3602
|
-
} while (!closed);
|
|
3579
|
+
} while (!closed && !watchFailed);
|
|
3603
3580
|
}
|
|
3604
3581
|
function startCompile() {
|
|
3605
|
-
if (closed) return Promise.resolve();
|
|
3582
|
+
if (closed || watchFailed) return Promise.resolve();
|
|
3606
3583
|
running ??= drain().finally(() => {
|
|
3607
3584
|
running = void 0;
|
|
3608
3585
|
});
|
|
3609
3586
|
return running;
|
|
3610
3587
|
}
|
|
3611
3588
|
function scheduleRecompile() {
|
|
3612
|
-
if (closed) return;
|
|
3589
|
+
if (closed || watchFailed) return;
|
|
3613
3590
|
requested++;
|
|
3614
3591
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
3615
3592
|
if (running) return;
|
|
@@ -3631,15 +3608,50 @@ async function watch(options) {
|
|
|
3631
3608
|
closed = true;
|
|
3632
3609
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
3633
3610
|
options.signal?.removeEventListener("abort", onAbort);
|
|
3634
|
-
|
|
3611
|
+
const closing = fsWatcher.close();
|
|
3612
|
+
if (fsWatcher.listenerCount("error") === 0) fsWatcher.on("error", () => {});
|
|
3613
|
+
await Promise.all([closing, running]);
|
|
3635
3614
|
};
|
|
3636
3615
|
const onAbort = () => {
|
|
3637
3616
|
close();
|
|
3638
3617
|
};
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3618
|
+
fsWatcher.on("error", (error) => {
|
|
3619
|
+
if (closed) return;
|
|
3620
|
+
watchFailed = true;
|
|
3621
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
3622
|
+
publish({
|
|
3623
|
+
status: "error",
|
|
3624
|
+
diagnostics: [{
|
|
3625
|
+
id: "watch-failed",
|
|
3626
|
+
message: "Source watching failed. Restart the preview to resume updates."
|
|
3627
|
+
}]
|
|
3628
|
+
});
|
|
3629
|
+
if (emitter.listenerCount("error") > 0) emitter.emit("error", error instanceof Error ? error : /* @__PURE__ */ new Error("Source watching failed"));
|
|
3642
3630
|
});
|
|
3631
|
+
try {
|
|
3632
|
+
await new Promise((resolveReady, rejectReady) => {
|
|
3633
|
+
const cleanup = () => {
|
|
3634
|
+
fsWatcher.off("ready", ready);
|
|
3635
|
+
fsWatcher.off("error", failed);
|
|
3636
|
+
options.signal?.removeEventListener("abort", ready);
|
|
3637
|
+
};
|
|
3638
|
+
const ready = () => {
|
|
3639
|
+
cleanup();
|
|
3640
|
+
resolveReady();
|
|
3641
|
+
};
|
|
3642
|
+
const failed = (error) => {
|
|
3643
|
+
cleanup();
|
|
3644
|
+
rejectReady(error);
|
|
3645
|
+
};
|
|
3646
|
+
fsWatcher.once("ready", ready);
|
|
3647
|
+
fsWatcher.once("error", failed);
|
|
3648
|
+
options.signal?.addEventListener("abort", ready, { once: true });
|
|
3649
|
+
if (options.signal?.aborted) ready();
|
|
3650
|
+
});
|
|
3651
|
+
} catch (error) {
|
|
3652
|
+
await close();
|
|
3653
|
+
throw error;
|
|
3654
|
+
}
|
|
3643
3655
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
3644
3656
|
if (options.signal?.aborted) await close();
|
|
3645
3657
|
else await startCompile();
|
|
@@ -3661,8 +3673,7 @@ async function watch(options) {
|
|
|
3661
3673
|
};
|
|
3662
3674
|
return watcher;
|
|
3663
3675
|
}
|
|
3664
|
-
|
|
3665
|
-
//#region src/source/diagnostics.ts
|
|
3676
|
+
// src/source/diagnostics.ts
|
|
3666
3677
|
var SourcePlanningError = class extends Error {
|
|
3667
3678
|
diagnostic;
|
|
3668
3679
|
constructor(diagnostic) {
|
|
@@ -3698,8 +3709,7 @@ function sourcePlanDiagnostics(error, fallback) {
|
|
|
3698
3709
|
}
|
|
3699
3710
|
return [fallback];
|
|
3700
3711
|
}
|
|
3701
|
-
|
|
3702
|
-
//#region src/source/metadata.ts
|
|
3712
|
+
// src/source/metadata.ts
|
|
3703
3713
|
/** Existing mapping leaves change individually so sibling metadata keeps its original syntax. */
|
|
3704
3714
|
function collectMetadataEdits(updates, selector, previous, desired) {
|
|
3705
3715
|
if (serializeTopikJson(previous ?? null) === serializeTopikJson(desired ?? null) && previous === void 0 === (desired === void 0)) return;
|
|
@@ -3709,8 +3719,7 @@ function collectMetadataEdits(updates, selector, previous, desired) {
|
|
|
3709
3719
|
for (const key of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) collectMetadataEdits(updates, `${selector}/${encodeURIComponent(key)}`, before[key], after[key]);
|
|
3710
3720
|
} else updates[selector] = desired;
|
|
3711
3721
|
}
|
|
3712
|
-
|
|
3713
|
-
//#region src/source/syntax.ts
|
|
3722
|
+
// src/source/syntax.ts
|
|
3714
3723
|
/** Commas in comments and nested values are never collection delimiters. */
|
|
3715
3724
|
function flowDelimiters(collection) {
|
|
3716
3725
|
const token = collection.srcToken;
|
|
@@ -4109,8 +4118,7 @@ function patchSourceFields(raw, updates, json = false, eol = raw.includes("\r\n"
|
|
|
4109
4118
|
edits
|
|
4110
4119
|
};
|
|
4111
4120
|
}
|
|
4112
|
-
|
|
4113
|
-
//#region src/source/course.ts
|
|
4121
|
+
// src/source/course.ts
|
|
4114
4122
|
function fail(code, message, resource) {
|
|
4115
4123
|
throw new SourcePlanningError({
|
|
4116
4124
|
code,
|
|
@@ -4259,11 +4267,9 @@ function planCourseConfiguration(input) {
|
|
|
4259
4267
|
membershipResources
|
|
4260
4268
|
};
|
|
4261
4269
|
}
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
//#endregion
|
|
4266
|
-
//#region src/source/project.ts
|
|
4270
|
+
// package.json
|
|
4271
|
+
var version = "0.1.0-alpha.7";
|
|
4272
|
+
// src/source/project.ts
|
|
4267
4273
|
const SOURCE_WRITER_VERSION = "topik-source-writer-v1";
|
|
4268
4274
|
const SOURCE_PROJECT_LIMITS = {
|
|
4269
4275
|
maxFiles: 1e4,
|
|
@@ -4607,8 +4613,7 @@ function sourceReferences(source, name, resource, compilation, assetPositions, s
|
|
|
4607
4613
|
}).ok) throw new TypeError("Source reference provenance cannot be inspected");
|
|
4608
4614
|
return references;
|
|
4609
4615
|
}
|
|
4610
|
-
|
|
4611
|
-
//#region src/source/reference-context.ts
|
|
4616
|
+
// src/source/reference-context.ts
|
|
4612
4617
|
/** Every saved body must have a source position in its own immutable Wiki snapshot. */
|
|
4613
4618
|
function resolveSourceReferenceContext(context, wikiName, pageName) {
|
|
4614
4619
|
if (context.type !== "Wiki" || context.name !== wikiName) return {
|
|
@@ -4625,8 +4630,7 @@ function resolveSourceReferenceContext(context, wikiName, pageName) {
|
|
|
4625
4630
|
navigation
|
|
4626
4631
|
};
|
|
4627
4632
|
}
|
|
4628
|
-
|
|
4629
|
-
//#region src/source/resource-references.ts
|
|
4633
|
+
// src/source/resource-references.ts
|
|
4630
4634
|
function courseName(resource, resources) {
|
|
4631
4635
|
if (resource.type !== "CoursePage") return void 0;
|
|
4632
4636
|
const module = resources.get(`CourseModule/${resource.spec.module}`);
|
|
@@ -4807,8 +4811,7 @@ function restoreSourceResourceReferences(resource, document, path, paths, origin
|
|
|
4807
4811
|
repairs
|
|
4808
4812
|
};
|
|
4809
4813
|
}
|
|
4810
|
-
|
|
4811
|
-
//#region src/source/asset-context.ts
|
|
4814
|
+
// src/source/asset-context.ts
|
|
4812
4815
|
/** Retained saved Asset names resolve only through independently pinned identity mappings. */
|
|
4813
4816
|
function applySourceAssetReferenceContexts(resources, contexts, scope) {
|
|
4814
4817
|
for (const [key, mappings] of Object.entries(contexts ?? {})) {
|
|
@@ -4827,8 +4830,7 @@ function applySourceAssetReferenceContexts(resources, contexts, scope) {
|
|
|
4827
4830
|
resource.spec.content.value = rewritten.content;
|
|
4828
4831
|
}
|
|
4829
4832
|
}
|
|
4830
|
-
|
|
4831
|
-
//#region src/source/plan.ts
|
|
4833
|
+
// src/source/plan.ts
|
|
4832
4834
|
function block(code, message, resource, path) {
|
|
4833
4835
|
throw new SourcePlanningError({
|
|
4834
4836
|
code,
|
|
@@ -5596,8 +5598,7 @@ async function planSourceUpdates(input) {
|
|
|
5596
5598
|
};
|
|
5597
5599
|
}
|
|
5598
5600
|
}
|
|
5599
|
-
|
|
5600
|
-
//#region src/source/initialize.ts
|
|
5601
|
+
// src/source/initialize.ts
|
|
5601
5602
|
/** Initialization is distinct from adding a source to a valid existing manifest. */
|
|
5602
5603
|
async function initializeSourceProject(input) {
|
|
5603
5604
|
return buildSource(input);
|
|
@@ -6012,5 +6013,4 @@ async function buildSource(input, existing) {
|
|
|
6012
6013
|
};
|
|
6013
6014
|
}
|
|
6014
6015
|
}
|
|
6015
|
-
//#endregion
|
|
6016
6016
|
export { ASSET_API_VERSION, ASSET_SCHEMA_ID, ASSET_TYPE, AssetCompilationError, CompileError, DEFAULT_ASSET_DIRECTORY, ManifestSourceError, PublicCompileError, SOURCE_PROJECT_LIMITS, SOURCE_WRITER_DESCRIPTOR, SOURCE_WRITER_VERSION, TOPIK_ASSET_CORRELATION_ID_PATTERN, TOPIK_ASSET_DEFAULT_CORRELATION_ID, TOPIK_ASSET_DIAGNOSTIC_IDS, TOPIK_ASSET_LIMITS, TOPIK_ASSET_NAME_VERSION, TOPIK_ASSET_REFERENCE_VERSION, TOPIK_BLOB_OUTPUT_PREFIX, TOPIK_JSON_VERSION, TOPIK_MANIFEST_FILENAME, TOPIK_MANIFEST_LIMITS, TOPIK_MATERIALIZATION_VERSION, TOPIK_PATH_V1_DESCRIPTOR, TOPIK_PATH_VERSION, TOPIK_PREVIEW_PROTOCOL, TOPIK_UNRESOLVED_ACTIVE_CONTENT_TYPE, TopikJsonSyntaxError, addSourceToProject, compareTopikAssetIdentities, compile, compileAssetResources, compileCourse, compileGuides, compileManifest, compileResourceLinks, compileWiki, computeTopikPathCollisionKey, correlateTopikAssetResult, createProjectAssetNameGenerator, createTopikAssetSemanticRecord, createTopikMaterializationRecord, digestSourceResourceGraph, digestSourceTree, digestTopikAssetSemanticRecord, digestTopikMaterializationRecord, discoverCourseResources, discoverGuideResources, discoverManifestSources, discoverWikiResources, findFirstWikiPage, findWikiPageAncestors, generateAutomaticAssetName, hasWikiNavChildren, initializeSourceProject, isAssetBlobUri, isErrorDiagnostic, isExternalWikiDropdown, isExternalWikiTab, isGeneratedAssetName, isInlineMediaCompatible, isInternalWikiDropdown, isInternalWikiTab, isTopikActiveMediaType, joinWikiPath, lint, loadTopikManifest, looksLikeGitLfsPointer, pagePathToName, parseAsset, parseAssetBlobUri, parseCollectionConfig, parseCourseConfig, parseGeneratedAssetName, parseStrictTopikJson, parseTopikManifest, parseWikiConfig, planSourceUpdates, publicCompileErrorMessage, readPortableAssetFile, readSourceProject, resolveCourseContentHref, resolveCourseContentReference, resolveCourseNavigation, resolveWikiContentHref, resolveWikiContentReference, resolveWikiNavigation, serializeAsset, serializeTopikJson, sniffPortableMediaType, sourceAssetsConfigSchema, toNfkcCasefold, topikAssetNameDescriptor, topikJsonDescriptor, topikManifestSchema, topikManifestSourceSchema, validateAssetBlobUri, validateAssetValue, validatePortableAssetFile, validatePortableAssetTree, validateProjectNamespace, validateResources, validateTopikMaterializationRecord, validateTopikPath, validateTopikPathSet, watch };
|
|
@@ -7,13 +7,10 @@ import { CoursePage } from "@topik/schema/course-page/v1";
|
|
|
7
7
|
import { Guide } from "@topik/schema/guide/v1";
|
|
8
8
|
import { Wiki } from "@topik/schema/wiki/v1";
|
|
9
9
|
import { WikiPage } from "@topik/schema/wiki-page/v1";
|
|
10
|
-
//#region src/resource.d.ts
|
|
11
10
|
type Resource = Asset | Course | CourseModule | CoursePage | Guide | Person | Wiki | WikiPage;
|
|
12
11
|
/** Resources accepted as compiler input. `Asset` exists only in compiler output. */
|
|
13
12
|
type SourceResource = Exclude<Resource, Asset>;
|
|
14
13
|
type ResourceType = Resource["type"];
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region src/assets/constants.d.ts
|
|
17
14
|
declare const ASSET_API_VERSION: "v1";
|
|
18
15
|
declare const ASSET_TYPE: "Asset";
|
|
19
16
|
declare const ASSET_SCHEMA_ID: "https://topik.dev/schemas/asset/v1.json";
|
|
@@ -43,8 +40,6 @@ declare const TOPIK_ASSET_LIMITS: {
|
|
|
43
40
|
readonly maxComponents: 64;
|
|
44
41
|
readonly maxRepositoryPathUtf8Bytes: 768;
|
|
45
42
|
};
|
|
46
|
-
//#endregion
|
|
47
|
-
//#region src/assets/diagnostics.d.ts
|
|
48
43
|
declare const TOPIK_ASSET_DIAGNOSTIC_IDS: readonly ["TOPIK_ASSET_UNSUPPORTED_VERSION", "TOPIK_ASSET_DUPLICATE_MEMBER", "TOPIK_ASSET_SCHEMA_INVALID", "TOPIK_ASSET_NON_CANONICAL", "TOPIK_ASSET_NAME_INVALID", "TOPIK_ASSET_NAME_COLLISION", "TOPIK_ASSET_NAME_GENERATOR_REQUIRED", "TOPIK_ASSET_PROJECT_NAMESPACE_INVALID", "TOPIK_ASSET_PATH_INVALID", "TOPIK_ASSET_PATH_COLLISION", "TOPIK_ASSET_REFERENCE_AMBIGUOUS", "TOPIK_ASSET_REFERENCE_MALFORMED", "TOPIK_ASSET_REFERENCE_MISSING", "TOPIK_ASSET_FILE_MISSING", "TOPIK_ASSET_DIGEST_MISMATCH", "TOPIK_ASSET_SIZE_MISMATCH", "TOPIK_ASSET_MEDIA_TYPE_MISMATCH", "TOPIK_ASSET_FILE_TYPE_UNSUPPORTED", "TOPIK_ASSET_ACTIVE_CONTENT_UNSUPPORTED", "TOPIK_ASSET_REFERENCE_ACCESSIBILITY_INVALID", "TOPIK_EXTERNAL_REFERENCE_UNSAFE", "TOPIK_ASSET_INVENTORY_INCOMPLETE", "TOPIK_ASSET_VERSION_INCOMPARABLE"];
|
|
49
44
|
declare const TOPIK_ASSET_DEFAULT_CORRELATION_ID: "cor_00000000000000000000000000";
|
|
50
45
|
declare const TOPIK_ASSET_CORRELATION_ID_PATTERN: RegExp;
|
|
@@ -85,8 +80,6 @@ type TopikAssetResult<T> = {
|
|
|
85
80
|
source?: Uint8Array;
|
|
86
81
|
};
|
|
87
82
|
declare function correlateTopikAssetResult<T>(result: TopikAssetResult<T>, correlationId: TopikAssetCorrelationId): TopikAssetResult<T>;
|
|
88
|
-
//#endregion
|
|
89
|
-
//#region src/assets/asset.d.ts
|
|
90
83
|
interface ParsedAsset {
|
|
91
84
|
asset: Asset;
|
|
92
85
|
canonicalBytes: Uint8Array;
|
|
@@ -129,8 +122,6 @@ declare function generateAutomaticAssetName(options: GenerateAutomaticAssetNameO
|
|
|
129
122
|
declare function topikAssetNameDescriptor(): {
|
|
130
123
|
id: typeof TOPIK_ASSET_NAME_VERSION;
|
|
131
124
|
};
|
|
132
|
-
//#endregion
|
|
133
|
-
//#region src/assets/identity.d.ts
|
|
134
125
|
interface TopikAssetReferenceMappingV1 {
|
|
135
126
|
resource: string;
|
|
136
127
|
position: string;
|
|
@@ -186,8 +177,6 @@ declare function compareTopikAssetIdentities(left: {
|
|
|
186
177
|
semanticEqual: boolean;
|
|
187
178
|
exactEqual: boolean;
|
|
188
179
|
}>;
|
|
189
|
-
//#endregion
|
|
190
|
-
//#region src/compile/assets.d.ts
|
|
191
180
|
type ContentBearingResource = CoursePage | Guide | WikiPage;
|
|
192
181
|
interface AssetNameInput {
|
|
193
182
|
/** Absolute native path after resolving the authored reference within its allowed root.
|
|
@@ -232,8 +221,6 @@ declare class AssetCompilationError extends Error {
|
|
|
232
221
|
}
|
|
233
222
|
/** Discover and resolve one compilation-wide Asset set and deduplicated payload inventory. */
|
|
234
223
|
declare function compileAssetResources(input: CompileAssetResourcesInput): Promise<AssetCompilationResult>;
|
|
235
|
-
//#endregion
|
|
236
|
-
//#region src/preview.d.ts
|
|
237
224
|
/** Browser-safe capability and wire types. No filesystem imports at runtime. */
|
|
238
225
|
declare const TOPIK_PREVIEW_PROTOCOL: "topik-preview/1";
|
|
239
226
|
interface CourseNavigationModule {
|
|
@@ -264,5 +251,4 @@ interface PreviewState {
|
|
|
264
251
|
payloads: PreviewPayloadDescriptor[];
|
|
265
252
|
courseNavigation: CourseNavigationIndex;
|
|
266
253
|
}
|
|
267
|
-
//#endregion
|
|
268
254
|
export { TopikAssetPathDiagnosticReason as $, AssetBlobUri as A, parseGeneratedAssetName as B, TopikMaterializationResourceV1 as C, digestTopikAssetSemanticRecord as D, createTopikMaterializationRecord as E, generateAutomaticAssetName as F, validateProjectNamespace as G, topikAssetNameDescriptor as H, isAssetBlobUri as I, TOPIK_ASSET_DIAGNOSTIC_IDS as J, TOPIK_ASSET_CORRELATION_ID_PATTERN as K, isGeneratedAssetName as L, GenerateAutomaticAssetNameOptions as M, GeneratedAssetName as N, digestTopikMaterializationRecord as O, ParsedAsset as P, TopikAssetDiagnosticLocation as Q, parseAsset as R, TopikMaterializationResourceInput as S, createTopikAssetSemanticRecord as T, validateAssetBlobUri as U, serializeAsset as V, validateAssetValue as W, TopikAssetDiagnostic as X, TopikAssetCorrelationId as Y, TopikAssetDiagnosticId as Z, TopikAssetReferenceMappingV1 as _, PreviewState as a, ASSET_TYPE as at, TopikMaterializationPayloadV1 as b, AssetCompilationOptions as c, TOPIK_ASSET_REFERENCE_VERSION as ct, AssetNameInput as d, TOPIK_MATERIALIZATION_VERSION as dt, TopikAssetRecoveryCategory as et, AssetPayload as f, TOPIK_PATH_V1_DESCRIPTOR as ft, compileAssetResources as g, SourceResource as gt, ContentBearingResource as h, ResourceType as ht, PreviewPayloadDescriptor as i, ASSET_SCHEMA_ID as it, CompiledAsset as j, validateTopikMaterializationRecord as k, AssetCompilationResult as l, TOPIK_BLOB_OUTPUT_PREFIX as lt, CompiledResource as m, Resource as mt, CourseNavigationModule as n, correlateTopikAssetResult as nt, TOPIK_PREVIEW_PROTOCOL as o, TOPIK_ASSET_LIMITS as ot, CompileAssetResourcesInput as p, TOPIK_PATH_VERSION as pt, TOPIK_ASSET_DEFAULT_CORRELATION_ID as q, PreviewDiagnostic as r, ASSET_API_VERSION as rt, AssetCompilationError as s, TOPIK_ASSET_NAME_VERSION as st, CourseNavigationIndex as t, TopikAssetResult as tt, AssetNameGenerator as u, TOPIK_JSON_VERSION as ut, TopikAssetSemanticRecordV1 as v, compareTopikAssetIdentities as w, TopikMaterializationRecordV1 as x, TopikMaterializationPayloadInput as y, parseAssetBlobUri as z };
|
package/dist/preview.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as PreviewState, i as PreviewPayloadDescriptor, n as CourseNavigationModule, o as TOPIK_PREVIEW_PROTOCOL, r as PreviewDiagnostic, t as CourseNavigationIndex } from "./preview-
|
|
1
|
+
import { a as PreviewState, i as PreviewPayloadDescriptor, n as CourseNavigationModule, o as TOPIK_PREVIEW_PROTOCOL, r as PreviewDiagnostic, t as CourseNavigationIndex } from "./preview-DfACgOEg.mjs";
|
|
2
2
|
export { CourseNavigationIndex, CourseNavigationModule, PreviewDiagnostic, PreviewPayloadDescriptor, PreviewState, TOPIK_PREVIEW_PROTOCOL };
|
package/dist/preview.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { WikiDropdownNavNode, WikiExternalDropdownNavNode, WikiExternalTabNavNode, WikiInternalDropdownNavNode, WikiInternalTabNavNode, WikiNavContainerNode, WikiNavNode, WikiNavigation, WikiPageNavNode, WikiTabNavNode } from "@topik/schema/wiki/v1";
|
|
2
|
-
//#region src/wiki-navigation.d.ts
|
|
3
2
|
export type ResolvedWikiPage = {
|
|
4
3
|
/** The compiled WikiPage resource name. */
|
|
5
4
|
page: string;
|
|
@@ -61,5 +60,4 @@ export type InternalWikiTab = WikiInternalTabNavNode;
|
|
|
61
60
|
export type ExternalWikiTab = WikiExternalTabNavNode;
|
|
62
61
|
export type InternalWikiDropdown = WikiInternalDropdownNavNode;
|
|
63
62
|
export type ExternalWikiDropdown = WikiExternalDropdownNavNode;
|
|
64
|
-
export type WikiSwitcherNode = WikiTabNavNode | WikiDropdownNavNode;
|
|
65
|
-
//#endregion
|
|
63
|
+
export type WikiSwitcherNode = WikiTabNavNode | WikiDropdownNavNode;
|
package/dist/wiki-navigation.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as resolveDeclaredSourcePage, i as resolveDeclaredPublicRoute, n as hasDeclaredFolder, o as resolveNavigationPath, r as isFolderHref } from "./folder-links-
|
|
1
|
+
import { a as resolveDeclaredSourcePage, i as resolveDeclaredPublicRoute, n as hasDeclaredFolder, o as resolveNavigationPath, r as isFolderHref } from "./folder-links-jLZaG6xi.mjs";
|
|
2
2
|
import { parseTopikResourceReference } from "@topik/content";
|
|
3
|
-
|
|
3
|
+
// src/wiki-navigation.ts
|
|
4
4
|
const INTERNAL_WIKI_ORIGIN = "https://topik.invalid";
|
|
5
5
|
/** Classify an already-admitted compiled href without treating missing page context as external.
|
|
6
6
|
* Local files/downloads must first be compiled to Asset references using their source inventory;
|
|
@@ -129,5 +129,4 @@ function joinWikiPath(prefix, slug) {
|
|
|
129
129
|
if (!slug) return prefix;
|
|
130
130
|
return prefix ? `${prefix}/${slug}` : slug;
|
|
131
131
|
}
|
|
132
|
-
//#endregion
|
|
133
132
|
export { findFirstWikiPage, findWikiPageAncestors, hasWikiNavChildren, isExternalWikiDropdown, isExternalWikiTab, isInternalWikiDropdown, isInternalWikiTab, joinWikiPath, resolveWikiContentHref, resolveWikiContentReference, resolveWikiNavigation };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topik/core",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.7",
|
|
4
4
|
"description": "Topik core library",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,19 +23,19 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@topik/content": "0.1.0-alpha.7",
|
|
27
|
+
"@topik/schema": "0.1.0-alpha.7",
|
|
26
28
|
"ajv": "^8.20.0",
|
|
27
29
|
"ajv-formats": "^3.0.1",
|
|
28
30
|
"chokidar": "^5.0.0",
|
|
29
31
|
"yaml": "^2.9.1",
|
|
30
|
-
"zod": "^4.6.7"
|
|
31
|
-
"@topik/content": "0.1.0-alpha.6",
|
|
32
|
-
"@topik/schema": "0.1.0-alpha.6"
|
|
32
|
+
"zod": "^4.6.7"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@types/node": "22.20.
|
|
35
|
+
"@types/node": "22.20.5",
|
|
36
36
|
"typescript": "^7.0.2",
|
|
37
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@1.
|
|
38
|
-
"vite-plus": "1.
|
|
37
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0",
|
|
38
|
+
"vite-plus": "1.4.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "vp pack",
|