Skip to content

feat: external concept parenthesization in generic relations - #207

Merged
ronaldtse merged 2 commits into
mainfrom
feat/external-concepts-generic
Aug 11, 2026
Merged

feat: external concept parenthesization in generic relations#207
ronaldtse merged 2 commits into
mainfrom
feat/external-concepts-generic

Conversation

@ronaldtse

Copy link
Copy Markdown
Member

Summary

GenericRelationList.vue now handles external concepts the same as PartitiveRelationList — wrapping labels in parentheses per ISO 704 §5.5.4.3.1.

Changes:

  • GenericRelationList: external concept detection + parenthesization for both comprehensive and members
  • formatExternalLabel: guard against double-wrapping already-parenthesized labels
  • 4 tests

Before: generic relations showed external concepts identically to regular concepts — no visual signal.
After: both partitive and generic relations parenthesize external concepts consistently.

Test plan

  • 1565 tests pass (2 flaky perf timing)
  • Build succeeds
  • External label wrapping tests pass
  • No double-wrap guard tested

The table converter only understood the simplest shape (`| a | b | c`).
Four problems appeared on real-world tables (VIM 1.1 Note 1 is the
canonical case — a 5-column bilingual table of quantities with their
symbols):

1. `[cols="3", options="noheader,unnumbered"]` attribute lines before
   `|===` leaked as literal text.
2. `.2+` and `2+` cell-span modifiers leaked as cell content.
3. ` +` continuation markers leaked as cell text instead of joining the
   next physical line into the same cell.
4. `escapeHtml` was applied to cells that already contained rendered
   `<span class="math-pending">` markup from stage 1, double-escaping
   the angle brackets and rendering the spans as literal text.

Fixes:

- `stripAsciiDocTableAttributes()` consumes `[cols=…]` lines before the
  opener `|===`.
- `ASCII_DOC_LEADING_SPAN_PIPE_RE` strips leading `.N+|` / `N+|`
  modifiers; `ASCII_DOC_CELL_SPAN_RE` strips leading `.N+` modifiers
  inside cells.
- Rewrote row accumulation as a state machine with `rowHasContinuation`
  and `prevLineEndedWithContinuation`. The disambiguation rule:
  + Simple format (no `+` ever used): each leading `|` line is a new row.
  + Continuation format (row has used `+`): each leading `|` line is a
    new CELL in the same row. This is how bilingual sources lay out
    English + French as two lines of the same cell.
  + Continuation lines split on `|` so a line like
    `french line | cell-b` extends the previous cell with `french line`
    and starts a new cell with `cell-b`.
- Removed `escapeHtml` from `<th>` / `<td>` emission. Cells may contain
  already-rendered math spans (stage 1) and inline formatting (stage 3,
  applied after this stage); escaping them breaks both.

5 new tests covering attribute stripping, span stripping, `+`
continuation joining, row grouping under continuation, and math-span
preservation. All 1562 existing tests still pass.
GenericRelationList.vue now handles external concepts the same way
PartitiveRelationList does — wrapping labels in parentheses per
ISO 704 §5.5.4.3.1.

Changes:
- GenericRelationList: imports isExternalMember/isExternalComprehensive/
  formatExternalLabel, builds externalStore + externalCache, applies
  formatExternalLabel to both comprehensive and member designations
- formatExternalLabel: guard against double-wrapping already-parenthesized
  labels
- 4 tests: parens wrapping, regular passthrough, empty labels, no double-wrap

Previously generic relations showed external concepts identically to
regular concepts — no visual signal. Now both partitive and generic
relations parenthesize external concepts consistently.
@ronaldtse
ronaldtse merged commit e89c140 into main Aug 11, 2026
3 checks passed
@ronaldtse
ronaldtse deleted the feat/external-concepts-generic branch August 11, 2026 06:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant