Skip to content

Replace cmark-gfm with an in-house implementation - #2831

Merged
jviotti merged 3 commits into
mainfrom
no-cmark-gfm
Sep 16, 2026
Merged

jviotti merged 3 commits into
mainfrom
no-cmark-gfm

Conversation

@jviotti

@jviotti jviotti commented Sep 14, 2026

Copy link
Copy Markdown
Member

Signed-off-by: Juan Cruz Viotti [email protected]

Review in cubic

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/llvm)

Details
Benchmark suite Current: 6a8f25b Previous: 475302c Ratio
Regex_Lower_S_Or_Upper_S_Asterisk 2.2196957044764347 ns/iter 2.1849779774413958 ns/iter 1.02
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 2.191581364441137 ns/iter 2.179076205365935 ns/iter 1.01
Regex_Period_Asterisk 2.196048351178115 ns/iter 2.179316436167538 ns/iter 1.01
Regex_Group_Period_Asterisk_Group 2.192903690605228 ns/iter 2.180105136162346 ns/iter 1.01
Regex_Period_Plus 2.8030702887314183 ns/iter 2.801766706898488 ns/iter 1.00
Regex_Period 2.8022351974724407 ns/iter 2.8019069440411837 ns/iter 1.00
Regex_Caret_Period_Plus_Dollar 2.801623915044776 ns/iter 2.801061923642119 ns/iter 1.00
Regex_Caret_Group_Period_Plus_Group_Dollar 2.8023368073253883 ns/iter 2.800704089756349 ns/iter 1.00
Regex_Caret_Period_Asterisk_Dollar 3.4245606873335186 ns/iter 3.423481065486481 ns/iter 1.00
Regex_Caret_Group_Period_Asterisk_Group_Dollar 3.4243190844920446 ns/iter 3.420835314247628 ns/iter 1.00
Regex_Caret_X_Hyphen 6.545557497098034 ns/iter 6.5419532591026535 ns/iter 1.00
Regex_Period_Md_Dollar 28.082636860127565 ns/iter 27.145611875743725 ns/iter 1.03
Regex_Caret_Slash_Period_Asterisk 6.853043734422777 ns/iter 5.9343010282023965 ns/iter 1.15
Regex_Caret_Period_Range_Dollar 4.360785684222468 ns/iter 4.356406182423531 ns/iter 1.00
Regex_Nested_Backtrack 38.71583296977388 ns/iter 38.74969462814314 ns/iter 1.00
JSON_Array_Of_Objects_Unique 402.56372347761953 ns/iter 405.03896151483366 ns/iter 0.99
JSON_Parse_1 4593.246569133165 ns/iter 4488.046839248152 ns/iter 1.02
JSON_Parse_Real 4963.325861472867 ns/iter 5144.450941811035 ns/iter 0.96
JSON_Parse_Decimal 7473.060215605383 ns/iter 7388.36771100586 ns/iter 1.01
JSON_Parse_Schema_ISO_Language 3302008.21596244 ns/iter 3327200.4929577545 ns/iter 0.99
JSON_Parse_Integer 3598.0831569633283 ns/iter 3827.080478517961 ns/iter 0.94
JSON_Parse_String_NonSSO_Plain 3048.6196048883667 ns/iter 3224.935550392454 ns/iter 0.95
JSON_Parse_String_SSO_Plain 2614.0929074632627 ns/iter 2757.679016770515 ns/iter 0.95
JSON_Parse_String_Escape_Heavy 12179.569951697444 ns/iter 12669.800415764008 ns/iter 0.96
JSON_Parse_Object_Short_Keys 7872.575685258977 ns/iter 7831.974592564541 ns/iter 1.01
JSON_Parse_Object_Scalar_Properties 4036.921049297419 ns/iter 3998.7327270026058 ns/iter 1.01
JSON_Parse_Object_Array_Properties 5274.325699687939 ns/iter 5285.98003540513 ns/iter 1.00
JSON_Parse_Object_Object_Properties 5234.958086067361 ns/iter 5260.184427460251 ns/iter 1.00
JSON_Parse_Nested_Containers 34786.19086021617 ns/iter 34925.466314268204 ns/iter 1.00
JSON_From_String_Copy 11.318573248581428 ns/iter 11.313545193171967 ns/iter 1.00
JSON_From_String_Temporary 10.076163147372695 ns/iter 10.356972252535284 ns/iter 0.97
JSON_Number_To_Double 21.723247138289857 ns/iter 22.844398993620246 ns/iter 0.95
JSON_Object_At_Last_Key/8 5.8601060184760545 ns/iter 5.8749598101982725 ns/iter 1.00
JSON_Object_At_Last_Key/32 21.601627123755176 ns/iter 21.815006512318234 ns/iter 0.99
JSON_Object_At_Last_Key/128 87.91662724113164 ns/iter 87.86691366061967 ns/iter 1.00
JSON_Object_At_Last_Key/512 403.24554881312076 ns/iter 402.8702805340803 ns/iter 1.00
JSON_Fast_Hash_Helm_Chart_Lock 61.05858627572005 ns/iter 61.03952297146074 ns/iter 1.00
JSON_Equality_Helm_Chart_Lock 151.21665678832437 ns/iter 150.24961411086198 ns/iter 1.01
JSON_Divisible_By_Decimal 234.7154700254752 ns/iter 234.91227113209868 ns/iter 1.00
JSON_String_Equal/10 5.6108802245844585 ns/iter 5.609991542671502 ns/iter 1.00
JSON_String_Equal/100 6.237588134564268 ns/iter 6.2573325543489835 ns/iter 1.00
JSON_String_Equal_Small_By_Perfect_Hash/10 0.9358885717612072 ns/iter 0.9357451901284131 ns/iter 1.00
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 10.273830955341857 ns/iter 14.624625583250026 ns/iter 0.70
JSON_String_Fast_Hash/10 2.491382307803781 ns/iter 2.4928436596563475 ns/iter 1.00
JSON_String_Fast_Hash/100 2.4911056389991724 ns/iter 2.4917183161032828 ns/iter 1.00
JSON_String_Key_Hash/10 2.4920426361686636 ns/iter 2.6593313683780293 ns/iter 0.94
JSON_String_Key_Hash/100 6.538037629464709 ns/iter 9.024793870726768 ns/iter 0.72
JSON_Object_Defines_Miss_Same_Length 2.6842228533439147 ns/iter 2.651976231552102 ns/iter 1.01
JSON_Object_Defines_Miss_Too_Small 2.711292027924565 ns/iter 2.699695754021409 ns/iter 1.00
JSON_Object_Defines_Miss_Too_Large 3.057697567221359 ns/iter 3.037606272994197 ns/iter 1.01
Pointer_Object_Traverse 28.717168084152018 ns/iter 28.616310016908265 ns/iter 1.00
Pointer_Object_Try_Traverse 30.213836167161503 ns/iter 30.19800159451886 ns/iter 1.00
Pointer_Push_Back_Pointer_To_Weak_Pointer 146.04582980946768 ns/iter 167.26425947809147 ns/iter 0.87
Pointer_Walker_Schema_ISO_Language 1491305.471092029 ns/iter 1527329.9109588808 ns/iter 0.98
Pointer_Maybe_Tracked_Deeply_Nested/0 1254298.4634581313 ns/iter 1247677.9105545518 ns/iter 1.01
Pointer_Maybe_Tracked_Deeply_Nested/1 1591397.7241379714 ns/iter 1602020.622988482 ns/iter 0.99
Pointer_Position_Tracker_Get_Deeply_Nested 599.5916733961441 ns/iter 582.0384449902224 ns/iter 1.03
Schema_Tracker_ISO_Language 4587540.633986863 ns/iter 4700584.304635673 ns/iter 0.98
Schema_Tracker_ISO_Language_To_JSON 16247921.000000175 ns/iter 16958434.904761955 ns/iter 0.96
Schema_Frame_WoT_References 2197650.61919501 ns/iter 2226036.358730191 ns/iter 0.99
Schema_Frame_OMC_References 9617525.958333317 ns/iter 9676910.760563388 ns/iter 0.99
Schema_Frame_OMC_Pointers 18019787.3076924 ns/iter 18404368.351351988 ns/iter 0.98
Schema_Frame_OMC_Locations 8207379.732558103 ns/iter 8364502.096385656 ns/iter 0.98
Schema_Frame_ISO_Language_Locations 42100647.17647095 ns/iter 42784488.529411435 ns/iter 0.98
Schema_Frame_ISO_Language_Root 304.9647880314201 ns/iter 286.25840029790163 ns/iter 1.07
Schema_Frame_KrakenD_References 15281745.84782589 ns/iter 17438843.928571504 ns/iter 0.88
Schema_Frame_KrakenD_Reachable 137822465.59999293 ns/iter 142671172.3999915 ns/iter 0.97
Schema_Frame_ISO_Language_Locations_To_JSON 30842133.13043387 ns/iter 32357239.14285754 ns/iter 0.95
Schema_Frame_Many_Resources_References 137858539.60000056 ns/iter 142940704.40000156 ns/iter 0.96
Schema_Frame_Deeply_Nested_References 11175955.612902872 ns/iter 11723439.533333154 ns/iter 0.95
JSONPath_Descendant_Filter_Nested 1519.0340768911224 ns/iter 1537.318313842659 ns/iter 0.99
URITemplateRouter_Create 24926.993195846866 ns/iter 24257.713021189033 ns/iter 1.03
URITemplateRouter_Match 176.41426753113745 ns/iter 175.76821860896732 ns/iter 1.00
URITemplateRouter_Match_BasePath 205.25065697455878 ns/iter 206.67269765668706 ns/iter 0.99
URITemplateRouterView_Restore 8327.709392911598 ns/iter 7944.140887682161 ns/iter 1.05
URITemplateRouterView_Match 141.73548688476046 ns/iter 141.6929884286031 ns/iter 1.00
URITemplateRouterView_Match_BasePath 162.9025026051858 ns/iter 162.19944961048668 ns/iter 1.00
URITemplateRouterView_Arguments 432.24735904340326 ns/iter 425.4309159168048 ns/iter 1.02
JSONL_Parse_Large 9048427.55844163 ns/iter 8904724.692307843 ns/iter 1.02
JSONL_Parse_Large_GZIP 9222676.013157643 ns/iter 9060142.831168752 ns/iter 1.02
JSONLD_Catalog_Annotation_List_Populate 596001.9830508365 ns/iter 587421.4277360146 ns/iter 1.01
JSONLD_Catalog_Materialize 3469484.9154228074 ns/iter 3627378.190721597 ns/iter 0.96
HTML_Build_Table_100000 37991921.33333267 ns/iter 38547205.66666635 ns/iter 0.99
HTML_Render_Table_100000 1958814.8356941408 ns/iter 1959854.7920227726 ns/iter 1.00
Markdown_To_HTML_Realistic_Document 4200869.403614474 ns/iter 14465108.979590824 ns/iter 0.29
Markdown_To_HTML_Pathological 13021037.851851141 ns/iter 56741281.333330564 ns/iter 0.23
Markdown_To_HTML_Short_Descriptions 559.6310002242714 ns/iter 2172.2403713433223 ns/iter 0.26
GZIP_Compress_ISO_Language_Set_3_Locations 37498322.26315532 ns/iter 37476840.15789482 ns/iter 1.00
GZIP_Decompress_ISO_Language_Set_3_Locations 5140480.419117587 ns/iter 5191759.440298375 ns/iter 0.99
GZIP_Decompress_Default_Level_ISO_Language_Set_3_Locations 7100101.816326528 ns/iter 7158894.540815922 ns/iter 0.99
GZIP_Decompress_Stream_Default_Level_ISO_Language_Set_3_Locations 9089995.623376332 ns/iter 9197754.239999842 ns/iter 0.99
GZIP_Compress_ISO_Language_Set_3_Schema 2209113.5236593746 ns/iter 2206179.9053627206 ns/iter 1.00
GZIP_Decompress_ISO_Language_Set_3_Schema 428320.93646918 ns/iter 424993.63250456966 ns/iter 1.01
JOSE_VerifySignature_RS256 47035.99711196142 ns/iter 47655.533405682385 ns/iter 0.99
JOSE_VerifySignature_ES512 1820163.554123712 ns/iter 1790580.6301019203 ns/iter 1.02
CRYPTO_CRC32_Large_JSONL 101784.30572507484 ns/iter 101763.48605056683 ns/iter 1.00

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/gcc)

