严格校验预印红头留白边界

This commit is contained in:
mizzlelover
2026-09-11 08:56:39 +08:00
parent 2cd937a22e
commit 9f41d72aab
3 changed files with 35 additions and 2 deletions
BIN
View File
Binary file not shown.
+16 -2
View File
@@ -165,9 +165,23 @@ if (profile === "formal") {
check("Upward document number and signer share one row", paragraphs(doc).some((p) => /签发人/.test(textOf(p)) && /|\[|文号|发/.test(textOf(p))), "signer is in the same paragraph row as the document number");
}
} else {
const preprintedReserveParagraph = /w:line="1" w:lineRule="exact"[\s\S]*?w:snapToGrid w:val="false"[\s\S]*?w:sz w:val="2"/.test(doc);
check("Preprinted letterhead reserve", preprintedReserveParagraph, "first-page top reserve is present");
const preprintedParagraphs = paragraphs(doc);
const reserveCandidate = (p) => /w:jc w:val="left"/.test(p)
&& /w:line="1"/.test(p)
&& /w:lineRule="exact"/.test(p)
&& /w:snapToGrid w:val="false"/.test(p)
&& /w:sz w:val="2"/.test(p)
&& /<w:t[^>]*> <\/w:t>/.test(p);
const reserveIndex = preprintedParagraphs.findIndex(reserveCandidate);
const reserveParagraph = reserveIndex >= 0 ? preprintedParagraphs[reserveIndex] : "";
const reserveSpacing = reserveParagraph.match(/<w:spacing\b[^>]*>/)?.[0] ?? "";
const reserveBefore = Number((reserveSpacing.match(/w:before="(\d+)"/) ?? [])[1]);
const reserveBeforeInRange = Number.isFinite(reserveBefore) && reserveBefore >= 0 && reserveBefore <= Math.round((130 - 37) * 56.692913);
const priorParagraphsAreFloating = reserveIndex >= 0 && preprintedParagraphs.slice(0, reserveIndex).every((p) => /w:framePr\b/.test(p));
const preprintedReserveParagraph = reserveIndex >= 0
&& priorParagraphsAreFloating
&& reserveBeforeInRange;
check("Preprinted letterhead reserve", preprintedReserveParagraph, "first non-floating body paragraph reserves 37-130 mm paper-top agency-mark space");
const titleXmlStart = firstTitleIndex < 0 ? doc.length : doc.indexOf(preprintedParagraphs[firstTitleIndex]);
const preprintedHeaderXml = titleXmlStart < 0 ? doc : doc.slice(0, titleXmlStart);
check("No red drawing for preprinted letterhead", !/w:color w:val="FF0000"/.test(preprintedHeaderXml), "preprinted mode does not redraw red letterhead or rule");
+19
View File
@@ -42,6 +42,25 @@ PY
"$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/preprinted-minimum.docx" --format formal --letterhead preprinted --letterhead-reserve-mm 37 --doc-no "示例发〔20267号" --title "最小预印留白测试"
"$NODE" "$VERIFY" --input "$TMP_DIR/preprinted-minimum.docx" --profile formal --letterhead preprinted
python3 - "$TMP_DIR/preprinted-minimum.docx" "$TMP_DIR/preprinted-malformed.docx" <<'PY'
import sys, zipfile
source, target = sys.argv[1:]
with zipfile.ZipFile(source) as src, zipfile.ZipFile(target, 'w', zipfile.ZIP_DEFLATED) as dst:
for item in src.infolist():
data = src.read(item.filename)
if item.filename == 'word/document.xml':
text = data.decode()
old = '<w:spacing w:before="0" w:after="0" w:line="1" w:lineRule="exact"/>'
assert text.count(old) == 1
text = text.replace(old, '<w:spacing w:before="0" w:after="0" w:line="560" w:lineRule="exact"/>', 1)
data = text.encode()
dst.writestr(item, data)
PY
if "$NODE" "$VERIFY" --input "$TMP_DIR/preprinted-malformed.docx" --profile formal >"$TMP_DIR/preprinted-malformed.out" 2>&1; then
echo "malformed preprinted reserve unexpectedly passed" >&2
exit 1
fi
grep -q 'Preprinted letterhead reserve' "$TMP_DIR/preprinted-malformed.out"
"$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/digital.docx" --format formal --letterhead digital --org "示例单位文件" --doc-no "示例发〔20261号" --title "电子红头测试" --page-number standard
"$NODE" "$VERIFY" --input "$TMP_DIR/digital.docx" --profile formal --letterhead digital