(path, opts, counts)
| 132 | |
| 133 | |
| 134 | def process_file(path, opts, counts): |
| 135 | with open(path, "r", encoding="utf-8") as fh: |
| 136 | original = fh.read() |
| 137 | front_matter, body, _start = blog_text.split_front_matter(original) |
| 138 | new_body = transform_body(body, opts, counts) |
| 139 | if new_body == body: |
| 140 | return None |
| 141 | # Guardrails: front matter byte-identical; protected constructs and the word |
| 142 | # sequence unchanged (we only ever delete whitespace, never characters). |
| 143 | new_full = front_matter + new_body |
| 144 | assert new_full.startswith(front_matter), f"front matter changed in {path}" |
| 145 | before, after = _invariants(body), _invariants(new_body) |
| 146 | for key in ("code_spans", "shortcodes", "links", "words"): |
| 147 | if before[key] != after[key]: |
| 148 | raise AssertionError( |
| 149 | f"{path}: transform changed protected content ({key}); refusing to write" |
| 150 | ) |
| 151 | if opts["write"]: |
| 152 | with open(path, "w", encoding="utf-8") as fh: |
| 153 | fh.write(new_full) |
| 154 | return path |
| 155 | |
| 156 | |
| 157 | def expand_paths(paths): |
no test coverage detected