Rewrite renderer as component registry, expand token support - #1
Merged
Conversation
Replaces the single 500-line switch in index.tsx with per-token renderer
components wired through a shared context (styles/components overrides,
onLinkPress/onImagePress, renderNode). Adds support for fenced code blocks,
images, tables, hr, and ordered/nested/task lists with checkboxes.
Breaking API changes: `text` prop -> `value`, `rules` prop -> `components`
(new signature: `{ token, children, props, key }`, where `props` carries
what the default renderer would spread onto its host element so overrides
can extend rather than reimplement default behavior).
Fixes found via visual diffing against a plain-HTML CommonMark reference:
- blank-line `space` tokens were rendered as literal newlines, doubling
the gap between blocks on top of margin-based spacing
- soft line breaks inside a paragraph weren't collapsed to a space, so RN's
<Text> (unlike HTML) rendered them as real line breaks
- nested lists inherited full block-level vertical margins, and a list_item
ending in a nested list double-counted its own trailing margin
- image defaulted to width: '100%' inside an inline Text context, which
visually centered it instead of flowing it left like inline content
- Image's resizeMode was hardcoded as a prop, shadowing any
styles.image.resizeMode override
- blockquote had no visual fill (just an indent), unlike common renderers
Adds Jest + @testing-library/react-native component tests (34, incl.
regressions for every fix above) and a Reassure perf-test harness
(yarn test:perf) for the full-document render path.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same rescaffold as react-native-qr-svg: rebuilt from create-react-native-library@latest (Expo ~55, RN 0.83.10, React 19.2.0, yarn 4.11) instead of hand-patching the old toolchain, ESM-only build output (no more commonjs target). All library source (including renderers/, __fixtures__, __tests__, __perf__), README, and the example app were ported over as-is. What the new toolchain required to change: - src/createStyles.ts: RN's StyleSheet.create() no longer returns StyleSheet.NamedStyles<T> (removed) - create() now returns Readonly<S> matching the input shape directly, so createStyles/mergeNamedStyles are typed against StyleSheetRecord / Record<string, ViewStyle | TextStyle | ImageStyle> instead - src/getStyle.ts: dropped an explicit TextStyle annotation on a StyleSheet.flatten() result - RN's flatten() return type is generically computed from its input and no longer structurally matches our own TextStyle reference closely enough for TS - tests: @testing-library/react-native 14's render/rerender/fireEvent are async now (await them); no more UNSAFE_getAllByType - View/Text instances are queried via container.queryAll(i => i.type === 'View') instead; test globals imported explicitly from @jest/globals - reassure (test:perf) carried over: added back as a devDependency and script, its perf-test file's `test` global imported from @jest/globals too Verified: typecheck, lint, and all 34 tests pass.
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
components/stylesoverrides,onLinkPress/onImagePress,renderNode).hr, and ordered/nested/task lists with checkboxes.textprop →value;rulesprop →componentswith a new{ token, children, props, key }signature —propscarries what the default renderer would spread onto its host element (style,onPress, ...) so an override can extend the default instead of reimplementing it.Bugs fixed (found via visual diffing against a plain-HTML CommonMark reference)
spacetokens were rendered as literal newlines, doubling the gap between blocks on top of margin-based spacing.<Text>(unlike HTML) rendered the raw\nas a real line break.list_itemending in a nested list double-counted its own trailing margin.imagedefaulted towidth: '100%'inside an inlineTextcontext, which visually centered it instead of flowing it left like normal inline content.Image'sresizeModewas hardcoded as a prop, shadowing anystyles.image.resizeModeoverride.blockquotehad no visual fill (just an indent) — added a left border + background.Test plan
yarn test— 34 component/unit tests (Jest +@testing-library/react-native), including a regression for every fix aboveyarn test:perf— Reassure perf harness added for the full-document render pathyarn typecheck,yarn lint,yarn prepare(bob build) all cleanexample/(expo web) against a plain-HTML CommonMark reference render🤖 Generated with Claude Code