Details
Benchmark suite Current: 6a8f25b Previous: 475302c Ratio
CRYPTO_CRC32_Large_JSONL 114717.96729285318 ns/iter 106258.21777515441 ns/iter 1.08
JOSE_VerifySignature_RS256 24586.801550008684 ns/iter 22419.501340829192 ns/iter 1.10
JOSE_VerifySignature_ES512 649044.9276437893 ns/iter 599746.0591216267 ns/iter 1.08
GZIP_Compress_ISO_Language_Set_3_Locations 31892265.727272864 ns/iter 32373001.739131268 ns/iter 0.99
GZIP_Decompress_ISO_Language_Set_3_Locations 5632494.088709633 ns/iter 5214524.798507635 ns/iter 1.08
GZIP_Decompress_Default_Level_ISO_Language_Set_3_Locations 7554025.215053463 ns/iter 7228079.391752286 ns/iter 1.05
GZIP_Decompress_Stream_Default_Level_ISO_Language_Set_3_Locations 10194487.0144924 ns/iter 10213972.797101712 ns/iter 1.00
GZIP_Compress_ISO_Language_Set_3_Schema 2298053.4934210307 ns/iter 2083482.06845242 ns/iter 1.10
GZIP_Decompress_ISO_Language_Set_3_Schema 416314.89300656517 ns/iter 436681.6895261984 ns/iter 0.95
Markdown_To_HTML_Realistic_Document 4998298.900709382 ns/iter 13117734.981480883 ns/iter 0.38
Markdown_To_HTML_Pathological 13472414.23529371 ns/iter 50240038.23077167 ns/iter 0.27
Markdown_To_HTML_Short_Descriptions 578.550534699503 ns/iter 1943.5842459678815 ns/iter 0.30
HTML_Build_Table_100000 36405243.052633144 ns/iter 38964360.27777857 ns/iter 0.93
HTML_Render_Table_100000 2316594.243243198 ns/iter 2122688.7228916655 ns/iter 1.09
JSONLD_Catalog_Annotation_List_Populate 716643.6890244076 ns/iter 703799.8705036017 ns/iter 1.02
JSONLD_Catalog_Materialize 4140913.9444442783 ns/iter 4420089.118055397 ns/iter 0.94
JSONL_Parse_Large 9868284.621621273 ns/iter 9991335.371428737 ns/iter 0.99
JSONL_Parse_Large_GZIP 9618427.624999981 ns/iter 10205756.558823295 ns/iter 0.94
URITemplateRouter_Create 20709.839978998763 ns/iter 21247.32607380516 ns/iter 0.97
URITemplateRouter_Match 166.95603832737956 ns/iter 158.35316527136771 ns/iter 1.05
URITemplateRouter_Match_BasePath 191.46768285274715 ns/iter 188.26617066521405 ns/iter 1.02
URITemplateRouterView_Restore 9785.770130244933 ns/iter 8515.91798750441 ns/iter 1.15
URITemplateRouterView_Match 126.50570262229253 ns/iter 124.59743963124966 ns/iter 1.02
URITemplateRouterView_Match_BasePath 142.24164536333288 ns/iter 143.14602593669434 ns/iter 0.99
URITemplateRouterView_Arguments 464.6481495793524 ns/iter 486.20343852070545 ns/iter 0.96
JSONPath_Descendant_Filter_Nested 2148.0292664764393 ns/iter 1757.2643839648595 ns/iter 1.22
Schema_Frame_WoT_References 2352402.8020134536 ns/iter 2314123.7565789353 ns/iter 1.02
Schema_Frame_OMC_References 11278517.419354316 ns/iter 12262848.363635922 ns/iter 0.92
Schema_Frame_OMC_Pointers 21218702.12121304 ns/iter 23447960.29999922 ns/iter 0.90
Schema_Frame_OMC_Locations 9753298.972221892 ns/iter 10908253.939393573 ns/iter 0.89
Schema_Frame_ISO_Language_Locations 46825853.40000287 ns/iter 45821448.85714407 ns/iter 1.02
Schema_Frame_ISO_Language_Root 272.64449216814955 ns/iter 296.84446395328996 ns/iter 0.92
Schema_Frame_KrakenD_References 20200252.583333306 ns/iter 18471040.289473183 ns/iter 1.09
Schema_Frame_KrakenD_Reachable 112372270.71428283 ns/iter 130565430.9999909 ns/iter 0.86
Schema_Frame_ISO_Language_Locations_To_JSON 34228759.50000162 ns/iter 34710378.54999963 ns/iter 0.99
Schema_Frame_Many_Resources_References 156248042.24999878 ns/iter 148778096.749993 ns/iter 1.05
Schema_Frame_Deeply_Nested_References 12216829.089286055 ns/iter 12687977.272727577 ns/iter 0.96
Pointer_Object_Traverse 26.823060279896463 ns/iter 24.85592223953267 ns/iter 1.08
Pointer_Object_Try_Traverse 25.995314833700004 ns/iter 24.524903179869252 ns/iter 1.06
Pointer_Push_Back_Pointer_To_Weak_Pointer 142.28663355202218 ns/iter 132.73114514159366 ns/iter 1.07
Pointer_Walker_Schema_ISO_Language 1717727.2444987944 ns/iter 1612872.9714285412 ns/iter 1.07
Pointer_Maybe_Tracked_Deeply_Nested/0 1254309.5464285973 ns/iter 1243969.5396825834 ns/iter 1.01
Pointer_Maybe_Tracked_Deeply_Nested/1 1731462.2246912515 ns/iter 1964479.747899157 ns/iter 0.88
Pointer_Position_Tracker_Get_Deeply_Nested 717.525635269485 ns/iter 606.8735042186246 ns/iter 1.18
Schema_Tracker_ISO_Language 5044724.931297542 ns/iter 5074224.694029952 ns/iter 0.99
Schema_Tracker_ISO_Language_To_JSON 15785250.000000259 ns/iter 16737963.674418466 ns/iter 0.94
JSON_Array_Of_Objects_Unique 458.08027806233997 ns/iter 464.98223665207075 ns/iter 0.99
JSON_Parse_1 5107.779211915551 ns/iter 5572.201078960372 ns/iter 0.92
JSON_Parse_Real 5301.426239770382 ns/iter 5550.485241900433 ns/iter 0.96
JSON_Parse_Decimal 9153.28414780087 ns/iter 10336.383273510959 ns/iter 0.89
JSON_Parse_Schema_ISO_Language 3771134.5760871125 ns/iter 3825441.8663100637 ns/iter 0.99
JSON_Parse_Integer 3837.479884615342 ns/iter 3940.9519644757534 ns/iter 0.97
JSON_Parse_String_NonSSO_Plain 3563.307940157758 ns/iter 3610.115323019467 ns/iter 0.99
JSON_Parse_String_SSO_Plain 2949.496005651093 ns/iter 3024.0277090612108 ns/iter 0.98
JSON_Parse_String_Escape_Heavy 16954.989212168715 ns/iter 16542.191089626966 ns/iter 1.02
JSON_Parse_Object_Short_Keys 8846.601829045243 ns/iter 8888.096828942043 ns/iter 1.00
JSON_Parse_Object_Scalar_Properties 4505.231040722666 ns/iter 4509.26307613609 ns/iter 1.00
JSON_Parse_Object_Array_Properties 6762.73992077342 ns/iter 6750.5263999229655 ns/iter 1.00
JSON_Parse_Object_Object_Properties 6642.738391608873 ns/iter 6657.155262533448 ns/iter 1.00
JSON_Parse_Nested_Containers 40134.633117813006 ns/iter 40267.216825980475 ns/iter 1.00
JSON_From_String_Copy 9.642669588366479 ns/iter 9.456293054612013 ns/iter 1.02
JSON_From_String_Temporary 8.039043566118377 ns/iter 7.6464952236670705 ns/iter 1.05
JSON_Number_To_Double 21.141627437362374 ns/iter 19.360035353002385 ns/iter 1.09
JSON_Object_At_Last_Key/8 4.193152923186672 ns/iter 5.637844722741771 ns/iter 0.74
JSON_Object_At_Last_Key/32 13.403330721326483 ns/iter 21.524024160620638 ns/iter 0.62
JSON_Object_At_Last_Key/128 47.22098714259576 ns/iter 87.9511658149745 ns/iter 0.54
JSON_Object_At_Last_Key/512 249.98905166084802 ns/iter 393.1954923633387 ns/iter 0.64
JSON_Fast_Hash_Helm_Chart_Lock 80.71998739167239 ns/iter 76.26184298172382 ns/iter 1.06
JSON_Equality_Helm_Chart_Lock 168.47604040964615 ns/iter 154.44684503997294 ns/iter 1.09
JSON_Divisible_By_Decimal 265.9285254270451 ns/iter 274.4105461961583 ns/iter 0.97
JSON_String_Equal/10 5.365286432025236 ns/iter 5.694450542391807 ns/iter 0.94
JSON_String_Equal/100 6.068742244034112 ns/iter 6.313199153236477 ns/iter 0.96
JSON_String_Equal_Small_By_Perfect_Hash/10 0.7090561240775417 ns/iter 0.6240913232026215 ns/iter 1.14
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 18.195049911597575 ns/iter 25.202676184318097 ns/iter 0.72
JSON_String_Fast_Hash/10 3.1975571441478654 ns/iter 3.1626528264684937 ns/iter 1.01
JSON_String_Fast_Hash/100 3.180795132813022 ns/iter 3.15258999594179 ns/iter 1.01
JSON_String_Key_Hash/10 1.758118080893411 ns/iter 1.2475286391600349 ns/iter 1.41
JSON_String_Key_Hash/100 14.757762687307736 ns/iter 12.450196774145532 ns/iter 1.19
JSON_Object_Defines_Miss_Same_Length 3.1682199110391105 ns/iter 3.125283629705322 ns/iter 1.01
JSON_Object_Defines_Miss_Too_Small 3.1803469811857594 ns/iter 3.4285160387672984 ns/iter 0.93
JSON_Object_Defines_Miss_Too_Large 3.1665662503244034 ns/iter 3.1284869387726593 ns/iter 1.01
Regex_Lower_S_Or_Upper_S_Asterisk 2.3736439241889995 ns/iter 2.1024973004712124 ns/iter 1.13
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 2.3271181135209043 ns/iter 2.1111104936892517 ns/iter 1.10
Regex_Period_Asterisk 2.285883694349009 ns/iter 2.024985278751995 ns/iter 1.13
Regex_Group_Period_Asterisk_Group 2.374250756167524 ns/iter 2.0243181318954275 ns/iter 1.17
Regex_Period_Plus 2.376104861040809 ns/iter 2.102142483131925 ns/iter 1.13
Regex_Period 2.2853812070725232 ns/iter 2.103066716584614 ns/iter 1.09
Regex_Caret_Period_Plus_Dollar 2.29500901640027 ns/iter 2.024231285153594 ns/iter 1.13
Regex_Caret_Group_Period_Plus_Group_Dollar 2.3730158000679986 ns/iter 2.027684294808045 ns/iter 1.17
Regex_Caret_Period_Asterisk_Dollar 2.3741250294038783 ns/iter 2.10010438118966 ns/iter 1.13
Regex_Caret_Group_Period_Asterisk_Group_Dollar 2.3198535552807185 ns/iter 2.1001354311440794 ns/iter 1.10
Regex_Caret_X_Hyphen 7.211096030474696 ns/iter 6.39242168374626 ns/iter 1.13
Regex_Period_Md_Dollar 34.13262696265433 ns/iter 45.93831283574701 ns/iter 0.74
Regex_Caret_Slash_Period_Asterisk 8.047211733836509 ns/iter 6.780249808485514 ns/iter 1.19
Regex_Caret_Period_Range_Dollar 4.056450450742502 ns/iter 2.879847260359962 ns/iter 1.41
Regex_Nested_Backtrack 41.9978888437836 ns/iter 51.56810585362778 ns/iter 0.81

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (windows/msvc)

