herb 0.10.3-x86-linux-gnu → 0.11.0-x86-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/Makefile +16 -6
- data/README.md +36 -119
- data/Rakefile +2 -11
- data/config/action_view_helpers/actioncable/action_cable_helper/action_cable_meta_tag.yml +12 -8
- data/config/action_view_helpers/actionpack/content_security_policy/content_security_policy?.yml +9 -6
- data/config/action_view_helpers/actionpack/content_security_policy/content_security_policy_nonce.yml +9 -6
- data/config/action_view_helpers/actionpack/polymorphic_routes/polymorphic_path.yml +20 -12
- data/config/action_view_helpers/actionpack/polymorphic_routes/polymorphic_url.yml +30 -18
- data/config/action_view_helpers/actionpack/request_forgery_protection/form_authenticity_token.yml +15 -9
- data/config/action_view_helpers/actionpack/request_forgery_protection/protect_against_forgery?.yml +9 -6
- data/config/action_view_helpers/actiontext/content_helper/render_action_text_content.yml +15 -9
- data/config/action_view_helpers/actiontext/content_helper/sanitize_action_text_content.yml +15 -9
- data/config/action_view_helpers/actiontext/tag_helper/rich_textarea_tag.yml +34 -22
- data/config/action_view_helpers/actionview/active_model_helper/error_message.yml +9 -6
- data/config/action_view_helpers/actionview/active_model_helper/error_wrapping.yml +9 -6
- data/config/action_view_helpers/actionview/active_model_helper/object.yml +9 -6
- data/config/action_view_helpers/actionview/asset_tag_helper/apply_stylesheet_media_default.yml +9 -6
- data/config/action_view_helpers/actionview/asset_tag_helper/audio_tag.yml +40 -27
- data/config/action_view_helpers/actionview/asset_tag_helper/auto_discovery_link_tag.yml +37 -23
- data/config/action_view_helpers/actionview/asset_tag_helper/auto_include_nonce.yml +9 -6
- data/config/action_view_helpers/actionview/asset_tag_helper/auto_include_nonce_for_scripts.yml +9 -6
- data/config/action_view_helpers/actionview/asset_tag_helper/auto_include_nonce_for_styles.yml +9 -6
- data/config/action_view_helpers/actionview/asset_tag_helper/favicon_link_tag.yml +32 -22
- data/config/action_view_helpers/actionview/asset_tag_helper/image_decoding.yml +9 -6
- data/config/action_view_helpers/actionview/asset_tag_helper/image_loading.yml +9 -6
- data/config/action_view_helpers/actionview/asset_tag_helper/image_tag.yml +67 -46
- data/config/action_view_helpers/actionview/asset_tag_helper/javascript_include_tag.yml +58 -39
- data/config/action_view_helpers/actionview/asset_tag_helper/picture_tag.yml +22 -14
- data/config/action_view_helpers/actionview/asset_tag_helper/preload_link_tag.yml +45 -30
- data/config/action_view_helpers/actionview/asset_tag_helper/preload_links_header.yml +9 -6
- data/config/action_view_helpers/actionview/asset_tag_helper/stylesheet_link_tag.yml +49 -30
- data/config/action_view_helpers/actionview/asset_tag_helper/video_tag.yml +53 -35
- data/config/action_view_helpers/actionview/asset_url_helper/asset_path.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/asset_url.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/audio_path.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/audio_url.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/compute_asset_extname.yml +9 -6
- data/config/action_view_helpers/actionview/asset_url_helper/compute_asset_host.yml +9 -6
- data/config/action_view_helpers/actionview/asset_url_helper/compute_asset_path.yml +9 -6
- data/config/action_view_helpers/actionview/asset_url_helper/font_path.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/font_url.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/image_path.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/image_url.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/javascript_path.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/javascript_url.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/public_compute_asset_path.yml +9 -6
- data/config/action_view_helpers/actionview/asset_url_helper/stylesheet_path.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/stylesheet_url.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/video_path.yml +16 -10
- data/config/action_view_helpers/actionview/asset_url_helper/video_url.yml +16 -10
- data/config/action_view_helpers/actionview/atom_feed_helper/atom_feed.yml +52 -27
- data/config/action_view_helpers/actionview/cache_helper/cache.yml +25 -15
- data/config/action_view_helpers/actionview/cache_helper/cache_fragment_name.yml +9 -6
- data/config/action_view_helpers/actionview/cache_helper/cache_if.yml +20 -12
- data/config/action_view_helpers/actionview/cache_helper/cache_unless.yml +20 -12
- data/config/action_view_helpers/actionview/cache_helper/caching_predicate.yml +9 -6
- data/config/action_view_helpers/actionview/cache_helper/digest_path_from_template.yml +9 -6
- data/config/action_view_helpers/actionview/cache_helper/fragment_for.yml +9 -6
- data/config/action_view_helpers/actionview/cache_helper/fragment_name_with_digest.yml +9 -6
- data/config/action_view_helpers/actionview/cache_helper/read_fragment_for.yml +9 -6
- data/config/action_view_helpers/actionview/cache_helper/uncacheable.yml +9 -6
- data/config/action_view_helpers/actionview/cache_helper/write_fragment_for.yml +9 -6
- data/config/action_view_helpers/actionview/capture_helper/capture.yml +9 -6
- data/config/action_view_helpers/actionview/capture_helper/content_for.yml +20 -12
- data/config/action_view_helpers/actionview/capture_helper/content_for_predicate.yml +15 -9
- data/config/action_view_helpers/actionview/capture_helper/provide.yml +15 -9
- data/config/action_view_helpers/actionview/capture_helper/with_output_buffer.yml +9 -6
- data/config/action_view_helpers/actionview/content_exfiltration_prevention_helper/prepend_content_exfiltration_prevention.yml +9 -6
- data/config/action_view_helpers/actionview/content_exfiltration_prevention_helper/prevent_content_exfiltration.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/action_name.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/assign_controller.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/controller.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/controller_name.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/controller_path.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/cookies.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/flash.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/headers.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/logger.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/params.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/request.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/request_forgery_protection_token.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/response.yml +9 -6
- data/config/action_view_helpers/actionview/controller_helper/session.yml +9 -6
- data/config/action_view_helpers/actionview/csp_helper/csp_meta_tag.yml +18 -11
- data/config/action_view_helpers/actionview/csrf_helper/csrf_meta_tags.yml +16 -10
- data/config/action_view_helpers/actionview/date_helper/date_select.yml +85 -51
- data/config/action_view_helpers/actionview/date_helper/datetime_select.yml +65 -39
- data/config/action_view_helpers/actionview/date_helper/distance_of_time_in_words.yml +30 -18
- data/config/action_view_helpers/actionview/date_helper/relative_time_in_words.yml +35 -21
- data/config/action_view_helpers/actionview/date_helper/select_date.yml +50 -30
- data/config/action_view_helpers/actionview/date_helper/select_datetime.yml +65 -39
- data/config/action_view_helpers/actionview/date_helper/select_day.yml +40 -24
- data/config/action_view_helpers/actionview/date_helper/select_hour.yml +50 -30
- data/config/action_view_helpers/actionview/date_helper/select_minute.yml +40 -24
- data/config/action_view_helpers/actionview/date_helper/select_month.yml +60 -36
- data/config/action_view_helpers/actionview/date_helper/select_second.yml +35 -21
- data/config/action_view_helpers/actionview/date_helper/select_time.yml +55 -33
- data/config/action_view_helpers/actionview/date_helper/select_year.yml +45 -27
- data/config/action_view_helpers/actionview/date_helper/time_ago_in_words.yml +21 -13
- data/config/action_view_helpers/actionview/date_helper/time_select.yml +60 -36
- data/config/action_view_helpers/actionview/date_helper/time_tag.yml +32 -20
- data/config/action_view_helpers/actionview/debug_helper/debug.yml +15 -9
- data/config/action_view_helpers/actionview/form_builder/button.yml +60 -0
- data/config/action_view_helpers/actionview/form_builder/submit.yml +48 -0
- data/config/action_view_helpers/actionview/form_helper/apply_form_for_options.yml +9 -6
- data/config/action_view_helpers/actionview/form_helper/checkbox.yml +41 -25
- data/config/action_view_helpers/actionview/form_helper/color_field.yml +25 -15
- data/config/action_view_helpers/actionview/form_helper/date_field.yml +35 -21
- data/config/action_view_helpers/actionview/form_helper/datetime_field.yml +41 -25
- data/config/action_view_helpers/actionview/form_helper/email_field.yml +25 -15
- data/config/action_view_helpers/actionview/form_helper/emitted_hidden_id.yml +9 -6
- data/config/action_view_helpers/actionview/form_helper/fields.yml +37 -18
- data/config/action_view_helpers/actionview/form_helper/fields_for.yml +33 -15
- data/config/action_view_helpers/actionview/form_helper/file_field.yml +45 -27
- data/config/action_view_helpers/actionview/form_helper/form_for.yml +45 -24
- data/config/action_view_helpers/actionview/form_helper/form_with.yml +56 -30
- data/config/action_view_helpers/actionview/form_helper/form_with_generates_ids.yml +9 -6
- data/config/action_view_helpers/actionview/form_helper/form_with_generates_remote_forms.yml +9 -6
- data/config/action_view_helpers/actionview/form_helper/hidden_field.yml +25 -15
- data/config/action_view_helpers/actionview/form_helper/label.yml +52 -27
- data/config/action_view_helpers/actionview/form_helper/month_field.yml +25 -15
- data/config/action_view_helpers/actionview/form_helper/multipart.yml +9 -6
- data/config/action_view_helpers/actionview/form_helper/multiple_file_field_include_hidden.yml +9 -6
- data/config/action_view_helpers/actionview/form_helper/number_field.yml +45 -27
- data/config/action_view_helpers/actionview/form_helper/password_field.yml +25 -15
- data/config/action_view_helpers/actionview/form_helper/radio_button.yml +30 -18
- data/config/action_view_helpers/actionview/form_helper/range_field.yml +45 -27
- data/config/action_view_helpers/actionview/form_helper/search_field.yml +25 -15
- data/config/action_view_helpers/actionview/form_helper/telephone_field.yml +26 -16
- data/config/action_view_helpers/actionview/form_helper/text_field.yml +25 -15
- data/config/action_view_helpers/actionview/form_helper/textarea.yml +31 -19
- data/config/action_view_helpers/actionview/form_helper/time_field.yml +40 -24
- data/config/action_view_helpers/actionview/form_helper/url_field.yml +25 -15
- data/config/action_view_helpers/actionview/form_helper/week_field.yml +25 -15
- data/config/action_view_helpers/actionview/form_options_helper/collection_checkboxes.yml +58 -31
- data/config/action_view_helpers/actionview/form_options_helper/collection_radio_buttons.yml +57 -30
- data/config/action_view_helpers/actionview/form_options_helper/collection_select.yml +65 -39
- data/config/action_view_helpers/actionview/form_options_helper/grouped_collection_select.yml +65 -39
- data/config/action_view_helpers/actionview/form_options_helper/grouped_options_for_select.yml +35 -21
- data/config/action_view_helpers/actionview/form_options_helper/option_groups_from_collection_for_select.yml +40 -24
- data/config/action_view_helpers/actionview/form_options_helper/options_for_select.yml +20 -12
- data/config/action_view_helpers/actionview/form_options_helper/options_from_collection_for_select.yml +30 -18
- data/config/action_view_helpers/actionview/form_options_helper/select.yml +60 -36
- data/config/action_view_helpers/actionview/form_options_helper/time_zone_options_for_select.yml +25 -15
- data/config/action_view_helpers/actionview/form_options_helper/time_zone_select.yml +50 -30
- data/config/action_view_helpers/actionview/form_options_helper/weekday_options_for_select.yml +30 -18
- data/config/action_view_helpers/actionview/form_options_helper/weekday_select.yml +30 -18
- data/config/action_view_helpers/actionview/form_tag_helper/button_tag.yml +39 -21
- data/config/action_view_helpers/actionview/form_tag_helper/checkbox_tag.yml +33 -21
- data/config/action_view_helpers/actionview/form_tag_helper/color_field_tag.yml +26 -17
- data/config/action_view_helpers/actionview/form_tag_helper/date_field_tag.yml +27 -17
- data/config/action_view_helpers/actionview/form_tag_helper/datetime_field_tag.yml +28 -18
- data/config/action_view_helpers/actionview/form_tag_helper/default_enforce_utf8.yml +9 -6
- data/config/action_view_helpers/actionview/form_tag_helper/email_field_tag.yml +27 -17
- data/config/action_view_helpers/actionview/form_tag_helper/embed_authenticity_token_in_remote_forms.yml +9 -6
- data/config/action_view_helpers/actionview/form_tag_helper/field_id.yml +30 -18
- data/config/action_view_helpers/actionview/form_tag_helper/field_name.yml +30 -18
- data/config/action_view_helpers/actionview/form_tag_helper/field_set_tag.yml +23 -15
- data/config/action_view_helpers/actionview/form_tag_helper/file_field_tag.yml +35 -22
- data/config/action_view_helpers/actionview/form_tag_helper/form_tag.yml +38 -24
- data/config/action_view_helpers/actionview/form_tag_helper/hidden_field_tag.yml +27 -17
- data/config/action_view_helpers/actionview/form_tag_helper/image_submit_tag.yml +31 -21
- data/config/action_view_helpers/actionview/form_tag_helper/label_tag.yml +33 -17
- data/config/action_view_helpers/actionview/form_tag_helper/month_field_tag.yml +27 -17
- data/config/action_view_helpers/actionview/form_tag_helper/number_field_tag.yml +47 -29
- data/config/action_view_helpers/actionview/form_tag_helper/password_field_tag.yml +27 -17
- data/config/action_view_helpers/actionview/form_tag_helper/radio_button_tag.yml +32 -20
- data/config/action_view_helpers/actionview/form_tag_helper/range_field_tag.yml +47 -29
- data/config/action_view_helpers/actionview/form_tag_helper/search_field_tag.yml +27 -17
- data/config/action_view_helpers/actionview/form_tag_helper/select_tag.yml +47 -29
- data/config/action_view_helpers/actionview/form_tag_helper/submit_tag.yml +33 -21
- data/config/action_view_helpers/actionview/form_tag_helper/telephone_field_tag.yml +28 -18
- data/config/action_view_helpers/actionview/form_tag_helper/text_field_tag.yml +27 -17
- data/config/action_view_helpers/actionview/form_tag_helper/textarea_tag.yml +31 -20
- data/config/action_view_helpers/actionview/form_tag_helper/time_field_tag.yml +27 -17
- data/config/action_view_helpers/actionview/form_tag_helper/url_field_tag.yml +27 -17
- data/config/action_view_helpers/actionview/form_tag_helper/utf8_enforcer_tag.yml +9 -6
- data/config/action_view_helpers/actionview/form_tag_helper/week_field_tag.yml +28 -18
- data/config/action_view_helpers/actionview/javascript_helper/escape_javascript.yml +16 -10
- data/config/action_view_helpers/actionview/javascript_helper/javascript_cdata_section.yml +9 -6
- data/config/action_view_helpers/actionview/javascript_helper/javascript_tag.yml +41 -27
- data/config/action_view_helpers/actionview/number_helper/number_to_currency.yml +29 -18
- data/config/action_view_helpers/actionview/number_helper/number_to_human.yml +25 -15
- data/config/action_view_helpers/actionview/number_helper/number_to_human_size.yml +20 -12
- data/config/action_view_helpers/actionview/number_helper/number_to_percentage.yml +20 -12
- data/config/action_view_helpers/actionview/number_helper/number_to_phone.yml +33 -20
- data/config/action_view_helpers/actionview/number_helper/number_with_delimiter.yml +21 -13
- data/config/action_view_helpers/actionview/number_helper/number_with_precision.yml +25 -15
- data/config/action_view_helpers/actionview/output_safety_helper/raw.yml +15 -9
- data/config/action_view_helpers/actionview/output_safety_helper/safe_join.yml +20 -12
- data/config/action_view_helpers/actionview/output_safety_helper/to_sentence.yml +24 -15
- data/config/action_view_helpers/actionview/record_identifier/dom_class.yml +20 -12
- data/config/action_view_helpers/actionview/record_identifier/dom_id.yml +20 -12
- data/config/action_view_helpers/actionview/record_identifier/dom_target.yml +15 -9
- data/config/action_view_helpers/actionview/record_identifier/model_name_from_record_or_class.yml +9 -6
- data/config/action_view_helpers/actionview/rendering_helper/render.yml +108 -22
- data/config/action_view_helpers/actionview/sanitize_helper/sanitize.yml +25 -15
- data/config/action_view_helpers/actionview/sanitize_helper/sanitize_css.yml +15 -9
- data/config/action_view_helpers/actionview/sanitize_helper/sanitizer_vendor.yml +9 -6
- data/config/action_view_helpers/actionview/sanitize_helper/strip_links.yml +15 -9
- data/config/action_view_helpers/actionview/sanitize_helper/strip_tags.yml +15 -9
- data/config/action_view_helpers/actionview/tag_helper/cdata_section.yml +15 -9
- data/config/action_view_helpers/actionview/tag_helper/content_tag.yml +59 -38
- data/config/action_view_helpers/actionview/tag_helper/escape_once.yml +15 -9
- data/config/action_view_helpers/actionview/tag_helper/tag.yml +54 -31
- data/config/action_view_helpers/actionview/tag_helper/token_list.yml +16 -10
- data/config/action_view_helpers/actionview/text_helper/concat.yml +15 -9
- data/config/action_view_helpers/actionview/text_helper/current_cycle.yml +15 -9
- data/config/action_view_helpers/actionview/text_helper/cycle.yml +23 -14
- data/config/action_view_helpers/actionview/text_helper/excerpt.yml +33 -20
- data/config/action_view_helpers/actionview/text_helper/highlight.yml +37 -18
- data/config/action_view_helpers/actionview/text_helper/pluralize.yml +30 -18
- data/config/action_view_helpers/actionview/text_helper/reset_cycle.yml +15 -9
- data/config/action_view_helpers/actionview/text_helper/safe_concat.yml +9 -6
- data/config/action_view_helpers/actionview/text_helper/simple_format.yml +33 -20
- data/config/action_view_helpers/actionview/text_helper/truncate.yml +38 -23
- data/config/action_view_helpers/actionview/text_helper/word_wrap.yml +25 -15
- data/config/action_view_helpers/actionview/translation_helper/debug_missing_translation.yml +9 -6
- data/config/action_view_helpers/actionview/translation_helper/localize.yml +26 -16
- data/config/action_view_helpers/actionview/translation_helper/translate.yml +31 -19
- data/config/action_view_helpers/actionview/url_helper/button_to.yml +57 -33
- data/config/action_view_helpers/actionview/url_helper/button_to_generates_button_tag.yml +9 -6
- data/config/action_view_helpers/actionview/url_helper/current_page?.yml +25 -15
- data/config/action_view_helpers/actionview/url_helper/link_to.yml +76 -53
- data/config/action_view_helpers/actionview/url_helper/link_to_if.yml +54 -20
- data/config/action_view_helpers/actionview/url_helper/link_to_unless.yml +54 -20
- data/config/action_view_helpers/actionview/url_helper/link_to_unless_current.yml +49 -17
- data/config/action_view_helpers/actionview/url_helper/mail_to.yml +60 -34
- data/config/action_view_helpers/actionview/url_helper/phone_to.yml +40 -22
- data/config/action_view_helpers/actionview/url_helper/sms_to.yml +45 -25
- data/config/action_view_helpers/actionview/url_helper/url_for.yml +15 -9
- data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_import_module_tag.yml +32 -0
- data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_importmap_module_preload_tags.yml +39 -0
- data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_importmap_tags.yml +35 -0
- data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_inline_importmap_tag.yml +32 -0
- data/config/action_view_helpers/importmap-rails/importmap_tags_helper/javascript_module_preload_tag.yml +35 -0
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_cache.yml +9 -6
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_cache_tag.yml +12 -8
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_preview.yml +9 -6
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_exempts_page_from_preview_tag.yml +12 -8
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_page_requires_reload.yml +9 -6
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_page_requires_reload_tag.yml +12 -8
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_refresh_method_tag.yml +17 -11
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_refresh_scroll_tag.yml +17 -11
- data/config/action_view_helpers/turbo-rails/drive_helper/turbo_refreshes_with.yml +20 -12
- data/config/action_view_helpers/turbo-rails/frames_helper/turbo_frame_tag.yml +54 -33
- data/config/action_view_helpers/turbo-rails/includes_helper/turbo_include_tags.yml +9 -6
- data/config/action_view_helpers/turbo-rails/streams_action_helper/turbo_stream_action_tag.yml +32 -20
- data/config/action_view_helpers/turbo-rails/streams_action_helper/turbo_stream_refresh_tag.yml +18 -11
- data/config/action_view_helpers/turbo-rails/streams_helper/turbo_stream.yml +9 -6
- data/config/action_view_helpers/turbo-rails/streams_helper/turbo_stream_from.yml +28 -18
- data/config/html_elements.yml +597 -0
- data/config/options.yml +1 -0
- data/config/slots/components.yml +52 -0
- data/config/state/kind.yml +61 -0
- data/config/state/operators.yml +27 -0
- data/config/state/predicates.yml +39 -0
- data/config/state/transforms.yml +18 -0
- data/config/view_context_methods/actionview/base/annotate_rendered_view_with_filenames.yml +4 -4
- data/config/view_context_methods/actionview/base/assign.yml +4 -4
- data/config/view_context_methods/actionview/base/assigns.yml +4 -4
- data/config/view_context_methods/actionview/base/automatically_disable_submit_tag.yml +4 -4
- data/config/view_context_methods/actionview/base/compiled_method_container.yml +4 -4
- data/config/view_context_methods/actionview/base/config.yml +4 -4
- data/config/view_context_methods/actionview/base/default_form_builder.yml +4 -4
- data/config/view_context_methods/actionview/base/default_formats.yml +4 -4
- data/config/view_context_methods/actionview/base/field_error_proc.yml +4 -4
- data/config/view_context_methods/actionview/base/formats.yml +4 -4
- data/config/view_context_methods/actionview/base/in_rendering_context.yml +4 -4
- data/config/view_context_methods/actionview/base/locale.yml +4 -4
- data/config/view_context_methods/actionview/base/lookup_context.yml +4 -4
- data/config/view_context_methods/actionview/base/output_buffer.yml +4 -4
- data/config/view_context_methods/actionview/base/prefix_partial_path_with_controller_namespace.yml +4 -4
- data/config/view_context_methods/actionview/base/remove_hidden_field_autocomplete.yml +4 -4
- data/config/view_context_methods/actionview/base/streaming_completion_on_exception.yml +4 -4
- data/config/view_context_methods/actionview/base/view_flow.yml +4 -4
- data/config/view_context_methods/actionview/base/view_paths.yml +4 -4
- data/config/view_context_methods/actionview/base/view_renderer.yml +4 -4
- data/config/view_context_methods/actionview/template/local_assigns.yml +4 -4
- data/config/view_context_methods/activemodel/conversion/convert_to_model.yml +4 -4
- data/config/view_context_methods/activesupport/benchmarkable/benchmark.yml +4 -4
- data/config.yml +1240 -790
- data/exe/herb +2 -0
- data/ext/herb/error_helpers.c +355 -17
- data/ext/herb/error_helpers.h +1 -1
- data/ext/herb/extconf.rb +4 -2
- data/ext/herb/extension.c +137 -89
- data/ext/herb/extension_helpers.c +81 -42
- data/ext/herb/extension_helpers.h +4 -1
- data/ext/herb/nodes.c +826 -358
- data/ext/herb/nodes.h +3 -2
- data/ext/herb/parser_options_helpers.c +151 -0
- data/ext/herb/parser_options_helpers.h +14 -0
- data/herb.gemspec +2 -2
- 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/helper_registry.rb +1358 -62
- data/lib/herb/analysis/partial_declaration.rb +140 -0
- data/lib/herb/analysis/partial_index.rb +189 -0
- data/lib/herb/analysis/partial_resolution.rb +161 -0
- data/lib/herb/analysis/partial_resolver.rb +144 -0
- data/lib/herb/analysis/project_index.rb +152 -0
- data/lib/herb/{action_view → analysis}/render_analyzer.rb +287 -77
- data/lib/herb/analysis/render_graph/ancestor_chain.rb +27 -0
- data/lib/herb/analysis/render_graph/builder.rb +376 -0
- data/lib/herb/analysis/render_graph/call_frame.rb +9 -0
- data/lib/herb/analysis/render_graph/call_site_location.rb +23 -0
- data/lib/herb/analysis/render_graph/inferred_signature.rb +21 -0
- data/lib/herb/analysis/render_graph/partial_call_site.rb +40 -0
- data/lib/herb/analysis/render_graph/partial_context.rb +46 -0
- data/lib/herb/analysis/render_graph/template_roots.rb +31 -0
- data/lib/herb/analysis/render_graph.rb +285 -0
- data/lib/herb/analysis/ruby_locals_index/local.rb +25 -0
- data/lib/herb/analysis/ruby_locals_index/named_reference.rb +22 -0
- data/lib/herb/analysis/ruby_locals_index/offset_table.rb +44 -0
- data/lib/herb/analysis/ruby_locals_index/reference_collector.rb +80 -0
- data/lib/herb/analysis/ruby_locals_index/state_locals.rb +49 -0
- data/lib/herb/analysis/ruby_locals_index.rb +165 -0
- data/lib/herb/analysis/ruby_reference.rb +67 -0
- data/lib/herb/analysis/template_dependencies/dependency_collector.rb +179 -0
- data/lib/herb/analysis/template_dependencies/node_dependency_collector.rb +309 -0
- data/lib/herb/analysis/template_dependencies.rb +562 -0
- data/lib/herb/ast/erb_render_node.rb +26 -94
- data/lib/herb/ast/helpers.rb +90 -10
- data/lib/herb/ast/herb_directive_node.rb +18 -0
- data/lib/herb/ast/node.rb +32 -2
- data/lib/herb/ast/nodes.rb +1342 -105
- data/lib/herb/backend.rb +73 -0
- data/lib/herb/bootstrap.rb +3 -7
- data/lib/herb/cli.rb +550 -32
- data/lib/herb/colors.rb +14 -0
- data/lib/herb/configuration.rb +71 -35
- data/lib/herb/defaults.yml +2 -1
- data/lib/herb/dev/assets.rb +57 -0
- data/lib/herb/dev/classifier.rb +84 -0
- data/lib/herb/dev/embedded.rb +27 -0
- data/lib/herb/dev/pipeline.rb +305 -0
- data/lib/herb/dev/protocol.rb +221 -0
- data/lib/herb/dev/runner.rb +175 -175
- data/lib/herb/dev/server.rb +89 -26
- data/lib/herb/dev/server_entry.rb +41 -6
- data/lib/herb/dev/watcher.rb +181 -0
- data/lib/herb/dev.rb +163 -0
- data/lib/herb/diagnostic/formatter.rb +88 -0
- data/lib/herb/diagnostic.rb +172 -0
- data/lib/herb/diff/operation.rb +36 -0
- data/lib/herb/diff/result.rb +62 -0
- data/lib/herb/diff.rb +10 -0
- data/lib/herb/engine/collector.rb +62 -0
- data/lib/herb/engine/compiler.rb +346 -108
- data/lib/herb/engine/component_tags/constant_resolver.rb +28 -0
- data/lib/herb/engine/component_tags/partial_resolver.rb +54 -0
- data/lib/herb/engine/component_tags/resolver.rb +32 -0
- data/lib/herb/engine/component_tags/visitor.rb +231 -0
- data/lib/herb/engine/css_inliner/inliner.rb +101 -0
- data/lib/herb/engine/css_inliner/visitor.rb +174 -0
- data/lib/herb/engine/errors.rb +122 -0
- data/lib/herb/engine/helpers.rb +82 -0
- data/lib/herb/engine/inline_render/inliner.rb +122 -0
- data/lib/herb/engine/inline_render/visitor.rb +267 -0
- data/lib/herb/engine/runtime/entry.rb +62 -0
- data/lib/herb/engine/runtime/error_page.rb +362 -0
- data/lib/herb/engine/runtime/html_safe_assertions.rb +217 -0
- data/lib/herb/engine/runtime/journal/summary.rb +227 -0
- data/lib/herb/engine/runtime/journal.rb +379 -0
- data/lib/herb/engine/runtime/middleware.rb +212 -0
- data/lib/herb/engine/runtime/observations.rb +73 -0
- data/lib/herb/engine/runtime/report.rb +204 -0
- data/lib/herb/engine/runtime/session.rb +437 -0
- data/lib/herb/engine/runtime.rb +21 -0
- data/lib/herb/engine/scoped_style/channel.rb +66 -0
- data/lib/herb/engine/scoped_style/collector.rb +74 -0
- data/lib/herb/engine/scoped_style/visitor.rb +533 -0
- data/lib/herb/engine/slots/annotation.rb +98 -0
- data/lib/herb/engine/slots/bindings.rb +61 -0
- data/lib/herb/engine/slots/callee.rb +118 -0
- data/lib/herb/engine/slots/component_definitions.rb +67 -0
- data/lib/herb/engine/slots/components/async.rb +24 -0
- data/lib/herb/engine/slots/components/base.rb +132 -0
- data/lib/herb/engine/slots/components/deferred.rb +81 -0
- data/lib/herb/engine/slots/components/fallback.rb +27 -0
- data/lib/herb/engine/slots/components/fragment.rb +99 -0
- data/lib/herb/engine/slots/components/lazy.rb +24 -0
- data/lib/herb/engine/slots/components.rb +52 -0
- data/lib/herb/engine/slots/dependencies/channel.rb +72 -0
- data/lib/herb/engine/slots/dependencies.rb +269 -0
- data/lib/herb/engine/slots/dynamics_compiler.rb +854 -0
- data/lib/herb/engine/slots/identifier.rb +35 -0
- data/lib/herb/engine/slots/manifest/channel.rb +74 -0
- data/lib/herb/engine/slots/manifest/collector.rb +75 -0
- data/lib/herb/engine/slots/markers.rb +128 -0
- data/lib/herb/engine/slots/render_bindings.rb +141 -0
- data/lib/herb/engine/slots/schema_compiler.rb +94 -0
- data/lib/herb/engine/slots/state_anchor.rb +94 -0
- data/lib/herb/engine/slots/state_compiler.rb +1326 -0
- data/lib/herb/engine/slots/state_directives.rb +854 -0
- data/lib/herb/engine/slots/state_kinds.rb +54 -0
- data/lib/herb/engine/slots/state_operators.rb +36 -0
- data/lib/herb/engine/slots/state_overrides.rb +79 -0
- data/lib/herb/engine/slots/state_predicates.rb +65 -0
- data/lib/herb/engine/slots/state_transforms.rb +42 -0
- data/lib/herb/engine/slots/statics.rb +185 -0
- data/lib/herb/engine/slots/subtree.rb +82 -0
- data/lib/herb/engine/slots/subtree_compiler.rb +255 -0
- data/lib/herb/engine/slots/types.rb +42 -0
- data/lib/herb/engine/slots/visitor.rb +2256 -0
- data/lib/herb/engine/validators/accessibility_validator.rb +3 -3
- data/lib/herb/engine/validators/base.rb +36 -0
- data/lib/herb/engine/validators/generator_template_validator.rb +39 -0
- data/lib/herb/engine/validators/nesting_validator.rb +3 -3
- data/lib/herb/engine/validators/render_validator.rb +13 -33
- data/lib/herb/engine/validators/security_validator.rb +3 -17
- data/lib/herb/engine/validators.rb +43 -0
- data/lib/herb/engine/visitors/auto_close_omitted_tags_visitor.rb +48 -0
- data/lib/herb/engine/visitors/content_for_visitor.rb +127 -0
- data/lib/herb/engine/{debug_visitor.rb → visitors/debug_visitor.rb} +121 -93
- data/lib/herb/engine/visitors/html_safe_assertions_visitor.rb +281 -0
- data/lib/herb/engine/visitors/instrumentation_visitor.rb +290 -0
- data/lib/herb/engine/visitors/optimize_visitor.rb +728 -0
- data/lib/herb/engine/visitors/remove_comments_visitor.rb +106 -0
- data/lib/herb/engine/visitors/source_attribution_visitor.rb +177 -0
- data/lib/herb/engine.rb +218 -257
- data/lib/herb/ensure_installed.rb +43 -0
- data/lib/herb/errors.rb +646 -157
- data/lib/herb/fingerprint.rb +82 -0
- data/lib/herb/html/elements.rb +18 -0
- data/lib/herb/html/util.rb +21 -2
- data/lib/herb/lex_result.rb +0 -10
- data/lib/herb/locate.rb +163 -0
- data/lib/herb/location.rb +20 -0
- data/lib/herb/parse_result.rb +17 -11
- data/lib/herb/parser_options.rb +65 -46
- data/lib/herb/position.rb +19 -0
- data/lib/herb/prism_inspect.rb +1 -4
- data/lib/herb/project.rb +31 -18
- data/lib/herb/range.rb +5 -0
- data/lib/herb/result.rb +2 -2
- data/lib/herb/ruby_program.rb +110 -0
- data/lib/herb/source_path.rb +232 -0
- data/lib/herb/token.rb +14 -3
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor/context/origin.rb +52 -0
- data/lib/herb/visitor/context/replacements.rb +59 -0
- data/lib/herb/visitor/context.rb +169 -0
- data/lib/herb/visitor/context_aware.rb +45 -0
- data/lib/herb/visitor/diagnostics.rb +148 -0
- data/lib/herb/visitor/experimental.rb +33 -0
- data/lib/herb/visitor/parser_option_requirements.rb +151 -0
- data/lib/herb/visitor/stack.rb +192 -0
- data/lib/herb/visitor.rb +47 -1
- data/lib/herb/warnings.rb +25 -0
- data/lib/herb.rb +74 -63
- data/sig/herb/action_view/helper_registry.rbs +82 -10
- data/sig/herb/analysis/partial_declaration.rbs +80 -0
- data/sig/herb/analysis/partial_index.rbs +66 -0
- data/sig/herb/analysis/partial_resolution.rbs +57 -0
- data/sig/herb/analysis/partial_resolver.rbs +76 -0
- data/sig/herb/analysis/project_index.rbs +57 -0
- data/sig/herb/{action_view → analysis}/render_analyzer.rbs +25 -4
- data/sig/herb/analysis/render_graph/ancestor_chain.rbs +22 -0
- data/sig/herb/analysis/render_graph/builder.rbs +180 -0
- data/sig/herb/analysis/render_graph/call_frame.rbs +26 -0
- data/sig/herb/analysis/render_graph/call_site_location.rbs +28 -0
- data/sig/herb/analysis/render_graph/inferred_signature.rbs +27 -0
- data/sig/herb/analysis/render_graph/partial_call_site.rbs +36 -0
- data/sig/herb/analysis/render_graph/partial_context.rbs +31 -0
- data/sig/herb/analysis/render_graph/template_roots.rbs +32 -0
- data/sig/herb/analysis/render_graph.rbs +83 -0
- data/sig/herb/analysis/ruby_locals_index/local.rbs +21 -0
- data/sig/herb/analysis/ruby_locals_index/named_reference.rbs +20 -0
- data/sig/herb/analysis/ruby_locals_index/offset_table.rbs +26 -0
- data/sig/herb/analysis/ruby_locals_index/reference_collector.rbs +40 -0
- data/sig/herb/analysis/ruby_locals_index/state_locals.rbs +19 -0
- data/sig/herb/analysis/ruby_locals_index.rbs +62 -0
- data/sig/herb/analysis/ruby_reference.rbs +28 -0
- data/sig/herb/analysis/template_dependencies/dependency_collector.rbs +52 -0
- data/sig/herb/analysis/template_dependencies/node_dependency_collector.rbs +81 -0
- data/sig/herb/analysis/template_dependencies.rbs +125 -0
- data/sig/herb/ast/erb_render_node.rbs +10 -2
- data/sig/herb/ast/helpers.rbs +31 -1
- data/sig/herb/ast/herb_directive_node.rbs +13 -0
- data/sig/herb/ast/node.rbs +9 -0
- data/sig/herb/ast/nodes.rbs +662 -89
- data/sig/herb/backend.rbs +52 -0
- data/sig/herb/colors.rbs +3 -0
- data/sig/herb/configuration.rbs +27 -3
- data/sig/herb/dev/assets.rbs +27 -0
- data/sig/herb/dev/classifier.rbs +57 -0
- data/sig/herb/dev/embedded.rbs +21 -0
- data/sig/herb/dev/pipeline.rbs +118 -0
- data/sig/herb/dev/protocol.rbs +78 -0
- data/sig/herb/dev/runner.rbs +61 -23
- data/sig/herb/dev/server.rbs +49 -22
- data/sig/herb/dev/server_entry.rbs +46 -21
- data/sig/herb/dev/watcher.rbs +84 -0
- data/sig/herb/dev.rbs +58 -0
- data/sig/herb/diagnostic/formatter.rbs +28 -0
- data/sig/herb/diagnostic.rbs +88 -0
- data/sig/herb/diff/operation.rbs +36 -0
- data/sig/herb/diff/result.rbs +36 -0
- data/sig/herb/diff.rbs +6 -0
- data/sig/herb/engine/collector.rbs +48 -0
- data/sig/herb/engine/compiler.rbs +62 -23
- data/sig/herb/engine/component_tags/constant_resolver.rbs +19 -0
- data/sig/herb/engine/component_tags/partial_resolver.rbs +30 -0
- data/sig/herb/engine/component_tags/resolver.rbs +25 -0
- data/sig/herb/engine/component_tags/visitor.rbs +69 -0
- data/sig/herb/engine/css_inliner/inliner.rbs +65 -0
- data/sig/herb/engine/css_inliner/visitor.rbs +87 -0
- data/sig/herb/engine/errors.rbs +68 -0
- data/sig/herb/engine/helpers.rbs +28 -0
- data/sig/herb/engine/inline_render/inliner.rbs +39 -0
- data/sig/herb/engine/inline_render/visitor.rbs +104 -0
- data/sig/herb/engine/runtime/entry.rbs +43 -0
- data/sig/herb/engine/runtime/error_page.rbs +115 -0
- data/sig/herb/engine/runtime/html_safe_assertions.rbs +99 -0
- data/sig/herb/engine/runtime/journal/summary.rbs +172 -0
- data/sig/herb/engine/runtime/journal.rbs +126 -0
- data/sig/herb/engine/runtime/middleware.rbs +96 -0
- data/sig/herb/engine/runtime/observations.rbs +38 -0
- data/sig/herb/engine/runtime/report.rbs +97 -0
- data/sig/herb/engine/runtime/session.rbs +233 -0
- data/sig/herb/engine/runtime.rbs +14 -0
- data/sig/herb/engine/scoped_style/channel.rbs +45 -0
- data/sig/herb/engine/scoped_style/collector.rbs +45 -0
- data/sig/herb/engine/scoped_style/visitor.rbs +220 -0
- data/sig/herb/engine/slots/annotation.rbs +72 -0
- data/sig/herb/engine/slots/bindings.rbs +34 -0
- data/sig/herb/engine/slots/callee.rbs +62 -0
- data/sig/herb/engine/slots/component_definitions.rbs +19 -0
- data/sig/herb/engine/slots/components/async.rbs +20 -0
- data/sig/herb/engine/slots/components/base.rbs +60 -0
- data/sig/herb/engine/slots/components/deferred.rbs +29 -0
- data/sig/herb/engine/slots/components/fallback.rbs +21 -0
- data/sig/herb/engine/slots/components/fragment.rbs +34 -0
- data/sig/herb/engine/slots/components/lazy.rbs +20 -0
- data/sig/herb/engine/slots/components.rbs +30 -0
- data/sig/herb/engine/slots/dependencies/channel.rbs +51 -0
- data/sig/herb/engine/slots/dependencies.rbs +94 -0
- data/sig/herb/engine/slots/dynamics_compiler.rbs +349 -0
- data/sig/herb/engine/slots/identifier.rbs +19 -0
- data/sig/herb/engine/slots/manifest/channel.rbs +49 -0
- data/sig/herb/engine/slots/manifest/collector.rbs +45 -0
- data/sig/herb/engine/slots/markers.rbs +85 -0
- data/sig/herb/engine/slots/render_bindings.rbs +69 -0
- data/sig/herb/engine/slots/schema_compiler.rbs +62 -0
- data/sig/herb/engine/slots/state_anchor.rbs +41 -0
- data/sig/herb/engine/slots/state_compiler.rbs +258 -0
- data/sig/herb/engine/slots/state_directives.rbs +278 -0
- data/sig/herb/engine/slots/state_kinds.rbs +24 -0
- data/sig/herb/engine/slots/state_operators.rbs +19 -0
- data/sig/herb/engine/slots/state_overrides.rbs +33 -0
- data/sig/herb/engine/slots/state_predicates.rbs +16 -0
- data/sig/herb/engine/slots/state_transforms.rbs +15 -0
- data/sig/herb/engine/slots/statics.rbs +67 -0
- data/sig/herb/engine/slots/subtree.rbs +49 -0
- data/sig/herb/engine/slots/subtree_compiler.rbs +130 -0
- data/sig/herb/engine/slots/types.rbs +46 -0
- data/sig/herb/engine/slots/visitor.rbs +599 -0
- data/sig/herb/engine/validators/accessibility_validator.rbs +1 -1
- data/sig/herb/engine/validators/base.rbs +28 -0
- data/sig/herb/engine/validators/generator_template_validator.rbs +19 -0
- data/sig/herb/engine/validators/nesting_validator.rbs +1 -1
- data/sig/herb/engine/validators/render_validator.rbs +2 -6
- data/sig/herb/engine/validators/security_validator.rbs +1 -3
- data/sig/herb/engine/validators.rbs +21 -0
- data/sig/herb/engine/visitors/auto_close_omitted_tags_visitor.rbs +26 -0
- data/sig/herb/engine/visitors/content_for_visitor.rbs +52 -0
- data/sig/herb/engine/{debug_visitor.rbs → visitors/debug_visitor.rbs} +26 -15
- data/sig/herb/engine/visitors/html_safe_assertions_visitor.rbs +100 -0
- data/sig/herb/engine/visitors/instrumentation_visitor.rbs +111 -0
- data/sig/herb/engine/visitors/optimize_visitor.rbs +246 -0
- data/sig/herb/engine/visitors/remove_comments_visitor.rbs +66 -0
- data/sig/herb/engine/visitors/source_attribution_visitor.rbs +90 -0
- data/sig/herb/engine.rbs +47 -41
- data/sig/herb/ensure_installed.rbs +9 -0
- data/sig/herb/errors.rbs +293 -0
- data/sig/herb/fingerprint.rbs +37 -0
- data/sig/herb/html/elements.rbs +19 -0
- data/sig/herb/html/util.rbs +15 -1
- data/sig/herb/lex_result.rbs +0 -6
- data/sig/herb/locate.rbs +89 -0
- data/sig/herb/location.rbs +12 -0
- data/sig/herb/parse_result.rbs +10 -8
- data/sig/herb/parser_options.rbs +47 -21
- data/sig/herb/position.rbs +11 -0
- data/sig/herb/range.rbs +3 -0
- data/sig/herb/ruby_program.rbs +51 -0
- data/sig/herb/source_path.rbs +132 -0
- data/sig/herb/token.rbs +5 -2
- data/sig/herb/visitor/context/origin.rbs +51 -0
- data/sig/herb/visitor/context/replacements.rbs +39 -0
- data/sig/herb/visitor/context.rbs +83 -0
- data/sig/herb/visitor/context_aware.rbs +32 -0
- data/sig/herb/visitor/diagnostics.rbs +82 -0
- data/sig/herb/visitor/experimental.rbs +23 -0
- data/sig/herb/visitor/parser_option_requirements.rbs +76 -0
- data/sig/herb/visitor/stack.rbs +91 -0
- data/sig/herb/visitor.rbs +22 -0
- data/sig/herb/warnings.rbs +10 -0
- data/sig/herb.rbs +27 -10
- data/sig/serialized_ast_errors.rbs +58 -1
- data/sig/serialized_ast_nodes.rbs +58 -2
- data/src/analyze/action_view/attribute_extraction_helpers.c +73 -36
- data/src/analyze/action_view/generated_handlers.c +37 -1
- data/src/analyze/action_view/generated_handlers.h +2 -1
- data/src/analyze/action_view/helper_registry.c +1353 -58
- data/src/analyze/action_view/registry.c +10 -17
- data/src/analyze/action_view/stylesheet_link_tag.c +40 -0
- data/src/analyze/action_view/tag_helper_node_builders.c +57 -0
- data/src/analyze/action_view/tag_helpers.c +423 -93
- data/src/analyze/analyze.c +301 -64
- data/src/analyze/analyze_helpers.c +420 -23
- data/src/analyze/builders.c +79 -51
- data/src/analyze/conditional_elements.c +13 -8
- data/src/analyze/conditional_open_tags.c +11 -5
- data/src/analyze/control_type.c +16 -1
- data/src/analyze/herb_directives.c +701 -0
- data/src/analyze/invalid_structures.c +11 -7
- data/src/analyze/iteration_nodes.c +306 -0
- data/src/analyze/missing_end.c +116 -32
- data/src/analyze/parse_errors.c +8 -3
- data/src/analyze/postfix_conditionals.c +98 -63
- data/src/analyze/prism_annotate.c +13 -4
- data/src/analyze/render_nodes.c +345 -123
- data/src/analyze/strict_locals.c +30 -26
- data/src/analyze/ternary_conditionals.c +95 -70
- data/src/analyze/transform.c +43 -1
- data/src/ast/ast_node.c +3 -13
- data/src/ast/ast_nodes.c +911 -112
- data/src/ast/ast_pretty_print.c +161 -2
- data/src/diff/herb_diff.c +8 -0
- data/src/diff/herb_diff_attributes.c +1 -0
- data/src/diff/herb_diff_children.c +4 -3
- data/src/diff/herb_diff_helpers.c +7 -1
- data/src/diff/herb_diff_nodes.c +186 -71
- data/src/diff/herb_hash_tree.c +99 -1
- data/src/errors.c +1096 -128
- data/src/extract.c +30 -8
- data/src/herb.c +30 -11
- data/src/include/analyze/action_view/attribute_extraction_helpers.h +1 -1
- data/src/include/analyze/action_view/helper_registry.h +28 -4
- data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
- data/src/include/analyze/action_view/tag_helper_node_builders.h +7 -0
- data/src/include/analyze/analyze.h +11 -0
- data/src/include/analyze/builders.h +16 -0
- data/src/include/analyze/helpers.h +23 -2
- data/src/include/analyze/herb_directive_kinds.h +41 -0
- data/src/include/analyze/herb_directives.h +14 -0
- data/src/include/analyze/iteration_nodes.h +11 -0
- data/src/include/analyze/prism_annotate.h +3 -3
- data/src/include/analyze/ternary_conditionals.h +2 -0
- data/src/include/ast/ast_node.h +1 -5
- data/src/include/ast/ast_nodes.h +76 -2
- data/src/include/ast/ast_pretty_print.h +1 -1
- data/src/include/diff/herb_diff.h +11 -0
- data/src/include/errors.h +156 -39
- data/src/include/extract.h +11 -0
- data/src/include/herb.h +6 -0
- data/src/include/lexer/erb_openers.h +29 -0
- data/src/include/lexer/lexer_peek_helpers.h +8 -1
- data/src/include/lexer/lexer_struct.h +4 -0
- data/src/include/lexer/token.h +3 -0
- data/src/include/lexer/token_struct.h +8 -6
- data/src/include/lib/hb_allocator.h +2 -1
- data/src/include/lib/hb_array.h +2 -0
- data/src/include/lib/hb_foreach.h +1 -1
- data/src/include/lib/hb_string.h +7 -0
- data/src/include/parser/dot_notation.h +1 -1
- data/src/include/parser/foreign_content_elements.h +32 -0
- data/src/include/parser/parser.h +16 -30
- data/src/include/parser/parser_helpers.h +13 -11
- data/src/include/parser/parser_options.h +41 -0
- data/src/include/prism/ruby_parser.h +6 -0
- data/src/include/util/html_elements.h +85 -0
- data/src/include/util/html_util.h +1 -0
- data/src/include/version.h +1 -1
- data/src/lexer/lexer_peek_helpers.c +15 -1
- data/src/lexer/token.c +83 -1
- data/src/lexer.c +196 -12
- data/src/lib/hb_allocator.c +2 -0
- data/src/lib/hb_array.c +26 -0
- data/src/lib/hb_string.c +26 -0
- data/src/main.c +1 -1
- data/src/parser/dot_notation.c +4 -3
- data/src/parser/match_tags.c +66 -1
- data/src/parser/parser_helpers.c +69 -37
- data/src/parser.c +606 -383
- data/src/parser_options_defaults.c +30 -0
- data/src/prism/prism_helpers.c +3 -0
- data/src/prism/ruby_parser.c +49 -0
- data/src/util/html_util.c +11 -58
- data/src/visitor.c +77 -1
- data/templates/ext/herb/error_helpers.c.erb +1 -1
- data/templates/ext/herb/nodes.c.erb +18 -13
- data/templates/ext/herb/nodes.h.erb +2 -1
- data/templates/ext/herb/parser_options_helpers.c.erb +69 -0
- data/templates/ext/herb/parser_options_helpers.h.erb +11 -0
- data/templates/java/nodes.c.erb +20 -16
- data/templates/java/nodes.h.erb +3 -2
- data/templates/java/org/herb/ParserOptions.java.erb +24 -0
- data/templates/java/org/herb/ast/HelperRegistry.java.erb +67 -31
- data/templates/java/org/herb/ast/HelperType.java.erb +29 -0
- data/templates/java/org/herb/ast/Nodes.java.erb +11 -7
- data/templates/java/parser_options_helpers.c.erb +45 -0
- data/templates/java/parser_options_helpers.h.erb +10 -0
- data/templates/javascript/packages/client/src/state-kinds.ts.erb +49 -0
- data/templates/javascript/packages/client/src/state-operators.ts.erb +15 -0
- data/templates/javascript/packages/client/src/state-predicates.ts.erb +27 -0
- data/templates/javascript/packages/client/src/state-transforms.ts.erb +19 -0
- data/templates/javascript/packages/core/src/action-view-helpers.ts.erb +47 -0
- data/templates/javascript/packages/core/src/built-in-components.ts.erb +67 -0
- data/templates/javascript/packages/core/src/errors.ts.erb +9 -3
- data/templates/javascript/packages/core/src/foreign-content-elements.ts.erb +18 -0
- data/templates/javascript/packages/core/src/html-constants.ts.erb +32 -0
- data/templates/javascript/packages/core/src/html-elements.ts.erb +41 -0
- data/templates/javascript/packages/core/src/node-type-guards.ts.erb +11 -7
- data/templates/javascript/packages/core/src/nodes.ts.erb +82 -19
- data/templates/javascript/packages/core/src/parser-options.ts.erb +41 -0
- data/templates/javascript/packages/core/src/visitor.ts.erb +1 -1
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +3 -3
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +17 -12
- data/templates/javascript/packages/node/extension/nodes.h.erb +3 -3
- data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +41 -0
- data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +12 -0
- data/templates/lib/herb/action_view/helper_registry.rb.erb +77 -3
- data/templates/lib/herb/ast/nodes.rb.erb +16 -6
- data/templates/lib/herb/engine/slots/component_definitions.rb.erb +38 -0
- data/templates/lib/herb/engine/slots/state_kinds.rb.erb +37 -0
- data/templates/lib/herb/engine/slots/state_operators.rb.erb +26 -0
- data/templates/lib/herb/engine/slots/state_predicates.rb.erb +39 -0
- data/templates/lib/herb/engine/slots/state_transforms.rb.erb +27 -0
- data/templates/lib/herb/errors.rb.erb +34 -6
- data/templates/lib/herb/html/elements.rb.erb +12 -0
- data/templates/lib/herb/parser_options.rb.erb +32 -0
- data/templates/lib/herb/visitor.rb.erb +7 -1
- data/templates/rust/herb-printer/src/printer_visitor.rs.erb +14 -0
- data/templates/rust/src/action_view_helpers.rs.erb +38 -0
- data/templates/rust/src/ast/nodes.rs.erb +24 -31
- data/templates/rust/src/errors.rs.erb +1 -1
- data/templates/rust/src/nodes.rs.erb +58 -26
- data/templates/rust/src/parser_options.rs.erb +16 -0
- data/templates/rust/src/prism/generated_deserialize.rs.erb +109 -0
- data/templates/rust/src/prism/generated_prettyprint.rs.erb +153 -0
- data/templates/rust/src/union_types.rs.erb +7 -1
- data/templates/rust/src/visitor.rs.erb +1 -1
- data/templates/src/analyze/action_view/helper_registry.c.erb +22 -0
- data/templates/src/analyze/missing_end.c.erb +13 -5
- data/templates/src/ast/ast_nodes.c.erb +41 -2
- data/templates/src/diff/herb_diff_nodes.c.erb +44 -8
- data/templates/src/errors.c.erb +8 -3
- data/templates/src/include/analyze/action_view/helper_registry.h.erb +19 -0
- data/templates/src/include/analyze/herb_directive_kinds.h.erb +25 -0
- data/templates/src/include/errors.h.erb +3 -1
- data/templates/src/include/parser/foreign_content_elements.h.erb +23 -0
- data/templates/src/include/parser/parser_options.h.erb +21 -0
- data/templates/src/include/util/html_elements.h.erb +28 -0
- data/templates/src/parser_options_defaults.c.erb +9 -0
- data/templates/template.rb +564 -9
- data/templates/wasm/error_helpers.cpp.erb +4 -4
- data/templates/wasm/nodes.cpp.erb +12 -12
- data/templates/wasm/nodes.h.erb +3 -3
- data/templates/wasm/parser_options_helpers.cpp.erb +25 -0
- data/templates/wasm/parser_options_helpers.h.erb +12 -0
- metadata +306 -27
- data/config/action_view_helpers/actionview/form_helper/button.yml +0 -38
- data/config/action_view_helpers/actionview/form_helper/submit.yml +0 -35
- data/lib/herb/ast.rb +0 -7
- data/lib/herb/diff_operation.rb +0 -34
- data/lib/herb/diff_result.rb +0 -59
- data/lib/herb/engine/error_formatter.rb +0 -432
- data/lib/herb/engine/parser_error_overlay.rb +0 -773
- data/lib/herb/engine/validation_error_overlay.rb +0 -182
- data/lib/herb/engine/validation_errors.rb +0 -65
- data/lib/herb/engine/validator.rb +0 -80
- data/sig/herb/ast.rbs +0 -6
- data/sig/herb/diff_operation.rbs +0 -34
- data/sig/herb/diff_result.rbs +0 -34
- data/sig/herb/engine/debug.rbs +0 -38
- data/sig/herb/engine/error_formatter.rbs +0 -47
- data/sig/herb/engine/parser_error_overlay.rbs +0 -41
- data/sig/herb/engine/validation_error_overlay.rbs +0 -35
- data/sig/herb/engine/validation_errors.rbs +0 -45
- data/sig/herb/engine/validator.rbs +0 -41
- data/sig/herb_c_extension.rbs +0 -10
data/src/parser.c
CHANGED
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
#include <strings.h>
|
|
24
24
|
|
|
25
25
|
#define MAX_CONSECUTIVE_ERRORS 10
|
|
26
|
-
static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T
|
|
27
|
-
static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_array_T
|
|
28
|
-
static
|
|
26
|
+
static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T** errors);
|
|
27
|
+
static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_array_T** errors);
|
|
28
|
+
static bool parser_element_has_foreign_content(parser_T* parser, hb_string_T tag_name);
|
|
29
|
+
static AST_NODE_T* parser_parse_erb_tag(parser_T* parser);
|
|
29
30
|
static void parser_handle_whitespace(parser_T* parser, token_T* whitespace_token, hb_array_T* children);
|
|
30
31
|
static void parser_consume_whitespace(parser_T* parser, hb_array_T* children);
|
|
31
32
|
static void parser_skip_erb_content(lexer_T* lexer);
|
|
@@ -34,24 +35,6 @@ static bool parser_lookahead_erb_is_control_flow(parser_T* parser);
|
|
|
34
35
|
static void parser_handle_erb_in_open_tag(parser_T* parser, hb_array_T* children);
|
|
35
36
|
static void parser_handle_whitespace_in_open_tag(parser_T* parser, hb_array_T* children);
|
|
36
37
|
|
|
37
|
-
const parser_options_T HERB_DEFAULT_PARSER_OPTIONS = { .track_whitespace = false,
|
|
38
|
-
.analyze = true,
|
|
39
|
-
.strict = true,
|
|
40
|
-
.action_view_helpers = false,
|
|
41
|
-
.transform_conditionals = false,
|
|
42
|
-
.render_nodes = false,
|
|
43
|
-
.strict_locals = false,
|
|
44
|
-
.prism_nodes_deep = false,
|
|
45
|
-
.prism_nodes = false,
|
|
46
|
-
.prism_program = false,
|
|
47
|
-
.dot_notation_tags = false,
|
|
48
|
-
.html = true,
|
|
49
|
-
.start_line = 0,
|
|
50
|
-
.start_column = 0,
|
|
51
|
-
.timeout_ms = 1000,
|
|
52
|
-
.max_errors = 25,
|
|
53
|
-
.deadline_ms = 0 };
|
|
54
|
-
|
|
55
38
|
size_t parser_sizeof(void) {
|
|
56
39
|
return sizeof(struct PARSER_STRUCT);
|
|
57
40
|
}
|
|
@@ -62,25 +45,32 @@ void herb_parser_init(parser_T* parser, lexer_T* lexer, parser_options_T options
|
|
|
62
45
|
parser->current_token = lexer_next_token(lexer);
|
|
63
46
|
parser->open_tags_stack = hb_array_init(16, parser->allocator);
|
|
64
47
|
parser->state = PARSER_STATE_DATA;
|
|
65
|
-
parser->
|
|
48
|
+
parser->foreign_content_kind = FOREIGN_CONTENT_NONE;
|
|
49
|
+
parser->foreign_content_tag_name = HB_STRING_NULL;
|
|
50
|
+
parser->svg_depth = 0;
|
|
51
|
+
parser->xml_document = false;
|
|
66
52
|
parser->options = options;
|
|
67
53
|
parser->consecutive_error_count = 0;
|
|
68
54
|
parser->in_recovery_mode = false;
|
|
55
|
+
|
|
56
|
+
for (size_t index = 0; index < HERB_MAX_FOREIGN_CONTENT_ELEMENTS; index++) {
|
|
57
|
+
parser->foreign_content_absent_from[index] = UINT32_MAX;
|
|
58
|
+
}
|
|
69
59
|
}
|
|
70
60
|
|
|
71
61
|
static AST_CDATA_NODE_T* parser_parse_cdata(parser_T* parser) {
|
|
72
|
-
hb_array_T* errors =
|
|
62
|
+
hb_array_T* errors = NULL;
|
|
73
63
|
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
74
64
|
hb_buffer_T content;
|
|
75
65
|
hb_buffer_init(&content, 128, parser->allocator);
|
|
76
66
|
|
|
77
|
-
token_T* tag_opening = parser_consume_expected(parser, TOKEN_CDATA_START, errors);
|
|
67
|
+
token_T* tag_opening = parser_consume_expected(parser, TOKEN_CDATA_START, &errors);
|
|
78
68
|
position_T start = parser->current_token->location.start;
|
|
79
69
|
|
|
80
70
|
while (token_is_none_of(parser, TOKEN_CDATA_END, TOKEN_EOF)) {
|
|
81
71
|
if (token_is(parser, TOKEN_ERB_START)) {
|
|
82
72
|
parser_append_literal_node_from_buffer(parser, &content, children, start);
|
|
83
|
-
|
|
73
|
+
AST_NODE_T* erb_node = parser_parse_erb_tag(parser);
|
|
84
74
|
hb_array_append(children, erb_node);
|
|
85
75
|
start = parser->current_token->location.start;
|
|
86
76
|
continue;
|
|
@@ -92,7 +82,7 @@ static AST_CDATA_NODE_T* parser_parse_cdata(parser_T* parser) {
|
|
|
92
82
|
}
|
|
93
83
|
|
|
94
84
|
parser_append_literal_node_from_buffer(parser, &content, children, start);
|
|
95
|
-
token_T* tag_closing = parser_consume_expected(parser, TOKEN_CDATA_END, errors);
|
|
85
|
+
token_T* tag_closing = parser_consume_expected(parser, TOKEN_CDATA_END, &errors);
|
|
96
86
|
|
|
97
87
|
AST_CDATA_NODE_T* cdata = ast_cdata_node_init(
|
|
98
88
|
tag_opening,
|
|
@@ -105,26 +95,59 @@ static AST_CDATA_NODE_T* parser_parse_cdata(parser_T* parser) {
|
|
|
105
95
|
);
|
|
106
96
|
|
|
107
97
|
hb_buffer_free(&content);
|
|
108
|
-
token_free(tag_opening, parser->allocator);
|
|
109
|
-
token_free(tag_closing, parser->allocator);
|
|
110
98
|
|
|
111
99
|
return cdata;
|
|
112
100
|
}
|
|
113
101
|
|
|
102
|
+
// <!-- a <!-->
|
|
103
|
+
static token_T* parser_parse_html_comment_abrupt_end(
|
|
104
|
+
parser_T* parser,
|
|
105
|
+
hb_buffer_T* comment,
|
|
106
|
+
hb_array_T* children,
|
|
107
|
+
position_T start
|
|
108
|
+
) {
|
|
109
|
+
token_T* nested_start = parser_advance(parser);
|
|
110
|
+
token_T* tag_end = parser_advance(parser);
|
|
111
|
+
|
|
112
|
+
position_T dashes_start = nested_start->location.start;
|
|
113
|
+
dashes_start.column += 2;
|
|
114
|
+
|
|
115
|
+
hb_buffer_append_string(comment, hb_string("<!"));
|
|
116
|
+
|
|
117
|
+
hb_string_T content = { .data = comment->value, .length = (uint32_t) comment->length };
|
|
118
|
+
hb_array_append(children, ast_literal_node_init(content, start, dashes_start, NULL, parser->allocator));
|
|
119
|
+
hb_buffer_clear(comment);
|
|
120
|
+
|
|
121
|
+
token_T* comment_end = hb_allocator_alloc(parser->allocator, sizeof(token_T));
|
|
122
|
+
|
|
123
|
+
comment_end->type = TOKEN_HTML_COMMENT_END;
|
|
124
|
+
comment_end->value = hb_string_from_data(hb_allocator_strndup(parser->allocator, "-->", 3), 3);
|
|
125
|
+
comment_end->owns_value = true;
|
|
126
|
+
comment_end->location = (location_T) { .start = dashes_start, .end = tag_end->location.end };
|
|
127
|
+
comment_end->range = (range_T) { .from = nested_start->range.from + 2, .to = tag_end->range.to };
|
|
128
|
+
|
|
129
|
+
token_free(nested_start, parser->allocator);
|
|
130
|
+
token_free(tag_end, parser->allocator);
|
|
131
|
+
|
|
132
|
+
return comment_end;
|
|
133
|
+
}
|
|
134
|
+
|
|
114
135
|
static AST_HTML_COMMENT_NODE_T* parser_parse_html_comment(parser_T* parser) {
|
|
115
|
-
hb_array_T* errors =
|
|
136
|
+
hb_array_T* errors = NULL;
|
|
116
137
|
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
117
|
-
token_T* comment_start = parser_consume_expected(parser, TOKEN_HTML_COMMENT_START, errors);
|
|
138
|
+
token_T* comment_start = parser_consume_expected(parser, TOKEN_HTML_COMMENT_START, &errors);
|
|
118
139
|
position_T start = parser->current_token->location.start;
|
|
119
140
|
|
|
120
141
|
hb_buffer_T comment;
|
|
121
142
|
hb_buffer_init(&comment, 512, parser->allocator);
|
|
122
143
|
|
|
144
|
+
token_T* comment_end = NULL;
|
|
145
|
+
|
|
123
146
|
while (token_is_none_of(parser, TOKEN_HTML_COMMENT_END, TOKEN_HTML_COMMENT_INVALID_END, TOKEN_EOF)) {
|
|
124
147
|
if (token_is(parser, TOKEN_ERB_START)) {
|
|
125
148
|
parser_append_literal_node_from_buffer(parser, &comment, children, start);
|
|
126
149
|
|
|
127
|
-
|
|
150
|
+
AST_NODE_T* erb_node = parser_parse_erb_tag(parser);
|
|
128
151
|
hb_array_append(children, erb_node);
|
|
129
152
|
|
|
130
153
|
start = parser->current_token->location.start;
|
|
@@ -132,6 +155,33 @@ static AST_HTML_COMMENT_NODE_T* parser_parse_html_comment(parser_T* parser) {
|
|
|
132
155
|
continue;
|
|
133
156
|
}
|
|
134
157
|
|
|
158
|
+
if (token_is(parser, TOKEN_HTML_COMMENT_START)) {
|
|
159
|
+
lexer_T lexer_copy = *parser->lexer;
|
|
160
|
+
token_T* next_token = lexer_next_token(&lexer_copy);
|
|
161
|
+
token_type_T next_type = next_token ? next_token->type : TOKEN_EOF;
|
|
162
|
+
|
|
163
|
+
if (next_token) { token_free(next_token, parser->allocator); }
|
|
164
|
+
|
|
165
|
+
// <!--[if !mso]><!--><meta><!--<![endif]-->
|
|
166
|
+
if (next_type == TOKEN_HTML_TAG_END) {
|
|
167
|
+
comment_end = parser_parse_html_comment_abrupt_end(parser, &comment, children, start);
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// <!-- outer <!-- inner -->
|
|
172
|
+
if (next_type != TOKEN_EOF && parser->options.strict) {
|
|
173
|
+
append_nested_comment_error(
|
|
174
|
+
comment_start,
|
|
175
|
+
parser->current_token,
|
|
176
|
+
parser->current_token->location.start,
|
|
177
|
+
parser->current_token->location.end,
|
|
178
|
+
parser->allocator,
|
|
179
|
+
&errors,
|
|
180
|
+
&parser->options
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
135
185
|
token_T* token = parser_advance(parser);
|
|
136
186
|
hb_buffer_append_string(&comment, token->value);
|
|
137
187
|
token_free(token, parser->allocator);
|
|
@@ -139,19 +189,31 @@ static AST_HTML_COMMENT_NODE_T* parser_parse_html_comment(parser_T* parser) {
|
|
|
139
189
|
|
|
140
190
|
parser_append_literal_node_from_buffer(parser, &comment, children, start);
|
|
141
191
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (token_is(parser, TOKEN_HTML_COMMENT_INVALID_END)) {
|
|
192
|
+
if (comment_end != NULL) {
|
|
193
|
+
// closed by <!-->
|
|
194
|
+
} else if (token_is(parser, TOKEN_HTML_COMMENT_INVALID_END)) {
|
|
145
195
|
comment_end = parser_advance(parser);
|
|
146
196
|
append_invalid_comment_closing_tag_error(
|
|
147
197
|
comment_end,
|
|
148
198
|
comment_end->location.start,
|
|
149
199
|
comment_end->location.end,
|
|
150
200
|
parser->allocator,
|
|
151
|
-
errors
|
|
201
|
+
&errors,
|
|
202
|
+
&parser->options
|
|
152
203
|
);
|
|
204
|
+
} else if (token_is(parser, TOKEN_EOF)) {
|
|
205
|
+
append_unclosed_comment_error(
|
|
206
|
+
comment_start,
|
|
207
|
+
comment_start->location.start,
|
|
208
|
+
parser->current_token->location.start,
|
|
209
|
+
parser->allocator,
|
|
210
|
+
&errors,
|
|
211
|
+
&parser->options
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
comment_end = parser_advance(parser);
|
|
153
215
|
} else {
|
|
154
|
-
comment_end = parser_consume_expected(parser, TOKEN_HTML_COMMENT_END, errors);
|
|
216
|
+
comment_end = parser_consume_expected(parser, TOKEN_HTML_COMMENT_END, &errors);
|
|
155
217
|
}
|
|
156
218
|
|
|
157
219
|
AST_HTML_COMMENT_NODE_T* comment_node = ast_html_comment_node_init(
|
|
@@ -165,19 +227,17 @@ static AST_HTML_COMMENT_NODE_T* parser_parse_html_comment(parser_T* parser) {
|
|
|
165
227
|
);
|
|
166
228
|
|
|
167
229
|
hb_buffer_free(&comment);
|
|
168
|
-
token_free(comment_start, parser->allocator);
|
|
169
|
-
token_free(comment_end, parser->allocator);
|
|
170
230
|
|
|
171
231
|
return comment_node;
|
|
172
232
|
}
|
|
173
233
|
|
|
174
234
|
static AST_HTML_DOCTYPE_NODE_T* parser_parse_html_doctype(parser_T* parser) {
|
|
175
|
-
hb_array_T* errors =
|
|
235
|
+
hb_array_T* errors = NULL;
|
|
176
236
|
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
177
237
|
hb_buffer_T content;
|
|
178
238
|
hb_buffer_init(&content, 64, parser->allocator);
|
|
179
239
|
|
|
180
|
-
token_T* tag_opening = parser_consume_expected(parser, TOKEN_HTML_DOCTYPE, errors);
|
|
240
|
+
token_T* tag_opening = parser_consume_expected(parser, TOKEN_HTML_DOCTYPE, &errors);
|
|
181
241
|
|
|
182
242
|
position_T start = parser->current_token->location.start;
|
|
183
243
|
|
|
@@ -185,20 +245,20 @@ static AST_HTML_DOCTYPE_NODE_T* parser_parse_html_doctype(parser_T* parser) {
|
|
|
185
245
|
if (token_is(parser, TOKEN_ERB_START)) {
|
|
186
246
|
parser_append_literal_node_from_buffer(parser, &content, children, start);
|
|
187
247
|
|
|
188
|
-
|
|
248
|
+
AST_NODE_T* erb_node = parser_parse_erb_tag(parser);
|
|
189
249
|
hb_array_append(children, erb_node);
|
|
190
250
|
|
|
191
251
|
continue;
|
|
192
252
|
}
|
|
193
253
|
|
|
194
|
-
token_T* token = parser_consume_expected(parser, parser->current_token->type, errors);
|
|
254
|
+
token_T* token = parser_consume_expected(parser, parser->current_token->type, &errors);
|
|
195
255
|
hb_buffer_append_string(&content, token->value);
|
|
196
256
|
token_free(token, parser->allocator);
|
|
197
257
|
}
|
|
198
258
|
|
|
199
259
|
parser_append_literal_node_from_buffer(parser, &content, children, start);
|
|
200
260
|
|
|
201
|
-
token_T* tag_closing = parser_consume_expected(parser, TOKEN_HTML_TAG_END, errors);
|
|
261
|
+
token_T* tag_closing = parser_consume_expected(parser, TOKEN_HTML_TAG_END, &errors);
|
|
202
262
|
|
|
203
263
|
AST_HTML_DOCTYPE_NODE_T* doctype = ast_html_doctype_node_init(
|
|
204
264
|
tag_opening,
|
|
@@ -210,20 +270,20 @@ static AST_HTML_DOCTYPE_NODE_T* parser_parse_html_doctype(parser_T* parser) {
|
|
|
210
270
|
parser->allocator
|
|
211
271
|
);
|
|
212
272
|
|
|
213
|
-
token_free(tag_opening, parser->allocator);
|
|
214
|
-
token_free(tag_closing, parser->allocator);
|
|
215
273
|
hb_buffer_free(&content);
|
|
216
274
|
|
|
217
275
|
return doctype;
|
|
218
276
|
}
|
|
219
277
|
|
|
220
278
|
static AST_XML_DECLARATION_NODE_T* parser_parse_xml_declaration(parser_T* parser) {
|
|
221
|
-
hb_array_T* errors =
|
|
279
|
+
hb_array_T* errors = NULL;
|
|
222
280
|
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
223
281
|
hb_buffer_T content;
|
|
224
282
|
hb_buffer_init(&content, 64, parser->allocator);
|
|
225
283
|
|
|
226
|
-
token_T* tag_opening = parser_consume_expected(parser, TOKEN_XML_DECLARATION, errors);
|
|
284
|
+
token_T* tag_opening = parser_consume_expected(parser, TOKEN_XML_DECLARATION, &errors);
|
|
285
|
+
|
|
286
|
+
parser->xml_document = true;
|
|
227
287
|
|
|
228
288
|
position_T start = parser->current_token->location.start;
|
|
229
289
|
|
|
@@ -231,7 +291,7 @@ static AST_XML_DECLARATION_NODE_T* parser_parse_xml_declaration(parser_T* parser
|
|
|
231
291
|
if (token_is(parser, TOKEN_ERB_START)) {
|
|
232
292
|
parser_append_literal_node_from_buffer(parser, &content, children, start);
|
|
233
293
|
|
|
234
|
-
|
|
294
|
+
AST_NODE_T* erb_node = parser_parse_erb_tag(parser);
|
|
235
295
|
hb_array_append(children, erb_node);
|
|
236
296
|
|
|
237
297
|
start = parser->current_token->location.start;
|
|
@@ -246,7 +306,7 @@ static AST_XML_DECLARATION_NODE_T* parser_parse_xml_declaration(parser_T* parser
|
|
|
246
306
|
|
|
247
307
|
parser_append_literal_node_from_buffer(parser, &content, children, start);
|
|
248
308
|
|
|
249
|
-
token_T* tag_closing = parser_consume_expected(parser, TOKEN_XML_DECLARATION_END, errors);
|
|
309
|
+
token_T* tag_closing = parser_consume_expected(parser, TOKEN_XML_DECLARATION_END, &errors);
|
|
250
310
|
|
|
251
311
|
AST_XML_DECLARATION_NODE_T* xml_declaration = ast_xml_declaration_node_init(
|
|
252
312
|
tag_opening,
|
|
@@ -258,14 +318,61 @@ static AST_XML_DECLARATION_NODE_T* parser_parse_xml_declaration(parser_T* parser
|
|
|
258
318
|
parser->allocator
|
|
259
319
|
);
|
|
260
320
|
|
|
261
|
-
token_free(tag_opening, parser->allocator);
|
|
262
|
-
token_free(tag_closing, parser->allocator);
|
|
263
321
|
hb_buffer_free(&content);
|
|
264
322
|
|
|
265
323
|
return xml_declaration;
|
|
266
324
|
}
|
|
267
325
|
|
|
268
|
-
static
|
|
326
|
+
static AST_XML_PROCESSING_INSTRUCTION_NODE_T* parser_parse_xml_processing_instruction(parser_T* parser) {
|
|
327
|
+
hb_array_T* errors = NULL;
|
|
328
|
+
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
329
|
+
hb_buffer_T content;
|
|
330
|
+
hb_buffer_init(&content, 64, parser->allocator);
|
|
331
|
+
|
|
332
|
+
token_T* tag_opening = parser_consume_expected(parser, TOKEN_XML_PROCESSING_INSTRUCTION_START, &errors);
|
|
333
|
+
token_T* target = parser_consume_expected(parser, TOKEN_IDENTIFIER, &errors);
|
|
334
|
+
|
|
335
|
+
position_T start = parser->current_token->location.start;
|
|
336
|
+
|
|
337
|
+
while (token_is_none_of(parser, TOKEN_XML_DECLARATION_END, TOKEN_HTML_TAG_END, TOKEN_EOF)) {
|
|
338
|
+
if (token_is(parser, TOKEN_ERB_START)) {
|
|
339
|
+
parser_append_literal_node_from_buffer(parser, &content, children, start);
|
|
340
|
+
|
|
341
|
+
AST_NODE_T* erb_node = parser_parse_erb_tag(parser);
|
|
342
|
+
hb_array_append(children, erb_node);
|
|
343
|
+
|
|
344
|
+
start = parser->current_token->location.start;
|
|
345
|
+
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
token_T* token = parser_advance(parser);
|
|
350
|
+
hb_buffer_append_string(&content, token->value);
|
|
351
|
+
token_free(token, parser->allocator);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
parser_append_literal_node_from_buffer(parser, &content, children, start);
|
|
355
|
+
|
|
356
|
+
token_type_T closing_type = token_is(parser, TOKEN_HTML_TAG_END) ? TOKEN_HTML_TAG_END : TOKEN_XML_DECLARATION_END;
|
|
357
|
+
token_T* tag_closing = parser_consume_expected(parser, closing_type, &errors);
|
|
358
|
+
|
|
359
|
+
AST_XML_PROCESSING_INSTRUCTION_NODE_T* processing_instruction = ast_xml_processing_instruction_node_init(
|
|
360
|
+
tag_opening,
|
|
361
|
+
target,
|
|
362
|
+
children,
|
|
363
|
+
tag_closing,
|
|
364
|
+
tag_opening->location.start,
|
|
365
|
+
tag_closing->location.end,
|
|
366
|
+
errors,
|
|
367
|
+
parser->allocator
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
hb_buffer_free(&content);
|
|
371
|
+
|
|
372
|
+
return processing_instruction;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_array_T** document_errors) {
|
|
269
376
|
position_T start = parser->current_token->location.start;
|
|
270
377
|
|
|
271
378
|
hb_buffer_T content;
|
|
@@ -277,6 +384,8 @@ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_arra
|
|
|
277
384
|
TOKEN_HTML_TAG_START_CLOSE,
|
|
278
385
|
TOKEN_HTML_DOCTYPE,
|
|
279
386
|
TOKEN_HTML_COMMENT_START,
|
|
387
|
+
TOKEN_XML_DECLARATION,
|
|
388
|
+
TOKEN_XML_PROCESSING_INSTRUCTION_START,
|
|
280
389
|
TOKEN_ERB_START,
|
|
281
390
|
TOKEN_EOF
|
|
282
391
|
)) {
|
|
@@ -297,7 +406,13 @@ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_arra
|
|
|
297
406
|
position_T stray_end = peek_token->location.end;
|
|
298
407
|
token_free(peek_token, parser->allocator);
|
|
299
408
|
|
|
300
|
-
append_stray_erb_closing_tag_error(
|
|
409
|
+
append_stray_erb_closing_tag_error(
|
|
410
|
+
stray_start,
|
|
411
|
+
stray_end,
|
|
412
|
+
parser->allocator,
|
|
413
|
+
document_errors,
|
|
414
|
+
&parser->options
|
|
415
|
+
);
|
|
301
416
|
|
|
302
417
|
token_T* percent = parser_advance(parser);
|
|
303
418
|
hb_buffer_append_string(&content, percent->value);
|
|
@@ -318,7 +433,7 @@ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_arra
|
|
|
318
433
|
token_free(token, parser->allocator);
|
|
319
434
|
}
|
|
320
435
|
|
|
321
|
-
hb_array_T* errors =
|
|
436
|
+
hb_array_T* errors = NULL;
|
|
322
437
|
|
|
323
438
|
AST_HTML_TEXT_NODE_T* text_node = NULL;
|
|
324
439
|
|
|
@@ -336,22 +451,42 @@ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_arra
|
|
|
336
451
|
return text_node;
|
|
337
452
|
}
|
|
338
453
|
|
|
454
|
+
static bool parser_token_starts_tag(const parser_T* parser) {
|
|
455
|
+
return token_is_any_of(
|
|
456
|
+
parser,
|
|
457
|
+
TOKEN_HTML_TAG_START,
|
|
458
|
+
TOKEN_HTML_TAG_START_CLOSE,
|
|
459
|
+
TOKEN_HTML_COMMENT_START,
|
|
460
|
+
TOKEN_HTML_DOCTYPE,
|
|
461
|
+
TOKEN_XML_PROCESSING_INSTRUCTION_START
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
|
|
339
465
|
static AST_HTML_ATTRIBUTE_NAME_NODE_T* parser_parse_html_attribute_name(parser_T* parser) {
|
|
340
|
-
hb_array_T* errors =
|
|
466
|
+
hb_array_T* errors = NULL;
|
|
341
467
|
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
342
468
|
hb_buffer_T buffer;
|
|
343
469
|
hb_buffer_init(&buffer, 128, parser->allocator);
|
|
344
470
|
position_T start = parser->current_token->location.start;
|
|
345
471
|
|
|
472
|
+
// <div =foo>
|
|
473
|
+
if (token_is(parser, TOKEN_EQUALS)) {
|
|
474
|
+
token_T* equals = parser_advance(parser);
|
|
475
|
+
hb_buffer_append_string(&buffer, equals->value);
|
|
476
|
+
token_free(equals, parser->allocator);
|
|
477
|
+
}
|
|
478
|
+
|
|
346
479
|
while (token_is_none_of(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
480
|
+
parser,
|
|
481
|
+
TOKEN_EQUALS,
|
|
482
|
+
TOKEN_WHITESPACE,
|
|
483
|
+
TOKEN_NEWLINE,
|
|
484
|
+
TOKEN_SLASH,
|
|
485
|
+
TOKEN_HTML_TAG_END,
|
|
486
|
+
TOKEN_HTML_TAG_SELF_CLOSE,
|
|
487
|
+
TOKEN_EOF
|
|
488
|
+
)
|
|
489
|
+
&& !parser_token_starts_tag(parser)) {
|
|
355
490
|
if (token_is(parser, TOKEN_ERB_START)) {
|
|
356
491
|
hb_string_T tag = parser->current_token->value;
|
|
357
492
|
bool is_output_tag = (tag.length >= 3 && tag.data[2] == '=');
|
|
@@ -365,13 +500,24 @@ static AST_HTML_ATTRIBUTE_NAME_NODE_T* parser_parse_html_attribute_name(parser_T
|
|
|
365
500
|
|
|
366
501
|
parser_append_literal_node_from_buffer(parser, &buffer, children, start);
|
|
367
502
|
|
|
368
|
-
|
|
503
|
+
AST_NODE_T* erb_node = parser_parse_erb_tag(parser);
|
|
369
504
|
hb_array_append(children, erb_node);
|
|
370
505
|
|
|
371
506
|
start = parser->current_token->location.start;
|
|
372
507
|
continue;
|
|
373
508
|
}
|
|
374
509
|
|
|
510
|
+
if (token_is(parser, TOKEN_QUOTE)) {
|
|
511
|
+
append_unexpected_character_in_attribute_name_error(
|
|
512
|
+
parser->current_token,
|
|
513
|
+
parser->current_token->location.start,
|
|
514
|
+
parser->current_token->location.end,
|
|
515
|
+
parser->allocator,
|
|
516
|
+
&errors,
|
|
517
|
+
&parser->options
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
|
|
375
521
|
token_T* token = parser_advance(parser);
|
|
376
522
|
hb_buffer_append_string(&buffer, token->value);
|
|
377
523
|
token_free(token, parser->allocator);
|
|
@@ -404,7 +550,7 @@ static AST_HTML_ATTRIBUTE_NAME_NODE_T* parser_parse_html_attribute_name(parser_T
|
|
|
404
550
|
static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value(
|
|
405
551
|
parser_T* parser,
|
|
406
552
|
hb_array_T* children,
|
|
407
|
-
hb_array_T
|
|
553
|
+
hb_array_T** errors
|
|
408
554
|
) {
|
|
409
555
|
hb_buffer_T buffer;
|
|
410
556
|
hb_buffer_init(&buffer, 512, parser->allocator);
|
|
@@ -452,26 +598,23 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value
|
|
|
452
598
|
opening_quote->location.start,
|
|
453
599
|
parser->current_token->location.start,
|
|
454
600
|
parser->allocator,
|
|
455
|
-
errors
|
|
601
|
+
errors,
|
|
602
|
+
&parser->options
|
|
456
603
|
);
|
|
457
604
|
|
|
458
605
|
parser_append_literal_node_from_buffer(parser, &buffer, children, start);
|
|
459
606
|
hb_buffer_free(&buffer);
|
|
460
607
|
|
|
461
|
-
|
|
608
|
+
return ast_html_attribute_value_node_init(
|
|
462
609
|
opening_quote,
|
|
463
610
|
children,
|
|
464
611
|
NULL,
|
|
465
612
|
true,
|
|
466
613
|
opening_quote->location.start,
|
|
467
614
|
parser->current_token->location.start,
|
|
468
|
-
errors,
|
|
615
|
+
*errors,
|
|
469
616
|
parser->allocator
|
|
470
617
|
);
|
|
471
|
-
|
|
472
|
-
token_free(opening_quote, parser->allocator);
|
|
473
|
-
|
|
474
|
-
return attribute_value;
|
|
475
618
|
}
|
|
476
619
|
|
|
477
620
|
bool buffer_ends_with_whitespace = buffer.length > 0 && is_whitespace(buffer.value[buffer.length - 1]);
|
|
@@ -499,26 +642,23 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value
|
|
|
499
642
|
opening_quote->location.start,
|
|
500
643
|
parser->current_token->location.start,
|
|
501
644
|
parser->allocator,
|
|
502
|
-
errors
|
|
645
|
+
errors,
|
|
646
|
+
&parser->options
|
|
503
647
|
);
|
|
504
648
|
|
|
505
649
|
parser_append_literal_node_from_buffer(parser, &buffer, children, start);
|
|
506
650
|
hb_buffer_free(&buffer);
|
|
507
651
|
|
|
508
|
-
|
|
652
|
+
return ast_html_attribute_value_node_init(
|
|
509
653
|
opening_quote,
|
|
510
654
|
children,
|
|
511
655
|
NULL,
|
|
512
656
|
true,
|
|
513
657
|
opening_quote->location.start,
|
|
514
658
|
parser->current_token->location.start,
|
|
515
|
-
errors,
|
|
659
|
+
*errors,
|
|
516
660
|
parser->allocator
|
|
517
661
|
);
|
|
518
|
-
|
|
519
|
-
token_free(opening_quote, parser->allocator);
|
|
520
|
-
|
|
521
|
-
return attribute_value;
|
|
522
662
|
}
|
|
523
663
|
}
|
|
524
664
|
|
|
@@ -538,176 +678,133 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value
|
|
|
538
678
|
parser->current_token = lexer_next_token(parser->lexer);
|
|
539
679
|
}
|
|
540
680
|
|
|
541
|
-
if (token_is(parser, TOKEN_QUOTE) && opening_quote != NULL
|
|
542
|
-
&& hb_string_equals(parser->current_token->value, opening_quote->value)) {
|
|
543
|
-
lexer_state_snapshot_T saved_state = lexer_save_state(parser->lexer);
|
|
544
|
-
|
|
545
|
-
token_T* potential_closing = parser->current_token;
|
|
546
|
-
parser->current_token = lexer_next_token(parser->lexer);
|
|
547
|
-
|
|
548
|
-
if (token_is(parser, TOKEN_IDENTIFIER) || token_is(parser, TOKEN_CHARACTER)) {
|
|
549
|
-
append_unexpected_error(
|
|
550
|
-
hb_string("Unescaped quote character in attribute value"),
|
|
551
|
-
hb_string("HTML entity ('/") or different quote style"),
|
|
552
|
-
opening_quote->value,
|
|
553
|
-
potential_closing->location.start,
|
|
554
|
-
potential_closing->location.end,
|
|
555
|
-
parser->allocator,
|
|
556
|
-
errors
|
|
557
|
-
);
|
|
558
|
-
|
|
559
|
-
lexer_restore_state(parser->lexer, saved_state);
|
|
560
|
-
|
|
561
|
-
token_free(parser->current_token, parser->allocator);
|
|
562
|
-
parser->current_token = potential_closing;
|
|
563
|
-
|
|
564
|
-
hb_buffer_append_string(&buffer, parser->current_token->value);
|
|
565
|
-
token_free(parser->current_token, parser->allocator);
|
|
566
|
-
parser->current_token = lexer_next_token(parser->lexer);
|
|
567
|
-
|
|
568
|
-
while (!token_is(parser, TOKEN_EOF)
|
|
569
|
-
&& !(
|
|
570
|
-
token_is(parser, TOKEN_QUOTE) && opening_quote != NULL
|
|
571
|
-
&& hb_string_equals(parser->current_token->value, opening_quote->value)
|
|
572
|
-
)) {
|
|
573
|
-
if (token_is(parser, TOKEN_ERB_START)) {
|
|
574
|
-
parser_append_literal_node_from_buffer(parser, &buffer, children, start);
|
|
575
|
-
|
|
576
|
-
hb_array_append(children, parser_parse_erb_tag(parser));
|
|
577
|
-
|
|
578
|
-
start = parser->current_token->location.start;
|
|
579
|
-
|
|
580
|
-
continue;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
hb_buffer_append_string(&buffer, parser->current_token->value);
|
|
584
|
-
token_free(parser->current_token, parser->allocator);
|
|
585
|
-
|
|
586
|
-
parser->current_token = lexer_next_token(parser->lexer);
|
|
587
|
-
}
|
|
588
|
-
} else {
|
|
589
|
-
token_free(parser->current_token, parser->allocator);
|
|
590
|
-
parser->current_token = potential_closing;
|
|
591
|
-
|
|
592
|
-
lexer_restore_state(parser->lexer, saved_state);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
681
|
parser_append_literal_node_from_buffer(parser, &buffer, children, start);
|
|
597
682
|
hb_buffer_free(&buffer);
|
|
598
683
|
|
|
599
684
|
token_T* closing_quote = parser_consume_expected(parser, TOKEN_QUOTE, errors);
|
|
600
685
|
|
|
601
|
-
|
|
686
|
+
return ast_html_attribute_value_node_init(
|
|
602
687
|
opening_quote,
|
|
603
688
|
children,
|
|
604
689
|
closing_quote,
|
|
605
690
|
true,
|
|
606
691
|
opening_quote->location.start,
|
|
607
692
|
closing_quote->location.end,
|
|
608
|
-
errors,
|
|
693
|
+
*errors,
|
|
609
694
|
parser->allocator
|
|
610
695
|
);
|
|
696
|
+
}
|
|
611
697
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
return attribute_value;
|
|
698
|
+
static bool parser_attribute_value_is_missing(const parser_T* parser) {
|
|
699
|
+
return token_is_any_of(parser, TOKEN_HTML_TAG_END, TOKEN_HTML_TAG_SELF_CLOSE, TOKEN_EOF)
|
|
700
|
+
|| parser_token_starts_tag(parser);
|
|
616
701
|
}
|
|
617
702
|
|
|
618
703
|
static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser_T* parser) {
|
|
619
704
|
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
620
|
-
hb_array_T* errors =
|
|
705
|
+
hb_array_T* errors = NULL;
|
|
621
706
|
|
|
622
|
-
// <div id
|
|
623
|
-
if (token_is(parser,
|
|
624
|
-
AST_ERB_CONTENT_NODE_T* erb_node = parser_parse_erb_tag(parser);
|
|
625
|
-
hb_array_append(children, erb_node);
|
|
707
|
+
// <div id="home">
|
|
708
|
+
if (token_is(parser, TOKEN_QUOTE)) { return parser_parse_quoted_html_attribute_value(parser, children, &errors); }
|
|
626
709
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
)
|
|
637
|
-
|
|
710
|
+
// <div id=home> or <div id=<%= "home" %>>
|
|
711
|
+
hb_buffer_T buffer;
|
|
712
|
+
hb_buffer_init(&buffer, 128, parser->allocator);
|
|
713
|
+
position_T value_start = parser->current_token->location.start;
|
|
714
|
+
position_T value_end = value_start;
|
|
715
|
+
position_T start = value_start;
|
|
716
|
+
|
|
717
|
+
while (
|
|
718
|
+
token_is_none_of(parser, TOKEN_WHITESPACE, TOKEN_NEWLINE, TOKEN_HTML_TAG_END, TOKEN_HTML_TAG_SELF_CLOSE, TOKEN_EOF)
|
|
719
|
+
&& !parser_token_starts_tag(parser)
|
|
720
|
+
) {
|
|
721
|
+
if (token_is(parser, TOKEN_ERB_START)) {
|
|
722
|
+
parser_append_literal_node_from_buffer(parser, &buffer, children, start);
|
|
638
723
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
token_T* identifier = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors);
|
|
642
|
-
AST_LITERAL_NODE_T* literal = ast_literal_node_init_from_token(identifier, parser->allocator);
|
|
643
|
-
token_free(identifier, parser->allocator);
|
|
724
|
+
AST_NODE_T* erb_node = parser_parse_erb_tag(parser);
|
|
725
|
+
hb_array_append(children, erb_node);
|
|
644
726
|
|
|
645
|
-
|
|
727
|
+
value_end = erb_node->location.end;
|
|
728
|
+
start = parser->current_token->location.start;
|
|
646
729
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
children,
|
|
650
|
-
NULL,
|
|
651
|
-
false,
|
|
652
|
-
literal->base.location.start,
|
|
653
|
-
literal->base.location.end,
|
|
654
|
-
errors,
|
|
655
|
-
parser->allocator
|
|
656
|
-
);
|
|
657
|
-
}
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
658
732
|
|
|
659
|
-
|
|
660
|
-
|
|
733
|
+
if (token_is_any_of(parser, TOKEN_QUOTE, TOKEN_BACKTICK, TOKEN_EQUALS)) {
|
|
734
|
+
append_unexpected_character_in_unquoted_attribute_value_error(
|
|
735
|
+
parser->current_token,
|
|
736
|
+
parser->current_token->location.start,
|
|
737
|
+
parser->current_token->location.end,
|
|
738
|
+
parser->allocator,
|
|
739
|
+
&errors,
|
|
740
|
+
&parser->options
|
|
741
|
+
);
|
|
742
|
+
}
|
|
661
743
|
|
|
662
|
-
if (token_is(parser, TOKEN_BACKTICK)) {
|
|
663
744
|
token_T* token = parser_advance(parser);
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
hb_string("Invalid quote character for HTML attribute"),
|
|
669
|
-
hb_string("single quote (') or double quote (\")"),
|
|
670
|
-
hb_string("a backtick"),
|
|
671
|
-
start,
|
|
672
|
-
end,
|
|
673
|
-
parser->allocator,
|
|
674
|
-
errors
|
|
675
|
-
);
|
|
745
|
+
hb_buffer_append_string(&buffer, token->value);
|
|
746
|
+
value_end = token->location.end;
|
|
747
|
+
token_free(token, parser->allocator);
|
|
748
|
+
}
|
|
676
749
|
|
|
677
|
-
|
|
678
|
-
|
|
750
|
+
parser_append_literal_node_from_buffer(parser, &buffer, children, start);
|
|
751
|
+
hb_buffer_free(&buffer);
|
|
679
752
|
|
|
680
|
-
|
|
753
|
+
return ast_html_attribute_value_node_init(
|
|
754
|
+
NULL,
|
|
755
|
+
children,
|
|
756
|
+
NULL,
|
|
757
|
+
false,
|
|
758
|
+
value_start,
|
|
759
|
+
value_end,
|
|
760
|
+
errors,
|
|
761
|
+
parser->allocator
|
|
762
|
+
);
|
|
763
|
+
}
|
|
681
764
|
|
|
682
|
-
|
|
683
|
-
|
|
765
|
+
static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute_missing_value(
|
|
766
|
+
parser_T* parser,
|
|
767
|
+
AST_HTML_ATTRIBUTE_NAME_NODE_T* attribute_name,
|
|
768
|
+
token_T* equals
|
|
769
|
+
) {
|
|
770
|
+
hb_array_T* errors = NULL;
|
|
771
|
+
hb_string_T attribute_name_string = hb_string("unknown");
|
|
772
|
+
|
|
773
|
+
if (hb_array_size(attribute_name->children) > 0) {
|
|
774
|
+
AST_LITERAL_NODE_T* first_child = (AST_LITERAL_NODE_T*) hb_array_get(attribute_name->children, 0);
|
|
684
775
|
|
|
685
|
-
|
|
776
|
+
if (first_child && !hb_string_is_empty(first_child->content)) { attribute_name_string = first_child->content; }
|
|
777
|
+
}
|
|
686
778
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
token_type_to_friendly_string(parser->current_token->type),
|
|
779
|
+
append_missing_attribute_value_error(
|
|
780
|
+
attribute_name_string,
|
|
781
|
+
equals->location.start,
|
|
691
782
|
parser->current_token->location.start,
|
|
692
|
-
parser->current_token->location.end,
|
|
693
783
|
parser->allocator,
|
|
694
|
-
errors
|
|
784
|
+
&errors,
|
|
785
|
+
&parser->options
|
|
695
786
|
);
|
|
696
787
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
AST_HTML_ATTRIBUTE_VALUE_NODE_T* value = ast_html_attribute_value_node_init(
|
|
788
|
+
AST_HTML_ATTRIBUTE_VALUE_NODE_T* empty_value = ast_html_attribute_value_node_init(
|
|
700
789
|
NULL,
|
|
701
|
-
|
|
790
|
+
hb_array_init(8, parser->allocator),
|
|
702
791
|
NULL,
|
|
703
792
|
false,
|
|
793
|
+
equals->location.end,
|
|
704
794
|
parser->current_token->location.start,
|
|
705
|
-
parser->current_token->location.end,
|
|
706
795
|
errors,
|
|
707
796
|
parser->allocator
|
|
708
797
|
);
|
|
709
798
|
|
|
710
|
-
return
|
|
799
|
+
return ast_html_attribute_node_init(
|
|
800
|
+
attribute_name,
|
|
801
|
+
equals,
|
|
802
|
+
empty_value,
|
|
803
|
+
attribute_name->base.location.start,
|
|
804
|
+
parser->current_token->location.start,
|
|
805
|
+
NULL,
|
|
806
|
+
parser->allocator
|
|
807
|
+
);
|
|
711
808
|
}
|
|
712
809
|
|
|
713
810
|
static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute(parser_T* parser) {
|
|
@@ -780,12 +877,18 @@ static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute(parser_T* parser)
|
|
|
780
877
|
|
|
781
878
|
char* arena_copy = hb_allocator_strndup(parser->allocator, equals_buffer.value, equals_buffer.length);
|
|
782
879
|
equals_with_whitespace->value = hb_string_from_data(arena_copy, equals_buffer.length);
|
|
880
|
+
equals_with_whitespace->owns_value = true;
|
|
783
881
|
|
|
784
882
|
hb_buffer_free(&equals_buffer);
|
|
785
883
|
|
|
786
884
|
equals_with_whitespace->location = (location_T) { .start = equals_start, .end = equals_end };
|
|
787
885
|
equals_with_whitespace->range = (range_T) { .from = range_start, .to = range_end };
|
|
788
886
|
|
|
887
|
+
// <div class = >
|
|
888
|
+
if (parser_attribute_value_is_missing(parser)) {
|
|
889
|
+
return parser_parse_html_attribute_missing_value(parser, attribute_name, equals_with_whitespace);
|
|
890
|
+
}
|
|
891
|
+
|
|
789
892
|
AST_HTML_ATTRIBUTE_VALUE_NODE_T* attribute_value = parser_parse_html_attribute_value(parser);
|
|
790
893
|
|
|
791
894
|
return ast_html_attribute_node_init(
|
|
@@ -818,53 +921,13 @@ static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute(parser_T* parser)
|
|
|
818
921
|
parser_consume_whitespace(parser, NULL);
|
|
819
922
|
|
|
820
923
|
// <div class= >
|
|
821
|
-
if (
|
|
822
|
-
|
|
823
|
-
hb_string_T attribute_name_string = hb_string("unknown");
|
|
824
|
-
|
|
825
|
-
if (hb_array_size(attribute_name->children) > 0) {
|
|
826
|
-
AST_LITERAL_NODE_T* first_child = (AST_LITERAL_NODE_T*) hb_array_get(attribute_name->children, 0);
|
|
827
|
-
|
|
828
|
-
if (first_child && !hb_string_is_empty(first_child->content)) { attribute_name_string = first_child->content; }
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
append_missing_attribute_value_error(
|
|
832
|
-
attribute_name_string,
|
|
833
|
-
equals->location.start,
|
|
834
|
-
parser->current_token->location.start,
|
|
835
|
-
parser->allocator,
|
|
836
|
-
errors
|
|
837
|
-
);
|
|
838
|
-
|
|
839
|
-
AST_HTML_ATTRIBUTE_VALUE_NODE_T* empty_value = ast_html_attribute_value_node_init(
|
|
840
|
-
NULL,
|
|
841
|
-
hb_array_init(8, parser->allocator),
|
|
842
|
-
NULL,
|
|
843
|
-
false,
|
|
844
|
-
equals->location.end,
|
|
845
|
-
parser->current_token->location.start,
|
|
846
|
-
errors,
|
|
847
|
-
parser->allocator
|
|
848
|
-
);
|
|
849
|
-
|
|
850
|
-
AST_HTML_ATTRIBUTE_NODE_T* attribute_node = ast_html_attribute_node_init(
|
|
851
|
-
attribute_name,
|
|
852
|
-
equals,
|
|
853
|
-
empty_value,
|
|
854
|
-
attribute_name->base.location.start,
|
|
855
|
-
parser->current_token->location.start,
|
|
856
|
-
NULL,
|
|
857
|
-
parser->allocator
|
|
858
|
-
);
|
|
859
|
-
|
|
860
|
-
token_free(equals, parser->allocator);
|
|
861
|
-
|
|
862
|
-
return attribute_node;
|
|
924
|
+
if (parser_attribute_value_is_missing(parser)) {
|
|
925
|
+
return parser_parse_html_attribute_missing_value(parser, attribute_name, equals);
|
|
863
926
|
}
|
|
864
927
|
|
|
865
928
|
AST_HTML_ATTRIBUTE_VALUE_NODE_T* attribute_value = parser_parse_html_attribute_value(parser);
|
|
866
929
|
|
|
867
|
-
|
|
930
|
+
return ast_html_attribute_node_init(
|
|
868
931
|
attribute_name,
|
|
869
932
|
equals,
|
|
870
933
|
attribute_value,
|
|
@@ -873,10 +936,6 @@ static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute(parser_T* parser)
|
|
|
873
936
|
NULL,
|
|
874
937
|
parser->allocator
|
|
875
938
|
);
|
|
876
|
-
|
|
877
|
-
token_free(equals, parser->allocator);
|
|
878
|
-
|
|
879
|
-
return attribute_node;
|
|
880
939
|
}
|
|
881
940
|
|
|
882
941
|
return ast_html_attribute_node_init(
|
|
@@ -1032,25 +1091,28 @@ static void parser_handle_whitespace_in_open_tag(parser_T* parser, hb_array_T* c
|
|
|
1032
1091
|
}
|
|
1033
1092
|
|
|
1034
1093
|
static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
1035
|
-
hb_array_T* errors =
|
|
1094
|
+
hb_array_T* errors = NULL;
|
|
1036
1095
|
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
1037
1096
|
|
|
1038
|
-
token_T* tag_start = parser_consume_expected(parser, TOKEN_HTML_TAG_START, errors);
|
|
1039
|
-
token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors);
|
|
1097
|
+
token_T* tag_start = parser_consume_expected(parser, TOKEN_HTML_TAG_START, &errors);
|
|
1098
|
+
token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, &errors);
|
|
1099
|
+
|
|
1100
|
+
parser_consume_dot_notation_segments(parser, tag_name, &errors);
|
|
1040
1101
|
|
|
1041
|
-
|
|
1102
|
+
bool previous_was_quoted_value = false;
|
|
1042
1103
|
|
|
1043
1104
|
while (token_is_none_of(parser, TOKEN_HTML_TAG_END, TOKEN_HTML_TAG_SELF_CLOSE, TOKEN_EOF)) {
|
|
1044
|
-
if (
|
|
1105
|
+
if (parser_token_starts_tag(parser)) {
|
|
1045
1106
|
append_unclosed_open_tag_error(
|
|
1046
1107
|
tag_name,
|
|
1047
1108
|
tag_name->location.start,
|
|
1048
1109
|
parser->current_token->location.start,
|
|
1049
1110
|
parser->allocator,
|
|
1050
|
-
errors
|
|
1111
|
+
&errors,
|
|
1112
|
+
&parser->options
|
|
1051
1113
|
);
|
|
1052
1114
|
|
|
1053
|
-
|
|
1115
|
+
return ast_html_open_tag_node_init(
|
|
1054
1116
|
tag_start,
|
|
1055
1117
|
tag_name,
|
|
1056
1118
|
NULL,
|
|
@@ -1061,48 +1123,21 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
|
1061
1123
|
errors,
|
|
1062
1124
|
parser->allocator
|
|
1063
1125
|
);
|
|
1064
|
-
|
|
1065
|
-
token_free(tag_start, parser->allocator);
|
|
1066
|
-
token_free(tag_name, parser->allocator);
|
|
1067
|
-
|
|
1068
|
-
return open_tag_node;
|
|
1069
1126
|
}
|
|
1070
1127
|
|
|
1071
1128
|
if (token_is_any_of(parser, TOKEN_WHITESPACE, TOKEN_NEWLINE)) {
|
|
1129
|
+
previous_was_quoted_value = false;
|
|
1072
1130
|
parser_handle_whitespace_in_open_tag(parser, children);
|
|
1073
1131
|
continue;
|
|
1074
1132
|
}
|
|
1075
1133
|
|
|
1076
|
-
if (parser
|
|
1077
|
-
|
|
1078
|
-
continue;
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
if (parser->current_token->type == TOKEN_ERB_START) {
|
|
1134
|
+
if (token_is(parser, TOKEN_ERB_START)) {
|
|
1135
|
+
previous_was_quoted_value = false;
|
|
1082
1136
|
parser_handle_erb_in_open_tag(parser, children);
|
|
1083
1137
|
continue;
|
|
1084
1138
|
}
|
|
1085
1139
|
|
|
1086
|
-
if (parser
|
|
1087
|
-
hb_array_append(children, parser_parse_html_attribute(parser));
|
|
1088
|
-
continue;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
if (parser->current_token->type == TOKEN_COLON) {
|
|
1092
|
-
lexer_T lexer_copy = *parser->lexer;
|
|
1093
|
-
token_T* next_token = lexer_next_token(&lexer_copy);
|
|
1094
|
-
|
|
1095
|
-
if (next_token && next_token->type == TOKEN_IDENTIFIER) {
|
|
1096
|
-
token_free(next_token, parser->allocator);
|
|
1097
|
-
hb_array_append(children, parser_parse_html_attribute(parser));
|
|
1098
|
-
|
|
1099
|
-
continue;
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
token_free(next_token, parser->allocator);
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
if (parser->current_token->type == TOKEN_PERCENT) {
|
|
1140
|
+
if (token_is(parser, TOKEN_PERCENT)) {
|
|
1106
1141
|
lexer_T lexer_copy = *parser->lexer;
|
|
1107
1142
|
token_T* peek_token = lexer_next_token(&lexer_copy);
|
|
1108
1143
|
|
|
@@ -1111,7 +1146,7 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
|
1111
1146
|
position_T stray_end = peek_token->location.end;
|
|
1112
1147
|
token_free(peek_token, parser->allocator);
|
|
1113
1148
|
|
|
1114
|
-
append_stray_erb_closing_tag_error(stray_start, stray_end, parser->allocator, errors);
|
|
1149
|
+
append_stray_erb_closing_tag_error(stray_start, stray_end, parser->allocator, &errors, &parser->options);
|
|
1115
1150
|
|
|
1116
1151
|
token_T* percent = parser_advance(parser);
|
|
1117
1152
|
token_T* gt = parser_advance(parser);
|
|
@@ -1123,22 +1158,73 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
|
1123
1158
|
token_free(percent, parser->allocator);
|
|
1124
1159
|
token_free(gt, parser->allocator);
|
|
1125
1160
|
|
|
1161
|
+
previous_was_quoted_value = false;
|
|
1126
1162
|
continue;
|
|
1127
1163
|
}
|
|
1128
1164
|
|
|
1129
1165
|
token_free(peek_token, parser->allocator);
|
|
1130
1166
|
}
|
|
1131
1167
|
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1168
|
+
// <div / class="a">
|
|
1169
|
+
if (token_is(parser, TOKEN_SLASH)) {
|
|
1170
|
+
token_T* solidus = parser_advance(parser);
|
|
1171
|
+
|
|
1172
|
+
append_unexpected_solidus_in_tag_error(
|
|
1173
|
+
solidus,
|
|
1174
|
+
solidus->location.start,
|
|
1175
|
+
solidus->location.end,
|
|
1176
|
+
parser->allocator,
|
|
1177
|
+
&errors,
|
|
1178
|
+
&parser->options
|
|
1179
|
+
);
|
|
1180
|
+
|
|
1181
|
+
token_free(solidus, parser->allocator);
|
|
1182
|
+
previous_was_quoted_value = false;
|
|
1183
|
+
continue;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
if (token_is(parser, TOKEN_ERROR)) {
|
|
1187
|
+
parser_append_unexpected_error(
|
|
1188
|
+
parser,
|
|
1189
|
+
&errors,
|
|
1190
|
+
"Unexpected Token",
|
|
1191
|
+
TOKEN_IDENTIFIER,
|
|
1192
|
+
TOKEN_AT,
|
|
1193
|
+
TOKEN_ERB_START,
|
|
1194
|
+
TOKEN_WHITESPACE,
|
|
1195
|
+
TOKEN_NEWLINE
|
|
1196
|
+
);
|
|
1197
|
+
continue;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
// <div class="a"id="b">
|
|
1201
|
+
if (previous_was_quoted_value) {
|
|
1202
|
+
append_missing_whitespace_between_attributes_error(
|
|
1203
|
+
parser->current_token,
|
|
1204
|
+
parser->current_token->location.start,
|
|
1205
|
+
parser->current_token->location.end,
|
|
1206
|
+
parser->allocator,
|
|
1207
|
+
&errors,
|
|
1208
|
+
&parser->options
|
|
1209
|
+
);
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
// <div =foo>
|
|
1213
|
+
if (token_is(parser, TOKEN_EQUALS)) {
|
|
1214
|
+
append_unexpected_equals_sign_before_attribute_name_error(
|
|
1215
|
+
parser->current_token,
|
|
1216
|
+
parser->current_token->location.start,
|
|
1217
|
+
parser->current_token->location.end,
|
|
1218
|
+
parser->allocator,
|
|
1219
|
+
&errors,
|
|
1220
|
+
&parser->options
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
AST_HTML_ATTRIBUTE_NODE_T* attribute = parser_parse_html_attribute(parser);
|
|
1225
|
+
hb_array_append(children, attribute);
|
|
1226
|
+
|
|
1227
|
+
previous_was_quoted_value = attribute->value != NULL && attribute->value->close_quote != NULL;
|
|
1142
1228
|
}
|
|
1143
1229
|
|
|
1144
1230
|
if (token_is(parser, TOKEN_EOF)) {
|
|
@@ -1147,10 +1233,11 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
|
1147
1233
|
tag_name->location.start,
|
|
1148
1234
|
parser->current_token->location.start,
|
|
1149
1235
|
parser->allocator,
|
|
1150
|
-
errors
|
|
1236
|
+
&errors,
|
|
1237
|
+
&parser->options
|
|
1151
1238
|
);
|
|
1152
1239
|
|
|
1153
|
-
|
|
1240
|
+
return ast_html_open_tag_node_init(
|
|
1154
1241
|
tag_start,
|
|
1155
1242
|
tag_name,
|
|
1156
1243
|
NULL,
|
|
@@ -1161,11 +1248,6 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
|
1161
1248
|
errors,
|
|
1162
1249
|
parser->allocator
|
|
1163
1250
|
);
|
|
1164
|
-
|
|
1165
|
-
token_free(tag_start, parser->allocator);
|
|
1166
|
-
token_free(tag_name, parser->allocator);
|
|
1167
|
-
|
|
1168
|
-
return open_tag_node;
|
|
1169
1251
|
}
|
|
1170
1252
|
|
|
1171
1253
|
bool is_self_closing = false;
|
|
@@ -1173,7 +1255,7 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
|
1173
1255
|
token_T* tag_end = parser_consume_if_present(parser, TOKEN_HTML_TAG_END);
|
|
1174
1256
|
|
|
1175
1257
|
if (tag_end == NULL) {
|
|
1176
|
-
tag_end = parser_consume_expected(parser, TOKEN_HTML_TAG_SELF_CLOSE, errors);
|
|
1258
|
+
tag_end = parser_consume_expected(parser, TOKEN_HTML_TAG_SELF_CLOSE, &errors);
|
|
1177
1259
|
|
|
1178
1260
|
if (tag_end == NULL) {
|
|
1179
1261
|
token_free(tag_start, parser->allocator);
|
|
@@ -1188,7 +1270,7 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
|
1188
1270
|
is_self_closing = true;
|
|
1189
1271
|
}
|
|
1190
1272
|
|
|
1191
|
-
|
|
1273
|
+
return ast_html_open_tag_node_init(
|
|
1192
1274
|
tag_start,
|
|
1193
1275
|
tag_name,
|
|
1194
1276
|
tag_end,
|
|
@@ -1199,37 +1281,50 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
|
1199
1281
|
errors,
|
|
1200
1282
|
parser->allocator
|
|
1201
1283
|
);
|
|
1202
|
-
|
|
1203
|
-
token_free(tag_start, parser->allocator);
|
|
1204
|
-
token_free(tag_name, parser->allocator);
|
|
1205
|
-
token_free(tag_end, parser->allocator);
|
|
1206
|
-
|
|
1207
|
-
return open_tag_node;
|
|
1208
1284
|
}
|
|
1209
1285
|
|
|
1210
1286
|
static AST_HTML_CLOSE_TAG_NODE_T* parser_parse_html_close_tag(parser_T* parser) {
|
|
1211
|
-
hb_array_T* errors =
|
|
1287
|
+
hb_array_T* errors = NULL;
|
|
1212
1288
|
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
1213
1289
|
|
|
1214
|
-
token_T* tag_opening = parser_consume_expected(parser, TOKEN_HTML_TAG_START_CLOSE, errors);
|
|
1290
|
+
token_T* tag_opening = parser_consume_expected(parser, TOKEN_HTML_TAG_START_CLOSE, &errors);
|
|
1215
1291
|
|
|
1216
1292
|
parser_consume_whitespace(parser, children);
|
|
1217
1293
|
|
|
1218
|
-
token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors);
|
|
1294
|
+
token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, &errors);
|
|
1219
1295
|
|
|
1220
|
-
parser_consume_dot_notation_segments(parser, tag_name, errors);
|
|
1296
|
+
parser_consume_dot_notation_segments(parser, tag_name, &errors);
|
|
1297
|
+
|
|
1298
|
+
if (parser->svg_depth > 0 && hb_string_equals_case_insensitive(tag_name->value, hb_string("svg"))) {
|
|
1299
|
+
parser->svg_depth--;
|
|
1300
|
+
}
|
|
1221
1301
|
|
|
1222
1302
|
parser_consume_whitespace(parser, children);
|
|
1223
1303
|
|
|
1224
1304
|
token_T* tag_closing = parser_consume_if_present(parser, TOKEN_HTML_TAG_END);
|
|
1225
1305
|
|
|
1306
|
+
// </div/>
|
|
1307
|
+
if (tag_closing == NULL && token_is(parser, TOKEN_HTML_TAG_SELF_CLOSE) && tag_name != NULL) {
|
|
1308
|
+
tag_closing = parser_advance(parser);
|
|
1309
|
+
|
|
1310
|
+
append_end_tag_with_trailing_solidus_error(
|
|
1311
|
+
tag_name,
|
|
1312
|
+
tag_closing->location.start,
|
|
1313
|
+
tag_closing->location.end,
|
|
1314
|
+
parser->allocator,
|
|
1315
|
+
&errors,
|
|
1316
|
+
&parser->options
|
|
1317
|
+
);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1226
1320
|
if (tag_closing == NULL) {
|
|
1227
1321
|
append_unclosed_close_tag_error(
|
|
1228
1322
|
tag_name,
|
|
1229
1323
|
tag_opening->location.start,
|
|
1230
1324
|
tag_name->location.end,
|
|
1231
1325
|
parser->allocator,
|
|
1232
|
-
errors
|
|
1326
|
+
&errors,
|
|
1327
|
+
&parser->options
|
|
1233
1328
|
);
|
|
1234
1329
|
}
|
|
1235
1330
|
|
|
@@ -1245,7 +1340,8 @@ static AST_HTML_CLOSE_TAG_NODE_T* parser_parse_html_close_tag(parser_T* parser)
|
|
|
1245
1340
|
tag_opening->location.start,
|
|
1246
1341
|
tag_closing->location.end,
|
|
1247
1342
|
parser->allocator,
|
|
1248
|
-
errors
|
|
1343
|
+
&errors,
|
|
1344
|
+
&parser->options
|
|
1249
1345
|
);
|
|
1250
1346
|
|
|
1251
1347
|
hb_allocator_dealloc(parser->allocator, expected.data);
|
|
@@ -1254,7 +1350,7 @@ static AST_HTML_CLOSE_TAG_NODE_T* parser_parse_html_close_tag(parser_T* parser)
|
|
|
1254
1350
|
|
|
1255
1351
|
position_T end_position = tag_closing != NULL ? tag_closing->location.end : tag_name->location.end;
|
|
1256
1352
|
|
|
1257
|
-
|
|
1353
|
+
return ast_html_close_tag_node_init(
|
|
1258
1354
|
tag_opening,
|
|
1259
1355
|
tag_name,
|
|
1260
1356
|
children,
|
|
@@ -1264,12 +1360,6 @@ static AST_HTML_CLOSE_TAG_NODE_T* parser_parse_html_close_tag(parser_T* parser)
|
|
|
1264
1360
|
errors,
|
|
1265
1361
|
parser->allocator
|
|
1266
1362
|
);
|
|
1267
|
-
|
|
1268
|
-
token_free(tag_opening, parser->allocator);
|
|
1269
|
-
token_free(tag_name, parser->allocator);
|
|
1270
|
-
token_free(tag_closing, parser->allocator);
|
|
1271
|
-
|
|
1272
|
-
return close_tag;
|
|
1273
1363
|
}
|
|
1274
1364
|
|
|
1275
1365
|
// TODO: this should probably be AST_HTML_ELEMENT_NODE_T with a AST_HTML_SELF_CLOSING_TAG_NODE_T
|
|
@@ -1279,7 +1369,7 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_self_closing_element(
|
|
|
1279
1369
|
) {
|
|
1280
1370
|
return ast_html_element_node_init(
|
|
1281
1371
|
(AST_NODE_T*) open_tag,
|
|
1282
|
-
open_tag->tag_name,
|
|
1372
|
+
token_copy(open_tag->tag_name, parser->allocator),
|
|
1283
1373
|
NULL,
|
|
1284
1374
|
NULL,
|
|
1285
1375
|
true,
|
|
@@ -1295,28 +1385,30 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_regular_element(
|
|
|
1295
1385
|
parser_T* parser,
|
|
1296
1386
|
AST_HTML_OPEN_TAG_NODE_T* open_tag
|
|
1297
1387
|
) {
|
|
1298
|
-
hb_array_T* errors =
|
|
1388
|
+
hb_array_T* errors = NULL;
|
|
1299
1389
|
hb_array_T* body = hb_array_init(8, parser->allocator);
|
|
1300
1390
|
|
|
1301
1391
|
parser_push_open_tag(parser, open_tag->tag_name);
|
|
1302
1392
|
|
|
1303
|
-
if (
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1393
|
+
if (parser_element_has_foreign_content(parser, open_tag->tag_name->value)) {
|
|
1394
|
+
hb_string_T tag_name = open_tag->tag_name->value;
|
|
1395
|
+
hb_string_T end_tag_name = parser_foreign_content_has_end_tag(tag_name) ? tag_name : HB_STRING_NULL;
|
|
1396
|
+
|
|
1397
|
+
parser_enter_foreign_content(parser, parser_get_foreign_content_kind(tag_name), end_tag_name);
|
|
1398
|
+
parser_parse_foreign_content(parser, body, &errors);
|
|
1307
1399
|
} else {
|
|
1308
|
-
parser_parse_in_data_state(parser, body, errors);
|
|
1400
|
+
parser_parse_in_data_state(parser, body, &errors);
|
|
1309
1401
|
}
|
|
1310
1402
|
|
|
1311
1403
|
if (!token_is(parser, TOKEN_HTML_TAG_START_CLOSE)) {
|
|
1312
|
-
return parser_handle_missing_close_tag(parser, open_tag, body, errors);
|
|
1404
|
+
return parser_handle_missing_close_tag(parser, open_tag, body, &errors);
|
|
1313
1405
|
}
|
|
1314
1406
|
|
|
1315
1407
|
AST_HTML_CLOSE_TAG_NODE_T* close_tag = parser_parse_html_close_tag(parser);
|
|
1316
1408
|
|
|
1317
1409
|
if (parser_in_svg_context(parser) == false && is_void_element(close_tag->tag_name->value)) {
|
|
1318
1410
|
hb_array_push(body, close_tag);
|
|
1319
|
-
parser_parse_in_data_state(parser, body, errors);
|
|
1411
|
+
parser_parse_in_data_state(parser, body, &errors);
|
|
1320
1412
|
close_tag = parser_parse_html_close_tag(parser);
|
|
1321
1413
|
}
|
|
1322
1414
|
|
|
@@ -1337,7 +1429,8 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_regular_element(
|
|
|
1337
1429
|
unclosed->location.start,
|
|
1338
1430
|
unclosed->location.end,
|
|
1339
1431
|
parser->allocator,
|
|
1340
|
-
errors
|
|
1432
|
+
&errors,
|
|
1433
|
+
&parser->options
|
|
1341
1434
|
);
|
|
1342
1435
|
token_free(unclosed, parser->allocator);
|
|
1343
1436
|
}
|
|
@@ -1346,12 +1439,12 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_regular_element(
|
|
|
1346
1439
|
token_T* popped_token = parser_pop_open_tag(parser);
|
|
1347
1440
|
token_free(popped_token, parser->allocator);
|
|
1348
1441
|
} else {
|
|
1349
|
-
parser_handle_mismatched_tags(parser, close_tag, errors);
|
|
1442
|
+
parser_handle_mismatched_tags(parser, close_tag, &errors);
|
|
1350
1443
|
}
|
|
1351
1444
|
|
|
1352
1445
|
return ast_html_element_node_init(
|
|
1353
1446
|
(AST_NODE_T*) open_tag,
|
|
1354
|
-
open_tag->tag_name,
|
|
1447
|
+
token_copy(open_tag->tag_name, parser->allocator),
|
|
1355
1448
|
body,
|
|
1356
1449
|
(AST_NODE_T*) close_tag,
|
|
1357
1450
|
false,
|
|
@@ -1371,12 +1464,14 @@ static AST_NODE_T* parser_parse_html_element(parser_T* parser) {
|
|
|
1371
1464
|
// <tag />
|
|
1372
1465
|
if (open_tag->is_void) { return (AST_NODE_T*) parser_parse_html_self_closing_element(parser, open_tag); }
|
|
1373
1466
|
|
|
1467
|
+
if (hb_string_equals_case_insensitive(open_tag->tag_name->value, hb_string("svg"))) { parser->svg_depth++; }
|
|
1468
|
+
|
|
1374
1469
|
// <tag>, in void element list, and not in inside an <svg> element
|
|
1375
1470
|
if (!open_tag->is_void && is_void_element(open_tag->tag_name->value) && !parser_in_svg_context(parser)) {
|
|
1376
1471
|
return (AST_NODE_T*) parser_parse_html_self_closing_element(parser, open_tag);
|
|
1377
1472
|
}
|
|
1378
1473
|
|
|
1379
|
-
if (
|
|
1474
|
+
if (parser_element_has_foreign_content(parser, open_tag->tag_name->value)) {
|
|
1380
1475
|
AST_HTML_ELEMENT_NODE_T* regular_element = parser_parse_html_regular_element(parser, open_tag);
|
|
1381
1476
|
|
|
1382
1477
|
if (regular_element != NULL) { return (AST_NODE_T*) regular_element; }
|
|
@@ -1385,18 +1480,35 @@ static AST_NODE_T* parser_parse_html_element(parser_T* parser) {
|
|
|
1385
1480
|
return (AST_NODE_T*) open_tag;
|
|
1386
1481
|
}
|
|
1387
1482
|
|
|
1388
|
-
static
|
|
1389
|
-
hb_array_T* errors =
|
|
1483
|
+
static AST_NODE_T* parser_parse_erb_tag(parser_T* parser) {
|
|
1484
|
+
hb_array_T* errors = NULL;
|
|
1390
1485
|
|
|
1391
|
-
token_T* opening_tag = parser_consume_expected(parser, TOKEN_ERB_START, errors);
|
|
1392
|
-
token_T* content = parser_consume_expected(parser, TOKEN_ERB_CONTENT, errors);
|
|
1486
|
+
token_T* opening_tag = parser_consume_expected(parser, TOKEN_ERB_START, &errors);
|
|
1487
|
+
token_T* content = parser_consume_expected(parser, TOKEN_ERB_CONTENT, &errors);
|
|
1393
1488
|
|
|
1394
1489
|
token_T* closing_tag = NULL;
|
|
1395
1490
|
position_T end_position;
|
|
1396
1491
|
|
|
1397
1492
|
if (token_is(parser, TOKEN_ERB_END)) {
|
|
1398
|
-
closing_tag = parser_consume_expected(parser, TOKEN_ERB_END, errors);
|
|
1493
|
+
closing_tag = parser_consume_expected(parser, TOKEN_ERB_END, &errors);
|
|
1399
1494
|
end_position = closing_tag->location.end;
|
|
1495
|
+
|
|
1496
|
+
bool is_well_formed = hb_string_equals(closing_tag->value, hb_string("%>"))
|
|
1497
|
+
|| hb_string_equals(closing_tag->value, hb_string("-%>"))
|
|
1498
|
+
|| hb_string_equals(closing_tag->value, hb_string("=%>"))
|
|
1499
|
+
|| hb_string_equals(closing_tag->value, hb_string("%%>"));
|
|
1500
|
+
|
|
1501
|
+
if (!is_well_formed) {
|
|
1502
|
+
append_malformed_erb_closing_tag_error(
|
|
1503
|
+
opening_tag,
|
|
1504
|
+
closing_tag,
|
|
1505
|
+
opening_tag->location.start,
|
|
1506
|
+
closing_tag->location.end,
|
|
1507
|
+
parser->allocator,
|
|
1508
|
+
&errors,
|
|
1509
|
+
&parser->options
|
|
1510
|
+
);
|
|
1511
|
+
}
|
|
1400
1512
|
} else if (token_is(parser, TOKEN_ERB_START)) {
|
|
1401
1513
|
append_nested_erb_tag_error(
|
|
1402
1514
|
opening_tag,
|
|
@@ -1405,7 +1517,8 @@ static AST_ERB_CONTENT_NODE_T* parser_parse_erb_tag(parser_T* parser) {
|
|
|
1405
1517
|
parser->current_token->location.start,
|
|
1406
1518
|
parser->current_token->location.end,
|
|
1407
1519
|
parser->allocator,
|
|
1408
|
-
errors
|
|
1520
|
+
&errors,
|
|
1521
|
+
&parser->options
|
|
1409
1522
|
);
|
|
1410
1523
|
end_position = parser->current_token->location.start;
|
|
1411
1524
|
} else {
|
|
@@ -1414,12 +1527,25 @@ static AST_ERB_CONTENT_NODE_T* parser_parse_erb_tag(parser_T* parser) {
|
|
|
1414
1527
|
opening_tag->location.start,
|
|
1415
1528
|
parser->current_token->location.start,
|
|
1416
1529
|
parser->allocator,
|
|
1417
|
-
errors
|
|
1530
|
+
&errors,
|
|
1531
|
+
&parser->options
|
|
1418
1532
|
);
|
|
1419
1533
|
end_position = parser->current_token->location.start;
|
|
1420
1534
|
}
|
|
1421
1535
|
|
|
1422
|
-
|
|
1536
|
+
if (hb_string_equals(opening_tag->value, hb_string("<%#"))) {
|
|
1537
|
+
return (AST_NODE_T*) ast_erb_comment_node_init(
|
|
1538
|
+
opening_tag,
|
|
1539
|
+
content,
|
|
1540
|
+
closing_tag,
|
|
1541
|
+
opening_tag->location.start,
|
|
1542
|
+
end_position,
|
|
1543
|
+
errors,
|
|
1544
|
+
parser->allocator
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
return (AST_NODE_T*) ast_erb_content_node_init(
|
|
1423
1549
|
opening_tag,
|
|
1424
1550
|
content,
|
|
1425
1551
|
closing_tag,
|
|
@@ -1432,26 +1558,103 @@ static AST_ERB_CONTENT_NODE_T* parser_parse_erb_tag(parser_T* parser) {
|
|
|
1432
1558
|
errors,
|
|
1433
1559
|
parser->allocator
|
|
1434
1560
|
);
|
|
1561
|
+
}
|
|
1435
1562
|
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1563
|
+
static bool is_tag_name_character(char character) {
|
|
1564
|
+
return (character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z')
|
|
1565
|
+
|| (character >= '0' && character <= '9') || character == '-';
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
static bool parser_scan_for_end_tag(const parser_T* parser, hb_string_T tag_name) {
|
|
1569
|
+
hb_string_T source = parser->lexer->source;
|
|
1570
|
+
|
|
1571
|
+
if (hb_string_is_empty(source) || hb_string_is_empty(tag_name)) { return false; }
|
|
1572
|
+
|
|
1573
|
+
for (uint32_t index = parser->current_token->range.from; index + 2 < source.length; index++) {
|
|
1574
|
+
if (source.data[index] != '<' || source.data[index + 1] != '/') { continue; }
|
|
1575
|
+
|
|
1576
|
+
uint32_t name_start = index + 2;
|
|
1577
|
+
|
|
1578
|
+
if (name_start + tag_name.length > source.length) { return false; }
|
|
1579
|
+
|
|
1580
|
+
hb_string_T candidate = { .data = source.data + name_start, .length = tag_name.length };
|
|
1581
|
+
|
|
1582
|
+
if (!hb_string_equals_case_insensitive(candidate, tag_name)) { continue; }
|
|
1583
|
+
|
|
1584
|
+
uint32_t after = name_start + tag_name.length;
|
|
1585
|
+
|
|
1586
|
+
if (after >= source.length || !is_tag_name_character(source.data[after])) { return true; }
|
|
1587
|
+
}
|
|
1439
1588
|
|
|
1440
|
-
return
|
|
1589
|
+
return false;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
static bool parser_foreign_content_end_tag_ahead(parser_T* parser, hb_string_T tag_name) {
|
|
1593
|
+
int index = parser_foreign_content_element_index(tag_name);
|
|
1594
|
+
uint32_t position = parser->current_token->range.from;
|
|
1595
|
+
|
|
1596
|
+
if (index >= 0 && position >= parser->foreign_content_absent_from[index]) { return false; }
|
|
1597
|
+
|
|
1598
|
+
if (parser_scan_for_end_tag(parser, tag_name)) { return true; }
|
|
1599
|
+
|
|
1600
|
+
if (index >= 0 && position < parser->foreign_content_absent_from[index]) {
|
|
1601
|
+
parser->foreign_content_absent_from[index] = position;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
return false;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
// <title> and <plaintext> are ordinary elements in XML documents, <title> also inside <svg>
|
|
1608
|
+
static bool parser_element_has_foreign_content(parser_T* parser, hb_string_T tag_name) {
|
|
1609
|
+
if (parser_get_foreign_content_kind(tag_name) == FOREIGN_CONTENT_NONE) { return false; }
|
|
1610
|
+
if (parser_foreign_content_is_html_only(tag_name) && parser->xml_document) { return false; }
|
|
1611
|
+
if (hb_string_equals_case_insensitive(tag_name, hb_string("title")) && parser_in_svg_context(parser)) {
|
|
1612
|
+
return false;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
if (parser_foreign_content_has_end_tag(tag_name) && !parser_foreign_content_end_tag_ahead(parser, tag_name)) {
|
|
1616
|
+
return false;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
return true;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
// <textarea> and <title> hold text, <script> and <style> hold raw source
|
|
1623
|
+
static void parser_append_foreign_content_from_buffer(
|
|
1624
|
+
const parser_T* parser,
|
|
1625
|
+
hb_buffer_T* buffer,
|
|
1626
|
+
hb_array_T* children,
|
|
1627
|
+
position_T start
|
|
1628
|
+
) {
|
|
1629
|
+
bool is_text = parser->foreign_content_kind == FOREIGN_CONTENT_RCDATA;
|
|
1630
|
+
|
|
1631
|
+
if (!is_text || buffer->length == 0) {
|
|
1632
|
+
parser_append_literal_node_from_buffer(parser, buffer, children, start);
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
hb_string_T content = { .data = buffer->value, .length = (uint32_t) buffer->length };
|
|
1637
|
+
|
|
1638
|
+
hb_array_append(
|
|
1639
|
+
children,
|
|
1640
|
+
ast_html_text_node_init(content, start, parser->current_token->location.start, NULL, parser->allocator)
|
|
1641
|
+
);
|
|
1642
|
+
|
|
1643
|
+
hb_buffer_free(buffer);
|
|
1644
|
+
hb_buffer_init(buffer, 128, parser->allocator);
|
|
1441
1645
|
}
|
|
1442
1646
|
|
|
1443
|
-
static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_array_T
|
|
1647
|
+
static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_array_T** errors) {
|
|
1444
1648
|
hb_buffer_T content;
|
|
1445
1649
|
hb_buffer_init(&content, 1024, parser->allocator);
|
|
1446
1650
|
position_T start = parser->current_token->location.start;
|
|
1447
|
-
|
|
1448
|
-
bool has_closing_tag = !hb_string_is_empty(expected_closing_tag);
|
|
1651
|
+
bool has_closing_tag = !hb_string_is_empty(parser->foreign_content_tag_name);
|
|
1449
1652
|
|
|
1450
1653
|
while (!token_is(parser, TOKEN_EOF)) {
|
|
1451
1654
|
if (token_is(parser, TOKEN_ERB_START)) {
|
|
1452
|
-
|
|
1655
|
+
parser_append_foreign_content_from_buffer(parser, &content, children, start);
|
|
1453
1656
|
|
|
1454
|
-
|
|
1657
|
+
AST_NODE_T* erb_node = parser_parse_erb_tag(parser);
|
|
1455
1658
|
hb_array_append(children, erb_node);
|
|
1456
1659
|
|
|
1457
1660
|
start = parser->current_token->location.start;
|
|
@@ -1466,7 +1669,7 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children,
|
|
|
1466
1669
|
bool is_potential_match = false;
|
|
1467
1670
|
|
|
1468
1671
|
if (next_token && next_token->type == TOKEN_IDENTIFIER && !hb_string_is_empty(next_token->value)) {
|
|
1469
|
-
is_potential_match =
|
|
1672
|
+
is_potential_match = parser_is_foreign_content_closing_tag_name(parser, next_token->value);
|
|
1470
1673
|
}
|
|
1471
1674
|
|
|
1472
1675
|
lexer_restore_state(parser->lexer, saved_state);
|
|
@@ -1474,7 +1677,7 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children,
|
|
|
1474
1677
|
if (next_token) { token_free(next_token, parser->allocator); }
|
|
1475
1678
|
|
|
1476
1679
|
if (is_potential_match) {
|
|
1477
|
-
|
|
1680
|
+
parser_append_foreign_content_from_buffer(parser, &content, children, start);
|
|
1478
1681
|
parser_exit_foreign_content(parser);
|
|
1479
1682
|
|
|
1480
1683
|
hb_buffer_free(&content);
|
|
@@ -1488,12 +1691,12 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children,
|
|
|
1488
1691
|
token_free(token, parser->allocator);
|
|
1489
1692
|
}
|
|
1490
1693
|
|
|
1491
|
-
|
|
1694
|
+
parser_append_foreign_content_from_buffer(parser, &content, children, start);
|
|
1492
1695
|
parser_exit_foreign_content(parser);
|
|
1493
1696
|
hb_buffer_free(&content);
|
|
1494
1697
|
}
|
|
1495
1698
|
|
|
1496
|
-
static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T
|
|
1699
|
+
static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T** errors) {
|
|
1497
1700
|
if (!parser->options.html) {
|
|
1498
1701
|
parser_parse_foreign_content(parser, children, errors);
|
|
1499
1702
|
return;
|
|
@@ -1520,6 +1723,12 @@ static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, h
|
|
|
1520
1723
|
continue;
|
|
1521
1724
|
}
|
|
1522
1725
|
|
|
1726
|
+
if (token_is(parser, TOKEN_XML_PROCESSING_INSTRUCTION_START)) {
|
|
1727
|
+
hb_array_append(children, parser_parse_xml_processing_instruction(parser));
|
|
1728
|
+
parser->consecutive_error_count = 0;
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1523
1732
|
if (token_is(parser, TOKEN_CDATA_START)) {
|
|
1524
1733
|
hb_array_append(children, parser_parse_cdata(parser));
|
|
1525
1734
|
parser->consecutive_error_count = 0;
|
|
@@ -1694,6 +1903,17 @@ static hb_array_T* collect_close_tag_names(hb_array_T* nodes, hb_allocator_T* al
|
|
|
1694
1903
|
return close_tag_names;
|
|
1695
1904
|
}
|
|
1696
1905
|
|
|
1906
|
+
static void free_close_tag_names(hb_array_T** close_tag_names, hb_allocator_T* allocator) {
|
|
1907
|
+
if (close_tag_names == NULL || *close_tag_names == NULL) { return; }
|
|
1908
|
+
|
|
1909
|
+
for (size_t i = 0; i < hb_array_size(*close_tag_names); i++) {
|
|
1910
|
+
hb_string_T* name = (hb_string_T*) hb_array_get(*close_tag_names, i);
|
|
1911
|
+
if (name != NULL) { hb_allocator_dealloc(allocator, name); }
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
hb_array_free(close_tag_names);
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1697
1917
|
static hb_array_T* parser_build_elements_from_tags(
|
|
1698
1918
|
hb_array_T* nodes,
|
|
1699
1919
|
hb_array_T* errors,
|
|
@@ -1740,7 +1960,7 @@ static hb_array_T* parser_build_elements_from_tags(
|
|
|
1740
1960
|
if (last_body_node != NULL) { end_position = last_body_node->location.end; }
|
|
1741
1961
|
}
|
|
1742
1962
|
|
|
1743
|
-
hb_array_T* element_errors =
|
|
1963
|
+
hb_array_T* element_errors = NULL;
|
|
1744
1964
|
|
|
1745
1965
|
if (strict) {
|
|
1746
1966
|
append_omitted_closing_tag_error(
|
|
@@ -1749,21 +1969,22 @@ static hb_array_T* parser_build_elements_from_tags(
|
|
|
1749
1969
|
open_tag->base.location.start,
|
|
1750
1970
|
open_tag->base.location.end,
|
|
1751
1971
|
allocator,
|
|
1752
|
-
element_errors
|
|
1972
|
+
&element_errors,
|
|
1973
|
+
options
|
|
1753
1974
|
);
|
|
1754
1975
|
}
|
|
1755
1976
|
|
|
1756
1977
|
AST_HTML_OMITTED_CLOSE_TAG_NODE_T* omitted_close_tag = ast_html_omitted_close_tag_node_init(
|
|
1757
|
-
open_tag->tag_name,
|
|
1978
|
+
token_copy(open_tag->tag_name, allocator),
|
|
1758
1979
|
end_position,
|
|
1759
1980
|
end_position,
|
|
1760
|
-
|
|
1981
|
+
NULL,
|
|
1761
1982
|
allocator
|
|
1762
1983
|
);
|
|
1763
1984
|
|
|
1764
1985
|
AST_HTML_ELEMENT_NODE_T* element = ast_html_element_node_init(
|
|
1765
1986
|
(AST_NODE_T*) open_tag,
|
|
1766
|
-
open_tag->tag_name,
|
|
1987
|
+
token_copy(open_tag->tag_name, allocator),
|
|
1767
1988
|
processed_body,
|
|
1768
1989
|
(AST_NODE_T*) omitted_close_tag,
|
|
1769
1990
|
false,
|
|
@@ -1778,16 +1999,15 @@ static hb_array_T* parser_build_elements_from_tags(
|
|
|
1778
1999
|
|
|
1779
2000
|
index = implicit_close_index - 1;
|
|
1780
2001
|
} else {
|
|
1781
|
-
if (hb_array_size(open_tag->base.errors) == 0
|
|
2002
|
+
if (hb_array_size(open_tag->base.errors) == 0) {
|
|
1782
2003
|
append_missing_closing_tag_error(
|
|
1783
2004
|
open_tag->tag_name,
|
|
1784
2005
|
open_tag->base.location.start,
|
|
1785
2006
|
open_tag->base.location.end,
|
|
1786
2007
|
allocator,
|
|
1787
|
-
open_tag->base.errors
|
|
2008
|
+
&open_tag->base.errors,
|
|
2009
|
+
options
|
|
1788
2010
|
);
|
|
1789
|
-
|
|
1790
|
-
parser_options_increment_error_count(options);
|
|
1791
2011
|
}
|
|
1792
2012
|
|
|
1793
2013
|
hb_array_append(result, node);
|
|
@@ -1804,11 +2024,11 @@ static hb_array_T* parser_build_elements_from_tags(
|
|
|
1804
2024
|
hb_array_T* processed_body = parser_build_elements_from_tags(body, errors, options, allocator);
|
|
1805
2025
|
hb_array_free(&body);
|
|
1806
2026
|
|
|
1807
|
-
hb_array_T* element_errors =
|
|
2027
|
+
hb_array_T* element_errors = NULL;
|
|
1808
2028
|
|
|
1809
2029
|
AST_HTML_ELEMENT_NODE_T* element = ast_html_element_node_init(
|
|
1810
2030
|
(AST_NODE_T*) open_tag,
|
|
1811
|
-
open_tag->tag_name,
|
|
2031
|
+
token_copy(open_tag->tag_name, allocator),
|
|
1812
2032
|
processed_body,
|
|
1813
2033
|
(AST_NODE_T*) close_tag,
|
|
1814
2034
|
false,
|
|
@@ -1827,16 +2047,15 @@ static hb_array_T* parser_build_elements_from_tags(
|
|
|
1827
2047
|
AST_HTML_CLOSE_TAG_NODE_T* close_tag = (AST_HTML_CLOSE_TAG_NODE_T*) node;
|
|
1828
2048
|
|
|
1829
2049
|
if (!is_void_element(close_tag->tag_name->value)) {
|
|
1830
|
-
if (hb_array_size(close_tag->base.errors) == 0
|
|
2050
|
+
if (hb_array_size(close_tag->base.errors) == 0) {
|
|
1831
2051
|
append_missing_opening_tag_error(
|
|
1832
2052
|
close_tag->tag_name,
|
|
1833
2053
|
close_tag->base.location.start,
|
|
1834
2054
|
close_tag->base.location.end,
|
|
1835
2055
|
allocator,
|
|
1836
|
-
close_tag->base.errors
|
|
2056
|
+
&close_tag->base.errors,
|
|
2057
|
+
options
|
|
1837
2058
|
);
|
|
1838
|
-
|
|
1839
|
-
parser_options_increment_error_count(options);
|
|
1840
2059
|
}
|
|
1841
2060
|
}
|
|
1842
2061
|
|
|
@@ -1846,17 +2065,19 @@ static hb_array_T* parser_build_elements_from_tags(
|
|
|
1846
2065
|
}
|
|
1847
2066
|
}
|
|
1848
2067
|
|
|
2068
|
+
free_close_tag_names(&close_tag_names, allocator);
|
|
2069
|
+
|
|
1849
2070
|
return result;
|
|
1850
2071
|
}
|
|
1851
2072
|
|
|
1852
2073
|
static AST_DOCUMENT_NODE_T* parser_parse_document(parser_T* parser) {
|
|
1853
2074
|
hb_array_T* children = hb_array_init(8, parser->allocator);
|
|
1854
|
-
hb_array_T* errors =
|
|
2075
|
+
hb_array_T* errors = NULL;
|
|
1855
2076
|
position_T start = parser->current_token->location.start;
|
|
1856
2077
|
|
|
1857
|
-
parser_parse_in_data_state(parser, children, errors);
|
|
2078
|
+
parser_parse_in_data_state(parser, children, &errors);
|
|
1858
2079
|
|
|
1859
|
-
token_T* eof = parser_consume_expected(parser, TOKEN_EOF, errors);
|
|
2080
|
+
token_T* eof = parser_consume_expected(parser, TOKEN_EOF, &errors);
|
|
1860
2081
|
|
|
1861
2082
|
AST_DOCUMENT_NODE_T* document_node =
|
|
1862
2083
|
ast_document_node_init(children, NULL, HERB_PRISM_NODE_EMPTY, start, eof->location.end, errors, parser->allocator);
|
|
@@ -1872,7 +2093,7 @@ AST_DOCUMENT_NODE_T* herb_parser_parse(parser_T* parser) {
|
|
|
1872
2093
|
|
|
1873
2094
|
static void parser_handle_whitespace(parser_T* parser, token_T* whitespace_token, hb_array_T* children) {
|
|
1874
2095
|
if (parser->options.track_whitespace) {
|
|
1875
|
-
hb_array_T* errors =
|
|
2096
|
+
hb_array_T* errors = NULL;
|
|
1876
2097
|
AST_WHITESPACE_NODE_T* whitespace_node = ast_whitespace_node_init(
|
|
1877
2098
|
whitespace_token,
|
|
1878
2099
|
whitespace_token->location.start,
|
|
@@ -1881,6 +2102,8 @@ static void parser_handle_whitespace(parser_T* parser, token_T* whitespace_token
|
|
|
1881
2102
|
parser->allocator
|
|
1882
2103
|
);
|
|
1883
2104
|
hb_array_append(children, whitespace_node);
|
|
2105
|
+
|
|
2106
|
+
return;
|
|
1884
2107
|
}
|
|
1885
2108
|
|
|
1886
2109
|
token_free(whitespace_token, parser->allocator);
|