herb 0.10.4-arm-linux-gnu → 0.11.1-arm-linux-gnu

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (793) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +16 -6
  3. data/README.md +36 -119
  4. data/Rakefile +2 -11
  5. data/config/action_view_helpers/actioncable/action_cable_helper/action_cable_meta_tag.yml +12 -8
  6. data/config/action_view_helpers/actionpack/content_security_policy/content_security_policy?.yml +9 -6
  7. data/config/action_view_helpers/actionpack/content_security_policy/content_security_policy_nonce.yml +9 -6
  8. data/config/action_view_helpers/actionpack/polymorphic_routes/polymorphic_path.yml +20 -12
  9. data/config/action_view_helpers/actionpack/polymorphic_routes/polymorphic_url.yml +30 -18
  10. data/config/action_view_helpers/actionpack/request_forgery_protection/form_authenticity_token.yml +15 -9
  11. data/config/action_view_helpers/actionpack/request_forgery_protection/protect_against_forgery?.yml +9 -6
  12. data/config/action_view_helpers/actiontext/content_helper/render_action_text_content.yml +15 -9
  13. data/config/action_view_helpers/actiontext/content_helper/sanitize_action_text_content.yml +15 -9
  14. data/config/action_view_helpers/actiontext/tag_helper/rich_textarea_tag.yml +34 -22
  15. data/config/action_view_helpers/actionview/active_model_helper/error_message.yml +9 -6
  16. data/config/action_view_helpers/actionview/active_model_helper/error_wrapping.yml +9 -6
  17. data/config/action_view_helpers/actionview/active_model_helper/object.yml +9 -6
  18. data/config/action_view_helpers/actionview/asset_tag_helper/apply_stylesheet_media_default.yml +9 -6
  19. data/config/action_view_helpers/actionview/asset_tag_helper/audio_tag.yml +40 -27
  20. data/config/action_view_helpers/actionview/asset_tag_helper/auto_discovery_link_tag.yml +37 -23
  21. data/config/action_view_helpers/actionview/asset_tag_helper/auto_include_nonce.yml +9 -6
  22. data/config/action_view_helpers/actionview/asset_tag_helper/auto_include_nonce_for_scripts.yml +9 -6
  23. data/config/action_view_helpers/actionview/asset_tag_helper/auto_include_nonce_for_styles.yml +9 -6
  24. data/config/action_view_helpers/actionview/asset_tag_helper/favicon_link_tag.yml +32 -22
  25. data/config/action_view_helpers/actionview/asset_tag_helper/image_decoding.yml +9 -6
  26. data/config/action_view_helpers/actionview/asset_tag_helper/image_loading.yml +9 -6
  27. data/config/action_view_helpers/actionview/asset_tag_helper/image_tag.yml +67 -46
  28. data/config/action_view_helpers/actionview/asset_tag_helper/javascript_include_tag.yml +58 -39
  29. data/config/action_view_helpers/actionview/asset_tag_helper/picture_tag.yml +22 -14
  30. data/config/action_view_helpers/actionview/asset_tag_helper/preload_link_tag.yml +45 -30
  31. data/config/action_view_helpers/actionview/asset_tag_helper/preload_links_header.yml +9 -6
  32. data/config/action_view_helpers/actionview/asset_tag_helper/stylesheet_link_tag.yml +49 -30
  33. data/config/action_view_helpers/actionview/asset_tag_helper/video_tag.yml +53 -35
  34. data/config/action_view_helpers/actionview/asset_url_helper/asset_path.yml +16 -10
  35. data/config/action_view_helpers/actionview/asset_url_helper/asset_url.yml +16 -10
  36. data/config/action_view_helpers/actionview/asset_url_helper/audio_path.yml +16 -10
  37. data/config/action_view_helpers/actionview/asset_url_helper/audio_url.yml +16 -10
  38. data/config/action_view_helpers/actionview/asset_url_helper/compute_asset_extname.yml +9 -6
  39. data/config/action_view_helpers/actionview/asset_url_helper/compute_asset_host.yml +9 -6
  40. data/config/action_view_helpers/actionview/asset_url_helper/compute_asset_path.yml +9 -6
  41. data/config/action_view_helpers/actionview/asset_url_helper/font_path.yml +16 -10
  42. data/config/action_view_helpers/actionview/asset_url_helper/font_url.yml +16 -10
  43. data/config/action_view_helpers/actionview/asset_url_helper/image_path.yml +16 -10
  44. data/config/action_view_helpers/actionview/asset_url_helper/image_url.yml +16 -10
  45. data/config/action_view_helpers/actionview/asset_url_helper/javascript_path.yml +16 -10
  46. data/config/action_view_helpers/actionview/asset_url_helper/javascript_url.yml +16 -10
  47. data/config/action_view_helpers/actionview/asset_url_helper/public_compute_asset_path.yml +9 -6
  48. data/config/action_view_helpers/actionview/asset_url_helper/stylesheet_path.yml +16 -10
  49. data/config/action_view_helpers/actionview/asset_url_helper/stylesheet_url.yml +16 -10
  50. data/config/action_view_helpers/actionview/asset_url_helper/video_path.yml +16 -10
  51. data/config/action_view_helpers/actionview/asset_url_helper/video_url.yml +16 -10
  52. data/config/action_view_helpers/actionview/atom_feed_helper/atom_feed.yml +52 -27
  53. data/config/action_view_helpers/actionview/cache_helper/cache.yml +25 -15
  54. data/config/action_view_helpers/actionview/cache_helper/cache_fragment_name.yml +9 -6
  55. data/config/action_view_helpers/actionview/cache_helper/cache_if.yml +20 -12
  56. data/config/action_view_helpers/actionview/cache_helper/cache_unless.yml +20 -12
  57. data/config/action_view_helpers/actionview/cache_helper/caching_predicate.yml +9 -6
  58. data/config/action_view_helpers/actionview/cache_helper/digest_path_from_template.yml +9 -6
  59. data/config/action_view_helpers/actionview/cache_helper/fragment_for.yml +9 -6
  60. data/config/action_view_helpers/actionview/cache_helper/fragment_name_with_digest.yml +9 -6
  61. data/config/action_view_helpers/actionview/cache_helper/read_fragment_for.yml +9 -6
  62. data/config/action_view_helpers/actionview/cache_helper/uncacheable.yml +9 -6
  63. data/config/action_view_helpers/actionview/cache_helper/write_fragment_for.yml +9 -6
  64. data/config/action_view_helpers/actionview/capture_helper/capture.yml +9 -6
  65. data/config/action_view_helpers/actionview/capture_helper/content_for.yml +20 -12
  66. data/config/action_view_helpers/actionview/capture_helper/content_for_predicate.yml +15 -9
  67. data/config/action_view_helpers/actionview/capture_helper/provide.yml +15 -9
  68. data/config/action_view_helpers/actionview/capture_helper/with_output_buffer.yml +9 -6
  69. data/config/action_view_helpers/actionview/content_exfiltration_prevention_helper/prepend_content_exfiltration_prevention.yml +9 -6
  70. data/config/action_view_helpers/actionview/content_exfiltration_prevention_helper/prevent_content_exfiltration.yml +9 -6
  71. data/config/action_view_helpers/actionview/controller_helper/action_name.yml +9 -6
  72. data/config/action_view_helpers/actionview/controller_helper/assign_controller.yml +9 -6
  73. data/config/action_view_helpers/actionview/controller_helper/controller.yml +9 -6
  74. data/config/action_view_helpers/actionview/controller_helper/controller_name.yml +9 -6
  75. data/config/action_view_helpers/actionview/controller_helper/controller_path.yml +9 -6
  76. data/config/action_view_helpers/actionview/controller_helper/cookies.yml +9 -6
  77. data/config/action_view_helpers/actionview/controller_helper/flash.yml +9 -6
  78. data/config/action_view_helpers/actionview/controller_helper/headers.yml +9 -6
  79. data/config/action_view_helpers/actionview/controller_helper/logger.yml +9 -6
  80. data/config/action_view_helpers/actionview/controller_helper/params.yml +9 -6
  81. data/config/action_view_helpers/actionview/controller_helper/request.yml +9 -6
  82. data/config/action_view_helpers/actionview/controller_helper/request_forgery_protection_token.yml +9 -6
  83. data/config/action_view_helpers/actionview/controller_helper/response.yml +9 -6
  84. data/config/action_view_helpers/actionview/controller_helper/session.yml +9 -6
  85. data/config/action_view_helpers/actionview/csp_helper/csp_meta_tag.yml +18 -11
  86. data/config/action_view_helpers/actionview/csrf_helper/csrf_meta_tags.yml +16 -10
  87. data/config/action_view_helpers/actionview/date_helper/date_select.yml +85 -51
  88. data/config/action_view_helpers/actionview/date_helper/datetime_select.yml +65 -39
  89. data/config/action_view_helpers/actionview/date_helper/distance_of_time_in_words.yml +30 -18
  90. data/config/action_view_helpers/actionview/date_helper/relative_time_in_words.yml +35 -21
  91. data/config/action_view_helpers/actionview/date_helper/select_date.yml +50 -30
  92. data/config/action_view_helpers/actionview/date_helper/select_datetime.yml +65 -39
  93. data/config/action_view_helpers/actionview/date_helper/select_day.yml +40 -24
  94. data/config/action_view_helpers/actionview/date_helper/select_hour.yml +50 -30
  95. data/config/action_view_helpers/actionview/date_helper/select_minute.yml +40 -24
  96. data/config/action_view_helpers/actionview/date_helper/select_month.yml +60 -36
  97. data/config/action_view_helpers/actionview/date_helper/select_second.yml +35 -21
  98. data/config/action_view_helpers/actionview/date_helper/select_time.yml +55 -33
  99. data/config/action_view_helpers/actionview/date_helper/select_year.yml +45 -27
  100. data/config/action_view_helpers/actionview/date_helper/time_ago_in_words.yml +21 -13
  101. data/config/action_view_helpers/actionview/date_helper/time_select.yml +60 -36
  102. data/config/action_view_helpers/actionview/date_helper/time_tag.yml +32 -20
  103. data/config/action_view_helpers/actionview/debug_helper/debug.yml +15 -9
  104. data/config/action_view_helpers/actionview/form_builder/button.yml +60 -0
  105. data/config/action_view_helpers/actionview/form_builder/submit.yml +48 -0
  106. data/config/action_view_helpers/actionview/form_helper/apply_form_for_options.yml +9 -6
  107. data/config/action_view_helpers/actionview/form_helper/checkbox.yml +41 -25
  108. data/config/action_view_helpers/actionview/form_helper/color_field.yml +25 -15
  109. data/config/action_view_helpers/actionview/form_helper/date_field.yml +35 -21
  110. data/config/action_view_helpers/actionview/form_helper/datetime_field.yml +41 -25
  111. data/config/action_view_helpers/actionview/form_helper/email_field.yml +25 -15
  112. data/config/action_view_helpers/actionview/form_helper/emitted_hidden_id.yml +9 -6
  113. data/config/action_view_helpers/actionview/form_helper/fields.yml +37 -18
  114. data/config/action_view_helpers/actionview/form_helper/fields_for.yml +33 -15
  115. data/config/action_view_helpers/actionview/form_helper/file_field.yml +45 -27
  116. data/config/action_view_helpers/actionview/form_helper/form_for.yml +45 -24
  117. data/config/action_view_helpers/actionview/form_helper/form_with.yml +56 -30
  118. data/config/action_view_helpers/actionview/form_helper/form_with_generates_ids.yml +9 -6
  119. data/config/action_view_helpers/actionview/form_helper/form_with_generates_remote_forms.yml +9 -6
  120. data/config/action_view_helpers/actionview/form_helper/hidden_field.yml +25 -15
  121. data/config/action_view_helpers/actionview/form_helper/label.yml +52 -27
  122. data/config/action_view_helpers/actionview/form_helper/month_field.yml +25 -15
  123. data/config/action_view_helpers/actionview/form_helper/multipart.yml +9 -6
  124. data/config/action_view_helpers/actionview/form_helper/multiple_file_field_include_hidden.yml +9 -6
  125. data/config/action_view_helpers/actionview/form_helper/number_field.yml +45 -27
  126. data/config/action_view_helpers/actionview/form_helper/password_field.yml +25 -15
  127. data/config/action_view_helpers/actionview/form_helper/radio_button.yml +30 -18
  128. data/config/action_view_helpers/actionview/form_helper/range_field.yml +45 -27
  129. data/config/action_view_helpers/actionview/form_helper/search_field.yml +25 -15
  130. data/config/action_view_helpers/actionview/form_helper/telephone_field.yml +26 -16
  131. data/config/action_view_helpers/actionview/form_helper/text_field.yml +25 -15
  132. data/config/action_view_helpers/actionview/form_helper/textarea.yml +31 -19
  133. data/config/action_view_helpers/actionview/form_helper/time_field.yml +40 -24
  134. data/config/action_view_helpers/actionview/form_helper/url_field.yml +25 -15
  135. data/config/action_view_helpers/actionview/form_helper/week_field.yml +25 -15
  136. data/config/action_view_helpers/actionview/form_options_helper/collection_checkboxes.yml +58 -31
  137. data/config/action_view_helpers/actionview/form_options_helper/collection_radio_buttons.yml +57 -30
  138. data/config/action_view_helpers/actionview/form_options_helper/collection_select.yml +65 -39
  139. data/config/action_view_helpers/actionview/form_options_helper/grouped_collection_select.yml +65 -39
  140. data/config/action_view_helpers/actionview/form_options_helper/grouped_options_for_select.yml +35 -21
  141. data/config/action_view_helpers/actionview/form_options_helper/option_groups_from_collection_for_select.yml +40 -24
  142. data/config/action_view_helpers/actionview/form_options_helper/options_for_select.yml +20 -12
  143. data/config/action_view_helpers/actionview/form_options_helper/options_from_collection_for_select.yml +30 -18
  144. data/config/action_view_helpers/actionview/form_options_helper/select.yml +60 -36
  145. data/config/action_view_helpers/actionview/form_options_helper/time_zone_options_for_select.yml +25 -15
  146. data/config/action_view_helpers/actionview/form_options_helper/time_zone_select.yml +50 -30
  147. data/config/action_view_helpers/actionview/form_options_helper/weekday_options_for_select.yml +30 -18
  148. data/config/action_view_helpers/actionview/form_options_helper/weekday_select.yml +30 -18
  149. data/config/action_view_helpers/actionview/form_tag_helper/button_tag.yml +39 -21
  150. data/config/action_view_helpers/actionview/form_tag_helper/checkbox_tag.yml +33 -21
  151. data/config/action_view_helpers/actionview/form_tag_helper/color_field_tag.yml +26 -17
  152. data/config/action_view_helpers/actionview/form_tag_helper/date_field_tag.yml +27 -17
  153. data/config/action_view_helpers/actionview/form_tag_helper/datetime_field_tag.yml +28 -18
  154. data/config/action_view_helpers/actionview/form_tag_helper/default_enforce_utf8.yml +9 -6
  155. data/config/action_view_helpers/actionview/form_tag_helper/email_field_tag.yml +27 -17
  156. data/config/action_view_helpers/actionview/form_tag_helper/embed_authenticity_token_in_remote_forms.yml +9 -6
  157. data/config/action_view_helpers/actionview/form_tag_helper/field_id.yml +30 -18
  158. data/config/action_view_helpers/actionview/form_tag_helper/field_name.yml +30 -18
  159. data/config/action_view_helpers/actionview/form_tag_helper/field_set_tag.yml +23 -15
  160. data/config/action_view_helpers/actionview/form_tag_helper/file_field_tag.yml +35 -22
  161. data/config/action_view_helpers/actionview/form_tag_helper/form_tag.yml +38 -24
  162. data/config/action_view_helpers/actionview/form_tag_helper/hidden_field_tag.yml +27 -17
  163. data/config/action_view_helpers/actionview/form_tag_helper/image_submit_tag.yml +31 -21
  164. data/config/action_view_helpers/actionview/form_tag_helper/label_tag.yml +33 -17
  165. data/config/action_view_helpers/actionview/form_tag_helper/month_field_tag.yml +27 -17
  166. data/config/action_view_helpers/actionview/form_tag_helper/number_field_tag.yml +47 -29
  167. data/config/action_view_helpers/actionview/form_tag_helper/password_field_tag.yml +27 -17
  168. data/config/action_view_helpers/actionview/form_tag_helper/radio_button_tag.yml +32 -20
  169. data/config/action_view_helpers/actionview/form_tag_helper/range_field_tag.yml +47 -29
  170. data/config/action_view_helpers/actionview/form_tag_helper/search_field_tag.yml +27 -17
  171. data/config/action_view_helpers/actionview/form_tag_helper/select_tag.yml +47 -29
  172. data/config/action_view_helpers/actionview/form_tag_helper/submit_tag.yml +33 -21
  173. data/config/action_view_helpers/actionview/form_tag_helper/telephone_field_tag.yml +28 -18
  174. data/config/action_view_helpers/actionview/form_tag_helper/text_field_tag.yml +27 -17
  175. data/config/action_view_helpers/actionview/form_tag_helper/textarea_tag.yml +31 -20
  176. data/config/action_view_helpers/actionview/form_tag_helper/time_field_tag.yml +27 -17
  177. data/config/action_view_helpers/actionview/form_tag_helper/url_field_tag.yml +27 -17
  178. data/config/action_view_helpers/actionview/form_tag_helper/utf8_enforcer_tag.yml +9 -6
  179. data/config/action_view_helpers/actionview/form_tag_helper/week_field_tag.yml +28 -18
  180. data/config/action_view_helpers/actionview/javascript_helper/escape_javascript.yml +16 -10
  181. data/config/action_view_helpers/actionview/javascript_helper/javascript_cdata_section.yml +9 -6
  182. data/config/action_view_helpers/actionview/javascript_helper/javascript_tag.yml +41 -27
  183. data/config/action_view_helpers/actionview/number_helper/number_to_currency.yml +29 -18
  184. data/config/action_view_helpers/actionview/number_helper/number_to_human.yml +25 -15
  185. data/config/action_view_helpers/actionview/number_helper/number_to_human_size.yml +20 -12
  186. data/config/action_view_helpers/actionview/number_helper/number_to_percentage.yml +20 -12
  187. data/config/action_view_helpers/actionview/number_helper/number_to_phone.yml +33 -20
  188. data/config/action_view_helpers/actionview/number_helper/number_with_delimiter.yml +21 -13
  189. data/config/action_view_helpers/actionview/number_helper/number_with_precision.yml +25 -15
  190. data/config/action_view_helpers/actionview/output_safety_helper/raw.yml +15 -9
  191. data/config/action_view_helpers/actionview/output_safety_helper/safe_join.yml +20 -12
  192. data/config/action_view_helpers/actionview/output_safety_helper/to_sentence.yml +24 -15
  193. data/config/action_view_helpers/actionview/record_identifier/dom_class.yml +20 -12
  194. data/config/action_view_helpers/actionview/record_identifier/dom_id.yml +20 -12
  195. data/config/action_view_helpers/actionview/record_identifier/dom_target.yml +15 -9
  196. data/config/action_view_helpers/actionview/record_identifier/model_name_from_record_or_class.yml +9 -6
  197. data/config/action_view_helpers/actionview/rendering_helper/render.yml +108 -22
  198. data/config/action_view_helpers/actionview/sanitize_helper/sanitize.yml +25 -15
  199. data/config/action_view_helpers/actionview/sanitize_helper/sanitize_css.yml +15 -9
  200. data/config/action_view_helpers/actionview/sanitize_helper/sanitizer_vendor.yml +9 -6
  201. data/config/action_view_helpers/actionview/sanitize_helper/strip_links.yml +15 -9
  202. data/config/action_view_helpers/actionview/sanitize_helper/strip_tags.yml +15 -9
  203. data/config/action_view_helpers/actionview/tag_helper/cdata_section.yml +15 -9
  204. data/config/action_view_helpers/actionview/tag_helper/content_tag.yml +59 -38
  205. data/config/action_view_helpers/actionview/tag_helper/escape_once.yml +15 -9
  206. data/config/action_view_helpers/actionview/tag_helper/tag.yml +54 -31
  207. data/config/action_view_helpers/actionview/tag_helper/token_list.yml +16 -10
  208. data/config/action_view_helpers/actionview/text_helper/concat.yml +15 -9
  209. data/config/action_view_helpers/actionview/text_helper/current_cycle.yml +15 -9
  210. data/config/action_view_helpers/actionview/text_helper/cycle.yml +23 -14
  211. data/config/action_view_helpers/actionview/text_helper/excerpt.yml +33 -20
  212. data/config/action_view_helpers/actionview/text_helper/highlight.yml +37 -18
  213. data/config/action_view_helpers/actionview/text_helper/pluralize.yml +30 -18
  214. data/config/action_view_helpers/actionview/text_helper/reset_cycle.yml +15 -9
  215. data/config/action_view_helpers/actionview/text_helper/safe_concat.yml +9 -6
  216. data/config/action_view_helpers/actionview/text_helper/simple_format.yml +33 -20
  217. data/config/action_view_helpers/actionview/text_helper/truncate.yml +38 -23
  218. data/config/action_view_helpers/actionview/text_helper/word_wrap.yml +25 -15
  219. data/config/action_view_helpers/actionview/translation_helper/debug_missing_translation.yml +9 -6
  220. data/config/action_view_helpers/actionview/translation_helper/localize.yml +26 -16
  221. data/config/action_view_helpers/actionview/translation_helper/translate.yml +31 -19
  222. data/config/action_view_helpers/actionview/url_helper/button_to.yml +57 -33
  223. data/config/action_view_helpers/actionview/url_helper/button_to_generates_button_tag.yml +9 -6
  224. data/config/action_view_helpers/actionview/url_helper/current_page?.yml +25 -15
  225. data/config/action_view_helpers/actionview/url_helper/link_to.yml +76 -53
  226. data/config/action_view_helpers/actionview/url_helper/link_to_if.yml +54 -20
  227. data/config/action_view_helpers/actionview/url_helper/link_to_unless.yml +54 -20
  228. data/config/action_view_helpers/actionview/url_helper/link_to_unless_current.yml +49 -17
  229. data/config/action_view_helpers/actionview/url_helper/mail_to.yml +60 -34
  230. data/config/action_view_helpers/actionview/url_helper/phone_to.yml +40 -22
  231. data/config/action_view_helpers/actionview/url_helper/sms_to.yml +45 -25
  232. data/config/action_view_helpers/actionview/url_helper/url_for.yml +15 -9
  233. data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_import_module_tag.yml +32 -0
  234. data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_importmap_module_preload_tags.yml +39 -0
  235. data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_importmap_tags.yml +35 -0
  236. data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_inline_importmap_tag.yml +32 -0
  237. data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_module_preload_tag.yml +35 -0
  238. data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_cache.yml +9 -6
  239. data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_cache_tag.yml +12 -8
  240. data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_preview.yml +9 -6
  241. data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_preview_tag.yml +12 -8
  242. data/config/action_view_helpers/turbo-rails/drive_helper/turbo_page_requires_reload.yml +9 -6
  243. data/config/action_view_helpers/turbo-rails/drive_helper/turbo_page_requires_reload_tag.yml +12 -8
  244. data/config/action_view_helpers/turbo-rails/drive_helper/turbo_refresh_method_tag.yml +17 -11
  245. data/config/action_view_helpers/turbo-rails/drive_helper/turbo_refresh_scroll_tag.yml +17 -11
  246. data/config/action_view_helpers/turbo-rails/drive_helper/turbo_refreshes_with.yml +20 -12
  247. data/config/action_view_helpers/turbo-rails/frames_helper/turbo_frame_tag.yml +54 -33
  248. data/config/action_view_helpers/turbo-rails/includes_helper/turbo_include_tags.yml +9 -6
  249. data/config/action_view_helpers/turbo-rails/streams_action_helper/turbo_stream_action_tag.yml +32 -20
  250. data/config/action_view_helpers/turbo-rails/streams_action_helper/turbo_stream_refresh_tag.yml +18 -11
  251. data/config/action_view_helpers/turbo-rails/streams_helper/turbo_stream.yml +9 -6
  252. data/config/action_view_helpers/turbo-rails/streams_helper/turbo_stream_from.yml +28 -18
  253. data/config/html_elements.yml +597 -0
  254. data/config/options.yml +1 -0
  255. data/config/slots/components.yml +52 -0
  256. data/config/state/kind.yml +61 -0
  257. data/config/state/operators.yml +27 -0
  258. data/config/state/predicates.yml +39 -0
  259. data/config/state/transforms.yml +18 -0
  260. data/config/view_context_methods/actionview/base/annotate_rendered_view_with_filenames.yml +4 -4
  261. data/config/view_context_methods/actionview/base/assign.yml +4 -4
  262. data/config/view_context_methods/actionview/base/assigns.yml +4 -4
  263. data/config/view_context_methods/actionview/base/automatically_disable_submit_tag.yml +4 -4
  264. data/config/view_context_methods/actionview/base/compiled_method_container.yml +4 -4
  265. data/config/view_context_methods/actionview/base/config.yml +4 -4
  266. data/config/view_context_methods/actionview/base/default_form_builder.yml +4 -4
  267. data/config/view_context_methods/actionview/base/default_formats.yml +4 -4
  268. data/config/view_context_methods/actionview/base/field_error_proc.yml +4 -4
  269. data/config/view_context_methods/actionview/base/formats.yml +4 -4
  270. data/config/view_context_methods/actionview/base/in_rendering_context.yml +4 -4
  271. data/config/view_context_methods/actionview/base/locale.yml +4 -4
  272. data/config/view_context_methods/actionview/base/lookup_context.yml +4 -4
  273. data/config/view_context_methods/actionview/base/output_buffer.yml +4 -4
  274. data/config/view_context_methods/actionview/base/prefix_partial_path_with_controller_namespace.yml +4 -4
  275. data/config/view_context_methods/actionview/base/remove_hidden_field_autocomplete.yml +4 -4
  276. data/config/view_context_methods/actionview/base/streaming_completion_on_exception.yml +4 -4
  277. data/config/view_context_methods/actionview/base/view_flow.yml +4 -4
  278. data/config/view_context_methods/actionview/base/view_paths.yml +4 -4
  279. data/config/view_context_methods/actionview/base/view_renderer.yml +4 -4
  280. data/config/view_context_methods/actionview/template/local_assigns.yml +4 -4
  281. data/config/view_context_methods/activemodel/conversion/convert_to_model.yml +4 -4
  282. data/config/view_context_methods/activesupport/benchmarkable/benchmark.yml +4 -4
  283. data/config.yml +1243 -790
  284. data/exe/herb +2 -0
  285. data/ext/herb/error_helpers.c +355 -17
  286. data/ext/herb/error_helpers.h +1 -1
  287. data/ext/herb/extconf.rb +4 -2
  288. data/ext/herb/extension.c +137 -89
  289. data/ext/herb/extension_helpers.c +81 -42
  290. data/ext/herb/extension_helpers.h +4 -1
  291. data/ext/herb/nodes.c +859 -374
  292. data/ext/herb/nodes.h +3 -2
  293. data/ext/herb/parser_options_helpers.c +151 -0
  294. data/ext/herb/parser_options_helpers.h +14 -0
  295. data/herb.gemspec +2 -2
  296. data/lib/herb/3.2/herb.so +0 -0
  297. data/lib/herb/3.3/herb.so +0 -0
  298. data/lib/herb/3.4/herb.so +0 -0
  299. data/lib/herb/4.0/herb.so +0 -0
  300. data/lib/herb/action_view/helper_registry.rb +1358 -62
  301. data/lib/herb/analysis/partial_declaration.rb +140 -0
  302. data/lib/herb/analysis/partial_index.rb +189 -0
  303. data/lib/herb/analysis/partial_resolution.rb +161 -0
  304. data/lib/herb/analysis/partial_resolver.rb +144 -0
  305. data/lib/herb/analysis/project_index.rb +152 -0
  306. data/lib/herb/{action_view → analysis}/render_analyzer.rb +287 -77
  307. data/lib/herb/analysis/render_graph/ancestor_chain.rb +27 -0
  308. data/lib/herb/analysis/render_graph/builder.rb +376 -0
  309. data/lib/herb/analysis/render_graph/call_frame.rb +9 -0
  310. data/lib/herb/analysis/render_graph/call_site_location.rb +23 -0
  311. data/lib/herb/analysis/render_graph/inferred_signature.rb +21 -0
  312. data/lib/herb/analysis/render_graph/partial_call_site.rb +40 -0
  313. data/lib/herb/analysis/render_graph/partial_context.rb +46 -0
  314. data/lib/herb/analysis/render_graph/template_roots.rb +31 -0
  315. data/lib/herb/analysis/render_graph.rb +285 -0
  316. data/lib/herb/analysis/ruby_locals_index/local.rb +25 -0
  317. data/lib/herb/analysis/ruby_locals_index/named_reference.rb +22 -0
  318. data/lib/herb/analysis/ruby_locals_index/offset_table.rb +44 -0
  319. data/lib/herb/analysis/ruby_locals_index/reference_collector.rb +80 -0
  320. data/lib/herb/analysis/ruby_locals_index/state_locals.rb +49 -0
  321. data/lib/herb/analysis/ruby_locals_index.rb +165 -0
  322. data/lib/herb/analysis/ruby_reference.rb +67 -0
  323. data/lib/herb/analysis/template_dependencies/dependency_collector.rb +179 -0
  324. data/lib/herb/analysis/template_dependencies/node_dependency_collector.rb +309 -0
  325. data/lib/herb/analysis/template_dependencies.rb +562 -0
  326. data/lib/herb/ast/erb_render_node.rb +26 -94
  327. data/lib/herb/ast/helpers.rb +90 -10
  328. data/lib/herb/ast/herb_directive_node.rb +18 -0
  329. data/lib/herb/ast/node.rb +32 -2
  330. data/lib/herb/ast/nodes.rb +1368 -105
  331. data/lib/herb/backend.rb +73 -0
  332. data/lib/herb/bootstrap.rb +8 -8
  333. data/lib/herb/cli.rb +550 -32
  334. data/lib/herb/colors.rb +14 -0
  335. data/lib/herb/configuration.rb +71 -35
  336. data/lib/herb/defaults.yml +2 -1
  337. data/lib/herb/dev/assets.rb +57 -0
  338. data/lib/herb/dev/classifier.rb +84 -0
  339. data/lib/herb/dev/embedded.rb +27 -0
  340. data/lib/herb/dev/pipeline.rb +305 -0
  341. data/lib/herb/dev/protocol.rb +221 -0
  342. data/lib/herb/dev/runner.rb +180 -175
  343. data/lib/herb/dev/server.rb +89 -26
  344. data/lib/herb/dev/server_entry.rb +41 -6
  345. data/lib/herb/dev/watcher.rb +181 -0
  346. data/lib/herb/dev.rb +163 -0
  347. data/lib/herb/diagnostic/formatter.rb +88 -0
  348. data/lib/herb/diagnostic.rb +172 -0
  349. data/lib/herb/diff/operation.rb +36 -0
  350. data/lib/herb/diff/result.rb +62 -0
  351. data/lib/herb/diff.rb +10 -0
  352. data/lib/herb/engine/collector.rb +62 -0
  353. data/lib/herb/engine/compiler.rb +387 -113
  354. data/lib/herb/engine/component_tags/constant_resolver.rb +28 -0
  355. data/lib/herb/engine/component_tags/partial_resolver.rb +54 -0
  356. data/lib/herb/engine/component_tags/resolver.rb +32 -0
  357. data/lib/herb/engine/component_tags/visitor.rb +231 -0
  358. data/lib/herb/engine/css_inliner/inliner.rb +101 -0
  359. data/lib/herb/engine/css_inliner/visitor.rb +174 -0
  360. data/lib/herb/engine/errors.rb +122 -0
  361. data/lib/herb/engine/helpers.rb +82 -0
  362. data/lib/herb/engine/inline_render/inliner.rb +122 -0
  363. data/lib/herb/engine/inline_render/visitor.rb +267 -0
  364. data/lib/herb/engine/runtime/entry.rb +62 -0
  365. data/lib/herb/engine/runtime/error_page.rb +362 -0
  366. data/lib/herb/engine/runtime/html_safe_assertions.rb +217 -0
  367. data/lib/herb/engine/runtime/journal/summary.rb +227 -0
  368. data/lib/herb/engine/runtime/journal.rb +379 -0
  369. data/lib/herb/engine/runtime/middleware.rb +212 -0
  370. data/lib/herb/engine/runtime/observations.rb +73 -0
  371. data/lib/herb/engine/runtime/report.rb +204 -0
  372. data/lib/herb/engine/runtime/session.rb +437 -0
  373. data/lib/herb/engine/runtime.rb +21 -0
  374. data/lib/herb/engine/scoped_style/channel.rb +66 -0
  375. data/lib/herb/engine/scoped_style/collector.rb +74 -0
  376. data/lib/herb/engine/scoped_style/visitor.rb +533 -0
  377. data/lib/herb/engine/slots/annotation.rb +98 -0
  378. data/lib/herb/engine/slots/bindings.rb +61 -0
  379. data/lib/herb/engine/slots/callee.rb +118 -0
  380. data/lib/herb/engine/slots/component_definitions.rb +67 -0
  381. data/lib/herb/engine/slots/components/async.rb +24 -0
  382. data/lib/herb/engine/slots/components/base.rb +132 -0
  383. data/lib/herb/engine/slots/components/deferred.rb +81 -0
  384. data/lib/herb/engine/slots/components/fallback.rb +27 -0
  385. data/lib/herb/engine/slots/components/fragment.rb +99 -0
  386. data/lib/herb/engine/slots/components/lazy.rb +24 -0
  387. data/lib/herb/engine/slots/components.rb +52 -0
  388. data/lib/herb/engine/slots/dependencies/channel.rb +72 -0
  389. data/lib/herb/engine/slots/dependencies.rb +269 -0
  390. data/lib/herb/engine/slots/dynamics_compiler.rb +864 -0
  391. data/lib/herb/engine/slots/identifier.rb +35 -0
  392. data/lib/herb/engine/slots/manifest/channel.rb +74 -0
  393. data/lib/herb/engine/slots/manifest/collector.rb +75 -0
  394. data/lib/herb/engine/slots/markers.rb +152 -0
  395. data/lib/herb/engine/slots/render_bindings.rb +141 -0
  396. data/lib/herb/engine/slots/schema_compiler.rb +94 -0
  397. data/lib/herb/engine/slots/state_anchor.rb +94 -0
  398. data/lib/herb/engine/slots/state_compiler.rb +1325 -0
  399. data/lib/herb/engine/slots/state_directives.rb +854 -0
  400. data/lib/herb/engine/slots/state_kinds.rb +54 -0
  401. data/lib/herb/engine/slots/state_operators.rb +36 -0
  402. data/lib/herb/engine/slots/state_overrides.rb +79 -0
  403. data/lib/herb/engine/slots/state_predicates.rb +65 -0
  404. data/lib/herb/engine/slots/state_transforms.rb +42 -0
  405. data/lib/herb/engine/slots/statics.rb +185 -0
  406. data/lib/herb/engine/slots/subtree.rb +82 -0
  407. data/lib/herb/engine/slots/subtree_compiler.rb +255 -0
  408. data/lib/herb/engine/slots/types.rb +42 -0
  409. data/lib/herb/engine/slots/visitor.rb +2267 -0
  410. data/lib/herb/engine/validators/accessibility_validator.rb +3 -3
  411. data/lib/herb/engine/validators/base.rb +36 -0
  412. data/lib/herb/engine/validators/generator_template_validator.rb +39 -0
  413. data/lib/herb/engine/validators/nesting_validator.rb +3 -3
  414. data/lib/herb/engine/validators/render_validator.rb +13 -33
  415. data/lib/herb/engine/validators/security_validator.rb +3 -17
  416. data/lib/herb/engine/validators.rb +43 -0
  417. data/lib/herb/engine/visitors/auto_close_omitted_tags_visitor.rb +48 -0
  418. data/lib/herb/engine/visitors/content_for_visitor.rb +127 -0
  419. data/lib/herb/engine/{debug_visitor.rb → visitors/debug_visitor.rb} +121 -93
  420. data/lib/herb/engine/visitors/html_safe_assertions_visitor.rb +281 -0
  421. data/lib/herb/engine/visitors/instrumentation_visitor.rb +290 -0
  422. data/lib/herb/engine/visitors/optimize_visitor.rb +728 -0
  423. data/lib/herb/engine/visitors/remove_comments_visitor.rb +106 -0
  424. data/lib/herb/engine/visitors/source_attribution_visitor.rb +177 -0
  425. data/lib/herb/engine.rb +218 -259
  426. data/lib/herb/ensure_installed.rb +43 -0
  427. data/lib/herb/errors.rb +646 -157
  428. data/lib/herb/fingerprint.rb +82 -0
  429. data/lib/herb/html/elements.rb +18 -0
  430. data/lib/herb/html/util.rb +21 -2
  431. data/lib/herb/lex_result.rb +0 -10
  432. data/lib/herb/locate.rb +163 -0
  433. data/lib/herb/location.rb +20 -0
  434. data/lib/herb/parse_result.rb +17 -11
  435. data/lib/herb/parser_options.rb +65 -46
  436. data/lib/herb/position.rb +19 -0
  437. data/lib/herb/prism_inspect.rb +1 -4
  438. data/lib/herb/project.rb +28 -15
  439. data/lib/herb/range.rb +5 -0
  440. data/lib/herb/result.rb +2 -2
  441. data/lib/herb/ruby_program.rb +110 -0
  442. data/lib/herb/source_path.rb +232 -0
  443. data/lib/herb/token.rb +14 -3
  444. data/lib/herb/version.rb +1 -1
  445. data/lib/herb/visitor/context/origin.rb +52 -0
  446. data/lib/herb/visitor/context/replacements.rb +59 -0
  447. data/lib/herb/visitor/context.rb +169 -0
  448. data/lib/herb/visitor/context_aware.rb +45 -0
  449. data/lib/herb/visitor/diagnostics.rb +148 -0
  450. data/lib/herb/visitor/experimental.rb +33 -0
  451. data/lib/herb/visitor/parser_option_requirements.rb +151 -0
  452. data/lib/herb/visitor/stack.rb +192 -0
  453. data/lib/herb/visitor.rb +47 -1
  454. data/lib/herb/warnings.rb +25 -0
  455. data/lib/herb.rb +74 -63
  456. data/sig/herb/action_view/helper_registry.rbs +82 -10
  457. data/sig/herb/analysis/partial_declaration.rbs +80 -0
  458. data/sig/herb/analysis/partial_index.rbs +66 -0
  459. data/sig/herb/analysis/partial_resolution.rbs +57 -0
  460. data/sig/herb/analysis/partial_resolver.rbs +76 -0
  461. data/sig/herb/analysis/project_index.rbs +57 -0
  462. data/sig/herb/{action_view → analysis}/render_analyzer.rbs +25 -4
  463. data/sig/herb/analysis/render_graph/ancestor_chain.rbs +22 -0
  464. data/sig/herb/analysis/render_graph/builder.rbs +180 -0
  465. data/sig/herb/analysis/render_graph/call_frame.rbs +26 -0
  466. data/sig/herb/analysis/render_graph/call_site_location.rbs +28 -0
  467. data/sig/herb/analysis/render_graph/inferred_signature.rbs +27 -0
  468. data/sig/herb/analysis/render_graph/partial_call_site.rbs +36 -0
  469. data/sig/herb/analysis/render_graph/partial_context.rbs +31 -0
  470. data/sig/herb/analysis/render_graph/template_roots.rbs +32 -0
  471. data/sig/herb/analysis/render_graph.rbs +83 -0
  472. data/sig/herb/analysis/ruby_locals_index/local.rbs +21 -0
  473. data/sig/herb/analysis/ruby_locals_index/named_reference.rbs +20 -0
  474. data/sig/herb/analysis/ruby_locals_index/offset_table.rbs +26 -0
  475. data/sig/herb/analysis/ruby_locals_index/reference_collector.rbs +40 -0
  476. data/sig/herb/analysis/ruby_locals_index/state_locals.rbs +19 -0
  477. data/sig/herb/analysis/ruby_locals_index.rbs +62 -0
  478. data/sig/herb/analysis/ruby_reference.rbs +28 -0
  479. data/sig/herb/analysis/template_dependencies/dependency_collector.rbs +52 -0
  480. data/sig/herb/analysis/template_dependencies/node_dependency_collector.rbs +81 -0
  481. data/sig/herb/analysis/template_dependencies.rbs +125 -0
  482. data/sig/herb/ast/erb_render_node.rbs +10 -2
  483. data/sig/herb/ast/helpers.rbs +31 -1
  484. data/sig/herb/ast/herb_directive_node.rbs +13 -0
  485. data/sig/herb/ast/node.rbs +9 -0
  486. data/sig/herb/ast/nodes.rbs +668 -89
  487. data/sig/herb/backend.rbs +52 -0
  488. data/sig/herb/bootstrap.rbs +2 -0
  489. data/sig/herb/colors.rbs +3 -0
  490. data/sig/herb/configuration.rbs +27 -3
  491. data/sig/herb/dev/assets.rbs +27 -0
  492. data/sig/herb/dev/classifier.rbs +57 -0
  493. data/sig/herb/dev/embedded.rbs +21 -0
  494. data/sig/herb/dev/pipeline.rbs +118 -0
  495. data/sig/herb/dev/protocol.rbs +78 -0
  496. data/sig/herb/dev/runner.rbs +64 -23
  497. data/sig/herb/dev/server.rbs +49 -22
  498. data/sig/herb/dev/server_entry.rbs +46 -21
  499. data/sig/herb/dev/watcher.rbs +84 -0
  500. data/sig/herb/dev.rbs +58 -0
  501. data/sig/herb/diagnostic/formatter.rbs +28 -0
  502. data/sig/herb/diagnostic.rbs +88 -0
  503. data/sig/herb/diff/operation.rbs +36 -0
  504. data/sig/herb/diff/result.rbs +36 -0
  505. data/sig/herb/diff.rbs +6 -0
  506. data/sig/herb/engine/collector.rbs +48 -0
  507. data/sig/herb/engine/compiler.rbs +74 -24
  508. data/sig/herb/engine/component_tags/constant_resolver.rbs +19 -0
  509. data/sig/herb/engine/component_tags/partial_resolver.rbs +30 -0
  510. data/sig/herb/engine/component_tags/resolver.rbs +25 -0
  511. data/sig/herb/engine/component_tags/visitor.rbs +69 -0
  512. data/sig/herb/engine/css_inliner/inliner.rbs +65 -0
  513. data/sig/herb/engine/css_inliner/visitor.rbs +87 -0
  514. data/sig/herb/engine/errors.rbs +68 -0
  515. data/sig/herb/engine/helpers.rbs +28 -0
  516. data/sig/herb/engine/inline_render/inliner.rbs +39 -0
  517. data/sig/herb/engine/inline_render/visitor.rbs +104 -0
  518. data/sig/herb/engine/runtime/entry.rbs +43 -0
  519. data/sig/herb/engine/runtime/error_page.rbs +115 -0
  520. data/sig/herb/engine/runtime/html_safe_assertions.rbs +99 -0
  521. data/sig/herb/engine/runtime/journal/summary.rbs +172 -0
  522. data/sig/herb/engine/runtime/journal.rbs +126 -0
  523. data/sig/herb/engine/runtime/middleware.rbs +96 -0
  524. data/sig/herb/engine/runtime/observations.rbs +38 -0
  525. data/sig/herb/engine/runtime/report.rbs +97 -0
  526. data/sig/herb/engine/runtime/session.rbs +233 -0
  527. data/sig/herb/engine/runtime.rbs +14 -0
  528. data/sig/herb/engine/scoped_style/channel.rbs +45 -0
  529. data/sig/herb/engine/scoped_style/collector.rbs +45 -0
  530. data/sig/herb/engine/scoped_style/visitor.rbs +220 -0
  531. data/sig/herb/engine/slots/annotation.rbs +72 -0
  532. data/sig/herb/engine/slots/bindings.rbs +34 -0
  533. data/sig/herb/engine/slots/callee.rbs +62 -0
  534. data/sig/herb/engine/slots/component_definitions.rbs +19 -0
  535. data/sig/herb/engine/slots/components/async.rbs +20 -0
  536. data/sig/herb/engine/slots/components/base.rbs +60 -0
  537. data/sig/herb/engine/slots/components/deferred.rbs +29 -0
  538. data/sig/herb/engine/slots/components/fallback.rbs +21 -0
  539. data/sig/herb/engine/slots/components/fragment.rbs +34 -0
  540. data/sig/herb/engine/slots/components/lazy.rbs +20 -0
  541. data/sig/herb/engine/slots/components.rbs +30 -0
  542. data/sig/herb/engine/slots/dependencies/channel.rbs +51 -0
  543. data/sig/herb/engine/slots/dependencies.rbs +94 -0
  544. data/sig/herb/engine/slots/dynamics_compiler.rbs +352 -0
  545. data/sig/herb/engine/slots/identifier.rbs +19 -0
  546. data/sig/herb/engine/slots/manifest/channel.rbs +49 -0
  547. data/sig/herb/engine/slots/manifest/collector.rbs +45 -0
  548. data/sig/herb/engine/slots/markers.rbs +99 -0
  549. data/sig/herb/engine/slots/render_bindings.rbs +69 -0
  550. data/sig/herb/engine/slots/schema_compiler.rbs +62 -0
  551. data/sig/herb/engine/slots/state_anchor.rbs +41 -0
  552. data/sig/herb/engine/slots/state_compiler.rbs +258 -0
  553. data/sig/herb/engine/slots/state_directives.rbs +278 -0
  554. data/sig/herb/engine/slots/state_kinds.rbs +24 -0
  555. data/sig/herb/engine/slots/state_operators.rbs +19 -0
  556. data/sig/herb/engine/slots/state_overrides.rbs +33 -0
  557. data/sig/herb/engine/slots/state_predicates.rbs +16 -0
  558. data/sig/herb/engine/slots/state_transforms.rbs +15 -0
  559. data/sig/herb/engine/slots/statics.rbs +67 -0
  560. data/sig/herb/engine/slots/subtree.rbs +49 -0
  561. data/sig/herb/engine/slots/subtree_compiler.rbs +130 -0
  562. data/sig/herb/engine/slots/types.rbs +46 -0
  563. data/sig/herb/engine/slots/visitor.rbs +603 -0
  564. data/sig/herb/engine/validators/accessibility_validator.rbs +1 -1
  565. data/sig/herb/engine/validators/base.rbs +28 -0
  566. data/sig/herb/engine/validators/generator_template_validator.rbs +19 -0
  567. data/sig/herb/engine/validators/nesting_validator.rbs +1 -1
  568. data/sig/herb/engine/validators/render_validator.rbs +2 -6
  569. data/sig/herb/engine/validators/security_validator.rbs +1 -3
  570. data/sig/herb/engine/validators.rbs +21 -0
  571. data/sig/herb/engine/visitors/auto_close_omitted_tags_visitor.rbs +26 -0
  572. data/sig/herb/engine/visitors/content_for_visitor.rbs +52 -0
  573. data/sig/herb/engine/{debug_visitor.rbs → visitors/debug_visitor.rbs} +26 -15
  574. data/sig/herb/engine/visitors/html_safe_assertions_visitor.rbs +100 -0
  575. data/sig/herb/engine/visitors/instrumentation_visitor.rbs +111 -0
  576. data/sig/herb/engine/visitors/optimize_visitor.rbs +246 -0
  577. data/sig/herb/engine/visitors/remove_comments_visitor.rbs +66 -0
  578. data/sig/herb/engine/visitors/source_attribution_visitor.rbs +90 -0
  579. data/sig/herb/engine.rbs +47 -41
  580. data/sig/herb/ensure_installed.rbs +9 -0
  581. data/sig/herb/errors.rbs +293 -0
  582. data/sig/herb/fingerprint.rbs +37 -0
  583. data/sig/herb/html/elements.rbs +19 -0
  584. data/sig/herb/html/util.rbs +15 -1
  585. data/sig/herb/lex_result.rbs +0 -6
  586. data/sig/herb/locate.rbs +89 -0
  587. data/sig/herb/location.rbs +12 -0
  588. data/sig/herb/parse_result.rbs +10 -8
  589. data/sig/herb/parser_options.rbs +47 -21
  590. data/sig/herb/position.rbs +11 -0
  591. data/sig/herb/range.rbs +3 -0
  592. data/sig/herb/ruby_program.rbs +51 -0
  593. data/sig/herb/source_path.rbs +132 -0
  594. data/sig/herb/token.rbs +5 -2
  595. data/sig/herb/visitor/context/origin.rbs +51 -0
  596. data/sig/herb/visitor/context/replacements.rbs +39 -0
  597. data/sig/herb/visitor/context.rbs +83 -0
  598. data/sig/herb/visitor/context_aware.rbs +32 -0
  599. data/sig/herb/visitor/diagnostics.rbs +82 -0
  600. data/sig/herb/visitor/experimental.rbs +23 -0
  601. data/sig/herb/visitor/parser_option_requirements.rbs +76 -0
  602. data/sig/herb/visitor/stack.rbs +91 -0
  603. data/sig/herb/visitor.rbs +22 -0
  604. data/sig/herb/warnings.rbs +10 -0
  605. data/sig/herb.rbs +27 -10
  606. data/sig/serialized_ast_errors.rbs +58 -1
  607. data/sig/serialized_ast_nodes.rbs +59 -2
  608. data/src/analyze/action_view/attribute_extraction_helpers.c +73 -36
  609. data/src/analyze/action_view/generated_handlers.c +37 -1
  610. data/src/analyze/action_view/generated_handlers.h +2 -1
  611. data/src/analyze/action_view/helper_registry.c +1353 -58
  612. data/src/analyze/action_view/registry.c +10 -17
  613. data/src/analyze/action_view/stylesheet_link_tag.c +40 -0
  614. data/src/analyze/action_view/tag_helper_node_builders.c +63 -3
  615. data/src/analyze/action_view/tag_helpers.c +497 -111
  616. data/src/analyze/analyze.c +306 -89
  617. data/src/analyze/analyze_helpers.c +502 -243
  618. data/src/analyze/analyzed_ruby.c +2 -0
  619. data/src/analyze/builders.c +80 -51
  620. data/src/analyze/conditional_elements.c +13 -8
  621. data/src/analyze/conditional_open_tags.c +11 -5
  622. data/src/analyze/control_type.c +30 -5
  623. data/src/analyze/herb_directives.c +701 -0
  624. data/src/analyze/invalid_structures.c +11 -7
  625. data/src/analyze/iteration_nodes.c +306 -0
  626. data/src/analyze/missing_end.c +116 -32
  627. data/src/analyze/parse_errors.c +8 -3
  628. data/src/analyze/postfix_conditionals.c +98 -63
  629. data/src/analyze/prism_annotate.c +45 -13
  630. data/src/analyze/render_nodes.c +345 -123
  631. data/src/analyze/strict_locals.c +30 -26
  632. data/src/analyze/ternary_conditionals.c +95 -70
  633. data/src/analyze/transform.c +43 -1
  634. data/src/ast/ast_node.c +3 -13
  635. data/src/ast/ast_nodes.c +914 -113
  636. data/src/ast/ast_pretty_print.c +166 -3
  637. data/src/diff/herb_diff.c +8 -0
  638. data/src/diff/herb_diff_attributes.c +1 -0
  639. data/src/diff/herb_diff_children.c +4 -3
  640. data/src/diff/herb_diff_helpers.c +7 -1
  641. data/src/diff/herb_diff_nodes.c +186 -71
  642. data/src/diff/herb_hash_tree.c +99 -1
  643. data/src/errors.c +1096 -128
  644. data/src/extract.c +227 -144
  645. data/src/herb.c +30 -11
  646. data/src/include/analyze/action_view/attribute_extraction_helpers.h +1 -1
  647. data/src/include/analyze/action_view/helper_registry.h +28 -4
  648. data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
  649. data/src/include/analyze/action_view/tag_helper_node_builders.h +7 -0
  650. data/src/include/analyze/analyze.h +11 -22
  651. data/src/include/analyze/analyzed_ruby.h +25 -0
  652. data/src/include/analyze/builders.h +16 -0
  653. data/src/include/analyze/helpers.h +25 -24
  654. data/src/include/analyze/herb_directive_kinds.h +41 -0
  655. data/src/include/analyze/herb_directives.h +14 -0
  656. data/src/include/analyze/iteration_nodes.h +11 -0
  657. data/src/include/analyze/prism_annotate.h +3 -3
  658. data/src/include/analyze/ternary_conditionals.h +2 -0
  659. data/src/include/ast/ast_node.h +1 -5
  660. data/src/include/ast/ast_nodes.h +78 -3
  661. data/src/include/ast/ast_pretty_print.h +1 -1
  662. data/src/include/diff/herb_diff.h +11 -0
  663. data/src/include/errors.h +156 -39
  664. data/src/include/extract.h +11 -0
  665. data/src/include/herb.h +6 -0
  666. data/src/include/lexer/erb_openers.h +29 -0
  667. data/src/include/lexer/lexer.h +1 -0
  668. data/src/include/lexer/lexer_peek_helpers.h +8 -1
  669. data/src/include/lexer/lexer_struct.h +4 -0
  670. data/src/include/lexer/token.h +3 -0
  671. data/src/include/lexer/token_struct.h +8 -6
  672. data/src/include/lib/hb_allocator.h +2 -1
  673. data/src/include/lib/hb_array.h +2 -0
  674. data/src/include/lib/hb_foreach.h +1 -1
  675. data/src/include/lib/hb_string.h +7 -0
  676. data/src/include/parser/dot_notation.h +1 -1
  677. data/src/include/parser/foreign_content_elements.h +32 -0
  678. data/src/include/parser/parser.h +16 -30
  679. data/src/include/parser/parser_helpers.h +13 -11
  680. data/src/include/parser/parser_options.h +41 -0
  681. data/src/include/prism/herb_prism_node.h +6 -1
  682. data/src/include/prism/ruby_parser.h +6 -0
  683. data/src/include/util/html_elements.h +85 -0
  684. data/src/include/util/html_util.h +1 -0
  685. data/src/include/version.h +1 -1
  686. data/src/lexer/lexer_peek_helpers.c +15 -1
  687. data/src/lexer/token.c +83 -1
  688. data/src/lexer.c +228 -12
  689. data/src/lib/hb_allocator.c +2 -0
  690. data/src/lib/hb_array.c +26 -0
  691. data/src/lib/hb_string.c +26 -0
  692. data/src/main.c +1 -1
  693. data/src/parser/dot_notation.c +4 -3
  694. data/src/parser/match_tags.c +66 -1
  695. data/src/parser/parser_helpers.c +69 -37
  696. data/src/parser.c +606 -383
  697. data/src/parser_options_defaults.c +30 -0
  698. data/src/prism/prism_helpers.c +94 -0
  699. data/src/prism/ruby_parser.c +49 -0
  700. data/src/util/html_util.c +11 -58
  701. data/src/visitor.c +77 -1
  702. data/templates/ext/herb/error_helpers.c.erb +1 -1
  703. data/templates/ext/herb/nodes.c.erb +19 -14
  704. data/templates/ext/herb/nodes.h.erb +2 -1
  705. data/templates/ext/herb/parser_options_helpers.c.erb +69 -0
  706. data/templates/ext/herb/parser_options_helpers.h.erb +11 -0
  707. data/templates/java/nodes.c.erb +21 -17
  708. data/templates/java/nodes.h.erb +3 -2
  709. data/templates/java/org/herb/ParserOptions.java.erb +24 -0
  710. data/templates/java/org/herb/ast/HelperRegistry.java.erb +67 -31
  711. data/templates/java/org/herb/ast/HelperType.java.erb +29 -0
  712. data/templates/java/org/herb/ast/Nodes.java.erb +11 -7
  713. data/templates/java/parser_options_helpers.c.erb +45 -0
  714. data/templates/java/parser_options_helpers.h.erb +10 -0
  715. data/templates/javascript/packages/client/src/state-kinds.ts.erb +49 -0
  716. data/templates/javascript/packages/client/src/state-operators.ts.erb +15 -0
  717. data/templates/javascript/packages/client/src/state-predicates.ts.erb +27 -0
  718. data/templates/javascript/packages/client/src/state-transforms.ts.erb +19 -0
  719. data/templates/javascript/packages/core/src/action-view-helpers.ts.erb +47 -0
  720. data/templates/javascript/packages/core/src/built-in-components.ts.erb +67 -0
  721. data/templates/javascript/packages/core/src/errors.ts.erb +9 -3
  722. data/templates/javascript/packages/core/src/foreign-content-elements.ts.erb +18 -0
  723. data/templates/javascript/packages/core/src/html-constants.ts.erb +32 -0
  724. data/templates/javascript/packages/core/src/html-elements.ts.erb +41 -0
  725. data/templates/javascript/packages/core/src/node-type-guards.ts.erb +11 -7
  726. data/templates/javascript/packages/core/src/nodes.ts.erb +103 -20
  727. data/templates/javascript/packages/core/src/parser-options.ts.erb +41 -0
  728. data/templates/javascript/packages/core/src/visitor.ts.erb +1 -1
  729. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +3 -3
  730. data/templates/javascript/packages/node/extension/nodes.cpp.erb +18 -13
  731. data/templates/javascript/packages/node/extension/nodes.h.erb +3 -3
  732. data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +41 -0
  733. data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +12 -0
  734. data/templates/lib/herb/action_view/helper_registry.rb.erb +77 -3
  735. data/templates/lib/herb/ast/nodes.rb.erb +16 -6
  736. data/templates/lib/herb/engine/slots/component_definitions.rb.erb +38 -0
  737. data/templates/lib/herb/engine/slots/state_kinds.rb.erb +37 -0
  738. data/templates/lib/herb/engine/slots/state_operators.rb.erb +26 -0
  739. data/templates/lib/herb/engine/slots/state_predicates.rb.erb +39 -0
  740. data/templates/lib/herb/engine/slots/state_transforms.rb.erb +27 -0
  741. data/templates/lib/herb/errors.rb.erb +34 -6
  742. data/templates/lib/herb/html/elements.rb.erb +12 -0
  743. data/templates/lib/herb/parser_options.rb.erb +32 -0
  744. data/templates/lib/herb/visitor.rb.erb +7 -1
  745. data/templates/rust/herb-printer/src/printer_visitor.rs.erb +14 -0
  746. data/templates/rust/src/action_view_helpers.rs.erb +38 -0
  747. data/templates/rust/src/ast/nodes.rs.erb +21 -31
  748. data/templates/rust/src/errors.rs.erb +1 -1
  749. data/templates/rust/src/nodes.rs.erb +58 -26
  750. data/templates/rust/src/parser_options.rs.erb +16 -0
  751. data/templates/rust/src/prism/generated_deserialize.rs.erb +109 -0
  752. data/templates/rust/src/prism/generated_prettyprint.rs.erb +153 -0
  753. data/templates/rust/src/union_types.rs.erb +7 -1
  754. data/templates/rust/src/visitor.rs.erb +1 -1
  755. data/templates/src/analyze/action_view/helper_registry.c.erb +22 -0
  756. data/templates/src/analyze/missing_end.c.erb +13 -5
  757. data/templates/src/ast/ast_nodes.c.erb +41 -2
  758. data/templates/src/diff/herb_diff_nodes.c.erb +44 -8
  759. data/templates/src/errors.c.erb +8 -3
  760. data/templates/src/include/analyze/action_view/helper_registry.h.erb +19 -0
  761. data/templates/src/include/analyze/herb_directive_kinds.h.erb +25 -0
  762. data/templates/src/include/errors.h.erb +3 -1
  763. data/templates/src/include/parser/foreign_content_elements.h.erb +23 -0
  764. data/templates/src/include/parser/parser_options.h.erb +21 -0
  765. data/templates/src/include/util/html_elements.h.erb +28 -0
  766. data/templates/src/parser_options_defaults.c.erb +9 -0
  767. data/templates/template.rb +564 -9
  768. data/templates/wasm/error_helpers.cpp.erb +4 -4
  769. data/templates/wasm/nodes.cpp.erb +17 -27
  770. data/templates/wasm/nodes.h.erb +3 -3
  771. data/templates/wasm/parser_options_helpers.cpp.erb +25 -0
  772. data/templates/wasm/parser_options_helpers.h.erb +12 -0
  773. metadata +306 -27
  774. data/config/action_view_helpers/actionview/form_helper/button.yml +0 -38
  775. data/config/action_view_helpers/actionview/form_helper/submit.yml +0 -35
  776. data/lib/herb/ast.rb +0 -7
  777. data/lib/herb/diff_operation.rb +0 -34
  778. data/lib/herb/diff_result.rb +0 -59
  779. data/lib/herb/engine/error_formatter.rb +0 -432
  780. data/lib/herb/engine/parser_error_overlay.rb +0 -773
  781. data/lib/herb/engine/validation_error_overlay.rb +0 -182
  782. data/lib/herb/engine/validation_errors.rb +0 -65
  783. data/lib/herb/engine/validator.rb +0 -80
  784. data/sig/herb/ast.rbs +0 -6
  785. data/sig/herb/diff_operation.rbs +0 -34
  786. data/sig/herb/diff_result.rbs +0 -34
  787. data/sig/herb/engine/debug.rbs +0 -38
  788. data/sig/herb/engine/error_formatter.rbs +0 -47
  789. data/sig/herb/engine/parser_error_overlay.rbs +0 -41
  790. data/sig/herb/engine/validation_error_overlay.rbs +0 -35
  791. data/sig/herb/engine/validation_errors.rbs +0 -45
  792. data/sig/herb/engine/validator.rbs +0 -41
  793. data/sig/herb_c_extension.rbs +0 -10