Details
Benchmark suite Current: 6a8f25b Previous: 5e928fb Ratio
Regex_Lower_S_Or_Upper_S_Asterisk 2.487383457600803 ns/iter 5.1039460000004055 ns/iter 0.49
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 2.506211071428359 ns/iter 5.042475000000195 ns/iter 0.50
Regex_Period_Asterisk 2.480608214285748 ns/iter 5.035184999999842 ns/iter 0.49
Regex_Group_Period_Asterisk_Group 2.4060006669575524 ns/iter 5.02187900000024 ns/iter 0.48
Regex_Period_Plus 2.4876696428573757 ns/iter 4.8795395198202645 ns/iter 0.51
Regex_Period 2.4508992857144154 ns/iter 4.802858035714357 ns/iter 0.51
Regex_Caret_Period_Plus_Dollar 2.4547546428574862 ns/iter 4.73910493409351 ns/iter 0.52
Regex_Caret_Group_Period_Plus_Group_Dollar 2.594988571428709 ns/iter 4.863954666264554 ns/iter 0.53
Regex_Caret_Period_Asterisk_Dollar 2.5165553571428387 ns/iter 5.026313392857418 ns/iter 0.50
Regex_Caret_Group_Period_Asterisk_Group_Dollar 2.8446092385313553 ns/iter 5.108699999999544 ns/iter 0.56
Regex_Caret_X_Hyphen 6.633111607142591 ns/iter 8.166353794643351 ns/iter 0.81
Regex_Period_Md_Dollar 29.55281249999838 ns/iter 48.25522875570059 ns/iter 0.61
Regex_Caret_Slash_Period_Asterisk 6.427567000000636 ns/iter 7.923354910714307 ns/iter 0.81
Regex_Caret_Period_Range_Dollar 2.964860267857107 ns/iter 5.916300000000092 ns/iter 0.50
Regex_Nested_Backtrack 40.12878125000441 ns/iter 65.29049107142677 ns/iter 0.61
JSON_Array_Of_Objects_Unique 551.5125892857092 ns/iter 575.4264285713922 ns/iter 0.96
JSON_Parse_1 7576.999209825541 ns/iter 8819.091071428784 ns/iter 0.86
JSON_Parse_Real 14663.473862549577 ns/iter 16003.752232143548 ns/iter 0.92
JSON_Parse_Decimal 10582.014508928594 ns/iter 11746.68750000052 ns/iter 0.90
JSON_Parse_Schema_ISO_Language 8827902.22222209 ns/iter 7460158.888889307 ns/iter 1.18
JSON_Parse_Integer 5195.258377944516 ns/iter 6122.89821428545 ns/iter 0.85
JSON_Parse_String_NonSSO_Plain 6469.220535714319 ns/iter 7864.393973214336 ns/iter 0.82
JSON_Parse_String_SSO_Plain 2723.9484268084852 ns/iter 3828.3622707815507 ns/iter 0.71
JSON_Parse_String_Escape_Heavy 23336.475039340068 ns/iter 21876.469734778806 ns/iter 1.07
JSON_Parse_Object_Short_Keys 10184.770312500646 ns/iter 13034.398730362733 ns/iter 0.78
JSON_Parse_Object_Scalar_Properties 5065.958999999793 ns/iter 6706.255580357328 ns/iter 0.76
JSON_Parse_Object_Array_Properties 9072.749999999629 ns/iter 11480.295312500388 ns/iter 0.79
JSON_Parse_Object_Object_Properties 9013.751724322588 ns/iter 11566.571874999987 ns/iter 0.78
JSON_Parse_Nested_Containers 66856.70535713737 ns/iter 80127.58928571832 ns/iter 0.83
JSON_From_String_Copy 47.957050177618434 ns/iter 63.56633928571601 ns/iter 0.75
JSON_From_String_Temporary 56.109219999996185 ns/iter 58.15980357142893 ns/iter 0.96
JSON_Number_To_Double 86.69520089285804 ns/iter 120.90251785714656 ns/iter 0.72
JSON_Object_At_Last_Key/8 7.431808035714178 ns/iter 7.626958928571221 ns/iter 0.97
JSON_Object_At_Last_Key/32 18.645004785860817 ns/iter 23.06760242112068 ns/iter 0.81
JSON_Object_At_Last_Key/128 92.26219866071972 ns/iter 90.33765668135663 ns/iter 1.02
JSON_Object_At_Last_Key/512 332.1487219377254 ns/iter 425.51737499998416 ns/iter 0.78
JSON_Fast_Hash_Helm_Chart_Lock 84.55654017856925 ns/iter 104.8415468750008 ns/iter 0.81
JSON_Equality_Helm_Chart_Lock 218.882624999992 ns/iter 209.28948619244085 ns/iter 1.05
JSON_Divisible_By_Decimal 249.48974999996867 ns/iter 306.8798228928675 ns/iter 0.81
JSON_String_Equal/10 9.327727190501047 ns/iter 10.454948437500278 ns/iter 0.89
JSON_String_Equal/100 12.531262499998823 ns/iter 11.722001785714603 ns/iter 1.07
JSON_String_Equal_Small_By_Perfect_Hash/10 1.268912053571317 ns/iter 2.5305657142857694 ns/iter 0.50
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 9.491310225485275 ns/iter 15.127178571429567 ns/iter 0.63
JSON_String_Fast_Hash/10 4.115518534134867 ns/iter 6.711316071428846 ns/iter 0.61
JSON_String_Fast_Hash/100 4.343773579185492 ns/iter 6.78632924107081 ns/iter 0.64
JSON_String_Key_Hash/10 3.52529983824125 ns/iter 5.336455000000342 ns/iter 0.66
JSON_String_Key_Hash/100 8.379744605447462 ns/iter 11.901548214285842 ns/iter 0.70
JSON_Object_Defines_Miss_Same_Length 4.819852912544593 ns/iter 4.726418460876721 ns/iter 1.02
JSON_Object_Defines_Miss_Too_Small 4.934933716372249 ns/iter 4.721733170696974 ns/iter 1.05
JSON_Object_Defines_Miss_Too_Large 5.007461607143731 ns/iter 4.722431930184039 ns/iter 1.06
Pointer_Object_Traverse 41.40770501885378 ns/iter 70.67049107143397 ns/iter 0.59
Pointer_Object_Try_Traverse 40.856069743611236 ns/iter 74.36635714285497 ns/iter 0.55
Pointer_Push_Back_Pointer_To_Weak_Pointer 171.42761160714923 ns/iter 172.77585755194696 ns/iter 0.99
Pointer_Walker_Schema_ISO_Language 10279567.187501116 ns/iter 11209951.562499931 ns/iter 0.92
Pointer_Maybe_Tracked_Deeply_Nested/0 2119644.6874999 ns/iter 2485093.9393938156 ns/iter 0.85
Pointer_Maybe_Tracked_Deeply_Nested/1 4295850.837988253 ns/iter 3806447.4860330042 ns/iter 1.13
Pointer_Position_Tracker_Get_Deeply_Nested 580.8232142858114 ns/iter 546.2145089285235 ns/iter 1.06
Schema_Tracker_ISO_Language 10582304.687499544 ns/iter 10519296.87499964 ns/iter 1.01
Schema_Tracker_ISO_Language_To_JSON 49682559.99999656 ns/iter 63422011.111103736 ns/iter 0.78
Schema_Frame_WoT_References 4610930.872482738 ns/iter 5645503.999999165 ns/iter 0.82
Schema_Frame_OMC_References 20477270.588233914 ns/iter 23408979.999999244 ns/iter 0.87
Schema_Frame_OMC_Pointers 38852626.31579161 ns/iter 44627806.24999852 ns/iter 0.87
Schema_Frame_OMC_Locations 17539575.609755892 ns/iter 20050748.64864951 ns/iter 0.87
Schema_Frame_ISO_Language_Locations 70225266.66666333 ns/iter 79232900.00000331 ns/iter 0.89
Schema_Frame_ISO_Language_Root 1675.79657870759 ns/iter 2195.690263047011 ns/iter 0.76
Schema_Frame_KrakenD_References 43137333.33333403 ns/iter 40677883.33333687 ns/iter 1.06
Schema_Frame_KrakenD_Reachable 184807749.99997607 ns/iter 256792266.6666315 ns/iter 0.72
Schema_Frame_ISO_Language_Locations_To_JSON 139783125.0000081 ns/iter 161027574.99999142 ns/iter 0.87
Schema_Frame_Many_Resources_References 516136599.99998164 ns/iter 702780499.9999034 ns/iter 0.73
Schema_Frame_Deeply_Nested_References 17072320.51282039 ns/iter 21646208.000001937 ns/iter 0.79
JSONPath_Descendant_Filter_Nested 1650.1120869784854 ns/iter 2450.3155688439856 ns/iter 0.67
URITemplateRouter_Create 35917.74209388966 ns/iter 41847.73699753401 ns/iter 0.86
URITemplateRouter_Match 242.61321428570326 ns/iter 235.31940624998524 ns/iter 1.03
URITemplateRouter_Match_BasePath 273.73434492255626 ns/iter 268.729561103977 ns/iter 1.02
URITemplateRouterView_Restore 18331.208314359206 ns/iter 33408.65743469115 ns/iter 0.55
URITemplateRouterView_Match 188.79609721393243 ns/iter 183.70617524818152 ns/iter 1.03
URITemplateRouterView_Match_BasePath 213.80187623230782 ns/iter 209.54893750001702 ns/iter 1.02
URITemplateRouterView_Arguments 421.6332109694894 ns/iter 538.2802678572115 ns/iter 0.78
JSONL_Parse_Large 24914907.142857604 ns/iter 32585814.285712764 ns/iter 0.76
JSONL_Parse_Large_GZIP 22488368.750000376 ns/iter 31674759.09091102 ns/iter 0.71
JSONLD_Catalog_Annotation_List_Populate 2617305.714285781 ns/iter 2947489.8305085455 ns/iter 0.89
JSONLD_Catalog_Materialize 6356421.428571529 ns/iter 7833203.33333298 ns/iter 0.81
HTML_Build_Table_100000 86193266.66666894 ns/iter 66707127.27272778 ns/iter 1.29
HTML_Render_Table_100000 12339553.571428448 ns/iter 7634798.888889489 ns/iter 1.62
Markdown_To_HTML_Realistic_Document 4314060.389610297 ns/iter 5657159.821428845 ns/iter 0.76
Markdown_To_HTML_Pathological 15654142.222221404 ns/iter 17720063.414633 ns/iter 0.88
Markdown_To_HTML_Short_Descriptions 534.7091964285004 ns/iter 688.1186607142606 ns/iter 0.78
GZIP_Compress_ISO_Language_Set_3_Locations 30502762.50000176 ns/iter 38018294.73684392 ns/iter 0.80
GZIP_Decompress_ISO_Language_Set_3_Locations 11178023.437500073 ns/iter 9690174.66666628 ns/iter 1.15
GZIP_Decompress_Default_Level_ISO_Language_Set_3_Locations 12174762.499999555 ns/iter 12012266.071429119 ns/iter 1.01
GZIP_Decompress_Stream_Default_Level_ISO_Language_Set_3_Locations 16983480.48780478 ns/iter 15498414.63414706 ns/iter 1.10
GZIP_Compress_ISO_Language_Set_3_Schema 2048374.4927537043 ns/iter 2315058.4374999283 ns/iter 0.88
GZIP_Decompress_ISO_Language_Set_3_Schema 674671.9642857256 ns/iter 626487.2321427868 ns/iter 1.08
JOSE_VerifySignature_RS256 19249.953124583088 ns/iter 21638.578124999698 ns/iter 0.89
JOSE_VerifySignature_ES512 965995.4484606516 ns/iter 1382522.2891565303 ns/iter 0.70
CRYPTO_CRC32_Large_JSONL 49618.553571428536 ns/iter 103197.43749999334 ns/iter 0.48

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (macos/llvm)

