@ai-matrx/print 0.6.2 → 0.7.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/CHANGELOG.md +48 -0
- package/README.md +38 -0
- package/dist/directives.cjs +38 -1
- package/dist/directives.cjs.map +1 -1
- package/dist/directives.d.cts +17 -1
- package/dist/directives.d.ts +17 -1
- package/dist/directives.js +38 -1
- package/dist/directives.js.map +1 -1
- package/dist/document.cjs +2842 -0
- package/dist/document.cjs.map +1 -0
- package/dist/document.d.cts +490 -0
- package/dist/document.d.ts +490 -0
- package/dist/document.js +2809 -0
- package/dist/document.js.map +1 -0
- package/dist/markdown.cjs +30 -2
- package/dist/markdown.cjs.map +1 -1
- package/dist/markdown.js +30 -2
- package/dist/markdown.js.map +1 -1
- package/dist/pdf.cjs.map +1 -1
- package/dist/pdf.js.map +1 -1
- package/dist/react.cjs +117 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +24 -1
- package/dist/react.d.ts +24 -1
- package/dist/react.js +117 -0
- package/dist/react.js.map +1 -1
- package/package.json +29 -3
package/dist/react.d.cts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
+
interface DocumentNotice {
|
|
4
|
+
code: "frontmatter-invalid" | "setting-ignored" | "xref-unresolved" | "citation-unresolved" | "html-stripped" | "image-unavailable" | "glyph-substituted" | "empty-document";
|
|
5
|
+
message: string;
|
|
6
|
+
remedy: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* @ai-matrx/print/core — the Block Print contract & print-window composition.
|
|
5
11
|
*
|
|
@@ -320,5 +326,22 @@ interface LabelSheetPreviewProps {
|
|
|
320
326
|
className?: string;
|
|
321
327
|
}
|
|
322
328
|
declare function LabelSheetPreview({ template: t, labels, startAtLabel, showCaption, ecLevel, calibration, pageIndex, className, }: LabelSheetPreviewProps): React.JSX.Element;
|
|
329
|
+
interface DocumentPrintPreviewProps {
|
|
330
|
+
/** Markdown source, frontmatter settings included. */
|
|
331
|
+
markdown: string;
|
|
332
|
+
/** File name / fallback title when the frontmatter has none. */
|
|
333
|
+
title?: string;
|
|
334
|
+
className?: string;
|
|
335
|
+
/** Called for every degraded or dropped piece (also listed in the panel). */
|
|
336
|
+
onNotice?: (notice: DocumentNotice) => void;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Print preview for a markdown document: the real PDF (the same file the PDF
|
|
340
|
+
* download gives you — pages, header/footer, TOC page numbers), a "Web" view
|
|
341
|
+
* of the HTML with a clickable TOC, and one-click export to PDF, Word, EPUB,
|
|
342
|
+
* HTML and Markdown. Everything comes from one parsed tree, so what you see
|
|
343
|
+
* is what every format contains. Engines load lazily on mount.
|
|
344
|
+
*/
|
|
345
|
+
declare function DocumentPrintPreview({ markdown, title, className, onNotice }: DocumentPrintPreviewProps): React.JSX.Element;
|
|
323
346
|
|
|
324
|
-
export { LabelSheetPreview, type LabelSheetPreviewProps, PrintOptionsDialog, type PrintOptionsDialogProps, usePrintOptions };
|
|
347
|
+
export { DocumentPrintPreview, type DocumentPrintPreviewProps, LabelSheetPreview, type LabelSheetPreviewProps, PrintOptionsDialog, type PrintOptionsDialogProps, usePrintOptions };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
+
interface DocumentNotice {
|
|
4
|
+
code: "frontmatter-invalid" | "setting-ignored" | "xref-unresolved" | "citation-unresolved" | "html-stripped" | "image-unavailable" | "glyph-substituted" | "empty-document";
|
|
5
|
+
message: string;
|
|
6
|
+
remedy: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* @ai-matrx/print/core — the Block Print contract & print-window composition.
|
|
5
11
|
*
|
|
@@ -320,5 +326,22 @@ interface LabelSheetPreviewProps {
|
|
|
320
326
|
className?: string;
|
|
321
327
|
}
|
|
322
328
|
declare function LabelSheetPreview({ template: t, labels, startAtLabel, showCaption, ecLevel, calibration, pageIndex, className, }: LabelSheetPreviewProps): React.JSX.Element;
|
|
329
|
+
interface DocumentPrintPreviewProps {
|
|
330
|
+
/** Markdown source, frontmatter settings included. */
|
|
331
|
+
markdown: string;
|
|
332
|
+
/** File name / fallback title when the frontmatter has none. */
|
|
333
|
+
title?: string;
|
|
334
|
+
className?: string;
|
|
335
|
+
/** Called for every degraded or dropped piece (also listed in the panel). */
|
|
336
|
+
onNotice?: (notice: DocumentNotice) => void;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Print preview for a markdown document: the real PDF (the same file the PDF
|
|
340
|
+
* download gives you — pages, header/footer, TOC page numbers), a "Web" view
|
|
341
|
+
* of the HTML with a clickable TOC, and one-click export to PDF, Word, EPUB,
|
|
342
|
+
* HTML and Markdown. Everything comes from one parsed tree, so what you see
|
|
343
|
+
* is what every format contains. Engines load lazily on mount.
|
|
344
|
+
*/
|
|
345
|
+
declare function DocumentPrintPreview({ markdown, title, className, onNotice }: DocumentPrintPreviewProps): React.JSX.Element;
|
|
323
346
|
|
|
324
|
-
export { LabelSheetPreview, type LabelSheetPreviewProps, PrintOptionsDialog, type PrintOptionsDialogProps, usePrintOptions };
|
|
347
|
+
export { DocumentPrintPreview, type DocumentPrintPreviewProps, LabelSheetPreview, type LabelSheetPreviewProps, PrintOptionsDialog, type PrintOptionsDialogProps, usePrintOptions };
|
package/dist/react.js
CHANGED
|
@@ -1537,7 +1537,124 @@ function LabelSheetPreview({
|
|
|
1537
1537
|
}
|
|
1538
1538
|
);
|
|
1539
1539
|
}
|
|
1540
|
+
var EXPORT_BUTTONS = [
|
|
1541
|
+
{ format: "pdf", label: "PDF" },
|
|
1542
|
+
{ format: "docx", label: "Word" },
|
|
1543
|
+
{ format: "epub", label: "EPUB" },
|
|
1544
|
+
{ format: "html", label: "HTML" },
|
|
1545
|
+
{ format: "markdown", label: "Markdown" }
|
|
1546
|
+
];
|
|
1547
|
+
function DocumentPrintPreview({ markdown, title, className, onNotice }) {
|
|
1548
|
+
const [view, setView] = useState("pages");
|
|
1549
|
+
const [pdf, setPdf] = useState(null);
|
|
1550
|
+
const [html, setHtml] = useState("");
|
|
1551
|
+
const [notices, setNotices] = useState([]);
|
|
1552
|
+
const [summary, setSummary] = useState("");
|
|
1553
|
+
const [error, setError] = useState(null);
|
|
1554
|
+
const [busy, setBusy] = useState("render");
|
|
1555
|
+
const noticeRef = React.useRef(onNotice);
|
|
1556
|
+
noticeRef.current = onNotice;
|
|
1557
|
+
const frameRef = React.useRef(null);
|
|
1558
|
+
useEffect(() => {
|
|
1559
|
+
let cancelled = false;
|
|
1560
|
+
let url = null;
|
|
1561
|
+
setBusy("render");
|
|
1562
|
+
const timer = setTimeout(async () => {
|
|
1563
|
+
try {
|
|
1564
|
+
const doc = await import("@ai-matrx/print/document");
|
|
1565
|
+
const exp = await doc.exportDocument(markdown, "pdf", { title });
|
|
1566
|
+
if (cancelled) return;
|
|
1567
|
+
url = URL.createObjectURL(new Blob([exp.bytes], { type: "application/pdf" }));
|
|
1568
|
+
const images = await doc.resolveDocumentImages(exp.tree);
|
|
1569
|
+
if (cancelled) return;
|
|
1570
|
+
setPdf({ url, pages: exp.pageCount ?? 0 });
|
|
1571
|
+
setHtml(doc.documentToHtml(exp.tree, { images }));
|
|
1572
|
+
const s = exp.tree.settings;
|
|
1573
|
+
setSummary(
|
|
1574
|
+
[
|
|
1575
|
+
doc.PAGE_SIZES[s.page.size].label,
|
|
1576
|
+
s.page.orientation === "landscape" ? "Landscape" : "Portrait",
|
|
1577
|
+
exp.tree.figures.length ? `${exp.tree.figures.length} figure${exp.tree.figures.length === 1 ? "" : "s"}` : "",
|
|
1578
|
+
exp.tree.tables.length ? `${exp.tree.tables.length} table${exp.tree.tables.length === 1 ? "" : "s"}` : "",
|
|
1579
|
+
exp.tree.bibliography.length ? `${exp.tree.bibliography.length} reference${exp.tree.bibliography.length === 1 ? "" : "s"}` : ""
|
|
1580
|
+
].filter(Boolean).join(" \xB7 ")
|
|
1581
|
+
);
|
|
1582
|
+
setNotices(exp.notices);
|
|
1583
|
+
for (const n of exp.notices) noticeRef.current?.(n);
|
|
1584
|
+
setError(null);
|
|
1585
|
+
} catch (err) {
|
|
1586
|
+
if (!cancelled) setError(err instanceof Error ? err.message : String(err));
|
|
1587
|
+
} finally {
|
|
1588
|
+
if (!cancelled) setBusy(null);
|
|
1589
|
+
}
|
|
1590
|
+
}, 350);
|
|
1591
|
+
return () => {
|
|
1592
|
+
cancelled = true;
|
|
1593
|
+
clearTimeout(timer);
|
|
1594
|
+
if (url) URL.revokeObjectURL(url);
|
|
1595
|
+
};
|
|
1596
|
+
}, [markdown, title]);
|
|
1597
|
+
const download = async (format) => {
|
|
1598
|
+
setBusy(format);
|
|
1599
|
+
try {
|
|
1600
|
+
const doc = await import("@ai-matrx/print/document");
|
|
1601
|
+
const exp = await doc.exportDocument(markdown, format, { title });
|
|
1602
|
+
doc.downloadDocumentExport(exp);
|
|
1603
|
+
setError(null);
|
|
1604
|
+
} catch (err) {
|
|
1605
|
+
setError(`${format.toUpperCase()} export failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1606
|
+
} finally {
|
|
1607
|
+
setBusy(null);
|
|
1608
|
+
}
|
|
1609
|
+
};
|
|
1610
|
+
const print = () => {
|
|
1611
|
+
if (!pdf) return;
|
|
1612
|
+
try {
|
|
1613
|
+
frameRef.current?.contentWindow?.print();
|
|
1614
|
+
} catch {
|
|
1615
|
+
window.open(pdf.url, "_blank", "noopener");
|
|
1616
|
+
}
|
|
1617
|
+
};
|
|
1618
|
+
const btn = "inline-flex h-7 items-center gap-1 rounded-md border border-border bg-background px-2.5 text-xs font-medium text-foreground hover:bg-accent disabled:opacity-50";
|
|
1619
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex min-h-0 flex-1 flex-col", className), "data-testid": "document-print-preview", children: [
|
|
1620
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-1.5 text-xs", children: [
|
|
1621
|
+
/* @__PURE__ */ jsx("div", { className: "inline-flex overflow-hidden rounded-md border border-border", role: "tablist", children: ["pages", "web"].map((v) => /* @__PURE__ */ jsx(
|
|
1622
|
+
"button",
|
|
1623
|
+
{
|
|
1624
|
+
type: "button",
|
|
1625
|
+
role: "tab",
|
|
1626
|
+
"aria-selected": view === v,
|
|
1627
|
+
onClick: () => setView(v),
|
|
1628
|
+
className: cn("px-2.5 py-1 text-xs", view === v ? "bg-accent font-medium text-foreground" : "text-muted-foreground"),
|
|
1629
|
+
children: v === "pages" ? "Pages" : "Web"
|
|
1630
|
+
},
|
|
1631
|
+
v
|
|
1632
|
+
)) }),
|
|
1633
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", "data-testid": "document-print-summary", children: busy === "render" && !pdf ? "Laying out pages\u2026" : `${pdf?.pages ?? 0} page${pdf?.pages === 1 ? "" : "s"}${summary ? ` \xB7 ${summary}` : ""}` }),
|
|
1634
|
+
/* @__PURE__ */ jsxs("div", { className: "ml-auto flex flex-wrap items-center gap-1.5", children: [
|
|
1635
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: btn, onClick: print, disabled: !pdf, children: "Print" }),
|
|
1636
|
+
EXPORT_BUTTONS.map((b) => /* @__PURE__ */ jsx("button", { type: "button", className: btn, onClick: () => void download(b.format), disabled: busy === b.format, children: busy === b.format ? "Saving\u2026" : b.label }, b.format))
|
|
1637
|
+
] })
|
|
1638
|
+
] }),
|
|
1639
|
+
error && /* @__PURE__ */ jsx("p", { className: "border-b border-border bg-destructive/10 px-3 py-1.5 text-xs text-destructive", children: error }),
|
|
1640
|
+
notices.length > 0 && /* @__PURE__ */ jsxs("details", { className: "border-b border-border px-3 py-1.5 text-xs", children: [
|
|
1641
|
+
/* @__PURE__ */ jsxs("summary", { className: "cursor-pointer text-amber-700 dark:text-amber-400", children: [
|
|
1642
|
+
notices.length,
|
|
1643
|
+
" thing",
|
|
1644
|
+
notices.length === 1 ? "" : "s",
|
|
1645
|
+
" to fix before printing"
|
|
1646
|
+
] }),
|
|
1647
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-1 space-y-1", children: notices.map((n, i) => /* @__PURE__ */ jsxs("li", { children: [
|
|
1648
|
+
/* @__PURE__ */ jsx("span", { className: "text-foreground", children: n.message }),
|
|
1649
|
+
" ",
|
|
1650
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: n.remedy })
|
|
1651
|
+
] }, i)) })
|
|
1652
|
+
] }),
|
|
1653
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 bg-muted/40", children: view === "pages" ? pdf ? /* @__PURE__ */ jsx("iframe", { ref: frameRef, title: "Print preview", src: pdf.url, className: "h-full min-h-[480px] w-full border-0" }) : /* @__PURE__ */ jsx("p", { className: "p-8 text-center text-xs text-muted-foreground", children: error ? "No preview." : "Laying out pages\u2026" }) : /* @__PURE__ */ jsx("iframe", { title: "Web preview", srcDoc: html, sandbox: "allow-same-origin", className: "h-full min-h-[480px] w-full border-0 bg-white" }) })
|
|
1654
|
+
] });
|
|
1655
|
+
}
|
|
1540
1656
|
export {
|
|
1657
|
+
DocumentPrintPreview,
|
|
1541
1658
|
LabelSheetPreview,
|
|
1542
1659
|
PrintOptionsDialog,
|
|
1543
1660
|
usePrintOptions
|