@mdgate/epub 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.
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # @mdgate/epub
2
+
3
+ Convert EPUB books to Markdown. Outputs GitHub-Flavored Markdown. Works in Node, Edge, and
4
+ browsers. No native addons.
5
+
6
+ Handles: `.epub`
7
+
8
+ ## Usage
9
+
10
+ ```ts
11
+ import { toMarkdown } from '@mdgate/epub';
12
+
13
+ const markdown = await toMarkdown(bytes);
14
+ ```
15
+
16
+ Compose with other converters:
17
+
18
+ ```ts
19
+ import { create } from '@mdgate/core';
20
+ import { epub } from '@mdgate/epub';
21
+
22
+ const convert = create([epub()]);
23
+ ```
24
+
25
+ Part of [mdgate converters](https://github.com/mdgate/converters); install
26
+ `@mdgate/converters` for every format at once.
package/dist/epub.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { Converter } from '@mdgate/core';
2
+ export declare function epub(): Converter;
@@ -0,0 +1,2 @@
1
+ export { epub } from './epub.js';
2
+ export { toMarkdown } from './to-markdown.js';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{detectZipDoc as v8}from"@mdgate/containers";import{documentToMarkdown as T8}from"@mdgate/document";import{fileExtension as f8}from"@mdgate/utils";import{decodeFragment as M8,Package as Y8,resolve as _}from"@mdgate/containers";import{ConvertError as l}from"@mdgate/core";import{emptyDocument as _8,heading as N8,plain as D8}from"@mdgate/document";import{AssetSink as C8,mediaTypeFor as B8}from"@mdgate/office-common";import{isAbsoluteUri as t,trim as R8,warn as v}from"@mdgate/utils";import{cellSpanning as z8,GridBuilder as J8,inlinesAreEmpty as x,inlinesToPlainText as P,plain as K8,resolveHeaderRows as Q8}from"@mdgate/document";import{deltasEqual as V8,emptyDelta as o,mergeDelta as i,rebaseEmphasis as X8,resolveDelta as k}from"@mdgate/office-common";import{cleanText as y,collapseWs as g,trim as u}from"@mdgate/utils";function m(Z,z,J){let K=new E(z,J,!0);return K.walkChildren(Z,o()),K.finish()}var c={bold:void 0,italic:void 0,strike:void 0,code:void 0},R={delta:c,hidden:void 0};function w(){return{delta:o(),hidden:void 0}}function b(Z,z){return{delta:i(Z.delta,z.delta),hidden:z.hidden??Z.hidden}}function D(Z){return V8(Z.delta,c)&&Z.hidden===void 0}var h=1e5,n=1e6,$8=[],q8=[];class B{rules=[];get isEmpty(){return this.rules.length===0}addFrom(Z){let z=Z.rules;for(let J=0;J<z.length;J+=1)this.rules.push(z[J])}add(Z){if(Z.length===0)return;let z=F8(Z);if(z.length===0)return;for(let J of z.split("}")){let K=J.indexOf("{");if(K<0)continue;let V=J.slice(K+1);if(!W8(V))continue;let Q=r(V);if(D(Q.normal)&&D(Q.important))continue;let X=J.slice(0,K);for(let G of X.split(",")){let q=G.trim();if(q.length===0||q.includes(" ")||q.includes(":")||q.includes("["))continue;let $=q.indexOf("."),L,j;if($>=0){let F=q.slice(0,$);L=F.length===0?void 0:F.toLowerCase(),j=q.slice($+1)}else L=q.toLowerCase();let W=(j!==void 0?10:0)+(L!==void 0?1:0);if(!D(Q.normal))this.rules.push({tag:L,className:j,priority:W,props:Q.normal});if(!D(Q.important))this.rules.push({tag:L,className:j,priority:n+W,props:Q.important})}}}matchingRules(Z,z){let J=this.rules;if(J.length===0)return $8;let K=[];for(let V=0;V<J.length;V+=1){let Q=J[V];if(Q.tag!==void 0&&Q.tag!==Z)continue;if(Q.className!==void 0&&!z.includes(Q.className))continue;K.push([Q.priority,Q.props])}return K}}function W8(Z){return Z.includes("display")||Z.includes("font-weight")||Z.includes("font-style")||Z.includes("text-decoration")}function F8(Z){let z=Z.indexOf("/*");if(z<0)return Z;let J=[],K=0,V=z;while(V>=0){if(V>K)J.push(Z.slice(K,V));let Q=Z.indexOf("*/",V+2);if(Q<0)return J.join("");K=Q+2,V=Z.indexOf("/*",K)}if(K<Z.length)J.push(Z.slice(K));return J.join("")}function r(Z){let z={normal:w(),important:w()};for(let J of Z.split(";")){let K=J.indexOf(":");if(K<0)continue;let V=J.slice(0,K).trim().toLowerCase(),Q=J.slice(K+1).trim().toLowerCase(),X=!1,G=Q.indexOf("!");if(G>=0){if(Q.slice(G+1).trim()==="important")X=!0;Q=Q.slice(0,G).trimEnd()}let q=X?z.important:z.normal;switch(V){case"font-weight":{let $=A(Q);q.delta.bold=Q==="bold"||Q==="bolder"||$!==void 0&&$>=600;break}case"font-style":q.delta.italic=Q==="italic"||Q==="oblique";break;case"text-decoration":case"text-decoration-line":if(Q.includes("line-through"))q.delta.strike=!0;else if(Q==="none")q.delta.strike=!1;break;case"display":q.hidden=Q==="none";break;default:break}}return z}function A(Z){if(!/^\d+$/.test(Z))return;let z=Number(Z);if(!Number.isSafeInteger(z)||z<0||z>4294967295)return;return z}class E{blocks=[];inlines=[];css;ctx;startBoundary;constructor(Z,z,J){this.css=Z,this.ctx=z,this.startBoundary=J}finish(){return this.flushParagraph(),this.blocks}subBlocks(Z,z){return this.subBlocksAt(Z,z,!0)}subBlocksAt(Z,z,J){let K=new E(this.css,this.ctx,J);return K.walkChildren(Z,z),K.finish()}elementProps(Z){let z=Z.attrAny("style");if(this.css.isEmpty&&z===void 0)return R;let J=Z.attrAny("class"),K=J!==void 0&&J.length>0?J.split(/\s+/).filter((X)=>X.length>0):q8,V=this.css.matchingRules(Z.local,K);if(z!==void 0){let X=r(z);V.push([h,X.normal]),V.push([n+h,X.important])}if(V.length===0)return R;if(V.length===1)return b(R,V[0][1]);V.sort((X,G)=>X[0]-G[0]);let Q=w();for(let X=0;X<V.length;X+=1)Q=b(Q,V[X][1]);return Q}pushAnchor(Z){let z=Z.attrAny("id");if(z!==void 0&&z.length>0)this.inlines.push({type:"anchor",id:this.ctx.anchorId(z)});if(Z.local==="a"){let J=Z.attrAny("name");if(J!==void 0&&J.length>0)this.inlines.push({type:"anchor",id:this.ctx.anchorId(J)})}}walkChildren(Z,z){for(let J of Z.children)if(J.type==="text")this.pushText(J.text,z);else this.walkElem(J.elem,z)}pushText(Z,z){let J=g(y(Z));if(J.length===0)return;let K=J;if(S(this.inlines,this.startBoundary))K=O8(J," ");if(K.length===0)return;this.inlines.push({type:"text",text:K,style:k(z)})}walkElem(Z,z){let J=this.elementProps(Z);if(J.hidden===!0)return;z=i(G8(Z,z),J.delta);let K=Z.local;if(K==="h1"||K==="h2"||K==="h3"||K==="h4"||K==="h5"||K==="h6"){this.flushParagraph();let V=Number.parseInt(K.slice(1),10)||1,Q=this.inlineChildren(Z,z);X8(Q,k(z));let X=Z.attrAny("id"),G=X!==void 0?this.ctx.anchorId(X):void 0;if(!x(Q))this.blocks.push({type:"heading",level:V,anchor:G,content:Q});else{let q=[];if(G!==void 0)q.push({type:"anchor",id:G});for(let $ of Q)if($.type==="anchor")q.push($);if(q.length>0)this.blocks.push({type:"paragraph",inlines:q})}return}if(K==="p"){this.flushParagraph(),this.pushAnchor(Z);let V=this.inlines.splice(0,this.inlines.length);if(V.push(...this.inlineChildren(Z,z)),I(V))this.blocks.push({type:"paragraph",inlines:V});return}if(K==="ul"||K==="ol"){this.flushParagraph(),this.blocks.push(...this.parseList(Z,z));return}if(K==="table"){this.flushParagraph();let V=Z.childElems().find((X)=>X.local==="caption");if(V!==void 0){let X=this.inlineChildren(V,z);if(I(X))this.blocks.push({type:"paragraph",inlines:X})}let Q=this.parseTable(Z,z);if(Q!==void 0)this.blocks.push(Q);return}if(K==="blockquote"){this.flushParagraph();let V=this.subBlocks(Z,z);if(V.length>0)this.blocks.push({type:"blockQuote",blocks:V});return}if(K==="pre"){this.flushParagraph();let V=Z.text();if(u(V).length>0)this.blocks.push({type:"codeBlock",lang:void 0,text:V});return}if(K==="hr"){this.flushParagraph(),this.blocks.push({type:"rule"});return}if(s(K)){if(this.pushAnchor(Z),L8(Z))this.flushParagraph(),this.walkChildren(Z,z),this.flushParagraph();else this.walkChildren(Z,z);return}if(K==="script"||K==="style"||K==="head"||K==="template"||K==="noscript")return;this.walkInline(Z,z)}walkInline(Z,z){this.pushAnchor(Z);let J=Z.local;if(J==="br"){this.inlines.push({type:"lineBreak"});return}if(J==="img"||J==="image"){let K=y(Z.attrAny("alt")??""),V=Z.attrAny("src")??Z.attrAny("href")??"",Q=this.ctx.imageSource(V);if(Q!==void 0||u(K).length>0)this.inlines.push({type:"image",alt:K,source:Q??{type:"unavailable"}});return}if(J==="a"){let K=Z.attrAny("href"),V=K!==void 0?this.ctx.linkTarget(K):void 0,Q=this.inlineChildrenAt(Z,z,S(this.inlines,this.startBoundary));if(V!==void 0)this.inlines.push({type:"link",content:Q,target:V});else this.inlines.push(...Q);return}this.walkChildren(Z,z)}inlineChildren(Z,z){return this.inlineChildrenAt(Z,z,!0)}inlineChildrenAt(Z,z,J){let K=this.subBlocksAt(Z,z,J);if(K.length===1&&K[0].type==="paragraph")return K[0].inlines;let V=[];for(let Q=0;Q<K.length;Q+=1){if(Q>0)V.push({type:"lineBreak"});let X=K[Q];if(X.type==="paragraph")V.push(...X.inlines);else if(X.type==="heading")V.push(...X.content);else V.push(K8(g(C(X))))}return V}parseList(Z,z){let J=Z.local==="ol",K=Z.childElems().filter((U)=>U.local==="li");if(K.length===0)return[];if(!J)return[{type:"list",list:{marker:"bullet",start:1,items:K.map((H)=>({blocks:this.subBlocks(H,z),checked:void 0,markerLabel:void 0}))}}];let V=Z.attrAny("type"),Q="decimal";if(V==="a")Q="lowerAlpha";else if(V==="A")Q="upperAlpha";else if(V==="i")Q="lowerRoman";else if(V==="I")Q="upperRoman";let X=Z.attrAny("reversed")!==void 0,G=Z.attrAny("start"),$=(G!==void 0?d(G):void 0)??(X?K.length:1),L=[];for(let U of K){let H=U.attrAny("value"),O=H!==void 0?d(H):void 0;if(O!==void 0)$=O;L.push($),$=X?$-1:$+1}if(L.some((U)=>U<1)){let U=K.map((H,O)=>({blocks:this.subBlocks(H,z),checked:void 0,markerLabel:`${L[O]}.`}));return[{type:"list",list:{marker:Q,start:1,items:U}}]}let j=[],W,F=0;for(let U=0;U<K.length;U+=1){let H=L[U],O={blocks:this.subBlocks(K[U],z),checked:void 0,markerLabel:void 0};if(!(W!==void 0&&F+1===H)){if(W!==void 0)j.push({type:"list",list:W});W={marker:Q,start:H,items:[]}}W.items.push(O),F=H}if(W!==void 0)j.push({type:"list",list:W});return j}parseTable(Z,z){let J=[],K=0,V=!1;for(let $ of Z.childElems())if($.local==="thead"||$.local==="tbody"||$.local==="tfoot"){if(V)V=!1,K+=1;let L=$.local==="thead";for(let j of $.childElems())if(j.local==="tr")J.push([j,L,K]);K+=1}else if($.local==="tr")V=!0,J.push([$,!1,K]);if(J.length===0)return;let Q=new Map;for(let $=0;$<J.length;$+=1)Q.set(J[$][2],$);let X=new J8,G=0;for(let $=0;$<J.length;$+=1){let[L,j,W]=J[$];X.nextRow();let F=!0,U=!1;for(let H of L.childElems()){if(H.local!=="td"&&H.local!=="th")continue;if(U=!0,H.local!=="th")F=!1;let O=p(A(H.attrAny("colspan")??"")??1,1,1000),Y,N=H.attrAny("rowspan"),M=N!==void 0?A(N):void 0;if(M===0)Y=(Q.get(W)??$)-$+1;else if(M!==void 0)Y=p(M,1,65534);else Y=1;X.place(z8(this.subBlocks(H,z),O,Y))}if($===G&&(j||F&&U))G+=1}let q=X.finish("data");if(q.grid.length===0)return;return q.headerRows=Q8(q,G),{type:"table",table:q}}flushParagraph(){if(this.inlines.length>0){let Z=this.inlines.splice(0,this.inlines.length);if(I(Z))this.blocks.push({type:"paragraph",inlines:Z})}this.startBoundary=!0}}function G8(Z,z){let J={...z};switch(Z.local){case"b":case"strong":J.bold=!0;break;case"i":case"em":case"cite":case"dfn":case"var":J.italic=!0;break;case"s":case"del":case"strike":J.strike=!0;break;case"code":case"kbd":case"samp":case"tt":J.code=!0;break;default:break}return J}function C(Z){switch(Z.type){case"paragraph":return P(Z.inlines);case"heading":return P(Z.content);case"list":return Z.list.items.flatMap((z)=>z.blocks.map(C)).join(" ");case"blockQuote":return Z.blocks.map(C).join(" ");case"codeBlock":return Z.text;case"table":return Z.table.grid.flatMap((z)=>z.flatMap((J)=>J.type==="origin"?[J.cell.blocks.map(C).join(" ")]:[])).join(" ");case"rule":return""}}function s(Z){return Z==="div"||Z==="section"||Z==="article"||Z==="aside"||Z==="main"||Z==="nav"||Z==="header"||Z==="footer"||Z==="figure"||Z==="figcaption"||Z==="center"||Z==="details"||Z==="summary"||Z==="li"||Z==="dl"||Z==="dt"||Z==="dd"||Z==="body"}function U8(Z){return s(Z)||Z==="p"||Z==="ul"||Z==="ol"||Z==="table"||Z==="blockquote"||Z==="pre"||Z==="hr"||Z==="h1"||Z==="h2"||Z==="h3"||Z==="h4"||Z==="h5"||Z==="h6"}function L8(Z){return Z.childElems().some((z)=>U8(z.local))}function I(Z){return!x(Z)||Z.some((z)=>z.type==="anchor")}function S(Z,z){for(let J=Z.length-1;J>=0;J-=1){let K=Z[J];if(K.type==="anchor")continue;if(K.type==="text"){if(K.text.length===0)continue;return H8(j8(K.text))}if(K.type==="lineBreak")return!0;if(K.type==="link"){if(x(K.content))continue;return S(K.content,!1)}return!1}return z}function j8(Z){let z=Z.length;if(z===0)return 0;let J=Z.charCodeAt(z-1);if(J>=56320&&J<=57343&&z>=2){let K=Z.charCodeAt(z-2);if(K>=55296&&K<=56319)return(K-55296<<10)+(J-56320)+65536}return J}function H8(Z){return Z>=9&&Z<=13||Z===32||Z===133||Z===160||Z===5760||Z>=8192&&Z<=8202||Z===8232||Z===8233||Z===8239||Z===8287||Z===12288}function O8(Z,z){let J=0;while(J<Z.length&&Z[J]===z)J+=1;return Z.slice(J)}function d(Z){let z=Z.trim();if(!/^-?\d+$/.test(z))return;let J=Number(z);return Number.isFinite(J)?J:void 0}function p(Z,z,J){return Math.min(J,Math.max(z,Z))}function e(Z){let z=Y8.open(Z),J=z.requiredXmlPart("META-INF/container.xml"),K;for(let W of J.descendantsAny("rootfile")){K=W.attrAny("full-path");break}if(K===void 0)throw l.malformedPart("META-INF/container.xml","no rootfile entry");let V=z.requiredXmlPart(K),Q=_8();for(let W of V.descendantsAny("title")){let F=R8(W.text());if(F.length>0)Q.blocks.push(N8(1,[D8(F)]));break}let X=new Map;for(let W of V.descendantsAny("item")){let F=W.attrAny("id"),U=W.attrAny("href");if(F===void 0||U===void 0)continue;X.set(F,{href:U,media:W.attrAny("media-type")??""})}let G=[];for(let W of V.descendantsAny("itemref")){let F=W.attrAny("idref");if(F===void 0)continue;let U=X.get(F);if(U!==void 0)G.push(U.href)}let q=new Set;for(let W of G)try{q.add(_(K,W).path)}catch{}let $=new C8,L=new Map,j=0;for(let W of G){let F;try{F=_(K,W).path}catch(M){v(`skipping chapter with unresolvable href ${x8(W)}: ${E8(M)}`),j+=1;continue}let U=z.optionalXmlPart(F);if(U===void 0){v(`skipping unusable chapter ${F}`),j+=1;continue}let O=U.childElems().find((M)=>M.local==="html")?.childElems().find((M)=>M.local==="body");if(O===void 0){v(`skipping chapter ${F}: no body element`),j+=1;continue}let Y=I8(U,F,z,L),N=new Z8(z,$,F,q);Q.blocks.push({type:"paragraph",inlines:[{type:"anchor",id:F}]}),Q.blocks.push(...m(O,Y,N))}if(G.length>0&&j===G.length)throw l.malformed("no chapter in the book could be read");return Q.assets=$.assets,Q}function I8(Z,z,J,K){let V=new B,Q=Z.childElems();Q.reverse();while(Q.length>0){let X=Q.pop();switch(X.local){case"link":{let q=(X.attrAny("rel")??"").split(/\s+/).some((L)=>A8(L,"stylesheet")),$=X.attrAny("href");if(q&&$!==void 0){let L;try{L=_(z,$).path}catch{break}if(!K.has(L)){let W=J.optionalPart(L);if(W===void 0)K.set(L,void 0);else{let F=new B;F.add(w8(W)),K.set(L,F)}}let j=K.get(L);if(j!==void 0)V.addFrom(j)}break}case"style":V.add(X.text());break;default:{let G=Q.length;for(let q of X.childElems())Q.push(q);S8(Q,G);break}}}return V}class Z8{pkg;assets;chapterPath;spineParts;constructor(Z,z,J,K){this.pkg=Z;this.assets=z;this.chapterPath=J;this.spineParts=K}linkTarget(Z){if(Z.length===0)return;if(Z.startsWith("#")){let z=M8(Z.slice(1));return{type:"anchor",id:T(this.chapterPath,z)}}if(t(Z))return{type:"external",url:Z};try{let z=_(this.chapterPath,Z);if(this.spineParts.has(z.path))return{type:"anchor",id:T(z.path,z.fragment)}}catch{}return{type:"relative",url:Z}}imageSource(Z){if(Z.length===0)return;if(t(Z))return{type:"external",url:Z};let z;try{z=_(this.chapterPath,Z).path}catch{return}let J=this.pkg.optionalPart(z);if(J===void 0)return;return{type:"asset",id:this.assets.add(B8(z),z,J)}}anchorId(Z){return T(this.chapterPath,Z)}}function T(Z,z){if(z!==void 0&&z.length>0)return`${Z}#${z}`;return Z}function w8(Z){return new TextDecoder("utf-8",{fatal:!1}).decode(Z)}function A8(Z,z){if(Z.length!==z.length)return!1;for(let J=0;J<Z.length;J+=1){let K=Z.charCodeAt(J),V=z.charCodeAt(J);if(a(K)!==a(V))return!1}return!0}function a(Z){return Z>=65&&Z<=90?Z+32:Z}function S8(Z,z){let J=z,K=Z.length-1;while(J<K){let V=Z[J];Z[J]=Z[K],Z[K]=V,J+=1,K-=1}}function x8(Z){return JSON.stringify(Z)}function E8(Z){return Z instanceof Error?Z.message:String(Z)}function f(){return{id:"epub",sniff(Z,z){if(v8(Z)==="epub")return 2;if(z?.path!==void 0&&f8(z.path)==="epub")return 1;return 0},convert(Z){return{markdown:T8(e(Z))}}}}import{create as P8}from"@mdgate/core";var k8=P8([f()]);function y8(Z,z){return k8(Z,z)}export{y8 as toMarkdown,f as epub};
@@ -0,0 +1,6 @@
1
+ import { type ConvertHint } from '@mdgate/core';
2
+ /**
3
+ * Convert a single file's bytes to Markdown with the epub converter.
4
+ * `hint.path` is only a sniff hint; it is never read from disk.
5
+ */
6
+ export declare function toMarkdown(bytes: Uint8Array, hint?: ConvertHint): Promise<string>;
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@mdgate/epub",
3
+ "version": "0.1.0",
4
+ "description": "mdgate EPUB converter",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "sideEffects": false,
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "main": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "files": [
17
+ "dist/**/*.js",
18
+ "dist/**/*.d.ts"
19
+ ],
20
+ "scripts": {
21
+ "build": "bun ../../scripts/build-package.ts",
22
+ "prepublishOnly": "bun run build"
23
+ },
24
+ "dependencies": {
25
+ "@mdgate/containers": "0.1.0",
26
+ "@mdgate/core": "0.1.3",
27
+ "@mdgate/document": "0.1.0",
28
+ "@mdgate/office-common": "0.1.0",
29
+ "@mdgate/utils": "0.1.2"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "engines": {
35
+ "node": ">=20"
36
+ },
37
+ "keywords": [
38
+ "mdgate",
39
+ "markdown",
40
+ "epub",
41
+ "ebook"
42
+ ]
43
+ }