视觉画布设计
canvas-design
基于设计原则创作静态视觉作品,用于海报与品牌图形。
docx-template-translator【文档与办公】Adaptive conversion of LaTeX, PDF, or Markdown sources into a complete Word .docx that follows a user-supplied .docx template. Use when pandoc --reference-doc alone is not enough — for thesis, dissertation, report, or institutional Word formatting that needs cover pages, declarations, TOC, heading numbering, captions, three-line tables, equations, ci…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Treat the input file as the content source and the Word template as the formatting source. Do not expect pandoc or PDF import to infer template semantics. Build a project-specific Python postprocessor after inspecting the template and the converted body document.
Do not treat the bundled starter pipeline or a preset JSON file as a finished converter for institutional templates. For thesis/dissertation templates, you must create or patch a project-specific pipeline for the concrete template and source project before claiming success.
.tex project, .pdf, .md, or an existing rough .docx..docx.python scripts/inspect_docx_template.py template.docx --out template_report.json.docx:
pdf2docx; prefer PDF only when the original source is unavailable.scripts/adaptive_docx_pipeline.py.Heading 1/2/3 can silently become an unrelated template style when source and template style IDs collide.formatting_start_marker. Never run body-style remapping across native cover/declaration pages.致谢 must not appear on body pages.scripts/finalize_word_docx.py to update fields/TOC and export a PDF preview.scripts/validate_docx_conversion.py final.docx --template template.docx --protected-until "中 文 摘 要" --pdf final.pdf --out validation.json for placeholder/order/header/image/table checks plus protected-front-matter format checks. Choose the real first generated marker for non-Zhengzhou templates.scripts/validate_docx_render.py final.docx --pdf final.pdf --out validation_render.json for render-level checks: TOC field presence, numId↔abstractNum consistency, multilevel heading format, reference-counter independence, body-header static-text leakage, and PDF field-error strings. The structural validator can return PASS while the document is visibly broken; the render validator is what catches "empty TOC", "chapters not auto-numbered", "references start at [47]", "body header still says 致谢", and "STYLEREF prints 错误!使用'开始'选项卡…".scripts/render_pdf_preview.py to inspect cover pages, abstracts, TOC, representative tables, figures, formulas, and references.Before reporting success, run an automated and visual QA pass. If any check fails, patch the project-specific pipeline and rerun; do not present the output as complete.
致谢, Acknowledgements, 参考文献, or sample appendices.李四, 王五, 张三, red formatting instructions, lorem ipsum, sample chapter headings, and template-only reference lists.validate_docx_render.py)The structural quality gate above checks counts and presence. It can return
PASS while the rendered Word/PDF is visibly broken because pandoc-derived
DOCX bodies often ship with a TOC paragraph that has no field, a Heading 1
style with no <w:numPr>, a numId rebound to a single-level abstract during
reference repair, or a body section header whose static text is "致谢". Run
validate_docx_render.py after validate_docx_conversion.py to catch those:
<w:fldChar w:fldCharType="begin"> plus <w:instrText> TOC . If absent, Word's "update fields" cannot populate a non-existent TOC. Use scripts/inject_toc_field.py to add one before finalization.(numId, ilvl) pair used by a paragraph or by a style's <w:numPr> must resolve to a defined <w:lvl ilvl=N> inside the bound abstract numbering. Missing levels silently fall back to level 0 — that is how 1.1 / 1.1.1 headings collapse to [1] after a reference repair re-points numId=1 at a single-level abstract.lvlText matching the user-supplied chapter prefix pattern (default 第%1章 or Chapter %1) at level 0 and a multilevel pattern (default contains both %1 and %2) at levels 1/2. Configure with --chapter-prefix-pattern and --multilevel-pattern for non-default templates.参考文献 / References Heading 1 must not reuse a numId already used by Heading 1/2/3. This is the bug where 33 references render as [47]–[79] because their counter was shared with H2/H3 paragraphs upstream.<w:headerReference>, the referenced headerN.xml must either contain a Word field (<w:fldChar>) or its static text must not equal 致谢 / Acknowledgements / 参考文献 / 附录 / 攻读学位期间…. The recommended fix is scripts/set_styleref_header.py --style-id 1 so the header dynamically shows the current chapter title.错误!, Error!, !Reference source not found, !未找到引用源). These appear when STYLEREF/PAGEREF/REF can't resolve their target and are an immediate FAIL.--source-latex-dir <dir> or --min-figures <N>): rendered <w:drawing> count must be ≥ the LaTeX project's \includegraphics count. Pandoc silently drops figures whose path lacks an explicit extension (e.g. \includegraphics{thesis_structure}) when the basename also matches a vector file (.pdf / .vsdx). The structural validator counts what was embedded; this check tells you what should have been embedded.--expected-table-style three-line for Chinese-thesis templates, default any): every data table must classify as a recognizable three-line layout (top heavy, header-row bottom thin, last-row bottom heavy, vertical edges nil) or a tblStyle that may carry borders. A docx that contains 20 borderless tables when the template requires three-line tables is the failure mode this catches. Layout/wrapper tables (≤ --table-min-data-rows rows) are skipped.--source-latex-dir <dir> or --min-citations <N>): the docx must contain at least as many <w:hyperlink w:anchor="ref_*"> elements as the source has \cite{} calls. Pandoc's default behavior is to render \cite{key} as (Author Year) — a visible author-year token but without an internal hyperlink. For GB/T 7714 thesis style every citation must render as numeric [N] superscript hyperlinking to the bibliography entry; missing this is invisible to image-count / paragraph-count validators.--source-latex-dir <dir> or --min-figure-captions <N> / --min-table-captions <N>): count caption-style paragraphs (图 X.Y / 表 X.Y lead, excluding inline body mentions like 图 4.4 与图 4.3 分别给出…) and require at least the source \begin{figure}+\caption / \begin{table}+\caption env count. The pandoc rough-conversion for Chinese theses commonly drops captions onto a plain body style without the chapter-relative number prefix; the structural validator counts <w:drawing> and <w:tbl> but never checks whether each has a labeled caption beside it.图/表/Figure/Table followed by a digit — must match the strict form 图 X.Y 说明文字 / 表 X.Y 说明文字 (with non-empty trailing description). The candidate filter must require a digit after the heading character so body sentences like 表格型 Q-learning… or 表中的实验配置… are not mistaken for captions. Inline body mentions like 图 4.4 与图 4.3 分别给出… are skipped via a verb-list pattern.w:jc="center". Off-center captions are the first thing a thesis reviewer flags and signal a pandoc-only conversion that did not run a caption-formatter pass.<w:drawing> paragraph must be followed (within one step, after collapsing adjacent drawing paragraphs into a single subfigure group) by a caption-pattern paragraph, and every data <w:tbl> (≥2 rows, ≥2 cells in the header row) must be preceded by one. Front-matter drawings before the first body Heading 1 (cover-page logos, school crests, declaration page emblems) are excluded — they are not captioned figures. This catches pandoc-converted figures whose caption was emitted as a plain body paragraph without the X.Y prefix.Demote any single check to a warning with --allow <check-name> when a project intentionally omits a TOC, intentionally shares a counter, etc.
doc.paragraphs / doc.tables.w:pStyle, w:rStyle, and w:tblStyle IDs by visible style name unless you have a stronger project-specific mapping.headerReference / footerReference entries after deleting sample sections..tex, .aux, .bbl, .toc, and source captions when pandoc loses numbering or labels.m:oMath unless necessary.numId (and a matching <w:abstractNum> with level 0 = [%1]) for the reference list — do not reuse the heading numId. Sharing the counter is what produces "33 references rendered as [47]…[79]" because the counter accumulates through every Heading 2/3 paragraph upstream.Body Text; inspect the template because those names may be repurposed.finalize_word_docx.py sets Word.Application.AutomationSecurity = msoAutomationSecurityForceDisable before opening the document; do not loosen this for inputs of unknown provenance.--three-line-tables or enable_three_line_tables in config). Don't enable it unless the target template actually requires that layout. When you do enable it, also write the borders through the raw <w:tc> elements inside the last <w:tr> — python-docx's row.cells wrappers silently no-op on vMerge="continue" cells, leaving a gap in the bottom heavy line at the end of any column whose final cell is a vertical-merge continuation.\includegraphics{name} to \includegraphics{name.png} (or whichever raster extension exists alongside) before invoking pandoc. Pandoc resolves bare basenames against the cwd, prefers vector extensions (.pdf, .vsdx), and silently drops the figure when it cannot embed the vector. Always cross-check the rendered <w:drawing> count against the source \includegraphics count via validate_docx_render.py --source-latex-dir.These are recurring failures observed when running this skill on real institutional templates. Each line names what to look for and which script or rule fixes it.
<w:fldChar> field after it. Word's "update fields" pass does nothing. → Run scripts/inject_toc_field.py final.docx --in-place before finalization, or detect via the toc-field check in validate_docx_render.py.<w:numPr> and the body H1 paragraphs also have no inline numPr. → Either add <w:numPr><w:ilvl w:val="0"/><w:numId w:val="N"/></w:numPr> to the Heading 1 style, or insert paragraph-level numPr on every body H1 (skip the unnumbered front/back-matter titles like 摘要/ABSTRACT/参考文献/附录/致谢/攻读…). Detected by the multilevel-headings check.[1], not 1.1 / 1.1.1. A reference repair re-pointed numId=1 at a single-level abstract list. Heading 2/3 paragraphs use (numId=1, ilvl=1/2) and fall back to level 0 = [%1]. → Restore the multilevel binding (the abstractNum whose level 0 is 第%1章 and level 1/2 contain %1.%2 / %1.%2.%3) and assign references their own numId. Detected by the numbering-consistency check.[47] instead of [1]. The reference list shares numId=1 with body Heading 2/3 paragraphs, so the counter has already advanced through 46 sections before it reaches [1]. → Allocate a fresh numId for the reference list. Detected by the ref-counter-independence check.headerReference whose target headerN.xml has the static text 致谢. → Run scripts/set_styleref_header.py final.docx --header headerN.xml --style-id 1 --in-place to replace the static text with a STYLEREF field that resolves to the current chapter heading. Detected by the body-header-non-back-matter check.错误!使用'开始'选项卡… or Error! No text of specified style…. A STYLEREF "Heading 1" field references the display name of the heading style; on localized templates the actual style name is "heading 1" (lowercase) or "标题 1", and the field cannot resolve. → Use STYLEREF 1 (the numeric styleId); set_styleref_header.py defaults to this. Detected by the pdf-field-errors check when --pdf is supplied.<w:pgNumType> and silently inherits whichever format the previous (Roman) section used. → Set <w:pgNumType w:fmt="decimal" w:start="1"/> on the body section's sectPr. For thesis templates that demand a separate Roman TOC section and Arabic body section, insert a section break between TOC and the first body chapter and give each its own pgNumType.\includegraphics{name} reference omits the extension and the basename also matches a vector file (name.pdf / name.vsdx) which pandoc cannot embed. → Either preprocess the LaTeX to add .png to every \includegraphics, or post-process the rough DOCX to insert the missing images at their caption paragraphs (from docx import Document; new_p.add_run().add_picture(...)). Detected by the figure-count-vs-source check when --source-latex-dir is supplied.format_three_line_tables, or only ran set_cell_border through python-docx's cell wrappers (which silently no-op on vMerge="continue" cells whose wrappers collapse onto the merge-start cell above). → Call format_three_line_tables from adaptive_docx_pipeline.py, or fall back to writing <w:tcBorders> directly into the raw <w:tc> elements inside <w:tr>. Detected by the table-border-style check with --expected-table-style three-line.(Author Year) instead of GB/T-7714 [N] superscript. Pandoc with default --citeproc (or no citeproc at all when the source uses \cite) emits (Zhu et al. 2025)-style author-year tokens — visible but not a Word hyperlink and not the numeric format Chinese thesis templates require. The structural validator counts paragraphs and reference bookmarks; it does not see that the in-text mark format is wrong. → After pandoc, parse main.bbl for \bibitem{key} order to build a cite_key → number map and a per-key (first_surname, year) token; walk every paragraph in document.xml looking for (Author Year[; Author Year]*) patterns; replace each with [N1, N2] wrapped in <w:hyperlink w:anchor="ref_N"> runs that carry <w:vertAlign w:val="superscript"/>. Disambiguate same-(surname,year) collisions (e.g. two Lozano-Cuadra 2024 or two Lu 2025 entries) by combining the bbl opt's secondary author list and the first author's initial from the bbl author line — pandoc emits (W. Lu et al. 2025) vs (J. Lu et al. 2025) exactly to disambiguate. Use word-boundary \b<initial>\b matching so single letters do not accidentally match inside et al.. Detected by the citation-coverage check.图 X.Y / 表 X.Y number prefix and not centered. Pandoc maps \caption{} to a plain body style without the chapter-relative number; \begin{figure} / \begin{table} envs that contain no embeddable visual (e.g. complex multirow tables) are dropped entirely, taking their captions with them. → Walk the docx body, advance a chapter counter on every body H1, count drawings (collapsing adjacent drawing paragraphs into one figure-group) and data <w:tbl> elements per chapter, and insert a centered caption paragraph after each figure-group / before each table. Source captions for the text content come from re-parsing each chapter's .tex for \begin{figure}…\caption{…} and \begin{table}…\caption{…} envs in document order. If pandoc dropped a table entirely, the missing caption surfaces as a caption-count-vs-source FAIL — re-render the lost <w:tbl> from \begin{tabular} separately rather than masking the gap. The three render-check pieces (caption-numbering, caption-centering, caption-untagged-near-figure-table) each enforce a different invariant; do not collapse them into one "caption format" check, because each can hide the others (e.g. centering everything that happens to be a numbered caption is meaningless if the numbering itself is missing on half the captions).When you add or change a check inside validate_docx_render.py (or any
text-pattern rule that disambiguates between candidates), follow these two
rules. Both come from real regressions on this skill.
Translate every user-visible requirement into its own enforcement, not
just its own detection. When the template demands "captions must be
图 X.Y 说明 AND centered", that is two requirements. A single
check_caption_format that filters paragraphs to "those already
matching 图 X.Y …" and then checks w:jc=center only enforces the
centering half — captions that lost the 图 X.Y prefix are silently
dropped from the candidate set and never reported. Split such checks
into one per requirement (in this skill: caption-numbering,
caption-centering, caption-untagged-near-figure-table) and make sure
the candidate filter for each does not depend on the other requirements
being met. The candidate filter for the "numbering" check must accept
paragraphs whose lead is 图/表 with a digit follow (so body
sentences like 表格型 Q-learning… or 表中的实验配置… are excluded
by the \d requirement, not by accidentally matching the numbering
pattern).
Disambiguation rules need a unit test before commit. When a citation
or anchor disambiguator picks one of N candidates by a heuristic
("with et al. → the one with more secondary authors"), write the
minimal unit test first:
assert disambig("(Lozano-Cuadra et al. 2024)") == "lozano2024". The
fall-back direction (keys_sorted[0] vs keys_sorted[-1]) is
coin-flip easy to write backwards from the comment, and the only
cheap way to catch the inversion is a fixture-driven test, not code
review. For the GB/T 7714 citation rewriter specifically: when two
bbl entries share (surname, year) and both carry et al., prefer
the one whose secondary-author set or first-author initial matches
the rendered author-year token; use word-boundary \b<initial>\b
matching so a single-letter initial does not accidentally match
inside et al. itself.
When a user files a list of complaints (e.g. "red text / double numbering / reference numbers / wrong header"), treat the list as a sample, not as an exhaustive bug catalog. Before reporting completion, run an explicit "source vs output" content audit at minimum:
\includegraphics (or equivalent figure references) in the source
project and compare to <w:drawing> in the final docx.\caption directives and compare to caption-styled paragraphs.\begin{table} and compare to <w:tbl> count with three-line
borders applied if the template requires three-line tables.Concretely, do not declare success based only on a structural validator's
PASS. Run the render validator with --source-latex-dir,
--expected-table-style, and --pdf, and fix anything they surface.
scripts/inspect_docx_template.py: dumps template styles (including those defined but unused in the body), paragraphs, tables, section settings, numbering hints, and hyperlink colors.scripts/adaptive_docx_pipeline.py: reusable starter pipeline for template-based reconstruction. It is a code base to copy and patch, not a final institutional-template converter. Behavior is config-driven (--config). It remaps copied DOCX style IDs by visible style name by default, provides run-preserving replacement helpers for protected regions, and can scope formatting with formatting_start_marker / formatting_end_marker. Optional config keys include clear_header_references, clear_footer_references, and heading_1_page_breaks. Three-line tables and other Chinese-thesis-specific tweaks are opt-in.scripts/finalize_word_docx.py: updates Word fields/TOC and optionally exports PDF through Word COM. Disables macros for safety, bootstraps missing Windows environment variables, and falls back through EnsureDispatch, DispatchEx, and Dispatch; use --prefer-dispatch-ex when an existing Word instance is unreliable.scripts/validate_docx_conversion.py: structural QA for common failures, including template placeholders, body/back-matter ordering, heading-style preservation, inherited section headers, image/table counts, and protected front-matter format drift against the original template.scripts/validate_docx_render.py: render-level QA that complements the structural validator. Twelve checks (TOC field, numbering consistency, multilevel heading format, reference-counter independence, body-header literal, figure-count-vs-source, table-border-style, citation-coverage, caption-count-vs-source, caption-numbering, caption-centering, caption-untagged-near-figure-table) plus the pdf-field-errors check when --pdf is supplied; each can be demoted with --allow. Run after Word COM finalization.scripts/inject_toc_field.py: idempotently insert a { TOC \o "1-3" \h \z \u } field after the 目录 / Contents / Table of Contents heading. Use when a rough conversion produced a TOC heading without a TOC field. Word's "update fields" cannot populate a TOC that isn't there.scripts/set_styleref_header.py: rewrite a single headerN.xml so its first paragraph contains a STYLEREF <styleId> \* MERGEFORMAT field that resolves to the current chapter title. Use --style-id 1 (numeric form) for portability — the display-name form fails on localized templates and prints 错误!使用'开始'选项卡… in the rendered header.scripts/render_pdf_preview.py: renders selected PDF pages into contact sheets for visual QA.presets/zhengzhou_thesis.json: style/table/hyperlink config for the Zhengzhou-University case study. It does not delete sample pages, fill cover fields, replace abstracts, rebuild TOC, or repair section headers by itself.references/pandoc-limitations.md when explaining why this workflow differs from pandoc defaults.references/zhengzhou-case-study.md when building or adapting a university-thesis pipeline.