@@ -0,0 +1,864 @@
1
+ # frozen_string_literal: true
2
+ # typed: false
3
+
4
+ require_relative "../../../herb"
5
+ require_relative "../../engine"
6
+ require_relative "visitor"
7
+ require_relative "state_overrides"
8
+
9
+ module Herb
10
+ class Engine
11
+ module Slots
12
+ # Compiles a template into Ruby that returns its dynamic values rather than its HTML.
13
+ #
14
+ # `Herb::Engine` answers "what does this template render". This answers "what did the template
15
+ # evaluate to render it", which is the half that changes when state changes:
16
+ #
17
+ # require "herb/engine/slots/dynamics_compiler"
18
+ #
19
+ # source = Herb::Engine::Slots::DynamicsCompiler.new(%(<h1><%= @title %></h1>)).src
20
+ # view.instance_eval(source)
21
+ # #=> { template: "app/views/posts/index.html.erb", version: "fd3dfd36", slots: { 0 => "Hello" } }
22
+ #
23
+ # The names follow Phoenix LiveView, which splits a rendered template into its `static` strings
24
+ # and its `dynamic` values for the same reason. A template's statics never change between
25
+ # renders, so anything re-rendering on a state change only has to send the dynamics.
26
+ #
27
+ # This is a separate compiler rather than an option on `Herb::Engine` because that class is a
28
+ # drop-in for `Erubi::Engine` and has to keep answering the way Erubi does.
29
+ #
30
+ # ## Values name the template they came from
31
+ #
32
+ # An index means nothing on its own, because it is a position in one template's numbering, and
33
+ # it means something else in the next template. So the values arrive wrapped in the identifier
34
+ # and version `Visitor` gave the markers, which is the same pair the page carries in
35
+ # `<!--herb-region:ID:VERSION-->`. A client holding both can tell that they were compiled
36
+ # together, and a version that no longer matches says the indices cannot be trusted.
37
+ #
38
+ # ## The shape follows the template, not the render
39
+ #
40
+ # Every insertion point owns an index, decided while compiling and the same on every render.
41
+ # Control flow owns one too, because what it decided is itself a value that changes:
42
+ #
43
+ # <% if admin? %><%= secret %><% else %><%= public %><% end %>
44
+ # #=> { 0 => { branch: 0, slots: { 1 => "s" } } } when admin?
45
+ # #=> { 0 => { branch: 1, slots: { 2 => "p" } } } otherwise
46
+ #
47
+ # Both branches keep their own indices, so a condition flipping changes which indices are
48
+ # present and never what an index means.
49
+ #
50
+ # ## Absent means it did not run
51
+ #
52
+ # A key is missing when the code that would have filled it never ran, which is the same thing
53
+ # the rendered markup says by not being there. Nothing has to be sent about a branch that was
54
+ # not taken, and nothing can be learned about one either.
55
+ #
56
+ # A conditional and a collection are always present, because both are evaluated on every render
57
+ # even when they produce nothing. A conditional that matched no branch is `{ branch: nil }` and
58
+ # an empty collection is `{ items: {} }`, both of which the client has to be told.
59
+ #
60
+ # ## Collections group by item
61
+ #
62
+ # A collection holds its items in render order, each item carrying the slots inside it:
63
+ #
64
+ # <% users.each do |user| %><%= user.first %> <%= user.last %><% end %>
65
+ # #=> { 0 => { items: { 1 => { 1 => "Marco", 2 => "Roth" },
66
+ # 2 => { 1 => "Joe", 2 => "Doe" } } } }
67
+ #
68
+ # Grouping the other way would give one list per slot and leave the client to zip them back
69
+ # together, which it cannot do once an item is inserted rather than appended.
70
+ #
71
+ # An item is keyed by the key its template declares, through `herb-key` or `id` or a
72
+ # `<%# herb:key %>` directive, which is what makes it survive being reordered. `Visitor`
73
+ # decides what that key is and this evaluates it, so an item arrives under the same key the
74
+ # marker around it carries. A collection that declares none falls back to position.
75
+ #
76
+ # ## A partial keeps its own values
77
+ #
78
+ # `<%= render "posts/card" %>` evaluates to that partial's own values, so the slot holding it
79
+ # holds a whole payload rather than a string:
80
+ #
81
+ # { template: "index.html.erb", version: "a1b2c3d4",
82
+ # slots: { 0 => { template: "_card.html.erb", version: "e5f6a7b8", slots: { 0 => "Marco" } } } }
83
+ #
84
+ # Nothing else would work, because the partial numbers its slots in its own template and the
85
+ # page marks them out as their own region. Coercing it to a string would flatten a partial's
86
+ # values into the markup they were meant to replace, and a partial rendering a partial is
87
+ # ordinary, so this nests as deeply as the template does.
88
+ #
89
+ # ## Escaping
90
+ #
91
+ # A value carries the escaping of the place it was written, because that is where it is going
92
+ # back to. The same expression is escaped differently in an attribute, in a `<script>`, and in
93
+ # text, so the tree is left intact and the compiler decides as it normally would.
94
+ #
95
+ # ## Blocks
96
+ #
97
+ # A tag that takes a block, such as `<%= form_with do |f| %>`, owns an entry holding everything
98
+ # the block rendered, because the helper wraps that output in markup of its own that only the
99
+ # helper can produce. What the template wrote inside the block keeps its own indices alongside:
100
+ #
101
+ # <%= form_with(model: @user) do |f| %><%= f.label %><% end %>
102
+ # #=> { 0 => "<form>Name</form>", 1 => "Name" }
103
+ #
104
+ # So a caller that can address slot 1 sends a value, and one that cannot falls back to slot 0
105
+ # and the whole block. Slot 1 is inside slot 0, which the client already has to reason about
106
+ # for conditionals and collections.
107
+ #
108
+ # A block yielding more than once is the exception, since one index cannot stand for the several
109
+ # values its interior took. `each` and the other iterations are compiled as collections for that
110
+ # reason, and a helper that yields repeatedly reports the last value its interior took.
111
+ #
112
+ class DynamicsCompiler < Herb::Engine
113
+ BUFFER = "__herb_dynamics" #: String
114
+ BLOCK_BUFFER = "__herb_block" #: String
115
+ SLOT_BUFFER = "__herb_slot" #: String
116
+ SCOPE_BUFFER = "__herb_scope" #: String
117
+ ITEMS_BUFFER = "__herb_items" #: String
118
+ KEY_BUFFER = "__herb_key" #: String
119
+ OCCURRENCE_BUFFER = "__herb_occurrence" #: String
120
+
121
+ BRANCHING_NODES = [
122
+ "AST_ERB_IF_NODE",
123
+ "AST_ERB_UNLESS_NODE",
124
+ "AST_ERB_ELSE_NODE",
125
+ "AST_ERB_WHEN_NODE",
126
+ "AST_ERB_IN_NODE"
127
+ ].freeze #: Array[String]
128
+
129
+ class Compiler < Herb::Engine::Compiler
130
+ #: (untyped, ?Hash[Symbol, untyped]) -> void
131
+ def initialize(engine, options = {})
132
+ super
133
+
134
+ @slot_visitor = engine.slot_visitor
135
+ @current_node = nil
136
+ @current_attribute = nil
137
+ @current_rcdata = nil
138
+ @rendering = false
139
+ @capturing_part = false
140
+ @block_depth = 0
141
+
142
+ branch_counts = {} #: Hash[Integer, Integer]
143
+ branch_owner = {} #: Hash[untyped, Integer]
144
+
145
+ @branch_counts = branch_counts
146
+ @branch_owner = branch_owner.compare_by_identity
147
+ end
148
+
149
+ #: (untyped) -> void
150
+ def visit_html_attribute_node(node)
151
+ previous = @current_attribute
152
+ @current_attribute = node
153
+
154
+ super
155
+ ensure
156
+ @current_attribute = previous
157
+ end
158
+
159
+ #: (untyped) -> void
160
+ def visit_html_element_node(node)
161
+ index = @slot_visitor.index_for(node)
162
+ previous = @current_rcdata
163
+ slot = index ? @slot_visitor.slots[index] : nil #: untyped
164
+
165
+ @current_rcdata = node if slot&.type == :raw_text_interpolation
166
+
167
+ if slot&.type == :keyed
168
+ @tokens << [:scope, "", nil, [:open_keyed, index, slot.key_expression]]
169
+
170
+ begin
171
+ super
172
+ ensure
173
+ @tokens << [:scope, "", nil, [:close_keyed, index]]
174
+ end
175
+ else
176
+ super
177
+ end
178
+ ensure
179
+ @current_rcdata = previous
180
+ end
181
+
182
+ #: (untyped) -> void
183
+ def visit_erb_content_node(node)
184
+ previous = @current_node
185
+ @current_node = node
186
+
187
+ super
188
+ ensure
189
+ @current_node = previous
190
+ end
191
+
192
+ #: (untyped) -> void
193
+ def visit_ruby_literal_node(node)
194
+ previous = @current_node
195
+ @current_node = node
196
+
197
+ super
198
+ ensure
199
+ @current_node = previous
200
+ end
201
+
202
+ #: (untyped) -> void
203
+ def visit_erb_yield_node(node)
204
+ previous = @current_node
205
+ @current_node = node
206
+
207
+ super
208
+ ensure
209
+ @current_node = previous
210
+ end
211
+
212
+ #: (untyped) -> void
213
+ def visit_erb_render_node(node)
214
+ previous = @current_node
215
+ @current_node = node
216
+ @rendering = node.end_node.nil?
217
+
218
+ super
219
+ ensure
220
+ @current_node = previous
221
+ @rendering = false
222
+ end
223
+
224
+ #: (untyped) { () -> void } -> void
225
+ def visit_erb_control_node(node, &block)
226
+ return super unless block
227
+ return super unless branch?(node)
228
+
229
+ index = @branch_owner[node]
230
+
231
+ branched = lambda do
232
+ @tokens << [:scope, "", nil, [:branch, index, next_branch(index)]]
233
+
234
+ yield
235
+ end
236
+
237
+ super(node, &branched)
238
+ end
239
+
240
+ #: (untyped) -> void
241
+ def visit_erb_if_node(node)
242
+ conditional(node) { super }
243
+ end
244
+
245
+ #: (untyped) -> void
246
+ def visit_erb_unless_node(node)
247
+ conditional(node) { super }
248
+ end
249
+
250
+ #: (untyped) -> void
251
+ def visit_erb_case_node(node)
252
+ conditional(node) { super }
253
+ end
254
+
255
+ #: (untyped) -> void
256
+ def visit_erb_case_match_node(node)
257
+ conditional(node) { super }
258
+ end
259
+
260
+ #: (untyped) -> void
261
+ def visit_erb_iteration_block_node(node)
262
+ collection(node) do |index|
263
+ visit_erb_control_node(node) do
264
+ item(index) do
265
+ visit_all(node.body)
266
+
267
+ visit(node.rescue_clause)
268
+ visit(node.else_clause)
269
+ visit(node.ensure_clause)
270
+ end
271
+
272
+ visit(node.end_node)
273
+ end
274
+ end
275
+ end
276
+
277
+ #: (untyped) -> void
278
+ def visit_erb_for_node(node)
279
+ iteration(node, :statements)
280
+ end
281
+
282
+ #: (untyped) -> void
283
+ def visit_erb_while_node(node)
284
+ iteration(node, :statements)
285
+ end
286
+
287
+ #: (untyped) -> void
288
+ def visit_erb_until_node(node)
289
+ iteration(node, :statements)
290
+ end
291
+
292
+ #: (untyped) -> void
293
+ def visit_erb_block_node(node)
294
+ return super unless output_block?(node)
295
+
296
+ opening = node.tag_opening.value
297
+
298
+ return super if erb_escaped?(opening)
299
+
300
+ should_escape = should_escape_output?(opening)
301
+ index = claim(node)
302
+
303
+ @tokens << [
304
+ should_escape ? :expr_block_escaped : :expr_block,
305
+ node.content.value.strip,
306
+ current_context,
307
+ index
308
+ ]
309
+
310
+ @last_trim_consumed_newline = false
311
+ @trim_next_whitespace = true if right_trim?(node)
312
+
313
+ @block_depth += 1
314
+
315
+ begin
316
+ visit_all(node.body)
317
+ ensure
318
+ @block_depth -= 1
319
+ end
320
+
321
+ visit_erb_block_end_node(node.end_node, escaped: should_escape)
322
+ end
323
+
324
+ #: () -> void
325
+ def generate_output
326
+ @engine.send(:capture_occurrence)
327
+
328
+ optimize_tokens(@tokens).each do |type, value, context, extra|
329
+ case type
330
+ when :text then @engine.send(:add_text, value)
331
+ when :code then @engine.send(:add_code, value)
332
+ when :scope then @engine.send(:add_scope, *extra)
333
+ when :dynamic
334
+ index, escaped, nested = extra
335
+
336
+ @engine.send(:add_dynamic, value, context, index, escaped, nested: nested)
337
+ when :expr_block, :expr_block_escaped
338
+ @engine.send(:add_dynamic_block, value, extra, type == :expr_block_escaped)
339
+ when :expr_block_end
340
+ @engine.send(:add_expression_block_end, value, escaped: extra)
341
+ end
342
+ end
343
+ end
344
+
345
+ private
346
+
347
+ #: (untyped) -> Integer?
348
+ def claim(node)
349
+ return nil if @capturing_part
350
+
351
+ @slot_visitor.index_for(@current_attribute || @current_rcdata || node)
352
+ end
353
+
354
+ #: (String) -> void
355
+ def add_expression(code)
356
+ @tokens << [:dynamic, code, current_context, [claim(@current_node), false, @rendering]]
357
+ @last_trim_consumed_newline = false
358
+ end
359
+
360
+ #: (String) -> void
361
+ def add_expression_escaped(code)
362
+ @tokens << [:dynamic, code, current_context, [claim(@current_node), true, @rendering]]
363
+ @last_trim_consumed_newline = false
364
+ end
365
+
366
+ #: (untyped) -> bool
367
+ def output_block?(node)
368
+ node.tag_opening.value.include?("=")
369
+ end
370
+
371
+ #: (untyped) -> bool
372
+ def branch?(node)
373
+ @branch_owner.key?(node)
374
+ end
375
+
376
+ #: (Integer) -> Integer
377
+ def next_branch(index)
378
+ count = @branch_counts[index] || 0
379
+ @branch_counts[index] = count + 1
380
+
381
+ count
382
+ end
383
+
384
+ #: (untyped) { () -> void } -> void
385
+ def conditional(node)
386
+ return yield if branch?(node)
387
+
388
+ if @current_attribute || @current_rcdata
389
+ return yield if @capturing_part
390
+
391
+ index = claim(node)
392
+
393
+ return yield unless index
394
+
395
+ @capturing_part = true
396
+ @tokens << [:scope, "", nil, [:part_open]]
397
+
398
+ yield
399
+
400
+ @tokens << [:scope, "", nil, [:part_close, index]]
401
+ @capturing_part = false
402
+
403
+ return
404
+ end
405
+
406
+ index = claim(node)
407
+
408
+ return yield unless index
409
+
410
+ own_branches(node, index)
411
+
412
+ @tokens << [:scope, "", nil, [:open_conditional, index]]
413
+
414
+ yield
415
+
416
+ @tokens << [:scope, "", nil, [:close_conditional, index]]
417
+ end
418
+
419
+ #: (untyped, Integer) -> void
420
+ def own_branches(node, index)
421
+ return unless node
422
+
423
+ @branch_owner[node] = index if BRANCHING_NODES.include?(node.type.to_s)
424
+
425
+ [:subsequent, :else_clause, :conditions].each do |property|
426
+ next unless node.respond_to?(property)
427
+
428
+ value = node.send(property)
429
+
430
+ case value
431
+ when Array then value.each { |child| own_branches(child, index) }
432
+ when nil then next
433
+ else own_branches(value, index)
434
+ end
435
+ end
436
+ end
437
+
438
+ #: (untyped) { (Integer?) -> void } -> void
439
+ def collection(node)
440
+ index = claim(node)
441
+
442
+ return yield(nil) unless index
443
+
444
+ @tokens << [:scope, "", nil, [:open_collection, index]]
445
+
446
+ yield(index)
447
+
448
+ @tokens << [:scope, "", nil, [:close_collection, index]]
449
+ end
450
+
451
+ #: (Integer?) { () -> void } -> void
452
+ def item(index)
453
+ return yield unless index
454
+
455
+ @tokens << [:scope, "", nil, [:item_begin, index, item_key(index)]]
456
+
457
+ yield
458
+
459
+ @tokens << [:scope, "", nil, [:item_end, index]]
460
+ end
461
+
462
+ #: (Integer) -> String?
463
+ def item_key(index)
464
+ @slot_visitor.slots[index]&.key_expression
465
+ end
466
+
467
+ #: (untyped, Symbol) -> void
468
+ def iteration(node, part)
469
+ collection(node) do |index|
470
+ visit_erb_control_node(node) do
471
+ item(index) do
472
+ visit_all(node.send(part) || [])
473
+ end
474
+
475
+ visit(node.end_node)
476
+ end
477
+ end
478
+ end
479
+ end
480
+
481
+ class Prune < Herb::Visitor
482
+ #: (Visitor, Integer) -> void
483
+ def initialize(slot_visitor, index)
484
+ super()
485
+
486
+ @slot_visitor = slot_visitor
487
+ @index = index
488
+ end
489
+
490
+ #: (untyped) -> void
491
+ def visit_document_node(node)
492
+ target = @slot_visitor.slot_nodes[@index]
493
+
494
+ return unless target
495
+
496
+ keep(node, target)
497
+ end
498
+
499
+ private
500
+
501
+ #: (untyped, untyped) -> void
502
+ def keep(node, target)
503
+ Visitor::BRANCH_BODY_PROPERTIES.each do |property|
504
+ next unless node.respond_to?(property)
505
+
506
+ value = node.send(property)
507
+
508
+ case value
509
+ when Array
510
+ if property == :conditions
511
+ value.each { |arm| keep(arm, target) if contains?(arm, target) }
512
+ else
513
+ value.replace(value.select { |child| child.equal?(target) || contains?(child, target) || @slot_visitor.assignment_node?(child) })
514
+ value.each { |child| keep(child, target) if !child.equal?(target) && contains?(child, target) }
515
+ end
516
+ when Herb::AST::Node
517
+ keep(value, target) if contains?(value, target)
518
+ end
519
+ end
520
+
521
+ Visitor::BRANCH_CONTINUATION_PROPERTIES.each do |property|
522
+ next unless node.respond_to?(property)
523
+
524
+ continuation = node.send(property)
525
+
526
+ keep(continuation, target) if continuation && contains?(continuation, target)
527
+ end
528
+ end
529
+
530
+ #: (untyped, untyped) -> bool
531
+ def contains?(node, target)
532
+ return true if node.equal?(target)
533
+ return false unless node.is_a?(Herb::AST::Node)
534
+
535
+ node.compact_child_nodes.any? { |child| contains?(child, target) }
536
+ end
537
+ end
538
+
539
+ attr_reader :slot_visitor #: Visitor
540
+
541
+ #: (String, ?Hash[Symbol, untyped]) -> void
542
+ def initialize(input, properties = {})
543
+ @block_depth = 0
544
+ @scopes = [] #: Array[Integer]
545
+ @withheld = {} #: Hash[Integer, bool]
546
+ @input = input
547
+ @filename = properties[:filename]
548
+ @slot_visitor = properties[:slot_visitor] || Visitor.new(mode: :server, mark: false)
549
+ @slot_visitor.state_overrides!
550
+ visitors = [*properties[:visitors], @slot_visitor]
551
+ visitors << Prune.new(@slot_visitor, properties[:block]) if properties[:block]
552
+
553
+ super(
554
+ input,
555
+ properties.merge(
556
+ bufvar: BUFFER,
557
+ bufval: "::Hash.new",
558
+ postamble: "#{BUFFER}\n",
559
+ visitors: visitors
560
+ )
561
+ )
562
+ end
563
+
564
+ #: () -> untyped
565
+ def compiler_class
566
+ Compiler
567
+ end
568
+
569
+ #: (String) -> void
570
+ def add_text(text)
571
+ return if @block_depth.zero?
572
+
573
+ super
574
+ end
575
+
576
+ #: (Symbol, *untyped) -> void
577
+ def add_scope(kind, *)
578
+ send(:"scope_#{kind}", *)
579
+ end
580
+
581
+ #: (String, Symbol?, Integer?, bool, ?nested: bool) -> void
582
+ def add_dynamic(code, context, index, escaped, nested: false)
583
+ value = if index && boolean_presence?(index)
584
+ "!!(#{code})"
585
+ elsif nested
586
+ "(#{code})"
587
+ else
588
+ dynamic_value(code, context, escaped)
589
+ end
590
+
591
+ unless @block_depth.zero?
592
+ if index && boolean_presence?(index)
593
+ attribute = @slot_visitor.slots[index].attribute.to_s.inspect
594
+
595
+ return add_block_dynamic("(#{assignment(index, value)}) ? #{attribute} : \"\"")
596
+ end
597
+
598
+ if index && interpolated?(index)
599
+ return add_block_dynamic("(#{assignment(index, value)}).fetch(-1)")
600
+ end
601
+
602
+ return add_block_dynamic(index ? assignment(index, value) : value)
603
+ end
604
+ return if index.nil?
605
+
606
+ @src << "; " << assignment(index, value) << ";"
607
+ end
608
+
609
+ #: (Integer) -> bool
610
+ def boolean_presence?(index)
611
+ @slot_visitor.slots[index]&.type == :boolean_attribute
612
+ end
613
+
614
+ #: (String, Integer?, bool) -> void
615
+ def add_dynamic_block(code, index, escaped)
616
+ @_in_expression_block = true
617
+ @_expression_block_open_paren = true
618
+
619
+ opening = escaped ? "#{@escapefunc}((" : "("
620
+
621
+ @src << if @block_depth.zero?
622
+ "; #{current_scope}[#{index}] = #{opening}#{code}"
623
+ else
624
+ "; #{@bufvar} << #{opening}#{code}"
625
+ end
626
+
627
+ open_block
628
+ end
629
+
630
+ #: (String, ?escaped: bool) -> void
631
+ def add_expression_block_end(code, escaped: false)
632
+ @src << "; ::Herb::Engine.raw(" << @bufvar << ")"
633
+
634
+ close_block
635
+
636
+ super
637
+ end
638
+
639
+ #: () -> String
640
+ def inspect
641
+ "#<#{self.class.name}>"
642
+ end
643
+
644
+ private
645
+
646
+ #: (String) -> void
647
+ def add_postamble(_postamble)
648
+ super("{ template: #{@slot_visitor.identifier.inspect}, " \
649
+ "version: #{@slot_visitor.version.inspect}, " \
650
+ "occurrence: #{OCCURRENCE_BUFFER}#{region_seeds}, " \
651
+ "slots: #{BUFFER} }\n")
652
+ end
653
+
654
+ #: () -> String
655
+ def region_seeds
656
+ names = @slot_visitor.seeded_region_states
657
+
658
+ return "" if names.nil? || names.empty?
659
+
660
+ pairs = names.map { |name| "#{name.inspect} => #{name}" }.join(", ")
661
+
662
+ ", seeds: #{Markers.seeds_expression(pairs)}"
663
+ end
664
+
665
+ #: () -> void
666
+ def capture_occurrence
667
+ @src << "; #{OCCURRENCE_BUFFER} = #{@slot_visitor.occurrence_expression};"
668
+ end
669
+
670
+ #: () -> String
671
+ def current_scope
672
+ @scopes.empty? ? BUFFER : "#{SCOPE_BUFFER}#{@scopes.last}"
673
+ end
674
+
675
+ #: (Integer) -> void
676
+ def scope_open_conditional(index)
677
+ @src << "; #{SLOT_BUFFER}#{index} = nil;"
678
+ end
679
+
680
+ #: (Integer, Integer) -> void
681
+ def scope_branch(index, branch)
682
+ leave_scope(index)
683
+
684
+ @withheld[index] = withheld?(index, branch)
685
+
686
+ statics = payload_statics(index, branch)
687
+ parked = statics ? " statics: #{statics.inspect}," : ""
688
+
689
+ @src << "; #{SLOT_BUFFER}#{index} = { branch: #{branch},#{parked} slots: (#{SCOPE_BUFFER}#{index} = ::Hash.new) };"
690
+
691
+ @scopes.push(index)
692
+ end
693
+
694
+ #: (Integer, Integer) -> String?
695
+ def payload_statics(index, branch)
696
+ return nil unless server_mode? || withheld?(index, branch)
697
+
698
+ branch_statics["#{index}:#{branch}"]
699
+ end
700
+
701
+ #: () -> bool
702
+ def server_mode?
703
+ @input.is_a?(String) && Visitor.directive_mode(@input) == :server
704
+ end
705
+
706
+ #: (Integer, Integer) -> bool
707
+ def withheld?(index, branch)
708
+ branch.zero? && @slot_visitor.deferred_entries.key?(index)
709
+ end
710
+
711
+ #: (Integer) -> String?
712
+ def item_statics(index)
713
+ return nil unless server_mode? || @scopes.any? { |scope| @withheld[scope] }
714
+
715
+ branch_statics["#{index}:#{Markers::ITEM_STATICS}"]
716
+ end
717
+
718
+ #: () -> Hash[String, String]
719
+ def branch_statics
720
+ @branch_statics ||= begin
721
+ visitor = Visitor.new(fatal: false)
722
+
723
+ Herb::Engine.new(@input, visitors: [visitor], filename: @filename)
724
+
725
+ visitor.statics || {}
726
+ end
727
+ end
728
+
729
+ #: (Integer) -> void
730
+ def scope_close_conditional(index)
731
+ leave_scope(index)
732
+
733
+ @withheld.delete(index)
734
+
735
+ @src << "; #{current_scope}[#{index}] = (#{SLOT_BUFFER}#{index} || { branch: nil });"
736
+ end
737
+
738
+ #: (Integer) -> void
739
+ def scope_open_collection(index)
740
+ @src << "; #{ITEMS_BUFFER}#{index} = ::Hash.new;"
741
+ end
742
+
743
+ #: (Integer, ?String?) -> void
744
+ def scope_item_begin(index, key = nil)
745
+ @src << "; #{KEY_BUFFER}#{index} = (#{key}).to_s" if key
746
+ @src << "; #{SCOPE_BUFFER}#{index} = ::Hash.new;"
747
+
748
+ @scopes.push(index)
749
+ end
750
+
751
+ #: (Integer) -> void
752
+ def scope_item_end(index)
753
+ leave_scope(index)
754
+
755
+ return unless keyed?(index)
756
+
757
+ @src << item_seeds(index)
758
+ @src << "; #{ITEMS_BUFFER}#{index}[#{KEY_BUFFER}#{index}.to_s] = #{SCOPE_BUFFER}#{index};"
759
+ end
760
+
761
+ #: (Integer) -> bool
762
+ def keyed?(index)
763
+ !@slot_visitor.slots[index]&.key_expression.nil?
764
+ end
765
+
766
+ #: (Integer) -> String
767
+ def item_seeds(index)
768
+ names = @slot_visitor.seeded_item_states[index]
769
+
770
+ return "" if names.nil? || names.empty?
771
+
772
+ pairs = names.map { |name| "#{name.inspect} => #{name}" }.join(", ")
773
+
774
+ "; #{SCOPE_BUFFER}#{index}[:seeds] = #{Markers.seeds_expression(pairs)};"
775
+ end
776
+
777
+ #: (Integer) -> void
778
+ def scope_close_collection(index)
779
+ statics = item_statics(index)
780
+ parked = statics ? ", statics: #{statics.inspect}" : ""
781
+
782
+ @src << "; #{current_scope}[#{index}] = { items: #{ITEMS_BUFFER}#{index}, order: #{ITEMS_BUFFER}#{index}.keys#{parked} };"
783
+ end
784
+
785
+ #: (Integer, String) -> void
786
+ def scope_open_keyed(index, key)
787
+ @src << "; #{KEY_BUFFER}#{index} = (#{key}).to_s"
788
+ @src << "; #{SCOPE_BUFFER}#{index} = ::Hash.new;"
789
+
790
+ @scopes.push(index)
791
+ end
792
+
793
+ #: (Integer) -> void
794
+ def scope_close_keyed(index)
795
+ leave_scope(index)
796
+
797
+ @src << "; #{current_scope}[#{index}] = { key: #{KEY_BUFFER}#{index}, slots: #{SCOPE_BUFFER}#{index} };"
798
+ end
799
+
800
+ #: (Integer) -> void
801
+ def leave_scope(index)
802
+ @scopes.pop if @scopes.last == index
803
+ end
804
+
805
+ #: (String, Symbol?, bool) -> String
806
+ def dynamic_value(code, context, escaped)
807
+ escapefunc = context_escape_function(context)
808
+
809
+ return "#{escapefunc}((#{code}))" if escapefunc
810
+ return "#{@escapefunc}((#{code}))" if escaped
811
+
812
+ "(#{code}).to_s"
813
+ end
814
+
815
+ #: (Integer, String) -> String
816
+ def assignment(index, value)
817
+ if interpolated?(index)
818
+ "(#{current_scope}[#{index}] ||= []) << #{value}"
819
+ else
820
+ "#{current_scope}[#{index}] = #{value}"
821
+ end
822
+ end
823
+
824
+ #: (Integer) -> bool
825
+ def interpolated?(index)
826
+ @slot_visitor.slots[index]&.interpolated? || false
827
+ end
828
+
829
+ #: (String) -> void
830
+ def add_block_dynamic(value)
831
+ @src << "; " << @bufvar << " << (" << value << ");"
832
+ end
833
+
834
+ #: () -> void
835
+ def scope_part_open
836
+ open_block
837
+ end
838
+
839
+ #: (Integer) -> void
840
+ def scope_part_close(index)
841
+ buffer = @bufvar
842
+
843
+ close_block
844
+
845
+ @src << "; " << assignment(index, buffer) << ";"
846
+ end
847
+
848
+ #: () -> void
849
+ def open_block
850
+ @block_depth += 1
851
+ @bufvar = "#{BLOCK_BUFFER}#{@block_depth}"
852
+
853
+ @src << "; " << @bufvar << " = ::String.new;"
854
+ end
855
+
856
+ #: () -> void
857
+ def close_block
858
+ @block_depth -= 1
859
+ @bufvar = @block_depth.zero? ? BUFFER : "#{BLOCK_BUFFER}#{@block_depth}"
860
+ end
861
+ end
862
+ end
863
+ end
864
+ end