From 9fabe821bf0c33d41e4e55170c8c3f26b10106b7 Mon Sep 17 00:00:00 2001 From: Gregory Moskaliuk Date: Fri, 16 Oct 2026 17:17:11 +0200 Subject: [PATCH 01/11] fix: size ordered list markers to their widest number (#1015) * fix: size ordered list markers to their widest number * fix: carry the marker widening through the list context and move tasks with it The nested-item margin lives in BaseListSpan, driven by a markerExtraWidth that OrderedListSpan and TaskListSpan override, so a later change to nested margins has one formula to extend. ListContextManager saves and restores the widening like the rest of the list state, and the column is measured by a companion function instead of a throwaway span. The extra is rounded to whole pixels so the Int leading margins and the float marker positions agree at every depth. A task item inside a widened ordered list now moves with its numbered siblings on every platform, as the Swift package already did; before, the checkbox column stayed put and left a notch in long lists. iOS names the nesting offset ancestorMarkerOffset like Android, keeps the per-list extra cached on the context, and derives the default column width from ListStyle instead of a static on a sibling renderer. Co-Authored-By: Claude Fable 5.1 * test: name list tests by feature and share the Android render harness The marker width suites become ListRenderingTest(s) on every platform, growing with later list fixes instead of one file per bug. The checkbox toggle test moves to TaskListInteractionTest. The RN Android package gets a test/ support package like the standalone one: a render helper, an AST factory, and the canvas that records drawn markers, which both Android packages now share. Task alignment tests assert that every row of a widened list, tasks and their children included, shifts by the same amount. The Android baselines for ordered_list_wide_markers_test are recaptured on the repo's Pixel 9 API 36 AVD, where the committed ordered-list baselines pass exact-match; the iOS captures reproduce byte for byte and are unchanged. Co-Authored-By: Claude Fable 5.1 --------- Co-authored-by: Mike Olson Co-authored-by: Claude Fable 5.1 --- .../ordered_list_wide_markers_test.yaml | 163 +++++++++++ ...red_list_wide_markers_hundreds_display.png | Bin 0 -> 26423 bytes ...dered_list_wide_markers_nested_display.png | Bin 0 -> 27640 bytes ...ist_wide_markers_short_control_display.png | Bin 0 -> 16260 bytes ...ed_list_wide_markers_thousands_display.png | Bin 0 -> 26240 bytes ...red_list_wide_markers_hundreds_display.png | Bin 0 -> 32647 bytes ...dered_list_wide_markers_nested_display.png | Bin 0 -> 33258 bytes ...ist_wide_markers_short_control_display.png | Bin 0 -> 19441 bytes ...ed_list_wide_markers_thousands_display.png | Bin 0 -> 32425 bytes .../ordered_list_wide_markers_test.yaml | 33 +++ .../ios/ordered_list_wide_markers_display.png | Bin 0 -> 46912 bytes .../android/api-reference/style-properties.md | 2 +- .../ios/api-reference/style-properties.md | 2 +- .../api-reference/style-properties.md | 2 +- .../markdown/renderer/BlockStyleContext.kt | 6 + .../markdown/renderer/ListContextManager.kt | 19 ++ .../markdown/renderer/ListItemRenderer.kt | 46 ++- .../markdown/renderer/ListRenderer.kt | 21 +- .../enriched/markdown/spans/BaseListSpan.kt | 6 +- .../markdown/spans/OrderedListSpan.kt | 61 ++-- .../enriched/markdown/spans/TaskListSpan.kt | 7 +- .../markdown/spans/UnorderedListSpan.kt | 4 +- .../enriched/markdown/ListRenderingTest.kt | 230 +++++++++++++++ .../markdown/test/ListMarkerCanvas.kt | 101 +++++++ .../test/MarkdownRenderTestSupport.kt | 7 +- .../Rendering/RenderContext.swift | 9 + .../Renderers/BlockquoteRenderer.swift | 11 + .../Renderers/ListItemRenderer.swift | 93 ++++-- .../Rendering/Renderers/ListRenderer.swift | 27 ++ .../Views/Layout/BlockDecorationConfig.swift | 4 +- .../ListRenderingTests.swift | 198 +++++++++++++ .../__tests__/ios/ListRenderingTests.mm | 177 ++++++++++++ .../markdown/renderer/BlockStyleContext.kt | 6 + .../markdown/renderer/ListContextManager.kt | 19 ++ .../markdown/renderer/ListItemRenderer.kt | 24 +- .../markdown/renderer/ListRenderer.kt | 21 +- .../enriched/markdown/spans/BaseListSpan.kt | 6 +- .../markdown/spans/OrderedListSpan.kt | 61 ++-- .../enriched/markdown/spans/TaskListSpan.kt | 7 +- .../markdown/spans/UnorderedListSpan.kt | 4 +- .../text/interaction/TaskListTapUtils.kt | 30 +- .../enriched/markdown/ListRenderingTest.kt | 270 ++++++++++++++++++ .../markdown/TaskListInteractionTest.kt | 102 +++++++ .../markdown/test/ListMarkerCanvas.kt | 101 +++++++ .../test/MarkdownRenderTestSupport.kt | 126 ++++++++ .../enriched/markdown/test/TestAstFactory.kt | 36 +++ .../ios/renderer/ListItemRenderer.m | 10 +- .../ios/renderer/ListRenderer.m | 18 ++ .../ios/renderer/RenderContext.h | 4 + .../ios/renderer/RenderContext.m | 8 + .../ios/styles/StyleConfig.h | 2 +- .../ios/styles/StyleConfig.mm | 6 +- 52 files changed, 1987 insertions(+), 103 deletions(-) create mode 100644 .maestro/enrichedMarkdownText/flows/advanced/block_elements/ordered_list_wide_markers_test.yaml create mode 100644 .maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_hundreds_display.png create mode 100644 .maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_nested_display.png create mode 100644 .maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_short_control_display.png create mode 100644 .maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_thousands_display.png create mode 100644 .maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_hundreds_display.png create mode 100644 .maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_nested_display.png create mode 100644 .maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_short_control_display.png create mode 100644 .maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_thousands_display.png create mode 100644 .maestro/iosExample/enrichedMarkdownText/flows/basic/block_elements/ordered_list_wide_markers_test.yaml create mode 100644 .maestro/iosExample/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_display.png create mode 100644 packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt create mode 100644 packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt create mode 100644 packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/ListRenderingTests.swift create mode 100644 packages/react-native-enriched-markdown/__tests__/ios/ListRenderingTests.mm create mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt create mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/TaskListInteractionTest.kt create mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt create mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt create mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/TestAstFactory.kt diff --git a/.maestro/enrichedMarkdownText/flows/advanced/block_elements/ordered_list_wide_markers_test.yaml b/.maestro/enrichedMarkdownText/flows/advanced/block_elements/ordered_list_wide_markers_test.yaml new file mode 100644 index 000000000..730e26b0e --- /dev/null +++ b/.maestro/enrichedMarkdownText/flows/advanced/block_elements/ordered_list_wide_markers_test.yaml @@ -0,0 +1,163 @@ +appId: swmansion.enriched.markdown.example +tags: + - block + - advanced + - list + - text +--- +- launchApp: + permissions: {} + +- waitForAnimationToEnd + +- runFlow: + file: '../../../../subflows/move_to_playground.yaml' + +- assertVisible: + id: playground-screen + +- runFlow: + file: '../../../subflows/set_enriched_text_value.yaml' + env: + VALUE: | + 1. First short item + 2. Second short item + 3. Third short item + +- runFlow: + when: + platform: Android + commands: + - scrollUntilVisible: + element: + id: blur-button + direction: UP + visibilityPercentage: 100 + - tapOn: + id: blur-button + +- scrollUntilVisible: + element: + id: preview-container + direction: DOWN + visibilityPercentage: 100 + +- runFlow: + file: '../../../subflows/capture_or_assert_screenshot.yaml' + env: + SCREENSHOT_NAME: 'ordered_list_wide_markers_short_control_display' + +- scrollUntilVisible: + element: + id: set-markdown-button + direction: UP + visibilityPercentage: 100 + +- runFlow: + file: '../../../subflows/set_enriched_text_value.yaml' + env: + VALUE: | + 98. Before the boundary + 99. Two-digit marker + 100. Three-digit marker + 101. After the boundary + +- runFlow: + when: + platform: Android + commands: + - scrollUntilVisible: + element: + id: blur-button + direction: UP + visibilityPercentage: 100 + - tapOn: + id: blur-button + +- scrollUntilVisible: + element: + id: preview-container + direction: DOWN + visibilityPercentage: 100 + +- runFlow: + file: '../../../subflows/capture_or_assert_screenshot.yaml' + env: + SCREENSHOT_NAME: 'ordered_list_wide_markers_hundreds_display' + +- scrollUntilVisible: + element: + id: set-markdown-button + direction: UP + visibilityPercentage: 100 + +- runFlow: + file: '../../../subflows/set_enriched_text_value.yaml' + env: + VALUE: | + 998. Before the boundary + 999. Three-digit marker + 1000. Four-digit marker + 1001. After the boundary + +- runFlow: + when: + platform: Android + commands: + - scrollUntilVisible: + element: + id: blur-button + direction: UP + visibilityPercentage: 100 + - tapOn: + id: blur-button + +- scrollUntilVisible: + element: + id: preview-container + direction: DOWN + visibilityPercentage: 100 + +- runFlow: + file: '../../../subflows/capture_or_assert_screenshot.yaml' + env: + SCREENSHOT_NAME: 'ordered_list_wide_markers_thousands_display' + +- scrollUntilVisible: + element: + id: set-markdown-button + direction: UP + visibilityPercentage: 100 + +- runFlow: + file: '../../../subflows/set_enriched_text_value.yaml' + env: + VALUE: | + 1000. Wide parent + 1. Nested first item + 1. Deeper nested item + 2. Nested second item + 1001. Next wide parent + +- runFlow: + when: + platform: Android + commands: + - scrollUntilVisible: + element: + id: blur-button + direction: UP + visibilityPercentage: 100 + - tapOn: + id: blur-button + +- scrollUntilVisible: + element: + id: preview-container + direction: DOWN + visibilityPercentage: 100 + +- runFlow: + file: '../../../subflows/capture_or_assert_screenshot.yaml' + env: + SCREENSHOT_NAME: 'ordered_list_wide_markers_nested_display' diff --git a/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_hundreds_display.png b/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_hundreds_display.png new file mode 100644 index 0000000000000000000000000000000000000000..e2bf9313789f99f8a8464b6d285fafe1f61c5675 GIT binary patch literal 26423 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

TYWN%ZxLQ4#v~u2 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%0AY8z_3S>~{J zQuBeD1&Evd?*bIc zo6Lop!#+SwdQUB2ldG7ev|}^{t8Z0vcQN{WUe%6$P1qvPJ5flisO89HCZ(s_Xbq%M zq_&5aluC9Uv|nQn#mr|X6?&N!bu006g}-3jKIhqqOC9?)vUPE|g1(-HDqjJd5D#tz z@|HsNoS1Iw7+$7pcmU;0luG<>+P;5z+W!>yRRR6L_uahB{6mQAhQWbHx$a=);=MQ= zp)B#QU!qXEgF-;(D zW|%67@Dn<=WlIA#+7gc`GfBy;1&xQbPKE|xB*IMVKA>VOxj5Ucb*zCfR1JRAYVTUA z=ek>@qvo(|6ZL@y>i=*gI|oS5^!XKy!0u{6Of@l?(qtxxt@fdQ$2>+RM$n7LA+0(3 zxIl-o5NB>am#ZK!4zvOnJ%JuIT~%KfG_SQKOo64UAex)nv`fUwJnE_o7u;?OUHGY* zBEt0BXh9C|O_U1`oB)a!@52EPZI7^Uh-3XL)L_>=VQ!fO0c$ghnUMh1+jq9vWfI`v zz>5jKCJVX#FT55KY0IizkdIZuzT9IqB7dVVcE(sUIn;KnKZJ4~NYRWIDdR4%Kq^c7 zTBld&+s{zah|L<(5)evyg)MW46;qt)f(JEFj*CQc5ncAUztrl~k)I}lq+y|Cf`Q^% z;4bfcd-bc>g|ARGp>|ELFFz2-`5qtd-D^Ub-Z+I4JrkPLBl?^G@SOI0hsZgFh`Xpn zY5ubW3I+WK7yFLVtF#^}wGFL0Sot&Y1E6AySUDRPF2&h@2@r>O8TIGn&7dzgj0q$h z9rCSNW8A<4m-TBtA3s%+0KV0HUs%VX1&71k*k}h>cwTL)U|Ik?*V-l~RC;|8p8{IQ zX+Zsq3Znl({rYPoWWRq0aurSJ#J=3Y9U#a@#sISLrU2Azi#fk;*aHO=Uyu?D#G&II zkB!b@vHME8kz8V*6)CUl)fPhcyZKF1}UIt`ZnU+cwg9e|Hmf0YesW zjK57r@o#JvP68Si@_(uw!HGB^ku^S~`v4FaF!<=xM9|=IpLE{+DrFkHtq!zl_N||= za1KjeAlXf`ffyU!5)i144f7<*wfQOa7s!9VaU&}x*28_}JF4dJ-E`DevC!r{laqnL zMP?ETDA4F_9L459Tdv%Uc(2jRE(5Q1U0f1hnD2=u0ABVApe~+fiA9T7yOlxe({!~3 zOvh!bB2UEH)chrwOzBk)!0J0=7qcZfP!&=))nQrq28JQUkW4_ ztze;5j7H{nD9_lH^!sS%g0_K)tZdf5pW{^bG+B)75&DmFoPAs9!*@^qV<^dgFMg1& zT@hT1s$HJ5>Lf81oIR$G?ER0Sl&F~RjXZJDluspu$~aRm3P#67^Kxe~GchF+e~-TR zb)uX_P5nRw2aq*-O4@GxYq+!iABSF*DT9C3A4ik$O&B z(T52ilp6J8tkPce_uMW+g{~)LF@T)sL9tjxD_{c`tgdAKciRIhp!0 z8N0%rJ_0pCTjBRH=#afDly|5oXP}2SL)0_+81PCqvrgdrbmuA$uND5U`o@yev(TW;JpHDQBEWY)rzDg@FH7eV3cBIBjkOzVS zhliKIp*E^FV)Q9IPn5!99vCi78LAg%9Wx%~bG*2AlkD(B9r4WIiHRe^V!Htthb~M_ zP1k&d5qxRQB>d^^Z?MTPzGeX}^l?0*O0Q$iF0a{D!C9~1wZc38m(HkHUSu(hCeuk? X%i$8R;d%ouPo*HMB2)0>#k>Ct2>nc8 literal 0 HcmV?d00001 diff --git a/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_thousands_display.png b/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_thousands_display.png new file mode 100644 index 0000000000000000000000000000000000000000..d1f269bfd1cea39bbec2165ff2dc0466c3bb2c05 GIT binary patch literal 26240 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 literal 0 HcmV?d00001 diff --git a/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_hundreds_display.png b/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_hundreds_display.png new file mode 100644 index 0000000000000000000000000000000000000000..dca78bab856a6b2012a0129ce778879dc5131784 GIT binary patch literal 32647 zcmdSBWmr_e41;`nzh!mo?qVg{o|{GoCF3MG1{FwcQ7R1iYnc?gRFAr&Rrc;ByeOa zVh(cWj;EZY=jYeQA1DU7X_K!?iW{bquyIwyZxSmo$ish zu*}k2SinWLnd#Q%Bd}`l=a?k?y6AHwir6DGVq7lKqeQ|tx}tFkx#lOLiH(bc-L5=Y z8^0zn?E}zH2`5rSgz9XUhdniQPGVu@W7?{_h!chNQ$D;o`0@r# z3=fTQ6E|fdH$eCtr6r4tja;as={xz~yVBz-(Pb-qNE%P>eYI&wiKJZTd_Y0VC9nj6 zLZ9p4{Wo?EMLvz_VuTL)-(w)i*_m!Om%B~5+Y%fc+-H9ui#bRS-G?CHCGN-J z4RQ7o>`YiPTxIpzFC>1k^WVMDaUpb#3ZVm4X625^$>XAdD+IU)lz$%fjur_DQ2^U& zFp7z2VkZGhpJ&Q`vjoD7?%c6{fNMlIYz!et#r7(;vn?qmU%2A>`^`JVH~j4#%4?)# zUU2k)A-3Ixn+Jcsn;)ecRwz}Rqn~<)ct7d0-ObkpfA01BUO36U$F8Q?lE~Fj*Xsvi z{B=+N{N$5s@+T2i2|gq|{HW>n_UybCdh5T}qNJNw=uRq3!S=G8b5~GM>yG+!{EoE| zt{vU>KI(flt!R%+vR$OV_a^hzd+b9Rz)yoscL2OidQtFicdsBWCF)}nk z7HWh&14Eo=pbXO;o_Ro2rjFRR>4%T$IUKM9&L-zmAA1hfIs;G|r zuY>t%Gx>QrOL2d16YujGvn9b(Tehah_3sh>0cBB&KOgtW{DuE~m>0wH`t#v;AO+H& zXZb|%8u{;=Vfl=T{O3CeGB)a;4=_|JtUn)|vHx=+s{cDKmUj4IOVsi0xCVGO^1gO>>H3x=GtA1dvh5a;>*j)_CnOusZvQ@8ej zvZ-F}N+oUWrYQRdLm~wBR|^EJPD!3-<(9P%ZUpU1Z&N=+Pfyp}ehL}CjH^z4c1}jN+Q8@&uoVITJu_z1~J&#nK z=q+@nZ3JV{^|99vIkkuLI#fxQiL02jilal;WsJgptd!}<*K{!aHg=nrIiMe?hgQ)4 zpRX-LEHOFxhvd*&(HSep$AMpV9dITzvNgfLX`-%9x3>E;RjxY3-vYnQ_TeYxI-HGf zJisI$8-`V{`soe!X#VONGuMw8-kmk;&M`2jl1Q95jDqiuNl8f$SR?u zX*e8xydmx2-Rg8NtZnPt=H})}E1ABxAIn_(mR3Xr_FFoZ0zy{HY_%`Zdq0IC%j|)w zxddCJ0=m3=zGGNk(=H;@*a+9JqzMTS2Jdj28D&U>8V#-NFoa5Q;VJryj3+E`s+6WS z`7VPxeQz>>@|SUwU^7WznU!A%s-9_5V`XJ#t{>@p77e?~YJR2G@8#rj^HH->SVx-0 zD4;~DI`*xkM#L0rSu#AY;5crEwIJ*z!(}0sWw950j%^*%D1GXU4Bt2|oG5=!uGwsvhS){Z<~~j!n08qFsbrCQUy&Ys$Z(F&UXT zQ?kl*ZgiA7fRo-AqE_WTR=4fP1C#sVvNXEU{4A|wZ64z|h619hadU`NSD1CASy8d$ zpY&8L=f?Hp?{DhpW9HvV;qkW5)6(?B;1~@IIoWhrgZSq`7^#?cS|9vxj2+#ORI1~C zJ)d3pO_|dCKWrbyD!y;2$X6RIDFbgFLH6|Y`FEAU+o^}a9uP#QI}?0Yt* zG(=FKCd6a>_*yN!C$^r)cB~3LYMWbFTkX9JAM~u4Lm%n0_?dhXD<-+LGyLe6mcALX zQa)2G@v9II5UbiA$i#7gz&8E;thm?~lC5VM)^kmmz~6&&Y}5;JW($1|r?ooJ0>SLh zj*jn4_G-p)jl1WcwvsL3W#@d`4isL^C$;4`5u=C}`prJ~eRm&P_KZI+{3|@c3ed<(Nw95+ja^z6TV(Kj(D*;gX^rouJ*JiL2$*i0W!1h!8Geb@W`eJSI>k}0o#iylAeS%(Y9 zX?M<;mHn20!Zl46$9cAhy-e-~q2a*lmoGk^F*hlB95{B7r(&7a<4DL z%8!Z^j28kW*}2r$+TKcPdMI8KnI`Mp-AT~PDm{7x0l9bgcM4VLZK^sAbSbzD>OJ$@ zVqowX*7$+jV{n;~PveVfW_UOpXF)3OOf#LKkOk?vHjFBAb2>$6k5gGi#nRxLI!sSM zr*alMv#>DpmO{v(sM>undFdQI>KtB>Wu(nMr;NFng6Fk){!pz$5g2&yOyrK|dzR-F zt2@=2b`o&k32QG4)HD_;vrUI0d_r9D2oN!YCj%d0Jn?!=E}ck` zUivmy+32{~Hf8wrt=We{W~6}|;e>J*EQgd>$E#(cx+}9y+43{}tGQ40ErD!n;y)i5 zwXU{n>tRa`z)0@gnf@XnmiT??^9oG&nvwwjy|^rDR@OpE0&q=y70VkX{5|#JL%6ax=sCtX>0d@iMmng~c>GQV z0)*MeZmaFA99BTIaX+eRB`=?|7_`02cQ?mEiE$W^d0$&OsD_+@(9qVQY+`8qX(a(sEV&mMzuVF4 z602s0qnQCNx_W_uR@ujfA{}(?CYGe`?YE~BV{iuCFfsuTJyxU@{>~BpGm(@IE49*F zw@J?9RwluK@1#QF7vjreGHpYnr>CCHRMDEC+_G#)p~7-~wc#T@=IlcRSCZ;-PqtZ< z+HP>JGHe_!?5>%BwfoapT*?MsUm5ZDjt~xUOkjH%H@+^xF~E+#?(g^(mdTN!Qkjnt0kX<01wyEJ3w!PCz}_F;*k=_OJzoOX3|Bm{(1AZUphq`@eH z=E}yb;O#s0w>&RgSY*e->n{lK@e*XE$TqoN$1m0&+H`H1Y{0qEprgkJ1apqN2QO$# zH^$9|znH|7@4#Yh1ybke7Q*Wv%pr+iBs4 z?Fg28A(y3Lu3Cw@+n&^rd_6|_!e{o=CqFS{cO`b|G zQShK63}dE!Hl#IR1D<-(Egf%PW`wY2BKJY;*_MKBSs&F(P6~}s{t`svj7|oLN8oO* zc9ftZ-|0YaO7r^*GJQ<4%bN^U?5N^=w{RJ@myZbf-;i1R@131}5&fRLVdO!1-kGSY zzY_g;<}y0?AOLKT#&_6hwvadt%WW0v<`L#K&LQXwBB1Y)(R9jR%aO*Uob019r5UUs zHmZBDol}_w!l+)Q&P>9?d^Y}7ly#342II0{+2K1?$qV_>1!{pf!5sGji?NUIkdq~s z^95}5EJefKt~@2QTc-V`6hmJ0LzNH@7q>Gbt3Q_J^y`T(SIjOdL6KV=%rW}*7vJ2* z@`fG!D03*}dL*j6tAu%=F)B~j;9HZ>U4{vF3GOr>Cau=MZ@Y#wQ5j1|f;|FSIf|TG zwUico*GKaU)DR=llG|I(Te9$VZWaT?v!)cP{#|#8<#|@#4~CMGL@Y`?Zr#gXLQ>MTN$%enu5~!Lo+0?w6PN_t^MJX;Ciiv-@ zarD;6YGjjdM*MQn5lj~Aczug3cCMPm?tq-!PU+%z7Hm{2Q!nHjxM;$*c4#?5qj{*$ zPPmky*1T9{4R;-PoqxG^|IVG$1x4(2n_V`1A;UhMBu}mpY5FXW8~##-noQRxGqu~X z7@Cgfpmb%Ss{oZGIj>7+G~uf0GU`VIvyr3+vfSfA5hKfCds7Y@DY3q(BJqNp7B_LL zWkjPAiN`S&ft@ru4u#GuTto{(VvO*n+nW!y=A&smZ2GYWAl&bw4kx+l*m>@$D(rD7 z=?%bwUh7+M2MUi)pE5pU)Ef4@YN^<+3`n|i=|JrEcCc{tci#ij!__w_S(Jy)PD>V*FoZLtdTzf_R8xDVgKPid05-j~ zU)w%^g_;UoB|IGAvikA6V`xo{FczPE`KJLKwYe%Mexn^@EUc_l3-!pS8=|=UovI1vi^Ab|A}yP^Fv( zUg4A*bGWjHR;38HJWnfnutY0^p`X)l!pT_ERvbV8Qm zH#(Q%gp!^2txM)sU~_5BV#UpPe`gW@5kkwY&+>{}2uYoPReU*v#A4bIuC)QS7j8`O zqs((&26AHu&2kY>v?E~tnpC$n8{#x|qmR36#Jd%Xe%eK$qi86b3R0EostI=cKKx?o znZsj6VzHnLEDq(ZcZz@mO_#;|>? zKWA<9ehzggzsN)0H--}W0L$&9mSAS%{illz1AKt-bs_Oak*)7zI8$Dmyk8E^};ZJ!>=+$0VxwMIu zJOSdnHq0#!|6w#9WxaE zPgiGFeONT9@sCJx=$txAnB(fn(f{qcORU*>Voy1#l^l+eM56e#br_@5lx^g@?MWQk z$j#X`r-N#?6Dsd8>QD|>8X^JRYPBz7iPUX4qEWJ%0?ke^wSGP1hi(qoW5dBb|SCzKmWy>gq&&My|9zVfAv4(`u+ZPOl-slZ3`;f_DqC;c4RE zgo7#<;J(W%LcmIzX`cn8X_Vh8!gjv_mxg20y>bazFE+_p(brj}QUI9Dq+92&V)XQ?<_K$gc>EmTBeUFyl+Utb~FJRb-7>$nC0>+a>I9 z{b3F^!DITtL93F_C6bYSC>aL?1>?_HI7}}1uldZXP%o)M8=QMS@h_#CBuv+sUaJfk z=v;2bSi(P{F;HXmY>G~NYM^$mfYzMW@lf=GV#_uvuY{S_9ZAKs8Fd(8ss6`K2U69} zVvHlpIgb||jJCz@M}-K($4<8rJZz)t<|hK1KSyJ)ca97@YG3#hGsHAehc+B}9*wU_ z-ra}`(Ls3@^91zKm5lPi!f#&dDz46K2S(*M$mr)O8i&Lx% zg;H1AA^5g^*I=z3T`7gVB~UA52HXEz^h;UBOW^8NW^3{HlDpcR8^3Y{Dao$GTBL?x z9KRy4+o!W+@$;r|pW}Z#6w)-(Mp)mlKXxWI*YqfcVta;%I}_vPm+p6;9$ z#~`mZf8Im|(Aohg9RrZk6z8`Gociae?->(dJVejfb6+Z77bx;GA;;qA^%wRFj>iq` zV;3Nho2{r2-HEILyCVw~LoTK}>3_(RWylKxR;>{CRXrq}o#B4Hup?ExCom zuZlQtmOrN)7^!(ZcBFwU%XP^cn%f_L6(*?=3p5bAfW=KaEE)Q)Uz8fqR^wg&}e6*!sYg$%T2A6Fu&{`oNnyfY=wx{ktE{#bJEU!*2eZMO46Qe{!nk7wypXH!DCV1d1e}K3iGx$kE(8Jt+O#Pfppg3-u9e z0CqE|%C)9-EQOAyCW2C|Lz+pWI$o9V5qi|mr!>*5u0;_cygl8W zkpxdIXWVg#wcV*g-Hd3DIWXa}wgilj7MC4;1LRjfZ=QR|2xIMy+VZkWGQvShZh21Q zd0VbOy7Eo_x0Ee%apie%kg#v-lr>Z&n)9|dnwrpjHy+^4r@U?~uYN-O2Xh?=MsvjN zY|cq}FX^z(m-bkb$2y-$4k#j)1K=WD?W9BeF70R<*#xG|I9#u{mwTRu)cv>q^aXCC z*(JxAq5!`qSX0E#Oik_Xn_He81&}rLdsbjnL5aWZ+O9j~2#y*0Kz*WPND}sTr6q6^ zMS8RdrG%V+(c!+xMP4^fMz2n-M@jYMBrOwf#0<8v{I+fp1qT`}FN$oP`R(!sn@Xa1 zp#RpA$%_s|5mxjd35xV2GU32y&=Hf=UjWe=o zE-=#Ow(4v3_}wn2W)*HX7OD=_{0=LnYZ<0=qdB3Ki~Ih<@CK~OP0(rPeuBc;_q+|~ z+O2+wQ9vE=LnH;ex}q@acvz4+qF$wINr&})j>*5QX9Dmqg#QH+_Q?_1T+wR+X6+@h z0)PdV1iGo@2QG_=L(fq>ZrId*PSo!C_mbuxCJ^+-*MDYuQs+j^;Hs$2G{^0_I&C1< z@;o4BN&0Qrbera2`y0$BUAbPD!^&hA0fOi+IV zt48$J0X4^DnYSh^TE!Z;?*fH73htKt+jfRgbNsEeQw8PY&#G^ql6euEHK`-J)SGNI zA9ldrJ}Dbo#ui`bnvF%tus(x`zIefKyH`>m)`NOW4}0^ZWG|6FQQliL@$=_5=UR0D z`!3Az=va>-<^G843QU4Y4JKt@wsRELJNxsHuEM<{VI?V+z{^-QBTkm+%jXI=)o)uS zTu=_+yG-(d!tx0#A;eZcOf&N)Dyip=6f*#xJLN?BAw(qY_JVtCTPHomv9(w?OVOpu zeGTHXvEhj80ZR3_m(OLi3;4e(&@bd&4EDU5V7--)ldEJ-QddRp1&83-KwJ?C zJ9mm@5n%B!F@y?-{{y2i!sP>fSJz-I9 z-<&#dFipeK=Bk+<$fW^8B1*li?~pyb4;bY6I({Z3B1rsmPn9@<%plCz65|cuw48Do z4E5CAG{+OztTHc%ecJ&PRVY0gG6M!3ojpq#-HN9#m;ek;ezd~TkfZkNc6kDp+0cRA z-sU_QZU`U;uY|JA+<0b%t>Z48Xgi6Peb%s*MJGW^$;0~0_1cUleYD!JCq%V=G{M_@ zb?g|O9*OQvS}{~uL^xQ_LS%+|JjLZFi(GFfQkTQcOddQY#ni0a9*T@xCZ6nGL-BD- zbm^{sdihXoWA^$1JUm=uPsgu2y5i$bYkOJ_C+<(nL^i6>BvwwX*-&6^z=I2}Y5;y< z(zJy0q#z@WoF`s5;gj3tt27g`B1LX%7NvGBca_P$dW@8DYXIa)ao3!-_QcnR&z1~w z*i7cKOnR`qAfZ7T86E9Zy*MYVh<>AOFT?2W1l+h~n~(6N!|0`~CPVFzVJ{byxu5q& zE0Nrj>{*DommR3daf6Dn=qTJDERW`2SImQN{e1NyjlrXn>AdRM|XSrCX8O(G=GJxPo?9nvg ztFWreqfnyQ1Aq-T#;^BIsb1HqNoP3h9BV3%1p2zMXYU`WL!#pAv*&(PACq$DR#$5X zAqlu#rP_t4Cdt+Bgz#-{uOU5LS-~UcG@~tu`vKVv%YZ!wAm=Y5aSGebZXeckrxeby zR=Gz4P77!{v)?8sC&MzrT4m$&$lA2fH7ljuZ(^_#tb<2t8oj+i*Q(<&!(^D?qp3g# zxSCao-1l-agI1u&E}7s#;P8x^wFfga1QVQE?rudyMivPz2adkP zZttHb$)63Kaa{r}mSQdMz|En_)IGo8L$6Zqk1S8mz^O>L>#_GCdC-f)1YE}Y2gh+tckle3ftn*z ziHSXrp*}4nA#3mP9Lyc}J}}76xTF4FL&anN?dOZ9oK-=Oe^!~g52rC?ZQ@)Ql$AMX zR_x(PGpSeo(pDd)1BH#1`}h^GWnTNeDX00uLZ2??46U&_wX#@=DmwzEG5(m~bU{Ej zXxcq2c1Ls=$v#Gbk@<=`Cc-3LVJ_aU(G#wb?hTlFXr!MmC*q+j=dmoeTi+~OVX zc%5*J{dV93Nq!Zjk624-PJ74;C5@rgIYs_1PfOd4#JY<;u}5hIprJ@73#wy5ySG@^ z9faqF`_QO&r~qLg~i_$@$&7`C#{YHjQs&hl1CCj)O44KGxw5A0A~l z;EMJ#5bEafTz~`kP&3)FErH*TZAs3=gs8wSz4Zcloi_BB!>#40JKqh~JXTQILIAKf z*HiMRK|*Cbwgm2b6>KH;yVB`>3$6nxZSr)|{l=OVZO`Is-rklq2;y%Ebalzs*;<^= zR_@fCXvFMtUCqWOpK%uw?B7im46hWN3S7zO@2>^m%%-9YxrK7eveP?=b1vCU} zxDT1L-({jDPjjECIxT^@L4bxM9tpu|!=iYRfXi;{21f}dgBC&>af?rkrrub@Ly$0J5B{&$I^3;{Ej{{%P&Dj#oQTX?h-!;m(_FE+3{IqeoLyrN zDpq14NC>5K^bP2gLO@n`$`Aj4^bK;PPhmr#e{&N&lQQ`uQn)X&-JqZRNuvq*hqyZZ z)n&a!v(XLr=|cq2d1nf0i=3U6Rpq>)(F_l2YLgi=4>Mxqwq6%CFu>CpM3WIGJIl50lf& zU1R6)>R4XqrOi>-ME;&Uqng-7xv5=VM)Ab>>-${^hYIx%VT})o4bna#1T6E`@kCzC z8L2_P2(uqQ;{_tQQ0TDdzNdi{!@)04i>ptP09kH1Tub_3h^Wl-zEC%NvSFq*=wHXMfVd;JP z2l}S%$!u#sancvl?Di}(%|7V5vZ0buO$uO+s#KrkSFbNB|5TCDFB z3wysG`yAHT4z7>=zpt-R#HrLv0^o*2G^Rdye3!Ih4T5^Nh0j|yr=uP%o6I8k^RzUh zeam<9@q#!lztr*bW2zIb6>yDax>jd?{H4-=k<{rOecA8~dGwRjY#}=6J5YqcoE3Yd zNx(8~x^F}lx<iQw6KuQaPGB60g%JY zv3eb0UR>Cc{o-%p0tEu=c2jJdZPaV0G!Py|#}EvBOonIRScHnAA|;D)(2qf-qBB5$ zEFObsnsSh_%B&%%H~s#?RyA)<3T0(wa%so~r%zj}9(vhqQsNto`tu2Y)Mg3!@;5Qujs>IU}oH=!yd`fp8fvc+)4KmFZU!f%K5S=IM- zW2MT7WE#qDc5OJ0pgk)766(+whWY;(^@+t^YXPR~5|y|SD`87^Z<%W6mJjp+g!V(I zBGAN+sGX6mA0+M>oj9>aV>u;*_k)F}oOV)vRl8UZP(>EJi_FW+Ev=;O7fkf@FV4;7 ze@Q1(n^+CB1WgBFMrUyG&Ade9e6j`!JQ7eL;hwGZJu_c;1<@6qf+KVg5!q9Vcw6U< z1rxQP@4ds^2za)3n+6*C=R=d>R4if^!(T$9qcv2P{_ed0xA>RZ!$XWgPW3122QeFE zgTYVb=fw(Udb^((XuDpwx|sa9c37J=XD8Rsy;!#kq6SE-iR3#|PJeyH&Ot4X9?OXa zq5#Pw#dQg6Z%g9uq}=wg0-YNpR0*ZmeHj)js_SO%7mV_rwY&@#?Wo}nESJ~mc`Xdl zfmdN&}!3oKC)w-W07KZ=s_W1loSQb<~hPTiGI^Xd%{F z#(rEZRYHxlBVeu8D}>!O3Yf@?0FDHAnM-fO)YzBLOY`%CLzF`P%kI;A9s#@mOPDjJ zDRj9v_J!DPg4i;OT1tCTm1~9-WP|`(LaIR zo?OcptfsR|Mqp}Xrue_+3PQys6VyA;c1@T&Z6i$^p-1V1!#7B_ueY$$DnNRJZ}@B; zZ{~&zDsL)B&y5Q!ir?ZFFyy7Div$0Ff2lD!+*@}a6so(bCfT{)$+Q7bil;)*R?i=j zlO{t&sz8*}S+D7K*#z5rP~LVi>%F0s_@OsCYtty~gPXk?~JE!I}Tw?OYUKp=Wq2uo~1 z73B+g`e9fnw%=*~<+=OK*&#)zT<482Lz;c{$CdjRA6BA)i1Li?cpM)X9|2%B>D(sn z^O%?e^%+BHcw|J*J1Il_`o>vADgeSSS$VPX#4MpbkDa~mcj3(dOICcq;vyUWk-;eV zA$HeThqp|$pr)jtDXn}$SjZRqi=z54=9%~>{Hh+(2==))%|}|LD?&=MN=08hCrtdy z+zl~(h=})Lz?gAwwjgREq=18ggL@&^8vaGoB%yTOS#`^oXnRUk20)WiUpLU7pc6ST8t(M)j%)qX{LAP4Zd#UjDz5-S?ekWW;7 z&#@VxK8mkjFWlb0V(O$@SQdnKnr_ejXXVDHb=0O@Zx99NQ^Tkx%;f#4I5j}$ns&`6)lQ1x(T=4$!EIs za!37V1(_AyxtH*TbnK;c(|Gk~-55HQ_0P%k==2Jyf4hxy8Bz!st_<&G;?3khUU z=H^3Ew63+~h#;sv0d$}3fl(fB%v4}Ih!SGY-DNjL@PYou|1)LXk~+%};Bu0kC%eyc zqbyMJW^a;IL5C+DtXf-uE*bGeB8yf8y}?=7@QFyjI6UdJ}ANxVWjQ>2giqubNIDU8ry^ zwmg5Qsl{m@X+64Q4`!FGU5r@yqpzG<~w{ zPhw7vkJy2%`n0}+U9NSu+NoEIK`~BemEv-w(@f*oUXRk9_<+2c!l`56`HDt#13M4G z;RwPIO1bK~oeQCJ2dKu0Zi(aQ9F+0HW{h3y=QjlH+6NE60<@x{uIND?M6QZi{3daN zYg1ab`@5BC#-GJLTj+)kOu@9BMsxH5D;;;dS@7Q46!`*hgRm*wKw*3*Z~ey+K@Z78%hYiGMh~z3erW1U|N6X znAt(BxdXk|4!EppQq%*iMadPKdtSM!67%1&* zuHewZeVZ_EzhKn$(>CjiFH?>e8weQlID0S9Vo0TZ8MS$LB@ddONt{M=Ui**u9yI!` z02QvOKmpCWn6n}BE7+CLM$Ao^VV3^aX+vM88rQuQZ{nOBvvCJL=sAtV3qoM1i$Glp z50lS`5szZM`?_-rBsv@xW`L7Ji zE$6$4Q=AXF#mxS2`yfRs_9$|&J^NTwY_Gucq6k8|n9SIN*t&ff>U-s5y`9##=dHf@ zF=13#W>%iVR14o$QiS2PSlecdzo-5cXZqAw^ehG3Hk&|j{+u!P+f#z4yiVr}OBpRk zbZY}RD%ANqtZg7$yt)J!xnxrDdjK?c7I@C4=fE$3ey=4^H9tL|to?L@nCpCGiNyq> zrl@O69WX*t{#6WA%#=1K(O5i}WNSL~wpvzE?=}AW-RW8<_z};Rrj2A4tkSK!GrfY{ zaq&@6;@{_Yp-mo3m*!ZOE+5_+(aD;Z#P&bw3#mU-A?t5*u0JMoe=uMqrb+Mwzs|Yk zB4{f4w3+O2T!q>&Hw%*cX!fBm6W?-Mk|UUfxUM7+I4L)~pc|k#?hNcwwNip8CeU)4HnOLgo&D_S zWPszk9s63Ouh1-2Y<_4emGL0nSbsPKbrNVF`!LS_F5F5t_ivPI?NMz|GU>EvW(30w zVf9+aF2|}boMn)cF-4zNyH#~0l*W-&Q(PuZpr7Z~Q^&UCg%+WvPJ3y1AV-F5I--1Y zbNwbKbh0*6Uh>z?k*WHn0RkHJu5%?k>h!rCZpP!;eE=CpC@X^ykyo5p*=9NC)fBD@ z8VxokPrH~e={@!DEW@x$ZbQ`^fH)=>QipQ{6m5|JEJm{P4T`42kL9p>2*Na=iB>A! zE1BAUd+T@g7XPnvgZAhs>Fa0NDaT?YSx`Lri?RQ)C4DLdw>QcB;Vre=9i%J8X3@?BN{{c_PivJ=XXXg8@+$RW> z0j%Nv#=Ng>%quDSMVseiLuWj1QBZtjiUt+Uu8l~in-f$)$64ad#|*c+c2WSKt| z6L|k96g>5}CW-4VTTQEodNk5C1qNH3OMso5Om}DQ z$)5kmK>!GHH1UzgN+y=GFFLVUw~HB?B_=&~i1r6C0UCs6Wv*}wFvAhjnxJ&EwPsOm zET~;H#^Onj(nbyFH>IF?N;WA>uA6Ob_WrP zcg49o*#7+8P{z4$F^yNXmn?g4vS{WE-4TO1Q{w+gkC~|Nm6TT3fUXBx&TtIu5F>)I=T+l_Nrtz&;YPU_q-tjKCM8T%fb<$RwqZl z4)h#DMo>LKEFQpy=}zWZ6%R-KdWHtsoPDw;CpFF~Q$25%`WQB4>sUBzpC30cuXYT< zFr(e6@ec+9sP1nKw)fT7@^&bg@Z!t`X{NLcnK+D^^+)5Htl-A)_)k9w|U z@-2_;SujSm^#(DE3lkfI>+lz>Dvy=ww~%Kxt@A9|IS5gYsbR0SxE(iSSqiN9(V#Lj zA_-2_DB3SLh%ahHR|uI>=HI42OsERU1SZl|Q1i87Ebmm9w?zjB00UA?sLL269dsC)QW;`OtraoZ% z=S~pP7r2aPeuXtU57N66B>UDGU)xdl0n+*hUdvK9V_5yn_`lEx#EL^k=P9i*$e5;P zoV$SeBQ{Z2KR?laFpeX=Q7_m#a=Dbrc0WXbuf@pFf%M|bw)hvhI0i8o80cbQrL6{~k zNRtA>W6n_fZmkWR5@}%8Vo*uTC#@8SlXn4)Nz;d-(KcqbB4tt#DxosB-l)PUTS-dj z1&HYHe#AhvwradlVcFH7X@WuI)$VWeZl#PxyUYu;cYtXLH>0~yvRx8u%~>)IiLko_ zcyMm(e^9E!C<`yM{x>HX){<{9Of5uG@a0PmWp|g2Zi)7-mBv z6^x|lYjR^0BR((oNK=nhD&aE#lPQ7!AEc~I-RH)(v)l*-DNFGnD=%*cbblw2bT(pb z%{1DuA8soe-F4n~-x<};m6i?iS**H+ts!M4`!{T|>%A1DUI$dla#;>Zk5iwHbCoCW zGbF`uy^N6oRerPCA7EV3#FSa+xufn{)Xp1|!8NkH@npz-(|g01y}k4Ukx@M=%rFG45rs8deA zbU!rmE1{b)5Sl-|Tk+oorT1tOUSN-wsG{BWJfO1-TJFAEgHx$0^?|6NabbxQw)7<0 zvj~6jF?m#=d+BNx=-VQk(?dD(j-3S9EDtr!`9?uR&~~}WhLru|PA9#v{ipjp2nlg% zbh4->f#4ja5Av+H$L=jMRruoYmXgM3tvSTvD{yo$k0=q6U=K{E7H_j$XxI22KS8?| zIIZ)BVdi0+UfxAYdg>8qdErx|RtXgwE@MZy+&=$lR@sogzcXU~25^5l>P=2Zz4a<| z)iZeYQ*LLsMxOGw%e`s{=O*%cl-+e?H9cHo^4jLBii0i%GNgy8%-VVm2ez z=}JPJWDs=Dn_LtX4Ncb(TubAqsfph~!2yBkU7!8_1*WAUbEk!M$YYfFULYZO*n2w3 zS!*l!6YL9)2u-0#%>@!um16mHp@Co0YqFqh5L8+p;C#JoXV`mvZO?dd-W{SwAN9+u zlq>qO_&*Rs5w<@rUIdugXxf#e-~uqF9%ifAtZ)aF1O_OsDjY5$MZ-TLVi3UqERQpF^o(i{cegNOvPfZhH9#_y{q0)Um3 z@9y7d*)QbL@QYFhsIkm*z| zaK&+{+Y82-oOZrWJt^b6S^gD6YsgcFWwg&ZohB5z)m6P4YM*V#+PEO{D?kZq? zH0&-W06M4l9W$oPZ2F!7z!2{AdZQxGdx06+oApDk)5cxU`&$*n>Sv-_}@ge5uqr6B-`F2>LSy>Q3*J~*RK;x!!@ zgd9{Rxw&eq2P1kqPP;S3*C8{PS2qBb_F`*X#CZay8qZ!KE=q>>e?5`<+B-o0Ex+Sp z=^!Wzp< zmgoRE)59dgK^Z2d31#n;x?8URZ1BD%mKOkpPRYL|fKh2n;1|wuL=FxP;qspi#U7Ef zY0n^~_X>a>)4>5lryH%8r0Rb%tY`T?4}1DCF-o zT~0_CJ@Wv?ypKj}93Fw>kpz%J3@u)yIN54`-Vf=#s*fs|krds~fHJf;*N}uq@N9Ia z#toGXTo6#O@HhV`*fE#wW)ndD{%;QU%m>H?xU2_I->az9ximRC#A5a6A-g~na0y`w zwG;-~>W8Y|V)!*n7`A5b35Et7iaVkRTs(FuFky(J>64l}uS}~JwggRd@d0at?Q47> zmnM7*9(vm7cmKF|n{&dDTFKyn7h4OU`wlG&vHv|kE7DANB_EG*9q-$AaKC8sqDZDE zyjIZBYd@f3k!k>C6KHe{I6yvBQBnC7+{|P3v0`6rYOm$d#{2*dZ0d+ z&eGOmI2z>RGVJ>dDplwj_T+d0C7ZUoxgtvFOk|`I39>0kpJ0;F*5ux!DfA&-o_zF7TfsU$8TCh{6-H86x8bt zqF`^=VJm?Bg;LjG(~2ef@q~b3=UB4pc>wu?J_aMM!g(tA=Nbyjy~5xhgM&j~C8cVd z>BV3Wb!EJg+x}drG!XLKtngWCeP|CP7#XzH>MSc|Qmo0kNf-zdm;Wg!q_=XSeF>yv z`@CD+j-@Uy7+<7^PywzUz&q4e8H|vkoBg6MpkwO*j4zgZ{Gy#4ztsq}6c{AXJ0VRy z28rr~6zA=2V(s%a#eA(Wo6CH{lcY_8ypqAGU+T$bpeA4J8LDsDlFG>}Jg>~DipvI0 zY}^ZLUY8sSu7b(6O)%TfKp=}E5R_uNF5d9W0OA`aFH!(x| z1>~<%X@CHl3#Uu83jKd`yOef~CgM5oHw#pa(tu7u1v7tQcc$W8?prjU@>K^Ln2^pQ zOMvjlG_&afc?iHSUu(-){GP|gxAXa&ei?1{ezIQ3gwOV>lve&Y9xJbk65o?_Qzw%L z2n;)frohlA94+PImU(*$@n1$rnF$a&21OlheRo8BN>CQ;oFkLkT5|KGs6N2+8$e3BaN0hZDe%Pp*EwMikP4YMIl~yaw;1{U%MJn5E z8-w!nFMVqkMbbkN#tdOq0}bd5d!quGG2FoQxO!Q)Rz}4n;3VyL;>+XDo1yU%m-zg{UT3!LyM{u|5By;b}4|1U?)dH%p;h}Inv5J%*$cB zbl`I=z2E~PF^L4Tr&mds38b+}KabWAaIWd}`emt$fflfYR-#s8IjkH38(pF8h#e(u zAa)jXRK>dn^`J#@7CZD#i#vG(?|R8&XJFDr%6vBzqtwNeV-0f`9|I^!7heg$XYa^nfzKDQ?(jg!Sh?F!)ivG$`FjH%JUH#PB`C`>S)Vb6wy0>+t6=vuF0+>silQ_r30WGsYG! zk;;ai7>-rZgBvPjz>b>$?&ZXNCsocQ+Arr9y;fLjhufSwd+YtRA3)CGx)Urh-`@h7 z6fvL@e)PfW)xxORFVO8d(X*#*4OE&?^?PK%r#cnKzQ1vwe>k>-VU9UE4o*(zWPh&M%ZIqu*G z*nP1wVJG#(tgaiJLu#$*NwOb-V@Ij?a6|vjK_`2f?|1hfj9X8D_%P$(@ct8L&}$2A z4C`8gX&V$Cb)tOP}VC~IQ7oA{<^8Jo0vgd6#|9!o|EVJ!ctv=@@RmErR_=tDQAL?KK zNzO)m18JHZkOkQZ!hXwOP7vKc$BV)O3s#FY5pQ`(%*yPmQR){3S5BG4GL?ztca+TCZEvn3%` z^@*#~%p5Y~D(9d7-1429&%Wo83lx>^ZPq{x(;X9C=I%H0=~!oX<7b!zV7{96casV) z>De2Ye`X3mW5pItFvM+5Ir(eHJJ6%^>tBE4h4p;Lo+#)c6$UN#Z*``QwK$fZl-=ML zz@mGJaG6+AKy{KA^ysF?$%7T$v^}MNufSp~l)4ZD`h{)_NC<_1=6(;u8@uCMY6xB| z92y}@+;13tBcZONIfZciOvmXTEaVB8gD5uO^E#gq&t&Or1M}X=E?i0E4VCU~o@xq4 zQ77STJvBrbul;x2N4gJAO{!T_`JKdev~2zPn(p}8;bqL$0RmPJ1fgSbPifQbQ+_bH zCh<8(CcQ+aV5v-}Ag#rT1NF83x4#2WC;wxmP}d&uxxIfb*)S{b#E7~!Xk(WpNMu^M zGr_VBRKn`IZ95I$lLfsbhXjDmF{x4rB!noIalkxp>q5kepUBu(11+yH(LcaNfMhD( zD+e-ywtk=g4Z*6WrKLP4X}NBa`WMvLI2Uxq9#vLS2($}Dk6e07J8`QT0_-?MNTVHl ziO}orc(Z1UsIk{ZI1rZ@@QpKwe2H#QR9lNxSCBW5R!u zimM&Fco6!|o?0&Qc51Ocb|$dbIhNK;Qs_LwEZ*lH0y^Wx>3o9H<vI3vkU*FL;ap@l!oxXiUU?Z>8TfQC={BhQF0-`zHp7lq0-t?A?gf}(9AWPd znX#YHyU615-Mt^Q$I(qAx*R9;Hj$=Q;xX~lm0s>E?V(z5(73jB3`KiI>qf_27(o6( zIQ0e#@8NHvbC$sp>#DLp( zs6=!{D@=KTO4uQh%cN`WKf_4ywsxo44KS=oYMwRI5l((UP1%YG8~HmEqz4PTc~o@) zAW8Zh3zli8QdS%v-WVx}^<0R}%^{crTqAi=2X{|t<|EMKt#InuLA~}4dRy|qur@g( z94naZFWZ>d5cmgk6Y-H}MaCZN#k$3JPM*7rV2Ry4qSXTX+Fd*K$GE!nR}2dd?L%Dv zyq2Q$f=o&`SYqT%=-y-8lxHqlQzU2NX_cZe?x|eq^MC%eT>_{QARS9(hF*mGw|F=q zwai@4-n^h-e>c;y-R46i4{dr>VJmDb-2lTQ4htET+!s_+!4@AQydDw2&p^nMSLV;A zjH6E*vpDY|h=$!0ffO&rOuZ*q(W~ku(AlH9t?^sAB@EQp*=Hf21%1KR^6?n=leWJ(CPQ`>TKbn)%n*sps)3AmSy#!{2A z6?A}QPPz}~i@v{lpj!beSUpFnhyxZGWamp3`Cn9I$2JreCpTiR94LXn0+b(lV#9C+ z&;D6r0v^0IRq6o{JQY7-G`}G7kVHkPqzIIGIc(rFsf=t{?EccCQ#i4Q;@tm}ZJ=f4LWs9qh%t2;fz zQX*s?&$4n=J8al#U9NI{x%3pTJN}+lfOXax1oZjGK79l)n$s10yTi(M0|2aaX9E>q zw3Y3hmOcs$2G(egb1#3*$C*#76>G0Tn&hspBCr%Q=rzEo^Ccq~t_PHZ2dl#VV(b&O z;U(`TEcoq$W=Oo^4{6mF>hTW%*A4DmIPK?&-OolqgN-&O{`{XSn`U{jtgHSE7n0@2 z5K=!>bNkFr4_jVVyWmA~P3-{dsu^2G?2_H%qZsji@WK1G$>01Kurcw6&~7wpz0%fZ z*-`xaD#hbV)8ao&5J);xm;|;>pmFKodkUO9EF7fp$b6!ORf}iq4Pk0fO2UK|IQgM1 zm{fm%2Mhr7hQtG%Rgp-Na{_tZ&$l*bEB&{1L$LYYj@oCj^CX8uc-M|n5M=VYR9E%- zG^`@@5!C6ueA<8VbxKKamRmr4)p?88us)iB?3Y0?=Eb$J00}Uru%}7}H`rT{2HF=^ zvw+cdJiJbO`*ACz1+MUahKlrv%@n=1p3_z@-~tw9zJ8YdbBhrKsw@c9m^ke-Fr8@} z0pK@xKMrgw0V?cn+MO?%TGLhMz6)Dake;=eBrVX(wXWKqdH zz=QV~6o!My!3aPn>QdQw*{y=>^Ve5__mC2I(w)i(P~A0&V`vy>`T;lKQ56fQIe!`N zasagl@-}b#iU@dLD}F*+5jD&EHy_wR^cJhytV~f7jsd$6pe=rp3iazr&&V|*N-U4t0Cm zPu=LJN^)iUuk6^x%AkOp-h+P;WZ(Z?U4Rm>rF-S8kvZzd9qY7v&L~fzf+2C$g+CES z8roctQiY+ON0Q%fY6on0SHSc0>wksP6k^_T?47QGk;!FW zgH(~;Q?u~mSB$h#YT%@XElrPRo}ushyaf}6Xvm<}9{YtYX1d{&@MY@l^3dYZu9yL3 z)-bA4Z|Z-Z%1^&V_C3{1mY1Vc9OoljSly`h2``XR0h}aev=Pj5Lgs${Yt!Rlyjv5O z!eegCsvqdsapqqEXHlAYpto&2TbxD zm`4^H1dY2rdA*JR0(LFWoZe*nJp(#TQ2wUK{`JEG4+>1q>Rnwj(c9?TTsvP^!||on z0#md`Pe7xGF@5NX}g#D zHA?W^B06ZaZ2oi=9u=hzunFN0f=u(VWv&$}CxINF&DZu1XqyCix9Pt?P1fCAHn-1A79{-NYv8{VDt;X2S zl57$ry&b$HQ`8DnnBR}nbHGUHEGE~F;=2K*$dr+2g9$c&lEy_Jg08@GYcoZJ%iSZq zwUkI+l5rr^h0B{ndX`q?&IV3v_`8T~ZzNrsxK7GlO2}zUTZwY_ot(KeLwKoYZ*1kd#avUM-Zu~jQ0l*tXQ8jN#uTE zzKj3x3N90UNH_%8M00A5h?%7=QuTDAVX3I8&z+v5eGp-m8C16&r~Q4m78ZR@c6Or* zyMhONZgYV^&5X?D&*LHLm^(~~&O?&bk5z|Egj$u2Y|dD#Zu%)MQ;d4oRU`%pc_S1@ z*$Azi$}6eGB2Wcv`*L_?Qt(vNyjejA#Jm2XDfD(Eg+>GflAsaqE%J3usIC#i6e+j<0 zs3@87CRmSfUj?={j0bV z?HWQrFZoRcsCTULtE(5s<7h;0pSEx{I>BoUTT{>Tbtd8iczOZCjMD_9dVhR?59C_j zatMFQh|QRB{hjLa@`J@ZB(2*o* zkh033MCx#HcSKg!5S6(K!BJsscVpUMWebb_`4M9~u~mB!)Z9-r5-tQE8N?S4mBn++ z?qm9l{U&Lk>Z7A$RGnxDeuN~`&+IOobnAU(u|1`f!h6oL@h+2qR(O9tyI}dXidD6J z#caOIoTtIsKt+!3oBp1fAk>!p=_#_9&+b>FL-!%i^5drkYI*;8=syfUfnDe6r_d_% zzmmA67+$P)LE3`X-iT95F~8IgcW10YAg0v9UAas!^O~|stNwYQ z#?q|P@KZVDpnFNEpG&5a&u2Z@iP$#AD)7+NWf9ySlq6 ztKRPD2#RVp1?b5r2)po)AY85cR1}BD8hzywrpX{nAHU5H53Rp+ybMz8a>J#=RZ6Yt z@F%(YNml|2_V}d3vd5 zY`mbGrMY>f_jEzL11J9sYojAy=i`CJ#l;7+ZYzNKXQ18EPp5chldLDWHPz6Rp8k97 zdN0)l64s*SC&Rg)MM@;UYh~raEI5=9fX9FpM*7_I@g$@`dd*6@%!X=nFO2fdc`l80 zI`!TP%4Qc>!`_qETE}l^aX;XtS{PYv>+p*Xrq`VH2a10ce^r>xaJVVZu0iUyyZ2>v zA#}vzH$Gp9+|Kv)jnLSLgoh~YqKEm#&RZDY{5UuzDm2AmXA^y!ebg@XneBEJ^z#9= zh?VD9Gni4Be%WX{qASwTt2w(0lJNQlF}k^GCzjxFTYPf^a`ho?tw%=6mkD*J7^+D7 zS;I2#-rSo!jc75A(5;V_PFlr;{XHj)A=*+EVKLAm=2sxUI-MkM*7sz~rTye4vEbCN znVIZ<9CO^QZK@twWk%*`YHIBmJtgj?>UOFecp_<_Ty5?u%qU#^X;Gwu&(jbZ+lsC} z78K{87V<1R6AGphhqfgu$*CmQrtM1MzNeY#kQ%a?Va_U}6p9X&4Z$t~oAFXPj-;V! zVURf2gN$Ip>FfA|V6VwHKH9445Z|tU@YE`@qT5ojc5W{MT9!3a;{`wEoJM3mXPcE~ zVprA`Noe6MKYvz+qGA_AZMgsweXg!0aN*SKIHXl z)cziym46l#Ihnv*D3nVd$rJ*~Ny~OBC7<0I8m^5RSZ|nclsXR0pM0nAmB+4Y)8c{1 znXunXYW}SBtI}H*X z%8{W1`Yp>l9^T9Deqo_8&>zxFPz60Cj4P9XQdEYm*H$wo1$wby*HCCus3cYkBpdwg z)-+Oh6G*NXA3nOw9vqI3&U%S_A@`!kwEeI}n4p;R768shdI$`bXcph<3mDr*4j$4z zvkAS3a_ORhLor8d0_#BwIiEDglWzmhkXKSnGD*NUUk9W%A#zH4SYG6LyuR{q?`IWOF1NkBCnN95iYh`~%G;@Y>}G0hlX>!vUfj;f@qGYl9lFta zR>hS96SFiTA7eP z8lWCp_i6Dbz^ncYMv|7XX~qnE3QNhiZ~u+GtYQ(JJj;R@diG6_wIIsX%kJgaO0s4w z=<287nDh*|HJUduseq~O#I?Qupo?tB8B+JA;PDCdO6Xz*f5VJ@#EzTYz+cGwIqfsoJrQK{ zwNntEdJRWk^dczSd^?_QR0v!Yc-qeJZSSx&uN6aL_(g5L=&C(pXV-69myLb6-^@o>s&9sgX;BLLb|`iK3U;VH^1Gutyc9rhUH|jC(c=Q;@KOU zJNjGXUUQLpZ+NYK^?6+_Z%WI|2ptfyhr#?aKNrayPvG zcGpciR8vFDQ*!o-g0Oj;Nq|IBr8EVf(79bQe8}2Vbkc)k_Y+K3G13<`s-AN(BbdmC ztFWlrFzrR~)RTY~wwuC6BM7S=^m4W zB8?^TMg*hwV_ns$y*e#|hAYD#wbcisq`Hr4tHp-~CSNK(R;D%iJ$adTHbstXrlQC5 zF*R|synU084NH|#BVHBR?JGC@0sm1ze{nubZeDf4`1AK1NieSOqLApE&W=Y^THZSJ zFnjrEfCs#I=4}Ko$ZRAW!DfA~?_<9VQUo;)6iu5>`Z{^&3ywAzX${Yt6*nR@4hnuR z;*WWViQ(XoN)r13`}V=^!*f_G;@w==Fw=tmy?bX4Nr7^Qpf`x(E5c;u9e4MMvvJI9 zA*?d)(DKxAoIUV4SmCUOKldG|HuK_JR6THL=+2|;2GgFJ%QTtm$6oyMCBWqFH`HEtOo^kBj#VmRB1Bkdev@ot< zgJaJhE2Nx)glK?T#Nt=a6pTl+)%o()iI@&!xHbbJl~$6YC;RIPIP`$Uw7Q1OZn*ZH zCO-&jB=Dyv{{Sp(CM2S_)9A#gdmu$8Hg7}w0D0)bUS zaHkFmQ~c2jKBF|*7N+Z&Run#=sn4?chu0ejd$%8)oiG{H6kV^aA=}QhYtTqYk-zzO z%IV}GUo#UvqIv>SPF;LD;pQ;By!V3K4nAvDW8X-q$^Mr>4t1p6)GM*~>&v*MX0lEWM=H9kQmg9bZS{m1$>kl~|M(Xmw& zsE1V2lR|w#es$MNR^m zYs-f0cQ8Q`O|&8zY}wEgOZl5Ilawd$34x<`#`VK>fu2>AHC`E7cU{;$`hl@@ zdc$d^Mw~VhJlZAv!74XyXZy=L#inZx>gI%0LY1HdCu}-aZdMo^*=hQjTQQ;RAB1cj zjxWo&;hrhgvX?kcy{sWTB6(e!ObpC49n0 zekp|3Zi0OFKs_c!e8bYNfbBwt?i_8>-W^(4cF3RKqr;TL5*wc@W98EMC@XV0i_HtuP8~^o0s{lhP9k|Uv)h;V z@uMRWvbQmgLRw9?IJwupV)L9e$aBF0$$gNLDa1Q^?^6gg{oE~oVzz3cXLtR_I^Ra` zlF)@rx{RW>uG^1-Lo1{kieSW)z~VDl630Tg=rf)19FiKW?|oIY0>*I)-1H@77Wl0Q~E-ELlWWL5oXzXLPG zRVn_?p_xQ+v^*eGg;#UL1_^f!RV4V2U?7{oh;G>yKZ;` z_Df|od^gS&R%P+nxVYk&GCeO)-h*l+=2I_SJxJ2ERX*-pu~37Ez}63ga{w3IIzCZH zC7I6l{{l|8e^^-=!p|;H-&=B4W8^};VBYyQy<;%Yo$D@sIENObEc&kn)!2!i%58=m zj0JlsPKhLqfz&ylEw^I{{i0@#ob>u{mwJul=4|8Srt6!j#c|~vr$=-7Cnw_Td|kc0 zgV$>Y_dnAPe+w8~e$e2FcTzhlkvW==K)i%^949zA$V&2wDcUh$(d2wZ^Q~R(;6RKy z3nT8Do4&#%YI4W3I0ln%0GFoY_TJQ}xE904gDe}?e77fs5CWKEKe+q>54%S)T~>T6J^;qWl;qK88bIEG&;id0`%}D$Z3>JcQCBB;flZk2?epulhuui z$4vCP3A^xl7J^Qra9!#QPR7c`Wh5S42S=h17wn_Ns1#m?pPL5=#vOQi}+SH1TuKv4vef;49qf8 z&0ioTp2Ppj>}7iNOKnzx5f`;B{?bJ$ei?lwUP@N!6$&&M8EwKTAspU&ODzSzAvRM# zFt;N>8w;RsAgQ@SE3D21%1uk%gl_G%`-Bmvu-`hT+TS(ZYwQ^?dlj>UG{WRwd0DO7 z`qbwv;!VF3uJ;Z%KQ!)#A)6~cd|)$qNR&Vt1CR(QITbAwts9TM{^bHB9R={H)r2Ur z`T3{Z$#XL^gd5tFVC9px`o0I=9;hEx()`Q8GZ_*{$xa-N;0%>5p@yd#JF}^lZ}FH4 z%F3Re6MO-1!#6~3uD_rYWVZ9Tn+79nDI&ScElqcB>fa-D_`F{2wY-ud9PDjSmJs|b zxNz7C(@wU^C51Uu1;2}u*Wfc0HPuI}ENZPe#@mI}@D05!4hTx?_D`UtXV+^};J z{{Xa8`Izj{NitH>BvSAcIFURxR2uZWp&&}_4nS^Rv9syQK@{u19G(1^lkWGIP#Lx- zhCcrBcmOf2v&4@a-={UawnA3}d?LmP9!h3zW2t-M*2e)Mk9Fac3h7Y4vr0e237&U?`a&*Z93ki?-rLumxg>t*Aq9h~%y3oR3+q9QNe)t3Nl}}NSkr-_mDoqQRm5}u zmHd+W-s17bwL80U#j8Gpzd)R@m9I3d^{!o|z`-eD^k)c{ul1;#4I>Fwi+uO>^Lf41 z^hn9I?vR|5timA-;^UM*e z+kkK|(Q>Et0fpbd(F?sCm0Fc#erXdLsw?NaW}(Xm!68yjKYw{*W{TWMA;CX59%uvgh*)|13FqZkolOzB$Zqz9iv#ohR#3~@re{5Z4rOc=*vosm<^)rXFfyGiI z6g7>bO}RV#ppW2GeP10f|IaThDjLzN&xoa0HmcOOX1RD>P|gG`fIGQR+nFO!w9^B4 zm5UQbE<%UT{TOfKT|g$pv~uhf_4zXUj@+L1(!F(a071C)Qr@9I$#zL z0(VXO_+mI$=$t!dKny+5f&^nY?-(htKWX+}mCWW2rO?dShfEaB6VKsV+XP)s`^SeJ zm_`sH#d=kmF};S>8R_3Tp?AXMHvQx_V(wP$@Vlst3<5AyeNxSSUp1e|hl=4)*7a=F z+N5yvVEM+s$bdn{@BW5urt)TaApCHgTTLZ+Oc|%15{~uQ?v7=EMu+x=g zQC7i%M5>K@zjj>xTx_7|yl?RI$dnq+gFY-J$q}#((5Z1n+HAdQ9tQgivaeFuP5q%_ z$B0(p?JzOVSC|zO;m3#5iv3`lgzb;`1A-$(jM5r98v%VPe6xYL4{q4N4Yq4RPi0!^ zUH9amhTOe=9)iRb>#$M~wEB|Nfb_ZYX5hes4VQpQXatKRQ3AS2qEJgi17VcrA=cNT z`1%UYyD-4iv8Lou-N_-mT(EnpH0*s}K%*`UMo+;b=wm~gI*!&K9b-o(j`y8KVu1D{&w zt%S|_EwDYg2VuX`&=W;@xIB5War|pkJT$r5X6a;sr9U1hMTc-M<&ghJyfP?W|G$j( zVi>+Nra7i;&k=d~;N*3(n_|T9RR22XLO|y8ukJ&;S+$#`>o=xnpd0+dSAqX`DPomq)mDEcOTz zhV&6~*xv+pniqP@y^Hsd*dL0sek(wP*qcT+{p>??^|7_VZR|nPl_N_S!Q1;=@R_#s z25f0Uux_`1zuF!F1@GQWo;qe%SXx>##~LZ(;5`ixBz9%m(+H3N3g4!fm=u#(>;twX z=%V5o-^g7{1LT14%J;U9(%Y9$Sy#1?{}uuM)2@IQ8SA{?H$CL+gq1Gg;4$BPM(lJj zr2Y_hX^H%YVQp-h(c4h$q25bG#Tn6EkuwhM#%JPSWM>hh&nu7ap1b_ilbd|RwoJb% zBHDu`2JEJl73#qNPYW2^!NFH0wqP2PFE3rDW&zK4%suWxEiMXME`uf!2Z!#id~$@U zx{iTOudp&hc=?Cs`R-9WQ`6lt4eYK$Bx~U*u0l5#YxEo9)M^G`S&bth z5&nmP=<@&8KX&i>1hVyCGptEXcHh6FB8UB~YPW(-1bEAjVKl9r6FGRp&h1(k;fG@M z0W47j$Nr^+|5zdcumDN9}>;+ruPQ!!}H zj!UZ9$j7&~oDy_1KzCeliW++Ze{->Xm!1#!crSqM$EnIRZyiy`uQDeZgBln+=EW=7 zWoREh_E5))@)QyB41d4X+R9CSKA7Ax_i61A{!$Io^oE^ZB;{JRwga^ s>TrL0NvZiyfi%QYQzH8lCZ}+N;CE&Y)d)}!;NU38C`%VTfBoVA0b4wG;s5{u literal 0 HcmV?d00001 diff --git a/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_nested_display.png b/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_nested_display.png new file mode 100644 index 0000000000000000000000000000000000000000..a52b7111b5586acf818ced3ed6002fb84cb8e392 GIT binary patch literal 33258 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 literal 0 HcmV?d00001 diff --git a/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_short_control_display.png b/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_short_control_display.png new file mode 100644 index 0000000000000000000000000000000000000000..2b25b45bf4d052005c50aba4e09c9aba561d48d8 GIT binary patch literal 19441 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 literal 0 HcmV?d00001 diff --git a/.maestro/iosExample/enrichedMarkdownText/flows/basic/block_elements/ordered_list_wide_markers_test.yaml b/.maestro/iosExample/enrichedMarkdownText/flows/basic/block_elements/ordered_list_wide_markers_test.yaml new file mode 100644 index 000000000..3e1a0dd65 --- /dev/null +++ b/.maestro/iosExample/enrichedMarkdownText/flows/basic/block_elements/ordered_list_wide_markers_test.yaml @@ -0,0 +1,33 @@ +appId: swmansion.enriched.markdown.ios.example +tags: + - block + - list + - text +--- +- launchApp + +- runFlow: + file: '../../../../subflows/move_to_playground.yaml' + +- runFlow: + file: '../../../subflows/set_enriched_text_value.yaml' + env: + VALUE: | + 1. One + 2. Two + 3. Three + 4. Four + 5. Five + 6. Six + 7. Seven + 8. Eight + 9. Nine + 10. Ten + 11. Eleven + 12. Twelve + - Nested under a two-digit item + +- runFlow: + file: '../../../subflows/capture_or_assert_screenshot.yaml' + env: + SCREENSHOT_NAME: 'ordered_list_wide_markers_display' diff --git a/.maestro/iosExample/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_display.png b/.maestro/iosExample/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_display.png new file mode 100644 index 0000000000000000000000000000000000000000..db03347477d0267da43898fc2434e16d3f1fcd15 GIT binary patch literal 46912 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 literal 0 HcmV?d00001 diff --git a/docs/docs/android/api-reference/style-properties.md b/docs/docs/android/api-reference/style-properties.md index f734dbaa2..7dfc02153 100644 --- a/docs/docs/android/api-reference/style-properties.md +++ b/docs/docs/android/api-reference/style-properties.md @@ -236,7 +236,7 @@ Requires [`MarkdownOptions(admonitions = true)`](/android/api-reference/enriched | `bulletSize` | `Dp` | `6.dp` | Unordered list bullet size | | `markerColor` | `Color` | `#6B7280` | Ordered list number color | | `markerFontWeight` | `FontWeight` | `FontWeight.Medium` (500) | Ordered list number weight | -| `markerMinWidth` | `Dp` | `0.dp` | Minimum width reserved for the marker column | +| `markerMinWidth` | `Dp` | `0.dp` | Minimum width reserved for the marker column. An ordered list's column also grows to fit its widest number | | `gapWidth` | `Dp` | `12.dp` | Gap between the marker and the text | | `marginLeft` | `Dp` | `24.dp` | Indent applied per nesting level | diff --git a/docs/docs/ios/api-reference/style-properties.md b/docs/docs/ios/api-reference/style-properties.md index d294ee7c3..239fd7c87 100644 --- a/docs/docs/ios/api-reference/style-properties.md +++ b/docs/docs/ios/api-reference/style-properties.md @@ -256,7 +256,7 @@ Ordered and unordered lists, and their markers. Takes the [shared modifiers](#sh | `.bulletColor(_:)` | `Color \| semantic` | `.secondary` | The dot drawn for an unordered item | | `.bulletSize(_:)` | `CGFloat` | `6` | Diameter of that dot, in points | | `.markerColor(_:)` | `Color \| semantic` | `.secondary` | The `1.` `2.` `3.` of an ordered item | -| `.markerMinWidth(_:)` | `CGFloat` | `0` | Minimum width reserved for the marker column, so numbers past `9.` do not shift the text. `0` sizes the column to each marker | +| `.markerMinWidth(_:)` | `CGFloat` | `0` | Minimum width reserved for the marker column. An ordered list's column also grows to fit its widest number, so its markers are never clipped | | `.gapWidth(_:)` | `CGFloat` | `12` | Space between the marker and the item text. Clamped to a minimum of `4` | | `.marginLeading(_:)` | `CGFloat` | `24` | Indent added per nesting level | diff --git a/docs/docs/react-native/api-reference/style-properties.md b/docs/docs/react-native/api-reference/style-properties.md index 55e477e5c..a83eae0d1 100644 --- a/docs/docs/react-native/api-reference/style-properties.md +++ b/docs/docs/react-native/api-reference/style-properties.md @@ -254,7 +254,7 @@ Requires [`flavor="github"`](/react-native/api-reference/enriched-markdown-text# | ------------------ | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------- | | `bulletColor` | `string` | `#6B7280` | Bullet point color | | `bulletSize` | `number` | `6` | Bullet point size | -| `markerMinWidth` | `number` | `0` | Minimum reserved marker column width (floors the natural width of every list type) | +| `markerMinWidth` | `number` | `0` | Minimum reserved marker column width (floors the natural width of every list type). An ordered list's column also grows to fit its widest number | | `markerColor` | `string` | `#6B7280` | Number marker color | | `markerFontWeight` | `string` | `'500'` | Number marker font weight | | `gapWidth` | `number` | `12` | Gap between marker and text | diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt index 89c37ece7..7cab2df14 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt @@ -41,6 +41,9 @@ class BlockStyleContext { var listDepth = 0 var listType: ListType? = null var listItemNumber = 0 + var listMarkerExtra = 0f + var ancestorMarkerOffset = 0f + var listItemMarkerExtra = 0f var taskItemCount = 0 private val orderedListItemNumbers = ArrayDeque() @@ -149,6 +152,9 @@ class BlockStyleContext { listDepth = 0 listType = null listItemNumber = 0 + listMarkerExtra = 0f + ancestorMarkerOffset = 0f + listItemMarkerExtra = 0f taskItemCount = 0 orderedListItemNumbers.clear() } diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt index 567cc79dc..f8b81399e 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt @@ -12,6 +12,8 @@ import com.swmansion.enriched.markdown.styles.ListStyle * allowing each level to maintain its own counter while preserving parent's position. * - **Parent context restoration**: Restores parent list's style when exiting nested lists * so subsequent parent items render correctly. + * - **Marker column**: An ordered list widens its `99.` column to fit its widest marker, and a + * nested list inherits the widening of the item it sits in. */ class ListContextManager( private val context: BlockStyleContext, @@ -24,6 +26,8 @@ class ListContextManager( val previousDepth: Int, val parentListType: BlockStyleContext.ListType?, val wasNestedInOrderedList: Boolean, + val previousMarkerExtra: Float, + val previousMarkerOffset: Float, ) /** @@ -32,10 +36,12 @@ class ListContextManager( * - Incrementing list depth * - Setting the appropriate list style * - Resetting item number for the new list + * - Widening the marker column by [markerExtraWidth] and shifting a nested list by its parent item's widening */ fun enterList( listType: BlockStyleContext.ListType, style: ListStyle, + markerExtraWidth: Float = 0f, ): ListEntryState { val previousDepth = context.listDepth val isNested = previousDepth > 0 @@ -60,10 +66,19 @@ class ListContextManager( } context.resetListItemNumber() + val previousMarkerExtra = context.listMarkerExtra + val previousMarkerOffset = context.ancestorMarkerOffset + if (isNested) { + context.ancestorMarkerOffset += context.listItemMarkerExtra + } + context.listMarkerExtra = markerExtraWidth + return ListEntryState( previousDepth = previousDepth, parentListType = parentListType, wasNestedInOrderedList = isNested && parentIsOrdered, + previousMarkerExtra = previousMarkerExtra, + previousMarkerOffset = previousMarkerOffset, ) } @@ -73,6 +88,7 @@ class ListContextManager( * - Decrementing list depth back to previousDepth * - Restoring parent list item numbers from stack (if applicable) * - Restoring parent list metadata (if nested) so subsequent parent items render correctly + * - Restoring the parent list's marker column and offset */ fun exitList(entryState: ListEntryState) { context.listDepth = entryState.previousDepth @@ -85,5 +101,8 @@ class ListContextManager( if (entryState.previousDepth > 0) { context.listType = entryState.parentListType } + + context.listMarkerExtra = entryState.previousMarkerExtra + context.ancestorMarkerOffset = entryState.previousMarkerOffset } } diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt index 541d66f51..5878fe6c0 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt @@ -37,18 +37,8 @@ class ListItemRenderer( // indices, matching the top-down order of `- [ ]` markers in the source. val taskIndex = if (isTask) styleContext.taskItemCount++ else -1 - factory.renderChildren(node, builder, onLinkPress, onLinkLongPress) - - if (builder.length == start || builder.substring(start).isBlank()) return - - while (builder.length > start && builder.last() == '\n') { - builder.delete(builder.length - 1, builder.length) - } - builder.append("\n") - val depth = styleContext.listDepth - 1 val listStyle = config.style.listStyle - val itemEnd = builder.length val span = if (isTask) { TaskListSpan( @@ -59,21 +49,53 @@ class ListItemRenderer( styleCache = factory.styleCache, taskIndex = taskIndex, isChecked = isChecked, + ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + markerExtraWidth = styleContext.listMarkerExtra, ) } else { when (listType) { BlockStyleContext.ListType.UNORDERED -> { - UnorderedListSpan(listStyle, depth, factory.context, factory.styleCache) + UnorderedListSpan( + listStyle, + depth, + factory.context, + factory.styleCache, + ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + ) } BlockStyleContext.ListType.ORDERED -> { - OrderedListSpan(listStyle, depth, factory.context, factory.styleCache).apply { + OrderedListSpan( + listStyle, + depth, + factory.context, + factory.styleCache, + markerExtraWidth = styleContext.listMarkerExtra, + ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + ).apply { setItemNumber(styleContext.listItemNumber) } } } } + // Nested lists inside this item shift by its extra marker width. + val previousMarkerExtra = styleContext.listItemMarkerExtra + styleContext.listItemMarkerExtra = span.markerExtraWidth + try { + factory.renderChildren(node, builder, onLinkPress, onLinkLongPress) + } finally { + styleContext.listItemMarkerExtra = previousMarkerExtra + } + + if (builder.length == start || builder.substring(start).isBlank()) return + + while (builder.length > start && builder.last() == '\n') { + builder.delete(builder.length - 1, builder.length) + } + builder.append("\n") + + val itemEnd = builder.length builder.setSpan(span, start, itemEnd, SPAN_FLAGS_LIST_ITEM) if (isChecked) { diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt index e3e5f4f03..077824b16 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt @@ -3,6 +3,8 @@ package com.swmansion.enriched.markdown.renderer import android.text.SpannableStringBuilder import com.swmansion.enriched.markdown.parser.MarkdownASTNode import com.swmansion.enriched.markdown.spans.MarginBottomSpan +import com.swmansion.enriched.markdown.spans.OrderedListSpan +import com.swmansion.enriched.markdown.styles.ListStyle import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE import com.swmansion.enriched.markdown.utils.text.span.applyLineHeightSkippingImages import com.swmansion.enriched.markdown.utils.text.span.applyMarginTop @@ -22,8 +24,9 @@ class ListRenderer( val listStyle = config.style.listStyle val listType = if (isOrdered) BlockStyleContext.ListType.ORDERED else BlockStyleContext.ListType.UNORDERED + val markerExtraWidth = if (isOrdered) markerExtraWidth(node, listStyle, factory) else 0f val contextManager = ListContextManager(factory.blockStyleContext) - val entryState = contextManager.enterList(listType, listStyle) + val entryState = contextManager.enterList(listType, listStyle, markerExtraWidth) // For top-level lists, insert marginTop spacer before rendering content if (entryState.previousDepth == 0) { @@ -49,6 +52,22 @@ class ListRenderer( } } + /** Lists under 100 keep the `99.` column, so only numbers from 100 on widen it. Task items draw a checkbox. */ + private fun markerExtraWidth( + node: MarkdownASTNode, + listStyle: ListStyle, + factory: RendererFactory, + ): Float { + val wideNumbers = mutableListOf() + var number = 1 + for (item in node.children) { + if (item.type != MarkdownASTNode.NodeType.ListItem) continue + if (number >= 100 && item.attributes["isTask"] != "true") wideNumbers += number + number++ + } + return OrderedListSpan.measureExtraWidth(listStyle, factory.context, wideNumbers) + } + private fun applyListSpacing( builder: SpannableStringBuilder, start: Int, diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt index fea4aa03e..cffeb499a 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt @@ -22,6 +22,7 @@ abstract class BaseListSpan( protected val blockStyle: BlockStyle, protected val marginLeft: Float, protected val gapWidth: Float, + internal val ancestorMarkerOffset: Float = 0f, ) : MetricAffectingSpan(), LeadingMarginSpan { private var cachedText: CharSequence? = null @@ -37,6 +38,9 @@ abstract class BaseListSpan( protected abstract fun getMarkerWidth(): Float + /** How far an ordered list widened this item's column past the one short lists reserve. */ + internal open val markerExtraWidth: Float = 0f + override fun updateMeasureState(textPaint: TextPaint) = applyTextStyle(textPaint) override fun updateDrawState(textPaint: TextPaint) = applyTextStyle(textPaint) @@ -46,7 +50,7 @@ abstract class BaseListSpan( val effectiveGap = gapWidth.coerceAtLeast(DEFAULT_MIN_GAP) (getMarkerWidth() + effectiveGap).toInt() } else { - marginLeft.toInt() + (marginLeft + markerExtraWidth).toInt() } override fun drawLeadingMargin( diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt index e134bb669..2d1130e5d 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt @@ -10,12 +10,15 @@ import com.swmansion.enriched.markdown.renderer.BlockStyle import com.swmansion.enriched.markdown.renderer.SpanStyleCache import com.swmansion.enriched.markdown.styles.ListStyle import com.swmansion.enriched.markdown.utils.text.TypefaceUtils +import kotlin.math.ceil class OrderedListSpan( private val listStyle: ListStyle, depth: Int, context: Context, styleCache: SpanStyleCache, + override val markerExtraWidth: Float = 0f, + ancestorMarkerOffset: Float = 0f, ) : BaseListSpan( depth = depth, context = context, @@ -29,30 +32,52 @@ class OrderedListSpan( ), marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, + ancestorMarkerOffset = ancestorMarkerOffset, ) { companion object { private val sharedMarkerPaint = TextPaint().apply { isAntiAlias = true } - } - - private val markerTypeface: Typeface = - TypefaceUtils.applyStyles( - context = context, - fontFamily = listStyle.fontFamily.takeIf { it.isNotEmpty() }, - fontWeight = listStyle.markerFontWeight, - ) - private fun configureMarkerPaint(): TextPaint = - sharedMarkerPaint.apply { - textSize = listStyle.fontSize - color = listStyle.markerColor - typeface = markerTypeface + /** + * How far the `99.` column every ordered list reserves must grow to fit each of [numbers]. + * Whole pixels, so the Int leading margins and the float marker positions agree at every depth. + */ + fun measureExtraWidth( + listStyle: ListStyle, + context: Context, + numbers: Iterable, + ): Float { + val paint = markerPaint(listStyle, markerTypeface(listStyle, context)) + val default = paint.measureText("99.") + val widest = numbers.fold(default) { width, number -> maxOf(width, paint.measureText("$number.")) } + return ceil(listStyle.effectiveMarkerWidth(widest) - listStyle.effectiveMarkerWidth(default)) } - override fun getMarkerWidth(): Float { - val paint = configureMarkerPaint() - return listStyle.effectiveMarkerWidth(paint.measureText("99.")) + private fun markerTypeface( + listStyle: ListStyle, + context: Context, + ): Typeface = + TypefaceUtils.applyStyles( + context = context, + fontFamily = listStyle.fontFamily.takeIf { it.isNotEmpty() }, + fontWeight = listStyle.markerFontWeight, + ) + + private fun markerPaint( + listStyle: ListStyle, + typeface: Typeface, + ): TextPaint = + sharedMarkerPaint.apply { + textSize = listStyle.fontSize + color = listStyle.markerColor + this.typeface = typeface + } } + private val markerTypeface = markerTypeface(listStyle, context) + private val defaultMarkerWidth = listStyle.effectiveMarkerWidth(markerPaint(listStyle, markerTypeface).measureText("99.")) + + override fun getMarkerWidth(): Float = defaultMarkerWidth + markerExtraWidth + var itemNumber: Int = 1 private set @@ -67,11 +92,11 @@ class OrderedListSpan( layout: Layout?, start: Int, ) { - val markerPaint = configureMarkerPaint() + val markerPaint = markerPaint(listStyle, markerTypeface) val text = if (dir < 0) ".$itemNumber" else "$itemNumber." val textWidth = markerPaint.measureText(text) - val markerRightEdge = x + (depth * marginLeft + getMarkerWidth()) * dir + val markerRightEdge = x + (depth * marginLeft + ancestorMarkerOffset + getMarkerWidth()) * dir val markerX = if (dir > 0) markerRightEdge - textWidth else markerRightEdge canvas.drawText(text, markerX, baseline.toFloat(), markerPaint) diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt index 2784850b3..0c269f96f 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt @@ -26,6 +26,8 @@ class TaskListSpan( * moves it to the end of that order and shifts where its marker lands. */ var isChecked: Boolean, + ancestorMarkerOffset: Float = 0f, + override val markerExtraWidth: Float = 0f, ) : BaseListSpan( depth = depth, context = context, @@ -39,6 +41,7 @@ class TaskListSpan( ), marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, + ancestorMarkerOffset = ancestorMarkerOffset, ) { companion object { private val boxPaint = @@ -58,7 +61,7 @@ class TaskListSpan( } private val checkboxSize = taskStyle.checkboxSize - private val markerColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize) + private val markerColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize) + markerExtraWidth private val cornerRadius = taskStyle.checkboxBorderRadius private val rect = RectF() private val insetRect = RectF() @@ -79,7 +82,7 @@ class TaskListSpan( ) { val capHeight = -markerFontMetrics.ascent * CAP_HEIGHT_RATIO val centerY = baseline - capHeight / HALF_DIVISOR - val centerX = x + (depth * marginLeft + markerColumnWidth - checkboxSize / HALF_DIVISOR) * dir + val centerX = x + (depth * marginLeft + ancestorMarkerOffset + markerColumnWidth - checkboxSize / HALF_DIVISOR) * dir val half = checkboxSize / HALF_DIVISOR rect.set(centerX - half, centerY - half, centerX + half, centerY + half) diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt index 2b3465aa5..a5df5b519 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt @@ -13,6 +13,7 @@ class UnorderedListSpan( depth: Int, context: Context, styleCache: SpanStyleCache, + ancestorMarkerOffset: Float = 0f, ) : BaseListSpan( depth = depth, context = context, @@ -26,6 +27,7 @@ class UnorderedListSpan( ), marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, + ancestorMarkerOffset = ancestorMarkerOffset, ) { companion object { private val sharedBulletPaint = @@ -63,7 +65,7 @@ class UnorderedListSpan( // it hugs the gap before the text — matches iOS behavior and stays // visually flush-left when the column width equals the bullet radius // (the default). - val bulletX = x + (depth * marginLeft + markerColumnWidth) * dir + val bulletX = x + (depth * marginLeft + ancestorMarkerOffset + markerColumnWidth) * dir val fontMetrics = paint.fontMetrics val bulletY = baseline + (fontMetrics.ascent + fontMetrics.descent) / 2f diff --git a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt new file mode 100644 index 000000000..09a7eadb6 --- /dev/null +++ b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt @@ -0,0 +1,230 @@ +package com.swmansion.enriched.markdown + +import android.graphics.Typeface +import android.text.SpannableString +import android.text.TextPaint +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.swmansion.enriched.markdown.parser.MarkdownASTNode +import com.swmansion.enriched.markdown.spans.BaseListSpan +import com.swmansion.enriched.markdown.spans.OrderedListSpan +import com.swmansion.enriched.markdown.styles.StyleConfig +import com.swmansion.enriched.markdown.test.MarkdownRenderTestSupport +import com.swmansion.enriched.markdown.test.MarkdownRenderTestSupport.render +import com.swmansion.enriched.markdown.test.MarkerCanvas +import com.swmansion.enriched.markdown.test.MarkerGeometry +import com.swmansion.enriched.markdown.test.TestAstFactory.document +import com.swmansion.enriched.markdown.test.TestAstFactory.listItem +import com.swmansion.enriched.markdown.test.TestAstFactory.orderedList +import com.swmansion.enriched.markdown.test.TestAstFactory.paragraph +import com.swmansion.enriched.markdown.test.TestAstFactory.taskListItem +import com.swmansion.enriched.markdown.test.TestAstFactory.text +import com.swmansion.enriched.markdown.test.TestAstFactory.unorderedList +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode +import kotlin.math.ceil + +@RunWith(AndroidJUnit4::class) +@Config(sdk = [28]) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class ListRenderingTest { + @Test + fun shortListsKeepTheirIndentAndLongListsShareTheirWidestGutter() { + val style = styleConfig() + val paint = + TextPaint().apply { + textSize = style.listStyle.fontSize + typeface = Typeface.create("monospace", Typeface.NORMAL) + } + val baseline = paint.measureText("99.") + val gap = style.listStyle.gapWidth + val short = orderedSpans(style, numbered(99)) + short.forEach { assertEquals((baseline + gap).toInt(), it.getLeadingMargin(false)) } + for (count in listOf(100, 101, 250, 1000)) { + val spans = orderedSpans(style, numbered(count)) + val widest = maxOf(baseline, spans.maxOf { paint.measureText("${it.itemNumber}.") }) + spans.forEach { assertEquals((baseline + ceil(widest - baseline) + gap).toInt(), it.getLeadingMargin(false)) } + assertTrue(spans.first().getLeadingMargin(false) > short.first().getLeadingMargin(false)) + } + } + + @Test + fun nestedAndFollowingListsRestoreTheirOwnGutters() { + val style = styleConfig() + val outer = withChild(numbered(101), 0, numbered(1000)) + val spans = orderedSpans(style, outer, numbered(1)) + val parent = spans.filter { it.depth == 0 }.dropLast(1) + assertEquals(101, parent.size) + parent.forEach { assertEquals(parent.first().getLeadingMargin(false), it.getLeadingMargin(false)) } + spans.filter { it.depth == 1 }.forEach { assertTrue(it.getLeadingMargin(false) > style.listStyle.marginLeft) } + val following = spans.last() + assertEquals(0, following.depth) + assertTrue(following.getLeadingMargin(false) < parent.first().getLeadingMargin(false)) + } + + @Test + fun markerMinimumWidthRemainsAFloor() { + val style = styleConfig(minWidth = 200f) + orderedSpans(style, numbered(101)).forEach { + assertEquals((style.listStyle.markerMinWidth + style.listStyle.gapWidth).toInt(), it.getLeadingMargin(false)) + } + } + + @Test + fun drawnMarkersStayInsideTheGutterAndAttachedToTheirParagraphs() { + val style = styleConfig() + for (count in listOf(4, 101, 1000)) { + val threeLevels = withChild(numbered(1), 0, numbered(1)) + drawMarkers(style, withChild(numbered(count), 2, threeLevels)).forEach { geometry -> + assertEquals( + "marker right at depth ${geometry.depth} in a list of $count", + geometry.paragraphLeft - style.listStyle.gapWidth, + geometry.marker.right, + 0.01f, + ) + } + } + } + + @Test + fun nestedBulletColumnsKeepTheirGapUnderWideParents() { + val style = styleConfig() + + fun tree(count: Int) = withChild(numbered(count), 2, unorderedList(item(), item())) + for (count in listOf(101, 1000)) { + assertNestedMarkerGapsUnchanged(style, tree(4), tree(count)) + } + } + + @Test + fun tasksMoveWithTheirWideNumberedSiblings() { + val style = styleConfig() + + fun tree(count: Int): MarkdownASTNode { + val items = numbered(count).children.toMutableList() + items[1] = taskListItem(checked = false, paragraph(text("task")), numbered(1)) + items[2] = listItem(paragraph(text("item")), numbered(1)) + return orderedList(*items.toTypedArray()) + } + assertEveryRowShiftsTogether(style, tree(4), tree(1000)) + } + + @Test + fun nestedTasksKeepTheirGapUnderWideNumericParents() { + val style = styleConfig() + + fun tree(count: Int) = withChild(numbered(count), 2, orderedList(taskListItem(checked = false, paragraph(text("task"))))) + for (count in listOf(101, 1000)) { + assertNestedMarkerGapsUnchanged(style, tree(4), tree(count)) + } + } + + @Test + fun inheritedMarkerOffsetsFollowTheRtlDirection() { + val style = styleConfig() + val text = SpannableString(render(document(withChild(numbered(1000), 0, numbered(1))), style)) + val layout = MarkerCanvas.layout(text, style.listStyle.fontSize, rtl = true) + val markers = MarkerCanvas.drawMarkers(layout) + assertEquals(1001, markers.size) + markers.forEach { marker -> + val line = layout.getLineForVertical(marker.baseline.toInt()) + assertEquals(-1, layout.getParagraphDirection(line)) + assertEquals(layout.getParagraphRight(line) + style.listStyle.gapWidth, marker.left, 0.01f) + assertTrue(marker.right <= layout.width) + } + } + + /** The rows [wide] shares with [short], tasks and their children included, all sit [wide]'s widening further right. */ + private fun assertEveryRowShiftsTogether( + style: StyleConfig, + short: MarkdownASTNode, + wide: MarkdownASTNode, + ) { + val shortRows = drawMarkers(style, short) + val wideRows = drawMarkers(style, wide).take(shortRows.size) + assertEquals(shortRows.size, wideRows.size) + val shift = wideRows.first().paragraphLeft - shortRows.first().paragraphLeft + assertTrue(shift > 0f) + wideRows.zip(shortRows).forEach { (actual, control) -> + assertEquals(control.depth, actual.depth) + assertEquals("text shift at depth ${actual.depth}", shift, actual.paragraphLeft - control.paragraphLeft, 0.01f) + assertEquals( + "marker gap at depth ${actual.depth}", + control.paragraphLeft - control.marker.right, + actual.paragraphLeft - actual.marker.right, + 0.01f, + ) + } + } + + private fun assertNestedMarkerGapsUnchanged( + style: StyleConfig, + short: MarkdownASTNode, + wide: MarkdownASTNode, + ) { + val shortMarkers = drawMarkers(style, short).filter { it.depth > 0 } + val wideMarkers = drawMarkers(style, wide).filter { it.depth > 0 } + assertTrue(shortMarkers.isNotEmpty()) + assertEquals(shortMarkers.size, wideMarkers.size) + shortMarkers.zip(wideMarkers).forEach { (control, actual) -> + assertEquals(control.depth, actual.depth) + assertEquals( + "nested marker gap at depth ${actual.depth}", + control.paragraphLeft - control.marker.right, + actual.paragraphLeft - actual.marker.right, + 0.01f, + ) + } + } + + private fun drawMarkers( + style: StyleConfig, + vararg lists: MarkdownASTNode, + ): List { + // SpannableString reports spans in insertion order, as the text view does. + val text = SpannableString(render(document(*lists), style)) + val geometry = MarkerCanvas.markerGeometry(text, MarkerCanvas.layout(text, style.listStyle.fontSize)) + assertEquals(text.getSpans(0, text.length, BaseListSpan::class.java).size, geometry.size) + geometry.forEach { assertTrue("marker left ${it.marker.left} at depth ${it.depth}", it.marker.left >= 0f) } + return geometry + } + + private fun orderedSpans( + style: StyleConfig, + vararg lists: MarkdownASTNode, + ): List { + val text = render(document(*lists), style) + return text + .getSpans(0, text.length, OrderedListSpan::class.java) + .sortedWith(compareBy({ text.getSpanStart(it) }, { it.depth })) + } + + private fun item(): MarkdownASTNode = listItem(paragraph(text("item"))) + + private fun numbered(count: Int): MarkdownASTNode = orderedList(*Array(count) { item() }) + + private fun withChild( + list: MarkdownASTNode, + index: Int, + child: MarkdownASTNode, + ): MarkdownASTNode { + val items = list.children.toMutableList() + items[index] = items[index].copy(children = items[index].children + child) + return list.copy(children = items) + } + + private fun styleConfig(minWidth: Float = 0f): StyleConfig { + val base = MarkdownRenderTestSupport.defaultStyle + return MarkdownRenderTestSupport.styleWithList( + base.listStyle.copy( + fontFamily = "monospace", + markerMinWidth = minWidth, + gapWidth = 8f, + marginLeft = 24f, + ), + ) + } +} diff --git a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt new file mode 100644 index 000000000..7383db048 --- /dev/null +++ b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt @@ -0,0 +1,101 @@ +package com.swmansion.enriched.markdown.test + +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import android.graphics.RectF +import android.text.Layout +import android.text.Spanned +import android.text.StaticLayout +import android.text.TextDirectionHeuristics +import android.text.TextPaint +import com.swmansion.enriched.markdown.spans.BaseListSpan + +/** A list marker as the layout drew it: a number, a bullet, or a checkbox. */ +data class DrawnMarker( + val left: Float, + val right: Float, + val baseline: Float, +) + +/** A drawn marker with the text edge and list depth of the paragraph it belongs to. */ +data class MarkerGeometry( + val marker: DrawnMarker, + val paragraphLeft: Float, + val depth: Int, +) + +/** Records the list markers a layout draws instead of painting them. */ +class MarkerCanvas : Canvas(Bitmap.createBitmap(LAYOUT_WIDTH, 1, Bitmap.Config.ARGB_8888)) { + val markers = mutableListOf() + + // Layout draws only the lines inside the clip; report one tall enough for every list. + override fun getClipBounds(bounds: Rect): Boolean { + bounds.set(0, 0, LAYOUT_WIDTH, Int.MAX_VALUE / 2) + return true + } + + override fun drawCircle( + cx: Float, + cy: Float, + radius: Float, + paint: Paint, + ) { + // Bullets are centered on the reserved column edge, matching the iOS drawer. + val outerRadius = radius + paint.strokeWidth / 2f + markers += DrawnMarker(cx - outerRadius, cx, cy) + super.drawCircle(cx, cy, radius, paint) + } + + override fun drawRoundRect( + rect: RectF, + rx: Float, + ry: Float, + paint: Paint, + ) { + val halfStroke = if (paint.style == Paint.Style.STROKE) paint.strokeWidth / 2f else 0f + markers += DrawnMarker(rect.left - halfStroke, rect.right + halfStroke, rect.centerY()) + super.drawRoundRect(rect, rx, ry, paint) + } + + override fun drawText( + text: String, + x: Float, + y: Float, + paint: Paint, + ) { + if (text.matches(Regex("(?:[0-9]+\\.|\\.[0-9]+)"))) markers += DrawnMarker(x, x + paint.measureText(text), y) + super.drawText(text, x, y, paint) + } + + companion object { + const val LAYOUT_WIDTH = 2000 + + fun layout( + text: CharSequence, + textSize: Float, + rtl: Boolean = false, + ): StaticLayout = + StaticLayout.Builder + .obtain(text, 0, text.length, TextPaint().apply { this.textSize = textSize }, LAYOUT_WIDTH) + .apply { if (rtl) setTextDirection(TextDirectionHeuristics.RTL) } + .build() + + /** The markers [layout] draws, top to bottom. */ + fun drawMarkers(layout: Layout): List = + MarkerCanvas().also(layout::draw).markers.sortedWith(compareBy({ it.baseline }, { it.left })) + + /** Every marker [layout] draws, with the text edge and depth of its paragraph. */ + fun markerGeometry( + text: Spanned, + layout: Layout, + ): List = + drawMarkers(layout).map { marker -> + val line = layout.getLineForVertical(marker.baseline.toInt()) + val start = layout.getLineStart(line) + val depth = text.getSpans(start, start + 1, BaseListSpan::class.java).maxOf { it.depth } + MarkerGeometry(marker, layout.getParagraphLeft(line).toFloat(), depth) + } + } +} diff --git a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt index 9a03ee04b..06a22103f 100644 --- a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt +++ b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt @@ -16,6 +16,7 @@ import com.swmansion.enriched.markdown.styles.CodeStyle import com.swmansion.enriched.markdown.styles.HeadingStyle import com.swmansion.enriched.markdown.styles.HighlightStyle import com.swmansion.enriched.markdown.styles.LinkStyle +import com.swmansion.enriched.markdown.styles.ListStyle import com.swmansion.enriched.markdown.styles.ParagraphStyle import com.swmansion.enriched.markdown.styles.SpoilerStyle import com.swmansion.enriched.markdown.styles.StrikethroughStyle @@ -101,6 +102,9 @@ object MarkdownRenderTestSupport { ) } + /** [defaultStyle] with only its [ListStyle] replaced. */ + fun styleWithList(listStyle: ListStyle): StyleConfig = copyOfDefault(listStyle = listStyle) + /** [defaultStyle] with only its [TaskListStyle] replaced. */ fun styleWithTaskList(taskListStyle: TaskListStyle): StyleConfig = copyOfDefault(taskListStyle = taskListStyle) @@ -111,6 +115,7 @@ object MarkdownRenderTestSupport { strikethroughStyle: StrikethroughStyle? = null, underlineStyle: UnderlineStyle? = null, highlightStyle: HighlightStyle? = null, + listStyle: ListStyle? = null, taskListStyle: TaskListStyle? = null, blockquoteStyle: BlockquoteStyle? = null, codeStyle: CodeStyle? = null, @@ -137,7 +142,7 @@ object MarkdownRenderTestSupport { imageStyle = base.imageStyle, inlineImageStyle = base.inlineImageStyle, blockquoteStyle = blockquoteStyle ?: base.blockquoteStyle, - listStyle = base.listStyle, + listStyle = listStyle ?: base.listStyle, taskListStyle = taskListStyle ?: base.taskListStyle, codeBlockStyle = codeBlockStyle ?: base.codeBlockStyle, thematicBreakStyle = base.thematicBreakStyle, diff --git a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/RenderContext.swift b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/RenderContext.swift index 52185914f..623bacd8f 100644 --- a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/RenderContext.swift +++ b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/RenderContext.swift @@ -43,6 +43,9 @@ enum MarkdownAttribute { /// Leading inset of a quote's bars and fill, set on quote paragraphs /// that sit inside a list item (the item's text column). static let blockquoteBarOffset = NSAttributedString.Key("EnrichedMarkdownBlockquoteBarOffset") + /// Marker widening already applied to a quote paragraph by the list items + /// it sits in, so an enclosing item's bar offset keeps it. + static let blockquoteMarkerExtra = NSAttributedString.Key("EnrichedMarkdownBlockquoteMarkerExtra") /// Present on blockquote paragraphs inside a GitHub admonition: the bar /// color of each nesting level, outermost first. static let blockquoteBarColors = NSAttributedString.Key("EnrichedMarkdownBlockquoteBarColors") @@ -76,6 +79,12 @@ package final class RenderContext { var listDepth = 0 var listType: ListType = .unordered var listItemNumber = 0 + /// Marker column of the current ordered list, sized to its widest number. + var listMarkerWidth: CGFloat = 0 + /// Extra marker width of the enclosing list items, carried into nested lists. + var ancestorMarkerOffset: CGFloat = 0 + /// Extra marker width of the list item whose children are rendering. + var listItemMarkerExtra: CGFloat = 0 var taskItemIndex = 0 var rendersBlockImage = false /// Set once a superscript or subscript run is rendered, so the post-pass diff --git a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/BlockquoteRenderer.swift b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/BlockquoteRenderer.swift index 27966a2c9..ce9fbc986 100644 --- a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/BlockquoteRenderer.swift +++ b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/BlockquoteRenderer.swift @@ -27,11 +27,22 @@ final class BlockquoteRenderer: NodeRenderer { if let admonition { appendHeader(for: admonition, font: font, to: output) } + // An enclosing list item shifts the whole quote by its own indent, which + // already includes any widened marker column, so lists inside start fresh. + let prevMarkerOffset = context.ancestorMarkerOffset + let prevItemMarkerExtra = context.listItemMarkerExtra + context.ancestorMarkerOffset = 0 + context.listItemMarkerExtra = 0 factory.renderChildren(of: node, into: output, context: context) + context.ancestorMarkerOffset = prevMarkerOffset + context.listItemMarkerExtra = prevItemMarkerExtra context.clearBlockStyle() context.exitBlockquote() guard output.length > start else { return } + // Bars share one offset per paragraph, so widening from lists inside this + // quote must not move this quote's own bar when an outer item shifts it. + output.removeAttribute(MarkdownAttribute.blockquoteMarkerExtra, range: NSRange(location: start, length: output.length - start)) applyStylingAndSpacing(to: output, start: start, end: output.length, levels: levels) } diff --git a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/ListItemRenderer.swift b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/ListItemRenderer.swift index c779225fc..cf1590cf5 100644 --- a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/ListItemRenderer.swift +++ b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/ListItemRenderer.swift @@ -22,20 +22,27 @@ final class ListItemRenderer: NodeRenderer { context.taskItemIndex += 1 } + let baseMarkerWidth = isTask + ? effectiveTaskMarkerWidth(in: context) + : effectiveMarkerWidth(in: context) + // How far a widened ordered list grew this item's own column; nested lists move by it. + let markerExtra = baseMarkerWidth - defaultColumnWidth(isTask: isTask, listType: context.listType) + let startLocation = output.length + let prevMarkerExtra = context.listItemMarkerExtra + context.listItemMarkerExtra = markerExtra factory.renderChildren(of: node, into: output, context: context) + context.listItemMarkerExtra = prevMarkerExtra ParagraphStyleHelpers.ensureTrailingNewline(in: output) let itemRange = NSRange(location: startLocation, length: output.length - startLocation) guard itemRange.length > 0 else { return } - let baseMarkerWidth = isTask - ? effectiveTaskMarkerWidth(for: context.listType) - : effectiveMarkerWidth(for: context.listType) let gapWidth = max(config.list.gapWidth ?? 12, 4) let marginLeading = config.list.marginLeading ?? 24 let blockquoteIndent = CGFloat(context.blockquoteDepth) * blockquoteLevelSpacing() let totalIndent = blockquoteIndent + baseMarkerWidth + gapWidth + (CGFloat(nestingLevel) * marginLeading) + + context.ancestorMarkerOffset let lineHeight = config.list.lineHeight ?? 0 let metadata: [NSAttributedString.Key: Any] = [ @@ -49,7 +56,11 @@ final class ListItemRenderer: NodeRenderer { itemRange: itemRange, nestingLevel: nestingLevel, metadata: metadata, - totalIndent: totalIndent, + indents: ItemIndents( + text: totalIndent, + quote: totalIndent - context.ancestorMarkerOffset, + markerExtra: markerExtra + ), lineHeight: lineHeight ) @@ -64,20 +75,23 @@ final class ListItemRenderer: NodeRenderer { } } - private func effectiveMarkerWidth(for listType: ListType) -> CGFloat { - let minWidth = config.list.markerMinWidth ?? 0 - switch listType { - case .ordered: - return max(minWidth, 20) - case .unordered: - return max(minWidth, config.list.bulletSize ?? 6) - } + /// An ordered list's column is sized to its widest number by `ListRenderer`. + private func effectiveMarkerWidth(in context: RenderContext) -> CGFloat { + context.listType == .ordered + ? context.listMarkerWidth + : config.list.defaultMarkerColumnWidth(for: .unordered) + } + + /// The item's column before an ordered list widens it for its numbers. + private func defaultColumnWidth(isTask: Bool, listType: ListType) -> CGFloat { + let markerWidth = config.list.defaultMarkerColumnWidth(for: listType) + return isTask ? max(markerWidth, config.taskList.checkboxSize ?? 14) : markerWidth } - /// The checkbox column is at least as wide as the list type's normal - /// marker column, so task items align with their non-task siblings. - private func effectiveTaskMarkerWidth(for listType: ListType) -> CGFloat { - max(effectiveMarkerWidth(for: listType), config.taskList.checkboxSize ?? 14) + /// The checkbox column is at least as wide as the list's marker column, + /// so task items align with their non-task siblings. + private func effectiveTaskMarkerWidth(in context: RenderContext) -> CGFloat { + max(effectiveMarkerWidth(in: context), config.taskList.checkboxSize ?? 14) } private func blockquoteLevelSpacing() -> CGFloat { @@ -139,7 +153,7 @@ final class ListItemRenderer: NodeRenderer { itemRange: NSRange, nestingLevel: Int, metadata: [NSAttributedString.Key: Any], - totalIndent: CGFloat, + indents: ItemIndents, lineHeight: CGFloat ) { let string = output.string as NSString @@ -153,7 +167,7 @@ final class ListItemRenderer: NodeRenderer { location = NSMaxRange(applyRange) if output.attribute(MarkdownAttribute.blockquoteDepth, at: applyRange.location, effectiveRange: nil) != nil { - shiftQuoteParagraph(in: output, range: applyRange, by: totalIndent) + shiftQuoteParagraph(in: output, range: applyRange, indents: indents) continue } if shouldSkipListStyling(in: output, range: applyRange, nestingLevel: nestingLevel) { @@ -161,8 +175,8 @@ final class ListItemRenderer: NodeRenderer { } let style = NSMutableParagraphStyle() - style.firstLineHeadIndent = totalIndent - style.headIndent = totalIndent + style.firstLineHeadIndent = indents.text + style.headIndent = indents.text if lineHeight > 0 { style.minimumLineHeight = lineHeight @@ -180,13 +194,20 @@ final class ListItemRenderer: NodeRenderer { } /// A quote inside the item keeps its own attributes and indent, moved - /// into the item's text column together with its bars. - private func shiftQuoteParagraph(in output: NSMutableAttributedString, range: NSRange, by offset: CGFloat) { + /// into the item's text column together with its bars. The bars also keep + /// the marker widening of any list item between this one and the quote. + private func shiftQuoteParagraph(in output: NSMutableAttributedString, range: NSRange, indents: ItemIndents) { + let innerExtra = output.attribute(MarkdownAttribute.blockquoteMarkerExtra, at: range.location, effectiveRange: nil) + as? CGFloat ?? 0 let style = ParagraphStyleHelpers.getOrCreateParagraphStyle(in: output, at: range.location) - style.firstLineHeadIndent += offset - style.headIndent += offset + style.firstLineHeadIndent += indents.quote + style.headIndent += indents.quote output.addAttributes( - [.paragraphStyle: style, MarkdownAttribute.blockquoteBarOffset: offset], + [ + .paragraphStyle: style, + MarkdownAttribute.blockquoteBarOffset: indents.quote + innerExtra, + MarkdownAttribute.blockquoteMarkerExtra: innerExtra + indents.markerExtra + ], range: range ) } @@ -216,3 +237,25 @@ final class ListItemRenderer: NodeRenderer { ).location == NSNotFound } } + +/// Where a list item moves its own paragraphs and the quotes inside it. +private struct ItemIndents { + let text: CGFloat + /// Each enclosing item shifts a quote too, adding its own widened column then. + let quote: CGFloat + /// How far a widened ordered list grew this item's marker column. + let markerExtra: CGFloat +} + +extension ListStyle { + /// The marker column before an ordered list widens it for its numbers. + func defaultMarkerColumnWidth(for listType: ListType) -> CGFloat { + let minWidth = markerMinWidth ?? 0 + switch listType { + case .ordered: + return max(minWidth, 20) + case .unordered: + return max(minWidth, bulletSize ?? 6) + } + } +} diff --git a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/ListRenderer.swift b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/ListRenderer.swift index d5c1149be..1263cc193 100644 --- a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/ListRenderer.swift +++ b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Rendering/Renderers/ListRenderer.swift @@ -15,6 +15,8 @@ final class ListRenderer: NodeRenderer { let prevDepth = context.listDepth let prevType = context.listType let prevNumber = context.listItemNumber + let prevMarkerWidth = context.listMarkerWidth + let prevMarkerOffset = context.ancestorMarkerOffset let startLocation = output.length if prevDepth == 0 { @@ -31,6 +33,12 @@ final class ListRenderer: NodeRenderer { context.listDepth = prevDepth + 1 context.listType = isOrdered ? .ordered : .unordered context.listItemNumber = 0 + if prevDepth > 0 { + context.ancestorMarkerOffset += context.listItemMarkerExtra + } + context.listMarkerWidth = isOrdered + ? widestMarkerWidth(of: node, atLeast: config.list.defaultMarkerColumnWidth(for: .ordered)) + : 0 let font = config.list.font ?? UIFont.preferredFont(forTextStyle: .body) let color = config.list.foregroundColor ?? UIColor.label @@ -45,6 +53,8 @@ final class ListRenderer: NodeRenderer { context.listDepth = prevDepth context.listType = prevType context.listItemNumber = prevNumber + context.listMarkerWidth = prevMarkerWidth + context.ancestorMarkerOffset = prevMarkerOffset if prevDepth == 0 { context.clearBlockStyle() @@ -53,4 +63,21 @@ final class ListRenderer: NodeRenderer { } } } + + /// Widens the marker column to the list's widest number, so markers are + /// never drawn past the column's leading edge. Task items draw a checkbox + /// instead of a number and do not count. + private func widestMarkerWidth(of node: MarkdownASTNode, atLeast minimumWidth: CGFloat) -> CGFloat { + let attributes: [NSAttributedString.Key: Any] = [ + .font: config.list.font ?? BlockDecorationConfig.defaultListMarkerFont + ] + var width = minimumWidth + var number = 0 + for item in node.children where item.type == .listItem { + number += 1 + guard item.attribute("isTask") != "true" else { continue } + width = max(width, ("\(number)." as NSString).size(withAttributes: attributes).width) + } + return width + } } diff --git a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Views/Layout/BlockDecorationConfig.swift b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Views/Layout/BlockDecorationConfig.swift index 7b587e8c8..34696c8e1 100644 --- a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Views/Layout/BlockDecorationConfig.swift +++ b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Views/Layout/BlockDecorationConfig.swift @@ -18,7 +18,9 @@ struct BlockDecorationConfig { var listBulletSize: CGFloat = 6 var listBulletColor: UIColor = UIColor(red: 0.42, green: 0.45, blue: 0.50, alpha: 1) var listMarkerColor: UIColor = UIColor(red: 0.42, green: 0.45, blue: 0.50, alpha: 1) - var listMarkerFont: UIFont = .systemFont(ofSize: 16, weight: .medium) + static let defaultListMarkerFont: UIFont = .systemFont(ofSize: 16, weight: .medium) + + var listMarkerFont: UIFont = defaultListMarkerFont var taskCheckboxSize: CGFloat = 14 var taskCheckboxBorderRadius: CGFloat = 3 diff --git a/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/ListRenderingTests.swift b/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/ListRenderingTests.swift new file mode 100644 index 000000000..fdc7b11c2 --- /dev/null +++ b/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/ListRenderingTests.swift @@ -0,0 +1,198 @@ +import UIKit +import XCTest +@testable import EnrichedMarkdown + +final class ListRenderingTests: XCTestCase { + private var config: MarkdownStyleConfiguration! + + override func setUp() { + super.setUp() + config = MarkdownStyleConfiguration.baseline() + } + + func testShortListsKeepTheirMarkerColumn() { + let result = MarkdownRenderer.render(numbered(9), config: config) + + // Default theme: 20pt ordered marker column + 12pt gap. + XCTAssertEqual(headIndent(in: result, at: "i1x"), 32) + XCTAssertEqual(headIndent(in: result, at: "i9x"), 32) + } + + func testListsWidenTheirColumnToTheirWidestNumber() { + for count in [12, 99, 101, 1000] { + let result = MarkdownRenderer.render(numbered(count), config: config) + let widest = (1...count).map { markerWidth("\($0).") }.max() ?? 0 + XCTAssertGreaterThan(widest, 20, "list of \(count)") + + for item in ["i1x", "i\(count)x"] { + XCTAssertEqual(headIndent(in: result, at: item), widest + 12, accuracy: 0.001, "\(item) of \(count)") + } + } + } + + func testMarkerMinWidthRemainsAFloor() { + config.list.markerMinWidth = 200 + let result = MarkdownRenderer.render(numbered(1000), config: config) + + XCTAssertEqual(headIndent(in: result, at: "i1x"), 212) + XCTAssertEqual(headIndent(in: result, at: "i1000x"), 212) + } + + func testFollowingListsRestoreTheirOwnColumn() { + let result = MarkdownRenderer.render(numbered(101) + "\nbreak\n\n" + numbered(3, prefix: "f"), config: config) + + XCTAssertGreaterThan(headIndent(in: result, at: "i101x"), 32) + XCTAssertEqual(headIndent(in: result, at: "f1x"), 32) + } + + func testNestedListsKeepTheirPlaceUnderWideParents() { + for nested in ["- nestedx", "1. nestedx", "- [ ] nestedx"] { + let short = nestedOffset(in: numbered(4, nesting: nested, under: 3), parent: "i3x") + for count in [101, 1000] { + let wide = nestedOffset(in: numbered(count, nesting: nested, under: 3), parent: "i3x") + XCTAssertEqual(wide, short, accuracy: 0.001, "\(nested) under a list of \(count)") + } + } + } + + func testListsInsideAQuoteUnderAWideParentShiftOnce() { + func offset(_ count: Int) -> CGFloat { + let source = numbered(count, nesting: "> quotex\n>\n> - nestedx", under: 3) + let result = MarkdownRenderer.render(source, config: config) + return headIndent(in: result, at: "nestedx") - headIndent(in: result, at: "quotex") + } + + for count in [101, 1000] { + XCTAssertEqual(offset(count), offset(4), accuracy: 0.001, "list of \(count)") + } + } + + func testQuotesUnderSeveralListLevelsShiftOnce() { + func offsets(_ count: Int) -> (text: CGFloat, bar: CGFloat) { + let source = numbered(count, nesting: "- childx\n > quotex", under: 3) + let result = MarkdownRenderer.render(source, config: config) + let quote = (result.string as NSString).range(of: "quotex").location + let bar = result.attribute(MarkdownAttribute.blockquoteBarOffset, at: quote, effectiveRange: nil) + let barOffset = bar as? CGFloat ?? -1 + return (headIndent(in: result, at: "quotex") - headIndent(in: result, at: "childx"), + headIndent(in: result, at: "quotex") - barOffset) + } + + let short = offsets(4) + for count in [101, 1000] { + let wide = offsets(count) + XCTAssertEqual(wide.text, short.text, accuracy: 0.001, "quote under a list of \(count)") + XCTAssertEqual(wide.bar, short.bar, accuracy: 0.001, "quote bar under a list of \(count)") + } + } + + func testQuoteBarsKeepTheWideningOfAnInnerList() { + func offsets(_ count: Int) -> (text: CGFloat, bar: CGFloat) { + let inner = numbered(count, prefix: "n", nesting: "> quotex", under: 3) + let result = MarkdownRenderer.render(numbered(4, nesting: inner, under: 2), config: config) + let quote = (result.string as NSString).range(of: "quotex").location + let bar = result.attribute(MarkdownAttribute.blockquoteBarOffset, at: quote, effectiveRange: nil) + let barOffset = bar as? CGFloat ?? -1 + return (headIndent(in: result, at: "quotex") - headIndent(in: result, at: "n3x"), + headIndent(in: result, at: "quotex") - barOffset) + } + + let short = offsets(4) + for count in [101, 1000] { + let wide = offsets(count) + XCTAssertEqual(wide.text, short.text, accuracy: 0.001, "quote in a nested list of \(count)") + XCTAssertEqual(wide.bar, short.bar, accuracy: 0.001, "quote bar in a nested list of \(count)") + } + } + + func testWideListsInsideAQuoteKeepTheQuoteBarInPlace() { + func barOffset(_ result: NSAttributedString, at text: String) -> CGFloat { + let location = (result.string as NSString).range(of: text).location + return result.attribute(MarkdownAttribute.blockquoteBarOffset, at: location, effectiveRange: nil) as? CGFloat ?? -1 + } + + for count in [4, 101, 1000] { + let inner = numbered(count, prefix: "n", nesting: "> innerx", under: 3) + let quote = "> beforex\n>\n" + inner.split(separator: "\n").map { "> " + $0 }.joined(separator: "\n") + + "\n>\n> afterx" + let result = MarkdownRenderer.render(numbered(4, nesting: quote, under: 1), config: config) + XCTAssertEqual(barOffset(result, at: "innerx"), barOffset(result, at: "beforex"), "list of \(count)") + XCTAssertEqual(barOffset(result, at: "afterx"), barOffset(result, at: "beforex"), "list of \(count)") + } + } + + func testTaskChildrenMoveOnlyAsFarAsTheirCheckboxColumn() { + for checkboxSize: CGFloat in [22, 100] { + config.taskList.checkboxSize = checkboxSize + func offset(_ count: Int) -> CGFloat { + var lines = (1...count).map { "\($0). i\($0)x" } + lines[1] = "2. [ ] taskx\n - childx" + let result = MarkdownRenderer.render(lines.joined(separator: "\n"), config: config) + return headIndent(in: result, at: "childx") - headIndent(in: result, at: "taskx") + } + + for count in [101, 1000] { + XCTAssertEqual(offset(count), offset(4), accuracy: 0.001, "checkbox \(checkboxSize), list of \(count)") + } + } + } + + func testNestedWideListsWidenOnlyThemselves() { + let source = numbered(3, nesting: numbered(101, prefix: "n"), under: 2) + let result = MarkdownRenderer.render(source, config: config) + let nestedWidest = (1...101).map { markerWidth("\($0).") }.max() ?? 0 + + XCTAssertEqual(headIndent(in: result, at: "i1x"), 32) + XCTAssertEqual(headIndent(in: result, at: "n101x"), 32 + 24 - 20 + nestedWidest, accuracy: 0.001) + } + + func testTaskItemsAlignWithWideNumberedSiblings() { + let source = (1...101).map { $0 == 2 ? "2. [ ] taskx" : "\($0). i\($0)x" }.joined(separator: "\n") + let result = MarkdownRenderer.render(source, config: config) + + XCTAssertEqual(headIndent(in: result, at: "taskx"), headIndent(in: result, at: "i1x")) + } + + func testTaskItemChildrenFollowTheirWideNumberedSiblings() { + var lines = (1...101).map { "\($0). i\($0)x" } + lines[1] = "2. [ ] taskx\n - undertaskx" + lines[2] = "3. i3x\n - undernumberx" + let result = MarkdownRenderer.render(lines.joined(separator: "\n"), config: config) + + XCTAssertEqual( + headIndent(in: result, at: "undertaskx") - headIndent(in: result, at: "taskx"), + headIndent(in: result, at: "undernumberx") - headIndent(in: result, at: "i3x"), + accuracy: 0.001 + ) + } + + private func nestedOffset(in source: String, parent: String) -> CGFloat { + let result = MarkdownRenderer.render(source, config: config) + return headIndent(in: result, at: "nestedx") - headIndent(in: result, at: parent) + } + + /// An ordered list of `count` items `x`, with `nesting` under item `under`. + private func numbered(_ count: Int, prefix: String = "i", nesting: String? = nil, under: Int = 0) -> String { + (1...count).map { number in + var item = "\(number). \(prefix)\(number)x" + if let nesting, number == under { + let indent = String(repeating: " ", count: "\(number). ".count) + item += "\n" + nesting.split(separator: "\n").map { indent + $0 }.joined(separator: "\n") + } + return item + }.joined(separator: "\n") + "\n" + } + + private func markerWidth(_ marker: String) -> CGFloat { + let font = config.list.font ?? BlockDecorationConfig.defaultListMarkerFont + return (marker as NSString).size(withAttributes: [.font: font]).width + } + + private func headIndent(in result: NSAttributedString, at substring: String) -> CGFloat { + let range = (result.string as NSString).range(of: substring) + XCTAssertNotEqual(range.location, NSNotFound, substring) + guard range.location != NSNotFound else { return -1 } + let style = result.attribute(.paragraphStyle, at: range.location, effectiveRange: nil) as? NSParagraphStyle + return style?.headIndent ?? -1 + } +} diff --git a/packages/react-native-enriched-markdown/__tests__/ios/ListRenderingTests.mm b/packages/react-native-enriched-markdown/__tests__/ios/ListRenderingTests.mm new file mode 100644 index 000000000..4209fdc80 --- /dev/null +++ b/packages/react-native-enriched-markdown/__tests__/ios/ListRenderingTests.mm @@ -0,0 +1,177 @@ +#import "../../ios/parser/ENRMMarkdownParser.h" +#import "../../ios/parser/MarkdownASTNode.h" +#import "../../ios/renderer/AttributedRenderer.h" +#import "../../ios/renderer/ListItemRenderer.h" +#import "../../ios/renderer/RenderContext.h" +#import "../../ios/styles/StyleConfig.h" +#import + +static MarkdownASTNode *ENRMOrderedList(NSInteger start, NSUInteger count) +{ + MarkdownASTNode *list = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeOrderedList]; + list.attributes[@"start"] = [@(start) stringValue]; + for (NSUInteger i = 0; i < count; i++) { + MarkdownASTNode *item = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeListItem]; + MarkdownASTNode *paragraph = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeParagraph]; + MarkdownASTNode *text = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeText]; + text.content = @"item"; + [paragraph addChild:text]; + [item addChild:paragraph]; + [list addChild:item]; + } + return list; +} + +@interface ENRMListRenderingTests : XCTestCase +@end + +@implementation ENRMListRenderingTests + +- (NSArray *)markersForLists:(NSArray *)lists + config:(StyleConfig *)config +{ + AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:config]; + NSAttributedString *text = [renderer renderNodes:lists context:[[RenderContext alloc] init] block:nil]; + NSMutableArray *markers = [NSMutableArray array]; + [text enumerateAttribute:ListItemMarkerStartAttribute + inRange:NSMakeRange(0, text.length) + options:0 + usingBlock:^(NSArray *value, NSRange range, BOOL *stop) { + if (value) + [markers addObjectsFromArray:value]; + }]; + return markers; +} + +- (void)testShortListKeepsItsIndentAndLongListsShareTheWidestGutter +{ + StyleConfig *config = [[StyleConfig alloc] init]; + [config setListStyleFontSize:16]; + [config setListStyleMarginLeft:24]; + [config setListStyleGapWidth:11]; + CGFloat baseline = [@"99." sizeWithAttributes:@{NSFontAttributeName : config.listMarkerFont}].width; + CGFloat shortIndent = MAX(config.listStyleMarkerMinWidth, baseline) + config.effectiveListGapWidth; + NSArray *shortMarkers = [self markersForLists:@[ ENRMOrderedList(1, 99) ] config:config]; + for (ENRMListMarkerDescriptor *marker in shortMarkers) { + XCTAssertEqualWithAccuracy(marker.indent, shortIndent, 0.01); + } + for (NSNumber *start in @[ @98, @998, @12345 ]) { + NSArray *markers = [self markersForLists:@[ ENRMOrderedList(start.integerValue, 4) ] config:config]; + CGFloat width = baseline; + for (ENRMListMarkerDescriptor *marker in markers) { + NSString *label = [NSString stringWithFormat:@"%ld.", (long)marker.number]; + width = MAX(width, [label sizeWithAttributes:@{NSFontAttributeName : config.listMarkerFont}].width); + } + for (ENRMListMarkerDescriptor *marker in markers) { + XCTAssertEqualWithAccuracy(marker.indent, width + config.effectiveListGapWidth, 0.01); + } + } +} + +- (void)testNestedAndFollowingListsRestoreTheirOwnGutters +{ + StyleConfig *config = [[StyleConfig alloc] init]; + [config setListStyleFontSize:16]; + [config setListStyleMarginLeft:24]; + [config setListStyleGapWidth:11]; + MarkdownASTNode *outer = ENRMOrderedList(98, 4); + [outer.children[0] addChild:ENRMOrderedList(9998, 4)]; + NSArray *markers = [self markersForLists:@[ outer, ENRMOrderedList(1, 1) ] config:config]; + CGFloat outerIndent = 0; + CGFloat nestedIndent = 0; + for (ENRMListMarkerDescriptor *marker in markers) { + if (marker.depth == 1) { + nestedIndent = marker.indent; + } else if (marker.number != 1) { + if (outerIndent == 0) + outerIndent = marker.indent; + XCTAssertEqualWithAccuracy(marker.indent, outerIndent, 0.01); + } + } + XCTAssertGreaterThan(nestedIndent, outerIndent + config.listStyleMarginLeft); + ENRMListMarkerDescriptor *last = markers.lastObject; + XCTAssertLessThan(last.indent, outerIndent); +} + +- (void)testNestedListsKeepTheSpaceReservedForWideParentMarkers +{ + StyleConfig *config = [[StyleConfig alloc] init]; + [config setListStyleFontSize:16]; + [config setListStyleMarginLeft:24]; + [config setListStyleGapWidth:11]; + MarkdownASTNode *outer = ENRMOrderedList(123456789, 1); + MarkdownASTNode *middle = ENRMOrderedList(1, 1); + [middle.children[0] addChild:ENRMOrderedList(1, 1)]; + [outer.children[0] addChild:middle]; + NSArray *markers = [self markersForLists:@[ outer ] config:config]; + ENRMListMarkerDescriptor *parent = markers[0]; + ENRMListMarkerDescriptor *child = markers[1]; + ENRMListMarkerDescriptor *leaf = markers[2]; + XCTAssertEqual(parent.depth, 0); + XCTAssertEqual(child.depth, 1); + XCTAssertEqual(leaf.depth, 2); + XCTAssertEqualWithAccuracy(child.indent, parent.indent + config.listStyleMarginLeft, 0.01); + XCTAssertEqualWithAccuracy(leaf.indent, parent.indent + 2 * config.listStyleMarginLeft, 0.01); +} + +- (void)testTaskItemsMoveWithTheirWideNumberedSiblings +{ + StyleConfig *config = [[StyleConfig alloc] init]; + [config setListStyleFontSize:16]; + [config setListStyleMarginLeft:24]; + [config setListStyleGapWidth:11]; + NSMutableArray *> *results = [NSMutableArray array]; + for (NSNumber *start in @[ @1, @12345 ]) { + MarkdownASTNode *outer = ENRMOrderedList(start.integerValue, 3); + MarkdownASTNode *task = outer.children[1]; + task.attributes[@"isTask"] = @"true"; + MarkdownASTNode *child = ENRMOrderedList(1, 1); + child.type = MarkdownNodeTypeUnorderedList; + [task addChild:child]; + [outer.children[2] addChild:ENRMOrderedList(1, 1)]; + [results addObject:[self markersForLists:@[ outer ] config:config]]; + } + NSArray *shortMarkers = results[0]; + NSArray *wideMarkers = results[1]; + XCTAssertEqual(shortMarkers.count, 5u); + XCTAssertEqual(wideMarkers.count, 5u); + ENRMListMarkerDescriptor *task = wideMarkers[1]; + ENRMListMarkerDescriptor *child = wideMarkers[2]; + XCTAssertTrue(task.isTask); + XCTAssertEqual(child.depth, 1); + XCTAssertEqual(child.listType, ListTypeUnordered); + CGFloat shift = [wideMarkers[0] indent] - [shortMarkers[0] indent]; + XCTAssertGreaterThan(shift, 0); + XCTAssertEqualWithAccuracy(task.indent, [shortMarkers[1] indent] + shift, 0.01); + XCTAssertEqualWithAccuracy(child.indent, [shortMarkers[2] indent] + shift, 0.01); + ENRMListMarkerDescriptor *numericChild = wideMarkers[4]; + ENRMListMarkerDescriptor *numericParent = wideMarkers[3]; + XCTAssertEqualWithAccuracy(numericChild.indent, numericParent.indent + config.listStyleMarginLeft, 0.01); +} + +- (void)testSourceNumbersAfterTheStartDoNotOverrideRenderedNumbers +{ + ENRMMarkdownParser *parser = [[ENRMMarkdownParser alloc] init]; + MarkdownASTNode *document = [parser parseMarkdown:@"98. a\n400. b\n1. c\n2. d"]; + StyleConfig *config = [[StyleConfig alloc] init]; + [config setListStyleFontSize:16]; + [config setListStyleMarginLeft:24]; + [config setListStyleGapWidth:11]; + NSArray *markers = [self markersForLists:document.children config:config]; + XCTAssertEqual(markers.count, 4u); + for (NSUInteger i = 0; i < markers.count; i++) { + ENRMListMarkerDescriptor *marker = markers[i]; + XCTAssertEqual(marker.number, 98 + (NSInteger)i); + } +} + +- (void)testMarkerMinimumWidthRemainsAFloor +{ + StyleConfig *config = [[StyleConfig alloc] init]; + [config setListStyleMarkerMinWidth:200]; + NSArray *markers = [self markersForLists:@[ ENRMOrderedList(998, 4) ] config:config]; + for (ENRMListMarkerDescriptor *marker in markers) { + XCTAssertEqualWithAccuracy(marker.indent, 200 + config.effectiveListGapWidth, 0.01); + } +} +@end diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt index 0286a8558..1ca6f3dd4 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt @@ -41,6 +41,9 @@ class BlockStyleContext { var listDepth = 0 var listType: ListType? = null var listItemNumber = 0 + var listMarkerExtra = 0f + var ancestorMarkerOffset = 0f + var listItemMarkerExtra = 0f var taskItemCount = 0 var accumulatedIndent = 0 @@ -151,6 +154,9 @@ class BlockStyleContext { listDepth = 0 listType = null listItemNumber = 0 + listMarkerExtra = 0f + ancestorMarkerOffset = 0f + listItemMarkerExtra = 0f taskItemCount = 0 accumulatedIndent = 0 listItemStarts.clear() diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt index cb3d2aa54..548dbda85 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt @@ -12,6 +12,8 @@ import com.swmansion.enriched.markdown.styles.ListStyle * allowing each level to maintain its own counter while preserving parent's position. * - **Parent context restoration**: Restores parent list's style when exiting nested lists * so subsequent parent items render correctly. + * - **Marker column**: An ordered list widens its `99.` column to fit its widest marker, and a + * nested list inherits the widening of the item it sits in. */ class ListContextManager( private val context: BlockStyleContext, @@ -24,6 +26,8 @@ class ListContextManager( val previousDepth: Int, val parentListType: BlockStyleContext.ListType?, val wasNestedInOrderedList: Boolean, + val previousMarkerExtra: Float, + val previousMarkerOffset: Float, ) /** @@ -32,11 +36,13 @@ class ListContextManager( * - Incrementing list depth * - Setting the appropriate list style * - Resetting item number for the new list + * - Widening the marker column by [markerExtraWidth] and shifting a nested list by its parent item's widening */ fun enterList( listType: BlockStyleContext.ListType, style: ListStyle, startNumber: Int = 1, + markerExtraWidth: Float = 0f, ): ListEntryState { val previousDepth = context.listDepth val isNested = previousDepth > 0 @@ -61,10 +67,19 @@ class ListContextManager( } context.resetListItemNumber(startNumber) + val previousMarkerExtra = context.listMarkerExtra + val previousMarkerOffset = context.ancestorMarkerOffset + if (isNested) { + context.ancestorMarkerOffset += context.listItemMarkerExtra + } + context.listMarkerExtra = markerExtraWidth + return ListEntryState( previousDepth = previousDepth, parentListType = parentListType, wasNestedInOrderedList = isNested && parentIsOrdered, + previousMarkerExtra = previousMarkerExtra, + previousMarkerOffset = previousMarkerOffset, ) } @@ -74,6 +89,7 @@ class ListContextManager( * - Decrementing list depth back to previousDepth * - Restoring parent list item numbers from stack (if applicable) * - Restoring parent list metadata (if nested) so subsequent parent items render correctly + * - Restoring the parent list's marker column and offset */ fun exitList(entryState: ListEntryState) { context.listDepth = entryState.previousDepth @@ -86,5 +102,8 @@ class ListContextManager( if (entryState.previousDepth > 0) { context.listType = entryState.parentListType } + + context.listMarkerExtra = entryState.previousMarkerExtra + context.ancestorMarkerOffset = entryState.previousMarkerOffset } } diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt index b849f7863..f79309fad 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt @@ -50,15 +50,32 @@ class ListItemRenderer( taskIndex = taskIndex, isChecked = isChecked, drawsMarker = drawsMarker, + ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + markerExtraWidth = styleContext.listMarkerExtra, ) } else { when (listType) { BlockStyleContext.ListType.UNORDERED -> { - UnorderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker) + UnorderedListSpan( + listStyle, + depth, + factory.context, + factory.styleCache, + drawsMarker, + ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + ) } BlockStyleContext.ListType.ORDERED -> { - OrderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker).apply { + OrderedListSpan( + listStyle, + depth, + factory.context, + factory.styleCache, + drawsMarker, + markerExtraWidth = styleContext.listMarkerExtra, + ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + ).apply { setItemNumber(styleContext.listItemNumber) } } @@ -67,12 +84,15 @@ class ListItemRenderer( val markerSpan = makeSpan(drawsMarker = true) + val previousMarkerExtra = styleContext.listItemMarkerExtra + styleContext.listItemMarkerExtra = markerSpan.markerExtraWidth val prevIndent = styleContext.accumulatedIndent styleContext.accumulatedIndent = prevIndent + markerSpan.getLeadingMargin(false) try { factory.renderChildren(node, builder, onLinkPress, onLinkLongPress) } finally { styleContext.accumulatedIndent = prevIndent + styleContext.listItemMarkerExtra = previousMarkerExtra } if (builder.length == start || builder.substring(start).isBlank()) return diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt index 2bac5b11d..d88422262 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt @@ -4,6 +4,7 @@ import android.text.SpannableStringBuilder import com.swmansion.enriched.markdown.parser.MarkdownASTNode import com.swmansion.enriched.markdown.spans.ListItemSpacingSpan import com.swmansion.enriched.markdown.spans.MarginBottomSpan +import com.swmansion.enriched.markdown.spans.OrderedListSpan import com.swmansion.enriched.markdown.styles.ListStyle import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE import com.swmansion.enriched.markdown.utils.text.span.applyLineHeightSkippingImages @@ -31,8 +32,9 @@ class ListRenderer( 1 } + val markerExtraWidth = if (isOrdered) markerExtraWidth(node, listStyle, startNumber, factory) else 0f val contextManager = ListContextManager(factory.blockStyleContext) - val entryState = contextManager.enterList(listType, listStyle, startNumber) + val entryState = contextManager.enterList(listType, listStyle, startNumber, markerExtraWidth) // For top-level lists, insert marginTop spacer before rendering content if (entryState.previousDepth == 0) { @@ -58,6 +60,23 @@ class ListRenderer( } } + /** Lists under 100 keep the `99.` column, so only numbers from 100 on widen it. Task items draw a checkbox. */ + private fun markerExtraWidth( + node: MarkdownASTNode, + listStyle: ListStyle, + startNumber: Int, + factory: RendererFactory, + ): Float { + val wideNumbers = mutableListOf() + var number = startNumber + for (item in node.children) { + if (item.type != MarkdownASTNode.NodeType.ListItem) continue + if (number >= 100 && item.attributes["isTask"] != "true") wideNumbers += number + number++ + } + return OrderedListSpan.measureExtraWidth(listStyle, factory.context, wideNumbers) + } + private fun applyListSpacing( builder: SpannableStringBuilder, start: Int, diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt index 2ab00430c..054931d8d 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt @@ -23,6 +23,7 @@ abstract class BaseListSpan( protected val marginLeft: Float, protected val gapWidth: Float, internal val drawsMarker: Boolean = true, + internal val ancestorMarkerOffset: Float = 0f, ) : MetricAffectingSpan(), LeadingMarginSpan { private var cachedText: CharSequence? = null @@ -38,6 +39,9 @@ abstract class BaseListSpan( protected abstract fun getMarkerWidth(): Float + /** How far an ordered list widened this item's column past the one short lists reserve. */ + internal open val markerExtraWidth: Float = 0f + override fun updateMeasureState(textPaint: TextPaint) = applyTextStyle(textPaint) override fun updateDrawState(textPaint: TextPaint) = applyTextStyle(textPaint) @@ -47,7 +51,7 @@ abstract class BaseListSpan( val effectiveGap = gapWidth.coerceAtLeast(DEFAULT_MIN_GAP) (getMarkerWidth() + effectiveGap).toInt() } else { - marginLeft.toInt() + (marginLeft + markerExtraWidth).toInt() } override fun drawLeadingMargin( diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt index 566f52800..9a2b19930 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt @@ -12,6 +12,7 @@ import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight import com.swmansion.enriched.markdown.renderer.BlockStyle import com.swmansion.enriched.markdown.renderer.SpanStyleCache import com.swmansion.enriched.markdown.styles.ListStyle +import kotlin.math.ceil class OrderedListSpan( private val listStyle: ListStyle, @@ -19,6 +20,8 @@ class OrderedListSpan( context: Context, styleCache: SpanStyleCache, drawsMarker: Boolean = true, + override val markerExtraWidth: Float = 0f, + ancestorMarkerOffset: Float = 0f, ) : BaseListSpan( depth = depth, context = context, @@ -33,30 +36,54 @@ class OrderedListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, + ancestorMarkerOffset = ancestorMarkerOffset, ) { companion object { private val sharedMarkerPaint = TextPaint().apply { isAntiAlias = true } - } - private val markerTypeface: Typeface = - run { - val fontFamily = listStyle.fontFamily.takeIf { it.isNotEmpty() } - val fontWeight = parseFontWeight(listStyle.markerFontWeight) - applyStyles(null, ReactConstants.UNSET, fontWeight, fontFamily, context.assets) + /** + * How far the `99.` column every ordered list reserves must grow to fit each of [numbers]. + * Whole pixels, so the Int leading margins and the float marker positions agree at every depth. + */ + fun measureExtraWidth( + listStyle: ListStyle, + context: Context, + numbers: Iterable, + ): Float { + val paint = markerPaint(listStyle, markerTypeface(listStyle, context)) + val default = paint.measureText("99.") + val widest = numbers.fold(default) { width, number -> maxOf(width, paint.measureText("$number.")) } + return ceil(listStyle.effectiveMarkerWidth(widest) - listStyle.effectiveMarkerWidth(default)) } - private fun configureMarkerPaint(): TextPaint = - sharedMarkerPaint.apply { - textSize = listStyle.fontSize - color = listStyle.markerColor - typeface = markerTypeface - } + private fun markerTypeface( + listStyle: ListStyle, + context: Context, + ): Typeface = + applyStyles( + null, + ReactConstants.UNSET, + parseFontWeight(listStyle.markerFontWeight), + listStyle.fontFamily.takeIf { it.isNotEmpty() }, + context.assets, + ) - override fun getMarkerWidth(): Float { - val paint = configureMarkerPaint() - return listStyle.effectiveMarkerWidth(paint.measureText("99.")) + private fun markerPaint( + listStyle: ListStyle, + typeface: Typeface, + ): TextPaint = + sharedMarkerPaint.apply { + textSize = listStyle.fontSize + color = listStyle.markerColor + this.typeface = typeface + } } + private val markerTypeface = markerTypeface(listStyle, context) + private val defaultMarkerWidth = listStyle.effectiveMarkerWidth(markerPaint(listStyle, markerTypeface).measureText("99.")) + + override fun getMarkerWidth(): Float = defaultMarkerWidth + markerExtraWidth + var itemNumber: Int = 1 private set @@ -71,11 +98,11 @@ class OrderedListSpan( layout: Layout?, start: Int, ) { - val markerPaint = configureMarkerPaint() + val markerPaint = markerPaint(listStyle, markerTypeface) val text = if (dir < 0) ".$itemNumber" else "$itemNumber." val textWidth = markerPaint.measureText(text) - val markerRightEdge = x + (depth * marginLeft + getMarkerWidth()) * dir + val markerRightEdge = x + (depth * marginLeft + ancestorMarkerOffset + getMarkerWidth()) * dir val markerX = if (dir > 0) markerRightEdge - textWidth else markerRightEdge canvas.drawText(text, markerX, baseline.toFloat(), markerPaint) diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt index 3b5a5c60b..fb0088718 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt @@ -20,6 +20,8 @@ class TaskListSpan( val taskIndex: Int, val isChecked: Boolean, drawsMarker: Boolean = true, + ancestorMarkerOffset: Float = 0f, + override val markerExtraWidth: Float = 0f, ) : BaseListSpan( depth = depth, context = context, @@ -34,9 +36,10 @@ class TaskListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, + ancestorMarkerOffset = ancestorMarkerOffset, ) { private val checkboxSize = taskStyle.checkboxSize - private val markerColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize) + private val markerColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize) + markerExtraWidth private val cornerRadius = taskStyle.checkboxBorderRadius private val rect = RectF() private val checkPath = Path() @@ -76,7 +79,7 @@ class TaskListSpan( // Right-align the checkbox inside the reserved marker column so it hugs // the gap before the text. At the default (markerColumnWidth == // checkboxSize) this is identical to the previous flush-left layout. - val centerX = x + (depth * marginLeft + markerColumnWidth - checkboxSize / HALF_DIVISOR) * dir + val centerX = x + (depth * marginLeft + ancestorMarkerOffset + markerColumnWidth - checkboxSize / HALF_DIVISOR) * dir val half = checkboxSize / HALF_DIVISOR rect.set(centerX - half, centerY - half, centerX + half, centerY + half) diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt index cc3e70401..2f50f46a0 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt @@ -14,6 +14,7 @@ class UnorderedListSpan( context: Context, styleCache: SpanStyleCache, drawsMarker: Boolean = true, + ancestorMarkerOffset: Float = 0f, ) : BaseListSpan( depth = depth, context = context, @@ -28,6 +29,7 @@ class UnorderedListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, + ancestorMarkerOffset = ancestorMarkerOffset, ) { companion object { private val sharedBulletPaint = @@ -65,7 +67,7 @@ class UnorderedListSpan( // it hugs the gap before the text — matches iOS behavior and stays // visually flush-left when the column width equals the bullet radius // (the default). - val bulletX = x + (depth * marginLeft + markerColumnWidth) * dir + val bulletX = x + (depth * marginLeft + ancestorMarkerOffset + markerColumnWidth) * dir val bulletY = baseline + (markerFontMetrics.ascent + markerFontMetrics.descent) / 2f when (depth) { diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt index 1bb4b5313..a9e6e00d0 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt @@ -131,16 +131,30 @@ object TaskListTapUtils { taskIndex = targetIndex, isChecked = newChecked, drawsMarker = old.drawsMarker, + ancestorMarkerOffset = old.ancestorMarkerOffset, + markerExtraWidth = old.markerExtraWidth, ) - // Replace every segment of the item — spans are split around code blocks - for (old in targetSpans) { - val start = spannable.getSpanStart(old) - val end = spannable.getSpanEnd(old) - // Keep the original flags so the list item priority survives the toggle - val flags = spannable.getSpanFlags(old) - spannable.removeSpan(old) - spannable.setSpan(toggledCopy(old), start, end, flags) + // Layout draws leading margins in insertion order, and a re-added span moves to the end of it. + // Re-add the task's spans and everything attached after them (its ancestors) in their original + // order; the task's own nested items were attached first and stay where they are. + data class ListSpanState( + val span: BaseListSpan, + val start: Int, + val end: Int, + val flags: Int, + ) + + val coveringSpans = spannable.getSpans(spanStart, spanEnd, BaseListSpan::class.java) + val firstTarget = coveringSpans.indexOfFirst { it is TaskListSpan && it.taskIndex == targetIndex } + val listSpans = + coveringSpans.drop(firstTarget).map { + ListSpanState(it, spannable.getSpanStart(it), spannable.getSpanEnd(it), spannable.getSpanFlags(it)) + } + listSpans.forEach { spannable.removeSpan(it.span) } + for ((old, start, end, flags) in listSpans) { + val replacement = if (old is TaskListSpan && old.taskIndex == targetIndex) toggledCopy(old) else old + spannable.setSpan(replacement, start, end, flags) } // The marker may be drawn by an anchor span wrapping an unattached copy diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt new file mode 100644 index 000000000..c10a5a307 --- /dev/null +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt @@ -0,0 +1,270 @@ +package com.swmansion.enriched.markdown + +import android.graphics.Typeface +import android.text.SpannableString +import android.text.TextPaint +import com.swmansion.enriched.markdown.parser.MarkdownASTNode +import com.swmansion.enriched.markdown.spans.BaseListSpan +import com.swmansion.enriched.markdown.spans.ListMarkerAnchorSpan +import com.swmansion.enriched.markdown.spans.OrderedListSpan +import com.swmansion.enriched.markdown.styles.StyleConfig +import com.swmansion.enriched.markdown.test.MarkdownRenderTestSupport.render +import com.swmansion.enriched.markdown.test.MarkdownRenderTestSupport.styleConfig +import com.swmansion.enriched.markdown.test.MarkerCanvas +import com.swmansion.enriched.markdown.test.MarkerGeometry +import com.swmansion.enriched.markdown.test.TestAstFactory.listItem +import com.swmansion.enriched.markdown.test.TestAstFactory.orderedList +import com.swmansion.enriched.markdown.test.TestAstFactory.paragraph +import com.swmansion.enriched.markdown.test.TestAstFactory.taskListItem +import com.swmansion.enriched.markdown.test.TestAstFactory.text +import com.swmansion.enriched.markdown.test.TestAstFactory.unorderedList +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode +import kotlin.math.ceil + +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [30]) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class ListRenderingTest { + @Test + fun shortListsKeepTheirIndentAndLongListsShareTheirWidestGutter() { + val style = listStyle() + val paint = + TextPaint().apply { + textSize = style.listStyle.fontSize + typeface = Typeface.create("monospace", Typeface.NORMAL) + } + val baseline = paint.measureText("99.") + val gap = style.listStyle.gapWidth + val short = orderedSpans(style, numbered(1, 99)) + short.forEach { assertEquals((baseline + gap).toInt(), it.getLeadingMargin(false)) } + for ((start, count) in listOf(1 to 250, 98 to 4, 998 to 4, 12345 to 4, 0 to 101)) { + val spans = orderedSpans(style, numbered(start, count)) + val widest = maxOf(baseline, spans.maxOf { paint.measureText("${it.itemNumber}.") }) + spans.forEach { assertEquals((baseline + ceil(widest - baseline) + gap).toInt(), it.getLeadingMargin(false)) } + assertTrue(spans.first().getLeadingMargin(false) > short.first().getLeadingMargin(false)) + } + } + + @Test + fun nestedAndFollowingListsRestoreTheirOwnGutters() { + val style = listStyle() + val spans = orderedSpans(style, withChild(numbered(98, 4), 0, numbered(9998, 4)), numbered(1, 1)) + val parent = spans.filter { it.depth == 0 && it.itemNumber != 1 } + assertEquals(4, parent.size) + parent.forEach { assertEquals(parent.first().getLeadingMargin(false), it.getLeadingMargin(false)) } + spans.filter { it.depth == 1 }.forEach { assertTrue(it.getLeadingMargin(false) > style.listStyle.marginLeft) } + val following = spans.single { it.depth == 0 && it.itemNumber == 1 } + assertTrue(following.getLeadingMargin(false) < parent.first().getLeadingMargin(false)) + } + + @Test + fun markerMinimumWidthRemainsAFloor() { + val style = listStyle(minWidth = 200.0) + orderedSpans(style, numbered(998, 4)).forEach { + assertEquals((style.listStyle.markerMinWidth + style.listStyle.gapWidth).toInt(), it.getLeadingMargin(false)) + } + } + + @Test + fun drawnMarkersStayInsideTheGutterAndAttachedToTheirParagraphs() { + val style = listStyle() + for (start in listOf(1, 98, 9998)) { + val threeLevels = withChild(numbered(1, 1), 0, numbered(1, 1)) + assertDrawnMarkerPositions(style, withChild(numbered(start, 4), 2, threeLevels)) + } + } + + @Test + fun nestedBulletColumnsKeepTheirGapUnderWideParents() { + val style = listStyle() + + fun tree(start: Int) = withChild(numbered(start, 4), 2, unorderedList(item(), item())) + for (start in listOf(98, 9998)) { + assertNestedMarkerGapsUnchanged(style, tree(1), tree(start)) + } + } + + @Test + fun tasksMoveWithTheirWideNumberedSiblings() { + val style = listStyle() + + fun tree(start: Int): MarkdownASTNode { + val items = numbered(start, 3).children.toMutableList() + items[1] = taskListItem(checked = false, paragraph(text("item")), numbered(1, 1)) + items[2] = listItem(paragraph(text("item")), numbered(1, 1)) + return orderedList(*items.toTypedArray(), start = start) + } + assertEveryRowShiftsTogether(style, tree(1), tree(12345)) + } + + @Test + fun nestedTasksKeepTheirGapUnderWideNumericParents() { + val style = listStyle() + + fun tree(start: Int) = withChild(numbered(start, 4), 2, orderedList(taskListItem(checked = false, paragraph(text("item"))))) + for (start in listOf(98, 9998)) { + assertNestedMarkerGapsUnchanged(style, tree(1), tree(start)) + } + } + + @Test + fun sameTypeBulletAndTaskNestsKeepTheirMarkerGap() { + val style = listStyle() + val bullet = unorderedList(item()) + val task = orderedList(taskListItem(checked = false, paragraph(text("item")))) + for (parent in listOf(bullet, task)) { + assertDrawnMarkerPositions(style, withChild(parent, 0, parent)) + } + } + + @Test + fun shortMixedNestsKeepTheirOriginalTextIndents() { + val style = styleConfig(list = mapOf("gapWidth" to 6.0), taskList = mapOf("checkboxSize" to 14.0)) + val ordered = numbered(1, 1) + val bullet = unorderedList(item()) + val task = orderedList(taskListItem(checked = false, paragraph(text("item")))) + val shapes = listOf(ordered to bullet, bullet to ordered, bullet to task, ordered to task, task to bullet) + val baseIndents = listOf(52f, 33f, 33f, 52f, 44f) + for ((index, shape) in shapes.withIndex()) { + val (parent, child) = shape + val nested = drawMarkers(style, withChild(parent, 0, child)).single { it.depth == 1 } + assertEquals("base mixed indent for shape $index", baseIndents[index], nested.paragraphLeft, 0.01f) + assertTrue(nested.marker.left >= 0f) + } + } + + @Test + fun markersAnchoredOnANestedListKeepTheirAncestorsOffset() { + val style = listStyle() + // The middle item opens with its sublist, so its marker is drawn by an anchor span. + val middle = orderedList(listItem(numbered(1, 1)), start = 1) + val text = SpannableString(render(style, withChild(numbered(12345, 1), 0, middle))) + assertEquals(1, text.getSpans(0, text.length, ListMarkerAnchorSpan::class.java).size) + val markers = MarkerCanvas.drawMarkers(MarkerCanvas.layout(text, style.listStyle.fontSize)) + assertEquals(3, markers.size) + val (root, anchored, leaf) = markers.sortedBy { it.right } + assertEquals(root.right + style.listStyle.marginLeft, anchored.right, 0.01f) + assertEquals(anchored.right + style.listStyle.marginLeft, leaf.right, 0.01f) + assertTrue(markers.all { it.left >= 0f }) + } + + @Test + fun inheritedMarkerOffsetsFollowTheRtlDirection() { + val style = listStyle() + val text = SpannableString(render(style, withChild(numbered(12345, 1), 0, numbered(1, 1)))) + val layout = MarkerCanvas.layout(text, style.listStyle.fontSize, rtl = true) + val markers = MarkerCanvas.drawMarkers(layout) + assertEquals(2, markers.size) + markers.forEach { marker -> + val line = layout.getLineForVertical(marker.baseline.toInt()) + assertEquals(-1, layout.getParagraphDirection(line)) + assertEquals(layout.getParagraphRight(line) + style.listStyle.gapWidth, marker.left, 0.01f) + assertTrue(marker.right <= layout.width) + } + } + + private fun assertDrawnMarkerPositions( + style: StyleConfig, + vararg lists: MarkdownASTNode, + ) { + drawMarkers(style, *lists).forEach { geometry -> + assertEquals( + "marker right at depth ${geometry.depth}", + geometry.paragraphLeft - style.listStyle.gapWidth, + geometry.marker.right, + 0.01f, + ) + } + } + + /** The rows [wide] shares with [short], tasks and their children included, all sit [wide]'s widening further right. */ + private fun assertEveryRowShiftsTogether( + style: StyleConfig, + short: MarkdownASTNode, + wide: MarkdownASTNode, + ) { + val shortRows = drawMarkers(style, short) + val wideRows = drawMarkers(style, wide).take(shortRows.size) + assertEquals(shortRows.size, wideRows.size) + val shift = wideRows.first().paragraphLeft - shortRows.first().paragraphLeft + assertTrue(shift > 0f) + wideRows.zip(shortRows).forEach { (actual, control) -> + assertEquals(control.depth, actual.depth) + assertEquals("text shift at depth ${actual.depth}", shift, actual.paragraphLeft - control.paragraphLeft, 0.01f) + assertEquals( + "marker gap at depth ${actual.depth}", + control.paragraphLeft - control.marker.right, + actual.paragraphLeft - actual.marker.right, + 0.01f, + ) + } + } + + private fun assertNestedMarkerGapsUnchanged( + style: StyleConfig, + short: MarkdownASTNode, + wide: MarkdownASTNode, + ) { + val shortMarkers = drawMarkers(style, short).filter { it.depth > 0 } + val wideMarkers = drawMarkers(style, wide).filter { it.depth > 0 } + assertTrue(shortMarkers.isNotEmpty()) + assertEquals(shortMarkers.size, wideMarkers.size) + shortMarkers.zip(wideMarkers).forEach { (control, actual) -> + assertEquals(control.depth, actual.depth) + assertEquals( + "nested marker gap at depth ${actual.depth}", + control.paragraphLeft - control.marker.right, + actual.paragraphLeft - actual.marker.right, + 0.01f, + ) + } + } + + private fun drawMarkers( + style: StyleConfig, + vararg lists: MarkdownASTNode, + ): List { + // SpannableString reports spans in insertion order, as the text view does. + val text = SpannableString(render(style, *lists)) + val geometry = MarkerCanvas.markerGeometry(text, MarkerCanvas.layout(text, style.listStyle.fontSize)) + assertEquals(text.getSpans(0, text.length, BaseListSpan::class.java).count { it.drawsMarker }, geometry.size) + geometry.forEach { assertTrue("marker left ${it.marker.left} at depth ${it.depth}", it.marker.left >= 0f) } + return geometry + } + + private fun orderedSpans( + style: StyleConfig, + vararg lists: MarkdownASTNode, + ): List { + val text = render(style, *lists) + return text + .getSpans(0, text.length, OrderedListSpan::class.java) + .sortedWith(compareBy({ text.getSpanStart(it) }, { it.depth })) + } + + private fun item(): MarkdownASTNode = listItem(paragraph(text("item"))) + + private fun numbered( + start: Int, + count: Int, + ): MarkdownASTNode = orderedList(*Array(count) { item() }, start = start) + + private fun withChild( + list: MarkdownASTNode, + index: Int, + child: MarkdownASTNode, + ): MarkdownASTNode { + val items = list.children.toMutableList() + items[index] = items[index].copy(children = items[index].children + child) + return list.copy(children = items) + } + + private fun listStyle(minWidth: Double = 0.0): StyleConfig = + styleConfig(list = mapOf("fontFamily" to "monospace", "markerMinWidth" to minWidth)) +} diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/TaskListInteractionTest.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/TaskListInteractionTest.kt new file mode 100644 index 000000000..64a70db33 --- /dev/null +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/TaskListInteractionTest.kt @@ -0,0 +1,102 @@ +package com.swmansion.enriched.markdown + +import android.text.Spanned +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import com.swmansion.enriched.markdown.accessibility.AccessibleMarkdownTextView +import com.swmansion.enriched.markdown.parser.MarkdownASTNode +import com.swmansion.enriched.markdown.spans.BaseListSpan +import com.swmansion.enriched.markdown.spans.ListMarkerAnchorSpan +import com.swmansion.enriched.markdown.spans.TaskListSpan +import com.swmansion.enriched.markdown.test.DrawnMarker +import com.swmansion.enriched.markdown.test.MarkdownRenderTestSupport.render +import com.swmansion.enriched.markdown.test.MarkdownRenderTestSupport.styleConfig +import com.swmansion.enriched.markdown.test.MarkerCanvas +import com.swmansion.enriched.markdown.test.TestAstFactory.listItem +import com.swmansion.enriched.markdown.test.TestAstFactory.orderedList +import com.swmansion.enriched.markdown.test.TestAstFactory.paragraph +import com.swmansion.enriched.markdown.test.TestAstFactory.taskListItem +import com.swmansion.enriched.markdown.test.TestAstFactory.text +import com.swmansion.enriched.markdown.test.TestAstFactory.unorderedList +import com.swmansion.enriched.markdown.utils.text.interaction.TaskListTapUtils +import com.swmansion.enriched.markdown.utils.text.view.setupAsMarkdownTextView +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [30]) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class TaskListInteractionTest { + private val context = RuntimeEnvironment.getApplication() + + @Test + fun togglingATaskUnderAWideParentKeepsEveryMarginAndMarkerPosition() { + assertTaskToggleKeepsGeometry(opensWithSublist = false) + } + + @Test + fun togglingAnAnchoredTaskUnderAWideParentKeepsEveryMarginAndMarkerPosition() { + assertTaskToggleKeepsGeometry(opensWithSublist = true) + } + + // Layout draws leading margins in span insertion order, so a toggle that re-adds only the + // task's span would move its checkbox by its ancestors' margins. + private fun assertTaskToggleKeepsGeometry(opensWithSublist: Boolean) { + val style = styleConfig(list = mapOf("fontFamily" to "monospace")) + val taskChildren = if (opensWithSublist) arrayOf(numbered(1)) else arrayOf(paragraph(text("item")), numbered(1)) + val task = taskListItem(checked = false, *taskChildren) + val tree = orderedList(listItem(paragraph(text("item")), unorderedList(task)), item(), start = 100) + val textView = + object : AccessibleMarkdownTextView(context) {}.apply { + layoutParams = ViewGroup.LayoutParams(MarkerCanvas.LAYOUT_WIDTH, ViewGroup.LayoutParams.WRAP_CONTENT) + setupAsMarkdownTextView() + } + textView.setText(render(style, tree), TextView.BufferType.SPANNABLE) + val initialText = textView.text as Spanned + val taskIndex = initialText.getSpans(0, initialText.length, TaskListSpan::class.java).single().taskIndex + assertEquals(if (opensWithSublist) 1 else 0, initialText.getSpans(0, initialText.length, ListMarkerAnchorSpan::class.java).size) + val initialMargins = listMargins(initialText) + val initialMarkers = drawTextViewMarkers(textView) + assertEquals(4, initialMarkers.size) + + for (checked in listOf(true, false)) { + assertTrue(TaskListTapUtils.updateTaskListItemCheckedState(textView, taskIndex, checked, style)) + val text = textView.text as Spanned + val tasks = text.getSpans(0, text.length, TaskListSpan::class.java) + assertTrue(tasks.isNotEmpty()) + tasks.forEach { assertEquals(checked, it.isChecked) } + text.getSpans(0, text.length, ListMarkerAnchorSpan::class.java).forEach { + assertEquals(checked, (it.marker as TaskListSpan).isChecked) + } + assertEquals("list margins after checked=$checked", initialMargins, listMargins(text)) + assertEquals("drawn markers after checked=$checked", initialMarkers, drawTextViewMarkers(textView)) + } + } + + private fun listMargins(text: Spanned): List> = + text + .getSpans(0, text.length, BaseListSpan::class.java) + .sortedWith(compareBy({ text.getSpanStart(it) }, { it.depth }, { text.getSpanEnd(it) })) + .map { listOf(text.getSpanStart(it), text.getSpanEnd(it), it.depth, it.getLeadingMargin(true), it.getLeadingMargin(false)) } + + private fun drawTextViewMarkers(textView: TextView): List { + textView.forceLayout() + textView.measure( + View.MeasureSpec.makeMeasureSpec(MarkerCanvas.LAYOUT_WIDTH, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), + ) + textView.layout(0, 0, textView.measuredWidth, textView.measuredHeight) + return MarkerCanvas.drawMarkers(textView.layout) + } + + private fun item(): MarkdownASTNode = listItem(paragraph(text("item"))) + + private fun numbered(count: Int): MarkdownASTNode = orderedList(*Array(count) { item() }, start = 1) +} diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt new file mode 100644 index 000000000..7383db048 --- /dev/null +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt @@ -0,0 +1,101 @@ +package com.swmansion.enriched.markdown.test + +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import android.graphics.RectF +import android.text.Layout +import android.text.Spanned +import android.text.StaticLayout +import android.text.TextDirectionHeuristics +import android.text.TextPaint +import com.swmansion.enriched.markdown.spans.BaseListSpan + +/** A list marker as the layout drew it: a number, a bullet, or a checkbox. */ +data class DrawnMarker( + val left: Float, + val right: Float, + val baseline: Float, +) + +/** A drawn marker with the text edge and list depth of the paragraph it belongs to. */ +data class MarkerGeometry( + val marker: DrawnMarker, + val paragraphLeft: Float, + val depth: Int, +) + +/** Records the list markers a layout draws instead of painting them. */ +class MarkerCanvas : Canvas(Bitmap.createBitmap(LAYOUT_WIDTH, 1, Bitmap.Config.ARGB_8888)) { + val markers = mutableListOf() + + // Layout draws only the lines inside the clip; report one tall enough for every list. + override fun getClipBounds(bounds: Rect): Boolean { + bounds.set(0, 0, LAYOUT_WIDTH, Int.MAX_VALUE / 2) + return true + } + + override fun drawCircle( + cx: Float, + cy: Float, + radius: Float, + paint: Paint, + ) { + // Bullets are centered on the reserved column edge, matching the iOS drawer. + val outerRadius = radius + paint.strokeWidth / 2f + markers += DrawnMarker(cx - outerRadius, cx, cy) + super.drawCircle(cx, cy, radius, paint) + } + + override fun drawRoundRect( + rect: RectF, + rx: Float, + ry: Float, + paint: Paint, + ) { + val halfStroke = if (paint.style == Paint.Style.STROKE) paint.strokeWidth / 2f else 0f + markers += DrawnMarker(rect.left - halfStroke, rect.right + halfStroke, rect.centerY()) + super.drawRoundRect(rect, rx, ry, paint) + } + + override fun drawText( + text: String, + x: Float, + y: Float, + paint: Paint, + ) { + if (text.matches(Regex("(?:[0-9]+\\.|\\.[0-9]+)"))) markers += DrawnMarker(x, x + paint.measureText(text), y) + super.drawText(text, x, y, paint) + } + + companion object { + const val LAYOUT_WIDTH = 2000 + + fun layout( + text: CharSequence, + textSize: Float, + rtl: Boolean = false, + ): StaticLayout = + StaticLayout.Builder + .obtain(text, 0, text.length, TextPaint().apply { this.textSize = textSize }, LAYOUT_WIDTH) + .apply { if (rtl) setTextDirection(TextDirectionHeuristics.RTL) } + .build() + + /** The markers [layout] draws, top to bottom. */ + fun drawMarkers(layout: Layout): List = + MarkerCanvas().also(layout::draw).markers.sortedWith(compareBy({ it.baseline }, { it.left })) + + /** Every marker [layout] draws, with the text edge and depth of its paragraph. */ + fun markerGeometry( + text: Spanned, + layout: Layout, + ): List = + drawMarkers(layout).map { marker -> + val line = layout.getLineForVertical(marker.baseline.toInt()) + val start = layout.getLineStart(line) + val depth = text.getSpans(start, start + 1, BaseListSpan::class.java).maxOf { it.depth } + MarkerGeometry(marker, layout.getParagraphLeft(line).toFloat(), depth) + } + } +} diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt new file mode 100644 index 000000000..645ce339d --- /dev/null +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt @@ -0,0 +1,126 @@ +package com.swmansion.enriched.markdown.test + +import android.content.Context +import android.graphics.Color +import android.text.Spannable +import com.facebook.react.bridge.JavaOnlyArray +import com.facebook.react.bridge.JavaOnlyMap +import com.facebook.react.uimanager.DisplayMetricsHolder +import com.swmansion.enriched.markdown.parser.MarkdownASTNode +import com.swmansion.enriched.markdown.renderer.Renderer +import com.swmansion.enriched.markdown.styles.StyleConfig +import org.robolectric.RuntimeEnvironment + +object MarkdownRenderTestSupport { + // Resolved per call, not cached: a @Config qualifier applies to the current test's context. + private val context: Context + get() = RuntimeEnvironment.getApplication() + + fun render( + style: StyleConfig, + vararg blocks: MarkdownASTNode, + ): Spannable { + val renderer = Renderer() + renderer.configure(style, context) + return renderer.renderContent(blocks.toList()) + } + + /** + * The style map the JS side sends, with [list] and [taskList] entries replacing the defaults. + * Sizes are Double, colors Int, as in a ReadableMap. + */ + fun styleConfig( + list: Map = emptyMap(), + taskList: Map = emptyMap(), + ): StyleConfig { + DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context) + val style = JavaOnlyMap() + listOf("paragraph", "strong", "em", "strikethrough", "code", "superscript", "subscript", "highlight") + .forEach { style.putMap(it, textElement()) } + style.putMap("link", textElement().apply { putString("fontFamily", "serif") }) + style.putArray( + "linkVariants", + JavaOnlyArray.of( + textElement().apply { + putString("pattern", "^ref:") + putString("fontFamily", "monospace") + putInt("color", Color.BLUE) + }, + ), + ) + style.putMap( + "spoiler", + textElement().apply { + putMap("particles", JavaOnlyMap.of("density", 0.5, "speed", 1.0)) + putMap("solid", JavaOnlyMap.of("borderRadius", 0.0)) + }, + ) + style.putMap("taskList", JavaOnlyMap().apply { putAll(defaultTaskList + taskList) }) + style.putMap("list", textElement().apply { putAll(defaultList + list) }) + return StyleConfig(style, context, false, 0f) + } + + private val defaultList: Map = + mapOf( + "fontFamily" to "", + "bulletColor" to Color.BLACK, + "markerColor" to Color.BLACK, + "bulletSize" to 6.0, + "markerMinWidth" to 0.0, + "gapWidth" to 8.0, + "marginLeft" to 24.0, + "itemSpacing" to 0.0, + ) + + private val defaultTaskList: Map = + mapOf( + "checkedColor" to Color.BLACK, + "borderColor" to Color.BLACK, + "checkmarkColor" to Color.BLACK, + "checkedTextColor" to Color.BLACK, + "checkboxSize" to 16.0, + "checkboxBorderRadius" to 0.0, + "checkedStrikethrough" to false, + ) + + private fun textElement(): JavaOnlyMap = + JavaOnlyMap.of( + "fontFamily", + "", + "fontWeight", + "normal", + "fontSize", + 16.0, + "lineHeight", + 0.0, + "marginTop", + 0.0, + "marginBottom", + 0.0, + "color", + Color.BLACK, + "backgroundColor", + Color.TRANSPARENT, + "borderColor", + Color.TRANSPARENT, + "underline", + false, + "fontScale", + 0.8, + "baselineOffsetScale", + 0.5, + ) + + private fun JavaOnlyMap.putAll(values: Map) { + for ((key, value) in values) { + when (value) { + is String -> putString(key, value) + is Boolean -> putBoolean(key, value) + is Int -> putInt(key, value) + is Double -> putDouble(key, value) + is Float -> putDouble(key, value.toDouble()) + else -> error("Unsupported style value for $key: $value") + } + } + } +} diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/TestAstFactory.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/TestAstFactory.kt new file mode 100644 index 000000000..1808c3414 --- /dev/null +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/TestAstFactory.kt @@ -0,0 +1,36 @@ +package com.swmansion.enriched.markdown.test + +import com.swmansion.enriched.markdown.parser.MarkdownASTNode +import com.swmansion.enriched.markdown.parser.MarkdownASTNode.NodeType + +object TestAstFactory { + fun paragraph(vararg children: MarkdownASTNode): MarkdownASTNode = MarkdownASTNode(NodeType.Paragraph, children = children.toList()) + + fun text(content: String): MarkdownASTNode = MarkdownASTNode(NodeType.Text, content = content) + + /** An ordered list; [start] is the first number, as md4c reports it. */ + fun orderedList( + vararg items: MarkdownASTNode, + start: Int? = null, + ): MarkdownASTNode = + MarkdownASTNode( + type = NodeType.OrderedList, + attributes = start?.let { mapOf("start" to it.toString()) }.orEmpty(), + children = items.toList(), + ) + + fun unorderedList(vararg items: MarkdownASTNode): MarkdownASTNode = MarkdownASTNode(NodeType.UnorderedList, children = items.toList()) + + fun listItem(vararg children: MarkdownASTNode): MarkdownASTNode = MarkdownASTNode(NodeType.ListItem, children = children.toList()) + + /** A GFM task-list item, what md4c produces for `- [ ]` / `- [x]`. */ + fun taskListItem( + checked: Boolean, + vararg children: MarkdownASTNode, + ): MarkdownASTNode = + MarkdownASTNode( + type = NodeType.ListItem, + attributes = mapOf("isTask" to "true", "taskChecked" to checked.toString()), + children = children.toList(), + ) +} diff --git a/packages/react-native-enriched-markdown/ios/renderer/ListItemRenderer.m b/packages/react-native-enriched-markdown/ios/renderer/ListItemRenderer.m index ed80dfad7..dd6aa2478 100644 --- a/packages/react-native-enriched-markdown/ios/renderer/ListItemRenderer.m +++ b/packages/react-native-enriched-markdown/ios/renderer/ListItemRenderer.m @@ -83,25 +83,29 @@ - (void)renderNodeContent:(MarkdownASTNode *)node // currentDepth - 1 handles the horizontal offset for nested lists const NSInteger nestingLevel = currentDepth - 1; - const CGFloat baseMarkerWidth = isTask ? [_config effectiveListMarginLeftForTask] - : (context.listType == ListTypeOrdered) ? [_config effectiveListMarginLeftForNumber] + // A task in a widened ordered list moves with its numbered siblings. + const CGFloat baseMarkerWidth = isTask ? [_config effectiveListMarginLeftForTask] + context.listMarkerExtra + : (context.listType == ListTypeOrdered) ? context.listMarkerWidth : [_config effectiveListMarginLeftForBullet]; const CGFloat blockquoteIndent = blockquoteIndentForDepth(context.blockquoteDepth, [_config blockquoteBorderWidth] + [_config blockquoteGapWidth]); const CGFloat totalIndent = blockquoteIndent + baseMarkerWidth + [_config effectiveListGapWidth] + - (nestingLevel * [_config listStyleMarginLeft]); + (nestingLevel * [_config listStyleMarginLeft]) + context.ancestorMarkerOffset; const NSUInteger startLocation = output.length; // Manual save/restore — a scope snapshot would also roll back the listItemNumber increment + const CGFloat prevMarkerExtra = context.listItemMarkerExtra; + context.listItemMarkerExtra = context.listMarkerExtra; const CGFloat prevIndent = context.accumulatedIndent; context.accumulatedIndent = totalIndent; @try { [_rendererFactory renderChildrenOfNode:node into:output context:context]; } @finally { context.accumulatedIndent = prevIndent; + context.listItemMarkerExtra = prevMarkerExtra; } // Ensure every list item ends with a newline to prevent paragraph merging diff --git a/packages/react-native-enriched-markdown/ios/renderer/ListRenderer.m b/packages/react-native-enriched-markdown/ios/renderer/ListRenderer.m index 47283dc99..61812a7c0 100644 --- a/packages/react-native-enriched-markdown/ios/renderer/ListRenderer.m +++ b/packages/react-native-enriched-markdown/ios/renderer/ListRenderer.m @@ -90,6 +90,24 @@ - (void)renderNodeContent:(MarkdownASTNode *)node // ListItemRenderer pre-increments, so the counter starts one below the // first rendered number. context.listItemNumber = startNumber - 1; + const CGFloat defaultMarkerWidth = [_config effectiveListMarginLeftForNumber:99]; + if (prevDepth > 0) { + context.ancestorMarkerOffset += context.listItemMarkerExtra; + } + context.listMarkerWidth = defaultMarkerWidth; + if (_isOrdered) { + NSInteger number = startNumber; + for (MarkdownASTNode *item in node.children) { + if (item.type != MarkdownNodeTypeListItem) + continue; + // Keep the existing gutter for one- and two-digit markers. + if (number >= 100 && ![item.attributes[@"isTask"] isEqualToString:@"true"]) { + context.listMarkerWidth = MAX(context.listMarkerWidth, [_config effectiveListMarginLeftForNumber:number]); + } + number++; + } + } + context.listMarkerExtra = context.listMarkerWidth - defaultMarkerWidth; [context setBlockStyle:_isOrdered ? BlockTypeOrderedList : BlockTypeUnorderedList font:_config.listStyleFont diff --git a/packages/react-native-enriched-markdown/ios/renderer/RenderContext.h b/packages/react-native-enriched-markdown/ios/renderer/RenderContext.h index ad4a6431a..376b5e99e 100644 --- a/packages/react-native-enriched-markdown/ios/renderer/RenderContext.h +++ b/packages/react-native-enriched-markdown/ios/renderer/RenderContext.h @@ -52,6 +52,10 @@ typedef NS_ENUM(NSInteger, ListType) { ListTypeUnordered, ListTypeOrdered }; @property (nonatomic, assign) NSInteger listDepth; @property (nonatomic, assign) ListType listType; @property (nonatomic, assign) NSInteger listItemNumber; +@property (nonatomic, assign) CGFloat listMarkerWidth; +@property (nonatomic, assign) CGFloat listMarkerExtra; +@property (nonatomic, assign) CGFloat ancestorMarkerOffset; +@property (nonatomic, assign) CGFloat listItemMarkerExtra; @property (nonatomic, assign) CGFloat accumulatedIndent; @property (nonatomic, assign) BOOL allowFontScaling; @property (nonatomic, assign) CGFloat maxFontSizeMultiplier; diff --git a/packages/react-native-enriched-markdown/ios/renderer/RenderContext.m b/packages/react-native-enriched-markdown/ios/renderer/RenderContext.m index b22686708..fc5e6312c 100644 --- a/packages/react-native-enriched-markdown/ios/renderer/RenderContext.m +++ b/packages/react-native-enriched-markdown/ios/renderer/RenderContext.m @@ -24,6 +24,10 @@ @implementation BlockStyle @"listDepth", @"listType", @"listItemNumber", + @"listMarkerWidth", + @"listMarkerExtra", + @"ancestorMarkerOffset", + @"listItemMarkerExtra", @"accumulatedIndent", ]; }); @@ -313,6 +317,10 @@ - (void)reset _listDepth = 0; _listType = ListTypeUnordered; _listItemNumber = 0; + _listMarkerWidth = 0; + _listMarkerExtra = 0; + _ancestorMarkerOffset = 0; + _listItemMarkerExtra = 0; _accumulatedIndent = 0; _taskItemCount = 0; diff --git a/packages/react-native-enriched-markdown/ios/styles/StyleConfig.h b/packages/react-native-enriched-markdown/ios/styles/StyleConfig.h index 628d069ed..815a86a57 100644 --- a/packages/react-native-enriched-markdown/ios/styles/StyleConfig.h +++ b/packages/react-native-enriched-markdown/ios/styles/StyleConfig.h @@ -336,7 +336,7 @@ NS_ASSUME_NONNULL_BEGIN - (UIFont *)listStyleFont; - (CGFloat)effectiveListGapWidth; - (CGFloat)effectiveListMarginLeftForBullet; -- (CGFloat)effectiveListMarginLeftForNumber; +- (CGFloat)effectiveListMarginLeftForNumber:(NSInteger)number; - (CGFloat)effectiveListMarginLeftForTask; // Code block properties - (CGFloat)codeBlockFontSize; diff --git a/packages/react-native-enriched-markdown/ios/styles/StyleConfig.mm b/packages/react-native-enriched-markdown/ios/styles/StyleConfig.mm index 33876bd21..82ae4be95 100644 --- a/packages/react-native-enriched-markdown/ios/styles/StyleConfig.mm +++ b/packages/react-native-enriched-markdown/ios/styles/StyleConfig.mm @@ -2079,11 +2079,13 @@ - (CGFloat)effectiveListMarginLeftForBullet return MAX(_listStyleMarkerMinWidth, _listStyleBulletSize / 2.0); } -- (CGFloat)effectiveListMarginLeftForNumber +- (CGFloat)effectiveListMarginLeftForNumber:(NSInteger)number { UIFont *font = [self listMarkerFont]; CGFloat natural = - [@"99." sizeWithAttributes:@{NSFontAttributeName : font ?: [UIFont systemFontOfSize:_listStyleFontSize]}].width; + [[NSString stringWithFormat:@"%ld.", (long)number] + sizeWithAttributes:@{NSFontAttributeName : font ?: [UIFont systemFontOfSize:_listStyleFontSize]}] + .width; return MAX(_listStyleMarkerMinWidth, natural); } From c685fb3909ab5e17bd11513b4a3619ab4890b0ea Mon Sep 17 00:00:00 2001 From: Gregory Moskaliuk Date: Fri, 16 Oct 2026 20:46:10 +0200 Subject: [PATCH 02/11] fix(clipboard): preserve table cell line breaks and math (#1019) * fix(clipboard): preserve table cell line breaks and math * fix(ios): keep hard breaks inside their block when exporting HTML collectParagraphsData split on lineRangeForRange:, which treats the U+2028 a hard break renders as like a paragraph end. A paragraph with a hard break exported as two

blocks and a list item as two

  • items, and with the new
    escaping the first half gained a trailing
    . Split on paragraphRangeForRange: so the break stays in its block and becomes

    line one
    line two

    . Tests are named by feature like #1015: ClipboardExportTests.mm and ClipboardExportTest.kt, since both cover HTML and Markdown export. Added a rendered hard-break case on iOS, the code block gate on Android, a run that mixes escaped characters with a line break, and math nested in strong, on both platforms. Co-Authored-By: Claude Fable 5.1 --------- Co-authored-by: Yash Singh Co-authored-by: Claude Fable 5.1 --- .../__tests__/ios/ClipboardExportTests.mm | 80 ++++++++ .../serialization/MarkdownASTSerializer.kt | 6 + .../utils/text/conversion/HTMLGenerator.kt | 20 +- .../enriched/markdown/ClipboardExportTest.kt | 173 ++++++++++++++++++ .../ios/utils/HTMLGenerator.m | 39 ++-- .../ios/utils/MarkdownASTSerializer.m | 6 + 6 files changed, 308 insertions(+), 16 deletions(-) create mode 100644 packages/react-native-enriched-markdown/__tests__/ios/ClipboardExportTests.mm create mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ClipboardExportTest.kt diff --git a/packages/react-native-enriched-markdown/__tests__/ios/ClipboardExportTests.mm b/packages/react-native-enriched-markdown/__tests__/ios/ClipboardExportTests.mm new file mode 100644 index 000000000..5b629d52f --- /dev/null +++ b/packages/react-native-enriched-markdown/__tests__/ios/ClipboardExportTests.mm @@ -0,0 +1,80 @@ +#import "../../ios/parser/ENRMMarkdownParser.h" +#import "../../ios/parser/MarkdownASTNode.h" +#import "../../ios/styles/StyleConfig.h" +#import "../../ios/utils/ENRMTextRenderer.h" +#import "../../ios/utils/HTMLGenerator.h" +#import "../../ios/utils/LastElementUtils.h" +#import "../../ios/utils/MarkdownASTSerializer.h" +#import + +@interface ENRMClipboardExportTests : XCTestCase +@end + +@implementation ENRMClipboardExportTests + +- (void)testTableLineBreaksAreExportedAsHTMLBreaks +{ + for (NSString *separator in @[ @"\n", @"\r", @"\r\n", @"\u2028", @"\u2029" ]) { + NSAttributedString *text = + [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"first%@second", separator]]; + NSString *html = generateTableHTML(@[ @[ @{@"attributedText" : text} ] ], [[StyleConfig alloc] init]); + XCTAssertTrue([html containsString:@"first
    second"], @"%@", html); + XCTAssertFalse([html containsString:@"

    "], @"%@", html); + } +} + +- (void)testEscapedCharactersAndLineBreaksShareOneRun +{ + NSAttributedString *text = [[NSAttributedString alloc] initWithString:@"a & b\nc "]; + NSString *html = generateTableHTML(@[ @[ @{@"attributedText" : text} ] ], [[StyleConfig alloc] init]); + XCTAssertTrue([html containsString:@"a & b
    c <d>"], @"%@", html); +} + +- (NSString *)htmlForMarkdown:(NSString *)markdown +{ + MarkdownASTNode *ast = [[[ENRMMarkdownParser alloc] init] parseMarkdown:markdown + flags:[ENRMMd4cFlags defaultFlags] + isGFM:YES]; + StyleConfig *config = [[StyleConfig alloc] init]; + ENRMRenderResult *result = ENRMRenderASTNodes(ast.children, config, NO, YES, 0, NSLineBreakStrategyStandard); + return generateHTML(result.attributedText, config); +} + +- (void)testHardBreaksStayInsideTheirBlock +{ + NSString *paragraph = [self htmlForMarkdown:@"line one \nline two\n\npara two"]; + XCTAssertTrue([paragraph containsString:@"line one
    line two

    "], @"%@", paragraph); + XCTAssertFalse([paragraph containsString:@"

    "], @"%@", paragraph); + + NSString *list = [self htmlForMarkdown:@"- item one \n item two\n- item three"]; + XCTAssertTrue([list containsString:@"item one
    item two
  • "], @"%@", list); + XCTAssertEqual([list componentsSeparatedByString:@""], @"%@", html); + XCTAssertTrue([html containsString:@"first\nsecond"], @"%@", html); +} + +- (void)testSerializedTableFormulaKeepsInlineDelimiters +{ + MarkdownASTNode *formula = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeLatexMathInline]; + MarkdownASTNode *text = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeText]; + text.content = @"x_1"; + [formula addChild:text]; + MarkdownASTNode *cell = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeTableCell]; + [cell addChild:formula]; + XCTAssertEqualObjects(markdownFromASTNodeChildren(cell), @"$x_1$"); + + MarkdownASTNode *strong = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeStrong]; + [strong addChild:formula]; + MarkdownASTNode *nestedCell = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeTableCell]; + [nestedCell addChild:strong]; + XCTAssertEqualObjects(markdownFromASTNodeChildren(nestedCell), @"**$x_1$**"); +} + +@end diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt index 7e156aa9b..66ea56c4f 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt @@ -291,6 +291,12 @@ object MarkdownASTSerializer { buffer.append("==") } + NodeType.LatexMathInline -> { + buffer.append("\$") + appendChildren(node, buffer) + buffer.append("\$") + } + NodeType.Code -> { buffer.append("`") appendChildren(node, buffer) diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt index 3a60ebb80..b55937fd7 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt @@ -848,7 +848,7 @@ object HTMLGenerator { } } - escapeHTMLTo(html, content.trimEnd('\n')) + escapeHTMLTo(html, content.trimEnd('\n'), preserveLineBreaks = !isCodeBlock) if (isUnderline && link == null) html.append("") if (isStrikethrough) html.append("") @@ -1001,7 +1001,7 @@ object HTMLGenerator { if (cellText is Spannable) { append(generateInlineHTML(cellText, 0, cellText.length, cachedStyles, false)) } else { - escapeHTMLTo(this, cellText.toString()) + escapeHTMLTo(this, cellText.toString(), preserveLineBreaks = true) } } @@ -1042,6 +1042,7 @@ object HTMLGenerator { private fun escapeHTMLTo( output: StringBuilder, text: String, + preserveLineBreaks: Boolean = false, ) { val len = text.length @@ -1049,7 +1050,9 @@ object HTMLGenerator { var needsEscape = false for (i in 0 until len) { val c = text[i] - if (c == '&' || c == '<' || c == '>' || c == '"' || c == '\'') { + if (c == '&' || c == '<' || c == '>' || c == '"' || c == '\'' || + (preserveLineBreaks && (c == '\r' || c == '\n' || c == '\u2028' || c == '\u2029')) + ) { needsEscape = true break } @@ -1059,8 +1062,15 @@ object HTMLGenerator { return } - for (i in 0 until len) { - when (val c = text[i]) { + var index = 0 + while (index < len) { + val c = text[index++] + if (preserveLineBreaks && (c == '\r' || c == '\n' || c == '\u2028' || c == '\u2029')) { + if (c == '\r' && index < len && text[index] == '\n') index++ + output.append("
    ") + continue + } + when (c) { '&' -> output.append("&") '<' -> output.append("<") '>' -> output.append(">") diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ClipboardExportTest.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ClipboardExportTest.kt new file mode 100644 index 000000000..daf6b8a14 --- /dev/null +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ClipboardExportTest.kt @@ -0,0 +1,173 @@ +package com.swmansion.enriched.markdown + +import android.graphics.Color +import android.text.Layout +import android.text.SpannableString +import com.facebook.react.bridge.JavaOnlyMap +import com.swmansion.enriched.markdown.parser.MarkdownASTNode +import com.swmansion.enriched.markdown.renderer.Renderer +import com.swmansion.enriched.markdown.styles.StyleConfig +import com.swmansion.enriched.markdown.utils.common.serialization.MarkdownASTSerializer +import com.swmansion.enriched.markdown.utils.text.conversion.HTMLGenerator +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [30]) +class ClipboardExportTest { + private val context = RuntimeEnvironment.getApplication() + + @Test + fun tableLineBreaksAreExportedAsHtmlBreaks() { + for (separator in listOf("\n", "\r", "\r\n", "\u2028", "\u2029")) { + for (text in listOf(SpannableString("first${separator}second"), "first${separator}second")) { + val rows = listOf(listOf(Triple(text, false, Layout.Alignment.ALIGN_NORMAL))) + val html = HTMLGenerator.generateTableHTML(rows, style()) + assertTrue(html, html.contains("first
    second")) + assertFalse(html, html.contains("

    ")) + } + } + } + + @Test + fun escapedCharactersAndLineBreaksShareOneRun() { + val rows = listOf(listOf(Triple("a & b\nc ", false, Layout.Alignment.ALIGN_NORMAL))) + val html = HTMLGenerator.generateTableHTML(rows, style()) + assertTrue(html, html.contains("a & b
    c <d>")) + } + + @Test + fun codeBlockNewlinesRemainLiteral() { + val style = style() + val codeBlock = + MarkdownASTNode( + MarkdownASTNode.NodeType.CodeBlock, + content = "first\nsecond", + children = listOf(MarkdownASTNode(MarkdownASTNode.NodeType.Text, "first\nsecond")), + ) + val renderer = Renderer() + renderer.configure(style, context) + val html = HTMLGenerator.generateHTML(renderer.renderContent(listOf(codeBlock)), style) + assertFalse(html, html.contains("
    ")) + assertTrue(html, html.contains("first\nsecond")) + } + + @Test + fun serializedTableFormulaKeepsItsInlineDelimiters() { + val formula = + MarkdownASTNode(MarkdownASTNode.NodeType.LatexMathInline, children = listOf(MarkdownASTNode(MarkdownASTNode.NodeType.Text, "x_1"))) + val cell = MarkdownASTNode(MarkdownASTNode.NodeType.TableCell, children = listOf(formula)) + assertEquals("\$x_1\$", MarkdownASTSerializer.serializeChildren(cell)) + + val strong = MarkdownASTNode(MarkdownASTNode.NodeType.Strong, children = listOf(formula)) + val nestedCell = MarkdownASTNode(MarkdownASTNode.NodeType.TableCell, children = listOf(strong)) + assertEquals("**\$x_1\$**", MarkdownASTSerializer.serializeChildren(nestedCell)) + } + + private fun style(): StyleConfig { + com.facebook.react.uimanager.DisplayMetricsHolder + .initDisplayMetricsIfNotInitialized(context) + + fun element() = + JavaOnlyMap().apply { + listOf( + "aspectRatio", + "bulletSize", + "checkboxBorderRadius", + "checkboxSize", + "height", + "itemSpacing", + "markerMinWidth", + "maxHeight", + "cellPaddingHorizontal", + "cellPaddingVertical", + "horizontalOverflow", + "lineHeight", + "marginTop", + "marginBottom", + "padding", + "borderRadius", + "borderWidth", + "gapWidth", + "marginLeft", + ).forEach { + putDouble(it, 0.0) + } + listOf( + "bulletColor", + "checkedColor", + "checkedTextColor", + "checkmarkColor", + "headerBackgroundColor", + "headerTextColor", + "markerColor", + "rowEvenBackgroundColor", + "rowOddBackgroundColor", + "color", + "borderColor", + ).forEach { + putInt(it, Color.BLACK) + } + putString("resizeMode", "contain") + putString("fontFamily", "") + putString("fontWeight", "normal") + putDouble("fontSize", 16.0) + putDouble("fontScale", 0.8) + putDouble("baselineOffsetScale", 0.5) + putBoolean("underline", false) + putInt("backgroundColor", Color.TRANSPARENT) + } + val style = JavaOnlyMap() + listOf( + "table", + "paragraph", + "codeBlock", + "code", + "blockquote", + "list", + "link", + "strong", + "em", + "strikethrough", + "underline", + "highlight", + "image", + "superscript", + "subscript", + ).forEach { style.putMap(it, element()) } + style.putMap( + "spoiler", + element().apply { + putMap("particles", JavaOnlyMap.of("density", 0.5, "speed", 1.0)) + putMap("solid", JavaOnlyMap.of("borderRadius", 0.0)) + }, + ) + for (level in 1..6) style.putMap("h$level", element()) + style.putMap( + "taskList", + JavaOnlyMap.of( + "checkedColor", + Color.BLACK, + "borderColor", + Color.BLACK, + "checkmarkColor", + Color.BLACK, + "checkedTextColor", + Color.BLACK, + "checkboxSize", + 16.0, + "checkboxBorderRadius", + 0.0, + "checkedStrikethrough", + false, + ), + ) + return StyleConfig(style, context, false, 0f) + } +} diff --git a/packages/react-native-enriched-markdown/ios/utils/HTMLGenerator.m b/packages/react-native-enriched-markdown/ios/utils/HTMLGenerator.m index 77e8af072..f0018dfd2 100644 --- a/packages/react-native-enriched-markdown/ios/utils/HTMLGenerator.m +++ b/packages/react-native-enriched-markdown/ios/utils/HTMLGenerator.m @@ -167,7 +167,7 @@ - (instancetype)init #pragma mark - HTML Escaping -static void appendEscapedHTML(NSMutableString *output, NSString *text) +static void appendEscapedHTML(NSMutableString *output, NSString *text, BOOL preserveLineBreaks) { NSUInteger length = text.length; if (length == 0) @@ -191,6 +191,18 @@ static void appendEscapedHTML(NSMutableString *output, NSString *text) case '\'': [output appendString:@"'"]; break; + case '\r': + case '\n': + case 0x2028: + case 0x2029: + if (preserveLineBreaks) { + if (c == '\r' && i + 1 < length && [text characterAtIndex:i + 1] == '\n') + i++; + [output appendString:@"
    "]; + } else { + [output appendFormat:@"%C", c]; + } + break; default: [output appendFormat:@"%C", c]; break; @@ -198,19 +210,23 @@ static void appendEscapedHTML(NSMutableString *output, NSString *text) } } -static NSString *escapeHTML(NSString *text) +static NSString *escapeHTML(NSString *text, BOOL preserveLineBreaks) { // Fast path: skip if no special chars static NSCharacterSet *escapeChars = nil; + static NSCharacterSet *inlineEscapeChars = nil; static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ escapeChars = [NSCharacterSet characterSetWithCharactersInString:@"&<>\"'"]; }); + dispatch_once(&onceToken, ^{ + escapeChars = [NSCharacterSet characterSetWithCharactersInString:@"&<>\"'"]; + inlineEscapeChars = [NSCharacterSet characterSetWithCharactersInString:@"&<>\"'\n\r\u2028\u2029"]; + }); - if ([text rangeOfCharacterFromSet:escapeChars].location == NSNotFound) { + if ([text rangeOfCharacterFromSet:preserveLineBreaks ? inlineEscapeChars : escapeChars].location == NSNotFound) { return text; } NSMutableString *escaped = [NSMutableString stringWithCapacity:text.length + 16]; - appendEscapedHTML(escaped, text); + appendEscapedHTML(escaped, text, preserveLineBreaks); return escaped; } @@ -379,7 +395,8 @@ static ParagraphType getParagraphType(NSDictionary *attrs) NSUInteger count = 0; while (currentIndex < string.length) { - NSRange lineRange = [string lineRangeForRange:NSMakeRange(currentIndex, 0)]; + // Hard breaks render as U+2028 and must stay inside their block, so split on paragraphs, not lines. + NSRange lineRange = [string paragraphRangeForRange:NSMakeRange(currentIndex, 0)]; ParagraphData para = { .range = lineRange, .type = ParagraphTypeNormal, .depth = 0, .listNumber = 1, .isTaskChecked = NO}; @@ -496,7 +513,7 @@ static void generateInlineHTML(NSMutableString *html, NSAttributedString *attrib @"padding: %.0fpx %.0fpx; border-radius: %.0fpx; " @"font-size: 1em; font-family: Menlo, Monaco, Consolas, monospace;\">%@", styles.codeBackgroundColor, styles.codeColor, kCodePadding, kCodePadding * 2, - kCodeBorderRadius, escapeHTML(math.latex)]; + kCodeBorderRadius, escapeHTML(math.latex, NO)]; } #endif } @@ -535,11 +552,11 @@ static void generateInlineHTML(NSMutableString *html, NSAttributedString *attrib if (styles.linkFontFamily.length > 0) { [html appendFormat: @"
    ", - escapeHTML(href), styles.linkColor, styles.linkUnderline ? @"underline" : @"none", - styles.linkFontFamily]; + escapeHTML(href, NO), styles.linkColor, + styles.linkUnderline ? @"underline" : @"none", styles.linkFontFamily]; } else { [html appendFormat:@"", - escapeHTML(href), styles.linkColor, + escapeHTML(href, NO), styles.linkColor, styles.linkUnderline ? @"underline" : @"none"]; } } @@ -584,7 +601,7 @@ static void generateInlineHTML(NSMutableString *html, NSAttributedString *attrib } } - [html appendString:escapeHTML(text)]; + [html appendString:escapeHTML(text, !isCodeBlock)]; // Reverse order if ([underline integerValue] > 0 && !linkAttr) diff --git a/packages/react-native-enriched-markdown/ios/utils/MarkdownASTSerializer.m b/packages/react-native-enriched-markdown/ios/utils/MarkdownASTSerializer.m index c6ce7efb4..ffdee1a5e 100644 --- a/packages/react-native-enriched-markdown/ios/utils/MarkdownASTSerializer.m +++ b/packages/react-native-enriched-markdown/ios/utils/MarkdownASTSerializer.m @@ -74,6 +74,12 @@ static void serializeNode(MarkdownASTNode *node, NSMutableString *buffer) [buffer appendString:@"=="]; break; + case MarkdownNodeTypeLatexMathInline: + [buffer appendString:@"$"]; + serializeChildren(node, buffer); + [buffer appendString:@"$"]; + break; + case MarkdownNodeTypeCode: [buffer appendString:@"`"]; serializeChildren(node, buffer); From 01d613931f391c5e3d8e80be472c231ca707a95f Mon Sep 17 00:00:00 2001 From: Gregory Moskaliuk Date: Fri, 16 Oct 2026 21:05:06 +0200 Subject: [PATCH 03/11] fix(ios): retain intrinsic width for explicit line breaks (#1017) * fix(ios): retain tight widths for explicit line breaks * fix(ios): measure explicit-break content with its indents so it does not re-wrap Walk the line fragments once: stop at the first soft wrap (report maxWidth, as before) and otherwise return a tight width that adds each line's head indent and negative tail indent to its used rect. TextKit's usedRect leaves both out, so lists, code blocks and blockquotes measured narrower than they need and re-wrapped once Yoga handed the width back as the frame. Hard breaks are any newlineCharacterSet member at a fragment's end, and the scan exits early once the width reaches maxWidth. ENRMFinalizeMeasuredTextSize reads the layout manager's own text storage and drops its text parameter. Tests render real markdown through the parser and renderer and assert that relaying at the measured width keeps the line count and height, which fails on the previous implementation for lists, code blocks and blockquotes. * refactor(ios): return content width directly from the line fragment scan Soft wrap and reaching maxWidth both resolve to maxWidth, and tightWidth was incomplete whenever hasSoftWrap was set, so the struct carried no information the caller needed. Pass usedRect width as the fallback instead of a 0 sentinel so a zero maxWidth still clamps to 0. --------- Co-authored-by: Yash Singh Co-authored-by: eszlamczyk --- .../__tests__/ios/TextMeasurementTests.mm | 111 ++++++++++++++++++ .../ios/internals/ENRMViewFreeMeasurement.h | 2 +- .../ios/utils/ENRMTextViewSetup.h | 74 ++++++++---- 3 files changed, 166 insertions(+), 21 deletions(-) create mode 100644 packages/react-native-enriched-markdown/__tests__/ios/TextMeasurementTests.mm diff --git a/packages/react-native-enriched-markdown/__tests__/ios/TextMeasurementTests.mm b/packages/react-native-enriched-markdown/__tests__/ios/TextMeasurementTests.mm new file mode 100644 index 000000000..2c1d3007d --- /dev/null +++ b/packages/react-native-enriched-markdown/__tests__/ios/TextMeasurementTests.mm @@ -0,0 +1,111 @@ +#import "../../ios/parser/ENRMMarkdownParser.h" +#import "../../ios/styles/StyleConfig.h" +#import "../../ios/utils/ENRMTextRenderer.h" +#import "../../ios/utils/ENRMTextViewSetup.h" +#import + +typedef struct { + CGSize size; + NSUInteger lineCount; +} ENRMMeasuredLayout; + +static StyleConfig *ENRMMeasurementConfig(void) +{ + StyleConfig *config = [[StyleConfig alloc] init]; + [config setCodeBlockPadding:12]; + [config setBlockquotePadding:12]; + return config; +} + +@interface ENRMTextMeasurementTests : XCTestCase +@end + +@implementation ENRMTextMeasurementTests + +- (ENRMMeasuredLayout)layoutMarkdown:(NSString *)markdown maxWidth:(CGFloat)maxWidth numberOfLines:(NSInteger)lines +{ + StyleConfig *config = ENRMMeasurementConfig(); + MarkdownASTNode *ast = [[[ENRMMarkdownParser alloc] init] parseMarkdown:markdown + flags:[ENRMMd4cFlags defaultFlags] + isGFM:YES]; + ENRMRenderResult *result = ENRMRenderASTNodes(ast.children, config, NO, YES, 0, NSLineBreakStrategyStandard); + + NSTextContainer *container = [[NSTextContainer alloc] initWithSize:CGSizeMake(maxWidth, CGFLOAT_MAX)]; + container.lineFragmentPadding = 0; + if (lines > 0) { + container.maximumNumberOfLines = lines; + container.lineBreakMode = NSLineBreakByTruncatingTail; + } + NSLayoutManager *manager = [[NSLayoutManager alloc] init]; + manager.allowsNonContiguousLayout = NO; + [manager addTextContainer:container]; + NSTextStorage *storage = [[NSTextStorage alloc] initWithAttributedString:result.attributedText]; + [storage addLayoutManager:manager]; + [manager ensureLayoutForTextContainer:container]; + + ENRMTextLayoutResult layout = {[manager usedRectForTextContainer:container], manager.extraLineFragmentRect}; + ENRMMeasuredLayout out; + out.size = + ENRMFinalizeMeasuredTextSize(layout, manager, maxWidth, config, NO, result.lastElementMarginBottom, YES, 3); + __block NSUInteger lineCount = 0; + [manager enumerateLineFragmentsForGlyphRange:NSMakeRange(0, manager.numberOfGlyphs) + usingBlock:^(CGRect, CGRect, NSTextContainer *, NSRange, BOOL *) { lineCount++; }]; + out.lineCount = lineCount; + return out; +} + +// Yoga hands the measured width back as the frame, so relaying at it must not re-wrap. +- (void)assertTight:(NSString *)markdown +{ + ENRMMeasuredLayout measured = [self layoutMarkdown:markdown maxWidth:300 numberOfLines:0]; + XCTAssertLessThan(measured.size.width, 300, @"%@", markdown); + ENRMMeasuredLayout relaid = [self layoutMarkdown:markdown maxWidth:measured.size.width numberOfLines:0]; + XCTAssertEqual(relaid.lineCount, measured.lineCount, @"%@ re-wrapped at %g", markdown, measured.size.width); + XCTAssertEqualWithAccuracy(relaid.size.height, measured.size.height, 0.5, @"%@ at %g", markdown, measured.size.width); +} + +- (void)assertPinned:(NSString *)markdown +{ + XCTAssertEqual([self layoutMarkdown:markdown maxWidth:80 numberOfLines:0].size.width, 80, @"%@", markdown); +} + +- (void)testSingleLineKeepsItsIntrinsicWidth +{ + [self assertTight:@"short"]; + [self assertTight:@"short\n"]; +} + +- (void)testExplicitBreaksKeepTheirIntrinsicWidth +{ + [self assertTight:@"one\n\ntwo"]; + [self assertTight:@"one \ntwo"]; + [self assertTight:@"one\u2028two"]; + [self assertTight:@"one\u2029two"]; + [self assertTight:@"\U0001F600\n\nshort"]; + [self assertTight:@"# Title here\n\nshort"]; +} + +- (void)testIndentedBlocksKeepAWidthThatDoesNotRewrap +{ + [self assertTight:@"- alpha beta\n- gamma"]; + [self assertTight:@"1. alpha beta\n2. gamma"]; + [self assertTight:@"- alpha beta\n- gamma\n - nested item"]; + [self assertTight:@"- [ ] task item\n- [x] done item"]; + [self assertTight:@"```\nsome code here\nmore\n```"]; + [self assertTight:@"> quoted words here\n>\n> more"]; +} + +- (void)testSoftWrappingKeepsTheAvailableWidth +{ + [self assertPinned:@"one two three four five six seven eight nine ten"]; + [self assertPinned:@"short\n\none two three four five six seven eight nine ten"]; + [self assertPinned:@"- a\n- one two three four five six seven eight nine ten"]; + [self assertPinned:@"```\none two three four five six seven eight nine ten\n```"]; +} + +- (void)testLineClampStillMeasuresTight +{ + XCTAssertLessThan([self layoutMarkdown:@"one\n\ntwo three four" maxWidth:300 numberOfLines:1].size.width, 300); +} + +@end diff --git a/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h b/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h index 885353f4e..9b2a31d53 100644 --- a/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h +++ b/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h @@ -156,7 +156,7 @@ static inline CGSize ENRMMeasureAttributedTextViewFree(NSAttributedString *text, layout.usedRect = [layoutManager usedRectForTextContainer:textContainer]; layout.extraLineFragmentRect = layoutManager.extraLineFragmentRect; - return ENRMFinalizeMeasuredTextSize(layout, layoutManager, text, maxWidth, config, allowTrailingMargin, + return ENRMFinalizeMeasuredTextSize(layout, layoutManager, maxWidth, config, allowTrailingMargin, lastElementMarginBottom, subtractExtraLineFragment, pointScaleFactor); } diff --git a/packages/react-native-enriched-markdown/ios/utils/ENRMTextViewSetup.h b/packages/react-native-enriched-markdown/ios/utils/ENRMTextViewSetup.h index 9bd630724..675e5e0c9 100644 --- a/packages/react-native-enriched-markdown/ios/utils/ENRMTextViewSetup.h +++ b/packages/react-native-enriched-markdown/ios/utils/ENRMTextViewSetup.h @@ -30,16 +30,59 @@ static inline void ENRMDetachLayoutManager(ENRMPlatformTextView *textView) } } +/// Returns maxWidth for soft-wrapped content, otherwise the tight width of its +/// lines, or fallbackWidth when no line fragment was laid out. The tight width +/// adds each line's head and tail indent to its used rect, which TextKit leaves +/// out; lists and code blocks re-wrap without them. +static inline CGFloat ENRMContentWidth(NSLayoutManager *layoutManager, CGFloat maxWidth, CGFloat fallbackWidth) +{ + CGFloat tightWidth = 0; + NSTextStorage *storage = layoutManager.textStorage; + NSString *string = storage.string; + NSCharacterSet *newlines = [NSCharacterSet newlineCharacterSet]; + NSUInteger glyphCount = [layoutManager numberOfGlyphs]; + BOOL startsParagraph = YES; + NSUInteger glyphIndex = 0; + while (glyphIndex < glyphCount) { + NSRange lineGlyphRange; + CGRect usedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:glyphIndex effectiveRange:&lineGlyphRange]; + if (lineGlyphRange.location == NSNotFound || NSMaxRange(lineGlyphRange) <= glyphIndex) { + break; // past a numberOfLines clamp: no fragment holds these glyphs + } + NSRange lineCharRange = [layoutManager characterRangeForGlyphRange:lineGlyphRange actualGlyphRange:NULL]; + if (lineCharRange.length == 0) { + break; + } + + NSParagraphStyle *style = [storage attribute:NSParagraphStyleAttributeName + atIndex:lineCharRange.location + effectiveRange:NULL]; + CGFloat headIndent = startsParagraph ? style.firstLineHeadIndent : style.headIndent; + CGFloat tailInset = style.tailIndent < 0 ? -style.tailIndent : 0; + tightWidth = MAX(tightWidth, usedRect.size.width + headIndent + tailInset); + if (tightWidth >= maxWidth) { + return maxWidth; + } + + BOOL endsParagraph = [newlines characterIsMember:[string characterAtIndex:NSMaxRange(lineCharRange) - 1]]; + NSUInteger nextGlyphIndex = NSMaxRange(lineGlyphRange); + if (nextGlyphIndex < glyphCount && !endsParagraph) { + return maxWidth; // soft wrap + } + startsParagraph = endsParagraph; + glyphIndex = nextGlyphIndex; + } + return tightWidth > 0 ? tightWidth : fallbackWidth; +} + /// Turns a raw TextKit layout pass into the final measured size. Shared by /// the view-backed path (`ENRMMeasureMarkdownText`) and the view-free path /// (`ENRMMeasureMarkdownViewFree`) so both measure with one algorithm. /// /// Steps, in order: -/// - Multiline pin: if the first line fragment doesn't span all glyphs the -/// text wrapped, and returning the tight usedRect width would let flexShrink -/// narrow the view below maxWidth, re-wrapping at the narrower width and -/// mismatching the measured height — so multiline content reports maxWidth, -/// while single-line content keeps its tight width for shrink-to-fit. +/// - Soft-wrapped content reports maxWidth: a tight width would let flexShrink +/// narrow the view, re-wrapping it and mismatching the measured height. +/// Content broken only by explicit newlines keeps its tight width. /// - Optionally subtract the extra line fragment (iOS counts a trailing /// newline's empty line fragment into usedRect). Read-only markdown passes /// YES; text input passes NO so trailing newlines keep a blank line (RN Text @@ -51,27 +94,18 @@ static inline void ENRMDetachLayoutManager(ENRMPlatformTextView *textView) /// `RCTScreenScale()` dispatch_syncs to main on first use, which the /// measure path must never do, see issue #550). static inline CGSize ENRMFinalizeMeasuredTextSize(ENRMTextLayoutResult layout, NSLayoutManager *layoutManager, - NSAttributedString *text, CGFloat maxWidth, StyleConfig *config, - BOOL allowTrailingMargin, CGFloat lastElementMarginBottom, - BOOL subtractExtraLineFragment, CGFloat scale) + CGFloat maxWidth, StyleConfig *config, BOOL allowTrailingMargin, + CGFloat lastElementMarginBottom, BOOL subtractExtraLineFragment, + CGFloat scale) { - CGFloat measuredWidth = layout.usedRect.size.width; + CGFloat measuredWidth = ENRMContentWidth(layoutManager, maxWidth, layout.usedRect.size.width); CGFloat measuredHeight = layout.usedRect.size.height; - NSUInteger glyphCount = [layoutManager numberOfGlyphs]; - if (glyphCount > 0) { - NSRange firstLineRange; - [layoutManager lineFragmentRectForGlyphAtIndex:0 effectiveRange:&firstLineRange]; - if (NSMaxRange(firstLineRange) < glyphCount) { - measuredWidth = maxWidth; - } - } - if (subtractExtraLineFragment && !CGRectIsEmpty(layout.extraLineFragmentRect)) { measuredHeight -= layout.extraLineFragmentRect.size.height; } - if (isLastElementCodeBlock(text)) { + if (isLastElementCodeBlock(layoutManager.textStorage)) { measuredHeight += [config codeBlockPadding]; } @@ -91,7 +125,7 @@ static inline CGSize ENRMMeasureMarkdownText(ENRMPlatformTextView *textView, CGF } ENRMTextLayoutResult layout = ENRMMeasureTextLayout(textView, maxWidth); - return ENRMFinalizeMeasuredTextSize(layout, textView.layoutManager, text, maxWidth, config, allowTrailingMargin, + return ENRMFinalizeMeasuredTextSize(layout, textView.layoutManager, maxWidth, config, allowTrailingMargin, lastElementMarginBottom, YES, RCTScreenScale()); } From f1a8987e06877ee4c414c79c70597cec8268b7f5 Mon Sep 17 00:00:00 2001 From: Ernest Szlamczyk <127619251+eszlamczyk@users.noreply.github.com> Date: Fri, 16 Oct 2026 23:15:47 +0200 Subject: [PATCH 04/11] fix: isolate the embedded parser behind an ENRMRKD_ prefix (#922) * fix: isolate the embedded parser behind an ENRMRKD_ prefix Enriched embedded MD4C under its original global names, so an application that also links another MD4C copy failed with a duplicate definition of md_parse, and the CocoaPods header map could resolve the bare md4c.h include in the Objective-C++ input parser to another pod's copy (#846). Vendor the parser from software-mansion-labs/md4c rather than mity/md4c: the fork renames both the filenames and everything they expose to an ENRMRKD_/enrmrkd_ prefix, so two copies can coexist. Rename the consumers to match, and follow the vendored directory rename through the podspecs, the SwiftPM manifest, the Android CMake files and the example app project. Includes stay plain and keep resolving through each target's header search paths; what removes the header map ambiguity is the filename being specific to the fork, since no other pod ships an enrmrkd.h. The public API is unchanged: md4cFlags, Md4cFlags, MD4CParser and md4cType keep their names. Re-vendoring also moves the parser forward to the fork's master, which carries upstream work postdating the Sep 17 snapshot (HTML block start condition 4, the pipe handling rework, the video tag revert). Serialized ASTs are identical for every markdown file in the repo across five flag variants, and differ on 49 of 1000 generated adversarial documents - for instance an empty "||||" spoiler now staying literal text. Co-Authored-By: Claude Opus 5 (1M context) * test(core): guard the vendored parser with golden ASTs in CI The parser is synced from software-mansion-labs/md4c, so a sync can change how documents parse without any native build noticing. That is not hypothetical: the migration in the previous commit silently dropped video rendering, because the fork had inherited upstream's revert of ... + * Detail: Structure ENRMRKD_SPAN_A_DETAIL. */ + ENRMRKD_SPAN_A, + + /* ... + * Detail: Structure ENRMRKD_SPAN_IMG_DETAIL. + * Note: Image text can contain nested spans and even nested images. + * If rendered into ALT attribute of HTML tag, it's responsibility + * of the caller to deal with it. + */ + ENRMRKD_SPAN_IMG, + + /* ... */ + ENRMRKD_SPAN_CODE, + + /* ... + * Syntax: ++insert++ + * Note: Recognized only when ENRMRKD_FLAG_INSERT is enabled. */ + ENRMRKD_SPAN_INS, + + /* ... + * Note: Recognized only when ENRMRKD_FLAG_STRIKETHROUGH is enabled. + */ + ENRMRKD_SPAN_DEL, + + /* For recognizing inline ($) and display ($$) equations + * Note: Recognized only when ENRMRKD_FLAG_LATEXMATHSPANS is enabled. + */ + ENRMRKD_SPAN_LATEXMATH, + ENRMRKD_SPAN_LATEXMATH_DISPLAY, + + /* Wiki links + * Note: Recognized only when ENRMRKD_FLAG_WIKILINKS is enabled. + */ + ENRMRKD_SPAN_WIKILINK, + + /* ... + * Note: Recognized only when ENRMRKD_FLAG_UNDERLINE is enabled. */ + ENRMRKD_SPAN_U, + + /* Spoiler (hidden content revealed on interaction). + * Syntax: ||hidden text|| + * Note: Recognized only when ENRMRKD_FLAG_SPOILERS is enabled. */ + ENRMRKD_SPAN_SPOILER, + + /* ... + * Syntax: ^superscript^ + * Note: Recognized only when ENRMRKD_FLAG_SUPERSCRIPTS is enabled. */ + ENRMRKD_SPAN_SUPERSCRIPT, + + /* ... + * Syntax: ~subscript~ + * Note: Recognized only when ENRMRKD_FLAG_SUBSCRIPTS is enabled. */ + ENRMRKD_SPAN_SUBSCRIPT, + + /* Footnote reference, e.g. [^1] or [^note]. + * Syntax: [^label] + * Note: Recognized only when ENRMRKD_FLAG_FOOTNOTES is enabled. + * The span is self-contained: no ENRMRKD_TEXT callbacks fire between enter and + * leave. All needed information is in ENRMRKD_SPAN_FOOTNOTE_REF_DETAIL. */ + ENRMRKD_SPAN_FOOTNOTE_REF, + + /* ... + * Syntax: ==highlight== + * Note: Recognized only when ENRMRKD_FLAG_HIGHLIGHT is enabled. */ + ENRMRKD_SPAN_MARK +} ENRMRKD_SPANTYPE; + +/* Text is the actual textual contents of span. */ +typedef enum ENRMRKD_TEXTTYPE { + /* Normal text. */ + ENRMRKD_TEXT_NORMAL = 0, + + /* NULL character. CommonMark requires replacing NULL character with + * the replacement char U+FFFD, so this allows caller to do that easily. */ + ENRMRKD_TEXT_NULLCHAR, + + /* Line breaks. + * Note these are not sent from blocks with verbatim output (ENRMRKD_BLOCK_CODE + * or ENRMRKD_BLOCK_HTML). In such cases, '\n' is part of the text itself. */ + ENRMRKD_TEXT_BR, /*
    (hard break) */ + ENRMRKD_TEXT_SOFTBR, /* '\n' in source text where it is not semantically meaningful (soft break) */ + + /* Entity. + * (a) Named entity, e.g.   + * (Note MD4C does not have a list of known entities. + * Anything matching the regexp /&[A-Za-z][A-Za-z0-9]{1,47};/ is + * treated as a named entity.) + * (b) Numerical entity, e.g. Ӓ + * (c) Hexadecimal entity, e.g. ካ + * + * As MD4C is mostly encoding agnostic, application gets the verbatim + * entity text into the ENRMRKD_PARSER::text_callback(). */ + ENRMRKD_TEXT_ENTITY, + + /* Text in a code block (inside ENRMRKD_BLOCK_CODE) or inlined code (`code`). + * If it is inside ENRMRKD_BLOCK_CODE, it includes spaces for indentation and + * '\n' for new lines. ENRMRKD_TEXT_BR and ENRMRKD_TEXT_SOFTBR are not sent for this + * kind of text. */ + ENRMRKD_TEXT_CODE, + + /* Text is a raw HTML. If it is contents of a raw HTML block (i.e. not + * an inline raw HTML), then ENRMRKD_TEXT_BR and ENRMRKD_TEXT_SOFTBR are not used. + * The text contains verbatim '\n' for the new lines. */ + ENRMRKD_TEXT_HTML, + + /* Text is inside an equation. This is processed the same way as inlined code + * spans (`code`). */ + ENRMRKD_TEXT_LATEXMATH +} ENRMRKD_TEXTTYPE; + + +/* Alignment enumeration. */ +typedef enum ENRMRKD_ALIGN { + ENRMRKD_ALIGN_DEFAULT = 0, /* When unspecified. */ + ENRMRKD_ALIGN_LEFT, + ENRMRKD_ALIGN_CENTER, + ENRMRKD_ALIGN_RIGHT +} ENRMRKD_ALIGN; + + +/* String attribute. + * + * This wraps strings which are outside of a normal text flow and which are + * propagated within various detailed structures, but which still may contain + * string portions of different types like e.g. entities. + * + * So, for example, lets consider this image: + * + * ![image alt text](http://example.org/image.png 'foo " bar') + * + * The image alt text is propagated as a normal text via the ENRMRKD_PARSER::text() + * callback. However, the image title ('foo " bar') is propagated as + * ENRMRKD_ATTRIBUTE in ENRMRKD_SPAN_IMG_DETAIL::title. + * + * Then the attribute ENRMRKD_SPAN_IMG_DETAIL::title shall provide the following: + * -- [0]: "foo " (substr_types[0] == ENRMRKD_TEXT_NORMAL; substr_offsets[0] == 0) + * -- [1]: """ (substr_types[1] == ENRMRKD_TEXT_ENTITY; substr_offsets[1] == 4) + * -- [2]: " bar" (substr_types[2] == ENRMRKD_TEXT_NORMAL; substr_offsets[2] == 10) + * -- [3]: (n/a) (n/a ; substr_offsets[3] == 14) + * + * Note that these invariants are always guaranteed: + * -- substr_offsets[0] == 0 + * -- substr_offsets[LAST+1] == size + * -- Currently, only ENRMRKD_TEXT_NORMAL, ENRMRKD_TEXT_ENTITY, ENRMRKD_TEXT_NULLCHAR + * substrings can appear. This could change only if the specification + * changes. + */ +typedef struct ENRMRKD_ATTRIBUTE { + const ENRMRKD_CHAR* text; + ENRMRKD_SIZE size; + const ENRMRKD_TEXTTYPE* substr_types; + const ENRMRKD_OFFSET* substr_offsets; +} ENRMRKD_ATTRIBUTE; + + +/* Detailed info for ENRMRKD_BLOCK_UL. */ +typedef struct ENRMRKD_BLOCK_UL_DETAIL { + int is_tight; /* Non-zero if tight list, zero if loose. */ + ENRMRKD_CHAR mark; /* Item bullet character in MarkDown source of the list, e.g. '-', '+', '*'. */ +} ENRMRKD_BLOCK_UL_DETAIL; + +/* Detailed info for ENRMRKD_BLOCK_OL. */ +typedef struct ENRMRKD_BLOCK_OL_DETAIL { + unsigned start; /* Start index of the ordered list. */ + int is_tight; /* Non-zero if tight list, zero if loose. */ + ENRMRKD_CHAR mark_delimiter; /* Character delimiting the item marks in MarkDown source, e.g. '.' or ')' */ +} ENRMRKD_BLOCK_OL_DETAIL; + +/* Detailed info for ENRMRKD_BLOCK_LI. */ +typedef struct ENRMRKD_BLOCK_LI_DETAIL { + int is_task; /* Can be non-zero only with ENRMRKD_FLAG_TASKLISTS */ + ENRMRKD_CHAR task_mark; /* If is_task, then one of 'x', 'X' or ' '. Undefined otherwise. */ + ENRMRKD_OFFSET task_mark_offset; /* If is_task, then offset in the input of the char between '[' and ']'. */ +} ENRMRKD_BLOCK_LI_DETAIL; + +/* Detailed info for ENRMRKD_BLOCK_H. */ +typedef struct ENRMRKD_BLOCK_H_DETAIL { + unsigned level; /* Header level (1 - 6) */ +} ENRMRKD_BLOCK_H_DETAIL; + +/* Detailed info for ENRMRKD_BLOCK_CODE. */ +typedef struct ENRMRKD_BLOCK_CODE_DETAIL { + ENRMRKD_ATTRIBUTE info; + ENRMRKD_ATTRIBUTE lang; + ENRMRKD_CHAR fence_char; /* The character used for fenced code block; or zero for indented code block. */ +} ENRMRKD_BLOCK_CODE_DETAIL; + +/* Detailed info for ENRMRKD_BLOCK_TABLE. */ +typedef struct ENRMRKD_BLOCK_TABLE_DETAIL { + unsigned col_count; /* Count of columns in the table. */ + unsigned head_row_count; /* Count of rows in the table header (currently always 1) */ + unsigned body_row_count; /* Count of rows in the table body */ +} ENRMRKD_BLOCK_TABLE_DETAIL; + +/* Detailed info for ENRMRKD_BLOCK_TH and ENRMRKD_BLOCK_TD. */ +typedef struct ENRMRKD_BLOCK_TD_DETAIL { + ENRMRKD_ALIGN align; +} ENRMRKD_BLOCK_TD_DETAIL; + +/* Detailed info for ENRMRKD_BLOCK_ADMONITION. */ +typedef struct ENRMRKD_BLOCK_ADMONITION_DETAIL { + ENRMRKD_ATTRIBUTE type; /* One of "note", "tip", "important", "warning", "caution" */ +} ENRMRKD_BLOCK_ADMONITION_DETAIL; + +/* Detailed info for ENRMRKD_SPAN_A. */ +typedef struct ENRMRKD_SPAN_A_DETAIL { + ENRMRKD_ATTRIBUTE href; + ENRMRKD_ATTRIBUTE title; + int is_autolink; /* nonzero if this is an autolink */ +} ENRMRKD_SPAN_A_DETAIL; + +/* Detailed info for ENRMRKD_SPAN_IMG. */ +typedef struct ENRMRKD_SPAN_IMG_DETAIL { + ENRMRKD_ATTRIBUTE src; + ENRMRKD_ATTRIBUTE title; +} ENRMRKD_SPAN_IMG_DETAIL; + +/* Detailed info for ENRMRKD_SPAN_WIKILINK. */ +typedef struct ENRMRKD_SPAN_WIKILINK { + ENRMRKD_ATTRIBUTE target; +} ENRMRKD_SPAN_WIKILINK_DETAIL; + +/* Detailed info for ENRMRKD_SPAN_FOOTNOTE_REF. */ +typedef struct ENRMRKD_SPAN_FOOTNOTE_REF_DETAIL { + unsigned int id; /* 1-based identifier of the referenced footnote */ + unsigned int ref_id; /* 1-based identifier of this reference among references to the same footnote */ + ENRMRKD_ATTRIBUTE label; /* Raw label text, e.g. "1" or "note" */ +} ENRMRKD_SPAN_FOOTNOTE_REF_DETAIL; + +/* Detailed info for ENRMRKD_BLOCK_FOOTNOTE_DEF. */ +typedef struct ENRMRKD_BLOCK_FOOTNOTE_DEF_DETAIL { + unsigned int id; /* 1-based identifier of this footnote */ + unsigned int ref_count; /* Number of references to this footnote */ + ENRMRKD_ATTRIBUTE label; /* Raw label text */ +} ENRMRKD_BLOCK_FOOTNOTE_DEF_DETAIL; + +/* Detailed info for ENRMRKD_BLOCK_BLANK. */ +typedef struct ENRMRKD_BLOCK_BLANK_DETAIL { + unsigned line_count; /* Count of blank lines forming the block separation */ +} ENRMRKD_BLOCK_BLANK_DETAIL; + +/* Flags specifying extensions/deviations from CommonMark specification. + * + * By default (when ENRMRKD_PARSER::flags == 0), we follow CommonMark specification. + * The following flags may allow some extensions or deviations from it. + */ +#define ENRMRKD_FLAG_COLLAPSEWHITESPACE 0x1 /* In ENRMRKD_TEXT_NORMAL, collapse non-trivial whitespace into single ' ' */ +#define ENRMRKD_FLAG_PERMISSIVEATXHEADERS 0x2 /* Do not require space in ATX headers ( ###header ) */ +#define ENRMRKD_FLAG_PERMISSIVEURLAUTOLINKS 0x4 /* Recognize URLs as autolinks even without '<', '>' */ +#define ENRMRKD_FLAG_PERMISSIVEEMAILAUTOLINKS 0x8 /* Recognize e-mails as autolinks even without '<', '>' and 'mailto:' */ +#define ENRMRKD_FLAG_NOINDENTEDCODEBLOCKS 0x10 /* Disable indented code blocks. (Only fenced code works.) */ +#define ENRMRKD_FLAG_NOHTMLBLOCKS 0x20 /* Disable raw HTML blocks. */ +#define ENRMRKD_FLAG_NOHTMLSPANS 0x40 /* Disable raw HTML (inline). */ +#define ENRMRKD_FLAG_TABLES 0x100 /* Enable tables extension. */ +#define ENRMRKD_FLAG_STRIKETHROUGH 0x200 /* Enable strikethrough extension. */ +#define ENRMRKD_FLAG_PERMISSIVEWWWAUTOLINKS 0x400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */ +#define ENRMRKD_FLAG_TASKLISTS 0x800 /* Enable task list extension. */ +#define ENRMRKD_FLAG_LATEXMATHSPANS 0x1000 /* Enable $ and $$ containing LaTeX equations. */ +#define ENRMRKD_FLAG_WIKILINKS 0x2000 /* Enable wiki links extension. */ +#define ENRMRKD_FLAG_UNDERLINE 0x4000 /* Enable underline extension (and disables '_' for normal emphasis). */ +#define ENRMRKD_FLAG_HARD_SOFT_BREAKS 0x8000 /* Force all soft breaks to act as hard breaks. */ +#define ENRMRKD_FLAG_SPOILERS 0x10000 /* Enable ||hidden text|| spoiler spans. */ +#define ENRMRKD_FLAG_SUPERSCRIPTS 0x20000 /* Enable ^superscript^ spans. */ +#define ENRMRKD_FLAG_SUBSCRIPTS 0x40000 /* Enable ~subscript~ spans. */ +#define ENRMRKD_FLAG_ADMONITIONS 0x80000 /* Enable admonitions extension. */ +#define ENRMRKD_FLAG_FOOTNOTES 0x100000 /* Enable [^label] footnote references. */ +#define ENRMRKD_FLAG_HIGHLIGHT 0x200000 /* Enable ==highlight== spans. */ +#define ENRMRKD_FLAG_PRESERVEBLANKLINES 0x400000 /* Report blank line runs as ENRMRKD_BLOCK_BLANK. */ +#define ENRMRKD_FLAG_INSERT 0x800000 /* Enable insert extension. */ + +#define ENRMRKD_FLAG_PERMISSIVEAUTOLINKS (ENRMRKD_FLAG_PERMISSIVEEMAILAUTOLINKS | ENRMRKD_FLAG_PERMISSIVEURLAUTOLINKS | ENRMRKD_FLAG_PERMISSIVEWWWAUTOLINKS) +#define ENRMRKD_FLAG_NOHTML (ENRMRKD_FLAG_NOHTMLBLOCKS | ENRMRKD_FLAG_NOHTMLSPANS) + +/* Convenient sets of flags corresponding to well-known Markdown dialects. + * + * Note we may only support subset of features of the referred dialect. + * The constant just enables those extensions which bring us as close as + * possible given what features we implement. + * + * ABI compatibility note: Meaning of these can change in time as new + * extensions, bringing the dialect closer to the original, are implemented. + */ +#define ENRMRKD_DIALECT_COMMONMARK 0 +#define ENRMRKD_DIALECT_GITHUB (ENRMRKD_FLAG_PERMISSIVEAUTOLINKS | ENRMRKD_FLAG_TABLES | ENRMRKD_FLAG_STRIKETHROUGH | ENRMRKD_FLAG_TASKLISTS | ENRMRKD_FLAG_ADMONITIONS | ENRMRKD_FLAG_FOOTNOTES) + +/* Parser structure. + */ +typedef struct ENRMRKD_PARSER { + /* Reserved. Set to zero. + */ + unsigned abi_version; + + /* Dialect options. Bitmask of ENRMRKD_FLAG_xxxx values. + */ + unsigned flags; + + /* Caller-provided rendering callbacks. + * + * For some block/span types, more detailed information is provided in a + * type-specific structure pointed by the argument 'detail'. + * + * The last argument of all callbacks, 'userdata', is just propagated from + * enrmrkd_parse() and is available for any use by the application. + * + * Note any strings provided to the callbacks as their arguments or as + * members of any detail structure are generally not zero-terminated. + * Application has to take the respective size information into account. + * + * Any rendering callback may abort further parsing of the document by + * returning non-zero. + */ + int (*enter_block)(ENRMRKD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + int (*leave_block)(ENRMRKD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + + int (*enter_span)(ENRMRKD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + int (*leave_span)(ENRMRKD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + + int (*text)(ENRMRKD_TEXTTYPE /*type*/, const ENRMRKD_CHAR* /*text*/, ENRMRKD_SIZE /*size*/, void* /*userdata*/); + + /* Debug callback. Optional (may be NULL). + * + * If provided and something goes wrong, this function gets called. + * This is intended for debugging and problem diagnosis for developers; + * it is not intended to provide any errors suitable for displaying to an + * end user. + */ + void (*debug_log)(const char* /*msg*/, void* /*userdata*/); + + /* Reserved. Set to NULL. + */ + void (*syntax)(void); +} ENRMRKD_PARSER; + + +/* For backward compatibility. Do not use in new code. + */ +typedef ENRMRKD_PARSER ENRMRKD_RENDERER; + + +/* Parse the Markdown document stored in the string 'text' of size 'size'. + * The parser provides callbacks to be called during the parsing so the + * caller can render the document on the screen or convert the Markdown + * to another format. + * + * Zero is returned on success. If a runtime error occurs (e.g. a memory + * fails), -1 is returned. If the processing is aborted due any callback + * returning non-zero, the return value of the callback is returned. + */ +int enrmrkd_parse(const ENRMRKD_CHAR* text, ENRMRKD_SIZE size, const ENRMRKD_PARSER* parser, void* userdata); + + +#ifdef __cplusplus + } /* extern "C" { */ +#endif + +#endif /* ENRMRKD_H */ diff --git a/packages/core/cpp/md4c/md4c.h b/packages/core/cpp/md4c/md4c.h deleted file mode 100644 index cf965d8cc..000000000 --- a/packages/core/cpp/md4c/md4c.h +++ /dev/null @@ -1,492 +0,0 @@ -/* - * MD4C: Markdown parser for C - * (https://github.com/mity/md4c) - * - * Copyright (c) 2016-2026 Martin Mitáš - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MD4C_H -#define MD4C_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined MD4C_USE_UTF16 -/* Magic to support UTF-16. Note that in order to use it, you have to define - * the macro MD4C_USE_UTF16 both when building MD4C as well as when - * including this header in your code. */ -#ifdef _WIN32 -#include -typedef WCHAR MD_CHAR; -#else -#error MD4C_USE_UTF16 is only supported on Windows. -#endif -#else -typedef char MD_CHAR; -#endif - -typedef unsigned MD_SIZE; -typedef unsigned MD_OFFSET; - -/* Block represents a part of document hierarchy structure like a paragraph - * or list item. - */ -typedef enum MD_BLOCKTYPE { - /* ... */ - MD_BLOCK_DOC = 0, - - /*
    ...
    */ - MD_BLOCK_QUOTE, - - /*
      ...
    - * Detail: Structure MD_BLOCK_UL_DETAIL. */ - MD_BLOCK_UL, - - /*
      ...
    - * Detail: Structure MD_BLOCK_OL_DETAIL. */ - MD_BLOCK_OL, - - /*
  • ...
  • - * Detail: Structure MD_BLOCK_LI_DETAIL. */ - MD_BLOCK_LI, - - /*
    */ - MD_BLOCK_HR, - - /*

    ...

    (for levels up to 6) - * Detail: Structure MD_BLOCK_H_DETAIL. */ - MD_BLOCK_H, - - /*
    ...
    - * Note the text lines within code blocks are terminated with '\n' - * instead of explicit MD_TEXT_BR. */ - MD_BLOCK_CODE, - - /* Raw HTML block. This itself does not correspond to any particular HTML - * tag. The contents of it _is_ raw HTML source intended to be put - * in verbatim form to the HTML output. */ - MD_BLOCK_HTML, - - /*

    ...

    */ - MD_BLOCK_P, - - /* ...
    and its contents. - * Detail: Structure MD_BLOCK_TABLE_DETAIL (for MD_BLOCK_TABLE), - * structure MD_BLOCK_TD_DETAIL (for MD_BLOCK_TH and MD_BLOCK_TD) - * Note all of these are used only if extension MD_FLAG_TABLES is enabled. */ - MD_BLOCK_TABLE, - MD_BLOCK_THEAD, - MD_BLOCK_TBODY, - MD_BLOCK_TR, - MD_BLOCK_TH, - MD_BLOCK_TD, - - /* Container for all referenced footnote definitions, rendered at the end - * of the document. - * Detail: NULL. - * Note: Used only if extension MD_FLAG_FOOTNOTES is enabled, and only when - * at least one footnote definition is referenced. */ - MD_BLOCK_FOOTNOTE_DEF_SECTION, - - /* A single footnote definition, rendered at the end of the document. - * Detail: Structure MD_BLOCK_FOOTNOTE_DEF_DETAIL. - * Note: Used only if extension MD_FLAG_FOOTNOTES is enabled. - * Only definitions that are actually referenced in the document are - * emitted, in order of first reference. */ - MD_BLOCK_FOOTNOTE_DEF, - - /* Adminition extension. - * Detail MD_BLOCK_ADMONITION_DETAIL. - * Note: Recognized only when MD_FLAG_ADMONITIONS is enabled. */ - MD_BLOCK_ADMONITION, - - /* A run of blank lines separating two blocks. Has no contents. - * Detail: Structure MD_BLOCK_BLANK_DETAIL. - * Note: Emitted only when MD_FLAG_PRESERVEBLANKLINES is enabled. */ - MD_BLOCK_BLANK -} MD_BLOCKTYPE; - -/* Span represents an in-line piece of a document which should be rendered with - * the same font, color and other attributes. A sequence of spans forms a block - * like paragraph or list item. */ -typedef enum MD_SPANTYPE { - /* ... */ - MD_SPAN_EM, - - /* ... */ - MD_SPAN_STRONG, - - /* ... - * Detail: Structure MD_SPAN_A_DETAIL. */ - MD_SPAN_A, - - /* ... - * Detail: Structure MD_SPAN_IMG_DETAIL. - * Note: Image text can contain nested spans and even nested images. - * If rendered into ALT attribute of HTML tag, it's responsibility - * of the parser to deal with it. - */ - MD_SPAN_IMG, - - /* ... */ - MD_SPAN_CODE, - - /* ... - * Syntax: ++insert++ - * Note: Recognized only when MD_FLAG_INSERT is enabled. */ - MD_SPAN_INS, - - /* ... - * Note: Recognized only when MD_FLAG_STRIKETHROUGH is enabled. - */ - MD_SPAN_DEL, - - /* For recognizing inline ($) and display ($$) equations - * Note: Recognized only when MD_FLAG_LATEXMATHSPANS is enabled. - */ - MD_SPAN_LATEXMATH, - MD_SPAN_LATEXMATH_DISPLAY, - - /* Wiki links - * Note: Recognized only when MD_FLAG_WIKILINKS is enabled. - */ - MD_SPAN_WIKILINK, - - /* ... - * Note: Recognized only when MD_FLAG_UNDERLINE is enabled. */ - MD_SPAN_U, - - /* Spoiler (hidden content revealed on interaction). - * Syntax: ||hidden text|| - * Note: Recognized only when MD_FLAG_SPOILERS is enabled. */ - MD_SPAN_SPOILER, - - /* ... - * Syntax: ^superscript^ - * Note: Recognized only when MD_FLAG_SUPERSCRIPTS is enabled. */ - MD_SPAN_SUPERSCRIPT, - - /* ... - * Syntax: ~subscript~ - * Note: Recognized only when MD_FLAG_SUBSCRIPTS is enabled. */ - MD_SPAN_SUBSCRIPT, - - /* Footnote reference, e.g. [^1] or [^note]. - * Syntax: [^label] - * Note: Recognized only when MD_FLAG_FOOTNOTES is enabled. - * The span is self-contained: no MD_TEXT callbacks fire between enter and - * leave. All needed information is in MD_SPAN_FOOTNOTE_REF_DETAIL. */ - MD_SPAN_FOOTNOTE_REF, - - /* ... - * Syntax: ==highlight== - * Note: Recognized only when MD_FLAG_HIGHLIGHT is enabled. */ - MD_SPAN_MARK -} MD_SPANTYPE; - -/* Text is the actual textual contents of span. */ -typedef enum MD_TEXTTYPE { - /* Normal text. */ - MD_TEXT_NORMAL = 0, - - /* NULL character. CommonMark requires replacing NULL character with - * the replacement char U+FFFD, so this allows caller to do that easily. */ - MD_TEXT_NULLCHAR, - - /* Line breaks. - * Note these are not sent from blocks with verbatim output (MD_BLOCK_CODE - * or MD_BLOCK_HTML). In such cases, '\n' is part of the text itself. */ - MD_TEXT_BR, /*
    (hard break) */ - MD_TEXT_SOFTBR, /* '\n' in source text where it is not semantically meaningful (soft break) */ - - /* Entity. - * (a) Named entity, e.g.   - * (Note MD4C does not have a list of known entities. - * Anything matching the regexp /&[A-Za-z][A-Za-z0-9]{1,47};/ is - * treated as a named entity.) - * (b) Numerical entity, e.g. Ӓ - * (c) Hexadecimal entity, e.g. ካ - * - * As MD4C is mostly encoding agnostic, application gets the verbatim - * entity text into the MD_PARSER::text_callback(). */ - MD_TEXT_ENTITY, - - /* Text in a code block (inside MD_BLOCK_CODE) or inlined code (`code`). - * If it is inside MD_BLOCK_CODE, it includes spaces for indentation and - * '\n' for new lines. MD_TEXT_BR and MD_TEXT_SOFTBR are not sent for this - * kind of text. */ - MD_TEXT_CODE, - - /* Text is a raw HTML. If it is contents of a raw HTML block (i.e. not - * an inline raw HTML), then MD_TEXT_BR and MD_TEXT_SOFTBR are not used. - * The text contains verbatim '\n' for the new lines. */ - MD_TEXT_HTML, - - /* Text is inside an equation. This is processed the same way as inlined code - * spans (`code`). */ - MD_TEXT_LATEXMATH -} MD_TEXTTYPE; - -/* Alignment enumeration. */ -typedef enum MD_ALIGN { - MD_ALIGN_DEFAULT = 0, /* When unspecified. */ - MD_ALIGN_LEFT, - MD_ALIGN_CENTER, - MD_ALIGN_RIGHT -} MD_ALIGN; - -/* String attribute. - * - * This wraps strings which are outside of a normal text flow and which are - * propagated within various detailed structures, but which still may contain - * string portions of different types like e.g. entities. - * - * So, for example, lets consider this image: - * - * ![image alt text](http://example.org/image.png 'foo " bar') - * - * The image alt text is propagated as a normal text via the MD_PARSER::text() - * callback. However, the image title ('foo " bar') is propagated as - * MD_ATTRIBUTE in MD_SPAN_IMG_DETAIL::title. - * - * Then the attribute MD_SPAN_IMG_DETAIL::title shall provide the following: - * -- [0]: "foo " (substr_types[0] == MD_TEXT_NORMAL; substr_offsets[0] == 0) - * -- [1]: """ (substr_types[1] == MD_TEXT_ENTITY; substr_offsets[1] == 4) - * -- [2]: " bar" (substr_types[2] == MD_TEXT_NORMAL; substr_offsets[2] == 10) - * -- [3]: (n/a) (n/a ; substr_offsets[3] == 14) - * - * Note that these invariants are always guaranteed: - * -- substr_offsets[0] == 0 - * -- substr_offsets[LAST+1] == size - * -- Currently, only MD_TEXT_NORMAL, MD_TEXT_ENTITY, MD_TEXT_NULLCHAR - * substrings can appear. This could change only of the specification - * changes. - */ -typedef struct MD_ATTRIBUTE { - const MD_CHAR *text; - MD_SIZE size; - const MD_TEXTTYPE *substr_types; - const MD_OFFSET *substr_offsets; -} MD_ATTRIBUTE; - -/* Detailed info for MD_BLOCK_UL. */ -typedef struct MD_BLOCK_UL_DETAIL { - int is_tight; /* Non-zero if tight list, zero if loose. */ - MD_CHAR mark; /* Item bullet character in MarkDown source of the list, e.g. '-', '+', '*'. */ -} MD_BLOCK_UL_DETAIL; - -/* Detailed info for MD_BLOCK_OL. */ -typedef struct MD_BLOCK_OL_DETAIL { - unsigned start; /* Start index of the ordered list. */ - int is_tight; /* Non-zero if tight list, zero if loose. */ - MD_CHAR mark_delimiter; /* Character delimiting the item marks in MarkDown source, e.g. '.' or ')' */ -} MD_BLOCK_OL_DETAIL; - -/* Detailed info for MD_BLOCK_LI. */ -typedef struct MD_BLOCK_LI_DETAIL { - int is_task; /* Can be non-zero only with MD_FLAG_TASKLISTS */ - MD_CHAR task_mark; /* If is_task, then one of 'x', 'X' or ' '. Undefined otherwise. */ - MD_OFFSET task_mark_offset; /* If is_task, then offset in the input of the char between '[' and ']'. */ -} MD_BLOCK_LI_DETAIL; - -/* Detailed info for MD_BLOCK_H. */ -typedef struct MD_BLOCK_H_DETAIL { - unsigned level; /* Header level (1 - 6) */ -} MD_BLOCK_H_DETAIL; - -/* Detailed info for MD_BLOCK_CODE. */ -typedef struct MD_BLOCK_CODE_DETAIL { - MD_ATTRIBUTE info; - MD_ATTRIBUTE lang; - MD_CHAR fence_char; /* The character used for fenced code block; or zero for indented code block. */ -} MD_BLOCK_CODE_DETAIL; - -/* Detailed info for MD_BLOCK_TABLE. */ -typedef struct MD_BLOCK_TABLE_DETAIL { - unsigned col_count; /* Count of columns in the table. */ - unsigned head_row_count; /* Count of rows in the table header (currently always 1) */ - unsigned body_row_count; /* Count of rows in the table body */ -} MD_BLOCK_TABLE_DETAIL; - -/* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */ -typedef struct MD_BLOCK_TD_DETAIL { - MD_ALIGN align; -} MD_BLOCK_TD_DETAIL; - -/* Detailed info for MD_BLOCK_ADMONITION. */ -typedef struct MD_BLOCK_ADMONITION_DETAIL { - MD_ATTRIBUTE type; /* One of "note", "tip", "important", "warning", "caution" */ -} MD_BLOCK_ADMONITION_DETAIL; - -/* Detailed info for MD_SPAN_A. */ -typedef struct MD_SPAN_A_DETAIL { - MD_ATTRIBUTE href; - MD_ATTRIBUTE title; - int is_autolink; /* nonzero if this is an autolink */ -} MD_SPAN_A_DETAIL; - -/* Detailed info for MD_SPAN_IMG. */ -typedef struct MD_SPAN_IMG_DETAIL { - MD_ATTRIBUTE src; - MD_ATTRIBUTE title; -} MD_SPAN_IMG_DETAIL; - -/* Detailed info for MD_SPAN_WIKILINK. */ -typedef struct MD_SPAN_WIKILINK { - MD_ATTRIBUTE target; -} MD_SPAN_WIKILINK_DETAIL; - -/* Detailed info for MD_SPAN_FOOTNOTE_REF. */ -typedef struct MD_SPAN_FOOTNOTE_REF_DETAIL { - unsigned int id; /* 1-based identifier of the referenced footnote */ - unsigned int ref_id; /* 1-based identifier of this reference among references to the same footnote */ - MD_ATTRIBUTE label; /* Raw label text, e.g. "1" or "note" */ -} MD_SPAN_FOOTNOTE_REF_DETAIL; - -/* Detailed info for MD_BLOCK_FOOTNOTE_DEF. */ -typedef struct MD_BLOCK_FOOTNOTE_DEF_DETAIL { - unsigned int id; /* 1-based identifier of this footnote */ - unsigned int ref_count; /* Number of references to this footnote */ - MD_ATTRIBUTE label; /* Raw label text */ -} MD_BLOCK_FOOTNOTE_DEF_DETAIL; - -/* Detailed info for MD_BLOCK_BLANK. */ -typedef struct MD_BLOCK_BLANK_DETAIL { - unsigned line_count; /* Count of blank lines forming the block separation */ -} MD_BLOCK_BLANK_DETAIL; - -/* Flags specifying extensions/deviations from CommonMark specification. - * - * By default (when MD_PARSER::flags == 0), we follow CommonMark specification. - * The following flags may allow some extensions or deviations from it. - */ -#define MD_FLAG_COLLAPSEWHITESPACE 0x1 /* In MD_TEXT_NORMAL, collapse non-trivial whitespace into single ' ' */ -#define MD_FLAG_PERMISSIVEATXHEADERS 0x2 /* Do not require space in ATX headers ( ###header ) */ -#define MD_FLAG_PERMISSIVEURLAUTOLINKS 0x4 /* Recognize URLs as autolinks even without '<', '>' */ -#define MD_FLAG_PERMISSIVEEMAILAUTOLINKS 0x8 /* Recognize e-mails as autolinks even without '<', '>' and 'mailto:' */ -#define MD_FLAG_NOINDENTEDCODEBLOCKS 0x10 /* Disable indented code blocks. (Only fenced code works.) */ -#define MD_FLAG_NOHTMLBLOCKS 0x20 /* Disable raw HTML blocks. */ -#define MD_FLAG_NOHTMLSPANS 0x40 /* Disable raw HTML (inline). */ -#define MD_FLAG_TABLES 0x100 /* Enable tables extension. */ -#define MD_FLAG_STRIKETHROUGH 0x200 /* Enable strikethrough extension. */ -#define MD_FLAG_PERMISSIVEWWWAUTOLINKS \ - 0x400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */ -#define MD_FLAG_TASKLISTS 0x800 /* Enable task list extension. */ -#define MD_FLAG_LATEXMATHSPANS 0x1000 /* Enable $ and $$ containing LaTeX equations. */ -#define MD_FLAG_WIKILINKS 0x2000 /* Enable wiki links extension. */ -#define MD_FLAG_UNDERLINE 0x4000 /* Enable underline extension (and disables '_' for normal emphasis). */ -#define MD_FLAG_HARD_SOFT_BREAKS 0x8000 /* Force all soft breaks to act as hard breaks. */ -#define MD_FLAG_SPOILERS 0x10000 /* Enable ||hidden text|| spoiler spans. */ -#define MD_FLAG_SUPERSCRIPTS 0x20000 /* Enable ^superscript^ spans. */ -#define MD_FLAG_SUBSCRIPTS 0x40000 /* Enable ~subscript~ spans. */ -#define MD_FLAG_ADMONITIONS 0x80000 /* Enable admonitions extension. */ -#define MD_FLAG_FOOTNOTES 0x100000 /* Enable [^label] footnote references. */ -#define MD_FLAG_HIGHLIGHT 0x200000 /* Enable ==highlight== spans. */ -#define MD_FLAG_PRESERVEBLANKLINES 0x400000 /* Report blank line runs as MD_BLOCK_BLANK. */ -#define MD_FLAG_INSERT 0x800000 /* Enable insert extension. */ - -#define MD_FLAG_PERMISSIVEAUTOLINKS \ - (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS) -#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS) - -/* Convenient sets of flags corresponding to well-known Markdown dialects. - * - * Note we may only support subset of features of the referred dialect. - * The constant just enables those extensions which bring us as close as - * possible given what features we implement. - * - * ABI compatibility note: Meaning of these can change in time as new - * extensions, bringing the dialect closer to the original, are implemented. - */ -#define MD_DIALECT_COMMONMARK 0 -#define MD_DIALECT_GITHUB \ - (MD_FLAG_PERMISSIVEAUTOLINKS | MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_TASKLISTS | MD_FLAG_ADMONITIONS | \ - MD_FLAG_FOOTNOTES) - -/* Parser structure. - */ -typedef struct MD_PARSER { - /* Reserved. Set to zero. - */ - unsigned abi_version; - - /* Dialect options. Bitmask of MD_FLAG_xxxx values. - */ - unsigned flags; - - /* Caller-provided rendering callbacks. - * - * For some block/span types, more detailed information is provided in a - * type-specific structure pointed by the argument 'detail'. - * - * The last argument of all callbacks, 'userdata', is just propagated from - * md_parse() and is available for any use by the application. - * - * Note any strings provided to the callbacks as their arguments or as - * members of any detail structure are generally not zero-terminated. - * Application has to take the respective size information into account. - * - * Any rendering callback may abort further parsing of the document by - * returning non-zero. - */ - int (*enter_block)(MD_BLOCKTYPE /*type*/, void * /*detail*/, void * /*userdata*/); - int (*leave_block)(MD_BLOCKTYPE /*type*/, void * /*detail*/, void * /*userdata*/); - - int (*enter_span)(MD_SPANTYPE /*type*/, void * /*detail*/, void * /*userdata*/); - int (*leave_span)(MD_SPANTYPE /*type*/, void * /*detail*/, void * /*userdata*/); - - int (*text)(MD_TEXTTYPE /*type*/, const MD_CHAR * /*text*/, MD_SIZE /*size*/, void * /*userdata*/); - - /* Debug callback. Optional (may be NULL). - * - * If provided and something goes wrong, this function gets called. - * This is intended for debugging and problem diagnosis for developers; - * it is not intended to provide any errors suitable for displaying to an - * end user. - */ - void (*debug_log)(const char * /*msg*/, void * /*userdata*/); - - /* Reserved. Set to NULL. - */ - void (*syntax)(void); -} MD_PARSER; - -/* For backward compatibility. Do not use in new code. - */ -typedef MD_PARSER MD_RENDERER; - -/* Parse the Markdown document stored in the string 'text' of size 'size'. - * The parser provides callbacks to be called during the parsing so the - * caller can render the document on the screen or convert the Markdown - * to another format. - * - * Zero is returned on success. If a runtime error occurs (e.g. a memory - * fails), -1 is returned. If the processing is aborted due any callback - * returning non-zero, the return value of the callback is returned. - */ -int md_parse(const MD_CHAR *text, MD_SIZE size, const MD_PARSER *parser, void *userdata); - -#ifdef __cplusplus -} /* extern "C" { */ -#endif - -#endif /* MD4C_H */ diff --git a/packages/core/cpp/parser/MD4CParser.cpp b/packages/core/cpp/parser/MD4CParser.cpp index c99a52d97..1c99a7553 100644 --- a/packages/core/cpp/parser/MD4CParser.cpp +++ b/packages/core/cpp/parser/MD4CParser.cpp @@ -1,5 +1,5 @@ #include "MD4CParser.hpp" -#include "../md4c/md4c.h" +#include "enrmrkd.h" #include #include #include @@ -80,7 +80,7 @@ class MD4CParser::Impl { } } - std::string getAttributeText(const MD_ATTRIBUTE *attr) { + std::string getAttributeText(const ENRMRKD_ATTRIBUTE *attr) { if (!attr || attr->size == 0 || !attr->text) return {}; @@ -89,25 +89,25 @@ class MD4CParser::Impl { return std::string(attr->text, attr->size); } - static int enterBlock(MD_BLOCKTYPE type, void *detail, void *userdata) { + static int enterBlock(ENRMRKD_BLOCKTYPE type, void *detail, void *userdata) { if (!userdata) return 1; auto *impl = static_cast(userdata); switch (type) { - case MD_BLOCK_DOC: + case ENRMRKD_BLOCK_DOC: // Document node already created in reset() break; - case MD_BLOCK_P: { + case ENRMRKD_BLOCK_P: { impl->pushNode(std::make_shared(NodeType::Paragraph)); break; } - case MD_BLOCK_H: { + case ENRMRKD_BLOCK_H: { auto node = std::make_shared(NodeType::Heading); if (detail) { - auto *h = static_cast(detail); + auto *h = static_cast(detail); int level = static_cast(h->level); // Clamp level to valid range (1-6) level = (level < 1) ? 1 : (level > 6) ? 6 : level; @@ -120,15 +120,15 @@ class MD4CParser::Impl { break; } - case MD_BLOCK_QUOTE: { + case ENRMRKD_BLOCK_QUOTE: { impl->pushNode(std::make_shared(NodeType::Blockquote)); break; } - case MD_BLOCK_ADMONITION: { + case ENRMRKD_BLOCK_ADMONITION: { auto node = std::make_shared(NodeType::Admonition); if (detail) { - auto *adm = static_cast(detail); + auto *adm = static_cast(detail); std::string admonitionType = impl->getAttributeText(&adm->type); if (!admonitionType.empty()) { node->setAttribute(ATTR_ADMONITION_TYPE, admonitionType); @@ -138,15 +138,15 @@ class MD4CParser::Impl { break; } - case MD_BLOCK_UL: { + case ENRMRKD_BLOCK_UL: { impl->pushNode(std::make_shared(NodeType::UnorderedList)); break; } - case MD_BLOCK_OL: { + case ENRMRKD_BLOCK_OL: { auto node = std::make_shared(NodeType::OrderedList); if (detail) { - auto *ol = static_cast(detail); + auto *ol = static_cast(detail); if (ol->start != 1) { node->setAttribute(ATTR_START, std::to_string(ol->start)); } @@ -155,10 +155,10 @@ class MD4CParser::Impl { break; } - case MD_BLOCK_LI: { + case ENRMRKD_BLOCK_LI: { auto node = std::make_shared(NodeType::ListItem); if (detail) { - auto *li = static_cast(detail); + auto *li = static_cast(detail); if (li->is_task) { node->setAttribute(ATTR_IS_TASK, "true"); node->setAttribute(ATTR_TASK_CHECKED, (li->task_mark == 'x' || li->task_mark == 'X') ? "true" : "false"); @@ -168,10 +168,10 @@ class MD4CParser::Impl { break; } - case MD_BLOCK_CODE: { + case ENRMRKD_BLOCK_CODE: { auto node = std::make_shared(NodeType::CodeBlock); if (detail) { - auto *codeDetail = static_cast(detail); + auto *codeDetail = static_cast(detail); // Extract fence character (if fenced code block) if (codeDetail->fence_char != 0) { char fenceStr[2] = {static_cast(codeDetail->fence_char), '\0'}; @@ -187,25 +187,25 @@ class MD4CParser::Impl { break; } - case MD_BLOCK_HR: { + case ENRMRKD_BLOCK_HR: { impl->pushNode(std::make_shared(NodeType::ThematicBreak)); break; } - case MD_BLOCK_BLANK: { + case ENRMRKD_BLOCK_BLANK: { auto node = std::make_shared(NodeType::BlankLine); if (detail) { - auto *blankDetail = static_cast(detail); + auto *blankDetail = static_cast(detail); node->setAttribute(ATTR_BLANK_LINE_COUNT, std::to_string(blankDetail->line_count)); } impl->pushNode(node); break; } - case MD_BLOCK_TABLE: { + case ENRMRKD_BLOCK_TABLE: { auto node = std::make_shared(NodeType::Table); if (detail) { - auto *tableDetail = static_cast(detail); + auto *tableDetail = static_cast(detail); node->setAttribute("colCount", std::to_string(tableDetail->col_count)); node->setAttribute("headRowCount", std::to_string(tableDetail->head_row_count)); node->setAttribute("bodyRowCount", std::to_string(tableDetail->body_row_count)); @@ -214,36 +214,36 @@ class MD4CParser::Impl { break; } - case MD_BLOCK_THEAD: { + case ENRMRKD_BLOCK_THEAD: { impl->pushNode(std::make_shared(NodeType::TableHead)); break; } - case MD_BLOCK_TBODY: { + case ENRMRKD_BLOCK_TBODY: { impl->pushNode(std::make_shared(NodeType::TableBody)); break; } - case MD_BLOCK_TR: { + case ENRMRKD_BLOCK_TR: { impl->pushNode(std::make_shared(NodeType::TableRow)); break; } - case MD_BLOCK_TH: - case MD_BLOCK_TD: { - auto node = - std::make_shared(type == MD_BLOCK_TH ? NodeType::TableHeaderCell : NodeType::TableCell); + case ENRMRKD_BLOCK_TH: + case ENRMRKD_BLOCK_TD: { + auto node = std::make_shared(type == ENRMRKD_BLOCK_TH ? NodeType::TableHeaderCell + : NodeType::TableCell); if (detail) { - auto *tdDetail = static_cast(detail); + auto *tdDetail = static_cast(detail); const char *alignStr; switch (tdDetail->align) { - case MD_ALIGN_LEFT: + case ENRMRKD_ALIGN_LEFT: alignStr = "left"; break; - case MD_ALIGN_CENTER: + case ENRMRKD_ALIGN_CENTER: alignStr = "center"; break; - case MD_ALIGN_RIGHT: + case ENRMRKD_ALIGN_RIGHT: alignStr = "right"; break; default: @@ -256,7 +256,7 @@ class MD4CParser::Impl { break; } - case MD_BLOCK_HTML: { + case ENRMRKD_BLOCK_HTML: { impl->inHtmlBlock = true; impl->htmlBlockContent.clear(); break; @@ -270,13 +270,13 @@ class MD4CParser::Impl { return 0; } - static int leaveBlock(MD_BLOCKTYPE type, void *detail, void *userdata) { + static int leaveBlock(ENRMRKD_BLOCKTYPE type, void *detail, void *userdata) { (void)detail; if (!userdata) return 1; auto *impl = static_cast(userdata); - if (type == MD_BLOCK_HTML) { + if (type == ENRMRKD_BLOCK_HTML) { impl->inHtmlBlock = false; auto node = tryPromoteHtmlBlock(impl->htmlBlockContent); impl->htmlBlockContent.clear(); @@ -286,23 +286,23 @@ class MD4CParser::Impl { return 0; } - if (type != MD_BLOCK_DOC && !impl->nodeStack.empty()) { + if (type != ENRMRKD_BLOCK_DOC && !impl->nodeStack.empty()) { impl->popNode(); } return 0; } - static int enterSpan(MD_SPANTYPE type, void *detail, void *userdata) { + static int enterSpan(ENRMRKD_SPANTYPE type, void *detail, void *userdata) { if (!userdata) return 1; auto *impl = static_cast(userdata); switch (type) { - case MD_SPAN_A: { + case ENRMRKD_SPAN_A: { auto node = std::make_shared(NodeType::Link); if (detail) { - auto *linkDetail = static_cast(detail); + auto *linkDetail = static_cast(detail); std::string url = impl->getAttributeText(&linkDetail->href); if (!url.empty()) { node->setAttribute(ATTR_URL, url); @@ -312,35 +312,35 @@ class MD4CParser::Impl { break; } - case MD_SPAN_STRONG: { + case ENRMRKD_SPAN_STRONG: { impl->pushNode(std::make_shared(NodeType::Strong)); break; } - case MD_SPAN_EM: { + case ENRMRKD_SPAN_EM: { impl->pushNode(std::make_shared(NodeType::Emphasis)); break; } - case MD_SPAN_U: { + case ENRMRKD_SPAN_U: { impl->pushNode(std::make_shared(NodeType::Underline)); break; } - case MD_SPAN_CODE: { + case ENRMRKD_SPAN_CODE: { impl->pushNode(std::make_shared(NodeType::Code)); break; } - case MD_SPAN_DEL: { + case ENRMRKD_SPAN_DEL: { impl->pushNode(std::make_shared(NodeType::Strikethrough)); break; } - case MD_SPAN_IMG: { + case ENRMRKD_SPAN_IMG: { auto node = std::make_shared(NodeType::Image); if (detail) { - auto *imgDetail = static_cast(detail); + auto *imgDetail = static_cast(detail); std::string url = impl->getAttributeText(&imgDetail->src); if (!url.empty()) { node->setAttribute(ATTR_URL, url); @@ -354,32 +354,32 @@ class MD4CParser::Impl { break; } - case MD_SPAN_LATEXMATH: { + case ENRMRKD_SPAN_LATEXMATH: { impl->pushNode(std::make_shared(NodeType::LatexMathInline)); break; } - case MD_SPAN_LATEXMATH_DISPLAY: { + case ENRMRKD_SPAN_LATEXMATH_DISPLAY: { impl->pushNode(std::make_shared(NodeType::LatexMathDisplay)); break; } - case MD_SPAN_SPOILER: { + case ENRMRKD_SPAN_SPOILER: { impl->pushNode(std::make_shared(NodeType::Spoiler)); break; } - case MD_SPAN_SUPERSCRIPT: { + case ENRMRKD_SPAN_SUPERSCRIPT: { impl->pushNode(std::make_shared(NodeType::Superscript)); break; } - case MD_SPAN_SUBSCRIPT: { + case ENRMRKD_SPAN_SUBSCRIPT: { impl->pushNode(std::make_shared(NodeType::Subscript)); break; } - case MD_SPAN_MARK: { + case ENRMRKD_SPAN_MARK: { impl->pushNode(std::make_shared(NodeType::Highlight)); break; } @@ -391,7 +391,7 @@ class MD4CParser::Impl { return 0; } - static int leaveSpan(MD_SPANTYPE type, void *detail, void *userdata) { + static int leaveSpan(ENRMRKD_SPANTYPE type, void *detail, void *userdata) { (void)detail; if (!userdata) return 1; @@ -404,22 +404,22 @@ class MD4CParser::Impl { return 0; } - static int text(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size, void *userdata) { + static int text(ENRMRKD_TEXTTYPE type, const ENRMRKD_CHAR *text, ENRMRKD_SIZE size, void *userdata) { if (!userdata || !text || size == 0) return 0; auto *impl = static_cast(userdata); - if (type == MD_TEXT_SOFTBR) { + if (type == ENRMRKD_TEXT_SOFTBR) { impl->addInlineNode(std::make_shared(NodeType::SoftBreak)); return 0; } - if (type == MD_TEXT_BR) { + if (type == ENRMRKD_TEXT_BR) { impl->addInlineNode(std::make_shared(NodeType::LineBreak)); return 0; } - if (type == MD_TEXT_HTML) { + if (type == ENRMRKD_TEXT_HTML) { if (impl->inHtmlBlock) { impl->htmlBlockContent.append(text, size); } @@ -427,7 +427,7 @@ class MD4CParser::Impl { } // Handle text content (normal text, code text, LaTeX math, etc.) - if (type == MD_TEXT_NORMAL || type == MD_TEXT_CODE || type == MD_TEXT_LATEXMATH) { + if (type == ENRMRKD_TEXT_NORMAL || type == ENRMRKD_TEXT_CODE || type == ENRMRKD_TEXT_LATEXMATH) { impl->currentText.append(text, size); } @@ -817,40 +817,40 @@ std::shared_ptr MD4CParser::parse(const std::string &markdown, impl_->reset(estimatedDepth); impl_->inputText = markdown.c_str(); - unsigned flags = MD_FLAG_NOHTMLSPANS | MD_FLAG_SPOILERS; + unsigned flags = ENRMRKD_FLAG_NOHTMLSPANS | ENRMRKD_FLAG_SPOILERS; if (isGFM) { - flags |= MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_TASKLISTS; + flags |= ENRMRKD_FLAG_TABLES | ENRMRKD_FLAG_STRIKETHROUGH | ENRMRKD_FLAG_TASKLISTS; } if (md4cFlags.permissiveAutolinks) { - flags |= MD_FLAG_PERMISSIVEAUTOLINKS; + flags |= ENRMRKD_FLAG_PERMISSIVEAUTOLINKS; } if (md4cFlags.latexMath) { - flags |= MD_FLAG_LATEXMATHSPANS; + flags |= ENRMRKD_FLAG_LATEXMATHSPANS; } if (md4cFlags.underline) { - flags |= MD_FLAG_UNDERLINE; + flags |= ENRMRKD_FLAG_UNDERLINE; } if (md4cFlags.superscript) { - flags |= MD_FLAG_SUPERSCRIPTS; + flags |= ENRMRKD_FLAG_SUPERSCRIPTS; } if (md4cFlags.subscript) { - flags |= MD_FLAG_SUBSCRIPTS; + flags |= ENRMRKD_FLAG_SUBSCRIPTS; } if (md4cFlags.highlight) { - flags |= MD_FLAG_HIGHLIGHT; + flags |= ENRMRKD_FLAG_HIGHLIGHT; } if (md4cFlags.hardSoftBreaks) { - flags |= MD_FLAG_HARD_SOFT_BREAKS; + flags |= ENRMRKD_FLAG_HARD_SOFT_BREAKS; } if (md4cFlags.preserveBlankLines) { - flags |= MD_FLAG_PRESERVEBLANKLINES; + flags |= ENRMRKD_FLAG_PRESERVEBLANKLINES; } if (md4cFlags.admonitions) { - flags |= MD_FLAG_ADMONITIONS; + flags |= ENRMRKD_FLAG_ADMONITIONS; } // Configure MD4C parser with callbacks - MD_PARSER parser = { + ENRMRKD_PARSER parser = { 0, // abi_version flags, &Impl::enterBlock, &Impl::leaveBlock, &Impl::enterSpan, &Impl::leaveSpan, &Impl::text, nullptr, // debug_log @@ -858,7 +858,7 @@ std::shared_ptr MD4CParser::parse(const std::string &markdown, }; // Parse the markdown - int result = md_parse(markdown.c_str(), static_cast(markdown.size()), &parser, impl_.get()); + int result = enrmrkd_parse(markdown.c_str(), static_cast(markdown.size()), &parser, impl_.get()); if (result != 0) { // Parsing failed, return empty document diff --git a/packages/core/cpp/parser/MD4CParser.hpp b/packages/core/cpp/parser/MD4CParser.hpp index 10f1afbf0..36ffff454 100644 --- a/packages/core/cpp/parser/MD4CParser.hpp +++ b/packages/core/cpp/parser/MD4CParser.hpp @@ -1,37 +1,35 @@ #pragma once #include "MarkdownASTNode.hpp" -#include #include +#include namespace Markdown { struct Md4cFlags { - bool underline = false; - bool latexMath = true; - bool superscript = false; - bool subscript = false; - bool highlight = false; - bool permissiveAutolinks = true; - bool hardSoftBreaks = false; - bool preserveBlankLines = false; - bool admonitions = true; + bool underline = false; + bool latexMath = true; + bool superscript = false; + bool subscript = false; + bool highlight = false; + bool permissiveAutolinks = true; + bool hardSoftBreaks = false; + bool preserveBlankLines = false; + bool admonitions = true; }; class MD4CParser { public: - MD4CParser(); - ~MD4CParser(); + MD4CParser(); + ~MD4CParser(); - // Parse markdown string and return AST root node - std::shared_ptr parse( - const std::string& markdown, - const Md4cFlags& flags = Md4cFlags{}, - bool isGFM = true); + // Parse markdown string and return AST root node + std::shared_ptr parse(const std::string &markdown, const Md4cFlags &flags = Md4cFlags{}, + bool isGFM = true); private: - class Impl; - std::unique_ptr impl_; + class Impl; + std::unique_ptr impl_; }; } // namespace Markdown diff --git a/packages/core/cpp/parser/MarkdownASTNode.hpp b/packages/core/cpp/parser/MarkdownASTNode.hpp index bf8edfbc7..839e81c21 100644 --- a/packages/core/cpp/parser/MarkdownASTNode.hpp +++ b/packages/core/cpp/parser/MarkdownASTNode.hpp @@ -1,67 +1,66 @@ #pragma once -#include #include -#include +#include #include +#include namespace Markdown { enum class NodeType { - Document, - Paragraph, - Text, - Link, - Heading, - LineBreak, - Strong, - Emphasis, - Strikethrough, - Underline, - Code, - Image, - Blockquote, - UnorderedList, - OrderedList, - ListItem, - CodeBlock, - ThematicBreak, - Table, - TableHead, - TableBody, - TableRow, - TableHeaderCell, - TableCell, - LatexMathInline, - LatexMathDisplay, - Spoiler, - Superscript, - Subscript, - Highlight, - SoftBreak, - BlankLine, - Admonition, - Video + Document, + Paragraph, + Text, + Link, + Heading, + LineBreak, + Strong, + Emphasis, + Strikethrough, + Underline, + Code, + Image, + Blockquote, + UnorderedList, + OrderedList, + ListItem, + CodeBlock, + ThematicBreak, + Table, + TableHead, + TableBody, + TableRow, + TableHeaderCell, + TableCell, + LatexMathInline, + LatexMathDisplay, + Spoiler, + Superscript, + Subscript, + Highlight, + SoftBreak, + BlankLine, + Admonition, + Video }; struct MarkdownASTNode { - NodeType type; - std::string content; - std::unordered_map attributes; - std::vector> children; + NodeType type; + std::string content; + std::unordered_map attributes; + std::vector> children; - explicit MarkdownASTNode(NodeType t) : type(t) {} + explicit MarkdownASTNode(NodeType t) : type(t) {} - void addChild(std::shared_ptr child) { - if (child) { - children.push_back(std::move(child)); - } + void addChild(std::shared_ptr child) { + if (child) { + children.push_back(std::move(child)); } + } - void setAttribute(const std::string& key, const std::string& value) { - attributes[key] = value; - } + void setAttribute(const std::string &key, const std::string &value) { + attributes[key] = value; + } }; } // namespace Markdown - diff --git a/packages/core/cpp/parser/TextLinkRecognizer.cpp b/packages/core/cpp/parser/TextLinkRecognizer.cpp index 6f3d92391..c48da3531 100644 --- a/packages/core/cpp/parser/TextLinkRecognizer.cpp +++ b/packages/core/cpp/parser/TextLinkRecognizer.cpp @@ -13,163 +13,182 @@ using NodePtr = std::shared_ptr; using NodeList = std::vector; bool isOpaque(NodeType type) { - switch (type) { - case NodeType::Link: - case NodeType::CodeBlock: - case NodeType::Image: - case NodeType::Video: - case NodeType::LatexMathInline: - case NodeType::LatexMathDisplay: - return true; - default: - return false; - } + switch (type) { + case NodeType::Link: + case NodeType::CodeBlock: + case NodeType::Image: + case NodeType::Video: + case NodeType::LatexMathInline: + case NodeType::LatexMathDisplay: + return true; + default: + return false; + } } -NodePtr makeLink(NodePtr child, const std::string& url) { - auto link = std::make_shared(NodeType::Link); - link->setAttribute("url", url); - link->setAttribute("recognizedLink", "true"); - link->addChild(std::move(child)); - return link; +NodePtr makeLink(NodePtr child, const std::string &url) { + auto link = std::make_shared(NodeType::Link); + link->setAttribute("url", url); + link->setAttribute("recognizedLink", "true"); + link->addChild(std::move(child)); + return link; } -NodePtr textSlice(const MarkdownASTNode& source, std::string content) { - auto text = std::make_shared(NodeType::Text); - text->content = std::move(content); - text->attributes = source.attributes; - return text; +NodePtr textSlice(const MarkdownASTNode &source, std::string content) { + auto text = std::make_shared(NodeType::Text); + text->content = std::move(content); + text->attributes = source.attributes; + return text; } // Byte offset of each UTF-16 code unit boundary in a UTF-8 string, plus the end. -std::vector utf16BoundariesToBytes(const std::string& text) { - std::vector bytes; - bytes.reserve(text.size() + 1); - size_t i = 0; - while (i < text.size()) { - unsigned char lead = static_cast(text[i]); - size_t length = lead < 0x80 ? 1 : lead < 0xE0 ? 2 : lead < 0xF0 ? 3 : 4; - if (i + length > text.size()) length = text.size() - i; - bytes.push_back(i); - if (length == 4) bytes.push_back(i); // surrogate pair: two units, one start - i += length; - } - bytes.push_back(text.size()); - return bytes; +std::vector utf16BoundariesToBytes(const std::string &text) { + std::vector bytes; + bytes.reserve(text.size() + 1); + size_t i = 0; + while (i < text.size()) { + unsigned char lead = static_cast(text[i]); + size_t length = lead < 0x80 ? 1 : lead < 0xE0 ? 2 : lead < 0xF0 ? 3 : 4; + if (i + length > text.size()) + length = text.size() - i; + bytes.push_back(i); + if (length == 4) + bytes.push_back(i); // surrogate pair: two units, one start + i += length; + } + bytes.push_back(text.size()); + return bytes; } struct Candidate { - MarkdownASTNode* parent; - size_t index; + MarkdownASTNode *parent; + size_t index; }; -void collect(MarkdownASTNode& node, bool wantText, bool wantCode, std::vector& texts, - std::vector& codes) { - for (size_t i = 0; i < node.children.size(); i++) { - MarkdownASTNode& child = *node.children[i]; - if (isOpaque(child.type)) continue; - if (child.type == NodeType::Text) { - if (wantText && !child.content.empty()) texts.push_back({&node, i}); - } else if (child.type == NodeType::Code) { - if (wantCode) codes.push_back({&node, i}); - } else { - collect(child, wantText, wantCode, texts, codes); - } +void collect(MarkdownASTNode &node, bool wantText, bool wantCode, std::vector &texts, + std::vector &codes) { + for (size_t i = 0; i < node.children.size(); i++) { + MarkdownASTNode &child = *node.children[i]; + if (isOpaque(child.type)) + continue; + if (child.type == NodeType::Text) { + if (wantText && !child.content.empty()) + texts.push_back({&node, i}); + } else if (child.type == NodeType::Code) { + if (wantCode) + codes.push_back({&node, i}); + } else { + collect(child, wantText, wantCode, texts, codes); } + } } -std::string codeContent(const MarkdownASTNode& code) { - std::string content; - for (const auto& child : code.children) content += child->content; - return content; +std::string codeContent(const MarkdownASTNode &code) { + std::string content; + for (const auto &child : code.children) + content += child->content; + return content; } -using Replacements = std::unordered_map; - -void splitText(const NodePtr& textNode, const std::vector& ranges, Replacements& out) { - const std::string& content = textNode->content; - std::vector bytes = utf16BoundariesToBytes(content); - NodeList pieces; - size_t offset = 0; - for (const TextRange& range : ranges) { - if (range.end <= range.start || range.end >= bytes.size()) continue; - size_t start = bytes[range.start]; - size_t end = bytes[range.end]; - if (start < offset || end <= start) continue; - if (start > offset) pieces.push_back(textSlice(*textNode, content.substr(offset, start - offset))); - std::string matched = content.substr(start, end - start); - pieces.push_back(makeLink(textSlice(*textNode, matched), matched)); - offset = end; - } - if (offset == 0) return; - if (offset < content.size()) pieces.push_back(textSlice(*textNode, content.substr(offset))); - out[textNode.get()] = std::move(pieces); +using Replacements = std::unordered_map; + +void splitText(const NodePtr &textNode, const std::vector &ranges, Replacements &out) { + const std::string &content = textNode->content; + std::vector bytes = utf16BoundariesToBytes(content); + NodeList pieces; + size_t offset = 0; + for (const TextRange &range : ranges) { + if (range.end <= range.start || range.end >= bytes.size()) + continue; + size_t start = bytes[range.start]; + size_t end = bytes[range.end]; + if (start < offset || end <= start) + continue; + if (start > offset) + pieces.push_back(textSlice(*textNode, content.substr(offset, start - offset))); + std::string matched = content.substr(start, end - start); + pieces.push_back(makeLink(textSlice(*textNode, matched), matched)); + offset = end; + } + if (offset == 0) + return; + if (offset < content.size()) + pieces.push_back(textSlice(*textNode, content.substr(offset))); + out[textNode.get()] = std::move(pieces); } -void applyReplacements(MarkdownASTNode& node, const Replacements& replacements) { - bool changed = false; - for (const auto& child : node.children) { - if (replacements.count(child.get())) { - changed = true; - break; - } +void applyReplacements(MarkdownASTNode &node, const Replacements &replacements) { + bool changed = false; + for (const auto &child : node.children) { + if (replacements.count(child.get())) { + changed = true; + break; } - if (changed) { - NodeList children; - children.reserve(node.children.size()); - for (const auto& child : node.children) { - auto it = replacements.find(child.get()); - if (it == replacements.end()) { - children.push_back(child); - } else { - children.insert(children.end(), it->second.begin(), it->second.end()); - } - } - node.children = std::move(children); - } - for (const auto& child : node.children) { - if (!isOpaque(child->type)) applyReplacements(*child, replacements); + } + if (changed) { + NodeList children; + children.reserve(node.children.size()); + for (const auto &child : node.children) { + auto it = replacements.find(child.get()); + if (it == replacements.end()) { + children.push_back(child); + } else { + children.insert(children.end(), it->second.begin(), it->second.end()); + } } + node.children = std::move(children); + } + for (const auto &child : node.children) { + if (!isOpaque(child->type)) + applyReplacements(*child, replacements); + } } } // namespace -void recognizeTextLinks(MarkdownASTNode& root, const TextLinkMatchers& matchers) { - const bool wantText = static_cast(matchers.text); - const bool wantCode = static_cast(matchers.inlineCode); - if (!wantText && !wantCode) return; - - std::vector texts; - std::vector codes; - collect(root, wantText, wantCode, texts, codes); - if (texts.empty() && codes.empty()) return; - - Replacements replacements; - - if (!texts.empty()) { - std::vector runs; - runs.reserve(texts.size()); - for (const Candidate& c : texts) runs.emplace_back(c.parent->children[c.index]->content); - std::vector> matches = matchers.text(runs); - for (size_t i = 0; i < texts.size() && i < matches.size(); i++) { - if (!matches[i].empty()) splitText(texts[i].parent->children[texts[i].index], matches[i], replacements); - } +void recognizeTextLinks(MarkdownASTNode &root, const TextLinkMatchers &matchers) { + const bool wantText = static_cast(matchers.text); + const bool wantCode = static_cast(matchers.inlineCode); + if (!wantText && !wantCode) + return; + + std::vector texts; + std::vector codes; + collect(root, wantText, wantCode, texts, codes); + if (texts.empty() && codes.empty()) + return; + + Replacements replacements; + + if (!texts.empty()) { + std::vector runs; + runs.reserve(texts.size()); + for (const Candidate &c : texts) + runs.emplace_back(c.parent->children[c.index]->content); + std::vector> matches = matchers.text(runs); + for (size_t i = 0; i < texts.size() && i < matches.size(); i++) { + if (!matches[i].empty()) + splitText(texts[i].parent->children[texts[i].index], matches[i], replacements); } - - if (!codes.empty()) { - std::vector contents; - contents.reserve(codes.size()); - for (const Candidate& c : codes) contents.push_back(codeContent(*c.parent->children[c.index])); - std::vector spans(contents.begin(), contents.end()); - std::vector matched = matchers.inlineCode(spans); - for (size_t i = 0; i < codes.size() && i < matched.size(); i++) { - if (!matched[i] || contents[i].empty()) continue; - const NodePtr& code = codes[i].parent->children[codes[i].index]; - replacements[code.get()] = NodeList{makeLink(code, contents[i])}; - } + } + + if (!codes.empty()) { + std::vector contents; + contents.reserve(codes.size()); + for (const Candidate &c : codes) + contents.push_back(codeContent(*c.parent->children[c.index])); + std::vector spans(contents.begin(), contents.end()); + std::vector matched = matchers.inlineCode(spans); + for (size_t i = 0; i < codes.size() && i < matched.size(); i++) { + if (!matched[i] || contents[i].empty()) + continue; + const NodePtr &code = codes[i].parent->children[codes[i].index]; + replacements[code.get()] = NodeList{makeLink(code, contents[i])}; } + } - if (!replacements.empty()) applyReplacements(root, replacements); + if (!replacements.empty()) + applyReplacements(root, replacements); } } // namespace Markdown diff --git a/packages/core/cpp/parser/TextLinkRecognizer.hpp b/packages/core/cpp/parser/TextLinkRecognizer.hpp index e426affd6..e4de5db2d 100644 --- a/packages/core/cpp/parser/TextLinkRecognizer.hpp +++ b/packages/core/cpp/parser/TextLinkRecognizer.hpp @@ -2,8 +2,8 @@ #include "MarkdownASTNode.hpp" #include -#include #include +#include #include #include @@ -11,18 +11,18 @@ namespace Markdown { // Offsets are UTF-16 code units, as every host regex engine reports them. struct TextRange { - size_t start; - size_t end; + size_t start; + size_t end; }; // Host-provided matching, one call per kind per parse. A null function is off. struct TextLinkMatchers { - // Non-overlapping matches per run, in order. - std::function>(const std::vector& runs)> text; - std::function(const std::vector& spans)> inlineCode; + // Non-overlapping matches per run, in order. + std::function>(const std::vector &runs)> text; + std::function(const std::vector &spans)> inlineCode; }; // In place. Existing links, code blocks, media and math are not entered. -void recognizeTextLinks(MarkdownASTNode& root, const TextLinkMatchers& matchers); +void recognizeTextLinks(MarkdownASTNode &root, const TextLinkMatchers &matchers); } // namespace Markdown diff --git a/packages/core/cpp/tests/ast_dump.cpp b/packages/core/cpp/tests/ast_dump.cpp new file mode 100644 index 000000000..d3a04fd42 --- /dev/null +++ b/packages/core/cpp/tests/ast_dump.cpp @@ -0,0 +1,76 @@ +/* + * Dumps the serialized AST of each input file, under every flag variant, so a + * change in the vendored parser or in MD4CParser shows up as a golden diff. + * See scripts/test-core-parser.sh. + */ +#include "ASTSerializer.hpp" +#include "MD4CParser.hpp" +#include +#include +#include +#include +#include + +namespace { + +std::string basename(const std::string &path) { + const auto slash = path.find_last_of('/'); + return slash == std::string::npos ? path : path.substr(slash + 1); +} + +Markdown::Md4cFlags allDisabled() { + Markdown::Md4cFlags flags{}; + flags.latexMath = false; + flags.permissiveAutolinks = false; + flags.admonitions = false; + return flags; +} + +Markdown::Md4cFlags allEnabled() { + Markdown::Md4cFlags flags{}; + flags.underline = true; + flags.latexMath = true; + flags.superscript = true; + flags.subscript = true; + flags.highlight = true; + flags.permissiveAutolinks = true; + flags.hardSoftBreaks = true; + flags.preserveBlankLines = true; + flags.admonitions = true; + return flags; +} + +struct Variant { + const char *name; + Markdown::Md4cFlags flags; + bool isGFM; +}; + +} // namespace + +int main(int argc, char **argv) { + const std::vector variants = { + {"defaults-gfm", Markdown::Md4cFlags{}, true}, {"defaults-commonmark", Markdown::Md4cFlags{}, false}, + {"extensions-off-gfm", allDisabled(), true}, {"extensions-on-gfm", allEnabled(), true}, + {"extensions-on-commonmark", allEnabled(), false}, + }; + + Markdown::MD4CParser parser; + for (int i = 1; i < argc; i++) { + std::ifstream file(argv[i], std::ios::binary); + if (!file) { + std::cerr << "cannot open " << argv[i] << "\n"; + return 2; + } + std::stringstream buffer; + buffer << file.rdbuf(); + const std::string markdown = buffer.str(); + + for (const Variant &variant : variants) { + const auto root = parser.parse(markdown, variant.flags, variant.isGFM); + std::cout << "=== " << basename(argv[i]) << " [" << variant.name << "] ===\n" + << (root ? Markdown::ASTSerializer::serialize(*root) : std::string("")) << "\n"; + } + } + return 0; +} diff --git a/packages/core/cpp/tests/fixtures/commonmark.md b/packages/core/cpp/tests/fixtures/commonmark.md new file mode 100644 index 000000000..06a8c46af --- /dev/null +++ b/packages/core/cpp/tests/fixtures/commonmark.md @@ -0,0 +1,35 @@ +# Heading one + +Paragraph with *emphasis*, **strong**, `code`, a [link](https://example.com "Title") +and an ![image](https://example.com/i.png). + +> Blockquote with a second line +> and a lazy continuation. + +1. First +2. Second + - nested bullet + - another + +- [ ] unchecked task +- [x] checked task + +```js +const answer = 42; +``` + + indented code block + +Setext heading +============== + +--- + +Term & entity, hard break at the end of this line. +Next line after the hard break. + +A [reference link][ref] resolved below. + +[ref]: https://example.com/ref +------ +A dashed line directly after a link reference definition. diff --git a/packages/core/cpp/tests/fixtures/edge-cases.md b/packages/core/cpp/tests/fixtures/edge-cases.md new file mode 100644 index 000000000..e5c3d7e31 --- /dev/null +++ b/packages/core/cpp/tests/fixtures/edge-cases.md @@ -0,0 +1,29 @@ +Paragraph one. + + +Two blank lines above this paragraph. + + + + +Four blank lines above this one. + +- list item with + + a loose second paragraph + +- > blockquote inside a list item + +1. ordered + 1. nested ordered + - mixed nesting + +| broken | table +|---| + +*unclosed emphasis and `unclosed code + +Trailing spaces and tabs mixed in a line. + +Text with a NUL-ish escape \\ and a backslash-newline\ +continuation. diff --git a/packages/core/cpp/tests/fixtures/extensions.md b/packages/core/cpp/tests/fixtures/extensions.md new file mode 100644 index 000000000..b3fad8445 --- /dev/null +++ b/packages/core/cpp/tests/fixtures/extensions.md @@ -0,0 +1,18 @@ +Spoiler: ||hidden text|| in a paragraph. + +Highlight: ==marked== and insert: ++inserted++. + +Superscript: x^2^ and subscript: H~2~O. + +Underline: _underlined_ when the flag is on. + +Inline math $a^2 + b^2 = c^2$ and display math: + +$$ +\int_0^1 x^2 dx +$$ + +Wiki link [[Target Page]] and [[Target|Alias]]. + +Delimiter runs longer than the extension takes: |||three||| and ===three=== +and +++three+++ and x^^2^^. diff --git a/packages/core/cpp/tests/fixtures/gfm.md b/packages/core/cpp/tests/fixtures/gfm.md new file mode 100644 index 000000000..79523eeca --- /dev/null +++ b/packages/core/cpp/tests/fixtures/gfm.md @@ -0,0 +1,20 @@ +| Left | Center | Right | +|:-----|:------:|------:| +| a | b | c | +| `x` | **y** | [z](https://example.com) | + +~~struck through~~ and https://example.com/bare plus www.example.com +and someone@example.com. + +Prefixed e-mail autolinks: mailto:someone@example.com and +xmpp:someone@example.com. + +> [!NOTE] +> An admonition body. + +> [!WARNING] +> Another one with a [link](https://example.com). + +Footnote reference[^note] in a paragraph. + +[^note]: The footnote definition. diff --git a/packages/core/cpp/tests/fixtures/html-blocks.md b/packages/core/cpp/tests/fixtures/html-blocks.md new file mode 100644 index 000000000..cc5bc1ab7 --- /dev/null +++ b/packages/core/cpp/tests/fixtures/html-blocks.md @@ -0,0 +1,20 @@ +Intro paragraph before the video. + + + +Paragraph between. + +- + +
    + raw html block +
    + + + +Inline html span inside a paragraph. + + diff --git a/packages/core/cpp/tests/golden/ast.txt b/packages/core/cpp/tests/golden/ast.txt new file mode 100644 index 000000000..bee22d2aa --- /dev/null +++ b/packages/core/cpp/tests/golden/ast.txt @@ -0,0 +1,50 @@ +=== commonmark.md [defaults-gfm] === +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"SoftBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"SoftBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"false"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"unchecked task"}]}]},{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"true"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"checked task"}]}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +=== commonmark.md [defaults-commonmark] === +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"SoftBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"SoftBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[ ] unchecked task"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[x] checked task"}]}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +=== commonmark.md [extensions-off-gfm] === +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"SoftBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"SoftBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"false"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"unchecked task"}]}]},{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"true"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"checked task"}]}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +=== commonmark.md [extensions-on-gfm] === +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"LineBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"LineBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"false"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"unchecked task"}]}]},{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"true"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"checked task"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +=== commonmark.md [extensions-on-commonmark] === +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"LineBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"LineBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[ ] unchecked task"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[x] checked task"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +=== edge-cases.md [defaults-gfm] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph one."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Two blank lines above this paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Four blank lines above this one."}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","children":[{"type":"Text","content":"list item with"}]},{"type":"Paragraph","children":[{"type":"Text","content":"a loose second paragraph"}]}]},{"type":"ListItem","children":[{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"blockquote inside a list item"}]}]}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"ordered"}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested ordered"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"mixed nesting"}]}]}]}]}]}]}]},{"type":"Table","attributes":{"bodyRowCount":"0","colCount":"1","headRowCount":"1"},"children":[{"type":"TableHead","children":[{"type":"TableRow","children":[{"type":"TableHeaderCell","attributes":{"align":"default"},"children":[{"type":"Text","content":"broken"}]}]}]}]},{"type":"Paragraph","children":[{"type":"Text","content":"*unclosed emphasis and `unclosed code"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Trailing spaces and tabs\tmixed\tin\ta\tline."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Text with a NUL-ish escape \\ and a backslash-newline"},{"type":"LineBreak"},{"type":"Text","content":"continuation."}]}]} +=== edge-cases.md [defaults-commonmark] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph one."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Two blank lines above this paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Four blank lines above this one."}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","children":[{"type":"Text","content":"list item with"}]},{"type":"Paragraph","children":[{"type":"Text","content":"a loose second paragraph"}]}]},{"type":"ListItem","children":[{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"blockquote inside a list item"}]}]}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"ordered"}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested ordered"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"mixed nesting"}]}]}]}]}]}]}]},{"type":"Paragraph","children":[{"type":"Text","content":"| broken | table"},{"type":"SoftBreak"},{"type":"Text","content":"|---|"}]},{"type":"Paragraph","children":[{"type":"Text","content":"*unclosed emphasis and `unclosed code"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Trailing spaces and tabs\tmixed\tin\ta\tline."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Text with a NUL-ish escape \\ and a backslash-newline"},{"type":"LineBreak"},{"type":"Text","content":"continuation."}]}]} +=== edge-cases.md [extensions-off-gfm] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph one."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Two blank lines above this paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Four blank lines above this one."}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","children":[{"type":"Text","content":"list item with"}]},{"type":"Paragraph","children":[{"type":"Text","content":"a loose second paragraph"}]}]},{"type":"ListItem","children":[{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"blockquote inside a list item"}]}]}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"ordered"}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested ordered"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"mixed nesting"}]}]}]}]}]}]}]},{"type":"Table","attributes":{"bodyRowCount":"0","colCount":"1","headRowCount":"1"},"children":[{"type":"TableHead","children":[{"type":"TableRow","children":[{"type":"TableHeaderCell","attributes":{"align":"default"},"children":[{"type":"Text","content":"broken"}]}]}]}]},{"type":"Paragraph","children":[{"type":"Text","content":"*unclosed emphasis and `unclosed code"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Trailing spaces and tabs\tmixed\tin\ta\tline."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Text with a NUL-ish escape \\ and a backslash-newline"},{"type":"LineBreak"},{"type":"Text","content":"continuation."}]}]} +=== edge-cases.md [extensions-on-gfm] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph one."}]},{"type":"BlankLine","attributes":{"count":"2"}},{"type":"Paragraph","children":[{"type":"Text","content":"Two blank lines above this paragraph."}]},{"type":"BlankLine","attributes":{"count":"4"}},{"type":"Paragraph","children":[{"type":"Text","content":"Four blank lines above this one."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"list item with"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"a loose second paragraph"}]},{"type":"BlankLine","attributes":{"count":"1"}}]},{"type":"ListItem","children":[{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"blockquote inside a list item"}]}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"ordered"}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested ordered"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"mixed nesting"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]}]}]}]}]},{"type":"Table","attributes":{"bodyRowCount":"0","colCount":"1","headRowCount":"1"},"children":[{"type":"TableHead","children":[{"type":"TableRow","children":[{"type":"TableHeaderCell","attributes":{"align":"default"},"children":[{"type":"Text","content":"broken"}]}]}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"*unclosed emphasis and `unclosed code"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Trailing spaces and tabs\tmixed\tin\ta\tline."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Text with a NUL-ish escape \\ and a backslash-newline"},{"type":"LineBreak"},{"type":"Text","content":"continuation."}]}]} +=== edge-cases.md [extensions-on-commonmark] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph one."}]},{"type":"BlankLine","attributes":{"count":"2"}},{"type":"Paragraph","children":[{"type":"Text","content":"Two blank lines above this paragraph."}]},{"type":"BlankLine","attributes":{"count":"4"}},{"type":"Paragraph","children":[{"type":"Text","content":"Four blank lines above this one."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"list item with"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"a loose second paragraph"}]},{"type":"BlankLine","attributes":{"count":"1"}}]},{"type":"ListItem","children":[{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"blockquote inside a list item"}]}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"ordered"}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested ordered"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"mixed nesting"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]}]}]}]}]},{"type":"Paragraph","children":[{"type":"Text","content":"| broken | table"},{"type":"LineBreak"},{"type":"Text","content":"|---|"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"*unclosed emphasis and `unclosed code"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Trailing spaces and tabs\tmixed\tin\ta\tline."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Text with a NUL-ish escape \\ and a backslash-newline"},{"type":"LineBreak"},{"type":"Text","content":"continuation."}]}]} +=== extensions.md [defaults-gfm] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Spoiler: "},{"type":"Spoiler","children":[{"type":"Text","content":"hidden text"}]},{"type":"Text","content":" in a paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Highlight: ==marked== and insert: ++inserted++."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Superscript: x^2^ and subscript: H~2~O."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Underline: "},{"type":"Emphasis","children":[{"type":"Text","content":"underlined"}]},{"type":"Text","content":" when the flag is on."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Inline math "},{"type":"LatexMathInline","children":[{"type":"Text","content":"a^2 + b^2 = c^2"}]},{"type":"Text","content":" and display math:"}]},{"type":"LatexMathDisplay","children":[{"type":"Text","content":" \\int_0^1 x^2 dx "}]},{"type":"Paragraph","children":[{"type":"Text","content":"Wiki link [[Target Page]] and [[Target|Alias]]."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Delimiter runs longer than the extension takes: |||three||| and ===three==="},{"type":"SoftBreak"},{"type":"Text","content":"and +++three+++ and x^^2^^."}]}]} +=== extensions.md [defaults-commonmark] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Spoiler: "},{"type":"Spoiler","children":[{"type":"Text","content":"hidden text"}]},{"type":"Text","content":" in a paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Highlight: ==marked== and insert: ++inserted++."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Superscript: x^2^ and subscript: H~2~O."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Underline: "},{"type":"Emphasis","children":[{"type":"Text","content":"underlined"}]},{"type":"Text","content":" when the flag is on."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Inline math "},{"type":"LatexMathInline","children":[{"type":"Text","content":"a^2 + b^2 = c^2"}]},{"type":"Text","content":" and display math:"}]},{"type":"LatexMathDisplay","children":[{"type":"Text","content":" \\int_0^1 x^2 dx "}]},{"type":"Paragraph","children":[{"type":"Text","content":"Wiki link [[Target Page]] and [[Target|Alias]]."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Delimiter runs longer than the extension takes: |||three||| and ===three==="},{"type":"SoftBreak"},{"type":"Text","content":"and +++three+++ and x^^2^^."}]}]} +=== extensions.md [extensions-off-gfm] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Spoiler: "},{"type":"Spoiler","children":[{"type":"Text","content":"hidden text"}]},{"type":"Text","content":" in a paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Highlight: ==marked== and insert: ++inserted++."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Superscript: x^2^ and subscript: H~2~O."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Underline: "},{"type":"Emphasis","children":[{"type":"Text","content":"underlined"}]},{"type":"Text","content":" when the flag is on."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Inline math $a^2 + b^2 = c^2$ and display math:"}]},{"type":"Paragraph","children":[{"type":"Text","content":"$$"},{"type":"SoftBreak"},{"type":"Text","content":"\\int_0^1 x^2 dx"},{"type":"SoftBreak"},{"type":"Text","content":"$$"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Wiki link [[Target Page]] and [[Target|Alias]]."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Delimiter runs longer than the extension takes: |||three||| and ===three==="},{"type":"SoftBreak"},{"type":"Text","content":"and +++three+++ and x^^2^^."}]}]} +=== extensions.md [extensions-on-gfm] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Spoiler: "},{"type":"Spoiler","children":[{"type":"Text","content":"hidden text"}]},{"type":"Text","content":" in a paragraph."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Highlight: "},{"type":"Highlight","children":[{"type":"Text","content":"marked"}]},{"type":"Text","content":" and insert: ++inserted++."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Superscript: x"},{"type":"Superscript","children":[{"type":"Text","content":"2"}]},{"type":"Text","content":" and subscript: H"},{"type":"Subscript","children":[{"type":"Text","content":"2"}]},{"type":"Text","content":"O."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Underline: "},{"type":"Underline","children":[{"type":"Text","content":"underlined"}]},{"type":"Text","content":" when the flag is on."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Inline math "},{"type":"LatexMathInline","children":[{"type":"Text","content":"a^2 + b^2 = c^2"}]},{"type":"Text","content":" and display math:"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"LatexMathDisplay","children":[{"type":"Text","content":" \\int_0^1 x^2 dx "}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Wiki link [[Target Page]] and [[Target|Alias]]."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Delimiter runs longer than the extension takes: |||three||| and ===three==="},{"type":"LineBreak"},{"type":"Text","content":"and +++three+++ and x^^2^^."}]}]} +=== extensions.md [extensions-on-commonmark] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Spoiler: "},{"type":"Spoiler","children":[{"type":"Text","content":"hidden text"}]},{"type":"Text","content":" in a paragraph."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Highlight: "},{"type":"Highlight","children":[{"type":"Text","content":"marked"}]},{"type":"Text","content":" and insert: ++inserted++."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Superscript: x"},{"type":"Superscript","children":[{"type":"Text","content":"2"}]},{"type":"Text","content":" and subscript: H"},{"type":"Subscript","children":[{"type":"Text","content":"2"}]},{"type":"Text","content":"O."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Underline: "},{"type":"Underline","children":[{"type":"Text","content":"underlined"}]},{"type":"Text","content":" when the flag is on."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Inline math "},{"type":"LatexMathInline","children":[{"type":"Text","content":"a^2 + b^2 = c^2"}]},{"type":"Text","content":" and display math:"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"LatexMathDisplay","children":[{"type":"Text","content":" \\int_0^1 x^2 dx "}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Wiki link [[Target Page]] and [[Target|Alias]]."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Delimiter runs longer than the extension takes: |||three||| and ===three==="},{"type":"LineBreak"},{"type":"Text","content":"and +++three+++ and x^^2^^."}]}]} +=== gfm.md [defaults-gfm] === +{"type":"Document","children":[{"type":"Table","attributes":{"bodyRowCount":"2","colCount":"3","headRowCount":"1"},"children":[{"type":"TableHead","children":[{"type":"TableRow","children":[{"type":"TableHeaderCell","attributes":{"align":"left"},"children":[{"type":"Text","content":"Left"}]},{"type":"TableHeaderCell","attributes":{"align":"center"},"children":[{"type":"Text","content":"Center"}]},{"type":"TableHeaderCell","attributes":{"align":"right"},"children":[{"type":"Text","content":"Right"}]}]}]},{"type":"TableBody","children":[{"type":"TableRow","children":[{"type":"TableCell","attributes":{"align":"left"},"children":[{"type":"Text","content":"a"}]},{"type":"TableCell","attributes":{"align":"center"},"children":[{"type":"Text","content":"b"}]},{"type":"TableCell","attributes":{"align":"right"},"children":[{"type":"Text","content":"c"}]}]},{"type":"TableRow","children":[{"type":"TableCell","attributes":{"align":"left"},"children":[{"type":"Code","children":[{"type":"Text","content":"x"}]}]},{"type":"TableCell","attributes":{"align":"center"},"children":[{"type":"Strong","children":[{"type":"Text","content":"y"}]}]},{"type":"TableCell","attributes":{"align":"right"},"children":[{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"z"}]}]}]}]}]},{"type":"Paragraph","children":[{"type":"Strikethrough","children":[{"type":"Text","content":"struck through"}]},{"type":"Text","content":" and "},{"type":"Link","attributes":{"url":"https://example.com/bare"},"children":[{"type":"Text","content":"https://example.com/bare"}]},{"type":"Text","content":" plus "},{"type":"Link","attributes":{"url":"http://www.example.com"},"children":[{"type":"Text","content":"www.example.com"}]},{"type":"SoftBreak"},{"type":"Text","content":"and "},{"type":"Link","attributes":{"url":"mailto:someone@example.com"},"children":[{"type":"Text","content":"someone@example.com"}]},{"type":"Text","content":"."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Prefixed e-mail autolinks: "},{"type":"Link","attributes":{"url":"mailto:someone@example.com"},"children":[{"type":"Text","content":"mailto:someone@example.com"}]},{"type":"Text","content":" and"},{"type":"SoftBreak"},{"type":"Link","attributes":{"url":"xmpp:someone@example.com"},"children":[{"type":"Text","content":"xmpp:someone@example.com"}]},{"type":"Text","content":"."}]},{"type":"Admonition","attributes":{"admonitionType":"note"},"children":[{"type":"Paragraph","children":[{"type":"Text","content":"An admonition body."}]}]},{"type":"Admonition","attributes":{"admonitionType":"warning"},"children":[{"type":"Paragraph","children":[{"type":"Text","content":"Another one with a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"Text","content":"."}]}]},{"type":"Paragraph","children":[{"type":"Text","content":"Footnote reference[^note] in a paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"[^note]: The footnote definition."}]}]} +=== gfm.md [defaults-commonmark] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"| Left | Center | Right |"},{"type":"SoftBreak"},{"type":"Text","content":"|:-----|:------:|------:|"},{"type":"SoftBreak"},{"type":"Text","content":"| a | b | c |"},{"type":"SoftBreak"},{"type":"Text","content":"| "},{"type":"Code","children":[{"type":"Text","content":"x"}]},{"type":"Text","content":" | "},{"type":"Strong","children":[{"type":"Text","content":"y"}]},{"type":"Text","content":" | "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"z"}]},{"type":"Text","content":" |"}]},{"type":"Paragraph","children":[{"type":"Text","content":"~~struck through~~ and "},{"type":"Link","attributes":{"url":"https://example.com/bare"},"children":[{"type":"Text","content":"https://example.com/bare"}]},{"type":"Text","content":" plus "},{"type":"Link","attributes":{"url":"http://www.example.com"},"children":[{"type":"Text","content":"www.example.com"}]},{"type":"SoftBreak"},{"type":"Text","content":"and "},{"type":"Link","attributes":{"url":"mailto:someone@example.com"},"children":[{"type":"Text","content":"someone@example.com"}]},{"type":"Text","content":"."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Prefixed e-mail autolinks: "},{"type":"Link","attributes":{"url":"mailto:someone@example.com"},"children":[{"type":"Text","content":"mailto:someone@example.com"}]},{"type":"Text","content":" and"},{"type":"SoftBreak"},{"type":"Link","attributes":{"url":"xmpp:someone@example.com"},"children":[{"type":"Text","content":"xmpp:someone@example.com"}]},{"type":"Text","content":"."}]},{"type":"Admonition","attributes":{"admonitionType":"note"},"children":[{"type":"Paragraph","children":[{"type":"Text","content":"An admonition body."}]}]},{"type":"Admonition","attributes":{"admonitionType":"warning"},"children":[{"type":"Paragraph","children":[{"type":"Text","content":"Another one with a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"Text","content":"."}]}]},{"type":"Paragraph","children":[{"type":"Text","content":"Footnote reference[^note] in a paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"[^note]: The footnote definition."}]}]} +=== gfm.md [extensions-off-gfm] === +{"type":"Document","children":[{"type":"Table","attributes":{"bodyRowCount":"2","colCount":"3","headRowCount":"1"},"children":[{"type":"TableHead","children":[{"type":"TableRow","children":[{"type":"TableHeaderCell","attributes":{"align":"left"},"children":[{"type":"Text","content":"Left"}]},{"type":"TableHeaderCell","attributes":{"align":"center"},"children":[{"type":"Text","content":"Center"}]},{"type":"TableHeaderCell","attributes":{"align":"right"},"children":[{"type":"Text","content":"Right"}]}]}]},{"type":"TableBody","children":[{"type":"TableRow","children":[{"type":"TableCell","attributes":{"align":"left"},"children":[{"type":"Text","content":"a"}]},{"type":"TableCell","attributes":{"align":"center"},"children":[{"type":"Text","content":"b"}]},{"type":"TableCell","attributes":{"align":"right"},"children":[{"type":"Text","content":"c"}]}]},{"type":"TableRow","children":[{"type":"TableCell","attributes":{"align":"left"},"children":[{"type":"Code","children":[{"type":"Text","content":"x"}]}]},{"type":"TableCell","attributes":{"align":"center"},"children":[{"type":"Strong","children":[{"type":"Text","content":"y"}]}]},{"type":"TableCell","attributes":{"align":"right"},"children":[{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"z"}]}]}]}]}]},{"type":"Paragraph","children":[{"type":"Strikethrough","children":[{"type":"Text","content":"struck through"}]},{"type":"Text","content":" and https://example.com/bare plus www.example.com"},{"type":"SoftBreak"},{"type":"Text","content":"and someone@example.com."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Prefixed e-mail autolinks: mailto:someone@example.com and"},{"type":"SoftBreak"},{"type":"Text","content":"xmpp:someone@example.com."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"[!NOTE]"},{"type":"SoftBreak"},{"type":"Text","content":"An admonition body."}]}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"[!WARNING]"},{"type":"SoftBreak"},{"type":"Text","content":"Another one with a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"Text","content":"."}]}]},{"type":"Paragraph","children":[{"type":"Text","content":"Footnote reference[^note] in a paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"[^note]: The footnote definition."}]}]} +=== gfm.md [extensions-on-gfm] === +{"type":"Document","children":[{"type":"Table","attributes":{"bodyRowCount":"2","colCount":"3","headRowCount":"1"},"children":[{"type":"TableHead","children":[{"type":"TableRow","children":[{"type":"TableHeaderCell","attributes":{"align":"left"},"children":[{"type":"Text","content":"Left"}]},{"type":"TableHeaderCell","attributes":{"align":"center"},"children":[{"type":"Text","content":"Center"}]},{"type":"TableHeaderCell","attributes":{"align":"right"},"children":[{"type":"Text","content":"Right"}]}]}]},{"type":"TableBody","children":[{"type":"TableRow","children":[{"type":"TableCell","attributes":{"align":"left"},"children":[{"type":"Text","content":"a"}]},{"type":"TableCell","attributes":{"align":"center"},"children":[{"type":"Text","content":"b"}]},{"type":"TableCell","attributes":{"align":"right"},"children":[{"type":"Text","content":"c"}]}]},{"type":"TableRow","children":[{"type":"TableCell","attributes":{"align":"left"},"children":[{"type":"Code","children":[{"type":"Text","content":"x"}]}]},{"type":"TableCell","attributes":{"align":"center"},"children":[{"type":"Strong","children":[{"type":"Text","content":"y"}]}]},{"type":"TableCell","attributes":{"align":"right"},"children":[{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"z"}]}]}]}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Strikethrough","children":[{"type":"Text","content":"struck through"}]},{"type":"Text","content":" and "},{"type":"Link","attributes":{"url":"https://example.com/bare"},"children":[{"type":"Text","content":"https://example.com/bare"}]},{"type":"Text","content":" plus "},{"type":"Link","attributes":{"url":"http://www.example.com"},"children":[{"type":"Text","content":"www.example.com"}]},{"type":"LineBreak"},{"type":"Text","content":"and "},{"type":"Link","attributes":{"url":"mailto:someone@example.com"},"children":[{"type":"Text","content":"someone@example.com"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Prefixed e-mail autolinks: "},{"type":"Link","attributes":{"url":"mailto:someone@example.com"},"children":[{"type":"Text","content":"mailto:someone@example.com"}]},{"type":"Text","content":" and"},{"type":"LineBreak"},{"type":"Link","attributes":{"url":"xmpp:someone@example.com"},"children":[{"type":"Text","content":"xmpp:someone@example.com"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Admonition","attributes":{"admonitionType":"note"},"children":[{"type":"Paragraph","children":[{"type":"Text","content":"An admonition body."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Admonition","attributes":{"admonitionType":"warning"},"children":[{"type":"Paragraph","children":[{"type":"Text","content":"Another one with a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"Text","content":"."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Footnote reference[^note] in a paragraph."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"[^note]: The footnote definition."}]}]} +=== gfm.md [extensions-on-commonmark] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"| Left | Center | Right |"},{"type":"LineBreak"},{"type":"Text","content":"|:-----|:------:|------:|"},{"type":"LineBreak"},{"type":"Text","content":"| a | b | c |"},{"type":"LineBreak"},{"type":"Text","content":"| "},{"type":"Code","children":[{"type":"Text","content":"x"}]},{"type":"Text","content":" | "},{"type":"Strong","children":[{"type":"Text","content":"y"}]},{"type":"Text","content":" | "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"z"}]},{"type":"Text","content":" |"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"~~struck through~~ and "},{"type":"Link","attributes":{"url":"https://example.com/bare"},"children":[{"type":"Text","content":"https://example.com/bare"}]},{"type":"Text","content":" plus "},{"type":"Link","attributes":{"url":"http://www.example.com"},"children":[{"type":"Text","content":"www.example.com"}]},{"type":"LineBreak"},{"type":"Text","content":"and "},{"type":"Link","attributes":{"url":"mailto:someone@example.com"},"children":[{"type":"Text","content":"someone@example.com"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Prefixed e-mail autolinks: "},{"type":"Link","attributes":{"url":"mailto:someone@example.com"},"children":[{"type":"Text","content":"mailto:someone@example.com"}]},{"type":"Text","content":" and"},{"type":"LineBreak"},{"type":"Link","attributes":{"url":"xmpp:someone@example.com"},"children":[{"type":"Text","content":"xmpp:someone@example.com"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Admonition","attributes":{"admonitionType":"note"},"children":[{"type":"Paragraph","children":[{"type":"Text","content":"An admonition body."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Admonition","attributes":{"admonitionType":"warning"},"children":[{"type":"Paragraph","children":[{"type":"Text","content":"Another one with a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"Text","content":"."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Footnote reference[^note] in a paragraph."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"[^note]: The footnote definition."}]}]} +=== html-blocks.md [defaults-gfm] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Intro paragraph before the video."}]},{"type":"Video","attributes":{"url":"https://example.com/clip.mp4"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph between."}]},{"type":"Video","attributes":{"url":"https://example.com/in-list.mp4"}},{"type":"Paragraph","children":[{"type":"Text","content":"Inline html span inside a paragraph."}]},{"type":"Video","attributes":{"url":"https://example.com/multiline.mp4"}}]} +=== html-blocks.md [defaults-commonmark] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Intro paragraph before the video."}]},{"type":"Video","attributes":{"url":"https://example.com/clip.mp4"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph between."}]},{"type":"Video","attributes":{"url":"https://example.com/in-list.mp4"}},{"type":"Paragraph","children":[{"type":"Text","content":"Inline html span inside a paragraph."}]},{"type":"Video","attributes":{"url":"https://example.com/multiline.mp4"}}]} +=== html-blocks.md [extensions-off-gfm] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Intro paragraph before the video."}]},{"type":"Video","attributes":{"url":"https://example.com/clip.mp4"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph between."}]},{"type":"Video","attributes":{"url":"https://example.com/in-list.mp4"}},{"type":"Paragraph","children":[{"type":"Text","content":"Inline html span inside a paragraph."}]},{"type":"Video","attributes":{"url":"https://example.com/multiline.mp4"}}]} +=== html-blocks.md [extensions-on-gfm] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Intro paragraph before the video."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Video","attributes":{"url":"https://example.com/clip.mp4"}},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph between."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Video","attributes":{"url":"https://example.com/in-list.mp4"}},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Inline html span inside a paragraph."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Video","attributes":{"url":"https://example.com/multiline.mp4"}}]} +=== html-blocks.md [extensions-on-commonmark] === +{"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Intro paragraph before the video."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Video","attributes":{"url":"https://example.com/clip.mp4"}},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph between."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Video","attributes":{"url":"https://example.com/in-list.mp4"}},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Inline html span inside a paragraph."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Video","attributes":{"url":"https://example.com/multiline.mp4"}}]} diff --git a/packages/core/cpp/wasm/ASTSerializer.cpp b/packages/core/cpp/wasm/ASTSerializer.cpp index 9cd5d7647..fef695a04 100644 --- a/packages/core/cpp/wasm/ASTSerializer.cpp +++ b/packages/core/cpp/wasm/ASTSerializer.cpp @@ -1,6 +1,9 @@ #include "ASTSerializer.hpp" +#include #include #include +#include +#include namespace Markdown { @@ -130,15 +133,25 @@ void ASTSerializer::serializeNode(const MarkdownASTNode &node, std::string &out) } if (!node.attributes.empty()) { + // Sorted: attributes live in an unordered_map, whose iteration order is + // not fixed across standard library implementations, and the golden dump + // in packages/core/cpp/tests compares these bytes. + std::vector *> sorted; + sorted.reserve(node.attributes.size()); + for (const auto &kv : node.attributes) { + sorted.push_back(&kv); + } + std::sort(sorted.begin(), sorted.end(), [](const auto *lhs, const auto *rhs) { return lhs->first < rhs->first; }); + out += ",\"attributes\":{"; bool first = true; - for (const auto &kv : node.attributes) { + for (const auto *kv : sorted) { if (!first) out += ','; first = false; - appendEscaped(kv.first, out); + appendEscaped(kv->first, out); out += ':'; - appendEscaped(kv.second, out); + appendEscaped(kv->second, out); } out += '}'; } diff --git a/packages/core/cpp/wasm/build.sh b/packages/core/cpp/wasm/build.sh index 45e38440d..787d01131 100755 --- a/packages/core/cpp/wasm/build.sh +++ b/packages/core/cpp/wasm/build.sh @@ -11,16 +11,18 @@ # Output: # packages/react-native-enriched-markdown/src/web/wasm/md4c.js # -# NOTE: the committed md4c.js is an artifact, and the docs describe what the -# *committed* one can do - not what this source can. It was last rebuilt before -# the Video node type was added, so the shipped parser emits no `Video` node and -# three doc pages correctly say video does not render on web: -# docs/docs/introduction/supported-features.md (Videos | Web | No) -# docs/docs/react-native/guides/web-support.md ("Not supported on web") -# docs/docs/react-native/api-reference/element-structure.md (the video caution) -# A VideoRenderer, `videoStyle` and the 'Video' type already exist under -# src/web/, so the day this script is run those three pages flip to wrong at -# once. Update them in the same commit as the rebuilt artifact. +# NOTE: the committed md4c.js is an artifact, and the docs under docs/ describe +# what the *committed* one can do - not what this source can. Nothing rebuilds +# it on install, prepare or prepack, so a change under packages/core/cpp reaches +# native immediately and web only once someone runs this script. It had been +# behind by a release cycle and a whole feature (#765's video blocks, which the +# web renderer already had a VideoRenderer for) before anyone noticed, which is +# why scripts/test-web-bundle.mjs now compares the committed bundle against the +# same golden AST dump as the host parser, in CI. +# +# That test catches a stale bundle, not stale prose: after rebuilding, re-read +# whatever docs/ says about what web does and does not support, and update it in +# the same commit as the artifact. set -euo pipefail @@ -31,22 +33,29 @@ OUT_DIR="${OUT_DIR:-$REPO_ROOT/packages/react-native-enriched-markdown/src/web/w mkdir -p "$OUT_DIR" +# Intermediates stay out of the source tree: a failed link used to leave +# enrmrkd.o sitting next to the bundle. +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + echo "Building md4c WASM…" # Compile the C file separately (no -std=c++17) emcc \ -I "$CPP_ROOT" \ -O2 \ - -c "$CPP_ROOT/md4c/md4c.c" \ - -o "$OUT_DIR/md4c.o" + -c "$CPP_ROOT/enrmrkd/enrmrkd.c" \ + -o "$WORK/enrmrkd.o" -# Compile C++ sources and link everything together -emcc \ +# Compile C++ sources and link everything together. em++, not emcc: emscripten +# 6.0.6 turned DEFAULT_TO_CXX off, so emcc no longer links the C++ runtime. +em++ \ "$SCRIPT_DIR/md4c_wasm.cpp" \ "$SCRIPT_DIR/ASTSerializer.cpp" \ "$CPP_ROOT/parser/MD4CParser.cpp" \ - "$OUT_DIR/md4c.o" \ + "$WORK/enrmrkd.o" \ -I "$CPP_ROOT" \ + -I "$CPP_ROOT/enrmrkd" \ -I "$SCRIPT_DIR" \ -O2 \ -std=c++17 \ @@ -65,6 +74,4 @@ emcc \ -s GROWABLE_ARRAYBUFFERS=0 \ -o "$OUT_DIR/md4c.js" -rm "$OUT_DIR/md4c.o" - echo "Done → $OUT_DIR/md4c.js" diff --git a/packages/enriched-markdown-android/parser/src/main/cpp/CMakeLists.txt b/packages/enriched-markdown-android/parser/src/main/cpp/CMakeLists.txt index dc5b03288..8cb2edbb6 100644 --- a/packages/enriched-markdown-android/parser/src/main/cpp/CMakeLists.txt +++ b/packages/enriched-markdown-android/parser/src/main/cpp/CMakeLists.txt @@ -3,18 +3,18 @@ project(enriched_markdown_parser) set(CPP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../core/cpp") -if(NOT EXISTS "${CPP_ROOT}/md4c/md4c.c") +if(NOT EXISTS "${CPP_ROOT}/enrmrkd/enrmrkd.c") message(FATAL_ERROR "EnrichedMarkdown C++ sources not found at ${CPP_ROOT}") endif() -file(GLOB MD4C_SOURCES "${CPP_ROOT}/md4c/*.c") +file(GLOB ENRMRKD_SOURCES "${CPP_ROOT}/enrmrkd/*.c") file(GLOB PARSER_SOURCES "${CPP_ROOT}/parser/*.cpp") set(LANGUAGE_SOURCES "${CPP_ROOT}/highlight/CodeBlockLanguages.cpp") -add_library(md4c_lib STATIC ${MD4C_SOURCES}) -target_include_directories(md4c_lib PUBLIC "${CPP_ROOT}/md4c") -target_compile_definitions(md4c_lib PRIVATE MD4C_USE_UTF8=1) -set_target_properties(md4c_lib PROPERTIES +add_library(enrmrkd_lib STATIC ${ENRMRKD_SOURCES}) +target_include_directories(enrmrkd_lib PUBLIC "${CPP_ROOT}/enrmrkd") +target_compile_definitions(enrmrkd_lib PRIVATE ENRMRKD_USE_UTF8=1) +set_target_properties(enrmrkd_lib PROPERTIES C_STANDARD 11 C_STANDARD_REQUIRED ON ) @@ -31,19 +31,19 @@ target_include_directories( enriched_markdown_parser PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/jni" - "${CPP_ROOT}/md4c" + "${CPP_ROOT}/enrmrkd" "${CPP_ROOT}/parser" "${CPP_ROOT}/highlight" ) -target_compile_definitions(enriched_markdown_parser PRIVATE MD4C_USE_UTF8=1) +target_compile_definitions(enriched_markdown_parser PRIVATE ENRMRKD_USE_UTF8=1) find_package(fbjni REQUIRED CONFIG) find_library(LOG_LIB log) target_link_libraries( enriched_markdown_parser - md4c_lib + enrmrkd_lib fbjni::fbjni ${LOG_LIB} ) diff --git a/packages/enriched-markdown-ios/Package.swift b/packages/enriched-markdown-ios/Package.swift index 6e2cc3982..e7d6456c3 100644 --- a/packages/enriched-markdown-ios/Package.swift +++ b/packages/enriched-markdown-ios/Package.swift @@ -23,13 +23,13 @@ let package = Package( .target( name: "EnrichedMarkdownCore", path: "core", - sources: ["md4c", "parser", "highlight"], + sources: ["enrmrkd", "parser", "highlight"], publicHeadersPath: "parser", cSettings: [ - .define("MD4C_USE_UTF8", to: "1") + .define("ENRMRKD_USE_UTF8", to: "1") ], cxxSettings: [ - .headerSearchPath("md4c"), + .headerSearchPath("enrmrkd"), .headerSearchPath("parser") ] ), @@ -39,10 +39,10 @@ let package = Package( path: "cpp", publicHeadersPath: ".", cxxSettings: [ - .headerSearchPath("../core/md4c"), + .headerSearchPath("../core/enrmrkd"), .headerSearchPath("../core/parser"), .headerSearchPath("../core/highlight"), - .define("MD4C_USE_UTF8", to: "1") + .define("ENRMRKD_USE_UTF8", to: "1") ] ), .target( diff --git a/packages/enriched-markdown-ios/core/enrmrkd b/packages/enriched-markdown-ios/core/enrmrkd new file mode 120000 index 000000000..e2a2c12e1 --- /dev/null +++ b/packages/enriched-markdown-ios/core/enrmrkd @@ -0,0 +1 @@ +../../core/cpp/enrmrkd \ No newline at end of file diff --git a/packages/enriched-markdown-ios/core/md4c b/packages/enriched-markdown-ios/core/md4c deleted file mode 120000 index 8cb139bb0..000000000 --- a/packages/enriched-markdown-ios/core/md4c +++ /dev/null @@ -1 +0,0 @@ -../../core/cpp/md4c \ No newline at end of file diff --git a/packages/react-native-enriched-markdown/ReactNativeEnrichedMarkdown.podspec b/packages/react-native-enriched-markdown/ReactNativeEnrichedMarkdown.podspec index b16404913..e51da4893 100644 --- a/packages/react-native-enriched-markdown/ReactNativeEnrichedMarkdown.podspec +++ b/packages/react-native-enriched-markdown/ReactNativeEnrichedMarkdown.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.dependency "EnrichedMarkdownCore" else s.private_header_files = "ios/**/*.h", "cpp/**/*.{h,hpp}" - s.source_files = ["ios/**/*.{h,m,mm,cpp,swift}", "cpp/md4c/*.{c,h}", "cpp/parser/*.{hpp,cpp}", "cpp/highlight/*.{hpp,cpp}"] + code_highlight[:source_files] + s.source_files = ["ios/**/*.{h,m,mm,cpp,swift}", "cpp/enrmrkd/*.{c,h}", "cpp/parser/*.{hpp,cpp}", "cpp/highlight/*.{hpp,cpp}"] + code_highlight[:source_files] s.preserve_paths = "cpp/highlight/vendor/**/*" if code_highlight[:enabled] end @@ -108,7 +108,7 @@ Pod::Spec.new do |s| # Default on: consumers opt out via "enriched-markdown".enableVideo = false in package.json. enable_video = config.key?('enableVideo') ? config['enableVideo'] != false : true - preprocessor_defs = "$(inherited) MD4C_USE_UTF8=1#{code_highlight[:defines]}" + preprocessor_defs = "$(inherited) ENRMRKD_USE_UTF8=1#{code_highlight[:defines]}" if enable_video preprocessor_defs += ' ENRICHED_MARKDOWN_VIDEO=1' end @@ -130,7 +130,7 @@ Pod::Spec.new do |s| pod_xcconfig = { 'HEADER_SEARCH_PATHS' => ([ - "\"#{cpp_root}/md4c\"", "\"#{cpp_root}/parser\"", "\"#{cpp_root}/highlight\"", + "\"#{cpp_root}/enrmrkd\"", "\"#{cpp_root}/parser\"", "\"#{cpp_root}/highlight\"", "\"$(PODS_TARGET_SRCROOT)/ios/internals\"", "\"$(PODS_TARGET_SRCROOT)/ios/input/internals\"" ] + code_highlight[:header_paths].map { |p| "\"$(PODS_TARGET_SRCROOT)/#{p}\"" }).join(" "), 'GCC_PREPROCESSOR_DEFINITIONS' => preprocessor_defs, diff --git a/packages/react-native-enriched-markdown/android/src/main/jni/CMakeLists.txt b/packages/react-native-enriched-markdown/android/src/main/jni/CMakeLists.txt index 2bdaa07a0..cbdd7e558 100644 --- a/packages/react-native-enriched-markdown/android/src/main/jni/CMakeLists.txt +++ b/packages/react-native-enriched-markdown/android/src/main/jni/CMakeLists.txt @@ -15,9 +15,9 @@ set(LIB_ANDROID_GENERATED_COMPONENTS_DIR ${LIB_ANDROID_GENERATED_JNI_DIR}/react/ set(CPP_IN_PACKAGE "${CMAKE_CURRENT_SOURCE_DIR}/../../../../cpp") set(CPP_IN_MONOREPO "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../core/cpp") -if(EXISTS "${CPP_IN_PACKAGE}/md4c/md4c.c") +if(EXISTS "${CPP_IN_PACKAGE}/enrmrkd/enrmrkd.c") set(CPP_ROOT "${CPP_IN_PACKAGE}") -elseif(EXISTS "${CPP_IN_MONOREPO}/md4c/md4c.c") +elseif(EXISTS "${CPP_IN_MONOREPO}/enrmrkd/enrmrkd.c") set(CPP_ROOT "${CPP_IN_MONOREPO}") else() message(FATAL_ERROR "EnrichedMarkdown C++ sources not found. Expected cpp/ or packages/core/cpp.") @@ -33,15 +33,15 @@ if(EXISTS "${HIGHLIGHT_CONFIG}") include("${HIGHLIGHT_CONFIG}") endif() -file(GLOB MD4C_SOURCES "${CPP_ROOT}/md4c/*.c") +file(GLOB ENRMRKD_SOURCES "${CPP_ROOT}/enrmrkd/*.c") file(GLOB PARSER_SOURCES "${CPP_ROOT}/parser/*.cpp") file(GLOB HIGHLIGHT_SOURCES "${CPP_ROOT}/highlight/*.cpp") -# md4c is C code, build as separate static library with C flags -add_library(md4c_lib STATIC ${MD4C_SOURCES}) -target_include_directories(md4c_lib PUBLIC ${CPP_ROOT}/md4c) -target_compile_definitions(md4c_lib PRIVATE MD4C_USE_UTF8=1) -set_target_properties(md4c_lib PROPERTIES +# The vendored parser is C code, build as separate static library with C flags +add_library(enrmrkd_lib STATIC ${ENRMRKD_SOURCES}) +target_include_directories(enrmrkd_lib PUBLIC ${CPP_ROOT}/enrmrkd) +target_compile_definitions(enrmrkd_lib PRIVATE ENRMRKD_USE_UTF8=1) +set_target_properties(enrmrkd_lib PROPERTIES C_STANDARD 11 C_STANDARD_REQUIRED ON ) @@ -66,12 +66,12 @@ target_include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/react/renderer/components/${LIB_LITERAL} ${LIB_ANDROID_GENERATED_JNI_DIR} ${LIB_ANDROID_GENERATED_COMPONENTS_DIR} - ${CPP_ROOT}/md4c + ${CPP_ROOT}/enrmrkd ${CPP_ROOT}/parser ${CPP_ROOT}/highlight ) -target_compile_definitions(${LIB_TARGET_NAME} PRIVATE MD4C_USE_UTF8=1) +target_compile_definitions(${LIB_TARGET_NAME} PRIVATE ENRMRKD_USE_UTF8=1) find_package(fbjni REQUIRED CONFIG) find_package(ReactAndroid REQUIRED CONFIG) @@ -80,7 +80,7 @@ find_library(LOG_LIB log) target_link_libraries( ${LIB_TARGET_NAME} ${LOG_LIB} - md4c_lib + enrmrkd_lib fbjni::fbjni ReactAndroid::jsi ReactAndroid::reactnative diff --git a/packages/react-native-enriched-markdown/ios/input/ENRMInputParser.mm b/packages/react-native-enriched-markdown/ios/input/ENRMInputParser.mm index f82e72b3b..0cd5d7e9d 100644 --- a/packages/react-native-enriched-markdown/ios/input/ENRMInputParser.mm +++ b/packages/react-native-enriched-markdown/ios/input/ENRMInputParser.mm @@ -1,7 +1,7 @@ #import "ENRMInputParser.h" #import "ENRMFormattingRange.h" #import "ENRMInputRemend.h" -#include "md4c.h" +#include "enrmrkd.h" #include #include #include @@ -20,18 +20,18 @@ @implementation ENRMParseResult static const size_t kByteOffsetUnset = SIZE_MAX; struct SpanTypeMapping { - MD_SPANTYPE md4cType; + ENRMRKD_SPANTYPE md4cType; ENRMInputStyleType styleType; }; static const SpanTypeMapping kSupportedSpans[] = { - {MD_SPAN_STRONG, ENRMInputStyleTypeStrong}, {MD_SPAN_EM, ENRMInputStyleTypeEmphasis}, - {MD_SPAN_U, ENRMInputStyleTypeUnderline}, {MD_SPAN_DEL, ENRMInputStyleTypeStrikethrough}, - {MD_SPAN_A, ENRMInputStyleTypeLink}, {MD_SPAN_SPOILER, ENRMInputStyleTypeSpoiler}, + {ENRMRKD_SPAN_STRONG, ENRMInputStyleTypeStrong}, {ENRMRKD_SPAN_EM, ENRMInputStyleTypeEmphasis}, + {ENRMRKD_SPAN_U, ENRMInputStyleTypeUnderline}, {ENRMRKD_SPAN_DEL, ENRMInputStyleTypeStrikethrough}, + {ENRMRKD_SPAN_A, ENRMInputStyleTypeLink}, {ENRMRKD_SPAN_SPOILER, ENRMInputStyleTypeSpoiler}, }; static const size_t kSupportedSpanCount = sizeof(kSupportedSpans) / sizeof(kSupportedSpans[0]); -static bool isSupportedSpan(MD_SPANTYPE md4cType, ENRMInputStyleType &outStyleType) +static bool isSupportedSpan(ENRMRKD_SPANTYPE md4cType, ENRMInputStyleType &outStyleType) { for (size_t index = 0; index < kSupportedSpanCount; index++) { if (kSupportedSpans[index].md4cType == md4cType) { @@ -44,23 +44,23 @@ static bool isSupportedSpan(MD_SPANTYPE md4cType, ENRMInputStyleType &outStyleTy // Block-type mapping mirrors kSupportedSpans for the inline pipeline. A block // handler extends recognition by adding its md4c block here and, if leveled, -// reading its detail in resolveBlockLevel below. MD_BLOCK_P maps to the +// reading its detail in resolveBlockLevel below. ENRMRKD_BLOCK_P maps to the // implicit Paragraph default and produces no stored block range. struct BlockTypeMapping { - MD_BLOCKTYPE md4cType; + ENRMRKD_BLOCKTYPE md4cType; ENRMInputBlockType blockType; }; static const BlockTypeMapping kSupportedBlocks[] = { - {MD_BLOCK_P, ENRMInputBlockTypeParagraph}, - // MD_BLOCK_H maps to a representative heading type; onEnterBlock resolves the + {ENRMRKD_BLOCK_P, ENRMInputBlockTypeParagraph}, + // ENRMRKD_BLOCK_H maps to a representative heading type; onEnterBlock resolves the // level (via resolveBlockLevel) and rewrites the type to the level-specific // ENRMInputBlockTypeHeadingN. - {MD_BLOCK_H, ENRMInputBlockTypeHeading1}, + {ENRMRKD_BLOCK_H, ENRMInputBlockTypeHeading1}, }; static const size_t kSupportedBlockCount = sizeof(kSupportedBlocks) / sizeof(kSupportedBlocks[0]); -static bool isSupportedBlock(MD_BLOCKTYPE md4cType, ENRMInputBlockType &outBlockType) +static bool isSupportedBlock(ENRMRKD_BLOCKTYPE md4cType, ENRMInputBlockType &outBlockType) { for (size_t index = 0; index < kSupportedBlockCount; index++) { if (kSupportedBlocks[index].md4cType == md4cType) { @@ -72,12 +72,12 @@ static bool isSupportedBlock(MD_BLOCKTYPE md4cType, ENRMInputBlockType &outBlock } // Per-block integer payload (heading level, list depth). md4c exposes this in -// the block's MD_BLOCK_*_DETAIL struct. Headings read MD_BLOCK_H_DETAIL.level +// the block's ENRMRKD_BLOCK_*_DETAIL struct. Headings read ENRMRKD_BLOCK_H_DETAIL.level // (1-6); other blocks have no level and return 0. -static NSInteger resolveBlockLevel(MD_BLOCKTYPE blockType, void *detail) +static NSInteger resolveBlockLevel(ENRMRKD_BLOCKTYPE blockType, void *detail) { - if (blockType == MD_BLOCK_H && detail) { - return (NSInteger)(static_cast(detail)->level); + if (blockType == ENRMRKD_BLOCK_H && detail) { + return (NSInteger)(static_cast(detail)->level); } return 0; } @@ -178,21 +178,21 @@ static size_t closingDelimiterEndByte(const ParseContext &context, const InlineS // text offset into the currently open block(s). On leave_block the block is // resolved with whatever text range it accumulated; empty blocks (no text) are // discarded later when building results. -static int onEnterBlock(MD_BLOCKTYPE blockType, void *detail, void *userdata) +static int onEnterBlock(ENRMRKD_BLOCKTYPE blockType, void *detail, void *userdata) { auto *context = static_cast(userdata); // List nesting is tracked by the container stack, not stored as its own // block: the UL/OL container only frames the items that read it. - if (blockType == MD_BLOCK_UL || blockType == MD_BLOCK_OL) { - context->listContainerStack.push_back(blockType == MD_BLOCK_OL); + if (blockType == ENRMRKD_BLOCK_UL || blockType == ENRMRKD_BLOCK_OL) { + context->listContainerStack.push_back(blockType == ENRMRKD_BLOCK_OL); return 0; } - // Tag the item itself, not its inner paragraph: md4c emits MD_BLOCK_P inside + // Tag the item itself, not its inner paragraph: md4c emits ENRMRKD_BLOCK_P inside // items only for *loose* lists, so a tight list has no paragraph to tag. The // item's range is clipped back to its own first line when building results. - if (blockType == MD_BLOCK_LI) { + if (blockType == ENRMRKD_BLOCK_LI) { BlockInfo blockInfo; BOOL ordered = !context->listContainerStack.empty() && context->listContainerStack.back(); blockInfo.type = ordered ? ENRMInputBlockTypeOrderedListItem : ENRMInputBlockTypeUnorderedListItem; @@ -215,16 +215,16 @@ static int onEnterBlock(MD_BLOCKTYPE blockType, void *detail, void *userdata) blockInfo.level = resolveBlockLevel(blockType, detail); // Headings share one md4c block type but split into six ENRMInputBlockTypes by // level; map the resolved level onto the concrete heading type. - blockInfo.type = (blockType == MD_BLOCK_H) ? ENRMBlockTypeForHeadingLevel(blockInfo.level) : mappedType; + blockInfo.type = (blockType == ENRMRKD_BLOCK_H) ? ENRMBlockTypeForHeadingLevel(blockInfo.level) : mappedType; context->openBlockStack.push_back(blockInfo); return 0; } -static int onLeaveBlock(MD_BLOCKTYPE blockType, void *, void *userdata) +static int onLeaveBlock(ENRMRKD_BLOCKTYPE blockType, void *, void *userdata) { auto *context = static_cast(userdata); - if (blockType == MD_BLOCK_UL || blockType == MD_BLOCK_OL) { + if (blockType == ENRMRKD_BLOCK_UL || blockType == ENRMRKD_BLOCK_OL) { if (!context->listContainerStack.empty()) { context->listContainerStack.pop_back(); } @@ -233,7 +233,7 @@ static int onLeaveBlock(MD_BLOCKTYPE blockType, void *, void *userdata) // List items are tagged in onEnterBlock (not via isSupportedBlock); resolve // them here the same way as supported blocks. - if (blockType == MD_BLOCK_LI) { + if (blockType == ENRMRKD_BLOCK_LI) { if (!context->openBlockStack.empty()) { context->resolvedBlocks.push_back(context->openBlockStack.back()); context->openBlockStack.pop_back(); @@ -255,7 +255,7 @@ static int onLeaveBlock(MD_BLOCKTYPE blockType, void *, void *userdata) return 0; } -static int onEnterSpan(MD_SPANTYPE spanType, void *detail, void *userdata) +static int onEnterSpan(ENRMRKD_SPANTYPE spanType, void *detail, void *userdata) { ENRMInputStyleType styleType; if (!isSupportedSpan(spanType, styleType)) { @@ -267,8 +267,8 @@ static int onEnterSpan(MD_SPANTYPE spanType, void *detail, void *userdata) spanInfo.type = styleType; spanInfo.openingDelimiterByteOffset = context->lastTextEnd; - if (spanType == MD_SPAN_A && detail) { - auto *linkDetail = static_cast(detail); + if (spanType == ENRMRKD_SPAN_A && detail) { + auto *linkDetail = static_cast(detail); if (linkDetail->href.text && linkDetail->href.size > 0) { spanInfo.linkURL = std::string(linkDetail->href.text, linkDetail->href.size); } @@ -278,7 +278,7 @@ static int onEnterSpan(MD_SPANTYPE spanType, void *detail, void *userdata) return 0; } -static int onLeaveSpan(MD_SPANTYPE spanType, void *, void *userdata) +static int onLeaveSpan(ENRMRKD_SPANTYPE spanType, void *, void *userdata) { ENRMInputStyleType styleType; if (!isSupportedSpan(spanType, styleType)) { @@ -295,7 +295,7 @@ static int onLeaveSpan(MD_SPANTYPE spanType, void *, void *userdata) return 0; } -static int onText(MD_TEXTTYPE, const MD_CHAR *text, MD_SIZE size, void *userdata) +static int onText(ENRMRKD_TEXTTYPE, const ENRMRKD_CHAR *text, ENRMRKD_SIZE size, void *userdata) { if (!text || size == 0) { return 0; @@ -303,7 +303,7 @@ static int onText(MD_TEXTTYPE, const MD_CHAR *text, MD_SIZE size, void *userdata auto *context = static_cast(userdata); // md4c passes pointers outside the input buffer for synthetic tokens - // (e.g. MD_TEXT_SOFTBR, MD_TEXT_BR use a string literal "\n"). + // (e.g. ENRMRKD_TEXT_SOFTBR, ENRMRKD_TEXT_BR use a string literal "\n"). // Pointer arithmetic against context->buffer would underflow, corrupting offsets. // // Skipping out-of-buffer tokens means lastTextEnd doesn't advance past @@ -349,9 +349,9 @@ static bool runMd4cParse(NSString *markdown, ParseContext &context) context.bufferLength = completedLength; context.originalLength = originalLength; - MD_PARSER parser = { + ENRMRKD_PARSER parser = { .abi_version = 0, - .flags = MD_FLAG_NOHTML | MD_FLAG_UNDERLINE | MD_FLAG_STRIKETHROUGH | MD_FLAG_SPOILERS, + .flags = ENRMRKD_FLAG_NOHTML | ENRMRKD_FLAG_UNDERLINE | ENRMRKD_FLAG_STRIKETHROUGH | ENRMRKD_FLAG_SPOILERS, .enter_block = onEnterBlock, .leave_block = onLeaveBlock, .enter_span = onEnterSpan, @@ -361,7 +361,7 @@ static bool runMd4cParse(NSString *markdown, ParseContext &context) .syntax = nullptr, }; - return md_parse(completedUTF8, (MD_SIZE)completedLength, &parser, &context) == 0; + return enrmrkd_parse(completedUTF8, (ENRMRKD_SIZE)completedLength, &parser, &context) == 0; } // Builds inline styled ranges (raw-markdown UTF-16 coords) from a completed diff --git a/packages/react-native-enriched-markdown/src/web/wasm/md4c.js b/packages/react-native-enriched-markdown/src/web/wasm/md4c.js index 26a61d7c35bb867263c13d11a59907a315f62b8b..d14134bad4ca2be584b34d4e97f2401386b816fd 100644 GIT binary patch literal 147039 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⋙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 OLe+pf8}9f1aI38w~N^1`-# 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 exit 2 ;; +esac + +CC_BIN="${CC:-cc}" +CXX_BIN="${CXX:-c++}" +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +echo "==> Building the vendored parser and the AST dumper" +"$CC_BIN" -O1 -std=c99 -DENRMRKD_USE_UTF8=1 -c "$CPP_ROOT/enrmrkd/enrmrkd.c" -o "$WORK/enrmrkd.o" +"$CXX_BIN" -O1 -std=c++17 -Wall -I "$CPP_ROOT/enrmrkd" -I "$CPP_ROOT/parser" -I "$CPP_ROOT/wasm" \ + "$TESTS_DIR/ast_dump.cpp" \ + "$CPP_ROOT/parser/MD4CParser.cpp" \ + "$CPP_ROOT/wasm/ASTSerializer.cpp" \ + "$WORK/enrmrkd.o" -o "$WORK/ast-dump" + +echo "==> Checking the vendored parser's exported symbols" +if command -v nm >/dev/null 2>&1; then + # Some platforms (e.g. MacOS) prefix C symbols with an underscore. + unexpected=$(nm -g --defined-only "$WORK/enrmrkd.o" \ + | awk 'NF >= 3 { print $3 }' | grep -vE '^_?enrmrkd_' | sort -u || true) + if [ -n "$unexpected" ]; then + echo "FAIL: the vendored parser defines globals without the enrmrkd_ prefix:" >&2 + echo "$unexpected" | sed 's/^/ /' >&2 + echo >&2 + echo "Each would collide with another embedded MD4C copy. They usually arrive" >&2 + echo "with a merge from upstream into software-mansion-labs/md4c; run that" >&2 + echo "repo's scripts/rename-upstream-symbols.pl and re-sync." >&2 + exit 1 + fi + nm -g --defined-only "$WORK/enrmrkd.o" | awk 'NF >= 3 { print " " $3 }' | sort -u +else + echo " nm not available, skipped" +fi + +echo "==> Comparing the parsed AST against the golden dump" +shopt -s nullglob +fixtures=("$TESTS_DIR"/fixtures/*.md) +shopt -u nullglob +if [ "${#fixtures[@]}" -eq 0 ]; then + echo "FAIL: no fixtures in ${TESTS_DIR#"$REPO_ROOT"/}/fixtures" >&2 + exit 1 +fi +"$WORK/ast-dump" "${fixtures[@]}" > "$WORK/ast.txt" +if [ "$update" -eq 1 ]; then + mv "$WORK/ast.txt" "$GOLDEN" + echo " golden dump updated: ${GOLDEN#"$REPO_ROOT"/}" +elif ! diff -u "$GOLDEN" "$WORK/ast.txt" > "$WORK/ast.diff"; then + echo "FAIL: the AST changed for the fixture corpus:" >&2 + head -40 "$WORK/ast.diff" | cut -c1-200 >&2 + echo >&2 + echo "If the change is intended (a parser sync, or a MD4CParser change), review" >&2 + echo "it and re-record with: scripts/test-core-parser.sh --update" >&2 + exit 1 +else + echo " $(grep -c '^=== ' "$GOLDEN") fixture/flag combinations unchanged" +fi + +echo "==> Linking beside another embedded MD4C copy (mity/md4c $UPSTREAM_MD4C_REF)" +mkdir -p "$WORK/other" +base="https://raw.githubusercontent.com/mity/md4c/$UPSTREAM_MD4C_REF/src" +if ! curl -fsSL --retry 2 "$base/md4c.c" -o "$WORK/other/md4c.c" \ + || ! curl -fsSL --retry 2 "$base/md4c.h" -o "$WORK/other/md4c.h"; then + if [ "${ENRM_SKIP_COEXISTENCE_CHECK:-0}" = "1" ] && [ -z "${CI:-}" ]; then + echo " could not fetch upstream MD4C; skipped by ENRM_SKIP_COEXISTENCE_CHECK" + echo + echo "PASS (coexistence check skipped)" + exit 0 + fi + echo "FAIL: could not fetch mity/md4c $UPSTREAM_MD4C_REF from $base" >&2 + echo >&2 + echo "The coexistence check is the regression guard for #846, so a download" >&2 + echo "failure is a failure, not a skip. Working offline, outside CI, you can" >&2 + echo "run the rest with ENRM_SKIP_COEXISTENCE_CHECK=1." >&2 + exit 1 +fi +cat > "$WORK/coexist.cpp" <<'EOF' +/* + * An application linking Enriched and another MD4C-embedding dependency. + * + * Both headers are included in this one translation unit, on purpose and in + * this order: a vendored enrmrkd.h that re-introduced an MD_-prefixed name, or + * whose include guard regressed to MD4C_H and so swallowed the second header, + * must not compile. The link step below then covers the symbols. + */ +#include "enrmrkd.h" +extern "C" { +#include "other/md4c.h" +} +#include "MD4CParser.hpp" +#include +#include +#include +static int onBlock(MD_BLOCKTYPE, void *, void *) { return 0; } +static int onSpan(MD_SPANTYPE, void *, void *) { return 0; } +static int onText(MD_TEXTTYPE, const MD_CHAR *, MD_SIZE, void *) { return 0; } +static int onEnrmBlock(ENRMRKD_BLOCKTYPE, void *, void *) { return 0; } +static int onEnrmSpan(ENRMRKD_SPANTYPE, void *, void *) { return 0; } +static int onEnrmText(ENRMRKD_TEXTTYPE, const ENRMRKD_CHAR *, ENRMRKD_SIZE, void *) { return 0; } +int main() { + const std::string doc = "# hi *there* ||spoiler||\n"; + const auto root = Markdown::MD4CParser().parse(doc, Markdown::Md4cFlags{}, true); + MD_PARSER other{0, MD_DIALECT_GITHUB, onBlock, onBlock, onSpan, onSpan, onText, nullptr, nullptr}; + const int rc = md_parse(doc.c_str(), (MD_SIZE)doc.size(), &other, nullptr); + ENRMRKD_PARSER ours{0, ENRMRKD_DIALECT_GITHUB, + onEnrmBlock, onEnrmBlock, + onEnrmSpan, onEnrmSpan, + onEnrmText, nullptr, + nullptr}; + const int ourRc = enrmrkd_parse(doc.c_str(), (ENRMRKD_SIZE)doc.size(), &ours, nullptr); + if (!root || rc != 0 || ourRc != 0) { + std::cerr << "coexistence check failed: root=" << (root ? "ok" : "null") << " rc=" << rc + << " ourRc=" << ourRc << "\n"; + return 1; + } + return 0; +} +EOF +"$CC_BIN" -O1 -std=c99 -c "$WORK/other/md4c.c" -o "$WORK/other.o" +"$CXX_BIN" -O1 -std=c++17 -I "$CPP_ROOT/enrmrkd" -I "$CPP_ROOT/parser" -I "$WORK" \ + -DENRMRKD_USE_UTF8=1 -c "$WORK/coexist.cpp" -o "$WORK/coexist.o" +"$CXX_BIN" -O1 -std=c++17 -I "$CPP_ROOT/enrmrkd" -I "$CPP_ROOT/parser" -c "$CPP_ROOT/parser/MD4CParser.cpp" -o "$WORK/parser.o" +"$CXX_BIN" "$WORK/other.o" "$WORK/enrmrkd.o" "$WORK/parser.o" "$WORK/coexist.o" -o "$WORK/coexist" +"$WORK/coexist" +echo " both parsers linked and ran in one binary" + +echo +echo "PASS" diff --git a/scripts/test-web-bundle.mjs b/scripts/test-web-bundle.mjs new file mode 100755 index 000000000..9ca845106 --- /dev/null +++ b/scripts/test-web-bundle.mjs @@ -0,0 +1,126 @@ +#!/usr/bin/env node +/* + * Checks the committed WASM bundle against the same golden AST dump that + * scripts/test-core-parser.sh records for the host-compiled parser. + * + * packages/react-native-enriched-markdown/src/web/wasm/md4c.js is a build + * artifact: nothing rebuilds it on install, prepare or prepack, so a change to + * packages/core/cpp reaches native immediately and web only once someone runs + * `yarn build:wasm`. It had been behind by a release cycle and a feature + * (#765's video blocks) before anyone noticed. Comparing the bundle's own + * output to the golden dump catches that without emscripten in CI. + * + * Usage: + * node scripts/test-web-bundle.mjs + */ +import { readFileSync, readdirSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +const REPO_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); +const BUNDLE = join( + REPO_ROOT, + 'packages/react-native-enriched-markdown/src/web/wasm/md4c.js' +); +const FIXTURES = join(REPO_ROOT, 'packages/core/cpp/tests/fixtures'); +const GOLDEN = join(REPO_ROOT, 'packages/core/cpp/tests/golden/ast.txt'); + +// parseMarkdown() in md4c_wasm.cpp exposes eight of the parser's flags; isGFM +// and permissiveAutolinks keep their Md4cFlags defaults (true). That reaches +// two of the golden dump's five variants - the other three turn one of those +// two off, so they cannot be reproduced through this entry point. +const VARIANTS = { + // underline, latexMath, superscript, subscript, highlight, hardSoftBreaks, + // preserveBlankLines, admonitions + 'defaults-gfm': [0, 1, 0, 0, 0, 0, 0, 1], + 'extensions-on-gfm': [1, 1, 1, 1, 1, 1, 1, 1], +}; + +function readGolden() { + const lines = readFileSync(GOLDEN, 'utf8').split('\n'); + const sections = new Map(); + for (let i = 0; i < lines.length - 1; i++) { + const header = lines[i].match(/^=== (\S+) \[(\S+)\] ===$/); + if (header) { + sections.set(`${header[1]} [${header[2]}]`, lines[i + 1]); + } + } + return sections; +} + +function firstDifference(actual, expected) { + const limit = Math.min(actual.length, expected.length); + let at = limit; + for (let i = 0; i < limit; i++) { + if (actual[i] !== expected[i]) { + at = i; + break; + } + } + const from = Math.max(0, at - 60); + return { + at, + actual: actual.slice(from, at + 60), + expected: expected.slice(from, at + 60), + }; +} + +function fail(message) { + console.error(`FAIL: ${message}`); + console.error(); + console.error( + 'The committed bundle is a build artifact and nothing rebuilds it' + ); + console.error('automatically. Rebuild and commit it with:'); + console.error(); + console.error(' yarn build:wasm'); + process.exit(1); +} + +const golden = readGolden(); +const fixtures = readdirSync(FIXTURES) + .filter((name) => name.endsWith('.md')) + .sort(); +if (fixtures.length === 0) { + fail(`no fixtures in ${FIXTURES}`); +} + +console.log('==> Loading the committed WASM bundle'); +const module = await import(pathToFileURL(BUNDLE).href); +const instance = await module.default(); +const parse = instance.cwrap('parseMarkdown', 'string', [ + 'string', + ...Array(8).fill('number'), +]); + +console.log('==> Comparing its AST against the golden dump'); +let compared = 0; +for (const fixture of fixtures) { + const markdown = readFileSync(join(FIXTURES, fixture), 'utf8'); + for (const [variant, flags] of Object.entries(VARIANTS)) { + const section = `${fixture} [${variant}]`; + const expected = golden.get(section); + if (expected === undefined) { + fail( + `the golden dump has no "${section}" section. Re-record it with ` + + './scripts/test-core-parser.sh --update, or update VARIANTS here.' + ); + } + const actual = parse(markdown, ...flags); + if (actual !== expected) { + const diff = firstDifference(actual, expected); + console.error(`FAIL: the bundle disagrees with the C++ parser on`); + console.error(` ${section}, at character ${diff.at}:`); + console.error(); + console.error(` bundle: …${diff.actual}…`); + console.error(` golden: …${diff.expected}…`); + console.error(); + fail(`${section} does not match the golden dump`); + } + compared++; + } +} + +console.log(` ${compared} fixture/flag combinations match`); +console.log(); +console.log('PASS'); From 131d261d07b14ef6a2edeb30e09b411101fd9688 Mon Sep 17 00:00:00 2001 From: Gregory Moskaliuk Date: Fri, 16 Oct 2026 23:15:48 +0200 Subject: [PATCH 05/11] fix(parser): preserve named and numeric character references (#1018) * fix(parser): preserve named and numeric character references * fix(parser): clamp decoded codepoints in one place and rebuild the web parser appendCodepoint now maps zero, surrogates and anything above U+10FFFF to U+FFFD itself, so the named table and the numeric path share one guard and the UTF-8 encoder can never emit a sequence for an out-of-range value. The numeric path only validates the digits. The committed md4c.js is rebuilt with entity.c linked in; web dropped character references until this artifact caught up with the sources. Co-Authored-By: Claude Fable 5.1 * fix(parser): parse numeric references without std::from_chars The Swift package and the Android CMake targets set no C++ standard, so is not guaranteed; the standalone iOS package failed to compile. md4c already caps numeric references at 7 decimal or 6 hex digits, so a plain digit loop cannot overflow and needs no library support. Co-Authored-By: Claude Fable 5.1 * fix(parser): decode character references in link and image attributes md4c hands attributes as typed substrings; getAttributeText copied the raw bytes, so `[q](/u?a=1&b=2)` decoded the text but kept `&` in the href. Entity segments now go through the same decoder as text. Include before the extern "C" block so entity.h's stdlib include is a no-op there, and add a jest test that runs the committed web parser so a stale md4c.js fails CI. Co-Authored-By: Claude Fable 5.1 * fix(ios): anchor decoded entities in the source offset annotator The Swift package's annotator and its tests assumed the shared core drops entity references, so a text node that now starts with a decoded entity failed to anchor and the slicer returned nil. The matcher already bridged one decoded scalar; it now bridges two for the handful of entities that decode to a pair, and the tests assert the decoded content with its source range spanning the reference. The entity branch moves into its own method to keep matchRemainder under the complexity limit. Co-Authored-By: Claude Fable 5.1 * fix(parser): look up entities through the fork's prefixed table The vendored entity.c exported a bare entity_lookup, the same duplicate-symbol class #846 fixed for the parser: an app that also links md4c-html would fail to link. software-mansion-labs/md4c already ships the table as enrmrkd-entity.{c,h} with enrmrkd_entity_lookup, so fetch-md4c.sh syncs that instead and MD4CParser uses the prefixed names. The table itself is unchanged. test-core-parser.sh builds the table into the AST dumper, runs the prefix check over it, and links upstream md4c-html's entity.c into the coexistence binary. The golden dump is re-recorded: the only change is the decoded "&" in commonmark.md's "Term & entity" across its five variants. --------- Co-authored-by: Yash Singh Co-authored-by: Claude Fable 5.1 Co-authored-by: eszlamczyk --- packages/core/cpp/enrmrkd/enrmrkd-entity.c | 2185 +++++++++++++++++ packages/core/cpp/enrmrkd/enrmrkd-entity.h | 43 + packages/core/cpp/parser/MD4CParser.cpp | 89 +- packages/core/cpp/tests/golden/ast.txt | 10 +- packages/core/cpp/wasm/build.sh | 7 + .../enriched/markdown/parser/ParserTest.kt | 34 + .../Parser/SourceOffsetAnnotator.swift | 33 +- .../MarkdownSourceSlicerTests.swift | 4 +- .../EnrichedMarkdownTests/ParserTests.swift | 18 + .../SourceOffsetAnnotatorTests.swift | 33 +- .../src/web/__tests__/parseMarkdown.test.ts | 61 + .../src/web/wasm/md4c.js | Bin 147039 -> 197228 bytes scripts/fetch-md4c.sh | 2 + scripts/test-core-parser.sh | 16 +- 14 files changed, 2495 insertions(+), 40 deletions(-) create mode 100644 packages/core/cpp/enrmrkd/enrmrkd-entity.c create mode 100644 packages/core/cpp/enrmrkd/enrmrkd-entity.h create mode 100644 packages/react-native-enriched-markdown/src/web/__tests__/parseMarkdown.test.ts diff --git a/packages/core/cpp/enrmrkd/enrmrkd-entity.c b/packages/core/cpp/enrmrkd/enrmrkd-entity.c new file mode 100644 index 000000000..dafe05080 --- /dev/null +++ b/packages/core/cpp/enrmrkd/enrmrkd-entity.c @@ -0,0 +1,2185 @@ +/* + * MD4C: Markdown parser for C + * (https://github.com/mity/md4c) + * + * Copyright (c) 2016-2026 Martin Mitáš + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "enrmrkd-entity.h" +#include + + +/* Generated by scripts/build_entity_map.py. */ +static const ENRMRKD_ENTITY ENRMRKD_ENTITY_MAP[] = { + { "Æ", { 198, 0 } }, + { "&", { 38, 0 } }, + { "Á", { 193, 0 } }, + { "Ă", { 258, 0 } }, + { "Â", { 194, 0 } }, + { "А", { 1040, 0 } }, + { "𝔄", { 120068, 0 } }, + { "À", { 192, 0 } }, + { "Α", { 913, 0 } }, + { "Ā", { 256, 0 } }, + { "⩓", { 10835, 0 } }, + { "Ą", { 260, 0 } }, + { "𝔸", { 120120, 0 } }, + { "⁡", { 8289, 0 } }, + { "Å", { 197, 0 } }, + { "𝒜", { 119964, 0 } }, + { "≔", { 8788, 0 } }, + { "Ã", { 195, 0 } }, + { "Ä", { 196, 0 } }, + { "∖", { 8726, 0 } }, + { "⫧", { 10983, 0 } }, + { "⌆", { 8966, 0 } }, + { "Б", { 1041, 0 } }, + { "∵", { 8757, 0 } }, + { "ℬ", { 8492, 0 } }, + { "Β", { 914, 0 } }, + { "𝔅", { 120069, 0 } }, + { "𝔹", { 120121, 0 } }, + { "˘", { 728, 0 } }, + { "ℬ", { 8492, 0 } }, + { "≎", { 8782, 0 } }, + { "Ч", { 1063, 0 } }, + { "©", { 169, 0 } }, + { "Ć", { 262, 0 } }, + { "⋒", { 8914, 0 } }, + { "ⅅ", { 8517, 0 } }, + { "ℭ", { 8493, 0 } }, + { "Č", { 268, 0 } }, + { "Ç", { 199, 0 } }, + { "Ĉ", { 264, 0 } }, + { "∰", { 8752, 0 } }, + { "Ċ", { 266, 0 } }, + { "¸", { 184, 0 } }, + { "·", { 183, 0 } }, + { "ℭ", { 8493, 0 } }, + { "Χ", { 935, 0 } }, + { "⊙", { 8857, 0 } }, + { "⊖", { 8854, 0 } }, + { "⊕", { 8853, 0 } }, + { "⊗", { 8855, 0 } }, + { "∲", { 8754, 0 } }, + { "”", { 8221, 0 } }, + { "’", { 8217, 0 } }, + { "∷", { 8759, 0 } }, + { "⩴", { 10868, 0 } }, + { "≡", { 8801, 0 } }, + { "∯", { 8751, 0 } }, + { "∮", { 8750, 0 } }, + { "ℂ", { 8450, 0 } }, + { "∐", { 8720, 0 } }, + { "∳", { 8755, 0 } }, + { "⨯", { 10799, 0 } }, + { "𝒞", { 119966, 0 } }, + { "⋓", { 8915, 0 } }, + { "≍", { 8781, 0 } }, + { "ⅅ", { 8517, 0 } }, + { "⤑", { 10513, 0 } }, + { "Ђ", { 1026, 0 } }, + { "Ѕ", { 1029, 0 } }, + { "Џ", { 1039, 0 } }, + { "‡", { 8225, 0 } }, + { "↡", { 8609, 0 } }, + { "⫤", { 10980, 0 } }, + { "Ď", { 270, 0 } }, + { "Д", { 1044, 0 } }, + { "∇", { 8711, 0 } }, + { "Δ", { 916, 0 } }, + { "𝔇", { 120071, 0 } }, + { "´", { 180, 0 } }, + { "˙", { 729, 0 } }, + { "˝", { 733, 0 } }, + { "`", { 96, 0 } }, + { "˜", { 732, 0 } }, + { "⋄", { 8900, 0 } }, + { "ⅆ", { 8518, 0 } }, + { "𝔻", { 120123, 0 } }, + { "¨", { 168, 0 } }, + { "⃜", { 8412, 0 } }, + { "≐", { 8784, 0 } }, + { "∯", { 8751, 0 } }, + { "¨", { 168, 0 } }, + { "⇓", { 8659, 0 } }, + { "⇐", { 8656, 0 } }, + { "⇔", { 8660, 0 } }, + { "⫤", { 10980, 0 } }, + { "⟸", { 10232, 0 } }, + { "⟺", { 10234, 0 } }, + { "⟹", { 10233, 0 } }, + { "⇒", { 8658, 0 } }, + { "⊨", { 8872, 0 } }, + { "⇑", { 8657, 0 } }, + { "⇕", { 8661, 0 } }, + { "∥", { 8741, 0 } }, + { "↓", { 8595, 0 } }, + { "⤓", { 10515, 0 } }, + { "⇵", { 8693, 0 } }, + { "̑", { 785, 0 } }, + { "⥐", { 10576, 0 } }, + { "⥞", { 10590, 0 } }, + { "↽", { 8637, 0 } }, + { "⥖", { 10582, 0 } }, + { "⥟", { 10591, 0 } }, + { "⇁", { 8641, 0 } }, + { "⥗", { 10583, 0 } }, + { "⊤", { 8868, 0 } }, + { "↧", { 8615, 0 } }, + { "⇓", { 8659, 0 } }, + { "𝒟", { 119967, 0 } }, + { "Đ", { 272, 0 } }, + { "Ŋ", { 330, 0 } }, + { "Ð", { 208, 0 } }, + { "É", { 201, 0 } }, + { "Ě", { 282, 0 } }, + { "Ê", { 202, 0 } }, + { "Э", { 1069, 0 } }, + { "Ė", { 278, 0 } }, + { "𝔈", { 120072, 0 } }, + { "È", { 200, 0 } }, + { "∈", { 8712, 0 } }, + { "Ē", { 274, 0 } }, + { "◻", { 9723, 0 } }, + { "▫", { 9643, 0 } }, + { "Ę", { 280, 0 } }, + { "𝔼", { 120124, 0 } }, + { "Ε", { 917, 0 } }, + { "⩵", { 10869, 0 } }, + { "≂", { 8770, 0 } }, + { "⇌", { 8652, 0 } }, + { "ℰ", { 8496, 0 } }, + { "⩳", { 10867, 0 } }, + { "Η", { 919, 0 } }, + { "Ë", { 203, 0 } }, + { "∃", { 8707, 0 } }, + { "ⅇ", { 8519, 0 } }, + { "Ф", { 1060, 0 } }, + { "𝔉", { 120073, 0 } }, + { "◼", { 9724, 0 } }, + { "▪", { 9642, 0 } }, + { "𝔽", { 120125, 0 } }, + { "∀", { 8704, 0 } }, + { "ℱ", { 8497, 0 } }, + { "ℱ", { 8497, 0 } }, + { "Ѓ", { 1027, 0 } }, + { ">", { 62, 0 } }, + { "Γ", { 915, 0 } }, + { "Ϝ", { 988, 0 } }, + { "Ğ", { 286, 0 } }, + { "Ģ", { 290, 0 } }, + { "Ĝ", { 284, 0 } }, + { "Г", { 1043, 0 } }, + { "Ġ", { 288, 0 } }, + { "𝔊", { 120074, 0 } }, + { "⋙", { 8921, 0 } }, + { "𝔾", { 120126, 0 } }, + { "≥", { 8805, 0 } }, + { "⋛", { 8923, 0 } }, + { "≧", { 8807, 0 } }, + { "⪢", { 10914, 0 } }, + { "≷", { 8823, 0 } }, + { "⩾", { 10878, 0 } }, + { "≳", { 8819, 0 } }, + { "𝒢", { 119970, 0 } }, + { "≫", { 8811, 0 } }, + { "Ъ", { 1066, 0 } }, + { "ˇ", { 711, 0 } }, + { "^", { 94, 0 } }, + { "Ĥ", { 292, 0 } }, + { "ℌ", { 8460, 0 } }, + { "ℋ", { 8459, 0 } }, + { "ℍ", { 8461, 0 } }, + { "─", { 9472, 0 } }, + { "ℋ", { 8459, 0 } }, + { "Ħ", { 294, 0 } }, + { "≎", { 8782, 0 } }, + { "≏", { 8783, 0 } }, + { "Е", { 1045, 0 } }, + { "IJ", { 306, 0 } }, + { "Ё", { 1025, 0 } }, + { "Í", { 205, 0 } }, + { "Î", { 206, 0 } }, + { "И", { 1048, 0 } }, + { "İ", { 304, 0 } }, + { "ℑ", { 8465, 0 } }, + { "Ì", { 204, 0 } }, + { "ℑ", { 8465, 0 } }, + { "Ī", { 298, 0 } }, + { "ⅈ", { 8520, 0 } }, + { "⇒", { 8658, 0 } }, + { "∬", { 8748, 0 } }, + { "∫", { 8747, 0 } }, + { "⋂", { 8898, 0 } }, + { "⁣", { 8291, 0 } }, + { "⁢", { 8290, 0 } }, + { "Į", { 302, 0 } }, + { "𝕀", { 120128, 0 } }, + { "Ι", { 921, 0 } }, + { "ℐ", { 8464, 0 } }, + { "Ĩ", { 296, 0 } }, + { "І", { 1030, 0 } }, + { "Ï", { 207, 0 } }, + { "Ĵ", { 308, 0 } }, + { "Й", { 1049, 0 } }, + { "𝔍", { 120077, 0 } }, + { "𝕁", { 120129, 0 } }, + { "𝒥", { 119973, 0 } }, + { "Ј", { 1032, 0 } }, + { "Є", { 1028, 0 } }, + { "Х", { 1061, 0 } }, + { "Ќ", { 1036, 0 } }, + { "Κ", { 922, 0 } }, + { "Ķ", { 310, 0 } }, + { "К", { 1050, 0 } }, + { "𝔎", { 120078, 0 } }, + { "𝕂", { 120130, 0 } }, + { "𝒦", { 119974, 0 } }, + { "Љ", { 1033, 0 } }, + { "<", { 60, 0 } }, + { "Ĺ", { 313, 0 } }, + { "Λ", { 923, 0 } }, + { "⟪", { 10218, 0 } }, + { "ℒ", { 8466, 0 } }, + { "↞", { 8606, 0 } }, + { "Ľ", { 317, 0 } }, + { "Ļ", { 315, 0 } }, + { "Л", { 1051, 0 } }, + { "⟨", { 10216, 0 } }, + { "←", { 8592, 0 } }, + { "⇤", { 8676, 0 } }, + { "⇆", { 8646, 0 } }, + { "⌈", { 8968, 0 } }, + { "⟦", { 10214, 0 } }, + { "⥡", { 10593, 0 } }, + { "⇃", { 8643, 0 } }, + { "⥙", { 10585, 0 } }, + { "⌊", { 8970, 0 } }, + { "↔", { 8596, 0 } }, + { "⥎", { 10574, 0 } }, + { "⊣", { 8867, 0 } }, + { "↤", { 8612, 0 } }, + { "⥚", { 10586, 0 } }, + { "⊲", { 8882, 0 } }, + { "⧏", { 10703, 0 } }, + { "⊴", { 8884, 0 } }, + { "⥑", { 10577, 0 } }, + { "⥠", { 10592, 0 } }, + { "↿", { 8639, 0 } }, + { "⥘", { 10584, 0 } }, + { "↼", { 8636, 0 } }, + { "⥒", { 10578, 0 } }, + { "⇐", { 8656, 0 } }, + { "⇔", { 8660, 0 } }, + { "⋚", { 8922, 0 } }, + { "≦", { 8806, 0 } }, + { "≶", { 8822, 0 } }, + { "⪡", { 10913, 0 } }, + { "⩽", { 10877, 0 } }, + { "≲", { 8818, 0 } }, + { "𝔏", { 120079, 0 } }, + { "⋘", { 8920, 0 } }, + { "⇚", { 8666, 0 } }, + { "Ŀ", { 319, 0 } }, + { "⟵", { 10229, 0 } }, + { "⟷", { 10231, 0 } }, + { "⟶", { 10230, 0 } }, + { "⟸", { 10232, 0 } }, + { "⟺", { 10234, 0 } }, + { "⟹", { 10233, 0 } }, + { "𝕃", { 120131, 0 } }, + { "↙", { 8601, 0 } }, + { "↘", { 8600, 0 } }, + { "ℒ", { 8466, 0 } }, + { "↰", { 8624, 0 } }, + { "Ł", { 321, 0 } }, + { "≪", { 8810, 0 } }, + { "⤅", { 10501, 0 } }, + { "М", { 1052, 0 } }, + { " ", { 8287, 0 } }, + { "ℳ", { 8499, 0 } }, + { "𝔐", { 120080, 0 } }, + { "∓", { 8723, 0 } }, + { "𝕄", { 120132, 0 } }, + { "ℳ", { 8499, 0 } }, + { "Μ", { 924, 0 } }, + { "Њ", { 1034, 0 } }, + { "Ń", { 323, 0 } }, + { "Ň", { 327, 0 } }, + { "Ņ", { 325, 0 } }, + { "Н", { 1053, 0 } }, + { "​", { 8203, 0 } }, + { "​", { 8203, 0 } }, + { "​", { 8203, 0 } }, + { "​", { 8203, 0 } }, + { "≫", { 8811, 0 } }, + { "≪", { 8810, 0 } }, + { " ", { 10, 0 } }, + { "𝔑", { 120081, 0 } }, + { "⁠", { 8288, 0 } }, + { " ", { 160, 0 } }, + { "ℕ", { 8469, 0 } }, + { "⫬", { 10988, 0 } }, + { "≢", { 8802, 0 } }, + { "≭", { 8813, 0 } }, + { "∦", { 8742, 0 } }, + { "∉", { 8713, 0 } }, + { "≠", { 8800, 0 } }, + { "≂̸", { 8770, 824 } }, + { "∄", { 8708, 0 } }, + { "≯", { 8815, 0 } }, + { "≱", { 8817, 0 } }, + { "≧̸", { 8807, 824 } }, + { "≫̸", { 8811, 824 } }, + { "≹", { 8825, 0 } }, + { "⩾̸", { 10878, 824 } }, + { "≵", { 8821, 0 } }, + { "≎̸", { 8782, 824 } }, + { "≏̸", { 8783, 824 } }, + { "⋪", { 8938, 0 } }, + { "⧏̸", { 10703, 824 } }, + { "⋬", { 8940, 0 } }, + { "≮", { 8814, 0 } }, + { "≰", { 8816, 0 } }, + { "≸", { 8824, 0 } }, + { "≪̸", { 8810, 824 } }, + { "⩽̸", { 10877, 824 } }, + { "≴", { 8820, 0 } }, + { "⪢̸", { 10914, 824 } }, + { "⪡̸", { 10913, 824 } }, + { "⊀", { 8832, 0 } }, + { "⪯̸", { 10927, 824 } }, + { "⋠", { 8928, 0 } }, + { "∌", { 8716, 0 } }, + { "⋫", { 8939, 0 } }, + { "⧐̸", { 10704, 824 } }, + { "⋭", { 8941, 0 } }, + { "⊏̸", { 8847, 824 } }, + { "⋢", { 8930, 0 } }, + { "⊐̸", { 8848, 824 } }, + { "⋣", { 8931, 0 } }, + { "⊂⃒", { 8834, 8402 } }, + { "⊈", { 8840, 0 } }, + { "⊁", { 8833, 0 } }, + { "⪰̸", { 10928, 824 } }, + { "⋡", { 8929, 0 } }, + { "≿̸", { 8831, 824 } }, + { "⊃⃒", { 8835, 8402 } }, + { "⊉", { 8841, 0 } }, + { "≁", { 8769, 0 } }, + { "≄", { 8772, 0 } }, + { "≇", { 8775, 0 } }, + { "≉", { 8777, 0 } }, + { "∤", { 8740, 0 } }, + { "𝒩", { 119977, 0 } }, + { "Ñ", { 209, 0 } }, + { "Ν", { 925, 0 } }, + { "Œ", { 338, 0 } }, + { "Ó", { 211, 0 } }, + { "Ô", { 212, 0 } }, + { "О", { 1054, 0 } }, + { "Ő", { 336, 0 } }, + { "𝔒", { 120082, 0 } }, + { "Ò", { 210, 0 } }, + { "Ō", { 332, 0 } }, + { "Ω", { 937, 0 } }, + { "Ο", { 927, 0 } }, + { "𝕆", { 120134, 0 } }, + { "“", { 8220, 0 } }, + { "‘", { 8216, 0 } }, + { "⩔", { 10836, 0 } }, + { "𝒪", { 119978, 0 } }, + { "Ø", { 216, 0 } }, + { "Õ", { 213, 0 } }, + { "⨷", { 10807, 0 } }, + { "Ö", { 214, 0 } }, + { "‾", { 8254, 0 } }, + { "⏞", { 9182, 0 } }, + { "⎴", { 9140, 0 } }, + { "⏜", { 9180, 0 } }, + { "∂", { 8706, 0 } }, + { "П", { 1055, 0 } }, + { "𝔓", { 120083, 0 } }, + { "Φ", { 934, 0 } }, + { "Π", { 928, 0 } }, + { "±", { 177, 0 } }, + { "ℌ", { 8460, 0 } }, + { "ℙ", { 8473, 0 } }, + { "⪻", { 10939, 0 } }, + { "≺", { 8826, 0 } }, + { "⪯", { 10927, 0 } }, + { "≼", { 8828, 0 } }, + { "≾", { 8830, 0 } }, + { "″", { 8243, 0 } }, + { "∏", { 8719, 0 } }, + { "∷", { 8759, 0 } }, + { "∝", { 8733, 0 } }, + { "𝒫", { 119979, 0 } }, + { "Ψ", { 936, 0 } }, + { """, { 34, 0 } }, + { "𝔔", { 120084, 0 } }, + { "ℚ", { 8474, 0 } }, + { "𝒬", { 119980, 0 } }, + { "⤐", { 10512, 0 } }, + { "®", { 174, 0 } }, + { "Ŕ", { 340, 0 } }, + { "⟫", { 10219, 0 } }, + { "↠", { 8608, 0 } }, + { "⤖", { 10518, 0 } }, + { "Ř", { 344, 0 } }, + { "Ŗ", { 342, 0 } }, + { "Р", { 1056, 0 } }, + { "ℜ", { 8476, 0 } }, + { "∋", { 8715, 0 } }, + { "⇋", { 8651, 0 } }, + { "⥯", { 10607, 0 } }, + { "ℜ", { 8476, 0 } }, + { "Ρ", { 929, 0 } }, + { "⟩", { 10217, 0 } }, + { "→", { 8594, 0 } }, + { "⇥", { 8677, 0 } }, + { "⇄", { 8644, 0 } }, + { "⌉", { 8969, 0 } }, + { "⟧", { 10215, 0 } }, + { "⥝", { 10589, 0 } }, + { "⇂", { 8642, 0 } }, + { "⥕", { 10581, 0 } }, + { "⌋", { 8971, 0 } }, + { "⊢", { 8866, 0 } }, + { "↦", { 8614, 0 } }, + { "⥛", { 10587, 0 } }, + { "⊳", { 8883, 0 } }, + { "⧐", { 10704, 0 } }, + { "⊵", { 8885, 0 } }, + { "⥏", { 10575, 0 } }, + { "⥜", { 10588, 0 } }, + { "↾", { 8638, 0 } }, + { "⥔", { 10580, 0 } }, + { "⇀", { 8640, 0 } }, + { "⥓", { 10579, 0 } }, + { "⇒", { 8658, 0 } }, + { "ℝ", { 8477, 0 } }, + { "⥰", { 10608, 0 } }, + { "⇛", { 8667, 0 } }, + { "ℛ", { 8475, 0 } }, + { "↱", { 8625, 0 } }, + { "⧴", { 10740, 0 } }, + { "Щ", { 1065, 0 } }, + { "Ш", { 1064, 0 } }, + { "Ь", { 1068, 0 } }, + { "Ś", { 346, 0 } }, + { "⪼", { 10940, 0 } }, + { "Š", { 352, 0 } }, + { "Ş", { 350, 0 } }, + { "Ŝ", { 348, 0 } }, + { "С", { 1057, 0 } }, + { "𝔖", { 120086, 0 } }, + { "↓", { 8595, 0 } }, + { "←", { 8592, 0 } }, + { "→", { 8594, 0 } }, + { "↑", { 8593, 0 } }, + { "Σ", { 931, 0 } }, + { "∘", { 8728, 0 } }, + { "𝕊", { 120138, 0 } }, + { "√", { 8730, 0 } }, + { "□", { 9633, 0 } }, + { "⊓", { 8851, 0 } }, + { "⊏", { 8847, 0 } }, + { "⊑", { 8849, 0 } }, + { "⊐", { 8848, 0 } }, + { "⊒", { 8850, 0 } }, + { "⊔", { 8852, 0 } }, + { "𝒮", { 119982, 0 } }, + { "⋆", { 8902, 0 } }, + { "⋐", { 8912, 0 } }, + { "⋐", { 8912, 0 } }, + { "⊆", { 8838, 0 } }, + { "≻", { 8827, 0 } }, + { "⪰", { 10928, 0 } }, + { "≽", { 8829, 0 } }, + { "≿", { 8831, 0 } }, + { "∋", { 8715, 0 } }, + { "∑", { 8721, 0 } }, + { "⋑", { 8913, 0 } }, + { "⊃", { 8835, 0 } }, + { "⊇", { 8839, 0 } }, + { "⋑", { 8913, 0 } }, + { "Þ", { 222, 0 } }, + { "™", { 8482, 0 } }, + { "Ћ", { 1035, 0 } }, + { "Ц", { 1062, 0 } }, + { " ", { 9, 0 } }, + { "Τ", { 932, 0 } }, + { "Ť", { 356, 0 } }, + { "Ţ", { 354, 0 } }, + { "Т", { 1058, 0 } }, + { "𝔗", { 120087, 0 } }, + { "∴", { 8756, 0 } }, + { "Θ", { 920, 0 } }, + { "  ", { 8287, 8202 } }, + { " ", { 8201, 0 } }, + { "∼", { 8764, 0 } }, + { "≃", { 8771, 0 } }, + { "≅", { 8773, 0 } }, + { "≈", { 8776, 0 } }, + { "𝕋", { 120139, 0 } }, + { "⃛", { 8411, 0 } }, + { "𝒯", { 119983, 0 } }, + { "Ŧ", { 358, 0 } }, + { "Ú", { 218, 0 } }, + { "↟", { 8607, 0 } }, + { "⥉", { 10569, 0 } }, + { "Ў", { 1038, 0 } }, + { "Ŭ", { 364, 0 } }, + { "Û", { 219, 0 } }, + { "У", { 1059, 0 } }, + { "Ű", { 368, 0 } }, + { "𝔘", { 120088, 0 } }, + { "Ù", { 217, 0 } }, + { "Ū", { 362, 0 } }, + { "_", { 95, 0 } }, + { "⏟", { 9183, 0 } }, + { "⎵", { 9141, 0 } }, + { "⏝", { 9181, 0 } }, + { "⋃", { 8899, 0 } }, + { "⊎", { 8846, 0 } }, + { "Ų", { 370, 0 } }, + { "𝕌", { 120140, 0 } }, + { "↑", { 8593, 0 } }, + { "⤒", { 10514, 0 } }, + { "⇅", { 8645, 0 } }, + { "↕", { 8597, 0 } }, + { "⥮", { 10606, 0 } }, + { "⊥", { 8869, 0 } }, + { "↥", { 8613, 0 } }, + { "⇑", { 8657, 0 } }, + { "⇕", { 8661, 0 } }, + { "↖", { 8598, 0 } }, + { "↗", { 8599, 0 } }, + { "ϒ", { 978, 0 } }, + { "Υ", { 933, 0 } }, + { "Ů", { 366, 0 } }, + { "𝒰", { 119984, 0 } }, + { "Ũ", { 360, 0 } }, + { "Ü", { 220, 0 } }, + { "⊫", { 8875, 0 } }, + { "⫫", { 10987, 0 } }, + { "В", { 1042, 0 } }, + { "⊩", { 8873, 0 } }, + { "⫦", { 10982, 0 } }, + { "⋁", { 8897, 0 } }, + { "‖", { 8214, 0 } }, + { "‖", { 8214, 0 } }, + { "∣", { 8739, 0 } }, + { "|", { 124, 0 } }, + { "❘", { 10072, 0 } }, + { "≀", { 8768, 0 } }, + { " ", { 8202, 0 } }, + { "𝔙", { 120089, 0 } }, + { "𝕍", { 120141, 0 } }, + { "𝒱", { 119985, 0 } }, + { "⊪", { 8874, 0 } }, + { "Ŵ", { 372, 0 } }, + { "⋀", { 8896, 0 } }, + { "𝔚", { 120090, 0 } }, + { "𝕎", { 120142, 0 } }, + { "𝒲", { 119986, 0 } }, + { "𝔛", { 120091, 0 } }, + { "Ξ", { 926, 0 } }, + { "𝕏", { 120143, 0 } }, + { "𝒳", { 119987, 0 } }, + { "Я", { 1071, 0 } }, + { "Ї", { 1031, 0 } }, + { "Ю", { 1070, 0 } }, + { "Ý", { 221, 0 } }, + { "Ŷ", { 374, 0 } }, + { "Ы", { 1067, 0 } }, + { "𝔜", { 120092, 0 } }, + { "𝕐", { 120144, 0 } }, + { "𝒴", { 119988, 0 } }, + { "Ÿ", { 376, 0 } }, + { "Ж", { 1046, 0 } }, + { "Ź", { 377, 0 } }, + { "Ž", { 381, 0 } }, + { "З", { 1047, 0 } }, + { "Ż", { 379, 0 } }, + { "​", { 8203, 0 } }, + { "Ζ", { 918, 0 } }, + { "ℨ", { 8488, 0 } }, + { "ℤ", { 8484, 0 } }, + { "𝒵", { 119989, 0 } }, + { "á", { 225, 0 } }, + { "ă", { 259, 0 } }, + { "∾", { 8766, 0 } }, + { "∾̳", { 8766, 819 } }, + { "∿", { 8767, 0 } }, + { "â", { 226, 0 } }, + { "´", { 180, 0 } }, + { "а", { 1072, 0 } }, + { "æ", { 230, 0 } }, + { "⁡", { 8289, 0 } }, + { "𝔞", { 120094, 0 } }, + { "à", { 224, 0 } }, + { "ℵ", { 8501, 0 } }, + { "ℵ", { 8501, 0 } }, + { "α", { 945, 0 } }, + { "ā", { 257, 0 } }, + { "⨿", { 10815, 0 } }, + { "&", { 38, 0 } }, + { "∧", { 8743, 0 } }, + { "⩕", { 10837, 0 } }, + { "⩜", { 10844, 0 } }, + { "⩘", { 10840, 0 } }, + { "⩚", { 10842, 0 } }, + { "∠", { 8736, 0 } }, + { "⦤", { 10660, 0 } }, + { "∠", { 8736, 0 } }, + { "∡", { 8737, 0 } }, + { "⦨", { 10664, 0 } }, + { "⦩", { 10665, 0 } }, + { "⦪", { 10666, 0 } }, + { "⦫", { 10667, 0 } }, + { "⦬", { 10668, 0 } }, + { "⦭", { 10669, 0 } }, + { "⦮", { 10670, 0 } }, + { "⦯", { 10671, 0 } }, + { "∟", { 8735, 0 } }, + { "⊾", { 8894, 0 } }, + { "⦝", { 10653, 0 } }, + { "∢", { 8738, 0 } }, + { "Å", { 197, 0 } }, + { "⍼", { 9084, 0 } }, + { "ą", { 261, 0 } }, + { "𝕒", { 120146, 0 } }, + { "≈", { 8776, 0 } }, + { "⩰", { 10864, 0 } }, + { "⩯", { 10863, 0 } }, + { "≊", { 8778, 0 } }, + { "≋", { 8779, 0 } }, + { "'", { 39, 0 } }, + { "≈", { 8776, 0 } }, + { "≊", { 8778, 0 } }, + { "å", { 229, 0 } }, + { "𝒶", { 119990, 0 } }, + { "*", { 42, 0 } }, + { "≈", { 8776, 0 } }, + { "≍", { 8781, 0 } }, + { "ã", { 227, 0 } }, + { "ä", { 228, 0 } }, + { "∳", { 8755, 0 } }, + { "⨑", { 10769, 0 } }, + { "⫭", { 10989, 0 } }, + { "≌", { 8780, 0 } }, + { "϶", { 1014, 0 } }, + { "‵", { 8245, 0 } }, + { "∽", { 8765, 0 } }, + { "⋍", { 8909, 0 } }, + { "⊽", { 8893, 0 } }, + { "⌅", { 8965, 0 } }, + { "⌅", { 8965, 0 } }, + { "⎵", { 9141, 0 } }, + { "⎶", { 9142, 0 } }, + { "≌", { 8780, 0 } }, + { "б", { 1073, 0 } }, + { "„", { 8222, 0 } }, + { "∵", { 8757, 0 } }, + { "∵", { 8757, 0 } }, + { "⦰", { 10672, 0 } }, + { "϶", { 1014, 0 } }, + { "ℬ", { 8492, 0 } }, + { "β", { 946, 0 } }, + { "ℶ", { 8502, 0 } }, + { "≬", { 8812, 0 } }, + { "𝔟", { 120095, 0 } }, + { "⋂", { 8898, 0 } }, + { "◯", { 9711, 0 } }, + { "⋃", { 8899, 0 } }, + { "⨀", { 10752, 0 } }, + { "⨁", { 10753, 0 } }, + { "⨂", { 10754, 0 } }, + { "⨆", { 10758, 0 } }, + { "★", { 9733, 0 } }, + { "▽", { 9661, 0 } }, + { "△", { 9651, 0 } }, + { "⨄", { 10756, 0 } }, + { "⋁", { 8897, 0 } }, + { "⋀", { 8896, 0 } }, + { "⤍", { 10509, 0 } }, + { "⧫", { 10731, 0 } }, + { "▪", { 9642, 0 } }, + { "▴", { 9652, 0 } }, + { "▾", { 9662, 0 } }, + { "◂", { 9666, 0 } }, + { "▸", { 9656, 0 } }, + { "␣", { 9251, 0 } }, + { "▒", { 9618, 0 } }, + { "░", { 9617, 0 } }, + { "▓", { 9619, 0 } }, + { "█", { 9608, 0 } }, + { "=⃥", { 61, 8421 } }, + { "≡⃥", { 8801, 8421 } }, + { "⌐", { 8976, 0 } }, + { "𝕓", { 120147, 0 } }, + { "⊥", { 8869, 0 } }, + { "⊥", { 8869, 0 } }, + { "⋈", { 8904, 0 } }, + { "╗", { 9559, 0 } }, + { "╔", { 9556, 0 } }, + { "╖", { 9558, 0 } }, + { "╓", { 9555, 0 } }, + { "═", { 9552, 0 } }, + { "╦", { 9574, 0 } }, + { "╩", { 9577, 0 } }, + { "╤", { 9572, 0 } }, + { "╧", { 9575, 0 } }, + { "╝", { 9565, 0 } }, + { "╚", { 9562, 0 } }, + { "╜", { 9564, 0 } }, + { "╙", { 9561, 0 } }, + { "║", { 9553, 0 } }, + { "╬", { 9580, 0 } }, + { "╣", { 9571, 0 } }, + { "╠", { 9568, 0 } }, + { "╫", { 9579, 0 } }, + { "╢", { 9570, 0 } }, + { "╟", { 9567, 0 } }, + { "⧉", { 10697, 0 } }, + { "╕", { 9557, 0 } }, + { "╒", { 9554, 0 } }, + { "┐", { 9488, 0 } }, + { "┌", { 9484, 0 } }, + { "─", { 9472, 0 } }, + { "╥", { 9573, 0 } }, + { "╨", { 9576, 0 } }, + { "┬", { 9516, 0 } }, + { "┴", { 9524, 0 } }, + { "⊟", { 8863, 0 } }, + { "⊞", { 8862, 0 } }, + { "⊠", { 8864, 0 } }, + { "╛", { 9563, 0 } }, + { "╘", { 9560, 0 } }, + { "┘", { 9496, 0 } }, + { "└", { 9492, 0 } }, + { "│", { 9474, 0 } }, + { "╪", { 9578, 0 } }, + { "╡", { 9569, 0 } }, + { "╞", { 9566, 0 } }, + { "┼", { 9532, 0 } }, + { "┤", { 9508, 0 } }, + { "├", { 9500, 0 } }, + { "‵", { 8245, 0 } }, + { "˘", { 728, 0 } }, + { "¦", { 166, 0 } }, + { "𝒷", { 119991, 0 } }, + { "⁏", { 8271, 0 } }, + { "∽", { 8765, 0 } }, + { "⋍", { 8909, 0 } }, + { "\", { 92, 0 } }, + { "⧅", { 10693, 0 } }, + { "⟈", { 10184, 0 } }, + { "•", { 8226, 0 } }, + { "•", { 8226, 0 } }, + { "≎", { 8782, 0 } }, + { "⪮", { 10926, 0 } }, + { "≏", { 8783, 0 } }, + { "≏", { 8783, 0 } }, + { "ć", { 263, 0 } }, + { "∩", { 8745, 0 } }, + { "⩄", { 10820, 0 } }, + { "⩉", { 10825, 0 } }, + { "⩋", { 10827, 0 } }, + { "⩇", { 10823, 0 } }, + { "⩀", { 10816, 0 } }, + { "∩︀", { 8745, 65024 } }, + { "⁁", { 8257, 0 } }, + { "ˇ", { 711, 0 } }, + { "⩍", { 10829, 0 } }, + { "č", { 269, 0 } }, + { "ç", { 231, 0 } }, + { "ĉ", { 265, 0 } }, + { "⩌", { 10828, 0 } }, + { "⩐", { 10832, 0 } }, + { "ċ", { 267, 0 } }, + { "¸", { 184, 0 } }, + { "⦲", { 10674, 0 } }, + { "¢", { 162, 0 } }, + { "·", { 183, 0 } }, + { "𝔠", { 120096, 0 } }, + { "ч", { 1095, 0 } }, + { "✓", { 10003, 0 } }, + { "✓", { 10003, 0 } }, + { "χ", { 967, 0 } }, + { "○", { 9675, 0 } }, + { "⧃", { 10691, 0 } }, + { "ˆ", { 710, 0 } }, + { "≗", { 8791, 0 } }, + { "↺", { 8634, 0 } }, + { "↻", { 8635, 0 } }, + { "®", { 174, 0 } }, + { "Ⓢ", { 9416, 0 } }, + { "⊛", { 8859, 0 } }, + { "⊚", { 8858, 0 } }, + { "⊝", { 8861, 0 } }, + { "≗", { 8791, 0 } }, + { "⨐", { 10768, 0 } }, + { "⫯", { 10991, 0 } }, + { "⧂", { 10690, 0 } }, + { "♣", { 9827, 0 } }, + { "♣", { 9827, 0 } }, + { ":", { 58, 0 } }, + { "≔", { 8788, 0 } }, + { "≔", { 8788, 0 } }, + { ",", { 44, 0 } }, + { "@", { 64, 0 } }, + { "∁", { 8705, 0 } }, + { "∘", { 8728, 0 } }, + { "∁", { 8705, 0 } }, + { "ℂ", { 8450, 0 } }, + { "≅", { 8773, 0 } }, + { "⩭", { 10861, 0 } }, + { "∮", { 8750, 0 } }, + { "𝕔", { 120148, 0 } }, + { "∐", { 8720, 0 } }, + { "©", { 169, 0 } }, + { "℗", { 8471, 0 } }, + { "↵", { 8629, 0 } }, + { "✗", { 10007, 0 } }, + { "𝒸", { 119992, 0 } }, + { "⫏", { 10959, 0 } }, + { "⫑", { 10961, 0 } }, + { "⫐", { 10960, 0 } }, + { "⫒", { 10962, 0 } }, + { "⋯", { 8943, 0 } }, + { "⤸", { 10552, 0 } }, + { "⤵", { 10549, 0 } }, + { "⋞", { 8926, 0 } }, + { "⋟", { 8927, 0 } }, + { "↶", { 8630, 0 } }, + { "⤽", { 10557, 0 } }, + { "∪", { 8746, 0 } }, + { "⩈", { 10824, 0 } }, + { "⩆", { 10822, 0 } }, + { "⩊", { 10826, 0 } }, + { "⊍", { 8845, 0 } }, + { "⩅", { 10821, 0 } }, + { "∪︀", { 8746, 65024 } }, + { "↷", { 8631, 0 } }, + { "⤼", { 10556, 0 } }, + { "⋞", { 8926, 0 } }, + { "⋟", { 8927, 0 } }, + { "⋎", { 8910, 0 } }, + { "⋏", { 8911, 0 } }, + { "¤", { 164, 0 } }, + { "↶", { 8630, 0 } }, + { "↷", { 8631, 0 } }, + { "⋎", { 8910, 0 } }, + { "⋏", { 8911, 0 } }, + { "∲", { 8754, 0 } }, + { "∱", { 8753, 0 } }, + { "⌭", { 9005, 0 } }, + { "⇓", { 8659, 0 } }, + { "⥥", { 10597, 0 } }, + { "†", { 8224, 0 } }, + { "ℸ", { 8504, 0 } }, + { "↓", { 8595, 0 } }, + { "‐", { 8208, 0 } }, + { "⊣", { 8867, 0 } }, + { "⤏", { 10511, 0 } }, + { "˝", { 733, 0 } }, + { "ď", { 271, 0 } }, + { "д", { 1076, 0 } }, + { "ⅆ", { 8518, 0 } }, + { "‡", { 8225, 0 } }, + { "⇊", { 8650, 0 } }, + { "⩷", { 10871, 0 } }, + { "°", { 176, 0 } }, + { "δ", { 948, 0 } }, + { "⦱", { 10673, 0 } }, + { "⥿", { 10623, 0 } }, + { "𝔡", { 120097, 0 } }, + { "⇃", { 8643, 0 } }, + { "⇂", { 8642, 0 } }, + { "⋄", { 8900, 0 } }, + { "⋄", { 8900, 0 } }, + { "♦", { 9830, 0 } }, + { "♦", { 9830, 0 } }, + { "¨", { 168, 0 } }, + { "ϝ", { 989, 0 } }, + { "⋲", { 8946, 0 } }, + { "÷", { 247, 0 } }, + { "÷", { 247, 0 } }, + { "⋇", { 8903, 0 } }, + { "⋇", { 8903, 0 } }, + { "ђ", { 1106, 0 } }, + { "⌞", { 8990, 0 } }, + { "⌍", { 8973, 0 } }, + { "$", { 36, 0 } }, + { "𝕕", { 120149, 0 } }, + { "˙", { 729, 0 } }, + { "≐", { 8784, 0 } }, + { "≑", { 8785, 0 } }, + { "∸", { 8760, 0 } }, + { "∔", { 8724, 0 } }, + { "⊡", { 8865, 0 } }, + { "⌆", { 8966, 0 } }, + { "↓", { 8595, 0 } }, + { "⇊", { 8650, 0 } }, + { "⇃", { 8643, 0 } }, + { "⇂", { 8642, 0 } }, + { "⤐", { 10512, 0 } }, + { "⌟", { 8991, 0 } }, + { "⌌", { 8972, 0 } }, + { "𝒹", { 119993, 0 } }, + { "ѕ", { 1109, 0 } }, + { "⧶", { 10742, 0 } }, + { "đ", { 273, 0 } }, + { "⋱", { 8945, 0 } }, + { "▿", { 9663, 0 } }, + { "▾", { 9662, 0 } }, + { "⇵", { 8693, 0 } }, + { "⥯", { 10607, 0 } }, + { "⦦", { 10662, 0 } }, + { "џ", { 1119, 0 } }, + { "⟿", { 10239, 0 } }, + { "⩷", { 10871, 0 } }, + { "≑", { 8785, 0 } }, + { "é", { 233, 0 } }, + { "⩮", { 10862, 0 } }, + { "ě", { 283, 0 } }, + { "≖", { 8790, 0 } }, + { "ê", { 234, 0 } }, + { "≕", { 8789, 0 } }, + { "э", { 1101, 0 } }, + { "ė", { 279, 0 } }, + { "ⅇ", { 8519, 0 } }, + { "≒", { 8786, 0 } }, + { "𝔢", { 120098, 0 } }, + { "⪚", { 10906, 0 } }, + { "è", { 232, 0 } }, + { "⪖", { 10902, 0 } }, + { "⪘", { 10904, 0 } }, + { "⪙", { 10905, 0 } }, + { "⏧", { 9191, 0 } }, + { "ℓ", { 8467, 0 } }, + { "⪕", { 10901, 0 } }, + { "⪗", { 10903, 0 } }, + { "ē", { 275, 0 } }, + { "∅", { 8709, 0 } }, + { "∅", { 8709, 0 } }, + { "∅", { 8709, 0 } }, + { " ", { 8196, 0 } }, + { " ", { 8197, 0 } }, + { " ", { 8195, 0 } }, + { "ŋ", { 331, 0 } }, + { " ", { 8194, 0 } }, + { "ę", { 281, 0 } }, + { "𝕖", { 120150, 0 } }, + { "⋕", { 8917, 0 } }, + { "⧣", { 10723, 0 } }, + { "⩱", { 10865, 0 } }, + { "ε", { 949, 0 } }, + { "ε", { 949, 0 } }, + { "ϵ", { 1013, 0 } }, + { "≖", { 8790, 0 } }, + { "≕", { 8789, 0 } }, + { "≂", { 8770, 0 } }, + { "⪖", { 10902, 0 } }, + { "⪕", { 10901, 0 } }, + { "=", { 61, 0 } }, + { "≟", { 8799, 0 } }, + { "≡", { 8801, 0 } }, + { "⩸", { 10872, 0 } }, + { "⧥", { 10725, 0 } }, + { "≓", { 8787, 0 } }, + { "⥱", { 10609, 0 } }, + { "ℯ", { 8495, 0 } }, + { "≐", { 8784, 0 } }, + { "≂", { 8770, 0 } }, + { "η", { 951, 0 } }, + { "ð", { 240, 0 } }, + { "ë", { 235, 0 } }, + { "€", { 8364, 0 } }, + { "!", { 33, 0 } }, + { "∃", { 8707, 0 } }, + { "ℰ", { 8496, 0 } }, + { "ⅇ", { 8519, 0 } }, + { "≒", { 8786, 0 } }, + { "ф", { 1092, 0 } }, + { "♀", { 9792, 0 } }, + { "ffi", { 64259, 0 } }, + { "ff", { 64256, 0 } }, + { "ffl", { 64260, 0 } }, + { "𝔣", { 120099, 0 } }, + { "fi", { 64257, 0 } }, + { "fj", { 102, 106 } }, + { "♭", { 9837, 0 } }, + { "fl", { 64258, 0 } }, + { "▱", { 9649, 0 } }, + { "ƒ", { 402, 0 } }, + { "𝕗", { 120151, 0 } }, + { "∀", { 8704, 0 } }, + { "⋔", { 8916, 0 } }, + { "⫙", { 10969, 0 } }, + { "⨍", { 10765, 0 } }, + { "½", { 189, 0 } }, + { "⅓", { 8531, 0 } }, + { "¼", { 188, 0 } }, + { "⅕", { 8533, 0 } }, + { "⅙", { 8537, 0 } }, + { "⅛", { 8539, 0 } }, + { "⅔", { 8532, 0 } }, + { "⅖", { 8534, 0 } }, + { "¾", { 190, 0 } }, + { "⅗", { 8535, 0 } }, + { "⅜", { 8540, 0 } }, + { "⅘", { 8536, 0 } }, + { "⅚", { 8538, 0 } }, + { "⅝", { 8541, 0 } }, + { "⅞", { 8542, 0 } }, + { "⁄", { 8260, 0 } }, + { "⌢", { 8994, 0 } }, + { "𝒻", { 119995, 0 } }, + { "≧", { 8807, 0 } }, + { "⪌", { 10892, 0 } }, + { "ǵ", { 501, 0 } }, + { "γ", { 947, 0 } }, + { "ϝ", { 989, 0 } }, + { "⪆", { 10886, 0 } }, + { "ğ", { 287, 0 } }, + { "ĝ", { 285, 0 } }, + { "г", { 1075, 0 } }, + { "ġ", { 289, 0 } }, + { "≥", { 8805, 0 } }, + { "⋛", { 8923, 0 } }, + { "≥", { 8805, 0 } }, + { "≧", { 8807, 0 } }, + { "⩾", { 10878, 0 } }, + { "⩾", { 10878, 0 } }, + { "⪩", { 10921, 0 } }, + { "⪀", { 10880, 0 } }, + { "⪂", { 10882, 0 } }, + { "⪄", { 10884, 0 } }, + { "⋛︀", { 8923, 65024 } }, + { "⪔", { 10900, 0 } }, + { "𝔤", { 120100, 0 } }, + { "≫", { 8811, 0 } }, + { "⋙", { 8921, 0 } }, + { "ℷ", { 8503, 0 } }, + { "ѓ", { 1107, 0 } }, + { "≷", { 8823, 0 } }, + { "⪒", { 10898, 0 } }, + { "⪥", { 10917, 0 } }, + { "⪤", { 10916, 0 } }, + { "≩", { 8809, 0 } }, + { "⪊", { 10890, 0 } }, + { "⪊", { 10890, 0 } }, + { "⪈", { 10888, 0 } }, + { "⪈", { 10888, 0 } }, + { "≩", { 8809, 0 } }, + { "⋧", { 8935, 0 } }, + { "𝕘", { 120152, 0 } }, + { "`", { 96, 0 } }, + { "ℊ", { 8458, 0 } }, + { "≳", { 8819, 0 } }, + { "⪎", { 10894, 0 } }, + { "⪐", { 10896, 0 } }, + { ">", { 62, 0 } }, + { "⪧", { 10919, 0 } }, + { "⩺", { 10874, 0 } }, + { "⋗", { 8919, 0 } }, + { "⦕", { 10645, 0 } }, + { "⩼", { 10876, 0 } }, + { "⪆", { 10886, 0 } }, + { "⥸", { 10616, 0 } }, + { "⋗", { 8919, 0 } }, + { "⋛", { 8923, 0 } }, + { "⪌", { 10892, 0 } }, + { "≷", { 8823, 0 } }, + { "≳", { 8819, 0 } }, + { "≩︀", { 8809, 65024 } }, + { "≩︀", { 8809, 65024 } }, + { "⇔", { 8660, 0 } }, + { " ", { 8202, 0 } }, + { "½", { 189, 0 } }, + { "ℋ", { 8459, 0 } }, + { "ъ", { 1098, 0 } }, + { "↔", { 8596, 0 } }, + { "⥈", { 10568, 0 } }, + { "↭", { 8621, 0 } }, + { "ℏ", { 8463, 0 } }, + { "ĥ", { 293, 0 } }, + { "♥", { 9829, 0 } }, + { "♥", { 9829, 0 } }, + { "…", { 8230, 0 } }, + { "⊹", { 8889, 0 } }, + { "𝔥", { 120101, 0 } }, + { "⤥", { 10533, 0 } }, + { "⤦", { 10534, 0 } }, + { "⇿", { 8703, 0 } }, + { "∻", { 8763, 0 } }, + { "↩", { 8617, 0 } }, + { "↪", { 8618, 0 } }, + { "𝕙", { 120153, 0 } }, + { "―", { 8213, 0 } }, + { "𝒽", { 119997, 0 } }, + { "ℏ", { 8463, 0 } }, + { "ħ", { 295, 0 } }, + { "⁃", { 8259, 0 } }, + { "‐", { 8208, 0 } }, + { "í", { 237, 0 } }, + { "⁣", { 8291, 0 } }, + { "î", { 238, 0 } }, + { "и", { 1080, 0 } }, + { "е", { 1077, 0 } }, + { "¡", { 161, 0 } }, + { "⇔", { 8660, 0 } }, + { "𝔦", { 120102, 0 } }, + { "ì", { 236, 0 } }, + { "ⅈ", { 8520, 0 } }, + { "⨌", { 10764, 0 } }, + { "∭", { 8749, 0 } }, + { "⧜", { 10716, 0 } }, + { "℩", { 8489, 0 } }, + { "ij", { 307, 0 } }, + { "ī", { 299, 0 } }, + { "ℑ", { 8465, 0 } }, + { "ℐ", { 8464, 0 } }, + { "ℑ", { 8465, 0 } }, + { "ı", { 305, 0 } }, + { "⊷", { 8887, 0 } }, + { "Ƶ", { 437, 0 } }, + { "∈", { 8712, 0 } }, + { "℅", { 8453, 0 } }, + { "∞", { 8734, 0 } }, + { "⧝", { 10717, 0 } }, + { "ı", { 305, 0 } }, + { "∫", { 8747, 0 } }, + { "⊺", { 8890, 0 } }, + { "ℤ", { 8484, 0 } }, + { "⊺", { 8890, 0 } }, + { "⨗", { 10775, 0 } }, + { "⨼", { 10812, 0 } }, + { "ё", { 1105, 0 } }, + { "į", { 303, 0 } }, + { "𝕚", { 120154, 0 } }, + { "ι", { 953, 0 } }, + { "⨼", { 10812, 0 } }, + { "¿", { 191, 0 } }, + { "𝒾", { 119998, 0 } }, + { "∈", { 8712, 0 } }, + { "⋹", { 8953, 0 } }, + { "⋵", { 8949, 0 } }, + { "⋴", { 8948, 0 } }, + { "⋳", { 8947, 0 } }, + { "∈", { 8712, 0 } }, + { "⁢", { 8290, 0 } }, + { "ĩ", { 297, 0 } }, + { "і", { 1110, 0 } }, + { "ï", { 239, 0 } }, + { "ĵ", { 309, 0 } }, + { "й", { 1081, 0 } }, + { "𝔧", { 120103, 0 } }, + { "ȷ", { 567, 0 } }, + { "𝕛", { 120155, 0 } }, + { "𝒿", { 119999, 0 } }, + { "ј", { 1112, 0 } }, + { "є", { 1108, 0 } }, + { "κ", { 954, 0 } }, + { "ϰ", { 1008, 0 } }, + { "ķ", { 311, 0 } }, + { "к", { 1082, 0 } }, + { "𝔨", { 120104, 0 } }, + { "ĸ", { 312, 0 } }, + { "х", { 1093, 0 } }, + { "ќ", { 1116, 0 } }, + { "𝕜", { 120156, 0 } }, + { "𝓀", { 120000, 0 } }, + { "⇚", { 8666, 0 } }, + { "⇐", { 8656, 0 } }, + { "⤛", { 10523, 0 } }, + { "⤎", { 10510, 0 } }, + { "≦", { 8806, 0 } }, + { "⪋", { 10891, 0 } }, + { "⥢", { 10594, 0 } }, + { "ĺ", { 314, 0 } }, + { "⦴", { 10676, 0 } }, + { "ℒ", { 8466, 0 } }, + { "λ", { 955, 0 } }, + { "⟨", { 10216, 0 } }, + { "⦑", { 10641, 0 } }, + { "⟨", { 10216, 0 } }, + { "⪅", { 10885, 0 } }, + { "«", { 171, 0 } }, + { "←", { 8592, 0 } }, + { "⇤", { 8676, 0 } }, + { "⤟", { 10527, 0 } }, + { "⤝", { 10525, 0 } }, + { "↩", { 8617, 0 } }, + { "↫", { 8619, 0 } }, + { "⤹", { 10553, 0 } }, + { "⥳", { 10611, 0 } }, + { "↢", { 8610, 0 } }, + { "⪫", { 10923, 0 } }, + { "⤙", { 10521, 0 } }, + { "⪭", { 10925, 0 } }, + { "⪭︀", { 10925, 65024 } }, + { "⤌", { 10508, 0 } }, + { "❲", { 10098, 0 } }, + { "{", { 123, 0 } }, + { "[", { 91, 0 } }, + { "⦋", { 10635, 0 } }, + { "⦏", { 10639, 0 } }, + { "⦍", { 10637, 0 } }, + { "ľ", { 318, 0 } }, + { "ļ", { 316, 0 } }, + { "⌈", { 8968, 0 } }, + { "{", { 123, 0 } }, + { "л", { 1083, 0 } }, + { "⤶", { 10550, 0 } }, + { "“", { 8220, 0 } }, + { "„", { 8222, 0 } }, + { "⥧", { 10599, 0 } }, + { "⥋", { 10571, 0 } }, + { "↲", { 8626, 0 } }, + { "≤", { 8804, 0 } }, + { "←", { 8592, 0 } }, + { "↢", { 8610, 0 } }, + { "↽", { 8637, 0 } }, + { "↼", { 8636, 0 } }, + { "⇇", { 8647, 0 } }, + { "↔", { 8596, 0 } }, + { "⇆", { 8646, 0 } }, + { "⇋", { 8651, 0 } }, + { "↭", { 8621, 0 } }, + { "⋋", { 8907, 0 } }, + { "⋚", { 8922, 0 } }, + { "≤", { 8804, 0 } }, + { "≦", { 8806, 0 } }, + { "⩽", { 10877, 0 } }, + { "⩽", { 10877, 0 } }, + { "⪨", { 10920, 0 } }, + { "⩿", { 10879, 0 } }, + { "⪁", { 10881, 0 } }, + { "⪃", { 10883, 0 } }, + { "⋚︀", { 8922, 65024 } }, + { "⪓", { 10899, 0 } }, + { "⪅", { 10885, 0 } }, + { "⋖", { 8918, 0 } }, + { "⋚", { 8922, 0 } }, + { "⪋", { 10891, 0 } }, + { "≶", { 8822, 0 } }, + { "≲", { 8818, 0 } }, + { "⥼", { 10620, 0 } }, + { "⌊", { 8970, 0 } }, + { "𝔩", { 120105, 0 } }, + { "≶", { 8822, 0 } }, + { "⪑", { 10897, 0 } }, + { "↽", { 8637, 0 } }, + { "↼", { 8636, 0 } }, + { "⥪", { 10602, 0 } }, + { "▄", { 9604, 0 } }, + { "љ", { 1113, 0 } }, + { "≪", { 8810, 0 } }, + { "⇇", { 8647, 0 } }, + { "⌞", { 8990, 0 } }, + { "⥫", { 10603, 0 } }, + { "◺", { 9722, 0 } }, + { "ŀ", { 320, 0 } }, + { "⎰", { 9136, 0 } }, + { "⎰", { 9136, 0 } }, + { "≨", { 8808, 0 } }, + { "⪉", { 10889, 0 } }, + { "⪉", { 10889, 0 } }, + { "⪇", { 10887, 0 } }, + { "⪇", { 10887, 0 } }, + { "≨", { 8808, 0 } }, + { "⋦", { 8934, 0 } }, + { "⟬", { 10220, 0 } }, + { "⇽", { 8701, 0 } }, + { "⟦", { 10214, 0 } }, + { "⟵", { 10229, 0 } }, + { "⟷", { 10231, 0 } }, + { "⟼", { 10236, 0 } }, + { "⟶", { 10230, 0 } }, + { "↫", { 8619, 0 } }, + { "↬", { 8620, 0 } }, + { "⦅", { 10629, 0 } }, + { "𝕝", { 120157, 0 } }, + { "⨭", { 10797, 0 } }, + { "⨴", { 10804, 0 } }, + { "∗", { 8727, 0 } }, + { "_", { 95, 0 } }, + { "◊", { 9674, 0 } }, + { "◊", { 9674, 0 } }, + { "⧫", { 10731, 0 } }, + { "(", { 40, 0 } }, + { "⦓", { 10643, 0 } }, + { "⇆", { 8646, 0 } }, + { "⌟", { 8991, 0 } }, + { "⇋", { 8651, 0 } }, + { "⥭", { 10605, 0 } }, + { "‎", { 8206, 0 } }, + { "⊿", { 8895, 0 } }, + { "‹", { 8249, 0 } }, + { "𝓁", { 120001, 0 } }, + { "↰", { 8624, 0 } }, + { "≲", { 8818, 0 } }, + { "⪍", { 10893, 0 } }, + { "⪏", { 10895, 0 } }, + { "[", { 91, 0 } }, + { "‘", { 8216, 0 } }, + { "‚", { 8218, 0 } }, + { "ł", { 322, 0 } }, + { "<", { 60, 0 } }, + { "⪦", { 10918, 0 } }, + { "⩹", { 10873, 0 } }, + { "⋖", { 8918, 0 } }, + { "⋋", { 8907, 0 } }, + { "⋉", { 8905, 0 } }, + { "⥶", { 10614, 0 } }, + { "⩻", { 10875, 0 } }, + { "⦖", { 10646, 0 } }, + { "◃", { 9667, 0 } }, + { "⊴", { 8884, 0 } }, + { "◂", { 9666, 0 } }, + { "⥊", { 10570, 0 } }, + { "⥦", { 10598, 0 } }, + { "≨︀", { 8808, 65024 } }, + { "≨︀", { 8808, 65024 } }, + { "∺", { 8762, 0 } }, + { "¯", { 175, 0 } }, + { "♂", { 9794, 0 } }, + { "✠", { 10016, 0 } }, + { "✠", { 10016, 0 } }, + { "↦", { 8614, 0 } }, + { "↦", { 8614, 0 } }, + { "↧", { 8615, 0 } }, + { "↤", { 8612, 0 } }, + { "↥", { 8613, 0 } }, + { "▮", { 9646, 0 } }, + { "⨩", { 10793, 0 } }, + { "м", { 1084, 0 } }, + { "—", { 8212, 0 } }, + { "∡", { 8737, 0 } }, + { "𝔪", { 120106, 0 } }, + { "℧", { 8487, 0 } }, + { "µ", { 181, 0 } }, + { "∣", { 8739, 0 } }, + { "*", { 42, 0 } }, + { "⫰", { 10992, 0 } }, + { "·", { 183, 0 } }, + { "−", { 8722, 0 } }, + { "⊟", { 8863, 0 } }, + { "∸", { 8760, 0 } }, + { "⨪", { 10794, 0 } }, + { "⫛", { 10971, 0 } }, + { "…", { 8230, 0 } }, + { "∓", { 8723, 0 } }, + { "⊧", { 8871, 0 } }, + { "𝕞", { 120158, 0 } }, + { "∓", { 8723, 0 } }, + { "𝓂", { 120002, 0 } }, + { "∾", { 8766, 0 } }, + { "μ", { 956, 0 } }, + { "⊸", { 8888, 0 } }, + { "⊸", { 8888, 0 } }, + { "⋙̸", { 8921, 824 } }, + { "≫⃒", { 8811, 8402 } }, + { "≫̸", { 8811, 824 } }, + { "⇍", { 8653, 0 } }, + { "⇎", { 8654, 0 } }, + { "⋘̸", { 8920, 824 } }, + { "≪⃒", { 8810, 8402 } }, + { "≪̸", { 8810, 824 } }, + { "⇏", { 8655, 0 } }, + { "⊯", { 8879, 0 } }, + { "⊮", { 8878, 0 } }, + { "∇", { 8711, 0 } }, + { "ń", { 324, 0 } }, + { "∠⃒", { 8736, 8402 } }, + { "≉", { 8777, 0 } }, + { "⩰̸", { 10864, 824 } }, + { "≋̸", { 8779, 824 } }, + { "ʼn", { 329, 0 } }, + { "≉", { 8777, 0 } }, + { "♮", { 9838, 0 } }, + { "♮", { 9838, 0 } }, + { "ℕ", { 8469, 0 } }, + { " ", { 160, 0 } }, + { "≎̸", { 8782, 824 } }, + { "≏̸", { 8783, 824 } }, + { "⩃", { 10819, 0 } }, + { "ň", { 328, 0 } }, + { "ņ", { 326, 0 } }, + { "≇", { 8775, 0 } }, + { "⩭̸", { 10861, 824 } }, + { "⩂", { 10818, 0 } }, + { "н", { 1085, 0 } }, + { "–", { 8211, 0 } }, + { "≠", { 8800, 0 } }, + { "⇗", { 8663, 0 } }, + { "⤤", { 10532, 0 } }, + { "↗", { 8599, 0 } }, + { "↗", { 8599, 0 } }, + { "≐̸", { 8784, 824 } }, + { "≢", { 8802, 0 } }, + { "⤨", { 10536, 0 } }, + { "≂̸", { 8770, 824 } }, + { "∄", { 8708, 0 } }, + { "∄", { 8708, 0 } }, + { "𝔫", { 120107, 0 } }, + { "≧̸", { 8807, 824 } }, + { "≱", { 8817, 0 } }, + { "≱", { 8817, 0 } }, + { "≧̸", { 8807, 824 } }, + { "⩾̸", { 10878, 824 } }, + { "⩾̸", { 10878, 824 } }, + { "≵", { 8821, 0 } }, + { "≯", { 8815, 0 } }, + { "≯", { 8815, 0 } }, + { "⇎", { 8654, 0 } }, + { "↮", { 8622, 0 } }, + { "⫲", { 10994, 0 } }, + { "∋", { 8715, 0 } }, + { "⋼", { 8956, 0 } }, + { "⋺", { 8954, 0 } }, + { "∋", { 8715, 0 } }, + { "њ", { 1114, 0 } }, + { "⇍", { 8653, 0 } }, + { "≦̸", { 8806, 824 } }, + { "↚", { 8602, 0 } }, + { "‥", { 8229, 0 } }, + { "≰", { 8816, 0 } }, + { "↚", { 8602, 0 } }, + { "↮", { 8622, 0 } }, + { "≰", { 8816, 0 } }, + { "≦̸", { 8806, 824 } }, + { "⩽̸", { 10877, 824 } }, + { "⩽̸", { 10877, 824 } }, + { "≮", { 8814, 0 } }, + { "≴", { 8820, 0 } }, + { "≮", { 8814, 0 } }, + { "⋪", { 8938, 0 } }, + { "⋬", { 8940, 0 } }, + { "∤", { 8740, 0 } }, + { "𝕟", { 120159, 0 } }, + { "¬", { 172, 0 } }, + { "∉", { 8713, 0 } }, + { "⋹̸", { 8953, 824 } }, + { "⋵̸", { 8949, 824 } }, + { "∉", { 8713, 0 } }, + { "⋷", { 8951, 0 } }, + { "⋶", { 8950, 0 } }, + { "∌", { 8716, 0 } }, + { "∌", { 8716, 0 } }, + { "⋾", { 8958, 0 } }, + { "⋽", { 8957, 0 } }, + { "∦", { 8742, 0 } }, + { "∦", { 8742, 0 } }, + { "⫽⃥", { 11005, 8421 } }, + { "∂̸", { 8706, 824 } }, + { "⨔", { 10772, 0 } }, + { "⊀", { 8832, 0 } }, + { "⋠", { 8928, 0 } }, + { "⪯̸", { 10927, 824 } }, + { "⊀", { 8832, 0 } }, + { "⪯̸", { 10927, 824 } }, + { "⇏", { 8655, 0 } }, + { "↛", { 8603, 0 } }, + { "⤳̸", { 10547, 824 } }, + { "↝̸", { 8605, 824 } }, + { "↛", { 8603, 0 } }, + { "⋫", { 8939, 0 } }, + { "⋭", { 8941, 0 } }, + { "⊁", { 8833, 0 } }, + { "⋡", { 8929, 0 } }, + { "⪰̸", { 10928, 824 } }, + { "𝓃", { 120003, 0 } }, + { "∤", { 8740, 0 } }, + { "∦", { 8742, 0 } }, + { "≁", { 8769, 0 } }, + { "≄", { 8772, 0 } }, + { "≄", { 8772, 0 } }, + { "∤", { 8740, 0 } }, + { "∦", { 8742, 0 } }, + { "⋢", { 8930, 0 } }, + { "⋣", { 8931, 0 } }, + { "⊄", { 8836, 0 } }, + { "⫅̸", { 10949, 824 } }, + { "⊈", { 8840, 0 } }, + { "⊂⃒", { 8834, 8402 } }, + { "⊈", { 8840, 0 } }, + { "⫅̸", { 10949, 824 } }, + { "⊁", { 8833, 0 } }, + { "⪰̸", { 10928, 824 } }, + { "⊅", { 8837, 0 } }, + { "⫆̸", { 10950, 824 } }, + { "⊉", { 8841, 0 } }, + { "⊃⃒", { 8835, 8402 } }, + { "⊉", { 8841, 0 } }, + { "⫆̸", { 10950, 824 } }, + { "≹", { 8825, 0 } }, + { "ñ", { 241, 0 } }, + { "≸", { 8824, 0 } }, + { "⋪", { 8938, 0 } }, + { "⋬", { 8940, 0 } }, + { "⋫", { 8939, 0 } }, + { "⋭", { 8941, 0 } }, + { "ν", { 957, 0 } }, + { "#", { 35, 0 } }, + { "№", { 8470, 0 } }, + { " ", { 8199, 0 } }, + { "⊭", { 8877, 0 } }, + { "⤄", { 10500, 0 } }, + { "≍⃒", { 8781, 8402 } }, + { "⊬", { 8876, 0 } }, + { "≥⃒", { 8805, 8402 } }, + { ">⃒", { 62, 8402 } }, + { "⧞", { 10718, 0 } }, + { "⤂", { 10498, 0 } }, + { "≤⃒", { 8804, 8402 } }, + { "<⃒", { 60, 8402 } }, + { "⊴⃒", { 8884, 8402 } }, + { "⤃", { 10499, 0 } }, + { "⊵⃒", { 8885, 8402 } }, + { "∼⃒", { 8764, 8402 } }, + { "⇖", { 8662, 0 } }, + { "⤣", { 10531, 0 } }, + { "↖", { 8598, 0 } }, + { "↖", { 8598, 0 } }, + { "⤧", { 10535, 0 } }, + { "Ⓢ", { 9416, 0 } }, + { "ó", { 243, 0 } }, + { "⊛", { 8859, 0 } }, + { "⊚", { 8858, 0 } }, + { "ô", { 244, 0 } }, + { "о", { 1086, 0 } }, + { "⊝", { 8861, 0 } }, + { "ő", { 337, 0 } }, + { "⨸", { 10808, 0 } }, + { "⊙", { 8857, 0 } }, + { "⦼", { 10684, 0 } }, + { "œ", { 339, 0 } }, + { "⦿", { 10687, 0 } }, + { "𝔬", { 120108, 0 } }, + { "˛", { 731, 0 } }, + { "ò", { 242, 0 } }, + { "⧁", { 10689, 0 } }, + { "⦵", { 10677, 0 } }, + { "Ω", { 937, 0 } }, + { "∮", { 8750, 0 } }, + { "↺", { 8634, 0 } }, + { "⦾", { 10686, 0 } }, + { "⦻", { 10683, 0 } }, + { "‾", { 8254, 0 } }, + { "⧀", { 10688, 0 } }, + { "ō", { 333, 0 } }, + { "ω", { 969, 0 } }, + { "ο", { 959, 0 } }, + { "⦶", { 10678, 0 } }, + { "⊖", { 8854, 0 } }, + { "𝕠", { 120160, 0 } }, + { "⦷", { 10679, 0 } }, + { "⦹", { 10681, 0 } }, + { "⊕", { 8853, 0 } }, + { "∨", { 8744, 0 } }, + { "↻", { 8635, 0 } }, + { "⩝", { 10845, 0 } }, + { "ℴ", { 8500, 0 } }, + { "ℴ", { 8500, 0 } }, + { "ª", { 170, 0 } }, + { "º", { 186, 0 } }, + { "⊶", { 8886, 0 } }, + { "⩖", { 10838, 0 } }, + { "⩗", { 10839, 0 } }, + { "⩛", { 10843, 0 } }, + { "ℴ", { 8500, 0 } }, + { "ø", { 248, 0 } }, + { "⊘", { 8856, 0 } }, + { "õ", { 245, 0 } }, + { "⊗", { 8855, 0 } }, + { "⨶", { 10806, 0 } }, + { "ö", { 246, 0 } }, + { "⌽", { 9021, 0 } }, + { "∥", { 8741, 0 } }, + { "¶", { 182, 0 } }, + { "∥", { 8741, 0 } }, + { "⫳", { 10995, 0 } }, + { "⫽", { 11005, 0 } }, + { "∂", { 8706, 0 } }, + { "п", { 1087, 0 } }, + { "%", { 37, 0 } }, + { ".", { 46, 0 } }, + { "‰", { 8240, 0 } }, + { "⊥", { 8869, 0 } }, + { "‱", { 8241, 0 } }, + { "𝔭", { 120109, 0 } }, + { "φ", { 966, 0 } }, + { "ϕ", { 981, 0 } }, + { "ℳ", { 8499, 0 } }, + { "☎", { 9742, 0 } }, + { "π", { 960, 0 } }, + { "⋔", { 8916, 0 } }, + { "ϖ", { 982, 0 } }, + { "ℏ", { 8463, 0 } }, + { "ℎ", { 8462, 0 } }, + { "ℏ", { 8463, 0 } }, + { "+", { 43, 0 } }, + { "⨣", { 10787, 0 } }, + { "⊞", { 8862, 0 } }, + { "⨢", { 10786, 0 } }, + { "∔", { 8724, 0 } }, + { "⨥", { 10789, 0 } }, + { "⩲", { 10866, 0 } }, + { "±", { 177, 0 } }, + { "⨦", { 10790, 0 } }, + { "⨧", { 10791, 0 } }, + { "±", { 177, 0 } }, + { "⨕", { 10773, 0 } }, + { "𝕡", { 120161, 0 } }, + { "£", { 163, 0 } }, + { "≺", { 8826, 0 } }, + { "⪳", { 10931, 0 } }, + { "⪷", { 10935, 0 } }, + { "≼", { 8828, 0 } }, + { "⪯", { 10927, 0 } }, + { "≺", { 8826, 0 } }, + { "⪷", { 10935, 0 } }, + { "≼", { 8828, 0 } }, + { "⪯", { 10927, 0 } }, + { "⪹", { 10937, 0 } }, + { "⪵", { 10933, 0 } }, + { "⋨", { 8936, 0 } }, + { "≾", { 8830, 0 } }, + { "′", { 8242, 0 } }, + { "ℙ", { 8473, 0 } }, + { "⪵", { 10933, 0 } }, + { "⪹", { 10937, 0 } }, + { "⋨", { 8936, 0 } }, + { "∏", { 8719, 0 } }, + { "⌮", { 9006, 0 } }, + { "⌒", { 8978, 0 } }, + { "⌓", { 8979, 0 } }, + { "∝", { 8733, 0 } }, + { "∝", { 8733, 0 } }, + { "≾", { 8830, 0 } }, + { "⊰", { 8880, 0 } }, + { "𝓅", { 120005, 0 } }, + { "ψ", { 968, 0 } }, + { " ", { 8200, 0 } }, + { "𝔮", { 120110, 0 } }, + { "⨌", { 10764, 0 } }, + { "𝕢", { 120162, 0 } }, + { "⁗", { 8279, 0 } }, + { "𝓆", { 120006, 0 } }, + { "ℍ", { 8461, 0 } }, + { "⨖", { 10774, 0 } }, + { "?", { 63, 0 } }, + { "≟", { 8799, 0 } }, + { """, { 34, 0 } }, + { "⇛", { 8667, 0 } }, + { "⇒", { 8658, 0 } }, + { "⤜", { 10524, 0 } }, + { "⤏", { 10511, 0 } }, + { "⥤", { 10596, 0 } }, + { "∽̱", { 8765, 817 } }, + { "ŕ", { 341, 0 } }, + { "√", { 8730, 0 } }, + { "⦳", { 10675, 0 } }, + { "⟩", { 10217, 0 } }, + { "⦒", { 10642, 0 } }, + { "⦥", { 10661, 0 } }, + { "⟩", { 10217, 0 } }, + { "»", { 187, 0 } }, + { "→", { 8594, 0 } }, + { "⥵", { 10613, 0 } }, + { "⇥", { 8677, 0 } }, + { "⤠", { 10528, 0 } }, + { "⤳", { 10547, 0 } }, + { "⤞", { 10526, 0 } }, + { "↪", { 8618, 0 } }, + { "↬", { 8620, 0 } }, + { "⥅", { 10565, 0 } }, + { "⥴", { 10612, 0 } }, + { "↣", { 8611, 0 } }, + { "↝", { 8605, 0 } }, + { "⤚", { 10522, 0 } }, + { "∶", { 8758, 0 } }, + { "ℚ", { 8474, 0 } }, + { "⤍", { 10509, 0 } }, + { "❳", { 10099, 0 } }, + { "}", { 125, 0 } }, + { "]", { 93, 0 } }, + { "⦌", { 10636, 0 } }, + { "⦎", { 10638, 0 } }, + { "⦐", { 10640, 0 } }, + { "ř", { 345, 0 } }, + { "ŗ", { 343, 0 } }, + { "⌉", { 8969, 0 } }, + { "}", { 125, 0 } }, + { "р", { 1088, 0 } }, + { "⤷", { 10551, 0 } }, + { "⥩", { 10601, 0 } }, + { "”", { 8221, 0 } }, + { "”", { 8221, 0 } }, + { "↳", { 8627, 0 } }, + { "ℜ", { 8476, 0 } }, + { "ℛ", { 8475, 0 } }, + { "ℜ", { 8476, 0 } }, + { "ℝ", { 8477, 0 } }, + { "▭", { 9645, 0 } }, + { "®", { 174, 0 } }, + { "⥽", { 10621, 0 } }, + { "⌋", { 8971, 0 } }, + { "𝔯", { 120111, 0 } }, + { "⇁", { 8641, 0 } }, + { "⇀", { 8640, 0 } }, + { "⥬", { 10604, 0 } }, + { "ρ", { 961, 0 } }, + { "ϱ", { 1009, 0 } }, + { "→", { 8594, 0 } }, + { "↣", { 8611, 0 } }, + { "⇁", { 8641, 0 } }, + { "⇀", { 8640, 0 } }, + { "⇄", { 8644, 0 } }, + { "⇌", { 8652, 0 } }, + { "⇉", { 8649, 0 } }, + { "↝", { 8605, 0 } }, + { "⋌", { 8908, 0 } }, + { "˚", { 730, 0 } }, + { "≓", { 8787, 0 } }, + { "⇄", { 8644, 0 } }, + { "⇌", { 8652, 0 } }, + { "‏", { 8207, 0 } }, + { "⎱", { 9137, 0 } }, + { "⎱", { 9137, 0 } }, + { "⫮", { 10990, 0 } }, + { "⟭", { 10221, 0 } }, + { "⇾", { 8702, 0 } }, + { "⟧", { 10215, 0 } }, + { "⦆", { 10630, 0 } }, + { "𝕣", { 120163, 0 } }, + { "⨮", { 10798, 0 } }, + { "⨵", { 10805, 0 } }, + { ")", { 41, 0 } }, + { "⦔", { 10644, 0 } }, + { "⨒", { 10770, 0 } }, + { "⇉", { 8649, 0 } }, + { "›", { 8250, 0 } }, + { "𝓇", { 120007, 0 } }, + { "↱", { 8625, 0 } }, + { "]", { 93, 0 } }, + { "’", { 8217, 0 } }, + { "’", { 8217, 0 } }, + { "⋌", { 8908, 0 } }, + { "⋊", { 8906, 0 } }, + { "▹", { 9657, 0 } }, + { "⊵", { 8885, 0 } }, + { "▸", { 9656, 0 } }, + { "⧎", { 10702, 0 } }, + { "⥨", { 10600, 0 } }, + { "℞", { 8478, 0 } }, + { "ś", { 347, 0 } }, + { "‚", { 8218, 0 } }, + { "≻", { 8827, 0 } }, + { "⪴", { 10932, 0 } }, + { "⪸", { 10936, 0 } }, + { "š", { 353, 0 } }, + { "≽", { 8829, 0 } }, + { "⪰", { 10928, 0 } }, + { "ş", { 351, 0 } }, + { "ŝ", { 349, 0 } }, + { "⪶", { 10934, 0 } }, + { "⪺", { 10938, 0 } }, + { "⋩", { 8937, 0 } }, + { "⨓", { 10771, 0 } }, + { "≿", { 8831, 0 } }, + { "с", { 1089, 0 } }, + { "⋅", { 8901, 0 } }, + { "⊡", { 8865, 0 } }, + { "⩦", { 10854, 0 } }, + { "⇘", { 8664, 0 } }, + { "⤥", { 10533, 0 } }, + { "↘", { 8600, 0 } }, + { "↘", { 8600, 0 } }, + { "§", { 167, 0 } }, + { ";", { 59, 0 } }, + { "⤩", { 10537, 0 } }, + { "∖", { 8726, 0 } }, + { "∖", { 8726, 0 } }, + { "✶", { 10038, 0 } }, + { "𝔰", { 120112, 0 } }, + { "⌢", { 8994, 0 } }, + { "♯", { 9839, 0 } }, + { "щ", { 1097, 0 } }, + { "ш", { 1096, 0 } }, + { "∣", { 8739, 0 } }, + { "∥", { 8741, 0 } }, + { "­", { 173, 0 } }, + { "σ", { 963, 0 } }, + { "ς", { 962, 0 } }, + { "ς", { 962, 0 } }, + { "∼", { 8764, 0 } }, + { "⩪", { 10858, 0 } }, + { "≃", { 8771, 0 } }, + { "≃", { 8771, 0 } }, + { "⪞", { 10910, 0 } }, + { "⪠", { 10912, 0 } }, + { "⪝", { 10909, 0 } }, + { "⪟", { 10911, 0 } }, + { "≆", { 8774, 0 } }, + { "⨤", { 10788, 0 } }, + { "⥲", { 10610, 0 } }, + { "←", { 8592, 0 } }, + { "∖", { 8726, 0 } }, + { "⨳", { 10803, 0 } }, + { "⧤", { 10724, 0 } }, + { "∣", { 8739, 0 } }, + { "⌣", { 8995, 0 } }, + { "⪪", { 10922, 0 } }, + { "⪬", { 10924, 0 } }, + { "⪬︀", { 10924, 65024 } }, + { "ь", { 1100, 0 } }, + { "/", { 47, 0 } }, + { "⧄", { 10692, 0 } }, + { "⌿", { 9023, 0 } }, + { "𝕤", { 120164, 0 } }, + { "♠", { 9824, 0 } }, + { "♠", { 9824, 0 } }, + { "∥", { 8741, 0 } }, + { "⊓", { 8851, 0 } }, + { "⊓︀", { 8851, 65024 } }, + { "⊔", { 8852, 0 } }, + { "⊔︀", { 8852, 65024 } }, + { "⊏", { 8847, 0 } }, + { "⊑", { 8849, 0 } }, + { "⊏", { 8847, 0 } }, + { "⊑", { 8849, 0 } }, + { "⊐", { 8848, 0 } }, + { "⊒", { 8850, 0 } }, + { "⊐", { 8848, 0 } }, + { "⊒", { 8850, 0 } }, + { "□", { 9633, 0 } }, + { "□", { 9633, 0 } }, + { "▪", { 9642, 0 } }, + { "▪", { 9642, 0 } }, + { "→", { 8594, 0 } }, + { "𝓈", { 120008, 0 } }, + { "∖", { 8726, 0 } }, + { "⌣", { 8995, 0 } }, + { "⋆", { 8902, 0 } }, + { "☆", { 9734, 0 } }, + { "★", { 9733, 0 } }, + { "ϵ", { 1013, 0 } }, + { "ϕ", { 981, 0 } }, + { "¯", { 175, 0 } }, + { "⊂", { 8834, 0 } }, + { "⫅", { 10949, 0 } }, + { "⪽", { 10941, 0 } }, + { "⊆", { 8838, 0 } }, + { "⫃", { 10947, 0 } }, + { "⫁", { 10945, 0 } }, + { "⫋", { 10955, 0 } }, + { "⊊", { 8842, 0 } }, + { "⪿", { 10943, 0 } }, + { "⥹", { 10617, 0 } }, + { "⊂", { 8834, 0 } }, + { "⊆", { 8838, 0 } }, + { "⫅", { 10949, 0 } }, + { "⊊", { 8842, 0 } }, + { "⫋", { 10955, 0 } }, + { "⫇", { 10951, 0 } }, + { "⫕", { 10965, 0 } }, + { "⫓", { 10963, 0 } }, + { "≻", { 8827, 0 } }, + { "⪸", { 10936, 0 } }, + { "≽", { 8829, 0 } }, + { "⪰", { 10928, 0 } }, + { "⪺", { 10938, 0 } }, + { "⪶", { 10934, 0 } }, + { "⋩", { 8937, 0 } }, + { "≿", { 8831, 0 } }, + { "∑", { 8721, 0 } }, + { "♪", { 9834, 0 } }, + { "¹", { 185, 0 } }, + { "²", { 178, 0 } }, + { "³", { 179, 0 } }, + { "⊃", { 8835, 0 } }, + { "⫆", { 10950, 0 } }, + { "⪾", { 10942, 0 } }, + { "⫘", { 10968, 0 } }, + { "⊇", { 8839, 0 } }, + { "⫄", { 10948, 0 } }, + { "⟉", { 10185, 0 } }, + { "⫗", { 10967, 0 } }, + { "⥻", { 10619, 0 } }, + { "⫂", { 10946, 0 } }, + { "⫌", { 10956, 0 } }, + { "⊋", { 8843, 0 } }, + { "⫀", { 10944, 0 } }, + { "⊃", { 8835, 0 } }, + { "⊇", { 8839, 0 } }, + { "⫆", { 10950, 0 } }, + { "⊋", { 8843, 0 } }, + { "⫌", { 10956, 0 } }, + { "⫈", { 10952, 0 } }, + { "⫔", { 10964, 0 } }, + { "⫖", { 10966, 0 } }, + { "⇙", { 8665, 0 } }, + { "⤦", { 10534, 0 } }, + { "↙", { 8601, 0 } }, + { "↙", { 8601, 0 } }, + { "⤪", { 10538, 0 } }, + { "ß", { 223, 0 } }, + { "⌖", { 8982, 0 } }, + { "τ", { 964, 0 } }, + { "⎴", { 9140, 0 } }, + { "ť", { 357, 0 } }, + { "ţ", { 355, 0 } }, + { "т", { 1090, 0 } }, + { "⃛", { 8411, 0 } }, + { "⌕", { 8981, 0 } }, + { "𝔱", { 120113, 0 } }, + { "∴", { 8756, 0 } }, + { "∴", { 8756, 0 } }, + { "θ", { 952, 0 } }, + { "ϑ", { 977, 0 } }, + { "ϑ", { 977, 0 } }, + { "≈", { 8776, 0 } }, + { "∼", { 8764, 0 } }, + { " ", { 8201, 0 } }, + { "≈", { 8776, 0 } }, + { "∼", { 8764, 0 } }, + { "þ", { 254, 0 } }, + { "˜", { 732, 0 } }, + { "×", { 215, 0 } }, + { "⊠", { 8864, 0 } }, + { "⨱", { 10801, 0 } }, + { "⨰", { 10800, 0 } }, + { "∭", { 8749, 0 } }, + { "⤨", { 10536, 0 } }, + { "⊤", { 8868, 0 } }, + { "⌶", { 9014, 0 } }, + { "⫱", { 10993, 0 } }, + { "𝕥", { 120165, 0 } }, + { "⫚", { 10970, 0 } }, + { "⤩", { 10537, 0 } }, + { "‴", { 8244, 0 } }, + { "™", { 8482, 0 } }, + { "▵", { 9653, 0 } }, + { "▿", { 9663, 0 } }, + { "◃", { 9667, 0 } }, + { "⊴", { 8884, 0 } }, + { "≜", { 8796, 0 } }, + { "▹", { 9657, 0 } }, + { "⊵", { 8885, 0 } }, + { "◬", { 9708, 0 } }, + { "≜", { 8796, 0 } }, + { "⨺", { 10810, 0 } }, + { "⨹", { 10809, 0 } }, + { "⧍", { 10701, 0 } }, + { "⨻", { 10811, 0 } }, + { "⏢", { 9186, 0 } }, + { "𝓉", { 120009, 0 } }, + { "ц", { 1094, 0 } }, + { "ћ", { 1115, 0 } }, + { "ŧ", { 359, 0 } }, + { "≬", { 8812, 0 } }, + { "↞", { 8606, 0 } }, + { "↠", { 8608, 0 } }, + { "⇑", { 8657, 0 } }, + { "⥣", { 10595, 0 } }, + { "ú", { 250, 0 } }, + { "↑", { 8593, 0 } }, + { "ў", { 1118, 0 } }, + { "ŭ", { 365, 0 } }, + { "û", { 251, 0 } }, + { "у", { 1091, 0 } }, + { "⇅", { 8645, 0 } }, + { "ű", { 369, 0 } }, + { "⥮", { 10606, 0 } }, + { "⥾", { 10622, 0 } }, + { "𝔲", { 120114, 0 } }, + { "ù", { 249, 0 } }, + { "↿", { 8639, 0 } }, + { "↾", { 8638, 0 } }, + { "▀", { 9600, 0 } }, + { "⌜", { 8988, 0 } }, + { "⌜", { 8988, 0 } }, + { "⌏", { 8975, 0 } }, + { "◸", { 9720, 0 } }, + { "ū", { 363, 0 } }, + { "¨", { 168, 0 } }, + { "ų", { 371, 0 } }, + { "𝕦", { 120166, 0 } }, + { "↑", { 8593, 0 } }, + { "↕", { 8597, 0 } }, + { "↿", { 8639, 0 } }, + { "↾", { 8638, 0 } }, + { "⊎", { 8846, 0 } }, + { "υ", { 965, 0 } }, + { "ϒ", { 978, 0 } }, + { "υ", { 965, 0 } }, + { "⇈", { 8648, 0 } }, + { "⌝", { 8989, 0 } }, + { "⌝", { 8989, 0 } }, + { "⌎", { 8974, 0 } }, + { "ů", { 367, 0 } }, + { "◹", { 9721, 0 } }, + { "𝓊", { 120010, 0 } }, + { "⋰", { 8944, 0 } }, + { "ũ", { 361, 0 } }, + { "▵", { 9653, 0 } }, + { "▴", { 9652, 0 } }, + { "⇈", { 8648, 0 } }, + { "ü", { 252, 0 } }, + { "⦧", { 10663, 0 } }, + { "⇕", { 8661, 0 } }, + { "⫨", { 10984, 0 } }, + { "⫩", { 10985, 0 } }, + { "⊨", { 8872, 0 } }, + { "⦜", { 10652, 0 } }, + { "ϵ", { 1013, 0 } }, + { "ϰ", { 1008, 0 } }, + { "∅", { 8709, 0 } }, + { "ϕ", { 981, 0 } }, + { "ϖ", { 982, 0 } }, + { "∝", { 8733, 0 } }, + { "↕", { 8597, 0 } }, + { "ϱ", { 1009, 0 } }, + { "ς", { 962, 0 } }, + { "⊊︀", { 8842, 65024 } }, + { "⫋︀", { 10955, 65024 } }, + { "⊋︀", { 8843, 65024 } }, + { "⫌︀", { 10956, 65024 } }, + { "ϑ", { 977, 0 } }, + { "⊲", { 8882, 0 } }, + { "⊳", { 8883, 0 } }, + { "в", { 1074, 0 } }, + { "⊢", { 8866, 0 } }, + { "∨", { 8744, 0 } }, + { "⊻", { 8891, 0 } }, + { "≚", { 8794, 0 } }, + { "⋮", { 8942, 0 } }, + { "|", { 124, 0 } }, + { "|", { 124, 0 } }, + { "𝔳", { 120115, 0 } }, + { "⊲", { 8882, 0 } }, + { "⊂⃒", { 8834, 8402 } }, + { "⊃⃒", { 8835, 8402 } }, + { "𝕧", { 120167, 0 } }, + { "∝", { 8733, 0 } }, + { "⊳", { 8883, 0 } }, + { "𝓋", { 120011, 0 } }, + { "⫋︀", { 10955, 65024 } }, + { "⊊︀", { 8842, 65024 } }, + { "⫌︀", { 10956, 65024 } }, + { "⊋︀", { 8843, 65024 } }, + { "⦚", { 10650, 0 } }, + { "ŵ", { 373, 0 } }, + { "⩟", { 10847, 0 } }, + { "∧", { 8743, 0 } }, + { "≙", { 8793, 0 } }, + { "℘", { 8472, 0 } }, + { "𝔴", { 120116, 0 } }, + { "𝕨", { 120168, 0 } }, + { "℘", { 8472, 0 } }, + { "≀", { 8768, 0 } }, + { "≀", { 8768, 0 } }, + { "𝓌", { 120012, 0 } }, + { "⋂", { 8898, 0 } }, + { "◯", { 9711, 0 } }, + { "⋃", { 8899, 0 } }, + { "▽", { 9661, 0 } }, + { "𝔵", { 120117, 0 } }, + { "⟺", { 10234, 0 } }, + { "⟷", { 10231, 0 } }, + { "ξ", { 958, 0 } }, + { "⟸", { 10232, 0 } }, + { "⟵", { 10229, 0 } }, + { "⟼", { 10236, 0 } }, + { "⋻", { 8955, 0 } }, + { "⨀", { 10752, 0 } }, + { "𝕩", { 120169, 0 } }, + { "⨁", { 10753, 0 } }, + { "⨂", { 10754, 0 } }, + { "⟹", { 10233, 0 } }, + { "⟶", { 10230, 0 } }, + { "𝓍", { 120013, 0 } }, + { "⨆", { 10758, 0 } }, + { "⨄", { 10756, 0 } }, + { "△", { 9651, 0 } }, + { "⋁", { 8897, 0 } }, + { "⋀", { 8896, 0 } }, + { "ý", { 253, 0 } }, + { "я", { 1103, 0 } }, + { "ŷ", { 375, 0 } }, + { "ы", { 1099, 0 } }, + { "¥", { 165, 0 } }, + { "𝔶", { 120118, 0 } }, + { "ї", { 1111, 0 } }, + { "𝕪", { 120170, 0 } }, + { "𝓎", { 120014, 0 } }, + { "ю", { 1102, 0 } }, + { "ÿ", { 255, 0 } }, + { "ź", { 378, 0 } }, + { "ž", { 382, 0 } }, + { "з", { 1079, 0 } }, + { "ż", { 380, 0 } }, + { "ℨ", { 8488, 0 } }, + { "ζ", { 950, 0 } }, + { "𝔷", { 120119, 0 } }, + { "ж", { 1078, 0 } }, + { "⇝", { 8669, 0 } }, + { "𝕫", { 120171, 0 } }, + { "𝓏", { 120015, 0 } }, + { "‍", { 8205, 0 } }, + { "‌", { 8204, 0 } } +}; + + +typedef struct ENTITY_KEY_tag ENTITY_KEY; +struct ENTITY_KEY_tag { + const char* name; + size_t name_size; +}; + +static int +entity_cmp(const void* p_key, const void* p_entity) +{ + ENTITY_KEY* key = (ENTITY_KEY*) p_key; + ENRMRKD_ENTITY* ent = (ENRMRKD_ENTITY*) p_entity; + + return strncmp(key->name, ent->name, key->name_size); +} + +const ENRMRKD_ENTITY* +enrmrkd_entity_lookup(const char* name, size_t name_size) +{ + ENTITY_KEY key = { name, name_size }; + + return bsearch(&key, + ENRMRKD_ENTITY_MAP, + sizeof(ENRMRKD_ENTITY_MAP) / sizeof(ENRMRKD_ENTITY_MAP[0]), + sizeof(ENRMRKD_ENTITY), + entity_cmp); +} diff --git a/packages/core/cpp/enrmrkd/enrmrkd-entity.h b/packages/core/cpp/enrmrkd/enrmrkd-entity.h new file mode 100644 index 000000000..c87d2edbd --- /dev/null +++ b/packages/core/cpp/enrmrkd/enrmrkd-entity.h @@ -0,0 +1,43 @@ +/* + * MD4C: Markdown parser for C + * (https://github.com/mity/md4c) + * + * Copyright (c) 2016-2026 Martin Mitáš + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef ENRMRKD_ENTITY_H +#define ENRMRKD_ENTITY_H + +#include + + +/* Most entities are formed by single Unicode codepoint, few by two codepoints. + * Single-codepoint entities have codepoints[1] set to zero. */ +typedef struct ENRMRKD_ENTITY_tag ENRMRKD_ENTITY; +struct ENRMRKD_ENTITY_tag { + const char* name; + unsigned codepoints[2]; +}; + +const ENRMRKD_ENTITY* enrmrkd_entity_lookup(const char* name, size_t name_size); + + +#endif /* ENRMRKD_ENTITY_H */ diff --git a/packages/core/cpp/parser/MD4CParser.cpp b/packages/core/cpp/parser/MD4CParser.cpp index 1c99a7553..2b5ed1900 100644 --- a/packages/core/cpp/parser/MD4CParser.cpp +++ b/packages/core/cpp/parser/MD4CParser.cpp @@ -1,12 +1,76 @@ #include "MD4CParser.hpp" #include "enrmrkd.h" #include +#include +extern "C" { +#include "enrmrkd-entity.h" +} #include #include namespace Markdown { namespace { +void appendCodepoint(std::string &output, unsigned int codepoint) { + if (codepoint == 0 || codepoint > 0x10FFFF || (codepoint >= 0xD800 && codepoint <= 0xDFFF)) { + codepoint = 0xFFFD; + } + if (codepoint < 0x80) { + output += static_cast(codepoint); + } else if (codepoint < 0x800) { + output += static_cast(0xC0 | (codepoint >> 6)); + output += static_cast(0x80 | (codepoint & 0x3F)); + } else if (codepoint < 0x10000) { + output += static_cast(0xE0 | (codepoint >> 12)); + output += static_cast(0x80 | ((codepoint >> 6) & 0x3F)); + output += static_cast(0x80 | (codepoint & 0x3F)); + } else { + output += static_cast(0xF0 | (codepoint >> 18)); + output += static_cast(0x80 | ((codepoint >> 12) & 0x3F)); + output += static_cast(0x80 | ((codepoint >> 6) & 0x3F)); + output += static_cast(0x80 | (codepoint & 0x3F)); + } +} + +// md4c has already classified syntax, so a decoded delimiter stays literal text. +void appendCharacterReference(std::string &output, const char *text, size_t size) { + if (size < 4) { + output.append(text, size); + return; + } + if (text[1] != '#') { + const ENRMRKD_ENTITY *entity = enrmrkd_entity_lookup(text, size); + if (!entity) { + output.append(text, size); + return; + } + appendCodepoint(output, entity->codepoints[0]); + if (entity->codepoints[1]) + appendCodepoint(output, entity->codepoints[1]); + return; + } + const bool hex = text[2] == 'x' || text[2] == 'X'; + const char *begin = text + (hex ? 3 : 2); + const char *end = text + size - 1; + unsigned int codepoint = 0; + for (const char *p = begin; p != end; ++p) { + unsigned int digit; + if (*p >= '0' && *p <= '9') { + digit = *p - '0'; + } else if (hex && *p >= 'a' && *p <= 'f') { + digit = *p - 'a' + 10; + } else if (hex && *p >= 'A' && *p <= 'F') { + digit = *p - 'A' + 10; + } else { + codepoint = 0; + break; + } + // md4c caps numeric references at 7 decimal or 6 hex digits, so this cannot overflow. + codepoint = codepoint * (hex ? 16 : 10) + digit; + } + appendCodepoint(output, codepoint); +} + struct HtmlTag { std::string name; std::unordered_map attributes; @@ -80,13 +144,25 @@ class MD4CParser::Impl { } } + // Attributes arrive as typed substrings; entity segments decode like text does. std::string getAttributeText(const ENRMRKD_ATTRIBUTE *attr) { if (!attr || attr->size == 0 || !attr->text) return {}; - - // Use string constructor directly - let SSO handle small strings efficiently - // Empty return {} avoids allocating empty string object - return std::string(attr->text, attr->size); + if (!attr->substr_types || !attr->substr_offsets) + return std::string(attr->text, attr->size); + + std::string result; + result.reserve(attr->size); + for (size_t i = 0; attr->substr_offsets[i] < attr->size; i++) { + const char *start = attr->text + attr->substr_offsets[i]; + const size_t length = attr->substr_offsets[i + 1] - attr->substr_offsets[i]; + if (attr->substr_types[i] == ENRMRKD_TEXT_ENTITY) { + appendCharacterReference(result, start, length); + } else { + result.append(start, length); + } + } + return result; } static int enterBlock(ENRMRKD_BLOCKTYPE type, void *detail, void *userdata) { @@ -426,6 +502,11 @@ class MD4CParser::Impl { return 0; } + if (type == ENRMRKD_TEXT_ENTITY) { + appendCharacterReference(impl->currentText, text, size); + return 0; + } + // Handle text content (normal text, code text, LaTeX math, etc.) if (type == ENRMRKD_TEXT_NORMAL || type == ENRMRKD_TEXT_CODE || type == ENRMRKD_TEXT_LATEXMATH) { impl->currentText.append(text, size); diff --git a/packages/core/cpp/tests/golden/ast.txt b/packages/core/cpp/tests/golden/ast.txt index bee22d2aa..92d22823c 100644 --- a/packages/core/cpp/tests/golden/ast.txt +++ b/packages/core/cpp/tests/golden/ast.txt @@ -1,13 +1,13 @@ === commonmark.md [defaults-gfm] === -{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"SoftBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"SoftBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"false"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"unchecked task"}]}]},{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"true"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"checked task"}]}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"SoftBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"SoftBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"false"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"unchecked task"}]}]},{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"true"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"checked task"}]}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"Term & entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} === commonmark.md [defaults-commonmark] === -{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"SoftBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"SoftBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[ ] unchecked task"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[x] checked task"}]}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"SoftBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"SoftBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[ ] unchecked task"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[x] checked task"}]}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"Term & entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} === commonmark.md [extensions-off-gfm] === -{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"SoftBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"SoftBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"false"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"unchecked task"}]}]},{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"true"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"checked task"}]}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"SoftBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"SoftBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"false"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"unchecked task"}]}]},{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"true"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"checked task"}]}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"Term & entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} === commonmark.md [extensions-on-gfm] === -{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"LineBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"LineBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"false"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"unchecked task"}]}]},{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"true"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"checked task"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"LineBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"LineBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"false"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"unchecked task"}]}]},{"type":"ListItem","attributes":{"isTask":"true","taskChecked":"true"},"children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"checked task"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Term & entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} === commonmark.md [extensions-on-commonmark] === -{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"LineBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"LineBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[ ] unchecked task"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[x] checked task"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Term entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} +{"type":"Document","children":[{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Heading one"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph with "},{"type":"Emphasis","children":[{"type":"Text","content":"emphasis"}]},{"type":"Text","content":", "},{"type":"Strong","children":[{"type":"Text","content":"strong"}]},{"type":"Text","content":", "},{"type":"Code","children":[{"type":"Text","content":"code"}]},{"type":"Text","content":", a "},{"type":"Link","attributes":{"url":"https://example.com"},"children":[{"type":"Text","content":"link"}]},{"type":"LineBreak"},{"type":"Text","content":"and an "},{"type":"Image","attributes":{"url":"https://example.com/i.png"},"children":[{"type":"Text","content":"image"}]},{"type":"Text","content":"."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Blockquote with a second line"},{"type":"LineBreak"},{"type":"Text","content":"and a lazy continuation."}]}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"First"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"Second"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested bullet"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"another"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]}]}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[ ] unchecked task"}]}]},{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"[x] checked task"}]},{"type":"BlankLine","attributes":{"count":"1"}}]}]},{"type":"CodeBlock","attributes":{"fenceChar":"`","language":"js"},"children":[{"type":"Text","content":"const answer = 42;\n"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"CodeBlock","children":[{"type":"Text","content":"indented code block\n"}]},{"type":"Heading","attributes":{"level":"1"},"children":[{"type":"Text","content":"Setext heading"}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"Term & entity, hard break at the end of this line."},{"type":"LineBreak"},{"type":"Text","content":"Next line after the hard break."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"Paragraph","children":[{"type":"Text","content":"A "},{"type":"Link","attributes":{"url":"https://example.com/ref"},"children":[{"type":"Text","content":"reference link"}]},{"type":"Text","content":" resolved below."}]},{"type":"BlankLine","attributes":{"count":"1"}},{"type":"ThematicBreak"},{"type":"Paragraph","children":[{"type":"Text","content":"A dashed line directly after a link reference definition."}]}]} === edge-cases.md [defaults-gfm] === {"type":"Document","children":[{"type":"Paragraph","children":[{"type":"Text","content":"Paragraph one."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Two blank lines above this paragraph."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Four blank lines above this one."}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","children":[{"type":"Text","content":"list item with"}]},{"type":"Paragraph","children":[{"type":"Text","content":"a loose second paragraph"}]}]},{"type":"ListItem","children":[{"type":"Blockquote","children":[{"type":"Paragraph","children":[{"type":"Text","content":"blockquote inside a list item"}]}]}]}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"ordered"}]},{"type":"OrderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"nested ordered"}]},{"type":"UnorderedList","children":[{"type":"ListItem","children":[{"type":"Paragraph","attributes":{"tight":"true"},"children":[{"type":"Text","content":"mixed nesting"}]}]}]}]}]}]}]},{"type":"Table","attributes":{"bodyRowCount":"0","colCount":"1","headRowCount":"1"},"children":[{"type":"TableHead","children":[{"type":"TableRow","children":[{"type":"TableHeaderCell","attributes":{"align":"default"},"children":[{"type":"Text","content":"broken"}]}]}]}]},{"type":"Paragraph","children":[{"type":"Text","content":"*unclosed emphasis and `unclosed code"}]},{"type":"Paragraph","children":[{"type":"Text","content":"Trailing spaces and tabs\tmixed\tin\ta\tline."}]},{"type":"Paragraph","children":[{"type":"Text","content":"Text with a NUL-ish escape \\ and a backslash-newline"},{"type":"LineBreak"},{"type":"Text","content":"continuation."}]}]} === edge-cases.md [defaults-commonmark] === diff --git a/packages/core/cpp/wasm/build.sh b/packages/core/cpp/wasm/build.sh index 787d01131..6501a223e 100755 --- a/packages/core/cpp/wasm/build.sh +++ b/packages/core/cpp/wasm/build.sh @@ -47,6 +47,12 @@ emcc \ -c "$CPP_ROOT/enrmrkd/enrmrkd.c" \ -o "$WORK/enrmrkd.o" +emcc \ + -I "$CPP_ROOT" \ + -O2 \ + -c "$CPP_ROOT/enrmrkd/enrmrkd-entity.c" \ + -o "$WORK/enrmrkd-entity.o" + # Compile C++ sources and link everything together. em++, not emcc: emscripten # 6.0.6 turned DEFAULT_TO_CXX off, so emcc no longer links the C++ runtime. em++ \ @@ -54,6 +60,7 @@ em++ \ "$SCRIPT_DIR/ASTSerializer.cpp" \ "$CPP_ROOT/parser/MD4CParser.cpp" \ "$WORK/enrmrkd.o" \ + "$WORK/enrmrkd-entity.o" \ -I "$CPP_ROOT" \ -I "$CPP_ROOT/enrmrkd" \ -I "$SCRIPT_DIR" \ diff --git a/packages/enriched-markdown-android/parser/src/androidTest/java/com/swmansion/enriched/markdown/parser/ParserTest.kt b/packages/enriched-markdown-android/parser/src/androidTest/java/com/swmansion/enriched/markdown/parser/ParserTest.kt index 836111939..8cd4b325c 100644 --- a/packages/enriched-markdown-android/parser/src/androidTest/java/com/swmansion/enriched/markdown/parser/ParserTest.kt +++ b/packages/enriched-markdown-android/parser/src/androidTest/java/com/swmansion/enriched/markdown/parser/ParserTest.kt @@ -28,6 +28,40 @@ class ParserTest { assertEquals("Hello world", text.content) } + @Test + fun decodesNamedCharacterReferencesWithoutReparsingSyntax() { + val ast = requireNotNull(parser.parseMarkdown("& © ∳ ≂̸")) + assertEquals( + "& © ∳ ≂̸", + ast.assertHasChildType(MarkdownASTNode.NodeType.Paragraph).assertHasChildType(MarkdownASTNode.NodeType.Text).content, + ) + val citation = requireNotNull(parser.parseMarkdown("[1]\n\n[1]: https://example.test")) + assertEquals( + "[1]", + citation.assertHasChildType(MarkdownASTNode.NodeType.Paragraph).assertHasChildType(MarkdownASTNode.NodeType.Text).content, + ) + assertNull(citation.firstOfType(MarkdownASTNode.NodeType.Link)) + } + + @Test + fun decodesNumericCharacterReferencesAndKeepsCodeLiteral() { + val ast = requireNotNull(parser.parseMarkdown("[1] 😀 � � �")) + assertEquals( + "[1] 😀 � � �", + ast.assertHasChildType(MarkdownASTNode.NodeType.Paragraph).assertHasChildType(MarkdownASTNode.NodeType.Text).content, + ) + val code = requireNotNull(parser.parseMarkdown("`&`")) + assertEquals( + "&", + requireNotNull(code.firstOfType(MarkdownASTNode.NodeType.Code)).assertHasChildType(MarkdownASTNode.NodeType.Text).content, + ) + val unknown = requireNotNull(parser.parseMarkdown("&bogus;")) + assertEquals( + "&bogus;", + unknown.assertHasChildType(MarkdownASTNode.NodeType.Paragraph).assertHasChildType(MarkdownASTNode.NodeType.Text).content, + ) + } + @Test fun parsesStrongAndEmphasis() { val ast = requireNotNull(parser.parseMarkdown("**bold** and *italic*")) diff --git a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Parser/SourceOffsetAnnotator.swift b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Parser/SourceOffsetAnnotator.swift index 022e85a94..6ee880db1 100644 --- a/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Parser/SourceOffsetAnnotator.swift +++ b/packages/enriched-markdown-ios/Sources/EnrichedMarkdown/Parser/SourceOffsetAnnotator.swift @@ -100,8 +100,8 @@ package enum SourceOffsetAnnotator { /// Matches `needle` at `index`, letting a source backslash escape /// match its bare character, a line break plus its indentation match /// the single space the parser flattens them to inside spans, and an - /// entity reference match either nothing (the shared - /// core drops entity text) or one decoded scalar of the needle. + /// entity reference match the one or two scalars the shared core + /// decodes it to (or nothing, for a reference the core left out). private func matchFlexible(_ needle: [UInt8], at index: Int) -> Int? { matchRemainder(of: needle, from: 0, sourceIndex: index) } @@ -133,24 +133,29 @@ package enum SourceOffsetAnnotator { continue } if let entityEnd = entityEnd(startingAt: sourceIndex) { - // A dropped entity is bridged only inside a match; a match - // never starts on one, so the forward scan anchors the text - // after a leading entity precisely. Entities are rare, so - // trying both readings stays cheap. - if needleIndex > 0, - let end = matchRemainder(of: needle, from: needleIndex, sourceIndex: entityEnd) { - return end - } - if let scalarLength = scalarLength(of: needle, at: needleIndex), - let end = matchRemainder(of: needle, from: needleIndex + scalarLength, sourceIndex: entityEnd) { - return end - } + return matchAcrossEntity(of: needle, from: needleIndex, entityEnd: entityEnd) } return nil } return sourceIndex } + /// Resumes a match past an entity reference, which the shared core + /// decodes to one or two scalars of the needle. An omitted reference + /// is bridged only inside a match; a match never starts on one, so the + /// forward scan anchors text after a leading entity precisely. + private func matchAcrossEntity(of needle: [UInt8], from needleIndex: Int, entityEnd: Int) -> Int? { + if needleIndex > 0, let end = matchRemainder(of: needle, from: needleIndex, sourceIndex: entityEnd) { + return end + } + guard let first = scalarLength(of: needle, at: needleIndex) else { return nil } + if let end = matchRemainder(of: needle, from: needleIndex + first, sourceIndex: entityEnd) { + return end + } + guard let second = scalarLength(of: needle, at: needleIndex + first) else { return nil } + return matchRemainder(of: needle, from: needleIndex + first + second, sourceIndex: entityEnd) + } + private func isLineBreak(_ byte: UInt8) -> Bool { byte == UInt8(ascii: "\n") || byte == UInt8(ascii: "\r") } diff --git a/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/MarkdownSourceSlicerTests.swift b/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/MarkdownSourceSlicerTests.swift index 94e08da39..9dac2d8a7 100644 --- a/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/MarkdownSourceSlicerTests.swift +++ b/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/MarkdownSourceSlicerTests.swift @@ -208,9 +208,9 @@ final class MarkdownSourceSlicerTests: XCTestCase { ) } - func testSelectionAcrossDroppedEntitySlicesVerbatim() { + func testSelectionAcrossDecodedEntitySlicesVerbatim() { XCTAssertEqual( - copyMarkdown(selecting: "an entity 2026", in: "next to an entity © 2026 here"), + copyMarkdown(selecting: "an entity \u{A9} 2026", in: "next to an entity © 2026 here"), "an entity © 2026" ) } diff --git a/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/ParserTests.swift b/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/ParserTests.swift index 47ff02176..a3800d862 100644 --- a/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/ParserTests.swift +++ b/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/ParserTests.swift @@ -24,6 +24,24 @@ final class ParserTests: XCTestCase { XCTAssertEqual(text?.content, "Hello world") } + func testDecodesNamedCharacterReferencesWithoutReparsingSyntax() { + let ast = parser.parseMarkdown("& © ∳ ≂̸") + XCTAssertEqual(ast.child(ofType: .paragraph)?.child(ofType: .text)?.content, "& © ∳ ≂̸") + + let citation = parser.parseMarkdown("[1]\n\n[1]: https://example.test") + XCTAssertEqual(citation.child(ofType: .paragraph)?.child(ofType: .text)?.content, "[1]") + XCTAssertNil(citation.first(ofType: .link)) + } + + func testDecodesNumericCharacterReferencesAndKeepsCodeLiteral() { + let ast = parser.parseMarkdown("[1] 😀 � � �") + XCTAssertEqual(ast.child(ofType: .paragraph)?.child(ofType: .text)?.content, "[1] 😀 � � �") + let code = parser.parseMarkdown("`&`") + XCTAssertEqual(code.first(ofType: .code)?.child(ofType: .text)?.content, "&") + let unknown = parser.parseMarkdown("&bogus;") + XCTAssertEqual(unknown.child(ofType: .paragraph)?.child(ofType: .text)?.content, "&bogus;") + } + func testParsesStrongAndEmphasis() { let ast = parser.parseMarkdown("**bold** and *italic*") diff --git a/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/SourceOffsetAnnotatorTests.swift b/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/SourceOffsetAnnotatorTests.swift index 29aad7a9b..f9f1718b3 100644 --- a/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/SourceOffsetAnnotatorTests.swift +++ b/packages/enriched-markdown-ios/Tests/EnrichedMarkdownTests/SourceOffsetAnnotatorTests.swift @@ -102,28 +102,41 @@ final class SourceOffsetAnnotatorTests: XCTestCase { XCTAssertEqual(range(of: text)?.end, 4) } - /// Recognized entities never reach the AST (the shared core drops - /// MD_TEXT_ENTITY), so the text after one must still anchor past the - /// reference instead of derailing. - func testDroppedEntityDoesNotDerailFollowingText() { + /// The shared core decodes an entity into its scalar, so a text node that + /// starts with one anchors at the reference, not after it. + func testDecodedEntityAtTextStartAnchorsOnTheReference() { let ast = annotate("© 2026") - let text = ast.all(ofType: .text).first { $0.content == " 2026" } - XCTAssertEqual(range(of: text)?.start, 6) + let text = ast.all(ofType: .text).first { $0.content == "\u{A9} 2026" } + XCTAssertNotNil(text) + XCTAssertEqual(range(of: text)?.start, 0) XCTAssertEqual(range(of: text)?.end, 11) } - /// The core keeps the text around a dropped entity in one node, so the - /// node's range must span the reference it no longer contains. - func testDroppedEntityInsideTextNodeStillAnnotates() { + /// A decoded entity inside a text node is bridged back to its reference, + /// so the node's range spans the source form. + func testDecodedEntityInsideTextNodeStillAnnotates() { let ast = annotate("an entity © 2026.") - let text = ast.all(ofType: .text).first { $0.content == "an entity 2026." } + let text = ast.all(ofType: .text).first { $0.content == "an entity \u{A9} 2026." } XCTAssertNotNil(text) XCTAssertEqual(range(of: text)?.start, 0) XCTAssertEqual(range(of: text)?.end, 22) } + /// Numeric references and two-scalar entities bridge the same way. + func testNumericAndTwoScalarEntitiesStillAnnotate() { + let numeric = annotate("a © b") + let numericText = numeric.all(ofType: .text).first { $0.content == "a \u{A9} b" } + XCTAssertEqual(range(of: numericText)?.start, 0) + XCTAssertEqual(range(of: numericText)?.end, 10) + + let twoScalar = annotate("x ⪢̸ y") + let twoScalarText = twoScalar.all(ofType: .text).first { $0.content == "x \u{2AA2}\u{338} y" } + XCTAssertEqual(range(of: twoScalarText)?.start, 0) + XCTAssertEqual(range(of: twoScalarText)?.end, 29) + } + func testThematicBreakIsAnnotatedStructurally() { let ast = annotate("a\n\n---\n\nb") diff --git a/packages/react-native-enriched-markdown/src/web/__tests__/parseMarkdown.test.ts b/packages/react-native-enriched-markdown/src/web/__tests__/parseMarkdown.test.ts new file mode 100644 index 000000000..571ac409e --- /dev/null +++ b/packages/react-native-enriched-markdown/src/web/__tests__/parseMarkdown.test.ts @@ -0,0 +1,61 @@ +import { parseMarkdown } from '../parseMarkdown'; +import type { ASTNode } from '../types'; + +function texts(node: ASTNode): string[] { + const own = + typeof node.content === 'string' && node.content ? [node.content] : []; + return own.concat((node.children ?? []).flatMap(texts)); +} + +function find(node: ASTNode, type: string): ASTNode | undefined { + if (node.type === type) return node; + for (const child of node.children ?? []) { + const hit = find(child, type); + if (hit) return hit; + } + return undefined; +} + +describe('parseMarkdown character references', () => { + it('decodes named and numeric references in text', async () => { + expect( + texts(await parseMarkdown('Tom & Jerry © © ©')) + ).toEqual(['Tom & Jerry © © ©']); + }); + + it('decodes two-codepoint entities', async () => { + expect(texts(await parseMarkdown('⪢̸'))).toEqual([ + '⪢̸', + ]); + }); + + it('keeps unknown names, code spans and escapes literal', async () => { + expect( + texts(await parseMarkdown('&foo; and & `&` \\&')) + ).toEqual(['&foo; and & ', '&', ' &']); + }); + + it('replaces invalid numeric references with U+FFFD', async () => { + expect(texts(await parseMarkdown('� � �'))).toEqual([ + '� � �', + ]); + }); + + it('does not let decoded characters become syntax', async () => { + const ast = await parseMarkdown('<u>x</u> *y*'); + expect(find(ast, 'Underline')).toBeUndefined(); + expect(find(ast, 'Emphasis')).toBeUndefined(); + expect(texts(ast)).toEqual(['x *y*']); + }); + + it('decodes references in link and image attributes', async () => { + const ast = await parseMarkdown( + '[q](/u?a=1&b=2 "t & u") ![i](/p.png?x&y "c ©")' + ); + expect(find(ast, 'Link')?.attributes).toMatchObject({ url: '/u?a=1&b=2' }); + expect(find(ast, 'Image')?.attributes).toMatchObject({ + url: '/p.png?x&y', + title: 'c ©', + }); + }); +}); diff --git a/packages/react-native-enriched-markdown/src/web/wasm/md4c.js b/packages/react-native-enriched-markdown/src/web/wasm/md4c.js index d14134bad4ca2be584b34d4e97f2401386b816fd..2bd435b1b9edc1785848f8486981a63450622202 100644 GIT binary patch literal 197228 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 E4~m5*mjD0& delta 39954 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 diff --git a/scripts/fetch-md4c.sh b/scripts/fetch-md4c.sh index 09757d1fa..8d9d36b09 100755 --- a/scripts/fetch-md4c.sh +++ b/scripts/fetch-md4c.sh @@ -13,6 +13,8 @@ DEST_DIR="$(cd "$(dirname "$0")/.." && pwd)/packages/core/cpp/enrmrkd" FILES=( "enrmrkd.c" "enrmrkd.h" + "enrmrkd-entity.c" + "enrmrkd-entity.h" ) echo "Fetching parser sources from github.com/${REPO} (branch: ${BRANCH})..." diff --git a/scripts/test-core-parser.sh b/scripts/test-core-parser.sh index 3974f365c..41672d0c2 100755 --- a/scripts/test-core-parser.sh +++ b/scripts/test-core-parser.sh @@ -44,16 +44,17 @@ trap 'rm -rf "$WORK"' EXIT echo "==> Building the vendored parser and the AST dumper" "$CC_BIN" -O1 -std=c99 -DENRMRKD_USE_UTF8=1 -c "$CPP_ROOT/enrmrkd/enrmrkd.c" -o "$WORK/enrmrkd.o" +"$CC_BIN" -O1 -std=c99 -c "$CPP_ROOT/enrmrkd/enrmrkd-entity.c" -o "$WORK/enrmrkd-entity.o" "$CXX_BIN" -O1 -std=c++17 -Wall -I "$CPP_ROOT/enrmrkd" -I "$CPP_ROOT/parser" -I "$CPP_ROOT/wasm" \ "$TESTS_DIR/ast_dump.cpp" \ "$CPP_ROOT/parser/MD4CParser.cpp" \ "$CPP_ROOT/wasm/ASTSerializer.cpp" \ - "$WORK/enrmrkd.o" -o "$WORK/ast-dump" + "$WORK/enrmrkd.o" "$WORK/enrmrkd-entity.o" -o "$WORK/ast-dump" echo "==> Checking the vendored parser's exported symbols" if command -v nm >/dev/null 2>&1; then # Some platforms (e.g. MacOS) prefix C symbols with an underscore. - unexpected=$(nm -g --defined-only "$WORK/enrmrkd.o" \ + unexpected=$(nm -g --defined-only "$WORK/enrmrkd.o" "$WORK/enrmrkd-entity.o" \ | awk 'NF >= 3 { print $3 }' | grep -vE '^_?enrmrkd_' | sort -u || true) if [ -n "$unexpected" ]; then echo "FAIL: the vendored parser defines globals without the enrmrkd_ prefix:" >&2 @@ -64,7 +65,7 @@ if command -v nm >/dev/null 2>&1; then echo "repo's scripts/rename-upstream-symbols.pl and re-sync." >&2 exit 1 fi - nm -g --defined-only "$WORK/enrmrkd.o" | awk 'NF >= 3 { print " " $3 }' | sort -u + nm -g --defined-only "$WORK/enrmrkd.o" "$WORK/enrmrkd-entity.o" | awk 'NF >= 3 { print " " $3 }' | sort -u else echo " nm not available, skipped" fi @@ -96,7 +97,9 @@ echo "==> Linking beside another embedded MD4C copy (mity/md4c $UPSTREAM_MD4C_RE mkdir -p "$WORK/other" base="https://raw.githubusercontent.com/mity/md4c/$UPSTREAM_MD4C_REF/src" if ! curl -fsSL --retry 2 "$base/md4c.c" -o "$WORK/other/md4c.c" \ - || ! curl -fsSL --retry 2 "$base/md4c.h" -o "$WORK/other/md4c.h"; then + || ! curl -fsSL --retry 2 "$base/md4c.h" -o "$WORK/other/md4c.h" \ + || ! curl -fsSL --retry 2 "$base/entity.c" -o "$WORK/other/entity.c" \ + || ! curl -fsSL --retry 2 "$base/entity.h" -o "$WORK/other/entity.h"; then if [ "${ENRM_SKIP_COEXISTENCE_CHECK:-0}" = "1" ] && [ -z "${CI:-}" ]; then echo " could not fetch upstream MD4C; skipped by ENRM_SKIP_COEXISTENCE_CHECK" echo @@ -153,10 +156,13 @@ int main() { } EOF "$CC_BIN" -O1 -std=c99 -c "$WORK/other/md4c.c" -o "$WORK/other.o" +# md4c-html's entity table, which the other copy may ship beside its parser. +"$CC_BIN" -O1 -std=c99 -c "$WORK/other/entity.c" -o "$WORK/other-entity.o" "$CXX_BIN" -O1 -std=c++17 -I "$CPP_ROOT/enrmrkd" -I "$CPP_ROOT/parser" -I "$WORK" \ -DENRMRKD_USE_UTF8=1 -c "$WORK/coexist.cpp" -o "$WORK/coexist.o" "$CXX_BIN" -O1 -std=c++17 -I "$CPP_ROOT/enrmrkd" -I "$CPP_ROOT/parser" -c "$CPP_ROOT/parser/MD4CParser.cpp" -o "$WORK/parser.o" -"$CXX_BIN" "$WORK/other.o" "$WORK/enrmrkd.o" "$WORK/parser.o" "$WORK/coexist.o" -o "$WORK/coexist" +"$CXX_BIN" "$WORK/other.o" "$WORK/other-entity.o" "$WORK/enrmrkd.o" "$WORK/enrmrkd-entity.o" \ + "$WORK/parser.o" "$WORK/coexist.o" -o "$WORK/coexist" "$WORK/coexist" echo " both parsers linked and ran in one binary" From 2547e709d759eda2ee3a5c6d9d37b51f8fa51321 Mon Sep 17 00:00:00 2001 From: Ernest Szlamczyk <127619251+eszlamczyk@users.noreply.github.com> Date: Fri, 16 Oct 2026 23:27:08 +0200 Subject: [PATCH 06/11] feat: add a per-block line wrap toggle to code block headers (#1021) * feat: add a per-block line wrap toggle to code block headers Adds an opt-in `enableCodeBlockWrapToggle` prop to the React Native package. Each top-level fenced code block gets a wrap button next to copy; tapping it wraps that block's lines at the block width, and tapping again returns to horizontal scrolling. Wrap state is a set of document-order indexes of top-level code blocks, fed to the view-free measure pass (part of the iOS measurement cache key and the Android measure hash). It resets when anything before the previous document's last line changes, so streaming and task toggles keep it. Labels come from `accessibilityLabels.codeBlock.wrap` / `.unwrap`. Closes #1009 Co-authored-by: Julius Marminge Co-Authored-By: Claude Opus 5.5 * fix(ios): write the checked state a task toggle produces into the markdown toggleTaskListItemAtIndex wrote `[ ]` for checked and `[x]` for unchecked, the inverse of Android, since #92. The checkbox looked right because the attributed string is patched separately, but the cached markdown recorded the opposite state, so anything reading it after a tap saw a stale checkbox and a prop echo of the toggled document never matched the local render. Co-Authored-By: Claude Fable 5.1 * fix: keep wrap state across task toggles and stroke the Android wrap icon iOS reset the wrapped set when the markdown prop changed before its last line, which a task-toggle echo always does. The reset now skips a prop that equals the markdown already rendered locally, so the reader's choice stands. Android drew the wrap glyph through androidx.core.graphics.PathParser, a RestrictTo API, as a filled shape. WrapGlyph strokes the same Material outline with the copy glyph's paint, so the two header buttons match. Docs note that macOS accepts the prop without a toggle. Comments restating adjacent code are trimmed. CodeBlockContainerViewTest moves to a follow-up PR that adds native coverage on both platforms. Co-Authored-By: Claude Fable 5.1 * fix: update the logic acording to latest review * fix: apply inline cr --------- Co-authored-by: Abdullah1738 Co-authored-by: Julius Marminge Co-authored-by: Claude Opus 5.5 Co-authored-by: Gregory Moskaliuk --- .../android/app/src/main/AndroidManifest.xml | 2 +- docs-md/ACCESSIBILITY.md | 2 + docs-md/API_REFERENCE.md | 12 + .../api-reference/enriched-markdown-text.md | 11 + docs/docs/user-experience/accessibility.md | 4 +- .../ios/ENRMCodeBlockWrapStateTests.mm | 36 +++ .../enriched/markdown/CodeBlockWrapState.kt | 108 ++++++++ .../enriched/markdown/EnrichedMarkdown.kt | 31 ++- .../markdown/EnrichedMarkdownManager.kt | 11 +- .../enriched/markdown/MeasurementStore.kt | 29 ++- .../accessibility/AccessibilityLabels.kt | 2 + .../segments/BlockquoteContainerView.kt | 6 +- .../segments/CodeBlockContainerView.kt | 159 ++++++++++-- .../markdown/segments/ContainerNodeView.kt | 12 + .../segments/SegmentHeightMeasurer.kt | 24 +- .../markdown/segments/SegmentViewCreators.kt | 1 + .../utils/common/MarkdownViewManagerUtils.kt | 3 + .../enriched/markdown/views/WrapGlyph.kt | 40 +++ .../EnrichedMarkdownTextSpec/conversions.h | 2 + .../markdown/CodeBlockWrapStateTest.kt | 31 +++ .../ios/EnrichedMarkdown.h | 6 + .../ios/EnrichedMarkdown.mm | 43 ++++ .../ios/EnrichedMarkdownText.mm | 4 + .../ios/internals/ENRMViewFreeMeasurement.h | 20 +- .../internals/EnrichedMarkdownShadowNode.mm | 28 ++- .../ios/internals/MeasurementCache.h | 17 +- .../ios/internals/ShadowMeasurementUtils.h | 11 +- .../segments/ENRMBlockquoteContainerView.h | 9 +- .../segments/ENRMBlockquoteContainerView.mm | 6 +- .../ios/segments/ENRMCodeBlockContainerView.h | 24 ++ .../ios/segments/ENRMCodeBlockContainerView.m | 231 ++++++++++++++++-- .../ios/segments/ENRMContainerNodeView.h | 3 + .../ios/segments/ENRMContainerNodeView.mm | 5 + .../ios/segments/ENRMSegmentHeightMeasurer.h | 8 +- .../ios/segments/ENRMSegmentHeightMeasurer.mm | 14 +- .../ios/utils/ENRMAccessibilityLabels.h | 4 + .../ios/utils/ENRMCodeBlockWrapState.h | 91 +++++++ .../ios/utils/ENRMCodeBlockWrapState.mm | 124 ++++++++++ .../ios/utils/TaskListTapUtils.m | 2 +- .../src/EnrichedMarkdownNativeComponent.ts | 11 + .../EnrichedMarkdownTextNativeComponent.ts | 5 + .../src/accessibilityLabelDefaults.ts | 11 + .../src/native/EnrichedMarkdownText.tsx | 8 +- .../src/types/AccessibilityLabels.ts | 21 ++ .../src/types/MarkdownTextProps.ts | 13 + .../src/web/nativeProps.ts | 1 + 46 files changed, 1168 insertions(+), 78 deletions(-) create mode 100644 packages/react-native-enriched-markdown/__tests__/ios/ENRMCodeBlockWrapStateTests.mm create mode 100644 packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/CodeBlockWrapState.kt create mode 100644 packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/views/WrapGlyph.kt create mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/CodeBlockWrapStateTest.kt create mode 100644 packages/react-native-enriched-markdown/ios/utils/ENRMCodeBlockWrapState.h create mode 100644 packages/react-native-enriched-markdown/ios/utils/ENRMCodeBlockWrapState.mm diff --git a/apps/react-native-example/android/app/src/main/AndroidManifest.xml b/apps/react-native-example/android/app/src/main/AndroidManifest.xml index fb78f3974..be948b0f3 100644 --- a/apps/react-native-example/android/app/src/main/AndroidManifest.xml +++ b/apps/react-native-example/android/app/src/main/AndroidManifest.xml @@ -14,7 +14,7 @@ diff --git a/docs-md/ACCESSIBILITY.md b/docs-md/ACCESSIBILITY.md index 3591c49a0..542505221 100644 --- a/docs-md/ACCESSIBILITY.md +++ b/docs-md/ACCESSIBILITY.md @@ -55,6 +55,8 @@ Every field is optional. Any field you omit falls back to the English default be | `blockquote.nestedQuote` | `"Nested blockquote"` | iOS + Android | | `table.row` | `"Row {n}: {content}"` | iOS + Android | | `math.equation` | `"Math: {latex}"` | iOS + Android | +| `codeBlock.wrap` | `"Wrap lines"` | iOS + Android | +| `codeBlock.unwrap` | `"Disable line wrap"` | iOS + Android | | `rotor.headings` | `"Headings"` | iOS only | | `rotor.links` | `"Links"` | iOS only | | `rotor.images` | `"Images"` | iOS only | diff --git a/docs-md/API_REFERENCE.md b/docs-md/API_REFERENCE.md index e58e4c40b..2550ce710 100644 --- a/docs-md/API_REFERENCE.md +++ b/docs-md/API_REFERENCE.md @@ -237,6 +237,14 @@ Works in both flavors: `flavor="github"` fires on the container-based code block /> ``` +### `enableCodeBlockWrapToggle` + +Shows a line wrap toggle next to the copy button in each fenced code block header (`flavor="github"`); set it to `false` to hide the toggle. Blocks start unwrapped and scroll horizontally; tapping the toggle wraps that block's lines at the block width, and tapping again goes back to scrolling. The state belongs to the block's position in the document: it survives streaming appends and resets when the markdown is replaced rather than appended to. The toggle's spoken labels come from [`accessibilityLabels.codeBlock`](#accessibilitylabels). macOS accepts the prop but shows no toggle. + +| Type | Default Value | Platform | +| --------- | ------------- | ------------ | +| `boolean` | `true` | iOS, Android | + ### `enableBlockContextMenu` Controls the long-press copy popup on code blocks, tables, block math, and blockquotes/admonitions. @@ -737,6 +745,10 @@ interface AccessibilityLabels { math?: { equation?: string; // "Math: {latex}" }; + codeBlock?: { // enableCodeBlockWrapToggle + wrap?: string; // "Wrap lines" + unwrap?: string; // "Disable line wrap" + }; rotor?: { // iOS only headings?: string; // "Headings" links?: string; // "Links" diff --git a/docs/docs/react-native/api-reference/enriched-markdown-text.md b/docs/docs/react-native/api-reference/enriched-markdown-text.md index 0a84cc9df..957b69283 100644 --- a/docs/docs/react-native/api-reference/enriched-markdown-text.md +++ b/docs/docs/react-native/api-reference/enriched-markdown-text.md @@ -217,6 +217,12 @@ Controls the long-press context menu on block views - fenced code blocks, tables iOS, Android, and macOS only - the block context menu is a native interaction, and the web build renders blocks without one.} /> +### `enableCodeBlockWrapToggle` + +Shows a line wrap toggle next to the copy button in each fenced code block header; set it to `false` to hide the toggle. Blocks start unwrapped and scroll horizontally; tapping the toggle wraps that block's lines at the block width, and tapping again goes back to scrolling. The state belongs to the block's position in the document: it survives streaming appends and resets when the Markdown is replaced rather than appended to. Needs [`flavor="github"`](#flavor); the toggle's spoken labels come from [`accessibilityLabels.codeBlock`](#accessibilitylabels). iOS and Android only; macOS accepts the prop but shows no toggle. + + + ### `enableLinkPreview` {#enablelinkpreview} Controls the native link preview on long press. It is on by default, and supplying [`onLinkLongPress`](#onlinklongpress) turns it off - your handler owns the long press instead. That override cannot be undone from this prop: with `onLinkLongPress` set, even an explicit `enableLinkPreview={true}` is discarded. Setting [`selectable={false}`](#selectable) also suppresses the preview. @@ -491,6 +497,11 @@ interface AccessibilityLabels { math?: { equation?: string; // {latex} is the equation source }; + codeBlock?: { + // the enableCodeBlockWrapToggle header button + wrap?: string; + unwrap?: string; + }; rotor?: { // iOS only, Android has no rotor headings?: string; diff --git a/docs/docs/user-experience/accessibility.md b/docs/docs/user-experience/accessibility.md index aa8e4db92..3218744be 100644 --- a/docs/docs/user-experience/accessibility.md +++ b/docs/docs/user-experience/accessibility.md @@ -61,6 +61,8 @@ packages ship. */} | `blockquote.nestedQuote` | `"Nested blockquote"` | iOS + Android | | `table.row` | `"Row {n}: {content}"` | iOS + Android | | `math.equation` | `"Math: {latex}"` | iOS + Android | +| `codeBlock.wrap` | `"Wrap lines"` | iOS + Android | +| `codeBlock.unwrap` | `"Disable line wrap"` | iOS + Android | | `rotor.headings` / `rotor.links` / `rotor.images` | `"Headings"` / `"Links"` / `"Images"` | iOS only | Placeholders: `{n}` (1-based index), `{content}` (comma-joined cell texts), `{latex}` (equation source). Preserve placeholder names exactly in translations. Defaults use the no-plural cardinal form so a single template works in every language. @@ -117,7 +119,7 @@ Four sharp edges are worth knowing: - **Android** has no rotor concept, so `accessibilityLabels.rotor.*` is ignored there. - **Task list items** have no accessibility handling in the React Native package on either platform: a checkbox is read as plain list text, with no checked state announced and no toggle action exposed. There is no label key for it. - **Admonitions** carry no accessibility role; they are announced as the blockquote they are built from. -- **Code blocks** are covered only partially - under `flavor="github"` the header copy button carries the resolved copy label, and iOS vends a VoiceOver copy action, but the block itself has no dedicated role. +- **Code blocks** are covered only partially - under `flavor="github"` the header copy button carries the resolved copy label and the optional wrap toggle (`enableCodeBlockWrapToggle`) speaks `codeBlock.wrap` / `codeBlock.unwrap`, while iOS vends both as VoiceOver actions, but the block itself has no dedicated role. - The platform tabs above describe the renderer. The **editor** speaks neither heading level nor task state (see [Editor accessibility](#editor-accessibility)). ## Reference diff --git a/packages/react-native-enriched-markdown/__tests__/ios/ENRMCodeBlockWrapStateTests.mm b/packages/react-native-enriched-markdown/__tests__/ios/ENRMCodeBlockWrapStateTests.mm new file mode 100644 index 000000000..dab614426 --- /dev/null +++ b/packages/react-native-enriched-markdown/__tests__/ios/ENRMCodeBlockWrapStateTests.mm @@ -0,0 +1,36 @@ +#import "../../ios/utils/ENRMCodeBlockWrapState.h" +#import + +@interface ENRMCodeBlockWrapStateTests : XCTestCase +@end + +@implementation ENRMCodeBlockWrapStateTests + +- (void)testKeepsStateWhileTheDocumentGrows +{ + XCTAssertTrue(ENRMKeepsCodeBlockWrapState("a\nb", "a\nb\nc")); + // The unfinished last line may be rewritten. + XCTAssertTrue(ENRMKeepsCodeBlockWrapState("a\n\nc")); + // A single-line document has no stable prefix yet. + XCTAssertTrue(ENRMKeepsCodeBlockWrapState("abc", "xyz")); +} + +- (void)testResetsWhenAnEarlierLineChanges +{ + XCTAssertFalse(ENRMKeepsCodeBlockWrapState("a\nb\nc", "x\nb\nc")); + XCTAssertFalse(ENRMKeepsCodeBlockWrapState("a\nb\nc", "a\nx\nc")); + // Shorter than the stable prefix. + XCTAssertFalse(ENRMKeepsCodeBlockWrapState("a\nb\nc", "a\n")); +} + +- (void)testCursorCountsInVisitOrder +{ + ENRMCodeBlockWrapCursor *cursor = [[ENRMCodeBlockWrapCursor alloc] initWithWrapped:[NSSet setWithArray:@[ @1, @3 ]]]; + XCTAssertFalse([cursor nextIsWrapped]); + XCTAssertTrue([cursor nextIsWrapped]); + XCTAssertFalse([cursor nextIsWrapped]); + XCTAssertTrue([cursor nextIsWrapped]); + XCTAssertFalse([cursor nextIsWrapped]); +} + +@end diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/CodeBlockWrapState.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/CodeBlockWrapState.kt new file mode 100644 index 000000000..6246f87a1 --- /dev/null +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/CodeBlockWrapState.kt @@ -0,0 +1,108 @@ +package com.swmansion.enriched.markdown + +import com.swmansion.enriched.markdown.segments.CodeBlockContainerView + +// Code block wrap state is keyed by block position, so it only stays meaningful +// while the document grows in place. Streaming may rewrite its unfinished last +// line (an HTML tag closing, a link relabeled); anything earlier changing - a +// recycled cell, an edited message, a block inserted above - starts unwrapped. +// Compares in place: this runs on every streamed chunk while a block is wrapped. +internal fun keepsCodeBlockWrapState( + previous: String, + next: String, +): Boolean { + val cut = previous.lastIndexOf('\n') + return cut < 0 || next.regionMatches(0, previous, 0, cut) +} + +/** + * Which code blocks of one EnrichedMarkdown the user wrapped with the header + * toggle, and the only writer of that choice. + * + * Blocks are identified by document-order index, counted pre-order across + * nesting (a block inside a blockquote takes the next index, like a top-level + * one); [CodeBlockWrapCursor] counts the same way in the view-free measure + * pass. The set lives here rather than on the views, which are rebuilt on + * style and font-scale changes, and is mirrored into MeasurementStore under the + * view tag for that measure pass. + */ +internal class CodeBlockWrapState( + private val viewTag: () -> Int, + private val codeBlockViews: () -> Sequence, + private val onHeightChanged: () -> Unit, +) { + // Matches the prop's default, for a host that never receives the prop. + var enabled: Boolean = true + private set + + var indices: Set = emptySet() + private set + + // The markdown prop as last received, which local task toggles don't touch. + private var lastMarkdownProp: String = "" + + /** Returns whether the wrapped set was cleared, so the height must be recomputed. */ + fun setEnabled(value: Boolean): Boolean { + if (enabled == value) return false + enabled = value + val cleared = !value && indices.isNotEmpty() + if (cleared) write(emptySet()) + sync() + return cleared + } + + /** + * Applies the reset rule to a new markdown prop; [rendered] is the document on + * screen, which includes local task toggles. The prop is compared with the + * previous prop, so an app that ignores a checkbox tap and keeps streaming its + * own copy keeps the wrapped blocks; a prop equal to what's rendered is the app + * echoing a task toggle back and keeps them too. Returns whether the wrapped + * set was cleared. + */ + fun onMarkdownProp( + next: String, + rendered: String, + ): Boolean { + val previous = lastMarkdownProp + lastMarkdownProp = next + if (indices.isEmpty() || next == rendered || keepsCodeBlockWrapState(previous, next)) return false + write(emptySet()) + return true + } + + /** Pushes the wrapped set and the toggle onto the current code block views. */ + fun sync() { + codeBlockViews().forEachIndexed { index, view -> + view.onWrapToggle = ::toggle + view.showsWrapButton = enabled + view.wrapped = enabled && index in indices + } + } + + private fun toggle(view: CodeBlockContainerView) { + if (!enabled) return + val index = codeBlockViews().indexOf(view) + if (index < 0) return + write(if (index in indices) indices - index else indices + index) + sync() + onHeightChanged() + } + + private fun write(value: Set) { + indices = value + MeasurementStore.updateWrappedCodeBlocks(viewTag(), value) + } +} + +/** + * Hands out the wrapped flag of each code block in the order a view-free measure + * pass reaches them: pre-order, descending into blockquotes, the same order + * [CodeBlockWrapState] indexes the views in. + */ +class CodeBlockWrapCursor( + private val wrapped: Set, +) { + private var nextIndex = 0 + + fun nextIsWrapped(): Boolean = nextIndex++ in wrapped +} diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt index c12937c50..c7d04b9fd 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt @@ -50,6 +50,10 @@ class EnrichedMarkdown( private enum class DirtyFlag { RECREATE_SEGMENTS, FORCE_HEIGHT, + + // Yoga already measured with inputs that changed after (the wrapped code + // blocks a prop reset cleared), so it has to be asked to measure again. + REMEASURE, } private val parser = Parser.shared @@ -141,11 +145,30 @@ class EnrichedMarkdown( dynamicProps.enableCodeBlockPress = value } + private val codeBlockWrapState = + CodeBlockWrapState(viewTag = { id }, codeBlockViews = ::codeBlockViews, onHeightChanged = ::onImageLayoutChanged) + + var enableCodeBlockWrapToggle: Boolean + get() = codeBlockWrapState.enabled + set(value) { + if (codeBlockWrapState.setEnabled(value)) onImageLayoutChanged() + } + init { segmentViewFactory = RootFactory() } - fun setMarkdownContent(markdown: String) { + // isTaskToggle marks a checkbox flip rendered locally ahead of the prop; it + // moves no code block, so it skips the wrap state's reset rule. + fun setMarkdownContent( + markdown: String, + isTaskToggle: Boolean = false, + ) { + // The shadow node measures the new markdown before this setter runs, still + // with the old wrapped set, so a reset needs Yoga to measure again. + if (!isTaskToggle && codeBlockWrapState.onMarkdownProp(markdown, currentMarkdown)) { + dirtyFlags += DirtyFlag.REMEASURE + } if (currentMarkdown == markdown) return currentMarkdown = markdown renderPending = true @@ -360,6 +383,9 @@ class EnrichedMarkdown( segmentViews.filterIsInstance().forEach { it.accessibilityLabels = labels } + codeBlockViews().forEach { + it.accessibilityLabels = labels + } mathContainerClass?.let { mathClass -> segmentViews.filter { mathClass.isInstance(it) }.forEach { view -> runCatching { @@ -458,6 +484,7 @@ class EnrichedMarkdown( val reset = DirtyFlag.RECREATE_SEGMENTS in dirtyFlags val forceHeight = DirtyFlag.FORCE_HEIGHT in dirtyFlags + val remeasure = DirtyFlag.REMEASURE in dirtyFlags dirtyFlags.clear() val topologyChanged = applySegments(renderedSegments, reset) @@ -469,6 +496,7 @@ class EnrichedMarkdown( view.pending = pendingCodeBlockSegment != null && index == segmentViews.size - 1 } } + codeBlockWrapState.sync() if (width > 0) { val heightBefore = computeSegmentsTotalHeight() @@ -480,6 +508,7 @@ class EnrichedMarkdown( requestLayout() } } + if (remeasure) onImageLayoutChanged() } private fun isMathContainerView(view: View): Boolean = mathContainerClass?.isInstance(view) == true diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt index 5dd58285c..5dc9ce78c 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt @@ -61,7 +61,8 @@ class EnrichedMarkdownManager : view.setOnTaskListItemPressCallback { taskIndex, checked, itemText -> val newChecked = !checked val updatedMarkdown = TaskListToggleUtils.toggleAtIndex(view.currentMarkdown, taskIndex, newChecked) - view.setMarkdownContent(updatedMarkdown) + // A checkbox flip keeps every code block where it was, so keep their wrap state too. + view.setMarkdownContent(updatedMarkdown, isTaskToggle = true) view.commitProps() emitTaskListItemPress(view, taskIndex, newChecked, itemText) } @@ -244,6 +245,14 @@ class EnrichedMarkdownManager : view?.enableCodeBlockPress = enableCodeBlockPress } + @ReactProp(name = "enableCodeBlockWrapToggle", defaultBoolean = true) + override fun setEnableCodeBlockWrapToggle( + view: EnrichedMarkdown?, + enableCodeBlockWrapToggle: Boolean, + ) { + view?.enableCodeBlockWrapToggle = enableCodeBlockWrapToggle + } + @ReactProp(name = "lineBreakStrategyIOS") override fun setLineBreakStrategyIOS( view: EnrichedMarkdown?, diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt index f4840e420..9dfb3bbde 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt @@ -89,6 +89,9 @@ object MeasurementStore { private val streamingCodeBlockModes = ConcurrentHashMap() + // Code blocks the user wrapped, by document-order index across nesting (see CodeBlockWrapState). + private val wrappedCodeBlocks = ConcurrentHashMap>() + private fun resolveFontScalingSettings( viewId: Int?, props: ReadableMap?, @@ -141,6 +144,15 @@ object MeasurementStore { data.remove(id) numberOfLinesByViewId.remove(id) ellipsizeModeByViewId.remove(id) + wrappedCodeBlocks.remove(id) + } + + fun updateWrappedCodeBlocks( + viewId: Int, + indices: Set, + ) { + if (indices.isEmpty()) wrappedCodeBlocks.remove(viewId) else wrappedCodeBlocks[viewId] = indices + data.remove(viewId) } fun invalidate(id: Int) { @@ -477,7 +489,16 @@ object MeasurementStore { } else { rawMarkdown } - val propsHash = computePropsHashForMarkdown(markdown, props, allowFontScaling, fontScale, maxFontSizeMultiplier) + val wrapped = + if (props.getBooleanOrDefault("enableCodeBlockWrapToggle", true)) { + id?.let { wrappedCodeBlocks[it] } ?: emptySet() + } else { + emptySet() + } + // A Set's hashCode sums its elements, so {} and {0} would collide; the sorted list's doesn't. + val propsHash = + 31 * computePropsHashForMarkdown(markdown, props, allowFontScaling, fontScale, maxFontSizeMultiplier) + + wrapped.sorted().hashCode() // Streaming shortcut: reuse cached size when the filtered content and // width are unchanged. When the filter output changes (e.g. a table @@ -554,6 +575,7 @@ object MeasurementStore { val lastIndex = renderedSegments.lastIndex var totalHeightPx = 0f var maxContentWidthPx = 0f + val wrapCursor = CodeBlockWrapCursor(wrapped) for ((index, segment) in renderedSegments.withIndex()) { val isLastSegment = index == lastIndex @@ -594,7 +616,8 @@ object MeasurementStore { is RenderedSegment.CodeBlock -> { totalHeightPx += style.codeBlockStyle.marginTop - totalHeightPx += CodeBlockContainerView.measureCodeBlockNodeHeight(segment.node, style, context, width) + totalHeightPx += + CodeBlockContainerView.measureCodeBlockNodeHeight(segment.node, style, context, width, wrapCursor.nextIsWrapped()) maxContentWidthPx = width if (includeBottomMargin) { totalHeightPx += style.codeBlockStyle.marginBottom @@ -603,7 +626,7 @@ object MeasurementStore { is RenderedSegment.Blockquote -> { totalHeightPx += style.blockquoteStyle.marginTop - totalHeightPx += BlockquoteContainerView.measureBlockquoteNodeHeight(segment.node, style, context, width) + totalHeightPx += BlockquoteContainerView.measureBlockquoteNodeHeight(segment.node, style, context, width, wrapCursor) maxContentWidthPx = width if (includeBottomMargin) { totalHeightPx += style.blockquoteStyle.marginBottom diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt index 9091d349a..fba8adeed 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt @@ -9,6 +9,8 @@ data class AccessibilityLabels( val nestedBlockquote: String = "", val tableRow: String = "", val mathEquation: String = "", + val codeBlockWrap: String = "", + val codeBlockUnwrap: String = "", val rotorHeadings: String = "", val rotorLinks: String = "", val rotorImages: String = "", diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/BlockquoteContainerView.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/BlockquoteContainerView.kt index 8027e6054..b56010ca7 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/BlockquoteContainerView.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/BlockquoteContainerView.kt @@ -13,6 +13,7 @@ import android.view.View import androidx.core.graphics.withSave import com.facebook.react.common.ReactConstants import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles +import com.swmansion.enriched.markdown.CodeBlockWrapCursor import com.swmansion.enriched.markdown.EnrichedMarkdownInternalText import com.swmansion.enriched.markdown.parser.MarkdownASTNode import com.swmansion.enriched.markdown.styles.BlockquoteStyle @@ -345,7 +346,8 @@ class BlockquoteContainerView( * The children are summed at the reduced inner width (outer minus horizontal * inset) and the vertical inset is added; nested quotes recurse through this * same function via SegmentHeightMeasurer. Math child heights use the shared - * estimate to avoid a main-thread measure from the layout pass. + * estimate to avoid a main-thread measure from the layout pass. Wrapped code + * blocks (wrapCursor) lay out at the inner width, as the views do. * * Potential win: this runs splitASTIntoSegments + render for measurement, and * applyBlockquoteNode runs them again for display, so each nesting level renders @@ -359,6 +361,7 @@ class BlockquoteContainerView( config: StyleConfig, context: Context, width: Float, + wrapCursor: CodeBlockWrapCursor? = null, ): Float { val style = config.blockquoteStyle val leftInset = ceil(style.borderWidth + style.gapWidth + style.padding).toInt() @@ -388,6 +391,7 @@ class BlockquoteContainerView( breakStrategy = breakStrategy, allowTrailingMargin = false, mathHeightForIndex = { estimateMathHeight(config) }, + wrapCursor = wrapCursor, ) return childrenHeight + verticalInset * 2f + headerReserved diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerView.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerView.kt index cba082576..604eac25c 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerView.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerView.kt @@ -25,6 +25,7 @@ import android.widget.HorizontalScrollView import android.widget.ImageView import androidx.appcompat.widget.AppCompatImageButton import androidx.appcompat.widget.AppCompatTextView +import com.swmansion.enriched.markdown.accessibility.AccessibilityLabels import com.swmansion.enriched.markdown.parser.MarkdownASTNode import com.swmansion.enriched.markdown.spans.LineHeightSpan import com.swmansion.enriched.markdown.styles.CodeBlockStyle @@ -35,6 +36,7 @@ import com.swmansion.enriched.markdown.utils.text.extensions.applyCodeBlockTextS import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE import com.swmansion.enriched.markdown.views.ContextMenuPopup import com.swmansion.enriched.markdown.views.CopyGlyph +import com.swmansion.enriched.markdown.views.WrapGlyph import kotlin.math.ceil import kotlin.math.roundToInt @@ -47,8 +49,9 @@ import kotlin.math.roundToInt * * measureCodeBlockNodeHeight must stay in sync with the view: it builds the * same styled text, paint, and header metrics, so the height reported to - * Yoga matches the laid-out height. Since lines never wrap, the height is - * independent of the available width. + * Yoga matches the laid-out height. Unless the block is wrapped (the optional + * header wrap toggle), lines never wrap and the height is independent of the + * available width. */ class CodeBlockContainerView( context: Context, @@ -69,9 +72,18 @@ class CodeBlockContainerView( // created later see the same current values. See DynamicBlockProps. var dynamicProps: DynamicBlockProps = DynamicBlockProps() + // Wrap toggle labels (see AccessibilityLabels); the copy label lives on dynamicProps. + var accessibilityLabels: AccessibilityLabels = AccessibilityLabels() + set(value) { + if (field == value) return + field = value + updateWrapButtonAppearance() + } + private var code: String = "" private var language: String? = null private var fenceChar: String = "`" + private var appliedTextMaxWidth = Int.MAX_VALUE // True until the closing fence arrives: highlighting is deferred and copying // is disabled, while the header stays visible. @@ -85,6 +97,29 @@ class CodeBlockContainerView( rebuildCodeText() } + // Header wrap toggle next to copy; CodeBlockWrapState sets it from enableCodeBlockWrapToggle. + var showsWrapButton: Boolean = false + set(value) { + if (field == value) return + field = value + wrapButton.visibility = if (value) View.VISIBLE else View.GONE + requestLayout() + } + + // Wraps long lines at the block width instead of scrolling horizontally. Only + // CodeBlockWrapState writes it; the header toggle just asks through onWrapToggle. + var wrapped: Boolean = false + set(value) { + if (field == value) return + field = value + updateWrapButtonAppearance() + if (value) scrollView.scrollTo(0, 0) + requestLayout() + } + + // Fired when the header toggle is pressed; the host flips [wrapped] and re-measures. + var onWrapToggle: ((CodeBlockContainerView) -> Unit)? = null + private val textView = AppCompatTextView(context).apply { includeFontPadding = false @@ -142,6 +177,17 @@ class CodeBlockContainerView( setOnClickListener { copyCode() } } + private val wrapIcon = WrapIconDrawable(codeBlockStyle.color, ceil(codeBlockStyle.fontSize * HEADER_ICON_SCALE).toInt()) + + private val wrapButton = + AppCompatImageButton(context).apply { + background = null + scaleType = ImageView.ScaleType.CENTER + visibility = View.GONE + setImageDrawable(wrapIcon) + setOnClickListener { toggleWrap() } + } + private val dividerPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = dividerColor(codeBlockStyle.color) @@ -155,7 +201,7 @@ class CodeBlockContainerView( override fun onDown(e: MotionEvent): Boolean = true override fun onSingleTapUp(e: MotionEvent): Boolean { - if (isPointInsideCopyButton(e.x, e.y)) return false + if (isPointInsideHeaderButton(e.x, e.y)) return false handleCodeBlockPress() return false } @@ -177,6 +223,18 @@ class CodeBlockContainerView( addView(scrollView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)) addView(languageView, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)) addView(copyButton, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)) + addView(wrapButton, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)) + updateWrapButtonAppearance() + } + + private fun updateWrapButtonAppearance() { + // Full-strength tint marks the toggle as on; off matches the copy button. + wrapIcon.setColor(if (wrapped) codeBlockStyle.color else secondaryColor(codeBlockStyle.color)) + wrapButton.contentDescription = if (wrapped) accessibilityLabels.codeBlockUnwrap else accessibilityLabels.codeBlockWrap + } + + private fun toggleWrap() { + onWrapToggle?.invoke(this) } fun applyCodeBlockNode(node: MarkdownASTNode) { @@ -206,15 +264,22 @@ class CodeBlockContainerView( heightSpec: Int, ) { val measuredWidth = MeasureSpec.getSize(widthSpec) + val paneWidth = (measuredWidth - borderW * 2).coerceAtLeast(0) + // The scroll view measures its child unbounded; a max width makes the text wrap inside the pane. + val textMaxWidth = if (wrapped) paneWidth.coerceAtLeast(1) else Int.MAX_VALUE + if (textMaxWidth != appliedTextMaxWidth) { + appliedTextMaxWidth = textMaxWidth + textView.maxWidth = textMaxWidth + } scrollView.measure( - MeasureSpec.makeMeasureSpec((measuredWidth - borderW * 2).coerceAtLeast(0), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(paneWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), ) - copyButton.measure( - MeasureSpec.makeMeasureSpec(headerH, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(headerH, MeasureSpec.EXACTLY), - ) - val labelMaxWidth = (measuredWidth - inset * 2 - headerH).coerceAtLeast(0) + val buttonSpec = MeasureSpec.makeMeasureSpec(headerH, MeasureSpec.EXACTLY) + copyButton.measure(buttonSpec, buttonSpec) + wrapButton.measure(buttonSpec, buttonSpec) + val headerButtonsWidth = if (showsWrapButton) headerH * 2 else headerH + val labelMaxWidth = (measuredWidth - inset * 2 - headerButtonsWidth).coerceAtLeast(0) languageView.measure( MeasureSpec.makeMeasureSpec(labelMaxWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), @@ -250,6 +315,8 @@ class CodeBlockContainerView( buttonLeft + copyButton.measuredWidth, buttonTop + copyButton.measuredHeight, ) + val wrapLeft = (buttonLeft - wrapButton.measuredWidth).coerceAtLeast(0) + wrapButton.layout(wrapLeft, buttonTop, wrapLeft + wrapButton.measuredWidth, buttonTop + wrapButton.measuredHeight) scrollView.layout(borderW, headerH, width - borderW, bottom - top - borderW) } @@ -290,10 +357,16 @@ class CodeBlockContainerView( return super.dispatchTouchEvent(ev) } - private fun isPointInsideCopyButton( + private fun isPointInsideHeaderButton( + x: Float, + y: Float, + ): Boolean = isPointInside(copyButton, x, y) || (wrapButton.visibility == View.VISIBLE && isPointInside(wrapButton, x, y)) + + private fun isPointInside( + view: View, x: Float, y: Float, - ): Boolean = x >= copyButton.left && x < copyButton.right && y >= copyButton.top && y < copyButton.bottom + ): Boolean = x >= view.left && x < view.right && y >= view.top && y < view.bottom private fun copyFencedMarkdown() { if (code.isEmpty()) return @@ -340,6 +413,49 @@ class CodeBlockContainerView( override fun getOpacity() = PixelFormat.TRANSLUCENT } + // Material "wrap_text" glyph, stroked like the copy glyph at the same size. + private class WrapIconDrawable( + color: Int, + private val size: Int, + ) : Drawable() { + private val paint = + Paint(Paint.ANTI_ALIAS_FLAG).apply { + style = Paint.Style.STROKE + strokeWidth = size / 20f + strokeJoin = Paint.Join.ROUND + strokeCap = Paint.Cap.ROUND + this.color = color + } + private val glyph = WrapGlyph() + + fun setColor(color: Int) { + paint.color = color + invalidateSelf() + } + + override fun draw(canvas: Canvas) { + val saved = canvas.save() + canvas.translate(bounds.left.toFloat(), bounds.top.toFloat()) + glyph.draw(canvas, bounds.width().toFloat(), paint) + canvas.restoreToCount(saved) + } + + override fun getIntrinsicWidth() = size + + override fun getIntrinsicHeight() = size + + override fun setAlpha(alpha: Int) { + paint.alpha = alpha + } + + override fun setColorFilter(colorFilter: ColorFilter?) { + paint.colorFilter = colorFilter + } + + @Deprecated("Deprecated in Java") + override fun getOpacity() = PixelFormat.TRANSLUCENT + } + companion object { private const val HEADER_LABEL_SCALE = 0.85f @@ -389,14 +505,16 @@ class CodeBlockContainerView( } } - // Lines never wrap (the code pane scrolls horizontally), so the layout is - // built at the text's desired width and the result is independent of the - // available width. + // Unwrapped lines never wrap (the code pane scrolls horizontally), so the + // layout is built at the text's desired width and the result is independent + // of the available width. A wrapped block lays out at the pane's text width + // instead, the same width the view caps its text view at. fun measureCodeBlockNodeHeight( node: MarkdownASTNode, config: StyleConfig, context: Context, - @Suppress("unused") width: Float, + width: Float, + wrapped: Boolean = false, ): Float { val style = config.codeBlockStyle val inset = contentInset(style) @@ -404,7 +522,16 @@ class CodeBlockContainerView( val text = buildCodeText(CodeBlockNode.extractCode(node), style) if (text.isEmpty()) return headerH + inset * 2f val paint = createCodePaint(style, context) - val contentWidth = ceil(Layout.getDesiredWidth(text, paint)).toInt().coerceAtLeast(1) + val layoutWidth = + if (wrapped) { + val borderW = borderPx(style) + val horizontalPad = (inset - borderW).coerceAtLeast(0) + // Mirrors onMeasure: the text view is capped at the pane width (at least 1px), padding included. + (ceil(width).toInt() - borderW * 2).coerceAtLeast(1) - horizontalPad * 2 + } else { + ceil(Layout.getDesiredWidth(text, paint)).toInt() + } + val contentWidth = layoutWidth.coerceAtLeast(1) val layout = StaticLayout.Builder .obtain(text, 0, text.length, paint, contentWidth) diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/ContainerNodeView.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/ContainerNodeView.kt index 016d11dd3..61be99d9d 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/ContainerNodeView.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/ContainerNodeView.kt @@ -34,6 +34,18 @@ open class ContainerNodeView( protected var trailingMarginEnabled: Boolean = false + // Code block views in document order, descending into nested blockquotes: the + // order CodeBlockWrapState indexes them in. + internal fun codeBlockViews(): Sequence = + sequence { + segmentViews.forEach { view -> + when (view) { + is CodeBlockContainerView -> yield(view) + is ContainerNodeView -> yieldAll(view.codeBlockViews()) + } + } + } + /** * Reconciles the current child views against renderedSegments, attaching and * removing views as needed and updating segmentViews/segmentSignatures. diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentHeightMeasurer.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentHeightMeasurer.kt index 162ebfbff..a67c70708 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentHeightMeasurer.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentHeightMeasurer.kt @@ -6,6 +6,7 @@ import android.os.Build import android.text.Layout import android.text.StaticLayout import android.text.TextPaint +import com.swmansion.enriched.markdown.CodeBlockWrapCursor import com.swmansion.enriched.markdown.styles.StyleConfig import com.swmansion.enriched.markdown.utils.text.extensions.replaceMathSpansWithPlaceholders import com.swmansion.enriched.markdown.utils.text.span.prepareWidthAwareSpans @@ -20,7 +21,9 @@ import kotlin.math.ceil * Math heights must be measured up front on the main thread by the caller and * supplied through mathHeightForIndex, because the summation runs off the main * thread. Blockquote children recurse through - * BlockquoteContainerView.measureBlockquoteNodeHeight. + * BlockquoteContainerView.measureBlockquoteNodeHeight. wrapCursor, when given, + * says which code blocks the user wrapped; it is shared down the recursion so + * nested blocks keep counting in document order. */ object SegmentHeightMeasurer { fun measureSegmentsHeight( @@ -32,6 +35,7 @@ object SegmentHeightMeasurer { breakStrategy: Int, allowTrailingMargin: Boolean, mathHeightForIndex: (Int) -> Float, + wrapCursor: CodeBlockWrapCursor? = null, ): Float { val widthPx = ceil(contentWidthPx).toInt().coerceAtLeast(1) val lastIndex = segments.lastIndex @@ -69,7 +73,14 @@ object SegmentHeightMeasurer { is RenderedSegment.CodeBlock -> { totalHeightPx += style.codeBlockStyle.marginTop - totalHeightPx += CodeBlockContainerView.measureCodeBlockNodeHeight(segment.node, style, context, contentWidthPx) + totalHeightPx += + CodeBlockContainerView.measureCodeBlockNodeHeight( + segment.node, + style, + context, + contentWidthPx, + wrapCursor?.nextIsWrapped() ?: false, + ) if (includeBottomMargin) { totalHeightPx += style.codeBlockStyle.marginBottom } @@ -79,7 +90,14 @@ object SegmentHeightMeasurer { // A quote encountered here is always nested inside another quote, so it // carries no vertical margin (only the outermost quote does, added by // MeasurementStore); this mirrors BlockquoteContainerView.nested. - totalHeightPx += BlockquoteContainerView.measureBlockquoteNodeHeight(segment.node, style, context, contentWidthPx) + totalHeightPx += + BlockquoteContainerView.measureBlockquoteNodeHeight( + segment.node, + style, + context, + contentWidthPx, + wrapCursor, + ) } is RenderedSegment.Video -> { diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentViewCreators.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentViewCreators.kt index c9644d15d..a0c4c512e 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentViewCreators.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentViewCreators.kt @@ -145,6 +145,7 @@ object SegmentViewCreators { config: SegmentViewConfig, ) = CodeBlockContainerView(config.context, config.style).apply { dynamicProps = config.dynamicProps + accessibilityLabels = config.accessibilityLabels applyCodeBlockNode(segment.node) } diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt index b4d3cdc5f..40ef07bff 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt @@ -181,6 +181,7 @@ fun parseAccessibilityLabels(value: ReadableMap?): AccessibilityLabels { val blockquote = value.getMap("blockquote") val table = value.getMap("table") val math = value.getMap("math") + val codeBlock = value.getMap("codeBlock") val rotor = value.getMap("rotor") return AccessibilityLabels( bulletPoint = list?.getString("bulletPoint") ?: "", @@ -191,6 +192,8 @@ fun parseAccessibilityLabels(value: ReadableMap?): AccessibilityLabels { nestedBlockquote = blockquote?.getString("nestedQuote") ?: "", tableRow = table?.getString("row") ?: "", mathEquation = math?.getString("equation") ?: "", + codeBlockWrap = codeBlock?.getString("wrap") ?: "", + codeBlockUnwrap = codeBlock?.getString("unwrap") ?: "", rotorHeadings = rotor?.getString("headings") ?: "", rotorLinks = rotor?.getString("links") ?: "", rotorImages = rotor?.getString("images") ?: "", diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/views/WrapGlyph.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/views/WrapGlyph.kt new file mode 100644 index 000000000..0318a68ef --- /dev/null +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/views/WrapGlyph.kt @@ -0,0 +1,40 @@ +package com.swmansion.enriched.markdown.views + +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Path +import android.graphics.RectF + +/** + * Material "wrap_text" glyph as strokes on a 24-unit grid, drawn with the same + * paint as [CopyGlyph] so the two header buttons match in weight. + */ +internal class WrapGlyph { + private val lines = Path() + private val arrow = Path() + private val loop = RectF() + + fun draw( + canvas: Canvas, + width: Float, + stroke: Paint, + ) { + val u = width / 24f + lines.rewind() + lines.moveTo(4 * u, 6 * u) + lines.lineTo(20 * u, 6 * u) + lines.moveTo(4 * u, 18 * u) + lines.lineTo(10 * u, 18 * u) + lines.moveTo(4 * u, 12 * u) + lines.lineTo(17 * u, 12 * u) + loop.set(15 * u, 12 * u, 19 * u, 16 * u) + lines.arcTo(loop, -90f, 180f) + lines.lineTo(13 * u, 16 * u) + arrow.rewind() + arrow.moveTo(15 * u, 14 * u) + arrow.lineTo(13 * u, 16 * u) + arrow.lineTo(15 * u, 18 * u) + canvas.drawPath(lines, stroke) + canvas.drawPath(arrow, stroke) + } +} diff --git a/packages/react-native-enriched-markdown/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h b/packages/react-native-enriched-markdown/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h index d4961d13c..8e613e58f 100644 --- a/packages/react-native-enriched-markdown/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +++ b/packages/react-native-enriched-markdown/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h @@ -47,6 +47,8 @@ inline folly::dynamic toDynamic(const EnrichedMarkdownProps &props) { serializedProps["maxFontSizeMultiplier"] = props.maxFontSizeMultiplier; serializedProps["allowTrailingMargin"] = props.allowTrailingMargin; serializedProps["streamingAnimation"] = props.streamingAnimation; + // Wrapped code blocks measure at the block width; the indexes live in MeasurementStore. + serializedProps["enableCodeBlockWrapToggle"] = props.enableCodeBlockWrapToggle; folly::dynamic imageRequestHeaders = folly::dynamic::array(); for (const auto &header : props.imageRequestHeaders) { diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/CodeBlockWrapStateTest.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/CodeBlockWrapStateTest.kt new file mode 100644 index 000000000..00a04edb4 --- /dev/null +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/CodeBlockWrapStateTest.kt @@ -0,0 +1,31 @@ +package com.swmansion.enriched.markdown + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test + +class CodeBlockWrapStateTest { + @Test + fun keepsStateWhileTheDocumentGrows() { + assertTrue(keepsCodeBlockWrapState("a\nb", "a\nb\nc")) + // The unfinished last line may be rewritten. + assertTrue(keepsCodeBlockWrapState("a\n\nc")) + // A single-line document has no stable prefix yet. + assertTrue(keepsCodeBlockWrapState("abc", "xyz")) + } + + @Test + fun resetsWhenAnEarlierLineChanges() { + assertFalse(keepsCodeBlockWrapState("a\nb\nc", "x\nb\nc")) + assertFalse(keepsCodeBlockWrapState("a\nb\nc", "a\nx\nc")) + // Shorter than the stable prefix. + assertFalse(keepsCodeBlockWrapState("a\nb\nc", "a\n")) + } + + @Test + fun cursorCountsInVisitOrder() { + val cursor = CodeBlockWrapCursor(setOf(1, 3)) + assertEquals(listOf(false, true, false, true, false), List(5) { cursor.nextIsWrapped() }) + } +} diff --git a/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.h b/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.h index 99ea444f3..1d4df073d 100644 --- a/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.h +++ b/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.h @@ -20,6 +20,12 @@ NS_ASSUME_NONNULL_BEGIN /// Backed by a single lock-free atomic, so the pair can't tear. Returns /// CGSizeZero until the first layout is committed. - (CGSize)lastCommittedLayoutSize; + +/// Document-order indexes, counted across nesting, of the code blocks the user +/// wrapped with the header toggle (see ENRMCodeBlockWrapState). Written on main, +/// read by the shadow-node measure pass on any thread (atomic copy), so the +/// measured height follows the wrapped blocks. +@property (nonatomic, copy, readonly) NSSet *wrappedCodeBlockIndices; @end NS_ASSUME_NONNULL_END diff --git a/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.mm b/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.mm index 5a0b7e3e6..3fa8b849e 100644 --- a/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.mm +++ b/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.mm @@ -28,6 +28,7 @@ #endif #import "ENRMBlockquoteContainerView.h" #import "ENRMCodeBlockContainerView.h" +#import "ENRMCodeBlockWrapState.h" #import "ENRMDynamicBlockProps.h" #import "ENRMSpoilerCapable.h" #import "ENRMSpoilerOverlayView.h" @@ -133,6 +134,7 @@ @implementation EnrichedMarkdown { ENRMCodeBlockStreamingMode _codeBlockStreamingMode; // Trailing code block whose closing fence hasn't streamed in yet, if any. ENRMCodeBlockSegment *_pendingCodeBlockSegment; + ENRMCodeBlockWrapState *_codeBlockWrapState; size_t _renderedStyleFingerprint; size_t _pendingStyleFingerprint; @@ -217,6 +219,21 @@ - (instancetype)initWithFrame:(CGRect)frame _enableLinkPreview = YES; _enableTaskListItemToggle = YES; _enableImagePress = NO; + __weak EnrichedMarkdown *weakWrapSelf = self; + _codeBlockWrapState = [[ENRMCodeBlockWrapState alloc] + initWithCodeBlockViews:^{ + NSMutableArray *views = [NSMutableArray array]; + EnrichedMarkdown *strongSelf = weakWrapSelf; + if (strongSelf) { + ENRMCollectCodeBlockViews(strongSelf->_segmentViews, views); + } + return views; + } + onHeightChanged:^{ + EnrichedMarkdown *strongSelf = weakWrapSelf; + [strongSelf setNeedsLayout]; + [strongSelf requestHeightUpdate]; + }]; _dynamicBlockProps = [[ENRMDynamicBlockProps alloc] init]; _linkContextMenus = [[ENRMLinkContextMenus alloc] init]; __weak EnrichedMarkdown *weakMenuSelf = self; @@ -691,6 +708,8 @@ - (void)pushAccessibilityLabelsToSegments ((TableContainerView *)segment).accessibilityLabels = _accessibilityLabels; } else if ([segment isKindOfClass:[ENRMBlockquoteContainerView class]]) { ((ENRMBlockquoteContainerView *)segment).accessibilityLabels = _accessibilityLabels; + } else if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]]) { + ((ENRMCodeBlockContainerView *)segment).accessibilityLabels = _accessibilityLabels; } #if ENRICHED_MARKDOWN_MATH else if ([segment isKindOfClass:[ENRMMathContainerView class]]) { @@ -905,6 +924,7 @@ - (void)applyRenderedSegments:(NSArray *)renderedSegments self->_pendingCodeBlockSegment != nil && i == self->_segmentViews.count - 1; } }]; + [_codeBlockWrapState sync]; CGRect contentBounds = [self contentBounds]; if (contentBounds.size.width > 0) { @@ -1040,6 +1060,7 @@ - (ENRMCodeBlockContainerView *)createCodeBlockViewForSegment:(ENRMCodeBlockSegm { ENRMCodeBlockContainerView *codeBlockView = [[ENRMCodeBlockContainerView alloc] initWithConfig:_config]; codeBlockView.dynamicProps = _dynamicBlockProps; + codeBlockView.accessibilityLabels = _accessibilityLabels; __weak EnrichedMarkdown *weakSelf = self; codeBlockView.onCopyPress = ^(NSString *code, NSString *language) { @@ -1058,6 +1079,11 @@ - (ENRMCodeBlockContainerView *)createCodeBlockViewForSegment:(ENRMCodeBlockSegm return codeBlockView; } +- (NSSet *)wrappedCodeBlockIndices +{ + return _codeBlockWrapState.indices; +} + - (void)animateBlockViewIfNeeded:(RCTUIView *)view { if (!_streamingAnimation) @@ -1110,6 +1136,13 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & BOOL markdownChanged = oldViewProps.markdown != newViewProps.markdown; if (markdownChanged) { _dirtyFlags |= ENRMDirtyRender; + // A task toggle renders its result locally before JS echoes it back as a + // prop, so the rendered document is handed over for the echo check. + if ([_codeBlockWrapState markdownPropDidChangeFrom:oldViewProps.markdown + to:newViewProps.markdown + rendered:_cachedMarkdown]) { + _dirtyFlags |= ENRMDirtyForceHeight; + } } if (_config == nil) { @@ -1211,6 +1244,11 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & _dynamicBlockProps.enableBlockContextMenu = newViewProps.enableBlockContextMenu; _dynamicBlockProps.enableCodeBlockPress = newViewProps.enableCodeBlockPress; + if ([_codeBlockWrapState updateEnabled:newViewProps.enableCodeBlockWrapToggle]) { + [self setNeedsLayout]; + [self requestHeightUpdate]; + } + if (newViewProps.streamingAnimation != oldViewProps.streamingAnimation) { _streamingAnimation = newViewProps.streamingAnimation; _dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender; @@ -1278,6 +1316,10 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.table.row.c_str()]; _accessibilityLabels.mathEquation = [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.math.equation.c_str()]; + _accessibilityLabels.codeBlockWrap = + [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.codeBlock.wrap.c_str()]; + _accessibilityLabels.codeBlockUnwrap = + [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.codeBlock.unwrap.c_str()]; _accessibilityLabels.rotorHeadings = [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.rotor.headings.c_str()]; _accessibilityLabels.rotorLinks = @@ -1384,6 +1426,7 @@ - (void)prepareForRecycle _tableStreamingMode = ENRMTableStreamingModeProgressive; _codeBlockStreamingMode = ENRMCodeBlockStreamingModeProgressive; _pendingCodeBlockSegment = nil; + [_codeBlockWrapState reset]; _lineBreakStrategy = NSLineBreakStrategyNone; _writingDirectionMode = ENRMWritingDirectionModeFirstStrong; _renderedStyleFingerprint = 0; diff --git a/packages/react-native-enriched-markdown/ios/EnrichedMarkdownText.mm b/packages/react-native-enriched-markdown/ios/EnrichedMarkdownText.mm index b7b588b37..b09461dc5 100644 --- a/packages/react-native-enriched-markdown/ios/EnrichedMarkdownText.mm +++ b/packages/react-native-enriched-markdown/ios/EnrichedMarkdownText.mm @@ -760,6 +760,10 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.table.row.c_str()]; _accessibilityLabels.mathEquation = [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.math.equation.c_str()]; + _accessibilityLabels.codeBlockWrap = + [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.codeBlock.wrap.c_str()]; + _accessibilityLabels.codeBlockUnwrap = + [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.codeBlock.unwrap.c_str()]; _accessibilityLabels.rotorHeadings = [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.rotor.headings.c_str()]; _accessibilityLabels.rotorLinks = diff --git a/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h b/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h index 9b2a31d53..690ad873a 100644 --- a/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h +++ b/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h @@ -2,6 +2,7 @@ #import "ENRMBlockquoteContainerView.h" #import "ENRMCodeBlockContainerView.h" +#import "ENRMCodeBlockWrapState.h" #import "ENRMFeatureFlags.h" #import "ENRMLinkRegexProps.h" #import "ENRMMarkdownParser.h" @@ -231,11 +232,16 @@ static inline CGSize ENRMMeasureMarkdownViewFree(const PropsT &typedProps, CGFlo * same condition, tables report full width. Finishes with `measureSize:`'s * pixel rounding (width capped at maxWidth) and its * (maxWidth × system-16 line height) fallback for empty/failed content. + * `wrappedCodeBlocks` holds the document-order indexes, counted across nesting, + * of the code blocks the user wrapped (EnrichedMarkdown.wrappedCodeBlockIndices); + * those measure at the block width (a quote's inner width when nested) instead + * of their unwrapped height. */ template static inline CGSize ENRMMeasureSegmentedMarkdownViewFree(const PropsT &typedProps, CGFloat maxWidth, CGFloat fontScale, CGFloat pointScaleFactor, - NSWritingDirection resolvedLayoutDirection) + NSWritingDirection resolvedLayoutDirection, + NSSet *wrappedCodeBlocks = nil) { @autoreleasepool { CGSize fallback = CGSizeMake(maxWidth, UIFontLineHeight([UIFont systemFontOfSize:16.0])); @@ -294,6 +300,7 @@ static inline CGSize ENRMMeasureSegmentedMarkdownViewFree(const PropsT &typedPro CGFloat yOffset = 0.0; CGFloat maxContentWidth = 0.0; const NSUInteger lastIndex = segments.count - 1; + ENRMCodeBlockWrapCursor *wrapCursor = [[ENRMCodeBlockWrapCursor alloc] initWithWrapped:wrappedCodeBlocks]; for (NSUInteger i = 0; i < segments.count; i++) { ENRMRenderedSegment *segment = segments[i]; @@ -320,8 +327,12 @@ static inline CGSize ENRMMeasureSegmentedMarkdownViewFree(const PropsT &typedPro } } else if (segment.kind == ENRMSegmentKindCodeBlock && segment.codeBlockSegment) { yOffset += config.codeBlockMarginTop; - yOffset += [ENRMCodeBlockContainerView measureHeightForCodeBlockNode:segment.codeBlockSegment.codeBlockNode - config:config]; + MarkdownASTNode *codeBlockNode = segment.codeBlockSegment.codeBlockNode; + yOffset += [wrapCursor nextIsWrapped] + ? [ENRMCodeBlockContainerView measureWrappedHeightForCodeBlockNode:codeBlockNode + config:config + maxWidth:maxWidth] + : [ENRMCodeBlockContainerView measureHeightForCodeBlockNode:codeBlockNode config:config]; maxContentWidth = maxWidth; if (shouldAddBottomMargin) { yOffset += config.codeBlockMarginBottom; @@ -333,7 +344,8 @@ static inline CGSize ENRMMeasureSegmentedMarkdownViewFree(const PropsT &typedPro maxWidth:maxWidth pointScaleFactor:pointScaleFactor allowFontScaling:typedProps.allowFontScaling - lineBreakStrategy:lineBreakStrategy]; + lineBreakStrategy:lineBreakStrategy + wrapCursor:wrapCursor]; maxContentWidth = maxWidth; if (shouldAddBottomMargin) { yOffset += config.blockquoteMarginBottom; diff --git a/packages/react-native-enriched-markdown/ios/internals/EnrichedMarkdownShadowNode.mm b/packages/react-native-enriched-markdown/ios/internals/EnrichedMarkdownShadowNode.mm index 056225f54..701f52f92 100644 --- a/packages/react-native-enriched-markdown/ios/internals/EnrichedMarkdownShadowNode.mm +++ b/packages/react-native-enriched-markdown/ios/internals/EnrichedMarkdownShadowNode.mm @@ -45,6 +45,17 @@ } } +// Order-independent fingerprint of the wrapped set for the cache key; 0 for none, +// and {0} still hashes apart from {}. +static size_t ENRMWrappedCodeBlocksFingerprint(NSSet *wrappedCodeBlocks) +{ + size_t h = 0; + for (NSNumber *index in [wrappedCodeBlocks.allObjects sortedArrayUsingSelector:@selector(compare:)]) { + HashUtils::hash_one(h, index.unsignedLongValue); + } + return h; +} + Size EnrichedMarkdownShadowNode::measureContent(const LayoutContext &layoutContext, const LayoutConstraints &layoutConstraints) const { @@ -57,13 +68,20 @@ ? NSWritingDirectionRightToLeft : NSWritingDirectionLeftToRight; + // Wrapped code blocks are view state, not props, so they join the cache key by fingerprint. + const auto componentViewRef = getStateData().getComponentViewRef(); + RCTInternalGenericWeakWrapper *weakWrapper = (RCTInternalGenericWeakWrapper *)unwrapManagedObject(componentViewRef); + EnrichedMarkdown *view = weakWrapper ? (EnrichedMarkdown *)weakWrapper.object : nil; + NSSet *wrappedCodeBlocks = typedProps.enableCodeBlockWrapToggle ? view.wrappedCodeBlockIndices : nil; + return ENRMMeasureMarkdownContent( - typedProps, getStateData().getComponentViewRef(), receivedCounter, lastExactMeasurementCounter_, - lastExactMeasurementSize_, MarkdownFlavor::GitHub, layoutContext, layoutConstraints, - ^(EnrichedMarkdown *view, CGFloat maxWidth, CGFloat fontScale) { + typedProps, componentViewRef, receivedCounter, lastExactMeasurementCounter_, lastExactMeasurementSize_, + MarkdownFlavor::GitHub, layoutContext, layoutConstraints, + ^(EnrichedMarkdown *measuredView, CGFloat maxWidth, CGFloat fontScale) { return ENRMMeasureSegmentedMarkdownViewFree(*props, maxWidth, fontScale, pointScaleFactor, - resolvedLayoutDirection); - }); + resolvedLayoutDirection, wrappedCodeBlocks); + }, + ENRMWrappedCodeBlocksFingerprint(wrappedCodeBlocks)); } } // namespace facebook::react diff --git a/packages/react-native-enriched-markdown/ios/internals/MeasurementCache.h b/packages/react-native-enriched-markdown/ios/internals/MeasurementCache.h index 5f67471a7..0342e5cc5 100644 --- a/packages/react-native-enriched-markdown/ios/internals/MeasurementCache.h +++ b/packages/react-native-enriched-markdown/ios/internals/MeasurementCache.h @@ -45,6 +45,8 @@ struct MeasurementCacheKey { bool md4cFlagsAdmonitions; size_t styleFingerprint; size_t linkPillContentFingerprint; + // Code blocks the user wrapped (view state, not props); 0 when none. + size_t wrappedCodeBlocksFingerprint; CGFloat fontScale; MarkdownFlavor flavor; std::string lineBreakStrategyIOS; @@ -59,15 +61,16 @@ struct MeasurementCacheKey { return std::tie(markdown, maxWidth, allowTrailingMargin, allowFontScaling, maxFontSizeMultiplier, md4cFlagsUnderline, md4cFlagsSuperscript, md4cFlagsSubscript, md4cFlagsHighlight, md4cFlagsLatexMath, md4cFlagsHardSoftBreaks, md4cFlagsPreserveBlankLines, md4cFlagsAdmonitions, - styleFingerprint, linkPillContentFingerprint, fontScale, flavor, lineBreakStrategyIOS, - writingDirection, numberOfLines, ellipsizeMode, linkRegexKey, inlineCodeLinkRegexKey) == + styleFingerprint, linkPillContentFingerprint, wrappedCodeBlocksFingerprint, fontScale, flavor, + lineBreakStrategyIOS, writingDirection, numberOfLines, ellipsizeMode, linkRegexKey, + inlineCodeLinkRegexKey) == std::tie(other.markdown, other.maxWidth, other.allowTrailingMargin, other.allowFontScaling, other.maxFontSizeMultiplier, other.md4cFlagsUnderline, other.md4cFlagsSuperscript, other.md4cFlagsSubscript, other.md4cFlagsHighlight, other.md4cFlagsLatexMath, other.md4cFlagsHardSoftBreaks, other.md4cFlagsPreserveBlankLines, other.md4cFlagsAdmonitions, - other.styleFingerprint, other.linkPillContentFingerprint, other.fontScale, other.flavor, - other.lineBreakStrategyIOS, other.writingDirection, other.numberOfLines, other.ellipsizeMode, - other.linkRegexKey, other.inlineCodeLinkRegexKey); + other.styleFingerprint, other.linkPillContentFingerprint, other.wrappedCodeBlocksFingerprint, + other.fontScale, other.flavor, other.lineBreakStrategyIOS, other.writingDirection, + other.numberOfLines, other.ellipsizeMode, other.linkRegexKey, other.inlineCodeLinkRegexKey); } }; @@ -90,6 +93,7 @@ struct MeasurementCacheKeyHash { HashUtils::hash_one(h, key.md4cFlagsAdmonitions); HashUtils::hash_one(h, key.styleFingerprint); HashUtils::hash_one(h, key.linkPillContentFingerprint); + HashUtils::hash_one(h, key.wrappedCodeBlocksFingerprint); HashUtils::hash_one(h, key.fontScale); HashUtils::hash_one(h, static_cast(key.flavor)); HashUtils::hash_one(h, key.lineBreakStrategyIOS); @@ -194,7 +198,7 @@ template inline std::string buildLinkRecognitionCacheKey(c template inline MeasurementCacheKey buildMeasurementCacheKey(const PropsType &props, CGFloat maxWidth, CGFloat fontScale, - MarkdownFlavor flavor) + MarkdownFlavor flavor, size_t wrappedCodeBlocksFingerprint = 0) { return MeasurementCacheKey{ .markdown = props.markdown, @@ -212,6 +216,7 @@ inline MeasurementCacheKey buildMeasurementCacheKey(const PropsType &props, CGFl .md4cFlagsAdmonitions = props.md4cFlags.admonitions, .styleFingerprint = computeStyleFingerprint(props.markdownStyle), .linkPillContentFingerprint = computeLinkPillContentFingerprint(props.linkPillContent), + .wrappedCodeBlocksFingerprint = wrappedCodeBlocksFingerprint, .fontScale = fontScale, .flavor = flavor, .lineBreakStrategyIOS = props.lineBreakStrategyIOS, diff --git a/packages/react-native-enriched-markdown/ios/internals/ShadowMeasurementUtils.h b/packages/react-native-enriched-markdown/ios/internals/ShadowMeasurementUtils.h index 9904ae55f..6a30af0ee 100644 --- a/packages/react-native-enriched-markdown/ios/internals/ShadowMeasurementUtils.h +++ b/packages/react-native-enriched-markdown/ios/internals/ShadowMeasurementUtils.h @@ -85,14 +85,17 @@ static inline bool ENRMPropsNeedExactStreamingMeasurement(const PropsT &oldProps * `ENRMMeasureSegmentedMarkdownViewFree`); the resolved view is still handed * to the block for strategies that can use it. `fontScale` handed to the * block is the real multiplier even when streaming skips the cache — - * rendering must always use it. + * rendering must always use it. `wrappedCodeBlocksFingerprint` folds view + * state outside the props that changes the size (code blocks the user wrapped) + * into the cache key. */ template static inline Size ENRMMeasureMarkdownContent(const PropsT &typedProps, const std::shared_ptr &componentViewRef, int receivedCounter, int &lastExactMeasurementCounter, CGSize &lastExactMeasurementSize, MarkdownFlavor flavor, const LayoutContext &layoutContext, const LayoutConstraints &layoutConstraints, - CGSize (^measureUncached)(ViewT *view, CGFloat maxWidth, CGFloat fontScale)) + CGSize (^measureUncached)(ViewT *view, CGFloat maxWidth, CGFloat fontScale), + size_t wrappedCodeBlocksFingerprint = 0) { CGFloat maxWidth = layoutConstraints.maximumSize.width; @@ -117,7 +120,7 @@ ENRMMeasureMarkdownContent(const PropsT &typedProps, const std::shared_ptr CGFloat fontScale = ENRMFontScaleForMeasurement(typedProps.allowFontScaling, layoutContext); if (shouldUseMeasurementCache && !typedProps.markdown.empty()) { - auto cacheKey = buildMeasurementCacheKey(typedProps, maxWidth, fontScale, flavor); + auto cacheKey = buildMeasurementCacheKey(typedProps, maxWidth, fontScale, flavor, wrappedCodeBlocksFingerprint); CachedSize cached; if (MeasurementCache::shared().get(cacheKey, cached)) { return ENRMClampMeasuredSize(CGSizeMake(cached.width, cached.height), layoutConstraints); @@ -127,7 +130,7 @@ ENRMMeasureMarkdownContent(const PropsT &typedProps, const std::shared_ptr CGSize size = measureUncached(view, maxWidth, fontScale); if (shouldUseMeasurementCache && !typedProps.markdown.empty()) { - auto cacheKey = buildMeasurementCacheKey(typedProps, maxWidth, fontScale, flavor); + auto cacheKey = buildMeasurementCacheKey(typedProps, maxWidth, fontScale, flavor, wrappedCodeBlocksFingerprint); MeasurementCache::shared().set(cacheKey, {size.width, size.height}); } diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMBlockquoteContainerView.h b/packages/react-native-enriched-markdown/ios/segments/ENRMBlockquoteContainerView.h index 1657128ae..3349efc7b 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMBlockquoteContainerView.h +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMBlockquoteContainerView.h @@ -6,6 +6,7 @@ @class MarkdownASTNode; @class ENRMAccessibilityLabels; +@class ENRMCodeBlockWrapCursor; NS_ASSUME_NONNULL_BEGIN @@ -46,13 +47,17 @@ typedef void (^ENRMBlockquoteLinkBlock)(NSString *url); // sums the child segments at the reduced inner width and adds the vertical // inset, recursing into itself for nested quotes. pointScaleFactor is the layout // context's scale (the visible instance path uses RCTScreenScale), threaded so -// the per-text-segment pixel rounding matches the laid-out height. +// the per-text-segment pixel rounding matches the laid-out height. wrapCursor, +// when given, says which code blocks the user wrapped and is shared down the +// recursion so nested blocks keep counting in document order; wrapped ones lay +// out at the inner width, as the views do. + (CGFloat)measureHeightForBlockquoteNode:(MarkdownASTNode *)node config:(StyleConfig *)config maxWidth:(CGFloat)maxWidth pointScaleFactor:(CGFloat)pointScaleFactor allowFontScaling:(BOOL)allowFontScaling - lineBreakStrategy:(NSLineBreakStrategy)lineBreakStrategy; + lineBreakStrategy:(NSLineBreakStrategy)lineBreakStrategy + wrapCursor:(nullable ENRMCodeBlockWrapCursor *)wrapCursor; // Consumer text props threaded into the quote's inner content so it honors them // the same way the root document path does, instead of assuming defaults. Set by diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMBlockquoteContainerView.mm b/packages/react-native-enriched-markdown/ios/segments/ENRMBlockquoteContainerView.mm index 79c79cf67..036e74816 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMBlockquoteContainerView.mm +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMBlockquoteContainerView.mm @@ -175,6 +175,8 @@ - (void)setAccessibilityLabels:(ENRMAccessibilityLabels *)accessibilityLabels ((TableContainerView *)child).accessibilityLabels = accessibilityLabels; } else if ([child isKindOfClass:[ENRMBlockquoteContainerView class]]) { ((ENRMBlockquoteContainerView *)child).accessibilityLabels = accessibilityLabels; + } else if ([child isKindOfClass:[ENRMCodeBlockContainerView class]]) { + ((ENRMCodeBlockContainerView *)child).accessibilityLabels = accessibilityLabels; } #if ENRICHED_MARKDOWN_MATH else if ([child isKindOfClass:[ENRMMathContainerView class]]) { @@ -261,6 +263,7 @@ - (ENRMSegmentViewRegistry *)buildChildRegistry ENRMCodeBlockContainerView *view = [[ENRMCodeBlockContainerView alloc] initWithConfig:config]; ENRMBlockquoteContainerView *strongSelf = weakSelf; view.dynamicProps = strongSelf.dynamicProps; + view.accessibilityLabels = strongSelf.accessibilityLabels; view.onCopyPress = ^(NSString *code, NSString *language) { ENRMBlockquoteContainerView *s = weakSelf; if (s.onCopyPress) @@ -400,6 +403,7 @@ + (CGFloat)measureHeightForBlockquoteNode:(MarkdownASTNode *)node pointScaleFactor:(CGFloat)pointScaleFactor allowFontScaling:(BOOL)allowFontScaling lineBreakStrategy:(NSLineBreakStrategy)lineBreakStrategy + wrapCursor:(ENRMCodeBlockWrapCursor *)wrapCursor { UIEdgeInsets insets = ENRMBlockquoteContentInsetsForNode(config, ENRMAdmonitionTypeForNode(node) != nil); CGFloat innerWidth = MAX(maxWidth - insets.left - insets.right, 1); @@ -408,7 +412,7 @@ + (CGFloat)measureHeightForBlockquoteNode:(MarkdownASTNode *)node ENRMRenderBlockquoteChildren(node, config, allowFontScaling, lineBreakStrategy); CGFloat childrenHeight = ENRMMeasureSegmentsHeightViewFree( rendered, config, innerWidth, /*allowTrailingMargin*/ NO, pointScaleFactor, ENRMWritingDirectionModeFirstStrong, - NSWritingDirectionNatural, allowFontScaling, lineBreakStrategy); + NSWritingDirectionNatural, allowFontScaling, lineBreakStrategy, wrapCursor); return childrenHeight + insets.top + insets.bottom; } diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.h b/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.h index e17d3dfb9..4afebd0dc 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.h +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.h @@ -4,11 +4,14 @@ #import "StyleConfig.h" @class MarkdownASTNode; +@class ENRMAccessibilityLabels; +@class ENRMCodeBlockContainerView; NS_ASSUME_NONNULL_BEGIN typedef void (^ENRMCodeBlockCopyBlock)(NSString *code, NSString *language); typedef void (^ENRMCodeBlockPressBlock)(NSString *code, NSString *language); +typedef void (^ENRMCodeBlockWrapToggleBlock)(ENRMCodeBlockContainerView *view); @interface ENRMCodeBlockContainerView : RCTUIView @@ -22,8 +25,25 @@ typedef void (^ENRMCodeBlockPressBlock)(NSString *code, NSString *language); // instance's measureHeight: reports for the node, without building a view. + (CGFloat)measureHeightForCodeBlockNode:(MarkdownASTNode *)node config:(StyleConfig *)config; +// View-free height of the node with `wrapped` on, laid out at the block width. ++ (CGFloat)measureWrappedHeightForCodeBlockNode:(MarkdownASTNode *)node + config:(StyleConfig *)config + maxWidth:(CGFloat)maxWidth; + @property (nonatomic, strong) StyleConfig *config; +// Header wrap toggle next to copy (iOS only); ENRMCodeBlockWrapState sets it +// from enableCodeBlockWrapToggle. +@property (nonatomic, assign) BOOL showsWrapButton; + +// Wraps long lines at the block width instead of scrolling horizontally. Only +// ENRMCodeBlockWrapState writes it; the header toggle just asks through onWrapToggle. +@property (nonatomic, assign) BOOL wrapped; + +// Fired when the header toggle or the VoiceOver action is used; the host flips +// `wrapped` and re-measures. +@property (nonatomic, copy, nullable) ENRMCodeBlockWrapToggleBlock onWrapToggle; + // True until the closing fence arrives: highlighting is deferred and copying is // disabled, while the header stays visible. @property (nonatomic, assign) BOOL pending; @@ -33,6 +53,10 @@ typedef void (^ENRMCodeBlockPressBlock)(NSString *code, NSString *language); // block added after a toggle is born current. See ENRMDynamicBlockProps. @property (nonatomic, strong) ENRMDynamicBlockProps *dynamicProps; +// Wrap toggle labels (see ENRMAccessibilityLabels); the copy label lives on +// dynamicProps. +@property (nonatomic, strong, nullable) ENRMAccessibilityLabels *accessibilityLabels; + // Fired when the code is copied (header button, context-menu Copy, or the // VoiceOver copy action); set by the host to bridge up to the JS onCopyPress // event. Not fired for "Copy as Markdown". diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.m b/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.m index 53029a745..ad6a4e010 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.m +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.m @@ -1,4 +1,5 @@ #import "ENRMCodeBlockContainerView.h" +#import "ENRMAccessibilityLabels.h" #import "ENRMCodeBlockContent.h" #import "ENRMCodeBlockHighlighter.h" #import "ENRMHorizontalScrollView.h" @@ -18,8 +19,9 @@ // // measureHeight: must stay in sync with the drawn content: it uses the // unconstrained bounding rect of the same attributed string and the same -// header metrics, so the reported height matches the drawn height. Since -// lines never wrap, the height is independent of the available width. +// header metrics, so the reported height matches the drawn height. Unless the +// block is wrapped (the optional header wrap toggle), lines never wrap and the +// height is independent of the available width. static const CGFloat kENRMHeaderLabelScale = 0.85; // The copy glyph reads cleaner a touch smaller than the language label and at a @@ -42,6 +44,12 @@ static CGFloat ENRMCodeBlockContentInset(StyleConfig *config) return [UIFont systemFontOfSize:[config codeBlockFont].pointSize * kENRMHeaderLabelScale weight:UIFontWeightMedium]; } +static UIImageSymbolConfiguration *ENRMCodeBlockHeaderSymbolConfiguration(StyleConfig *config) +{ + return [UIImageSymbolConfiguration configurationWithPointSize:[config codeBlockFont].pointSize * kENRMHeaderIconScale + weight:UIImageSymbolWeightRegular]; +} + static CGFloat ENRMCodeBlockHeaderLabelLineHeight(UIFont *headerFont) { return ceil(UIFontLineHeight(headerFont)); @@ -96,6 +104,37 @@ static CGFloat ENRMCodeBlockCodeHeight(NSString *code, StyleConfig *config) return ceil(lineCount * ENRMCodeBlockPerLineHeight(config)); } +// Width the code text gets when wrapped: the block width minus the border and +// the code pane's horizontal padding, exactly as layoutScrollArea insets it. +static CGFloat ENRMCodeBlockWrapWidth(CGFloat blockWidth, StyleConfig *config) +{ + CGFloat borderW = ceil([config codeBlockBorderWidth]); + CGFloat horizontalPad = MAX(ENRMCodeBlockContentInset(config) - borderW, 0); + return MAX(blockWidth - borderW * 2, 0) - horizontalPad * 2; +} + +// Wrapped code height: the same per-line-height arithmetic as the analytic +// height, over visual lines from a call-confined TextKit layout at the wrap width. +static CGFloat ENRMCodeBlockWrappedCodeHeight(NSAttributedString *code, CGFloat wrapWidth, StyleConfig *config) +{ + if (code.length == 0) { + return 0; + } + NSTextStorage *storage = [[NSTextStorage alloc] initWithAttributedString:code]; + NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; + layoutManager.usesFontLeading = ENRMLayoutManagerUsesFontLeading; + NSTextContainer *container = [[NSTextContainer alloc] initWithSize:CGSizeMake(wrapWidth, CGFLOAT_MAX)]; + container.lineFragmentPadding = 0; + [layoutManager addTextContainer:container]; + [storage addLayoutManager:layoutManager]; + [layoutManager ensureLayoutForTextContainer:container]; + __block NSUInteger lineCount = 0; + [layoutManager enumerateLineFragmentsForGlyphRange:NSMakeRange(0, layoutManager.numberOfGlyphs) + usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *textContainer, + NSRange glyphRange, BOOL *stop) { lineCount++; }]; + return ceil(MAX(lineCount, 1) * ENRMCodeBlockPerLineHeight(config)); +} + // Used only to pick the scroll indicator style for the code pane, so the // indicator stays visible on dark code block backgrounds without affecting // any other scroll view. @@ -132,10 +171,12 @@ static BOOL ENRMColorIsDark(RCTUIColor *color) // the same rendering path drawAtPoint used internally, so output is identical, // but the layout is no longer thrown away on every draw. The container is // unbounded (lines never wrap) with zero line-fragment padding and font leading -// disabled, matching the NSStringDrawing origin the block used before. +// disabled, matching the NSStringDrawing origin the block used before. A +// positive wrapWidth bounds it instead, so lines wrap at that width. @interface ENRMCodeBlockContentView : RCTUIView @property (nonatomic, strong, nullable) NSAttributedString *attributedCode; @property (nonatomic, assign) CGPoint textOrigin; +@property (nonatomic, assign) CGFloat wrapWidth; // Laid-out content width, for the horizontal scroll extent. Free once the // cached stack exists; no separate measurement pass. @property (nonatomic, readonly) CGFloat usedWidth; @@ -174,7 +215,7 @@ - (void)setAttributedCode:(nullable NSAttributedString *)attributedCode _textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedCode]; _layoutManager = [[NSLayoutManager alloc] init]; _layoutManager.usesFontLeading = ENRMLayoutManagerUsesFontLeading; - _textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)]; + _textContainer = [[NSTextContainer alloc] initWithSize:[self containerSize]]; _textContainer.lineFragmentPadding = 0; _textContainer.maximumNumberOfLines = 0; [_layoutManager addTextContainer:_textContainer]; @@ -182,6 +223,28 @@ - (void)setAttributedCode:(nullable NSAttributedString *)attributedCode [_layoutManager ensureLayoutForTextContainer:_textContainer]; } +- (CGSize)containerSize +{ + return CGSizeMake(_wrapWidth > 0 ? _wrapWidth : CGFLOAT_MAX, CGFLOAT_MAX); +} + +- (void)setWrapWidth:(CGFloat)wrapWidth +{ + if (_wrapWidth == wrapWidth) { + return; + } + _wrapWidth = wrapWidth; + if (_textContainer) { + _textContainer.size = [self containerSize]; + [_layoutManager ensureLayoutForTextContainer:_textContainer]; + } +#if !TARGET_OS_OSX + [self setNeedsDisplay]; +#else + [self setNeedsDisplay:YES]; +#endif +} + - (CGFloat)usedWidth { if (!_layoutManager) { @@ -221,9 +284,13 @@ @implementation ENRMCodeBlockContainerView { CGFloat _headerLabelLineHeight; NSAttributedString *_languageLabel; CGSize _languageLabelSize; + // Wrapped code height, valid for _wrappedHeightWidth until the code changes. + CGFloat _wrappedHeight; + CGFloat _wrappedHeightWidth; #if !TARGET_OS_OSX UIFont *_headerFont; UIButton *_copyButton; + UIButton *_wrapButton; UITapGestureRecognizer *_tapRecognizer; #else NSFont *_headerFont; @@ -260,6 +327,7 @@ - (instancetype)initWithConfig:(StyleConfig *)config _config = config; _cachedCode = @""; _fenceChar = @"`"; + _wrappedHeightWidth = -1; _dynamicProps = [[ENRMDynamicBlockProps alloc] init]; _headerFont = ENRMCodeBlockHeaderFont(config); _headerLabelLineHeight = ENRMCodeBlockHeaderLabelLineHeight(_headerFont); @@ -274,9 +342,7 @@ - (instancetype)initWithConfig:(StyleConfig *)config [self addInteraction:contextMenu]; _copyButton = [UIButton buttonWithType:UIButtonTypeSystem]; - UIImageSymbolConfiguration *symbolConfig = - [UIImageSymbolConfiguration configurationWithPointSize:[config codeBlockFont].pointSize * kENRMHeaderIconScale - weight:UIImageSymbolWeightRegular]; + UIImageSymbolConfiguration *symbolConfig = ENRMCodeBlockHeaderSymbolConfiguration(config); [_copyButton setImage:[UIImage systemImageNamed:@"doc.on.doc" withConfiguration:symbolConfig] forState:UIControlStateNormal]; _copyButton.tintColor = [[config codeBlockColor] colorWithAlphaComponent:kENRMHeaderSecondaryAlpha]; @@ -340,12 +406,17 @@ - (void)layoutScrollArea _scrollView.frame = frame; CGFloat horizontalPad = MAX(inset - borderW, 0); - CGFloat contentWidth = MAX(_codeSize.width + horizontalPad * 2, frame.size.width); + _codeContentView.wrapWidth = _wrapped ? MAX(ENRMCodeBlockWrapWidth(self.bounds.size.width, _config), 1) : 0; + CGFloat codeWidth = _wrapped ? 0 : _codeSize.width; + CGFloat contentWidth = MAX(codeWidth + horizontalPad * 2, frame.size.width); _codeContentView.textOrigin = CGPointMake(horizontalPad, inset); _codeContentView.frame = CGRectMake(0, 0, contentWidth, frame.size.height); #if !TARGET_OS_OSX _scrollView.contentSize = CGSizeMake(contentWidth, frame.size.height); _scrollView.scrollEnabled = contentWidth > frame.size.width; + if (_wrapped) { + _scrollView.contentOffset = CGPointZero; + } #endif } @@ -372,6 +443,85 @@ - (void)layoutHeaderButton CGFloat buttonLeft = MAX(self.bounds.size.width - [self contentInset] - headerH + iconSlack, 0); CGFloat buttonTop = MAX([self headerCenterY] - headerH / 2, 0); _copyButton.frame = CGRectMake(buttonLeft, buttonTop, headerH, headerH); +#if !TARGET_OS_OSX + _wrapButton.frame = CGRectMake(MAX(buttonLeft - headerH, 0), buttonTop, headerH, headerH); +#endif +} + +#if !TARGET_OS_OSX +- (void)setShowsWrapButton:(BOOL)showsWrapButton +{ + if (_showsWrapButton == showsWrapButton) { + return; + } + _showsWrapButton = showsWrapButton; + if (showsWrapButton && !_wrapButton) { + _wrapButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [_wrapButton setImage:[UIImage systemImageNamed:@"text.alignleft" + withConfiguration:ENRMCodeBlockHeaderSymbolConfiguration(_config)] + forState:UIControlStateNormal]; + [_wrapButton addTarget:self action:@selector(toggleWrap) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:_wrapButton]; + [self updateWrapButtonAppearance]; + } + _wrapButton.hidden = !showsWrapButton; + [self setNeedsLayout]; + // The language label's room shrinks by one button. + [self setNeedsDisplay]; +} + +- (void)updateWrapButtonAppearance +{ + // Full-strength tint marks the toggle as on; off matches the copy button. + CGFloat alpha = _wrapped ? 1 : kENRMHeaderSecondaryAlpha; + _wrapButton.tintColor = [[_config codeBlockColor] colorWithAlphaComponent:alpha]; + _wrapButton.accessibilityLabel = [self wrapActionLabel]; +} +#endif + +- (NSString *)wrapActionLabel +{ + return _wrapped ? _accessibilityLabels.codeBlockUnwrap : _accessibilityLabels.codeBlockWrap; +} + +- (void)setAccessibilityLabels:(ENRMAccessibilityLabels *)labels +{ + if (_accessibilityLabels == labels) { + return; + } + _accessibilityLabels = labels; +#if !TARGET_OS_OSX + [self updateWrapButtonAppearance]; +#endif +} + +- (void)setWrapped:(BOOL)wrapped +{ + if (_wrapped == wrapped) { + return; + } + _wrapped = wrapped; + if (!wrapped) { + // Restore the unwrapped width for the scroll extent; a rebuild while + // wrapped measured at the wrap width. + _codeContentView.wrapWidth = 0; + _codeSize.width = _codeContentView.usedWidth; + } +#if !TARGET_OS_OSX + [self updateWrapButtonAppearance]; + [self setNeedsLayout]; + [_codeContentView setNeedsDisplay]; +#else + self.needsLayout = YES; + [_codeContentView setNeedsDisplay:YES]; +#endif +} + +- (void)toggleWrap +{ + if (self.onWrapToggle) { + self.onWrapToggle(self); + } } #if !TARGET_OS_OSX @@ -414,6 +564,7 @@ - (void)rebuildAttributedCode // width then reads out of that layout, and height stays analytic. _codeContentView.attributedCode = _attributedCode; _codeSize = CGSizeMake(_codeContentView.usedWidth, ENRMCodeBlockCodeHeight(_cachedCode, _config)); + _wrappedHeightWidth = -1; } - (void)applyCodeBlockNode:(MarkdownASTNode *)node @@ -479,7 +630,16 @@ - (CGFloat)contentInset - (CGFloat)measureHeight:(CGFloat)maxWidth { CGFloat inset = [self contentInset]; - return _codeSize.height + inset * 2 + [self headerHeight]; + CGFloat codeHeight = _codeSize.height; + if (_wrapped) { + if (_wrappedHeightWidth != maxWidth) { + _wrappedHeight = ENRMCodeBlockWrappedCodeHeight([self plainAttributedCode], + MAX(ENRMCodeBlockWrapWidth(maxWidth, _config), 1), _config); + _wrappedHeightWidth = maxWidth; + } + codeHeight = _wrappedHeight; + } + return codeHeight + inset * 2 + [self headerHeight]; } + (CGFloat)measureHeightForCodeBlockNode:(MarkdownASTNode *)node config:(StyleConfig *)config @@ -490,6 +650,17 @@ + (CGFloat)measureHeightForCodeBlockNode:(MarkdownASTNode *)node config:(StyleCo return codeHeight + inset * 2 + headerH; } ++ (CGFloat)measureWrappedHeightForCodeBlockNode:(MarkdownASTNode *)node + config:(StyleConfig *)config + maxWidth:(CGFloat)maxWidth +{ + CGFloat inset = ENRMCodeBlockContentInset(config); + CGFloat headerH = inset + ENRMCodeBlockHeaderLabelLineHeight(ENRMCodeBlockHeaderFont(config)); + NSAttributedString *code = ENRMCodeBlockPlainAttributedCode(ENRMCodeBlockExtractCode(node), config); + CGFloat codeHeight = ENRMCodeBlockWrappedCodeHeight(code, MAX(ENRMCodeBlockWrapWidth(maxWidth, config), 1), config); + return codeHeight + inset * 2 + headerH; +} + - (void)drawRect:(CGRect)rect { CGFloat borderWidth = [_config codeBlockBorderWidth]; @@ -533,7 +704,15 @@ - (void)drawRect:(CGRect)rect } if (_languageLabel.length > 0) { - [_languageLabel drawAtPoint:CGPointMake(inset, [self headerCenterY] - _languageLabelSize.height / 2)]; + // Keep clear of the header buttons, as Android caps its label view; a long + // name is cut short with an ellipsis. + CGFloat headerButtonsWidth = _showsWrapButton ? headerH * 2 : headerH; + CGFloat labelMaxWidth = MAX(self.bounds.size.width - inset * 2 - headerButtonsWidth, 0); + CGRect labelRect = CGRectMake(inset, [self headerCenterY] - _languageLabelSize.height / 2, + MIN(_languageLabelSize.width, labelMaxWidth), _languageLabelSize.height); + [_languageLabel drawWithRect:labelRect + options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine + context:nil]; } } @@ -576,9 +755,9 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { - // Let the copy button handle its own tap. + // Let the header buttons handle their own taps. for (UIView *hit = touch.view; hit != nil; hit = hit.superview) { - if (hit == _copyButton) { + if (hit == _copyButton || (_wrapButton != nil && hit == _wrapButton)) { return NO; } } @@ -643,18 +822,22 @@ - (UIAccessibilityTraits)accessibilityTraits return UIAccessibilityTraitStaticText; } -// The container is a single accessibility element, which hides the copy -// button subview from VoiceOver; expose the copy action explicitly instead. +// The container is a single accessibility element, which hides the header +// button subviews from VoiceOver; expose their actions explicitly instead. - (NSArray *)accessibilityCustomActions { - if (_pending || self.dynamicProps.menuCopyLabel.length == 0) { - return @[]; + NSMutableArray *actions = [NSMutableArray array]; + if (!_pending && self.dynamicProps.menuCopyLabel.length > 0) { + [actions addObject:[[UIAccessibilityCustomAction alloc] initWithName:self.dynamicProps.menuCopyLabel + target:self + selector:@selector(performCopyAccessibilityAction:)]]; } - UIAccessibilityCustomAction *copyAction = - [[UIAccessibilityCustomAction alloc] initWithName:self.dynamicProps.menuCopyLabel - target:self - selector:@selector(performCopyAccessibilityAction:)]; - return @[ copyAction ]; + if (_showsWrapButton && [self wrapActionLabel].length > 0) { + [actions addObject:[[UIAccessibilityCustomAction alloc] initWithName:[self wrapActionLabel] + target:self + selector:@selector(performWrapAccessibilityAction:)]]; + } + return actions; } - (BOOL)performCopyAccessibilityAction:(UIAccessibilityCustomAction *)action @@ -662,6 +845,12 @@ - (BOOL)performCopyAccessibilityAction:(UIAccessibilityCustomAction *)action [self copyCodeToPasteboard]; return YES; } + +- (BOOL)performWrapAccessibilityAction:(UIAccessibilityCustomAction *)action +{ + [self toggleWrap]; + return YES; +} #endif @end diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMContainerNodeView.h b/packages/react-native-enriched-markdown/ios/segments/ENRMContainerNodeView.h index 41e522d05..17b9b9d2f 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMContainerNodeView.h +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMContainerNodeView.h @@ -39,6 +39,9 @@ NS_ASSUME_NONNULL_BEGIN // Whether the last child contributes its trailing bottom margin. @property (nonatomic, assign) BOOL allowTrailingMargin; +// The current child views in document order. +@property (nonatomic, readonly) NSArray *segmentViews; + // Reconciles the current child views against renderedSegments, attaching and // removing subviews as needed. Requests a re-layout. - (void)applySegments:(NSArray *)renderedSegments reset:(BOOL)reset; diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMContainerNodeView.mm b/packages/react-native-enriched-markdown/ios/segments/ENRMContainerNodeView.mm index 448840013..989f46c3a 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMContainerNodeView.mm +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMContainerNodeView.mm @@ -32,6 +32,11 @@ - (instancetype)initWithFrame:(CGRect)frame return self; } +- (NSArray *)segmentViews +{ + return [_segmentViews copy]; +} + #if TARGET_OS_OSX - (BOOL)isFlipped { diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMSegmentHeightMeasurer.h b/packages/react-native-enriched-markdown/ios/segments/ENRMSegmentHeightMeasurer.h index 0f26dccfc..d7877b31e 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMSegmentHeightMeasurer.h +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMSegmentHeightMeasurer.h @@ -7,6 +7,8 @@ NS_ASSUME_NONNULL_BEGIN +@class ENRMCodeBlockWrapCursor; + /** * View-free height summation for a vertical stack of already-rendered * segments at a fixed content width. This is the iOS counterpart of Android's @@ -22,12 +24,14 @@ NS_ASSUME_NONNULL_BEGIN * +[ENRMBlockquoteContainerView measureHeightForBlockquoteNode:...] (recursion). * Per-kind margins come from the config exactly as computeSegmentLayout applies * them: marginTop before, marginBottom after unless it is the last segment and - * trailing margins are disabled. + * trailing margins are disabled. Code blocks the user wrapped (wrapCursor, + * shared with nested quotes) measure at contentWidth. */ CGFloat ENRMMeasureSegmentsHeightViewFree(NSArray *segments, StyleConfig *config, CGFloat contentWidth, BOOL allowTrailingMargin, CGFloat pointScaleFactor, ENRMWritingDirectionMode writingDirectionMode, NSWritingDirection resolvedLayoutDirection, BOOL allowFontScaling, - NSLineBreakStrategy lineBreakStrategy); + NSLineBreakStrategy lineBreakStrategy, + ENRMCodeBlockWrapCursor *_Nullable wrapCursor); NS_ASSUME_NONNULL_END diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMSegmentHeightMeasurer.mm b/packages/react-native-enriched-markdown/ios/segments/ENRMSegmentHeightMeasurer.mm index a8328804a..c60364677 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMSegmentHeightMeasurer.mm +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMSegmentHeightMeasurer.mm @@ -1,6 +1,7 @@ #import "ENRMSegmentHeightMeasurer.h" #import "ENRMBlockquoteContainerView.h" #import "ENRMCodeBlockContainerView.h" +#import "ENRMCodeBlockWrapState.h" #import "ENRMFeatureFlags.h" #import "ENRMTextRenderer.h" #import "ENRMViewFreeMeasurement.h" @@ -16,7 +17,7 @@ CGFloat ENRMMeasureSegmentsHeightViewFree(NSArray *segmen CGFloat contentWidth, BOOL allowTrailingMargin, CGFloat pointScaleFactor, ENRMWritingDirectionMode writingDirectionMode, NSWritingDirection resolvedLayoutDirection, BOOL allowFontScaling, - NSLineBreakStrategy lineBreakStrategy) + NSLineBreakStrategy lineBreakStrategy, ENRMCodeBlockWrapCursor *wrapCursor) { if (segments.count == 0) { return 0; @@ -49,8 +50,12 @@ CGFloat ENRMMeasureSegmentsHeightViewFree(NSArray *segmen } } else if (segment.kind == ENRMSegmentKindCodeBlock && segment.codeBlockSegment) { totalHeight += config.codeBlockMarginTop; - totalHeight += [ENRMCodeBlockContainerView measureHeightForCodeBlockNode:segment.codeBlockSegment.codeBlockNode - config:config]; + MarkdownASTNode *codeBlockNode = segment.codeBlockSegment.codeBlockNode; + totalHeight += [wrapCursor nextIsWrapped] + ? [ENRMCodeBlockContainerView measureWrappedHeightForCodeBlockNode:codeBlockNode + config:config + maxWidth:contentWidth] + : [ENRMCodeBlockContainerView measureHeightForCodeBlockNode:codeBlockNode config:config]; if (shouldAddBottomMargin) { totalHeight += config.codeBlockMarginBottom; } @@ -64,7 +69,8 @@ CGFloat ENRMMeasureSegmentsHeightViewFree(NSArray *segmen maxWidth:contentWidth pointScaleFactor:pointScaleFactor allowFontScaling:allowFontScaling - lineBreakStrategy:lineBreakStrategy]; + lineBreakStrategy:lineBreakStrategy + wrapCursor:wrapCursor]; } #if ENRICHED_MARKDOWN_MATH else if (segment.kind == ENRMSegmentKindMath && segment.mathSegment) { diff --git a/packages/react-native-enriched-markdown/ios/utils/ENRMAccessibilityLabels.h b/packages/react-native-enriched-markdown/ios/utils/ENRMAccessibilityLabels.h index 9dbeefb2e..4ddfd6084 100644 --- a/packages/react-native-enriched-markdown/ios/utils/ENRMAccessibilityLabels.h +++ b/packages/react-native-enriched-markdown/ios/utils/ENRMAccessibilityLabels.h @@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) NSString *nestedBlockquote; @property (nonatomic, copy) NSString *tableRow; @property (nonatomic, copy) NSString *mathEquation; +@property (nonatomic, copy) NSString *codeBlockWrap; +@property (nonatomic, copy) NSString *codeBlockUnwrap; @property (nonatomic, copy) NSString *rotorHeadings; @property (nonatomic, copy) NSString *rotorLinks; @property (nonatomic, copy) NSString *rotorImages; @@ -30,6 +32,8 @@ template static bool ENRMAccessibilityLabelsChanged(const T &oldLab oldLabels.blockquote.quote != newLabels.blockquote.quote || oldLabels.blockquote.nestedQuote != newLabels.blockquote.nestedQuote || oldLabels.table.row != newLabels.table.row || oldLabels.math.equation != newLabels.math.equation || + oldLabels.codeBlock.wrap != newLabels.codeBlock.wrap || + oldLabels.codeBlock.unwrap != newLabels.codeBlock.unwrap || oldLabels.rotor.headings != newLabels.rotor.headings || oldLabels.rotor.links != newLabels.rotor.links || oldLabels.rotor.images != newLabels.rotor.images; } diff --git a/packages/react-native-enriched-markdown/ios/utils/ENRMCodeBlockWrapState.h b/packages/react-native-enriched-markdown/ios/utils/ENRMCodeBlockWrapState.h new file mode 100644 index 000000000..ca99ded71 --- /dev/null +++ b/packages/react-native-enriched-markdown/ios/utils/ENRMCodeBlockWrapState.h @@ -0,0 +1,91 @@ +#pragma once + +#import "ENRMCodeBlockContainerView.h" +#import "ENRMUIKit.h" + +#ifdef __cplusplus +#include +#endif + +NS_ASSUME_NONNULL_BEGIN + +#ifdef __cplusplus +// Code block wrap state is keyed by block position, so it only stays meaningful +// while the document grows in place. Streaming may rewrite its unfinished last +// line (an HTML tag closing, a link relabeled); anything earlier changing - a +// recycled cell, an edited message, a block inserted above - starts unwrapped. +// Compares in place: this runs on every streamed chunk while a block is wrapped. +inline bool ENRMKeepsCodeBlockWrapState(const std::string &previous, const std::string &next) +{ + const auto cut = previous.rfind('\n'); + return cut == std::string::npos || next.compare(0, cut, previous, 0, cut) == 0; +} +#endif + +// Appends the code block views among `segmentViews` in document order, +// descending into nested blockquotes: the order ENRMCodeBlockWrapState indexes +// them in. +void ENRMCollectCodeBlockViews(NSArray *segmentViews, + NSMutableArray *codeBlockViews); + +/** + * Hands out the wrapped flag of each code block in the order a view-free + * measure pass reaches them: pre-order, descending into blockquotes, the same + * order ENRMCodeBlockWrapState indexes the views in. + */ +@interface ENRMCodeBlockWrapCursor : NSObject + +- (instancetype)initWithWrapped:(nullable NSSet *)wrapped; + +- (BOOL)nextIsWrapped; + +@end + +/** + * Which code blocks of one EnrichedMarkdown the user wrapped with the header + * toggle, and the only writer of that choice; mirrors Android's + * CodeBlockWrapState. + * + * Blocks are identified by document-order index, counted pre-order across + * nesting (a block inside a blockquote takes the next index, like a top-level + * one). The set lives here rather than on the views, which are rebuilt on style, + * font-scale and pill-content changes, and the shadow node's view-free measure + * pass reads it through EnrichedMarkdown.wrappedCodeBlockIndices. + */ +@interface ENRMCodeBlockWrapState : NSObject + +// `codeBlockViews` returns the host's current code block views (see +// ENRMCollectCodeBlockViews); `onHeightChanged` re-lays out and re-measures it +// after a toggle. +- (instancetype)initWithCodeBlockViews:(NSArray * (^)(void))codeBlockViews + onHeightChanged:(void (^)(void))onHeightChanged; + +@property (nonatomic, readonly) BOOL enabled; + +// Written on main, read by the shadow-node measure pass on any thread. +@property (atomic, copy, readonly) NSSet *indices; + +// Returns whether the wrapped set was cleared, so the height must be recomputed. +- (BOOL)updateEnabled:(BOOL)enabled; + +#ifdef __cplusplus +// Applies the reset rule to a new markdown prop; `rendered` is the document on +// screen, which includes local task toggles. The prop is compared with the +// previous prop, so an app that ignores a checkbox tap and keeps streaming its +// own copy keeps the wrapped blocks; a prop equal to what's rendered is the app +// echoing a task toggle back and keeps them too. Returns whether the wrapped set +// was cleared. +- (BOOL)markdownPropDidChangeFrom:(const std::string &)previous + to:(const std::string &)next + rendered:(nullable NSString *)rendered; +#endif + +// Pushes the wrapped set and the toggle onto the current code block views. +- (void)sync; + +// Back to the initial state (toggle on, nothing wrapped) for a recycled view. +- (void)reset; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/react-native-enriched-markdown/ios/utils/ENRMCodeBlockWrapState.mm b/packages/react-native-enriched-markdown/ios/utils/ENRMCodeBlockWrapState.mm new file mode 100644 index 000000000..451f27302 --- /dev/null +++ b/packages/react-native-enriched-markdown/ios/utils/ENRMCodeBlockWrapState.mm @@ -0,0 +1,124 @@ +#import "ENRMCodeBlockWrapState.h" +#import "ENRMContainerNodeView.h" + +void ENRMCollectCodeBlockViews(NSArray *segmentViews, + NSMutableArray *codeBlockViews) +{ + for (RCTUIView *view in segmentViews) { + if ([view isKindOfClass:[ENRMCodeBlockContainerView class]]) { + [codeBlockViews addObject:(ENRMCodeBlockContainerView *)view]; + } else if ([view isKindOfClass:[ENRMContainerNodeView class]]) { + ENRMCollectCodeBlockViews(((ENRMContainerNodeView *)view).segmentViews, codeBlockViews); + } + } +} + +@implementation ENRMCodeBlockWrapCursor { + NSSet *_wrapped; + NSUInteger _nextIndex; +} + +- (instancetype)initWithWrapped:(NSSet *)wrapped +{ + if (self = [super init]) { + _wrapped = wrapped; + } + return self; +} + +- (BOOL)nextIsWrapped +{ + return [_wrapped containsObject:@(_nextIndex++)]; +} + +@end + +@interface ENRMCodeBlockWrapState () +@property (atomic, copy, readwrite) NSSet *indices; +@end + +@implementation ENRMCodeBlockWrapState { + NSArray * (^_codeBlockViews)(void); + void (^_onHeightChanged)(void); +} + +- (instancetype)initWithCodeBlockViews:(NSArray * (^)(void))codeBlockViews + onHeightChanged:(void (^)(void))onHeightChanged +{ + if (self = [super init]) { + _codeBlockViews = [codeBlockViews copy]; + _onHeightChanged = [onHeightChanged copy]; + // Matches the prop's default. + _enabled = YES; + self.indices = [NSSet set]; + } + return self; +} + +- (BOOL)updateEnabled:(BOOL)enabled +{ + if (_enabled == enabled) { + return NO; + } + _enabled = enabled; + BOOL cleared = !enabled && self.indices.count > 0; + if (cleared) { + self.indices = [NSSet set]; + } + [self sync]; + return cleared; +} + +- (BOOL)markdownPropDidChangeFrom:(const std::string &)previous + to:(const std::string &)next + rendered:(NSString *)rendered +{ + if (self.indices.count == 0) { + return NO; + } + const bool echoesRendered = rendered != nil && next.compare(rendered.UTF8String) == 0; + if (echoesRendered || ENRMKeepsCodeBlockWrapState(previous, next)) { + return NO; + } + self.indices = [NSSet set]; + return YES; +} + +- (void)sync +{ + NSSet *wrapped = self.indices; + __weak ENRMCodeBlockWrapState *weakSelf = self; + [_codeBlockViews() enumerateObjectsUsingBlock:^(ENRMCodeBlockContainerView *view, NSUInteger index, BOOL *stop) { + view.onWrapToggle = ^(ENRMCodeBlockContainerView *toggled) { [weakSelf toggle:toggled]; }; + view.showsWrapButton = self->_enabled; + view.wrapped = self->_enabled && [wrapped containsObject:@(index)]; + }]; +} + +- (void)toggle:(ENRMCodeBlockContainerView *)view +{ + if (!_enabled) { + return; + } + NSUInteger index = [_codeBlockViews() indexOfObjectIdenticalTo:view]; + if (index == NSNotFound) { + return; + } + NSMutableSet *wrapped = [self.indices mutableCopy]; + if ([wrapped containsObject:@(index)]) { + [wrapped removeObject:@(index)]; + } else { + [wrapped addObject:@(index)]; + } + self.indices = wrapped; + [self sync]; + _onHeightChanged(); +} + +- (void)reset +{ + _enabled = YES; + self.indices = [NSSet set]; +} + +@end diff --git a/packages/react-native-enriched-markdown/ios/utils/TaskListTapUtils.m b/packages/react-native-enriched-markdown/ios/utils/TaskListTapUtils.m index d15bfbdd8..7ddd38954 100644 --- a/packages/react-native-enriched-markdown/ios/utils/TaskListTapUtils.m +++ b/packages/react-native-enriched-markdown/ios/utils/TaskListTapUtils.m @@ -137,7 +137,7 @@ BOOL handleTaskListTap(ENRMPlatformTextView *textView, ENRMTapRecognizer *recogn NSTextCheckingResult *match = matches[targetIndex]; NSRange prefixRange = [match rangeAtIndex:1]; NSString *prefix = [markdown substringWithRange:prefixRange]; - NSString *replacement = [NSString stringWithFormat:@"%@[%@]", prefix, checked ? @" " : @"x"]; + NSString *replacement = [NSString stringWithFormat:@"%@[%@]", prefix, checked ? @"x" : @" "]; NSMutableString *result = [markdown mutableCopy]; [result replaceCharactersInRange:match.range withString:replacement]; diff --git a/packages/react-native-enriched-markdown/src/EnrichedMarkdownNativeComponent.ts b/packages/react-native-enriched-markdown/src/EnrichedMarkdownNativeComponent.ts index 32ff76827..eea51c405 100644 --- a/packages/react-native-enriched-markdown/src/EnrichedMarkdownNativeComponent.ts +++ b/packages/react-native-enriched-markdown/src/EnrichedMarkdownNativeComponent.ts @@ -360,6 +360,10 @@ export interface AccessibilityLabelsTableProps { export interface AccessibilityLabelsMathProps { equation: string; } +export interface AccessibilityLabelsCodeBlockProps { + wrap: string; + unwrap: string; +} export interface AccessibilityLabelsRotorProps { headings: string; links: string; @@ -370,6 +374,7 @@ export interface AccessibilityLabelsProps { blockquote: Readonly; table: Readonly; math: Readonly; + codeBlock: Readonly; rotor: Readonly; } @@ -522,6 +527,12 @@ export interface NativeProps extends ViewProps { * @default false */ enableCodeBlockPress?: CodegenTypes.WithDefault; + /** + * Shows a per-block line wrap toggle next to the copy button in fenced code + * block headers. Each block starts unwrapped. + * @default false + */ + enableCodeBlockWrapToggle?: CodegenTypes.WithDefault; /** * Callback fired when a math expression cannot be parsed or rendered by the * LaTeX engine. Receives the raw LaTeX `source` of the failing inline span or diff --git a/packages/react-native-enriched-markdown/src/EnrichedMarkdownTextNativeComponent.ts b/packages/react-native-enriched-markdown/src/EnrichedMarkdownTextNativeComponent.ts index 6f31ccc1c..a557505da 100644 --- a/packages/react-native-enriched-markdown/src/EnrichedMarkdownTextNativeComponent.ts +++ b/packages/react-native-enriched-markdown/src/EnrichedMarkdownTextNativeComponent.ts @@ -361,6 +361,10 @@ export interface AccessibilityLabelsTableProps { export interface AccessibilityLabelsMathProps { equation: string; } +export interface AccessibilityLabelsCodeBlockProps { + wrap: string; + unwrap: string; +} export interface AccessibilityLabelsRotorProps { headings: string; links: string; @@ -371,6 +375,7 @@ export interface AccessibilityLabelsProps { blockquote: Readonly; table: Readonly; math: Readonly; + codeBlock: Readonly; rotor: Readonly; } diff --git a/packages/react-native-enriched-markdown/src/accessibilityLabelDefaults.ts b/packages/react-native-enriched-markdown/src/accessibilityLabelDefaults.ts index bdb4857a9..04884ba08 100644 --- a/packages/react-native-enriched-markdown/src/accessibilityLabelDefaults.ts +++ b/packages/react-native-enriched-markdown/src/accessibilityLabelDefaults.ts @@ -25,6 +25,10 @@ export const DEFAULT_ACCESSIBILITY_LABELS: ResolvedAccessibilityLabels = { math: { equation: 'Math: {latex}', }, + codeBlock: { + wrap: 'Wrap lines', + unwrap: 'Disable line wrap', + }, rotor: { headings: 'Headings', links: 'Links', @@ -72,6 +76,13 @@ export function resolveAccessibilityLabels( equation: labels?.math?.equation ?? DEFAULT_ACCESSIBILITY_LABELS.math.equation, }, + codeBlock: { + wrap: + labels?.codeBlock?.wrap ?? DEFAULT_ACCESSIBILITY_LABELS.codeBlock.wrap, + unwrap: + labels?.codeBlock?.unwrap ?? + DEFAULT_ACCESSIBILITY_LABELS.codeBlock.unwrap, + }, rotor: { headings: labels?.rotor?.headings ?? DEFAULT_ACCESSIBILITY_LABELS.rotor.headings, diff --git a/packages/react-native-enriched-markdown/src/native/EnrichedMarkdownText.tsx b/packages/react-native-enriched-markdown/src/native/EnrichedMarkdownText.tsx index ca7157e39..dd5621a31 100644 --- a/packages/react-native-enriched-markdown/src/native/EnrichedMarkdownText.tsx +++ b/packages/react-native-enriched-markdown/src/native/EnrichedMarkdownText.tsx @@ -145,6 +145,7 @@ export const EnrichedMarkdownText = ({ onCopyPress, onLatexError, onCodeBlockPress, + enableCodeBlockWrapToggle = true, enableBlockContextMenu = true, enableLinkPreview, selectable = true, @@ -455,7 +456,12 @@ export const EnrichedMarkdownText = ({ }; if (flavor === 'github') { - return ; + return ( + + ); } return ; diff --git a/packages/react-native-enriched-markdown/src/types/AccessibilityLabels.ts b/packages/react-native-enriched-markdown/src/types/AccessibilityLabels.ts index a53a694b0..383ab11a1 100644 --- a/packages/react-native-enriched-markdown/src/types/AccessibilityLabels.ts +++ b/packages/react-native-enriched-markdown/src/types/AccessibilityLabels.ts @@ -74,6 +74,23 @@ export interface AccessibilityLabels { equation?: string; }; + /** + * Labels for the fenced code block header's line wrap toggle + * (`enableCodeBlockWrapToggle`). iOS + Android. + */ + codeBlock?: { + /** + * Spoken while the block scrolls horizontally. + * @default 'Wrap lines' + */ + wrap?: string; + /** + * Spoken while the block's lines are wrapped. + * @default 'Disable line wrap' + */ + unwrap?: string; + }; + /** * Labels for the VoiceOver rotor (the secondary jump-by-type navigator on iOS). * iOS only — Android has no rotor concept. @@ -110,6 +127,10 @@ export interface ResolvedAccessibilityLabels { math: { equation: string; }; + codeBlock: { + wrap: string; + unwrap: string; + }; rotor: { headings: string; links: string; diff --git a/packages/react-native-enriched-markdown/src/types/MarkdownTextProps.ts b/packages/react-native-enriched-markdown/src/types/MarkdownTextProps.ts index acf3cfccf..c198d8d0b 100644 --- a/packages/react-native-enriched-markdown/src/types/MarkdownTextProps.ts +++ b/packages/react-native-enriched-markdown/src/types/MarkdownTextProps.ts @@ -263,6 +263,19 @@ export interface EnrichedMarkdownTextProps extends Omit { * @platform ios, android, web */ onCodeBlockPress?: (event: CodeBlockPressEvent) => void; + /** + * Shows a line wrap toggle next to the copy button in each fenced code block + * header; set `false` to hide it. Every block starts unwrapped (horizontal scroll) and toggles on its + * own. The state belongs to the block's position in the document: it survives + * streaming appends and resets when the markdown is replaced. Code blocks + * inside blockquotes and admonitions get the toggle too. The toggle's spoken + * labels come from `accessibilityLabels.codeBlock`. + * + * Only applies when `flavor="github"`. + * @default true + * @platform ios, android + */ + enableCodeBlockWrapToggle?: boolean; /** * Controls the long-press context menu on block views (code blocks, tables, * and block math). When false, long-pressing a block does not open the copy diff --git a/packages/react-native-enriched-markdown/src/web/nativeProps.ts b/packages/react-native-enriched-markdown/src/web/nativeProps.ts index 2f8f98f1a..58db5dd6d 100644 --- a/packages/react-native-enriched-markdown/src/web/nativeProps.ts +++ b/packages/react-native-enriched-markdown/src/web/nativeProps.ts @@ -33,6 +33,7 @@ export const NATIVE_ONLY_PROP_NAMES: Record = { onCopyPress: true, onLatexError: true, enableBlockContextMenu: true, + enableCodeBlockWrapToggle: true, enableLinkPreview: true, selectionHandleColor: true, allowFontScaling: true, From fd59c2c00056ce9d414953eb70c44634cb8a6ebf Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Fri, 16 Oct 2026 14:51:28 -0700 Subject: [PATCH 07/11] revert: drop the fork's code block wrap toggle for upstream #1021 Upstream merged the toggle as software-mansion/enriched-markdown#1021 (2547e709), which carries this fork's #1 plus the review fixes. Dropping the fork copy lets the upstream merge bring in that version unchanged. This reverts commit 57af70aa. Co-Authored-By: Claude Opus 5.5 --- docs-md/ACCESSIBILITY.md | 2 - docs-md/API_REFERENCE.md | 12 - .../api-reference/enriched-markdown-text.md | 11 - docs/docs/user-experience/accessibility.md | 4 +- .../enriched/markdown/EnrichedMarkdown.kt | 61 +---- .../markdown/EnrichedMarkdownManager.kt | 11 +- .../enriched/markdown/MeasurementStore.kt | 28 +-- .../accessibility/AccessibilityLabels.kt | 2 - .../segments/CodeBlockContainerView.kt | 167 ++----------- .../markdown/segments/SegmentViewCreators.kt | 1 - .../utils/common/MarkdownViewManagerUtils.kt | 3 - .../EnrichedMarkdownTextSpec/conversions.h | 2 - .../segments/CodeBlockContainerViewTest.kt | 106 --------- .../ios/EnrichedMarkdown.h | 5 - .../ios/EnrichedMarkdown.mm | 78 ------- .../ios/EnrichedMarkdownText.mm | 4 - .../ios/internals/ENRMViewFreeMeasurement.h | 16 +- .../internals/EnrichedMarkdownShadowNode.mm | 28 +-- .../ios/internals/MeasurementCache.h | 17 +- .../ios/internals/ShadowMeasurementUtils.h | 11 +- .../ios/segments/ENRMCodeBlockContainerView.h | 23 -- .../ios/segments/ENRMCodeBlockContainerView.m | 221 ++---------------- .../ios/utils/ENRMAccessibilityLabels.h | 4 - .../src/EnrichedMarkdownNativeComponent.ts | 11 - .../EnrichedMarkdownTextNativeComponent.ts | 5 - .../src/accessibilityLabelDefaults.ts | 11 - .../src/native/EnrichedMarkdownText.tsx | 3 - .../src/types/AccessibilityLabels.ts | 21 -- .../src/types/MarkdownTextProps.ts | 13 -- .../src/web/nativeProps.ts | 1 - 30 files changed, 59 insertions(+), 823 deletions(-) delete mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerViewTest.kt diff --git a/docs-md/ACCESSIBILITY.md b/docs-md/ACCESSIBILITY.md index 542505221..3591c49a0 100644 --- a/docs-md/ACCESSIBILITY.md +++ b/docs-md/ACCESSIBILITY.md @@ -55,8 +55,6 @@ Every field is optional. Any field you omit falls back to the English default be | `blockquote.nestedQuote` | `"Nested blockquote"` | iOS + Android | | `table.row` | `"Row {n}: {content}"` | iOS + Android | | `math.equation` | `"Math: {latex}"` | iOS + Android | -| `codeBlock.wrap` | `"Wrap lines"` | iOS + Android | -| `codeBlock.unwrap` | `"Disable line wrap"` | iOS + Android | | `rotor.headings` | `"Headings"` | iOS only | | `rotor.links` | `"Links"` | iOS only | | `rotor.images` | `"Images"` | iOS only | diff --git a/docs-md/API_REFERENCE.md b/docs-md/API_REFERENCE.md index b21dc41af..d64f1d10d 100644 --- a/docs-md/API_REFERENCE.md +++ b/docs-md/API_REFERENCE.md @@ -282,14 +282,6 @@ Works in both flavors: `flavor="github"` fires on the container-based code block /> ``` -### `enableCodeBlockWrapToggle` - -Adds a line wrap toggle next to the copy button in each fenced code block header (`flavor="github"`). Blocks start unwrapped and scroll horizontally; tapping the toggle wraps that block's lines at the block width, and tapping again goes back to scrolling. The state belongs to the block's position in the document: it survives streaming appends and resets when the markdown is replaced rather than appended to. Code blocks inside blockquotes and admonitions have no toggle and keep scrolling. The toggle's spoken labels come from [`accessibilityLabels.codeBlock`](#accessibilitylabels). - -| Type | Default Value | Platform | -| --------- | ------------- | ------------ | -| `boolean` | `false` | iOS, Android | - ### `enableBlockContextMenu` Controls the long-press copy popup on code blocks, tables, block math, and blockquotes/admonitions. @@ -790,10 +782,6 @@ interface AccessibilityLabels { math?: { equation?: string; // "Math: {latex}" }; - codeBlock?: { // enableCodeBlockWrapToggle - wrap?: string; // "Wrap lines" - unwrap?: string; // "Disable line wrap" - }; rotor?: { // iOS only headings?: string; // "Headings" links?: string; // "Links" diff --git a/docs/docs/react-native/api-reference/enriched-markdown-text.md b/docs/docs/react-native/api-reference/enriched-markdown-text.md index 767402bca..0a84cc9df 100644 --- a/docs/docs/react-native/api-reference/enriched-markdown-text.md +++ b/docs/docs/react-native/api-reference/enriched-markdown-text.md @@ -217,12 +217,6 @@ Controls the long-press context menu on block views - fenced code blocks, tables iOS, Android, and macOS only - the block context menu is a native interaction, and the web build renders blocks without one.} /> -### `enableCodeBlockWrapToggle` - -Adds a line wrap toggle next to the copy button in each fenced code block header. Blocks start unwrapped and scroll horizontally; tapping the toggle wraps that block's lines at the block width, and tapping again goes back to scrolling. The state belongs to the block's position in the document: it survives streaming appends and resets when the Markdown is replaced rather than appended to. Code blocks inside blockquotes and admonitions have no toggle and keep scrolling. Needs [`flavor="github"`](#flavor); the toggle's spoken labels come from [`accessibilityLabels.codeBlock`](#accessibilitylabels). iOS and Android only. - - - ### `enableLinkPreview` {#enablelinkpreview} Controls the native link preview on long press. It is on by default, and supplying [`onLinkLongPress`](#onlinklongpress) turns it off - your handler owns the long press instead. That override cannot be undone from this prop: with `onLinkLongPress` set, even an explicit `enableLinkPreview={true}` is discarded. Setting [`selectable={false}`](#selectable) also suppresses the preview. @@ -497,11 +491,6 @@ interface AccessibilityLabels { math?: { equation?: string; // {latex} is the equation source }; - codeBlock?: { - // the enableCodeBlockWrapToggle header button - wrap?: string; - unwrap?: string; - }; rotor?: { // iOS only, Android has no rotor headings?: string; diff --git a/docs/docs/user-experience/accessibility.md b/docs/docs/user-experience/accessibility.md index 0b0a70a90..aa8e4db92 100644 --- a/docs/docs/user-experience/accessibility.md +++ b/docs/docs/user-experience/accessibility.md @@ -61,8 +61,6 @@ packages ship. */} | `blockquote.nestedQuote` | `"Nested blockquote"` | iOS + Android | | `table.row` | `"Row {n}: {content}"` | iOS + Android | | `math.equation` | `"Math: {latex}"` | iOS + Android | -| `codeBlock.wrap` | `"Wrap lines"` | iOS + Android | -| `codeBlock.unwrap` | `"Disable line wrap"` | iOS + Android | | `rotor.headings` / `rotor.links` / `rotor.images` | `"Headings"` / `"Links"` / `"Images"` | iOS only | Placeholders: `{n}` (1-based index), `{content}` (comma-joined cell texts), `{latex}` (equation source). Preserve placeholder names exactly in translations. Defaults use the no-plural cardinal form so a single template works in every language. @@ -119,7 +117,7 @@ Four sharp edges are worth knowing: - **Android** has no rotor concept, so `accessibilityLabels.rotor.*` is ignored there. - **Task list items** have no accessibility handling in the React Native package on either platform: a checkbox is read as plain list text, with no checked state announced and no toggle action exposed. There is no label key for it. - **Admonitions** carry no accessibility role; they are announced as the blockquote they are built from. -- **Code blocks** are covered only partially - under `flavor="github"` the header copy button carries the resolved copy label and the optional wrap toggle (`enableCodeBlockWrapToggle`) speaks `codeBlock.wrap` / `codeBlock.unwrap`; iOS vends both as VoiceOver actions, but the block itself has no dedicated role. +- **Code blocks** are covered only partially - under `flavor="github"` the header copy button carries the resolved copy label, and iOS vends a VoiceOver copy action, but the block itself has no dedicated role. - The platform tabs above describe the renderer. The **editor** speaks neither heading level nor task state (see [Editor accessibility](#editor-accessibility)). ## Reference diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt index 987f30058..8ac85e9d8 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt @@ -53,15 +53,6 @@ import java.util.EnumSet import java.util.concurrent.ExecutorService import java.util.concurrent.Executors -// Code block wrap state is keyed by block position, so it only stays meaningful -// while the document grows in place. Streaming may rewrite its unfinished last -// line (an HTML tag closing, a link relabeled); anything earlier changing - a -// recycled cell, an edited message, a block inserted above - starts unwrapped. -internal fun keepsCodeBlockWrapState( - previous: String, - next: String, -): Boolean = next.startsWith(previous.substringBeforeLast('\n', "")) - class EnrichedMarkdown( context: Context, ) : ContainerNodeView(context), @@ -253,58 +244,12 @@ class EnrichedMarkdown( dynamicProps.enableCodeBlockPress = value } - // Document-order indexes of the top-level code blocks the user wrapped. Kept - // across renders so streaming and segment recreation keep the choice, and - // mirrored into MeasurementStore so the Yoga measure pass sees it. - private var wrappedCodeBlocks: Set = emptySet() - - var enableCodeBlockWrapToggle: Boolean = false - set(value) { - if (field == value) return - field = value - val hadWrappedBlocks = wrappedCodeBlocks.isNotEmpty() - if (!value) setWrappedCodeBlocks(emptySet()) - syncCodeBlockWrapState() - if (hadWrappedBlocks && !value) onImageLayoutChanged() - } - - private fun setWrappedCodeBlocks(value: Set) { - wrappedCodeBlocks = value - MeasurementStore.updateWrappedCodeBlocks(id, value) - } - - private fun syncCodeBlockWrapState() { - var codeBlockIndex = 0 - segmentViews.forEach { view -> - if (view is CodeBlockContainerView) { - view.onWrapToggle = ::codeBlockDidToggleWrap - view.showsWrapButton = enableCodeBlockWrapToggle - view.wrapped = enableCodeBlockWrapToggle && codeBlockIndex in wrappedCodeBlocks - codeBlockIndex++ - } - } - } - - private fun codeBlockDidToggleWrap(view: CodeBlockContainerView) { - val codeBlockIndex = segmentViews.filterIsInstance().indexOf(view) - if (codeBlockIndex < 0) return - setWrappedCodeBlocks(if (view.wrapped) wrappedCodeBlocks + codeBlockIndex else wrappedCodeBlocks - codeBlockIndex) - onImageLayoutChanged() - } - init { segmentViewFactory = RootFactory() } - fun setMarkdownContent( - markdown: String, - keepWrapState: Boolean = false, - ) { + fun setMarkdownContent(markdown: String) { if (currentMarkdown == markdown) return - if (!keepWrapState && wrappedCodeBlocks.isNotEmpty() && !keepsCodeBlockWrapState(currentMarkdown, markdown)) { - setWrappedCodeBlocks(emptySet()) - dirtyFlags += DirtyFlag.FORCE_HEIGHT - } currentMarkdown = markdown ++currentRenderId renderPending = true @@ -521,9 +466,6 @@ class EnrichedMarkdown( segmentViews.filterIsInstance().forEach { it.accessibilityLabels = labels } - segmentViews.filterIsInstance().forEach { - it.accessibilityLabels = labels - } mathContainerClass?.let { mathClass -> segmentViews.filter { mathClass.isInstance(it) }.forEach { view -> runCatching { @@ -662,7 +604,6 @@ class EnrichedMarkdown( view.pending = pendingCodeBlockSegment != null && index == segmentViews.size - 1 } } - syncCodeBlockWrapState() if (width > 0) { val heightBefore = computeSegmentsTotalHeight() diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt index 41f308f6d..74ce4a8f3 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt @@ -63,8 +63,7 @@ class EnrichedMarkdownManager : view.setOnTaskListItemPressCallback { taskIndex, checked, itemText -> val newChecked = !checked val updatedMarkdown = TaskListToggleUtils.toggleAtIndex(view.currentMarkdown, taskIndex, newChecked) - // A checkbox flip keeps every code block where it was, so keep their wrap state too. - view.setMarkdownContent(updatedMarkdown, keepWrapState = true) + view.setMarkdownContent(updatedMarkdown) view.commitProps() emitTaskListItemPress(view, taskIndex, newChecked, itemText) } @@ -331,14 +330,6 @@ class EnrichedMarkdownManager : view?.enableCodeBlockPress = enableCodeBlockPress } - @ReactProp(name = "enableCodeBlockWrapToggle", defaultBoolean = false) - override fun setEnableCodeBlockWrapToggle( - view: EnrichedMarkdown?, - enableCodeBlockWrapToggle: Boolean, - ) { - view?.enableCodeBlockWrapToggle = enableCodeBlockWrapToggle - } - @ReactProp(name = "lineBreakStrategyIOS") override fun setLineBreakStrategyIOS( view: EnrichedMarkdown?, diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt index 97656c5f0..09d723563 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt @@ -95,9 +95,6 @@ object MeasurementStore { private val streamingCodeBlockModes = ConcurrentHashMap() - // Top-level code blocks the user wrapped, by document-order index (see EnrichedMarkdown). - private val wrappedCodeBlocks = ConcurrentHashMap>() - private fun resolveFontScalingSettings( viewId: Int?, props: ReadableMap?, @@ -150,15 +147,6 @@ object MeasurementStore { data.remove(id) numberOfLinesByViewId.remove(id) ellipsizeModeByViewId.remove(id) - wrappedCodeBlocks.remove(id) - } - - fun updateWrappedCodeBlocks( - viewId: Int, - indices: Set, - ) { - if (indices.isEmpty()) wrappedCodeBlocks.remove(viewId) else wrappedCodeBlocks[viewId] = indices - data.remove(viewId) } fun invalidate(id: Int) { @@ -503,16 +491,7 @@ object MeasurementStore { } else { rawMarkdown } - val wrapped = - if (props.getBooleanOrDefault("enableCodeBlockWrapToggle", false)) { - id?.let { wrappedCodeBlocks[it] } ?: emptySet() - } else { - emptySet() - } - // A Set's hashCode sums its elements, so {} and {0} would collide; the sorted list's doesn't. - val propsHash = - 31 * computePropsHashForMarkdown(markdown, props, allowFontScaling, fontScale, maxFontSizeMultiplier) + - wrapped.sorted().hashCode() + val propsHash = computePropsHashForMarkdown(markdown, props, allowFontScaling, fontScale, maxFontSizeMultiplier) // Streaming shortcut: reuse cached size when the filtered content and // width are unchanged. When the filter output changes (e.g. a table @@ -610,7 +589,6 @@ object MeasurementStore { val lastIndex = renderedSegments.lastIndex var totalHeightPx = 0f var maxContentWidthPx = 0f - var codeBlockIndex = 0 for ((index, segment) in renderedSegments.withIndex()) { val isLastSegment = index == lastIndex @@ -651,9 +629,7 @@ object MeasurementStore { is RenderedSegment.CodeBlock -> { totalHeightPx += style.codeBlockStyle.marginTop - totalHeightPx += - CodeBlockContainerView.measureCodeBlockNodeHeight(segment.node, style, context, width, codeBlockIndex in wrapped) - codeBlockIndex++ + totalHeightPx += CodeBlockContainerView.measureCodeBlockNodeHeight(segment.node, style, context, width) maxContentWidthPx = width if (includeBottomMargin) { totalHeightPx += style.codeBlockStyle.marginBottom diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt index fba8adeed..9091d349a 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt @@ -9,8 +9,6 @@ data class AccessibilityLabels( val nestedBlockquote: String = "", val tableRow: String = "", val mathEquation: String = "", - val codeBlockWrap: String = "", - val codeBlockUnwrap: String = "", val rotorHeadings: String = "", val rotorLinks: String = "", val rotorImages: String = "", diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerView.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerView.kt index 932a44a6e..cba082576 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerView.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerView.kt @@ -6,7 +6,6 @@ import android.content.Context import android.graphics.Canvas import android.graphics.ColorFilter import android.graphics.Paint -import android.graphics.Path import android.graphics.PixelFormat import android.graphics.Typeface import android.graphics.drawable.Drawable @@ -26,8 +25,6 @@ import android.widget.HorizontalScrollView import android.widget.ImageView import androidx.appcompat.widget.AppCompatImageButton import androidx.appcompat.widget.AppCompatTextView -import androidx.core.graphics.PathParser -import com.swmansion.enriched.markdown.accessibility.AccessibilityLabels import com.swmansion.enriched.markdown.parser.MarkdownASTNode import com.swmansion.enriched.markdown.spans.LineHeightSpan import com.swmansion.enriched.markdown.styles.CodeBlockStyle @@ -50,9 +47,8 @@ import kotlin.math.roundToInt * * measureCodeBlockNodeHeight must stay in sync with the view: it builds the * same styled text, paint, and header metrics, so the height reported to - * Yoga matches the laid-out height. Unless the block is wrapped (the optional - * header wrap toggle), lines never wrap and the height is independent of the - * available width. + * Yoga matches the laid-out height. Since lines never wrap, the height is + * independent of the available width. */ class CodeBlockContainerView( context: Context, @@ -73,18 +69,9 @@ class CodeBlockContainerView( // created later see the same current values. See DynamicBlockProps. var dynamicProps: DynamicBlockProps = DynamicBlockProps() - // Wrap toggle labels (see AccessibilityLabels); the copy label lives on dynamicProps. - var accessibilityLabels: AccessibilityLabels = AccessibilityLabels() - set(value) { - if (field == value) return - field = value - updateWrapButtonAppearance() - } - private var code: String = "" private var language: String? = null private var fenceChar: String = "`" - private var appliedTextMaxWidth = Int.MAX_VALUE // True until the closing fence arrives: highlighting is deferred and copying // is disabled, while the header stays visible. @@ -98,30 +85,6 @@ class CodeBlockContainerView( rebuildCodeText() } - // Shows the header wrap toggle next to the copy button. Set by the root host - // from the enableCodeBlockWrapToggle prop. - var showsWrapButton: Boolean = false - set(value) { - if (field == value) return - field = value - wrapButton.visibility = if (value) View.VISIBLE else View.GONE - requestLayout() - } - - // Wraps long lines at the block width instead of scrolling horizontally. - var wrapped: Boolean = false - set(value) { - if (field == value) return - field = value - updateWrapButtonAppearance() - if (value) scrollView.scrollTo(0, 0) - requestLayout() - } - - // Fired after the header toggle flips [wrapped], so the host can remember the - // choice and re-measure. - var onWrapToggle: ((CodeBlockContainerView) -> Unit)? = null - private val textView = AppCompatTextView(context).apply { includeFontPadding = false @@ -179,17 +142,6 @@ class CodeBlockContainerView( setOnClickListener { copyCode() } } - private val wrapIcon = WrapIconDrawable(codeBlockStyle.color, ceil(codeBlockStyle.fontSize * HEADER_ICON_SCALE).toInt()) - - private val wrapButton = - AppCompatImageButton(context).apply { - background = null - scaleType = ImageView.ScaleType.CENTER - visibility = View.GONE - setImageDrawable(wrapIcon) - setOnClickListener { toggleWrap() } - } - private val dividerPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = dividerColor(codeBlockStyle.color) @@ -203,7 +155,7 @@ class CodeBlockContainerView( override fun onDown(e: MotionEvent): Boolean = true override fun onSingleTapUp(e: MotionEvent): Boolean { - if (isPointInsideHeaderButton(e.x, e.y)) return false + if (isPointInsideCopyButton(e.x, e.y)) return false handleCodeBlockPress() return false } @@ -225,19 +177,6 @@ class CodeBlockContainerView( addView(scrollView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)) addView(languageView, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)) addView(copyButton, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)) - addView(wrapButton, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)) - updateWrapButtonAppearance() - } - - private fun updateWrapButtonAppearance() { - // Full-strength tint marks the toggle as on; off matches the copy button. - wrapIcon.setColor(if (wrapped) codeBlockStyle.color else secondaryColor(codeBlockStyle.color)) - wrapButton.contentDescription = if (wrapped) accessibilityLabels.codeBlockUnwrap else accessibilityLabels.codeBlockWrap - } - - private fun toggleWrap() { - wrapped = !wrapped - onWrapToggle?.invoke(this) } fun applyCodeBlockNode(node: MarkdownASTNode) { @@ -267,22 +206,15 @@ class CodeBlockContainerView( heightSpec: Int, ) { val measuredWidth = MeasureSpec.getSize(widthSpec) - val paneWidth = (measuredWidth - borderW * 2).coerceAtLeast(0) - // The scroll view measures its child unbounded; a max width makes the text wrap inside the pane. - val textMaxWidth = if (wrapped) paneWidth.coerceAtLeast(1) else Int.MAX_VALUE - if (textMaxWidth != appliedTextMaxWidth) { - appliedTextMaxWidth = textMaxWidth - textView.maxWidth = textMaxWidth - } scrollView.measure( - MeasureSpec.makeMeasureSpec(paneWidth, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec((measuredWidth - borderW * 2).coerceAtLeast(0), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), ) - val buttonSpec = MeasureSpec.makeMeasureSpec(headerH, MeasureSpec.EXACTLY) - copyButton.measure(buttonSpec, buttonSpec) - wrapButton.measure(buttonSpec, buttonSpec) - val headerButtonsWidth = if (showsWrapButton) headerH * 2 else headerH - val labelMaxWidth = (measuredWidth - inset * 2 - headerButtonsWidth).coerceAtLeast(0) + copyButton.measure( + MeasureSpec.makeMeasureSpec(headerH, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(headerH, MeasureSpec.EXACTLY), + ) + val labelMaxWidth = (measuredWidth - inset * 2 - headerH).coerceAtLeast(0) languageView.measure( MeasureSpec.makeMeasureSpec(labelMaxWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), @@ -318,9 +250,6 @@ class CodeBlockContainerView( buttonLeft + copyButton.measuredWidth, buttonTop + copyButton.measuredHeight, ) - // The wrap toggle sits one button-width left of copy, in the same row. - val wrapLeft = (buttonLeft - wrapButton.measuredWidth).coerceAtLeast(0) - wrapButton.layout(wrapLeft, buttonTop, wrapLeft + wrapButton.measuredWidth, buttonTop + wrapButton.measuredHeight) scrollView.layout(borderW, headerH, width - borderW, bottom - top - borderW) } @@ -361,16 +290,10 @@ class CodeBlockContainerView( return super.dispatchTouchEvent(ev) } - private fun isPointInsideHeaderButton( - x: Float, - y: Float, - ): Boolean = isPointInside(copyButton, x, y) || (wrapButton.visibility == View.VISIBLE && isPointInside(wrapButton, x, y)) - - private fun isPointInside( - view: View, + private fun isPointInsideCopyButton( x: Float, y: Float, - ): Boolean = x >= view.left && x < view.right && y >= view.top && y < view.bottom + ): Boolean = x >= copyButton.left && x < copyButton.right && y >= copyButton.top && y < copyButton.bottom private fun copyFencedMarkdown() { if (code.isEmpty()) return @@ -417,54 +340,7 @@ class CodeBlockContainerView( override fun getOpacity() = PixelFormat.TRANSLUCENT } - // Material "wrap_text" glyph, drawn from its 24-unit path at the copy glyph's size. - private class WrapIconDrawable( - color: Int, - private val size: Int, - ) : Drawable() { - private val paint = - Paint(Paint.ANTI_ALIAS_FLAG).apply { - style = Paint.Style.FILL - this.color = color - } - - fun setColor(color: Int) { - paint.color = color - invalidateSelf() - } - - override fun draw(canvas: Canvas) { - val scale = bounds.width() / 24f - val saved = canvas.save() - canvas.translate(bounds.left.toFloat(), bounds.top.toFloat()) - canvas.scale(scale, scale) - canvas.drawPath(WRAP_TEXT_PATH, paint) - canvas.restoreToCount(saved) - } - - override fun getIntrinsicWidth() = size - - override fun getIntrinsicHeight() = size - - override fun setAlpha(alpha: Int) { - paint.alpha = alpha - } - - override fun setColorFilter(colorFilter: ColorFilter?) { - paint.colorFilter = colorFilter - } - - @Deprecated("Deprecated in Java") - override fun getOpacity() = PixelFormat.TRANSLUCENT - } - companion object { - private val WRAP_TEXT_PATH: Path by lazy { - PathParser.createPathFromPathData( - "M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z", - ) - } - private const val HEADER_LABEL_SCALE = 0.85f // Drawable box for the copy glyph, as a multiple of the code font size. @@ -513,16 +389,14 @@ class CodeBlockContainerView( } } - // Unwrapped lines never wrap (the code pane scrolls horizontally), so the - // layout is built at the text's desired width and the result is independent - // of the available width. A wrapped block lays out at the pane's text width - // instead, the same width the view caps its text view at. + // Lines never wrap (the code pane scrolls horizontally), so the layout is + // built at the text's desired width and the result is independent of the + // available width. fun measureCodeBlockNodeHeight( node: MarkdownASTNode, config: StyleConfig, context: Context, - width: Float, - wrapped: Boolean = false, + @Suppress("unused") width: Float, ): Float { val style = config.codeBlockStyle val inset = contentInset(style) @@ -530,16 +404,7 @@ class CodeBlockContainerView( val text = buildCodeText(CodeBlockNode.extractCode(node), style) if (text.isEmpty()) return headerH + inset * 2f val paint = createCodePaint(style, context) - val layoutWidth = - if (wrapped) { - val borderW = borderPx(style) - val horizontalPad = (inset - borderW).coerceAtLeast(0) - // Mirrors onMeasure: the text view is capped at the pane width (at least 1px), padding included. - (ceil(width).toInt() - borderW * 2).coerceAtLeast(1) - horizontalPad * 2 - } else { - ceil(Layout.getDesiredWidth(text, paint)).toInt() - } - val contentWidth = layoutWidth.coerceAtLeast(1) + val contentWidth = ceil(Layout.getDesiredWidth(text, paint)).toInt().coerceAtLeast(1) val layout = StaticLayout.Builder .obtain(text, 0, text.length, paint, contentWidth) diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentViewCreators.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentViewCreators.kt index f677c50fd..4dcaf4d1c 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentViewCreators.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/segments/SegmentViewCreators.kt @@ -146,7 +146,6 @@ object SegmentViewCreators { config: SegmentViewConfig, ) = CodeBlockContainerView(config.context, config.style).apply { dynamicProps = config.dynamicProps - accessibilityLabels = config.accessibilityLabels applyCodeBlockNode(segment.node) } diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt index 40ef07bff..b4d3cdc5f 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt @@ -181,7 +181,6 @@ fun parseAccessibilityLabels(value: ReadableMap?): AccessibilityLabels { val blockquote = value.getMap("blockquote") val table = value.getMap("table") val math = value.getMap("math") - val codeBlock = value.getMap("codeBlock") val rotor = value.getMap("rotor") return AccessibilityLabels( bulletPoint = list?.getString("bulletPoint") ?: "", @@ -192,8 +191,6 @@ fun parseAccessibilityLabels(value: ReadableMap?): AccessibilityLabels { nestedBlockquote = blockquote?.getString("nestedQuote") ?: "", tableRow = table?.getString("row") ?: "", mathEquation = math?.getString("equation") ?: "", - codeBlockWrap = codeBlock?.getString("wrap") ?: "", - codeBlockUnwrap = codeBlock?.getString("unwrap") ?: "", rotorHeadings = rotor?.getString("headings") ?: "", rotorLinks = rotor?.getString("links") ?: "", rotorImages = rotor?.getString("images") ?: "", diff --git a/packages/react-native-enriched-markdown/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h b/packages/react-native-enriched-markdown/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h index fd78a9446..daca4ce8b 100644 --- a/packages/react-native-enriched-markdown/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +++ b/packages/react-native-enriched-markdown/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h @@ -47,8 +47,6 @@ inline folly::dynamic toDynamic(const EnrichedMarkdownProps &props) { serializedProps["maxFontSizeMultiplier"] = props.maxFontSizeMultiplier; serializedProps["allowTrailingMargin"] = props.allowTrailingMargin; serializedProps["streamingAnimation"] = props.streamingAnimation; - // Wrapped code blocks measure at the block width; the indexes live in MeasurementStore. - serializedProps["enableCodeBlockWrapToggle"] = props.enableCodeBlockWrapToggle; serializedProps["enableImageSourceResolution"] = props.enableImageSourceResolution; serializedProps["imageSourcesRevision"] = props.imageSourcesRevision; diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerViewTest.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerViewTest.kt deleted file mode 100644 index 2860211f5..000000000 --- a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/segments/CodeBlockContainerViewTest.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.swmansion.enriched.markdown.segments - -import android.graphics.Color -import android.view.View.MeasureSpec -import com.facebook.react.bridge.JavaOnlyMap -import com.facebook.react.uimanager.DisplayMetricsHolder -import com.swmansion.enriched.markdown.keepsCodeBlockWrapState -import com.swmansion.enriched.markdown.parser.MarkdownASTNode -import com.swmansion.enriched.markdown.parser.MarkdownASTNode.NodeType -import com.swmansion.enriched.markdown.styles.StyleConfig -import org.junit.Assert.assertEquals -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.RuntimeEnvironment -import org.robolectric.annotation.Config -import org.robolectric.annotation.GraphicsMode - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [30]) -@GraphicsMode(GraphicsMode.Mode.NATIVE) -class CodeBlockContainerViewTest { - private val context = RuntimeEnvironment.getApplication() - - @Test - fun measuredHeightMatchesTheLaidOutViewWrappedAndUnwrapped() { - val config = styleConfig() - val line = "val values = listOf(" + (1..60).joinToString(", ") { "item$it" } + ")" - val node = - MarkdownASTNode( - NodeType.CodeBlock, - attributes = mapOf("fenceChar" to "`", "language" to "kotlin"), - children = listOf(MarkdownASTNode(NodeType.Text, "$line\n")), - ) - - for (width in listOf(240, 360, 600)) { - val view = CodeBlockContainerView(context, config).apply { applyCodeBlockNode(node) } - - fun measure(wrapped: Boolean): Int { - view.wrapped = wrapped - view.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)) - return view.measuredHeight - } - - val unwrapped = measure(false) - assertEquals( - "unwrapped at width $width", - CodeBlockContainerView.measureCodeBlockNodeHeight(node, config, context, width.toFloat(), false), - unwrapped.toFloat(), - 0f, - ) - val wrapped = measure(true) - assertEquals( - "wrapped at width $width", - CodeBlockContainerView.measureCodeBlockNodeHeight(node, config, context, width.toFloat(), true), - wrapped.toFloat(), - 0f, - ) - assertTrue("wrapped $wrapped should be taller than unwrapped $unwrapped at width $width", wrapped > unwrapped) - } - } - - @Test - fun wrapStateSurvivesOnlyInPlaceGrowth() { - val block = "```kotlin\nval a = 1\n```\n" - assertTrue("streaming append", keepsCodeBlockWrapState("Intro\n\n```kotlin\nval a", "Intro\n\n$block")) - assertTrue("identical markdown", keepsCodeBlockWrapState("Intro\n\n$block", "Intro\n\n$block")) - assertTrue("unfinished last line rewritten", keepsCodeBlockWrapState("$block\nSee *wrappedCodeBlockIndices; @end NS_ASSUME_NONNULL_END diff --git a/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.mm b/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.mm index 4d92d0c84..9cd82174a 100644 --- a/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.mm +++ b/packages/react-native-enriched-markdown/ios/EnrichedMarkdown.mm @@ -98,7 +98,6 @@ - (void)emitContextMenuItemPress:(NSString *)itemText selectedText:(NSString *)selectedText selectionStart:(NSUInteger)selectionStart selectionEnd:(NSUInteger)selectionEnd; -@property (atomic, copy, readwrite) NSSet *wrappedCodeBlockIndices; @end #if !TARGET_OS_OSX @@ -139,7 +138,6 @@ @implementation EnrichedMarkdown { ENRMCodeBlockStreamingMode _codeBlockStreamingMode; // Trailing code block whose closing fence hasn't streamed in yet, if any. ENRMCodeBlockSegment *_pendingCodeBlockSegment; - BOOL _enableCodeBlockWrapToggle; size_t _renderedStyleFingerprint; size_t _pendingStyleFingerprint; @@ -246,7 +244,6 @@ - (instancetype)initWithFrame:(CGRect)frame _enableLinkPreview = YES; _enableTaskListItemToggle = YES; _enableImagePress = NO; - self.wrappedCodeBlockIndices = [NSSet set]; _dynamicBlockProps = [[ENRMDynamicBlockProps alloc] init]; _linkContextMenus = [[ENRMLinkContextMenus alloc] init]; __weak EnrichedMarkdown *weakMenuSelf = self; @@ -766,8 +763,6 @@ - (void)pushAccessibilityLabelsToSegments ((TableContainerView *)segment).accessibilityLabels = _accessibilityLabels; } else if ([segment isKindOfClass:[ENRMBlockquoteContainerView class]]) { ((ENRMBlockquoteContainerView *)segment).accessibilityLabels = _accessibilityLabels; - } else if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]]) { - ((ENRMCodeBlockContainerView *)segment).accessibilityLabels = _accessibilityLabels; } #if ENRICHED_MARKDOWN_MATH else if ([segment isKindOfClass:[ENRMMathContainerView class]]) { @@ -1012,7 +1007,6 @@ - (void)applyRenderedSegments:(NSArray *)renderedSegments self->_pendingCodeBlockSegment != nil && i == self->_segmentViews.count - 1; } }]; - [self syncCodeBlockWrapState]; CGRect contentBounds = [self contentBounds]; if (contentBounds.size.width > 0) { @@ -1148,7 +1142,6 @@ - (ENRMCodeBlockContainerView *)createCodeBlockViewForSegment:(ENRMCodeBlockSegm { ENRMCodeBlockContainerView *codeBlockView = [[ENRMCodeBlockContainerView alloc] initWithConfig:_config]; codeBlockView.dynamicProps = _dynamicBlockProps; - codeBlockView.accessibilityLabels = _accessibilityLabels; __weak EnrichedMarkdown *weakSelf = self; codeBlockView.onCopyPress = ^(NSString *code, NSString *language) { @@ -1161,53 +1154,12 @@ - (ENRMCodeBlockContainerView *)createCodeBlockViewForSegment:(ENRMCodeBlockSegm if (strongSelf) [strongSelf emitCodeBlockPress:code language:language]; }; - codeBlockView.onWrapToggle = ^(ENRMCodeBlockContainerView *view) { [weakSelf codeBlockDidToggleWrap:view]; }; codeBlockView.pending = codeBlockSegment == _pendingCodeBlockSegment; [codeBlockView applyCodeBlockNode:codeBlockSegment.codeBlockNode]; return codeBlockView; } -// Wrap state is keyed by a code block's position among the top-level code -// blocks, so it survives streaming updates and segment recreation; the view-free -// measure pass reads the same indexes (see wrappedCodeBlockIndices). -- (void)syncCodeBlockWrapState -{ - NSSet *wrapped = self.wrappedCodeBlockIndices; - NSUInteger codeBlockIndex = 0; - for (RCTUIView *segment in _segmentViews) { - if (![segment isKindOfClass:[ENRMCodeBlockContainerView class]]) { - continue; - } - ENRMCodeBlockContainerView *codeBlock = (ENRMCodeBlockContainerView *)segment; - codeBlock.showsWrapButton = _enableCodeBlockWrapToggle; - codeBlock.wrapped = _enableCodeBlockWrapToggle && [wrapped containsObject:@(codeBlockIndex)]; - codeBlockIndex++; - } -} - -- (void)codeBlockDidToggleWrap:(ENRMCodeBlockContainerView *)view -{ - NSUInteger codeBlockIndex = 0; - for (RCTUIView *segment in _segmentViews) { - if (segment == view) { - NSMutableSet *wrapped = [self.wrappedCodeBlockIndices mutableCopy]; - if (view.wrapped) { - [wrapped addObject:@(codeBlockIndex)]; - } else { - [wrapped removeObject:@(codeBlockIndex)]; - } - self.wrappedCodeBlockIndices = wrapped; - [self setNeedsLayout]; - [self requestHeightUpdate]; - return; - } - if ([segment isKindOfClass:[ENRMCodeBlockContainerView class]]) { - codeBlockIndex++; - } - } -} - - (void)animateBlockViewIfNeeded:(RCTUIView *)view { if (!_streamingAnimation) @@ -1260,17 +1212,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & BOOL markdownChanged = oldViewProps.markdown != newViewProps.markdown; if (markdownChanged) { _dirtyFlags |= ENRMDirtyRender; - // Wrap state is keyed by block position, so it only stays meaningful while - // the document grows in place. Streaming may rewrite its unfinished last line - // (an HTML tag closing, a link relabeled); anything earlier changing - a - // recycled cell, an edited message, a block inserted above - starts unwrapped. - const auto &previous = oldViewProps.markdown; - const auto lastNewline = previous.rfind('\n'); - const auto stablePrefix = lastNewline == std::string::npos ? std::string() : previous.substr(0, lastNewline); - if (self.wrappedCodeBlockIndices.count > 0 && newViewProps.markdown.rfind(stablePrefix, 0) != 0) { - self.wrappedCodeBlockIndices = [NSSet set]; - _dirtyFlags |= ENRMDirtyForceHeight; - } } NSDictionary *mediaOverrides = ENRMMediaOverridesFromProps(newViewProps); @@ -1405,19 +1346,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & _dynamicBlockProps.enableBlockContextMenu = newViewProps.enableBlockContextMenu; _dynamicBlockProps.enableCodeBlockPress = newViewProps.enableCodeBlockPress; - if (_enableCodeBlockWrapToggle != newViewProps.enableCodeBlockWrapToggle) { - _enableCodeBlockWrapToggle = newViewProps.enableCodeBlockWrapToggle; - BOOL hadWrappedBlocks = self.wrappedCodeBlockIndices.count > 0; - if (!_enableCodeBlockWrapToggle) { - self.wrappedCodeBlockIndices = [NSSet set]; - } - [self syncCodeBlockWrapState]; - if (hadWrappedBlocks && !_enableCodeBlockWrapToggle) { - [self setNeedsLayout]; - [self requestHeightUpdate]; - } - } - if (newViewProps.streamingAnimation != oldViewProps.streamingAnimation) { _streamingAnimation = newViewProps.streamingAnimation; _dirtyFlags |= ENRMDirtyForceHeight | ENRMDirtyRender; @@ -1485,10 +1413,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.table.row.c_str()]; _accessibilityLabels.mathEquation = [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.math.equation.c_str()]; - _accessibilityLabels.codeBlockWrap = - [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.codeBlock.wrap.c_str()]; - _accessibilityLabels.codeBlockUnwrap = - [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.codeBlock.unwrap.c_str()]; _accessibilityLabels.rotorHeadings = [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.rotor.headings.c_str()]; _accessibilityLabels.rotorLinks = @@ -1610,8 +1534,6 @@ - (void)prepareForRecycle _tableStreamingMode = ENRMTableStreamingModeProgressive; _codeBlockStreamingMode = ENRMCodeBlockStreamingModeProgressive; _pendingCodeBlockSegment = nil; - _enableCodeBlockWrapToggle = NO; - self.wrappedCodeBlockIndices = [NSSet set]; _lineBreakStrategy = NSLineBreakStrategyNone; _writingDirectionMode = ENRMWritingDirectionModeFirstStrong; _renderedStyleFingerprint = 0; diff --git a/packages/react-native-enriched-markdown/ios/EnrichedMarkdownText.mm b/packages/react-native-enriched-markdown/ios/EnrichedMarkdownText.mm index 331b2bcd6..43b3a3796 100644 --- a/packages/react-native-enriched-markdown/ios/EnrichedMarkdownText.mm +++ b/packages/react-native-enriched-markdown/ios/EnrichedMarkdownText.mm @@ -768,10 +768,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.table.row.c_str()]; _accessibilityLabels.mathEquation = [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.math.equation.c_str()]; - _accessibilityLabels.codeBlockWrap = - [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.codeBlock.wrap.c_str()]; - _accessibilityLabels.codeBlockUnwrap = - [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.codeBlock.unwrap.c_str()]; _accessibilityLabels.rotorHeadings = [[NSString alloc] initWithUTF8String:newViewProps.accessibilityLabels.rotor.headings.c_str()]; _accessibilityLabels.rotorLinks = diff --git a/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h b/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h index 8cb91b8e9..6aa96222b 100644 --- a/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h +++ b/packages/react-native-enriched-markdown/ios/internals/ENRMViewFreeMeasurement.h @@ -233,15 +233,11 @@ static inline CGSize ENRMMeasureMarkdownViewFree(const PropsT &typedProps, CGFlo * same condition, tables report full width. Finishes with `measureSize:`'s * pixel rounding (width capped at maxWidth) and its * (maxWidth × system-16 line height) fallback for empty/failed content. - * `wrappedCodeBlocks` holds the document-order indexes of top-level code blocks - * the user wrapped (EnrichedMarkdown.wrappedCodeBlockIndices); those measure at - * the block width instead of their unwrapped height. */ template static inline CGSize ENRMMeasureSegmentedMarkdownViewFree(const PropsT &typedProps, CGFloat maxWidth, CGFloat fontScale, CGFloat pointScaleFactor, - NSWritingDirection resolvedLayoutDirection, - NSSet *wrappedCodeBlocks = nil) + NSWritingDirection resolvedLayoutDirection) { @autoreleasepool { CGSize fallback = CGSizeMake(maxWidth, UIFontLineHeight([UIFont systemFontOfSize:16.0])); @@ -308,7 +304,6 @@ static inline CGSize ENRMMeasureSegmentedMarkdownViewFree(const PropsT &typedPro CGFloat yOffset = 0.0; CGFloat maxContentWidth = 0.0; const NSUInteger lastIndex = segments.count - 1; - NSUInteger codeBlockIndex = 0; for (NSUInteger i = 0; i < segments.count; i++) { ENRMRenderedSegment *segment = segments[i]; @@ -342,13 +337,8 @@ static inline CGSize ENRMMeasureSegmentedMarkdownViewFree(const PropsT &typedPro } } else if (segment.kind == ENRMSegmentKindCodeBlock && segment.codeBlockSegment) { yOffset += config.codeBlockMarginTop; - MarkdownASTNode *codeBlockNode = segment.codeBlockSegment.codeBlockNode; - yOffset += [wrappedCodeBlocks containsObject:@(codeBlockIndex)] - ? [ENRMCodeBlockContainerView measureWrappedHeightForCodeBlockNode:codeBlockNode - config:config - maxWidth:maxWidth] - : [ENRMCodeBlockContainerView measureHeightForCodeBlockNode:codeBlockNode config:config]; - codeBlockIndex++; + yOffset += [ENRMCodeBlockContainerView measureHeightForCodeBlockNode:segment.codeBlockSegment.codeBlockNode + config:config]; maxContentWidth = maxWidth; if (shouldAddBottomMargin) { yOffset += config.codeBlockMarginBottom; diff --git a/packages/react-native-enriched-markdown/ios/internals/EnrichedMarkdownShadowNode.mm b/packages/react-native-enriched-markdown/ios/internals/EnrichedMarkdownShadowNode.mm index 3405c6ea5..ac9b15897 100644 --- a/packages/react-native-enriched-markdown/ios/internals/EnrichedMarkdownShadowNode.mm +++ b/packages/react-native-enriched-markdown/ios/internals/EnrichedMarkdownShadowNode.mm @@ -50,17 +50,6 @@ } } -// Order-independent fingerprint of the wrapped set for the measurement cache -// key: 0 for none, and {0} hashes apart from {} (HashUtils::combine is not 0 at 0). -static size_t ENRMWrappedCodeBlocksFingerprint(NSSet *wrappedCodeBlocks) -{ - size_t h = 0; - for (NSNumber *index in [wrappedCodeBlocks.allObjects sortedArrayUsingSelector:@selector(compare:)]) { - HashUtils::hash_one(h, index.unsignedLongValue); - } - return h; -} - Size EnrichedMarkdownShadowNode::measureContent(const LayoutContext &layoutContext, const LayoutConstraints &layoutConstraints) const { @@ -73,20 +62,13 @@ static size_t ENRMWrappedCodeBlocksFingerprint(NSSet *wrappedCodeBlo ? NSWritingDirectionRightToLeft : NSWritingDirectionLeftToRight; - // Wrapped code blocks are view state, not props, so they join the cache key by fingerprint. - const auto componentViewRef = getStateData().getComponentViewRef(); - RCTInternalGenericWeakWrapper *weakWrapper = (RCTInternalGenericWeakWrapper *)unwrapManagedObject(componentViewRef); - EnrichedMarkdown *view = weakWrapper ? (EnrichedMarkdown *)weakWrapper.object : nil; - NSSet *wrappedCodeBlocks = typedProps.enableCodeBlockWrapToggle ? view.wrappedCodeBlockIndices : nil; - return ENRMMeasureMarkdownContent( - typedProps, componentViewRef, receivedCounter, lastExactMeasurementCounter_, lastExactMeasurementSize_, - MarkdownFlavor::GitHub, layoutContext, layoutConstraints, - ^(EnrichedMarkdown *measuredView, CGFloat maxWidth, CGFloat fontScale) { + typedProps, getStateData().getComponentViewRef(), receivedCounter, lastExactMeasurementCounter_, + lastExactMeasurementSize_, MarkdownFlavor::GitHub, layoutContext, layoutConstraints, + ^(EnrichedMarkdown *view, CGFloat maxWidth, CGFloat fontScale) { return ENRMMeasureSegmentedMarkdownViewFree(*props, maxWidth, fontScale, pointScaleFactor, - resolvedLayoutDirection, wrappedCodeBlocks); - }, - ENRMWrappedCodeBlocksFingerprint(wrappedCodeBlocks)); + resolvedLayoutDirection); + }); } } // namespace facebook::react diff --git a/packages/react-native-enriched-markdown/ios/internals/MeasurementCache.h b/packages/react-native-enriched-markdown/ios/internals/MeasurementCache.h index dbd7e959c..c69302c7c 100644 --- a/packages/react-native-enriched-markdown/ios/internals/MeasurementCache.h +++ b/packages/react-native-enriched-markdown/ios/internals/MeasurementCache.h @@ -47,8 +47,6 @@ struct MeasurementCacheKey { bool md4cFlagsAdmonitions; size_t styleFingerprint; size_t linkPillContentFingerprint; - // Code blocks the user wrapped (view state, not props); 0 when none. - size_t wrappedCodeBlocksFingerprint; CGFloat fontScale; MarkdownFlavor flavor; std::string lineBreakStrategyIOS; @@ -63,16 +61,15 @@ struct MeasurementCacheKey { return std::tie(markdown, maxWidth, allowTrailingMargin, allowFontScaling, maxFontSizeMultiplier, md4cFlagsUnderline, md4cFlagsSuperscript, md4cFlagsSubscript, md4cFlagsHighlight, md4cFlagsLatexMath, md4cFlagsHardSoftBreaks, md4cFlagsPreserveBlankLines, md4cFlagsAdmonitions, - styleFingerprint, linkPillContentFingerprint, wrappedCodeBlocksFingerprint, fontScale, flavor, - lineBreakStrategyIOS, writingDirection, numberOfLines, ellipsizeMode, linkRegexKey, - inlineCodeLinkRegexKey) == + styleFingerprint, linkPillContentFingerprint, fontScale, flavor, lineBreakStrategyIOS, + writingDirection, numberOfLines, ellipsizeMode, linkRegexKey, inlineCodeLinkRegexKey) == std::tie(other.markdown, other.maxWidth, other.allowTrailingMargin, other.allowFontScaling, other.maxFontSizeMultiplier, other.md4cFlagsUnderline, other.md4cFlagsSuperscript, other.md4cFlagsSubscript, other.md4cFlagsHighlight, other.md4cFlagsLatexMath, other.md4cFlagsHardSoftBreaks, other.md4cFlagsPreserveBlankLines, other.md4cFlagsAdmonitions, - other.styleFingerprint, other.linkPillContentFingerprint, other.wrappedCodeBlocksFingerprint, - other.fontScale, other.flavor, other.lineBreakStrategyIOS, other.writingDirection, - other.numberOfLines, other.ellipsizeMode, other.linkRegexKey, other.inlineCodeLinkRegexKey); + other.styleFingerprint, other.linkPillContentFingerprint, other.fontScale, other.flavor, + other.lineBreakStrategyIOS, other.writingDirection, other.numberOfLines, other.ellipsizeMode, + other.linkRegexKey, other.inlineCodeLinkRegexKey); } }; @@ -95,7 +92,6 @@ struct MeasurementCacheKeyHash { HashUtils::hash_one(h, key.md4cFlagsAdmonitions); HashUtils::hash_one(h, key.styleFingerprint); HashUtils::hash_one(h, key.linkPillContentFingerprint); - HashUtils::hash_one(h, key.wrappedCodeBlocksFingerprint); HashUtils::hash_one(h, key.fontScale); HashUtils::hash_one(h, static_cast(key.flavor)); HashUtils::hash_one(h, key.lineBreakStrategyIOS); @@ -200,7 +196,7 @@ template inline std::string buildLinkRecognitionCacheKey(c template inline MeasurementCacheKey buildMeasurementCacheKey(const PropsType &props, CGFloat maxWidth, CGFloat fontScale, - MarkdownFlavor flavor, size_t wrappedCodeBlocksFingerprint = 0) + MarkdownFlavor flavor) { return MeasurementCacheKey{ .markdown = props.markdown, @@ -219,7 +215,6 @@ inline MeasurementCacheKey buildMeasurementCacheKey(const PropsType &props, CGFl .styleFingerprint = computeStyleFingerprint(props.markdownStyle) ^ ENRMImageSourcesFingerprint(props) ^ ENRMMediaPropsFingerprint(props), .linkPillContentFingerprint = computeLinkPillContentFingerprint(props.linkPillContent), - .wrappedCodeBlocksFingerprint = wrappedCodeBlocksFingerprint, .fontScale = fontScale, .flavor = flavor, .lineBreakStrategyIOS = props.lineBreakStrategyIOS, diff --git a/packages/react-native-enriched-markdown/ios/internals/ShadowMeasurementUtils.h b/packages/react-native-enriched-markdown/ios/internals/ShadowMeasurementUtils.h index 523809baa..48defb1bf 100644 --- a/packages/react-native-enriched-markdown/ios/internals/ShadowMeasurementUtils.h +++ b/packages/react-native-enriched-markdown/ios/internals/ShadowMeasurementUtils.h @@ -87,17 +87,14 @@ static inline bool ENRMPropsNeedExactStreamingMeasurement(const PropsT &oldProps * `ENRMMeasureSegmentedMarkdownViewFree`); the resolved view is still handed * to the block for strategies that can use it. `fontScale` handed to the * block is the real multiplier even when streaming skips the cache — - * rendering must always use it. `wrappedCodeBlocksFingerprint` folds view - * state outside the props that changes the size (code blocks the user wrapped) - * into the cache key. + * rendering must always use it. */ template static inline Size ENRMMeasureMarkdownContent(const PropsT &typedProps, const std::shared_ptr &componentViewRef, int receivedCounter, int &lastExactMeasurementCounter, CGSize &lastExactMeasurementSize, MarkdownFlavor flavor, const LayoutContext &layoutContext, const LayoutConstraints &layoutConstraints, - CGSize (^measureUncached)(ViewT *view, CGFloat maxWidth, CGFloat fontScale), - size_t wrappedCodeBlocksFingerprint = 0) + CGSize (^measureUncached)(ViewT *view, CGFloat maxWidth, CGFloat fontScale)) { CGFloat maxWidth = layoutConstraints.maximumSize.width; @@ -123,7 +120,7 @@ ENRMMeasureMarkdownContent(const PropsT &typedProps, const std::shared_ptr CGFloat fontScale = ENRMFontScaleForMeasurement(typedProps.allowFontScaling, layoutContext); if (shouldUseMeasurementCache && !typedProps.markdown.empty()) { - auto cacheKey = buildMeasurementCacheKey(typedProps, maxWidth, fontScale, flavor, wrappedCodeBlocksFingerprint); + auto cacheKey = buildMeasurementCacheKey(typedProps, maxWidth, fontScale, flavor); CachedSize cached; if (MeasurementCache::shared().get(cacheKey, cached)) { return ENRMClampMeasuredSize(CGSizeMake(cached.width, cached.height), layoutConstraints); @@ -133,7 +130,7 @@ ENRMMeasureMarkdownContent(const PropsT &typedProps, const std::shared_ptr CGSize size = measureUncached(view, maxWidth, fontScale); if (shouldUseMeasurementCache && !typedProps.markdown.empty()) { - auto cacheKey = buildMeasurementCacheKey(typedProps, maxWidth, fontScale, flavor, wrappedCodeBlocksFingerprint); + auto cacheKey = buildMeasurementCacheKey(typedProps, maxWidth, fontScale, flavor); MeasurementCache::shared().set(cacheKey, {size.width, size.height}); } diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.h b/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.h index e84d65c52..e17d3dfb9 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.h +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.h @@ -4,14 +4,11 @@ #import "StyleConfig.h" @class MarkdownASTNode; -@class ENRMAccessibilityLabels; -@class ENRMCodeBlockContainerView; NS_ASSUME_NONNULL_BEGIN typedef void (^ENRMCodeBlockCopyBlock)(NSString *code, NSString *language); typedef void (^ENRMCodeBlockPressBlock)(NSString *code, NSString *language); -typedef void (^ENRMCodeBlockWrapToggleBlock)(ENRMCodeBlockContainerView *view); @interface ENRMCodeBlockContainerView : RCTUIView @@ -25,24 +22,8 @@ typedef void (^ENRMCodeBlockWrapToggleBlock)(ENRMCodeBlockContainerView *view); // instance's measureHeight: reports for the node, without building a view. + (CGFloat)measureHeightForCodeBlockNode:(MarkdownASTNode *)node config:(StyleConfig *)config; -// View-free height of the node with `wrapped` on, laid out at the block width. -+ (CGFloat)measureWrappedHeightForCodeBlockNode:(MarkdownASTNode *)node - config:(StyleConfig *)config - maxWidth:(CGFloat)maxWidth; - @property (nonatomic, strong) StyleConfig *config; -// Shows the header wrap toggle next to the copy button (iOS only). Set by the -// root host from the enableCodeBlockWrapToggle prop. -@property (nonatomic, assign) BOOL showsWrapButton; - -// Wraps long lines at the block width instead of scrolling horizontally. -@property (nonatomic, assign) BOOL wrapped; - -// Fired after the header toggle or the VoiceOver action flips `wrapped`, so the -// host can remember the choice and re-measure. -@property (nonatomic, copy, nullable) ENRMCodeBlockWrapToggleBlock onWrapToggle; - // True until the closing fence arrives: highlighting is deferred and copying is // disabled, while the header stays visible. @property (nonatomic, assign) BOOL pending; @@ -52,10 +33,6 @@ typedef void (^ENRMCodeBlockWrapToggleBlock)(ENRMCodeBlockContainerView *view); // block added after a toggle is born current. See ENRMDynamicBlockProps. @property (nonatomic, strong) ENRMDynamicBlockProps *dynamicProps; -// Wrap toggle labels (see ENRMAccessibilityLabels); the copy label lives on -// dynamicProps. -@property (nonatomic, strong, nullable) ENRMAccessibilityLabels *accessibilityLabels; - // Fired when the code is copied (header button, context-menu Copy, or the // VoiceOver copy action); set by the host to bridge up to the JS onCopyPress // event. Not fired for "Copy as Markdown". diff --git a/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.m b/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.m index 69cd0af86..53029a745 100644 --- a/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.m +++ b/packages/react-native-enriched-markdown/ios/segments/ENRMCodeBlockContainerView.m @@ -1,5 +1,4 @@ #import "ENRMCodeBlockContainerView.h" -#import "ENRMAccessibilityLabels.h" #import "ENRMCodeBlockContent.h" #import "ENRMCodeBlockHighlighter.h" #import "ENRMHorizontalScrollView.h" @@ -19,9 +18,8 @@ // // measureHeight: must stay in sync with the drawn content: it uses the // unconstrained bounding rect of the same attributed string and the same -// header metrics, so the reported height matches the drawn height. Unless the -// block is wrapped (the optional header wrap toggle), lines never wrap and the -// height is independent of the available width. +// header metrics, so the reported height matches the drawn height. Since +// lines never wrap, the height is independent of the available width. static const CGFloat kENRMHeaderLabelScale = 0.85; // The copy glyph reads cleaner a touch smaller than the language label and at a @@ -44,12 +42,6 @@ static CGFloat ENRMCodeBlockContentInset(StyleConfig *config) return [UIFont systemFontOfSize:[config codeBlockFont].pointSize * kENRMHeaderLabelScale weight:UIFontWeightMedium]; } -static UIImageSymbolConfiguration *ENRMCodeBlockHeaderSymbolConfiguration(StyleConfig *config) -{ - return [UIImageSymbolConfiguration configurationWithPointSize:[config codeBlockFont].pointSize * kENRMHeaderIconScale - weight:UIImageSymbolWeightRegular]; -} - static CGFloat ENRMCodeBlockHeaderLabelLineHeight(UIFont *headerFont) { return ceil(UIFontLineHeight(headerFont)); @@ -104,37 +96,6 @@ static CGFloat ENRMCodeBlockCodeHeight(NSString *code, StyleConfig *config) return ceil(lineCount * ENRMCodeBlockPerLineHeight(config)); } -// Width the code text gets when wrapped: the block width minus the border and -// the code pane's horizontal padding, exactly as layoutScrollArea insets it. -static CGFloat ENRMCodeBlockWrapWidth(CGFloat blockWidth, StyleConfig *config) -{ - CGFloat borderW = ceil([config codeBlockBorderWidth]); - CGFloat horizontalPad = MAX(ENRMCodeBlockContentInset(config) - borderW, 0); - return MAX(blockWidth - borderW * 2, 0) - horizontalPad * 2; -} - -// Wrapped code height: the same per-line-height arithmetic as the analytic -// height, over visual lines from a call-confined TextKit layout at the wrap width. -static CGFloat ENRMCodeBlockWrappedCodeHeight(NSAttributedString *code, CGFloat wrapWidth, StyleConfig *config) -{ - if (code.length == 0) { - return 0; - } - NSTextStorage *storage = [[NSTextStorage alloc] initWithAttributedString:code]; - NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; - layoutManager.usesFontLeading = ENRMLayoutManagerUsesFontLeading; - NSTextContainer *container = [[NSTextContainer alloc] initWithSize:CGSizeMake(wrapWidth, CGFLOAT_MAX)]; - container.lineFragmentPadding = 0; - [layoutManager addTextContainer:container]; - [storage addLayoutManager:layoutManager]; - [layoutManager ensureLayoutForTextContainer:container]; - __block NSUInteger lineCount = 0; - [layoutManager enumerateLineFragmentsForGlyphRange:NSMakeRange(0, layoutManager.numberOfGlyphs) - usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *textContainer, - NSRange glyphRange, BOOL *stop) { lineCount++; }]; - return ceil(MAX(lineCount, 1) * ENRMCodeBlockPerLineHeight(config)); -} - // Used only to pick the scroll indicator style for the code pane, so the // indicator stays visible on dark code block backgrounds without affecting // any other scroll view. @@ -171,12 +132,10 @@ static BOOL ENRMColorIsDark(RCTUIColor *color) // the same rendering path drawAtPoint used internally, so output is identical, // but the layout is no longer thrown away on every draw. The container is // unbounded (lines never wrap) with zero line-fragment padding and font leading -// disabled, matching the NSStringDrawing origin the block used before. A -// positive wrapWidth bounds it instead, so lines wrap at that width. +// disabled, matching the NSStringDrawing origin the block used before. @interface ENRMCodeBlockContentView : RCTUIView @property (nonatomic, strong, nullable) NSAttributedString *attributedCode; @property (nonatomic, assign) CGPoint textOrigin; -@property (nonatomic, assign) CGFloat wrapWidth; // Laid-out content width, for the horizontal scroll extent. Free once the // cached stack exists; no separate measurement pass. @property (nonatomic, readonly) CGFloat usedWidth; @@ -215,7 +174,7 @@ - (void)setAttributedCode:(nullable NSAttributedString *)attributedCode _textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedCode]; _layoutManager = [[NSLayoutManager alloc] init]; _layoutManager.usesFontLeading = ENRMLayoutManagerUsesFontLeading; - _textContainer = [[NSTextContainer alloc] initWithSize:[self containerSize]]; + _textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)]; _textContainer.lineFragmentPadding = 0; _textContainer.maximumNumberOfLines = 0; [_layoutManager addTextContainer:_textContainer]; @@ -223,28 +182,6 @@ - (void)setAttributedCode:(nullable NSAttributedString *)attributedCode [_layoutManager ensureLayoutForTextContainer:_textContainer]; } -- (CGSize)containerSize -{ - return CGSizeMake(_wrapWidth > 0 ? _wrapWidth : CGFLOAT_MAX, CGFLOAT_MAX); -} - -- (void)setWrapWidth:(CGFloat)wrapWidth -{ - if (_wrapWidth == wrapWidth) { - return; - } - _wrapWidth = wrapWidth; - if (_textContainer) { - _textContainer.size = [self containerSize]; - [_layoutManager ensureLayoutForTextContainer:_textContainer]; - } -#if !TARGET_OS_OSX - [self setNeedsDisplay]; -#else - [self setNeedsDisplay:YES]; -#endif -} - - (CGFloat)usedWidth { if (!_layoutManager) { @@ -284,13 +221,9 @@ @implementation ENRMCodeBlockContainerView { CGFloat _headerLabelLineHeight; NSAttributedString *_languageLabel; CGSize _languageLabelSize; - // Wrapped code height, valid for _wrappedHeightWidth until the code changes. - CGFloat _wrappedHeight; - CGFloat _wrappedHeightWidth; #if !TARGET_OS_OSX UIFont *_headerFont; UIButton *_copyButton; - UIButton *_wrapButton; UITapGestureRecognizer *_tapRecognizer; #else NSFont *_headerFont; @@ -327,7 +260,6 @@ - (instancetype)initWithConfig:(StyleConfig *)config _config = config; _cachedCode = @""; _fenceChar = @"`"; - _wrappedHeightWidth = -1; _dynamicProps = [[ENRMDynamicBlockProps alloc] init]; _headerFont = ENRMCodeBlockHeaderFont(config); _headerLabelLineHeight = ENRMCodeBlockHeaderLabelLineHeight(_headerFont); @@ -342,7 +274,9 @@ - (instancetype)initWithConfig:(StyleConfig *)config [self addInteraction:contextMenu]; _copyButton = [UIButton buttonWithType:UIButtonTypeSystem]; - UIImageSymbolConfiguration *symbolConfig = ENRMCodeBlockHeaderSymbolConfiguration(config); + UIImageSymbolConfiguration *symbolConfig = + [UIImageSymbolConfiguration configurationWithPointSize:[config codeBlockFont].pointSize * kENRMHeaderIconScale + weight:UIImageSymbolWeightRegular]; [_copyButton setImage:[UIImage systemImageNamed:@"doc.on.doc" withConfiguration:symbolConfig] forState:UIControlStateNormal]; _copyButton.tintColor = [[config codeBlockColor] colorWithAlphaComponent:kENRMHeaderSecondaryAlpha]; @@ -406,17 +340,12 @@ - (void)layoutScrollArea _scrollView.frame = frame; CGFloat horizontalPad = MAX(inset - borderW, 0); - _codeContentView.wrapWidth = _wrapped ? MAX(ENRMCodeBlockWrapWidth(self.bounds.size.width, _config), 1) : 0; - CGFloat codeWidth = _wrapped ? 0 : _codeSize.width; - CGFloat contentWidth = MAX(codeWidth + horizontalPad * 2, frame.size.width); + CGFloat contentWidth = MAX(_codeSize.width + horizontalPad * 2, frame.size.width); _codeContentView.textOrigin = CGPointMake(horizontalPad, inset); _codeContentView.frame = CGRectMake(0, 0, contentWidth, frame.size.height); #if !TARGET_OS_OSX _scrollView.contentSize = CGSizeMake(contentWidth, frame.size.height); _scrollView.scrollEnabled = contentWidth > frame.size.width; - if (_wrapped) { - _scrollView.contentOffset = CGPointZero; - } #endif } @@ -443,85 +372,6 @@ - (void)layoutHeaderButton CGFloat buttonLeft = MAX(self.bounds.size.width - [self contentInset] - headerH + iconSlack, 0); CGFloat buttonTop = MAX([self headerCenterY] - headerH / 2, 0); _copyButton.frame = CGRectMake(buttonLeft, buttonTop, headerH, headerH); -#if !TARGET_OS_OSX - // The wrap toggle sits one button-width left of copy, in the same row. - _wrapButton.frame = CGRectMake(MAX(buttonLeft - headerH, 0), buttonTop, headerH, headerH); -#endif -} - -#if !TARGET_OS_OSX -- (void)setShowsWrapButton:(BOOL)showsWrapButton -{ - if (_showsWrapButton == showsWrapButton) { - return; - } - _showsWrapButton = showsWrapButton; - if (showsWrapButton && !_wrapButton) { - _wrapButton = [UIButton buttonWithType:UIButtonTypeSystem]; - [_wrapButton setImage:[UIImage systemImageNamed:@"text.alignleft" - withConfiguration:ENRMCodeBlockHeaderSymbolConfiguration(_config)] - forState:UIControlStateNormal]; - [_wrapButton addTarget:self action:@selector(toggleWrap) forControlEvents:UIControlEventTouchUpInside]; - [self addSubview:_wrapButton]; - [self updateWrapButtonAppearance]; - } - _wrapButton.hidden = !showsWrapButton; - [self setNeedsLayout]; -} - -- (void)updateWrapButtonAppearance -{ - // Full-strength tint marks the toggle as on; off matches the copy button. - CGFloat alpha = _wrapped ? 1 : kENRMHeaderSecondaryAlpha; - _wrapButton.tintColor = [[_config codeBlockColor] colorWithAlphaComponent:alpha]; - _wrapButton.accessibilityLabel = [self wrapActionLabel]; -} -#endif - -- (NSString *)wrapActionLabel -{ - return _wrapped ? _accessibilityLabels.codeBlockUnwrap : _accessibilityLabels.codeBlockWrap; -} - -- (void)setAccessibilityLabels:(ENRMAccessibilityLabels *)labels -{ - if (_accessibilityLabels == labels) { - return; - } - _accessibilityLabels = labels; -#if !TARGET_OS_OSX - [self updateWrapButtonAppearance]; -#endif -} - -- (void)setWrapped:(BOOL)wrapped -{ - if (_wrapped == wrapped) { - return; - } - _wrapped = wrapped; - if (!wrapped) { - // The scroll extent reads the unwrapped width, which a rebuild while wrapped - // measured at the wrap width. - _codeContentView.wrapWidth = 0; - _codeSize.width = _codeContentView.usedWidth; - } -#if !TARGET_OS_OSX - [self updateWrapButtonAppearance]; - [self setNeedsLayout]; - [_codeContentView setNeedsDisplay]; -#else - self.needsLayout = YES; - [_codeContentView setNeedsDisplay:YES]; -#endif -} - -- (void)toggleWrap -{ - self.wrapped = !_wrapped; - if (self.onWrapToggle) { - self.onWrapToggle(self); - } } #if !TARGET_OS_OSX @@ -564,7 +414,6 @@ - (void)rebuildAttributedCode // width then reads out of that layout, and height stays analytic. _codeContentView.attributedCode = _attributedCode; _codeSize = CGSizeMake(_codeContentView.usedWidth, ENRMCodeBlockCodeHeight(_cachedCode, _config)); - _wrappedHeightWidth = -1; } - (void)applyCodeBlockNode:(MarkdownASTNode *)node @@ -630,16 +479,7 @@ - (CGFloat)contentInset - (CGFloat)measureHeight:(CGFloat)maxWidth { CGFloat inset = [self contentInset]; - CGFloat codeHeight = _codeSize.height; - if (_wrapped) { - if (_wrappedHeightWidth != maxWidth) { - _wrappedHeight = ENRMCodeBlockWrappedCodeHeight([self plainAttributedCode], - MAX(ENRMCodeBlockWrapWidth(maxWidth, _config), 1), _config); - _wrappedHeightWidth = maxWidth; - } - codeHeight = _wrappedHeight; - } - return codeHeight + inset * 2 + [self headerHeight]; + return _codeSize.height + inset * 2 + [self headerHeight]; } + (CGFloat)measureHeightForCodeBlockNode:(MarkdownASTNode *)node config:(StyleConfig *)config @@ -650,17 +490,6 @@ + (CGFloat)measureHeightForCodeBlockNode:(MarkdownASTNode *)node config:(StyleCo return codeHeight + inset * 2 + headerH; } -+ (CGFloat)measureWrappedHeightForCodeBlockNode:(MarkdownASTNode *)node - config:(StyleConfig *)config - maxWidth:(CGFloat)maxWidth -{ - CGFloat inset = ENRMCodeBlockContentInset(config); - CGFloat headerH = inset + ENRMCodeBlockHeaderLabelLineHeight(ENRMCodeBlockHeaderFont(config)); - NSAttributedString *code = ENRMCodeBlockPlainAttributedCode(ENRMCodeBlockExtractCode(node), config); - CGFloat codeHeight = ENRMCodeBlockWrappedCodeHeight(code, MAX(ENRMCodeBlockWrapWidth(maxWidth, config), 1), config); - return codeHeight + inset * 2 + headerH; -} - - (void)drawRect:(CGRect)rect { CGFloat borderWidth = [_config codeBlockBorderWidth]; @@ -747,9 +576,9 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { - // Let the header buttons handle their own taps. + // Let the copy button handle its own tap. for (UIView *hit = touch.view; hit != nil; hit = hit.superview) { - if (hit == _copyButton || (_wrapButton != nil && hit == _wrapButton)) { + if (hit == _copyButton) { return NO; } } @@ -814,22 +643,18 @@ - (UIAccessibilityTraits)accessibilityTraits return UIAccessibilityTraitStaticText; } -// The container is a single accessibility element, which hides the header -// button subviews from VoiceOver; expose their actions explicitly instead. +// The container is a single accessibility element, which hides the copy +// button subview from VoiceOver; expose the copy action explicitly instead. - (NSArray *)accessibilityCustomActions { - NSMutableArray *actions = [NSMutableArray array]; - if (!_pending && self.dynamicProps.menuCopyLabel.length > 0) { - [actions addObject:[[UIAccessibilityCustomAction alloc] initWithName:self.dynamicProps.menuCopyLabel - target:self - selector:@selector(performCopyAccessibilityAction:)]]; + if (_pending || self.dynamicProps.menuCopyLabel.length == 0) { + return @[]; } - if (_showsWrapButton && [self wrapActionLabel].length > 0) { - [actions addObject:[[UIAccessibilityCustomAction alloc] initWithName:[self wrapActionLabel] - target:self - selector:@selector(performWrapAccessibilityAction:)]]; - } - return actions; + UIAccessibilityCustomAction *copyAction = + [[UIAccessibilityCustomAction alloc] initWithName:self.dynamicProps.menuCopyLabel + target:self + selector:@selector(performCopyAccessibilityAction:)]; + return @[ copyAction ]; } - (BOOL)performCopyAccessibilityAction:(UIAccessibilityCustomAction *)action @@ -837,12 +662,6 @@ - (BOOL)performCopyAccessibilityAction:(UIAccessibilityCustomAction *)action [self copyCodeToPasteboard]; return YES; } - -- (BOOL)performWrapAccessibilityAction:(UIAccessibilityCustomAction *)action -{ - [self toggleWrap]; - return YES; -} #endif @end diff --git a/packages/react-native-enriched-markdown/ios/utils/ENRMAccessibilityLabels.h b/packages/react-native-enriched-markdown/ios/utils/ENRMAccessibilityLabels.h index 4ddfd6084..9dbeefb2e 100644 --- a/packages/react-native-enriched-markdown/ios/utils/ENRMAccessibilityLabels.h +++ b/packages/react-native-enriched-markdown/ios/utils/ENRMAccessibilityLabels.h @@ -12,8 +12,6 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) NSString *nestedBlockquote; @property (nonatomic, copy) NSString *tableRow; @property (nonatomic, copy) NSString *mathEquation; -@property (nonatomic, copy) NSString *codeBlockWrap; -@property (nonatomic, copy) NSString *codeBlockUnwrap; @property (nonatomic, copy) NSString *rotorHeadings; @property (nonatomic, copy) NSString *rotorLinks; @property (nonatomic, copy) NSString *rotorImages; @@ -32,8 +30,6 @@ template static bool ENRMAccessibilityLabelsChanged(const T &oldLab oldLabels.blockquote.quote != newLabels.blockquote.quote || oldLabels.blockquote.nestedQuote != newLabels.blockquote.nestedQuote || oldLabels.table.row != newLabels.table.row || oldLabels.math.equation != newLabels.math.equation || - oldLabels.codeBlock.wrap != newLabels.codeBlock.wrap || - oldLabels.codeBlock.unwrap != newLabels.codeBlock.unwrap || oldLabels.rotor.headings != newLabels.rotor.headings || oldLabels.rotor.links != newLabels.rotor.links || oldLabels.rotor.images != newLabels.rotor.images; } diff --git a/packages/react-native-enriched-markdown/src/EnrichedMarkdownNativeComponent.ts b/packages/react-native-enriched-markdown/src/EnrichedMarkdownNativeComponent.ts index 4b9346ffe..257f5d6a7 100644 --- a/packages/react-native-enriched-markdown/src/EnrichedMarkdownNativeComponent.ts +++ b/packages/react-native-enriched-markdown/src/EnrichedMarkdownNativeComponent.ts @@ -360,10 +360,6 @@ export interface AccessibilityLabelsTableProps { export interface AccessibilityLabelsMathProps { equation: string; } -export interface AccessibilityLabelsCodeBlockProps { - wrap: string; - unwrap: string; -} export interface AccessibilityLabelsRotorProps { headings: string; links: string; @@ -374,7 +370,6 @@ export interface AccessibilityLabelsProps { blockquote: Readonly; table: Readonly; math: Readonly; - codeBlock: Readonly; rotor: Readonly; } @@ -602,12 +597,6 @@ export interface NativeProps extends ViewProps { * @default false */ enableCodeBlockPress?: CodegenTypes.WithDefault; - /** - * Shows a per-block line wrap toggle next to the copy button in fenced code - * block headers. Each block starts unwrapped. - * @default false - */ - enableCodeBlockWrapToggle?: CodegenTypes.WithDefault; /** * Callback fired when a math expression cannot be parsed or rendered by the * LaTeX engine. Receives the raw LaTeX `source` of the failing inline span or diff --git a/packages/react-native-enriched-markdown/src/EnrichedMarkdownTextNativeComponent.ts b/packages/react-native-enriched-markdown/src/EnrichedMarkdownTextNativeComponent.ts index 1a7590886..001c380e8 100644 --- a/packages/react-native-enriched-markdown/src/EnrichedMarkdownTextNativeComponent.ts +++ b/packages/react-native-enriched-markdown/src/EnrichedMarkdownTextNativeComponent.ts @@ -361,10 +361,6 @@ export interface AccessibilityLabelsTableProps { export interface AccessibilityLabelsMathProps { equation: string; } -export interface AccessibilityLabelsCodeBlockProps { - wrap: string; - unwrap: string; -} export interface AccessibilityLabelsRotorProps { headings: string; links: string; @@ -375,7 +371,6 @@ export interface AccessibilityLabelsProps { blockquote: Readonly; table: Readonly; math: Readonly; - codeBlock: Readonly; rotor: Readonly; } diff --git a/packages/react-native-enriched-markdown/src/accessibilityLabelDefaults.ts b/packages/react-native-enriched-markdown/src/accessibilityLabelDefaults.ts index 04884ba08..bdb4857a9 100644 --- a/packages/react-native-enriched-markdown/src/accessibilityLabelDefaults.ts +++ b/packages/react-native-enriched-markdown/src/accessibilityLabelDefaults.ts @@ -25,10 +25,6 @@ export const DEFAULT_ACCESSIBILITY_LABELS: ResolvedAccessibilityLabels = { math: { equation: 'Math: {latex}', }, - codeBlock: { - wrap: 'Wrap lines', - unwrap: 'Disable line wrap', - }, rotor: { headings: 'Headings', links: 'Links', @@ -76,13 +72,6 @@ export function resolveAccessibilityLabels( equation: labels?.math?.equation ?? DEFAULT_ACCESSIBILITY_LABELS.math.equation, }, - codeBlock: { - wrap: - labels?.codeBlock?.wrap ?? DEFAULT_ACCESSIBILITY_LABELS.codeBlock.wrap, - unwrap: - labels?.codeBlock?.unwrap ?? - DEFAULT_ACCESSIBILITY_LABELS.codeBlock.unwrap, - }, rotor: { headings: labels?.rotor?.headings ?? DEFAULT_ACCESSIBILITY_LABELS.rotor.headings, diff --git a/packages/react-native-enriched-markdown/src/native/EnrichedMarkdownText.tsx b/packages/react-native-enriched-markdown/src/native/EnrichedMarkdownText.tsx index 5d602fe08..4d92f7abf 100644 --- a/packages/react-native-enriched-markdown/src/native/EnrichedMarkdownText.tsx +++ b/packages/react-native-enriched-markdown/src/native/EnrichedMarkdownText.tsx @@ -151,7 +151,6 @@ export const EnrichedMarkdownText = ({ onCopyPress, onLatexError, onCodeBlockPress, - enableCodeBlockWrapToggle = false, enableBlockContextMenu = true, enableLinkPreview, selectable = true, @@ -490,7 +489,6 @@ export const EnrichedMarkdownText = ({ @@ -502,7 +500,6 @@ export const EnrichedMarkdownText = ({ ); } diff --git a/packages/react-native-enriched-markdown/src/types/AccessibilityLabels.ts b/packages/react-native-enriched-markdown/src/types/AccessibilityLabels.ts index 383ab11a1..a53a694b0 100644 --- a/packages/react-native-enriched-markdown/src/types/AccessibilityLabels.ts +++ b/packages/react-native-enriched-markdown/src/types/AccessibilityLabels.ts @@ -74,23 +74,6 @@ export interface AccessibilityLabels { equation?: string; }; - /** - * Labels for the fenced code block header's line wrap toggle - * (`enableCodeBlockWrapToggle`). iOS + Android. - */ - codeBlock?: { - /** - * Spoken while the block scrolls horizontally. - * @default 'Wrap lines' - */ - wrap?: string; - /** - * Spoken while the block's lines are wrapped. - * @default 'Disable line wrap' - */ - unwrap?: string; - }; - /** * Labels for the VoiceOver rotor (the secondary jump-by-type navigator on iOS). * iOS only — Android has no rotor concept. @@ -127,10 +110,6 @@ export interface ResolvedAccessibilityLabels { math: { equation: string; }; - codeBlock: { - wrap: string; - unwrap: string; - }; rotor: { headings: string; links: string; diff --git a/packages/react-native-enriched-markdown/src/types/MarkdownTextProps.ts b/packages/react-native-enriched-markdown/src/types/MarkdownTextProps.ts index 26060e2ec..73233a3ea 100644 --- a/packages/react-native-enriched-markdown/src/types/MarkdownTextProps.ts +++ b/packages/react-native-enriched-markdown/src/types/MarkdownTextProps.ts @@ -299,19 +299,6 @@ export interface EnrichedMarkdownTextProps extends Omit { * @platform ios, android, web */ onCodeBlockPress?: (event: CodeBlockPressEvent) => void; - /** - * Shows a line wrap toggle next to the copy button in each fenced code block - * header. Every block starts unwrapped (horizontal scroll) and toggles on its - * own. The state belongs to the block's position in the document: it survives - * streaming appends and resets when the markdown is replaced. Code blocks - * inside blockquotes and admonitions have no toggle and keep scrolling. The - * toggle's spoken labels come from `accessibilityLabels.codeBlock`. - * - * Only applies when `flavor="github"`. - * @default false - * @platform ios, android - */ - enableCodeBlockWrapToggle?: boolean; /** * Controls the long-press context menu on block views (code blocks, tables, * and block math). When false, long-pressing a block does not open the copy diff --git a/packages/react-native-enriched-markdown/src/web/nativeProps.ts b/packages/react-native-enriched-markdown/src/web/nativeProps.ts index 111128d58..0ffb2c7ed 100644 --- a/packages/react-native-enriched-markdown/src/web/nativeProps.ts +++ b/packages/react-native-enriched-markdown/src/web/nativeProps.ts @@ -37,7 +37,6 @@ export const NATIVE_ONLY_PROP_NAMES: Record = { onCopyPress: true, onLatexError: true, enableBlockContextMenu: true, - enableCodeBlockWrapToggle: true, enableLinkPreview: true, selectionHandleColor: true, allowFontScaling: true, From 789435dd42c631bc96f1bbb59ef4f54b72bf7c86 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Fri, 16 Oct 2026 14:51:28 -0700 Subject: [PATCH 08/11] revert: drop the fork's ordered list marker width fix for upstream #1015 Upstream merged the fix as software-mansion/enriched-markdown#1015 (9fabe821), which carries #1005 (this fork's #2) plus the review follow-ups. This reverts commit d8466259. Co-Authored-By: Claude Opus 5.5 --- .../ordered_list_wide_markers_test.yaml | 163 ------ ...red_list_wide_markers_hundreds_display.png | Bin 30529 -> 0 bytes ...dered_list_wide_markers_nested_display.png | Bin 33515 -> 0 bytes ...ist_wide_markers_short_control_display.png | Bin 18555 -> 0 bytes ...ed_list_wide_markers_thousands_display.png | Bin 31267 -> 0 bytes ...red_list_wide_markers_hundreds_display.png | Bin 32647 -> 0 bytes ...dered_list_wide_markers_nested_display.png | Bin 33258 -> 0 bytes ...ist_wide_markers_short_control_display.png | Bin 19441 -> 0 bytes ...ed_list_wide_markers_thousands_display.png | Bin 32425 -> 0 bytes .../ios/OrderedListMarkerWidthTests.mm | 178 ------ .../markdown/renderer/BlockStyleContext.kt | 6 - .../markdown/renderer/ListItemRenderer.kt | 25 +- .../markdown/renderer/ListRenderer.kt | 24 - .../enriched/markdown/spans/BaseListSpan.kt | 1 - .../markdown/spans/OrderedListSpan.kt | 18 +- .../enriched/markdown/spans/TaskListSpan.kt | 4 +- .../markdown/spans/UnorderedListSpan.kt | 4 +- .../text/interaction/TaskListTapUtils.kt | 29 +- .../spans/OrderedListMarkerWidthTest.kt | 530 ------------------ .../ios/renderer/ListItemRenderer.m | 7 +- .../ios/renderer/ListRenderer.m | 19 - .../ios/renderer/RenderContext.h | 4 - .../ios/renderer/RenderContext.m | 8 - .../ios/styles/StyleConfig.h | 2 +- .../ios/styles/StyleConfig.mm | 6 +- 25 files changed, 21 insertions(+), 1007 deletions(-) delete mode 100644 .maestro/enrichedMarkdownText/flows/advanced/block_elements/ordered_list_wide_markers_test.yaml delete mode 100644 .maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_hundreds_display.png delete mode 100644 .maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_nested_display.png delete mode 100644 .maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_short_control_display.png delete mode 100644 .maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_thousands_display.png delete mode 100644 .maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_hundreds_display.png delete mode 100644 .maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_nested_display.png delete mode 100644 .maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_short_control_display.png delete mode 100644 .maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_thousands_display.png delete mode 100644 packages/react-native-enriched-markdown/__tests__/ios/OrderedListMarkerWidthTests.mm delete mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/spans/OrderedListMarkerWidthTest.kt diff --git a/.maestro/enrichedMarkdownText/flows/advanced/block_elements/ordered_list_wide_markers_test.yaml b/.maestro/enrichedMarkdownText/flows/advanced/block_elements/ordered_list_wide_markers_test.yaml deleted file mode 100644 index 730e26b0e..000000000 --- a/.maestro/enrichedMarkdownText/flows/advanced/block_elements/ordered_list_wide_markers_test.yaml +++ /dev/null @@ -1,163 +0,0 @@ -appId: swmansion.enriched.markdown.example -tags: - - block - - advanced - - list - - text ---- -- launchApp: - permissions: {} - -- waitForAnimationToEnd - -- runFlow: - file: '../../../../subflows/move_to_playground.yaml' - -- assertVisible: - id: playground-screen - -- runFlow: - file: '../../../subflows/set_enriched_text_value.yaml' - env: - VALUE: | - 1. First short item - 2. Second short item - 3. Third short item - -- runFlow: - when: - platform: Android - commands: - - scrollUntilVisible: - element: - id: blur-button - direction: UP - visibilityPercentage: 100 - - tapOn: - id: blur-button - -- scrollUntilVisible: - element: - id: preview-container - direction: DOWN - visibilityPercentage: 100 - -- runFlow: - file: '../../../subflows/capture_or_assert_screenshot.yaml' - env: - SCREENSHOT_NAME: 'ordered_list_wide_markers_short_control_display' - -- scrollUntilVisible: - element: - id: set-markdown-button - direction: UP - visibilityPercentage: 100 - -- runFlow: - file: '../../../subflows/set_enriched_text_value.yaml' - env: - VALUE: | - 98. Before the boundary - 99. Two-digit marker - 100. Three-digit marker - 101. After the boundary - -- runFlow: - when: - platform: Android - commands: - - scrollUntilVisible: - element: - id: blur-button - direction: UP - visibilityPercentage: 100 - - tapOn: - id: blur-button - -- scrollUntilVisible: - element: - id: preview-container - direction: DOWN - visibilityPercentage: 100 - -- runFlow: - file: '../../../subflows/capture_or_assert_screenshot.yaml' - env: - SCREENSHOT_NAME: 'ordered_list_wide_markers_hundreds_display' - -- scrollUntilVisible: - element: - id: set-markdown-button - direction: UP - visibilityPercentage: 100 - -- runFlow: - file: '../../../subflows/set_enriched_text_value.yaml' - env: - VALUE: | - 998. Before the boundary - 999. Three-digit marker - 1000. Four-digit marker - 1001. After the boundary - -- runFlow: - when: - platform: Android - commands: - - scrollUntilVisible: - element: - id: blur-button - direction: UP - visibilityPercentage: 100 - - tapOn: - id: blur-button - -- scrollUntilVisible: - element: - id: preview-container - direction: DOWN - visibilityPercentage: 100 - -- runFlow: - file: '../../../subflows/capture_or_assert_screenshot.yaml' - env: - SCREENSHOT_NAME: 'ordered_list_wide_markers_thousands_display' - -- scrollUntilVisible: - element: - id: set-markdown-button - direction: UP - visibilityPercentage: 100 - -- runFlow: - file: '../../../subflows/set_enriched_text_value.yaml' - env: - VALUE: | - 1000. Wide parent - 1. Nested first item - 1. Deeper nested item - 2. Nested second item - 1001. Next wide parent - -- runFlow: - when: - platform: Android - commands: - - scrollUntilVisible: - element: - id: blur-button - direction: UP - visibilityPercentage: 100 - - tapOn: - id: blur-button - -- scrollUntilVisible: - element: - id: preview-container - direction: DOWN - visibilityPercentage: 100 - -- runFlow: - file: '../../../subflows/capture_or_assert_screenshot.yaml' - env: - SCREENSHOT_NAME: 'ordered_list_wide_markers_nested_display' diff --git a/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_hundreds_display.png b/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_hundreds_display.png deleted file mode 100644 index 229d97a520e291276283d9289bb87ef6b6c7fd07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30529 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

    i0Vbr)ybSxQfjkf^lg-uF_FMWJPsH!r-LkL2p&> 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�+mlMXL6 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 diff --git a/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_short_control_display.png b/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_short_control_display.png deleted file mode 100644 index 887005cc76cf9eca0f52b0dceb466abc95a629c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18555 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 L&BrAVpTGSdKXeml diff --git a/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_thousands_display.png b/.maestro/enrichedMarkdownText/screenshots/android/ordered_list_wide_markers_thousands_display.png deleted file mode 100644 index a3ca7e714d3b3c4a8dcab6443189fc71e4bc4f32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31267 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 diff --git a/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_nested_display.png b/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_nested_display.png deleted file mode 100644 index a52b7111b5586acf818ced3ed6002fb84cb8e392..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33258 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 diff --git a/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_short_control_display.png b/.maestro/enrichedMarkdownText/screenshots/ios/ordered_list_wide_markers_short_control_display.png deleted file mode 100644 index 2b25b45bf4d052005c50aba4e09c9aba561d48d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19441 zcmdtKby$>J`!$PrqRI6M9cEJ*OftjhWPb@$wa(7sYA3CK8IM@71h}alk%k+lT+)aO$;l~r|G9Ezd&B<9lL!3Gh z5>RV@T6Mz5b~ZiBq%_daRhG@Z=xPIjh=BLSx*hn>kH3;4@V`qWRdlu4ghdfYPEj_n zfzpjfi1WzPUCu(s#-_xx0rR0>mPEpg?_{orKc)|tc<;|s>|%wKOq+`u)OCLS&2}=H zN^1KOxJ{XjF-V3n{3ZRCgm?f?ZH>7TgECYKF}YNOB2*6syzi*HUE6t%SCn3l5 zk&P6xo;J2MSrl^vGtO0ZqF0QqHLey_C_KheSzfoKU3FR_%>Pajamf9-B;jOp^w`G2 z$HzOiL@B%BnE#~Fhw(F{|D5-D%0{pJ*2-P|Emf-5W$+K>r?N@m%EZK!wq1fy9B5J$ z5zU*}MOw^f@_HEuWhzQV9@Z=4$n~^>k&Re1z&NBUmSRadTt?yg}z zkoG#_9Ro*;BW76OG=$NK9n!xr*VT!L>=+khM&1y5+f4e)$|?3$V=li7c>X%%1GO;r zz1*yiQ*|9`zc5$TIf)z?S7qiN-u9;7_$lJ~jVv8A?ejihF1lXyM~SbrJ=raA@tvIP zw-5=Mt0LzTX$L=;`u1nh%$R57J!0IJ**s*zo(u_)l~ov!$6QP+3u|Tgy10QC6@9we zjvjZvb`x9`yLUfa`hDn+RIP}V9JxFF$Czo6W*`2GVQVoOyxGhQ?MgD{0EtG+i zX|Wc06>}{*5Qo-Z6sFhc#KOm}w1ERIy=#}eXvSHcll%sz5%1cU*y%BEiM2?Fjk#cV z>-V2m?*1S7=ht!{X~nn8gd>&vX_2oMcSUL(4_@STru1=^m+jiTuq(ZU^{!tE=lvDI zeJXc!Q)*oB$9%1`({qbNwS78~ryEkQ^sGRyU%%!3wkLIQeZ;|K^@o5(ppr}0@L@IK zQ#FdJgDRJ`#gfy(^s%=~86|S{do)>l--PMIv}#7cK$Fv9lSCYBZv8O#azb&5TXK{V z?5dvc$?u=7sP-4`xemaF(sim(S$j^)gn9q|9Q-Zks`!StVew(hG@;qr&ozsUuMA9s z5U))dyQHKW%JI4^@kNUpQ>*9~?L=Z%{)*ZoIzh*A4Ha)jYFqw5jOqeC}b$PBOdsTv9UaxRijD zO_z(_tR2=wusZ7XqBkp^^H*e66LC%TH(O+cwNGvjike?sD$+1AoPhSmLyIaNWJ;rI zvMV21BEi1f@^)pkC0|D=uo?DoqUi zm>;&b+IifucS+CfX45WR51pQ^+oj@v`}Xsobc+j85DROQgueF^;Zv@4WIe1=5l6M{ z+a#47=`PgS^K8Cw+T^Ji92P{TRXn~8>5^JNNtLr*Q&S!I`8*CXpV?C>S6+!4=`!xW z!~MFUa>Tgaja_PLr0O+oN*jeYjR^FS>0)Jdp{}%Bxz4+};1;EbT@^jovy)nhD9x#} z*VHX$v`)U&!b1;dHfcO&o^+G9f9?>|E;2D1rc_vjzU zPd%TuFJZJsSoHQkNo#Q7e10DJwOja#r91MQ&ZFXIxhc^b9^xQ~L=G_Y22|>nmz7lx z`-?I26{`9;>OWwyMP1v_kjHuAcGmA#nfRikLK7W%gji&Vb$`05B73tZOET@#xU&V~ zxc|wgv4UZ1&-t+%9%L9ar=7fp>#q&RJBuEL<~~s`+Yj}H@;Am~i&4aC9^LBoXV8sGAb>H_}%>@;;0d%23)l5Jd0IE#ax(rVnfHDi};F!7p^*b)AKs zY0nSaj1*}7+MF-slS|@v-r5eCykc*ERx3DvxU=Y(Siw;Zh0Ar3JCHFkiE8)>6H*|` z)_P2WE5ag8JCSp_5A9z{p}=a>W;o|H;7eGQCm)K5piPkt7F(#lHF)pfgg>RKb) z40^Q-Pd42yCK~N+kJ4zPCTp*QuA_AF!Ub5vHC_Av&G1}AK zt*F$)@3HW06<2;JP-3i1gL0P|bXh7rcC8qWYOQuO#h_#Qs8Lt$@WU#rDMQV6xzm$u z7O3PU?fV6^kcf{(5S1^BJy&+7r_Bp>&53in`vR{`_}AqkRq4$c1&`w)QK{^&o>N=* ze%g}SE`0)>iJ~Z^@EAqTUnUB8bM#y!)isnX@oV9!oQS$tMH|-wiUc4$VjBkK~zSCA7_fu`Zgm|K|6iKp0XUVR_551(t1m4jvecHBlR zHVC_7IQHogl4%=WhaN+9th|Yjwky(wO5`dXr#DL@(bocRCPNd@HtQmMSvlEl;s`Ug zsjbgVbX9GBez{UbjtmHlg$>o~U(Gv@u5I)0 zeOxJ@Sa|9ek`GU4&2zKZTKDkVz1BPsrCxckf=-0uf{mY=J`7)iF1ke{zmCnlP=_@( zw7=hKs&Z;#4s6;z1{JEXP2W@8QUwtqAs+0HDNhQWb%PSQJBl{IFpQxYA8LDi`&t_q zI|Shy)D4O$dXbAJo&8T2b)DwqWap<+2D!aN={if{C~)wRbEWql3+dq4pR*;!Sb*?Q zq;-3*FV`Th8Np`=kP`u+w;mmKJ{Yti$5+8Ux=WKKt#M=DKk0f6yRP|Kmst$TTYs*l ztLnKJGO$ta+5~2^3@4)Xp*RKlD?&}DPxVm_Jpr6{Bm54}P~YnV!Ai*H*jaeT2F9%G z6ax1gcog|A-I?sEhx_{&@uAwIEJd!$4!J-vnjS4Nc28J}VIq2FyimVUxINFwf_2*Y@=I&!*nGj>OTf^ZDzBBOPyGa~ zUOzG3U|n7NYCv3PXI{o1dSz9&KFo(NXC9Y5-H^5*B_2D~HqVu_pR0e#d*u zFjF;(mKsVhH($1ZQ8uBEzE9XqWNGWz$||P*x#iVPq4?-K%l0jJ`~P3Q1R0^R+B9`K zNOk_A)g1n9?|luoix8&uot>TM4g2;6>rJr(j4T@kse^pgV`YXgP33=d7#{AL=}f`zFISK^}8OxSws;dB4!o`zttX+DNfD$Xi5PA z8chM?pQ#MJ0I-ri(l)MO9p7J?B%M0nt`|595(wN~KRE$uNF45(SHJE4evBF?Q4-2bF6370lCk`|wlFI>UUv6c!NtHMir#*HefSvrr0isVK zH`mK@yUawRDdX)h@)=ap^Q_?`OXqt6OTM;l&m1k6@6~>b<9Jcw;fGtMU7hbuioNW- z;0np;+@o?T5sC~g7q27r#^ghHN)T($JO}#wv%frwX-J4pE+%_8x0-11$Gy8;oGU3~ zsDE_Os&rbi+fB>pz*yVfz;+)|X*zA6M%~QxTG=kB0Wu({Kk(WQVHvaG(nRe;Pcg&T z9;^|EUjPkR|D0%se&lm^b7>3~6Mr3a^qtrIa1y?B3|09W{LJwFb1fFPUFr-nlFhx{ ze0RZ}LtZvsAFbm_w_kZW698eAzS#nIDyVg6*{W|OmUTC2IY{DQV|}p&yY6RN@B51S zX&QT!LJ)Rlf-@@bA9V`jLqpSEqIq0KgFgbj^gSY?9>KS+`ZI}tH|a9a0pNd#Q#*a- zGD(da`vQm;h0(=LC?T8vBFPR!C*(7C{>$gEgUwBM8gB_Ot%gp|P{|Yk((5$2wzPeA zh-EVvuiWqbk?(*k9F-{!cQK)A(BM!^ZCm8p*m}+7Qa@$m@ke1ZOe=phd+`eZbJPUF z)J}Ud2{&}_u^}w?f^~Mlh-4VPu6*;4?dJU{9=GcPeX;$o&oAM5LIml?V( z4%!2z8m2w2l~W*tll4cmXN-Zw0r~KRkl*Lu{dbdAFk7Q!v_=i|pC^s?^>VUD8mZfQ z>V=x{uVq6tB9OS47-U0ND8kynu@b-zCO<6-!q&%&J;t``j>#>9h`p8)N%*| zS+w6ZLa=gam>ye941yOa2$U@6vDzwrq#GHTx{^rpYX9teapS2ZJW@KLL)X}f`EWWK zg452<-(X%&RzM*0csy|k8@fwv4{~1*%D@PKFkmJCoaJmeHG%o_bzq^9w)aIbU&4<` zu>5Phjz0d~3GQ?v(|y?;(;WNyEsP^?_930qhUtk_>ySG8(->+ur4PQf4W^ShK|!4W zk2q(nX9Kk8(L6K$eTP+BS9&T`*kj>66|%iD5oElzgm1==Uiy|z@5EQP6`n54&B;7} zLhfYqJtoib>dG(d?%rf=RaKContf-aODw%TL909-(e%mv1gEkX#y1^us*yNH8zU_j# zYT5ZsT>(yuJ6E3KA=p^Ge)Zx-B_uRjPW1uipbkwwU8WFM_v=M#{KSNwN5{1X!or3i zHN(JWw&uY-lgf9r^}EQ@<9ChsPOu2`#4QKX1CQ!4`~@7q;wS+osWh-HU8f?o3KmB2 zzG^=isR@9$j>FIG&~;tKr7gzCb>Crp4D{%`$|aw~NOU@!k_Qb+0VjY4oV4-+6`6O{ zhKNz{6PvM(%Tm%ve}r^C9Y6;a3sn0Gq%|$#im1!!C%3%Y`*#KK6RTEUavxSB*Wi_u z)rCz4S3;9|S*{(pH-TK|hN&dr^~j3uO6$Nb8NSaw6|k#8Rr~&NJw7b#K!&zsqbsRe zB9L#x{lz{=j|gZ4UX8BYsNbhe;qfx>Ir~oGHFSn%<{2sjDYf~M`TC1ZGKsV@?w74E zc5)-VP?OE{5A%%c6|JAV9j#qVL+*>4uL4@@cJouh2fS?QrspaaRm(`{xo%-UhRh5H z`xHtZe*#+h=M<0MzK?lt(ya?|dFg?kG^|*(G5ANMt+ds=3l5yBOF^0>$5#@yh zilO*65P>H{-=#wX2~9w}7Pa0LbznKHhIns_;V{e3lSsB(g8t=?RHN@b4AdGD8nE3w zn3xcP=Y3Y0H7!W&OlT5^ZEEHA=sk{A>j$Z4&-M`I(2dB52=uim0eWR^X4nH&$T2R~ zm-r+i?>%av^o4lWKur`0Y2omOG9Ni1_cQQuOI|CUST))~iwtKnRxYk`fT`D>IB|^y ze;S8=Y|ic&)-0LCM5q$@74%Ii4%eS2j)_%Z=NUp-MJBgzT~SIMX0daLO}XqBl)!J; zodF1m6w&iVPgdB6sfJ4EDJi)^$lCDKl@JO($LTU2zffNxx0uXW9gt8aIclceb4Iu~ZyaU2oljl49vdI-AAsQ#Spx#Z_6=!UCqnQN=yxW{&p)Thav6VN zYF6mWelt^6R&HE1ud@a?las+yzaS2&dO$xS&UN zrXo%#NO|=CCJMWAf@=RF3K{J`{7n?j4LdC@z03~{DRl(YeUxynL>fBLd7p;AO6yk~ ziDzM03cH= zUp-?GXelDd+mGIwG0-aEvpn^26f@Tl&2M_u(f!Tvwycw|$;@uGXr3kYVzEUfqiCFW zdo`G*JPJ9b?b4~b`mupR`v}9*L1=JI^rkXkT%yd@oIBa7v+*YdM*-MwD7K8;3!eKda)kwP}>% zlZq^-2|qer1==A4Hi>zAQL_ck6PLLx$TaNr?99+T8Pvv;ard1cAwT>=^%`%`kA9gi zduV5-3`waUFPSr=tU5r{P3sO>obLNPVKZ=!d~Z~GpgoH~6eEjBH@p4VkoK;CY0};V zW6&Gp%dtN@IP1E$wt}I6sFiijzhf&%Kqu$#dpRg@(0z&+)ca7Z~S>lOfZLi=Cp0}S$zJM~V_s?4*x`H*| zFoY3!-Kbm!1Sf0L>kEEUaVy@zYtf;0aA*ZUWa4ezb&|*N?it9BWTKJ@H*^L8h2WY#EpMDKR4H^V~se;ru9NRFV-$K zi4t(p?!<&A~?ck z^9o9qhfFMM+bXuLV8{kS=hQ9%Fll?}ar|J~HqV`-cjp&-x59?W8B68)7kB+Rz z!_lZCJKU6-yjLcAN$|(SZ~5c(MA*W8 zY(Tb(obagU7V4n?`01x&JPwjV$|=UZ1KIxc%)6(5kjM#g#t$q$;y%-#-64(4>50Xs zV-XYtX|?znhDSyHheuWR1o(GuVF6d^SglLckg5COif!JREGcX()o===Gzt;*b>nY_?uXz^p=3;dR{H2}QMmN9xmCy#uzI_>WnPsq?jNhuulL zIpWnCml0yOQY2almrrcUiz77a*b`o$vwxM;GZMe>m$tna>}qetRI za-Q4DDWg64ZAW|g;~%n-=sL}Xh@R9=&{O#hV=!B<8^r@?n_yr2_1z~O=A1eJ3hAH0 z+5y{St6pp#a|-h?1?cJB_A?y&>E6Cbi?i^(VG=Sgt38LW1B=?jEHKg&508;JSuj5x zYVF=IfH`&42fM0ff+7h3f&|(@flbR10F3-<#M>1_&(W~W5FiN$X&K8lnH6H3E%284 zS|@Y+w((Uno{RyqwgMZ~Z#SUnJavP|Xs%-;Cb~HlZ5n=A(*Xm0CKfGF- z4&L03!87Z+-&`+bS9}=hGdQzuUK*&209xe~CMOn?#rF$G+^4m1xrVc*x%X&9Q>r>03jr0Li4?Xqs(1oY$` z9_%4oBtj=G0{Nt!Xkxwu4EGIML2VYh@1D0y+ZG917n^*?-Ui3>>$5256HLVNT6HqQ z#R;AEGIUnAg&$yHwc`@zg&mh}d7R^^?(}@-7zj9G4!U-CcTjtcEigj|?86%Zc0alT zG*3Sb0_qHHqlLZVWo%wGM0WIam@Vu?%v_Jex}dQI^^Qcv;*eZ<3M9+C?80@KH%+!GRZ3W z1*H@$q|%&9O#%=BD{L(*PX*8rKY_a(Q23MXOaTl;x6Nh z1pV{Vw2;$OEe~SYNS`F>%vgEEJVjW!q35MS4-g7#)(*)eO74|6%7=;-S63+M0ZKhj zpJp_Oe(#VM`|xD=ant5o57pdwL}4F&Sj!HH^2R)+G9U@xozr2TDx7(F%+-)voMAGO z!$3(SvEJ2IB7h$@YrWWpQ+%v=*SgURElLG&zzSCk3@TLkWl;;+e_JgWsHq&&xb7Ea z>w~u7-uc>y$yG9(^5vh+vM>m*Q1gGAkO&kzCZJ|P5<0Dme3|$Rrj^xrWzSJC2iQ}= zLL4|~D+eS%DY@Su9wW*PKK>eg#A*WP!9HyB=lVzUr#hA~WC-&WdSy=?=+6;mg_x65ejl{NnKj4LZsL!?=$rM)fpaZ@4}KGU612H(7ctYT4M#6GnqADR~CGy z+zpnXxV9oECyeS5t!5n{9I?P+}C!vH79?-d`XN5HAh&2trS| z9ljGu(Y@iKFVp&EhjKp7TRTUdTaB&KH%Ycs6SgWTCbgN|E(O#nW+yp>D3Ss8^TG*X zY$}?_=};QurI@tq?&oam2zCVhsl4hNRugsdYZR11-xVpzx$l|vKhHE*A{Yn!u|PuA z2UcGNT?4jHiPeWH8*F12TzsX`%->BS+&eXls(sbQ5Ox$J)46Y7_el&Gg1*)gE@>-vce-}49xf(979U%Cty-{Y zH(DG=9v+p34J@F78?9hgD$hY4l5kn)oO7*sHl3Y-J+0BtI7#mGNagBdi&!oBXFiE| zS;*#B4%|LRw~P!V=`>VTx6hun_y#5A!LJ-x5E^{MELkR|ZX>RM5kTTztX}rqK%ji& zQBhHNr-=3>SDW!1wlIU2cW6_sf5ozc#<20j7yvPv5l3$`#c{%=mxPGya4R`1owMwr}X1T@}!f-3~3{VywGU3@Nu=6?GqdY}ifj z(6-&Qm)teX#mPCeXx7oLF`CB@3@Q0XZ-gDb1nW94lOS6=J5PGt*a>=0hXoUiE@=US z!-6JAJ2l+k7wx2LBeHNA0i^JlZj^4g%EEnEj6Du#E4{98AK*zWasM~%dqenuo!z#1 ztT>wIe2(l<=){8`Vk79 zZe_-!1!x-0Mq;V4@L8rxYz0NdkfZ$1<%{h3a0~-h4{@tMs@%k@9A@U@(>g_{pd?%| zFAyrW;!rw|2h-d6O#fWQeRqmrB`&eSLV$r+zt+j{YlMarhG0QjZ=JF?CAuX6tb#y+ zC`rK7&FwOW<1oG_>bmu-F=Hf1Y;PY0kPs~A_f$D? zt6hrX1$i$3a`0CAnZ0CR)<&M{qaL?Z5m`A+{Qmxa(W29BDMIZBrpBg)xCwxQNZgQa z>*ob>gy!a|w&LV{>&{EYmA4&46$@4Jr+g3R`PgZPUbeQjo*a~$m^>{JE}fQ@WrUv9RnT>mQS>YriZinDTAGj-{-za3={+Zr=OaT8qI_AF zX472@AgSnh_b`NsCh-qobQSA)i=GQvrOgDVtjQqtoC3AJa+__L7Y;Hqi!=uSSna_C-HwBO=?iao#%nK5J7w znTG*8bIrL?=Z9qr2n$Auj%ji=U8@~oWPX2)(L zIs~4HuBX5uw2e{j)#=usiUY9Q*$#lJZmQC+9lWTGD@@%Li(d#GPe68sB7u~Vd;doB z@B}u%RHxb7$>G#_&Q|f9yNutYxjN*V%g#}(9)H;1A3z_6Hh^lY zDK5K_n(BffPAK5L^p@PbNy(V7{Q<{TD0sSY#nCq?;lY6A$uA%xMTD9DM?(@rU5-`+ z>wJUQG-3*$$DvVYQ2#u&myTz2GLzpr2T)pfO zMFt2oH{6@mHX7=Yw7fG2YL6&v3>2VY2m`!%Yl47&Rh8&TOl0J2Bwkc(EK^&1U7!}e zW)Ffa`$A7rO^c#eK1|_{PAueDv8jNp`FDX?Fz@McV7WB(8x~w9Yz;IC76aYV53C^* z`9o2el!Vnyhi7~!XsbdbZgmT6DIC2!N4_&8C>3ClT!$_%LF(x=LNn{C*a{q%1_u<* zIJyoU;*a$FGIYji>+9SpzhcJXCFtO&L2mSp30vax|;r_u4yJ zMkY|tO)>KE+QpY3zo<80#;{Lb>th?8AOrp>85kT0T!#Cn?|vfsjFKm7kFoZvCv}BA zBe*Tk`hl59_X@C-6o)kJjRN(uQK65Bh*mKXt_<%%S^<=|1jx!gF##4>jPDfsE6Wr;7~`t#AwD=;JCVpL{xFjl`h19RXvWhu1aBQS4epT~w?HE$)4 z0}}fke#>K=tQh&F%y0wvbz-XrW6911-jI{WhpX(bOH9fu_4FRgMQRk6ec8 ztO=_#ce_p?`y$VPOBY{h4KInyN>G7t9rZTfG0J!u?xURq`E%@_&$h=CeXJM z&h=z~OZWG+`V-1tuZ-0+9MSj zS2Ek0&^8;R4Pow$7&G)!0Tygy6BD4#eW9=q;en}-VrD@gO!0L4D^)uWL+w%HPhY`}zG=FsyL4!ceW#ItvI4ZBhmflZt&Fd0Ap z!q?4A4-~UXN@t7F`*uq|o=Gbq>pXzzgsX{;VKStF3ARhktyrj6XCEn|*Sw3ddf|T+ zz7n!DX`_M279h-f6s>jpA?y@rfL^m{c)Lq)RC~@ouAg5`*)vtyKLj=iDo$vD&IEj; z)h{$<$&ut1VQT=MdQ3Y@K-91&aEvv*QN|goafDHr1GTTK&9#K=ArY;JCMr9b-&K>n z;N2%NO(4LjLsYUZ9Ofs%KJ;NuWWA+fT+ojn_gYuG#`l*={)eZ^VLT(5BDlvu=^7Z| z+NBSSwye%4%(I`ksZK$-%o=m#~f6xa_t^OUiA&u!7c2VZ6tZSQqvWCwcP! z>?ChxpFG~D6#Z*WuJTnkQbb_Rzwm%Sr648Z&i$k7c|n6PPc?mJ=Mn9beNL|@ht-F5 zeVkn9jVwJZHf)Tv>-&Hb2PsPoZL#IXQ%-YxlVR&I8V^xTSos5s5+LCbP>Ik8S(hZq zk=p_As`_#w%IuyW8FXb8a4TnbL`neOcqV;C-s5f1A{=PXEI=Fr)4k;56zBMw;QsD4 zt*SMl)_O5!RR76zW=mPW2gsxrP$n2Bc##jS=)-MUDCc|aM+~UR!^2pZZzAp`bR#E3 zuhOQ&jfc|w*uK^-Dv9g2uv17P?*{CNZ3KWk3YG(TK-6Fb2XT(p;gSQ&GZ;}~$hZHr zwR)!r!)yPSv)rAPUdPqV0%WDOld&C6`;h19!lS&`Zt3klWVaK_sq*RePR%o=9?p59i?7&S{HZ$7-__7bHH^Jxo;3-V=0dTAu_-e znZW}z5fUdASl&BengTgvzV?PZs_eP-5Q?|Se$7`z`4S(CmXG7wgF*)s8^n>syF?G) z3)s0URjtb)1cJx=0_a!&F{JNjR{|rK^Ui_ERCoD9fkX4-ROpN9$|`3|ZXsZgXoPG;18og zE*m=UG;h(12myYb@|!l?tk`Yar^y8R4TlVFhyRl#Ba%PxT(cDD{${~O3_dwa&u(w7 z2~isPpZ}%%{IV}W=IN+ut{gpJcX6|jyCXT_;BXfx1AqstJ;|89uKwc063xOF4oXxX*6+xC7}PSZi7DZuNaiBVW-Ki=KUB zci0#xwqVdwk0y6t>2x*3jfszTJeB$Z5|OhVWbO))HPALa9#wmY_rY?KZfpMwV7_JzN z)B??Th@|QSPpjl3$`ClY23rp}&oAuowZ$jn?vrMm!AIRfZ!UW5-^O*el#};|QLPyC z6)I|(gD842JLB}!@&Au+J?w+1+gDXIeRvfh$URy>B*K%ROD_7rW&j@rX$sFd6+czR zu*QqV05PdVe#a1q`Y**nVYKEI?R%!Cq5~EaMS3?@#`>(v*alJ8BJZRjz+U(B#k?-Y zIOlkB7#KkAjq$wSq<=c|r{}%7AhkHcu?jMcawR4DIoJo*tHEFrmGB$6U=2VAZERn< z+APTPN2+Li*X&25O^c=of+1S#{}OgiT9_Cuco4PFYN=-eZ*;U9=efy?p_2<3DX9N_ zy+4?D1CNdkj=M4D=LhdWg-CiPlkqV%S>VXFne#k6vKNBEe);c%2u4Ol2w*dVM=|4RTF87@32 zckuw59(wviW3s7sR0pKqEMV6=c!gmonu$7dIz661?FZWb=ltE`;8u*c&&svLCt zInrL3vSXr?^#LE|$le?x26jB|E2U?j69y}|wM{9zo&+~0FM^~r9u6dU+r_(M!pApw z_{_H)rQ!82a(^0OxbiJ=PTK;XAZW@z2c@%?ErL}{iX0g@!*+(LK)4`o$B z^Y@?60bB6Ol)V60z|#P@m6xC!CNyi!d&u;iO~`#$Vk&KBM+2vft+Kdo-_>>hqa(-S zoB4ubYFkOEWfIad2p_6N$!WjEZQ!U&a1ef55W9`Q>}LPgun4r8&t0$w3Ll*IvYr;Z??88q17yx&`q3t0)!MfPUa4k=e-=2TEygz zN~}ouMi?aBB_X1K)Bx_O1_RK$R_E2#pS5J{2HL~TM zM*t3*!)dfiR>rn2M1(BXre7Tnolx_iT$Mu5-2?wRjZ%i*J^kaZr+`m_mbSF*FAIqR z=0=pE+e?S0d~@@a#Xn|gMvf54pkA<3;pg)Q zyCR{a-V;sux!DwIS)AU6 z(@MK(+Jk%$Hu<^h1Y7gioxf*=s`0;#_i$kz=0uerBB5jvUl%-KkS6n(HugZIJ`Q^8 zs?Ify#g)h>U4v{atk|wX2A9x~#$ySL6ZL+sG+pcrF%7GJWv$y(tid&-25KX?HJpB1 z0|)wYR&ZGhW2%pRj7>iEa2W~6-p->Z!MdnPNz{bLyV_T!3}GWxmZ@k;Lx5>}%k* zk8S1MZx8W1PGDf_Uu$&(<$|hey%8jo=!|Q5MACF=PV-Hnl-Bq52J*fXK_)m4VD8gjx>7Q31!T7P==ox-OwX1}|hIV@Y07XsH4 zC^kr}UgPDn8e4HI9v)ZAEF+g(-Ep}KEc9CNfPmo&rTRbZ;O$t1tv;8YG3601eVJB< zXJq96AT-0c>^*jPMOQ%29=AMj_#Pom_Y4aC+33>(Dt~&@Tm>EMioxth&imki@lUL3 ze9j5!YP--0ie3Bv`}?wjZ=}4+4Zfa0#BH9_SK)W?&+i6kw~)|mw4e(rdGWSTGQVVK zeJ&6jJx^YjR3&xxdNxO z((R*laXwPOZrboK_GtY1_C{CHc)(v(pjBhf!r4ACH>4UO_J_97IbdG8glX^vib)Ra zQnFxJD7T4_yBPsFU{?2mt#jc%2xsh0qKKrBw4w=h!>p*&(*gq7 zRL=4&+Y{*T!h`mA!24IZscR7t?sV$AD7wBb_*Q&;rSq@@Fu0xvU9CV%Ja?RzQVj7! z2Z-iP5XyM4?O|#F?7O~aJO;=PSkVn_wk_WLvz9=3aSqgbO-{^$Qi2M|RQC?>x(o@_ z{#7_wDZBVvoa6nW=!l$_~-bKYB_JCu8UH z?0?ha#Cm_y<79A<4W2$*gqW1}1(10wCJVrB()-K6lv^WoPX8DJ-d%HC5Ke(78eldP zQf|Nt92dR?CX%7l`OUstzZ-5lea&I~KP3rm004nfxr&On4<85KgSBU8{G-&Mpf_{p z&+4Iz=AUmg4NMKv2UpbMYw0(*1GBr~?C6i}se=!GracBJBBuG32S3^z#^L}@Kv-aA zo@zKdgU)#0)83BG$+1D5xcxPEeCUd5Z!kT{pExBch_4UFtCUXIoqQ!`S1*f*h!VYKhcAKuV)@=b<=&^iwaP_9$)Vx;{b zeI1unTi?e-x-2?E)bXC*rT7Lc;) za=Cr&&!XR3@&)1i*P16tPKrpIAlW9sbP60KPC~mCdNRPq8eQ`OHp*ww1xio@L;Qz+ zZvC}@0o!uYv_UfZDwvOE{F^b#_*HRebgJloiXK{f)Q|8O0S96MY-$d=e8s?}28?M3 zjM!i!lPxP-pBZ{TRF0N3e;R4Bl6jGw{mFjQJX0wKIWJ-L`ch_t@~WC)*ogULW?u$? zm_sQ5m_CQB@d1OeYDQ&Q-X7SFov(S}bpQHY*YeS2f1^;DxS0k-jX>BNd3 z^#}c2K<%ZP&S^rhAevru_5&WHs_MXCPhzbVV7R%E^P93boS;@j-2=~2r5KpPIyAxP z$%53^qC2$%nYZ#JG{1N)R6h`U-l80#7HMEt9=xZRJX)mkg8{7Iw((QBqGTb%M(C`j zibBb~ScW+_fr}!i_IJb#V7_=wb%6^1gM)`V#qljxPa_xBkF<7!qDR=}}*9&dER5sEh7Pjx-+XvH}!gimMl8jc! zdL68iA!w%T#2SDt$GHYBe@*gd3}MS{k#j(5qFR#*hoS1(xC1M-3E&S7-}Xa>DT>0 zaiXkR)vJFs4lFja#6-a@c>tpaG%x?Ao-_Y1V4_c`z1a-vqZ4Cu_W`m8QY8IX>6soD zEnA6&IiX=eOm)UzC#itrbVf&e{(VRaB6+D|_xisNNg*RXKWJ0?*EQF$%?E5}>Hj)7 zg;7`mPEC^O49L&_e699qPl;Yra$;iPKH$`_#EkF$d9X`a>b%Syxqlx61KK%7_&{V! zcK6f;jyZk>iy7Zvh{*lSUyM9nTkAW+;Ug+=@gE1w(3yuj8@h7y{(Y6<_=MOyLaiU1 zC)Cx^F<^P|zVwlC46mf=mD2GT*AU5ZS#!7Hmo;z8dI5L+hK27PK`WVAev`3^D3$dvGh zm!w}Sh7-z+&1OYyeyZSc&r$9zs5hscz1&`8+Lq)U*EJ`6|+rhE(=!iqB;s+jLo ze@tY=*e#P+dOw+-A*>>(^U>(@Z^WseFg>k&SH>kAkKw7*Oc2kk%O|l>+znjtY*FSX zA-N2gXKy+X=`uFRe0aEWN}E|52yWQNZT|7oPkLfrb`*2NNzCtak@S$~nY;vqt!Do@ zTp^?vJOt#QMJG3dGwPB*4Urh5ugslr8Tzk35;TRXW+dn`vrSE!nM7)-NgU>ntPgGVPM)>B zGG8Vi?T_6NiY4f{XbRia+e9pkdNM!4((bFAn2uLH%Al)r7q@W0blysMLN!I{^BHi5~T|;-g z=iv3d?)!=N4|w=#KAXK~_F2cVj(_Vxog9 z>ya}sG&E0Jsh8p^F0hR$KP{D!n%moZ$uX|oL7$UoGDq>!iy?U2u4(MQe?1Pu&Cec% zJj7>GFLqW?Va8O&$0dM>-%!NI#fRJw7eMd6NFa;0s25Hgd%k!fyj~sRJX|@FBwR{o zQnztfG*0Ab`d@$K{g)Y@cOU%cuS+NXCY6HhX5iQ5#gJtDMG^Wc2R5X!s@!S81}U*~ zVS4I+{>Fyr6%_JQY{hXu_}p%OfJKHcJP7|aZ0v=Rn_I}>a=KyN{h=)0dG$(!k)GM} z5Rq1r8+E$2MhdGRya9%dhBoSpeybS^iwK{c-c(`oVc!RROkZ3_iQO#KlPg(oq?{BesH{F9g#^NyEin9_zSF}uP4vRBxMZiQ@iSDnx>%!p{+(C{P7<%a90-Up`fy+~aW_w*J( zZeyxwD@DaRQXGk1KZObSgJ?8#O_+7pgp4UJtJSWt}2TVLPg<{D7+W0wD=D z#LnX1N3`*7Jqh6dO|4+2anhBa@ac8}`klW|_@HAqKfw}&QuQXf;Ydq&96$Q|MBx{G zY+o{R)WUKgCtGx8uP^`TQs_+m{vxb}65VK~ht2cToz&}@d{3GNt}e@>CP%8L^Y)U6e=rLtfhrv;?+PpV?_xjFR82z!r`H31hJT*10 z|Let(pf7?C*mQU0uJ1%Ul4$gs?`bGBnVb{;du3}yfa>A(M;Gjul-D1&DgDK+Kg^0h z^uGS^;{zr7-vz!Sj`4RYaC|WTz7jbGF6Q-3LYV*aMGyZU`J()TdB{}tFB!q6BR1V~ zy|MO#_zK?{L}YW|4=lT#&sp6x^aVAUpPXwkk4CYGBEw>ziJVU&{1D(g|6o1}5o>OK zrl#C4pD6X^OTZMa-L}GhPU&4KoV|N4i8@?lh;L;Za)%cdImBGX^BH-({Wdc_9YqBm zjq74=j*gBp5>1*OedWz}bla^O=M`XBs>erOf}eY~?Hci>H>oBKn6w8MR`;6yC@SD| z$lGXW&pWKB6+ApHBJ+49MyyE%&64_f94<@JTe=4a2X~(pq^!<1_eh73i`Lq%3LJbN zq<#HBz0&Ncxr4#c@xWb*h@H(=;|S?RI6!n-**9!5yFCMy-;bS>--|!1#yO^!_22E0 zZwL+x4>9!@JG2Ygo+a0sOG9md6!u9@bYT`|SQYc@M2f*K=dJk#3p00kX&LExbD#j0 z9KQYFi=22}1yg9IjHjKKtE{5Q-N4OS3P0WIxb_zFM;&TbZ*7(~aV8vB#*1E5dUmK5 zE)TuEb%cqtRZPH&h1x$PKOa!{mJfcB8n`(W+xS}0lhHdw-^b}gbhH{PCM+E`=`QH9 zKts{GI!5FjvD9FDi$cx-Od>_)I_osrv*fDMWrqA+fgZvVV*})kpApcjr76ZOTyoSb z;-j`D*QZ)Y%0_~aP4dZF_Uz^#-U%=G?ALN-V^)Q#7>8uM=5>2N%#R^wT@+fn?U60uer zuIXI=5aO(SHz1&M!kNc%YAVx!O|hsfVto~%$%z~0_sjJRhq$d)90#}6v9byB6r5c# zgQ_uCGdnee;}s{UAOiPlmM~e z{cqc3Ocf1{W^0<~Y|qQS4Z6Hk{MD>$s4=fSPXPOtwL04(PuFS$3%?*2u6Uj(09KXs z9InC7X0KWSrBu?HP3cOIZbVM4937F!Ln|R4SvGuCFLW> zg&6gK@t@}{2nkYuv0*U``>B7IY75VM*a|C}x^ZbU4AB(RlxD&#GgIo3L#hRORC0qS39DLniPT?pLYJ zoDCU@7E zd3+fdT{Ld@zGfdzyt(kyf=6!mfOMHN{HH~-mZ{b+*LRDjqqIy3*tElw;GyD{hl4;bpOkXAX%16}}qQL617u&3Mo5KPmL| z8`Sg|W8q*Nx4j>3s)g?JLbGBujePlHn2h03pqP;|M%v4#Hux4-msOk|91&W_`bET3 zhMb~M>G9pbwVq!3)4RQw3{mZ^o$~}}XtR7^o4Olg5Wn=P9fqPig_INIRc?dH67?9K zWfs)@sFod}wv9K($b9j106t3O{k8C$e}?NJX?yK65aCpfW5Chf_C3hgM)($Es%W0N zuVC6ZX4H607M^8vjEv6vxDG?Ybq*+5zCcobd!Y~8zQt&-aVzo|p%}c^USJhnPl$Xq z%|*)ky&z>Dq9|L(I&6G$OZgdvOtYe(65h*{KUwn(knEY5NzV%hL~}aaj5s#gX(b1y zY8@f4B6>?8kNV-}qkZqZ7De6w^Q@kv<&O0n-m&?R9j~94kJwn%pO`;SxC@eUAcP*W zXAST!J=hw5vW`2#ew?OLG0VJ;Aym-qp`(w(hNBL#_qXHVM2a(MSDug#vK zO1x!PNLW2K9QWtW7t-^I8GT%3EdaoR=S6V+g@yKahe#1k7;uIR0--s&C{qEx&%r_A z7MWdlyX&J{0{2b(oql~EoiMrlgHCNAz#>TXu#4Z+DUDeIk1}p-J7DBC4h413E6-!I zU#aOWX7;ajxK_W#K7-`2)vr;HY+%mx+=i=%D!~+u6xQRIeP4$@Cu(@;5`y> zq<0lL06sVY%V>3hNcL$e`;juQt{Y|y4 zzsP8OWy!GBrcls^0RnRz zr44t`ZrOSj2c>Lxxwv!HCqbcdPE=SG>8Muy_|x>$&E&Pv*A%x%Wp@zy3Bs3oGDYIJ zXV?SX>AzG?$SHRM@*%28@h(3mFkn zi9i4NWqt@BCt_3e-3;ycEx#k`NUQkT^<9zmeI1A8t&0OKss)asHqX06UuG;O%*OD& zP06dT-hPQ8?-NqufAE|BggtXG>eHtkth%pXl}@+_;s)@A*x{pHr-Dtsg;UH$iA!FY z-Od8>wu(vQ2giEZr!`LS;b)qyaY6ZC`sVSzLk+etv&v={EnLE;>k_o#P&u2SmA&#f zqn|@sebp@?IOHPpj;>s1S2hziki|Pz^*oMswFb^Kvecpd^d31qm~Rqf5c{xo>@@q{ z?|le~kgo+ovk@9MGI`)9xeqKiSza%+F{vpp#_71Fxini$I7zlgu9ad9#ZNW`P^7!l z5dWGOuC;YW|c=@0YAzFUFJb>d@i z>O457E;4D6(bKWOX-mk$NmQ6?VZMMD)Y&;+@I{O(JSxjogtIeoFMU9li!C6hPbiY$ zyT*tX%Y>$oVQL@9w@@f$+~OWqTjR#H;;i8sBYzmFnJ8D5$Cv>}9` z*@1}JsLtv9vE%769bvHxYr^?$Y%<~Q|CtV9R(iv`dUO4bOGqbIZtkfGzhx|QHI?OR zGl8lNPuS&f;#r-?QXWyn#22_sNTQI5?0p9bdyJA2$Ccrbr6+4{OdSj1$l869Zwa3a zKM6ToP916~j~J^Hdsl3XQn!Q5)HNSDW0=rmS=@Sbb(VNgq7m(?nVE?i_V1S|U~9*p zhBx@QHbhATp32?sDxYIU*Kn9AeLwq9@v3imCL3p*&t0-#09`hotQG4qmZN=>qV8j; zZuZK>b}6ebq&fe6DzZ}f=*F(wa}w{BhMtI^NaOw1)GyG7=|NA{f4XiSv#;%+6}Zo5 zoQC5sl+Lc;J-?z50C67^#C^lD_AX{dW^F>%oEqJzdHY?*13Q9@XWFlphDdN&5!rdQ zF%eCy!b+6~@zh&W%ba)B^dvD(w_4`%nkwQNqKn;eK6Fh`yHv7AXP_Jwe6>i1-wv+gw137sI`ajLC5%q^&Y1$8Q@LIwJ>;j*p{1$_zcpXFCp^Jq^8 zbPIcOd2L82YMyG>)30dHKU1CECX-sn{3c@cdb6WwhQ_<}E|CUXGf$tzPN#bF^i9cy zqqkh>V>DYEaCVZ5kxvKXI|eGP&aKZKSSJgG71J!+^UoFrA4$^&`(i;LV3h0ztc+HfIrxk*c5;yo50(9GFT4A`anX(&zb+Z3dSxw{l9(wd=2s)wfwzaSYRc|Q>63EFmhTjeP-0;F` zqZaaNnIy-$nVR(G)pDog_uM3S-jCQc>tke-q%Vc-K1~jNA!W7k&GC34TmSeonS8H4 zYMnKNmY@rgq*fDF+uEy5Y5MT8jy9<0lsTliXCZ@x!kZOV&j>xMKt3F{SPxMQrC70C z(ymIDbotC-K?Nuit|To8GTx00PNgAd}UbYJw)4*PK9zDjypZaDz)DF47v@8I+L0c*(ERy=Z% zHNET%Bfl>OGs5wR9H}~1<4}}M0n*o&`R@nOl~k-EVb1ZCGn=zV4YX}Knj0XMqzqd% z7}Y_861kL_OZ4&@9eN5gGCvpMjJsQ1NPXUw-9ya+&9lJ1PDx4&&o3M&(9JcRaC}iF zT$4s{Dtk`dZ=sz2^-iMvdL$(7R zSnfQ~Iuvp_j_LAdWXiMtHj}hk89|WzrPS$k@xEmZb%LCi<>qmYOI);n2H+I9_bM9Y z+?FP9^~qR`w%QGI!Eu$3a!Y8@6QjD*PHL9Lrmav3KwrE_s&s)BK5VpvZ1MSL@yUtQ zMXXERknx

    KI`7yqNaR%y;;kFF&yB=hT1j46iL44dV(D8{UXDoG*jx;}UwyB?J@c z@L27Ftf((;LG^Iccz;JJ3L6tUmSezcpKk_)xD5AxkV|%j)ifX1vQ?19Gqx>V(X~!X%waWfkov$p}8D?N6Vg*LjGa z(54Z(QB8NwpeIL1vguTRX0hkyP8{K9(xMJc%gxmk`LI$dS0^Kr90)t{aXE|2S&atk zF7mC{tM%2i)%fAm*)Jc_3jyd>iQ{m_6o_!fU&Okq=5|%_2}J))(f(?t3&4#l$CvE4&*kYuoi^ST+5KEB_lTuUqrBqPALF;T*OwA9+_}Wmf zd$}D|+qtJ(CBbaUh@PP>kLAo*7R>E)t9Zih7+6v>5 zv~;q`Oh>K#!SA7n{gzwu>+5j2l#xYdcDlE>n4YKae6X1&XCT7BDB^KAmvj44cZT^~X@>e&mQuh!JL!DmwQo4jM*l+a{e6Tf-L1joaFpBfDfZP5zY7 za8FdrL}%Osec1Fj=HM4n>vdK71?7f%4k5IR=HP_|+*g;Umg5U;1IvN8f}km1I`czB zuAqbTK^!Ka2D~Ie%D9<{*?KxPYW5mKvs5o$y#l1J z`Gey+bn^BsRQ zyJ6qhR<)P^{z5j-uT_^pwD7pDgul|&+`LaE|vo$l^r9kKQLQzr~T8nkru3=F;xy z8J1e$mf3BIA>C2+tj09FgNbng#<@Tzm_r@v-bheB8g8O~gIbhjWDeKA^H7%=`Y>l# zLn?>wUU0qmPml@3v_K_mZf@Su&iFDfw{VW&w@|AWa~38*yabVN5U)BKJ(gLcEGz}F zxP%p8hi~_#U~>^5MP>GQI6NqGCvbc7=Ac1zi@C;>k%489e)wg|+S=Nc`>ydOom|Tv zmciQkx|YY7EOYZxZ$)>_b&&spn@!9Ma=D%I(l%J3bUY?in+Q};TWGO9B<9oJ;$TFI z*JsJY7tr&6&s$;MW$e?SOJ&6=9+Py<0MuE91VGDM)O zyDgmPiN%x$eu6l_9PTD`PF)||!zYcHMmltY^kgymi7$ygzZOv-d1#-qOEK?yt_K?} z-uAkxFc{7N`0N2cx<=^<_7}05r3qU&lV;_`a2)kx%dMoa*k-IJ_0(-dX=SUUGFu!0 zOY^&egQxTlPcDk2(ni{8r1}&+!`CnugyB&u5420Z9^`h#R4NQw;CjCrL3-*__j)x( zsEKU$4xHYh`lo>~~A+b*Eg zOWwqf`M`0=cLWky_nZ!69il-!mYY|4$R4O!Du_<@MTC{`8+7iMicKC{jR;(m{)hw; z=)eBQjJ&P(ApeV4UvbvUF@U{uvnpP{c=6%fvPJarQ16ygXARdWMn3z1O_=&YFK!fa zeQ^|XP#XXg$h~zZV|Y!^mVbfmad1R}{R_|V4R1|zQ0_e);T6aDiu0+LHp|Gc1bwM( zAPr<`mIf(DjISf6JKqiU6pP)rWz#WfbX#Ivsb7fPvrbyQ`i_S79ttWE+{5=|U^7M+ zP0vD#jFuOQ*KM14{Pw6mLq8A^M7x}IMlhi)srX4ztHxZN475e)@E4OIpY%OF!hN-BE3a6J#* zRJ|Zh(88pbAYc7GZihU_(lD?kOlX=DRC1K z$*m)9Kc1h2>E8D!{V6H?)<%iUJE}mN%~kN|xUUmC_9{EYA~|`Xk1If|EP0?i^S(r* zRy`9`^EV3&gG<~%kbhTL6EnV2s*lVqZc+PnnS z;`$mk+LzB2)-A4EhVp_Vf^p*`HBXLqJL4e1X zb4g4Bg)N6`LeaU%YGO7Lp?kE(Mys_z`jo!lE>&pvc3?%aJ>J#{O?Y3}RdJu@y6L}q4`4lWIELrNsR4xj^K1l+=E)XeO5h)z<9fCkdj z?rzMw0O=AB7Gv38mL;~Dx!^k=z!o0jyloB`&Vj*wyNz$L_KSiPIb(6bC4P&0|ks9KE^*1KK|KN`9%AcVdeX8`cVD@4TP zT3}&&gWLJ@2p%C;5q1{py!ZW0 zLT6J(-l{N@&cO0*kLeRZ#W612Y*cRPEb{dXXXt}KAp_3Q3HH=$w)x0}lp`%?71w1} zb@OfQlrACkFbYqSr#P=-9oD<+@Pl^Am$GIMWDZo;lM(#wL0l_tgZtHDKBttV<)Ap& z2GwM5QZ0a1#px7;@hARN1E#jp;%gRe`Ih*d$F{CAYS#LZ^$vu4X-hw-LJO?6ZM^cb z1|=LFxn&85WMa+1arNlgfGhAoQsTxnPv!~;wOVY>Os1+^B>PI;h8MTxe@JsNy}>Cg zOE`n)s|R8Z?vr*`_;BEKctc5tHpcOqTR0ZLBs|s4H_AL9-?p&Y49s-r%H1yeo~?GJ zJ7^;{1vofmH8m4g>LP;Z>_@0zC1*mgd{T|#;_jL;ps_NJuM`{S z2`qw=q$T%~02xz&z!(G4g_~oa#9Y7-=}ReHYYrZhNkLcF zvvgas{nC(uU*A`;IXFNlA?GJD`{8O0ZLkY3ey_O_`chi-)qOR+zLx0<8C@QdMMG)o zc`b_)%y&;2G(1U%&t-voplr4R_Z0w!RExj6>h9qEHRveQRo7V<*QDL6L%tH#18*=pY(x`=0{*?<9j z#0E>fs%#S>TqhtTpv#)%v!yrgx%@ezG%)%z*b+kesycf21e9p{!O5BOJ%i03HEWZc zloyhttZKL}y%>P(E@DlNvLqz@0+9oP5yvr*?0geo;%iqzuQu>RoSb)(t`d@?-$O$i z|9f@vx78fg)jp|^59(Gtlt_uzI}CX4nUj^Si;GUt$G|XE_6cQYm~{bCwR)N5!Jx*y zQM>@pD~m^Lx6s~a`u_c=?$Hx^I*JUBA&0kmitPXWpEXP_u($k9$WQ&jw`W~@BW7J- z;l>^VXI>yWJDg6Y6bK&C>PXE20jKx%|NFj*s?Sx&zX0HkP}NcXS(_SbXlVQy`HUC& z6gj-Qa?m$DaGAvSM?#4MIqD`;%ltIF#Govt*Cnkn&y2wng&nAr`(rW{ zzGsYhA5;iQt~@0=GTfu?ufHdRpI{CGV&O!PY*RRhz%*4u73PQ0NIJelhad?>00iy+4cu=`SXE= z&#NH$s}Z%bEV|YR@zJVxx4C2VuilipdP;rg0Vx@oTfmXo@3=_0#Bwo&!znNFHt9dh zGDX!3A}!|D&T63n@caEJHkHnS=(+x zoml+Ew(j6!;{P*Mc__aCx1Ra?ga=EvK1D^4;5-VbIu2x(1JXiM;C>mYc5RprHdW{u zIM28KnHxs*L;(kJxm$lSJJ~!{+XGb&$^FBkcXi7G)K<)RtDLB7pS+|z`hbanbuIx^ z1vqd&XjU?4%iW5vlmz+zUmNt$k;#=1M0h z`R)PG|G`RDy6Bh<4Gr!33_mYd=H}u`_##;8(yTcyx@w`*U_?Zq@`jiqc{tu>r#*_y zEwkqViEy`b#g%?;kK5Zlkx=+q_osr|Wenz2VR*!d$_&3auqJ^l_eNE9M~Oh0RR3~B zZ;i-Y1t9*D0aoC8Bl!CJoONS@5D@f^0NJ7w6-81vW-!@Y9(5vaHCim(!hw)hOGP++ zu;4A}u(QNqWM<5)?f~^%zz77DQsc$|5jvNSaH1Ag#&=#BmxtQ{3Riyo=K2Vo0<5@oQl0ev%L}{Z9pzJD|h-iALO9(P)ekFpEI`IeRRnC0$W<&fT{(O=mmC2N&^cteqE z74}nv75Q-nk`DerK$REVS82FW-FKg3RXU&$*X(1eP%nVoYXogUhZKuuicUpkpQ(F+ zVr`aLNUmMhTOJ>2lxJc7DR^6zsCDy?(-bF1>3vl*|HBLo&&IV|Lj^<8Q*z0|J<(pW zbx()S1whpexSqCTDZp=lAu0aXkWzM(&mWY$tSHxzfCY>LuIb?5K|b_49xn1RqAv=! zB6of&z)vMgP15~72)tXT!zODT{Y8HO{p6~VQT(}YpouD7{{00Yxq{@JvbwO{Pj)ke zd^(HM`F{bsfyjAhYa_+!`PdF|fD~}A6$=Kn29pbRk&_;mA4(I+Z1;JzC;}54V8}1bsfIIIO#LRa>=&BwVyEb^)!zq7*#5?me9GFO$B&O@ z4wcAhXBKW2{>9&6G2xDmx79H3lZ!yf&;632z4^h$mV=N;E*ls@#X(@vX)8ByJ9JRD zJ`vRXBh1ERGf*6js9~+U4cQQU&8cY=AcbTRI2?2qz2p?mfakhzG-Yy80WjJ@P***flq|vUMOfs%=81*`N4zVI6|zt<>G}Z znxnKLIo#pUkGfY+*l;AM_X0*tn{q`k-_A%ol1$>t)hPqJi{NGuLN4o`PHpU)ir(Z( zDYMY%wIW*A$~SI`hktq%5fWLo_S|pC%}0{xVLRg$Al^L7V20^gzR*1(MlGOxz{Ec|4P_5|4YJtG^jy!K`WX8`)8=n(E;BUs`d&SN)a76 z6fOMyb03J1ai>fr3a5zI_3B1_B|``aB^~9xH$C2I>cT&rHcYX@62qC2-MOvXpD5E2 zF%bIY<26f{QU}q%5L6-GLBxmY`FDkEYUN0*W9}!*3uI}_FGGqhfR3kqZswQ7eQp`d}yER^SUrBUr@zXyV;7bwwfPMy2V3@rM?kWCEo?!``5}>NN#ch>kiA zzpMX>_vA$QC9l2%kLli#OI=*t*5;qA?ni1WCh7m=T}jBbWGo<%nlfFKQ5|;bW5&bI zA%JUmxFO2C24rXzWvvdT`-u&<8iSRfQi`t-aN_a{T^^(G9L@liE49aIN0T{cXvMGY z)%LgUSBs~mID}BJcw#Rs&O_@s%6W-jc`;ynKi85ds~5EQlZMJC0sgj2Uu zxDMFmKZ&rj54IMIAhgO+;q6@}b?=Vy&OH4v$S8pV_OCVl9gdMr^;S2~(A1Vyas8RK zs$*L|8|g*TvKrJSxKCM>gi(sK%%L}s707jE{(Fyty zWVane~9L25)|;!i&{Og zHSNB7@E^mGSelY4cv*kozBGb#YOKNho^figlARnjCPN0|Eae@217K}zVV65e{|p_pU~*K__+_ThjF5RWU{<| zq`7yLNQRtbU_*hKke2YS`ukvx(Jt!kUOkkWe5%7QF2kt;^_jyq67ud)rkxc4rYnsPBKL5a@ zn_0@h`TY9KIooVT(n*@?S}5|g@p`^taH@Te<8Zh zI+XH+(dsNNf$520Tv{0Jt9pTktI#m}Xn4KD^kmPEVXhLOXZD?SP)z5Ke91`Fb1G7? zZNOB~I@2Gh*hZ<#k~}kjXU?y?(5pS(iwZ$E+xd5sTVYTEcEhAw2LxVwL%FRnF!S@)pNV!)BaE9j`)EyG6;@;}-pd8lR{TkQehEku~c zYk=8i+@xYNSm?1w!XbrXx(>!^*^3^qs_h{!HZL!FmMCtgH2)jXaB*AHRt!uQn2X(z zxUfFV@dp5Zb~QT!S#HiVgyPe#H7Pg~exYnXzc1ayU8sFL5eK!NZhutAl7FV@cni5OiJjPHKbMX$wC9Ab)m>2doNqSd^U%BEwm$oUQ0NAJp*ExeB4y zz$+aco%M>D03YBCEJja9Ra=3h#Y&A4tRia}HlGk}^&qbqu{Suplp zR3mrWU!RMS|axZQZzmW#5^Cz%z>N*H{n|@_+F_l{Jw1rZ3>22L&+!MO8Y0eERAl1IkcfQp#7aQ)KRMD&%U~ z`hegwBrAH3UmP;S)fpVgxPZykHWK1I(Vdyt?v2~(w#(c{P-U1gX*Bo+eh=b-_mXn= z`Bkwy=a#CjQ*H9uT4uC4_SJs@mB?r{*R#iyGy)uqQAETw_AIi6Sx!eVRCJ6LyqCrO8#2@=P|Bv(u%?@i-68@Qdhw9k z{Er+;u4Y9erfpoWLPQFog%SA^RWBm?oB>Dcqc+-ly(In;=__lKeIoF}&iz+?uD#8;69| zoUbj(&r?g87w26ET%@;l?cwdH97+m zzL378jQfd#=IX=xXZgxVx7=_CjF#Y~hw}FVT@S7xb>@zwLhi41bQ0649=3J4@pZ7N z*DFEF0MoY(96Sjz%i#U#n{q}nP>K^`{879UV+%9|bWiSY@T$}itO4!F5KoAxwUaGE zY0N7_FjYDKjn^Rd`M>MKi5}*#%qAa4p51+ajR)>J3p&NFo4O{wsartDPT)sm;1Wdc z_XDa>xhtA>kgjdKM&-V|&Arx&rrA+Js=b}*)47Q1#qH5}xa#g2-{+gup+294AA7ii zG6VEO#Vo8>GFmciGH#GMt6=12XB$e^y)6BcUSXDHZ;3&*NI|uNys4H74N%;s2>Kt1#WG|!hXW*0n02c=grNQC)SJie7Nbi^jT1U(} z)n;S4U4SDc7ldz_OS`^#!(CJn22O+d!hb0&;IY!H?ef90l3grV-;)IyU2F>B#@bDYXx&D_q#J)V;T76kr>S4+ zTd`_u5ER&3P#cs*h7x$6a*oo5#&MbU4(mr>qwm(5QY93B~AQafY<9I`+W zP+HJ>P|8R*6L6n=j0J?6P1mXk;0J$Eu}r*E)PdpWS>!vQyj<|6cx63x~em~z{5mhzHr{-nkcVPlH603}h8wk(-IlUCvR z%AU;^5iV3mtk4tCw8vLoQ&V&K;VQIL_TI&Z_X3_1C^Y%OFJ!g1UMoZV~ApADcE`~dgvsPVcg_1FZfbZk3|xkTLy ziljyQUBJ8Ni&1x#!{o2!yrdsv*J92r0qG$7toWq?%)B$bMV^pVCkvKP4g?jH(U^#* zgFw>h5#aH|mdkm{QK=l~PVie1^aBbGrAtDno4mm-60^bsR}Qd4(6%w;$Uyz46Tea` zCVWO=p@WfjyddaY?5dG&b*^$X;k>o;^tEksSmGV3P&^I_Z>mGGs0Lr4cBy+q^EGT* z{Rl0>== z{}IKuw~Dr%VHTBS3IJFhfJI-|0?oWjKfS4ALc|0-NLED+7r-QdsooJ`(a=T$1@o6+ z*0r33+NLh(CSSxVOSZc9wQ`fTI=b{RG)ZbcvplLYw36HU39Pl!jX?F{CUq(%nc)w# zFgJf7Iseb^`O2v6S({=LQil#mVAwPNorP`!Z(y~j|U*&4!kBKn0wGxEAu20MXYTJf0$k(thP{I`uC?a#z|sZxw6kaLZqP*2 zAHaC*qyl;AC_L*=P zslJay_NoGI))ew@`=lF4mo4(mqQDC`0w!`_wV9R%Rr+8*XzO)sbLf%<~}aV`!+i@{keIY`~v1{Octi5e8kSyI|1dO zh)AuoxQNnGQ81cEV=fTbnU7=eBl&Kmrf52;TSz3VuLLa}kq(WUFsG4B~ctW{BllQH7aSmAc`7 z^;Gr>g&a)3>cOx3Uz#@sxwvC1NUbczY+rTo=!^zrgKh?c*{_knco!+XhwGo&lop-Y znja0{-o}+3L$%rsGI=bgAKnO*FcrvCiPO#L-ghyBD8v_N&f^|?bu}^L-^2beL+?pAc%0tfp(=Y8*?#=jzoKHSBUvem?ga7n~4X8fET+4 zYkDYUcP6LJs`Lj^B|k}Wy<6Z!Ishb<)t+jP zX($$EgD05+AThuO^f30*#`>X>&BX;ZJ^S|8UMG&O6T7L8`f7kq)EEB$s}ng1fmRt{ z5LrCOt1-qa>P;`I>iIFZHq>|dmP=kPp6qxxW9Mpr3`O>%W%8+Ea5SG{ma#FavTBi- zpL@j*p|ofs?TWSJhE=TVv07r}=H;!U8YQt`hIgQRHU&1OroF30AFD$ngvQX=RTE>dpl&g&Q+XMo#)Mdqur^^?#1QWH&4@hBNT-2?<(~ zgg8ObBaH<4qUCjrwQ+{Pzomz;=u z$8<COR3#ODIh)9oc;4=U|AT}xwBA0hIfM)+q|*^ z2;2Oip#jzWD4%K!jx`NMIbdTJ4RD1$ADi#Dn}NLzmQ=+Ep{=v8eO&2xpiL33BW*l2~IQX!YCb(SlWrh4(8*bp&*z8m)X z;$>4R8?iouZLsSa{ZH>^|J8#tnFvJ$uwO+Gjn!W7tST)G%{tF4?F!^9J4~->abbPe zr{0066#aUP&(ZrVr9}4HO+JYhJ%4xEWCX{8nE9!hQlJcP!-L5+WK=*^5SjijwJ3ZB zcF(}h|X}&Af0JQqZpH8fCrgt(e;`HR zbVF47M}A>zFsnadbd`k5M%E6Z%0B!ao$nFOc@<6VWIeAj0)W?cfr5lZKe??`3iJTC zMSo<`G~P0S=_petx0>(El>HMQDlzd9`X96jtqun4K{L}=q9?pYB1|aI6#m2;%>6l- zJyo8#+r_D<{=`q_2S$}9&x(?$jHdaL$MnOHS4V=#VG(rV!~%g(p|;DvJ%)%T1z9Vr ztgV|1&e?L*gz5hZNB>`SUmX@@`>pGTAP5SAGy)1rhX_cA!hnEu*O1a7-5^MJDbgh& zE!`;6DM)t=AVR+f zV`T;?r9vOwjuK=b8N96la3nyLff+itWtW$Sw!R;>u+;0)wKxn3v6F~ATAVE?F0=3C zB=U_+4|-`2tQ|Wu%`0SC|-qd1`yVc-p&AII;gfYqRm2LfzI#A`W0z z2)OK4sH&)scU}9vSlVb=SueJT+A{yCrD&(3@qADk?lmfq*8s#iz(6#>h=kP174`PK zxAMSy5Hp|2AMq)Q28G-fuZ2UGvN~E(%TZ=imFopMza4*?`YYf|SC+tG%Pj!rrdg+B zwIO$F47BS(!w+Voez?_GFc;12hf8FD&b+ooHSCwGH8EW-zSIB0tOz!%{_ELr(d!53 znDpOtCUmKAm}FwQyUPLt`5V0?B*XMc4xCI696M1YkG68a9vmw)M|W>=l03-E;Z_2j z^cp1GD^!1DLrQu02Z}JjG;y;#zED;sCntw_JkM7zsHlWOKw0uYl0>uMtLwz}!N7co z;gPTGrY>lL4?nP;f7CcVM=4L~%U~IDA-0^tANMVRLj|h%C_U|LouehAD<9jg0Gu0(BZy0|8k1Wl-b+_Wcr_rbq0& z*3M7=*%cDuiJqY9`hgWt`y$=7`0>{_({8S?9kiu}eF42~?e5$WqD$Y8b5GcH9)%X0 zgDMBCUH+Pv=S7#@m>Y^QYTo8a7!n>z+~jo&*R;u`FA2H&SH{MN4VGf{Oegg6lMm)3 zzGesJ^z-!&wxVyl;uEj3J5O;>y;!_jQ#~$DKwCImI%1AwI=A>946Drsc6qKB=UT-P zp9DkvH=t_r)8DBd!12K5rBB$NGJ>Z;UbhA?!~G6ON{s)+{t?PWmF_L@%?W)qQ0dkF8Y?wM>~4U*o^qbce-_4;Ifzm<``GuhB2%JCR7BE8z*#~LG;~l@ z?+`EFq2P;jNp@aP2-heBFra3sjN~7*$cdbT8Ukxz{MnXzl=MiXn zIl&C>Vsjb=oXhPg`vWTYn>*bCnO?G9@XY@_QP9L@KN+8h0|Hd0WlcAZ&9u`yqS~dd zfo?^7Gvs$3sgB%4#OgM_;R`1@vpFnB#M~taRmHYId}P)ImXrU?M)>_I@{XVXzEW+10s+6C%tb> zVWBdvF&u<~upBn%YRxb>*{8;3)BLP!<56F9SvUDn^vaub9aQZ#N+|)icI5dpH11eW zvOw9**j>XSIoj3iu6}LJteSugx1?NfrdMj_N&4fwYGu*0@cd)@lD98w4;sI{al<>v zf!v*Nl;jQ5epH6_dB$7I`-VD>5dfCDYdY6Kf6<&Z$$y?HSHvg494Tpxc8nnT^3%-f z!gNqtGvc4U?!f`nJG>x}C!htZ&;PgK_lzfn8l?|>*Ne-cRe^!GPKm!Uj{nkpp*%1* z{LBXQJh=sY=b+()<(23E3O;2}Qdb|Z->%8h2WeN)w|t;p&`u+9?Y07@#WO$-6*Xu1gU= zzrOwqxCdgfL?7=QQO*&7(%hH%LT%q-DIdRHwR&X}=qVXMN}phxnFyg^iI<;JZ| zmvRS~EJ*Ld6pcYvtGMSh=*wMI)%Y@C7X39?r$n2hb&BZN&}NCoD-ik2Z!g0r_RSq> zQanXV>vLCuFjrU!s3Hg@>tEb90iY`K>ZBj<0C;MsfxzECGEcZDNt}|#K1jITVm=?Y zqt^sgHMH;08Pti2% z@HC8nsjuc=v(sFK-iE9+2n?XuX@JT#+{FI|@gF=(l(WkR#V$aCLXp!Ey`?U|%j&ELL?b%6WO`_g zD{o<0zJ@UR6c>K*W2kiX>KGPgc2rmrII+FK+v5%;#;=ih_3E`@)88)jnj@W->>V*m zEo5^Mp0R13STuaGNJv6{3elbIahito`?Xt|m2`w9y$2=%Y9xu?5q|a&ib3`q)f7dj z946qAroJwJa@r!_LcqQ3X>x!q1%xr&z7fma^95~HE1Z|^c%*7tXDK92YRcLIo+Ieh zw}B^?C9F$`>n-`5S1FY~2$lr-p;+wDg>UVj>3cB}`yf-^SpyIw=9gAu3}yH{$2 zQ56pMn!bN;BG818WP6GcP!0iHNzX4rt52oOi4wRb8d zSS3D{z>>B+2B3}SF>_VgWgz+G>oh^uGdKSPC0go_ih1~!SpY}+_T==QuNjKRC!CM0 zzB~r~r0>_ztXDyLSu+P511v^t+-CJ3^XpSmXregnrUbLa-pn=Ac6#S<1KJuW$i$2T z7L^**!1W~~cW86`jBCtQi+N>3PbR3qazTxE|5OOl@PlUtd(*juqFEv42IlLzx*oXT zXw$L7Ap57I#N6{CkvbWl>#4iimeJAuATB_O{H#1%82YmJe_?mg>izin5?L8%`lLgi za)fNoM#CI%;RF4?{|5Sbi$BHF=bS-v027Lj)y?DL9Ec@uSHGJv4@1bO--a{;ipXbX zMz9|MfADPJHY)GSaoO?9xiyHPl!N+lmaJOa{{^z81>uH>66Q>pJKgjlBdRnW1u|J& z-0X}Tr>w~a*E?JsXb$-cs(`#5JXo0_hFt@1(5%Tpzr^6d;6k1upM5(G$CwEX$eSUk zp1zJBTJr(A1_0tjDKCsDWV;Hwr`Z1Cx|xaGi4r6Q?Y@))S&j*aZ(UyBwoyIGH(V<5i}iuA->?qX_v6wouR_LFr$JAs?4Hg;W&B_Trt?xq zddJYJji{v9VertpY^Oc{AcD#Zg#V;d4}4#p^|Kts+;^f78AV#5wcHpNT%+b=yQ0y4 z>Jx->P4?p|%%a(4QlhpPTE!7Lz2&>j~SVdQ*HAO0UAmbMLT z=NUtK;QtEQS#EW6T1ju`W2q=Ac1OC06QLN=bNrbW8pV#2e*q%;z&B1iVQ$8%CY4?%8M3A;f3Pc%X=?3sfZ&I5t6- z_?CpJ^m(nWOH$z2=qTfx0Wx1gPzkt8Wn+9FV5kAPWm$cT_+8}i%OW1D+5QG=9oxQ; z+P_4QQhE`Mi4yF7S_A_P#X#rRih=g}pb3zUVmFlf?~tCV9(Ufa`4$6E zOa)42j3mqv1hfC3iGkOx@HdooXwkT#p!zZVL8XU?qGtOp^y?!l2iK99`ymM>!mKQ- z02+bE;G_}e%yoJ0{hVrBzh!nS5%Cl`ykdEd*Rd7Od(Y+gqPVDGqeWhO7e$&PHmm%H zG&R01IGFf9NmC>8Viv^k9QL57w1wGYKoT4n=x$1gvpn?fFY!C(z`hl~S-m?);&8#W z{bQ6{ZlC^613*y}X_}(rACM7I0=+I89l$4KLnwo?IAVbjz<69o$nDu6Jr(sS%)JZx zEfbyw+t-e9W&}oI5)n`8KYmg*$_n8iHwsIg@Q@_*kQ$j_R@-7=QY+%Z!2c|T8H0Os zmv;OC-XN<3<|@HX-|jhII%3&A&Eb;+89a^JAv!=@<~(Zx5`PVTES`B7$Yn8A!bbfIbZFkFy?zUTNiI@NN_PWhk>~gwYf~7h z!a%C2Uvqts8Fe2P!1lOdQ|A6djc?R*s%~)SGH6oFgPDoRX119}e~+OKK8q*v%hQYw zy!RahfG^+f_Vo689G$-ycrHB3vt&8?RlW2|?CdW2T)EgF&-{uDt52a+VIfcJ2}+;v zh8l`FhG1Y}IkTD2Ahy4wRWYXfo*lYafqGHn4lrV-WAQCImB468ulmL}+M1f=>Quh@ z!4vmKsCR?`3Eg+eiudXf5AFLqibXC2Gl6nNy7SJjEU%~?Juk#;+1FpIEVprQvof-- z7@wCzz_mw%LO;N@fHDAeeM8+B^^bQX|48$)|0B%{{YRR&@xP>b|DWF| z3eZTr84u5nXE86;ZMB*$mTiG7g;4k+WG`$MyzBqgYhhq!(p>LX$6dV*#G&ioD z>biR!ocgq=IV*O`r!5oFDO~*)c*~0;A}xmgY=La?JExif(CD~vL!YENT$C(vQbx^6 z2{Zh2ylJC~%tpl_#Cvn}hi05o7(7~!%)yG%I9;uyn_%jXIj9jJ zi_)Zhr#nH1CKT@W%&9t^|3)q0tqU}7BQatYZ4xBc7M`Xotc;As zeD_U<`fN0-bWbp>?w!*QO*!xU*t`Supv1$sM}4q%$CfNq%5eUt4bOu`S5}CEBGVLY zFK>=nJ22i67jG{+W1YrRQ8AlITo{>@DT0sG$uzz)Z13CAs?t?aQ>(U`SDqAX8vXoX z;uT}q{NAvYbN=kY;Ti>JB>@|$bW_8b(_}tbw`RcYZ$!s&p z{t_hf^r@(Tm2RN|+t5pu)Y{Z{0Z$OtoeH=WKs|iX5^#R?+B=vl& zNjn9qa{WnusA7Ls;%vD^L&moQxeDi=fiH@`oDW3`p;W$!h5|&6XM)tUA;IpBe20O< z67ngJB<@mhYkKOM10lSg=!sg_{q`4PKKNqm^H#xd!#gt`_v(xWGXr|nkb=%V6WtXT zXwSEVT)8;-0>-~IGBDhmUm4r>SlWz7phcx--Ik0USm3zM zG4jd%ONNgo*YNXF=O?r2U+3}3r{hQscEwv-;QOvW zwVA57>}Y&*XhY3!AG;e4EVaSnzptaA(I#U#tX)1=D(^1wF~7zBXmv9rB__&qgVW#Q z#tl4!WGpVr7ox4dj88Y&0({LKKK6e2{%G7aK)P?)^|^?bB-D8FdOti6_SV`;X~Piw z{wQ-P3>8^cgUOpIo~x;l*HnBjEon@8W(l+;DxL_AHd|6#f00k&pRbtLKf0H`L61Ka z8TVY?^OOH^ZdNn!Ha#RRJ9j->AoS0*W5&M3CT*0nIk|TA_2kOJ=E=F$@sOr*A1m7l zV}>5>?S^%BQjA@QTd76fEX7k$WuavNb~!H<$oPaSI=gp zWeM+&4Hp=(bNI(T-W>I0pT&DDNBT}-wunW5M?X(=o3>$l9+ub7}t9Kdm(#DqC z91^2}&XfRDqRY*u=Z?k8k;f5FmZb&F@U$irOdU7Adre2+0 z>`te*k$}`TpCdIAth~@i@mX%5eP-e#YG%To*;S6k>W^<9EDh|*+VSk5i5xAe+%`^4 z9!L%~{n^JM@)a4&?tbdxEdtFm3ff_IY*pZ(_~TY zYpTdRKiCu#!F7Ape_DBTzGKQEZVLg?RuVXR_r4(Co4)ib&syHiy9Pvh1^K~zd({s* z9kqBWs16FN!|t|h-%Ab$JE=>T=f_TH348N{$1dIW_6KGag_Vg1mu=A~XIY9$NyN!w z5rTT2idXUPuKEM>ZEfakf4)_eFP5DDE-9Ci+vKf!M6X_{2yHUhluUPyv#j0~?xOor zP#5HZ_%Xab2`QpK+!@`D?kiI`n4`{I4|xC8N-NN9-iPNAZPhNFm}MQeOr zyb{b-))pc>o4!8kye*`_W`l&x3!O*(Y}PwH368uNr7-v*A^Y+DQu1y!R@BIec3=*E z@H1$sx5$YK=7+j4HNkMVBAq*8rO|VWKma$$uRqr{4Vh(L$Y%ehflY6l?``~?p!DmU z^yU4ywRIBZ-#JChKH|9~q_8MYuL4^n=>q~LC9X@hU$&P(t9~U3clLZVWjROd;_RnO z%zXXEk1pdkYrz?E$fvx_U{H!xCo=$SQ-fgTU}GL&Q$A9+>AAVa2K|9ul&l$bsyYqn z+_`Me_1C@kQlMB~_`GzT+hMVG)WtuJx=Fg9UH@ij{>S8G`gA8T?aIo-J8HDMi{jdK z&YaAJ+zDfoUYfNNx3t`cUq#1gY*XjV0vUSIA$D z+4-Ig=Gsl0vp2^s*#@OvyxeW81BJrw^DQ}{Tlu!p`sV0Ln3mMLrjP?WdJf*0Bb z?T1>#TdmxtmrKs8F-DFiPq-k4y5nkW=Ho1#ckaT7e5R@`TXen%7b-LvQ{Qh9hHopS zq~X*U4L(v7G+Sp!rJP%R;3r6m03grJAfRnd2^L`QO)pb;i?jBh)fuqY6=WDUgz_#@ z3OFB&2`~dtcfX`Fzq<%3=7R~Qq^cc@i_Y_|by7aOaHJD%X?{W0E4uO5p9~%08mdRLB(QN& z-yot9F?4=c-r&(Ln2a6pfB|Q;-)m3u;GLTB4@O#&pPeG)%#-kgm4X;Z`RxgIOTHix zwBq}Hr`|<1&Mm@($hLcVYpvbv3tb_<{>#W%qGVY4vew|@(BZ?SOu@H@;>|+kHYP%= z>ee{%N^NvTG3gy_iO%_13qPLgtzS}Vm2shUj}ugG!aw}VBkI;(r0W+bKbV}Ll56TN zq&?VF>RQYcLwI)tCAm*aXF|N_Z=x*JKz{~AXx#w5apod&@%l2e|Kqj?=qFh(M*U(RFPMNaX$npaICU^2^IB7(28<-5tTLLzuIuZ|_8^Q}PAj)n z)Hs;a8S5|VyZ~n(a8?VG4O}G}41HJC5>h^N-*j&$sVGd89UB`~k$K2QZeSus?a;5? zsI(J{cnf0p8%qVYpvBw$n`S==Y2+?`T%ILXspNc3<;^cUNP$H!NH+1n2`@e zk}pNHHciHiyhrcO%Nu#N)BRX53i8jB%G#RWt>LJ}aQN^6pMhp0hT*)dpQKSc$W!LV z$NMm$8T#}~^&NYhKL#C~+(s$I8l~q`Kes5KSvfX(lhzoz5Uns*EY>{z9U&4C*8rnd z&d%K)N$6kSPyMQJ$JiDkL#q(CN~u|zi@%&3`Uo7XVjFg5a7c7*d8{q3K8v5`x;aIO z0x6S_$#B}}Lf}RsrbaR2jMreH6$@I<>*jEg0TAkFq4>UPwi9d#l!AuGtz+6X)Ll2} zHtg0xnJ^d)VpUVxa z;pk&y5a)@dV{xKR!o#2-Q}Y3ln#ro&qr{giXsG9;PTSSak7pnHKIna0J}6VryQC(_ zby`fx@!F=LSJb?zhL2bW5g(`%m3iu=?fxv9LQ#iAMgt6>%Bbb4s-qBLRkErF5MRw54* zwr4CWgFfmuyUS4Vn&P+6COUC$aOkEm%}$j*(%|Kf;l zGN*7wpK3yut=pS-!!h;1l&Z?g@W>kwS;ei&Iv$i3OK4#WS7(pu_jdZna4?pjOr$he zbc^pZAQ~+b@q@!j3}!*Pr^RfadtYh2uX5U)Mnf**Qvwq+?avNYfzi^ooMXFb8@RvI zpPdh&brM6Z|IUeXz!ic!NfUID1nBnZSy(P!@BqzU8$L+ol!lFO>+-;#cHAutv&yN_m1>)rqTc;BgVba$K*7wGAdh_!qtOv5Ol$3lI2=T998Q?-;+x@|Ape z+PO9y+ll0tyfYFm8Z*SP>wS`#uSou8Ano!NlB*+OF6ZE5(P!$*YTa`@Y7thE`+eK^ z>)=FXcyf^hqKNGlrAOaY0vU*v?aVX^_R{2qeLVv!5G{t`uI!Ron2W@pC^8$(s$KVD z?q=Q81f8mhE;@D{{46sx)&0)GY)RoV)c_-S>^gVxZsB)rclHRn5#cLFxz^yGTGg;) z-ucjAA^5uDJ&p+7Y4IyJv7G`4dX`HtsUeVqWM6s4m;6VV6%?(MV(~GM?xp=j7`^x7 zoY>L0d?a}jpr5lUE4M`Y1uSr>pSs4wkH98FMQ0aK&FI_<#S%xBy1);g*sqLI4A|OB zSA0Enu!n0z{JmnsaFZI-0jtOJXQF;ygf2A8#ny0>Mq%W~IG(u|IC9Nx*YoczraY@- z`yTPnclYg-+qa=SATAxz?)~wpGi#GNLYt6~u&3!(AQE0kTKjg=qE04KR3tKm!NuI3 z_W@kCV|Ok}AEU~ZolHCfWE5FpAFVv`BoZ%-=}|V;W;w&RFx0+v$@e;Wpwj?8A`xe> zN@83x{eWL~x_&=Cs4en=RTI-cecb)Qq@-!mW6xjEcnmFq0#j9!uYxW?ZT4xm&rHr; z%PX7;3YJrEWn~ldbO$qCbil8>8uzdkf3h9!77(`49K>nz-&c8xFhn|9Bvs?9NyUt+ zj?Tp{La%hC@AO`sx;z8|0bx5>ktMu4YIX}831@N`IT#@$=Nd>x1p|W^Pg40*Zl_Wt zs2!X_3TS^4Agi(vo8M_QOQ){BEoaSb)3@UDha2AdBf|>f)c6BXKTP|fP4lyg!bQ_= zqv8(qF(WH;^3yk&IxQl5kJ$@MX8V$Kw48o$8T9CU?IwLbmEf`|V7Jjo`s!S!e@$eJ z11;hpwZGws{Vi=!eA{(aoJG9t=qr_3?7&i4*|~Q1AWKO)MSs6NOPg(^;d|j0nMf-I zBKkeCIg8=Y70=U`@wvtIUAjrIAS{$2_hNRxn>~|Ka*Wse%#Rj9E+Tu#rm=cK^-0+T zOv6zVe>i*<)@&7M>+R}9JcG$9knHmi47HnxtP#%$4GsP6aJgcL9Myh+JBvB@Rl6x7 zkym|Jha1E(*l>Z=VRkJ}LdiUyj|SA{I41HVcoa4xm8laA=&8bk%!foIzr^uAND*Znsa+K7M-(W#}9hYz}27wnf;* z*d8{KTLVg8mDd}d!f>LUy}A+J#`^&G^id|LH~13y&w4#<=~|bRyTa+SN!P#wa?MZu zKR%!$>&O0d7+wTQ;U7>|ch3*~?u<>;oP-D25<@bolB+|cc7%fC2mO-Y?6gn;x34@$ z;9CF{w!FYC6tUAfM~^yR94Z<>Q4WWzZX)l!IY=n+N<;dQj5d5T%43!hL@mX_|Ehpzq?P;oMSG{`;ndXiKBg`XD8kIYNzMa=WdEk_tz2? zD3F^E=C=FVd&k?}PH~u;ys7X58dq_q?7@#lP$gRC$8g5iBko7%zSWkE`DdM%oh3Kn zbV`&2Gvz^?3&ZsVGnBpsGw!I!xsPxW-v81(w}ndbOU};A*GQ_a8f&0*d8D-J&cBcP zf3+DyRW4uTc$#8ZWOv9fLq-E5jz8$pH^ufyUk%xv_O=*W#n}31RDvO1s@&Au(!~yg ze_1ih4Jy(sZ%FuLhJDVA0$1aWHjA@gR>F37fWTTFTy{lXC+i>cSWOK-q1#VJ)?4D`b&fjK38AUh?V?gz znnQPu<)|rUA4yC! zVaCwQrRpuUsChe_sp!ea#`Q*3yliF+9zMf;Aoq0FErxXJGBZl?Yd+Q;b@f7Ai2Zx5&&~9(wP39MaI>b1LW~TckSmK6M zoyceAR1{`EOLQ9g^L`r4_B}f&Jk~y$cZ2@dDz(+gWt&5+(L z5v#@AT*b4M+td+yx)sJh&%6*7b88}KZwk79k>q#w6obQ|G~I;^;Q0C|{sg$@1_>R{ z*>}b;CvxAeFh8_wfmG_wG0O7-7H_VC*Ugeos%*XAdhY^GSDAoqxTxx=^pqj%A+ z=kxc&60)C~9Cn9NbY^>f?t-Ie>qP-&WKXI`RB-tyMKuYDrQVu?NGq+Lt)}N;y7dO3 z^%rfR0J4gYcc?JJhQ{bOfR4C2ldRSqYrJ|96Pr}+*j|sP<@|B;gT!=gCM`Xgp5k_g zPzp!frcw~55gnMg5D5~jepQ&zU>?tVl=LaL`CQDBrn8()KVQnL!7d#T?9beZERa^i z_9G|epkA_Ubf|c?A@H`=o$1U?k>DQU%~c^yG!3lh$ooC$dr5%K>(sd`$0vpW%YYoJ zf$dz0KyrlrvmE?=<-!^)$0LbP7the5>Yc;L!7o5dA(>I%JIG#Zw@LNnBS=|THNTqw z*loBOm3q6$TYxrB&v=(<)5KX-%YCc~b4aRtisLqyVq`>^&)MTEa{~kXUFA$!ruN%Y zkZnA{W>X~oR1H7^^VzL!v2?T&h_0rLR^IXwq|v3`ZLah}dY$!B-g@1i#k(CF_9;LlRmf7U)JovU;`O_KVxT0u|fh5W?}1?BTJoa_G*GCkl0 zgJoCB3n04t3U;TR&~ALw1N=MiZ36hwjwrYUHP?Ovm}23}pL>Nr;MuMyL2h0G?(Be0 zty5<+Ma>Qz+;0yp7@(ox`u_v7b|dqp67S$=Vs`s8-}#+s=7QM%T10S=9l#O)nb%u! zJ+D_n<+Uehw*GrK?;Z^49 z>=pnI8eD=n7}TL6wlHCzeO}>^f4`G~krgM(ed{f+>z`rD@A5Lb#89JrDZoT(!a%ql z;ojc^kmX;*1o`2$rzhYuu+q|V@I{~o5`fDUJ5-R+6AH=5T8a%`=S{)+GmV%kq!kx6 zrMQ&lURA9>;S4z_RDw&8Ab>JdQ2N-7$QKUB$uhdn#LVo5BBg*ngH*-qS;~15=vl<) zj~RK`(-Z#8lb#?$jbx@dX^a$gJ7v!@T(W}zF9j~wJJ`I04h&mn;twruhk*T2aq{r` zg&Q7O@5DGH<%GCt6buxl+J4k#Wf2Gid24Wev%wAvWds`GLlL4Q@T~?6OqS46lGgGxWZJ>~W72boUEs^R5DKTcpUU+^e`}uma0QYX3(B@&+gCf#r2R-iJ?G2UvVC(RgoAfnlmad zEBoqoL}h%G!xI*s9>V zA|RAth*fx+>H6{!Bvt25k|q8tbGK6ryW5QTLv|tE<^bS~4!C}629?5L#*LR8{;gOL z0&KdC%B9LtIyA=Ovf9V2v}<;rO0FYDXDwgM6XSniV~0t9DQ#@^ja&Ki(dvIqX~!30 g2qc|3m@+^2i7V+pVCpWFLcL82A}3z*Qs3|Y00+HnWB>pF diff --git a/packages/react-native-enriched-markdown/__tests__/ios/OrderedListMarkerWidthTests.mm b/packages/react-native-enriched-markdown/__tests__/ios/OrderedListMarkerWidthTests.mm deleted file mode 100644 index 03e42822c..000000000 --- a/packages/react-native-enriched-markdown/__tests__/ios/OrderedListMarkerWidthTests.mm +++ /dev/null @@ -1,178 +0,0 @@ -#import "../../ios/parser/ENRMMarkdownParser.h" -#import "../../ios/parser/MarkdownASTNode.h" -#import "../../ios/renderer/AttributedRenderer.h" -#import "../../ios/renderer/ListItemRenderer.h" -#import "../../ios/renderer/RenderContext.h" -#import "../../ios/styles/StyleConfig.h" -#import - -static MarkdownASTNode *ENRMWidthList(NSInteger start, NSUInteger count) -{ - MarkdownASTNode *list = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeOrderedList]; - list.attributes[@"start"] = [@(start) stringValue]; - for (NSUInteger i = 0; i < count; i++) { - MarkdownASTNode *item = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeListItem]; - MarkdownASTNode *paragraph = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeParagraph]; - MarkdownASTNode *text = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeText]; - text.content = @"item"; - [paragraph addChild:text]; - [item addChild:paragraph]; - [list addChild:item]; - } - return list; -} - -@interface ENRMOrderedListMarkerWidthTests : XCTestCase -@end - -@implementation ENRMOrderedListMarkerWidthTests - -- (NSArray *)markersForLists:(NSArray *)lists - config:(StyleConfig *)config -{ - AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:config]; - NSAttributedString *text = [renderer renderNodes:lists context:[[RenderContext alloc] init] block:nil]; - NSMutableArray *markers = [NSMutableArray array]; - [text enumerateAttribute:ListItemMarkerStartAttribute - inRange:NSMakeRange(0, text.length) - options:0 - usingBlock:^(NSArray *value, NSRange range, BOOL *stop) { - if (value) - [markers addObjectsFromArray:value]; - }]; - return markers; -} - -- (void)testShortListKeepsItsIndentAndLongListsShareTheWidestGutter -{ - StyleConfig *config = [[StyleConfig alloc] init]; - [config setListStyleFontSize:16]; - [config setListStyleMarginLeft:24]; - [config setListStyleGapWidth:11]; - CGFloat baseline = [@"99." sizeWithAttributes:@{NSFontAttributeName : config.listMarkerFont}].width; - CGFloat shortIndent = MAX(config.listStyleMarkerMinWidth, baseline) + config.effectiveListGapWidth; - NSArray *shortMarkers = [self markersForLists:@[ ENRMWidthList(1, 99) ] config:config]; - for (ENRMListMarkerDescriptor *marker in shortMarkers) { - XCTAssertEqualWithAccuracy(marker.indent, shortIndent, 0.01); - } - for (NSNumber *start in @[ @98, @998, @12345 ]) { - NSArray *markers = [self markersForLists:@[ ENRMWidthList(start.integerValue, 4) ] config:config]; - CGFloat width = baseline; - for (ENRMListMarkerDescriptor *marker in markers) { - NSString *label = [NSString stringWithFormat:@"%ld.", (long)marker.number]; - width = MAX(width, [label sizeWithAttributes:@{NSFontAttributeName : config.listMarkerFont}].width); - } - for (ENRMListMarkerDescriptor *marker in markers) { - XCTAssertEqualWithAccuracy(marker.indent, width + config.effectiveListGapWidth, 0.01); - } - } -} - -- (void)testNestedAndFollowingListsRestoreTheirOwnGutters -{ - StyleConfig *config = [[StyleConfig alloc] init]; - [config setListStyleFontSize:16]; - [config setListStyleMarginLeft:24]; - [config setListStyleGapWidth:11]; - MarkdownASTNode *outer = ENRMWidthList(98, 4); - [outer.children[0] addChild:ENRMWidthList(9998, 4)]; - NSArray *markers = [self markersForLists:@[ outer, ENRMWidthList(1, 1) ] config:config]; - CGFloat outerIndent = 0; - CGFloat nestedIndent = 0; - for (ENRMListMarkerDescriptor *marker in markers) { - if (marker.depth == 1) { - nestedIndent = marker.indent; - } else if (marker.number != 1) { - if (outerIndent == 0) - outerIndent = marker.indent; - XCTAssertEqualWithAccuracy(marker.indent, outerIndent, 0.01); - } - } - XCTAssertGreaterThan(nestedIndent, outerIndent + config.listStyleMarginLeft); - ENRMListMarkerDescriptor *last = markers.lastObject; - XCTAssertLessThan(last.indent, outerIndent); -} - -- (void)testNestedListsKeepTheSpaceReservedForWideParentMarkers -{ - StyleConfig *config = [[StyleConfig alloc] init]; - [config setListStyleFontSize:16]; - [config setListStyleMarginLeft:24]; - [config setListStyleGapWidth:11]; - MarkdownASTNode *outer = ENRMWidthList(123456789, 1); - MarkdownASTNode *middle = ENRMWidthList(1, 1); - [middle.children[0] addChild:ENRMWidthList(1, 1)]; - [outer.children[0] addChild:middle]; - NSArray *markers = [self markersForLists:@[ outer ] config:config]; - ENRMListMarkerDescriptor *parent = markers[0]; - ENRMListMarkerDescriptor *child = markers[1]; - ENRMListMarkerDescriptor *leaf = markers[2]; - XCTAssertEqual(parent.depth, 0); - XCTAssertEqual(child.depth, 1); - XCTAssertEqual(leaf.depth, 2); - XCTAssertEqualWithAccuracy(child.indent, parent.indent + config.listStyleMarginLeft, 0.01); - XCTAssertEqualWithAccuracy(leaf.indent, parent.indent + 2 * config.listStyleMarginLeft, 0.01); -} - -- (void)testTaskItemsDoNotPassTheOrderedListsExtraWidthToTheirChildren -{ - StyleConfig *config = [[StyleConfig alloc] init]; - [config setListStyleFontSize:16]; - [config setListStyleMarginLeft:24]; - [config setListStyleGapWidth:11]; - NSMutableArray *> *results = [NSMutableArray array]; - for (NSNumber *start in @[ @1, @12345 ]) { - MarkdownASTNode *outer = ENRMWidthList(start.integerValue, 3); - MarkdownASTNode *task = outer.children[1]; - task.attributes[@"isTask"] = @"true"; - MarkdownASTNode *child = ENRMWidthList(1, 1); - child.type = MarkdownNodeTypeUnorderedList; - [task addChild:child]; - [outer.children[2] addChild:ENRMWidthList(1, 1)]; - [results addObject:[self markersForLists:@[ outer ] config:config]]; - } - NSArray *shortMarkers = results[0]; - NSArray *wideMarkers = results[1]; - XCTAssertEqual(shortMarkers.count, 5u); - XCTAssertEqual(wideMarkers.count, 5u); - ENRMListMarkerDescriptor *task = wideMarkers[1]; - ENRMListMarkerDescriptor *child = wideMarkers[2]; - XCTAssertTrue(task.isTask); - XCTAssertEqual(child.depth, 1); - XCTAssertEqual(child.listType, ListTypeUnordered); - XCTAssertEqualWithAccuracy(task.indent, [shortMarkers[1] indent], 0.01); - CGFloat bulletIndent = - [config effectiveListMarginLeftForBullet] + config.effectiveListGapWidth + config.listStyleMarginLeft; - XCTAssertEqualWithAccuracy(child.indent, bulletIndent, 0.01); - XCTAssertEqualWithAccuracy(child.indent, [shortMarkers[2] indent], 0.01); - ENRMListMarkerDescriptor *numericChild = wideMarkers[4]; - ENRMListMarkerDescriptor *numericParent = wideMarkers[3]; - XCTAssertEqualWithAccuracy(numericChild.indent, numericParent.indent + config.listStyleMarginLeft, 0.01); -} - -- (void)testSourceNumbersAfterTheStartDoNotOverrideRenderedNumbers -{ - ENRMMarkdownParser *parser = [[ENRMMarkdownParser alloc] init]; - MarkdownASTNode *document = [parser parseMarkdown:@"98. a\n400. b\n1. c\n2. d"]; - StyleConfig *config = [[StyleConfig alloc] init]; - [config setListStyleFontSize:16]; - [config setListStyleMarginLeft:24]; - [config setListStyleGapWidth:11]; - NSArray *markers = [self markersForLists:document.children config:config]; - XCTAssertEqual(markers.count, 4u); - for (NSUInteger i = 0; i < markers.count; i++) { - ENRMListMarkerDescriptor *marker = markers[i]; - XCTAssertEqual(marker.number, 98 + (NSInteger)i); - } -} - -- (void)testMarkerMinimumWidthRemainsAFloor -{ - StyleConfig *config = [[StyleConfig alloc] init]; - [config setListStyleMarkerMinWidth:200]; - NSArray *markers = [self markersForLists:@[ ENRMWidthList(998, 4) ] config:config]; - for (ENRMListMarkerDescriptor *marker in markers) { - XCTAssertEqualWithAccuracy(marker.indent, 200 + config.effectiveListGapWidth, 0.01); - } -} -@end diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt index 55d5a6366..0f921dbb5 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt @@ -42,9 +42,6 @@ class BlockStyleContext { var listType: ListType? = null var listItemMarkerWidth: Float? = null var listItemNumber = 0 - var listMarkerWidth = 0f - var ancestorMarkerOffset = 0f - var listItemMarkerExtra = 0f var taskItemCount = 0 var accumulatedIndent = 0 @@ -155,9 +152,6 @@ class BlockStyleContext { listDepth = 0 listType = null listItemNumber = 0 - listMarkerWidth = 0f - ancestorMarkerOffset = 0f - listItemMarkerExtra = 0f listItemMarkerWidth = null taskItemCount = 0 accumulatedIndent = 0 diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt index f572d3fbf..f73b54f00 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt @@ -51,34 +51,16 @@ class ListItemRenderer( taskIndex = taskIndex, isChecked = isChecked, drawsMarker = drawsMarker, - ancestorMarkerOffset = styleContext.ancestorMarkerOffset, parentMarkerWidth = parentMarkerWidth, ) } else { when (listType) { BlockStyleContext.ListType.UNORDERED -> { - UnorderedListSpan( - listStyle, - depth, - factory.context, - factory.styleCache, - drawsMarker, - styleContext.ancestorMarkerOffset, - parentMarkerWidth, - ) + UnorderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker, parentMarkerWidth) } BlockStyleContext.ListType.ORDERED -> { - OrderedListSpan( - listStyle, - depth, - factory.context, - factory.styleCache, - drawsMarker, - styleContext.listMarkerWidth, - styleContext.ancestorMarkerOffset, - parentMarkerWidth, - ).apply { + OrderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker, parentMarkerWidth).apply { setItemNumber(styleContext.listItemNumber) } } @@ -87,8 +69,6 @@ class ListItemRenderer( val markerSpan = makeSpan(drawsMarker = true) - val previousMarkerExtra = styleContext.listItemMarkerExtra - styleContext.listItemMarkerExtra = (markerSpan as? OrderedListSpan)?.markerExtraWidth ?: 0f val prevIndent = styleContext.accumulatedIndent styleContext.accumulatedIndent = prevIndent + markerSpan.getLeadingMargin(false) try { @@ -96,7 +76,6 @@ class ListItemRenderer( factory.renderChildren(node, builder, onLinkPress, onLinkLongPress) } finally { styleContext.accumulatedIndent = prevIndent - styleContext.listItemMarkerExtra = previousMarkerExtra styleContext.listItemMarkerWidth = parentMarkerWidth } diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt index 430011a7c..2bac5b11d 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt @@ -4,7 +4,6 @@ import android.text.SpannableStringBuilder import com.swmansion.enriched.markdown.parser.MarkdownASTNode import com.swmansion.enriched.markdown.spans.ListItemSpacingSpan import com.swmansion.enriched.markdown.spans.MarginBottomSpan -import com.swmansion.enriched.markdown.spans.OrderedListSpan import com.swmansion.enriched.markdown.styles.ListStyle import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE import com.swmansion.enriched.markdown.utils.text.span.applyLineHeightSkippingImages @@ -34,27 +33,6 @@ class ListRenderer( val contextManager = ListContextManager(factory.blockStyleContext) val entryState = contextManager.enterList(listType, listStyle, startNumber) - val previousMarkerWidth = factory.blockStyleContext.listMarkerWidth - val previousMarkerOffset = factory.blockStyleContext.ancestorMarkerOffset - if (entryState.previousDepth > 0) { - factory.blockStyleContext.ancestorMarkerOffset += factory.blockStyleContext.listItemMarkerExtra - } - factory.blockStyleContext.listMarkerWidth = - if (isOrdered) { - val marker = OrderedListSpan(listStyle, 0, factory.context, factory.styleCache) - var number = startNumber - var width = marker.measureMarkerWidth(99) - for (item in node.children) { - if (item.type != MarkdownASTNode.NodeType.ListItem) continue - if (number >= 100 && item.attributes["isTask"] != "true") { - width = maxOf(width, marker.measureMarkerWidth(number)) - } - number++ - } - width - } else { - 0f - } // For top-level lists, insert marginTop spacer before rendering content if (entryState.previousDepth == 0) { @@ -72,8 +50,6 @@ class ListRenderer( try { factory.renderChildren(node, builder, onLinkPress, onLinkLongPress) } finally { - factory.blockStyleContext.listMarkerWidth = previousMarkerWidth - factory.blockStyleContext.ancestorMarkerOffset = previousMarkerOffset contextManager.exitList(entryState) } diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt index 4d90eab01..a7715a730 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt @@ -23,7 +23,6 @@ abstract class BaseListSpan( protected val marginLeft: Float, protected val gapWidth: Float, internal val drawsMarker: Boolean = true, - internal val ancestorMarkerOffset: Float = 0f, internal val parentMarkerWidth: Float? = null, ) : MetricAffectingSpan(), LeadingMarginSpan { diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt index fd34fb40e..1d5541f09 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt @@ -19,8 +19,6 @@ class OrderedListSpan( context: Context, styleCache: SpanStyleCache, drawsMarker: Boolean = true, - private val markerWidth: Float = 0f, - ancestorMarkerOffset: Float = 0f, parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, @@ -36,7 +34,6 @@ class OrderedListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, - ancestorMarkerOffset = ancestorMarkerOffset, parentMarkerWidth = parentMarkerWidth, ) { companion object { @@ -50,6 +47,8 @@ class OrderedListSpan( applyStyles(null, ReactConstants.UNSET, fontWeight, fontFamily, context.assets) } + private val markerColumnWidth = listStyle.effectiveMarkerWidth(configureMarkerPaint().measureText("99.")) + private fun configureMarkerPaint(): TextPaint = sharedMarkerPaint.apply { textSize = listStyle.fontSize @@ -57,16 +56,7 @@ class OrderedListSpan( typeface = markerTypeface } - private val defaultMarkerWidth = measureMarkerWidth(99) - private val resolvedMarkerWidth = maxOf(markerWidth, defaultMarkerWidth) - - internal val markerExtraWidth = resolvedMarkerWidth - defaultMarkerWidth - - override fun getMarkerWidth(): Float = resolvedMarkerWidth - - internal fun measureMarkerWidth(number: Int): Float = listStyle.effectiveMarkerWidth(configureMarkerPaint().measureText("$number.")) - - internal override fun getBaselineMarkerWidth(): Float = defaultMarkerWidth + override fun getMarkerWidth(): Float = markerColumnWidth var itemNumber: Int = 1 private set @@ -86,7 +76,7 @@ class OrderedListSpan( val text = if (dir < 0) ".$itemNumber" else "$itemNumber." val textWidth = markerPaint.measureText(text) - val markerRightEdge = x + (depth * marginLeft + ancestorMarkerOffset + getMarkerWidth()) * dir + val markerRightEdge = x + (depth * marginLeft + getMarkerWidth()) * dir val markerX = if (dir > 0) markerRightEdge - textWidth else markerRightEdge canvas.drawText(text, markerX, baseline.toFloat(), markerPaint) diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt index 93eddfe44..f4677263f 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt @@ -20,7 +20,6 @@ class TaskListSpan( val taskIndex: Int, val isChecked: Boolean, drawsMarker: Boolean = true, - ancestorMarkerOffset: Float = 0f, parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, @@ -36,7 +35,6 @@ class TaskListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, - ancestorMarkerOffset = ancestorMarkerOffset, parentMarkerWidth = parentMarkerWidth, ) { private val checkboxSize = taskStyle.checkboxSize @@ -80,7 +78,7 @@ class TaskListSpan( // Right-align the checkbox inside the reserved marker column so it hugs // the gap before the text. At the default (markerColumnWidth == // checkboxSize) this is identical to the previous flush-left layout. - val centerX = x + (depth * marginLeft + ancestorMarkerOffset + markerColumnWidth - checkboxSize / HALF_DIVISOR) * dir + val centerX = x + (depth * marginLeft + markerColumnWidth - checkboxSize / HALF_DIVISOR) * dir val half = checkboxSize / HALF_DIVISOR rect.set(centerX - half, centerY - half, centerX + half, centerY + half) diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt index a7597f88a..dd41e46ba 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt @@ -14,7 +14,6 @@ class UnorderedListSpan( context: Context, styleCache: SpanStyleCache, drawsMarker: Boolean = true, - ancestorMarkerOffset: Float = 0f, parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, @@ -30,7 +29,6 @@ class UnorderedListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, - ancestorMarkerOffset = ancestorMarkerOffset, parentMarkerWidth = parentMarkerWidth, ) { companion object { @@ -69,7 +67,7 @@ class UnorderedListSpan( // it hugs the gap before the text — matches iOS behavior and stays // visually flush-left when the column width equals the bullet radius // (the default). - val bulletX = x + (depth * marginLeft + ancestorMarkerOffset + markerColumnWidth) * dir + val bulletX = x + (depth * marginLeft + markerColumnWidth) * dir val bulletY = baseline + (markerFontMetrics.ascent + markerFontMetrics.descent) / 2f when (depth) { diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt index 36c0e22ca..4f2efc075 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt @@ -131,30 +131,17 @@ object TaskListTapUtils { taskIndex = targetIndex, isChecked = newChecked, drawsMarker = old.drawsMarker, - ancestorMarkerOffset = old.ancestorMarkerOffset, parentMarkerWidth = old.parentMarkerWidth, ) - // Layout draws leading margins in insertion order, and a re-added span moves to the end of it. - // Re-add the task's spans and everything attached after them (its ancestors) in their original - // order; the task's own nested items were attached first and stay where they are. - data class ListSpanState( - val span: BaseListSpan, - val start: Int, - val end: Int, - val flags: Int, - ) - - val coveringSpans = spannable.getSpans(spanStart, spanEnd, BaseListSpan::class.java) - val firstTarget = coveringSpans.indexOfFirst { it is TaskListSpan && it.taskIndex == targetIndex } - val listSpans = - coveringSpans.drop(firstTarget).map { - ListSpanState(it, spannable.getSpanStart(it), spannable.getSpanEnd(it), spannable.getSpanFlags(it)) - } - listSpans.forEach { spannable.removeSpan(it.span) } - for ((old, start, end, flags) in listSpans) { - val replacement = if (old is TaskListSpan && old.taskIndex == targetIndex) toggledCopy(old) else old - spannable.setSpan(replacement, start, end, flags) + // Replace every segment of the item — spans are split around code blocks + for (old in targetSpans) { + val start = spannable.getSpanStart(old) + val end = spannable.getSpanEnd(old) + // Keep the original flags so the list item priority survives the toggle + val flags = spannable.getSpanFlags(old) + spannable.removeSpan(old) + spannable.setSpan(toggledCopy(old), start, end, flags) } // The marker may be drawn by an anchor span wrapping an unattached copy diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/spans/OrderedListMarkerWidthTest.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/spans/OrderedListMarkerWidthTest.kt deleted file mode 100644 index c7e74a81d..000000000 --- a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/spans/OrderedListMarkerWidthTest.kt +++ /dev/null @@ -1,530 +0,0 @@ -package com.swmansion.enriched.markdown.spans - -import android.graphics.Bitmap -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.Typeface -import android.text.SpannableString -import android.text.Spanned -import android.text.StaticLayout -import android.text.TextPaint -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import com.facebook.react.bridge.JavaOnlyArray -import com.facebook.react.bridge.JavaOnlyMap -import com.facebook.react.uimanager.DisplayMetricsHolder -import com.swmansion.enriched.markdown.accessibility.AccessibleMarkdownTextView -import com.swmansion.enriched.markdown.parser.MarkdownASTNode -import com.swmansion.enriched.markdown.parser.MarkdownASTNode.NodeType -import com.swmansion.enriched.markdown.renderer.Renderer -import com.swmansion.enriched.markdown.styles.StyleConfig -import com.swmansion.enriched.markdown.utils.text.interaction.TaskListTapUtils -import com.swmansion.enriched.markdown.utils.text.view.setupAsMarkdownTextView -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.RuntimeEnvironment -import org.robolectric.annotation.Config -import org.robolectric.annotation.GraphicsMode - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [30]) -@GraphicsMode(GraphicsMode.Mode.NATIVE) -class OrderedListMarkerWidthTest { - private val context = RuntimeEnvironment.getApplication() - - @Test - fun shortListsKeepTheirIndentAndLongListsShareTheirWidestGutter() { - val config = styleConfig() - val paint = - TextPaint().apply { - textSize = config.listStyle.fontSize - typeface = Typeface.create("monospace", Typeface.NORMAL) - } - val baseline = paint.measureText("99.") - val short = render(config, list(1, 99)) - short.forEach { assertEquals((baseline + config.listStyle.gapWidth).toInt(), it.getLeadingMargin(false)) } - for ((start, count) in listOf(1 to 250, 98 to 4, 998 to 4, 12345 to 4, 0 to 101)) { - val spans = render(config, list(start, count)) - val widest = maxOf(baseline, spans.maxOf { paint.measureText("${it.itemNumber}.") }) - spans.forEach { assertEquals((widest + config.listStyle.gapWidth).toInt(), it.getLeadingMargin(false)) } - assertTrue(spans.first().getLeadingMargin(false) > short.first().getLeadingMargin(false)) - } - } - - @Test - fun nestedAndFollowingListsRestoreTheirOwnGutters() { - val config = styleConfig() - val outer = list(98, 4) - val first = outer.children.first() - val nested = outer.copy(children = listOf(first.copy(children = first.children + list(9998, 4))) + outer.children.drop(1)) - val spans = render(config, nested, list(1, 1)) - val parent = spans.filter { it.depth == 0 && it.itemNumber != 1 } - assertEquals(4, parent.size) - parent.forEach { assertEquals(parent.first().getLeadingMargin(false), it.getLeadingMargin(false)) } - spans.filter { it.depth == 1 }.forEach { assertTrue(it.getLeadingMargin(false) > config.listStyle.marginLeft) } - val following = spans.single { it.depth == 0 && it.itemNumber == 1 } - assertTrue(following.getLeadingMargin(false) < parent.first().getLeadingMargin(false)) - } - - @Test - fun markerMinimumWidthRemainsAFloor() { - val config = styleConfig(200.0) - render(config, list(998, 4)).forEach { - assertEquals((config.listStyle.markerMinWidth + config.listStyle.gapWidth).toInt(), it.getLeadingMargin(false)) - } - } - - @Test - fun drawnMarkersStayInsideTheGutterAndAttachedToTheirParagraphs() { - for (start in listOf(1, 98, 9998)) { - val config = styleConfig() - val outer = list(start, 4) - val parent = outer.children[2] - val middle = list(1, 1) - val child = middle.children[0] - val threeLevels = middle.copy(children = listOf(child.copy(children = child.children + list(1, 1)))) - val nested = - outer.copy( - children = - outer.children.take(2) + parent.copy(children = parent.children + threeLevels) + outer.children.drop(3), - ) - assertDrawnMarkerPositions(config, nested) - } - } - - @Test - fun nestedBulletColumnsKeepTheirGapUnderWideParents() { - val config = styleConfig() - - fun tree(start: Int): MarkdownASTNode { - val outer = list(start, 4) - val parent = outer.children[2] - val bullets = list(1, 2).copy(type = NodeType.UnorderedList) - return outer.copy( - children = outer.children.take(2) + parent.copy(children = parent.children + bullets) + outer.children.drop(3), - ) - } - for (start in listOf(98, 9998)) { - assertNestedMarkerGapsUnchanged(config, tree(1), tree(start)) - } - } - - @Test - fun tasksDoNotPassTheWideListsNumericExtraToTheirChildren() { - val config = styleConfig() - - fun tree(start: Int): MarkdownASTNode { - val outer = list(start, 3) - val task = outer.children[1] - val taskWithChild = task.copy(attributes = mapOf("isTask" to "true"), children = task.children + list(1, 1)) - val numeric = outer.children[2] - val numericWithChild = numeric.copy(children = numeric.children + list(1, 1)) - return outer.copy(children = listOf(outer.children[0], taskWithChild, numericWithChild)) - } - assertNestedMarkerGapsUnchanged(config, tree(1), tree(12345)) - } - - @Test - fun nestedTasksKeepTheirGapUnderWideNumericParents() { - val config = styleConfig() - - fun tree(start: Int): MarkdownASTNode { - val outer = list(start, 4) - val parent = outer.children[2] - val nested = list(1, 1) - val task = nested.children[0].copy(attributes = mapOf("isTask" to "true")) - val taskList = nested.copy(children = listOf(task)) - return outer.copy( - children = outer.children.take(2) + parent.copy(children = parent.children + taskList) + outer.children.drop(3), - ) - } - for (start in listOf(98, 9998)) { - assertNestedMarkerGapsUnchanged(config, tree(1), tree(start)) - } - } - - @Test - fun togglingATaskUnderAWideParentKeepsEveryMarginAndMarkerPosition() { - assertTaskToggleKeepsGeometry(opensWithSublist = false) - } - - @Test - fun togglingAnAnchoredTaskUnderAWideParentKeepsEveryMarginAndMarkerPosition() { - assertTaskToggleKeepsGeometry(opensWithSublist = true) - } - - @Test - fun sameTypeBulletAndTaskNestsKeepTheirMarkerGap() { - val config = styleConfig() - val ordered = list(1, 1) - val bullet = ordered.copy(type = NodeType.UnorderedList) - val task = ordered.copy(children = listOf(ordered.children[0].copy(attributes = mapOf("isTask" to "true")))) - for (parent in listOf(bullet, task)) { - val item = parent.children[0] - assertDrawnMarkerPositions(config, parent.copy(children = listOf(item.copy(children = item.children + parent)))) - } - } - - @Test - fun shortMixedNestsUseTheirOwnMarkerColumns() { - val config = styleConfig(fontFamily = "", gapWidth = 6.0, checkboxSize = 14.0) - val ordered = list(1, 1) - val bullet = ordered.copy(type = NodeType.UnorderedList) - val task = ordered.copy(children = listOf(ordered.children[0].copy(attributes = mapOf("isTask" to "true")))) - val shapes = listOf(ordered to bullet, bullet to ordered, bullet to task, ordered to task, task to bullet) - val mixedIndents = listOf(33f, 52f, 44f, 44f, 33f) - for ((index, shape) in shapes.withIndex()) { - val (parent, child) = shape - val tree = parent.copy(children = listOf(parent.children[0].copy(children = parent.children[0].children + child))) - val nested = drawMarkers(config, tree).single { it.depth == 1 } - assertEquals("mixed indent for shape $index", mixedIndents[index], nested.paragraphLeft, 0.01f) - assertTrue(nested.marker.left >= 0f) - } - } - - @Test - fun markersAnchoredOnANestedListKeepTheirAncestorsOffset() { - val config = styleConfig() - val outer = list(12345, 1) - val middle = list(1, 1) - val openingSublist = middle.children[0].copy(children = listOf(list(1, 1))) - val renderer = Renderer() - renderer.configure(config, context) - val nested = - outer.copy( - children = - listOf( - outer.children[0].copy( - children = - outer.children[0].children + middle.copy(children = listOf(openingSublist)), - ), - ), - ) - val text = SpannableString(renderer.renderContent(listOf(nested))) - assertEquals(1, text.getSpans(0, text.length, ListMarkerAnchorSpan::class.java).size) - val layout = StaticLayout.Builder.obtain(text, 0, text.length, TextPaint(), 2000).build() - val canvas = MarkerCanvas(Bitmap.createBitmap(2000, 2000, Bitmap.Config.ARGB_8888)) - layout.draw(canvas) - assertEquals(3, canvas.markers.size) - val markersByColumn = canvas.markers.sortedBy { it.right } - val root = markersByColumn[0] - val anchored = markersByColumn[1] - val leaf = markersByColumn[2] - assertEquals(root.right + config.listStyle.marginLeft, anchored.right, 0.01f) - assertEquals(anchored.right + config.listStyle.marginLeft, leaf.right, 0.01f) - assertTrue(canvas.markers.all { it.left >= 0f }) - } - - @Test - fun inheritedMarkerOffsetsFollowTheRtlDirection() { - val config = styleConfig() - val outer = list(12345, 1) - val renderer = Renderer() - renderer.configure(config, context) - val nested = outer.copy(children = listOf(outer.children[0].copy(children = outer.children[0].children + list(1, 1)))) - val text = SpannableString(renderer.renderContent(listOf(nested))) - val layout = - StaticLayout.Builder - .obtain(text, 0, text.length, TextPaint(), 2000) - .setTextDirection(android.text.TextDirectionHeuristics.RTL) - .build() - val canvas = MarkerCanvas(Bitmap.createBitmap(2000, 2000, Bitmap.Config.ARGB_8888)) - layout.draw(canvas) - assertEquals(2, canvas.markers.size) - canvas.markers.forEach { marker -> - val line = layout.getLineForVertical(marker.baseline.toInt()) - assertEquals(-1, layout.getParagraphDirection(line)) - assertEquals(layout.getParagraphRight(line) + config.listStyle.gapWidth, marker.left, 0.01f) - assertTrue(marker.right <= layout.width) - } - } - - private fun assertTaskToggleKeepsGeometry(opensWithSublist: Boolean) { - val config = styleConfig() - val outer = list(100, 2) - val nested = list(1, 1).copy(type = NodeType.UnorderedList) - val taskItem = nested.children.single() - val taskChildren = if (opensWithSublist) listOf(list(1, 1)) else taskItem.children + list(1, 1) - val task = taskItem.copy(attributes = mapOf("isTask" to "true"), children = taskChildren) - val parent = outer.children.first() - val tree = - outer.copy( - children = - listOf(parent.copy(children = parent.children + nested.copy(children = listOf(task)))) + outer.children.drop(1), - ) - val renderer = Renderer() - renderer.configure(config, context) - val textView = - object : AccessibleMarkdownTextView(context) {}.apply { - layoutParams = ViewGroup.LayoutParams(2000, ViewGroup.LayoutParams.WRAP_CONTENT) - setupAsMarkdownTextView() - } - textView.setText(renderer.renderContent(listOf(tree)), TextView.BufferType.SPANNABLE) - val initialText = textView.text as Spanned - val taskIndex = initialText.getSpans(0, initialText.length, TaskListSpan::class.java).single().taskIndex - assertEquals(if (opensWithSublist) 1 else 0, initialText.getSpans(0, initialText.length, ListMarkerAnchorSpan::class.java).size) - val initialMargins = listMargins(initialText) - val initialMarkers = drawTextViewMarkers(textView) - assertEquals(4, initialMarkers.size) - - for (checked in listOf(true, false)) { - assertTrue(TaskListTapUtils.updateTaskListItemCheckedState(textView, taskIndex, checked, config)) - val text = textView.text as Spanned - val tasks = text.getSpans(0, text.length, TaskListSpan::class.java) - assertTrue(tasks.isNotEmpty()) - tasks.forEach { assertEquals(checked, it.isChecked) } - text.getSpans(0, text.length, ListMarkerAnchorSpan::class.java).forEach { - assertEquals(checked, (it.marker as TaskListSpan).isChecked) - } - assertEquals("list margins after checked=$checked", initialMargins, listMargins(text)) - assertEquals("drawn markers after checked=$checked", initialMarkers, drawTextViewMarkers(textView)) - } - } - - private fun listMargins(text: Spanned): List> = - text - .getSpans(0, text.length, BaseListSpan::class.java) - .sortedWith(compareBy({ text.getSpanStart(it) }, { it.depth }, { text.getSpanEnd(it) })) - .map { listOf(text.getSpanStart(it), text.getSpanEnd(it), it.depth, it.getLeadingMargin(true), it.getLeadingMargin(false)) } - - private fun drawTextViewMarkers(textView: TextView): List { - textView.forceLayout() - textView.measure( - View.MeasureSpec.makeMeasureSpec(2000, View.MeasureSpec.EXACTLY), - View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), - ) - textView.layout(0, 0, textView.measuredWidth, textView.measuredHeight) - val canvas = MarkerCanvas(Bitmap.createBitmap(2000, 2000, Bitmap.Config.ARGB_8888)) - textView.layout.draw(canvas) - return canvas.markers.sortedWith(compareBy({ it.baseline }, { it.left })) - } - - private fun assertDrawnMarkerPositions( - config: StyleConfig, - vararg lists: MarkdownASTNode, - ) { - drawMarkers(config, *lists).forEach { geometry -> - assertEquals( - "marker right at depth ${geometry.depth}", - geometry.paragraphLeft - config.listStyle.gapWidth, - geometry.marker.right, - 0.01f, - ) - } - } - - private fun assertNestedMarkerGapsUnchanged( - config: StyleConfig, - short: MarkdownASTNode, - wide: MarkdownASTNode, - ) { - val shortMarkers = drawMarkers(config, short).filter { it.depth > 0 } - val wideMarkers = drawMarkers(config, wide).filter { it.depth > 0 } - assertTrue(shortMarkers.isNotEmpty()) - assertEquals(shortMarkers.size, wideMarkers.size) - shortMarkers.zip(wideMarkers).forEach { (control, actual) -> - assertEquals(control.depth, actual.depth) - assertEquals( - "nested marker gap at depth ${actual.depth}", - control.paragraphLeft - control.marker.right, - actual.paragraphLeft - actual.marker.right, - 0.01f, - ) - } - } - - private fun drawMarkers( - config: StyleConfig, - vararg lists: MarkdownASTNode, - ): List { - val renderer = Renderer() - renderer.configure(config, context) - // The view exposes spans in insertion order, as SpannableString does. - val text = SpannableString(renderer.renderContent(lists.toList())) - val paint = TextPaint().apply { textSize = config.listStyle.fontSize } - val layout = StaticLayout.Builder.obtain(text, 0, text.length, paint, 2000).build() - val canvas = MarkerCanvas(Bitmap.createBitmap(2000, 2000, Bitmap.Config.ARGB_8888)) - layout.draw(canvas) - assertEquals(text.getSpans(0, text.length, BaseListSpan::class.java).count { it.drawsMarker }, canvas.markers.size) - return canvas.markers.map { marker -> - val line = layout.getLineForVertical(marker.baseline.toInt()) - assertTrue("marker left ${marker.left} on line $line", marker.left >= 0f) - val start = layout.getLineStart(line) - val depth = text.getSpans(start, start + 1, BaseListSpan::class.java).maxOf { it.depth } - MarkerGeometry(marker, layout.getParagraphLeft(line).toFloat(), depth) - } - } - - private data class MarkerGeometry( - val marker: DrawnMarker, - val paragraphLeft: Float, - val depth: Int, - ) - - private data class DrawnMarker( - val left: Float, - val right: Float, - val baseline: Float, - ) - - private class MarkerCanvas( - bitmap: Bitmap, - ) : Canvas(bitmap) { - val markers = mutableListOf() - - override fun drawCircle( - cx: Float, - cy: Float, - radius: Float, - paint: Paint, - ) { - // Bullets are centered on the reserved column edge, matching the iOS drawer. - val outerRadius = radius + paint.strokeWidth / 2f - markers += DrawnMarker(cx - outerRadius, cx, cy) - super.drawCircle(cx, cy, radius, paint) - } - - override fun drawRoundRect( - rect: android.graphics.RectF, - rx: Float, - ry: Float, - paint: Paint, - ) { - val halfStroke = if (paint.style == Paint.Style.STROKE) paint.strokeWidth / 2f else 0f - markers += DrawnMarker(rect.left - halfStroke, rect.right + halfStroke, rect.centerY()) - super.drawRoundRect(rect, rx, ry, paint) - } - - override fun drawText( - text: String, - x: Float, - y: Float, - paint: Paint, - ) { - if (text.matches(Regex("(?:[0-9]+\\.|\\.[0-9]+)"))) markers += DrawnMarker(x, x + paint.measureText(text), y) - super.drawText(text, x, y, paint) - } - } - - private fun render( - config: StyleConfig, - vararg lists: MarkdownASTNode, - ): List { - val renderer = Renderer() - renderer.configure(config, context) - val text = renderer.renderContent(lists.toList()) - return text.getSpans(0, text.length, OrderedListSpan::class.java).toList() - } - - private fun list( - start: Int, - count: Int, - ) = MarkdownASTNode( - NodeType.OrderedList, - attributes = mapOf("start" to start.toString()), - children = - List(count) { - MarkdownASTNode( - NodeType.ListItem, - children = listOf(MarkdownASTNode(NodeType.Paragraph, children = listOf(MarkdownASTNode(NodeType.Text, "item")))), - ) - }, - ) - - private fun styleConfig( - minWidth: Double = 0.0, - fontFamily: String = "monospace", - gapWidth: Double = 8.0, - checkboxSize: Double = 16.0, - ): StyleConfig { - DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context) - - fun element() = - JavaOnlyMap.of( - "fontFamily", - "", - "fontWeight", - "normal", - "fontSize", - 16.0, - "lineHeight", - 0.0, - "marginTop", - 0.0, - "marginBottom", - 0.0, - "color", - Color.BLACK, - "backgroundColor", - Color.TRANSPARENT, - "borderColor", - Color.TRANSPARENT, - "underline", - false, - "fontScale", - 0.8, - "baselineOffsetScale", - 0.5, - ) - - val style = JavaOnlyMap() - listOf("paragraph", "strong", "em", "strikethrough", "code", "superscript", "subscript", "highlight") - .forEach { style.putMap(it, element()) } - style.putMap("link", element().apply { putString("fontFamily", "serif") }) - style.putArray( - "linkVariants", - JavaOnlyArray.of( - element().apply { - putString("pattern", "^ref:") - putString("fontFamily", "monospace") - putInt("color", Color.BLUE) - }, - ), - ) - style.putMap( - "spoiler", - element().apply { - putMap("particles", JavaOnlyMap.of("density", 0.5, "speed", 1.0)) - putMap("solid", JavaOnlyMap.of("borderRadius", 0.0)) - }, - ) - style.putMap( - "taskList", - JavaOnlyMap.of( - "checkedColor", - Color.BLACK, - "borderColor", - Color.BLACK, - "checkmarkColor", - Color.BLACK, - "checkedTextColor", - Color.BLACK, - "checkboxSize", - checkboxSize, - "checkboxBorderRadius", - 0.0, - "checkedStrikethrough", - false, - ), - ) - style.putMap( - "list", - element().apply { - putString("fontFamily", fontFamily) - putInt("bulletColor", Color.BLACK) - putInt("markerColor", Color.BLACK) - putDouble("bulletSize", 6.0) - putDouble("markerMinWidth", minWidth) - putDouble("gapWidth", gapWidth) - putDouble("marginLeft", 24.0) - putDouble("itemSpacing", 0.0) - }, - ) - return StyleConfig(style, context, false, 0f) - } -} diff --git a/packages/react-native-enriched-markdown/ios/renderer/ListItemRenderer.m b/packages/react-native-enriched-markdown/ios/renderer/ListItemRenderer.m index c26b10764..ed80dfad7 100644 --- a/packages/react-native-enriched-markdown/ios/renderer/ListItemRenderer.m +++ b/packages/react-native-enriched-markdown/ios/renderer/ListItemRenderer.m @@ -84,27 +84,24 @@ - (void)renderNodeContent:(MarkdownASTNode *)node // currentDepth - 1 handles the horizontal offset for nested lists const NSInteger nestingLevel = currentDepth - 1; const CGFloat baseMarkerWidth = isTask ? [_config effectiveListMarginLeftForTask] - : (context.listType == ListTypeOrdered) ? context.listMarkerWidth + : (context.listType == ListTypeOrdered) ? [_config effectiveListMarginLeftForNumber] : [_config effectiveListMarginLeftForBullet]; const CGFloat blockquoteIndent = blockquoteIndentForDepth(context.blockquoteDepth, [_config blockquoteBorderWidth] + [_config blockquoteGapWidth]); const CGFloat totalIndent = blockquoteIndent + baseMarkerWidth + [_config effectiveListGapWidth] + - (nestingLevel * [_config listStyleMarginLeft]) + context.listMarkerOffset; + (nestingLevel * [_config listStyleMarginLeft]); const NSUInteger startLocation = output.length; // Manual save/restore — a scope snapshot would also roll back the listItemNumber increment - const CGFloat prevMarkerExtra = context.listItemMarkerExtra; - context.listItemMarkerExtra = !isTask && context.listType == ListTypeOrdered ? context.listMarkerExtra : 0; const CGFloat prevIndent = context.accumulatedIndent; context.accumulatedIndent = totalIndent; @try { [_rendererFactory renderChildrenOfNode:node into:output context:context]; } @finally { context.accumulatedIndent = prevIndent; - context.listItemMarkerExtra = prevMarkerExtra; } // Ensure every list item ends with a newline to prevent paragraph merging diff --git a/packages/react-native-enriched-markdown/ios/renderer/ListRenderer.m b/packages/react-native-enriched-markdown/ios/renderer/ListRenderer.m index 3b0844a1e..47283dc99 100644 --- a/packages/react-native-enriched-markdown/ios/renderer/ListRenderer.m +++ b/packages/react-native-enriched-markdown/ios/renderer/ListRenderer.m @@ -90,25 +90,6 @@ - (void)renderNodeContent:(MarkdownASTNode *)node // ListItemRenderer pre-increments, so the counter starts one below the // first rendered number. context.listItemNumber = startNumber - 1; - const CGFloat defaultMarkerWidth = [_config effectiveListMarginLeftForNumber:99]; - if (prevDepth > 0) { - context.listMarkerOffset += context.listItemMarkerExtra; - } - context.listMarkerWidth = defaultMarkerWidth; - if (_isOrdered) { - NSInteger number = startNumber; - for (MarkdownASTNode *item in node.children) { - if (item.type != MarkdownNodeTypeListItem) - continue; - // Keep the existing gutter for one- and two-digit markers. - if (number >= 100 && ![item.attributes[@"isTask"] isEqualToString:@"true"]) { - context.listMarkerWidth = MAX(context.listMarkerWidth, [_config effectiveListMarginLeftForNumber:number]); - } - number++; - } - } - - context.listMarkerExtra = context.listMarkerWidth - defaultMarkerWidth; [context setBlockStyle:_isOrdered ? BlockTypeOrderedList : BlockTypeUnorderedList font:_config.listStyleFont diff --git a/packages/react-native-enriched-markdown/ios/renderer/RenderContext.h b/packages/react-native-enriched-markdown/ios/renderer/RenderContext.h index 5bafb9ac3..ad4a6431a 100644 --- a/packages/react-native-enriched-markdown/ios/renderer/RenderContext.h +++ b/packages/react-native-enriched-markdown/ios/renderer/RenderContext.h @@ -52,10 +52,6 @@ typedef NS_ENUM(NSInteger, ListType) { ListTypeUnordered, ListTypeOrdered }; @property (nonatomic, assign) NSInteger listDepth; @property (nonatomic, assign) ListType listType; @property (nonatomic, assign) NSInteger listItemNumber; -@property (nonatomic, assign) CGFloat listMarkerWidth; -@property (nonatomic, assign) CGFloat listMarkerExtra; -@property (nonatomic, assign) CGFloat listMarkerOffset; -@property (nonatomic, assign) CGFloat listItemMarkerExtra; @property (nonatomic, assign) CGFloat accumulatedIndent; @property (nonatomic, assign) BOOL allowFontScaling; @property (nonatomic, assign) CGFloat maxFontSizeMultiplier; diff --git a/packages/react-native-enriched-markdown/ios/renderer/RenderContext.m b/packages/react-native-enriched-markdown/ios/renderer/RenderContext.m index 40776aaf7..b22686708 100644 --- a/packages/react-native-enriched-markdown/ios/renderer/RenderContext.m +++ b/packages/react-native-enriched-markdown/ios/renderer/RenderContext.m @@ -24,10 +24,6 @@ @implementation BlockStyle @"listDepth", @"listType", @"listItemNumber", - @"listMarkerWidth", - @"listMarkerExtra", - @"listMarkerOffset", - @"listItemMarkerExtra", @"accumulatedIndent", ]; }); @@ -317,10 +313,6 @@ - (void)reset _listDepth = 0; _listType = ListTypeUnordered; _listItemNumber = 0; - _listMarkerWidth = 0; - _listMarkerExtra = 0; - _listMarkerOffset = 0; - _listItemMarkerExtra = 0; _accumulatedIndent = 0; _taskItemCount = 0; diff --git a/packages/react-native-enriched-markdown/ios/styles/StyleConfig.h b/packages/react-native-enriched-markdown/ios/styles/StyleConfig.h index af5d73070..f4837c8d7 100644 --- a/packages/react-native-enriched-markdown/ios/styles/StyleConfig.h +++ b/packages/react-native-enriched-markdown/ios/styles/StyleConfig.h @@ -337,7 +337,7 @@ NS_ASSUME_NONNULL_BEGIN - (UIFont *)listStyleFont; - (CGFloat)effectiveListGapWidth; - (CGFloat)effectiveListMarginLeftForBullet; -- (CGFloat)effectiveListMarginLeftForNumber:(NSInteger)number; +- (CGFloat)effectiveListMarginLeftForNumber; - (CGFloat)effectiveListMarginLeftForTask; // Code block properties - (CGFloat)codeBlockFontSize; diff --git a/packages/react-native-enriched-markdown/ios/styles/StyleConfig.mm b/packages/react-native-enriched-markdown/ios/styles/StyleConfig.mm index 3caac66f5..230ef2571 100644 --- a/packages/react-native-enriched-markdown/ios/styles/StyleConfig.mm +++ b/packages/react-native-enriched-markdown/ios/styles/StyleConfig.mm @@ -2080,13 +2080,11 @@ - (CGFloat)effectiveListMarginLeftForBullet return MAX(_listStyleMarkerMinWidth, _listStyleBulletSize / 2.0); } -- (CGFloat)effectiveListMarginLeftForNumber:(NSInteger)number +- (CGFloat)effectiveListMarginLeftForNumber { UIFont *font = [self listMarkerFont]; CGFloat natural = - [[NSString stringWithFormat:@"%ld.", (long)number] - sizeWithAttributes:@{NSFontAttributeName : font ?: [UIFont systemFontOfSize:_listStyleFontSize]}] - .width; + [@"99." sizeWithAttributes:@{NSFontAttributeName : font ?: [UIFont systemFontOfSize:_listStyleFontSize]}].width; return MAX(_listStyleMarkerMinWidth, natural); } From c9949033199708b7548a7c4da4f7f0a5d403e0bf Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Fri, 16 Oct 2026 14:51:28 -0700 Subject: [PATCH 09/11] revert: drop the fork's mixed nested list fix for the rebased upstream #1006 mwolson rebased software-mansion/enriched-markdown#1006 onto upstream main after #1015 landed. The fork takes that rebased commit next, so the eventual upstream merge replaces it cleanly. This reverts commit 65cbb5f9. Co-Authored-By: Claude Opus 5.5 --- .../mixed_nested_list_markers_test.yaml | 92 ---- .../mixed_nested_list_test.yaml | 7 - .../list_sublist_first_combo_display.png | Bin 11163 -> 11047 bytes .../android/mixed_nested_list_display.png | Bin 38028 -> 37682 bytes ...ed_list_markers_bullet_ordered_display.png | Bin 49416 -> 0 bytes ...ixed_nested_list_markers_tasks_display.png | Bin 65165 -> 0 bytes .../markdown/renderer/BlockStyleContext.kt | 2 - .../markdown/renderer/ListItemRenderer.kt | 8 +- .../enriched/markdown/spans/BaseListSpan.kt | 24 +- .../markdown/spans/OrderedListSpan.kt | 9 +- .../enriched/markdown/spans/TaskListSpan.kt | 2 - .../markdown/spans/UnorderedListSpan.kt | 2 - .../text/interaction/TaskListTapUtils.kt | 1 - .../spans/MixedNestedListIndentTest.kt | 403 ------------------ 14 files changed, 13 insertions(+), 537 deletions(-) delete mode 100644 .maestro/enrichedMarkdownText/flows/advanced/block_elements/mixed_nested_list_markers_test.yaml delete mode 100644 .maestro/enrichedMarkdownText/screenshots/android/mixed_nested_list_markers_bullet_ordered_display.png delete mode 100644 .maestro/enrichedMarkdownText/screenshots/android/mixed_nested_list_markers_tasks_display.png delete mode 100644 packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/spans/MixedNestedListIndentTest.kt diff --git a/.maestro/enrichedMarkdownText/flows/advanced/block_elements/mixed_nested_list_markers_test.yaml b/.maestro/enrichedMarkdownText/flows/advanced/block_elements/mixed_nested_list_markers_test.yaml deleted file mode 100644 index fe8051110..000000000 --- a/.maestro/enrichedMarkdownText/flows/advanced/block_elements/mixed_nested_list_markers_test.yaml +++ /dev/null @@ -1,92 +0,0 @@ -appId: swmansion.enriched.markdown.example -tags: - - block - - advanced - - list - - task_list - - text - - android-only ---- -- launchApp: - permissions: {} - -- waitForAnimationToEnd - -- runFlow: - file: '../../../../subflows/move_to_playground.yaml' - -- assertVisible: - id: playground-screen - -- runFlow: - file: '../../../subflows/set_enriched_text_value.yaml' - env: - VALUE: | - 1. Ordered parent - - Bullet child - - Second bullet child - 2. Following ordered sibling - - - Bullet parent - 1. Ordered child - 2. Second ordered child - - Following bullet sibling - -- scrollUntilVisible: - element: - id: blur-button - direction: UP - visibilityPercentage: 100 - -- tapOn: - id: blur-button - -- scroll - -- waitForAnimationToEnd - -- runFlow: - file: '../../../subflows/capture_or_assert_screenshot.yaml' - env: - SCREENSHOT_NAME: 'mixed_nested_list_markers_bullet_ordered_display' - -- scrollUntilVisible: - element: - id: set-markdown-button - direction: UP - visibilityPercentage: 100 - -- runFlow: - file: '../../../subflows/set_enriched_text_value.yaml' - env: - VALUE: | - - Bullet parent - - [ ] Unchecked task child - - [x] Checked task child - - 1. Ordered parent - - [ ] Unchecked task child - - [x] Checked task child - - - [ ] Unchecked task parent - - Bullet child - - [x] Checked task parent - - Second bullet child - -- scrollUntilVisible: - element: - id: blur-button - direction: UP - visibilityPercentage: 100 - -- tapOn: - id: blur-button - -- scroll - -- waitForAnimationToEnd - -- runFlow: - file: '../../../subflows/capture_or_assert_screenshot.yaml' - env: - SCREENSHOT_NAME: 'mixed_nested_list_markers_tasks_display' diff --git a/.maestro/enrichedMarkdownText/flows/basic/block_elements/mixed_nested_list_test.yaml b/.maestro/enrichedMarkdownText/flows/basic/block_elements/mixed_nested_list_test.yaml index df5738ffe..c7abe1af5 100644 --- a/.maestro/enrichedMarkdownText/flows/basic/block_elements/mixed_nested_list_test.yaml +++ b/.maestro/enrichedMarkdownText/flows/basic/block_elements/mixed_nested_list_test.yaml @@ -25,13 +25,6 @@ tags: 1. Django 2. FastAPI -- runFlow: - when: - platform: Android - commands: - - scroll - - waitForAnimationToEnd - - runFlow: file: '../../../subflows/capture_or_assert_screenshot.yaml' env: diff --git a/.maestro/enrichedMarkdownText/screenshots/android/list_sublist_first_combo_display.png b/.maestro/enrichedMarkdownText/screenshots/android/list_sublist_first_combo_display.png index 8a34b7c4c02b2a50e47d4e9fe27931dfb457628c..2e90f0cc94ae80d29c14551f55d40f35f4a53223 100644 GIT binary patch literal 11047 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�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 diff --git a/.maestro/enrichedMarkdownText/screenshots/android/mixed_nested_list_markers_bullet_ordered_display.png b/.maestro/enrichedMarkdownText/screenshots/android/mixed_nested_list_markers_bullet_ordered_display.png deleted file mode 100644 index cdd2dd8524e19dbd8fb5a5703b97141a884d6513..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49416 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 WJ45QhEa&gJ^t6m_7T<9C>;C`*$lfRb diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt index 0f921dbb5..0286a8558 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt @@ -40,7 +40,6 @@ class BlockStyleContext { var blockquoteDepth = 0 var listDepth = 0 var listType: ListType? = null - var listItemMarkerWidth: Float? = null var listItemNumber = 0 var taskItemCount = 0 var accumulatedIndent = 0 @@ -152,7 +151,6 @@ class BlockStyleContext { listDepth = 0 listType = null listItemNumber = 0 - listItemMarkerWidth = null taskItemCount = 0 accumulatedIndent = 0 listItemStarts.clear() diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt index f73b54f00..b849f7863 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt @@ -38,7 +38,6 @@ class ListItemRenderer( val depth = styleContext.listDepth - 1 val listStyle = config.style.listStyle - val parentMarkerWidth = styleContext.listItemMarkerWidth fun makeSpan(drawsMarker: Boolean): BaseListSpan = if (isTask) { @@ -51,16 +50,15 @@ class ListItemRenderer( taskIndex = taskIndex, isChecked = isChecked, drawsMarker = drawsMarker, - parentMarkerWidth = parentMarkerWidth, ) } else { when (listType) { BlockStyleContext.ListType.UNORDERED -> { - UnorderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker, parentMarkerWidth) + UnorderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker) } BlockStyleContext.ListType.ORDERED -> { - OrderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker, parentMarkerWidth).apply { + OrderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker).apply { setItemNumber(styleContext.listItemNumber) } } @@ -72,11 +70,9 @@ class ListItemRenderer( val prevIndent = styleContext.accumulatedIndent styleContext.accumulatedIndent = prevIndent + markerSpan.getLeadingMargin(false) try { - styleContext.listItemMarkerWidth = markerSpan.getBaselineMarkerWidth() factory.renderChildren(node, builder, onLinkPress, onLinkLongPress) } finally { styleContext.accumulatedIndent = prevIndent - styleContext.listItemMarkerWidth = parentMarkerWidth } if (builder.length == start || builder.substring(start).isBlank()) return diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt index a7715a730..2ab00430c 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt @@ -23,7 +23,6 @@ abstract class BaseListSpan( protected val marginLeft: Float, protected val gapWidth: Float, internal val drawsMarker: Boolean = true, - internal val parentMarkerWidth: Float? = null, ) : MetricAffectingSpan(), LeadingMarginSpan { private var cachedText: CharSequence? = null @@ -39,26 +38,17 @@ abstract class BaseListSpan( protected abstract fun getMarkerWidth(): Float - /** The marker column a child measures its offset against. */ - internal open fun getBaselineMarkerWidth(): Float = getMarkerWidth() - override fun updateMeasureState(textPaint: TextPaint) = applyTextStyle(textPaint) override fun updateDrawState(textPaint: TextPaint) = applyTextStyle(textPaint) - override fun getLeadingMargin(first: Boolean): Int { - val effectiveGap = gapWidth.coerceAtLeast(DEFAULT_MIN_GAP) - val markerWidth = getMarkerWidth() - if (depth == 0) return (markerWidth + effectiveGap).toInt() - - val parentWidth = parentMarkerWidth ?: getBaselineMarkerWidth() - if (parentWidth == markerWidth) return marginLeft.toInt() - - // Subtract truncated absolute indents so mixed columns do not accumulate their own rounding. - val indent = (depth * marginLeft + markerWidth + effectiveGap).toInt() - val parentIndent = ((depth - 1) * marginLeft + parentWidth + effectiveGap).toInt() - return indent - parentIndent - } + override fun getLeadingMargin(first: Boolean): Int = + if (depth == 0) { + val effectiveGap = gapWidth.coerceAtLeast(DEFAULT_MIN_GAP) + (getMarkerWidth() + effectiveGap).toInt() + } else { + marginLeft.toInt() + } override fun drawLeadingMargin( canvas: Canvas, diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt index 1d5541f09..566f52800 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt @@ -19,7 +19,6 @@ class OrderedListSpan( context: Context, styleCache: SpanStyleCache, drawsMarker: Boolean = true, - parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, context = context, @@ -34,7 +33,6 @@ class OrderedListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, - parentMarkerWidth = parentMarkerWidth, ) { companion object { private val sharedMarkerPaint = TextPaint().apply { isAntiAlias = true } @@ -47,8 +45,6 @@ class OrderedListSpan( applyStyles(null, ReactConstants.UNSET, fontWeight, fontFamily, context.assets) } - private val markerColumnWidth = listStyle.effectiveMarkerWidth(configureMarkerPaint().measureText("99.")) - private fun configureMarkerPaint(): TextPaint = sharedMarkerPaint.apply { textSize = listStyle.fontSize @@ -56,7 +52,10 @@ class OrderedListSpan( typeface = markerTypeface } - override fun getMarkerWidth(): Float = markerColumnWidth + override fun getMarkerWidth(): Float { + val paint = configureMarkerPaint() + return listStyle.effectiveMarkerWidth(paint.measureText("99.")) + } var itemNumber: Int = 1 private set diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt index f4677263f..3b5a5c60b 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt @@ -20,7 +20,6 @@ class TaskListSpan( val taskIndex: Int, val isChecked: Boolean, drawsMarker: Boolean = true, - parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, context = context, @@ -35,7 +34,6 @@ class TaskListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, - parentMarkerWidth = parentMarkerWidth, ) { private val checkboxSize = taskStyle.checkboxSize private val markerColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize) diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt index dd41e46ba..cc3e70401 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt @@ -14,7 +14,6 @@ class UnorderedListSpan( context: Context, styleCache: SpanStyleCache, drawsMarker: Boolean = true, - parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, context = context, @@ -29,7 +28,6 @@ class UnorderedListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, - parentMarkerWidth = parentMarkerWidth, ) { companion object { private val sharedBulletPaint = diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt index 4f2efc075..1bb4b5313 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt @@ -131,7 +131,6 @@ object TaskListTapUtils { taskIndex = targetIndex, isChecked = newChecked, drawsMarker = old.drawsMarker, - parentMarkerWidth = old.parentMarkerWidth, ) // Replace every segment of the item — spans are split around code blocks diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/spans/MixedNestedListIndentTest.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/spans/MixedNestedListIndentTest.kt deleted file mode 100644 index fda1cee74..000000000 --- a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/spans/MixedNestedListIndentTest.kt +++ /dev/null @@ -1,403 +0,0 @@ -package com.swmansion.enriched.markdown.spans - -import android.graphics.Bitmap -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.text.SpannableString -import android.text.Spanned -import android.text.StaticLayout -import android.text.TextPaint -import android.widget.TextView -import com.facebook.react.bridge.JavaOnlyMap -import com.facebook.react.uimanager.DisplayMetricsHolder -import com.swmansion.enriched.markdown.parser.MarkdownASTNode -import com.swmansion.enriched.markdown.parser.MarkdownASTNode.NodeType -import com.swmansion.enriched.markdown.renderer.Renderer -import com.swmansion.enriched.markdown.styles.StyleConfig -import com.swmansion.enriched.markdown.utils.text.interaction.TaskListTapUtils -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.RuntimeEnvironment -import org.robolectric.annotation.Config -import org.robolectric.annotation.GraphicsMode - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [30]) -@GraphicsMode(GraphicsMode.Mode.NATIVE) -class MixedNestedListIndentTest { - private val context = RuntimeEnvironment.getApplication() - - @Test - fun bulletsUnderNumbers() = assertMixedGap(Kind.ORDERED, Kind.BULLET) - - @Test - fun numbersUnderBullets() = assertMixedGap(Kind.BULLET, Kind.ORDERED) - - @Test - fun tasksUnderBullets() = assertMixedGap(Kind.BULLET, Kind.TASK) - - @Test - fun tasksUnderNumbers() = assertMixedGap(Kind.ORDERED, Kind.TASK) - - @Test - fun bulletsUnderTasks() = assertMixedGap(Kind.TASK, Kind.BULLET) - - @Test - fun numbersUnderTasks() = assertMixedGap(Kind.TASK, Kind.ORDERED) - - @Test - fun topLevelAndSameTypeNestsKeepBaseGeometry() { - val config = styleConfig() - val baseColumns = mapOf(Kind.ORDERED to 22f, Kind.BULLET to 3f, Kind.TASK to 14f) - for ((kind, column) in baseColumns) { - val markers = drawMarkers(config, list(kind, list(kind, list(kind)))) - assertEquals(listOf(0, 1, 2), markers.map { it.depth }) - markers.forEach { - assertEquals("base text for $kind at depth ${it.depth}", column + 6f + it.depth * 24f, it.paragraphLeft, 0f) - assertEquals(column + it.depth * 24f, it.marker.right, 0.01f) - } - } - } - - @Test - fun mixedColumnsUseAbsoluteIndentsWithoutFractionalDrift() { - for (margin in listOf(24.0, 4.0)) { - val config = styleConfig(bulletSize = 6.5, marginLeft = margin) - val tree = list(Kind.BULLET, list(Kind.ORDERED, list(Kind.BULLET, list(Kind.TASK)))) - val columns = listOf(3.25f, 22f, 3.25f, 14f) - drawMarkers(config, tree).forEach { - val expected = (it.depth * margin + columns[it.depth] + 6f).toInt().toFloat() - assertEquals("absolute indent at depth ${it.depth}, margin $margin", expected, it.paragraphLeft, 0f) - assertEquals(it.paragraphLeft - 6f, it.marker.right, 0.99f) - } - } - } - - @Test - fun mixedAncestorsAndFollowingSiblingsRestoreTheirOwnColumns() { - val config = styleConfig() - val kinds = listOf(Kind.ORDERED, Kind.BULLET, Kind.TASK) - for (parent in kinds) { - val tree = list(parent).copy(children = kinds.map { child -> item(parent, list(child, list(parent))) }) - assertGaps(config, tree, list(Kind.BULLET), list(Kind.ORDERED), list(Kind.TASK)) - } - } - - @Test - fun wrappedLinesKeepTheChildsOwnColumn() { - val config = styleConfig() - val child = list(Kind.ORDERED) - val paragraph = MarkdownASTNode(NodeType.Paragraph, children = listOf(MarkdownASTNode(NodeType.Text, "wrapped child text ".repeat(12)))) - val tree = list(Kind.BULLET, child.copy(children = listOf(child.children[0].copy(children = listOf(paragraph))))) - val renderer = Renderer() - renderer.configure(config, context) - val text = SpannableString(renderer.renderContent(listOf(tree))) - val layout = StaticLayout.Builder.obtain(text, 0, text.length, TextPaint(), 180).build() - val span = text.getSpans(0, text.length, OrderedListSpan::class.java).single() - val firstLine = layout.getLineForOffset(text.getSpanStart(span)) - val lastLine = layout.getLineForOffset(text.getSpanEnd(span) - 1) - assertTrue(lastLine > firstLine) - for (line in firstLine..lastLine) { - assertEquals(52, layout.getParagraphLeft(line)) - } - val canvas = MarkerCanvas(Bitmap.createBitmap(2000, 2000, Bitmap.Config.ARGB_8888)) - layout.draw(canvas) - assertEquals(2, canvas.markers.size) - assertEquals(46f, canvas.markers.last().right, 0.01f) - } - - @Test - fun togglingTaskUnderBulletKeepsEveryListMargin() = assertTaskToggleKeepsMargins(list(Kind.BULLET, list(Kind.TASK, list(Kind.ORDERED)))) - - @Test - fun togglingTaskUnderNumberKeepsEveryListMargin() = assertTaskToggleKeepsMargins(list(Kind.ORDERED, list(Kind.TASK))) - - private fun assertTaskToggleKeepsMargins(tree: MarkdownASTNode) { - val config = styleConfig() - val renderer = Renderer() - renderer.configure(config, context) - val textView = TextView(context) - textView.setText(SpannableString(renderer.renderContent(listOf(tree))), TextView.BufferType.SPANNABLE) - - fun margins(): List> { - val text = textView.text as Spanned - return text - .getSpans(0, text.length, BaseListSpan::class.java) - .sortedWith(compareBy({ text.getSpanStart(it) }, { it.depth }, { text.getSpanEnd(it) })) - .map { listOf(text.getSpanStart(it), text.getSpanEnd(it), it.depth, it.getLeadingMargin(true), it.getLeadingMargin(false)) } - } - - val before = margins() - assertTrue(before.isNotEmpty()) - for (checked in listOf(true, false)) { - assertTrue(TaskListTapUtils.updateTaskListItemCheckedState(textView, 0, checked, config)) - val text = textView.text as Spanned - assertTrue(text.getSpans(0, text.length, TaskListSpan::class.java).all { it.isChecked == checked }) - assertEquals("all list margins after checked=$checked", before, margins()) - } - } - - @Test - fun rtlMixedNestsKeepMarkerGapsAtBothDepths() { - fun rtl(node: MarkdownASTNode): MarkdownASTNode { - if (node.type == NodeType.Text) return node.copy(content = "\u05e4\u05e8\u05d9\u05d8") - return node.copy(children = node.children.map { rtl(it) }) - } - - val config = styleConfig() - for (parent in Kind.entries) { - for (child in Kind.entries.filter { it != parent }) { - val checkedStates = if (parent == Kind.TASK || child == Kind.TASK) listOf(false, true) else listOf(false) - for (checked in checkedStates) { - val tree = list(parent, list(child, list(parent, checked = checked), checked), checked) - val markers = drawMarkers(config, rtl(tree)) - assertEquals(listOf(0, 1, 2), markers.map { it.depth }) - markers.forEach { - assertEquals("RTL paragraph at depth ${it.depth}", -1, it.direction) - assertEquals("$child under $parent, checked=$checked, depth ${it.depth}", it.paragraphRight + 6f, it.marker.left, 0.01f) - } - } - } - } - } - - @Test - fun equalMinimumColumnsKeepBaseGeometryForMixedNests() { - val config = styleConfig(markerMinWidth = 40.0) - for (parent in Kind.entries) { - for (child in Kind.entries.filter { it != parent }) { - val markers = drawMarkers(config, list(parent, list(child, list(parent)))) - assertEquals(listOf(0, 1, 2), markers.map { it.depth }) - markers.forEach { - assertEquals("base text for $child under $parent at depth ${it.depth}", 46f + it.depth * 24f, it.paragraphLeft, 0f) - assertEquals(40f + it.depth * 24f, it.marker.right, 0.01f) - } - } - } - } - - private fun assertMixedGap( - parent: Kind, - child: Kind, - ) { - val config = styleConfig() - val checkedStates = if (parent == Kind.TASK || child == Kind.TASK) listOf(false, true) else listOf(false) - for (checked in checkedStates) { - val markers = drawMarkers(config, list(parent, list(child, checked = checked), checked)) - assertEquals(2, markers.size) - assertEquals(1, markers.last().depth) - markers.forEach { - assertEquals("$child under $parent at depth ${it.depth}", it.paragraphLeft - 6f, it.marker.right, 0.01f) - } - } - } - - private fun assertGaps( - config: StyleConfig, - vararg lists: MarkdownASTNode, - ) { - drawMarkers(config, *lists).forEach { - assertEquals("marker at depth ${it.depth}", it.paragraphLeft - 6f, it.marker.right, 0.01f) - } - } - - private enum class Kind { ORDERED, BULLET, TASK } - - private fun list( - kind: Kind, - child: MarkdownASTNode? = null, - checked: Boolean = false, - ) = MarkdownASTNode( - if (kind == Kind.ORDERED) NodeType.OrderedList else NodeType.UnorderedList, - attributes = mapOf("start" to "1"), - children = listOf(item(kind, child, checked)), - ) - - private fun item( - kind: Kind, - child: MarkdownASTNode? = null, - checked: Boolean = false, - ) = MarkdownASTNode( - NodeType.ListItem, - attributes = if (kind == Kind.TASK) mapOf("isTask" to "true", "taskChecked" to checked.toString()) else emptyMap(), - children = - listOf( - MarkdownASTNode(NodeType.Paragraph, children = listOf(MarkdownASTNode(NodeType.Text, "item"))), - ) + listOfNotNull(child), - ) - - private fun drawMarkers( - config: StyleConfig, - vararg lists: MarkdownASTNode, - ): List { - val renderer = Renderer() - renderer.configure(config, context) - // The view exposes spans in insertion order, as SpannableString does. - val text = SpannableString(renderer.renderContent(lists.toList())) - val paint = TextPaint().apply { textSize = config.listStyle.fontSize } - val layout = StaticLayout.Builder.obtain(text, 0, text.length, paint, 2000).build() - val canvas = MarkerCanvas(Bitmap.createBitmap(2000, 2000, Bitmap.Config.ARGB_8888)) - layout.draw(canvas) - assertEquals(text.getSpans(0, text.length, BaseListSpan::class.java).count { it.drawsMarker }, canvas.markers.size) - return canvas.markers.map { marker -> - val line = layout.getLineForVertical(marker.baseline.toInt()) - assertTrue("marker left ${marker.left} on line $line", marker.left >= 0f) - val start = layout.getLineStart(line) - val depth = text.getSpans(start, start + 1, BaseListSpan::class.java).maxOf { it.depth } - MarkerGeometry( - marker, - layout.getParagraphLeft(line).toFloat(), - layout.getParagraphRight(line).toFloat(), - layout.getParagraphDirection(line), - depth, - ) - } - } - - private data class MarkerGeometry( - val marker: DrawnMarker, - val paragraphLeft: Float, - val paragraphRight: Float, - val direction: Int, - val depth: Int, - ) - - private data class DrawnMarker( - val left: Float, - val right: Float, - val baseline: Float, - ) - - private class MarkerCanvas( - bitmap: Bitmap, - ) : Canvas(bitmap) { - val markers = mutableListOf() - - override fun drawCircle( - cx: Float, - cy: Float, - radius: Float, - paint: Paint, - ) { - // Bullets are centered on the reserved column edge, matching the iOS drawer. - markers += DrawnMarker(cx, cx, cy) - super.drawCircle(cx, cy, radius, paint) - } - - override fun drawRect( - left: Float, - top: Float, - right: Float, - bottom: Float, - paint: Paint, - ) { - val centerX = (left + right) / 2f - markers += DrawnMarker(centerX, centerX, (top + bottom) / 2f) - super.drawRect(left, top, right, bottom, paint) - } - - override fun drawRoundRect( - rect: android.graphics.RectF, - rx: Float, - ry: Float, - paint: Paint, - ) { - val halfStroke = if (paint.style == Paint.Style.STROKE) paint.strokeWidth / 2f else 0f - markers += DrawnMarker(rect.left - halfStroke, rect.right + halfStroke, rect.centerY()) - super.drawRoundRect(rect, rx, ry, paint) - } - - override fun drawText( - text: String, - x: Float, - y: Float, - paint: Paint, - ) { - if (text.matches(Regex("(?:[0-9]+\\.|\\.[0-9]+)"))) markers += DrawnMarker(x, x + paint.measureText(text), y) - super.drawText(text, x, y, paint) - } - } - - private fun styleConfig( - markerMinWidth: Double = 0.0, - bulletSize: Double = 6.0, - marginLeft: Double = 24.0, - ): StyleConfig { - DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context) - - fun element() = - JavaOnlyMap.of( - "fontFamily", - "", - "fontWeight", - "normal", - "fontSize", - 16.0, - "lineHeight", - 0.0, - "marginTop", - 0.0, - "marginBottom", - 0.0, - "color", - Color.BLACK, - "backgroundColor", - Color.TRANSPARENT, - "borderColor", - Color.TRANSPARENT, - "underline", - false, - "fontScale", - 0.8, - "baselineOffsetScale", - 0.5, - ) - - val style = JavaOnlyMap() - listOf("paragraph", "strong", "em", "strikethrough", "code", "superscript", "subscript", "highlight", "link") - .forEach { style.putMap(it, element()) } - style.putMap( - "spoiler", - element().apply { - putMap("particles", JavaOnlyMap.of("density", 0.5, "speed", 1.0)) - putMap("solid", JavaOnlyMap.of("borderRadius", 0.0)) - }, - ) - style.putMap( - "taskList", - JavaOnlyMap.of( - "checkedColor", - Color.BLACK, - "borderColor", - Color.BLACK, - "checkmarkColor", - Color.BLACK, - "checkedTextColor", - Color.BLACK, - "checkboxSize", - 14.0, - "checkboxBorderRadius", - 0.0, - "checkedStrikethrough", - false, - ), - ) - style.putMap( - "list", - element().apply { - putInt("bulletColor", Color.BLACK) - putInt("markerColor", Color.BLACK) - putDouble("bulletSize", bulletSize) - putDouble("markerMinWidth", markerMinWidth) - putDouble("gapWidth", 6.0) - putDouble("marginLeft", marginLeft) - putDouble("itemSpacing", 0.0) - }, - ) - return StyleConfig(style, context, false, 0f) - } -} From cf8e76555a646747ef7c5afa5a21d4eb1d29dce3 Mon Sep 17 00:00:00 2001 From: Mike Olson Date: Thu, 15 Oct 2026 09:58:24 -0400 Subject: [PATCH 10/11] fix(android): align mixed nested list indents with iOS (cherry picked from commit 23a3096c940a957a88665e024fd9fa1fe3e6f0bf) --- .../android/mixed_nested_list_display.png | Bin 34803 -> 34972 bytes .../mixed_nested_list_markers_test.yaml | 92 ++++++++ .../mixed_nested_list_test.yaml | 7 + .../list_sublist_first_combo_display.png | Bin 11047 -> 11163 bytes .../android/mixed_nested_list_display.png | Bin 37682 -> 38028 bytes ...ed_list_markers_bullet_ordered_display.png | Bin 0 -> 49416 bytes ...ixed_nested_list_markers_tasks_display.png | Bin 0 -> 65165 bytes .../markdown/renderer/BlockStyleContext.kt | 2 + .../markdown/renderer/ListItemRenderer.kt | 8 +- .../enriched/markdown/spans/BaseListSpan.kt | 23 +- .../markdown/spans/OrderedListSpan.kt | 4 + .../enriched/markdown/spans/TaskListSpan.kt | 7 +- .../markdown/spans/UnorderedListSpan.kt | 2 + .../enriched/markdown/ListRenderingTest.kt | 207 +++++++++++++++++ .../markdown/test/ListMarkerCanvas.kt | 26 ++- .../test/MarkdownRenderTestSupport.kt | 7 +- .../markdown/renderer/BlockStyleContext.kt | 2 + .../markdown/renderer/ListItemRenderer.kt | 6 + .../enriched/markdown/spans/BaseListSpan.kt | 23 +- .../markdown/spans/OrderedListSpan.kt | 4 + .../enriched/markdown/spans/TaskListSpan.kt | 7 +- .../markdown/spans/UnorderedListSpan.kt | 2 + .../text/interaction/TaskListTapUtils.kt | 1 + .../enriched/markdown/ListRenderingTest.kt | 212 +++++++++++++++++- .../markdown/TaskListInteractionTest.kt | 33 ++- .../markdown/test/ListMarkerCanvas.kt | 26 ++- 26 files changed, 657 insertions(+), 44 deletions(-) create mode 100644 .maestro/enrichedMarkdownText/flows/advanced/block_elements/mixed_nested_list_markers_test.yaml create mode 100644 .maestro/enrichedMarkdownText/screenshots/android/mixed_nested_list_markers_bullet_ordered_display.png create mode 100644 .maestro/enrichedMarkdownText/screenshots/android/mixed_nested_list_markers_tasks_display.png diff --git a/.maestro/androidExample/enrichedMarkdownText/screenshots/android/mixed_nested_list_display.png b/.maestro/androidExample/enrichedMarkdownText/screenshots/android/mixed_nested_list_display.png index f5ff1ff701d37eca7f0cbea123b37de165f651bc..e031d7079d8342526aab18ba3db996d4cf24c083 100644 GIT binary patch literal 34972 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 literal 34803 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

    Rvw(S6AB(PfEx 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 F{{SFj#|Z!c diff --git a/.maestro/enrichedMarkdownText/flows/advanced/block_elements/mixed_nested_list_markers_test.yaml b/.maestro/enrichedMarkdownText/flows/advanced/block_elements/mixed_nested_list_markers_test.yaml new file mode 100644 index 000000000..fe8051110 --- /dev/null +++ b/.maestro/enrichedMarkdownText/flows/advanced/block_elements/mixed_nested_list_markers_test.yaml @@ -0,0 +1,92 @@ +appId: swmansion.enriched.markdown.example +tags: + - block + - advanced + - list + - task_list + - text + - android-only +--- +- launchApp: + permissions: {} + +- waitForAnimationToEnd + +- runFlow: + file: '../../../../subflows/move_to_playground.yaml' + +- assertVisible: + id: playground-screen + +- runFlow: + file: '../../../subflows/set_enriched_text_value.yaml' + env: + VALUE: | + 1. Ordered parent + - Bullet child + - Second bullet child + 2. Following ordered sibling + + - Bullet parent + 1. Ordered child + 2. Second ordered child + - Following bullet sibling + +- scrollUntilVisible: + element: + id: blur-button + direction: UP + visibilityPercentage: 100 + +- tapOn: + id: blur-button + +- scroll + +- waitForAnimationToEnd + +- runFlow: + file: '../../../subflows/capture_or_assert_screenshot.yaml' + env: + SCREENSHOT_NAME: 'mixed_nested_list_markers_bullet_ordered_display' + +- scrollUntilVisible: + element: + id: set-markdown-button + direction: UP + visibilityPercentage: 100 + +- runFlow: + file: '../../../subflows/set_enriched_text_value.yaml' + env: + VALUE: | + - Bullet parent + - [ ] Unchecked task child + - [x] Checked task child + + 1. Ordered parent + - [ ] Unchecked task child + - [x] Checked task child + + - [ ] Unchecked task parent + - Bullet child + - [x] Checked task parent + - Second bullet child + +- scrollUntilVisible: + element: + id: blur-button + direction: UP + visibilityPercentage: 100 + +- tapOn: + id: blur-button + +- scroll + +- waitForAnimationToEnd + +- runFlow: + file: '../../../subflows/capture_or_assert_screenshot.yaml' + env: + SCREENSHOT_NAME: 'mixed_nested_list_markers_tasks_display' diff --git a/.maestro/enrichedMarkdownText/flows/basic/block_elements/mixed_nested_list_test.yaml b/.maestro/enrichedMarkdownText/flows/basic/block_elements/mixed_nested_list_test.yaml index c7abe1af5..df5738ffe 100644 --- a/.maestro/enrichedMarkdownText/flows/basic/block_elements/mixed_nested_list_test.yaml +++ b/.maestro/enrichedMarkdownText/flows/basic/block_elements/mixed_nested_list_test.yaml @@ -25,6 +25,13 @@ tags: 1. Django 2. FastAPI +- runFlow: + when: + platform: Android + commands: + - scroll + - waitForAnimationToEnd + - runFlow: file: '../../../subflows/capture_or_assert_screenshot.yaml' env: diff --git a/.maestro/enrichedMarkdownText/screenshots/android/list_sublist_first_combo_display.png b/.maestro/enrichedMarkdownText/screenshots/android/list_sublist_first_combo_display.png index 2e90f0cc94ae80d29c14551f55d40f35f4a53223..8a34b7c4c02b2a50e47d4e9fe27931dfb457628c 100644 GIT binary patch literal 11163 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 literal 37682 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�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 WJ45QhEa&gJ^t6m_7T<9C>;C`*$lfRb literal 0 HcmV?d00001 diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt index 7cab2df14..401383bef 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt @@ -44,6 +44,7 @@ class BlockStyleContext { var listMarkerExtra = 0f var ancestorMarkerOffset = 0f var listItemMarkerExtra = 0f + var listItemMarkerWidth: Float? = null var taskItemCount = 0 private val orderedListItemNumbers = ArrayDeque() @@ -155,6 +156,7 @@ class BlockStyleContext { listMarkerExtra = 0f ancestorMarkerOffset = 0f listItemMarkerExtra = 0f + listItemMarkerWidth = null taskItemCount = 0 orderedListItemNumbers.clear() } diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt index 5878fe6c0..a120eb812 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt @@ -39,6 +39,7 @@ class ListItemRenderer( val depth = styleContext.listDepth - 1 val listStyle = config.style.listStyle + val parentMarkerWidth = styleContext.listItemMarkerWidth val span = if (isTask) { TaskListSpan( @@ -51,6 +52,7 @@ class ListItemRenderer( isChecked = isChecked, ancestorMarkerOffset = styleContext.ancestorMarkerOffset, markerExtraWidth = styleContext.listMarkerExtra, + parentMarkerWidth = parentMarkerWidth, ) } else { when (listType) { @@ -61,6 +63,7 @@ class ListItemRenderer( factory.context, factory.styleCache, ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ) } @@ -72,6 +75,7 @@ class ListItemRenderer( factory.styleCache, markerExtraWidth = styleContext.listMarkerExtra, ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ).apply { setItemNumber(styleContext.listItemNumber) } @@ -79,13 +83,15 @@ class ListItemRenderer( } } - // Nested lists inside this item shift by its extra marker width. + // Nested lists inside this item shift by its extra marker width and measure their indent from its column. val previousMarkerExtra = styleContext.listItemMarkerExtra styleContext.listItemMarkerExtra = span.markerExtraWidth + styleContext.listItemMarkerWidth = span.getBaselineMarkerWidth() try { factory.renderChildren(node, builder, onLinkPress, onLinkLongPress) } finally { styleContext.listItemMarkerExtra = previousMarkerExtra + styleContext.listItemMarkerWidth = parentMarkerWidth } if (builder.length == start || builder.substring(start).isBlank()) return diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt index cffeb499a..b5a4ebe93 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt @@ -23,6 +23,7 @@ abstract class BaseListSpan( protected val marginLeft: Float, protected val gapWidth: Float, internal val ancestorMarkerOffset: Float = 0f, + internal val parentMarkerWidth: Float? = null, ) : MetricAffectingSpan(), LeadingMarginSpan { private var cachedText: CharSequence? = null @@ -41,17 +42,25 @@ abstract class BaseListSpan( /** How far an ordered list widened this item's column past the one short lists reserve. */ internal open val markerExtraWidth: Float = 0f + /** This item's marker column without [markerExtraWidth]; a nested item measures its indent against it. */ + internal open fun getBaselineMarkerWidth(): Float = getMarkerWidth() + override fun updateMeasureState(textPaint: TextPaint) = applyTextStyle(textPaint) override fun updateDrawState(textPaint: TextPaint) = applyTextStyle(textPaint) - override fun getLeadingMargin(first: Boolean): Int = - if (depth == 0) { - val effectiveGap = gapWidth.coerceAtLeast(DEFAULT_MIN_GAP) - (getMarkerWidth() + effectiveGap).toInt() - } else { - (marginLeft + markerExtraWidth).toInt() - } + override fun getLeadingMargin(first: Boolean): Int { + val effectiveGap = gapWidth.coerceAtLeast(DEFAULT_MIN_GAP) + if (depth == 0) return (getMarkerWidth() + effectiveGap).toInt() + + // Subtract truncated absolute indents, each measured from its own item's column, so neither mixed + // columns nor fractional margins accumulate rounding. The widenings are whole pixels and add unchanged. + val markerWidth = getBaselineMarkerWidth() + val parentWidth = parentMarkerWidth ?: markerWidth + val indent = (depth * marginLeft + markerWidth + effectiveGap).toInt() + val parentIndent = ((depth - 1) * marginLeft + parentWidth + effectiveGap).toInt() + return indent - parentIndent + markerExtraWidth.toInt() + } override fun drawLeadingMargin( canvas: Canvas, diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt index 2d1130e5d..2f092c263 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt @@ -19,6 +19,7 @@ class OrderedListSpan( styleCache: SpanStyleCache, override val markerExtraWidth: Float = 0f, ancestorMarkerOffset: Float = 0f, + parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, context = context, @@ -33,6 +34,7 @@ class OrderedListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, ancestorMarkerOffset = ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ) { companion object { private val sharedMarkerPaint = TextPaint().apply { isAntiAlias = true } @@ -78,6 +80,8 @@ class OrderedListSpan( override fun getMarkerWidth(): Float = defaultMarkerWidth + markerExtraWidth + override fun getBaselineMarkerWidth(): Float = defaultMarkerWidth + var itemNumber: Int = 1 private set diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt index 0c269f96f..e2a4a9a9f 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt @@ -28,6 +28,7 @@ class TaskListSpan( var isChecked: Boolean, ancestorMarkerOffset: Float = 0f, override val markerExtraWidth: Float = 0f, + parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, context = context, @@ -42,6 +43,7 @@ class TaskListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, ancestorMarkerOffset = ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ) { companion object { private val boxPaint = @@ -61,7 +63,8 @@ class TaskListSpan( } private val checkboxSize = taskStyle.checkboxSize - private val markerColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize) + markerExtraWidth + private val checkboxColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize) + private val markerColumnWidth = checkboxColumnWidth + markerExtraWidth private val cornerRadius = taskStyle.checkboxBorderRadius private val rect = RectF() private val insetRect = RectF() @@ -69,6 +72,8 @@ class TaskListSpan( override fun getMarkerWidth(): Float = markerColumnWidth + override fun getBaselineMarkerWidth(): Float = checkboxColumnWidth + override fun drawMarker( canvas: Canvas, paint: Paint, diff --git a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt index a5df5b519..381e7dbc7 100644 --- a/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +++ b/packages/enriched-markdown-android/ui/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt @@ -14,6 +14,7 @@ class UnorderedListSpan( context: Context, styleCache: SpanStyleCache, ancestorMarkerOffset: Float = 0f, + parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, context = context, @@ -28,6 +29,7 @@ class UnorderedListSpan( marginLeft = listStyle.marginLeft, gapWidth = listStyle.gapWidth, ancestorMarkerOffset = ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ) { companion object { private val sharedBulletPaint = diff --git a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt index 09a7eadb6..e4e21adc0 100644 --- a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt +++ b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt @@ -2,6 +2,7 @@ package com.swmansion.enriched.markdown import android.graphics.Typeface import android.text.SpannableString +import android.text.StaticLayout import android.text.TextPaint import androidx.test.ext.junit.runners.AndroidJUnit4 import com.swmansion.enriched.markdown.parser.MarkdownASTNode @@ -137,6 +138,146 @@ class ListRenderingTest { } } + @Test + fun mixedNestsStartTheirTextFromTheirOwnMarkerColumn() { + val style = mixedStyle() + for (parent in Kind.entries) { + for (child in Kind.entries.filter { it != parent }) { + for (checked in checkedStates(parent, child)) { + val markers = drawMarkers(style, list(parent, list(child, checked = checked), checked)) + assertEquals(listOf(0, 1), markers.map { it.depth }) + val expected = (24f + columnOf(style, child) + MIXED_GAP).toInt().toFloat() + assertEquals("$child under $parent", expected, markers.last().paragraphLeft, 0f) + assertMixedGaps(markers, "$child under $parent, checked=$checked") + } + } + } + } + + @Test + fun topLevelAndSameTypeNestsKeepTheirGeometry() { + val style = mixedStyle() + for (kind in Kind.entries) { + val column = columnOf(style, kind) + val markers = drawMarkers(style, list(kind, list(kind, list(kind)))) + assertEquals(listOf(0, 1, 2), markers.map { it.depth }) + markers.forEach { + assertEquals("text for $kind at depth ${it.depth}", (column + MIXED_GAP).toInt() + it.depth * 24f, it.paragraphLeft, 0f) + assertEquals(column + it.depth * 24f, it.marker.right, 0.01f) + } + } + } + + @Test + fun mixedColumnsUseAbsoluteIndentsWithoutFractionalDrift() { + val alternating = listOf(Kind.BULLET, Kind.ORDERED, Kind.BULLET, Kind.TASK) + val sameTypeRun = List(5) { Kind.BULLET } + Kind.TASK + for (margin in listOf(24f, 24.5f, 4f)) { + val style = mixedStyle(bulletSize = 6.5f, marginLeft = margin) + for (kinds in listOf(alternating, sameTypeRun)) { + val columns = kinds.map { columnOf(style, it) } + val tree = kinds.dropLast(1).foldRight(list(kinds.last())) { kind, child -> list(kind, child) } + val markers = drawMarkers(style, tree) + assertEquals(kinds.indices.toList(), markers.map { it.depth }) + markers.forEach { + val expected = (it.depth * margin + columns[it.depth] + MIXED_GAP).toInt().toFloat() + assertEquals("absolute indent at depth ${it.depth} of $kinds, margin $margin", expected, it.paragraphLeft, 0f) + assertEquals(it.paragraphLeft - MIXED_GAP, it.marker.right, 0.99f) + } + } + } + } + + @Test + fun mixedAncestorsAndFollowingSiblingsRestoreTheirOwnColumns() { + val style = mixedStyle() + for (parent in Kind.entries) { + val tree = list(parent).copy(children = Kind.entries.map { child -> item(parent, list(child, list(parent))) }) + assertMixedGaps(drawMarkers(style, tree, list(Kind.BULLET), list(Kind.ORDERED), list(Kind.TASK)), "under $parent") + } + } + + @Test + fun mixedNestsAroundWideNumberedListsKeepTheirMarkerGap() { + val style = mixedStyle() + val wide = numbered(101) + val wideWithTask = withChild(numbered(101), 1, list(Kind.TASK, list(Kind.BULLET))) + val shapes = + listOf( + withChild(wide, 0, list(Kind.BULLET)), + wideWithTask, + list(Kind.BULLET, wide), + list(Kind.TASK, wide), + withChild(numbered(1000), 999, withChild(wide, 0, list(Kind.BULLET))), + list(Kind.BULLET, withChild(wide, 1, list(Kind.TASK))), + orderedList(*numbered(101).children.toTypedArray(), item(Kind.TASK, list(Kind.BULLET))), + ) + for ((index, shape) in shapes.withIndex()) { + assertMixedGaps(drawMarkers(style, shape), "shape $index") + } + } + + @Test + fun wrappedLinesKeepTheChildsOwnColumn() { + val style = mixedStyle() + val wrapped = orderedList(listItem(paragraph(text("wrapped child text ".repeat(12))))) + val text = SpannableString(render(document(list(Kind.BULLET, wrapped)), style)) + val layout = StaticLayout.Builder.obtain(text, 0, text.length, TextPaint(), 180).build() + val span = text.getSpans(0, text.length, OrderedListSpan::class.java).single() + val firstLine = layout.getLineForOffset(text.getSpanStart(span)) + val lastLine = layout.getLineForOffset(text.getSpanEnd(span) - 1) + assertTrue(lastLine > firstLine) + val column = columnOf(style, Kind.ORDERED) + for (line in firstLine..lastLine) { + assertEquals((24f + column + MIXED_GAP).toInt(), layout.getParagraphLeft(line)) + } + val markers = MarkerCanvas.drawMarkers(layout) + assertEquals(2, markers.size) + assertEquals(24f + column, markers.last().right, 0.01f) + } + + @Test + fun rtlMixedNestsKeepTheirMarkerGapAtEveryDepth() { + fun rtl(node: MarkdownASTNode): MarkdownASTNode { + if (node.type == MarkdownASTNode.NodeType.Text) return node.copy(content = "\u05e4\u05e8\u05d9\u05d8") + return node.copy(children = node.children.map { rtl(it) }) + } + + val style = mixedStyle() + for (parent in Kind.entries) { + for (child in Kind.entries.filter { it != parent }) { + for (checked in checkedStates(parent, child)) { + val tree = list(parent, list(child, list(parent, checked = checked), checked), checked) + val text = SpannableString(render(document(rtl(tree)), style)) + val markers = MarkerCanvas.markerGeometry(text, MarkerCanvas.layout(text, style.listStyle.fontSize, rtl = true)) + assertEquals(listOf(0, 1, 2), markers.map { it.depth }) + markers.forEach { + assertEquals("RTL paragraph at depth ${it.depth}", -1, it.direction) + // Bullets are centered on the column edge, so their recorded right is that edge in both directions. + val kind = if (it.depth == 1) child else parent + val edge = if (kind == Kind.BULLET) it.marker.right else it.marker.left + assertEquals("$child under $parent, checked=$checked, depth ${it.depth}", it.paragraphRight + MIXED_GAP, edge, 0.01f) + } + } + } + } + } + + @Test + fun equalMinimumColumnsKeepTheirGeometryForMixedNests() { + val style = mixedStyle(markerMinWidth = 40f) + for (parent in Kind.entries) { + for (child in Kind.entries.filter { it != parent }) { + val markers = drawMarkers(style, list(parent, list(child, list(parent)))) + assertEquals(listOf(0, 1, 2), markers.map { it.depth }) + markers.forEach { + assertEquals("text for $child under $parent at depth ${it.depth}", 46f + it.depth * 24f, it.paragraphLeft, 0f) + assertEquals(40f + it.depth * 24f, it.marker.right, 0.01f) + } + } + } + } + /** The rows [wide] shares with [short], tasks and their children included, all sit [wide]'s widening further right. */ private fun assertEveryRowShiftsTogether( style: StyleConfig, @@ -160,6 +301,16 @@ class ListRenderingTest { } } + private fun assertMixedGaps( + markers: List, + shape: String, + ) { + assertTrue(markers.isNotEmpty()) + markers.forEach { + assertEquals("marker gap at depth ${it.depth}, $shape", it.paragraphLeft - MIXED_GAP, it.marker.right, 0.01f) + } + } + private fun assertNestedMarkerGapsUnchanged( style: StyleConfig, short: MarkdownASTNode, @@ -227,4 +378,60 @@ class ListRenderingTest { ), ) } + + private enum class Kind { ORDERED, BULLET, TASK } + + private fun list( + kind: Kind, + child: MarkdownASTNode? = null, + checked: Boolean = false, + ): MarkdownASTNode { + val item = item(kind, child, checked) + return if (kind == Kind.ORDERED) orderedList(item) else unorderedList(item) + } + + private fun item( + kind: Kind, + child: MarkdownASTNode? = null, + checked: Boolean = false, + ): MarkdownASTNode { + val children = listOfNotNull(paragraph(text("item")), child).toTypedArray() + return if (kind == Kind.TASK) taskListItem(checked, *children) else listItem(*children) + } + + private fun checkedStates( + parent: Kind, + child: Kind, + ) = if (parent == Kind.TASK || child == Kind.TASK) listOf(false, true) else listOf(false) + + /** The marker column [kind] reserves before any widening, read from a rendered top-level item. */ + private fun columnOf( + style: StyleConfig, + kind: Kind, + ): Float { + val text = render(document(list(kind)), style) + return text.getSpans(0, text.length, BaseListSpan::class.java).single().getBaselineMarkerWidth() + } + + private fun mixedStyle( + markerMinWidth: Float = 0f, + bulletSize: Float = 6f, + marginLeft: Float = 24f, + ): StyleConfig { + val base = MarkdownRenderTestSupport.defaultStyle + return MarkdownRenderTestSupport.styleWithList( + base.listStyle.copy( + fontSize = 16f, + bulletSize = bulletSize, + markerMinWidth = markerMinWidth, + gapWidth = MIXED_GAP, + marginLeft = marginLeft, + ), + base.taskListStyle.copy(checkboxSize = 14f), + ) + } + + private companion object { + const val MIXED_GAP = 6f + } } diff --git a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt index 7383db048..7d925cc12 100644 --- a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt +++ b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt @@ -19,11 +19,13 @@ data class DrawnMarker( val baseline: Float, ) -/** A drawn marker with the text edge and list depth of the paragraph it belongs to. */ +/** A drawn marker with the text edges, direction and list depth of the paragraph it belongs to. */ data class MarkerGeometry( val marker: DrawnMarker, val paragraphLeft: Float, val depth: Int, + val paragraphRight: Float, + val direction: Int, ) /** Records the list markers a layout draws instead of painting them. */ @@ -48,6 +50,18 @@ class MarkerCanvas : Canvas(Bitmap.createBitmap(LAYOUT_WIDTH, 1, Bitmap.Config.A super.drawCircle(cx, cy, radius, paint) } + override fun drawRect( + left: Float, + top: Float, + right: Float, + bottom: Float, + paint: Paint, + ) { + // Bullets from depth 2 on are squares, centered like the round ones. + markers += DrawnMarker(left, (left + right) / 2f, (top + bottom) / 2f) + super.drawRect(left, top, right, bottom, paint) + } + override fun drawRoundRect( rect: RectF, rx: Float, @@ -86,7 +100,7 @@ class MarkerCanvas : Canvas(Bitmap.createBitmap(LAYOUT_WIDTH, 1, Bitmap.Config.A fun drawMarkers(layout: Layout): List = MarkerCanvas().also(layout::draw).markers.sortedWith(compareBy({ it.baseline }, { it.left })) - /** Every marker [layout] draws, with the text edge and depth of its paragraph. */ + /** Every marker [layout] draws, with the text edges, direction and depth of its paragraph. */ fun markerGeometry( text: Spanned, layout: Layout, @@ -95,7 +109,13 @@ class MarkerCanvas : Canvas(Bitmap.createBitmap(LAYOUT_WIDTH, 1, Bitmap.Config.A val line = layout.getLineForVertical(marker.baseline.toInt()) val start = layout.getLineStart(line) val depth = text.getSpans(start, start + 1, BaseListSpan::class.java).maxOf { it.depth } - MarkerGeometry(marker, layout.getParagraphLeft(line).toFloat(), depth) + MarkerGeometry( + marker, + layout.getParagraphLeft(line).toFloat(), + depth, + layout.getParagraphRight(line).toFloat(), + layout.getParagraphDirection(line), + ) } } } diff --git a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt index 06a22103f..c68628907 100644 --- a/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt +++ b/packages/enriched-markdown-android/ui/src/test/java/com/swmansion/enriched/markdown/test/MarkdownRenderTestSupport.kt @@ -102,8 +102,11 @@ object MarkdownRenderTestSupport { ) } - /** [defaultStyle] with only its [ListStyle] replaced. */ - fun styleWithList(listStyle: ListStyle): StyleConfig = copyOfDefault(listStyle = listStyle) + /** [defaultStyle] with its [ListStyle] and, when given, its [TaskListStyle] replaced. */ + fun styleWithList( + listStyle: ListStyle, + taskListStyle: TaskListStyle? = null, + ): StyleConfig = copyOfDefault(listStyle = listStyle, taskListStyle = taskListStyle) /** [defaultStyle] with only its [TaskListStyle] replaced. */ fun styleWithTaskList(taskListStyle: TaskListStyle): StyleConfig = copyOfDefault(taskListStyle = taskListStyle) diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt index 1ca6f3dd4..c908586bf 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt @@ -44,6 +44,7 @@ class BlockStyleContext { var listMarkerExtra = 0f var ancestorMarkerOffset = 0f var listItemMarkerExtra = 0f + var listItemMarkerWidth: Float? = null var taskItemCount = 0 var accumulatedIndent = 0 @@ -157,6 +158,7 @@ class BlockStyleContext { listMarkerExtra = 0f ancestorMarkerOffset = 0f listItemMarkerExtra = 0f + listItemMarkerWidth = null taskItemCount = 0 accumulatedIndent = 0 listItemStarts.clear() diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt index f79309fad..dea6196c2 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt @@ -38,6 +38,7 @@ class ListItemRenderer( val depth = styleContext.listDepth - 1 val listStyle = config.style.listStyle + val parentMarkerWidth = styleContext.listItemMarkerWidth fun makeSpan(drawsMarker: Boolean): BaseListSpan = if (isTask) { @@ -52,6 +53,7 @@ class ListItemRenderer( drawsMarker = drawsMarker, ancestorMarkerOffset = styleContext.ancestorMarkerOffset, markerExtraWidth = styleContext.listMarkerExtra, + parentMarkerWidth = parentMarkerWidth, ) } else { when (listType) { @@ -63,6 +65,7 @@ class ListItemRenderer( factory.styleCache, drawsMarker, ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ) } @@ -75,6 +78,7 @@ class ListItemRenderer( drawsMarker, markerExtraWidth = styleContext.listMarkerExtra, ancestorMarkerOffset = styleContext.ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ).apply { setItemNumber(styleContext.listItemNumber) } @@ -86,6 +90,7 @@ class ListItemRenderer( val previousMarkerExtra = styleContext.listItemMarkerExtra styleContext.listItemMarkerExtra = markerSpan.markerExtraWidth + styleContext.listItemMarkerWidth = markerSpan.getBaselineMarkerWidth() val prevIndent = styleContext.accumulatedIndent styleContext.accumulatedIndent = prevIndent + markerSpan.getLeadingMargin(false) try { @@ -93,6 +98,7 @@ class ListItemRenderer( } finally { styleContext.accumulatedIndent = prevIndent styleContext.listItemMarkerExtra = previousMarkerExtra + styleContext.listItemMarkerWidth = parentMarkerWidth } if (builder.length == start || builder.substring(start).isBlank()) return diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt index 054931d8d..f58fc9b3c 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt @@ -24,6 +24,7 @@ abstract class BaseListSpan( protected val gapWidth: Float, internal val drawsMarker: Boolean = true, internal val ancestorMarkerOffset: Float = 0f, + internal val parentMarkerWidth: Float? = null, ) : MetricAffectingSpan(), LeadingMarginSpan { private var cachedText: CharSequence? = null @@ -42,17 +43,25 @@ abstract class BaseListSpan( /** How far an ordered list widened this item's column past the one short lists reserve. */ internal open val markerExtraWidth: Float = 0f + /** This item's marker column without [markerExtraWidth]; a nested item measures its indent against it. */ + internal open fun getBaselineMarkerWidth(): Float = getMarkerWidth() + override fun updateMeasureState(textPaint: TextPaint) = applyTextStyle(textPaint) override fun updateDrawState(textPaint: TextPaint) = applyTextStyle(textPaint) - override fun getLeadingMargin(first: Boolean): Int = - if (depth == 0) { - val effectiveGap = gapWidth.coerceAtLeast(DEFAULT_MIN_GAP) - (getMarkerWidth() + effectiveGap).toInt() - } else { - (marginLeft + markerExtraWidth).toInt() - } + override fun getLeadingMargin(first: Boolean): Int { + val effectiveGap = gapWidth.coerceAtLeast(DEFAULT_MIN_GAP) + if (depth == 0) return (getMarkerWidth() + effectiveGap).toInt() + + // Subtract truncated absolute indents, each measured from its own item's column, so neither mixed + // columns nor fractional margins accumulate rounding. The widenings are whole pixels and add unchanged. + val markerWidth = getBaselineMarkerWidth() + val parentWidth = parentMarkerWidth ?: markerWidth + val indent = (depth * marginLeft + markerWidth + effectiveGap).toInt() + val parentIndent = ((depth - 1) * marginLeft + parentWidth + effectiveGap).toInt() + return indent - parentIndent + markerExtraWidth.toInt() + } override fun drawLeadingMargin( canvas: Canvas, diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt index 9a2b19930..ebb52a568 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt @@ -22,6 +22,7 @@ class OrderedListSpan( drawsMarker: Boolean = true, override val markerExtraWidth: Float = 0f, ancestorMarkerOffset: Float = 0f, + parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, context = context, @@ -37,6 +38,7 @@ class OrderedListSpan( gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, ancestorMarkerOffset = ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ) { companion object { private val sharedMarkerPaint = TextPaint().apply { isAntiAlias = true } @@ -84,6 +86,8 @@ class OrderedListSpan( override fun getMarkerWidth(): Float = defaultMarkerWidth + markerExtraWidth + override fun getBaselineMarkerWidth(): Float = defaultMarkerWidth + var itemNumber: Int = 1 private set diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt index fb0088718..87f992fec 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt @@ -22,6 +22,7 @@ class TaskListSpan( drawsMarker: Boolean = true, ancestorMarkerOffset: Float = 0f, override val markerExtraWidth: Float = 0f, + parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, context = context, @@ -37,9 +38,11 @@ class TaskListSpan( gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, ancestorMarkerOffset = ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ) { private val checkboxSize = taskStyle.checkboxSize - private val markerColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize) + markerExtraWidth + private val checkboxColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize) + private val markerColumnWidth = checkboxColumnWidth + markerExtraWidth private val cornerRadius = taskStyle.checkboxBorderRadius private val rect = RectF() private val checkPath = Path() @@ -63,6 +66,8 @@ class TaskListSpan( override fun getMarkerWidth(): Float = markerColumnWidth + override fun getBaselineMarkerWidth(): Float = checkboxColumnWidth + override fun drawMarker( canvas: Canvas, paint: Paint, diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt index 2f50f46a0..a7597f88a 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt @@ -15,6 +15,7 @@ class UnorderedListSpan( styleCache: SpanStyleCache, drawsMarker: Boolean = true, ancestorMarkerOffset: Float = 0f, + parentMarkerWidth: Float? = null, ) : BaseListSpan( depth = depth, context = context, @@ -30,6 +31,7 @@ class UnorderedListSpan( gapWidth = listStyle.gapWidth, drawsMarker = drawsMarker, ancestorMarkerOffset = ancestorMarkerOffset, + parentMarkerWidth = parentMarkerWidth, ) { companion object { private val sharedBulletPaint = diff --git a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt index a9e6e00d0..e70b24167 100644 --- a/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +++ b/packages/react-native-enriched-markdown/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt @@ -133,6 +133,7 @@ object TaskListTapUtils { drawsMarker = old.drawsMarker, ancestorMarkerOffset = old.ancestorMarkerOffset, markerExtraWidth = old.markerExtraWidth, + parentMarkerWidth = old.parentMarkerWidth, ) // Layout draws leading margins in insertion order, and a re-added span moves to the end of it. diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt index c10a5a307..35f69a064 100644 --- a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/ListRenderingTest.kt @@ -2,6 +2,7 @@ package com.swmansion.enriched.markdown import android.graphics.Typeface import android.text.SpannableString +import android.text.StaticLayout import android.text.TextPaint import com.swmansion.enriched.markdown.parser.MarkdownASTNode import com.swmansion.enriched.markdown.spans.BaseListSpan @@ -124,18 +125,143 @@ class ListRenderingTest { } @Test - fun shortMixedNestsKeepTheirOriginalTextIndents() { - val style = styleConfig(list = mapOf("gapWidth" to 6.0), taskList = mapOf("checkboxSize" to 14.0)) - val ordered = numbered(1, 1) - val bullet = unorderedList(item()) - val task = orderedList(taskListItem(checked = false, paragraph(text("item")))) - val shapes = listOf(ordered to bullet, bullet to ordered, bullet to task, ordered to task, task to bullet) - val baseIndents = listOf(52f, 33f, 33f, 52f, 44f) + fun mixedNestsStartTheirTextFromTheirOwnMarkerColumn() { + val style = mixedStyle() + // Each child's text sits one marginLeft plus its own column and gap in: 24 + (3, 22 or 14) + 6. + val indents = mapOf(Kind.BULLET to 33f, Kind.ORDERED to 52f, Kind.TASK to 44f) + for (parent in Kind.entries) { + for (child in Kind.entries.filter { it != parent }) { + for (checked in checkedStates(parent, child)) { + val markers = drawMarkers(style, list(parent, list(child, checked = checked), checked)) + assertEquals(listOf(0, 1), markers.map { it.depth }) + assertEquals("$child under $parent", indents.getValue(child), markers.last().paragraphLeft, 0f) + assertMixedGaps(markers, "$child under $parent, checked=$checked") + } + } + } + } + + @Test + fun topLevelAndSameTypeNestsKeepTheirGeometry() { + val style = mixedStyle() + for (kind in Kind.entries) { + val column = columnOf(style, kind) + val markers = drawMarkers(style, list(kind, list(kind, list(kind)))) + assertEquals(listOf(0, 1, 2), markers.map { it.depth }) + markers.forEach { + assertEquals("text for $kind at depth ${it.depth}", (column + MIXED_GAP).toInt() + it.depth * 24f, it.paragraphLeft, 0f) + assertEquals(column + it.depth * 24f, it.marker.right, 0.01f) + } + } + } + + @Test + fun mixedColumnsUseAbsoluteIndentsWithoutFractionalDrift() { + val alternating = listOf(Kind.BULLET, Kind.ORDERED, Kind.BULLET, Kind.TASK) + val sameTypeRun = List(5) { Kind.BULLET } + Kind.TASK + for (margin in listOf(24.0, 24.5, 4.0)) { + val style = mixedStyle(bulletSize = 6.5, marginLeft = margin) + for (kinds in listOf(alternating, sameTypeRun)) { + val columns = kinds.map { columnOf(style, it) } + val tree = kinds.dropLast(1).foldRight(list(kinds.last())) { kind, child -> list(kind, child) } + val markers = drawMarkers(style, tree) + assertEquals(kinds.indices.toList(), markers.map { it.depth }) + markers.forEach { + val expected = (it.depth * margin + columns[it.depth] + MIXED_GAP).toInt().toFloat() + assertEquals("absolute indent at depth ${it.depth} of $kinds, margin $margin", expected, it.paragraphLeft, 0f) + assertEquals(it.paragraphLeft - MIXED_GAP, it.marker.right, 0.99f) + } + } + } + } + + @Test + fun mixedAncestorsAndFollowingSiblingsRestoreTheirOwnColumns() { + val style = mixedStyle() + for (parent in Kind.entries) { + val tree = list(parent).copy(children = Kind.entries.map { child -> item(parent, list(child, list(parent))) }) + assertMixedGaps(drawMarkers(style, tree, list(Kind.BULLET), list(Kind.ORDERED), list(Kind.TASK)), "under $parent") + } + } + + @Test + fun mixedNestsAroundWideNumberedListsKeepTheirMarkerGap() { + val style = mixedStyle() + val wide = numbered(12345, 2) + val wideWithTask = orderedList(item(), item(Kind.TASK, list(Kind.BULLET)), start = 998) + val shapes = + listOf( + withChild(wide, 0, list(Kind.BULLET)), + withChild(wide, 1, list(Kind.TASK, list(Kind.BULLET))), + list(Kind.BULLET, wide), + list(Kind.TASK, wide), + withChild(numbered(998, 4), 3, withChild(wide, 0, list(Kind.BULLET))), + list(Kind.BULLET, withChild(wide, 1, list(Kind.TASK))), + withChild(wideWithTask, 0, list(Kind.BULLET)), + ) for ((index, shape) in shapes.withIndex()) { - val (parent, child) = shape - val nested = drawMarkers(style, withChild(parent, 0, child)).single { it.depth == 1 } - assertEquals("base mixed indent for shape $index", baseIndents[index], nested.paragraphLeft, 0.01f) - assertTrue(nested.marker.left >= 0f) + assertMixedGaps(drawMarkers(style, shape), "shape $index") + } + } + + @Test + fun wrappedLinesKeepTheChildsOwnColumn() { + val style = mixedStyle() + val wrapped = orderedList(listItem(paragraph(text("wrapped child text ".repeat(12))))) + val text = SpannableString(render(style, list(Kind.BULLET, wrapped))) + val layout = StaticLayout.Builder.obtain(text, 0, text.length, TextPaint(), 180).build() + val span = text.getSpans(0, text.length, OrderedListSpan::class.java).single() + val firstLine = layout.getLineForOffset(text.getSpanStart(span)) + val lastLine = layout.getLineForOffset(text.getSpanEnd(span) - 1) + assertTrue(lastLine > firstLine) + val column = columnOf(style, Kind.ORDERED) + for (line in firstLine..lastLine) { + assertEquals((24f + column + MIXED_GAP).toInt(), layout.getParagraphLeft(line)) + } + val markers = MarkerCanvas.drawMarkers(layout) + assertEquals(2, markers.size) + assertEquals(24f + column, markers.last().right, 0.01f) + } + + @Test + fun rtlMixedNestsKeepTheirMarkerGapAtEveryDepth() { + fun rtl(node: MarkdownASTNode): MarkdownASTNode { + if (node.type == MarkdownASTNode.NodeType.Text) return node.copy(content = "\u05e4\u05e8\u05d9\u05d8") + return node.copy(children = node.children.map { rtl(it) }) + } + + val style = mixedStyle() + for (parent in Kind.entries) { + for (child in Kind.entries.filter { it != parent }) { + for (checked in checkedStates(parent, child)) { + val tree = list(parent, list(child, list(parent, checked = checked), checked), checked) + val text = SpannableString(render(style, rtl(tree))) + val markers = MarkerCanvas.markerGeometry(text, MarkerCanvas.layout(text, style.listStyle.fontSize, rtl = true)) + assertEquals(listOf(0, 1, 2), markers.map { it.depth }) + markers.forEach { + assertEquals("RTL paragraph at depth ${it.depth}", -1, it.direction) + // Bullets are centered on the column edge, so their recorded right is that edge in both directions. + val kind = if (it.depth == 1) child else parent + val edge = if (kind == Kind.BULLET) it.marker.right else it.marker.left + assertEquals("$child under $parent, checked=$checked, depth ${it.depth}", it.paragraphRight + MIXED_GAP, edge, 0.01f) + } + } + } + } + } + + @Test + fun equalMinimumColumnsKeepTheirGeometryForMixedNests() { + val style = mixedStyle(markerMinWidth = 40.0) + for (parent in Kind.entries) { + for (child in Kind.entries.filter { it != parent }) { + val markers = drawMarkers(style, list(parent, list(child, list(parent)))) + assertEquals(listOf(0, 1, 2), markers.map { it.depth }) + markers.forEach { + assertEquals("text for $child under $parent at depth ${it.depth}", 46f + it.depth * 24f, it.paragraphLeft, 0f) + assertEquals(40f + it.depth * 24f, it.marker.right, 0.01f) + } + } } } @@ -169,6 +295,16 @@ class ListRenderingTest { } } + private fun assertMixedGaps( + markers: List, + shape: String, + ) { + assertTrue(markers.isNotEmpty()) + markers.forEach { + assertEquals("marker gap at depth ${it.depth}, $shape", it.paragraphLeft - MIXED_GAP, it.marker.right, 0.01f) + } + } + private fun assertDrawnMarkerPositions( style: StyleConfig, vararg lists: MarkdownASTNode, @@ -267,4 +403,58 @@ class ListRenderingTest { private fun listStyle(minWidth: Double = 0.0): StyleConfig = styleConfig(list = mapOf("fontFamily" to "monospace", "markerMinWidth" to minWidth)) + + private enum class Kind { ORDERED, BULLET, TASK } + + private fun list( + kind: Kind, + child: MarkdownASTNode? = null, + checked: Boolean = false, + ): MarkdownASTNode { + val item = item(kind, child, checked) + return if (kind == Kind.ORDERED) orderedList(item) else unorderedList(item) + } + + private fun item( + kind: Kind, + child: MarkdownASTNode? = null, + checked: Boolean = false, + ): MarkdownASTNode { + val children = listOfNotNull(paragraph(text("item")), child).toTypedArray() + return if (kind == Kind.TASK) taskListItem(checked, *children) else listItem(*children) + } + + private fun checkedStates( + parent: Kind, + child: Kind, + ) = if (parent == Kind.TASK || child == Kind.TASK) listOf(false, true) else listOf(false) + + /** The marker column [kind] reserves before any widening, read from a rendered top-level item. */ + private fun columnOf( + style: StyleConfig, + kind: Kind, + ): Float { + val text = render(style, list(kind)) + return text.getSpans(0, text.length, BaseListSpan::class.java).single().getBaselineMarkerWidth() + } + + private fun mixedStyle( + markerMinWidth: Double = 0.0, + bulletSize: Double = 6.0, + marginLeft: Double = 24.0, + ): StyleConfig = + styleConfig( + list = + mapOf( + "bulletSize" to bulletSize, + "markerMinWidth" to markerMinWidth, + "gapWidth" to MIXED_GAP.toDouble(), + "marginLeft" to marginLeft, + ), + taskList = mapOf("checkboxSize" to 14.0), + ) + + private companion object { + const val MIXED_GAP = 6f + } } diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/TaskListInteractionTest.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/TaskListInteractionTest.kt index 64a70db33..4ade5adce 100644 --- a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/TaskListInteractionTest.kt +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/TaskListInteractionTest.kt @@ -38,21 +38,38 @@ class TaskListInteractionTest { @Test fun togglingATaskUnderAWideParentKeepsEveryMarginAndMarkerPosition() { - assertTaskToggleKeepsGeometry(opensWithSublist = false) + assertTaskToggleKeepsGeometry(wideParentTree(opensWithSublist = false), anchors = 0, markers = 4) } @Test fun togglingAnAnchoredTaskUnderAWideParentKeepsEveryMarginAndMarkerPosition() { - assertTaskToggleKeepsGeometry(opensWithSublist = true) + assertTaskToggleKeepsGeometry(wideParentTree(opensWithSublist = true), anchors = 1, markers = 4) + } + + @Test + fun togglingATaskInAMixedNestKeepsEveryMarginAndMarkerPosition() { + // The task's indent depends on its parent's marker column, so the toggled copy has to keep it. + val tasks = unorderedList(taskListItem(checked = false, paragraph(text("item")), numbered(1))) + val parent = listItem(paragraph(text("item")), tasks) + for (tree in listOf(unorderedList(parent), orderedList(parent))) { + assertTaskToggleKeepsGeometry(tree, anchors = 0, markers = 3) + } + } + + private fun wideParentTree(opensWithSublist: Boolean): MarkdownASTNode { + val taskChildren = if (opensWithSublist) arrayOf(numbered(1)) else arrayOf(paragraph(text("item")), numbered(1)) + val task = taskListItem(checked = false, *taskChildren) + return orderedList(listItem(paragraph(text("item")), unorderedList(task)), item(), start = 100) } // Layout draws leading margins in span insertion order, so a toggle that re-adds only the // task's span would move its checkbox by its ancestors' margins. - private fun assertTaskToggleKeepsGeometry(opensWithSublist: Boolean) { + private fun assertTaskToggleKeepsGeometry( + tree: MarkdownASTNode, + anchors: Int, + markers: Int, + ) { val style = styleConfig(list = mapOf("fontFamily" to "monospace")) - val taskChildren = if (opensWithSublist) arrayOf(numbered(1)) else arrayOf(paragraph(text("item")), numbered(1)) - val task = taskListItem(checked = false, *taskChildren) - val tree = orderedList(listItem(paragraph(text("item")), unorderedList(task)), item(), start = 100) val textView = object : AccessibleMarkdownTextView(context) {}.apply { layoutParams = ViewGroup.LayoutParams(MarkerCanvas.LAYOUT_WIDTH, ViewGroup.LayoutParams.WRAP_CONTENT) @@ -61,10 +78,10 @@ class TaskListInteractionTest { textView.setText(render(style, tree), TextView.BufferType.SPANNABLE) val initialText = textView.text as Spanned val taskIndex = initialText.getSpans(0, initialText.length, TaskListSpan::class.java).single().taskIndex - assertEquals(if (opensWithSublist) 1 else 0, initialText.getSpans(0, initialText.length, ListMarkerAnchorSpan::class.java).size) + assertEquals(anchors, initialText.getSpans(0, initialText.length, ListMarkerAnchorSpan::class.java).size) val initialMargins = listMargins(initialText) val initialMarkers = drawTextViewMarkers(textView) - assertEquals(4, initialMarkers.size) + assertEquals(markers, initialMarkers.size) for (checked in listOf(true, false)) { assertTrue(TaskListTapUtils.updateTaskListItemCheckedState(textView, taskIndex, checked, style)) diff --git a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt index 7383db048..7d925cc12 100644 --- a/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt +++ b/packages/react-native-enriched-markdown/android/src/test/java/com/swmansion/enriched/markdown/test/ListMarkerCanvas.kt @@ -19,11 +19,13 @@ data class DrawnMarker( val baseline: Float, ) -/** A drawn marker with the text edge and list depth of the paragraph it belongs to. */ +/** A drawn marker with the text edges, direction and list depth of the paragraph it belongs to. */ data class MarkerGeometry( val marker: DrawnMarker, val paragraphLeft: Float, val depth: Int, + val paragraphRight: Float, + val direction: Int, ) /** Records the list markers a layout draws instead of painting them. */ @@ -48,6 +50,18 @@ class MarkerCanvas : Canvas(Bitmap.createBitmap(LAYOUT_WIDTH, 1, Bitmap.Config.A super.drawCircle(cx, cy, radius, paint) } + override fun drawRect( + left: Float, + top: Float, + right: Float, + bottom: Float, + paint: Paint, + ) { + // Bullets from depth 2 on are squares, centered like the round ones. + markers += DrawnMarker(left, (left + right) / 2f, (top + bottom) / 2f) + super.drawRect(left, top, right, bottom, paint) + } + override fun drawRoundRect( rect: RectF, rx: Float, @@ -86,7 +100,7 @@ class MarkerCanvas : Canvas(Bitmap.createBitmap(LAYOUT_WIDTH, 1, Bitmap.Config.A fun drawMarkers(layout: Layout): List = MarkerCanvas().also(layout::draw).markers.sortedWith(compareBy({ it.baseline }, { it.left })) - /** Every marker [layout] draws, with the text edge and depth of its paragraph. */ + /** Every marker [layout] draws, with the text edges, direction and depth of its paragraph. */ fun markerGeometry( text: Spanned, layout: Layout, @@ -95,7 +109,13 @@ class MarkerCanvas : Canvas(Bitmap.createBitmap(LAYOUT_WIDTH, 1, Bitmap.Config.A val line = layout.getLineForVertical(marker.baseline.toInt()) val start = layout.getLineStart(line) val depth = text.getSpans(start, start + 1, BaseListSpan::class.java).maxOf { it.depth } - MarkerGeometry(marker, layout.getParagraphLeft(line).toFloat(), depth) + MarkerGeometry( + marker, + layout.getParagraphLeft(line).toFloat(), + depth, + layout.getParagraphRight(line).toFloat(), + layout.getParagraphDirection(line), + ) } } } From e90c138875ec72f1d2d6a8ca06aa02d0ddee6443 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Fri, 16 Oct 2026 14:56:12 -0700 Subject: [PATCH 11/11] chore: prepare the T3 mobile fork archive on upstream 2547e709 Co-Authored-By: Claude Opus 5.5 --- packages/react-native-enriched-markdown/package.json | 2 +- scripts/pack-t3.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native-enriched-markdown/package.json b/packages/react-native-enriched-markdown/package.json index d86d6198f..6963a4a85 100644 --- a/packages/react-native-enriched-markdown/package.json +++ b/packages/react-native-enriched-markdown/package.json @@ -1,6 +1,6 @@ { "name": "react-native-enriched-markdown", - "version": "1.2.0-t3.13", + "version": "1.2.0-t3.14", "description": "Markdown-based Rich Text solution for React Native", "main": "./lib/module/index", "module": "./lib/module/index", diff --git a/scripts/pack-t3.mjs b/scripts/pack-t3.mjs index 0f4725d23..9badd6883 100644 --- a/scripts/pack-t3.mjs +++ b/scripts/pack-t3.mjs @@ -90,7 +90,7 @@ try { { repository: 'https://github.com/pingdotgg/enriched-markdown', commit: git('rev-parse', 'HEAD'), - upstreamCommit: 'a7703879e64704498d544da30194e96341b85fbb', + upstreamCommit: '2547e709d759eda2ee3a5c6d9d37b51f8fa51321', version: pkg.version, }, null,

    m~w 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