mark-epub-down 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/dist/application/convert-epub-document.d.ts +10 -0
  4. package/dist/application/convert-epub-document.js +80 -0
  5. package/dist/application/convert-epub-document.js.map +1 -0
  6. package/dist/application/convert-epub.d.ts +13 -0
  7. package/dist/application/convert-epub.js +35 -0
  8. package/dist/application/convert-epub.js.map +1 -0
  9. package/dist/cli/confirm-overwrite.d.ts +1 -0
  10. package/dist/cli/confirm-overwrite.js +29 -0
  11. package/dist/cli/confirm-overwrite.js.map +1 -0
  12. package/dist/cli/reporting.d.ts +3 -0
  13. package/dist/cli/reporting.js +24 -0
  14. package/dist/cli/reporting.js.map +1 -0
  15. package/dist/cli/run-convert-command.d.ts +10 -0
  16. package/dist/cli/run-convert-command.js +61 -0
  17. package/dist/cli/run-convert-command.js.map +1 -0
  18. package/dist/cli.d.ts +2 -0
  19. package/dist/cli.js +28 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/domain/errors.d.ts +7 -0
  22. package/dist/domain/errors.js +20 -0
  23. package/dist/domain/errors.js.map +1 -0
  24. package/dist/domain/spec.d.ts +8 -0
  25. package/dist/domain/spec.js +49 -0
  26. package/dist/domain/spec.js.map +1 -0
  27. package/dist/domain/types.d.ts +48 -0
  28. package/dist/domain/types.js +3 -0
  29. package/dist/domain/types.js.map +1 -0
  30. package/dist/domain/warnings.d.ts +8 -0
  31. package/dist/domain/warnings.js +49 -0
  32. package/dist/domain/warnings.js.map +1 -0
  33. package/dist/epub/archive.d.ts +3 -0
  34. package/dist/epub/archive.js +22 -0
  35. package/dist/epub/archive.js.map +1 -0
  36. package/dist/epub/container.d.ts +2 -0
  37. package/dist/epub/container.js +46 -0
  38. package/dist/epub/container.js.map +1 -0
  39. package/dist/epub/content.d.ts +7 -0
  40. package/dist/epub/content.js +34 -0
  41. package/dist/epub/content.js.map +1 -0
  42. package/dist/epub/opf.d.ts +2 -0
  43. package/dist/epub/opf.js +122 -0
  44. package/dist/epub/opf.js.map +1 -0
  45. package/dist/epub/spine.d.ts +2 -0
  46. package/dist/epub/spine.js +25 -0
  47. package/dist/epub/spine.js.map +1 -0
  48. package/dist/epub/toc.d.ts +3 -0
  49. package/dist/epub/toc.js +165 -0
  50. package/dist/epub/toc.js.map +1 -0
  51. package/dist/index.d.ts +4 -0
  52. package/dist/index.js +8 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/output/render.d.ts +9 -0
  55. package/dist/output/render.js +54 -0
  56. package/dist/output/render.js.map +1 -0
  57. package/dist/transform/anchors.d.ts +2 -0
  58. package/dist/transform/anchors.js +18 -0
  59. package/dist/transform/anchors.js.map +1 -0
  60. package/dist/transform/cleanup.d.ts +4 -0
  61. package/dist/transform/cleanup.js +37 -0
  62. package/dist/transform/cleanup.js.map +1 -0
  63. package/dist/transform/links.d.ts +14 -0
  64. package/dist/transform/links.js +174 -0
  65. package/dist/transform/links.js.map +1 -0
  66. package/dist/transform/markdown.d.ts +2 -0
  67. package/dist/transform/markdown.js +102 -0
  68. package/dist/transform/markdown.js.map +1 -0
  69. package/dist/transform/tables.d.ts +5 -0
  70. package/dist/transform/tables.js +130 -0
  71. package/dist/transform/tables.js.map +1 -0
  72. package/dist/utils/epub-path.d.ts +14 -0
  73. package/dist/utils/epub-path.js +56 -0
  74. package/dist/utils/epub-path.js.map +1 -0
  75. package/dist/utils/path.d.ts +2 -0
  76. package/dist/utils/path.js +33 -0
  77. package/dist/utils/path.js.map +1 -0
  78. package/docs/epub-to-md-v1-public-spec.md +176 -0
  79. package/docs/v1-technical-selection.md +106 -0
  80. package/package.json +67 -0
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderFrontMatter = renderFrontMatter;
4
+ exports.renderTopLevelTitle = renderTopLevelTitle;
5
+ exports.renderToc = renderToc;
6
+ exports.renderDocument = renderDocument;
7
+ const spec_1 = require("../domain/spec");
8
+ function renderFrontMatter(metadata) {
9
+ const entries = spec_1.FRONT_MATTER_FIELDS.flatMap((field) => {
10
+ const value = metadata[field];
11
+ return typeof value === "string" && value.length > 0 ? [[field, value]] : [];
12
+ });
13
+ if (entries.length === 0) {
14
+ return "";
15
+ }
16
+ const lines = ["---", ...entries.map(([key, value]) => `${key}: ${escapeYaml(value)}`), "---"];
17
+ return `${lines.join("\n")}\n\n`;
18
+ }
19
+ function renderTopLevelTitle(metadata) {
20
+ return metadata.title ? `# ${metadata.title}\n\n` : "";
21
+ }
22
+ function renderToc(items) {
23
+ const lines = [`## ${spec_1.GENERATED_TOC_HEADING}`, ""];
24
+ if (items.length === 0) {
25
+ return `${lines.join("\n")}\n`;
26
+ }
27
+ lines.push(...renderTocItems(items, 0), "");
28
+ return `${lines.join("\n")}\n`;
29
+ }
30
+ function renderDocument(input) {
31
+ const parts = [
32
+ renderFrontMatter(input.metadata).trimEnd(),
33
+ renderTopLevelTitle(input.metadata).trimEnd(),
34
+ renderToc(input.toc).trimEnd(),
35
+ input.body.trim(),
36
+ ].filter((part) => part.length > 0);
37
+ return `${parts.join("\n\n")}\n`;
38
+ }
39
+ function renderTocItems(items, depth) {
40
+ const indent = " ".repeat(depth);
41
+ const lines = [];
42
+ for (const item of items) {
43
+ const label = item.href ? `[${item.label}](${item.href})` : item.label;
44
+ lines.push(`${indent}- ${label}`);
45
+ if (item.children.length > 0) {
46
+ lines.push(...renderTocItems(item.children, depth + 1));
47
+ }
48
+ }
49
+ return lines;
50
+ }
51
+ function escapeYaml(value) {
52
+ return JSON.stringify(value);
53
+ }
54
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/output/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function normalizeAnchorToken(value: string): string;
2
+ export declare function buildMergedAnchor(idref: string, fragmentOrToken: string): string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeAnchorToken = normalizeAnchorToken;
4
+ exports.buildMergedAnchor = buildMergedAnchor;
5
+ function normalizeAnchorToken(value) {
6
+ return value
7
+ .trim()
8
+ .toLowerCase()
9
+ .replace(/[^a-z0-9]+/g, "-")
10
+ .replace(/^-+|-+$/g, "")
11
+ .replace(/-{2,}/g, "-");
12
+ }
13
+ function buildMergedAnchor(idref, fragmentOrToken) {
14
+ const prefix = normalizeAnchorToken(idref) || "item";
15
+ const suffix = normalizeAnchorToken(fragmentOrToken) || "section";
16
+ return `${prefix}-${suffix}`;
17
+ }
18
+ //# sourceMappingURL=anchors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchors.js","sourceRoot":"","sources":["../../src/transform/anchors.ts"],"names":[],"mappings":";;AAAA,oDAOC;AAED,8CAIC;AAbD,SAAgB,oBAAoB,CAAC,KAAa;IAChD,OAAO,KAAK;SACT,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,SAAgB,iBAAiB,CAAC,KAAa,EAAE,eAAuB;IACtE,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;IACrD,MAAM,MAAM,GAAG,oBAAoB,CAAC,eAAe,CAAC,IAAI,SAAS,CAAC;IAClE,OAAO,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export interface CleanupResult {
2
+ removedTags: string[];
3
+ }
4
+ export declare function cleanXhtmlDocument(document: Document): CleanupResult;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanXhtmlDocument = cleanXhtmlDocument;
4
+ const spec_1 = require("../domain/spec");
5
+ function cleanXhtmlDocument(document) {
6
+ const removedTags = [];
7
+ for (const tagName of spec_1.REMOVABLE_TAGS) {
8
+ const nodes = Array.from(document.getElementsByTagName(tagName));
9
+ for (const node of nodes) {
10
+ node.remove();
11
+ removedTags.push(tagName);
12
+ }
13
+ }
14
+ cleanupEmptyContainers(document.body);
15
+ return { removedTags };
16
+ }
17
+ function cleanupEmptyContainers(root) {
18
+ if (!root) {
19
+ return;
20
+ }
21
+ for (const child of Array.from(root.children)) {
22
+ cleanupEmptyContainers(child);
23
+ const tagName = child.tagName.toLowerCase();
24
+ if (!spec_1.NON_BLACKLISTED_STRUCTURAL_CONTAINERS.has(tagName)) {
25
+ continue;
26
+ }
27
+ if (child.children.length > 0) {
28
+ continue;
29
+ }
30
+ const hasVisibleText = child.textContent?.trim().length;
31
+ const hasStructuralId = child.hasAttribute("id");
32
+ if (!hasVisibleText && !hasStructuralId) {
33
+ child.remove();
34
+ }
35
+ }
36
+ }
37
+ //# sourceMappingURL=cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/transform/cleanup.ts"],"names":[],"mappings":";;AAMA,gDAcC;AApBD,yCAAuF;AAMvF,SAAgB,kBAAkB,CAAC,QAAkB;IACnD,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,MAAM,OAAO,IAAI,qBAAc,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;QACjE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEtC,OAAO,EAAE,WAAW,EAAE,CAAC;AACzB,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAwB;IACtD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO;IACT,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9C,sBAAsB,CAAC,KAAoB,CAAC,CAAC;QAE7C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,CAAC,4CAAqC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,SAAS;QACX,CAAC;QAED,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC;QACxD,MAAM,eAAe,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAEjD,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe,EAAE,CAAC;YACxC,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { TocItem } from "../domain/types";
2
+ import { WarningCollector } from "../domain/warnings";
3
+ export declare function buildAnchorMap(documents: Array<{
4
+ idref: string;
5
+ relativePath: string;
6
+ document: Document;
7
+ }>, warnings: WarningCollector): Map<string, string>;
8
+ export declare function injectAnchorTargets(item: {
9
+ idref: string;
10
+ relativePath: string;
11
+ document: Document;
12
+ }, anchorMap: Map<string, string>): void;
13
+ export declare function rewriteInternalLinks(document: Document, currentDocumentPath: string, anchorMap: Map<string, string>, warnings: WarningCollector): void;
14
+ export declare function rewriteTocTargets(items: TocItem[], anchorMap: Map<string, string>, warnings: WarningCollector): TocItem[];
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildAnchorMap = buildAnchorMap;
4
+ exports.injectAnchorTargets = injectAnchorTargets;
5
+ exports.rewriteInternalLinks = rewriteInternalLinks;
6
+ exports.rewriteTocTargets = rewriteTocTargets;
7
+ const anchors_1 = require("./anchors");
8
+ const spec_1 = require("../domain/spec");
9
+ const errors_1 = require("../domain/errors");
10
+ const epub_path_1 = require("../utils/epub-path");
11
+ function buildAnchorMap(documents, warnings) {
12
+ const anchorMap = new Map();
13
+ for (const item of documents) {
14
+ const docStartKey = (0, epub_path_1.buildTargetKey)(item.relativePath);
15
+ const docStartAnchor = (0, anchors_1.buildMergedAnchor)(item.idref, "start");
16
+ setAnchor(anchorMap, docStartKey, docStartAnchor, warnings);
17
+ const elementsWithTargets = Array.from(item.document.querySelectorAll("[id], a[name], [xml\\:id]"));
18
+ for (const element of elementsWithTargets) {
19
+ for (const sourceTarget of readSourceTargets(element)) {
20
+ const targetKey = (0, epub_path_1.buildTargetKey)(item.relativePath, sourceTarget);
21
+ const mergedAnchor = (0, anchors_1.buildMergedAnchor)(item.idref, sourceTarget);
22
+ setAnchor(anchorMap, targetKey, mergedAnchor, warnings);
23
+ }
24
+ }
25
+ }
26
+ return anchorMap;
27
+ }
28
+ function injectAnchorTargets(item, anchorMap) {
29
+ const { document } = item;
30
+ const body = document.body;
31
+ const elementsWithTargets = Array.from(document.querySelectorAll("[id], a[name], [xml\\:id]"));
32
+ if (!body) {
33
+ throw errors_1.ConversionError.fatal("CONTENT_BODY_MISSING", `spine content document is missing a body element: ${item.relativePath}`);
34
+ }
35
+ const docStartAnchor = anchorMap.get((0, epub_path_1.buildTargetKey)(item.relativePath));
36
+ if (docStartAnchor) {
37
+ body.prepend(createAnchorElement(document, docStartAnchor));
38
+ }
39
+ for (const element of elementsWithTargets) {
40
+ for (const sourceTarget of readSourceTargets(element)) {
41
+ const mergedAnchor = anchorMap.get((0, epub_path_1.buildTargetKey)(item.relativePath, sourceTarget));
42
+ if (!mergedAnchor) {
43
+ continue;
44
+ }
45
+ injectAnchorTarget(element, createAnchorElement(document, mergedAnchor));
46
+ }
47
+ clearSourceTargetAttributes(element);
48
+ }
49
+ }
50
+ function rewriteInternalLinks(document, currentDocumentPath, anchorMap, warnings) {
51
+ const linkNodes = Array.from(document.querySelectorAll("a[href]"));
52
+ for (const linkNode of linkNodes) {
53
+ const href = linkNode.getAttribute("href");
54
+ if (!href) {
55
+ continue;
56
+ }
57
+ const resolved = (0, epub_path_1.resolveEpubHref)(currentDocumentPath, href);
58
+ if (resolved.kind === "external") {
59
+ continue;
60
+ }
61
+ if (resolved.targetKey && anchorMap.has(resolved.targetKey)) {
62
+ linkNode.setAttribute("href", `#${anchorMap.get(resolved.targetKey)}`);
63
+ continue;
64
+ }
65
+ warnings.add(...buildUnresolvedLinkWarning(linkNode, currentDocumentPath, href));
66
+ unwrapNode(linkNode);
67
+ }
68
+ }
69
+ function rewriteTocTargets(items, anchorMap, warnings) {
70
+ return items.map((item) => {
71
+ let href;
72
+ if (item.href) {
73
+ const targetAnchor = anchorMap.get(item.href);
74
+ if (targetAnchor) {
75
+ href = `#${targetAnchor}`;
76
+ }
77
+ else {
78
+ warnings.add("TOC_TARGET_UNRESOLVED", `TOC entry was left as plain text because its target could not be mapped exactly: ${item.href}`);
79
+ }
80
+ }
81
+ return {
82
+ label: item.label,
83
+ href,
84
+ children: rewriteTocTargets(item.children, anchorMap, warnings),
85
+ };
86
+ });
87
+ }
88
+ function setAnchor(anchorMap, targetKey, mergedAnchor, warnings) {
89
+ const existing = anchorMap.get(targetKey);
90
+ if (existing && existing !== mergedAnchor) {
91
+ warnings.add("ANCHOR_COLLISION", `anchor collision detected; a later target may remain unresolved: ${targetKey}`);
92
+ return;
93
+ }
94
+ anchorMap.set(targetKey, mergedAnchor);
95
+ }
96
+ function createAnchorElement(document, anchorId) {
97
+ const anchor = document.createElement("a");
98
+ anchor.setAttribute("id", anchorId);
99
+ return anchor;
100
+ }
101
+ function injectAnchorTarget(element, anchor) {
102
+ const tagName = element.tagName.toLowerCase();
103
+ if (tagName === "li") {
104
+ element.prepend(anchor);
105
+ return;
106
+ }
107
+ element.before(anchor);
108
+ }
109
+ function unwrapNode(node) {
110
+ const parent = node.parentNode;
111
+ if (!parent) {
112
+ return;
113
+ }
114
+ while (node.firstChild) {
115
+ parent.insertBefore(node.firstChild, node);
116
+ }
117
+ parent.removeChild(node);
118
+ }
119
+ function readSourceTargets(element) {
120
+ const sourceTargets = new Set();
121
+ for (const attributeName of ["id", "name", "xml:id"]) {
122
+ const value = element.getAttribute(attributeName)?.trim();
123
+ if (value) {
124
+ sourceTargets.add(value);
125
+ }
126
+ }
127
+ return [...sourceTargets];
128
+ }
129
+ function clearSourceTargetAttributes(element) {
130
+ for (const attributeName of ["id", "name", "xml:id"]) {
131
+ element.removeAttribute(attributeName);
132
+ }
133
+ }
134
+ function buildUnresolvedLinkWarning(linkNode, currentDocumentPath, href) {
135
+ const noteRole = classifyNoteLink(linkNode);
136
+ if (noteRole) {
137
+ return [
138
+ "NOTE_LINK_UNRESOLVED",
139
+ `${noteRole} link was left as plain text because its target could not be rewritten safely: ${currentDocumentPath} -> ${href}`,
140
+ ];
141
+ }
142
+ return [
143
+ "INTERNAL_LINK_UNRESOLVED",
144
+ `internal link was left as plain text because its target could not be rewritten safely: ${currentDocumentPath} -> ${href}`,
145
+ ];
146
+ }
147
+ function classifyNoteLink(linkNode) {
148
+ const tokens = [
149
+ ...readSpaceSeparatedTokens(linkNode.getAttribute("epub:type")),
150
+ ...readSpaceSeparatedTokens(linkNode.getAttribute("role")),
151
+ ];
152
+ if (tokens.some((token) => spec_1.NOTE_REFERENCE_TYPES.has(token) || token === "doc-noteref")) {
153
+ return "note-reference";
154
+ }
155
+ if (tokens.some((token) => spec_1.NOTE_BACKLINK_TYPES.has(token) || token === "doc-backlink")) {
156
+ return "note-backlink";
157
+ }
158
+ const closestNoteBody = linkNode.closest("[epub\\:type], [role]");
159
+ if (closestNoteBody && isExplicitNoteBody(closestNoteBody)) {
160
+ return "note-link";
161
+ }
162
+ return undefined;
163
+ }
164
+ function isExplicitNoteBody(element) {
165
+ const tokens = [
166
+ ...readSpaceSeparatedTokens(element.getAttribute("epub:type")),
167
+ ...readSpaceSeparatedTokens(element.getAttribute("role")),
168
+ ];
169
+ return tokens.some((token) => spec_1.NOTE_BODY_TYPES.has(token) || token === "doc-footnote" || token === "doc-endnote");
170
+ }
171
+ function readSpaceSeparatedTokens(value) {
172
+ return value ? value.split(/\s+/).map((token) => token.trim().toLowerCase()).filter(Boolean) : [];
173
+ }
174
+ //# sourceMappingURL=links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"links.js","sourceRoot":"","sources":["../../src/transform/links.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import TurndownService from "turndown";
2
+ export declare function createMarkdownConverter(): TurndownService;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createMarkdownConverter = createMarkdownConverter;
7
+ const turndown_1 = __importDefault(require("turndown"));
8
+ const turndown_plugin_gfm_1 = require("turndown-plugin-gfm");
9
+ const spec_1 = require("../domain/spec");
10
+ const tables_1 = require("./tables");
11
+ function createMarkdownConverter() {
12
+ const service = new turndown_1.default({
13
+ codeBlockStyle: "fenced",
14
+ emDelimiter: "*",
15
+ headingStyle: "atx",
16
+ });
17
+ service.use(turndown_plugin_gfm_1.gfm);
18
+ service.addRule("anchorTarget", {
19
+ filter(node) {
20
+ return node.nodeName.toLowerCase() === "a" && node.hasAttribute("id") && !node.hasAttribute("href");
21
+ },
22
+ replacement(_content, node) {
23
+ const id = node.getAttribute("id");
24
+ return id ? `<a id="${id}"></a>` : "";
25
+ },
26
+ });
27
+ service.addRule("lineBreak", {
28
+ filter: "br",
29
+ replacement() {
30
+ return "\n";
31
+ },
32
+ });
33
+ service.addRule("noteContainer", {
34
+ filter(node) {
35
+ return isExplicitNoteBody(node) && node.nodeName.toLowerCase() !== "li";
36
+ },
37
+ replacement(content) {
38
+ const trimmed = content.trim();
39
+ return trimmed.length > 0 ? `\n\n${trimmed}\n\n` : "\n\n";
40
+ },
41
+ });
42
+ service.addRule("complexTable", {
43
+ filter(node) {
44
+ return (0, tables_1.isMarkedComplexTable)(node);
45
+ },
46
+ replacement(_content, node) {
47
+ const element = node;
48
+ element.removeAttribute("data-epub2md-complex-table");
49
+ return `\n\n${element.outerHTML}\n\n`;
50
+ },
51
+ });
52
+ service.addRule("ruby", {
53
+ filter: "ruby",
54
+ replacement(_content, node) {
55
+ const base = Array.from(node.childNodes)
56
+ .filter((child) => child.nodeName.toLowerCase() !== "rt" && child.nodeName.toLowerCase() !== "rp")
57
+ .map((child) => child.textContent ?? "")
58
+ .join("")
59
+ .trim();
60
+ const reading = Array.from(node.childNodes)
61
+ .filter((child) => child.nodeName.toLowerCase() === "rt")
62
+ .map((child) => child.textContent ?? "")
63
+ .join("")
64
+ .trim();
65
+ return reading ? `${base}(${reading})` : base;
66
+ },
67
+ });
68
+ service.addRule("subsup", {
69
+ filter(node) {
70
+ return node.nodeName === "SUP" || node.nodeName === "SUB";
71
+ },
72
+ replacement(content, node) {
73
+ const tagName = node.nodeName.toLowerCase();
74
+ return `<${tagName}>${content}</${tagName}>`;
75
+ },
76
+ });
77
+ service.addRule("definitionList", {
78
+ filter: ["dl", "dt", "dd"],
79
+ replacement(content, node) {
80
+ const tagName = node.nodeName.toLowerCase();
81
+ if (tagName === "dt") {
82
+ return `- ${content.trim()}\n`;
83
+ }
84
+ if (tagName === "dd") {
85
+ return ` - ${content.trim()}\n`;
86
+ }
87
+ return `\n${content.trim()}\n`;
88
+ },
89
+ });
90
+ return service;
91
+ }
92
+ function isExplicitNoteBody(node) {
93
+ const tokens = [
94
+ ...readSpaceSeparatedTokens(node.getAttribute("epub:type")),
95
+ ...readSpaceSeparatedTokens(node.getAttribute("role")),
96
+ ];
97
+ return tokens.some((token) => spec_1.NOTE_BODY_TYPES.has(token) || token === "doc-footnote" || token === "doc-endnote");
98
+ }
99
+ function readSpaceSeparatedTokens(value) {
100
+ return value ? value.split(/\s+/).map((token) => token.trim().toLowerCase()).filter(Boolean) : [];
101
+ }
102
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/transform/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export interface TableProcessingResult {
2
+ complexTableCount: number;
3
+ }
4
+ export declare function processTables(document: Document): TableProcessingResult;
5
+ export declare function isMarkedComplexTable(node: HTMLElement): boolean;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processTables = processTables;
4
+ exports.isMarkedComplexTable = isMarkedComplexTable;
5
+ const COMPLEX_TABLE_ATTRIBUTE = "data-epub2md-complex-table";
6
+ function processTables(document) {
7
+ const tables = Array.from(document.querySelectorAll("table"));
8
+ let complexTableCount = 0;
9
+ for (const table of tables) {
10
+ if (isComplexTable(table)) {
11
+ table.setAttribute(COMPLEX_TABLE_ATTRIBUTE, "true");
12
+ complexTableCount += 1;
13
+ continue;
14
+ }
15
+ table.removeAttribute(COMPLEX_TABLE_ATTRIBUTE);
16
+ }
17
+ return { complexTableCount };
18
+ }
19
+ function isMarkedComplexTable(node) {
20
+ return node.nodeName.toLowerCase() === "table" && node.getAttribute(COMPLEX_TABLE_ATTRIBUTE) === "true";
21
+ }
22
+ function isComplexTable(table) {
23
+ if (table.querySelector("table")) {
24
+ return true;
25
+ }
26
+ if (table.querySelector("caption, colgroup, tfoot")) {
27
+ return true;
28
+ }
29
+ const headerRows = getHeaderRows(table);
30
+ if (headerRows.length !== 1) {
31
+ return true;
32
+ }
33
+ const allRows = getAllRows(table);
34
+ if (allRows.length < 2) {
35
+ return true;
36
+ }
37
+ const headerRow = headerRows[0];
38
+ const headerCells = getDirectCells(headerRow);
39
+ if (headerCells.length === 0 || !headerCells.every((cell) => cell.tagName.toLowerCase() === "th")) {
40
+ return true;
41
+ }
42
+ const expectedColumnCount = headerCells.length;
43
+ const bodyRows = allRows.filter((row) => row !== headerRow);
44
+ if (bodyRows.length === 0) {
45
+ return true;
46
+ }
47
+ if (hasUnsupportedSpan(headerCells)) {
48
+ return true;
49
+ }
50
+ for (const row of bodyRows) {
51
+ const cells = getDirectCells(row);
52
+ if (cells.length !== expectedColumnCount) {
53
+ return true;
54
+ }
55
+ if (!isSupportedBodyRow(cells)) {
56
+ return true;
57
+ }
58
+ if (hasUnsupportedSpan(cells)) {
59
+ return true;
60
+ }
61
+ }
62
+ return false;
63
+ }
64
+ function getHeaderRows(table) {
65
+ const normalizedThead = Array.from(table.children).find((child) => child.tagName.toLowerCase() === "thead");
66
+ if (normalizedThead) {
67
+ return Array.from(normalizedThead.children).filter((child) => {
68
+ return child.tagName.toLowerCase() === "tr";
69
+ });
70
+ }
71
+ const rows = getAllRows(table);
72
+ const firstRow = rows[0];
73
+ if (!firstRow) {
74
+ return [];
75
+ }
76
+ const cells = getDirectCells(firstRow);
77
+ if (cells.length > 0 && cells.every((cell) => cell.tagName.toLowerCase() === "th")) {
78
+ return [firstRow];
79
+ }
80
+ return [];
81
+ }
82
+ function getAllRows(table) {
83
+ const rows = [];
84
+ for (const child of Array.from(table.children)) {
85
+ const tagName = child.tagName.toLowerCase();
86
+ if (tagName === "tr") {
87
+ rows.push(child);
88
+ continue;
89
+ }
90
+ if (tagName === "thead" || tagName === "tbody") {
91
+ rows.push(...Array.from(child.children).filter((row) => row.tagName.toLowerCase() === "tr"));
92
+ }
93
+ }
94
+ return rows;
95
+ }
96
+ function getDirectCells(row) {
97
+ return Array.from(row.children).filter((child) => {
98
+ const tagName = child.tagName.toLowerCase();
99
+ return tagName === "td" || tagName === "th";
100
+ });
101
+ }
102
+ function hasUnsupportedSpan(cells) {
103
+ return cells.some((cell) => {
104
+ const colspan = Number(cell.getAttribute("colspan") ?? "1");
105
+ const rowspan = Number(cell.getAttribute("rowspan") ?? "1");
106
+ return colspan > 1 || rowspan > 1;
107
+ });
108
+ }
109
+ function isSupportedBodyRow(cells) {
110
+ let rowHeaderCount = 0;
111
+ for (const [index, cell] of cells.entries()) {
112
+ const tagName = cell.tagName.toLowerCase();
113
+ if (tagName === "td") {
114
+ continue;
115
+ }
116
+ if (tagName !== "th" || index !== 0 || !isSupportedRowHeader(cell)) {
117
+ return false;
118
+ }
119
+ rowHeaderCount += 1;
120
+ if (rowHeaderCount > 1) {
121
+ return false;
122
+ }
123
+ }
124
+ return true;
125
+ }
126
+ function isSupportedRowHeader(cell) {
127
+ const scope = (cell.getAttribute("scope") ?? "").trim().toLowerCase();
128
+ return scope === "" || scope === "row";
129
+ }
130
+ //# sourceMappingURL=tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.js","sourceRoot":"","sources":["../../src/transform/tables.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface ResolvedEpubHref {
2
+ kind: "internal" | "external";
3
+ href: string;
4
+ resourcePath?: string;
5
+ fragment?: string;
6
+ targetKey?: string;
7
+ }
8
+ export declare function normalizeEpubPath(value: string): string;
9
+ export declare function splitEpubHref(href: string): {
10
+ pathPart: string;
11
+ fragment?: string;
12
+ };
13
+ export declare function buildTargetKey(resourcePath: string, fragment?: string): string;
14
+ export declare function resolveEpubHref(baseDocumentPath: string, href: string): ResolvedEpubHref;