严格校验预印红头留白边界
This commit is contained in:
Vendored
BIN
Binary file not shown.
@@ -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");
|
||||
|
||||
@@ -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 "示例发〔2026〕7号" --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 "示例发〔2026〕1号" --title "电子红头测试" --page-number standard
|
||||
"$NODE" "$VERIFY" --input "$TMP_DIR/digital.docx" --profile formal --letterhead digital
|
||||
|
||||
Reference in New Issue
Block a user