@topik/core 0.1.0-alpha.4 → 0.1.0-alpha.6
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 +558 -0
- package/dist/course-navigation.d.mts +52 -0
- package/dist/course-navigation.mjs +1 -0
- package/dist/folder-links-DI4xfipU.mjs +57 -0
- package/dist/index.d.mts +635 -30
- package/dist/index.mjs +5716 -680
- package/dist/preview-C_3OnNUi.d.mts +268 -0
- package/dist/preview.d.mts +2 -0
- package/dist/preview.mjs +5 -0
- package/dist/wiki-navigation.d.mts +65 -0
- package/dist/wiki-navigation.mjs +133 -0
- package/package.json +12 -9
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/course-navigation.d.ts
|
|
2
|
+
/** @internal Logical page sources become Markdown files and must agree on directory spelling. */
|
|
3
|
+
export declare function validateCoursePageSources(paths: readonly string[]): boolean;
|
|
4
|
+
/** Portable reference context for one Course, independent of filesystem access. */
|
|
5
|
+
export type CourseReferenceContext = {
|
|
6
|
+
course: string;
|
|
7
|
+
modules: readonly {
|
|
8
|
+
name: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
}[];
|
|
11
|
+
pages: readonly {
|
|
12
|
+
name: string;
|
|
13
|
+
module: string;
|
|
14
|
+
slug: string;
|
|
15
|
+
sourcePath: string;
|
|
16
|
+
}[];
|
|
17
|
+
};
|
|
18
|
+
export type ResolvedCoursePage = {
|
|
19
|
+
page: string;
|
|
20
|
+
module: string;
|
|
21
|
+
route: string;
|
|
22
|
+
sourcePath: string;
|
|
23
|
+
};
|
|
24
|
+
export type ResolvedCourseNavigation = {
|
|
25
|
+
course: string;
|
|
26
|
+
pages: readonly ResolvedCoursePage[];
|
|
27
|
+
pageByName: ReadonlyMap<string, ResolvedCoursePage>;
|
|
28
|
+
pageByRoute: ReadonlyMap<string, ResolvedCoursePage>;
|
|
29
|
+
pageBySourcePath: ReadonlyMap<string, ResolvedCoursePage>;
|
|
30
|
+
};
|
|
31
|
+
export type ResolvedCourseContentLink = {
|
|
32
|
+
page: ResolvedCoursePage;
|
|
33
|
+
route: string;
|
|
34
|
+
hash: string;
|
|
35
|
+
search: string;
|
|
36
|
+
};
|
|
37
|
+
export type ResolvedCourseContentReference = {
|
|
38
|
+
kind: "page";
|
|
39
|
+
target: ResolvedCourseContentLink;
|
|
40
|
+
} | {
|
|
41
|
+
kind: "asset";
|
|
42
|
+
} | {
|
|
43
|
+
kind: "external";
|
|
44
|
+
} | {
|
|
45
|
+
kind: "unresolved";
|
|
46
|
+
};
|
|
47
|
+
/** Public routes use module/page slugs; Markdown links use explicit logical source paths. */
|
|
48
|
+
export declare function resolveCourseNavigation(context: CourseReferenceContext): ResolvedCourseNavigation;
|
|
49
|
+
export declare function resolveCourseContentReference(href: string, currentPageName: string, resolved: ResolvedCourseNavigation): ResolvedCourseContentReference;
|
|
50
|
+
/** 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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as resolveCourseContentHref, n as resolveCourseContentReference, r as resolveCourseNavigation, i as validateCoursePageSources } from "./course-navigation-CWlVc0a0.mjs";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
//#region src/folder-links.ts
|
|
2
|
+
/** Resolve decoded source paths consistently without URL root-clamping or Node-only APIs. */
|
|
3
|
+
function resolveNavigationPath(href, sourcePath, directory = "") {
|
|
4
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//")) return void 0;
|
|
5
|
+
try {
|
|
6
|
+
const path = decodeURIComponent(href.split(/[?#]/, 1)[0]);
|
|
7
|
+
const base = path.startsWith("/") ? directory : sourcePath.split("/").slice(0, -1).join("/");
|
|
8
|
+
const relative = path.startsWith("/") ? path.slice(1) : path || sourcePath.split("/").at(-1);
|
|
9
|
+
const parts = [];
|
|
10
|
+
for (const part of `${base}/${relative}`.split("/")) {
|
|
11
|
+
if (!part || part === ".") continue;
|
|
12
|
+
if (part === "..") {
|
|
13
|
+
if (!parts.length) return void 0;
|
|
14
|
+
parts.pop();
|
|
15
|
+
} else parts.push(part);
|
|
16
|
+
}
|
|
17
|
+
if (!parts.length && (isFolderHref(href) || path === "/")) return "";
|
|
18
|
+
return parts.length ? parts.join("/") : void 0;
|
|
19
|
+
} catch {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Folder shorthand selects declared content, never an arbitrary directory listing. */
|
|
24
|
+
function folderLandingCandidates(directory, pages) {
|
|
25
|
+
const prefix = directory ? `${directory}/` : "";
|
|
26
|
+
return [...pages].filter(([path]) => path.startsWith(prefix) && /^(?:index|readme)$/i.test(path.slice(prefix.length))).map(([, page]) => page);
|
|
27
|
+
}
|
|
28
|
+
function hasDeclaredFolder(directory, pages) {
|
|
29
|
+
const prefix = directory ? `${directory}/` : "";
|
|
30
|
+
return [...pages.keys()].some((path) => path.startsWith(prefix));
|
|
31
|
+
}
|
|
32
|
+
/** Explicit Markdown filenames retain their historical trailing-separator spelling. */
|
|
33
|
+
function isFolderHref(href) {
|
|
34
|
+
const pathname = href.split(/[?#]/, 1)[0];
|
|
35
|
+
try {
|
|
36
|
+
const path = decodeURIComponent(pathname);
|
|
37
|
+
if (path === "/") return false;
|
|
38
|
+
return !/\.(?:mdx?|markdown)\/*$/i.test(path) && (path.endsWith("/") || /(?:^|\/)\.{1,2}$/.test(path));
|
|
39
|
+
} catch {
|
|
40
|
+
return /(?:\/|%2f)$|(?:^|\/|%2f)(?:\.|%2e){1,2}$/i.test(pathname);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function resolveDeclaredSourcePage(path, pages, folder = false) {
|
|
44
|
+
if (!folder && !hasDeclaredFolder(path, pages)) return pages.get(path);
|
|
45
|
+
const candidates = folderLandingCandidates(path, pages);
|
|
46
|
+
return candidates.length === 1 ? candidates[0] : void 0;
|
|
47
|
+
}
|
|
48
|
+
/** Wiki's index aliases are public routes in every consumer, including compilation. */
|
|
49
|
+
function resolveDeclaredPublicRoute(href, pages, wiki = false) {
|
|
50
|
+
if (!href.startsWith("/") || isFolderHref(href)) return void 0;
|
|
51
|
+
const path = resolveNavigationPath(href, "");
|
|
52
|
+
if (path === void 0 || /\.(?:mdx?|markdown)$/i.test(path)) return void 0;
|
|
53
|
+
const route = wiki ? path === "index" ? "" : path.replace(/\/index$/, "") : path;
|
|
54
|
+
return pages.get(route);
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { resolveDeclaredSourcePage as a, resolveDeclaredPublicRoute as i, hasDeclaredFolder as n, resolveNavigationPath as o, isFolderHref as r, folderLandingCandidates as t };
|