Plain-text citations and an existing reference list in a Microsoft Word .docx manuscript are converted into EndNote-compatible Word fields while preserving the document's visible text and formatting as far as the OOXML structure permits.
The hardened converter is the default entry point:
python endnote_docx.py -i manuscript.docx -o manuscript_EndNote.docx --strictThe original specialized converters remain in endnote-fieldcode-converter/scripts/ for compatibility, but new conversions should start with the root-level endnote_docx.py.
The converter does not rewrite whole paragraphs. It isolates only the detected citation range, preserves the existing result text and run properties, and inserts compound Word fields containing:
ADDIN EN.CITE- nested
ADDIN EN.CITE.DATA - Base64-encoded EndNote XML with the cited records
- one
ADDIN EN.REFLISTwrapper around the existing bibliography when the reference section can be wrapped safely
It also provides a deterministic fallback for documents that cannot be resolved automatically. An analysis report contains a manual_mapping_template; unresolved citations, missing references, or nonstandard citation spans can be explicitly mapped and then converted in --strict mode.
Python 3.9 or later is recommended.
python -m pip install -r requirements-hardened.txtOnly lxml is required by the hardened converter.
python endnote_docx.py \
-i manuscript.docx \
--analyze \
--strict \
--report manuscript.endnote-analysis.jsonIn strict analysis mode, exit code 1 means that the report contains an unresolved or unsafe item. No output DOCX is written.
python endnote_docx.py \
-i manuscript.docx \
-o manuscript_EndNote.docx \
--strict \
--report manuscript.endnote-report.jsonpython endnote_docx.py \
-i manuscript.docx \
-o manuscript_EndNote.docx \
--metadata library.ris \
--metadata additional.bib \
--strictSupported metadata inputs are RIS, ENW/EndNote tagged text, BibTeX, JSON, and CSL-JSON.
Edit the manual_mapping_template in the analysis report, or save that object as a separate JSON file, and run:
python endnote_docx.py \
-i manuscript.docx \
-o manuscript_EndNote.docx \
--mapping manuscript.endnote-mapping.json \
--strictSee MANUAL_MAPPING_KO.md, manual-mapping.schema.json, and examples/manual-mapping.example.json.
Automatic detection covers common forms including:
[1],[1,2,5],[1–3,5](1),(1, 2)- full-width punctuation variants
- true superscript numeric citations
(Smith, 2020; Jones, 2021)Smith et al. (2020)and corresponding Korean narrative author-year patterns- EndNote temporary citations such as
{Smith, 2020 #15} - citation text split across adjacent Word runs
- citations in the main document, tables, headers, footers, footnotes, endnotes, comments, glossary parts, and text boxes when represented as WordprocessingML paragraphs
Existing EndNote fields are detected and not nested again. Text in deleted tracked-change markup or hidden text is not treated as an ordinary visible citation.
A reference section is detected under headings such as References, Reference, Bibliography, or 참고문헌. Explicit bracketed or dotted numbering is preferred. The parser extracts, where available:
- authors
- year
- title
- journal or book title
- publisher
- volume, issue, and pages
- DOI
- PMID
- URL
- original formatted reference text
External metadata is matched first by DOI or PMID, then conservatively by title and author/year. Ambiguous matches are reported rather than guessed.
Before a final DOCX is committed, the converter checks:
- visible text equality before and after conversion
- per-character run-property equality for visible result text
- balanced Word field begin/separate/end markers
- decodable
w:fldDatapayloads and valid EndNote XML records - ZIP integrity and XML parseability
- reopening and revalidating the staging DOCX
- unchanged ZIP members retaining their original byte hashes
- absence of unresolved items in strict mode
The output is written to a staging file first and then atomically moved into place. --in-place is available only explicitly and creates a .pre-endnote.bak backup after staging validation.
-i, --input PATH input DOCX
-o, --output PATH output DOCX; default: *_EndNote.docx
--report PATH JSON analysis/conversion report
--analyze analyze only; do not write a DOCX
--strict block output if any unresolved or unsafe item remains
--mapping PATH manual mapping JSON or prior report
--ignore-mapping-hash deliberately use a mapping made for another DOCX
--metadata PATH RIS, ENW, BibTeX, JSON, or CSL-JSON; repeatable
--stories all|main process all Word story parts or main document only
--citation-style MODE auto|all|lancet|numeric|author-year|temporary
--bibliography wrap|keep|none wrap existing bibliography, retain it unfielded, or skip
--overwrite replace an existing output or backup
--in-place replace input after validation and create backup
Run python endnote_docx.py --help for the authoritative option list.
.
├── endnote_docx.py # hardened converter
├── requirements-hardened.txt
├── QUICKSTART_KO.md
├── MANUAL_MAPPING_KO.md
├── WORD_ENDNOTE_ACCEPTANCE_CHECKLIST_KO.md
├── BUILD_VERIFICATION.md
├── CHANGELOG_HARDENED.md
├── manual-mapping.schema.json
├── examples/
│ └── manual-mapping.example.json
├── tests/
│ └── test_hardened_converter.py
└── endnote-fieldcode-converter/ # original Skill and legacy utilities
└── scripts/
└── endnote_docx.py # compatibility launcher to root converter
The converter can always reach a deterministic outcome for an ordinary, readable, unsigned DOCX by either automatic mapping or explicit manual mapping. It intentionally does not claim that every document can be converted without review. Structurally corrupt, encrypted, or digitally signed packages are blocked; a working unsigned copy is required. Citations whose exact text range cannot be isolated safely are also blocked in strict mode rather than converted destructively.
Microsoft Word and the proprietary EndNote CWYW add-in are still required for the final application-level acceptance test, including opening the document, editing one citation, and running "Update Citations and Bibliography". Use WORD_ENDNOTE_ACCEPTANCE_CHECKLIST_KO.md for that test.
python -m unittest discover -s tests -vA reproducible verification wrapper is also included:
python verify_hardened_build.pyMIT. See LICENSE.