Skip to content

bug: preserve explicit false run properties across read/write #115

Description

@kiki830621

Problem

DocxReader.parseRunProperties treats <w:b>, <w:i>, <w:strike>, and <w:noProof> as true whenever the element exists, ignoring explicit off values such as w:val="0", false, or off. RunProperties.toXML() can then emit only the on form. A read → unrelated mutation → write round-trip therefore turns an untouched <w:b w:val="0"/> into <w:b/>.

Type

bug

Expected

  • Typed on/off run properties preserve three states: absent, explicitly on, explicitly off.
  • An untouched explicit-off property remains semantically off after save.
  • Existing source-compatible reads such as properties.bold still return false for absent and explicit-off states.
  • Merge/formatting APIs can intentionally apply false, rather than treating it as “unspecified”.

Actual

  • RunProperties.bold, italic, strikethrough, and noProof are plain Bool values.
  • The reader sets them to true on element presence.
  • The emitter omits false and emits naked elements for true.
  • merge(with:) applies only true, so callers cannot remove an existing boolean property.

Scope / Acceptance

  • Add RED→GREEN read/write tests for <w:b w:val="0"/>, including an unrelated paragraph mutation before save.
  • Cover accepted ST_OnOff spellings (0/false/off and omitted/1/true/on).
  • Preserve source compatibility for callers reading/writing the existing Bool properties.
  • Make merge distinguish an unspecified patch from an explicit false patch.
  • Cover italic, strikethrough, and noProof through the same typed mechanism; untyped raw run-property children remain outside this issue.
  • Run focused reader/writer/model tests and the full package suite.

Cross-repo tracking


Current Status

Phase: verified
Last updated: 2026-08-31 by idd-verify

Key Decisions

  • Preserve public Bool access while storing absent/on/off assignment presence internally.
  • Merge and copy by presence, not truthiness; explicit false and underline none survive parser, writer, RunPayload, reducer, reverse extractor, and revision paths.
  • rPrChange delegates to the single canonical RunProperties.toXML() emitter.

Blocking

  • (none)

Follow-up

Commits

  • 563039c — final program behavior.
  • a3fab8b — frozen consumer proof.

Verification

Pull Request

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions