Search-and-replace text merge over .docx files (body, headers, footers), cross-run XML matching — harvested from nestorwheelock/docsed
| Tier | infrastructure |
| Role | unclassified (baselined) |
| Path | crates/infrastructure/docx-merge |
| Edition | 2021 |
| Targets | infrastructure_docx_merge |
| Public items | 5 across 0 modules |
| Tests | 12 |
What it is for
Search-and-replace text merge over .docx files: body, headers, and footers, with cross-run XML matching so a search term split across Word's own <w:t> runs (which happens whenever the document was ever edited) still matches. Harvested from nestorwheelock/docsed (Alberto's PUMOT date-correction program, alberto-docsed) — proven in real use; this port adds the test coverage this framework requires (Gate 2.1), not a doubt about the original.
Verified against domain-legal-documents before this port (sprint 4.63, Consensus Log): that crate is record-keeping only (DocumentTemplate, GeneratedDocument — no substitution logic anywhere in it or in application-legal-documents), so this crate is the actual merge engine, not a duplicate of one.
Generalizes the original's single find/replace to an ordered list of replacements, so one call can fill every {{placeholder}} a mail-merge template needs, not just one search term per run.
Capabilities
crate root
Search-and-replace text merge over .docx files: body, headers, and
| Item |
|---|
fn replace_across_runs(run_texts : & String, search : & str, replace : & str,) -> Option <(Vec <String>, usize)> |
fn replace_in_xml(xml : & str, search : & str, replace : & str) ->(String, usize) |
DocxMergeError
Search-and-replace text merge over .docx files: body, headers, and
| Item |
|---|
pub enum DocxMergeError |
DocxMergeError :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result |
fn merge_docx_bytes(input : & u8, replacements : & (String, String),) -> Result <(Vec <u8>, usize), DocxMergeError> |
How to use it
No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.
Module structure
No public modules: the crate root is its whole surface.
Public surface
`crate root`
| Item | What it is |
|---|---|
pub enum DocxMergeError | — |
DocxMergeError :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result | — |
fn replace_across_runs(run_texts : & String, search : & str, replace : & str,) -> Option <(Vec <String>, usize)> | Given the visible-text runs of one <w:p> paragraph (already split by Word into however many <w:t> segments it happened to save), find every occurrence of search in the concatenated text — including one that spans a run boundary — and return each run's new text with search replaced by replace |
fn replace_in_xml(xml : & str, search : & str, replace : & str) ->(String, usize) | Runs replace_across_runs over every <w:p> paragraph in one XML part's content, applying a single (search, replace) pair |
fn merge_docx_bytes(input : & u8, replacements : & (String, String),) -> Result <(Vec <u8>, usize), DocxMergeError> | Merge an ordered list of (search, replace) pairs into a .docx's bytes, across body/headers/footers, applying each pair in sequence (so a mail-merge template's {{name}}, {{address}}, .. |
No pub use re-exports: every item above is declared in this crate.
Boundary
Depends on no other workspace tier.
Shares tier infrastructure with 82 other crates: infrastructure-acquire, infrastructure-adapters-google-calendar, infrastructure-adapters-google-gmail, infrastructure-adapters-google-places, infrastructure-adapters-google-trends, infrastructure-adapters-shodan, infrastructure-adapters-yelp, infrastructure-agent, … (82 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | infrastructure |
| Architectural role (taxonomy) | unclassified (baselined) |
| Location | crates/infrastructure/docx-merge |
| Vocabulary in force (lexicon) | current |
Dependencies
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
regex | ^1 | — | no | always |
zip | ^2 | — | no | always |
Development. None.
Build. None.
Depended on by. Nothing in this workspace.
Feature flags
No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.
Targets
| Kind | Name | Source |
|---|---|---|
| lib | infrastructure_docx_merge | `src/lib.rs` |
Error model
| Error type | Named by |
|---|---|
DocxMergeError | merge_docx_bytes |
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | none detected |
| async runtime | none detected |
| database access | none detected |
| network I/O | none detected |
| unsafe code | none detected |
| environment variables | none detected |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.
Related capabilities
No workspace crate depends on this one.
Verification
| Kind | Count |
|---|---|
| Unit tests | 12 |
| Integration tests | 0 |
| Examples | 0 |
| Doctests | 0 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
crate root | 4 | 0 | 0 |
What the tests establish, by name:
empty_search_never_matches—src/lib.rsmatch_split_across_three_runs_preserves_surrounding_text—src/lib.rsmatch_split_across_two_runs—src/lib.rsmatch_within_a_single_run—src/lib.rsmerge_docx_bytes_applies_every_placeholder_in_order—src/lib.rsmerge_docx_bytes_handles_a_placeholder_split_across_runs_by_word—src/lib.rsmerge_docx_bytes_with_no_matches_reports_zero_and_returns_input_unchanged—src/lib.rsmultiple_non_overlapping_matches_in_one_run—src/lib.rsno_match_returns_none—src/lib.rsreplace_in_xml_matches_across_two_runs—src/lib.rsreplace_in_xml_matches_within_one_run_and_preserves_the_tag—src/lib.rsreplace_in_xml_no_w_t_tags_is_left_untouched—src/lib.rs
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 3 | 5 |
Public modules with a //! block | 0 | 0 |
pie showData
title Public items with rustdoc
"Documented" : 3
"No rustdoc detected" : 2
Metrics
| Metric | Value |
|---|---|
| Rust source files | 1 |
| Source lines | 370 |
| Code lines | 299 |
| Public API items | 5 |
| Public modules | 0 |
| Tests | 12 |
| Examples | 0 |
| Cargo features | 0 |
| Direct runtime dependencies | 2 |
| Workspace reverse dependencies | 0 |
pie showData
title Public API by kind
"enum" : 1
"function" : 3
"method" : 1
pie showData
title Rust source composition
"Code" : 299
"Blank or comment" : 71
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.