#!/bin/sh set -eu SKILL_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) NODE=${NODE:-node} TMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/gongwen-test.XXXXXX") trap 'rm -rf "$TMP_DIR"' EXIT GEN="$SKILL_DIR/scripts/generate_gongwen_docx.mjs" VERIFY="$SKILL_DIR/scripts/verify_gongwen_docx.mjs" FIXTURE="$SKILL_DIR/tests/fixture.md" "$NODE" --check "$GEN" "$NODE" --check "$VERIFY" "$NODE" --check "$SKILL_DIR/tests/measure-header-coordinates.mjs" "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/layout.docx" --format ordinary --org "不应变红头的单位" --title "公文格式回归测试" --page-number center "$NODE" "$VERIFY" --input "$TMP_DIR/layout.docx" --profile ordinary unzip -t "$TMP_DIR/layout.docx" >/dev/null ! unzip -p "$TMP_DIR/layout.docx" word/document.xml | grep -q 'FF0000' unzip -p "$TMP_DIR/layout.docx" word/styles.xml | grep -q 'styleId="Heading4"' unzip -p "$TMP_DIR/layout.docx" word/document.xml | grep -q 'w:pStyle w:val="Heading4"' "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/standard.docx" --format formal --letterhead preprinted --letterhead-reserve-mm 72 --org "示例单位文件" --doc-no "示例发〔2026〕1号" --title "公文格式回归测试" --page-number standard "$NODE" "$VERIFY" --input "$TMP_DIR/standard.docx" --profile formal --letterhead preprinted ! unzip -p "$TMP_DIR/standard.docx" word/document.xml | grep -q '示例单位文件' unzip -p "$TMP_DIR/standard.docx" word/document.xml | grep -q '示例发〔2026〕1号' unzip -p "$TMP_DIR/standard.docx" word/document.xml | grep -q 'w:snapToGrid w:val="false"' "$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 unzip -p "$TMP_DIR/digital.docx" word/document.xml | grep -q '示例单位文件' unzip -p "$TMP_DIR/digital.docx" word/document.xml | grep -q 'FF0000' unzip -p "$TMP_DIR/digital.docx" word/document.xml | grep -q 'height:0.5mm' unzip -p "$TMP_DIR/digital.docx" word/document.xml | grep -q 'w:framePr.*w:hAnchor="margin".*w:vAnchor="margin".*w:xAlign="center".*w:y="1984"' unzip -p "$TMP_DIR/digital.docx" word/document.xml | grep -q 'w:before="0"' unzip -p "$TMP_DIR/digital.docx" word/document.xml | grep -q 'w:snapToGrid w:val="false"' "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/digital-fields.docx" --format formal --letterhead digital --copy-no 7 --secret "机密★3年" --urgent "特急" --org "示例单位文件" --doc-no "示例发〔2026〕3号" --title "版头字段定位测试" "$NODE" "$VERIFY" --input "$TMP_DIR/digital-fields.docx" --profile formal --letterhead digital unzip -p "$TMP_DIR/digital-fields.docx" word/document.xml | grep -q 'w:framePr.*w:hAnchor="margin".*w:vAnchor="margin".*w:xAlign="left".*w:y="0"' unzip -p "$TMP_DIR/digital-fields.docx" word/document.xml | grep -q 'w:framePr.*w:hAnchor="margin".*w:vAnchor="margin".*w:xAlign="left".*w:y="560"' "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/secret-only.docx" --format formal --letterhead digital --secret "机密★3年" --org "示例单位文件" --doc-no "示例发〔2026〕5号" --title "密级首行留空测试" "$NODE" "$VERIFY" --input "$TMP_DIR/secret-only.docx" --profile formal --letterhead digital unzip -p "$TMP_DIR/secret-only.docx" word/document.xml | grep -q 'w:framePr.*w:vAnchor="margin".*w:y="560"' "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/preprinted-fields.docx" --format formal --letterhead preprinted --letterhead-reserve-mm 72 --copy-no 7 --secret "机密★3年" --urgent "特急" --doc-no "示例发〔2026〕4号" --title "预印字段定位测试" "$NODE" "$VERIFY" --input "$TMP_DIR/preprinted-fields.docx" --profile formal --letterhead preprinted unzip -p "$TMP_DIR/preprinted-fields.docx" word/document.xml | grep -q 'w:before="1984"' cat >"$TMP_DIR/attachment.md" <<'EOF' # 附件一:测试附件 附件正文。 EOF cat >"$TMP_DIR/main-send.md" <<'EOF' 各主送机关: 主送机关只应在输出中出现一次。 EOF "$NODE" "$GEN" --input "$TMP_DIR/main-send.md" --output "$TMP_DIR/main-send.docx" --format formal --letterhead digital --org "示例单位文件" --doc-no "示例发〔2026〕2号" --title "主送机关匹配测试" --to "各主送机关" test "$(unzip -p "$TMP_DIR/main-send.docx" word/document.xml | grep -o '各主送机关' | wc -l | tr -d ' ')" -eq 1 "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/upward.docx" --format formal --letterhead digital --org "示例单位文件" --doc-no "示例发〔2026〕1号" --title "上行文测试" --upward true --signer "张三" "$NODE" "$VERIFY" --input "$TMP_DIR/upward.docx" --profile formal --letterhead digital --upward true unzip -p "$TMP_DIR/upward.docx" word/document.xml | grep -q '签发人:' "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/letter.docx" --format letter --org "示例机关" --doc-no "示例〔2026〕1号" --title "信函测试" "$NODE" "$VERIFY" --input "$TMP_DIR/letter.docx" --profile letter unzip -l "$TMP_DIR/letter.docx" | grep -q 'word/footerLetter.xml' unzip -p "$TMP_DIR/letter.docx" word/footerLetter.xml | grep -q 'w:fill="FF0000"' "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/with-attachment.docx" --format formal --letterhead preprinted --letterhead-reserve-mm 72 --doc-no "示例发〔2026〕1号" --title "附件测试" --attachment-note "1. 测试附件" --attachment-file "$TMP_DIR/attachment.md" unzip -p "$TMP_DIR/with-attachment.docx" word/document.xml | grep -q '附件:1. 测试附件' unzip -p "$TMP_DIR/with-attachment.docx" word/document.xml | grep -q 'w:pageBreakBefore' "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/detached-attachment.docx" --format formal --letterhead preprinted --letterhead-reserve-mm 72 --doc-no "示例发〔2026〕1号" --title "分离附件测试" --attachment-note "1. 测试附件" --attachment-file "$TMP_DIR/attachment.md" --attachment-detached unzip -p "$TMP_DIR/detached-attachment.docx" word/document.xml | grep -q '示例发〔2026〕1号 附件1' if "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/bad-attachment.docx" --format formal --letterhead preprinted --letterhead-reserve-mm 72 --doc-no "示例发〔2026〕6号" --title "附件一致性测试" --attachment-note "1. 另一份附件" --attachment-file "$TMP_DIR/attachment.md" >"$TMP_DIR/bad-attachment.out" 2>&1; then echo "mismatched attachment note unexpectedly succeeded" >&2 exit 1 fi grep -q 'GENERATOR ERROR:' "$TMP_DIR/bad-attachment.out" "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/command.docx" --format command --org "示例机关命令" --doc-no "第1号" --title "命令正文" "$NODE" "$VERIFY" --input "$TMP_DIR/command.docx" --profile command if "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/bad-command.docx" --format command --org "示例机关" --doc-no "第1号" --title "命令正文" >"$TMP_DIR/bad-command.out" 2>&1; then echo "command without 命令/令 unexpectedly succeeded" >&2 exit 1 fi grep -q 'GENERATOR ERROR:' "$TMP_DIR/bad-command.out" "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/minutes.docx" --format minutes --org "示例机关纪要" --title "纪要正文" --attendees "张三、李四" --absent "王五" "$NODE" "$VERIFY" --input "$TMP_DIR/minutes.docx" --profile minutes minutes_xml=$(unzip -p "$TMP_DIR/minutes.docx" word/document.xml) test "${minutes_xml%%出席:*}" != "$minutes_xml" test "${minutes_xml%%w:sectPr*}" != "$minutes_xml" test "${minutes_xml%%出席:*}" != "${minutes_xml%%w:sectPr*}" "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/seal-layout.docx" --format formal --letterhead preprinted --letterhead-reserve-mm 72 --title "签章位置测试" --sender "示例机关" --date "2026年9月10日" --seal-mode seal unzip -p "$TMP_DIR/seal-layout.docx" word/document.xml | grep -q 'w:right="1280"' if "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/bad-doc-no.docx" --format formal --letterhead digital --org "示例单位文件" --doc-no "示例发〔2026〕01号" --title "非法文号" >"$TMP_DIR/bad-doc-no.out" 2>&1; then echo "invalid document number unexpectedly succeeded" >&2 exit 1 fi grep -q 'GENERATOR ERROR:' "$TMP_DIR/bad-doc-no.out" if "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/bad-date.docx" --format formal --letterhead preprinted --date "2026年09月10日" --title "非法日期" >"$TMP_DIR/bad-date.out" 2>&1; then echo "invalid date unexpectedly succeeded" >&2 exit 1 fi grep -q 'GENERATOR ERROR:' "$TMP_DIR/bad-date.out" "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/letter-fields.docx" --format letter --org "示例机关" --copy-no 7 --secret "机密★3年" --urgent "特急" --doc-no "示例〔2026〕2号" --title "信函字段边界" "$NODE" "$VERIFY" --input "$TMP_DIR/letter-fields.docx" --profile letter unzip -p "$TMP_DIR/letter-fields.docx" word/document.xml | grep -q '000007' unzip -p "$TMP_DIR/letter-fields.docx" word/document.xml | grep -q '机密★3年' "$NODE" "$GEN" --input "$SKILL_DIR/tests/fixtures/visual-horizontal.md" --output "$TMP_DIR/horizontal-table.docx" --format horizontal-table --title "横排表格测试" --page-number standard "$NODE" "$VERIFY" --input "$TMP_DIR/horizontal-table.docx" --profile horizontal-table unzip -p "$TMP_DIR/horizontal-table.docx" word/document.xml | grep -q 'w:orient="landscape"' unzip -p "$TMP_DIR/horizontal-table.docx" word/document.xml | grep -q 'w:tblW w:w="12756"' "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/joint.docx" --format formal --letterhead digital --org "主办机关文件" --joint-org "协办机关" --doc-no "示例发〔2026〕3号" --title "联合行文测试" "$NODE" "$VERIFY" --input "$TMP_DIR/joint.docx" --profile formal --letterhead digital unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '主办机关' unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '协办机关' unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q '文件' unzip -p "$TMP_DIR/joint.docx" word/document.xml | grep -q 'w:sz w:val="48"' if "$NODE" "$GEN" --input "$FIXTURE" --output "$TMP_DIR/strict.docx" --format formal --letterhead digital --org "示例单位文件" --title "严格字体测试" --require-standard-fonts >"$TMP_DIR/strict.out" 2>&1; then if ! fc-list -f '%{family}\n' | grep -Eq '方正小标宋简体|方正小标宋_GBK|FZXiaoBiaoSong'; then echo "strict font mode unexpectedly succeeded without a small-standard-title font" >&2 exit 1 fi elif ! grep -q 'FONT ERROR:' "$TMP_DIR/strict.out"; then cat "$TMP_DIR/strict.out" >&2 echo "strict font mode failed for an unexpected reason" >&2 exit 1 fi if command -v soffice >/dev/null 2>&1; then mkdir -p "$TMP_DIR/pdf" soffice --headless --convert-to pdf --outdir "$TMP_DIR/pdf" "$TMP_DIR/layout.docx" >/dev/null 2>&1 test -s "$TMP_DIR/pdf/layout.pdf" fi printf '%s\n' "gongwen regression tests passed"