@taloswork/ose-shared 0.1.11 → 0.1.12
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/package.json +3 -3
- package/skills/document/SKILL.md +143 -215
- package/skills/document/art-directions/base.css +27 -2
- package/skills/document/art-directions/cinematic-depth.css +3 -1
- package/skills/document/art-directions/collage-paper.css +5 -1
- package/skills/document/art-directions/editorial-cut.css +5 -1
- package/skills/document/art-directions/geometric-pop.css +6 -0
- package/skills/document/art-directions/gradient-mesh.css +5 -1
- package/skills/document/art-directions/illustrated-doodle.css +5 -0
- package/skills/document/art-directions/luxury-ornament.css +4 -1
- package/skills/document/art-directions/maximalist-blocks.css +6 -0
- package/skills/document/art-directions/technical-grid.css +4 -0
- package/skills/document/assets/fonts/fonts.json +2 -2
- package/skills/document/assets/pdf-fonts/NotoSansSC-PDF-Bold.ttf +0 -0
- package/skills/document/assets/pdf-fonts/NotoSansSC-PDF-Regular.ttf +0 -0
- package/skills/document/assets/pdf-fonts/OFL.txt +93 -0
- package/skills/document/assets/pdf-fonts/README.md +35 -0
- package/skills/document/assets/tessdata/LICENSE-Apache-2.0.txt +202 -0
- package/skills/document/assets/tessdata/README.md +21 -0
- package/skills/document/assets/tessdata/chi_sim.traineddata.gz +0 -0
- package/skills/document/assets/tessdata/eng.traineddata.gz +0 -0
- package/skills/document/bin/deck-build.cjs +2311 -41
- package/skills/document/bin/deck-chart.cjs +762 -0
- package/skills/document/bin/deck-plan.cjs +802 -0
- package/skills/document/bin/deck-qa.cjs +984 -249
- package/skills/document/bin/deck-scenario.cjs +1346 -0
- package/skills/document/bin/doc-convert.cjs +130 -39
- package/skills/document/bin/doc-fill.cjs +73121 -170
- package/skills/document/bin/doc-gen.cjs +625 -68
- package/skills/document/bin/doc-run.cjs +162 -24
- package/skills/document/bin/doc-scan.cjs +13 -0
- package/skills/document/bin/doc-text.cjs +13 -0
- package/skills/document/bin/doc-validate.cjs +718 -23
- package/skills/document/bin/doc-xml.cjs +9 -5
- package/skills/document/bin/docx-annotate.cjs +95 -19
- package/skills/document/bin/fontkit.cjs +1 -0
- package/skills/document/bin/html2pptx.cjs +1372 -121
- package/skills/document/bin/ocr-worker.cjs +1 -0
- package/skills/document/bin/ocr.cjs +131 -40
- package/skills/document/bin/pdf-form.cjs +674 -177
- package/skills/document/bin/pdf-images.cjs +13 -0
- package/skills/document/bin/pdf-ops.cjs +634 -199
- package/skills/document/bin/pdf-render.cjs +19 -3
- package/skills/document/bin/pdf-tables.cjs +13 -0
- package/skills/document/bin/pptx-clone.cjs +3 -3
- package/skills/document/bin/pptx-slide.cjs +3 -3
- package/skills/document/bin/xlsx-query.cjs +192 -61
- package/skills/document/bin-reference.md +56 -33
- package/skills/document/content-pipeline.md +129 -242
- package/skills/document/deck-design.md +355 -638
- package/skills/document/layouts/README.md +46 -33
- package/skills/document/layouts/capacity.json +1 -0
- package/skills/document/layouts/slots.json +1 -1
- package/skills/document/layouts/toc-panel.tpl +1 -1
- package/skills/document/motion/README.md +3 -2
- package/skills/document/office.md +3 -3
- package/skills/document/packs/board-brief/backdrop.html +2 -0
- package/skills/document/packs/board-brief/pack.css +2 -1
- package/skills/document/packs/mckinsey-photo/backdrop.html +2 -0
- package/skills/document/packs/mckinsey-photo/pack.css +2 -1
- package/skills/document/packs/press-room/backdrop.html +2 -0
- package/skills/document/packs/press-room/pack.css +2 -1
- package/skills/document/packs/prismatic-3d/backdrop.html +2 -0
- package/skills/document/packs/prismatic-3d/pack.css +4 -1
- package/skills/document/pdf.md +53 -49
- package/skills/document/rewrite.md +241 -308
- package/skills/document/scenarios.json +1290 -0
- package/skills/document/scenarios.schema.json +103 -0
- package/skills/document/styles/README.md +15 -25
- package/skills/document/styles/_contract-defaults.css +25 -1
- package/skills/document/styles/anthropic/skin.css +6 -3
- package/skills/document/styles/apple/skin.css +4 -3
- package/skills/document/styles/bistro-warm/backdrop.html +2 -0
- package/skills/document/styles/bistro-warm/skin.css +4 -1
- package/skills/document/styles/black-gold/skin.css +6 -5
- package/skills/document/styles/bold-clash/backdrop.html +2 -0
- package/skills/document/styles/bold-clash/skin.css +2 -1
- package/skills/document/styles/branding/skin.css +4 -4
- package/skills/document/styles/campus-teal/backdrop.html +2 -0
- package/skills/document/styles/campus-teal/skin.css +2 -1
- package/skills/document/styles/cinereel/skin.css +7 -3
- package/skills/document/styles/clinic-care/backdrop.html +2 -0
- package/skills/document/styles/clinic-care/skin.css +2 -1
- package/skills/document/styles/cool/skin.css +6 -5
- package/skills/document/styles/dark-glass/backdrop.html +2 -0
- package/skills/document/styles/dark-glass/skin.css +2 -1
- package/skills/document/styles/gov-brief/backdrop.html +2 -0
- package/skills/document/styles/gov-brief/skin.css +2 -1
- package/skills/document/styles/grid-tech/backdrop.html +2 -0
- package/skills/document/styles/grid-tech/skin.css +2 -1
- package/skills/document/styles/hand-drawn/skin.css +3 -3
- package/skills/document/styles/ivory-gold/skin.css +7 -6
- package/skills/document/styles/legal-slate/backdrop.html +2 -0
- package/skills/document/styles/legal-slate/skin.css +2 -1
- package/skills/document/styles/magazine-ink/skin.css +4 -3
- package/skills/document/styles/mckinsey/skin.css +2 -1
- package/skills/document/styles/memphis/backdrop.html +2 -0
- package/skills/document/styles/memphis/skin.css +2 -1
- package/skills/document/styles/mono/skin.css +6 -2
- package/skills/document/styles/neon-cyber/backdrop.html +2 -0
- package/skills/document/styles/neon-cyber/skin.css +2 -1
- package/skills/document/styles/olive-gold/skin.css +7 -6
- package/skills/document/styles/organic-earth/backdrop.html +2 -0
- package/skills/document/styles/organic-earth/skin.css +2 -1
- package/skills/document/styles/pastel-saas/backdrop.html +2 -0
- package/skills/document/styles/pastel-saas/skin.css +2 -1
- package/skills/document/styles/portfolio-noir/backdrop.html +2 -0
- package/skills/document/styles/portfolio-noir/skin.css +2 -1
- package/skills/document/styles/retro-press/backdrop.html +2 -0
- package/skills/document/styles/retro-press/skin.css +2 -1
- package/skills/document/styles/sport-arena/backdrop.html +2 -0
- package/skills/document/styles/sport-arena/skin.css +4 -1
- package/skills/document/styles/swiss-grid/skin.css +10 -5
- package/skills/document/styles/wedding-blush/backdrop.html +2 -0
- package/skills/document/styles/wedding-blush/skin.css +4 -1
- package/skills/document/theme-system.md +85 -77
- package/skills/document/themes/README.md +7 -5
- package/skills/document/vision.md +8 -5
- package/skills/document/xlsx.md +15 -25
|
@@ -9863,7 +9863,7 @@ function replaceTextAcrossRuns(xml, find, replacement, opts) {
|
|
|
9863
9863
|
let flat = "";
|
|
9864
9864
|
for (const m of para.matchAll(textRe)) {
|
|
9865
9865
|
const text = unescXml(m[2]);
|
|
9866
|
-
segs.push({ el: m[0], attrs: m[1] ?? "", text, start: flat.length });
|
|
9866
|
+
segs.push({ el: m[0], at: m.index, attrs: m[1] ?? "", text, start: flat.length });
|
|
9867
9867
|
flat += text;
|
|
9868
9868
|
}
|
|
9869
9869
|
if (!flat.includes(find))
|
|
@@ -9892,7 +9892,7 @@ function replaceTextAcrossRuns(xml, find, replacement, opts) {
|
|
|
9892
9892
|
return pieces.join("");
|
|
9893
9893
|
});
|
|
9894
9894
|
let out = para;
|
|
9895
|
-
for (let i =
|
|
9895
|
+
for (let i = segs.length - 1; i >= 0; i--) {
|
|
9896
9896
|
if (newTexts[i] === segs[i].text)
|
|
9897
9897
|
continue;
|
|
9898
9898
|
const escaped = escXml(newTexts[i]);
|
|
@@ -9900,7 +9900,7 @@ function replaceTextAcrossRuns(xml, find, replacement, opts) {
|
|
|
9900
9900
|
if (textTag === "w:t" && /^\s|\s$/.test(newTexts[i]) && !/xml:space="preserve"/.test(attrs)) {
|
|
9901
9901
|
attrs = `${attrs} xml:space="preserve"`;
|
|
9902
9902
|
}
|
|
9903
|
-
out = out.
|
|
9903
|
+
out = out.slice(0, segs[i].at) + `<${textTag}${attrs}>${escaped}</${textTag}>` + out.slice(segs[i].at + segs[i].el.length);
|
|
9904
9904
|
}
|
|
9905
9905
|
return out;
|
|
9906
9906
|
});
|
|
@@ -10029,7 +10029,7 @@ async function replaceTextInDocx(bytes, find, replacement) {
|
|
|
10029
10029
|
}
|
|
10030
10030
|
if (!zip.file("word/document.xml"))
|
|
10031
10031
|
throw new Error("not a Word document (word/document.xml missing)");
|
|
10032
|
-
const parts = Object.keys(zip.files).filter((p) => p === "word/document.xml" || /^word\/(?:header|footer)\d+\.xml$/.test(p));
|
|
10032
|
+
const parts = Object.keys(zip.files).filter((p) => p === "word/document.xml" || p === "word/footnotes.xml" || p === "word/endnotes.xml" || /^word\/(?:header|footer)\d+\.xml$/.test(p));
|
|
10033
10033
|
let count = 0;
|
|
10034
10034
|
for (const part of parts) {
|
|
10035
10035
|
const xml = await zip.file(part).async("string");
|
|
@@ -10100,7 +10100,11 @@ async function main() {
|
|
|
10100
10100
|
const r = await replaceTextInDocx(bytes, find, replacement);
|
|
10101
10101
|
await (0, import_promises2.writeFile)(out, Buffer.from(r.bytes));
|
|
10102
10102
|
process.stdout.write(JSON.stringify({ ok: true, out, replaced: r.count }) + "\n");
|
|
10103
|
-
if (r.count === 0)
|
|
10103
|
+
if (r.count === 0) {
|
|
10104
|
+
process.stderr.write(
|
|
10105
|
+
"doc-xml: no occurrence found \u2014 the text must match exactly within one paragraph (body, tables, headers/footers and footnotes/endnotes are searched; comments are not)\n"
|
|
10106
|
+
);
|
|
10107
|
+
}
|
|
10104
10108
|
return;
|
|
10105
10109
|
}
|
|
10106
10110
|
} catch (e) {
|
|
@@ -9830,6 +9830,7 @@ function escXml(s) {
|
|
|
9830
9830
|
var import_node_crypto = require("node:crypto");
|
|
9831
9831
|
var W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
9832
9832
|
var W14_NS = "http://schemas.microsoft.com/office/word/2010/wordml";
|
|
9833
|
+
var MC_NS = "http://schemas.openxmlformats.org/markup-compatibility/2006";
|
|
9833
9834
|
var W15_NS = "http://schemas.microsoft.com/office/word/2012/wordml";
|
|
9834
9835
|
var W16CID_NS = "http://schemas.microsoft.com/office/word/2016/wordml/cid";
|
|
9835
9836
|
var MODERN_PARTS = [
|
|
@@ -9926,11 +9927,34 @@ async function ensureCommentsWiring(zip) {
|
|
|
9926
9927
|
}
|
|
9927
9928
|
const existing = zip.file("word/comments.xml");
|
|
9928
9929
|
if (!existing) {
|
|
9929
|
-
zip.file("word/comments.xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:comments xmlns:w="${W_NS}" xmlns:w14="${W14_NS}"></w:comments>`);
|
|
9930
|
+
zip.file("word/comments.xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:comments xmlns:w="${W_NS}" xmlns:mc="${MC_NS}" xmlns:w14="${W14_NS}" mc:Ignorable="w14"></w:comments>`);
|
|
9930
9931
|
return 0;
|
|
9931
9932
|
}
|
|
9932
9933
|
const body = await existing.async("string");
|
|
9933
|
-
return (body
|
|
9934
|
+
return maxId(body, /<w:comment\b[^>]*?\sw:id="(\d+)"/g) + 1;
|
|
9935
|
+
}
|
|
9936
|
+
function maxId(xml, re) {
|
|
9937
|
+
let max = -1;
|
|
9938
|
+
for (const m of xml.matchAll(re))
|
|
9939
|
+
max = Math.max(max, Number(m[1]));
|
|
9940
|
+
return max;
|
|
9941
|
+
}
|
|
9942
|
+
function prepareCommentsRoot(xml) {
|
|
9943
|
+
xml = xml.replace(/<w:comments\b([^>]*?)\s*\/>/, "<w:comments$1></w:comments>");
|
|
9944
|
+
return xml.replace(/<w:comments\b[^>]*>/, (open) => {
|
|
9945
|
+
let tag = open.slice(0, -1);
|
|
9946
|
+
if (!/\sxmlns:w14=/.test(tag))
|
|
9947
|
+
tag += ` xmlns:w14="${W14_NS}"`;
|
|
9948
|
+
if (!/\sxmlns:mc=/.test(tag))
|
|
9949
|
+
tag += ` xmlns:mc="${MC_NS}"`;
|
|
9950
|
+
const ign = /\smc:Ignorable="([^"]*)"/.exec(tag);
|
|
9951
|
+
if (!ign)
|
|
9952
|
+
tag += ` mc:Ignorable="w14"`;
|
|
9953
|
+
else if (!ign[1].split(/\s+/).includes("w14")) {
|
|
9954
|
+
tag = tag.replace(ign[0], ` mc:Ignorable="${`${ign[1]} w14`.trim()}"`);
|
|
9955
|
+
}
|
|
9956
|
+
return `${tag}>`;
|
|
9957
|
+
});
|
|
9934
9958
|
}
|
|
9935
9959
|
async function addComments(bytes, comments) {
|
|
9936
9960
|
if (!comments.length)
|
|
@@ -9943,12 +9967,13 @@ async function addComments(bytes, comments) {
|
|
|
9943
9967
|
let doc = documentXml;
|
|
9944
9968
|
let commentsBody = "";
|
|
9945
9969
|
const skipped = [];
|
|
9970
|
+
const warnings = [];
|
|
9946
9971
|
const paraIds = comments.map(() => void 0);
|
|
9947
9972
|
const modern = [];
|
|
9948
9973
|
comments.forEach((c, batchIdx) => {
|
|
9949
9974
|
const target = c.anchor ? paras.find((p) => textOf(p.full).includes(c.anchor)) ?? null : paras[0];
|
|
9950
9975
|
if (c.anchor && !target) {
|
|
9951
|
-
skipped.push(c.anchor);
|
|
9976
|
+
skipped.push({ index: batchIdx, anchor: c.anchor });
|
|
9952
9977
|
return;
|
|
9953
9978
|
}
|
|
9954
9979
|
const id = startId++;
|
|
@@ -9958,27 +9983,67 @@ async function addComments(bytes, comments) {
|
|
|
9958
9983
|
doc = doc.replace(target.full, wrapped);
|
|
9959
9984
|
target.full = wrapped;
|
|
9960
9985
|
commentsBody += commentXml(id, c, paraId);
|
|
9961
|
-
|
|
9986
|
+
let parentParaId;
|
|
9987
|
+
if (c.replyTo != null) {
|
|
9988
|
+
parentParaId = paraIds[c.replyTo];
|
|
9989
|
+
if (!parentParaId) {
|
|
9990
|
+
warnings.push(c.replyTo >= 0 && c.replyTo < comments.length && skipped.some((s) => s.index === c.replyTo) ? `comment ${batchIdx}: replyTo ${c.replyTo} was skipped (anchor not found) \u2014 written as a top-level comment` : `comment ${batchIdx}: replyTo ${c.replyTo} does not refer to an earlier written comment in this batch \u2014 written as a top-level comment`);
|
|
9991
|
+
}
|
|
9992
|
+
}
|
|
9962
9993
|
modern.push({ paraId, parentParaId, author: c.author });
|
|
9963
9994
|
});
|
|
9964
9995
|
if (skipped.length === comments.length)
|
|
9965
|
-
throw new Error(`no anchor matched: ${skipped.join(", ")}`);
|
|
9996
|
+
throw new Error(`no anchor matched: ${skipped.map((s) => s.anchor).join(", ")}`);
|
|
9966
9997
|
zip.file("word/document.xml", doc);
|
|
9967
|
-
const cx = await zip.file("word/comments.xml").async("string");
|
|
9968
|
-
|
|
9969
|
-
|
|
9998
|
+
const cx = prepareCommentsRoot(await zip.file("word/comments.xml").async("string"));
|
|
9999
|
+
if (!cx.includes("</w:comments>"))
|
|
10000
|
+
throw new Error("word/comments.xml has no <w:comments> root");
|
|
10001
|
+
const cxOut = cx.replace("</w:comments>", `${commentsBody}</w:comments>`);
|
|
10002
|
+
const bodies = new Set([...cxOut.matchAll(/<w:comment\b[^>]*?\sw:id="(\d+)"/g)].map((m) => m[1]));
|
|
10003
|
+
const dangling = [...new Set([...doc.matchAll(/<w:comment(?:RangeStart|RangeEnd|Reference)\b[^>]*?\sw:id="(\d+)"/g)].map((m) => m[1]))].filter((id) => !bodies.has(id));
|
|
10004
|
+
if (dangling.length)
|
|
10005
|
+
throw new Error(`internal: comment id(s) ${dangling.join(", ")} referenced in document.xml have no <w:comment> body`);
|
|
10006
|
+
zip.file("word/comments.xml", cxOut);
|
|
9970
10007
|
await writeModernCommentParts(zip, modern);
|
|
9971
10008
|
const out = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
9972
|
-
return new Uint8Array(out);
|
|
10009
|
+
return { bytes: new Uint8Array(out), written: comments.length - skipped.length, skipped, warnings };
|
|
10010
|
+
}
|
|
10011
|
+
function bodySectPrOffset(documentXml, bodyEnd) {
|
|
10012
|
+
let found = -1;
|
|
10013
|
+
let pPrDepth = 0;
|
|
10014
|
+
let changeDepth = 0;
|
|
10015
|
+
const re = /<(\/?)w:(pPr|sectPrChange|sectPr)\b[^>]*?(\/?)>/g;
|
|
10016
|
+
re.lastIndex = Math.max(0, documentXml.indexOf("<w:body"));
|
|
10017
|
+
let m;
|
|
10018
|
+
while ((m = re.exec(documentXml)) && m.index < bodyEnd) {
|
|
10019
|
+
const [, close, name, selfClose] = m;
|
|
10020
|
+
if (selfClose) {
|
|
10021
|
+
if (name === "sectPr" && pPrDepth === 0 && changeDepth === 0)
|
|
10022
|
+
found = m.index;
|
|
10023
|
+
continue;
|
|
10024
|
+
}
|
|
10025
|
+
const d = close ? -1 : 1;
|
|
10026
|
+
if (name === "pPr")
|
|
10027
|
+
pPrDepth += d;
|
|
10028
|
+
else if (name === "sectPrChange")
|
|
10029
|
+
changeDepth += d;
|
|
10030
|
+
else if (!close && pPrDepth === 0 && changeDepth === 0)
|
|
10031
|
+
found = m.index;
|
|
10032
|
+
}
|
|
10033
|
+
return found;
|
|
9973
10034
|
}
|
|
9974
10035
|
async function addTrackedInsertion(bytes, ins) {
|
|
9975
10036
|
const { zip, documentXml } = await loadDocx(bytes);
|
|
9976
|
-
const date = ins.date ?? "1970-01-01T00:00:00Z";
|
|
9977
|
-
const
|
|
9978
|
-
const
|
|
9979
|
-
|
|
10037
|
+
const date = escXml(ins.date ?? "1970-01-01T00:00:00Z");
|
|
10038
|
+
const author = escXml(ins.author);
|
|
10039
|
+
const base = maxId(documentXml, /\sw:id="(\d+)"/g) + 1;
|
|
10040
|
+
const para = `<w:p><w:pPr><w:rPr><w:ins w:id="${base}" w:author="${author}" w:date="${date}"/></w:rPr></w:pPr><w:ins w:id="${base + 1}" w:author="${author}" w:date="${date}"><w:r><w:t xml:space="preserve">${escXml(ins.text)}</w:t></w:r></w:ins></w:p>`;
|
|
10041
|
+
const bodyEnd = documentXml.lastIndexOf("</w:body>");
|
|
10042
|
+
if (bodyEnd < 0)
|
|
9980
10043
|
throw new Error("could not locate document body");
|
|
9981
|
-
|
|
10044
|
+
const sect = bodySectPrOffset(documentXml, bodyEnd);
|
|
10045
|
+
const at = sect >= 0 ? sect : bodyEnd;
|
|
10046
|
+
zip.file("word/document.xml", documentXml.slice(0, at) + para + documentXml.slice(at));
|
|
9982
10047
|
const out = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
9983
10048
|
return new Uint8Array(out);
|
|
9984
10049
|
}
|
|
@@ -10095,10 +10160,12 @@ function die(msg, code = 1) {
|
|
|
10095
10160
|
}
|
|
10096
10161
|
var nowIso = () => (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "Z");
|
|
10097
10162
|
async function main() {
|
|
10098
|
-
const
|
|
10163
|
+
const argv = process.argv.slice(2);
|
|
10164
|
+
const strictAnchors = argv.includes("--strict-anchors");
|
|
10165
|
+
const [mode, inDocx, out, a, b] = argv.filter((x) => x !== "--strict-anchors");
|
|
10099
10166
|
try {
|
|
10100
10167
|
if (mode === "comment") {
|
|
10101
|
-
if (!inDocx || !out || !a) die("usage: docx-annotate comment <in.docx> <out.docx> <comments.json>", 64);
|
|
10168
|
+
if (!inDocx || !out || !a) die("usage: docx-annotate comment <in.docx> <out.docx> <comments.json> [--strict-anchors]", 64);
|
|
10102
10169
|
let comments;
|
|
10103
10170
|
try {
|
|
10104
10171
|
comments = JSON.parse(await (0, import_promises.readFile)(a, "utf8"));
|
|
@@ -10107,9 +10174,18 @@ async function main() {
|
|
|
10107
10174
|
}
|
|
10108
10175
|
if (!Array.isArray(comments) || !comments.length) die("comments json must be a non-empty array", 64);
|
|
10109
10176
|
const bytes = new Uint8Array(await (0, import_promises.readFile)(inDocx).catch((e) => die(`cannot read ${inDocx}: ${e.message}`)));
|
|
10110
|
-
const
|
|
10111
|
-
await (0, import_promises.writeFile)(out, Buffer.from(
|
|
10112
|
-
process.
|
|
10177
|
+
const r = await addComments(bytes, comments.map((c) => ({ date: nowIso(), ...c })));
|
|
10178
|
+
await (0, import_promises.writeFile)(out, Buffer.from(r.bytes));
|
|
10179
|
+
for (const w of r.warnings) process.stderr.write(`docx-annotate: warning: ${w}
|
|
10180
|
+
`);
|
|
10181
|
+
if (r.skipped.length) {
|
|
10182
|
+
process.stderr.write(
|
|
10183
|
+
`docx-annotate: warning: ${r.skipped.length} of ${comments.length} comment(s) NOT written \u2014 anchor matched no paragraph: ` + r.skipped.map((s) => `#${s.index} ${JSON.stringify(s.anchor)}`).join(", ") + " (anchors must match text within one paragraph)\n"
|
|
10184
|
+
);
|
|
10185
|
+
}
|
|
10186
|
+
const ok = !(strictAnchors && r.skipped.length);
|
|
10187
|
+
process.stdout.write(JSON.stringify({ ok, out, written: r.written, skipped: r.skipped, warnings: r.warnings }) + "\n");
|
|
10188
|
+
if (!ok) process.exit(1);
|
|
10113
10189
|
return;
|
|
10114
10190
|
}
|
|
10115
10191
|
if (mode === "suggest") {
|