v0.2.95
This commit is contained in:
1 parent
25d04daaee
commit
b15a6c54ce
8 files changed
+214
-52
No files matched your search
@@ -9186,7 +9186,7 @@ dialog::backdrop {
|
||||
|
||||
.pdf-export-fields {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(150px, .62fr);
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
@@ -9209,22 +9209,17 @@ dialog::backdrop {
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
.pdf-export-color-toggle,
|
||||
.pdf-export-dark-toggle,
|
||||
.pdf-export-title-toggle {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.pdf-export-color-help,
|
||||
.pdf-export-help {
|
||||
color: var(--muted);
|
||||
font-size: .78rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.pdf-export-color-help {
|
||||
margin: -6px 0 0 24px;
|
||||
}
|
||||
|
||||
#pdf-export-dialog .dialog-actions .primary-button {
|
||||
width: auto;
|
||||
min-width: 132px;
|
||||
|
||||
+3
-5
@@ -316,20 +316,18 @@
|
||||
<option value="screen-4-3">4:3 — Presentation</option>
|
||||
</select></label>
|
||||
<label><span>Margins</span><select class="app-select-input" id="pdf-page-margin">
|
||||
<option value="0">None (0 mm)</option>
|
||||
<option value="8">Narrow (8 mm)</option>
|
||||
<option value="12" selected>Normal (12 mm)</option>
|
||||
<option value="20">Wide (20 mm)</option>
|
||||
</select></label>
|
||||
</div>
|
||||
<div class="pdf-export-options">
|
||||
<label class="public-task-toggle pdf-export-dark-toggle"><input id="pdf-dark-mode" type="checkbox"
|
||||
checked> <span data-i18n="editor.darkPdf">Dark PDF</span></label>
|
||||
<label class="public-task-toggle pdf-export-title-toggle"><input id="pdf-include-title" type="checkbox">
|
||||
Include document title</label>
|
||||
<label class="public-task-toggle pdf-export-color-toggle"><input id="pdf-preserve-colors"
|
||||
type="checkbox"> <span data-i18n="editor.preservePdfColors">Preserve colors and
|
||||
backgrounds</span></label>
|
||||
</div>
|
||||
<p class="pdf-export-color-help" data-i18n="editor.pdfColorHelp">Keeps syntax highlighting, alerts, quotes,
|
||||
highlights, table headers, and other colors in the PDF.</p>
|
||||
<p class="pdf-export-help">The browser print dialog will open. Choose Save as PDF.</p>
|
||||
<div class="dialog-actions"><button class="secondary-button" value="cancel" type="button"
|
||||
data-pdf-cancel>Cancel</button><button id="generate-pdf" class="primary-button"
|
||||
|
||||
+196
-32
@@ -201,12 +201,79 @@ function groupAtomicVisuals(root) {
|
||||
}
|
||||
}
|
||||
|
||||
function preparePrintPagination(root) {
|
||||
collapseHeadingGaps(root);
|
||||
groupAtomicVisuals(root);
|
||||
function isShortList(node) {
|
||||
if (!node?.matches?.("ul, ol")) return false;
|
||||
const items = [...node.children].filter(child => child.matches?.("li"));
|
||||
if (!items.length || items.length > 8) return false;
|
||||
if (node.querySelector(":scope > li > ul, :scope > li > ol")) return false;
|
||||
return node.textContent.trim().length <= 900;
|
||||
}
|
||||
|
||||
async function ensurePrintableMermaid(root) {
|
||||
function isShortCodeBlock(node) {
|
||||
if (!node?.matches?.("pre")) return false;
|
||||
const text = node.textContent || "";
|
||||
const lines = text ? text.split(/\r?\n/).length : 0;
|
||||
return lines > 0 && lines <= 12 && text.length <= 1400;
|
||||
}
|
||||
|
||||
function markShortKeepBlocks(root) {
|
||||
root.querySelectorAll("ul, ol").forEach(list => {
|
||||
if (isShortList(list)) list.classList.add("pdf-keep-short");
|
||||
});
|
||||
root.querySelectorAll("pre").forEach(pre => {
|
||||
if (isShortCodeBlock(pre)) pre.classList.add("pdf-keep-short");
|
||||
});
|
||||
}
|
||||
|
||||
function isHeadingLead(node) {
|
||||
if (!node || node.classList?.contains("pdf-page-break")) return false;
|
||||
if (node.matches?.("p, blockquote")) {
|
||||
const text = node.textContent.trim();
|
||||
return text.length > 0 && text.length <= 520;
|
||||
}
|
||||
return isShortList(node) || isShortCodeBlock(node);
|
||||
}
|
||||
|
||||
function groupHeadingsWithLead(root) {
|
||||
const headings = [...root.querySelectorAll(":scope > h1, :scope > h2, :scope > h3, :scope > h4, :scope > h5, :scope > h6")];
|
||||
|
||||
headings.forEach(heading => {
|
||||
if (heading.parentElement !== root) return;
|
||||
|
||||
let lead = heading.nextElementSibling;
|
||||
while (isBlankPrintLine(lead)) {
|
||||
const remove = lead;
|
||||
lead = lead.nextElementSibling;
|
||||
remove.remove();
|
||||
}
|
||||
if (!isHeadingLead(lead)) return;
|
||||
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.className = "pdf-keep-unit pdf-heading-lead";
|
||||
root.insertBefore(wrapper, heading);
|
||||
wrapper.appendChild(heading);
|
||||
wrapper.appendChild(lead);
|
||||
|
||||
if (lead.matches?.("p, blockquote")) {
|
||||
let next = wrapper.nextElementSibling;
|
||||
while (isBlankPrintLine(next)) {
|
||||
const remove = next;
|
||||
next = next.nextElementSibling;
|
||||
remove.remove();
|
||||
}
|
||||
if (isShortList(next) || isShortCodeBlock(next)) wrapper.appendChild(next);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function preparePrintPagination(root) {
|
||||
collapseHeadingGaps(root);
|
||||
markShortKeepBlocks(root);
|
||||
groupAtomicVisuals(root);
|
||||
groupHeadingsWithLead(root);
|
||||
}
|
||||
|
||||
async function ensurePrintableMermaid(root, darkMode = false) {
|
||||
const nodes = [...root.querySelectorAll(".mermaid[data-mermaid-source]")];
|
||||
if (!nodes.length) return;
|
||||
|
||||
@@ -228,7 +295,7 @@ async function ensurePrintableMermaid(root) {
|
||||
|
||||
staging.appendChild(root);
|
||||
document.body.appendChild(staging);
|
||||
mermaid.initialize({ startOnLoad: false, theme: "default", securityLevel: "strict" });
|
||||
mermaid.initialize({ startOnLoad: false, theme: darkMode ? "dark" : "default", securityLevel: "strict" });
|
||||
await mermaid.run({ nodes });
|
||||
} catch {
|
||||
originals.forEach(({ node, html, processed }) => {
|
||||
@@ -378,25 +445,46 @@ function preparePreview(preview) {
|
||||
return clone;
|
||||
}
|
||||
|
||||
function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, preserveColors) {
|
||||
const pageContentWidthMm = Math.max(20, Number(pageWidthMm) - (2 * Number(marginMm)));
|
||||
const pageContentHeightMm = Math.max(20, Number(pageHeightMm) - (2 * Number(marginMm)));
|
||||
function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, darkMode) {
|
||||
const safeMargin = Math.max(0, Number(marginMm) || 0);
|
||||
const pageContentWidthMm = Math.max(20, Number(pageWidthMm) - (2 * safeMargin));
|
||||
const pageContentHeightMm = Math.max(20, Number(pageHeightMm) - (2 * safeMargin));
|
||||
const atomicMaxHeightMm = Math.max(20, pageContentHeightMm - 20);
|
||||
const mediaMaxWidthMm = atomicMaxHeightMm * (16 / 9);
|
||||
const pageBackground = darkMode ? "#15181d" : "#fff";
|
||||
const textColor = darkMode ? "#e6e9ed" : "#16181d";
|
||||
const headingColor = darkMode ? "#f1f3f5" : "#111318";
|
||||
const borderColor = darkMode ? "#3a414b" : "#d7dce2";
|
||||
const footerColor = darkMode ? "#aeb5bf" : "#9299a3";
|
||||
const colorScheme = darkMode ? "dark" : "light";
|
||||
|
||||
return `
|
||||
@page { size: ${cssSize}; margin: ${marginMm}mm; }
|
||||
html { color-scheme: light; background: #fff !important; }
|
||||
@page { size: ${cssSize}; margin: ${safeMargin}mm; background: ${pageBackground}; }
|
||||
html {
|
||||
color-scheme: ${colorScheme};
|
||||
background: ${pageBackground} !important;
|
||||
print-color-adjust: exact !important;
|
||||
-webkit-print-color-adjust: exact !important;
|
||||
}
|
||||
body {
|
||||
width: ${pageContentWidthMm}mm;
|
||||
max-width: ${pageContentWidthMm}mm;
|
||||
min-height: 100vh;
|
||||
margin: 0 !important;
|
||||
background: #fff !important;
|
||||
color: #16181d !important;
|
||||
background: ${pageBackground} !important;
|
||||
color: ${textColor} !important;
|
||||
print-color-adjust: exact !important;
|
||||
-webkit-print-color-adjust: exact !important;
|
||||
}
|
||||
.pdf-document { width: ${pageContentWidthMm}mm; box-sizing: border-box; }
|
||||
.pdf-document-title { margin: 0 0 1.2em; padding: 0 0 .45em; border-bottom: 1px solid #d7dce2; }
|
||||
.pdf-document-title h1 { margin: 0; font: 700 1.7rem/1.18 Inter, ui-sans-serif, system-ui, sans-serif; color: #111318; }
|
||||
.pdf-document {
|
||||
width: ${pageContentWidthMm}mm;
|
||||
min-height: ${pageContentHeightMm}mm;
|
||||
box-sizing: border-box;
|
||||
background: ${pageBackground} !important;
|
||||
color: ${textColor} !important;
|
||||
}
|
||||
.pdf-document-title { margin: 0 0 1.2em; padding: 0 0 .45em; border-bottom: 1px solid ${borderColor}; }
|
||||
.pdf-document-title h1 { margin: 0; font: 700 1.7rem/1.18 Inter, ui-sans-serif, system-ui, sans-serif; color: ${headingColor}; }
|
||||
.pdf-footer-spacer {
|
||||
display: block;
|
||||
width: 100%;
|
||||
@@ -409,8 +497,8 @@ function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, preserveColor
|
||||
box-sizing: border-box;
|
||||
margin-top: 8mm;
|
||||
padding-top: 1.5mm;
|
||||
border-top: .2mm solid #e1e4e8;
|
||||
color: #9299a3;
|
||||
border-top: .2mm solid ${borderColor};
|
||||
color: ${footerColor};
|
||||
font: 500 7.5pt/1.2 Inter, ui-sans-serif, system-ui, sans-serif;
|
||||
letter-spacing: .01em;
|
||||
text-align: center;
|
||||
@@ -423,7 +511,7 @@ function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, preserveColor
|
||||
margin: 0;
|
||||
padding: 0 !important;
|
||||
overflow: visible !important;
|
||||
color: #16181d !important;
|
||||
color: ${textColor} !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.pdf-content .preview-source-line::before { display: none !important; content: none !important; }
|
||||
@@ -471,6 +559,10 @@ function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, preserveColor
|
||||
.pdf-content p,
|
||||
.pdf-content li,
|
||||
.pdf-content dd { orphans: 3; widows: 3; }
|
||||
.pdf-content p {
|
||||
break-inside: avoid-page;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.pdf-content ul,
|
||||
.pdf-content ol,
|
||||
@@ -545,6 +637,16 @@ function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, preserveColor
|
||||
}
|
||||
.pdf-content .pdf-keep-unit > :first-child { margin-top: 0 !important; }
|
||||
.pdf-content .pdf-keep-unit > :last-child { margin-bottom: 0 !important; }
|
||||
.pdf-content .pdf-keep-short {
|
||||
break-inside: avoid-page !important;
|
||||
page-break-inside: avoid !important;
|
||||
}
|
||||
.pdf-content .pdf-heading-lead > h1,
|
||||
.pdf-content .pdf-heading-lead > h2,
|
||||
.pdf-content .pdf-heading-lead > h3 {
|
||||
padding-bottom: 0;
|
||||
margin-bottom: .18em;
|
||||
}
|
||||
.pdf-content .pdf-atomic-visual {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
@@ -563,6 +665,24 @@ function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, preserveColor
|
||||
object-fit: contain;
|
||||
break-inside: avoid-page;
|
||||
page-break-inside: avoid;
|
||||
/* Dark PDF changes the document theme only. Never recolor raster images. */
|
||||
filter: none !important;
|
||||
-webkit-filter: none !important;
|
||||
opacity: 1 !important;
|
||||
mix-blend-mode: normal !important;
|
||||
forced-color-adjust: none !important;
|
||||
color-scheme: normal !important;
|
||||
}
|
||||
.pdf-content picture,
|
||||
.pdf-content picture > img,
|
||||
.pdf-content video,
|
||||
.pdf-content canvas {
|
||||
filter: none !important;
|
||||
-webkit-filter: none !important;
|
||||
opacity: 1 !important;
|
||||
mix-blend-mode: normal !important;
|
||||
forced-color-adjust: none !important;
|
||||
color-scheme: normal !important;
|
||||
}
|
||||
.pdf-content .markdown-alias-image--sized {
|
||||
height: auto !important;
|
||||
@@ -601,9 +721,50 @@ function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, preserveColor
|
||||
max-height: ${atomicMaxHeightMm}mm !important;
|
||||
}
|
||||
|
||||
${preserveColors ? `
|
||||
.pdf-document,
|
||||
.pdf-document * { print-color-adjust: exact !important; -webkit-print-color-adjust: exact !important; }
|
||||
|
||||
${darkMode ? `
|
||||
.pdf-content a { color: #b9b4d8 !important; }
|
||||
.pdf-content code:not(pre code) { background: #242931 !important; border-color: #414852 !important; color: #e2e5e9 !important; }
|
||||
.pdf-content pre { background: #1b1f25 !important; border-color: #3a414b !important; color: #d2d6dc !important; }
|
||||
.pdf-content pre code,
|
||||
.pdf-content .hljs { background: transparent !important; color: #d2d6dc !important; }
|
||||
.pdf-content .hljs-keyword,
|
||||
.pdf-content .hljs-selector-tag,
|
||||
.pdf-content .hljs-literal,
|
||||
.pdf-content .hljs-section,
|
||||
.pdf-content .hljs-link { color: #c2acd0 !important; }
|
||||
.pdf-content .hljs-string,
|
||||
.pdf-content .hljs-attr,
|
||||
.pdf-content .hljs-regexp,
|
||||
.pdf-content .hljs-template-tag,
|
||||
.pdf-content .hljs-template-variable { color: #b8c9a1 !important; }
|
||||
.pdf-content .hljs-number,
|
||||
.pdf-content .hljs-symbol,
|
||||
.pdf-content .hljs-bullet { color: #d8a08e !important; }
|
||||
.pdf-content .hljs-title,
|
||||
.pdf-content .hljs-title.class_,
|
||||
.pdf-content .hljs-title.function_,
|
||||
.pdf-content .hljs-built_in,
|
||||
.pdf-content .hljs-type { color: #9fb6d8 !important; }
|
||||
.pdf-content .hljs-variable,
|
||||
.pdf-content .hljs-selector-id,
|
||||
.pdf-content .hljs-selector-class,
|
||||
.pdf-content .hljs-property,
|
||||
.pdf-content .hljs-attribute { color: #d39ca2 !important; }
|
||||
.pdf-content .hljs-comment,
|
||||
.pdf-content .hljs-quote { color: #9299a3 !important; font-style: italic; }
|
||||
.pdf-content .hljs-meta { color: #cdbb8f !important; }
|
||||
.pdf-content blockquote { border-left-color: #85818f !important; color: #cfd3d8 !important; }
|
||||
.pdf-content mark { background: #5b5338 !important; color: #eee5b8 !important; }
|
||||
.pdf-content th { background: #242930 !important; color: #e1e4e8 !important; }
|
||||
.pdf-content .markdown-alert--success { border-color: #63806f !important; background: rgba(99, 128, 111, .12) !important; }
|
||||
.pdf-content .markdown-alert--info { border-color: #6e8198 !important; background: rgba(110, 129, 152, .12) !important; }
|
||||
.pdf-content .markdown-alert--warning { border-color: #9a8968 !important; background: rgba(154, 137, 104, .12) !important; }
|
||||
.pdf-content .markdown-alert--danger { border-color: #956f73 !important; background: rgba(149, 111, 115, .12) !important; }
|
||||
.pdf-content .task-checkbox { accent-color: #8c8798 !important; }
|
||||
` : `
|
||||
.pdf-content a { color: #5d50a5 !important; }
|
||||
.pdf-content code:not(pre code) { background: #eeeaf7 !important; border-color: #bcb2a6 !important; color: #403a33 !important; }
|
||||
.pdf-content pre { background: #efeae2 !important; border-color: #e2dcd3 !important; color: #413b34 !important; }
|
||||
@@ -643,7 +804,7 @@ function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, preserveColor
|
||||
.pdf-content .markdown-alert--warning { border-color: #a27831 !important; background: rgba(155, 112, 35, .11) !important; }
|
||||
.pdf-content .markdown-alert--danger { border-color: #a54b55 !important; background: rgba(155, 52, 67, .09) !important; }
|
||||
.pdf-content .task-checkbox { accent-color: #6859b5 !important; }
|
||||
` : ""}
|
||||
`}
|
||||
|
||||
.pdf-page-break {
|
||||
display: block;
|
||||
@@ -658,9 +819,9 @@ function printStyles(cssSize, pageWidthMm, pageHeightMm, marginMm, preserveColor
|
||||
`;
|
||||
}
|
||||
|
||||
function openPrintWindow({ preview, title, formatKey, marginMm, includeTitle, preserveColors }) {
|
||||
function openPrintWindow({ preview, title, formatKey, marginMm, includeTitle, darkMode }) {
|
||||
const format = PAGE_FORMATS[formatKey] || PAGE_FORMATS["a4-portrait"];
|
||||
const safeMargin = [8, 12, 20].includes(Number(marginMm)) ? Number(marginMm) : 12;
|
||||
const safeMargin = [0, 8, 12, 20].includes(Number(marginMm)) ? Number(marginMm) : 12;
|
||||
const printWindow = window.open("", "_blank");
|
||||
if (!printWindow) throw new Error(t("editor.pdfPopupBlocked", {}, "The PDF window was blocked by the browser."));
|
||||
try { printWindow.opener = null; } catch { /* same-origin hardening is best effort */ }
|
||||
@@ -671,15 +832,15 @@ function openPrintWindow({ preview, title, formatKey, marginMm, includeTitle, pr
|
||||
: "";
|
||||
const lang = escapeHtml(document.documentElement.lang || "en");
|
||||
const base = escapeHtml(`${location.origin}/`);
|
||||
const css = printStyles(format.cssSize, format.widthMm, format.heightMm, safeMargin, preserveColors);
|
||||
const css = printStyles(format.cssSize, format.widthMm, format.heightMm, safeMargin, darkMode);
|
||||
const footerText = escapeHtml(t("editor.pdfGeneratedFooter", {}, "Generated by RustPad"));
|
||||
|
||||
return (async () => {
|
||||
await ensurePrintableMermaid(content);
|
||||
if (preserveColors) await ensureSyntaxHighlight(content);
|
||||
await ensurePrintableMermaid(content, darkMode);
|
||||
await ensureSyntaxHighlight(content);
|
||||
|
||||
printWindow.document.open();
|
||||
printWindow.document.write(`<!doctype html><html lang="${lang}" data-theme="light"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><base href="${base}"><title>${escapeHtml(title || "RustPad")}</title>${stylesheetLinks()}<style>${css}</style></head><body><main class="pdf-document">${titleBlock}${content.outerHTML}<div class="pdf-footer-spacer" aria-hidden="true"></div><footer class="pdf-generated-footer" aria-hidden="true">${footerText}</footer></main></body></html>`);
|
||||
printWindow.document.write(`<!doctype html><html lang="${lang}" data-theme="${darkMode ? "dark" : "light"}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><base href="${base}"><title>${escapeHtml(title || "RustPad")}</title>${stylesheetLinks()}<style>${css}</style></head><body><main class="pdf-document">${titleBlock}${content.outerHTML}<div class="pdf-footer-spacer" aria-hidden="true"></div><footer class="pdf-generated-footer" aria-hidden="true">${footerText}</footer></main></body></html>`);
|
||||
printWindow.document.close();
|
||||
|
||||
const runPrint = async () => {
|
||||
@@ -707,15 +868,18 @@ export function bindPdfExport({ button, dialog, form, preview, title }) {
|
||||
if (!button || !dialog || !form || !preview) return;
|
||||
const formatSelect = form.querySelector("#pdf-page-format");
|
||||
const marginSelect = form.querySelector("#pdf-page-margin");
|
||||
const darkMode = form.querySelector("#pdf-dark-mode");
|
||||
const includeTitle = form.querySelector("#pdf-include-title");
|
||||
const preserveColors = form.querySelector("#pdf-preserve-colors");
|
||||
const cancelButtons = form.querySelectorAll("[data-pdf-cancel]");
|
||||
|
||||
const savedFormat = saved("format", "a4-portrait");
|
||||
formatSelect.value = Object.hasOwn(PAGE_FORMATS, savedFormat) ? savedFormat : "a4-portrait";
|
||||
marginSelect.value = ["8", "12", "20"].includes(saved("margin", "12")) ? saved("margin", "12") : "12";
|
||||
if (marginSelect) {
|
||||
const savedMargin = saved("margin", "12");
|
||||
marginSelect.value = ["0", "8", "12", "20"].includes(savedMargin) ? savedMargin : "12";
|
||||
}
|
||||
if (darkMode) darkMode.checked = saved("dark-mode", "on") !== "off";
|
||||
includeTitle.checked = saved("include-title", "off") === "on";
|
||||
if (preserveColors) preserveColors.checked = saved("preserve-colors", "on") !== "off";
|
||||
|
||||
button.addEventListener("click", () => dialog.showModal());
|
||||
cancelButtons.forEach(cancel => cancel.addEventListener("click", () => dialog.close("cancel")));
|
||||
@@ -724,11 +888,11 @@ export function bindPdfExport({ button, dialog, form, preview, title }) {
|
||||
form.addEventListener("submit", event => {
|
||||
event.preventDefault();
|
||||
const formatKey = formatSelect.value;
|
||||
const marginMm = Number(marginSelect.value);
|
||||
const marginMm = Number(marginSelect?.value ?? 12);
|
||||
save("format", formatKey);
|
||||
save("margin", marginMm);
|
||||
save("dark-mode", darkMode?.checked === false ? "off" : "on");
|
||||
save("include-title", includeTitle.checked ? "on" : "off");
|
||||
save("preserve-colors", preserveColors?.checked === false ? "off" : "on");
|
||||
try {
|
||||
const printJob = openPrintWindow({
|
||||
preview,
|
||||
@@ -736,7 +900,7 @@ export function bindPdfExport({ button, dialog, form, preview, title }) {
|
||||
formatKey,
|
||||
marginMm,
|
||||
includeTitle: includeTitle.checked,
|
||||
preserveColors: preserveColors?.checked !== false,
|
||||
darkMode: darkMode?.checked !== false,
|
||||
});
|
||||
dialog.close("confirm");
|
||||
void printJob.catch(error => {
|
||||
|
||||
Reference in new issue
Block a user