@dogsbay/format-fluidtopics-rest 0.2.0-beta.101

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.
Files changed (54) hide show
  1. package/README.md +87 -0
  2. package/dist/assets.d.ts +13 -0
  3. package/dist/assets.d.ts.map +1 -0
  4. package/dist/assets.js +53 -0
  5. package/dist/assets.js.map +1 -0
  6. package/dist/cli.d.ts +9 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +28 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/frontmatter.d.ts +36 -0
  11. package/dist/frontmatter.d.ts.map +1 -0
  12. package/dist/frontmatter.js +78 -0
  13. package/dist/frontmatter.js.map +1 -0
  14. package/dist/headings.d.ts +13 -0
  15. package/dist/headings.d.ts.map +1 -0
  16. package/dist/headings.js +76 -0
  17. package/dist/headings.js.map +1 -0
  18. package/dist/html-to-tree.d.ts +17 -0
  19. package/dist/html-to-tree.d.ts.map +1 -0
  20. package/dist/html-to-tree.js +309 -0
  21. package/dist/html-to-tree.js.map +1 -0
  22. package/dist/importer.d.ts +87 -0
  23. package/dist/importer.d.ts.map +1 -0
  24. package/dist/importer.js +354 -0
  25. package/dist/importer.js.map +1 -0
  26. package/dist/index.d.ts +26 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +9 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/inline-html.d.ts +52 -0
  31. package/dist/inline-html.d.ts.map +1 -0
  32. package/dist/inline-html.js +157 -0
  33. package/dist/inline-html.js.map +1 -0
  34. package/dist/khub.d.ts +86 -0
  35. package/dist/khub.d.ts.map +1 -0
  36. package/dist/khub.js +111 -0
  37. package/dist/khub.js.map +1 -0
  38. package/dist/links.d.ts +13 -0
  39. package/dist/links.d.ts.map +1 -0
  40. package/dist/links.js +55 -0
  41. package/dist/links.js.map +1 -0
  42. package/dist/nav.d.ts +7 -0
  43. package/dist/nav.d.ts.map +1 -0
  44. package/dist/nav.js +15 -0
  45. package/dist/nav.js.map +1 -0
  46. package/dist/single-page.d.ts +70 -0
  47. package/dist/single-page.d.ts.map +1 -0
  48. package/dist/single-page.js +77 -0
  49. package/dist/single-page.js.map +1 -0
  50. package/dist/tree.d.ts +2 -0
  51. package/dist/tree.d.ts.map +1 -0
  52. package/dist/tree.js +2 -0
  53. package/dist/tree.js.map +1 -0
  54. package/package.json +50 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-html.js","sourceRoot":"","sources":["../src/inline-html.ts"],"names":[],"mappings":"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"}
