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,155 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "did_you_mean"
|
|
4
|
+
|
|
5
|
+
module Herb
|
|
6
|
+
module AST
|
|
7
|
+
class ERBRenderNode < Node
|
|
8
|
+
PARTIAL_EXTENSIONS = Herb::PARTIAL_EXTENSIONS
|
|
9
|
+
|
|
10
|
+
def static_partial?
|
|
11
|
+
keywords&.partial && !keywords&.partial&.value&.empty?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def dynamic?
|
|
15
|
+
!static_partial? && (keywords&.object || keywords&.renderable)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def partial_path
|
|
19
|
+
keywords&.partial&.value
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def template_name
|
|
23
|
+
keywords&.template_path&.value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def layout_name
|
|
27
|
+
keywords&.layout&.value
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def local_names
|
|
31
|
+
keywords&.locals&.map { |local| local.name&.value }&.compact || []
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def resolve(view_root: nil, source_directory: nil)
|
|
35
|
+
name = partial_path || template_name
|
|
36
|
+
|
|
37
|
+
return nil unless name
|
|
38
|
+
|
|
39
|
+
view_root = Pathname.new(view_root) unless view_root.nil? || view_root.is_a?(Pathname)
|
|
40
|
+
|
|
41
|
+
candidates = candidate_paths(name, view_root, source_directory)
|
|
42
|
+
candidates.find(&:exist?)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def candidate_paths(name = nil, view_root = nil, source_directory = nil)
|
|
46
|
+
name ||= partial_path || template_name
|
|
47
|
+
|
|
48
|
+
return [] unless name
|
|
49
|
+
|
|
50
|
+
view_root = Pathname.new(view_root) unless view_root.nil? || view_root.is_a?(Pathname)
|
|
51
|
+
|
|
52
|
+
directory = File.dirname(name) if name.include?("/")
|
|
53
|
+
base = name.include?("/") ? File.basename(name) : name
|
|
54
|
+
source_directory = Pathname.new(source_directory) if source_directory && !source_directory.is_a?(Pathname)
|
|
55
|
+
|
|
56
|
+
PARTIAL_EXTENSIONS.flat_map do |extension|
|
|
57
|
+
paths = [] #: Array[Pathname]
|
|
58
|
+
|
|
59
|
+
if directory
|
|
60
|
+
paths << view_root.join(directory, "_#{base}#{extension}") if view_root
|
|
61
|
+
else
|
|
62
|
+
paths << source_directory.join("_#{base}#{extension}") if source_directory
|
|
63
|
+
paths << view_root.join("_#{base}#{extension}") if view_root
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
paths
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def similar_partials(view_root: nil, source_directory: nil, limit: 3)
|
|
71
|
+
name = partial_path || template_name
|
|
72
|
+
|
|
73
|
+
return [] unless name
|
|
74
|
+
|
|
75
|
+
suggestions = [] #: Array[String]
|
|
76
|
+
|
|
77
|
+
if view_root
|
|
78
|
+
view_root = Pathname.new(view_root) unless view_root.is_a?(Pathname)
|
|
79
|
+
|
|
80
|
+
if view_root.directory?
|
|
81
|
+
all_partials = Dir[File.join(view_root, "**", Herb::PARTIAL_GLOB_PATTERN)].map do |file|
|
|
82
|
+
relative = Pathname.new(file).relative_path_from(view_root).to_s
|
|
83
|
+
relative.sub(%r{(^|/)_}, '\1').sub(/\..*\z/, "")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
spell_checker = DidYouMean::SpellChecker.new(dictionary: all_partials)
|
|
87
|
+
suggestions = spell_checker.correct(name).first(limit)
|
|
88
|
+
end
|
|
89
|
+
elsif source_directory
|
|
90
|
+
source_directory = Pathname.new(source_directory) unless source_directory.is_a?(Pathname)
|
|
91
|
+
|
|
92
|
+
if source_directory.directory?
|
|
93
|
+
local_partials = Dir[File.join(source_directory, Herb::PARTIAL_GLOB_PATTERN)].map do |file|
|
|
94
|
+
File.basename(file).sub(/\A_/, "").sub(/\..*\z/, "")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
unless local_partials.empty?
|
|
98
|
+
spell_checker = DidYouMean::SpellChecker.new(dictionary: local_partials)
|
|
99
|
+
suggestions = spell_checker.correct(name).first(limit)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
if suggestions.empty?
|
|
105
|
+
suggestions.concat(find_non_partial_matches(name, view_root, source_directory))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
suggestions
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def find_non_partial_matches(name = nil, view_root = nil, source_directory = nil)
|
|
112
|
+
name ||= partial_path || template_name
|
|
113
|
+
|
|
114
|
+
return [] unless name
|
|
115
|
+
|
|
116
|
+
matches = [] #: Array[String]
|
|
117
|
+
|
|
118
|
+
PARTIAL_EXTENSIONS.each do |extension|
|
|
119
|
+
if name.include?("/")
|
|
120
|
+
next unless view_root
|
|
121
|
+
|
|
122
|
+
view_root = Pathname.new(view_root) unless view_root.is_a?(Pathname)
|
|
123
|
+
directory = File.dirname(name)
|
|
124
|
+
base = File.basename(name)
|
|
125
|
+
non_partial_path = view_root.join(directory, "#{base}#{extension}")
|
|
126
|
+
|
|
127
|
+
if non_partial_path.exist?
|
|
128
|
+
matches << "#{name}#{extension} exists as a template, not a partial. Rename to _#{base}#{extension} to use it with render"
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
if source_directory
|
|
132
|
+
source_directory = Pathname.new(source_directory) unless source_directory.is_a?(Pathname)
|
|
133
|
+
non_partial_path = source_directory.join("#{name}#{extension}")
|
|
134
|
+
|
|
135
|
+
if non_partial_path.exist?
|
|
136
|
+
matches << "#{name}#{extension} exists as a template, not a partial. Rename to _#{name}#{extension} to use it with render"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
if view_root
|
|
141
|
+
view_root = Pathname.new(view_root) unless view_root.is_a?(Pathname)
|
|
142
|
+
non_partial_path = view_root.join("#{name}#{extension}")
|
|
143
|
+
|
|
144
|
+
if non_partial_path.exist?
|
|
145
|
+
matches << "#{name}#{extension} exists as a template, not a partial. Rename to _#{name}#{extension} to use it with render"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
matches.uniq
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
data/lib/herb/bootstrap.rb
CHANGED
data/lib/herb/cli.rb
CHANGED
|
@@ -8,7 +8,7 @@ require "optparse"
|
|
|
8
8
|
class Herb::CLI
|
|
9
9
|
include Herb::Colors
|
|
10
10
|
|
|
11
|
-
attr_accessor :json, :silent, :log_file, :no_timing, :local, :escape, :no_escape, :freeze, :debug, :tool, :strict, :analyze, :track_whitespace, :verbose, :isolate, :arena_stats, :leak_check, :action_view_helpers, :trim
|
|
11
|
+
attr_accessor :json, :silent, :log_file, :no_timing, :local, :escape, :no_escape, :freeze, :debug, :tool, :strict, :analyze, :track_whitespace, :verbose, :isolate, :arena_stats, :leak_check, :action_view_helpers, :trim, :optimize
|
|
12
12
|
|
|
13
13
|
def initialize(args)
|
|
14
14
|
@args = args
|
|
@@ -17,7 +17,7 @@ class Herb::CLI
|
|
|
17
17
|
|
|
18
18
|
def call
|
|
19
19
|
options
|
|
20
|
-
@file = @args[1]
|
|
20
|
+
@file = @args[1] unless @command == "dev"
|
|
21
21
|
|
|
22
22
|
if silent
|
|
23
23
|
if result.failed?
|
|
@@ -90,23 +90,29 @@ class Herb::CLI
|
|
|
90
90
|
bundle exec herb [command] [options]
|
|
91
91
|
|
|
92
92
|
Commands:
|
|
93
|
-
bundle exec herb lex [file]
|
|
94
|
-
bundle exec herb parse [file]
|
|
95
|
-
bundle exec herb compile [file]
|
|
96
|
-
bundle exec herb render [file]
|
|
97
|
-
bundle exec herb analyze [path]
|
|
98
|
-
bundle exec herb report [file]
|
|
99
|
-
bundle exec herb config [path]
|
|
100
|
-
bundle exec herb ruby [file]
|
|
101
|
-
bundle exec herb html [file]
|
|
102
|
-
bundle exec herb
|
|
103
|
-
bundle exec herb
|
|
104
|
-
|
|
105
|
-
bundle exec herb
|
|
106
|
-
|
|
107
|
-
bundle exec herb
|
|
108
|
-
bundle exec herb
|
|
109
|
-
bundle exec herb
|
|
93
|
+
bundle exec herb lex [file] Lex a file.
|
|
94
|
+
bundle exec herb parse [file] Parse a file.
|
|
95
|
+
bundle exec herb compile [file] Compile ERB template to Ruby code.
|
|
96
|
+
bundle exec herb render [file] Compile and render ERB template to final output.
|
|
97
|
+
bundle exec herb analyze [path] Analyze a project by passing a directory to the root of the project.
|
|
98
|
+
bundle exec herb report [file] Generate a Markdown bug report for a file.
|
|
99
|
+
bundle exec herb config [path] Show configuration and file patterns for a project.
|
|
100
|
+
bundle exec herb ruby [file] Extract Ruby from a file.
|
|
101
|
+
bundle exec herb html [file] Extract HTML from a file.
|
|
102
|
+
bundle exec herb diff [old] [new] Diff two files and show the minimal set of AST differences.
|
|
103
|
+
bundle exec herb playground [file] Open the content of the source file in the playground.
|
|
104
|
+
bundle exec herb dev Start the dev server and watch for file changes.
|
|
105
|
+
bundle exec herb version Prints the versions of the Herb gem and the libherb library.
|
|
106
|
+
|
|
107
|
+
bundle exec herb actionview check [path] Check if render calls resolve to valid partial files.
|
|
108
|
+
bundle exec herb actionview graph [path] Show render dependency graph for a project or file.
|
|
109
|
+
bundle exec herb actionview render [file] Render ERB template using ActionView helpers.
|
|
110
|
+
|
|
111
|
+
bundle exec herb lint [patterns] Lint templates (delegates to @herb-tools/linter)
|
|
112
|
+
bundle exec herb format [patterns] Format templates (delegates to @herb-tools/formatter)
|
|
113
|
+
bundle exec herb highlight [file] Syntax highlight templates (delegates to @herb-tools/highlighter)
|
|
114
|
+
bundle exec herb print [file] Print AST (delegates to @herb-tools/printer)
|
|
115
|
+
bundle exec herb lsp Start the language server (delegates to @herb-tools/language-server)
|
|
110
116
|
|
|
111
117
|
stdin:
|
|
112
118
|
Commands that accept [file] also accept input via stdin:
|
|
@@ -197,6 +203,19 @@ class Herb::CLI
|
|
|
197
203
|
system(%(open "#{url}##{hash}"))
|
|
198
204
|
exit(0)
|
|
199
205
|
end
|
|
206
|
+
when "dev"
|
|
207
|
+
case @args[1]
|
|
208
|
+
when "stop" then dev_stop
|
|
209
|
+
when "restart" then dev_restart
|
|
210
|
+
when "status" then dev_status
|
|
211
|
+
else
|
|
212
|
+
@file = @args[1]
|
|
213
|
+
run_dev_server
|
|
214
|
+
end
|
|
215
|
+
when "actionview"
|
|
216
|
+
run_actionview_command
|
|
217
|
+
when "diff"
|
|
218
|
+
diff_files
|
|
200
219
|
when "lint"
|
|
201
220
|
run_node_tool("herb-lint", "@herb-tools/linter")
|
|
202
221
|
when "format"
|
|
@@ -306,6 +325,10 @@ class Herb::CLI
|
|
|
306
325
|
self.trim = true
|
|
307
326
|
end
|
|
308
327
|
|
|
328
|
+
parser.on("--optimize", "Enable compile-time optimizations for Action View helpers (for compile/render commands) (default: false)") do
|
|
329
|
+
self.optimize = true
|
|
330
|
+
end
|
|
331
|
+
|
|
309
332
|
parser.on("--tool TOOL", "Show config for specific tool: linter, formatter (for config command)") do |t|
|
|
310
333
|
self.tool = t.to_sym
|
|
311
334
|
end
|
|
@@ -342,6 +365,143 @@ class Herb::CLI
|
|
|
342
365
|
nil
|
|
343
366
|
end
|
|
344
367
|
|
|
368
|
+
def run_actionview_command
|
|
369
|
+
subcommand = @args[1]
|
|
370
|
+
@file = @args[2]
|
|
371
|
+
|
|
372
|
+
target_path = @file ? File.expand_path(@file) : Dir.pwd
|
|
373
|
+
target_directory = File.directory?(target_path) ? target_path : File.dirname(target_path)
|
|
374
|
+
config = Herb::Configuration.new(target_directory)
|
|
375
|
+
|
|
376
|
+
if !(subcommand == "help" || subcommand.nil?) && (config.framework != "actionview")
|
|
377
|
+
project = config.project_root || target_directory
|
|
378
|
+
abort <<~MESSAGE
|
|
379
|
+
Herb also works outside of ActionView, but the `herb actionview` commands require the project to be explicitly configured for ActionView.
|
|
380
|
+
|
|
381
|
+
The project at '#{project}' is not configured to use ActionView (current framework: '#{config.framework}').
|
|
382
|
+
|
|
383
|
+
To enable ActionView support, add the following to your `.herb.yml`:
|
|
384
|
+
|
|
385
|
+
framework: actionview
|
|
386
|
+
MESSAGE
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
case subcommand
|
|
390
|
+
when "check"
|
|
391
|
+
require_relative "action_view/render_analyzer"
|
|
392
|
+
|
|
393
|
+
path = File.expand_path(@file || ".")
|
|
394
|
+
|
|
395
|
+
unless File.directory?(path)
|
|
396
|
+
puts "Not a directory: '#{path}'."
|
|
397
|
+
exit(1)
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
analyzer = Herb::ActionView::RenderAnalyzer.new(path)
|
|
401
|
+
has_issues = analyzer.check!
|
|
402
|
+
|
|
403
|
+
exit(has_issues ? 1 : 0)
|
|
404
|
+
when "graph"
|
|
405
|
+
require_relative "action_view/render_analyzer"
|
|
406
|
+
|
|
407
|
+
path = @file || "."
|
|
408
|
+
|
|
409
|
+
unless File.directory?(path) || File.file?(path)
|
|
410
|
+
puts "Not a file or directory: '#{path}'."
|
|
411
|
+
exit(1)
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
path = File.expand_path(path)
|
|
415
|
+
project_root = File.directory?(path) ? path : config.project_root&.to_s || File.dirname(path)
|
|
416
|
+
analyzer = Herb::ActionView::RenderAnalyzer.new(project_root)
|
|
417
|
+
|
|
418
|
+
if File.file?(path)
|
|
419
|
+
analyzer.graph_file!(path)
|
|
420
|
+
else
|
|
421
|
+
analyzer.graph!
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
exit(0)
|
|
425
|
+
when "render"
|
|
426
|
+
@file = @args[2]
|
|
427
|
+
actionview_render
|
|
428
|
+
when nil, "help"
|
|
429
|
+
puts <<~HELP
|
|
430
|
+
Herb ActionView Commands
|
|
431
|
+
|
|
432
|
+
Usage:
|
|
433
|
+
bundle exec herb actionview [subcommand] [options]
|
|
434
|
+
|
|
435
|
+
Subcommands:
|
|
436
|
+
check [path] Check if render calls resolve to valid partial files
|
|
437
|
+
graph [path] Show render dependency graph for a project or file
|
|
438
|
+
render [file] Render ERB template using ActionView helpers
|
|
439
|
+
|
|
440
|
+
Examples:
|
|
441
|
+
bundle exec herb actionview check
|
|
442
|
+
bundle exec herb actionview graph
|
|
443
|
+
bundle exec herb actionview graph app/views/posts/show.html.erb
|
|
444
|
+
bundle exec herb actionview render app/views/posts/show.html.erb
|
|
445
|
+
|
|
446
|
+
HELP
|
|
447
|
+
exit(0)
|
|
448
|
+
else
|
|
449
|
+
puts "Unknown actionview subcommand: '#{subcommand}'"
|
|
450
|
+
puts "Run 'herb actionview help' for available subcommands."
|
|
451
|
+
exit(1)
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
def actionview_render
|
|
456
|
+
require "action_view"
|
|
457
|
+
|
|
458
|
+
source = file_content
|
|
459
|
+
|
|
460
|
+
lookup_context = ActionView::LookupContext.new([])
|
|
461
|
+
view = ActionView::Base.with_empty_template_cache.new(lookup_context, {}, nil)
|
|
462
|
+
handler = ActionView::Template::Handlers::ERB.new
|
|
463
|
+
|
|
464
|
+
template = ActionView::Template.new(
|
|
465
|
+
source,
|
|
466
|
+
@file || "(eval)",
|
|
467
|
+
handler,
|
|
468
|
+
locals: [],
|
|
469
|
+
format: :html
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
rendered = template.render(view, {})
|
|
473
|
+
|
|
474
|
+
if json
|
|
475
|
+
puts({ success: true, output: rendered, source: source }.to_json)
|
|
476
|
+
elsif silent
|
|
477
|
+
puts "Success"
|
|
478
|
+
else
|
|
479
|
+
puts rendered
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
exit(0)
|
|
483
|
+
rescue LoadError
|
|
484
|
+
puts "Error: ActionView is required for 'herb actionview render'."
|
|
485
|
+
puts ""
|
|
486
|
+
puts "Add it to your Gemfile:"
|
|
487
|
+
puts " gem 'actionview'"
|
|
488
|
+
puts ""
|
|
489
|
+
puts "Or install it directly:"
|
|
490
|
+
puts " gem install actionview"
|
|
491
|
+
exit(1)
|
|
492
|
+
rescue StandardError => e
|
|
493
|
+
if json
|
|
494
|
+
puts({ success: false, error: e.message, source: source }.to_json)
|
|
495
|
+
elsif silent
|
|
496
|
+
puts "Failed"
|
|
497
|
+
else
|
|
498
|
+
puts "Error: #{e.class}: #{e.message}"
|
|
499
|
+
puts e.backtrace.first(5).map { |line| " #{line}" }.join("\n")
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
exit(1)
|
|
503
|
+
end
|
|
504
|
+
|
|
345
505
|
def node_available?
|
|
346
506
|
system("which node > /dev/null 2>&1")
|
|
347
507
|
end
|
|
@@ -435,6 +595,77 @@ class Herb::CLI
|
|
|
435
595
|
project.print_file_report(@file)
|
|
436
596
|
end
|
|
437
597
|
|
|
598
|
+
def dev_stop
|
|
599
|
+
require_relative "dev/runner"
|
|
600
|
+
Herb::Dev::Runner.new.stop
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
def dev_restart
|
|
604
|
+
require_relative "dev/runner"
|
|
605
|
+
Herb::Dev::Runner.new(path: @file || ".").restart
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
def dev_status
|
|
609
|
+
require_relative "dev/runner"
|
|
610
|
+
Herb::Dev::Runner.new.status
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
def run_dev_server
|
|
614
|
+
require_relative "dev/runner"
|
|
615
|
+
Herb::Dev::Runner.new(path: @file || ".").run
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
def diff_files
|
|
619
|
+
old_file = @args[1]
|
|
620
|
+
new_file = @args[2]
|
|
621
|
+
|
|
622
|
+
if old_file.nil? || new_file.nil?
|
|
623
|
+
puts "Usage: herb diff <old_file> <new_file> [options]"
|
|
624
|
+
exit(1)
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
unless File.exist?(old_file)
|
|
628
|
+
puts "File doesn't exist: #{old_file}"
|
|
629
|
+
exit(1)
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
unless File.exist?(new_file)
|
|
633
|
+
puts "File doesn't exist: #{new_file}"
|
|
634
|
+
exit(1)
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
old_content = File.read(old_file)
|
|
638
|
+
new_content = File.read(new_file)
|
|
639
|
+
|
|
640
|
+
diff_result = Herb.diff(old_content, new_content)
|
|
641
|
+
|
|
642
|
+
if json
|
|
643
|
+
require "json"
|
|
644
|
+
puts JSON.pretty_generate(diff_result.to_hash)
|
|
645
|
+
elsif diff_result.identical?
|
|
646
|
+
puts "Trees are identical."
|
|
647
|
+
else
|
|
648
|
+
operations = diff_result.operations
|
|
649
|
+
puts "#{operations.size} difference#{"s" unless operations.size == 1} found:\n\n"
|
|
650
|
+
|
|
651
|
+
operations.each_with_index do |operation, index|
|
|
652
|
+
puts " #{index + 1}. #{operation.type} at path [#{operation.path.join(", ")}]"
|
|
653
|
+
|
|
654
|
+
if operation.old_node
|
|
655
|
+
puts " old: #{operation.old_node.type}"
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
if operation.new_node
|
|
659
|
+
puts " new: #{operation.new_node.type}"
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
puts
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
exit(0)
|
|
667
|
+
end
|
|
668
|
+
|
|
438
669
|
def compile_template
|
|
439
670
|
require_relative "engine"
|
|
440
671
|
|
|
@@ -450,6 +681,7 @@ class Herb::CLI
|
|
|
450
681
|
options[:debug_filename] = @file if @file
|
|
451
682
|
end
|
|
452
683
|
|
|
684
|
+
options[:optimize] = true if optimize
|
|
453
685
|
options[:trim] = true if trim
|
|
454
686
|
options[:validate_ruby] = true
|
|
455
687
|
engine = Herb::Engine.new(file_content, options)
|
|
@@ -538,7 +770,9 @@ class Herb::CLI
|
|
|
538
770
|
options[:debug_filename] = @file if @file
|
|
539
771
|
end
|
|
540
772
|
|
|
773
|
+
options[:optimize] = true if optimize
|
|
541
774
|
options[:trim] = true if trim
|
|
775
|
+
|
|
542
776
|
engine = Herb::Engine.new(file_content, options)
|
|
543
777
|
compiled_code = engine.src
|
|
544
778
|
|
data/lib/herb/colors.rb
CHANGED
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
module Herb
|
|
7
7
|
module Colors
|
|
8
|
+
HIDE_CURSOR = "\e[?25l"
|
|
9
|
+
SHOW_CURSOR = "\e[?25h"
|
|
10
|
+
CLEAR_SCREEN = "\e[2J\e[H"
|
|
11
|
+
|
|
8
12
|
module_function
|
|
9
13
|
|
|
10
14
|
#: () -> bool
|
|
@@ -78,5 +82,19 @@ module Herb
|
|
|
78
82
|
|
|
79
83
|
"\e[1m#{string}\e[0m"
|
|
80
84
|
end
|
|
85
|
+
|
|
86
|
+
#: (String, Integer) -> String
|
|
87
|
+
def fg(string, color)
|
|
88
|
+
return string unless enabled?
|
|
89
|
+
|
|
90
|
+
"\e[38;5;#{color}m#{string}\e[0m"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
#: (String, Integer, Integer) -> String
|
|
94
|
+
def fg_bg(string, foreground, background)
|
|
95
|
+
return string unless enabled?
|
|
96
|
+
|
|
97
|
+
"\e[38;5;#{foreground};48;5;#{background}m#{string}\e[0m"
|
|
98
|
+
end
|
|
81
99
|
end
|
|
82
100
|
end
|
data/lib/herb/configuration.rb
CHANGED
|
@@ -5,6 +5,12 @@ require "pathname"
|
|
|
5
5
|
|
|
6
6
|
module Herb
|
|
7
7
|
class Configuration
|
|
8
|
+
OPTIONS_PATH = File.expand_path("../../config/options.yml", __dir__ || __FILE__).freeze #: String
|
|
9
|
+
OPTIONS = YAML.safe_load_file(OPTIONS_PATH).freeze #: Hash[String, untyped]
|
|
10
|
+
|
|
11
|
+
VALID_FRAMEWORKS = OPTIONS["framework"]["values"].freeze #: Array[String]
|
|
12
|
+
VALID_TEMPLATE_ENGINES = OPTIONS["template_engine"]["values"].freeze #: Array[String]
|
|
13
|
+
|
|
8
14
|
CONFIG_FILENAMES = [".herb.yml"].freeze
|
|
9
15
|
|
|
10
16
|
PROJECT_INDICATORS = [
|
|
@@ -22,12 +28,13 @@ module Herb
|
|
|
22
28
|
DEFAULTS_PATH = File.expand_path("defaults.yml", __dir__ || __FILE__).freeze
|
|
23
29
|
DEFAULTS = YAML.safe_load_file(DEFAULTS_PATH).freeze
|
|
24
30
|
|
|
25
|
-
attr_reader :config, :config_path, :project_root
|
|
31
|
+
attr_reader :config, :user_config, :config_path, :project_root
|
|
26
32
|
|
|
27
33
|
def initialize(project_path = nil)
|
|
28
34
|
@start_path = project_path ? Pathname.new(project_path) : Pathname.pwd
|
|
29
35
|
@config_path, @project_root = find_config_file
|
|
30
|
-
@
|
|
36
|
+
@user_config = load_user_config
|
|
37
|
+
@config = deep_merge(DEFAULTS, @user_config)
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
def [](key)
|
|
@@ -42,6 +49,30 @@ module Herb
|
|
|
42
49
|
@config["version"]
|
|
43
50
|
end
|
|
44
51
|
|
|
52
|
+
#: () -> String
|
|
53
|
+
def framework
|
|
54
|
+
value = @config["framework"] || "ruby"
|
|
55
|
+
|
|
56
|
+
unless VALID_FRAMEWORKS.include?(value)
|
|
57
|
+
warn "[Herb] Unknown framework: #{value.inspect}. Valid values: #{VALID_FRAMEWORKS.join(", ")}. Defaulting to 'ruby'."
|
|
58
|
+
return "ruby"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
value
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
#: () -> String
|
|
65
|
+
def template_engine
|
|
66
|
+
value = @config["template_engine"] || "erubi"
|
|
67
|
+
|
|
68
|
+
unless VALID_TEMPLATE_ENGINES.include?(value)
|
|
69
|
+
warn "[Herb] Unknown template_engine: #{value.inspect}. Valid values: #{VALID_TEMPLATE_ENGINES.join(", ")}. Defaulting to 'erubi'."
|
|
70
|
+
return "erubi"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
value
|
|
74
|
+
end
|
|
75
|
+
|
|
45
76
|
def files
|
|
46
77
|
@config["files"] || {}
|
|
47
78
|
end
|
|
@@ -62,6 +93,11 @@ module Herb
|
|
|
62
93
|
@config["engine"] || {}
|
|
63
94
|
end
|
|
64
95
|
|
|
96
|
+
#: (String, untyped) -> untyped
|
|
97
|
+
def engine_option(key, default = nil)
|
|
98
|
+
engine.fetch(key.to_s, default)
|
|
99
|
+
end
|
|
100
|
+
|
|
65
101
|
def enabled_validators(overrides = {})
|
|
66
102
|
config = dig("engine", "validators") || {}
|
|
67
103
|
|
|
@@ -221,26 +257,26 @@ module Herb
|
|
|
221
257
|
end
|
|
222
258
|
end
|
|
223
259
|
|
|
224
|
-
def
|
|
225
|
-
return
|
|
260
|
+
def load_user_config
|
|
261
|
+
return {} unless @config_path&.exist?
|
|
226
262
|
|
|
227
263
|
begin
|
|
228
|
-
|
|
229
|
-
deep_merge(DEFAULTS, user_config)
|
|
264
|
+
YAML.safe_load_file(@config_path, permitted_classes: [Symbol]) || {}
|
|
230
265
|
rescue Psych::SyntaxError => e
|
|
231
266
|
warn "Warning: Invalid YAML in #{@config_path}: #{e.message}"
|
|
232
|
-
|
|
267
|
+
|
|
268
|
+
{}
|
|
233
269
|
end
|
|
234
270
|
end
|
|
235
271
|
|
|
236
272
|
def deep_merge(base, override, additive_keys: ["include", "exclude"])
|
|
237
|
-
base.merge(override) do |key,
|
|
238
|
-
if
|
|
239
|
-
deep_merge(
|
|
240
|
-
elsif
|
|
241
|
-
|
|
273
|
+
base.merge(override) do |key, old_value, new_value|
|
|
274
|
+
if old_value.is_a?(Hash) && new_value.is_a?(Hash)
|
|
275
|
+
deep_merge(old_value, new_value, additive_keys: additive_keys)
|
|
276
|
+
elsif old_value.is_a?(Array) && new_value.is_a?(Array) && additive_keys.include?(key)
|
|
277
|
+
old_value + new_value
|
|
242
278
|
else
|
|
243
|
-
|
|
279
|
+
new_value
|
|
244
280
|
end
|
|
245
281
|
end
|
|
246
282
|
end
|