@docx-editor.dev/docx-to-markdown 0.0.1 → 2.19.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/LICENSE +201 -0
- package/README.md +89 -6
- package/THIRD_PARTY_NOTICES.md +18 -0
- package/dist/chunk-CYF5JG4K.js +1 -0
- package/dist/chunk-NP5KYCWK.cjs +1 -0
- package/dist/index.cjs +28 -0
- package/dist/index.d.cts +84 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +28 -0
- package/dist/markdown-types-Cn-MizR0.d.cts +251 -0
- package/dist/markdown-types-Cn-MizR0.d.ts +251 -0
- package/dist/node.cjs +1 -0
- package/dist/node.d.cts +14 -0
- package/dist/node.d.ts +14 -0
- package/dist/node.js +1 -0
- package/docs/api.md +330 -0
- package/docs/fonts.md +172 -0
- package/docs/images.md +223 -0
- package/docs/integrations.md +112 -0
- package/package.json +56 -6
- package/types/index.d.cts +26 -0
- package/types/node.d.cts +3 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
import { M as MarkdownImageAsset, a as MarkdownExportResult, b as MarkdownExportOptions, c as MarkdownProjectionOptions, O as OpenMarkdownDocumentForExportOptions } from './markdown-types-Cn-MizR0.js';
|
|
3
|
+
export { d as MarkdownComment, e as MarkdownFontOrigin, f as MarkdownFontsSource, g as MarkdownImageData, h as MarkdownImageOccurrence, i as MarkdownImageOptions, j as MarkdownPage, k as MarkdownPaginationInfo, l as MarkdownReviewArtifact, m as MarkdownReviewBinding, n as MarkdownReviewCoverage, o as MarkdownReviewOccurrence, p as MarkdownReviewProjection, q as MarkdownReviewRange, r as MarkdownReviewRangePrecision, s as MarkdownReviewUnmappedReason, t as MarkdownTrackedChange, u as MarkdownWarning } from './markdown-types-Cn-MizR0.js';
|
|
4
|
+
import { ExportSession, ExportFontResolutionReport, OpenDocumentForExportResult, ExportDocumentSource, ExportSemanticLayout } from '@docx-editor.dev/core/export';
|
|
5
|
+
export { ExportContentWarning, ExportDestinationAnchor, ExportDestinationGeometry, ExportDocumentMetadata, ExportDocumentSource, ExportDroppedEmbeddedFont, ExportFontFaceResolution, ExportFontFamilyResolution, ExportFontResolutionReport, ExportResourceError, ExportSemanticLayout, ExportSession, FontOriginFailure, OpenDocumentForExportOptions, OpenDocumentForExportResult, PreservedImageConverter } from '@docx-editor.dev/core/export';
|
|
6
|
+
import { HeadlessDocumentRejection } from '@docx-editor.dev/core/store';
|
|
7
|
+
export { HeadlessDocumentRejection, HeadlessDocumentView, ImageDecodePort, ImageResourceState } from '@docx-editor.dev/core/store';
|
|
8
|
+
export { AnchoredDrawingLayoutFallback, AnchoredDrawingRecord, DrawingAccessibility, DrawingGeometry, DrawingHorizontalReferenceFrame, DrawingTransform, DrawingVerticalReferenceFrame, FontRequest, FontSubstitution, HARD_MAX_AGGREGATE_FONT_BYTES, HARD_MAX_FONT_BYTES, HARD_MAX_FONT_SOURCES, ImageWrapTarget, InlineDrawingRecord, LayoutBox, RevisionAttribution, RevisionDisplayMode, SemanticArtifactRootStoryKind, SemanticArtifactStoryKind, SemanticCommentArtifactRecord, SemanticDrawingVisit, SemanticLayout, SemanticReviewArtifactOccurrence, SemanticReviewArtifactOccurrenceGeometry, SemanticReviewArtifactPosition, SemanticReviewArtifactRecord, SemanticReviewArtifactSource, SemanticTrackedChangeArtifactRecord, SourceCrop, TextMeasurer, TextboxStoryLayout, VectorShapeProjection, forEachSemanticDrawing } from '@docx-editor.dev/core/layout';
|
|
9
|
+
export { createFontSource, defineFontResolver } from '@docx-editor.dev/core/editor';
|
|
10
|
+
|
|
11
|
+
/** Failure to produce a complete image export. @public */
|
|
12
|
+
declare class MarkdownMediaError extends Error {
|
|
13
|
+
readonly code: 'media-limit' | 'url-resolution-failed' | 'invalid-image-url' | 'image-bytes-unavailable';
|
|
14
|
+
readonly name = "MarkdownMediaError";
|
|
15
|
+
constructor(code: 'media-limit' | 'url-resolution-failed' | 'invalid-image-url' | 'image-bytes-unavailable', message: string, details?: {
|
|
16
|
+
readonly assetId?: string;
|
|
17
|
+
readonly limitBytes?: number;
|
|
18
|
+
readonly actualBytes?: number;
|
|
19
|
+
readonly cause?: unknown;
|
|
20
|
+
});
|
|
21
|
+
readonly assetId?: string;
|
|
22
|
+
readonly limitBytes?: number;
|
|
23
|
+
readonly actualBytes?: number;
|
|
24
|
+
}
|
|
25
|
+
/** Failure to write a complete portable Markdown bundle. @public */
|
|
26
|
+
declare class MarkdownBundleError extends Error {
|
|
27
|
+
readonly code: 'invalid-media-path' | 'duplicate-output-path' | 'non-portable-image-url' | 'output-not-empty' | 'write-failed' | 'archive-failed';
|
|
28
|
+
readonly name = "MarkdownBundleError";
|
|
29
|
+
constructor(code: 'invalid-media-path' | 'duplicate-output-path' | 'non-portable-image-url' | 'output-not-empty' | 'write-failed' | 'archive-failed', message: string, details?: {
|
|
30
|
+
readonly path?: string;
|
|
31
|
+
readonly cause?: unknown;
|
|
32
|
+
});
|
|
33
|
+
readonly path?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** JSON-safe image metadata. Binary bytes are delivered separately. @public */
|
|
37
|
+
type MarkdownJSONImage = Omit<MarkdownImageAsset, 'bytes'>;
|
|
38
|
+
/** JSON-safe export for HTTP responses and portable bundle manifests. @public */
|
|
39
|
+
type MarkdownJSONResult = Omit<MarkdownExportResult, 'media' | 'fontResolution'> & {
|
|
40
|
+
readonly media: readonly MarkdownJSONImage[];
|
|
41
|
+
readonly fontResolution: (Omit<NonNullable<MarkdownExportResult['fontResolution']>, 'originFailures'> & {
|
|
42
|
+
readonly originFailures: readonly {
|
|
43
|
+
readonly originIndex: number;
|
|
44
|
+
readonly originName?: string;
|
|
45
|
+
readonly cause: string;
|
|
46
|
+
}[];
|
|
47
|
+
}) | null;
|
|
48
|
+
};
|
|
49
|
+
/** Omit image bytes and normalize arbitrary font failure causes to diagnostic strings. @public */
|
|
50
|
+
declare function toMarkdownJSON(result: MarkdownExportResult): MarkdownJSONResult;
|
|
51
|
+
/** Create a portable ZIP containing document.md, document.json, and media files. @public */
|
|
52
|
+
declare function createMarkdownZip(result: MarkdownExportResult): Promise<Uint8Array>;
|
|
53
|
+
|
|
54
|
+
/** Typed one-shot failure for bytes that cannot be opened as a supported DOCX. @public */
|
|
55
|
+
declare class DocumentOpenError extends Error {
|
|
56
|
+
readonly reason: HeadlessDocumentRejection | 'aborted';
|
|
57
|
+
readonly detail?: string | undefined;
|
|
58
|
+
constructor(reason: HeadlessDocumentRejection | 'aborted', detail?: string | undefined);
|
|
59
|
+
}
|
|
60
|
+
/** Reusable Markdown session with the font evidence captured while it opened. @public */
|
|
61
|
+
interface MarkdownExportSession extends ExportSession {
|
|
62
|
+
/**
|
|
63
|
+
* Non-null for document-aware byte sessions opened by Markdown or Core; null for detached
|
|
64
|
+
* layouts, caller-supplied measurers, ordinary Core sessions, and live shared-shaping sessions.
|
|
65
|
+
*/
|
|
66
|
+
readonly fontResolution: ExportFontResolutionReport | null;
|
|
67
|
+
}
|
|
68
|
+
/** Open result whose successful session retains its structured font-resolution report. @public */
|
|
69
|
+
type OpenMarkdownDocumentForExportResult = {
|
|
70
|
+
readonly ok: true;
|
|
71
|
+
readonly session: MarkdownExportSession;
|
|
72
|
+
} | Exclude<OpenDocumentForExportResult, {
|
|
73
|
+
readonly ok: true;
|
|
74
|
+
}>;
|
|
75
|
+
/** Open a reusable export session with packaged fonts and HarfBuzz shaping by default. @public */
|
|
76
|
+
declare function openDocumentForExport(source: ExportDocumentSource, options?: OpenMarkdownDocumentForExportOptions): Promise<OpenMarkdownDocumentForExportResult>;
|
|
77
|
+
/** Translate an existing shared export session without reopening or re-laying out it. @public */
|
|
78
|
+
declare function exportMarkdownFrom(session: ExportSession, options?: MarkdownProjectionOptions): Promise<MarkdownExportResult>;
|
|
79
|
+
/** Translate a detached immutable core layout after its producer session is disposed. @public */
|
|
80
|
+
declare function exportMarkdownLayout(layout: ExportSemanticLayout): MarkdownExportResult;
|
|
81
|
+
/** Convert untrusted DOCX bytes with Node-safe resource and shaping defaults. @public */
|
|
82
|
+
declare function exportMarkdown(source: ExportDocumentSource, options?: MarkdownExportOptions): Promise<MarkdownExportResult>;
|
|
83
|
+
|
|
84
|
+
export { DocumentOpenError, MarkdownBundleError, MarkdownExportOptions, MarkdownExportResult, type MarkdownExportSession, MarkdownImageAsset, type MarkdownJSONImage, type MarkdownJSONResult, MarkdownMediaError, MarkdownProjectionOptions, OpenMarkdownDocumentForExportOptions, type OpenMarkdownDocumentForExportResult, createMarkdownZip, exportMarkdown, exportMarkdownFrom, exportMarkdownLayout, openDocumentForExport, toMarkdownJSON };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {a}from'./chunk-CYF5JG4K.js';export{b as MarkdownBundleError,a as MarkdownMediaError,e as createMarkdownZip,c as toMarkdownJSON}from'./chunk-CYF5JG4K.js';import {createPackagedFileFetch,openDocumentForExport,openFontBackedDocumentForExport,ExportResourceError,acquireSharedExportShaping}from'@docx-editor.dev/core/export';export{ExportResourceError}from'@docx-editor.dev/core/export';import {HARD_MAX_FONT_BYTES,forEachSemanticDrawing,forEachSemanticStory,forEachSemanticSpan,forEachStoryParagraphFragment,lineSegments,revisionsAreDeletion,prepareLayoutFontConfiguration}from'@docx-editor.dev/core/layout';export{HARD_MAX_AGGREGATE_FONT_BYTES,HARD_MAX_FONT_BYTES,HARD_MAX_FONT_SOURCES,forEachSemanticDrawing}from'@docx-editor.dev/core/layout';import {defineFontResolver}from'@docx-editor.dev/core/editor';export{createFontSource,defineFontResolver}from'@docx-editor.dev/core/editor';import {FONT_ASSET_ROOT,packagedFonts,loadDefaultFonts}from'@docx-editor.dev/fonts';var wn=Object.freeze([]),yn=Object.freeze({"image/png":"png","image/jpeg":"jpg","image/gif":"gif","image/bmp":"bmp","image/webp":"webp","image/svg+xml":"svg"});function I(e){if(e?.aborted)throw new ExportResourceError("aborted","Markdown export was aborted",{cause:e.reason})}function _(e){let n=e.images;if(n===void 0||n===false)return;if(n!==true&&(typeof n!="object"||n===null||Array.isArray(n)))throw new TypeError("images must be a boolean or an image options object");let r=n===true?{}:n;if(r.resolveUrl!==void 0&&typeof r.resolveUrl!="function")throw new TypeError("images.resolveUrl must be a function");if(r.syntax!==void 0&&r.syntax!=="markdown"&&r.syntax!=="html")throw new TypeError('images.syntax must be "markdown" or "html"');let o=r.maxTotalBytes??64*1024*1024;if(!Number.isSafeInteger(o)||o<=0)throw new TypeError("images.maxTotalBytes must be a positive safe integer");return r}function G(e,n,r){if(!r)return wn;let o=r.maxTotalBytes??64*1024*1024,t=new Map,a$1=0;return forEachSemanticDrawing(e,({drawing:s,page:i,story:d,rootStory:c})=>{let l=s.resource;if(l.kind!=="ready"||s.accessibility.hidden)return;let p=l.contentId.startsWith("sha256:")?l.contentId.slice(7):l.contentId,u=t.get(p);if(u){if(u.data.mimeType!==l.mime||u.data.pixelWidth!==l.pixelWidth||u.data.pixelHeight!==l.pixelHeight)throw new TypeError(`Conflicting image metadata for content ID ${p}`)}else {let g=yn[l.mime];if(!g||!/^[a-f0-9]{64}$/i.test(p))throw new TypeError("Invalid ready-image content identifier or MIME type");let f=n.validatedImageBytes(s);if(!f)throw new a("image-bytes-unavailable",`Image bytes for ${p} are unavailable; keep the owning session open during extraction.`,{assetId:p});if(a$1+=f.byteLength,a$1>o)throw new a("media-limit",`Extracted images exceed images.maxTotalBytes (${a$1} > ${o} bytes). Increase images.maxTotalBytes or use images: false.`,{assetId:p,limitBytes:o,actualBytes:a$1});u={data:{id:p,path:`media/${p}.${g}`,mimeType:l.mime,bytes:f,byteLength:f.byteLength,pixelWidth:l.pixelWidth,pixelHeight:l.pixelHeight},occurrences:[]},t.set(p,u);}u.occurrences.push(Object.freeze({pageNumber:i.index+1,story:d,rootStory:c,partName:s.ownerPartName,drawingNodeId:s.drawingNodeId,paragraphId:s.paragraphId,start:s.start,displayWidthPx:s.width*(96/72),displayHeightPx:s.height*(96/72),kind:s.kind==="inlineDrawing"?"inline":"anchored",decorative:s.accessibility.decorative,alt:s.accessibility.decorative?"":s.accessibility.label??""}));}),Object.freeze(Array.from(t.values(),({data:s,occurrences:i})=>Object.freeze({...s,occurrences:Object.freeze(i)})))}function kn(e,n){let r=typeof e=="string"&&e.trim().length>0&&!/[\u0000-\u001f\u007f\\]/.test(e)&&!e.startsWith("//")&&e===e.trim();if(r&&typeof e=="string"&&/^[a-z][a-z0-9+.-]*:/i.exec(e))try{let t=new URL(e);r=/^https?:\/\//i.test(e)&&!!t.hostname;}catch{r=false;}if(!r)throw new a("invalid-image-url",`Image ${n} needs a relative path or an absolute HTTP(S) URL.`,{assetId:n})}async function X(e,n){I(n);let r,o=new Promise((t,a)=>{r=()=>a(new ExportResourceError("aborted","Markdown export was aborted",{cause:n?.reason})),n?.addEventListener("abort",r,{once:true});});try{return await Promise.race([Promise.resolve().then(()=>(I(n),e())),o])}finally{r&&n?.removeEventListener("abort",r);}}async function J(e,n){let r=_(n)?.resolveUrl,o=[];for(let t of e){I(n.signal);let a$1=t.path;if(r)try{a$1=await X(()=>Promise.resolve(r(Object.freeze({...t,bytes:t.bytes.slice()}),{signal:n.signal})),n.signal);}catch(s){throw I(n.signal),new a("url-resolution-failed",`Could not resolve the URL for image ${t.id}. Completed uploads remain application-owned.`,{assetId:t.id,cause:s})}kn(a$1,t.id),o.push(Object.freeze({...t,url:a$1}));}return I(n.signal),Object.freeze(o)}var x=Object.freeze({markdown:"",sources:Object.freeze([])});function k(e){return e.length===0?x:{markdown:e,sources:[]}}function ue(e,n){return n===0?[...e]:e.map(r=>({...r,markdownStart:r.markdownStart+n,markdownEnd:r.markdownEnd+n,markdownBoundaries:r.markdownBoundaries?.map(o=>({...o,markdownOffset:o.markdownOffset+n}))}))}function b(e,n=""){let r="",o=[],t=[];for(let[a,s]of e.entries()){a>0&&(r+=n);for(let i of ue(s.sources,r.length))o.push(i);t.push(...s.paragraphs??[]),r+=s.markdown;}return {markdown:r,sources:o,...t.length>0?{paragraphs:t}:{}}}function C(e,n,r=""){return {markdown:n+e.markdown+r,sources:ue(e.sources,n.length),...e.paragraphs?{paragraphs:e.paragraphs}:{}}}function N(e,n){let r=n(e.markdown);if(r.boundaryMap.length!==e.markdown.length+1)throw new TypeError("Markdown transform returned an invalid boundary map");return {markdown:r.markdown,sources:e.sources.map(o=>({...o,markdownStart:r.boundaryMap[o.markdownStart],markdownEnd:r.boundaryMap[o.markdownEnd],markdownBoundaries:o.markdownBoundaries?.map(t=>({...t,markdownOffset:r.boundaryMap[t.markdownOffset]}))})),...e.paragraphs?{paragraphs:e.paragraphs}:{}}}function Z(e,n){return n.length===0?e:{...e,paragraphs:Object.freeze([...n])}}function ge(e){let n=/^[ \t]+/.exec(e.markdown)?.[0].length??0;return n===0?e:N(e,r=>{let o="",t=[0];for(let a=0;a<r.length;a+=1)o+=a<n?"\xA0":r[a],t.push(o.length);return {markdown:o,boundaryMap:t}})}function fe(e){return N(e,n=>{let r="",o=0,t=[0];for(let a=0;a<n.length;a+=1){let s=n[a];s==="\\"?(r+=s,o+=1):(s==="|"&&o%2===0&&(r+="\\"),r+=s,o=0),t[a+1]=r.length;}return {markdown:r,boundaryMap:t}})}function me(e){return N(e,n=>{let r="",o=[0],t=0;for(;t<n.length;){if(n[t]!==`
|
|
2
|
+
`){r+=n[t],t+=1,o[t]=r.length;continue}let a=t;for(;t<n.length&&n[t]===`
|
|
3
|
+
`;)t+=1;r+="<br>";for(let s=a+1;s<=t;s+=1)o[s]=r.length;}return {markdown:r,boundaryMap:o}})}function we(e,n){return N(e,r=>{let o="",t=[0];for(let a=0;a<r.length;a+=1){let s=r[a];o+=s,s===`
|
|
4
|
+
`&&(o+=n),t.push(o.length);}return {markdown:o,boundaryMap:t}})}function ye(e){return N(e,n=>{let r=a=>a===n.length||n[a]===`
|
|
5
|
+
`?">":"> ",o=r(0),t=[o.length];for(let a=0;a<n.length;a+=1){let s=n[a];o+=s,s===`
|
|
6
|
+
`&&(o+=r(a+1)),t.push(o.length);}return {markdown:o,boundaryMap:t}})}function v(e,n){return `${e}\0${n}`}var Mn=new Set("\\`*{}[]()#+-.!_|~="),ke=/[\p{P}\p{S}]/u,he=/[\p{L}\p{N}]/u;function bn(e,n,r){if(e[n]!=="-")return false;let o=n>0?T(e.slice(0,n),"last"):r.before,t=n+1<e.length?T(e.slice(n+1),"first"):r.after;return o!==void 0&&t!==void 0&&he.test(o)&&he.test(t)}function xe(e){throw new TypeError(`Unsupported Markdown inline style: ${String(e)}`)}function Se(e,n=false){return ne(e,n).markdown}function ne(e,n,r=new Set,o={}){let t="",a=new Map,s=d=>{r.has(d)&&a.set(d,t.length);};s(0);let i=0;for(;i<e.length;){let d=e[i];if(d==="\r"&&e[i+1]===`
|
|
7
|
+
`){t+=n?"<br>":`
|
|
8
|
+
`,i+=1,s(i),i+=1,s(i);continue}d==="\r"||d===`
|
|
9
|
+
`||d==="\f"?t+=n?"<br>":`
|
|
10
|
+
`:d==="&"?t+="&":d==="<"?t+="<":d===">"?t+=">":d===" "?t+=" ":(Mn.has(d)&&!bn(e,i,o)&&(t+="\\"),t+=d),i+=1,s(i);}return {markdown:t,boundaries:a}}function Re(e,n,r,o,t={}){let a=r?.offsetsBySource.get(v(o,e.paragraphId));if(!r||!r.allSourceScopes.has(o)&&!a)return k(ne(e.sourceText,n,new Set,t).markdown);let s=new Set([0,e.sourceText.length]);if(e.exact){let l=a??[],p=0,u=l.length;for(;p<u;){let g=p+u>>>1;l[g]<e.sourceStart?p=g+1:u=g;}for(let g=p;g<l.length;g+=1){let f=l[g];if(f>e.sourceEnd)break;s.add(f-e.sourceStart);}}let i=ne(e.sourceText,n,s,t),d=e.exact?[...i.boundaries].map(([l,p])=>({sourceOffset:e.sourceStart+l,markdownOffset:p})):void 0,c={sourceScope:o,paragraphId:e.paragraphId,sourceStart:e.sourceStart,sourceEnd:e.sourceEnd,markdownStart:0,markdownEnd:i.markdown.length,...d?{markdownBoundaries:d}:{},exact:e.exact};return {markdown:i.markdown,sources:[c]}}function xn(e,n){let r=n.displayMode==="all-markup"&&e.revisions!==void 0&&revisionsAreDeletion(e.revisions);return [...e.style.italic?["italic"]:[],...e.style.bold&&!n.suppressBold?["bold"]:[],...e.style.strike||e.style.doubleStrike||r?["strike"]:[]]}function Q(e,n){return e.length===n.length&&e.every((r,o)=>r===n[o])}function Me(e){return e.length>0&&/^[ \t]+$/u.test(e)}function Sn(e){let n=[...e],r=0;for(;r<e.length;){let o=e[r];if(o?.kind!=="text"||o.styles.length>0||!Me(o.sourceText)){r+=1;continue}let t=r,a=true;for(;r<e.length;){let d=e[r];if(d?.kind!=="text"||d.styles.length>0||d.paragraphId!==o.paragraphId||!Me(d.sourceText))break;Q(d.semanticStyles,o.semanticStyles)||(a=false),r+=1;}let s=e[t-1],i=e[r];if(!(s?.kind!=="text"||i?.kind!=="text"||s.paragraphId!==o.paragraphId||i.paragraphId!==o.paragraphId||!a||s.styles.length===0||!Q(o.semanticStyles,s.styles)||!Q(s.styles,i.styles)))for(let d=t;d<r;d+=1){let c=e[d];c?.kind==="text"&&(n[d]={...c,styles:s.styles});}}return n}function be(e){switch(e){case "strike":return "~~";case "italic":return "*";case "bold":return "**";default:return xe(e)}}function ee(e){switch(e){case "strike":return "del";case "italic":return "em";case "bold":return "strong";default:return xe(e)}}function H(e,n){let r=0;for(;r<e.length&&r<n.length&&e[r]===n[r];)r+=1;return r}function T(e,n){if(e.length===0)return;if(n==="first")return String.fromCodePoint(e.codePointAt(0));let r=e.length-1,o=e.charCodeAt(r),t=r>0?e.charCodeAt(r-1):0,a=o>=56320&&o<=57343&&t>=55296&&t<=56319;return e.slice(a?r-1:r)}function Ie(e,n){let r=e[n];if(r?.kind!=="text")return {};let o=e[n-1],t=e[n+1];return {...o?.kind==="text"&&o.paragraphId===r.paragraphId?{before:T(o.sourceText,"last")}:{},...t?.kind==="text"&&t.paragraphId===r.paragraphId?{after:T(t.sourceText,"first")}:{}}}function Rn(e,n,r){for(let o=n;o<r;o+=1){let t=e[o];if(t.kind!=="text")continue;let a=e[o-1],s=e[o+1],i=o>n&&a?.kind==="text"?a.styles:[],d=o+1<r&&s?.kind==="text"?s.styles:[],c=H(i,t.styles)<t.styles.length,l=H(t.styles,d)<t.styles.length,p=T(t.sourceText,"first"),u=T(t.sourceText,"last"),g=a?T(a.kind==="text"?a.sourceText:a.value.markdown,"last"):void 0,f=s?T(s.kind==="text"?s.sourceText:s.value.markdown,"first"):void 0;if(c&&p&&g&&ke.test(p)&&!/\s/u.test(g)||l&&u&&f&&ke.test(u)&&!/\s/u.test(f))return true}return false}function In(e,n,r,o,t,a){let s=[],i=[];for(let d=n;d<r;d+=1){let c=e[d];if(c.kind!=="text")continue;let l=H(i,c.styles);for(let p=i.length-1;p>=l;p-=1)s.push(k(`</${ee(i[p])}>`));for(let p=l;p<c.styles.length;p+=1)s.push(k(`<${ee(c.styles[p])}>`));s.push(Re(c,o,t,a,Ie(e,d))),i=c.styles;}for(let d=i.length-1;d>=0;d-=1)s.push(k(`</${ee(i[d])}>`));return b(s)}var j=class{#e;#n=[];constructor(n){this.#e=n;}#r(n,r,o,t,a,s=t){r.length!==0&&this.#n.push({kind:"text",sourceText:r,styles:t,semanticStyles:s,paragraphId:n.paragraphId,sourceStart:a?n.span.range.start+(n.sourceOffset??0)+o:n.span.range.start,sourceEnd:a?n.span.range.start+(n.sourceOffset??0)+o+r.length:n.span.range.end,exact:a});}writeText(n){let r=/^(\s*)([\s\S]*?)(\s*)$/.exec(n.sourceText),o=r?.[1]??"",t=r?.[2]??n.sourceText,a=r?.[3]??"",s=n.exact??(n.span.projected!==true&&n.span.equation===void 0&&n.sourceText.length===n.span.range.end-n.span.range.start),i=xn(n.span,this.#e);this.#r(n,o,0,[],s,i),this.#r(n,t,o.length,i,s),this.#r(n,a,o.length+t.length,[],s,i);}writeBoundary(n){this.writeMappedBoundary(k(n));}writeMappedBoundary(n){n.markdown.length===0&&n.sources.length===0||this.#n.push({kind:"boundary",value:n});}finishMapped(){let n=Sn(this.#n),r=[],o=[],t=a=>{let s=H(o,a);for(let i=o.length-1;i>=s;i-=1)r.push(k(be(o[i])));for(let i=s;i<a.length;i+=1)r.push(k(be(a[i])));o=a;};for(let a=0;a<n.length;a+=1){let s=n[a];if(s.kind==="boundary"){t([]),r.push(s.value);continue}if(s.styles.length===0){t([]),r.push(this.#t(s,a));continue}let i=a+1;for(;i<n.length;){let d=n[i];if(d?.kind!=="text"||d.styles.length===0)break;i+=1;}if(Rn(n,a,i)){t([]),r.push(In(n,a,i,this.#e.tableCell||this.#e.hardBreakHtml===true,this.#e.sourceCapture,this.#e.sourceScope)),a=i-1;continue}t(s.styles),r.push(this.#t(s,a,n));}return t([]),b(r)}#t(n,r,o=this.#n){let t=this.#e.tableCell||this.#e.hardBreakHtml===true;return Re(n,t,this.#e.sourceCapture,this.#e.sourceScope,Ie(o,r))}finish(){return this.finishMapped().markdown}};function U(e){return e.replace(/[\u0000-\u0020\u007f<>()\\]/g,n=>`%${n.charCodeAt(0).toString(16).toUpperCase().padStart(2,"0")}`)}function K(e){return `${e.ownerPartName}\0${e.drawingNodeId}`}function Pe(e,n="markdown"){let r=new Map;for(let o of e)for(let t of o.occurrences)r.set(`${t.partName}\0${t.drawingNodeId}`,o);return {syntax:n,assets:e,byDrawing:r,represented:new Set,warnings:[]}}function Ee(e,n,r){if(!n||e.accessibility.hidden||e.kind==="anchoredDrawing"&&e.textboxStory)return "";let o=K(e),t=n.byDrawing.get(o);if(!t)return "";n.represented.add(o);let a=e.accessibility.decorative?"":e.accessibility.label??"";if(n.syntax==="html"){let i=Math.round(e.width*1.3333333333333333),d=Math.round(e.height*(96/72));return `<img src="${ve(t.url)}" alt="${ve(a)}" width="${i}" height="${d}">`}let s=U(t.url).replace(/&/g,"&").replace(/\|/g,"%7C");return `![${Se(a.replace(/[\r\n]+/g," "),r)}](${s})`}function ve(e){return e.replace(/[&"<>|\r\n\\]/g,n=>`&#${n.charCodeAt(0)};`)}function V(e,n){let r=new Map,o=new Set;if(n)for(let t of e){let a=K(t);if(o.has(a)||t.textboxStory||!n.byDrawing.has(a))continue;o.add(a);let s=r.get(t.paragraphId)??[];s.push(t),r.set(t.paragraphId,s);}for(let t of r.values())t.sort((a,s)=>a.start-s.start||(a.sourceOrder??0)-(s.sourceOrder??0)||a.drawingNodeId.localeCompare(s.drawingNodeId));return {byParagraph:r}}function re(e,n){let r=e?.byParagraph.get(n)??[];return e?.byParagraph.delete(n),r}function Te(e,n,r){let o=Array.from(e?.byParagraph.values()??[]).flat();e?.byParagraph.clear();for(let t of o)n?.warnings.push(Object.freeze({code:"image-placement-fallback",message:`Image ${t.drawingNodeId} has no rendered anchor paragraph; it follows this story.`,partName:t.ownerPartName,...r===void 0?{}:{pageNumber:r+1}}));return o}function L(e){return e.equation?.fallbackText??e.text}function $(e){return {span:e.span,paragraphId:e.span.range.paragraphId,sourceText:e.sourceText??L(e.span),sourceOffset:e.sourceOffset,...e.sourceText===void 0?{}:{exact:e.span.projected!==true&&e.span.equation===void 0&&L(e.span).length===e.span.range.end-e.span.range.start}}}function Ce(e){let n=[];for(let[r,o]of e.spans.entries())n.push({kind:"span",start:o.range.start,order:r*2+1,span:o});for(let[r,o]of e.drawings.entries())n.push({kind:"drawing",start:o.start,order:r*2,drawing:o});return n.sort((r,o)=>r.start-o.start||r.order-o.order)}function Ae(e,n){if(!n.length)return e;let r=new Set(e.flatMap(i=>i.kind==="drawing"?[`${i.drawing.ownerPartName}\0${i.drawing.drawingNodeId}`]:[])),o=n.filter(i=>!r.has(`${i.ownerPartName}\0${i.drawingNodeId}`)),t=[],a=0,s=()=>{let i=o[a++];t.push({kind:"drawing",start:i.start,order:0,drawing:i});};for(let i of e){for(;a<o.length&&o[a].start<=i.start;)s();if(i.kind!=="span"||i.span.noteNav||i.span.equation||i.span.projected===true){t.push(i);continue}let d=i.sourceText??L(i.span),c=0;for(;a<o.length&&o[a].start<i.start+d.length;){let l=o[a].start-i.start;l>c&&t.push({...i,start:i.start+c,sourceText:d.slice(c,l),sourceOffset:(i.sourceOffset??0)+c}),s(),c=l;}c===0?t.push(i):c<d.length&&t.push({...i,start:i.start+c,sourceText:d.slice(c),sourceOffset:(i.sourceOffset??0)+c});}for(;a<o.length;)s();return t}function Oe(e,n,r){if(!n?.byParagraph.size)return e;if(!e.length)return Ae(e,re(n,r));let o=[],t=[],a="",s=()=>{o.push(...Ae(t,re(n,a))),t=[];};for(let i of e){let d=i.kind==="span"?i.span.range.paragraphId:i.drawing.paragraphId;t.length&&a!==d&&s(),a=d,t.push(i);}return s(),o}function Fe(e,n){let r=e.contentWarnings?.map(t=>Object.freeze({code:t.code==="legacy-textbox"?"omitted-textbox":t.code==="legacy-drawing"?"omitted-drawing":"content-scan-limit",partName:t.partName,message:t.code==="legacy-textbox"?`Legacy text box content in ${t.partName} may be omitted from Markdown.`:t.code==="legacy-drawing"?n?`Some legacy drawing content in ${t.partName} could not be represented by layout and may be omitted from Markdown.`:`Legacy images or shapes in ${t.partName} are omitted from Markdown and may affect page breaks.`:`Content checks stopped at the scan limit in ${t.partName}.`}))??[],o=new Set;return forEachSemanticStory(e,({host:t,page:a})=>{let s=i=>{if(n?.represented.has(K(i)))return;let d=i.kind==="anchoredDrawing"&&i.textboxStory!==void 0,c=d?"omitted-textbox":"omitted-drawing",l=`${a.index}:${c}`;o.has(l)||(o.add(l),r.push(Object.freeze({code:c,message:d?"Text box content is omitted from Markdown.":"Images and shapes are omitted from Markdown.",pageNumber:a.index+1})));};if("anchoredDrawings"in t)for(let i of t.anchoredDrawings??[])s(i);forEachStoryParagraphFragment(t,(i,d)=>{if(!(d.textboxDepth>0))for(let c of i.lines)for(let l of c.drawings??[])s(l);});}),r.concat(n?.warnings??[])}function Be(e,n){return Math.max(e??(n??1)-1,1)}function De(e,n,r){let o=e.map(t=>{let a=t.isHeaderRow?"th":"td",s=Array.from({length:n},(i,d)=>b([k(`<${a}>`),r(t,d),k(`</${a}>`)]));return b([k("<tr>"),...s,k("</tr>")])});return b([k("<table>"),...o,k("</table>")])}function q(e){throw new TypeError(`Unsupported semantic record: ${JSON.stringify(e)}`)}function P(e){let n=[];for(let r of e){let o=n[n.length-1];switch(r.kind){case "paragraph":o?.kind==="paragraph"&&o.fragments[0]?.paragraphId===r.paragraphId?o.fragments.push(r):n.push({kind:"paragraph",fragments:[r]});break;case "table":o?.kind==="table"&&o.fragments[0]?.tableId===r.tableId?o.fragments.push(r):n.push({kind:"table",fragments:[r]});break;default:q(r);}}return n}function O(e,n){let r=[],o=new Map;for(let t of e)for(let a of t.rows){if(a.isHeaderRepeat&&!n)continue;let s=o.get(a.id);if(!(s&&n&&a.isHeaderRepeat)){s||(s={id:a.id,isHeaderRow:a.isHeaderRow,isHeaderRepeat:a.isHeaderRepeat,cells:[]},o.set(a.id,s),r.push(s));for(let[i,d]of a.cells.entries()){let c=d.logicalGridColumn??d.gridColumn??i,l=s.cells.find(p=>p.gridColumn===c);l?l.blocks.push(...d.blocks):s.cells.push({blocks:[...d.blocks],gridSpan:d.gridSpan,vMergeContinue:d.vMergeContinue,gridColumn:c});}s.cells.sort((i,d)=>i.gridColumn-d.gridColumn);}}return r}function En(e){for(let n of e.blocks)if(n.kind==="paragraph")return n.alignment;return "left"}function Ne(e,n,r){let o=Be(n?.columnCount,r[0]?.columnEdges.length);for(let t of e)for(let a of t.cells)o=Math.max(o,a.gridColumn+Math.max(a.gridSpan,1));return o}function je(e,n,r,o){let t=e[0]?.tableId,a=t?n.tablesById.get(t):void 0,s=a?.fragments??e,i=r?O(e,true):O(s,false);if(i.length===0)return x;let d=Ne(i,a,e),c={...n,tableCell:true};return De(i,d,(l,p)=>{let u=l.cells.find(g=>g.gridColumn===p);return !u||u.vMergeContinue?x:o(P(u.blocks),c,true,r)})}function Tn(e,n,r,o){let t=[],a={...n,tableCell:true};for(let s of e.cells){let i=s.vMergeContinue?x:me(fe(o(P(s.blocks),a,true,r)));for(;t.length<s.gridColumn;)t.push(x);t[s.gridColumn]=i;for(let d=1;d<s.gridSpan;d+=1)t[s.gridColumn+d]=x;}return t}function Le(e,n,r,o){let t=e[0]?.tableId,a=t?n.tablesById.get(t):void 0,s=a?.fragments??e,i=r?O(e,true):O(s,false);if(i.length===0)return x;let d=Ne(i,a,e),c=(g,f=x)=>Array.from({length:d},(w,m)=>g[m]??f),l=g=>b([k("| "),b(c(Tn(g,n,r,o))," | "),k(" |")],""),p=i[0],u=[];for(let g of p.cells){let f=En(g),w=f==="center"?":---:":f==="right"?"---:":"---";for(;u.length<g.gridColumn;)u.push("---");u[g.gridColumn]=w;for(let m=1;m<g.gridSpan;m+=1)u[g.gridColumn+m]="---";}return b([l(p),k(`| ${Array.from({length:d},(g,f)=>u[f]??"---").join(" | ")} |`),...i.slice(1).map(l)],`
|
|
11
|
+
`)}function Y(e,n){for(let r of e){if(r.kind==="paragraph")continue;let o=n.get(r.tableId);o||(o={fragments:[],columnCount:Math.max(1,r.columnEdges.length-1)},n.set(r.tableId,o)),o.fragments.push(r);for(let t of r.rows)if(!t.isHeaderRepeat)for(let a of t.cells)Y(a.blocks,n);}}function We(e,n,r){switch(e){case "body":return "body";case "header":case "footer":return `${e}:${n}`;case "footnote":case "endnote":return `${e}:${r??n}`;case "note-separator":return `note-separator:${n}`}}function _e(e){let n=new Map,r=new Set,o=(a,s,i)=>{let d=v(a,s),c=n.get(d)??new Set;c.add(i),n.set(d,c);};for(let a of e)for(let s of a.occurrences){let{start:i,end:d}=s.source,c=We(s.rootStory,s.source.partName,s.noteScopeId);o(c,i.paragraphId,i.offset),o(c,d.paragraphId,d.offset),i.paragraphId!==d.paragraphId&&r.add(c);}if(n.size===0)return;let t=new Map;for(let[a,s]of n)t.set(a,[...s].sort((i,d)=>i-d));return {allSourceScopes:r,offsetsBySource:t}}function He(e){let n=new Map;for(let r of e)for(let o of r.occurrences){let t=n.get(o.pageIndex)??{comments:[],trackedChanges:[],keys:new Set};n.set(o.pageIndex,t);let a=`${r.kind}\0${r.id}`;t.keys.has(a)||(t.keys.add(a),r.kind==="comment"?t.comments.push(r):t.trackedChanges.push(r));}return n}function ae(e,n,r){let o=Math.max(n,e.sourceStart),t=Math.min(r,e.sourceEnd);if(o>t||n!==r&&o===t)return null;if(n===r&&!e.exact)return n===e.sourceStart?{start:e.markdownStart,end:e.markdownStart,unit:"utf16-code-unit",precision:"exact"}:n===e.sourceEnd?{start:e.markdownEnd,end:e.markdownEnd,unit:"utf16-code-unit",precision:"exact"}:null;if(!e.exact||!e.markdownBoundaries)return {start:e.markdownStart,end:e.markdownEnd,unit:"utf16-code-unit",precision:"containing-construct"};let a=d=>{if(d===e.sourceStart)return e.markdownStart;if(d===e.sourceEnd)return e.markdownEnd;let c=e.markdownBoundaries??[],l=0,p=c.length;for(;l<p;){let u=l+p>>>1;c[u].sourceOffset<d?l=u+1:p=u;}return c[l]?.sourceOffset===d?c[l].markdownOffset:null},s=a(o),i=a(t);return s===null||i===null?null:{start:s,end:i,unit:"utf16-code-unit",precision:"exact"}}function $e(e){let n=[];for(let r of e){let o=n[n.length-1],t=o&&r.start<o.end,a=o&&r.start===o.end&&r.precision===o.precision;o&&(t||a)?n[n.length-1]={start:o.start,end:Math.max(o.end,r.end),unit:"utf16-code-unit",precision:o.precision==="containing-construct"||r.precision==="containing-construct"?"containing-construct":"exact"}:n.push(r);}return Object.freeze(n.map(r=>Object.freeze(r)))}function An(e){let n=new Map;for(let[s,i]of e.sources.entries()){let d=v(i.sourceScope,i.paragraphId),c=n.get(d)??[];c.push({index:s,slice:i}),n.set(d,c);}let r=new Map;for(let[s,i]of n){let d=i.sort((g,f)=>g.slice.sourceStart-f.slice.sourceStart||g.slice.sourceEnd-f.slice.sourceEnd||g.index-f.index),c=[],l=new Map,p=new Map,u=Number.NEGATIVE_INFINITY;for(let[g,f]of d.entries()){u=Math.max(u,f.slice.sourceEnd),c[g]=u;let w=l.get(f.slice.sourceStart)??[];w.push(f),l.set(f.slice.sourceStart,w);let m=p.get(f.slice.sourceEnd)??[];m.push(f),p.set(f.slice.sourceEnd,m);}r.set(s,{entries:d,prefixMaxEnd:c,byStart:l,byEnd:p});}let o=[];for(let s of e.paragraphs??[]){let i=o[o.length-1];i&&i.sourceScope===s.sourceScope&&i.paragraphId===s.paragraphId?o[o.length-1]={...i,sourceStart:Math.min(i.sourceStart,s.sourceStart),sourceEnd:Math.max(i.sourceEnd,s.sourceEnd)}:o.push(s);}let t=new Map,a=new Map;for(let s of o){let i=a.get(s.sourceScope)??[];i.push(s),a.set(s.sourceScope,i);}for(let[s,i]of a){let d=new Map;for(let[c,l]of i.entries()){let p=d.get(l.paragraphId)??[];p.push(c),d.set(l.paragraphId,p);}t.set(s,{entries:i,positionsByParagraphId:d});}return {sources:e.sources,bySourceKey:r,paragraphsByScope:t}}function ze(e,n){let r=0,o=e.length;for(;r<o;){let t=r+o>>>1;e[t]<n?r=t+1:o=t;}return e[r]??-1}function se(e,n){let r=0,o=e.prefixMaxEnd.length;for(;r<o;){let t=r+o>>>1;e.prefixMaxEnd[t]<=n?r=t+1:o=t;}return r}function Cn(e,n,r){let o=[];for(let t=se(e,n);t<e.entries.length;t+=1){let a=e.entries[t];if(a.slice.sourceStart>=r)break;a.slice.sourceEnd>n&&o.push(a);}return o.sort((t,a)=>t.index-a.index)}function On(e,n){let r=d=>d.reduce((c,l)=>!c||l.index<c.index?l:c,void 0),o=r(e.byStart.get(n)??[]),t=[];for(let d=se(e,n);d<e.entries.length;d+=1){let c=e.entries[d];if(c.slice.sourceStart>=n)break;c.slice.sourceEnd>n&&t.push(c);}let a=r(t),s=o??a??r(e.byEnd.get(n)??[]);if(!s)return Object.freeze([]);let i=ae(s.slice,n,n);return Object.freeze(i?[Object.freeze(i)]:[])}function te(e,n,r){let o=n;for(let t of [...e].sort((a,s)=>a.start-s.start||a.end-s.end))if(!(t.end<=o)){if(t.start>o)return false;if(o=t.end,o>=r)return true}return o>=r}function oe(e,n){return e.length===0?"none":n?"complete":"partial"}function Fn(e,n){let r=We(n.rootStory,n.source.partName,n.noteScopeId),o=n.source,{start:t,end:a}=o;if(t.paragraphId===a.paragraphId){let w=e.bySourceKey.get(v(r,t.paragraphId));if(!w)return {ranges:Object.freeze([]),coverage:"none"};if(t.offset===a.offset){let h=On(w,t.offset);return {ranges:h,coverage:oe(h,h.length>0)}}let m=[],y=Cn(w,t.offset,a.offset).map(({slice:h})=>{let S=ae(h,t.offset,a.offset);return S&&m.push({start:Math.max(t.offset,h.sourceStart),end:Math.min(a.offset,h.sourceEnd)}),S}).filter(h=>h!==null),M=$e(y);return {ranges:M,coverage:oe(M,te(m,t.offset,a.offset))}}let s=e.bySourceKey.get(v(r,t.paragraphId)),i;if(s)for(let w=se(s,t.offset);w<s.entries.length;w+=1){let m=s.entries[w];if(!(m.slice.sourceEnd<=t.offset)){i=m.index;break}}if(i===void 0){let w=e.paragraphsByScope.get(r),m=w?.positionsByParagraphId.get(t.paragraphId)?.[0];if(w&&m!==void 0){let y=ze(w.positionsByParagraphId.get(a.paragraphId)??[],m);for(let M=m+1;M>=0&&M<=y;M+=1){let h=w.entries[M],E=e.bySourceKey.get(v(r,h.paragraphId))?.entries.reduce((R,D)=>!R||D.index<R.index?D:R,void 0);if(E){i=E.index;break}}}}if(i===void 0)return {ranges:Object.freeze([]),coverage:"none"};let d=[],c=new Map,l=new Map,p=false;for(let w=i;w<e.sources.length;w+=1){let m=e.sources[w];if(m.sourceScope!==r||m.paragraphId===t.paragraphId&&m.sourceEnd<=t.offset)continue;let y=m.paragraphId===t.paragraphId?t.offset:m.sourceStart,M=m.paragraphId===a.paragraphId?a.offset:m.sourceEnd,h=Math.max(y,m.sourceStart),S=Math.min(M,m.sourceEnd),E=l.get(m.paragraphId);l.set(m.paragraphId,{start:Math.min(E?.start??h,h),end:Math.max(E?.end??S,S)});let R=ae(m,y,M);if(R){d.push(R);let D=c.get(m.paragraphId)??[];D.push({start:h,end:S}),c.set(m.paragraphId,D);}if(m.paragraphId===a.paragraphId&&m.sourceEnd>=a.offset){p=true;break}}let u=$e(d),g=p,f=e.paragraphsByScope.get(r);if(g&&f&&f.entries.length>0){let w=f.positionsByParagraphId.get(t.paragraphId)?.[0]??-1,m=ze(f.positionsByParagraphId.get(a.paragraphId)??[],Math.max(0,w));g=w>=0&&m>=w;for(let y=w;g&&y<=m;y+=1){let M=f.entries[y],h=M.paragraphId===t.paragraphId?t.offset:M.sourceStart,S=M.paragraphId===a.paragraphId?a.offset:M.sourceEnd;te(c.get(M.paragraphId)??[],h,S)||(g=false);}}else if(g)for(let[w,m]of l){let y=w===t.paragraphId?t.offset:0,M=w===a.paragraphId?a.offset:m.end;if(!te(c.get(w)??[],y,M)){g=false;break}}return {ranges:u,coverage:oe(u,g)}}function Bn(e){return Object.freeze({kind:"page",pageIndex:e.pageIndex,pageNumber:e.physicalPageNumber,field:e.rootStory==="header"?"headerMarkdown":e.rootStory==="footer"?"footerMarkdown":"markdown"})}function Dn(e,n,r){return n.story==="textbox"||n.rootStory==="note-separator"?"omitted-story-content":e.kind==="tracked-change"&&e.change==="structural"?"non-linear-structural-change":r.length===0?"not-represented-in-markdown":void 0}function Ue(e,n,r){let o=[],t=new WeakMap,a=i=>{let d=t.get(i);if(d)return d;let c=An(i);return t.set(i,c),c},s=(i,d,c,l,p)=>{let u=d.story==="textbox"||d.rootStory==="note-separator"||i.kind==="tracked-change"&&i.change==="structural"?{ranges:Object.freeze([]),coverage:"none"}:Fn(a(p),d),g=Dn(i,d,u.ranges);o.push(Object.freeze({artifactId:i.id,artifactKind:i.kind,occurrenceIndex:c,projection:l,ranges:u.ranges,coverage:u.coverage,...g?{unmappedReason:g}:{}}));};for(let i of e)for(let[d,c]of i.occurrences.entries()){let l=Bn(c),p=r.get(c.pageIndex);s(i,c,d,l,p?.[l.field]??x),c.story!=="textbox"&&(c.rootStory==="body"||c.rootStory==="footnote"||c.rootStory==="endnote")&&s(i,c,d,Object.freeze({kind:"document"}),n);}return Object.freeze(o)}var Ke=new Map;function Ve(e){let n=new Map,r=new Map,o=(t,a,s,i)=>{let d=t.get(a)??{kind:s,blocks:[]};d.blocks.push(...i),t.set(a,d);};return forEachSemanticStory(e,({page:t,story:a,host:s,noteScopeId:i})=>{if(i===null||a!=="footnote"&&a!=="endnote")return;o(n,i,a,s.fragments);let d=r.get(t);d||(d=new Map,r.set(t,d)),o(d,i,a,s.fragments);}),{document:n,byPage:r}}function qe(e){let n=new Map;return forEachSemanticSpan(e,({span:r,story:o})=>{o!=="textbox"&&(r.noteNav?.direction!=="to-note"||n.has(r.noteNav.scopeId)||n.set(r.noteNav.scopeId,String(n.size+1)));}),n}var $n=Object.freeze([]);function de(e,n,r){switch(e){case "body":return "body";case "header":case "footer":return `${e}:${n}`;case "footnote":case "endnote":return `${e}:${r??n}`;case "note-separator":return `note-separator:${n}`}}function Ze(e,n){return Ee(e,n.media,n.tableCell)}function ce(e){return b(Te(e.anchors,e.media,e.pageIndex).map(n=>en(n,e,Ze(n,e))),`
|
|
12
|
+
|
|
13
|
+
`)}function Qe(e,n){let r=e.sourceCapture;return !!(r&&(r.allSourceScopes.has(e.sourceScope)||r.offsetsBySource.has(v(e.sourceScope,n))))}function en(e,n,r){return r.length===0?x:Qe(n,e.paragraphId)?{markdown:r,sources:[{sourceScope:n.sourceScope,paragraphId:e.paragraphId,sourceStart:e.start,sourceEnd:e.start+1,markdownStart:0,markdownEnd:r.length,exact:false}]}:k(r)}function zn(e,n){if(!e.noteNav)return null;switch(e.noteNav.direction){case "to-note":{let r=n.noteLabelByScope.get(e.noteNav.scopeId);return r&&n.emittedNoteLabels?.add(r),r?`[^${r}]`:""}case "to-body":return "";default:return q(e.noteNav.direction)}}function Wn(e){let n=e.map(t=>({...t})),r=[];for(let t=0;t<n.length;t+=1){let a=n[t];if(a.sourceText.length===0)continue;let s=/^\s+/.exec(a.sourceText);if(!s||(r.push({...a,sourceText:s[0]}),n[t]={...a,sourceText:a.sourceText.slice(s[0].length),sourceOffset:(a.sourceOffset??0)+s[0].length},n[t].sourceText.length>0))break}let o=[];for(let t=n.length-1;t>=0;t-=1){let a=n[t];if(a.sourceText.length===0)continue;let s=/\s+$/.exec(a.sourceText);if(!s||(o.unshift({...a,sourceText:s[0],sourceOffset:(a.sourceOffset??0)+a.sourceText.length-s[0].length}),n[t]={...a,sourceText:a.sourceText.slice(0,-s[0].length)},n[t].sourceText.length>0))break}return {leading:r,content:n,trailing:o}}function ie(e,n){let r=new j(n);for(let o of e)r.writeText(o);return r.finishMapped()}function _n(e,n,r){let{leading:o,content:t,trailing:a}=Wn(e),s=ie(o,r),i=ie(t,r),d=ie(a,r);return i.markdown.length===0&&s.markdown.length+d.markdown.length>0?C(b([s,d]),"[",`](${U(n)})`):b([s,i.markdown.length>0?b([k("["),i,k(`](${U(n)})`)]):x,d])}function Hn(e,n){return e===n||e!==void 0&&n!==void 0&&e.id===n.id&&e.kind===n.kind&&e.href===n.href&&e.anchor===n.anchor&&e.tooltip===n.tooltip}function Un(e,n,r){for(let o=0;o<e.length;o+=1){let t=e[o];if(t.kind==="drawing"){let i=Ze(t.drawing,n);r.writeMappedBoundary(en(t.drawing,n,i)),i.length===0&&Kn(e,o)&&r.writeBoundary(" ");continue}let a=t.span.range.paragraphId,s=zn(t.span,n);if(s!==null){s.length>0&&Qe(n,a)?r.writeMappedBoundary({markdown:s,sources:[{sourceScope:n.sourceScope,paragraphId:a,sourceStart:t.span.range.start,sourceEnd:t.span.range.end,markdownStart:0,markdownEnd:s.length,exact:false}]}):r.writeBoundary(s);continue}if(t.span.link?.kind==="external"&&t.span.link.href){let i=[$(t)];for(;e[o+1]?.kind==="span";){let d=e[o+1];if(d.kind!=="span"||d.span.noteNav||!Hn(t.span.link,d.span.link))break;i.push($(d)),o+=1;}r.writeMappedBoundary(_n(i,t.span.link.href,n));continue}r.writeText($(t));}}function Ye(e){return e?.kind==="span"?$(e).sourceText:""}function Kn(e,n){if(e[n-1]?.kind==="drawing")return false;let r=n+1;for(;e[r]?.kind==="drawing";)r+=1;let o=Ye(e[n-1]),t=Ye(e[r]);return /[\p{L}\p{N}_]\p{M}*$/u.test(o)&&/^[\p{L}\p{N}_]\p{M}*/u.test(t)}function Vn(e,n){let r=new j(n),o=[];for(let t of e)for(let a of t.lines)for(let s of lineSegments(a))o.push(...Ce(s));return Un(Oe(o,n.anchors,e[0]?.paragraphId??""),n,r),r.finishMapped()}function qn(e){let n=false;for(let r of e)for(let o of r.lines)for(let t of lineSegments(o))for(let a of t.spans)if(L(a).trim().length!==0&&(n=true,!a.style.bold))return false;return n}function Yn(e,n,r=true){let o=e[0];if(!o)return x;let t=o.outlineLevel===null?null:o.outlineLevel+1,a=!n.tableCell&&t!==null&&t>=1&&t<=9?`${"#".repeat(Math.min(t,6))} `:"",s=ge(Vn(e,a.length>0?{...n,hardBreakHtml:true,suppressBold:qn(e)}:n)),i=o.marker??n.listMarkerByParagraphId.get(o.paragraphId),d=" ".repeat(n.listIndentByParagraphId.get(o.paragraphId)??(i?.level??0)*4),c;if(!r&&o.fragmentIndex>0)if(!i)c=s;else {let u=i.numFmt==="bullet"?"-":`${i.ordinal??1}.`;c=C(s,`${d}${" ".repeat(u.length+1)}`);}else if(i){let u=i.numFmt==="bullet"?"-":`${i.ordinal??1}.`;c=C(s,`${d}${u} ${a}`);}else c=C(s,a);if(!n.sourceCapture?.allSourceScopes.has(n.sourceScope))return c;let l=u=>{if(u.range)return u.range;let g=u.lines.map(f=>f.range);return {start:Math.min(...g.map(f=>f.start)),end:Math.max(...g.map(f=>f.end))}},p=e.map(l);return Z(c,[{sourceScope:n.sourceScope,paragraphId:o.paragraphId,sourceStart:Math.min(...p.map(u=>u.start)),sourceEnd:Math.max(...p.map(u=>u.end))}])}function F(e,n,r=false,o=false){let t=e.map(s=>{switch(s.kind){case "paragraph":return Yn(s.fragments,n,!o);case "table":return n.tableCell?je(s.fragments,n,o,F):Le(s.fragments,n,o,F);default:return q(s)}}),a=b(t.filter((s,i)=>s.markdown.length>0||i<t.length-1),r?`
|
|
14
|
+
`:`
|
|
15
|
+
|
|
16
|
+
`);return Z(a,t.flatMap(s=>s.paragraphs??[]))}function nn(e){return P(e.pages.flatMap(n=>n.fragments))}function Gn(e){return (e.numFmt==="bullet"?"-":`${e.ordinal??1}.`).length+1}function z(e,n,r){let o=new Map,t=null;for(let a of e){if(a.kind==="table"){o.clear(),t=null;for(let c of O(a.fragments,false))for(let l of c.cells)z(P(l.blocks),n,r);continue}let s=a.fragments[0];if(!s)continue;let i=a.fragments.find(c=>c.marker)?.marker;if(!i){o.clear(),t=null;continue}t!==i.numId&&o.clear(),t=i.numId;let d=0;for(let c=0;c<i.level;c+=1)d+=o.get(c)??0;n.set(s.paragraphId,d),r.set(s.paragraphId,i),o.set(i.level,Gn(i));for(let c of o.keys())c>i.level&&o.delete(c);}}function Xn(e){let n=new Map,r=new Map,o=new Map;return z(nn(e),n,r),forEachSemanticStory(e,({story:t,host:a})=>{t==="header"||t==="footer"||t==="note-separator"||Y(a.fragments,o);}),{listIndentByParagraphId:n,listMarkerByParagraphId:r,tablesById:o}}function Jn(e,n){let r=P(e.fragments),o=new Map,t=new Map,a=new Set;z(r,o,t);let s={...n,pageIndex:e.index,anchors:V(e.anchoredDrawings??[],n.media),listIndentByParagraphId:o,listMarkerByParagraphId:t,emittedNoteLabels:a},i=F(r,s,false,true),d=ce(s);return {value:b([i,d].filter(c=>c.markdown.length>0),`
|
|
17
|
+
|
|
18
|
+
`),noteLabels:a}}function Zn(e,n){let r=new Map,o=new Map,t=new Map;z(P(e.fragments),r,o),Y(e.fragments,t);let a={...n,sourceScope:de(e.kind,e.partName,null),anchors:V(e.anchoredDrawings??[],n.media),listIndentByParagraphId:r,listMarkerByParagraphId:o,tablesById:t},s=F(P(e.fragments),a);return b([s,ce(a)].filter(i=>i.markdown.length>0),`
|
|
19
|
+
|
|
20
|
+
`)}function Qn(e,n,r){let t=`> **${e.kind==="footnote"?"Footnote":"Endnote"} ${n} (continued):**`;return r.markdown.length===0?k(t):b([k(`${t}
|
|
21
|
+
>
|
|
22
|
+
`),ye(r)])}function Ge(e,n,r=false,o=new Set,t=new Set){let a=[];for(let[s,i]of e){let d=n.noteLabelByScope.get(s);if(!d)continue;let c=P(i.blocks),l=new Map,p=new Map;z(c,l,p);let u={...n,sourceScope:de(i.kind,"",s),anchors:void 0,listIndentByParagraphId:l,listMarkerByParagraphId:p},g=F(c,u,false,r),f=r&&t.has(s)&&!o.has(d);if(r&&t.add(s),f){a.push(Qn(i,d,g));continue}let w=we(g," ");a.push(C(w,`[^${d}]: `));}return b(a,`
|
|
23
|
+
|
|
24
|
+
`)}function Xe(e,n){return b([e,n].filter(r=>r.markdown.length>0),`
|
|
25
|
+
|
|
26
|
+
`)}function W(e,n,r="markdown"){let o=e.reviewArtifacts??$n,t=e.displayMode??"all-markup",a=Xn(e),s=Ve(e),i=n===void 0?void 0:Pe(n,r),d={media:i,anchors:V(e.pages.flatMap(y=>y.anchoredDrawings??[]),i),noteLabelByScope:qe(e),tableCell:false,displayMode:t,sourceScope:de("body","",null),sourceCapture:_e(o),...a},c=Xe(b([F(nn(e),d),ce(d)].filter(y=>y.markdown.length>0),`
|
|
27
|
+
|
|
28
|
+
`),Ge(s.document,d)),l=He(o),p=new Set,u=new WeakMap,g=y=>{if(!y)return x;let M=`${y.kind}:${y.partName}`,h=u.get(y.fragments);if(h&&h.scope===M)return h.value;let S=Zn(y,d);return u.set(y.fragments,{scope:M,value:S}),S},f=new Map,w=e.pages.map(y=>{let M={...d,pageIndex:y.index},h=Jn(y,d),S=Ge(s.byPage.get(y)??Ke,M,true,h.noteLabels,p),E=l.get(y.index),R={markdown:Xe(h.value,S),headerMarkdown:g(y.header),footerMarkdown:g(y.footer)};return f.set(y.index,R),Object.freeze({id:y.id,number:y.index+1,markdown:R.markdown.markdown,headerMarkdown:R.headerMarkdown.markdown,footerMarkdown:R.footerMarkdown.markdown,comments:Object.freeze(E?.comments??[]),trackedChanges:Object.freeze(E?.trackedChanges??[])})}),m=Fe(e,i);return Object.freeze({media:n??Object.freeze([]),warnings:Object.freeze(m),pages:Object.freeze(w),reviewArtifacts:o,reviewBindings:Ue(o,c,f),fontResolution:null,pagination:Object.freeze({source:"layout-engine",scope:"export-snapshot",layoutRevision:e.revision,displayMode:t}),markdown:c.markdown})}async function rn(e,n){let r=n.resourceTimeoutMs??6e4;if(!Number.isFinite(r)||r<=0)throw new RangeError("resourceTimeoutMs must be a positive finite number");if(n.signal?.aborted)throw new ExportResourceError("aborted","Font provisioning was aborted",{cause:n.signal.reason});let o=new AbortController,t,a=new Promise((d,c)=>{t=c;}),s=()=>{let d=new ExportResourceError("aborted","Font provisioning was aborted",{cause:n.signal?.reason});t?.(d),o.abort(d);};n.signal?.addEventListener("abort",s,{once:true});let i=setTimeout(()=>{let d=new ExportResourceError("timedOut","Font provisioning timed out");t?.(d),o.abort(d);},Math.max(1,r));try{return await Promise.race([Promise.resolve().then(()=>e(o.signal)),a])}catch(d){throw d instanceof ExportResourceError?d:o.signal.reason instanceof ExportResourceError?o.signal.reason:new ExportResourceError("layoutFailed","Font provisioning failed",{cause:d})}finally{clearTimeout(i),n.signal?.removeEventListener("abort",s),t=void 0;}}function tn(e){let n,r;return async o=>{if(n!==void 0)return n;if(o.aborted)throw o.reason;let t=r;if(!t){let d=new AbortController,c={controller:d,subscribers:0,promise:void 0};c.promise=Promise.resolve().then(()=>e(d.signal)).then(l=>(r===c&&(n??=l),n??l)).finally(()=>{r===c&&(r=void 0);}),r=c,t=c;}t.subscribers+=1;let a,s=new Promise((d,c)=>{a=c;}),i=()=>a?.(o.reason);o.addEventListener("abort",i,{once:true});try{return await Promise.race([t.promise,s])}finally{o.removeEventListener("abort",i),a=void 0,t.subscribers-=1,t.subscribers===0&&r===t&&n===void 0&&(r=void 0,t.controller.abort(o.reason));}}}var le=class extends Error{constructor(r,o){super(`Unable to open DOCX for export: ${r}${o?` (${o})`:""}`);this.reason=r;this.detail=o;this.name="DocumentOpenError";}reason;detail},ln=FONT_ASSET_ROOT.protocol==="file:"?createPackagedFileFetch({trustedRoot:new URL("./",FONT_ASSET_ROOT),maxBytes:HARD_MAX_FONT_BYTES}):fetch,dr=tn(async e=>{let n=await loadDefaultFonts({fetcher:ln,signal:e});if(n.failures.length>0||n.sources.length===0){let t=n.failures.map(a=>`${a.file}: ${a.diagnostic}`).join("; ");throw new Error(`Unable to provision packaged fonts for headless export${t?`: ${t}`:""}`)}let r=Object.freeze({epoch:1,maxFontBytes:HARD_MAX_FONT_BYTES,sources:n.sources,substitutions:n.substitutions,defaultFont:Object.freeze({family:"Calibri",sizeHalfPoints:22})}),o=prepareLayoutFontConfiguration(r);return Object.freeze({configuration:o})}),cr=packagedFonts({fetcher:ln,onFailure(){}}),lr=defineFontResolver(async e=>{let n=await cr(e);return {...n,failures:n.failures.map(r=>new Error(`Unable to load bundled font ${r.file}: ${r.diagnostic}. In Next.js, add the converter, core, and fonts packages to serverExternalPackages.`))}});function pr(e){return ArrayBuffer.isView(e)}function sn(e){return e===void 0?[]:Array.isArray(e)?e:[e]}function ur(e,n){return Object.freeze({fontResolution:n,layout:()=>e.layout(),layoutFor:r=>e.layoutFor(r),validatedImageBytes:r=>e.validatedImageBytes(r),dispose:()=>e.dispose()})}function dn(e,n){return e.ok?{ok:true,session:ur(e.session,n)}:e}function gr(e){return e.ok?{ok:true,session:e.session}:e}function pn(e,n){let r=[...e.warnings];for(let o of n?.originFailures??[]){let t="unknown error";try{o.cause instanceof Error&&typeof o.cause.message=="string"&&(t=o.cause.message);}catch{}r.push(Object.freeze({code:"font-origin-failed",message:`A font source failed: ${t}`}));}for(let o of n?.families??[])o.coverage!=="complete"&&r.push(Object.freeze({code:"incomplete-font",message:`Font coverage is incomplete for ${o.family}; page breaks may differ.`}));return Object.freeze({...e,fontResolution:n,warnings:Object.freeze(r)})}async function fr(e,n={}){let{fonts:r,fallbackFonts:o,...t}=n;if(n.measurer){if(n.fontPolicy!==void 0||n.onFontResolution!==void 0)throw new TypeError("fontPolicy and onFontResolution cannot verify a caller-supplied measurer; omit measurer to use document-aware Core font resolution");return dn(await openDocumentForExport(e,t),null)}let a=sn(n.fonts),s=sn(n.fallbackFonts);if(pr(e)){if(n.reuseAcrossRevisions===true)throw new TypeError("reuseAcrossRevisions requires a live view or caller-supplied measurer; document-aware byte sessions are immutable");let d=await openFontBackedDocumentForExport(e,{...t,reuseAcrossRevisions:false,fonts:[...a,lr,...s],onFontResolution:n.onFontResolution});return gr(d)}if(a.length>0||s.length>0)throw new TypeError("fonts and fallbackFonts require immutable DOCX bytes; pass a revision-stable measurer when exporting a live HeadlessDocumentView");if(n.fontPolicy!==void 0||n.onFontResolution!==void 0)throw new TypeError("fontPolicy and onFontResolution require document-aware font resolution from immutable DOCX bytes; pass a revision-stable measurer when exporting a live HeadlessDocumentView");let i=await rn(d=>dr(d).then(c=>acquireSharedExportShaping(c.configuration)),n);return dn(await openDocumentForExport(e,{...t,reuseAcrossRevisions:n.reuseAcrossRevisions,measurer:i.createMeasurer(),producer:n.producer??i.producer}),null)}async function at(e,n={}){let r=_(n),o=await X(()=>e.layout(),n.signal);I(n.signal);let t=G(o,e,r),a=r?await J(t,n):void 0,s=W(o,a,r?.syntax);return pn(s,"fontResolution"in e?e.fontResolution:s.fontResolution)}function st(e){return W(e)}async function it(e,n={}){let r=_(n);I(n.signal);let{images:o,...t}=n,a=await fr(e,t);if(!a.ok)throw a.reason==="aborted"?new ExportResourceError("aborted","Export was aborted before layout",{cause:n.signal?.reason}):new le(a.reason,a.detail);let s,i;try{s=await a.session.layout(),I(n.signal),i=G(s,a.session,r);}finally{a.session.dispose();}let d=r?W(s,await J(i,n),r.syntax):W(s);return pn(d,a.session.fontResolution)}export{le as DocumentOpenError,it as exportMarkdown,at as exportMarkdownFrom,st as exportMarkdownLayout,fr as openDocumentForExport};
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
import { SemanticDrawingVisit, SemanticCommentArtifactRecord, SemanticTrackedChangeArtifactRecord, SemanticReviewArtifactRecord, RevisionDisplayMode } from '@docx-editor.dev/core/layout';
|
|
3
|
+
import { OpenDocumentForExportOptions, FontOrigin, ExportFontResolutionReport } from '@docx-editor.dev/core/export';
|
|
4
|
+
|
|
5
|
+
/** One physical occurrence of an extracted image. @public */
|
|
6
|
+
interface MarkdownImageOccurrence {
|
|
7
|
+
readonly pageNumber: number;
|
|
8
|
+
readonly story: SemanticDrawingVisit['story'];
|
|
9
|
+
readonly rootStory: SemanticDrawingVisit['rootStory'];
|
|
10
|
+
readonly partName: string;
|
|
11
|
+
readonly drawingNodeId: string;
|
|
12
|
+
readonly paragraphId: string;
|
|
13
|
+
/** Source offset within the paragraph, in UTF-16 code units. */
|
|
14
|
+
readonly start: number;
|
|
15
|
+
/** Word's extent width in CSS pixels (96 px per inch), before crop or rotation. */
|
|
16
|
+
readonly displayWidthPx: number;
|
|
17
|
+
/** Word's extent height in CSS pixels (96 px per inch), before crop or rotation. */
|
|
18
|
+
readonly displayHeightPx: number;
|
|
19
|
+
/** Anchored images render at their paragraph position; Markdown does not reproduce text wrapping. */
|
|
20
|
+
readonly kind: 'inline' | 'anchored';
|
|
21
|
+
readonly decorative: boolean;
|
|
22
|
+
readonly alt: string;
|
|
23
|
+
}
|
|
24
|
+
/** Image bytes and provenance supplied to a URL resolver. @public */
|
|
25
|
+
interface MarkdownImageData {
|
|
26
|
+
/** Core's SHA-256 content identifier for the exported bytes. */
|
|
27
|
+
readonly id: string;
|
|
28
|
+
/** Portable relative filename, independent of the resolved URL. */
|
|
29
|
+
readonly path: string;
|
|
30
|
+
readonly mimeType: string;
|
|
31
|
+
/** Owned bytes. Treat as read-only to preserve the content identifier. */
|
|
32
|
+
readonly bytes: Uint8Array;
|
|
33
|
+
readonly byteLength: number;
|
|
34
|
+
/** Intrinsic pixel width of the exported bytes; use occurrence dimensions for display. */
|
|
35
|
+
readonly pixelWidth: number;
|
|
36
|
+
/** Intrinsic pixel height of the exported bytes; use occurrence dimensions for display. */
|
|
37
|
+
readonly pixelHeight: number;
|
|
38
|
+
readonly occurrences: readonly MarkdownImageOccurrence[];
|
|
39
|
+
}
|
|
40
|
+
/** One unique image returned by a Markdown export. @public */
|
|
41
|
+
interface MarkdownImageAsset extends MarkdownImageData {
|
|
42
|
+
/** Raw URL; Markdown output escapes destination syntax separately. */
|
|
43
|
+
readonly url: string;
|
|
44
|
+
}
|
|
45
|
+
/** Portable image extraction and optional application-owned storage. @public */
|
|
46
|
+
interface MarkdownImageOptions {
|
|
47
|
+
/**
|
|
48
|
+
* Default: `markdown` emits standard image links without dimensions.
|
|
49
|
+
* `html` emits an escaped `<img>` with each occurrence's display width and height,
|
|
50
|
+
* rounded to whole CSS pixels. Your renderer must allow HTML and these attributes.
|
|
51
|
+
* Neither syntax reproduces cropping, rotation, or floating text wrapping.
|
|
52
|
+
*/
|
|
53
|
+
readonly syntax?: 'markdown' | 'html';
|
|
54
|
+
/**
|
|
55
|
+
* Called sequentially once per unique image, after all extraction succeeds. Receives a
|
|
56
|
+
* separate byte copy; mutations cannot change result bytes. Return a relative path or HTTP(S)
|
|
57
|
+
* URL. The application owns completed uploads, their cleanup, and signed-URL expiry.
|
|
58
|
+
*/
|
|
59
|
+
readonly resolveUrl?: (image: MarkdownImageData, context: {
|
|
60
|
+
readonly signal?: AbortSignal;
|
|
61
|
+
}) => string | Promise<string>;
|
|
62
|
+
/** Unique extracted bytes; default 64 MiB. Not a total parsing/layout memory limit. */
|
|
63
|
+
readonly maxTotalBytes?: number;
|
|
64
|
+
}
|
|
65
|
+
/** Projection controls for an already-open export session. @public */
|
|
66
|
+
interface MarkdownProjectionOptions {
|
|
67
|
+
/** `true` or `{}` extracts images with portable relative URLs. Default: false. */
|
|
68
|
+
readonly images?: boolean | MarkdownImageOptions;
|
|
69
|
+
/** Cancels export waits; cannot interrupt synchronous parsing or layout. */
|
|
70
|
+
readonly signal?: AbortSignal;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Page/story/source provenance for one exported review artifact. @public */
|
|
74
|
+
type MarkdownReviewOccurrence = SemanticReviewArtifactRecord['occurrences'][number];
|
|
75
|
+
/**
|
|
76
|
+
* Normalized DOCX comment, independent of editor UI state.
|
|
77
|
+
*
|
|
78
|
+
* Its ID is opaque and stable only within one {@link MarkdownExportResult}. Never persist the ID
|
|
79
|
+
* across exports; pair citations with the caller's own document version or content hash.
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
type MarkdownComment = SemanticCommentArtifactRecord;
|
|
83
|
+
/**
|
|
84
|
+
* Normalized DOCX tracked change, independent of editor UI state.
|
|
85
|
+
*
|
|
86
|
+
* Its ID is opaque and stable only within one {@link MarkdownExportResult}. Never persist the ID
|
|
87
|
+
* across exports; pair citations with the caller's own document version or content hash.
|
|
88
|
+
* @public
|
|
89
|
+
*/
|
|
90
|
+
type MarkdownTrackedChange = SemanticTrackedChangeArtifactRecord;
|
|
91
|
+
/**
|
|
92
|
+
* Comment or tracked change returned by Markdown export. IDs are opaque and result-local.
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
type MarkdownReviewArtifact = SemanticReviewArtifactRecord;
|
|
96
|
+
/** A UTF-16 range suitable for slicing the named Markdown projection. @public */
|
|
97
|
+
interface MarkdownReviewRange {
|
|
98
|
+
/** Inclusive start offset in the selected Markdown string. */
|
|
99
|
+
readonly start: number;
|
|
100
|
+
/** Exclusive end offset in the selected Markdown string. */
|
|
101
|
+
readonly end: number;
|
|
102
|
+
/** Offsets use JavaScript string indexing and can be passed directly to `String.slice()`. */
|
|
103
|
+
readonly unit: 'utf16-code-unit';
|
|
104
|
+
/** Whether this is an exact text mapping or the smallest generated construct containing it. */
|
|
105
|
+
readonly precision: MarkdownReviewRangePrecision;
|
|
106
|
+
}
|
|
107
|
+
/** Precision of a source-to-Markdown review range. @public */
|
|
108
|
+
type MarkdownReviewRangePrecision = 'exact' | 'containing-construct';
|
|
109
|
+
/** How much of one Core source occurrence is represented by the returned ranges. @public */
|
|
110
|
+
type MarkdownReviewCoverage = 'complete' | 'partial' | 'none';
|
|
111
|
+
/** Markdown string containing one review binding. @public */
|
|
112
|
+
type MarkdownReviewProjection = {
|
|
113
|
+
/** Selects `MarkdownExportResult.markdown`. */
|
|
114
|
+
readonly kind: 'document';
|
|
115
|
+
} | {
|
|
116
|
+
/** Selects one field on one entry in `MarkdownExportResult.pages`. */
|
|
117
|
+
readonly kind: 'page';
|
|
118
|
+
/** Zero-based index into `MarkdownExportResult.pages`. */
|
|
119
|
+
readonly pageIndex: number;
|
|
120
|
+
/** One-based page number, included for citation and validation. */
|
|
121
|
+
readonly pageNumber: number;
|
|
122
|
+
/** Markdown page field containing the bound ranges. */
|
|
123
|
+
readonly field: 'markdown' | 'headerMarkdown' | 'footerMarkdown';
|
|
124
|
+
};
|
|
125
|
+
/** Why a source occurrence has no range in a particular Markdown projection. @public */
|
|
126
|
+
type MarkdownReviewUnmappedReason = 'not-represented-in-markdown' | 'non-linear-structural-change' | 'omitted-story-content';
|
|
127
|
+
/** Honest snapshot-local mapping from a Core review occurrence to generated Markdown. @public */
|
|
128
|
+
interface MarkdownReviewBinding {
|
|
129
|
+
/** ID of the corresponding artifact in this export result; do not join it across snapshots. */
|
|
130
|
+
readonly artifactId: string;
|
|
131
|
+
/** Discriminant of the corresponding review artifact. */
|
|
132
|
+
readonly artifactKind: MarkdownReviewArtifact['kind'];
|
|
133
|
+
/** Index into this snapshot's immutable artifact `occurrences` array. */
|
|
134
|
+
readonly occurrenceIndex: number;
|
|
135
|
+
/** Generated Markdown string containing this binding. */
|
|
136
|
+
readonly projection: MarkdownReviewProjection;
|
|
137
|
+
/** Ordered, non-overlapping ranges in the selected projection. */
|
|
138
|
+
readonly ranges: readonly MarkdownReviewRange[];
|
|
139
|
+
/** Whether the ranges represent all, some, or none of the source occurrence. */
|
|
140
|
+
readonly coverage: MarkdownReviewCoverage;
|
|
141
|
+
/** Present when the source occurrence has no honest linear range in this projection. */
|
|
142
|
+
readonly unmappedReason?: MarkdownReviewUnmappedReason;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Markdown emitted for one physical layout page. @public */
|
|
146
|
+
interface MarkdownPage {
|
|
147
|
+
/** Identifier for this page within this export result. */
|
|
148
|
+
readonly id: string;
|
|
149
|
+
/** One-based physical page number. */
|
|
150
|
+
readonly number: number;
|
|
151
|
+
/** Body projection, plus local note definitions or labelled continuation blocks. */
|
|
152
|
+
readonly markdown: string;
|
|
153
|
+
/** Header story for this page, kept separate from logical document content. */
|
|
154
|
+
readonly headerMarkdown: string;
|
|
155
|
+
/** Footer story for this page, kept separate from logical document content. */
|
|
156
|
+
readonly footerMarkdown: string;
|
|
157
|
+
/**
|
|
158
|
+
* Membership view of comments occurring on this page. Each entry is the complete document-wide
|
|
159
|
+
* artifact and can contain occurrences from other pages. For page-local provenance, filter with
|
|
160
|
+
* `occurrence.pageIndex === page.number - 1`.
|
|
161
|
+
*/
|
|
162
|
+
readonly comments: readonly MarkdownComment[];
|
|
163
|
+
/**
|
|
164
|
+
* Membership view of tracked changes occurring on this page. Each entry is the complete
|
|
165
|
+
* document-wide artifact and can contain occurrences from other pages. For page-local
|
|
166
|
+
* provenance, filter with `occurrence.pageIndex === page.number - 1`.
|
|
167
|
+
*/
|
|
168
|
+
readonly trackedChanges: readonly MarkdownTrackedChange[];
|
|
169
|
+
}
|
|
170
|
+
/** Machine-readable scope of the page numbers returned by this export. @public */
|
|
171
|
+
interface MarkdownPaginationInfo {
|
|
172
|
+
/** Pages come from the docx-editor semantic layout engine, not stale DOCX page-break hints. */
|
|
173
|
+
readonly source: 'layout-engine';
|
|
174
|
+
/** Page numbers describe this exact export result. */
|
|
175
|
+
readonly scope: 'export-snapshot';
|
|
176
|
+
/** Core store revision from which this layout snapshot was produced. */
|
|
177
|
+
readonly layoutRevision: number;
|
|
178
|
+
/** Tracked-change display mode used to paginate and translate this snapshot. */
|
|
179
|
+
readonly displayMode: RevisionDisplayMode;
|
|
180
|
+
}
|
|
181
|
+
/** Content or resources that could not be represented fully. @public */
|
|
182
|
+
interface MarkdownWarning {
|
|
183
|
+
/** Stable code for filtering warnings without parsing messages. */
|
|
184
|
+
readonly code: 'omitted-drawing' | 'omitted-textbox' | 'font-origin-failed' | 'incomplete-font' | 'content-scan-limit' | 'image-placement-fallback';
|
|
185
|
+
/** Human-readable description of the limitation. */
|
|
186
|
+
readonly message: string;
|
|
187
|
+
/** One-based page number, when the warning concerns a drawing occurrence. */
|
|
188
|
+
readonly pageNumber?: number;
|
|
189
|
+
/** Package part when the warning comes from source inspection. */
|
|
190
|
+
readonly partName?: string;
|
|
191
|
+
}
|
|
192
|
+
/** Full logical document plus page-scoped projections. @public */
|
|
193
|
+
interface MarkdownExportResult {
|
|
194
|
+
/** Unique extracted images; empty unless images are enabled. */
|
|
195
|
+
readonly media: readonly MarkdownImageAsset[];
|
|
196
|
+
/** Omitted content and font problems that may affect completeness or pagination. */
|
|
197
|
+
readonly warnings: readonly MarkdownWarning[];
|
|
198
|
+
/** Primary physical page projections, preserving Word layout boundaries and furniture. */
|
|
199
|
+
readonly pages: readonly MarkdownPage[];
|
|
200
|
+
/**
|
|
201
|
+
* Every normalized comment and tracked change, including artifacts without a page occurrence.
|
|
202
|
+
* Artifact IDs are opaque and stable only within this result.
|
|
203
|
+
*/
|
|
204
|
+
readonly reviewArtifacts: readonly MarkdownReviewArtifact[];
|
|
205
|
+
/** Markdown offsets valid only within this immutable result, with explicit mapping fidelity. */
|
|
206
|
+
readonly reviewBindings: readonly MarkdownReviewBinding[];
|
|
207
|
+
/** Structured font-resolution evidence, or null when the layout's font origin is unavailable. */
|
|
208
|
+
readonly fontResolution: ExportFontResolutionReport | null;
|
|
209
|
+
/** How page numbers and tracked changes were projected for this result. */
|
|
210
|
+
readonly pagination: MarkdownPaginationInfo;
|
|
211
|
+
/** Convenience logical Markdown with split records joined and repeated furniture excluded. */
|
|
212
|
+
readonly markdown: string;
|
|
213
|
+
}
|
|
214
|
+
/** One caller-controlled font origin used for headless pagination. @public */
|
|
215
|
+
type MarkdownFontOrigin = FontOrigin;
|
|
216
|
+
/** One font origin, or an ordered first-wins list of origins. @public */
|
|
217
|
+
type MarkdownFontsSource = MarkdownFontOrigin | readonly MarkdownFontOrigin[];
|
|
218
|
+
/** Layout controls for a reusable Markdown export session. @public */
|
|
219
|
+
interface OpenMarkdownDocumentForExportOptions extends OpenDocumentForExportOptions {
|
|
220
|
+
/**
|
|
221
|
+
* Retains incremental state for a live view or caller-measured session. Document-aware byte
|
|
222
|
+
* sessions are immutable and reject `true` instead of silently ignoring it.
|
|
223
|
+
*/
|
|
224
|
+
readonly reuseAcrossRevisions?: boolean;
|
|
225
|
+
/**
|
|
226
|
+
* Caller-supplied font bytes or resolvers, in first-wins order. These take precedence over the
|
|
227
|
+
* package's bundled metric-compatible Word substitutes. A resolver is invoked after the DOCX is
|
|
228
|
+
* parsed with the bounded family list layout can render. Custom origins require immutable DOCX
|
|
229
|
+
* bytes; for a live view, supply a revision-stable `measurer` instead. An explicit measurer takes
|
|
230
|
+
* precedence and font origins are not invoked.
|
|
231
|
+
*/
|
|
232
|
+
readonly fonts?: MarkdownFontsSource;
|
|
233
|
+
/**
|
|
234
|
+
* Opt-in origins consulted only after caller fonts and bundled substitutes. Put
|
|
235
|
+
* `googleFonts()` here to fetch catalogued families the local origins cannot paint. This has the
|
|
236
|
+
* same immutable-bytes restriction and explicit-measurer precedence as {@link fonts}.
|
|
237
|
+
*/
|
|
238
|
+
readonly fallbackFonts?: MarkdownFontsSource;
|
|
239
|
+
/** `strict` refuses failed origins or any requested family missing one of four static faces. */
|
|
240
|
+
readonly fontPolicy?: 'best-effort' | 'strict';
|
|
241
|
+
/**
|
|
242
|
+
* Fire-and-forget evidence for the exact direct/substituted faces behind page breaks. Returned
|
|
243
|
+
* promises are observed for rejection but do not delay export.
|
|
244
|
+
*/
|
|
245
|
+
readonly onFontResolution?: (report: ExportFontResolutionReport) => void;
|
|
246
|
+
}
|
|
247
|
+
/** Layout and resource controls for one-shot Markdown export. @public */
|
|
248
|
+
interface MarkdownExportOptions extends OpenMarkdownDocumentForExportOptions, MarkdownProjectionOptions {
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export type { MarkdownImageAsset as M, OpenMarkdownDocumentForExportOptions as O, MarkdownExportResult as a, MarkdownExportOptions as b, MarkdownProjectionOptions as c, MarkdownComment as d, MarkdownFontOrigin as e, MarkdownFontsSource as f, MarkdownImageData as g, MarkdownImageOccurrence as h, MarkdownImageOptions as i, MarkdownPage as j, MarkdownPaginationInfo as k, MarkdownReviewArtifact as l, MarkdownReviewBinding as m, MarkdownReviewCoverage as n, MarkdownReviewOccurrence as o, MarkdownReviewProjection as p, MarkdownReviewRange as q, MarkdownReviewRangePrecision as r, MarkdownReviewUnmappedReason as s, MarkdownTrackedChange as t, MarkdownWarning as u };
|