Details
Benchmark suite Current: 6a8f25b Previous: 475302c Ratio
Regex_Lower_S_Or_Upper_S_Asterisk 2.3013019483754102 ns/iter 2.0662817614230153 ns/iter 1.11
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 2.3584234516331444 ns/iter 2.1974881823459387 ns/iter 1.07
Regex_Period_Asterisk 2.3989564815129683 ns/iter 2.269154915848098 ns/iter 1.06
Regex_Group_Period_Asterisk_Group 2.411556061892736 ns/iter 2.3445000980489956 ns/iter 1.03
Regex_Period_Plus 2.5660204216448763 ns/iter 2.763313553179142 ns/iter 0.93
Regex_Period 2.6762063604940733 ns/iter 2.8740134527030357 ns/iter 0.93
Regex_Caret_Period_Plus_Dollar 2.8595072710928076 ns/iter 2.5293082308373736 ns/iter 1.13
Regex_Caret_Group_Period_Plus_Group_Dollar 2.767955432503619 ns/iter 2.9572845027731627 ns/iter 0.94
Regex_Caret_Period_Asterisk_Dollar 2.48796601504765 ns/iter 2.348360020922432 ns/iter 1.06
Regex_Caret_Group_Period_Asterisk_Group_Dollar 2.5967087186062963 ns/iter 2.496058555781547 ns/iter 1.04
Regex_Caret_X_Hyphen 7.310216741436646 ns/iter 7.1122538775615 ns/iter 1.03
Regex_Period_Md_Dollar 20.902493208503618 ns/iter 23.375254373740432 ns/iter 0.89
Regex_Caret_Slash_Period_Asterisk 5.7184116023832825 ns/iter 5.870711866901464 ns/iter 0.97
Regex_Caret_Period_Range_Dollar 3.0857108432588416 ns/iter 3.2090059785675877 ns/iter 0.96
Regex_Nested_Backtrack 33.06479755545244 ns/iter 36.99347374024539 ns/iter 0.89
JSON_Array_Of_Objects_Unique 413.3751984860077 ns/iter 466.5500986634439 ns/iter 0.89
JSON_Parse_1 3384.2942105684974 ns/iter 5035.531545344818 ns/iter 0.67
JSON_Parse_Real 6613.87686859805 ns/iter 6069.6298607214785 ns/iter 1.09
JSON_Parse_Decimal 6317.290476770082 ns/iter 6440.128019068253 ns/iter 0.98
JSON_Parse_Schema_ISO_Language 2494160.203448324 ns/iter 3723869.565217381 ns/iter 0.67
JSON_Parse_Integer 3478.094955350955 ns/iter 5696.652701576745 ns/iter 0.61
JSON_Parse_String_NonSSO_Plain 4049.3363158003895 ns/iter 6048.821954040321 ns/iter 0.67
JSON_Parse_String_SSO_Plain 1977.5915207746248 ns/iter 2884.0718853208864 ns/iter 0.69
JSON_Parse_String_Escape_Heavy 19159.78845137703 ns/iter 30053.85541158961 ns/iter 0.64
JSON_Parse_Object_Short_Keys 7608.285060527867 ns/iter 8966.247764780974 ns/iter 0.85
JSON_Parse_Object_Scalar_Properties 2946.1890647188775 ns/iter 3758.158699002499 ns/iter 0.78
JSON_Parse_Object_Array_Properties 3618.0057808701695 ns/iter 5055.841916540712 ns/iter 0.72
JSON_Parse_Object_Object_Properties 3786.0992103783183 ns/iter 4752.656852375413 ns/iter 0.80
JSON_Parse_Nested_Containers 26708.84933832413 ns/iter 32828.949544137206 ns/iter 0.81
JSON_From_String_Copy 11.340256386554632 ns/iter 16.116939866112325 ns/iter 0.70
JSON_From_String_Temporary 6.753221430638745 ns/iter 9.833953571038087 ns/iter 0.69
JSON_Number_To_Double 35.050884676605996 ns/iter 46.83136462970223 ns/iter 0.75
JSON_Object_At_Last_Key/8 4.72739669217559 ns/iter 6.254827499999465 ns/iter 0.76
JSON_Object_At_Last_Key/32 12.986794681676914 ns/iter 18.31273538163029 ns/iter 0.71
JSON_Object_At_Last_Key/128 58.753520361313 ns/iter 76.08655608911903 ns/iter 0.77
JSON_Object_At_Last_Key/512 231.96860961869544 ns/iter 287.5534068024399 ns/iter 0.81
JSON_Fast_Hash_Helm_Chart_Lock 64.0229913483878 ns/iter 90.63517127098481 ns/iter 0.71
JSON_Equality_Helm_Chart_Lock 186.53338976250961 ns/iter 266.12781745473825 ns/iter 0.70
JSON_Divisible_By_Decimal 196.79737333416566 ns/iter 277.1545949324511 ns/iter 0.71
JSON_String_Equal/10 7.70838768289221 ns/iter 10.309697323069457 ns/iter 0.75
JSON_String_Equal/100 7.142530695873271 ns/iter 9.320872620944899 ns/iter 0.77
JSON_String_Equal_Small_By_Perfect_Hash/10 0.36453880642994085 ns/iter 0.4407687394790088 ns/iter 0.83
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 3.2806166685145595 ns/iter 5.009361592680227 ns/iter 0.65
JSON_String_Fast_Hash/10 2.4268298452220978 ns/iter 3.421266078069105 ns/iter 0.71
JSON_String_Fast_Hash/100 2.1939755343151046 ns/iter 3.0731496842167774 ns/iter 0.71
JSON_String_Key_Hash/10 1.891167511571638 ns/iter 2.728739103484092 ns/iter 0.69
JSON_String_Key_Hash/100 2.6367204213795454 ns/iter 3.5818573482532083 ns/iter 0.74
JSON_Object_Defines_Miss_Same_Length 3.5493602342707025 ns/iter 3.5037587569372457 ns/iter 1.01
JSON_Object_Defines_Miss_Too_Small 3.165949931757891 ns/iter 4.107843105514397 ns/iter 0.77
JSON_Object_Defines_Miss_Too_Large 3.0953330975548226 ns/iter 4.507963965720521 ns/iter 0.69
Pointer_Object_Traverse 22.026691451773704 ns/iter 27.623546336866617 ns/iter 0.80
Pointer_Object_Try_Traverse 49.759188356531965 ns/iter 50.012016464677856 ns/iter 0.99
Pointer_Push_Back_Pointer_To_Weak_Pointer 163.10239434228419 ns/iter 202.06377186778735 ns/iter 0.81
Pointer_Walker_Schema_ISO_Language 1657518.1297070663 ns/iter 2290959.1876832885 ns/iter 0.72
Pointer_Maybe_Tracked_Deeply_Nested/0 903405.5559999008 ns/iter 1331019.7860618788 ns/iter 0.68
Pointer_Maybe_Tracked_Deeply_Nested/1 1246761.1955778822 ns/iter 1709739.4471362461 ns/iter 0.73
Pointer_Position_Tracker_Get_Deeply_Nested 386.14169939913995 ns/iter 550.6857344100866 ns/iter 0.70
Schema_Tracker_ISO_Language 3207873.0867348374 ns/iter 4280716.57754049 ns/iter 0.75
Schema_Tracker_ISO_Language_To_JSON 13290544.534482189 ns/iter 13719385.037036233 ns/iter 0.97
Schema_Frame_WoT_References 2468329.1356589245 ns/iter 2586349.1228073253 ns/iter 0.95
Schema_Frame_OMC_References 10686424.603172494 ns/iter 10022288.043478182 ns/iter 1.07
Schema_Frame_OMC_Pointers 22038654.58064654 ns/iter 21225185.81080766 ns/iter 1.04
Schema_Frame_OMC_Locations 9969643.345238226 ns/iter 8556101.744184796 ns/iter 1.17
Schema_Frame_ISO_Language_Locations 26301136.680003766 ns/iter 22087100.249997605 ns/iter 1.19
Schema_Frame_ISO_Language_Root 114.84441268147313 ns/iter 132.040019457674 ns/iter 0.87
Schema_Frame_KrakenD_References 15652028.086957097 ns/iter 26960443.702702485 ns/iter 0.58
Schema_Frame_KrakenD_Reachable 161148656.5000746 ns/iter 225427520.74997452 ns/iter 0.71
Schema_Frame_ISO_Language_Locations_To_JSON 27848421.29629531 ns/iter 25677092.961534355 ns/iter 1.08
Schema_Frame_Many_Resources_References 145548493.1666433 ns/iter 163990992.99997035 ns/iter 0.89
Schema_Frame_Deeply_Nested_References 15017692.073170997 ns/iter 16233593.023259323 ns/iter 0.93
JSONPath_Descendant_Filter_Nested 1830.3845299881896 ns/iter 1754.9475984587093 ns/iter 1.04
URITemplateRouter_Create 22447.055047024944 ns/iter 28773.08519534507 ns/iter 0.78
URITemplateRouter_Match 209.89786426321413 ns/iter 245.46420190930652 ns/iter 0.86
URITemplateRouter_Match_BasePath 273.74882349200067 ns/iter 216.12880905870367 ns/iter 1.27
URITemplateRouterView_Restore 15941.314168044119 ns/iter 14513.792258475929 ns/iter 1.10
URITemplateRouterView_Match 153.19747101351436 ns/iter 163.87902975835155 ns/iter 0.93
URITemplateRouterView_Match_BasePath 178.67754413161842 ns/iter 168.46115134490606 ns/iter 1.06
URITemplateRouterView_Arguments 727.2140798372192 ns/iter 625.6055479634382 ns/iter 1.16
JSONL_Parse_Large 10075698.170730792 ns/iter 9007942.837208014 ns/iter 1.12
JSONL_Parse_Large_GZIP 7317064.134831321 ns/iter 8063759.979165752 ns/iter 0.91
JSONLD_Catalog_Annotation_List_Populate 557625.3750000433 ns/iter 578567.484112087 ns/iter 0.96
JSONLD_Catalog_Materialize 3958824.5153579474 ns/iter 2330492.0932472977 ns/iter 1.70
HTML_Build_Table_100000 43910298.210520476 ns/iter 26205623.24999772 ns/iter 1.68
HTML_Render_Table_100000 2454058.9779412453 ns/iter 1583351.8279301424 ns/iter 1.55
Markdown_To_HTML_Realistic_Document 4383619.729884001 ns/iter 10339965.081080614 ns/iter 0.42
Markdown_To_HTML_Pathological 18163019.28358113 ns/iter 42626219.39998705 ns/iter 0.43
Markdown_To_HTML_Short_Descriptions 377.65676723439856 ns/iter 1201.1199023758911 ns/iter 0.31
GZIP_Compress_ISO_Language_Set_3_Locations 45765141.22221751 ns/iter 27020630.208331417 ns/iter 1.69
GZIP_Decompress_ISO_Language_Set_3_Locations 3998939.226520387 ns/iter 2834619.773278539 ns/iter 1.41
GZIP_Decompress_Default_Level_ISO_Language_Set_3_Locations 5665336.669999306 ns/iter 4275918.147929194 ns/iter 1.32
GZIP_Decompress_Stream_Default_Level_ISO_Language_Set_3_Locations 7394512.593750827 ns/iter 5117307.079999591 ns/iter 1.45
GZIP_Compress_ISO_Language_Set_3_Schema 2458991.425992412 ns/iter 1609720.990654538 ns/iter 1.53
GZIP_Decompress_ISO_Language_Set_3_Schema 429988.3495089477 ns/iter 282902.03918437153 ns/iter 1.52
JOSE_VerifySignature_RS256 28748.481501930506 ns/iter 22725.686338252883 ns/iter 1.27
JOSE_VerifySignature_ES512 1387728.8017543005 ns/iter 947962.588652638 ns/iter 1.46
CRYPTO_CRC32_Large_JSONL 30147.306711495923 ns/iter 19797.518620613973 ns/iter 1.52

