Skip to content

v0.22.0 — math-script-insensitive anchor lookup

Choose a tag to compare

@kiki830621 kiki830621 released this 02 May 22:14
ce3ce3f

Highlights

AnchorLookupOptions.mathScriptInsensitive — bidirectional matching between Unicode math-script forms and ASCII for text-anchor lookup (findBodyChildContainingText / bodyChildContainsText / tableContainsText / InsertLocation.afterText / .beforeText).

Closes the lib-level dependency for PsychQuant/che-word-mcp#90 and unblocks che-word-mcp#115 (math_script_insensitive surface on insertion tools).

What's covered

  • Subscript / superscript digits — U+2080..U+2089, U+2070, U+2074..U+2079, U+00B2/³/¹ → ASCII 0..9
  • Subscript letters — U+2090..U+209C (full block, including U+2094 ₔ schwa)
  • Superscript letters — Latin lowercase a..z (no q in Unicode) + uppercase A..W (gaps Unicode-imposed, not implementation)
  • Greek subscripts U+1D66..U+1D6A — ᵦᵧᵨᵩᵪ → β γ ρ φ χ (common in stats / physics theses)
  • Combining-mark accents (U+0058 + U+0304) → X, ŷy etc. via Unicode NFD decomposition + nonspacing-mark stripping. Handles both precomposed and decomposed forms identically.
  • Bidirectional matching — needle and haystack both canonicalized; H₀ finds H0 AND H0 finds H₀.
  • Bracket / operator pairs — U+2080..U+208E + U+207A..U+207E for +, -, =, (, ).

Behavior notes

  • Default .exact is preserved — old call sites unchanged, no source-compat break.
  • Combining-mark stripping intentionally folds all NFD combining marks (e.g., cafécafe, = because decomposes to = + U+0338 overlay). This is the right trade-off for math anchor matching; callers needing exact-with-accents keep .exact.
  • Negative cases pinned: H₂H₃, Greek α ≠ ASCII a (no over-folding to ASCII variables).
  • No memoization — each .contains rerun canonicalizes both sides. For 1000+ paragraph docs with many lookups this is ~200-500ms; acceptable but a follow-up perf opportunity.

Test coverage

848 tests (1 skipped). New Issue90MathScriptAnchorLookupTests adds 19 cases covering each Unicode category, bidirectional matching, decomposed-vs-precomposed identity, and 3 negative cases (over-fold prevention).

Known gaps (follow-ups)

  • Greek superscripts U+1D5D..U+1D61, U+1D45 — not yet mapped
  • Mathematical Alphanumeric Symbols U+1D400..U+1D7FF (LaTeX/MathJax italic forms) — not yet mapped
  • MathAccent.visibleText only emits base glyph; combining-mark detection is matcher-side only

Migration

-.package(url: "https://github.com/PsychQuant/ooxml-swift.git", from: "0.21.0"),
+.package(url: "https://github.com/PsychQuant/ooxml-swift.git", from: "0.22.0"),

API is additive; no caller code changes required for existing usage.