herb 0.9.7-arm-linux-gnu → 0.10.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.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/config/action_view_helpers/actioncable/action_cable_helper/action_cable_meta_tag.yml +20 -0
- data/config/action_view_helpers/actionpack/content_security_policy/content_security_policy?.yml +16 -0
- data/config/action_view_helpers/actionpack/content_security_policy/content_security_policy_nonce.yml +16 -0
- data/config/action_view_helpers/actionpack/polymorphic_routes/polymorphic_path.yml +27 -0
- data/config/action_view_helpers/actionpack/polymorphic_routes/polymorphic_url.yml +33 -0
- data/config/action_view_helpers/actionpack/request_forgery_protection/form_authenticity_token.yml +19 -0
- data/config/action_view_helpers/actionpack/request_forgery_protection/protect_against_forgery?.yml +16 -0
- data/config/action_view_helpers/actiontext/content_helper/render_action_text_content.yml +21 -0
- data/config/action_view_helpers/actiontext/content_helper/sanitize_action_text_content.yml +21 -0
- data/config/action_view_helpers/actiontext/tag_helper/rich_textarea_tag.yml +46 -0
- data/config/action_view_helpers/actionview/active_model_helper/error_message.yml +16 -0
- data/config/action_view_helpers/actionview/active_model_helper/error_wrapping.yml +16 -0
- data/config/action_view_helpers/actionview/active_model_helper/object.yml +16 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/apply_stylesheet_media_default.yml +16 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/audio_tag.yml +45 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/auto_discovery_link_tag.yml +44 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/auto_include_nonce.yml +16 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/auto_include_nonce_for_scripts.yml +16 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/auto_include_nonce_for_styles.yml +16 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/favicon_link_tag.yml +46 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/image_decoding.yml +16 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/image_loading.yml +16 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/image_tag.yml +68 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/javascript_include_tag.yml +59 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/picture_tag.yml +29 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/preload_link_tag.yml +50 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/preload_links_header.yml +16 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/stylesheet_link_tag.yml +50 -0
- data/config/action_view_helpers/actionview/asset_tag_helper/video_tag.yml +55 -0
- data/config/action_view_helpers/actionview/asset_url_helper/asset_path.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/asset_url.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/audio_path.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/audio_url.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/compute_asset_extname.yml +16 -0
- data/config/action_view_helpers/actionview/asset_url_helper/compute_asset_host.yml +16 -0
- data/config/action_view_helpers/actionview/asset_url_helper/compute_asset_path.yml +16 -0
- data/config/action_view_helpers/actionview/asset_url_helper/font_path.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/font_url.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/image_path.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/image_url.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/javascript_path.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/javascript_url.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/public_compute_asset_path.yml +16 -0
- data/config/action_view_helpers/actionview/asset_url_helper/stylesheet_path.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/stylesheet_url.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/video_path.yml +23 -0
- data/config/action_view_helpers/actionview/asset_url_helper/video_url.yml +23 -0
- data/config/action_view_helpers/actionview/atom_feed_helper/atom_feed.yml +40 -0
- data/config/action_view_helpers/actionview/cache_helper/cache.yml +28 -0
- data/config/action_view_helpers/actionview/cache_helper/cache_fragment_name.yml +16 -0
- data/config/action_view_helpers/actionview/cache_helper/cache_if.yml +27 -0
- data/config/action_view_helpers/actionview/cache_helper/cache_unless.yml +27 -0
- data/config/action_view_helpers/actionview/cache_helper/caching_predicate.yml +16 -0
- data/config/action_view_helpers/actionview/cache_helper/digest_path_from_template.yml +16 -0
- data/config/action_view_helpers/actionview/cache_helper/fragment_for.yml +16 -0
- data/config/action_view_helpers/actionview/cache_helper/fragment_name_with_digest.yml +16 -0
- data/config/action_view_helpers/actionview/cache_helper/read_fragment_for.yml +16 -0
- data/config/action_view_helpers/actionview/cache_helper/uncacheable.yml +16 -0
- data/config/action_view_helpers/actionview/cache_helper/write_fragment_for.yml +16 -0
- data/config/action_view_helpers/actionview/capture_helper/capture.yml +16 -0
- data/config/action_view_helpers/actionview/capture_helper/content_for.yml +24 -0
- data/config/action_view_helpers/actionview/capture_helper/content_for_predicate.yml +21 -0
- data/config/action_view_helpers/actionview/capture_helper/provide.yml +21 -0
- data/config/action_view_helpers/actionview/capture_helper/with_output_buffer.yml +16 -0
- data/config/action_view_helpers/actionview/content_exfiltration_prevention_helper/prepend_content_exfiltration_prevention.yml +16 -0
- data/config/action_view_helpers/actionview/content_exfiltration_prevention_helper/prevent_content_exfiltration.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/action_name.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/assign_controller.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/controller.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/controller_name.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/controller_path.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/cookies.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/flash.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/headers.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/logger.yml +18 -0
- data/config/action_view_helpers/actionview/controller_helper/params.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/request.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/request_forgery_protection_token.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/response.yml +16 -0
- data/config/action_view_helpers/actionview/controller_helper/session.yml +16 -0
- data/config/action_view_helpers/actionview/csp_helper/csp_meta_tag.yml +23 -0
- data/config/action_view_helpers/actionview/csrf_helper/csrf_meta_tags.yml +23 -0
- data/config/action_view_helpers/actionview/date_helper/date_select.yml +71 -0
- data/config/action_view_helpers/actionview/date_helper/datetime_select.yml +59 -0
- data/config/action_view_helpers/actionview/date_helper/distance_of_time_in_words.yml +33 -0
- data/config/action_view_helpers/actionview/date_helper/relative_time_in_words.yml +36 -0
- data/config/action_view_helpers/actionview/date_helper/select_date.yml +49 -0
- data/config/action_view_helpers/actionview/date_helper/select_datetime.yml +58 -0
- data/config/action_view_helpers/actionview/date_helper/select_day.yml +42 -0
- data/config/action_view_helpers/actionview/date_helper/select_hour.yml +48 -0
- data/config/action_view_helpers/actionview/date_helper/select_minute.yml +42 -0
- data/config/action_view_helpers/actionview/date_helper/select_month.yml +54 -0
- data/config/action_view_helpers/actionview/date_helper/select_second.yml +39 -0
- data/config/action_view_helpers/actionview/date_helper/select_time.yml +52 -0
- data/config/action_view_helpers/actionview/date_helper/select_year.yml +45 -0
- data/config/action_view_helpers/actionview/date_helper/time_ago_in_words.yml +26 -0
- data/config/action_view_helpers/actionview/date_helper/time_select.yml +56 -0
- data/config/action_view_helpers/actionview/date_helper/time_tag.yml +37 -0
- data/config/action_view_helpers/actionview/debug_helper/debug.yml +21 -0
- data/config/action_view_helpers/actionview/form_helper/apply_form_for_options.yml +16 -0
- data/config/action_view_helpers/actionview/form_helper/button.yml +38 -0
- data/config/action_view_helpers/actionview/form_helper/checkbox.yml +49 -0
- data/config/action_view_helpers/actionview/form_helper/color_field.yml +32 -0
- data/config/action_view_helpers/actionview/form_helper/date_field.yml +38 -0
- data/config/action_view_helpers/actionview/form_helper/datetime_field.yml +43 -0
- data/config/action_view_helpers/actionview/form_helper/email_field.yml +32 -0
- data/config/action_view_helpers/actionview/form_helper/emitted_hidden_id.yml +16 -0
- data/config/action_view_helpers/actionview/form_helper/fields.yml +31 -0
- data/config/action_view_helpers/actionview/form_helper/fields_for.yml +33 -0
- data/config/action_view_helpers/actionview/form_helper/file_field.yml +44 -0
- data/config/action_view_helpers/actionview/form_helper/form_for.yml +41 -0
- data/config/action_view_helpers/actionview/form_helper/form_with.yml +42 -0
- data/config/action_view_helpers/actionview/form_helper/form_with_generates_ids.yml +16 -0
- data/config/action_view_helpers/actionview/form_helper/form_with_generates_remote_forms.yml +16 -0
- data/config/action_view_helpers/actionview/form_helper/hidden_field.yml +32 -0
- data/config/action_view_helpers/actionview/form_helper/label.yml +47 -0
- data/config/action_view_helpers/actionview/form_helper/month_field.yml +32 -0
- data/config/action_view_helpers/actionview/form_helper/multipart.yml +16 -0
- data/config/action_view_helpers/actionview/form_helper/multiple_file_field_include_hidden.yml +16 -0
- data/config/action_view_helpers/actionview/form_helper/number_field.yml +44 -0
- data/config/action_view_helpers/actionview/form_helper/password_field.yml +32 -0
- data/config/action_view_helpers/actionview/form_helper/radio_button.yml +37 -0
- data/config/action_view_helpers/actionview/form_helper/range_field.yml +44 -0
- data/config/action_view_helpers/actionview/form_helper/search_field.yml +32 -0
- data/config/action_view_helpers/actionview/form_helper/submit.yml +35 -0
- data/config/action_view_helpers/actionview/form_helper/telephone_field.yml +34 -0
- data/config/action_view_helpers/actionview/form_helper/text_field.yml +32 -0
- data/config/action_view_helpers/actionview/form_helper/textarea.yml +37 -0
- data/config/action_view_helpers/actionview/form_helper/time_field.yml +41 -0
- data/config/action_view_helpers/actionview/form_helper/url_field.yml +32 -0
- data/config/action_view_helpers/actionview/form_helper/week_field.yml +32 -0
- data/config/action_view_helpers/actionview/form_options_helper/collection_checkboxes.yml +58 -0
- data/config/action_view_helpers/actionview/form_options_helper/collection_radio_buttons.yml +56 -0
- data/config/action_view_helpers/actionview/form_options_helper/collection_select.yml +65 -0
- data/config/action_view_helpers/actionview/form_options_helper/grouped_collection_select.yml +69 -0
- data/config/action_view_helpers/actionview/form_options_helper/grouped_options_for_select.yml +39 -0
- data/config/action_view_helpers/actionview/form_options_helper/option_groups_from_collection_for_select.yml +47 -0
- data/config/action_view_helpers/actionview/form_options_helper/options_for_select.yml +27 -0
- data/config/action_view_helpers/actionview/form_options_helper/options_from_collection_for_select.yml +37 -0
- data/config/action_view_helpers/actionview/form_options_helper/select.yml +59 -0
- data/config/action_view_helpers/actionview/form_options_helper/time_zone_options_for_select.yml +34 -0
- data/config/action_view_helpers/actionview/form_options_helper/time_zone_select.yml +53 -0
- data/config/action_view_helpers/actionview/form_options_helper/weekday_options_for_select.yml +31 -0
- data/config/action_view_helpers/actionview/form_options_helper/weekday_select.yml +38 -0
- data/config/action_view_helpers/actionview/form_tag_helper/button_tag.yml +39 -0
- data/config/action_view_helpers/actionview/form_tag_helper/checkbox_tag.yml +45 -0
- data/config/action_view_helpers/actionview/form_tag_helper/color_field_tag.yml +38 -0
- data/config/action_view_helpers/actionview/form_tag_helper/date_field_tag.yml +37 -0
- data/config/action_view_helpers/actionview/form_tag_helper/datetime_field_tag.yml +39 -0
- data/config/action_view_helpers/actionview/form_tag_helper/default_enforce_utf8.yml +16 -0
- data/config/action_view_helpers/actionview/form_tag_helper/email_field_tag.yml +37 -0
- data/config/action_view_helpers/actionview/form_tag_helper/embed_authenticity_token_in_remote_forms.yml +16 -0
- data/config/action_view_helpers/actionview/form_tag_helper/field_id.yml +32 -0
- data/config/action_view_helpers/actionview/form_tag_helper/field_name.yml +32 -0
- data/config/action_view_helpers/actionview/form_tag_helper/field_set_tag.yml +34 -0
- data/config/action_view_helpers/actionview/form_tag_helper/file_field_tag.yml +41 -0
- data/config/action_view_helpers/actionview/form_tag_helper/form_tag.yml +42 -0
- data/config/action_view_helpers/actionview/form_tag_helper/hidden_field_tag.yml +37 -0
- data/config/action_view_helpers/actionview/form_tag_helper/image_submit_tag.yml +40 -0
- data/config/action_view_helpers/actionview/form_tag_helper/label_tag.yml +38 -0
- data/config/action_view_helpers/actionview/form_tag_helper/month_field_tag.yml +37 -0
- data/config/action_view_helpers/actionview/form_tag_helper/number_field_tag.yml +49 -0
- data/config/action_view_helpers/actionview/form_tag_helper/password_field_tag.yml +38 -0
- data/config/action_view_helpers/actionview/form_tag_helper/radio_button_tag.yml +42 -0
- data/config/action_view_helpers/actionview/form_tag_helper/range_field_tag.yml +49 -0
- data/config/action_view_helpers/actionview/form_tag_helper/search_field_tag.yml +37 -0
- data/config/action_view_helpers/actionview/form_tag_helper/select_tag.yml +49 -0
- data/config/action_view_helpers/actionview/form_tag_helper/submit_tag.yml +39 -0
- data/config/action_view_helpers/actionview/form_tag_helper/telephone_field_tag.yml +39 -0
- data/config/action_view_helpers/actionview/form_tag_helper/text_field_tag.yml +37 -0
- data/config/action_view_helpers/actionview/form_tag_helper/textarea_tag.yml +43 -0
- data/config/action_view_helpers/actionview/form_tag_helper/time_field_tag.yml +37 -0
- data/config/action_view_helpers/actionview/form_tag_helper/url_field_tag.yml +37 -0
- data/config/action_view_helpers/actionview/form_tag_helper/utf8_enforcer_tag.yml +16 -0
- data/config/action_view_helpers/actionview/form_tag_helper/week_field_tag.yml +37 -0
- data/config/action_view_helpers/actionview/javascript_helper/escape_javascript.yml +23 -0
- data/config/action_view_helpers/actionview/javascript_helper/javascript_cdata_section.yml +16 -0
- data/config/action_view_helpers/actionview/javascript_helper/javascript_tag.yml +45 -0
- data/config/action_view_helpers/actionview/number_helper/number_to_currency.yml +36 -0
- data/config/action_view_helpers/actionview/number_helper/number_to_human.yml +27 -0
- data/config/action_view_helpers/actionview/number_helper/number_to_human_size.yml +24 -0
- data/config/action_view_helpers/actionview/number_helper/number_to_percentage.yml +24 -0
- data/config/action_view_helpers/actionview/number_helper/number_to_phone.yml +34 -0
- data/config/action_view_helpers/actionview/number_helper/number_with_delimiter.yml +29 -0
- data/config/action_view_helpers/actionview/number_helper/number_with_precision.yml +27 -0
- data/config/action_view_helpers/actionview/output_safety_helper/raw.yml +21 -0
- data/config/action_view_helpers/actionview/output_safety_helper/safe_join.yml +26 -0
- data/config/action_view_helpers/actionview/output_safety_helper/to_sentence.yml +33 -0
- data/config/action_view_helpers/actionview/record_identifier/dom_class.yml +27 -0
- data/config/action_view_helpers/actionview/record_identifier/dom_id.yml +27 -0
- data/config/action_view_helpers/actionview/record_identifier/dom_target.yml +22 -0
- data/config/action_view_helpers/actionview/record_identifier/model_name_from_record_or_class.yml +16 -0
- data/config/action_view_helpers/actionview/rendering_helper/render.yml +34 -0
- data/config/action_view_helpers/actionview/sanitize_helper/sanitize.yml +27 -0
- data/config/action_view_helpers/actionview/sanitize_helper/sanitize_css.yml +21 -0
- data/config/action_view_helpers/actionview/sanitize_helper/sanitizer_vendor.yml +16 -0
- data/config/action_view_helpers/actionview/sanitize_helper/strip_links.yml +21 -0
- data/config/action_view_helpers/actionview/sanitize_helper/strip_tags.yml +21 -0
- data/config/action_view_helpers/actionview/tag_helper/cdata_section.yml +21 -0
- data/config/action_view_helpers/actionview/tag_helper/content_tag.yml +64 -0
- data/config/action_view_helpers/actionview/tag_helper/escape_once.yml +21 -0
- data/config/action_view_helpers/actionview/tag_helper/tag.yml +47 -0
- data/config/action_view_helpers/actionview/tag_helper/token_list.yml +24 -0
- data/config/action_view_helpers/actionview/text_helper/concat.yml +21 -0
- data/config/action_view_helpers/actionview/text_helper/current_cycle.yml +22 -0
- data/config/action_view_helpers/actionview/text_helper/cycle.yml +31 -0
- data/config/action_view_helpers/actionview/text_helper/excerpt.yml +39 -0
- data/config/action_view_helpers/actionview/text_helper/highlight.yml +35 -0
- data/config/action_view_helpers/actionview/text_helper/pluralize.yml +32 -0
- data/config/action_view_helpers/actionview/text_helper/reset_cycle.yml +22 -0
- data/config/action_view_helpers/actionview/text_helper/safe_concat.yml +16 -0
- data/config/action_view_helpers/actionview/text_helper/simple_format.yml +40 -0
- data/config/action_view_helpers/actionview/text_helper/truncate.yml +40 -0
- data/config/action_view_helpers/actionview/text_helper/word_wrap.yml +27 -0
- data/config/action_view_helpers/actionview/translation_helper/debug_missing_translation.yml +16 -0
- data/config/action_view_helpers/actionview/translation_helper/localize.yml +29 -0
- data/config/action_view_helpers/actionview/translation_helper/translate.yml +32 -0
- data/config/action_view_helpers/actionview/url_helper/button_to.yml +55 -0
- data/config/action_view_helpers/actionview/url_helper/button_to_generates_button_tag.yml +16 -0
- data/config/action_view_helpers/actionview/url_helper/current_page?.yml +28 -0
- data/config/action_view_helpers/actionview/url_helper/link_to.yml +76 -0
- data/config/action_view_helpers/actionview/url_helper/link_to_if.yml +42 -0
- data/config/action_view_helpers/actionview/url_helper/link_to_unless.yml +42 -0
- data/config/action_view_helpers/actionview/url_helper/link_to_unless_current.yml +37 -0
- data/config/action_view_helpers/actionview/url_helper/mail_to.yml +56 -0
- data/config/action_view_helpers/actionview/url_helper/phone_to.yml +44 -0
- data/config/action_view_helpers/actionview/url_helper/sms_to.yml +47 -0
- data/config/action_view_helpers/actionview/url_helper/url_for.yml +22 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_cache.yml +16 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_cache_tag.yml +20 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_preview.yml +16 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_preview_tag.yml +20 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_page_requires_reload.yml +16 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_page_requires_reload_tag.yml +20 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_refresh_method_tag.yml +26 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_refresh_scroll_tag.yml +26 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_refreshes_with.yml +22 -0
- data/config/action_view_helpers/turbo-rails/frames_helper/turbo_frame_tag.yml +50 -0
- data/config/action_view_helpers/turbo-rails/includes_helper/turbo_include_tags.yml +16 -0
- data/config/action_view_helpers/turbo-rails/streams_action_helper/turbo_stream_action_tag.yml +34 -0
- data/config/action_view_helpers/turbo-rails/streams_action_helper/turbo_stream_refresh_tag.yml +23 -0
- data/config/action_view_helpers/turbo-rails/streams_helper/turbo_stream.yml +16 -0
- data/config/action_view_helpers/turbo-rails/streams_helper/turbo_stream_from.yml +33 -0
- data/config/options.yml +14 -0
- data/config/view_context_methods/actionview/base/annotate_rendered_view_with_filenames.yml +8 -0
- data/config/view_context_methods/actionview/base/assign.yml +8 -0
- data/config/view_context_methods/actionview/base/assigns.yml +8 -0
- data/config/view_context_methods/actionview/base/automatically_disable_submit_tag.yml +8 -0
- data/config/view_context_methods/actionview/base/compiled_method_container.yml +8 -0
- data/config/view_context_methods/actionview/base/config.yml +8 -0
- data/config/view_context_methods/actionview/base/default_form_builder.yml +8 -0
- data/config/view_context_methods/actionview/base/default_formats.yml +8 -0
- data/config/view_context_methods/actionview/base/field_error_proc.yml +8 -0
- data/config/view_context_methods/actionview/base/formats.yml +8 -0
- data/config/view_context_methods/actionview/base/in_rendering_context.yml +8 -0
- data/config/view_context_methods/actionview/base/locale.yml +8 -0
- data/config/view_context_methods/actionview/base/lookup_context.yml +8 -0
- data/config/view_context_methods/actionview/base/output_buffer.yml +8 -0
- data/config/view_context_methods/actionview/base/prefix_partial_path_with_controller_namespace.yml +10 -0
- data/config/view_context_methods/actionview/base/remove_hidden_field_autocomplete.yml +8 -0
- data/config/view_context_methods/actionview/base/streaming_completion_on_exception.yml +8 -0
- data/config/view_context_methods/actionview/base/view_flow.yml +8 -0
- data/config/view_context_methods/actionview/base/view_paths.yml +8 -0
- data/config/view_context_methods/actionview/base/view_renderer.yml +8 -0
- data/config/view_context_methods/actionview/template/local_assigns.yml +8 -0
- data/config/view_context_methods/activemodel/conversion/convert_to_model.yml +8 -0
- data/config/view_context_methods/activesupport/benchmarkable/benchmark.yml +8 -0
- data/ext/herb/extconf.rb +1 -0
- data/ext/herb/extension.c +108 -0
- data/herb.gemspec +2 -1
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +0 -0
- data/lib/herb/4.0/herb.so +0 -0
- data/lib/herb/action_view/render_analyzer.rb +1057 -0
- data/lib/herb/ast/erb_render_node.rb +155 -0
- data/lib/herb/bootstrap.rb +0 -1
- data/lib/herb/cli.rb +253 -19
- data/lib/herb/colors.rb +18 -0
- data/lib/herb/configuration.rb +49 -13
- data/lib/herb/defaults.yml +3 -0
- data/lib/herb/dev/runner.rb +445 -0
- data/lib/herb/dev/server.rb +207 -0
- data/lib/herb/dev/server_entry.rb +128 -0
- data/lib/herb/diff_operation.rb +34 -0
- data/lib/herb/diff_result.rb +59 -0
- data/lib/herb/engine/compiler.rb +56 -3
- data/lib/herb/engine/validators/render_validator.rb +92 -0
- data/lib/herb/engine.rb +58 -4
- data/lib/herb/html/util.rb +16 -0
- data/lib/herb/project.rb +1 -6
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +41 -5
- data/sig/herb/action_view/render_analyzer.rbs +122 -0
- data/sig/herb/ast/erb_render_node.rbs +29 -0
- data/sig/herb/colors.rbs +12 -0
- data/sig/herb/configuration.rbs +20 -1
- data/sig/herb/dev/runner.rbs +59 -0
- data/sig/herb/dev/server.rbs +50 -0
- data/sig/herb/dev/server_entry.rbs +51 -0
- data/sig/herb/diff_operation.rbs +34 -0
- data/sig/herb/diff_result.rbs +34 -0
- data/sig/herb/engine/compiler.rbs +6 -0
- data/sig/herb/engine/validators/render_validator.rbs +21 -0
- data/sig/herb/engine.rbs +15 -0
- data/sig/herb/html/util.rbs +13 -0
- data/sig/herb.rbs +12 -2
- data/sig/herb_c_extension.rbs +1 -1
- data/sig/vendor/did_you_mean.rbs +6 -0
- data/sig/vendor/parallel.rbs +4 -0
- data/src/analyze/action_view/attribute_extraction_helpers.c +3 -2
- data/src/diff/herb_diff.c +137 -0
- data/src/diff/herb_diff_attributes.c +207 -0
- data/src/diff/herb_diff_children.c +518 -0
- data/src/diff/herb_diff_helpers.c +114 -0
- data/src/diff/herb_diff_nodes.c +707 -0
- data/src/diff/herb_hash.c +42 -0
- data/src/diff/herb_hash_index_map.c +47 -0
- data/src/diff/herb_hash_map.c +104 -0
- data/src/diff/herb_hash_tree.c +680 -0
- data/src/include/diff/herb_diff.h +118 -0
- data/src/include/diff/herb_hash.h +25 -0
- data/src/include/diff/herb_hash_index_map.h +32 -0
- data/src/include/diff/herb_hash_map.h +30 -0
- data/src/include/herb.h +1 -0
- data/src/include/version.h +1 -1
- data/templates/javascript/packages/core/src/config.ts.erb +43 -0
- data/templates/rust/src/ast/nodes.rs.erb +1 -1
- data/templates/rust/src/config.rs.erb +50 -0
- data/templates/src/diff/herb_diff_helpers.c.erb +38 -0
- data/templates/src/diff/herb_diff_nodes.c.erb +224 -0
- data/templates/src/diff/herb_hash_tree.c.erb +147 -0
- data/templates/template.rb +4 -4
- metadata +307 -4
- data/lib/herb/3.0/herb.so +0 -0
- data/lib/herb/3.1/herb.so +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
|
|
6
|
+
module Herb
|
|
7
|
+
module Dev
|
|
8
|
+
class ServerEntry
|
|
9
|
+
SERVERS_DIR = File.expand_path("~/.herb/dev-servers").freeze
|
|
10
|
+
REQUIRED_KEYS = ["pid", "port", "project", "started_at"].freeze
|
|
11
|
+
|
|
12
|
+
attr_reader :pid, :port, :project, :started_at
|
|
13
|
+
|
|
14
|
+
def initialize(pid:, port:, project:, started_at: Time.now.utc.iso8601)
|
|
15
|
+
@pid = pid
|
|
16
|
+
@port = port
|
|
17
|
+
@project = project
|
|
18
|
+
@started_at = started_at
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def save
|
|
22
|
+
FileUtils.mkdir_p(SERVERS_DIR)
|
|
23
|
+
File.write(file_path, to_json)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def remove
|
|
27
|
+
File.delete(file_path)
|
|
28
|
+
rescue StandardError
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def alive?
|
|
33
|
+
self.class.process_alive?(pid)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def to_hash
|
|
37
|
+
{ pid: pid, port: port, project: project, started_at: started_at }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def to_json(*)
|
|
41
|
+
JSON.generate(to_hash)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def project_name
|
|
45
|
+
project&.split("/")&.last || "unknown"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def stop!
|
|
49
|
+
Process.kill("INT", pid)
|
|
50
|
+
remove
|
|
51
|
+
true
|
|
52
|
+
rescue Errno::ESRCH
|
|
53
|
+
remove
|
|
54
|
+
false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class << self
|
|
58
|
+
def all
|
|
59
|
+
FileUtils.mkdir_p(SERVERS_DIR)
|
|
60
|
+
|
|
61
|
+
Dir.glob(File.join(SERVERS_DIR, "*.json")).filter_map do |path|
|
|
62
|
+
entry = load_file(path)
|
|
63
|
+
|
|
64
|
+
if entry&.alive?
|
|
65
|
+
entry
|
|
66
|
+
else
|
|
67
|
+
begin
|
|
68
|
+
File.delete(path)
|
|
69
|
+
rescue StandardError
|
|
70
|
+
nil
|
|
71
|
+
end
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def find_by_port(port)
|
|
78
|
+
all.find { |entry| entry.port == port }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def find_by_project(project_path)
|
|
82
|
+
all.find { |entry| entry.project == project_path }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def stop_all
|
|
86
|
+
all.each(&:stop!)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def process_alive?(pid)
|
|
90
|
+
return false unless pid
|
|
91
|
+
|
|
92
|
+
Process.kill(0, pid)
|
|
93
|
+
true
|
|
94
|
+
rescue Errno::ESRCH, Errno::EPERM
|
|
95
|
+
false
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def load_file(path)
|
|
101
|
+
data = JSON.parse(File.read(path))
|
|
102
|
+
|
|
103
|
+
return nil unless data.is_a?(Hash) && REQUIRED_KEYS.all? { |key| data.key?(key) }
|
|
104
|
+
|
|
105
|
+
new(
|
|
106
|
+
pid: data["pid"],
|
|
107
|
+
port: data["port"],
|
|
108
|
+
project: data["project"],
|
|
109
|
+
started_at: data["started_at"]
|
|
110
|
+
)
|
|
111
|
+
rescue JSON::ParserError, Errno::ENOENT, Errno::EACCES
|
|
112
|
+
begin
|
|
113
|
+
File.delete(path)
|
|
114
|
+
rescue StandardError
|
|
115
|
+
nil
|
|
116
|
+
end
|
|
117
|
+
nil
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
def file_path
|
|
124
|
+
File.join(SERVERS_DIR, "#{pid}.json")
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
3
|
+
|
|
4
|
+
module Herb
|
|
5
|
+
DiffOperation = Data.define(
|
|
6
|
+
:type, #: Symbol
|
|
7
|
+
:path, #: Array[Integer]
|
|
8
|
+
:old_node, #: Herb::AST::Node?
|
|
9
|
+
:new_node, #: Herb::AST::Node?
|
|
10
|
+
:old_index, #: Integer
|
|
11
|
+
:new_index #: Integer
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
class DiffOperation
|
|
15
|
+
#: () -> Hash[Symbol, untyped]
|
|
16
|
+
def to_hash
|
|
17
|
+
{
|
|
18
|
+
type: type,
|
|
19
|
+
path: path,
|
|
20
|
+
old_node: old_node,
|
|
21
|
+
new_node: new_node,
|
|
22
|
+
old_index: old_index,
|
|
23
|
+
new_index: new_index,
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
alias to_h to_hash
|
|
28
|
+
|
|
29
|
+
#: () -> String
|
|
30
|
+
def inspect
|
|
31
|
+
"#<#{self.class.name} type=#{type} path=[#{path.join(", ")}]>"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
3
|
+
|
|
4
|
+
module Herb
|
|
5
|
+
class DiffResult
|
|
6
|
+
include Enumerable #[Herb::DiffOperation]
|
|
7
|
+
|
|
8
|
+
attr_reader :operations #: Array[Herb::DiffOperation]
|
|
9
|
+
|
|
10
|
+
#: (bool, Array[Herb::DiffOperation]) -> void
|
|
11
|
+
def initialize(identical, operations)
|
|
12
|
+
@identical = identical
|
|
13
|
+
@operations = operations.freeze
|
|
14
|
+
freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
#: () { (Herb::DiffOperation) -> void } -> void
|
|
18
|
+
#: () -> Enumerator[Herb::DiffOperation, void]
|
|
19
|
+
def each(&block)
|
|
20
|
+
return operations.each unless block
|
|
21
|
+
|
|
22
|
+
operations.each(&block)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#: () -> bool
|
|
26
|
+
def identical?
|
|
27
|
+
@identical
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
#: () -> Integer
|
|
31
|
+
def operation_count
|
|
32
|
+
operations.size
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#: () -> bool
|
|
36
|
+
def changed?
|
|
37
|
+
!identical?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
#: () -> Hash[Symbol, untyped]
|
|
41
|
+
def to_hash
|
|
42
|
+
{
|
|
43
|
+
identical: identical?,
|
|
44
|
+
operations: operations.map(&:to_hash),
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
alias to_h to_hash
|
|
49
|
+
|
|
50
|
+
#: () -> String
|
|
51
|
+
def inspect
|
|
52
|
+
if identical?
|
|
53
|
+
"#<#{self.class.name} identical>"
|
|
54
|
+
else
|
|
55
|
+
"#<#{self.class.name} #{operation_count} operation#{"s" unless operation_count == 1}>"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
data/lib/herb/engine/compiler.rb
CHANGED
|
@@ -25,6 +25,7 @@ module Herb
|
|
|
25
25
|
@last_trim_consumed_newline = false
|
|
26
26
|
@pending_leading_whitespace = nil
|
|
27
27
|
@pending_leading_whitespace_insert_index = 0
|
|
28
|
+
@current_element_source = nil
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
def generate_output
|
|
@@ -60,7 +61,20 @@ module Herb
|
|
|
60
61
|
with_element_context(node) do
|
|
61
62
|
visit(node.open_tag)
|
|
62
63
|
visit_all(node.body)
|
|
63
|
-
|
|
64
|
+
|
|
65
|
+
tag_name = node.tag_name&.value&.downcase
|
|
66
|
+
|
|
67
|
+
if node.open_tag.is_a?(Herb::AST::ERBOpenTagNode) && tag_name && node.close_tag
|
|
68
|
+
if node.close_tag.is_a?(Herb::AST::ERBEndNode)
|
|
69
|
+
remove_trailing_whitespace_from_last_token! if left_trim?(node.close_tag)
|
|
70
|
+
add_text("</#{tag_name}>")
|
|
71
|
+
@trim_next_whitespace = true
|
|
72
|
+
else
|
|
73
|
+
add_text("</#{tag_name}>")
|
|
74
|
+
end
|
|
75
|
+
else
|
|
76
|
+
visit(node.close_tag)
|
|
77
|
+
end
|
|
64
78
|
end
|
|
65
79
|
end
|
|
66
80
|
|
|
@@ -88,7 +102,9 @@ module Herb
|
|
|
88
102
|
|
|
89
103
|
return unless node.value
|
|
90
104
|
|
|
91
|
-
|
|
105
|
+
has_equals = node.equals.value&.include?("=")
|
|
106
|
+
add_text(has_equals ? node.equals.value : "=")
|
|
107
|
+
|
|
92
108
|
visit(node.value)
|
|
93
109
|
end
|
|
94
110
|
|
|
@@ -106,6 +122,40 @@ module Herb
|
|
|
106
122
|
pop_context
|
|
107
123
|
end
|
|
108
124
|
|
|
125
|
+
def visit_erb_open_tag_node(node)
|
|
126
|
+
tag_name = node.tag_name&.value
|
|
127
|
+
|
|
128
|
+
if tag_name
|
|
129
|
+
is_void = Herb::HTML::Util.void_element?(tag_name)
|
|
130
|
+
uses_self_closing = is_void && @current_element_source != "ActionView::Helpers::TagHelper#tag"
|
|
131
|
+
|
|
132
|
+
add_text("<")
|
|
133
|
+
add_text(tag_name)
|
|
134
|
+
|
|
135
|
+
node.children.each do |child|
|
|
136
|
+
visit(child)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
add_text(uses_self_closing ? " />" : ">")
|
|
140
|
+
else
|
|
141
|
+
process_erb_tag(node)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def visit_html_virtual_close_tag_node(node)
|
|
146
|
+
tag_name = node.tag_name&.value
|
|
147
|
+
|
|
148
|
+
return unless tag_name
|
|
149
|
+
|
|
150
|
+
add_text("</")
|
|
151
|
+
add_text(tag_name)
|
|
152
|
+
add_text(">")
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def visit_ruby_literal_node(node)
|
|
156
|
+
add_expression(node.content)
|
|
157
|
+
end
|
|
158
|
+
|
|
109
159
|
def visit_html_close_tag_node(node)
|
|
110
160
|
tag_name = node.tag_name&.value&.downcase
|
|
111
161
|
|
|
@@ -165,7 +215,7 @@ module Herb
|
|
|
165
215
|
process_erb_tag(node)
|
|
166
216
|
end
|
|
167
217
|
|
|
168
|
-
def visit_erb_control_node(node, &
|
|
218
|
+
def visit_erb_control_node(node, &)
|
|
169
219
|
if node.content
|
|
170
220
|
apply_trim(node, node.content.value.strip)
|
|
171
221
|
end
|
|
@@ -332,6 +382,8 @@ module Herb
|
|
|
332
382
|
#: (untyped node) { () -> untyped } -> untyped
|
|
333
383
|
def with_element_context(node)
|
|
334
384
|
tag_name = node.tag_name&.value&.downcase
|
|
385
|
+
previous_element_source = @current_element_source
|
|
386
|
+
@current_element_source = node.element_source
|
|
335
387
|
|
|
336
388
|
@element_stack.push(tag_name) if tag_name
|
|
337
389
|
|
|
@@ -346,6 +398,7 @@ module Herb
|
|
|
346
398
|
pop_context if ["script", "style"].include?(tag_name)
|
|
347
399
|
|
|
348
400
|
@element_stack.pop if tag_name
|
|
401
|
+
@current_element_source = previous_element_source
|
|
349
402
|
end
|
|
350
403
|
|
|
351
404
|
def process_erb_tag(node, skip_comment_check: false)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../validator"
|
|
4
|
+
|
|
5
|
+
module Herb
|
|
6
|
+
class Engine
|
|
7
|
+
module Validators
|
|
8
|
+
class RenderValidator < Validator
|
|
9
|
+
def initialize(enabled: true, filename: nil, project_path: nil)
|
|
10
|
+
super(enabled: enabled)
|
|
11
|
+
|
|
12
|
+
@filename = filename
|
|
13
|
+
@project_path = project_path
|
|
14
|
+
@view_root = find_view_root
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def visit_erb_render_node(node)
|
|
18
|
+
if node.dynamic?
|
|
19
|
+
warning(
|
|
20
|
+
"Dynamic render call cannot be statically resolved",
|
|
21
|
+
node.location,
|
|
22
|
+
code: "RenderDynamic",
|
|
23
|
+
source: "RenderValidator"
|
|
24
|
+
)
|
|
25
|
+
elsif node.static_partial?
|
|
26
|
+
validate_partial_exists(node)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
super
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def validate_partial_exists(node)
|
|
35
|
+
return unless @filename
|
|
36
|
+
|
|
37
|
+
source_directory = @project_path.join(@filename).dirname
|
|
38
|
+
resolved = node.resolve(view_root: @view_root, source_directory: source_directory)
|
|
39
|
+
|
|
40
|
+
return if resolved
|
|
41
|
+
|
|
42
|
+
message = "Partial '#{node.partial_path}' could not be resolved."
|
|
43
|
+
searched = node.candidate_paths(nil, @view_root, source_directory)
|
|
44
|
+
|
|
45
|
+
if searched.any?
|
|
46
|
+
relative_paths = searched.map { |path| relative_to_project(path) }.uniq
|
|
47
|
+
message += "\n Looked in:\n"
|
|
48
|
+
|
|
49
|
+
relative_paths.each do |path|
|
|
50
|
+
message += " - #{path}\n"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
suggestions = node.similar_partials(view_root: @view_root, source_directory: source_directory)
|
|
55
|
+
|
|
56
|
+
if suggestions.any?
|
|
57
|
+
partial_suggestions, hint_suggestions = suggestions.partition { |suggestion| !suggestion.include?("exists as a template") }
|
|
58
|
+
|
|
59
|
+
if partial_suggestions.any?
|
|
60
|
+
message += " Did you mean: #{partial_suggestions.map { |suggestion| "'#{suggestion}'" }.join(", ")}?\n"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
hint_suggestions.each do |hint|
|
|
64
|
+
message += "\n Note: #{hint}\n"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
error(
|
|
69
|
+
message,
|
|
70
|
+
node.location,
|
|
71
|
+
code: "RenderUnresolved",
|
|
72
|
+
source: "RenderValidator"
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def find_view_root
|
|
77
|
+
return nil unless @project_path
|
|
78
|
+
|
|
79
|
+
view_root = @project_path.join("app", "views")
|
|
80
|
+
|
|
81
|
+
view_root.directory? ? view_root : nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def relative_to_project(path)
|
|
85
|
+
path.relative_path_from(@project_path).to_s
|
|
86
|
+
rescue ArgumentError
|
|
87
|
+
path.to_s
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
data/lib/herb/engine.rb
CHANGED
|
@@ -14,12 +14,23 @@ require_relative "engine/validation_error_overlay"
|
|
|
14
14
|
require_relative "engine/validators/security_validator"
|
|
15
15
|
require_relative "engine/validators/nesting_validator"
|
|
16
16
|
require_relative "engine/validators/accessibility_validator"
|
|
17
|
+
require_relative "engine/validators/render_validator"
|
|
17
18
|
|
|
18
19
|
module Herb
|
|
19
20
|
class Engine
|
|
20
21
|
attr_reader :src, :filename, :project_path, :relative_file_path, :bufvar, :debug, :content_for_head,
|
|
21
22
|
:validation_error_template, :visitors, :enabled_validators
|
|
22
23
|
|
|
24
|
+
# @rbs!
|
|
25
|
+
# def self.optimize_warning_issued: () -> bool
|
|
26
|
+
# def self.optimize_warning_issued=: (bool) -> bool
|
|
27
|
+
|
|
28
|
+
class << self
|
|
29
|
+
attr_accessor :optimize_warning_issued #: bool
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
self.optimize_warning_issued = false
|
|
33
|
+
|
|
23
34
|
ESCAPE_TABLE = {
|
|
24
35
|
"&" => "&",
|
|
25
36
|
"<" => "<",
|
|
@@ -64,12 +75,20 @@ module Herb
|
|
|
64
75
|
@src = properties[:src] || String.new
|
|
65
76
|
@chain_appends = properties[:chain_appends]
|
|
66
77
|
@buffer_on_stack = false
|
|
67
|
-
@debug = properties.fetch(:debug, false)
|
|
78
|
+
@debug = properties.fetch(:debug, Herb.configuration.engine_option("debug", false))
|
|
68
79
|
@content_for_head = properties[:content_for_head]
|
|
69
80
|
@validation_error_template = nil
|
|
70
81
|
@validation_mode = properties.fetch(:validation_mode, :raise)
|
|
71
82
|
@enabled_validators = Herb.configuration.enabled_validators(properties[:validators] || {})
|
|
72
|
-
@
|
|
83
|
+
@optimize = properties.fetch(:optimize, Herb.configuration.engine_option("optimize", false))
|
|
84
|
+
@parser_options = properties.fetch(:parser_options, default_parser_options).transform_keys(&:to_sym)
|
|
85
|
+
|
|
86
|
+
if @optimize && !self.class.optimize_warning_issued
|
|
87
|
+
self.class.optimize_warning_issued = true
|
|
88
|
+
|
|
89
|
+
warn "[Herb] Compile-time optimizations are experimental. Output may differ from standard ActionView rendering."
|
|
90
|
+
end
|
|
91
|
+
|
|
73
92
|
@visitors = properties.fetch(:visitors, default_visitors)
|
|
74
93
|
|
|
75
94
|
if @debug && @visitors.empty?
|
|
@@ -110,7 +129,11 @@ module Herb
|
|
|
110
129
|
@src << "__herb = ::Herb::Engine; " if @escape && @escapefunc == "__herb.h"
|
|
111
130
|
@src << preamble
|
|
112
131
|
|
|
113
|
-
|
|
132
|
+
action_view_helpers = @optimize && source_may_contain_action_view_helpers?(input)
|
|
133
|
+
transform_conditionals = @optimize && action_view_helpers
|
|
134
|
+
parse_result = ::Herb.parse(input, **@parser_options, track_whitespace: true,
|
|
135
|
+
action_view_helpers: action_view_helpers,
|
|
136
|
+
transform_conditionals: transform_conditionals)
|
|
114
137
|
ast = parse_result.value
|
|
115
138
|
parser_errors = parse_result.errors
|
|
116
139
|
|
|
@@ -197,6 +220,10 @@ module Herb
|
|
|
197
220
|
end
|
|
198
221
|
end
|
|
199
222
|
|
|
223
|
+
def self.nested_attribute_value(value)
|
|
224
|
+
value.is_a?(::String) || value.is_a?(::Symbol) ? value.to_s : value.to_json
|
|
225
|
+
end
|
|
226
|
+
|
|
200
227
|
def self.comment?(code)
|
|
201
228
|
code.include?("#")
|
|
202
229
|
end
|
|
@@ -205,6 +232,26 @@ module Herb
|
|
|
205
232
|
code.match?(/<<[~-]?\s*['"`]?\w/)
|
|
206
233
|
end
|
|
207
234
|
|
|
235
|
+
def source_may_contain_action_view_helpers?(source)
|
|
236
|
+
self.class.action_view_helper_pattern.match?(source)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def self.action_view_helper_pattern
|
|
240
|
+
@action_view_helper_pattern ||= begin
|
|
241
|
+
require_relative "action_view/helper_registry"
|
|
242
|
+
|
|
243
|
+
names = ::Herb::ActionView::HelperRegistry.supported.flat_map { |entry|
|
|
244
|
+
if entry.receiver_call_detect?
|
|
245
|
+
"#{entry.name}."
|
|
246
|
+
else
|
|
247
|
+
[entry.name, *entry.aliases]
|
|
248
|
+
end
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
Regexp.new("\\b(?:#{names.map { |name| Regexp.escape(name) }.join("|")})")
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
208
255
|
protected
|
|
209
256
|
|
|
210
257
|
def add_text(text)
|
|
@@ -337,7 +384,7 @@ module Herb
|
|
|
337
384
|
@src << postamble
|
|
338
385
|
end
|
|
339
386
|
|
|
340
|
-
def with_buffer(&
|
|
387
|
+
def with_buffer(&)
|
|
341
388
|
if @chain_appends
|
|
342
389
|
@src << "; " << @bufvar unless @buffer_on_stack
|
|
343
390
|
yield
|
|
@@ -472,6 +519,13 @@ module Herb
|
|
|
472
519
|
[]
|
|
473
520
|
end
|
|
474
521
|
|
|
522
|
+
#: () -> Hash[Symbol, untyped]
|
|
523
|
+
def default_parser_options
|
|
524
|
+
fallback = {} #: Hash[Symbol, untyped]
|
|
525
|
+
|
|
526
|
+
Herb.configuration.engine_option("parser_options", fallback)
|
|
527
|
+
end
|
|
528
|
+
|
|
475
529
|
def ensure_valid_ruby!(source)
|
|
476
530
|
RubyVM::InstructionSequence.compile(source)
|
|
477
531
|
rescue SyntaxError => e
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# rbs_inline: enabled
|
|
3
|
+
|
|
4
|
+
module Herb
|
|
5
|
+
module HTML
|
|
6
|
+
module Util
|
|
7
|
+
# TODO: extract to shared utility for all languages in .yml
|
|
8
|
+
VOID_ELEMENTS = ["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"].freeze #: Array[String]
|
|
9
|
+
|
|
10
|
+
#: (String) -> bool
|
|
11
|
+
def self.void_element?(tag_name)
|
|
12
|
+
VOID_ELEMENTS.include?(tag_name.downcase)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/herb/project.rb
CHANGED
|
@@ -903,12 +903,7 @@ module Herb
|
|
|
903
903
|
def ensure_parallel!
|
|
904
904
|
return if defined?(Parallel)
|
|
905
905
|
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
gemfile(true, quiet: true) do
|
|
909
|
-
source "https://rubygems.org"
|
|
910
|
-
gem "parallel"
|
|
911
|
-
end
|
|
906
|
+
Herb.ensure_installed { gem "parallel" } # steep:ignore
|
|
912
907
|
end
|
|
913
908
|
|
|
914
909
|
def separator
|
data/lib/herb/version.rb
CHANGED
data/lib/herb.rb
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
# typed: false
|
|
3
3
|
|
|
4
|
+
module Herb
|
|
5
|
+
PARTIAL_EXTENSIONS = [
|
|
6
|
+
".html.erb", ".html.herb", ".erb", ".herb", ".turbo_stream.erb", ".turbo_stream.herb"
|
|
7
|
+
].freeze
|
|
8
|
+
|
|
9
|
+
PARTIAL_GLOB_PATTERN = "_*.{html.erb,html.herb,erb,herb,turbo_stream.erb,turbo_stream.herb}"
|
|
10
|
+
end
|
|
11
|
+
|
|
4
12
|
require_relative "herb/colors"
|
|
5
13
|
require_relative "herb/range"
|
|
6
14
|
require_relative "herb/position"
|
|
@@ -13,12 +21,15 @@ require_relative "herb/result"
|
|
|
13
21
|
require_relative "herb/lex_result"
|
|
14
22
|
require_relative "herb/parser_options"
|
|
15
23
|
require_relative "herb/parse_result"
|
|
24
|
+
require_relative "herb/diff_operation"
|
|
25
|
+
require_relative "herb/diff_result"
|
|
16
26
|
|
|
17
27
|
require_relative "herb/ast"
|
|
18
28
|
require_relative "herb/ast/node"
|
|
19
29
|
require_relative "herb/ast/nodes"
|
|
20
30
|
require_relative "herb/ast/erb_content_node"
|
|
21
31
|
require_relative "herb/ast/helpers"
|
|
32
|
+
require_relative "herb/ast/erb_render_node"
|
|
22
33
|
|
|
23
34
|
require_relative "herb/errors"
|
|
24
35
|
require_relative "herb/warnings"
|
|
@@ -29,6 +40,7 @@ require_relative "herb/configuration"
|
|
|
29
40
|
|
|
30
41
|
require_relative "herb/version"
|
|
31
42
|
|
|
43
|
+
require_relative "herb/html/util"
|
|
32
44
|
require_relative "herb/visitor"
|
|
33
45
|
require_relative "herb/engine"
|
|
34
46
|
|
|
@@ -69,13 +81,13 @@ end
|
|
|
69
81
|
module Herb
|
|
70
82
|
class << self
|
|
71
83
|
#: (String path, ?arena_stats: bool) -> LexResult
|
|
72
|
-
def lex_file(path, **
|
|
73
|
-
lex(File.read(path), **
|
|
84
|
+
def lex_file(path, **)
|
|
85
|
+
lex(File.read(path), **)
|
|
74
86
|
end
|
|
75
87
|
|
|
76
|
-
#: (String path, ?track_whitespace: bool, ?analyze: bool, ?strict: bool, ?arena_stats: bool) -> ParseResult
|
|
77
|
-
def parse_file(path, **
|
|
78
|
-
parse(File.read(path), **
|
|
88
|
+
#: (String path, ?track_whitespace: bool, ?analyze: bool, ?strict: bool, ?action_view_helpers: bool, ?transform_conditionals: bool, ?strict_locals: bool, ?prism_nodes: bool, ?prism_nodes_deep: bool, ?prism_program: bool, ?arena_stats: bool) -> ParseResult
|
|
89
|
+
def parse_file(path, **)
|
|
90
|
+
parse(File.read(path), **)
|
|
79
91
|
end
|
|
80
92
|
|
|
81
93
|
#: (String source) -> Prism::ParseResult
|
|
@@ -96,5 +108,29 @@ module Herb
|
|
|
96
108
|
def reset_configuration!
|
|
97
109
|
@configuration = nil
|
|
98
110
|
end
|
|
111
|
+
|
|
112
|
+
def dev_server_port(project_path = nil)
|
|
113
|
+
require_relative "herb/dev/server_entry"
|
|
114
|
+
|
|
115
|
+
project_path ||= Dir.pwd
|
|
116
|
+
entry = Dev::ServerEntry.find_by_project(project_path)
|
|
117
|
+
entry&.port
|
|
118
|
+
rescue StandardError
|
|
119
|
+
nil
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def ensure_installed(&block)
|
|
123
|
+
require "bundler/inline"
|
|
124
|
+
|
|
125
|
+
verbose = $VERBOSE
|
|
126
|
+
$VERBOSE = nil
|
|
127
|
+
|
|
128
|
+
gemfile(true, quiet: true) do # steep:ignore
|
|
129
|
+
source "https://rubygems.org" # steep:ignore
|
|
130
|
+
instance_eval(&block) # steep:ignore
|
|
131
|
+
end
|
|
132
|
+
ensure
|
|
133
|
+
$VERBOSE = verbose
|
|
134
|
+
end
|
|
99
135
|
end
|
|
100
136
|
end
|