This comment was automatically generated by workflow using github-action-benchmark.

@jviotti
jviotti force-pushed the no-cmark-gfm branch 2 times, most recently from 72406ca to e71ae05 Compare September 14, 2026 23:57
Comment thread src/core/markdown/characters.h Outdated
// Decode the codepoint that starts the input, returning its length in bytes,
// or zero when the input is empty or does not start with a well-formed
// sequence
inline auto decode_utf8(const std::string_view input,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Can't we use the Unicode module?

Comment thread src/core/markdown/render.h Outdated

this->written_footnote_index_ = this->footnote_index_;
auto &output{this->output_};
output.append("<a href=\"#fnref-");

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: We should use our own HTML output writer?

@jviotti
jviotti marked this pull request as ready for review September 15, 2026 15:02
@augmentcode

augmentcode Bot commented Sep 15, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR replaces the bundled cmark-gfm dependency with a native Markdown implementation.



Changes:

  • Adds document, block, inline, reference, character, scanner, postprocessing, and HTML-rendering components.
  • Preserves the public markdown_to_html API and its unsafe rendering option.
  • Implements CommonMark/GFM features including tables, task lists, strikethrough, autolinks, and footnotes.
  • Adds output buffering, URL sanitization, HTML filtering, and UTF-8 replacement handling.
  • Removes cmark sources, headers, build integration, and related dependency references.
  • Updates build targets and adds focused Markdown unit, safety, concurrency, and pathological-input tests.
Technical notes: The converter reuses a thread-local document to reduce per-call allocations while retaining per-thread isolation.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/core/markdown/inlines.h Outdated
++write;
}

