@ai-matrx/print 0.8.2 → 0.8.3

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.3
4
+
5
+ - **Fixed:** an `<artifact>` envelope (how chat answers store tables and code)
6
+ printed as raw pipes in documents. The document pipeline now unwraps it with
7
+ the same rules the print skins use (`unwrapArtifactsToMarkdown`, exported
8
+ from `/markdown`): a table stays a table, code stays code.
9
+ - **Fixed (EPUB):** a `$$…$$` formula inside a sentence rendered as a `<div>`
10
+ inside `<p>` (epubcheck RSC-005); it is now a block-styled span.
11
+ - **Word:** East-Asian text carries a CJK font hint, so Word/LibreOffice pick
12
+ an installed Japanese/Chinese face.
13
+ - Consumer action: none — refresh to latest.
14
+
3
15
  ## 0.8.2
4
16
 
5
17
  - **PDF font fallback covers Japanese / Chinese / Korean.** Characters the
package/dist/document.cjs CHANGED
@@ -3107,7 +3107,11 @@ async function documentToDocx(tree, options = {}) {
3107
3107
  numbering: { config: [...c.numbering.entries()].map(([reference, levels2]) => ({ reference, levels: levels2 })) },
3108
3108
  styles: {
3109
3109
  default: {
3110
- document: { run: { font: "Cambria", size, color: HEX.text }, paragraph: { spacing: { after: 140, line: 300 } } }
3110
+ // East-Asian text gets a CJK face (Word and LibreOffice substitute an installed one).
3111
+ document: {
3112
+ run: { font: { ascii: "Cambria", hAnsi: "Cambria", cs: "Cambria", eastAsia: "Yu Gothic" }, size, color: HEX.text },
3113
+ paragraph: { spacing: { after: 140, line: 300 } }
3114
+ }
3111
3115
  },
3112
3116
  paragraphStyles: [
3113
3117
  heading("Heading1", "Heading 1", s.fontSize * 1.8, 0),
@@ -3250,7 +3254,7 @@ function renderInlineHtml(nodes, x) {
3250
3254
  case "cite":
3251
3255
  return n.resolved ? `<a class="doc-cite" href="${(0, import_html_escape.escapeHtml)(href("ref-" + (n.keys[0] ?? ""), x))}">${(0, import_html_escape.escapeHtml)(n.label)}</a>` : `<span class="doc-cite doc-cite-missing">${(0, import_html_escape.escapeHtml)(n.label)}</span>`;
3252
3256
  case "math":
3253
- return mathHtml(n.tex, n.display, x);
3257
+ return mathHtml(n.tex, n.display, x, true);
3254
3258
  case "noteRef":
3255
3259
  return `<sup class="doc-note-ref"><a href="${(0, import_html_escape.escapeHtml)(href(`note-${n.n}`, x))}" id="noteref-${n.n}">${n.n}</a></sup>`;
3256
3260
  default:
@@ -3258,10 +3262,11 @@ function renderInlineHtml(nodes, x) {
3258
3262
  }
3259
3263
  }).join("");
3260
3264
  }
3261
- function mathHtml(tex, display, x) {
3265
+ function mathHtml(tex, display, x, inText = false) {
3262
3266
  const m = x.tree.math.get(mathKey(tex, display));
3263
3267
  if (m?.mathml && !m.error) {
3264
- return display ? `<div class="doc-math-display">${m.mathml}</div>` : `<span class="doc-math">${m.mathml}</span>`;
3268
+ if (!display) return `<span class="doc-math">${m.mathml}</span>`;
3269
+ return inText ? `<span class="doc-math-display">${m.mathml}</span>` : `<div class="doc-math-display">${m.mathml}</div>`;
3265
3270
  }
3266
3271
  return `<code class="doc-math-tex">${(0, import_html_escape.escapeHtml)(display ? `$$${tex}$$` : `$${tex}$`)}</code>`;
3267
3272
  }
@@ -3423,7 +3428,7 @@ table caption{caption-side:top;text-align:left;margin-bottom:4pt;}
3423
3428
  .doc-figure figcaption{margin-top:4pt;}
3424
3429
  .doc-image-missing{border:1px dashed var(--matrx-print-rule,#d1d5db);padding:16pt;color:var(--matrx-print-muted,#6b7280);}
3425
3430
  .doc-inline-img{max-height:1.2em;vertical-align:middle;}
3426
- .doc-math-display{margin:0.6em 0 0.9em;text-align:center;break-inside:avoid;overflow-x:auto;}
3431
+ .doc-math-display{display:block;margin:0.6em 0 0.9em;text-align:center;break-inside:avoid;overflow-x:auto;}
3427
3432
  .doc-math-display math{font-size:1.15em;}
3428
3433
  .doc-math-tex{color:var(--matrx-print-danger,#b91c1c);}
3429
3434
  .doc-task-list{list-style:none;padding-left:0.2em;}
@@ -3502,7 +3507,7 @@ blockquote{margin:0 0 0.8em;padding-left:1em;border-left:3px solid #d1d5db;color
3502
3507
  .doc-cover-logo{max-height:5em;}
3503
3508
  .doc-cover-title{font-size:2em;}
3504
3509
  .matrx-page-break{page-break-after:always;break-after:page;}
3505
- .doc-math-display{margin:0.6em 0;text-align:center;}
3510
+ .doc-math-display{display:block;margin:0.6em 0;text-align:center;}
3506
3511
  `.trim();
3507
3512
  function extOf(mime) {
3508
3513
  return mime === "image/png" ? "png" : mime === "image/gif" ? "gif" : "jpg";
@@ -4792,6 +4797,70 @@ function removeThinkingContent(content) {
4792
4797
  return result.trim();
4793
4798
  }
4794
4799
  var PAGE_BREAK_HTML = `<div class="${PAGE_BREAK_CLASS}" role="separator" aria-label="${PAGE_BREAK_LABEL}" data-label="${PAGE_BREAK_LABEL}"></div>`;
4800
+ var CODE_ARTIFACT_LANGUAGE = {
4801
+ html: "html",
4802
+ react: "tsx",
4803
+ svg: "svg",
4804
+ mermaid: "mermaid",
4805
+ diff: "diff",
4806
+ iframe: "html",
4807
+ code: ""
4808
+ };
4809
+ function parseTagAttributes(tag) {
4810
+ const attrs = {};
4811
+ for (const m of tag.matchAll(/([a-zA-Z_][\w-]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/g)) {
4812
+ attrs[m[1].toLowerCase()] = m[2] ?? m[3] ?? "";
4813
+ }
4814
+ return attrs;
4815
+ }
4816
+ function unwrapArtifactsToMarkdown(markdown) {
4817
+ if (!/<artifact\b/i.test(markdown)) return markdown;
4818
+ return markdown.split(/(^[ \t]*(?:`{3,}|~{3,})[\s\S]*?^[ \t]*(?:`{3,}|~{3,})[ \t]*$)/m).map(
4819
+ (part, i) => i % 2 === 1 ? part : part.replace(/<artifact\b((?:[^>"']|"[^"]*"|'[^']*')*?)>([\s\S]*?)<\/artifact>/gi, (_m, tag, body) => {
4820
+ const attrs = parseTagAttributes(tag);
4821
+ const type = (attrs.type ?? "").toLowerCase();
4822
+ const trimmed = body.replace(/^\n+|\n+$/g, "");
4823
+ if (!trimmed.trim()) return "";
4824
+ if (/^\s*(`{3,}|~{3,})/.test(trimmed)) return `
4825
+
4826
+ ${trimmed}
4827
+
4828
+ `;
4829
+ if (type in CODE_ARTIFACT_LANGUAGE) {
4830
+ const lang = CODE_ARTIFACT_LANGUAGE[type] || attrs.language || attrs.lang || "";
4831
+ return `
4832
+
4833
+ \`\`\`\`${lang}
4834
+ ${trimmed}
4835
+ \`\`\`\`
4836
+
4837
+ `;
4838
+ }
4839
+ if (looksLikeJson(trimmed)) return `
4840
+
4841
+ \`\`\`\`json
4842
+ ${JSON.stringify(JSON.parse(trimmed), null, 2)}
4843
+ \`\`\`\`
4844
+
4845
+ `;
4846
+ return `
4847
+
4848
+ ${trimmed}
4849
+
4850
+ `;
4851
+ })
4852
+ ).join("");
4853
+ }
4854
+ function looksLikeJson(body) {
4855
+ const t = body.trim();
4856
+ if (!/^[[{]/.test(t)) return false;
4857
+ try {
4858
+ JSON.parse(t);
4859
+ return true;
4860
+ } catch {
4861
+ return false;
4862
+ }
4863
+ }
4795
4864
  var LINK_URL = String.raw`((?:[^()\s]|\([^()\s]*\))+)(?:\s+"[^"]*")?`;
4796
4865
  var IMAGE_RE = new RegExp(String.raw`!\[([^\]]*)\]\(` + LINK_URL + String.raw`\)`, "g");
4797
4866
  var LINK_RE = new RegExp(String.raw`\[([^\]]+)\]\(` + LINK_URL + String.raw`\)`, "g");
@@ -5246,7 +5315,7 @@ function parseDocument(source, options = {}) {
5246
5315
  const settings = resolveSettings(fm.data, sink, options);
5247
5316
  for (const n of sink) notify(n);
5248
5317
  const body = removeThinkingContent(fm.body);
5249
- const lifted = extractMath(body);
5318
+ const lifted = extractMath(unwrapArtifactsToMarkdown(body));
5250
5319
  const root = (0, import_mdast_util_from_markdown.fromMarkdown)(prepass(lifted.text), {
5251
5320
  extensions: [(0, import_micromark_extension_gfm.gfm)()],
5252
5321
  mdastExtensions: [(0, import_mdast_util_gfm.gfmFromMarkdown)()]