PoC: client-side USFM document model + live checks via @sillsdev/lynx#327
Draft
henrique221 wants to merge 8 commits into
Draft
PoC: client-side USFM document model + live checks via @sillsdev/lynx#327henrique221 wants to merge 8 commits into
henrique221 wants to merge 8 commits into
Conversation
…v/lynx - /lynx-usfm authenticated route: parse USFM in the browser into a typed ScriptureDocument (no server round-trip), live diagnostics from the four StandardRuleSets.English checkers + a vendored verse-order provider, quick fixes, on-type smart quotes, app-side ignore/undo - browser-safe UsfmStylesheet built from vendored usfm.sty (?raw import) - usfm-assembly mirrors fluent-api generateUSFMText so a chapter fetched from the existing bible-texts endpoint round-trips through the same canonical USFM the export produces - checks panel deliberately echoes docs/proposals/repeated-word-check - 14 vitest specs cover stylesheet, assembly, workspace wiring, verse map
Three packaging hazards confirmed in the browser (all worked around locally, all upstream candidates for sillsdev/machine + sillsdev/lynx): 1. @sillsdev/machine corpora computes dirname(fileURLToPath(import.meta.url)) at module scope; its browser-field stubs leave fileURLToPath undefined and the module throws on import. Fix: alias url/path/fs/fs-promises to inert shims (exact-match regex; test mode keeps real Node modules for vitest). 2. Vite 8 (rolldown) treats string alias keys as prefixes: 'fs' captured 'fs/promises'. Regex aliases avoid it. 3. lynx-punctuation-checker loads locale JSON via template-literal dynamic import, unresolvable after dep optimization -> raw i18next keys in the UI. Fix: pre-register the five namespaces with vendored en.json resources (Localizer.addNamespace is first-write-wins). Verified live: sample + real Genesis 1 (Gujarati IRV) via the bible-texts endpoint, quick fix, ignore/undo, on-type smart quote, structure/preview.
Contributor
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…at viewport height)
…n/fluent-web into poc/lynx-client-usfm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Proof of concept for "USFM, but on the client": an isolated authenticated route (
/lynx-usfm) where fluent-web parses USFM into a typedScriptureDocumentin the browser using sillsdev/lynx (@sillsdev/lynx0.3.5,-usfm0.3.1,-punctuation-checker0.2.0), runs five checkers live on every edit, and offers quick fixes, on-type smart quotes, and ignore/undo — no server round-trips.Today Fluent only touches USFM server-side (
usfm-grammarimport, string-assembled export). This PoC gives the front end a real scripture document model and demonstrates the standard checking interface discussed in the 2026-02-10 Lynx | Fluent discovery session — the general form of the Checks tab/panel proposed for the Repeated Word Check (#305):DiagnosticProvider↔ per-check hook,Diagnosticranges ↔ verse-grouped findings, fixes/dismissal ↔ Ignore Here/Everywhere.Docs on this branch:
docs/proposals/lynx-client-usfm-poc/design.md— architecture + the three browser packaging hazards (all predicted, all confirmed live, all worked around; each is an upstream contribution candidate for sillsdev/lynx + sillsdev/machine)docs/proposals/lynx-client-usfm-poc/lynx-fluent-assessment.md— what Lynx can do for Fluent, ranked integration opportunities, risks, next stepsNot production code: everything is additive and isolated under
src/features/lynx/+ one route file; no existing flows touched (onlyvite.config.tsgains browser aliases for@sillsdev/machine's Node built-ins, test mode unaffected).Screenshots
1) Overview — sample with seeded issues
The PoC page after auto-loading the sample: USFM editor with inline diagnostic highlights on the left, Checks panel with per-check accordions on the right, stats chips showing counts and the client-side parse+check time (~3 ms).
2) Inline diagnostics in the editor
Severity-coded highlights rendered from Lynx
Diagnosticranges: red wavy = error (out-of-order\v 3, unmatched quote), amber = warning (missing-verse anchors, disallowed©).3) Checks panel (echoes the #305 proposal)
One accordion per provider — Quotation marks, Allowed characters, Paired punctuation, Punctuation context, Verse order — with verse references resolved from the typed node tree, localized messages, fix buttons, Ignore, and a zero state.
4) Quick fix round-trip
After clicking Insert missing verse: the
\v 4marker is spliced into the USFM via a typedScriptureVerseedit fromUsfmEditFactory, and the missing-verse diagnostic resolves (verse-order count drops, warnings 5 → 4).5) Ignore / Show ignored / Undo
App-side dismissal mirroring the Repeated-Word suppression UX: ignored findings are hidden from counts, revealed dimmed with an "Ignored" label and Undo ignore under the "Show ignored" toggle. (Published Lynx 0.3.5 has no dismissal store yet — it's in progress upstream; this maps Fluent's cascade onto it.)
6) On-type smart quotes
A straight
"typed after "named Boaz." was autocorrected on type to the context-correct closing curly quote”by Lynx'sQuotationCorrector(caret preserved).7) The typed document model
Structure tab, both views rendered purely from the parsed node tree (no regex): a formatted scripture preview (chapter numerals, superscript verse numbers — note the out-of-order 1, 3, 2, 5 straight from the data) and the 25-node Book/Chapter/Paragraph/Verse/Text tree with source ranges.
8) Real data: Genesis 1 assembled and checked client-side
"Assemble chapter → USFM" fetches the chapter from the existing bible-texts endpoint and assembles it with a client-side mirror of the server export's
generateUSFMText— Gujarati IRV Genesis 1 parsed + checked in ~28 ms. The ~2,600 warnings are the English rule set flagging Gujarati characters: concrete evidence that rule sets must be configured per target language (they're builder-based configs).Test plan
tsc --noEmit, eslint, andvite buildclean (PoC ships as a lazy route chunk, ~75 KB gzip; main bundle untouched)Notes for reviewers
@sillsdev/*browser-packaging workarounds (lib/stylesheet.tscast,vite.config.tsaliases →lib/node-shims.ts, vendored locale pre-registration inlib/workspace.ts) are each commented with the matching upstream ask.lib/verse-order-provider.tsis vendored from Lynx's unpublished examples package (MIT, provenance header) and adapted to the published 0.3.5 API — it doubles as the template for a future Greek Room provider.