if (buffer[read] != ' ') {

@augmentcode augmentcode Bot Sep 15, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/core/markdown/inlines.h:453: This treats a raw line ending in buffer[read] as non-space after it has been normalized to ' '. Consequently, a code span containing only two line endings is rendered empty instead of retaining its two normalized spaces, contrary to code-span whitespace normalization.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread src/core/markdown/blocks.h Outdated
set_flag(this->node(item), FLAG_TASK, true);
this->advance_offset(3, false);
set_flag(this->node(item), FLAG_CHECKED,
this->line_.find("[x]") != std::string_view::npos ||

@augmentcode augmentcode Bot Sep 15, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/core/markdown/blocks.h:942: This searches the entire raw item text instead of the validated task marker. An unchecked item such as - [ ] investigate [x] is therefore rendered as checked, even though only the leading marker defines the task state.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread src/core/markdown/render.h Outdated

break;
case NodeType::Strong:
if (nodes[node.parent].type != NodeType::Strong) {

@augmentcode augmentcode Bot Sep 15, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/core/markdown/render.h:595: Suppressing a Strong node whose parent is also Strong discards valid nesting. For example, CommonMark requires ****foo**** to render as <strong><strong>foo</strong></strong>, whereas this emits only one pair of tags.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 85 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/core/markdown/document.h">

<violation number="1" location="src/core/markdown/document.h:135">
P3: When a fresh `StringArena` receives a zero-size allocation, `cursor_ += size` performs pointer arithmetic on `nullptr`, which is undefined behavior. Return before the pointer arithmetic for `size == 0`.</violation>
</file>

<file name="src/core/markdown/scanners.h">

<violation number="1" location="src/core/markdown/scanners.h:301">
P2: When an HTML comment has a dash immediately before its closing `-->`, `scan_html_comment` misses the overlapping terminator and treats valid raw HTML as ordinary text. Detect the first `-->` substring directly or preserve the overlapping dash.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/core/markdown/render.h Outdated
Comment thread src/core/markdown/postprocess.h Outdated
Comment thread src/core/markdown/blocks.h Outdated
Comment thread src/core/markdown/references.h
Comment thread src/core/markdown/scanners.h Outdated
std::size_t dashes{0};
for (auto position{offset + 2}; position < input.size(); ++position) {
const auto character{input[position]};
if (dashes == 2) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When an HTML comment has a dash immediately before its closing -->, scan_html_comment misses the overlapping terminator and treats valid raw HTML as ordinary text. Detect the first --> substring directly or preserve the overlapping dash.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/markdown/scanners.h, line 301:

<comment>When an HTML comment has a dash immediately before its closing `-->`, `scan_html_comment` misses the overlapping terminator and treats valid raw HTML as ordinary text. Detect the first `-->` substring directly or preserve the overlapping dash.</comment>

<file context>
@@ -0,0 +1,930 @@
+  std::size_t dashes{0};
+  for (auto position{offset + 2}; position < input.size(); ++position) {
+    const auto character{input[position]};
+    if (dashes == 2) {
+      if (character == '>') {
+        return position + 1 - offset;
</file context>

Comment thread src/core/markdown/scanners.h Outdated
Comment thread src/core/markdown/inlines.h Outdated
Comment thread src/core/markdown/CMakeLists.txt
Comment thread src/core/markdown/scanners.h Outdated
}

auto *const result{this->cursor_};
this->cursor_ += size;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: When a fresh StringArena receives a zero-size allocation, cursor_ += size performs pointer arithmetic on nullptr, which is undefined behavior. Return before the pointer arithmetic for size == 0.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/markdown/document.h, line 135:

<comment>When a fresh `StringArena` receives a zero-size allocation, `cursor_ += size` performs pointer arithmetic on `nullptr`, which is undefined behavior. Return before the pointer arithmetic for `size == 0`.</comment>

<file context>
@@ -0,0 +1,277 @@
+    }
+
+    auto *const result{this->cursor_};
+    this->cursor_ += size;
+    this->remaining_ -= size;
+    return result;
</file context>
Suggested change
this->cursor_ += size;
if (size == 0) {
return result;
}
this->cursor_ += size;

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 42 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/core/html/include/sourcemeta/core/html_buffer.h">

<violation number="1" location="src/core/html/include/sourcemeta/core/html_buffer.h:87">
P1: A fresh buffer has null pointers, but `size()`, `capacity()`, and the append paths subtract them before allocation, which is undefined behavior. This affects empty-buffer calls, `HTMLWriter::reserve()`, and every buffer after `take()`. Keep an always-valid empty pointer range or guard null state before every pointer subtraction, including the state restored by `take()`.</violation>
</file>

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.

Re-trigger cubic

/// Get the number of bytes accumulated so far
[[nodiscard]] SOURCEMETA_FORCEINLINE auto size() const noexcept
-> std::size_t {
return static_cast<std::size_t>(this->cursor_ - this->begin_);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: A fresh buffer has null pointers, but size(), capacity(), and the append paths subtract them before allocation, which is undefined behavior. This affects empty-buffer calls, HTMLWriter::reserve(), and every buffer after take(). Keep an always-valid empty pointer range or guard null state before every pointer subtraction, including the state restored by take().

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/html/include/sourcemeta/core/html_buffer.h, line 87:

<comment>A fresh buffer has null pointers, but `size()`, `capacity()`, and the append paths subtract them before allocation, which is undefined behavior. This affects empty-buffer calls, `HTMLWriter::reserve()`, and every buffer after `take()`. Keep an always-valid empty pointer range or guard null state before every pointer subtraction, including the state restored by `take()`.</comment>

<file context>
@@ -49,35 +52,99 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLBuffer {
+  /// Get the number of bytes accumulated so far
+  [[nodiscard]] SOURCEMETA_FORCEINLINE auto size() const noexcept
+      -> std::size_t {
+    return static_cast<std::size_t>(this->cursor_ - this->begin_);
+  }
 
</file context>

Comment thread src/lang/text/include/sourcemeta/core/text.h Outdated
Comment thread src/core/uri/include/sourcemeta/core/uri.h Outdated
Comment thread test/html/html_encoder_test.cc Outdated
Comment thread src/core/uri/include/sourcemeta/core/uri.h

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread src/core/html/include/sourcemeta/core/html_writer.h Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 17 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="test/markdown/markdown_autolinks_test.cc">

<violation number="1" location="test/markdown/markdown_autolinks_test.cc:308">
P2: This expectation does not match the current parser and makes the test fail: `_` is an allowed autolink delimiter, so the URL is linked before emphasis is applied. Update the expected output to include the link, or change the parser if rejecting underscore-delimited autolinks is intentional.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

TEST(extended_autolink_after_underscore_emphasis_delimiter) {
const auto result{
sourcemeta::core::markdown_to_html("_https://sourcemeta.com_")};
EXPECT_EQ(result, "<p><em>https://sourcemeta.com</em></p>\n");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This expectation does not match the current parser and makes the test fail: _ is an allowed autolink delimiter, so the URL is linked before emphasis is applied. Update the expected output to include the link, or change the parser if rejecting underscore-delimited autolinks is intentional.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At test/markdown/markdown_autolinks_test.cc, line 308:

<comment>This expectation does not match the current parser and makes the test fail: `_` is an allowed autolink delimiter, so the URL is linked before emphasis is applied. Update the expected output to include the link, or change the parser if rejecting underscore-delimited autolinks is intentional.</comment>

<file context>
@@ -309,5 +299,203 @@ TEST(extended_autolink_email_after_invalid_candidate) {
+TEST(extended_autolink_after_underscore_emphasis_delimiter) {
+  const auto result{
+      sourcemeta::core::markdown_to_html("_https://sourcemeta.com_")};
+  EXPECT_EQ(result, "<p><em>https://sourcemeta.com</em></p>\n");
+}
+
</file context>
Suggested change
EXPECT_EQ(result, "<p><em>https://sourcemeta.com</em></p>\n");
EXPECT_EQ(result, "<p><em><a href=\"https://sourcemeta.com\">https://sourcemeta.com</a></em></p>\n");

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread test/html/html_encoder_test.cc
@jviotti

jviotti commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 16, 2026

Copy link
Copy Markdown

@cubic-dev-ai review

@jviotti I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 issues found across 106 files

Not reviewed (too large): test/markdown/markdown_spec_blocks_test.cc (~3,684 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/core/markdown/document.h">

<violation number="1" location="src/core/markdown/document.h:71">
P2: When a Markdown input exceeds 4 GiB, `Node::content_offset` and `content_length` truncate source positions. Reject oversized inputs or use `std::size_t` for content offsets and lengths throughout the parser.</violation>
</file>

<file name="src/core/markdown/render.h">

<violation number="1" location="src/core/markdown/render.h:151">
P2: When an image description contains a resolved footnote reference, `alternative_text()` omits the reference number from `alt` even though the renderer emits that number as visible text. Include `FootnoteReference` in the plain-text cases so image alternatives reflect their descendants.</violation>

<violation number="2" location="src/core/markdown/render.h:151">
P3: Image alt text includes raw HTML markup instead of stripping it. When an image label contains an inline HTML tag, `alternative_text()` appends the `HTMLInline` literal, so the generated accessible name contains escaped `<tag>` text. Exclude `NodeType::HTMLInline` from the appended-text branch.</violation>
</file>

<file name="src/core/markdown/postprocess.h">

<violation number="1" location="src/core/markdown/postprocess.h:118">
P2: When an unreferenced footnote definition contains a reference to another definition, this loop still promotes the nested definition into the rendered footnotes because definitions are not detached until after reference resolution. Exclude references under definitions that are not externally referenced before assigning footnote numbers.</violation>

<violation number="2" location="src/core/markdown/postprocess.h:186">
P2: When an image alt text contains an email address after other text, this traversal creates an autolink inside the image's alt-text subtree. Skip `NodeType::Image` alongside `NodeType::Link` so postprocessing only links email text rendered as document content.</violation>
</file>

<file name="src/core/markdown/scanners.h">

<violation number="1" location="src/core/markdown/scanners.h:305">
P2: Inline declarations without whitespace after the uppercase name, such as `<!A>`, are rejected even though the block scanner accepts them as GFM HTML declarations. Remove the mandatory whitespace requirement and scan for `>` directly after the declaration name.</violation>

<violation number="2" location="src/core/markdown/scanners.h:809">
P2: When a table cell contains an even-length run of backslashes before `|`, this keeps an unescaped pipe inside the cell. Count consecutive preceding backslashes and split the cell only when that count is even.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/core/markdown/references.h Outdated
std::uint32_t last_child{NO_NODE};
std::uint32_t previous{NO_NODE};
std::uint32_t next{NO_NODE};
std::uint32_t content_offset{0};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a Markdown input exceeds 4 GiB, Node::content_offset and content_length truncate source positions. Reject oversized inputs or use std::size_t for content offsets and lengths throughout the parser.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/markdown/document.h, line 71:

<comment>When a Markdown input exceeds 4 GiB, `Node::content_offset` and `content_length` truncate source positions. Reject oversized inputs or use `std::size_t` for content offsets and lengths throughout the parser.</comment>

<file context>
@@ -0,0 +1,278 @@
+  std::uint32_t last_child{NO_NODE};
+  std::uint32_t previous{NO_NODE};
+  std::uint32_t next{NO_NODE};
+  std::uint32_t content_offset{0};
+  std::uint32_t content_length{0};
+  std::uint32_t data{0};
</file context>

Comment thread src/core/markdown/markdown.cc Outdated
Comment thread src/core/markdown/characters.h Outdated
Comment on lines +151 to +152
if (node.type == NodeType::Text || node.type == NodeType::Code ||
node.type == NodeType::HTMLInline) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When an image description contains a resolved footnote reference, alternative_text() omits the reference number from alt even though the renderer emits that number as visible text. Include FootnoteReference in the plain-text cases so image alternatives reflect their descendants.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/markdown/render.h, line 151:

<comment>When an image description contains a resolved footnote reference, `alternative_text()` omits the reference number from `alt` even though the renderer emits that number as visible text. Include `FootnoteReference` in the plain-text cases so image alternatives reflect their descendants.</comment>

<file context>
@@ -0,0 +1,625 @@
+    auto current{nodes[image].first_child};
+    while (current != NO_NODE) {
+      const auto &node{nodes[current]};
+      if (node.type == NodeType::Text || node.type == NodeType::Code ||
+          node.type == NodeType::HTMLInline) {
+        this->value_.append(node.literal);
</file context>
Suggested change
if (node.type == NodeType::Text || node.type == NodeType::Code ||
node.type == NodeType::HTMLInline) {
if (node.type == NodeType::Text || node.type == NodeType::Code ||
node.type == NodeType::FootnoteReference ||
node.type == NodeType::HTMLInline) {


std::uint32_t last_index{0};
for (const auto reference : references) {
if (this->is_attached(reference)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When an unreferenced footnote definition contains a reference to another definition, this loop still promotes the nested definition into the rendered footnotes because definitions are not detached until after reference resolution. Exclude references under definitions that are not externally referenced before assigning footnote numbers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/markdown/postprocess.h, line 118:

<comment>When an unreferenced footnote definition contains a reference to another definition, this loop still promotes the nested definition into the rendered footnotes because definitions are not detached until after reference resolution. Exclude references under definitions that are not externally referenced before assigning footnote numbers.</comment>

<file context>
@@ -0,0 +1,524 @@
+
+    std::uint32_t last_index{0};
+    for (const auto reference : references) {
+      if (this->is_attached(reference)) {
+        this->resolve_reference(reference, last_index);
+      }
</file context>

Comment thread src/core/markdown/scanners.h Outdated
Comment on lines +809 to +812
if (character == '|' &&
(position == offset || input[position - 1] != '\\')) {
break;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a table cell contains an even-length run of backslashes before |, this keeps an unescaped pipe inside the cell. Count consecutive preceding backslashes and split the cell only when that count is even.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/markdown/scanners.h, line 809:

<comment>When a table cell contains an even-length run of backslashes before `|`, this keeps an unescaped pipe inside the cell. Count consecutive preceding backslashes and split the cell only when that count is even.</comment>

<file context>
@@ -0,0 +1,857 @@
+      break;
+    }
+
+    if (character == '|' &&
+        (position == offset || input[position - 1] != '\\')) {
+      break;
</file context>
Suggested change
if (character == '|' &&
(position == offset || input[position - 1] != '\\')) {
break;
}
if (character == '|') {
std::size_t backslashes{0};
for (auto previous{position}; previous > offset &&
input[previous - 1] == '\\';
--previous) {
++backslashes;
}
if (backslashes % 2 == 0) {
break;
}
}

}

const auto spaces{scan_spacechars(input, position)};
if (spaces == 0) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Inline declarations without whitespace after the uppercase name, such as <!A>, are rejected even though the block scanner accepts them as GFM HTML declarations. Remove the mandatory whitespace requirement and scan for > directly after the declaration name.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/markdown/scanners.h, line 305:

<comment>Inline declarations without whitespace after the uppercase name, such as `<!A>`, are rejected even though the block scanner accepts them as GFM HTML declarations. Remove the mandatory whitespace requirement and scan for `>` directly after the declaration name.</comment>

<file context>
@@ -0,0 +1,857 @@
+  }
+
+  const auto spaces{scan_spacechars(input, position)};
+  if (spaces == 0) {
+    return 0;
+  }
</file context>

auto current{nodes[image].first_child};
while (current != NO_NODE) {
const auto &node{nodes[current]};
if (node.type == NodeType::Text || node.type == NodeType::Code ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Image alt text includes raw HTML markup instead of stripping it. When an image label contains an inline HTML tag, alternative_text() appends the HTMLInline literal, so the generated accessible name contains escaped <tag> text. Exclude NodeType::HTMLInline from the appended-text branch.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/markdown/render.h, line 151:

<comment>Image alt text includes raw HTML markup instead of stripping it. When an image label contains an inline HTML tag, `alternative_text()` appends the `HTMLInline` literal, so the generated accessible name contains escaped `<tag>` text. Exclude `NodeType::HTMLInline` from the appended-text branch.</comment>

<file context>
@@ -0,0 +1,625 @@
+    auto current{nodes[image].first_child};
+    while (current != NO_NODE) {
+      const auto &node{nodes[current]};
+      if (node.type == NodeType::Text || node.type == NodeType::Code ||
+          node.type == NodeType::HTMLInline) {
+        this->value_.append(node.literal);
</file context>

Signed-off-by: Juan Cruz Viotti <[email protected]>
@jviotti

jviotti commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 16, 2026

Copy link
Copy Markdown

@cubic-dev-ai review

@jviotti I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 existing issue remains and 1 new issue found across 106 files

Not reviewed (too large): test/markdown/markdown_spec_blocks_test.cc (~3,684 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/core/markdown/references.h">

<violation number="1" location="src/core/markdown/references.h:161">
P2: When a link destination contains an escaped ampersand, `clean_url` decodes it as a character reference before applying the backslash escape. For example, `a\&amp;b` becomes `a&b` instead of the literal `a&amp;b`; process escapes and character references in one left-to-right pass, or make entity decoding skip escaped ampersands.</violation>
</file>

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.

Re-trigger cubic

Comment thread src/core/markdown/references.h Outdated
}

buffer.clear();
if (!decode_character_references(buffer, url)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a link destination contains an escaped ampersand, clean_url decodes it as a character reference before applying the backslash escape. For example, a\&amp;b becomes a&b instead of the literal a&amp;b; process escapes and character references in one left-to-right pass, or make entity decoding skip escaped ampersands.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/core/markdown/references.h, line 161:

<comment>When a link destination contains an escaped ampersand, `clean_url` decodes it as a character reference before applying the backslash escape. For example, `a\&amp;b` becomes `a&b` instead of the literal `a&amp;b`; process escapes and character references in one left-to-right pass, or make entity decoding skip escaped ampersands.</comment>

<file context>
@@ -0,0 +1,318 @@
+  }
+
+  buffer.clear();
+  if (!decode_character_references(buffer, url)) {
+    buffer.assign(url);
+  }
</file context>

Signed-off-by: Juan Cruz Viotti <[email protected]>
@jviotti
jviotti merged commit 5e928fb into main Sep 16, 2026
14 checks passed
@jviotti
jviotti deleted the no-cmark-gfm branch September 16, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant