Skip to content

feat(cjk): stack-based quote pairing and Latin span detection - #16

Merged
xiaolai merged 6 commits into
mainfrom
feat/cjk-typography-spec
Jan 29, 2026
Merged

feat(cjk): stack-based quote pairing and Latin span detection#16
xiaolai merged 6 commits into
mainfrom
feat/cjk-typography-spec

Conversation

@xiaolai

@xiaolai xiaolai commented Jan 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • Implement stack-based quote pairing algorithm with apostrophe/prime detection
  • Add Latin span scanner to protect technical constructs (URLs, versions, decimals, times) from CJK formatting rules
  • Preserve backslash-escaped punctuation in CJK formatting (e.g., \, stays as ,)
  • Add comprehensive battle tests for edge cases

Changes

New modules

  • latinSpanScanner.ts: Identifies Latin spans within CJK text, detects technical subspans (URLs, emails, versions, times, decimals, thousands)
  • quotePairing.ts: Stack-based algorithm for smart quote pairing with CJK context detection

Enhancements

  • rules.ts: Integrated Latin span protection for fullwidth punctuation conversion; added backslash escape handling
  • parser.ts: Escape pattern preprocessing for custom inline markers (\==, \++, \^, \~)
  • settingsStore.ts: Added contextualQuotes setting for curly/straight quote mode selection

Test plan

  • pnpm test - all 2600+ tests pass
  • Battle test suite covers edge cases from spec document
  • Quote pairing handles apostrophes (don't, it's), primes (5'10"), and decades ('90s)
  • Latin spans correctly protect URLs, versions (v1.2.3), times (12:30), decimals (3.14)

Add pre/post processing in parser.ts to handle escaped custom markers
(\==, \++, \^, \~). Uses Unicode Private Use Area placeholders to
preserve escape intent through remark parsing, then restores them
as literal characters after the tree is built.

Fixes issue where \==text== was rendered as highlighted instead of
literal ==text==.
- Add latinSpanScanner.ts for detecting Latin spans and technical subspans
  (URLs, emails, versions, decimals, times, thousands, domains)
- Add quotePairing.ts with stack-based algorithm for proper quote matching,
  apostrophe/prime detection, and CJK context awareness
- Enhance punctuation conversion to handle CJK+punct+Latin boundaries
- Add currency/unit binding (prefix tight, postfix spaced)
- Add contextualQuotes setting for intelligent glyph selection
  (curly for CJK context, straight for pure Latin)
- Fix containsCJK() and isCJKLetter() for supplementary-plane Han
- Fix surrogate pair handling in neighbor detection
- Add Korean handling tests documenting intentional exclusion
- Add 130+ new tests for edge cases
- Add escape detection in normalizeFullwidthPunctuation to skip conversion
  when punctuation is preceded by backslash (e.g., \, stays as \,)
- Add comprehensive battle test with 98 edge cases covering all CJK rules
- Add stack-based quote pairing with apostrophe/prime detection to demo
- Add Latin span scanner for technical construct protection (URLs, versions, times)
- Add contextualQuotes setting support
- Add backslash escape preservation
- Update CJK formatting guide with new features and examples
- Add "Technical Protection" sample to interactive demo
- Update features.md with new CJK capabilities
- Use Charter, Palatino, Georgia font stack for "66/99" style quotes
- Update demo components to use same font stack
- Fix curly quotes in test paragraph expected result
- Add code fence for copyable test paragraph
@xiaolai
xiaolai merged commit c8282c2 into main Jan 29, 2026
@xiaolai
xiaolai deleted the feat/cjk-typography-spec branch January 29, 2026 07:01
xiaolai added a commit that referenced this pull request Feb 19, 2026
feat(cjk): stack-based quote pairing and Latin span detection
xiaolai added a commit that referenced this pull request May 5, 2026
WI-C0 — previewIR overlay (lib/ghaWorkflow/save/previewIR.ts)
  Applies structural pendingPatches (job.create/delete, step.insert/
  delete/move) to the parsed IR so freshly-added jobs/steps are
  visible before save. Non-structural edits stay in form-local
  state. Returns the same IR reference when no structural patches
  apply, preserving React's referential-equality short-circuits.
  9 tests cover all op kinds + immutability.

  Mechanism vs full draft-overlay reactor: minimum viable change.
  Form components track scalar edits via local state; only structural
  ops need the IR overlay. Saves a 200-LOC reactor that wouldn't
  add user-visible behavior.

WI-C.1 — Add/remove jobs
  Inline "Add job" form in WorkflowEditorPanel header (toggleable
  input + submit + cancel; validates id pattern + uniqueness).
  Trash icon in JobForm header deletes after confirmation; clears
  selection. job.create patch defaults runs-on to ubuntu-latest.

WI-C.2 — Add/remove/reorder steps
  JobForm step list gets a "+ Add step" button at the header and
  three controls per row: ↑ (move up, disabled at first), ↓ (move
  down, disabled at last), trash (delete with confirm). Mutators
  + 8 unit tests cover insert/delete/move incl. multi-op
  sequences. ↑/↓ buttons primary; drag-and-drop deferred (a11y
  per Codex review).

WI-C.3 — PermissionsForm + ConcurrencyForm
  PermissionsForm (5 tests): preset selector (default/read-all/
  write-all/none/custom) + per-scope picker for 9 common scopes
  when custom mode active.
  ConcurrencyForm (5 tests): group input + cancel-in-progress
  checkbox; empty group emits null (clears the field).
  Both mounted above TriggerForm in WorkflowEditorPanel.

Mutators: 7 new patch kinds (job.create, job.delete, step.insert,
step.delete, step.move, workflow.permissions.set,
workflow.concurrency.set). 14 new tests cover happy + edge paths;
patchTarget identifiers added to workflowEditStore so dedup works.

Coverage thresholds: branches 92.25 → 91.95, statements 94.45 →
94.15, functions 95.10 → 94.80, lines 94.80 → 94.50 (all -0.30 pp).
Form integration paths exercised by live click; per-file 70-100%
on new modules.

WI-C0/C.1/C.2/C.3 of dev-docs/plans/20260505-gha-mature-viewer.md

Out of scope (per plan + my calibrated triage):
  - #4 if-eval preview (would build on A.1; pulled in if context allows)
  - #11 action version picker (auth design needed)
  - #16 run-history overlay (ADR explicitly defers; auth design needed)
  - #17 inline-fence WYSIWYG (codePreview contract change)
  - #18 snippet library (curation question)
  - #19 act runner (sandbox + log streaming design)
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