package/dist/khub.d.ts ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Minimal client for Fluid Topics' public khub REST API.
3
+ *
4
+ * {portal}/api/khub/maps → list publications (maps)
5
+ * {portal}/api/khub/maps/{id} → map metadata
6
+ * {portal}/api/khub/maps/{id}/toc → the topic tree
7
+ * {portal}/api/khub/maps/{id}/topics/{cid}/content→ DITA-OT HTML5 for one topic
8
+ *
9
+ * `portal` is the part before `/api/khub` and may be path-scoped
10
+ * (e.g. `https://www.servicenow.com/docs`, `https://docs.johnsoncontrols.com/bas`,
11
+ * `https://docs.fluidtopics.com`). Access is per-portal (RBAC) — gated portals
12
+ * return 401.
13
+ */
14
+ export interface KhubMap {
15
+ id: string;
16
+ title: string;
17
+ metadata?: Array<{
18
+ key: string;
19
+ label?: string;
20
+ values: string[];
21
+ }>;
22
+ }
23
+ export interface KhubTocNode {
24
+ tocId?: string;
25
+ contentId?: string;
26
+ title: string;
27
+ prettyUrl?: string;
28
+ children?: KhubTocNode[];
29
+ }
30
+ /**
31
+ * A topic as returned by `/maps/{id}/topics` — unlike the TOC, this carries
32
+ * per-topic `metadata` (audience, author, Product, the `PBS` "Subject matter"
33
+ * subjectScheme facet, …). The DITA-OT HTML5 from `/content` has no `<head>`,
34
+ * so this endpoint is the only source of per-topic metadata.
35
+ */
36
+ export interface KhubTopic {
37
+ id: string;
38
+ title?: string;
39
+ metadata?: Array<{
40
+ key: string;
41
+ label?: string;
42
+ values: string[];
43
+ }>;
44
+ }
45
+ export interface KhubClientOptions {
46
+ fetchImpl?: typeof fetch;
47
+ userAgent?: string;
48
+ /** Delay between requests (politeness). Default 150ms. */
49
+ throttleMs?: number;
50
+ }
51
+ export declare class KhubAuthError extends Error {
52
+ }
53
+ export declare class KhubClient {
54
+ private readonly khubBase;
55
+ private readonly fetchImpl;
56
+ private readonly userAgent;
57
+ private readonly throttleMs;
58
+ private lastAt;
59
+ constructor(portal: string, opts?: KhubClientOptions);
60
+ get base(): string;
61
+ listMaps(lang?: string): Promise<KhubMap[]>;
62
+ getMap(id: string): Promise<Record<string, unknown>>;
63
+ getToc(id: string): Promise<KhubTocNode[]>;
64
+ getTopicContent(mapId: string, contentId: string): Promise<string>;
65
+ /**
66
+ * Per-topic metadata for a whole map in ONE request (no content). Cheap, but
67
+ * the list returns only the facet keys (Category/Product/PBS/audience/author/…)
68
+ * — not the technical numerics or dates. For those use `getTopic`.
69
+ */
70
+ getTopics(id: string): Promise<KhubTopic[]>;
71
+ /**
72
+ * Full metadata for ONE topic (43 keys incl. `ft:wordCount`, `ft:outputSize`,
73
+ * `ft:lastTechChange`). One request per topic — only used when the caller
74
+ * opts into per-topic technical metadata.
75
+ */
76
+ getTopic(mapId: string, contentId: string): Promise<KhubTopic | undefined>;
77
+ private throttle;
78
+ private request;
79
+ private getJson;
80
+ private getText;
81
+ }
82
+ /** Accepts a portal root or a full `…/api/khub` URL; returns the khub base. */
83
+ export declare function normalizeKhubBase(portal: string): string;
84
+ /** Flatten a TOC tree to the nodes that have a contentId (i.e. real topics). */
85
+ export declare function tocTopics(nodes: KhubTocNode[]): KhubTocNode[];
86
+ //# sourceMappingURL=khub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"khub.d.ts","sourceRoot":"","sources":["../src/khub.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACrE;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACrE;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,aAAc,SAAQ,KAAK;CAAG;AAE3C,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,MAAM,CAAK;gBAEP,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB;IAOxD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAM3C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAIpD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAK1C,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIxE;;;;OAIG;IACG,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAKjD;;;;OAIG;IACG,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;YAOlE,QAAQ;YAMR,OAAO;YAYP,OAAO;YAIP,OAAO;CAGtB;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAU7D"}
package/dist/khub.js ADDED
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Minimal client for Fluid Topics' public khub REST API.
3
+ *
4
+ * {portal}/api/khub/maps → list publications (maps)
5
+ * {portal}/api/khub/maps/{id} → map metadata
6
+ * {portal}/api/khub/maps/{id}/toc → the topic tree
7
+ * {portal}/api/khub/maps/{id}/topics/{cid}/content→ DITA-OT HTML5 for one topic
8
+ *
9
+ * `portal` is the part before `/api/khub` and may be path-scoped
10
+ * (e.g. `https://www.servicenow.com/docs`, `https://docs.johnsoncontrols.com/bas`,
11
+ * `https://docs.fluidtopics.com`). Access is per-portal (RBAC) — gated portals
12
+ * return 401.
13
+ */
14
+ export class KhubAuthError extends Error {
15
+ }
16
+ export class KhubClient {
17
+ khubBase;
18
+ fetchImpl;
19
+ userAgent;
20
+ throttleMs;
21
+ lastAt = 0;
22
+ constructor(portal, opts = {}) {
23
+ this.khubBase = normalizeKhubBase(portal);
24
+ this.fetchImpl = opts.fetchImpl ?? globalThis.fetch;
25
+ this.userAgent = opts.userAgent ?? "dogsbay-format-fluidtopics-rest";
26
+ this.throttleMs = opts.throttleMs ?? 150;
27
+ }
28
+ get base() {
29
+ return this.khubBase;
30
+ }
31
+ async listMaps(lang) {
32
+ const q = lang ? `?lang=${encodeURIComponent(lang)}` : "";
33
+ const data = await this.getJson(`/maps${q}`);
34
+ return Array.isArray(data) ? data : [];
35
+ }
36
+ async getMap(id) {
37
+ return (await this.getJson(`/maps/${id}`));
38
+ }
39
+ async getToc(id) {
40
+ const data = await this.getJson(`/maps/${id}/toc`);
41
+ return Array.isArray(data) ? data : [];
42
+ }
43
+ async getTopicContent(mapId, contentId) {
44
+ return this.getText(`/maps/${mapId}/topics/${contentId}/content`);
45
+ }
46
+ /**
47
+ * Per-topic metadata for a whole map in ONE request (no content). Cheap, but
48
+ * the list returns only the facet keys (Category/Product/PBS/audience/author/…)
49
+ * — not the technical numerics or dates. For those use `getTopic`.
50
+ */
51
+ async getTopics(id) {
52
+ const data = await this.getJson(`/maps/${id}/topics`);
53
+ return Array.isArray(data) ? data : [];
54
+ }
55
+ /**
56
+ * Full metadata for ONE topic (43 keys incl. `ft:wordCount`, `ft:outputSize`,
57
+ * `ft:lastTechChange`). One request per topic — only used when the caller
58
+ * opts into per-topic technical metadata.
59
+ */
60
+ async getTopic(mapId, contentId) {
61
+ const data = await this.getJson(`/maps/${mapId}/topics/${contentId}`);
62
+ return data && typeof data === "object" ? data : undefined;
63
+ }
64
+ // ── internals ───────────────────────────────────────
65
+ async throttle() {
66
+ const wait = this.throttleMs - (Date.now() - this.lastAt);
67
+ if (wait > 0)
68
+ await new Promise((r) => setTimeout(r, wait));
69
+ this.lastAt = Date.now();
70
+ }
71
+ async request(path) {
72
+ await this.throttle();
73
+ const res = await this.fetchImpl(`${this.khubBase}${path}`, {
74
+ headers: { "User-Agent": this.userAgent, Accept: "application/json, text/html" },
75
+ });
76
+ if (res.status === 401 || res.status === 403) {
77
+ throw new KhubAuthError(`khub ${res.status} for ${path} — portal requires authentication (gated). Use a public portal or supply credentials.`);
78
+ }
79
+ if (!res.ok)
80
+ throw new Error(`khub ${res.status} for ${path}`);
81
+ return res;
82
+ }
83
+ async getJson(path) {
84
+ return (await this.request(path)).json();
85
+ }
86
+ async getText(path) {
87
+ return (await this.request(path)).text();
88
+ }
89
+ }
90
+ /** Accepts a portal root or a full `…/api/khub` URL; returns the khub base. */
91
+ export function normalizeKhubBase(portal) {
92
+ let p = portal.trim().replace(/\/+$/, "");
93
+ if (/\/api\/khub$/.test(p))
94
+ return p;
95
+ return `${p}/api/khub`;
96
+ }
97
+ /** Flatten a TOC tree to the nodes that have a contentId (i.e. real topics). */
98
+ export function tocTopics(nodes) {
99
+ const out = [];
100
+ const walk = (ns) => {
101
+ for (const n of ns) {
102
+ if (n.contentId)
103
+ out.push(n);
104
+ if (n.children?.length)
105
+ walk(n.children);
106
+ }
107
+ };
108
+ walk(nodes);
109
+ return out;
110
+ }
111
+ //# sourceMappingURL=khub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"khub.js","sourceRoot":"","sources":["../src/khub.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /** `/r/customer-relationship-management/crm-about-csm-in-crm.html` → `customer-relationship-management/crm-about-csm-in-crm` */
2
+ export declare function slugFromPrettyUrl(prettyUrl: string | undefined): string;
3
+ export declare function routeFromSlug(slug: string, hrefPrefix: string): string;
4
+ /**
5
+ * Resolve an in-content href to a Dogsbay route. Relative `.html` and reader
6
+ * (`/r/…`) links resolve into the route space; external/anchor/scheme links
7
+ * pass through. Returns `{ href, resolved }`.
8
+ */
9
+ export declare function resolveHref(href: string, fromSlug: string, hrefPrefix?: string): {
10
+ href: string;
11
+ resolved: boolean;
12
+ };
13
+ //# sourceMappingURL=links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAUA,gIAAgI;AAChI,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKvE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGtE;AAOD;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,SAAU,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAqBrC"}
package/dist/links.js ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Slug + link resolution for FT khub content.
3
+ *
4
+ * khub topics carry a `prettyUrl` like `/r/customer-relationship-management/
5
+ * crm-about-csm-in-crm.html`; we derive a clean route slug from it. In-content
6
+ * links are DITA-OT `.html` hrefs (relative or reader-absolute) resolved to the
7
+ * same route space.
8
+ */
9
+ import { posix } from "node:path";
10
+ /** `/r/customer-relationship-management/crm-about-csm-in-crm.html` → `customer-relationship-management/crm-about-csm-in-crm` */
11
+ export function slugFromPrettyUrl(prettyUrl) {
12
+ if (!prettyUrl)
13
+ return "";
14
+ let s = prettyUrl.split("#")[0].split("?")[0].trim();
15
+ s = s.replace(/^\/+/, "").replace(/^r\//, "").replace(/\.html?$/i, "");
16
+ return s.replace(/\/+$/, "").toLowerCase();
17
+ }
18
+ export function routeFromSlug(slug, hrefPrefix) {
19
+ if (!slug)
20
+ return hrefPrefix || "/";
21
+ return `${hrefPrefix}/${slug}`;
22
+ }
23
+ function splitAnchor(s) {
24
+ const i = s.indexOf("#");
25
+ return i >= 0 ? [s.slice(0, i), s.slice(i + 1)] : [s, ""];
26
+ }
27
+ /**
28
+ * Resolve an in-content href to a Dogsbay route. Relative `.html` and reader
29
+ * (`/r/…`) links resolve into the route space; external/anchor/scheme links
30
+ * pass through. Returns `{ href, resolved }`.
31
+ */
32
+ export function resolveHref(href, fromSlug, hrefPrefix = "/docs") {
33
+ if (!href)
34
+ return { href, resolved: false };
35
+ if (href.startsWith("#"))
36
+ return { href, resolved: true };
37
+ const [path, anchor] = splitAnchor(href);
38
+ const withAnchor = (route) => route + (anchor ? `#${anchor}` : "");
39
+ // Reader-absolute (/r/…) → slug
40
+ if (path.startsWith("/r/")) {
41
+ return { href: withAnchor(routeFromSlug(slugFromPrettyUrl(path), hrefPrefix)), resolved: true };
42
+ }
43
+ // External / scheme (http, mailto, tel)
44
+ if (/^[a-z][a-z0-9+.-]*:/i.test(href))
45
+ return { href, resolved: true };
46
+ // Relative .html → resolve against the current topic's dir
47
+ if (/\.html?$/i.test(path) || path === "") {
48
+ const dir = posix.dirname(fromSlug || "index");
49
+ const rel = posix.normalize(posix.join(dir, path || ".")).replace(/\.html?$/i, "");
50
+ const slug = rel.replace(/^\.\/?/, "").replace(/^\/+/, "").toLowerCase();
51
+ return { href: withAnchor(routeFromSlug(slug, hrefPrefix)), resolved: true };
52
+ }
53
+ return { href, resolved: false };
54
+ }
55
+ //# sourceMappingURL=links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"links.js","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"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"}
package/dist/nav.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Build a Dogsbay nav subtree from a khub map TOC (the authoritative DITA map).
3
+ */
4
+ import type { NavItem } from "@dogsbay/types";
5
+ import type { KhubTocNode } from "./khub.js";
6
+ export declare function tocToNav(nodes: KhubTocNode[], hrefPrefix?: string): NavItem[];
7
+ //# sourceMappingURL=nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav.d.ts","sourceRoot":"","sources":["../src/nav.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAG7C,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,UAAU,SAAU,GAAG,OAAO,EAAE,CAU9E"}
package/dist/nav.js ADDED
@@ -0,0 +1,15 @@
1
+ import { slugFromPrettyUrl, routeFromSlug } from "./links.js";
2
+ export function tocToNav(nodes, hrefPrefix = "/docs") {
3
+ const out = [];
4
+ for (const n of nodes) {
5
+ const item = { label: n.title };
6
+ const slug = slugFromPrettyUrl(n.prettyUrl);
7
+ if (slug)
8
+ item.href = routeFromSlug(slug, hrefPrefix);
9
+ if (n.children?.length)
10
+ item.children = tocToNav(n.children, hrefPrefix);
11
+ out.push(item);
12
+ }
13
+ return out;
14
+ }
15
+ //# sourceMappingURL=nav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav.js","sourceRoot":"","sources":["../src/nav.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,UAAU,QAAQ,CAAC,KAAoB,EAAE,UAAU,GAAG,OAAO;IACjE,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,GAAY,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACtD,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM;YAAE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACzE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Single-page (whole-map) assembly.
3
+ *
4
+ * FT publishes some books as one continuous page (and many readers *prefer* a
5
+ * single page over "bitty" per-topic pages — the fragmentation debate). This
6
+ * mode rolls an entire khub map into ONE Dogsbay page: each TOC node becomes a
7
+ * heading (level = TOC depth), the topic body nests beneath it, and internal
8
+ * xrefs resolve to in-page anchors instead of separate routes.
9
+ *
10
+ * Heading model: the page title (the book) is the implicit H1, so a top-level
11
+ * TOC node is H2, its children H3, … (clamped at H6). A topic's own body
12
+ * headings (DITA section titles, normally H2) are shifted down by `level - 1`
13
+ * so they sit one rank below their topic's title.
14
+ *
15
+ * ── Relationship to `@dogsbay/format-astro`'s `granularity.ts` ──────────────
16
+ *
17
+ * That module is the PLATFORM generalization of this algorithm, and the two
18
+ * deliberately coexist. They differ in WHAT THEY WALK, which is the whole
19
+ * point:
20
+ *
21
+ * granularity.ts walks `NavItem[]` — the nav a site already has, so it
22
+ * works for ANY source (Hugo, MkDocs, authored Dogsbay-MD).
23
+ * It runs at EMIT time, after nav exists.
24
+ * this module walks `KhubTocNode[]` — Fluid Topics' own map TOC, at
25
+ * IMPORT time, BEFORE any nav is built. `--single-page`
26
+ * collapses a whole map into one page, so there is no
27
+ * per-topic nav for the generic version to consume.
28
+ *
29
+ * `bookHeading`, `shiftHeadings` and `bookSlugFrom` are therefore duplicated
30
+ * on purpose, with identical semantics. KEEP THEM IN SYNC — a change to the
31
+ * heading model here needs the same change there, and vice versa.
32
+ *
33
+ * The `--single-page-books` flag is the other, preferred path: it annotates
34
+ * nav nodes with `single-page: yes` and lets granularity.ts do the assembly,
35
+ * which is the additive "Read as single page" view rather than a whole-site
36
+ * mode. See plans/granularity-views.md and docs/single-page-view.md.
37
+ */
38
+ import type { TreeNode, NavItem } from "@dogsbay/types";
39
+ import type { KhubTocNode } from "./khub.js";
40
+ export interface BookAnchor {
41
+ node: KhubTocNode;
42
+ depth: number;
43
+ /** Heading level for this node's title (clamped 2..6). */
44
+ level: number;
45
+ /** Stable, page-unique anchor id. */
46
+ anchor: string;
47
+ }
48
+ export interface BookAnchors {
49
+ ordered: BookAnchor[];
50
+ /** tocId → anchor (for xref resolution). */
51
+ byTocId: Map<string, string>;
52
+ }
53
+ /**
54
+ * Walk a map TOC in document order, assigning every node a heading level and a
55
+ * page-unique anchor (derived from its prettyUrl basename, else its title).
56
+ */
57
+ export declare function buildBookAnchors(toc: KhubTocNode[]): BookAnchors;
58
+ /** A heading node for a TOC entry's title, carrying the explicit anchor id. */
59
+ export declare function bookHeading(level: number, title: string, anchor: string): TreeNode;
60
+ /** Shift every heading in a (topic body) tree down by `offset` ranks (max H6). */
61
+ export declare function shiftHeadings(tree: TreeNode[], offset: number): void;
62
+ /**
63
+ * Longest common path prefix (slash-segment-wise) of the topic slugs — used as
64
+ * the book's route (e.g. the FT book base `…/metasys-ui…/16.0`). Falls back to
65
+ * `fallback` (slugified title) when there's no shared prefix.
66
+ */
67
+ export declare function bookSlugFrom(slugs: string[], fallback: string): string;
68
+ /** One nav leaf per book → its single page (anchors aren't carried in nav.yml). */
69
+ export declare function bookNavItem(title: string, route: string): NavItem;
70
+ //# sourceMappingURL=single-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single-page.d.ts","sourceRoot":"","sources":["../src/single-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI7C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,4CAA4C;IAC5C,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,WAAW,CAuBhE;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAMlF;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAUpE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWtE;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjE"}
@@ -0,0 +1,77 @@
1
+ import { slugFromPrettyUrl } from "./links.js";
2
+ import { slugify } from "./headings.js";
3
+ /**
4
+ * Walk a map TOC in document order, assigning every node a heading level and a
5
+ * page-unique anchor (derived from its prettyUrl basename, else its title).
6
+ */
7
+ export function buildBookAnchors(toc) {
8
+ const ordered = [];
9
+ const byTocId = new Map();
10
+ const seen = new Map();
11
+ const uniq = (base) => {
12
+ const b = base || "section";
13
+ const n = seen.get(b) ?? 0;
14
+ seen.set(b, n + 1);
15
+ return n === 0 ? b : `${b}-${n}`;
16
+ };
17
+ const walk = (nodes, depth) => {
18
+ for (const n of nodes) {
19
+ const seg = n.prettyUrl ? slugFromPrettyUrl(n.prettyUrl).split("/").pop() ?? "" : "";
20
+ const anchor = uniq(slugify(seg || n.title || "section"));
21
+ ordered.push({ node: n, depth, level: Math.min(depth + 2, 6), anchor });
22
+ if (n.tocId)
23
+ byTocId.set(n.tocId, anchor);
24
+ if (n.children?.length)
25
+ walk(n.children, depth + 1);
26
+ }
27
+ };
28
+ walk(toc, 0);
29
+ return { ordered, byTocId };
30
+ }
31
+ /** A heading node for a TOC entry's title, carrying the explicit anchor id. */
32
+ export function bookHeading(level, title, anchor) {
33
+ return {
34
+ type: "heading",
35
+ props: { level, slug: anchor, text: title },
36
+ children: [{ type: "prose", inline: [{ type: "text", text: title }] }],
37
+ };
38
+ }
39
+ /** Shift every heading in a (topic body) tree down by `offset` ranks (max H6). */
40
+ export function shiftHeadings(tree, offset) {
41
+ if (offset <= 0)
42
+ return;
43
+ for (const n of tree) {
44
+ if (n.type === "heading") {
45
+ const lvl = n.props?.level ?? 1;
46
+ if (!n.props)
47
+ n.props = {};
48
+ n.props.level = Math.min(lvl + offset, 6);
49
+ }
50
+ if (n.children)
51
+ shiftHeadings(n.children, offset);
52
+ }
53
+ }
54
+ /**
55
+ * Longest common path prefix (slash-segment-wise) of the topic slugs — used as
56
+ * the book's route (e.g. the FT book base `…/metasys-ui…/16.0`). Falls back to
57
+ * `fallback` (slugified title) when there's no shared prefix.
58
+ */
59
+ export function bookSlugFrom(slugs, fallback) {
60
+ const parts = slugs.filter(Boolean).map((s) => s.split("/"));
61
+ if (!parts.length)
62
+ return slugify(fallback);
63
+ const first = parts[0];
64
+ let i = 0;
65
+ for (; i < first.length; i++) {
66
+ const seg = first[i];
67
+ if (!parts.every((p) => p[i] === seg))
68
+ break;
69
+ }
70
+ const prefix = first.slice(0, i).join("/");
71
+ return prefix || slugify(fallback);
72
+ }
73
+ /** One nav leaf per book → its single page (anchors aren't carried in nav.yml). */
74
+ export function bookNavItem(title, route) {
75
+ return { label: title, href: route };
76
+ }
77
+ //# sourceMappingURL=single-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single-page.js","sourceRoot":"","sources":["../src/single-page.ts"],"names":[],"mappings":"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"}
package/dist/tree.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export type { TreeNode } from "@dogsbay/types";
2
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/tree.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@dogsbay/format-fluidtopics-rest",
3
+ "version": "0.2.0-beta.101",
4
+ "description": "Fluid Topics REST (khub) importer for Dogsbay — reverse-engineers a live FT portal's DITA-OT HTML5 into TreeNode[] / ExportPage[]",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./cli": {
14
+ "types": "./dist/cli.d.ts",
15
+ "import": "./dist/cli.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "devDependencies": {
23
+ "@types/node": "^25.9.5",
24
+ "tsx": "^4.23.1",
25
+ "typescript": "^5.9.3",
26
+ "vitest": "^4.1.10",
27
+ "@dogsbay/format-fluidtopics-markdown": "0.2.0-beta.101"
28
+ },
29
+ "dependencies": {
30
+ "cheerio": "^1.2.0",
31
+ "yaml": "^2.9.0",
32
+ "@dogsbay/types": "0.2.0-beta.101"
33
+ },
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/dogsbay/dogsbay.git",
38
+ "directory": "packages/format-fluidtopics-rest"
39
+ },
40
+ "homepage": "https://github.com/dogsbay/dogsbay/tree/main/packages/format-fluidtopics-rest",
41
+ "bugs": {
42
+ "url": "https://github.com/dogsbay/dogsbay/issues"
43
+ },
44
+ "scripts": {
45
+ "build": "tsc",
46
+ "test": "vitest run",
47
+ "test:watch": "vitest",
48
+ "reconcile": "tsx scripts/reconcile.ts"
49
+ }
50
+ }