├── .eslintignore ├── .eslintrc.js ├── .eslintrc.json ├── .github └── FUNDING.yml ├── .gitignore ├── .npmignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── _test ├── _cache │ └── .gitkeep └── _temp │ └── .gitkeep ├── changelog.md ├── formatter ├── README.md ├── _cache │ └── .gitkeep ├── _temp │ └── .gitkeep ├── changelog.md ├── package.json └── plugin.js ├── license.md ├── package-lock.json ├── package.json ├── pint ├── license.md ├── pint ├── pint.json └── readme.md ├── readme.md ├── src ├── analyzers │ ├── componentSlotPairAnalyzer.ts │ ├── conditionPairAnalyzer.ts │ ├── conditionalRewriteAnalyzer.ts │ ├── directivePairAnalyzer.ts │ ├── directiveStack.ts │ ├── forElsePairAnalyzer.ts │ ├── fragmentPositionAnalyzer.ts │ ├── genericLanguageStructures.ts │ ├── inlineEchoAnalyzer.ts │ ├── inlinePhpAnalyzer.ts │ ├── javaScriptStructuresAnalyzer.ts │ ├── pairManager.ts │ ├── phpStructuresAnalyzer.ts │ ├── speculativeConditionAnalyzer.ts │ └── switchPairAnalyzer.ts ├── compiler │ ├── compilers │ │ ├── append.ts │ │ ├── auth.ts │ │ ├── break.ts │ │ ├── can.ts │ │ ├── canAny.ts │ │ ├── cannot.ts │ │ ├── case.ts │ │ ├── checked.ts │ │ ├── choice.ts │ │ ├── class.ts │ │ ├── component.ts │ │ ├── componentFirst.ts │ │ ├── continue.ts │ │ ├── csrf.ts │ │ ├── dd.ts │ │ ├── disabled.ts │ │ ├── dump.ts │ │ ├── each.ts │ │ ├── else.ts │ │ ├── elseAuth.ts │ │ ├── elseCan.ts │ │ ├── elseCanAny.ts │ │ ├── elseCannot.ts │ │ ├── elseGuest.ts │ │ ├── elseIf.ts │ │ ├── empty.ts │ │ ├── endAuth.ts │ │ ├── endCan.ts │ │ ├── endCannot.ts │ │ ├── endComponent.ts │ │ ├── endComponentClass.ts │ │ ├── endEmpty.ts │ │ ├── endEnv.ts │ │ ├── endError.ts │ │ ├── endFor.ts │ │ ├── endForEach.ts │ │ ├── endForElse.ts │ │ ├── endGuest.ts │ │ ├── endIf.ts │ │ ├── endIsset.ts │ │ ├── endPhp.ts │ │ ├── endPrepend.ts │ │ ├── endPrependOnce.ts │ │ ├── endProduction.ts │ │ ├── endPush.ts │ │ ├── endPushOnce.ts │ │ ├── endSection.ts │ │ ├── endSlot.ts │ │ ├── endSwitch.ts │ │ ├── endUnless.ts │ │ ├── endVerbatim.ts │ │ ├── endWhile.ts │ │ ├── env.ts │ │ ├── error.ts │ │ ├── extends.ts │ │ ├── for.ts │ │ ├── forEach.ts │ │ ├── forElse.ts │ │ ├── guest.ts │ │ ├── hasSection.ts │ │ ├── if.ts │ │ ├── include.ts │ │ ├── includeFirst.ts │ │ ├── includeIf.ts │ │ ├── includeUnless.ts │ │ ├── includeWhen.ts │ │ ├── index.ts │ │ ├── inject.ts │ │ ├── isset.ts │ │ ├── js.ts │ │ ├── json.ts │ │ ├── lang.ts │ │ ├── method.ts │ │ ├── overwrite.ts │ │ ├── php.ts │ │ ├── prepend.ts │ │ ├── prependOnce.ts │ │ ├── production.ts │ │ ├── props.ts │ │ ├── push.ts │ │ ├── pushOnce.ts │ │ ├── section.ts │ │ ├── sectionMissing.ts │ │ ├── selected.ts │ │ ├── show.ts │ │ ├── slot.ts │ │ ├── stack.ts │ │ ├── stop.ts │ │ ├── switch.ts │ │ ├── unless.ts │ │ ├── unset.ts │ │ ├── verbatim.ts │ │ ├── vite.ts │ │ ├── viteReactRefresh.ts │ │ ├── while.ts │ │ └── yield.ts │ ├── componentClassNameResolver.ts │ ├── componentDetailsResolver.ts │ ├── componentTagCompiler.ts │ ├── directiveIdResolver.ts │ ├── nodeCompiler.ts │ ├── phpCompiler.ts │ └── uuidDirectiveIdResolver.ts ├── document │ ├── attributeRangeRemover.ts │ ├── bladeDocument.ts │ ├── documentCursor.ts │ ├── documentErrors.ts │ ├── documentPadder.ts │ ├── formatters.ts │ ├── fragmentTransformer.ts │ ├── pintCache.ts │ ├── pintTransformer.ts │ ├── printers │ │ ├── arrayPrinter.ts │ │ ├── commentPrinter.ts │ │ ├── directivePrinter.ts │ │ ├── echoPrinter.ts │ │ ├── errorPrinter.ts │ │ ├── indentLevel.ts │ │ ├── printWidthUtils.ts │ │ └── stringBuffer.ts │ ├── scanners │ │ ├── nodeQueries.ts │ │ ├── nodeScanner.ts │ │ └── wordScanner.ts │ ├── transformIgnore.ts │ ├── transformOptions.ts │ └── transformer.ts ├── errors │ ├── bladeError.ts │ └── bladeErrorCodes.ts ├── formatting │ ├── bladeJavaScriptFormatter.ts │ ├── classStringEmulation.ts │ ├── classStringsConfig.ts │ ├── documentFormatter.ts │ ├── formattingOptions.ts │ ├── generalSyntaxReflow.ts │ ├── optionDiscovery.ts │ ├── prettier │ │ ├── plugin.ts │ │ ├── prettierDocumentFormatter.ts │ │ ├── utils.ts │ │ └── voidHtmlTagsManager.ts │ ├── syntaxReflow.ts │ └── unsafeClassStringAttributes.ts ├── nodes │ ├── helpers.ts │ ├── labeledRange.ts │ ├── nodes.ts │ ├── offset.ts │ └── position.ts ├── parser.ts ├── parser │ ├── argStringSplitter.ts │ ├── bladeKeywords.ts │ ├── classEmulator.ts │ ├── componentParser.ts │ ├── documentIndex.ts │ ├── documentOffset.ts │ ├── documentParser.ts │ ├── excludeAttributes │ │ └── unsafe.ts │ ├── excludeDirectives │ │ ├── commonEventShortcuts.ts │ │ └── cssAtRules.ts │ ├── extractedAttribute.ts │ ├── fragmentsParser.ts │ ├── indexRange.ts │ ├── inlineStringParser.ts │ ├── lineOffset.ts │ ├── parenUnwrapper.ts │ ├── parserOptions.ts │ ├── php │ │ ├── phpParserPhpValidator.ts │ │ └── phpValidator.ts │ ├── scanResults.ts │ ├── scanners │ │ ├── isStartOfString.ts │ │ ├── nextNonWhitespace.ts │ │ ├── scanToEndOfLogicGroup.ts │ │ ├── skipToEndOfLine.ts │ │ ├── skipToEndOfMultilineComment.ts │ │ └── skipToEndOfString.ts │ ├── simpleArrayParser.ts │ ├── stringIterator.ts │ ├── stringRemover.ts │ └── stringSplitter.ts ├── test │ ├── acceptance │ │ ├── filament │ │ │ ├── actions_resources_views_button_action_blade_php.test.ts │ │ │ ├── actions_resources_views_button_group_blade_php.test.ts │ │ │ ├── actions_resources_views_components_action_blade_php.test.ts │ │ │ ├── actions_resources_views_components_actions_blade_php.test.ts │ │ │ ├── actions_resources_views_components_group_blade_php.test.ts │ │ │ ├── actions_resources_views_components_modals_blade_php.test.ts │ │ │ ├── actions_resources_views_grouped_action_blade_php.test.ts │ │ │ ├── actions_resources_views_grouped_group_blade_php.test.ts │ │ │ ├── actions_resources_views_icon_button_action_blade_php.test.ts │ │ │ ├── actions_resources_views_icon_button_group_blade_php.test.ts │ │ │ ├── actions_resources_views_link_action_blade_php.test.ts │ │ │ ├── actions_resources_views_link_group_blade_php.test.ts │ │ │ ├── actions_resources_views_select_action_blade_php.test.ts │ │ │ ├── forms_resources_views_component_container_blade_php.test.ts │ │ │ ├── forms_resources_views_components_actions_action_container_blade_php.test.ts │ │ │ ├── forms_resources_views_components_actions_blade_php.test.ts │ │ │ ├── forms_resources_views_components_affixes_blade_php.test.ts │ │ │ ├── forms_resources_views_components_builder_blade_php.test.ts │ │ │ ├── forms_resources_views_components_builder_block_blade_php.test.ts │ │ │ ├── forms_resources_views_components_builder_block_picker_blade_php.test.ts │ │ │ ├── forms_resources_views_components_card_blade_php.test.ts │ │ │ ├── forms_resources_views_components_checkbox_blade_php.test.ts │ │ │ ├── forms_resources_views_components_checkbox_list_blade_php.test.ts │ │ │ ├── forms_resources_views_components_color_picker_blade_php.test.ts │ │ │ ├── forms_resources_views_components_date_time_picker_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_error_message_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_helper_text_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_hint_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_index_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_inline_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_label_blade_php.test.ts │ │ │ ├── forms_resources_views_components_fieldset_blade_php.test.ts │ │ │ ├── forms_resources_views_components_file_upload_blade_php.test.ts │ │ │ ├── forms_resources_views_components_grid_blade_php.test.ts │ │ │ ├── forms_resources_views_components_group_blade_php.test.ts │ │ │ ├── forms_resources_views_components_hidden_blade_php.test.ts │ │ │ ├── forms_resources_views_components_key_value_blade_php.test.ts │ │ │ ├── forms_resources_views_components_markdown_editor_blade_php.test.ts │ │ │ ├── forms_resources_views_components_markdown_editor_toolbar_button_blade_php.test.ts │ │ │ ├── forms_resources_views_components_placeholder_blade_php.test.ts │ │ │ ├── forms_resources_views_components_radio_blade_php.test.ts │ │ │ ├── forms_resources_views_components_repeater_blade_php.test.ts │ │ │ ├── forms_resources_views_components_rich_editor_blade_php.test.ts │ │ │ ├── forms_resources_views_components_rich_editor_toolbar_button_blade_php.test.ts │ │ │ ├── forms_resources_views_components_section_blade_php.test.ts │ │ │ ├── forms_resources_views_components_select_blade_php.test.ts │ │ │ ├── forms_resources_views_components_tabs_blade_php.test.ts │ │ │ ├── forms_resources_views_components_tabs_tab_blade_php.test.ts │ │ │ ├── forms_resources_views_components_tags_input_blade_php.test.ts │ │ │ ├── forms_resources_views_components_text_input_blade_php.test.ts │ │ │ ├── forms_resources_views_components_textarea_blade_php.test.ts │ │ │ ├── forms_resources_views_components_toggle_blade_php.test.ts │ │ │ ├── forms_resources_views_components_wizard_blade_php.test.ts │ │ │ ├── forms_resources_views_components_wizard_step_blade_php.test.ts │ │ │ ├── infolists_resources_views_component_container_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_actions_action_container_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_actions_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_affixes_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_card_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_color_entry_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_entry_wrapper_helper_text_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_entry_wrapper_hint_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_entry_wrapper_index_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_entry_wrapper_inline_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_entry_wrapper_label_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_fieldset_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_grid_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_group_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_icon_entry_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_image_entry_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_repeatable_entry_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_section_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_split_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_tabs_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_tabs_tab_blade_php.test.ts │ │ │ ├── infolists_resources_views_components_text_entry_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_actions_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_body_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_close_button_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_echo_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_modal_actions_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_modal_empty_state_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_modal_heading_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_modal_index_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_trigger_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_date_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_echo_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_icon_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_notification_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_title_blade_php.test.ts │ │ │ ├── notifications_resources_views_database_notifications_blade_php.test.ts │ │ │ ├── notifications_resources_views_notification_blade_php.test.ts │ │ │ ├── notifications_resources_views_notifications_blade_php.test.ts │ │ │ ├── panels_resources_views_components_avatar_index_blade_php.test.ts │ │ │ ├── panels_resources_views_components_avatar_tenant_blade_php.test.ts │ │ │ ├── panels_resources_views_components_avatar_user_blade_php.test.ts │ │ │ ├── panels_resources_views_components_footer_blade_php.test.ts │ │ │ ├── panels_resources_views_components_form_actions_blade_php.test.ts │ │ │ ├── panels_resources_views_components_form_index_blade_php.test.ts │ │ │ ├── panels_resources_views_components_global_search_actions_blade_php.test.ts │ │ │ ├── panels_resources_views_components_global_search_index_blade_php.test.ts │ │ │ ├── panels_resources_views_components_global_search_input_blade_php.test.ts │ │ │ ├── panels_resources_views_components_global_search_no_results_message_blade_php.test.ts │ │ │ ├── panels_resources_views_components_global_search_result_blade_php.test.ts │ │ │ ├── panels_resources_views_components_global_search_result_group_blade_php.test.ts │ │ │ ├── panels_resources_views_components_global_search_results_container_blade_php.test.ts │ │ │ ├── panels_resources_views_components_header_heading_blade_php.test.ts │ │ │ ├── panels_resources_views_components_header_index_blade_php.test.ts │ │ │ ├── panels_resources_views_components_header_subheading_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_sidebar_badge_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_sidebar_group_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_sidebar_index_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_sidebar_item_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_topbar_badge_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_topbar_breadcrumbs_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_topbar_database_notifications_trigger_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_topbar_index_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_app_topbar_item_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_base_blade_php.test.ts │ │ │ ├── panels_resources_views_components_layouts_card_blade_php.test.ts │ │ │ ├── panels_resources_views_components_logo_blade_php.test.ts │ │ │ ├── panels_resources_views_components_page_blade_php.test.ts │ │ │ ├── panels_resources_views_components_resources_relation_managers_blade_php.test.ts │ │ │ ├── panels_resources_views_components_tenant_menu_blade_php.test.ts │ │ │ ├── panels_resources_views_components_user_menu_blade_php.test.ts │ │ │ ├── panels_resources_views_pages_auth_email_verification_email_verification_prompt_blade_php.test.ts │ │ │ ├── panels_resources_views_pages_auth_login_blade_php.test.ts │ │ │ ├── panels_resources_views_pages_auth_password_reset_request_password_reset_blade_php.test.ts │ │ │ ├── panels_resources_views_pages_auth_password_reset_reset_password_blade_php.test.ts │ │ │ ├── panels_resources_views_pages_auth_register_blade_php.test.ts │ │ │ ├── panels_resources_views_pages_dashboard_blade_php.test.ts │ │ │ ├── panels_resources_views_pages_tenancy_register_tenant_blade_php.test.ts │ │ │ ├── panels_resources_views_resources_pages_create_record_blade_php.test.ts │ │ │ ├── panels_resources_views_resources_pages_edit_record_blade_php.test.ts │ │ │ ├── panels_resources_views_resources_pages_list_records_blade_php.test.ts │ │ │ ├── panels_resources_views_resources_pages_view_record_blade_php.test.ts │ │ │ ├── panels_resources_views_resources_relation_manager_blade_php.test.ts │ │ │ ├── panels_resources_views_widgets_account_widget_blade_php.test.ts │ │ │ ├── panels_resources_views_widgets_filament_info_widget_blade_php.test.ts │ │ │ ├── spatie_laravel_settings_plugin_resources_views_pages_settings_page_blade_php.test.ts │ │ │ ├── support_resources_views_assets_blade_php.test.ts │ │ │ ├── support_resources_views_components_button_blade_php.test.ts │ │ │ ├── support_resources_views_components_card_header_blade_php.test.ts │ │ │ ├── support_resources_views_components_card_heading_blade_php.test.ts │ │ │ ├── support_resources_views_components_card_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_card_subheading_blade_php.test.ts │ │ │ ├── support_resources_views_components_dropdown_header_blade_php.test.ts │ │ │ ├── support_resources_views_components_dropdown_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_dropdown_list_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_dropdown_list_item_blade_php.test.ts │ │ │ ├── support_resources_views_components_grid_column_blade_php.test.ts │ │ │ ├── support_resources_views_components_grid_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_hr_blade_php.test.ts │ │ │ ├── support_resources_views_components_icon_blade_php.test.ts │ │ │ ├── support_resources_views_components_icon_button_blade_php.test.ts │ │ │ ├── support_resources_views_components_input_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_input_select_blade_php.test.ts │ │ │ ├── support_resources_views_components_link_blade_php.test.ts │ │ │ ├── support_resources_views_components_loading_indicator_blade_php.test.ts │ │ │ ├── support_resources_views_components_modal_actions_blade_php.test.ts │ │ │ ├── support_resources_views_components_modal_heading_blade_php.test.ts │ │ │ ├── support_resources_views_components_modal_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_modal_subheading_blade_php.test.ts │ │ │ ├── support_resources_views_components_section_blade_php.test.ts │ │ │ ├── support_resources_views_components_tabs_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_tabs_item_blade_php.test.ts │ │ │ ├── support_stubs_scaffolding_resources_views_layouts_app_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_checkbox_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_color_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_icon_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_image_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_layout_grid_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_layout_panel_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_layout_split_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_layout_stack_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_select_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_summaries_icon_count_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_summaries_range_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_summaries_text_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_summaries_values_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_text_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_text_input_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_toggle_column_blade_php.test.ts │ │ │ ├── tables_resources_views_components_actions_action_blade_php.test.ts │ │ │ ├── tables_resources_views_components_actions_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_actions_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_checkbox_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_checkbox_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_columns_column_blade_php.test.ts │ │ │ ├── tables_resources_views_components_columns_layout_blade_php.test.ts │ │ │ ├── tables_resources_views_components_container_blade_php.test.ts │ │ │ ├── tables_resources_views_components_empty_state_description_blade_php.test.ts │ │ │ ├── tables_resources_views_components_empty_state_heading_blade_php.test.ts │ │ │ ├── tables_resources_views_components_empty_state_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_filters_dropdown_blade_php.test.ts │ │ │ ├── tables_resources_views_components_filters_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_filters_indicators_blade_php.test.ts │ │ │ ├── tables_resources_views_components_groups_blade_php.test.ts │ │ │ ├── tables_resources_views_components_header_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_header_description_blade_php.test.ts │ │ │ ├── tables_resources_views_components_header_heading_blade_php.test.ts │ │ │ ├── tables_resources_views_components_header_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_loading_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_pagination_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_pagination_item_blade_php.test.ts │ │ │ ├── tables_resources_views_components_pagination_records_per_page_selector_blade_php.test.ts │ │ │ ├── tables_resources_views_components_reorder_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_reorder_handle_blade_php.test.ts │ │ │ ├── tables_resources_views_components_reorder_indicator_blade_php.test.ts │ │ │ ├── tables_resources_views_components_reorder_trigger_blade_php.test.ts │ │ │ ├── tables_resources_views_components_row_blade_php.test.ts │ │ │ ├── tables_resources_views_components_search_input_blade_php.test.ts │ │ │ ├── tables_resources_views_components_selection_indicator_blade_php.test.ts │ │ │ ├── tables_resources_views_components_summary_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_summary_row_blade_php.test.ts │ │ │ ├── tables_resources_views_components_table_blade_php.test.ts │ │ │ ├── tables_resources_views_components_toggleable_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_toggleable_trigger_blade_php.test.ts │ │ │ ├── tables_resources_views_index_blade_php.test.ts │ │ │ ├── widgets_resources_views_chart_widget_blade_php.test.ts │ │ │ ├── widgets_resources_views_components_widget_blade_php.test.ts │ │ │ ├── widgets_resources_views_components_widgets_blade_php.test.ts │ │ │ ├── widgets_resources_views_stats_overview_widget_blade_php.test.ts │ │ │ ├── widgets_resources_views_stats_overview_widget_card_blade_php.test.ts │ │ │ └── widgets_resources_views_table_widget_blade_php.test.ts │ │ ├── filament_2 │ │ │ ├── admin_resources_views_components_brand_blade_php.test.ts │ │ │ ├── admin_resources_views_components_brand_icon_blade_php.test.ts │ │ │ ├── admin_resources_views_components_button_blade_php.test.ts │ │ │ ├── admin_resources_views_components_card_heading_blade_php.test.ts │ │ │ ├── admin_resources_views_components_card_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_dropdown_header_blade_php.test.ts │ │ │ ├── admin_resources_views_components_dropdown_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_dropdown_item_blade_php.test.ts │ │ │ ├── admin_resources_views_components_dropdown_list_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_dropdown_list_item_blade_php.test.ts │ │ │ ├── admin_resources_views_components_footer_blade_php.test.ts │ │ │ ├── admin_resources_views_components_form_actions_blade_php.test.ts │ │ │ ├── admin_resources_views_components_form_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_actions_action_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_actions_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_end_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_input_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_no_results_message_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_result_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_result_group_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_results_container_blade_php.test.ts │ │ │ ├── admin_resources_views_components_global_search_start_blade_php.test.ts │ │ │ ├── admin_resources_views_components_header_heading_blade_php.test.ts │ │ │ ├── admin_resources_views_components_header_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_header_subheading_blade_php.test.ts │ │ │ ├── admin_resources_views_components_hr_blade_php.test.ts │ │ │ ├── admin_resources_views_components_icon_button_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_sidebar_badge_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_sidebar_end_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_sidebar_footer_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_sidebar_group_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_sidebar_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_sidebar_item_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_sidebar_start_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_topbar_breadcrumbs_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_topbar_database_notifications_trigger_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_app_topbar_user_menu_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_base_blade_php.test.ts │ │ │ ├── admin_resources_views_components_layouts_card_blade_php.test.ts │ │ │ ├── admin_resources_views_components_link_blade_php.test.ts │ │ │ ├── admin_resources_views_components_modal_actions_blade_php.test.ts │ │ │ ├── admin_resources_views_components_modal_heading_blade_php.test.ts │ │ │ ├── admin_resources_views_components_modal_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_modal_subheading_blade_php.test.ts │ │ │ ├── admin_resources_views_components_notification_manager_blade_php.test.ts │ │ │ ├── admin_resources_views_components_page_blade_php.test.ts │ │ │ ├── admin_resources_views_components_pages_actions_action_blade_php.test.ts │ │ │ ├── admin_resources_views_components_pages_actions_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_resources_relation_managers_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_stats_card_blade_php.test.ts │ │ │ ├── admin_resources_views_components_stats_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_tabs_index_blade_php.test.ts │ │ │ ├── admin_resources_views_components_tabs_item_blade_php.test.ts │ │ │ ├── admin_resources_views_components_topbar_blade_php.test.ts │ │ │ ├── admin_resources_views_components_user_avatar_blade_php.test.ts │ │ │ ├── admin_resources_views_components_widget_blade_php.test.ts │ │ │ ├── admin_resources_views_components_widgets_blade_php.test.ts │ │ │ ├── admin_resources_views_global_search_actions_button_action_blade_php.test.ts │ │ │ ├── admin_resources_views_global_search_actions_icon_button_action_blade_php.test.ts │ │ │ ├── admin_resources_views_global_search_actions_link_action_blade_php.test.ts │ │ │ ├── admin_resources_views_login_blade_php.test.ts │ │ │ ├── admin_resources_views_pages_actions_button_action_blade_php.test.ts │ │ │ ├── admin_resources_views_pages_actions_group_blade_php.test.ts │ │ │ ├── admin_resources_views_pages_actions_grouped_action_blade_php.test.ts │ │ │ ├── admin_resources_views_pages_actions_icon_button_action_blade_php.test.ts │ │ │ ├── admin_resources_views_pages_actions_link_action_blade_php.test.ts │ │ │ ├── admin_resources_views_pages_actions_modal_actions_button_action_blade_php.test.ts │ │ │ ├── admin_resources_views_pages_actions_select_action_blade_php.test.ts │ │ │ ├── admin_resources_views_pages_dashboard_blade_php.test.ts │ │ │ ├── admin_resources_views_resources_pages_create_record_blade_php.test.ts │ │ │ ├── admin_resources_views_resources_pages_edit_record_blade_php.test.ts │ │ │ ├── admin_resources_views_resources_pages_list_records_blade_php.test.ts │ │ │ ├── admin_resources_views_resources_pages_view_record_blade_php.test.ts │ │ │ ├── admin_resources_views_resources_relation_manager_blade_php.test.ts │ │ │ ├── admin_resources_views_widgets_account_widget_blade_php.test.ts │ │ │ ├── admin_resources_views_widgets_chart_widget_blade_php.test.ts │ │ │ ├── admin_resources_views_widgets_filament_info_widget_blade_php.test.ts │ │ │ ├── admin_resources_views_widgets_stats_overview_widget_blade_php.test.ts │ │ │ ├── admin_resources_views_widgets_stats_overview_widget_card_blade_php.test.ts │ │ │ ├── admin_resources_views_widgets_table_widget_blade_php.test.ts │ │ │ ├── forms_resources_views_component_container_blade_php.test.ts │ │ │ ├── forms_resources_views_components_actions_action_blade_php.test.ts │ │ │ ├── forms_resources_views_components_actions_icon_button_action_blade_php.test.ts │ │ │ ├── forms_resources_views_components_actions_modal_actions_button_action_blade_php.test.ts │ │ │ ├── forms_resources_views_components_actions_modal_index_blade_php.test.ts │ │ │ ├── forms_resources_views_components_builder_blade_php.test.ts │ │ │ ├── forms_resources_views_components_builder_block_blade_php.test.ts │ │ │ ├── forms_resources_views_components_builder_block_picker_blade_php.test.ts │ │ │ ├── forms_resources_views_components_button_blade_php.test.ts │ │ │ ├── forms_resources_views_components_card_blade_php.test.ts │ │ │ ├── forms_resources_views_components_checkbox_list_blade_php.test.ts │ │ │ ├── forms_resources_views_components_color_picker_blade_php.test.ts │ │ │ ├── forms_resources_views_components_date_time_picker_blade_php.test.ts │ │ │ ├── forms_resources_views_components_dropdown_header_blade_php.test.ts │ │ │ ├── forms_resources_views_components_dropdown_index_blade_php.test.ts │ │ │ ├── forms_resources_views_components_dropdown_item_blade_php.test.ts │ │ │ ├── forms_resources_views_components_dropdown_list_index_blade_php.test.ts │ │ │ ├── forms_resources_views_components_dropdown_list_item_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_error_message_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_helper_text_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_hint_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_index_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_inline_blade_php.test.ts │ │ │ ├── forms_resources_views_components_field_wrapper_label_blade_php.test.ts │ │ │ ├── forms_resources_views_components_fieldset_blade_php.test.ts │ │ │ ├── forms_resources_views_components_file_upload_blade_php.test.ts │ │ │ ├── forms_resources_views_components_grid_blade_php.test.ts │ │ │ ├── forms_resources_views_components_group_blade_php.test.ts │ │ │ ├── forms_resources_views_components_hidden_blade_php.test.ts │ │ │ ├── forms_resources_views_components_hr_blade_php.test.ts │ │ │ ├── forms_resources_views_components_icon_button_blade_php.test.ts │ │ │ ├── forms_resources_views_components_key_value_blade_php.test.ts │ │ │ ├── forms_resources_views_components_link_blade_php.test.ts │ │ │ ├── forms_resources_views_components_markdown_editor_blade_php.test.ts │ │ │ ├── forms_resources_views_components_markdown_editor_toolbar_button_blade_php.test.ts │ │ │ ├── forms_resources_views_components_modal_actions_blade_php.test.ts │ │ │ ├── forms_resources_views_components_modal_heading_blade_php.test.ts │ │ │ ├── forms_resources_views_components_modal_index_blade_php.test.ts │ │ │ ├── forms_resources_views_components_modal_subheading_blade_php.test.ts │ │ │ ├── forms_resources_views_components_multiple_file_upload_blade_php.test.ts │ │ │ ├── forms_resources_views_components_placeholder_blade_php.test.ts │ │ │ ├── forms_resources_views_components_repeater_blade_php.test.ts │ │ │ ├── forms_resources_views_components_rich_editor_blade_php.test.ts │ │ │ ├── forms_resources_views_components_rich_editor_toolbar_button_blade_php.test.ts │ │ │ ├── forms_resources_views_components_section_blade_php.test.ts │ │ │ ├── forms_resources_views_components_select_blade_php.test.ts │ │ │ ├── forms_resources_views_components_tabs_blade_php.test.ts │ │ │ ├── forms_resources_views_components_tabs_tab_blade_php.test.ts │ │ │ ├── forms_resources_views_components_tags_input_blade_php.test.ts │ │ │ ├── forms_resources_views_components_text_input_blade_php.test.ts │ │ │ ├── forms_resources_views_components_textarea_blade_php.test.ts │ │ │ ├── forms_resources_views_components_wizard_blade_php.test.ts │ │ │ ├── forms_resources_views_components_wizard_step_blade_php.test.ts │ │ │ ├── forms_stubs_scaffolding_resources_views_layouts_app_blade_php.test.ts │ │ │ ├── notifications_resources_views_actions_button_action_blade_php.test.ts │ │ │ ├── notifications_resources_views_actions_group_blade_php.test.ts │ │ │ ├── notifications_resources_views_actions_grouped_action_blade_php.test.ts │ │ │ ├── notifications_resources_views_actions_link_action_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_actions_action_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_actions_index_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_body_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_button_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_close_button_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_index_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_modal_actions_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_modal_empty_state_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_modal_heading_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_modal_index_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_database_trigger_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_date_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_dropdown_header_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_dropdown_index_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_dropdown_item_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_dropdown_list_index_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_dropdown_list_item_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_echo_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_hr_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_icon_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_link_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_modal_heading_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_modal_index_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_modal_subheading_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_notification_blade_php.test.ts │ │ │ ├── notifications_resources_views_components_title_blade_php.test.ts │ │ │ ├── notifications_resources_views_notification_blade_php.test.ts │ │ │ ├── notifications_resources_views_notifications_blade_php.test.ts │ │ │ ├── notifications_stubs_scaffolding_resources_views_layouts_app_blade_php.test.ts │ │ │ ├── spatie_laravel_settings_plugin_resources_views_pages_settings_page_blade_php.test.ts │ │ │ ├── support_resources_views_components_actions_group_blade_php.test.ts │ │ │ ├── support_resources_views_components_button_blade_php.test.ts │ │ │ ├── support_resources_views_components_dropdown_header_blade_php.test.ts │ │ │ ├── support_resources_views_components_dropdown_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_dropdown_item_blade_php.test.ts │ │ │ ├── support_resources_views_components_dropdown_list_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_dropdown_list_item_blade_php.test.ts │ │ │ ├── support_resources_views_components_grid_column_blade_php.test.ts │ │ │ ├── support_resources_views_components_grid_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_hr_blade_php.test.ts │ │ │ ├── support_resources_views_components_icon_button_blade_php.test.ts │ │ │ ├── support_resources_views_components_link_blade_php.test.ts │ │ │ ├── support_resources_views_components_loading_indicator_blade_php.test.ts │ │ │ ├── support_resources_views_components_modal_actions_blade_php.test.ts │ │ │ ├── support_resources_views_components_modal_heading_blade_php.test.ts │ │ │ ├── support_resources_views_components_modal_index_blade_php.test.ts │ │ │ ├── support_resources_views_components_modal_subheading_blade_php.test.ts │ │ │ ├── tables_resources_views_actions_bulk_action_blade_php.test.ts │ │ │ ├── tables_resources_views_actions_button_action_blade_php.test.ts │ │ │ ├── tables_resources_views_actions_group_blade_php.test.ts │ │ │ ├── tables_resources_views_actions_grouped_action_blade_php.test.ts │ │ │ ├── tables_resources_views_actions_icon_button_action_blade_php.test.ts │ │ │ ├── tables_resources_views_actions_link_action_blade_php.test.ts │ │ │ ├── tables_resources_views_actions_modal_actions_button_action_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_badge_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_checkbox_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_color_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_icon_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_image_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_layout_grid_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_layout_panel_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_layout_split_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_layout_stack_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_select_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_tags_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_text_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_text_input_column_blade_php.test.ts │ │ │ ├── tables_resources_views_columns_toggle_column_blade_php.test.ts │ │ │ ├── tables_resources_views_components_actions_action_blade_php.test.ts │ │ │ ├── tables_resources_views_components_actions_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_actions_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_bulk_actions_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_bulk_actions_trigger_blade_php.test.ts │ │ │ ├── tables_resources_views_components_button_blade_php.test.ts │ │ │ ├── tables_resources_views_components_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_checkbox_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_checkbox_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_columns_column_blade_php.test.ts │ │ │ ├── tables_resources_views_components_columns_layout_blade_php.test.ts │ │ │ ├── tables_resources_views_components_container_blade_php.test.ts │ │ │ ├── tables_resources_views_components_dropdown_header_blade_php.test.ts │ │ │ ├── tables_resources_views_components_dropdown_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_dropdown_item_blade_php.test.ts │ │ │ ├── tables_resources_views_components_dropdown_list_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_dropdown_list_item_blade_php.test.ts │ │ │ ├── tables_resources_views_components_empty_state_description_blade_php.test.ts │ │ │ ├── tables_resources_views_components_empty_state_heading_blade_php.test.ts │ │ │ ├── tables_resources_views_components_empty_state_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_filters_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_filters_indicators_blade_php.test.ts │ │ │ ├── tables_resources_views_components_filters_popover_blade_php.test.ts │ │ │ ├── tables_resources_views_components_filters_trigger_blade_php.test.ts │ │ │ ├── tables_resources_views_components_header_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_header_description_blade_php.test.ts │ │ │ ├── tables_resources_views_components_header_heading_blade_php.test.ts │ │ │ ├── tables_resources_views_components_header_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_hr_blade_php.test.ts │ │ │ ├── tables_resources_views_components_icon_button_blade_php.test.ts │ │ │ ├── tables_resources_views_components_link_blade_php.test.ts │ │ │ ├── tables_resources_views_components_loading_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_modal_actions_blade_php.test.ts │ │ │ ├── tables_resources_views_components_modal_heading_blade_php.test.ts │ │ │ ├── tables_resources_views_components_modal_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_modal_subheading_blade_php.test.ts │ │ │ ├── tables_resources_views_components_pagination_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_pagination_item_blade_php.test.ts │ │ │ ├── tables_resources_views_components_pagination_records_per_page_selector_blade_php.test.ts │ │ │ ├── tables_resources_views_components_reorder_cell_blade_php.test.ts │ │ │ ├── tables_resources_views_components_reorder_handle_blade_php.test.ts │ │ │ ├── tables_resources_views_components_reorder_indicator_blade_php.test.ts │ │ │ ├── tables_resources_views_components_reorder_trigger_blade_php.test.ts │ │ │ ├── tables_resources_views_components_row_blade_php.test.ts │ │ │ ├── tables_resources_views_components_search_input_blade_php.test.ts │ │ │ ├── tables_resources_views_components_selection_indicator_blade_php.test.ts │ │ │ ├── tables_resources_views_components_table_blade_php.test.ts │ │ │ ├── tables_resources_views_components_toggleable_index_blade_php.test.ts │ │ │ ├── tables_resources_views_components_toggleable_trigger_blade_php.test.ts │ │ │ ├── tables_resources_views_index_blade_php.test.ts │ │ │ └── tables_stubs_scaffolding_resources_views_layouts_app_blade_php.test.ts │ │ └── filament_license.md │ ├── array_parser.test.ts │ ├── basic_pairing.test.ts │ ├── child_nodes.test.ts │ ├── class_strings.test.ts │ ├── comments.test.ts │ ├── compiler_append.test.ts │ ├── compiler_auth.test.ts │ ├── compiler_break.test.ts │ ├── compiler_can.test.ts │ ├── compiler_canany.test.ts │ ├── compiler_cannot.test.ts │ ├── compiler_checked.test.ts │ ├── compiler_class.test.ts │ ├── compiler_comments.test.ts │ ├── compiler_componentfirst.test.ts │ ├── compiler_components.test.ts │ ├── compiler_componenttag.test.ts │ ├── compiler_continue.test.ts │ ├── compiler_echo.test.ts │ ├── compiler_else.test.ts │ ├── compiler_elseif.test.ts │ ├── compiler_endsection.test.ts │ ├── compiler_environment.test.ts │ ├── compiler_error.test.ts │ ├── compiler_escaped.test.ts │ ├── compiler_expression.test.ts │ ├── compiler_extends.test.ts │ ├── compiler_for.test.ts │ ├── compiler_foreach.test.ts │ ├── compiler_forelse.test.ts │ ├── compiler_guest.test.ts │ ├── compiler_hassection.test.ts │ ├── compiler_helpers.test.ts │ ├── compiler_if.test.ts │ ├── compiler_ifauth.test.ts │ ├── compiler_ifempty.test.ts │ ├── compiler_ifguest.test.ts │ ├── compiler_ifisset.test.ts │ ├── compiler_includes.test.ts │ ├── compiler_inject.test.ts │ ├── compiler_js.test.ts │ ├── compiler_json.test.ts │ ├── compiler_lang.test.ts │ ├── compiler_overwrite.test.ts │ ├── compiler_php.test.ts │ ├── compiler_prepend.test.ts │ ├── compiler_props.test.ts │ ├── compiler_push.test.ts │ ├── compiler_section.test.ts │ ├── compiler_sectionmissing.test.ts │ ├── compiler_show.test.ts │ ├── compiler_stack.test.ts │ ├── compiler_stopsection.test.ts │ ├── compiler_unknown.test.ts │ ├── compiler_unless.test.ts │ ├── compiler_unset.test.ts │ ├── compiler_verbatim.test.ts │ ├── compiler_while.test.ts │ ├── compiler_yield.test.ts │ ├── component_tags.test.ts │ ├── conditions.test.ts │ ├── custom_ifs.test.ts │ ├── error_printer.test.ts │ ├── exclusive_directives.test.ts │ ├── forelse.test.ts │ ├── format_inline_echo_block.test.ts │ ├── formatter_alpinejs_attributes.test.ts │ ├── formatter_basic_nodes.test.ts │ ├── formatter_can.test.ts │ ├── formatter_component_tags.test.ts │ ├── formatter_conditional_element_directive_pair.test.ts │ ├── formatter_conditional_element_echo.test.ts │ ├── formatter_conditional_element_if.test.ts │ ├── formatter_conditional_element_unless.test.ts │ ├── formatter_directives.test.ts │ ├── formatter_echos.test.ts │ ├── formatter_forelse.test.ts │ ├── formatter_if_statements.test.ts │ ├── formatter_ignore.test.ts │ ├── formatter_include.test.ts │ ├── formatter_inline_php.test.ts │ ├── formatter_js_attributes.test.ts │ ├── formatter_json_args.test.ts │ ├── formatter_json_params.test.ts │ ├── formatter_literals.test.ts │ ├── formatter_operators.test.ts │ ├── formatter_php_blocks.test.ts │ ├── formatter_pint_basic_nodes.test.ts │ ├── formatter_pint_can.test.ts │ ├── formatter_pint_component_tags.test.ts │ ├── formatter_pint_conditional_element_directive_pair.test.ts │ ├── formatter_pint_conditional_element_echo.test.ts │ ├── formatter_pint_conditional_element_unless.test.ts │ ├── formatter_pint_directives.test.ts │ ├── formatter_pint_echos.test.ts │ ├── formatter_pint_for.test.ts │ ├── formatter_pint_forelse.test.ts │ ├── formatter_pint_if_statements.test.ts │ ├── formatter_pint_ignore.test.ts │ ├── formatter_pint_inline_echo_block.test.ts │ ├── formatter_pint_inline_php.test.ts │ ├── formatter_pint_json_params.test.ts │ ├── formatter_pint_literals.test.ts │ ├── formatter_pint_operators.test.ts │ ├── formatter_pint_php_blocks.test.ts │ ├── formatter_pint_props_directive.test.ts │ ├── formatter_pint_script_structures.test.ts │ ├── formatter_pint_speculative_conditions.test.ts │ ├── formatter_pint_speculative_unless.test.ts │ ├── formatter_pint_style_script.test.ts │ ├── formatter_pint_switch.test.ts │ ├── formatter_pint_templates.test.ts │ ├── formatter_pint_unless.test.ts │ ├── formatter_pint_verbatim.test.ts │ ├── formatter_props_directive.test.ts │ ├── formatter_recovery.test.ts │ ├── formatter_script_structures.test.ts │ ├── formatter_speculative_conditions.test.ts │ ├── formatter_speculative_unless.test.ts │ ├── formatter_style_script.test.ts │ ├── formatter_style_structures.test.ts │ ├── formatter_switch.test.ts │ ├── formatter_syntax_reflow.test.ts │ ├── formatter_templates.test.ts │ ├── formatter_unless.test.ts │ ├── formatter_verbatim.test.ts │ ├── formatting_for.test.ts │ ├── formatting_options.test.ts │ ├── fragment_analysis.test.ts │ ├── fragment_structures.test.ts │ ├── fragments.test.ts │ ├── fragments_style_script.test.ts │ ├── ignored_directives.test.ts │ ├── inline_php.test.ts │ ├── neighboring_nodes.test.ts │ ├── nodes.test.ts │ ├── paren_unwrapper.test.ts │ ├── php_comments.test.ts │ ├── php_validator.test.ts │ ├── reflow_parser.test.ts │ ├── remove_blade_transformer.test.ts │ ├── switch.test.ts │ ├── testUtils │ │ ├── assertions.ts │ │ ├── formatting.ts │ │ └── transform.ts │ ├── transformer_basic_nodes.test.ts │ ├── transformer_component_tags.test.ts │ ├── transformer_conditional_element_directive_pair.test.ts │ ├── transformer_directives.test.ts │ ├── transformer_echos.test.ts │ ├── transformer_element_echo.test.ts │ ├── transformer_element_unless.test.ts │ ├── transformer_forelse.test.ts │ ├── transformer_if_statements.test.ts │ ├── transformer_inline_php.test.ts │ ├── transformer_json_params.test.ts │ ├── transformer_props_directive.test.ts │ ├── transformer_script_structures.test.ts │ ├── transformer_switch.test.ts │ ├── transformer_unless.test.ts │ ├── transformer_verbatim.test.ts │ └── verbatim.test.ts └── utilities │ ├── arrayHelpers.ts │ ├── isNumeric.ts │ ├── stringUtilities.ts │ └── validationUtilities.ts └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/** 2 | out/** 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /**@type {import('eslint').Linter.Config} */ 2 | // eslint-disable-next-line no-undef 3 | module.exports = { 4 | root: true, 5 | parser: '@typescript-eslint/parser', 6 | plugins: [ 7 | '@typescript-eslint', 8 | ], 9 | extends: [ 10 | 'eslint:recommended', 11 | 'plugin:@typescript-eslint/recommended', 12 | ], 13 | rules: { 14 | 'semi': [2, "always"], 15 | '@typescript-eslint/no-unused-vars': 0, 16 | '@typescript-eslint/no-explicit-any': 0, 17 | '@typescript-eslint/explicit-module-boundary-types': 0, 18 | '@typescript-eslint/no-non-null-assertion': 0, 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "ecmaVersion": 6, 5 | "sourceType": "module" 6 | }, 7 | "env": { 8 | "node": true 9 | }, 10 | "rules": { 11 | "semi": "error", 12 | "no-extra-semi": "warn", 13 | "curly": "warn", 14 | "quotes": [ 15 | "error", 16 | "single", 17 | { 18 | "allowTemplateLiterals": true 19 | } 20 | ], 21 | "eqeqeq": "error", 22 | "indent": [ 23 | "warn", 24 | "tab", 25 | { 26 | "SwitchCase": 1 27 | } 28 | ] 29 | } 30 | } -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: JohnathonKoster 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | _test/_temp/**/*.php 4 | _test/_temp/**/*.json 5 | _test/_cache/*.json -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | src/test 3 | out 4 | _test -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "type": "node", 7 | "request": "launch", 8 | "name": "Blade Parser", 9 | "program": "${workspaceFolder}/src/parser.ts", 10 | "outFiles": ["${workspaceFolder}/out/**/*.js"] 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.insertSpaces": true, 3 | "tslint.enable": true, 4 | "typescript.tsc.autoDetect": "off", 5 | "typescript.preferences.quoteStyle": "single", 6 | "editor.codeActionsOnSave": { 7 | "source.fixAll.eslint": "explicit" 8 | } 9 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "compile", 7 | "group": "build", 8 | "presentation": { 9 | "panel": "dedicated", 10 | "reveal": "never" 11 | }, 12 | "problemMatcher": [ 13 | "$tsc" 14 | ] 15 | }, 16 | { 17 | "type": "npm", 18 | "script": "watch", 19 | "isBackground": true, 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | "presentation": { 25 | "panel": "dedicated", 26 | "reveal": "never" 27 | }, 28 | "problemMatcher": [ 29 | "$tsc-watch" 30 | ] 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /_test/_cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stillat/blade-parser-typescript/2c18f70da21f2ac212523dfa02f8a72c57fb2552/_test/_cache/.gitkeep -------------------------------------------------------------------------------- /_test/_temp/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stillat/blade-parser-typescript/2c18f70da21f2ac212523dfa02f8a72c57fb2552/_test/_temp/.gitkeep -------------------------------------------------------------------------------- /formatter/_cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stillat/blade-parser-typescript/2c18f70da21f2ac212523dfa02f8a72c57fb2552/formatter/_cache/.gitkeep -------------------------------------------------------------------------------- /formatter/_temp/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stillat/blade-parser-typescript/2c18f70da21f2ac212523dfa02f8a72c57fb2552/formatter/_temp/.gitkeep -------------------------------------------------------------------------------- /formatter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prettier-plugin-blade", 3 | "version": "2.1.21", 4 | "description": "A Prettier plugin to format Laravel Blade templates", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/stillat/blade-parser-typescript.git" 8 | }, 9 | "type": "module", 10 | "main": "plugin.js", 11 | "scripts": {}, 12 | "keywords": [ 13 | "Blade", 14 | "Prettier", 15 | "Laravel" 16 | ], 17 | "peerDependencies": { 18 | "prettier": ">=3" 19 | }, 20 | "author": "John Koster", 21 | "license": "MIT", 22 | "engines": { 23 | "node": ">=12.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Johnathon Koster 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /pint/license.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Taylor Otwell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /pint/pint: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stillat/blade-parser-typescript/2c18f70da21f2ac212523dfa02f8a72c57fb2552/pint/pint -------------------------------------------------------------------------------- /pint/pint.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "laravel", 3 | "rules": { 4 | "blank_line_before_statement": false, 5 | "concat_space": { 6 | "spacing": "none" 7 | }, 8 | "no_unused_imports": true, 9 | "declare_strict_types": true, 10 | "method_argument_space": true, 11 | "single_trait_insert_per_statement": true, 12 | "types_spaces": { 13 | "space": "single" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /pint/readme.md: -------------------------------------------------------------------------------- 1 | This copy of Pint is used in the test suite. 2 | You will need to configure Pint to run in your project's environment. -------------------------------------------------------------------------------- /src/compiler/compilers/append.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class AppendCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'appendSection(); ?>'; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/compiler/compilers/auth.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class AuthCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | if (directive.hasDirectiveParameters) { 9 | return 'guard(' + directive.getInnerContent() + ')->check()): ?>' 10 | } 11 | 12 | return 'guard()->check()): ?>' 13 | } 14 | } -------------------------------------------------------------------------------- /src/compiler/compilers/break.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class BreakCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | if (directive.hasDirectiveParameters) { 9 | const value = parseInt(directive.getInnerContent()); 10 | 11 | if (isNaN(value)) { 12 | return ''; 13 | } else { 14 | if (value < 0) { 15 | return ''; 16 | } else { 17 | return ''; 18 | } 19 | } 20 | } 21 | 22 | return ''; 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/compiler/compilers/can.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class CanCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'check(' + directive.getInnerContent() + ')): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/canAny.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class CanAnyCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'any(' + directive.getInnerContent() + ')): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/cannot.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class CannotCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'denies(' + directive.getInnerContent() + ')): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/case.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | import { SwitchCompiler } from './switch.js'; 4 | 5 | export class CaseCompiler implements NodeCompiler { 6 | private switchCompiler: SwitchCompiler; 7 | 8 | constructor(switchCompiler: SwitchCompiler) { 9 | this.switchCompiler = switchCompiler; 10 | } 11 | 12 | compile(node: AbstractNode): string { 13 | const directive = node as DirectiveNode; 14 | 15 | 16 | if (directive == this.switchCompiler.getLastCase()) { 17 | return ''; 18 | } 19 | 20 | return ''; 21 | } 22 | } -------------------------------------------------------------------------------- /src/compiler/compilers/checked.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class CheckedCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/choice.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ChoiceCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'choice(' + directive.getInnerContent() + '); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/class.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ClassCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | 9 | return 'class=""'; 10 | } 11 | } -------------------------------------------------------------------------------- /src/compiler/compilers/componentFirst.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ComponentFirstCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'startComponentFirst(' + directive.getInnerContent() + '); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/continue.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ContinueCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | if (directive.hasDirectiveParameters) { 9 | const value = parseInt(directive.getInnerContent()); 10 | 11 | if (isNaN(value)) { 12 | return ''; 13 | } else { 14 | if (value < 0) { 15 | return ''; 16 | } else { 17 | return ''; 18 | } 19 | } 20 | } 21 | 22 | return ''; 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/compiler/compilers/csrf.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class CsrfCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/dd.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class DdCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/disabled.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class DisabledCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/dump.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class DumpCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/each.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EachCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'renderEach(' + directive.getInnerContent() + '); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/else.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ElseCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/elseAuth.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ElseAuthCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | if (directive.hasDirectiveParameters) { 9 | return 'guard()->check()): ?>' 10 | } 11 | 12 | return 'guard()->check()): ?>' 13 | } 14 | } -------------------------------------------------------------------------------- /src/compiler/compilers/elseCan.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ElseCanCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'check(' + directive.getInnerContent() + ')): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/elseCanAny.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ElseCanAnyCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'any(' + directive.getInnerContent() + ')): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/elseCannot.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ElseCannotCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'denies(' + directive.getInnerContent() + ')): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/elseGuest.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ElseGuestCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'guard(' + directive.getInnerContent() + ')->guest()): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/elseIf.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ElseIfCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/empty.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | import { ForElseCompiler } from './forElse.js'; 4 | 5 | export class EmptyCompiler implements NodeCompiler { 6 | private forElseCompiler: ForElseCompiler; 7 | 8 | constructor(forElse: ForElseCompiler) { 9 | this.forElseCompiler = forElse; 10 | } 11 | compile(node: AbstractNode): string { 12 | const directive = node as DirectiveNode; 13 | 14 | if (directive.hasDirectiveParameters) { 15 | return ''; 16 | } 17 | 18 | const result = 'popLoop(); $loop = $__env->getLastLoop(); if ($__empty_' + this.forElseCompiler.getActiveLoop() + '): ?>'; 19 | 20 | this.forElseCompiler.popLoop(); 21 | 22 | return result; 23 | } 24 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endAuth.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndAuthCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endCan.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndCanCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endCannot.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndCannotCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endComponent.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndComponentCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'renderComponent(); ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endComponentClass.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | import { ComponentCompiler } from './component.js'; 4 | 5 | export class EndComponentClassCompiler implements NodeCompiler { 6 | private componentCompiler: ComponentCompiler; 7 | 8 | constructor(componentCompiler: ComponentCompiler) { 9 | this.componentCompiler = componentCompiler; 10 | } 11 | 12 | compile(node: AbstractNode): string { 13 | const componentHash = this.componentCompiler.getClassHash(); 14 | this.componentCompiler.popHash(); 15 | 16 | return `'renderComponent(); ?> 17 | 18 | 19 | 20 | 21 | `; 22 | } 23 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endEmpty.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndEmptyCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endEnv.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndEnvCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endError.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndErrorCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ``; 10 | } 11 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endFor.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndForCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endForEach.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndForEachCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'popLoop(); $loop = $__env->getLastLoop(); ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endForElse.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndForElseCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endGuest.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndGuestCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endIf.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndIfCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endIsset.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndIssetCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endPhp.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndPhpCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return '?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endPrepend.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndPrependCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'stopPrepend(); ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endPrependOnce.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndPrependOnceCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'stopPrepend(); endif; ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endProduction.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndProductionCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endPush.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndPushCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'stopPush(); ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endPushOnce.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndPushOnceCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'stopPush(); endif; ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endSection.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndSectionCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'stopSection(); ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endSlot.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndSlotCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return `endSlot(); ?>`; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endSwitch.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndSwitchCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endUnless.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndUnlessCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endVerbatim.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndVerbatimCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/endWhile.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EndWhileCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return ''; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/env.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class EnvCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'environment(' + directive.getInnerContent() + ')): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/error.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ErrorCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return `getBag($__errorArgs[1] ?? \'default\'); 10 | if ($__bag->has($__errorArgs[0])) : 11 | if (isset($message)) { $__messageOriginal = $message; } 12 | $message = $__bag->first($__errorArgs[0]); ?>`; 13 | } 14 | } -------------------------------------------------------------------------------- /src/compiler/compilers/extends.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ExtendsCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'make(' + directive.getInnerContent() + ', \\Illuminate\\Support\\Arr::except(get_defined_vars(), [\'__data\', \'__path\']))->render(); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/for.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ForCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/compiler/compilers/forEach.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ForEachCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | content = directive.getInnerContent(), 8 | split = this.getVars(content), 9 | loopVar = split[0].trim(), 10 | tempVar = split[1].trim(); 11 | return 'addLoop($__currentLoopData); foreach($__currentLoopData as ' + tempVar + '): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>'; 12 | } 13 | 14 | private getVars(content: string): string[] { 15 | const split = content.split(' as '); 16 | 17 | if (split.length == 1) { 18 | return content.split(' AS '); 19 | } 20 | 21 | return split; 22 | } 23 | } -------------------------------------------------------------------------------- /src/compiler/compilers/guest.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class GuestCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'guard(' + directive.getInnerContent() + ')->guest()): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/hasSection.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class HasSectionCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'yieldContent(' + directive.getInnerContent() + ')))): ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/if.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class IfCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/include.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class IncludeCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'make(' + directive.getInnerContent() + ', \\Illuminate\\Support\\Arr::except(get_defined_vars(), [\'__data\', \'__path\']))->render(); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/includeFirst.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class IncludeFirstCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'first(' + directive.getInnerContent() + ', \\Illuminate\\Support\\Arr::except(get_defined_vars(), [\'__data\', \'__path\']))->render(); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/includeIf.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class IncludeIfCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'exists(' + directive.getInnerContent() + ')) echo $__env->make(' + directive.getInnerContent() + ', \\Illuminate\\Support\\Arr::except(get_defined_vars(), [\'__data\', \'__path\']))->render(); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/includeUnless.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class IncludeUnlessCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'renderUnless(' + directive.getInnerContent() + ', \\Illuminate\\Support\\Arr::except(get_defined_vars(), [\'__data\', \'__path\'])); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/includeWhen.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class IncludeWhenCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'renderWhen(' + directive.getInnerContent() + ', \\Illuminate\\Support\\Arr::except(get_defined_vars(), [\'__data\', \'__path\'])); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/inject.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { StringSplitter } from '../../parser/stringSplitter.js'; 3 | import { StringUtilities } from '../../utilities/stringUtilities.js'; 4 | import { NodeCompiler } from '../nodeCompiler.js'; 5 | 6 | export class InjectCompiler implements NodeCompiler { 7 | compile(node: AbstractNode): string { 8 | const directive = node as DirectiveNode, 9 | strings = StringSplitter.fromText(directive.getInnerContent()), 10 | variable = StringUtilities.unwrapString(strings[0]).trim(), 11 | service = strings[1].trim(); 12 | 13 | return ``; 14 | } 15 | } -------------------------------------------------------------------------------- /src/compiler/compilers/isset.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class IssetCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/js.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class JsCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'toHtml() ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/json.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { StringSplitter } from '../../parser/stringSplitter.js'; 3 | import { NodeCompiler } from '../nodeCompiler.js'; 4 | 5 | export class JsonCompiler implements NodeCompiler { 6 | compile(node: AbstractNode): string { 7 | const directive = node as DirectiveNode, 8 | params = StringSplitter.fromText(directive.getInnerContent()), 9 | variable = params[0].trim(); 10 | 11 | if (params.length == 1) { 12 | return ''; 13 | } 14 | 15 | const encoding = params[1].trim(); 16 | 17 | return ''; 18 | } 19 | } -------------------------------------------------------------------------------- /src/compiler/compilers/lang.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class LangCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'get(' + directive.getInnerContent() + '); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/method.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class MethodCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/overwrite.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class OverwriteCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'stopSection(true); ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/php.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class PhpDirectiveCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | if (directive.hasDirectiveParameters == false) { 9 | if (directive.isClosedBy == null) { 10 | return '@php'; 11 | } 12 | 13 | return ''; 17 | } 18 | } -------------------------------------------------------------------------------- /src/compiler/compilers/prepend.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class PrependCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'startPrepend(' + directive.getInnerContent() + '); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/prependOnce.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { StringSplitter } from '../../parser/stringSplitter.js'; 3 | import { DirectiveIdResolver } from '../directiveIdResolver.js'; 4 | import { NodeCompiler } from '../nodeCompiler.js'; 5 | 6 | export class PrependOnceCompiler implements NodeCompiler { 7 | private idResolver: DirectiveIdResolver; 8 | 9 | constructor(idResolver: DirectiveIdResolver) { 10 | this.idResolver = idResolver; 11 | } 12 | 13 | setIdResolver(idResolver: DirectiveIdResolver) { 14 | this.idResolver = idResolver; 15 | } 16 | 17 | compile(node: AbstractNode): string { 18 | const directive = node as DirectiveNode, 19 | params = StringSplitter.fromText(directive.getInnerContent()); 20 | 21 | let viewName = params[0].trim(), 22 | id = ''; 23 | 24 | if (params.length == 1) { 25 | id = "'" + this.idResolver.id(directive) + "'"; 26 | } else if (params.length == 2) { 27 | id = params[1].trim(); 28 | } 29 | 30 | return `hasRenderedOnce(${id})): $__env->markAsRenderedOnce(${id}); 31 | $__env->startPrepend(${viewName}); ?>`; 32 | } 33 | } -------------------------------------------------------------------------------- /src/compiler/compilers/production.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ProductionCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'environment(\'production\')): ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/props.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class PropsCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | props = directive.getInnerContent(); 8 | 9 | return `onlyProps(${props}) as $__key => $__value) { 10 | $$__key = $$__key ?? $__value; 11 | } ?> 12 | exceptProps(${props}); ?> 13 | $__value) { 14 | $$__key = $$__key ?? $__value; 15 | } ?> 16 | 17 | $__value) { 18 | if (array_key_exists($__key, $__defined_vars)) unset($$__key); 19 | } ?> 20 | `; 21 | } 22 | } -------------------------------------------------------------------------------- /src/compiler/compilers/push.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class PushCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return 'startPush(' + directive.getInnerContent() + '); ?>'; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/pushOnce.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { StringSplitter } from '../../parser/stringSplitter.js'; 3 | import { DirectiveIdResolver } from '../directiveIdResolver.js'; 4 | import { NodeCompiler } from '../nodeCompiler.js'; 5 | 6 | export class PushOnceCompiler implements NodeCompiler { 7 | private idResolver: DirectiveIdResolver; 8 | 9 | constructor(idResolver: DirectiveIdResolver) { 10 | this.idResolver = idResolver; 11 | } 12 | 13 | setIdResolver(idResolver: DirectiveIdResolver) { 14 | this.idResolver = idResolver; 15 | } 16 | 17 | compile(node: AbstractNode): string { 18 | const directive = node as DirectiveNode, 19 | params = StringSplitter.fromText(directive.getInnerContent()); 20 | 21 | let viewName = params[0].trim(), 22 | id = ''; 23 | 24 | if (params.length == 1) { 25 | id = "'" + this.idResolver.id(directive) + "'"; 26 | } else if (params.length == 2) { 27 | id = params[1].trim(); 28 | } 29 | 30 | return `hasRenderedOnce(${id})): $__env->markAsRenderedOnce(${id}); 31 | $__env->startPush(${viewName}); ?>`; 32 | } 33 | } -------------------------------------------------------------------------------- /src/compiler/compilers/section.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class SectionCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | params = directive.getInnerContent(); 8 | 9 | return `startSection(${params}); ?>`; 10 | } 11 | } -------------------------------------------------------------------------------- /src/compiler/compilers/sectionMissing.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class SectionMissingCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | params = directive.getInnerContent(); 8 | 9 | return `yieldContent(${params})))): ?>`; 10 | } 11 | } -------------------------------------------------------------------------------- /src/compiler/compilers/selected.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class SelectedCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/show.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ShowCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return 'yieldSection(); ?>'; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/slot.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class SlotCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | params = directive.getInnerContent(); 8 | 9 | return `slot(${params}); ?>`; 10 | } 11 | } -------------------------------------------------------------------------------- /src/compiler/compilers/stack.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class StackCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | params = directive.getInnerContent(); 8 | 9 | return `yieldPushContent(${params}); ?>`; 10 | } 11 | } -------------------------------------------------------------------------------- /src/compiler/compilers/stop.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class StopCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return `stopSection(); ?>`; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/switch.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class SwitchCompiler implements NodeCompiler { 5 | private lastCase: DirectiveNode | null = null; 6 | compile(node: AbstractNode): string { 7 | const directive = node as DirectiveNode; 8 | 9 | let result = ''; 15 | 16 | return result; 17 | } 18 | 19 | getLastCase(): DirectiveNode | null { 20 | return this.lastCase; 21 | } 22 | } -------------------------------------------------------------------------------- /src/compiler/compilers/unless.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class UnlessCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return ''; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/unset.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class UnsetCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | params = directive.getInnerContent(); 8 | 9 | return ``; 10 | } 11 | } -------------------------------------------------------------------------------- /src/compiler/compilers/verbatim.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class VerbatimCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode; 7 | 8 | return directive.documentContent; 9 | } 10 | } -------------------------------------------------------------------------------- /src/compiler/compilers/vite.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ViteCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | params = directive.getInnerContent(); 8 | 9 | if (params.trim().length == 0) { 10 | return ``; 11 | } 12 | 13 | return ``; 14 | } 15 | } -------------------------------------------------------------------------------- /src/compiler/compilers/viteReactRefresh.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class ViteReactRefreshCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | return `reactRefresh(); ?>`; 7 | } 8 | } -------------------------------------------------------------------------------- /src/compiler/compilers/while.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class WhileCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | params = directive.getInnerContent(); 8 | 9 | return ``; 10 | } 11 | } -------------------------------------------------------------------------------- /src/compiler/compilers/yield.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, DirectiveNode } from '../../nodes/nodes.js'; 2 | import { NodeCompiler } from '../nodeCompiler.js'; 3 | 4 | export class YieldCompiler implements NodeCompiler { 5 | compile(node: AbstractNode): string { 6 | const directive = node as DirectiveNode, 7 | params = directive.getInnerContent(); 8 | 9 | return `yieldContent(${params}); ?>`; 10 | } 11 | } -------------------------------------------------------------------------------- /src/compiler/componentClassNameResolver.ts: -------------------------------------------------------------------------------- 1 | export interface ComponentClassNameResolver { 2 | resolveName(name: string): string, 3 | } 4 | 5 | export class AppClassNameResolver implements ComponentClassNameResolver { 6 | private namespace = `App\\View\\Components\\`; 7 | 8 | setNamespace(namespace: string) { 9 | this.namespace = namespace; 10 | } 11 | 12 | resolveName(name: string): string { 13 | let className = name; 14 | 15 | if (name.endsWith('::class')) { 16 | className = className.substring(0, className.length - 7); 17 | } 18 | 19 | return `${this.namespace}${className}`; 20 | } 21 | } -------------------------------------------------------------------------------- /src/compiler/componentDetailsResolver.ts: -------------------------------------------------------------------------------- 1 | export interface ComponentDetails { 2 | properties: string[] 3 | } 4 | 5 | export interface ComponentDetailsResolver { 6 | getDetails(componentName: string): ComponentDetails | null 7 | } -------------------------------------------------------------------------------- /src/compiler/directiveIdResolver.ts: -------------------------------------------------------------------------------- 1 | import { DirectiveNode } from '../nodes/nodes.js'; 2 | 3 | export interface DirectiveIdResolver { 4 | id(node: DirectiveNode): string, 5 | } -------------------------------------------------------------------------------- /src/compiler/nodeCompiler.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../nodes/nodes.js'; 2 | 3 | export interface NodeCompiler { 4 | compile(node: AbstractNode): string 5 | } -------------------------------------------------------------------------------- /src/compiler/uuidDirectiveIdResolver.ts: -------------------------------------------------------------------------------- 1 | import { DirectiveNode } from '../nodes/nodes.js'; 2 | import { DirectiveIdResolver } from './directiveIdResolver.js'; 3 | import { v4 as uuidv4 } from 'uuid'; 4 | 5 | export class UuidDirectiveIdResolver implements DirectiveIdResolver { 6 | id(node: DirectiveNode): string { 7 | return uuidv4(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/document/documentErrors.ts: -------------------------------------------------------------------------------- 1 | import { BladeError } from '../errors/bladeError.js'; 2 | import { BladeDocument } from './bladeDocument.js'; 3 | 4 | export class DocumentErrors { 5 | private doc: BladeDocument; 6 | 7 | constructor(doc: BladeDocument) { 8 | this.doc = doc; 9 | } 10 | 11 | hasStructureErrors() { 12 | return this.doc.getParser().getStructureErrors().length > 0; 13 | } 14 | 15 | getFirstStructureError(): BladeError { 16 | return this.doc.getParser().getStructureErrors()[0]; 17 | } 18 | 19 | hasAny() { 20 | return this.all().length > 0; 21 | } 22 | 23 | all() { 24 | const errorHashes: string[] = [], 25 | errors: BladeError[] = []; 26 | 27 | this.doc.getAllNodes().forEach((node) => { 28 | node.getErrors().forEach((error) => { 29 | if (errorHashes.includes(error.hash()) == false) { 30 | errorHashes.push(error.hash()); 31 | errors.push(error); 32 | } 33 | 34 | }); 35 | }); 36 | 37 | this.doc.getParser().getErrors().forEach((error) => { 38 | if (errorHashes.includes(error.hash()) == false) { 39 | errorHashes.push(error.hash()); 40 | errors.push(error); 41 | } 42 | }); 43 | 44 | return errors; 45 | } 46 | } -------------------------------------------------------------------------------- /src/document/documentPadder.ts: -------------------------------------------------------------------------------- 1 | export class DocumentPadder { 2 | static pad(content: string, line: number, char: number) { 3 | let text = ''; 4 | 5 | for (let i = 0; i < line - 1; i++) { 6 | text += "\n"; 7 | } 8 | 9 | text += ' '.repeat(char); 10 | 11 | text += content; 12 | 13 | return text; 14 | } 15 | 16 | static substitute(content: string, char:string) { 17 | let text = ''; 18 | 19 | for (let i = 0; i < content.length; i++) { 20 | const sChar = content[i]; 21 | 22 | if (sChar == "\n") { 23 | text += sChar; 24 | } else { 25 | text += char; 26 | } 27 | } 28 | 29 | return text; 30 | } 31 | } -------------------------------------------------------------------------------- /src/document/formatters.ts: -------------------------------------------------------------------------------- 1 | import { ParserOptions } from 'prettier'; 2 | import { BladeDocument } from './bladeDocument.js'; 3 | import { TransformOptions } from './transformOptions.js'; 4 | 5 | export type PhpFormatter = (input: string, transformOptions:TransformOptions, options: ParserOptions|null) => Promise; 6 | export type BlockPhpFormatter = (input: string, transformOptions:TransformOptions, options: ParserOptions|null) => Promise; 7 | export type PhpTagFormatter = (input: string, transformOptions:TransformOptions, options: ParserOptions|null) => Promise; 8 | export type JsonFormatter = (input: string) => Promise; 9 | export type HtmlFormatter = (input: string) => Promise; 10 | export type PreFormatter = (document: BladeDocument) => string|null; -------------------------------------------------------------------------------- /src/document/fragmentTransformer.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode, BladeEchoNode, DirectiveNode, InlinePhpNode } from '../nodes/nodes.js'; 2 | import { StringUtilities } from '../utilities/stringUtilities.js'; 3 | 4 | export class FragmentsTransformer { 5 | static transform(nodes: AbstractNode[], content: string) { 6 | let result = content; 7 | 8 | nodes.forEach((node) => { 9 | if (node instanceof BladeEchoNode) { 10 | result = result.replace(node.sourceContent, this.transformContent(node.sourceContent)); 11 | } else if (node instanceof DirectiveNode && node.hasDirectiveParameters) { 12 | result = result.replace(node.sourceContent, this.transformContent(node.sourceContent)); 13 | } else if (node instanceof InlinePhpNode) { 14 | result = result.replace(node.sourceContent, StringUtilities.replaceWithFillerExceptNewlines(node.sourceContent)); 15 | } 16 | }); 17 | 18 | return result; 19 | } 20 | 21 | private static transformContent(content: string): string { 22 | const replacedContent = content.replace(/>/g, 'B').replace(/ { 11 | reflowedLines.push(' '.repeat(tabSize + targetIndent) + line.trim()); 12 | }); 13 | 14 | const content = reflowedLines.join("\n"); 15 | let newComment = "{{--\n"; 16 | newComment += content; 17 | newComment += "\n" + ' '.repeat(targetIndent) + '--}}'; 18 | 19 | return newComment; 20 | } 21 | 22 | return '{{-- ' + comment.innerContent.trim() + ' --}}'; 23 | } 24 | } -------------------------------------------------------------------------------- /src/document/printers/errorPrinter.ts: -------------------------------------------------------------------------------- 1 | import { BladeError } from '../../errors/bladeError.js'; 2 | 3 | export class ErrorPrinter { 4 | static printError(error: BladeError, lines: Map): string { 5 | let result = error.message + "\n\n", 6 | line = error.node?.startPosition?.line as number; 7 | 8 | let maxLine = line; 9 | 10 | lines.forEach((text, lineNumber) => { 11 | maxLine = lineNumber; 12 | }); 13 | 14 | let maxLineLen = maxLine.toString().length; 15 | 16 | lines.forEach((lineText, lineNumber) => { 17 | let curLineString = lineNumber.toString(), 18 | prefix = '', 19 | linePaddingLen = 0; 20 | 21 | linePaddingLen = maxLineLen - curLineString.length; 22 | 23 | if (line == lineNumber) { 24 | prefix = ' >' + '0'.repeat(linePaddingLen) + curLineString + '| '; 25 | } else { 26 | prefix = ' ' + '0'.repeat(linePaddingLen) + curLineString + '| '; 27 | } 28 | 29 | result += prefix + lineText + "\n"; 30 | }); 31 | 32 | 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /src/document/printers/stringBuffer.ts: -------------------------------------------------------------------------------- 1 | export class StringBuffer { 2 | private tabSize = 0; 3 | private content = ''; 4 | private activeIndentLevel = 0; 5 | 6 | constructor(tabSize: number, activeLevel: number) { 7 | this.tabSize = tabSize; 8 | this.activeIndentLevel = activeLevel; 9 | } 10 | 11 | appendNoRepeat(text: string) { 12 | if (this.content.trimEnd().endsWith(text) == false) { 13 | return this.append(text); 14 | } 15 | 16 | return this; 17 | } 18 | 19 | append(text: string) { 20 | this.content += text; 21 | return this; 22 | } 23 | 24 | getContents() { 25 | return this.content; 26 | } 27 | 28 | newLine() { 29 | this.content += "\n"; 30 | return this; 31 | } 32 | 33 | indent() { 34 | this.content += ' '.repeat(this.tabSize * this.activeIndentLevel); 35 | 36 | return this; 37 | } 38 | 39 | outdent() { 40 | let target = this.activeIndentLevel - 1; 41 | 42 | if (target < 1) { 43 | target = 1; 44 | } 45 | 46 | this.content += ' '.repeat(this.tabSize * target); 47 | 48 | return this; 49 | } 50 | } -------------------------------------------------------------------------------- /src/document/transformIgnore.ts: -------------------------------------------------------------------------------- 1 | export class TransformIgnore { 2 | public static FormatIgnoreStart = 'format-ignore-start'; 3 | public static FormatIgnoreEnd = 'format-ignore-end'; 4 | } -------------------------------------------------------------------------------- /src/document/transformOptions.ts: -------------------------------------------------------------------------------- 1 | import { IClassStringConfiguration } from '../formatting/classStringsConfig.js'; 2 | 3 | export interface TransformOptions { 4 | spacesAfterDirective: number, 5 | spacesAfterControlDirective: number, 6 | tabSize: number, 7 | formatDirectivePhpParameters: boolean, 8 | formatDirectiveJsonParameters: boolean, 9 | formatInsideEcho: boolean, 10 | phpOptions: any | undefined, 11 | attributeJsOptions: any | null | undefined, 12 | echoStyle: string, 13 | useLaravelPint: boolean, 14 | pintCommand: string, 15 | pintTempDirectory: string, 16 | pintCacheDirectory: string, 17 | pintCacheEnabled: boolean, 18 | pintConfigPath: string, 19 | classStrings: IClassStringConfiguration, 20 | formatJsAttributes: boolean, 21 | safeWrappingJsAttributes: string[], 22 | includeJsAttributes: string[], 23 | excludeJsAttributes: string[], 24 | } -------------------------------------------------------------------------------- /src/errors/bladeError.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from '../nodes/nodes.js'; 2 | import { Range } from '../nodes/position.js'; 3 | 4 | export enum ErrrorLevel { 5 | Error = 0, 6 | Warning = 1 7 | } 8 | 9 | export class BladeError { 10 | public node: AbstractNode | null = null; 11 | public errorCode = ''; 12 | public message = ''; 13 | public level: ErrrorLevel = ErrrorLevel.Error; 14 | public range: Range | null = null; 15 | 16 | hash() { 17 | let positionSlug = ''; 18 | 19 | if (this.node != null) { 20 | positionSlug = (this.node.endPosition?.offset ?? 0).toString() + "|" + 21 | (this.node.startPosition?.offset ?? 0).toString() + "|"; 22 | } 23 | 24 | return positionSlug + "|" + this.errorCode; 25 | } 26 | 27 | static makeSyntaxError(errorCode: string, node: AbstractNode | null, message: string, level?: ErrrorLevel) { 28 | if (level == null) { 29 | level = ErrrorLevel.Error; 30 | } 31 | 32 | const error = new BladeError(); 33 | 34 | error.errorCode = errorCode; 35 | error.node = node; 36 | error.message = message; 37 | error.level = level; 38 | 39 | return error; 40 | } 41 | } -------------------------------------------------------------------------------- /src/errors/bladeErrorCodes.ts: -------------------------------------------------------------------------------- 1 | export class BladeErrorCodes { 2 | static readonly TYPE_UNEXPECTED_END_OF_INPUT = 'BLADE_001'; 3 | static readonly TYPE_PARSE_UNCLOSED_CONDITION = 'BLADE_002'; 4 | static readonly TYPE_PARSE_UNCLOSED_SWITCH = 'BLADE_003'; 5 | static readonly TYPE_UNPAIRED_CLOSING_DIRECTIVE = 'BLADE_004'; 6 | static readonly TYPE_UNCLOSED_COMMENT = 'BLADE_005'; 7 | static readonly TYPE_UNCLOSED_PHP_DIRECTIVE = 'BLADE_006'; 8 | static readonly TYPE_UNPAIRED_PHP_CLOSING_DIRECTIVE = 'BLADE_007'; 9 | static readonly TYPE_UNCLOSED_VERBATIM = 'BLADE_008'; 10 | static readonly TYPE_UNPAIRED_VERBATIM_CLOSING_DIRECTIVE = 'BLADE_009'; 11 | static readonly TYPE_UNCLOSED_FOR_DIRECTIVE = 'BLADE_010'; 12 | static readonly TYPE_UNPAIRED_FOR_CLOSING_DIRECTIVE = 'BLADE_011'; 13 | static readonly TYPE_UNCLOSED_FOR_ELSE_DIRECTIVE = 'BLADE_012'; 14 | static readonly TYPE_UNPAIRED_FOR_ELSE_CLOSING_DIRECTIVE = 'BLADE_013'; 15 | static readonly TYPE_FOR_ELSE_MISSING_EMPTY_DIRECTIVE = 'BLADE_014'; 16 | } -------------------------------------------------------------------------------- /src/formatting/formattingOptions.ts: -------------------------------------------------------------------------------- 1 | import { TransformOptions } from '../document/transformOptions.js'; 2 | import { ParserOptions } from '../parser/parserOptions.js'; 3 | 4 | export type FormattingOptions = TransformOptions & ParserOptions; 5 | 6 | -------------------------------------------------------------------------------- /src/formatting/unsafeClassStringAttributes.ts: -------------------------------------------------------------------------------- 1 | const UnsafeClassStringAttributes:string[] = [ 2 | 'x-mask', 3 | ]; 4 | 5 | export default UnsafeClassStringAttributes; 6 | 7 | -------------------------------------------------------------------------------- /src/nodes/helpers.ts: -------------------------------------------------------------------------------- 1 | import { AbstractNode } from './nodes.js'; 2 | import { Position } from './position.js'; 3 | 4 | export function getStartPosition(nodes: AbstractNode[]): Position | null { 5 | if (nodes.length == 0) { return null; } 6 | 7 | return nodes[0].startPosition; 8 | } -------------------------------------------------------------------------------- /src/nodes/labeledRange.ts: -------------------------------------------------------------------------------- 1 | export interface ILabeledRange { 2 | label: string, 3 | start: number, 4 | end: number 5 | } -------------------------------------------------------------------------------- /src/nodes/offset.ts: -------------------------------------------------------------------------------- 1 | export interface Offset { 2 | start: number, 3 | end: number, 4 | length: number 5 | } -------------------------------------------------------------------------------- /src/parser.ts: -------------------------------------------------------------------------------- 1 | // Internal file used to debug the parser. 2 | -------------------------------------------------------------------------------- /src/parser/bladeKeywords.ts: -------------------------------------------------------------------------------- 1 | export class BladeKeywords { 2 | static readonly Verbatim = 'verbatim'; 3 | static readonly EndVerbatim = 'endverbatim'; 4 | static readonly Php = 'php'; 5 | static readonly EndPhp = 'endphp'; 6 | static readonly If = 'if'; 7 | static readonly ElseIf = 'elseif'; 8 | static readonly Else = 'else'; 9 | static readonly Unless = 'unless'; 10 | static readonly ForElse = 'forelse'; 11 | static readonly EndForElse = 'endforelse'; 12 | static readonly Switch = 'switch'; 13 | static readonly EndSwitch = 'endswitch'; 14 | static readonly Default = 'default'; 15 | static readonly Case = 'case'; 16 | } -------------------------------------------------------------------------------- /src/parser/documentIndex.ts: -------------------------------------------------------------------------------- 1 | export interface DocumentIndex { 2 | start: number, 3 | end: number 4 | } -------------------------------------------------------------------------------- /src/parser/documentOffset.ts: -------------------------------------------------------------------------------- 1 | export interface DocumentOffset { 2 | char: number; 3 | line: number; 4 | } 5 | -------------------------------------------------------------------------------- /src/parser/excludeAttributes/unsafe.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The following list should not be changed. 3 | * 4 | * For example, x-ref="id-{{ $variable }}" would 5 | * be formatted as a subtraction, breaking things. 6 | */ 7 | export const UnsafeJsAttributes:string[] = [ 8 | 'x-ref', 9 | 'is', 10 | 'ref', 11 | 12 | ]; -------------------------------------------------------------------------------- /src/parser/excludeDirectives/commonEventShortcuts.ts: -------------------------------------------------------------------------------- 1 | // Event shortcuts often used by frontend JavaScript libraries. 2 | 3 | export const CommonEventShortcuts: string[] = [ 4 | 'click', 5 | 'submit', 6 | 'scroll', 7 | 'keydown', 8 | 'keypress', 9 | 'keyup', 10 | 'blur', 11 | 'change', 12 | 'contextmenu', 13 | 'copy', 14 | 'cut', 15 | 'paste', 16 | 'dblclick', 17 | 'drag', 18 | 'dragend', 19 | 'dragenter', 20 | 'dragleave', 21 | 'dragover', 22 | 'dragstart', 23 | 'drop', 24 | 'focus', 25 | 'focusin', 26 | 'focusout', 27 | 'input', 28 | 'mousedown', 29 | 'mouseenter', 30 | 'mouseleave', 31 | 'mousemove', 32 | 'mouseover', 33 | 'mouseout', 34 | 'mouseup', 35 | 'mousewheel', 36 | 'resize', 37 | 'select', 38 | 'touchcancel', 39 | 'touchend', 40 | 'touchmove', 41 | 'touchstart', 42 | 'wheel' 43 | ]; -------------------------------------------------------------------------------- /src/parser/excludeDirectives/cssAtRules.ts: -------------------------------------------------------------------------------- 1 | export const CssAtRules: string[] = [ 2 | 'media', 3 | 'charset', 4 | 'import', 5 | 'namespace', 6 | 'supports', 7 | 'document', 8 | 'page', 9 | 'font-face', 10 | 'keyframes', 11 | 'viewport', 12 | 'counter-style', 13 | 'font-feature-values', 14 | 'swash', 15 | 'ornaments', 16 | 'annotation', 17 | 'stylistic', 18 | 'styleset', 19 | 'character-variant', 20 | 'font-variant-alternates', 21 | 'property', 22 | 'color-profile' 23 | ]; -------------------------------------------------------------------------------- /src/parser/extractedAttribute.ts: -------------------------------------------------------------------------------- 1 | export interface IExtractedAttribute { 2 | name: string, 3 | content: string, 4 | startedOn: number, 5 | endedOn: number, 6 | } 7 | 8 | export interface ITransformedExtractedAttribute extends IExtractedAttribute { 9 | transformedContent: string 10 | } -------------------------------------------------------------------------------- /src/parser/indexRange.ts: -------------------------------------------------------------------------------- 1 | export interface IndexRange { 2 | start: number, 3 | end: number 4 | } 5 | -------------------------------------------------------------------------------- /src/parser/lineOffset.ts: -------------------------------------------------------------------------------- 1 | export interface LineOffset { 2 | startIndex: number; 3 | endIndex: number; 4 | char: number; 5 | line: number; 6 | } 7 | -------------------------------------------------------------------------------- /src/parser/parserOptions.ts: -------------------------------------------------------------------------------- 1 | import { CssAtRules } from './excludeDirectives/cssAtRules.js'; 2 | import { CommonEventShortcuts } from './excludeDirectives/commonEventShortcuts.js'; 3 | 4 | export interface ParserOptions { 5 | ignoreDirectives: string[], 6 | directives: string[], 7 | customIfs: string[], 8 | } 9 | 10 | let globalOptions: ParserOptions = { 11 | ignoreDirectives: [ 12 | ...CssAtRules, 13 | ...CommonEventShortcuts 14 | ], 15 | directives: [], 16 | customIfs: [] 17 | }; 18 | 19 | export function updateParserOptions(options: ParserOptions) { 20 | globalOptions = options; 21 | } 22 | 23 | export function getParserOptions(): ParserOptions { 24 | return globalOptions; 25 | } -------------------------------------------------------------------------------- /src/parser/php/phpParserPhpValidator.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from 'php-parser'; 2 | import { PhpValidator } from './phpValidator.js'; 3 | 4 | export class PhpParserPhpValidator implements PhpValidator { 5 | private lastError: SyntaxError | null = null; 6 | 7 | isValid(template: string, isEval = true): boolean { 8 | const parser = new Engine({ 9 | parser: { 10 | extractDoc: true, 11 | }, 12 | ast: { 13 | withPositions: true, 14 | withSource: true, 15 | }, 16 | }); 17 | 18 | try { 19 | if (isEval) { 20 | parser.parseEval(template); 21 | } else { 22 | parser.parseCode(template, 'test.php'); 23 | } 24 | } catch (err) { 25 | if (err instanceof SyntaxError) { 26 | this.lastError = err; 27 | } 28 | 29 | return false; 30 | } 31 | 32 | this.lastError = null; 33 | 34 | return true; 35 | } 36 | getLastError(): SyntaxError | null { 37 | return this.lastError; 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/parser/php/phpValidator.ts: -------------------------------------------------------------------------------- 1 | export interface PhpValidator { 2 | isValid(template: string, isEval: boolean): boolean, 3 | getLastError(): SyntaxError | null, 4 | } 5 | -------------------------------------------------------------------------------- /src/parser/scanResults.ts: -------------------------------------------------------------------------------- 1 | export interface SeekResults { 2 | didFind: boolean, 3 | index: number | null, 4 | char: string 5 | } 6 | 7 | export interface LogicGroupScanResults { 8 | start: number, 9 | end: number, 10 | content: string, 11 | foundEnd: boolean 12 | } 13 | -------------------------------------------------------------------------------- /src/parser/scanners/isStartOfString.ts: -------------------------------------------------------------------------------- 1 | export function isStartOfString(char: string | null): boolean { 2 | if (char == null) { return false; } 3 | 4 | if (char == '"' || char == "'" || char == '`') { 5 | return true; 6 | } 7 | 8 | return false; 9 | } -------------------------------------------------------------------------------- /src/parser/scanners/nextNonWhitespace.ts: -------------------------------------------------------------------------------- 1 | import { StringUtilities } from '../../utilities/stringUtilities.js'; 2 | import { SeekResults } from '../scanResults.js'; 3 | import { StringIterator } from '../stringIterator.js'; 4 | 5 | export function nextNonWhitespace(iterator: StringIterator): SeekResults { 6 | for (let i = iterator.getCurrentIndex() + 1; i < iterator.inputLength(); i++) { 7 | const cur = iterator.getChar(i); 8 | 9 | if (!StringUtilities.ctypeSpace(cur)) { 10 | return { 11 | didFind: true, 12 | index: i, 13 | char: cur 14 | }; 15 | } 16 | } 17 | 18 | return { 19 | didFind: false, 20 | index: null, 21 | char: '' 22 | }; 23 | } -------------------------------------------------------------------------------- /src/parser/scanners/skipToEndOfLine.ts: -------------------------------------------------------------------------------- 1 | import { DocumentParser } from '../documentParser.js'; 2 | import { StringIterator } from '../stringIterator.js'; 3 | 4 | export function skipToEndOfLine(iterator: StringIterator, collect: boolean) { 5 | for (iterator.getCurrentIndex(); iterator.getCurrentIndex() < iterator.inputLength(); iterator.incrementIndex()) { 6 | iterator.checkCurrentOffsets(); 7 | 8 | if (collect) { 9 | iterator.pushChar(iterator.getCurrent() as string); 10 | } 11 | 12 | if (iterator.getCurrent() == DocumentParser.NewLine) { 13 | break; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/parser/scanners/skipToEndOfMultilineComment.ts: -------------------------------------------------------------------------------- 1 | import { DocumentParser } from '../documentParser.js'; 2 | import { StringIterator } from '../stringIterator.js'; 3 | 4 | export function skipToEndOfMultilineComment(iterator: StringIterator, collect: boolean) { 5 | for (iterator.getCurrentIndex(); iterator.getCurrentIndex() < iterator.inputLength(); iterator.incrementIndex()) { 6 | iterator.checkCurrentOffsets(); 7 | 8 | if (collect) { 9 | iterator.pushChar(iterator.getCurrent() as string); 10 | } 11 | 12 | if (iterator.getCurrent() == DocumentParser.Punctuation_Asterisk && iterator.getNext() == DocumentParser.Punctuation_ForwardSlash) { 13 | if (collect) { iterator.pushChar(DocumentParser.Punctuation_ForwardSlash); } 14 | iterator.incrementIndex(); 15 | iterator.checkCurrentOffsets(); 16 | break; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/parser/stringIterator.ts: -------------------------------------------------------------------------------- 1 | export interface StringIterator { 2 | updateIndex(index: number): void, 3 | advance(count:number): void, 4 | inputLength(): number, 5 | getCurrentIndex(): number, 6 | incrementIndex(): void, 7 | getCurrent(): string | null, 8 | getNext(): string | null, 9 | getPrev(): string | null, 10 | checkCurrentOffsets(): void, 11 | pushChar(value: string): void 12 | getChar(index: number): string; 13 | getSeedOffset(): number; 14 | getContentSubstring(from: number, length: number): string; 15 | encounteredFailure(): void; 16 | } -------------------------------------------------------------------------------- /src/test/acceptance/filament/forms_resources_views_components_actions_action_container_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_actions_action_container_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_actions_action_container_blade_php', async () => { 9 | const input = `@foreach ($getActions() as $action) 10 | @if ($action->isVisible()) 11 | {{ $action }} 12 | @endif 13 | @endforeach 14 | `; 15 | const output = `@foreach ($getActions() as $action) 16 | @if ($action->isVisible()) 17 | {{ $action }} 18 | @endif 19 | @endforeach 20 | `; 21 | 22 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 23 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 24 | }).timeout(30000); 25 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/forms_resources_views_components_field_wrapper_helper_text_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_field_wrapper_helper_text_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_field_wrapper_helper_text_blade_php', async () => { 9 | const input = `
class(['filament-forms-field-wrapper-helper-text text-sm text-gray-600 dark:text-gray-300']) }}> 10 | {{ $slot }} 11 |
12 | `; 13 | const output = `
class(['filament-forms-field-wrapper-helper-text text-sm text-gray-600 dark:text-gray-300']) }} 15 | > 16 | {{ $slot }} 17 |
18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/forms_resources_views_components_grid_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_grid_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_grid_blade_php', async () => { 9 | const input = `
merge($getExtraAttributes(), escape: false) }}> 10 | {{ $getChildComponentContainer() }} 11 |
12 | `; 13 | const output = `
merge($getExtraAttributes(), escape: false) }}> 14 | {{ $getChildComponentContainer() }} 15 |
16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/forms_resources_views_components_group_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_group_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_group_blade_php', async () => { 9 | const input = `
merge($getExtraAttributes(), escape: false) }}> 10 | {{ $getChildComponentContainer() }} 11 |
12 | `; 13 | const output = `
merge($getExtraAttributes(), escape: false) }}> 14 | {{ $getChildComponentContainer() }} 15 |
16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/infolists_resources_views_components_actions_action_container_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: infolists_resources_views_components_actions_action_container_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format infolists_resources_views_components_actions_action_container_blade_php', async () => { 9 | const input = `@foreach ($getActions() as $action) 10 | @if ($action->isVisible()) 11 | {{ $action }} 12 | @endif 13 | @endforeach 14 | `; 15 | const output = `@foreach ($getActions() as $action) 16 | @if ($action->isVisible()) 17 | {{ $action }} 18 | @endif 19 | @endforeach 20 | `; 21 | 22 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 23 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 24 | }).timeout(30000); 25 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/infolists_resources_views_components_grid_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: infolists_resources_views_components_grid_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format infolists_resources_views_components_grid_blade_php', async () => { 9 | const input = `
merge($getExtraAttributes(), escape: false) }}> 10 | {{ $getChildComponentContainer() }} 11 |
12 | `; 13 | const output = `
merge($getExtraAttributes(), escape: false) }}> 14 | {{ $getChildComponentContainer() }} 15 |
16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/infolists_resources_views_components_group_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: infolists_resources_views_components_group_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format infolists_resources_views_components_group_blade_php', async () => { 9 | const input = `
merge($getExtraAttributes(), escape: false) }}> 10 | {{ $getChildComponentContainer() }} 11 |
12 | `; 13 | const output = `
merge($getExtraAttributes(), escape: false) }}> 14 | {{ $getChildComponentContainer() }} 15 |
16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/notifications_resources_views_components_body_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: notifications_resources_views_components_body_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format notifications_resources_views_components_body_blade_php', async () => { 9 | const input = `
class(['filament-notifications-body mt-1 text-sm text-gray-500 dark:text-gray-300']) }}> 10 | {{ $slot }} 11 |
12 | `; 13 | const output = `
class(['filament-notifications-body mt-1 text-sm text-gray-500 dark:text-gray-300']) }} 15 | > 16 | {{ $slot }} 17 |
18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/notifications_resources_views_components_date_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: notifications_resources_views_components_date_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format notifications_resources_views_components_date_blade_php', async () => { 9 | const input = `

class(['filament-notifications-date text-xs text-gray-500 dark:text-gray-300']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-notifications-date text-xs text-gray-500 dark:text-gray-300']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/notifications_resources_views_components_title_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: notifications_resources_views_components_title_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format notifications_resources_views_components_title_blade_php', async () => { 9 | const input = `
class(['filament-notifications-title flex h-6 items-center text-sm font-medium text-gray-900 dark:text-gray-100']) }}> 10 | {{ $slot }} 11 |
12 | `; 13 | const output = `
class(['filament-notifications-title flex h-6 items-center text-sm font-medium text-gray-900 dark:text-gray-100']) }} 15 | > 16 | {{ $slot }} 17 |
18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/panels_resources_views_components_header_heading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: panels_resources_views_components_header_heading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format panels_resources_views_components_header_heading_blade_php', async () => { 9 | const input = `

class(['filament-header-heading text-2xl font-bold tracking-tight']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-header-heading text-2xl font-bold tracking-tight']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/panels_resources_views_components_header_subheading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: panels_resources_views_components_header_subheading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format panels_resources_views_components_header_subheading_blade_php', async () => { 9 | const input = `

class(['filament-header-subheading max-w-2xl tracking-tight text-gray-500']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-header-subheading max-w-2xl tracking-tight text-gray-500']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/support_resources_views_components_card_header_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: support_resources_views_components_card_header_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format support_resources_views_components_card_header_blade_php', async () => { 9 | const input = `
class(['filament-card-header space-y-1']) }}> 10 | {{ $slot }} 11 |
12 | `; 13 | const output = `
class(['filament-card-header space-y-1']) }}> 14 | {{ $slot }} 15 |
16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/support_resources_views_components_card_heading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: support_resources_views_components_card_heading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format support_resources_views_components_card_heading_blade_php', async () => { 9 | const input = `

class(['filament-card-heading text-xl font-medium tracking-tight']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-card-heading text-xl font-medium tracking-tight']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/support_resources_views_components_card_subheading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: support_resources_views_components_card_subheading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format support_resources_views_components_card_subheading_blade_php', async () => { 9 | const input = `

class(['filament-card-subheading text-sm text-gray-600 dark:text-gray-400']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-card-subheading text-sm text-gray-600 dark:text-gray-400']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/support_resources_views_components_dropdown_list_index_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: support_resources_views_components_dropdown_list_index_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format support_resources_views_components_dropdown_list_index_blade_php', async () => { 9 | const input = `
class(['filament-dropdown-list p-1']) }}> 10 | {{ $slot }} 11 |
12 | `; 13 | const output = `
class(['filament-dropdown-list p-1']) }}> 14 | {{ $slot }} 15 |
16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/support_resources_views_components_modal_heading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: support_resources_views_components_modal_heading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format support_resources_views_components_modal_heading_blade_php', async () => { 9 | const input = `

class(['filament-modal-heading text-xl font-medium tracking-tight']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-modal-heading text-xl font-medium tracking-tight']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/support_resources_views_components_modal_subheading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: support_resources_views_components_modal_subheading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format support_resources_views_components_modal_subheading_blade_php', async () => { 9 | const input = `

class(['filament-modal-subheading text-gray-500']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-modal-subheading text-gray-500']) }}> 14 | {{ $slot }} 15 |

16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/tables_resources_views_components_cell_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_cell_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_cell_blade_php', async () => { 9 | const input = `class(['filament-tables-cell dark:text-white']) }}> 10 | {{ $slot }} 11 | 12 | `; 13 | const output = `class(['filament-tables-cell dark:text-white']) }}> 14 | {{ $slot }} 15 | 16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/tables_resources_views_components_checkbox_cell_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_checkbox_cell_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_checkbox_cell_blade_php', async () => { 9 | const input = `class(['filament-tables-checkbox-cell w-4 px-4 whitespace-nowrap']) }}> 10 | {{ $slot }} 11 | 12 | `; 13 | const output = `class(['filament-tables-checkbox-cell w-4 whitespace-nowrap px-4']) }} 15 | > 16 | {{ $slot }} 17 | 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/tables_resources_views_components_empty_state_heading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_empty_state_heading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_empty_state_heading_blade_php', async () => { 9 | const input = `

class(['filament-tables-empty-state-heading text-xl font-medium tracking-tight dark:text-white']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-tables-empty-state-heading text-xl font-medium tracking-tight dark:text-white']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/tables_resources_views_components_header_description_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_header_description_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_header_description_blade_php', async () => { 9 | const input = `

class(['filament-tables-header-description']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-tables-header-description']) }}> 14 | {{ $slot }} 15 |

16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/tables_resources_views_components_header_heading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_header_heading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_header_heading_blade_php', async () => { 9 | const input = `

class(['filament-tables-header-heading text-xl font-medium tracking-tight']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-tables-header-heading text-xl font-medium tracking-tight']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/tables_resources_views_components_loading_cell_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_loading_cell_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_loading_cell_blade_php', async () => { 9 | const input = `class(['w-full px-4 py-4 animate-pulse']) }}> 10 |
11 | 12 | `; 13 | const output = `class(['w-full animate-pulse px-4 py-4']) }}> 14 |
15 | 16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/tables_resources_views_components_reorder_cell_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_reorder_cell_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_reorder_cell_blade_php', async () => { 9 | const input = `class(['filament-tables-reorder-cell w-4 px-4 whitespace-nowrap']) }}> 10 | {{ $slot }} 11 | 12 | `; 13 | const output = `class(['filament-tables-reorder-cell w-4 whitespace-nowrap px-4']) }} 15 | > 16 | {{ $slot }} 17 | 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament/widgets_resources_views_table_widget_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: widgets_resources_views_table_widget_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format widgets_resources_views_table_widget_blade_php', async () => { 9 | const input = ` 10 | {{ $this->table }} 11 | 12 | `; 13 | const output = ` 14 | {{ $this->table }} 15 | 16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_card_heading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_card_heading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_card_heading_blade_php', async () => { 9 | const input = `

class(['text-xl font-semibold tracking-tight filament-card-heading']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-card-heading text-xl font-semibold tracking-tight']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_global_search_end_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_global_search_end_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_global_search_end_blade_php', async () => { 9 | const input = ``; 10 | const output = ``; 11 | 12 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 13 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 14 | }).timeout(30000); 15 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_global_search_start_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_global_search_start_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_global_search_start_blade_php', async () => { 9 | const input = ``; 10 | const output = ``; 11 | 12 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 13 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 14 | }).timeout(30000); 15 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_header_heading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_header_heading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_header_heading_blade_php', async () => { 9 | const input = `

class(['filament-header-heading text-2xl font-bold tracking-tight']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-header-heading text-2xl font-bold tracking-tight']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_header_subheading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_header_subheading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_header_subheading_blade_php', async () => { 9 | const input = `

class(['filament-header-subheading max-w-2xl tracking-tight text-gray-500']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-header-subheading max-w-2xl tracking-tight text-gray-500']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_hr_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_hr_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_hr_blade_php', async () => { 9 | const input = ` 13 | `; 14 | const output = ` 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_icon_button_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_icon_button_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_icon_button_blade_php', async () => { 9 | const input = ` 13 | `; 14 | const output = ` 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_layouts_app_sidebar_end_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_layouts_app_sidebar_end_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_layouts_app_sidebar_end_blade_php', async () => { 9 | const input = ``; 10 | const output = ``; 11 | 12 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 13 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 14 | }).timeout(30000); 15 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_layouts_app_sidebar_footer_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_layouts_app_sidebar_footer_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_layouts_app_sidebar_footer_blade_php', async () => { 9 | const input = ` 10 | `; 11 | const output = ``; 12 | 13 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 14 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 15 | }).timeout(30000); 16 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_layouts_app_sidebar_start_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_layouts_app_sidebar_start_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_layouts_app_sidebar_start_blade_php', async () => { 9 | const input = ``; 10 | const output = ``; 11 | 12 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 13 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 14 | }).timeout(30000); 15 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_components_notification_manager_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_components_notification_manager_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_components_notification_manager_blade_php', async () => { 9 | const input = `@php 10 | /** @deprecated */ 11 | @endphp 12 | `; 13 | const output = `@php 14 | /** @deprecated */ 15 | @endphp 16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/admin_resources_views_widgets_table_widget_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: admin_resources_views_widgets_table_widget_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format admin_resources_views_widgets_table_widget_blade_php', async () => { 9 | const input = ` 10 | {{ $this->table }} 11 | 12 | `; 13 | const output = ` 14 | {{ $this->table }} 15 | 16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/forms_resources_views_components_builder_block_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_builder_block_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_builder_block_blade_php', async () => { 9 | const input = `
merge($getExtraAttributes())->class(['filament-forms-builder-component-block py-8']) }}> 10 | {{ $getChildComponentContainer() }} 11 |
12 | `; 13 | const output = `
merge($getExtraAttributes())->class(['filament-forms-builder-component-block py-8']) }} 15 | > 16 | {{ $getChildComponentContainer() }} 17 |
18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/forms_resources_views_components_grid_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_grid_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_grid_blade_php', async () => { 9 | const input = `
merge($getExtraAttributes()) }}> 10 | {{ $getChildComponentContainer() }} 11 |
12 | `; 13 | const output = `
merge($getExtraAttributes()) }}> 14 | {{ $getChildComponentContainer() }} 15 |
16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/forms_resources_views_components_group_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_group_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_group_blade_php', async () => { 9 | const input = `
merge($getExtraAttributes()) }}> 10 | {{ $getChildComponentContainer() }} 11 |
12 | `; 13 | const output = `
merge($getExtraAttributes()) }}> 14 | {{ $getChildComponentContainer() }} 15 |
16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/forms_resources_views_components_hr_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_hr_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_hr_blade_php', async () => { 9 | const input = ` 13 | `; 14 | const output = ` 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/forms_resources_views_components_icon_button_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_icon_button_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_icon_button_blade_php', async () => { 9 | const input = ` 13 | `; 14 | const output = ` 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/forms_resources_views_components_multiple_file_upload_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: forms_resources_views_components_multiple_file_upload_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format forms_resources_views_components_multiple_file_upload_blade_php', async () => { 9 | const input = `{{ $getChildComponentContainer() }} 10 | `; 11 | const output = `{{ $getChildComponentContainer() }} 12 | `; 13 | 14 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 15 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 16 | }).timeout(30000); 17 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/notifications_resources_views_components_close_button_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: notifications_resources_views_components_close_button_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format notifications_resources_views_components_close_button_blade_php', async () => { 9 | const input = ` 13 | `; 14 | const output = ` 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/notifications_resources_views_components_hr_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: notifications_resources_views_components_hr_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format notifications_resources_views_components_hr_blade_php', async () => { 9 | const input = ` 13 | `; 14 | const output = ` 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/support_resources_views_components_dropdown_list_index_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: support_resources_views_components_dropdown_list_index_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format support_resources_views_components_dropdown_list_index_blade_php', async () => { 9 | const input = `
class(['filament-dropdown-list p-1']) }}> 10 | {{ $slot }} 11 |
12 | `; 13 | const output = `
class(['filament-dropdown-list p-1']) }}> 14 | {{ $slot }} 15 |
16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/support_resources_views_components_modal_subheading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: support_resources_views_components_modal_subheading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format support_resources_views_components_modal_subheading_blade_php', async () => { 9 | const input = `@props([ 10 | 'darkMode' => false, 11 | ]) 12 | 13 |

class(['filament-modal-subheading text-gray-500']) }}> 14 | {{ $slot }} 15 |

16 | `; 17 | const output = `@props([ 18 | 'darkMode' => false, 19 | ]) 20 | 21 |

class(['filament-modal-subheading text-gray-500']) }}> 22 | {{ $slot }} 23 |

24 | `; 25 | 26 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 27 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 28 | }).timeout(30000); 29 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/tables_resources_views_components_checkbox_cell_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_checkbox_cell_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_checkbox_cell_blade_php', async () => { 9 | const input = `class(['filament-tables-checkbox-cell w-4 px-4 whitespace-nowrap']) }}> 10 | {{ $slot }} 11 | 12 | `; 13 | const output = `class(['filament-tables-checkbox-cell w-4 whitespace-nowrap px-4']) }} 15 | > 16 | {{ $slot }} 17 | 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/tables_resources_views_components_header_description_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_header_description_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_header_description_blade_php', async () => { 9 | const input = `

class(['filament-tables-header-description']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-tables-header-description']) }}> 14 | {{ $slot }} 15 |

16 | `; 17 | 18 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 19 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 20 | }).timeout(30000); 21 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/tables_resources_views_components_header_heading_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_header_heading_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_header_heading_blade_php', async () => { 9 | const input = `

class(['filament-tables-header-heading text-xl font-bold tracking-tight']) }}> 10 | {{ $slot }} 11 |

12 | `; 13 | const output = `

class(['filament-tables-header-heading text-xl font-bold tracking-tight']) }} 15 | > 16 | {{ $slot }} 17 |

18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/tables_resources_views_components_hr_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_hr_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_hr_blade_php', async () => { 9 | const input = ` 13 | `; 14 | const output = ` 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/tables_resources_views_components_icon_button_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_icon_button_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_icon_button_blade_php', async () => { 9 | const input = ` 13 | `; 14 | const output = ` 18 | `; 19 | 20 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 21 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 22 | }).timeout(30000); 23 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_2/tables_resources_views_components_reorder_cell_blade_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../../../formatting/prettier/utils.js'; 3 | import { StringUtilities } from '../../../utilities/stringUtilities.js'; 4 | import { setupTestHooks } from '../../../test/testUtils/formatting.js'; 5 | 6 | suite('Pint Transformer Acceptance: tables_resources_views_components_reorder_cell_blade_php', () => { 7 | setupTestHooks(); 8 | test('pint: it can format tables_resources_views_components_reorder_cell_blade_php', async () => { 9 | const input = `class(['filament-tables-reorder-cell w-4 px-4 whitespace-nowrap']) }} 11 | > 12 | {{ $slot }} 13 | 14 | `; 15 | const output = `class(['filament-tables-reorder-cell w-4 whitespace-nowrap px-4']) }} 17 | > 18 | {{ $slot }} 19 | 20 | `; 21 | 22 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(input)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 23 | assert.strictEqual(StringUtilities.normalizeLineEndings((await formatBladeStringWithPint(output)).trim()), StringUtilities.normalizeLineEndings(output.trim())); 24 | }).timeout(30000); 25 | }); -------------------------------------------------------------------------------- /src/test/acceptance/filament_license.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) Filament 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/test/array_parser.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { ArrayPrinter } from '../document/printers/arrayPrinter.js'; 3 | import { ArrayNode } from '../nodes/nodes.js'; 4 | import { SimpleArrayParser } from '../parser/simpleArrayParser.js'; 5 | import { assertNotNull } from './testUtils/assertions.js'; 6 | 7 | suite('Simple Array Parser', () => { 8 | test('it can parse and print arrays', () => { 9 | const parser = new SimpleArrayParser(), 10 | array = parser.parse(`['hello', 'world', 'this' => 'that', 11 | 12 | 'nested' => ['array', 'here', 'nested' => ['array', 'here']], 'test', [0,1,2], 'test', $variable, 13 | 'test' => \\Something\\Test\\Here::class, 14 | ]`); 15 | assertNotNull(array); 16 | 17 | const printed = ArrayPrinter.print(array as ArrayNode, 4, 1); 18 | 19 | assert.strictEqual( 20 | printed, 21 | `[ 22 | 'hello', 23 | 'world', 24 | 'this' => 'that', 25 | 'nested' => [ 26 | 'array', 27 | 'here', 28 | 'nested' => [ 29 | 'array', 30 | 'here', 31 | ], 32 | ], 33 | 'test', 34 | 'test', 35 | $variable, 36 | 'test' => \\Something\\Test\\Here::class, 37 | ]` 38 | ); 39 | }); 40 | }); -------------------------------------------------------------------------------- /src/test/compiler_append.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Compiler Append', () => { 5 | test('it compiles append', () => { 6 | assert.strictEqual(PhpCompiler.compileString('@append'), 'appendSection(); ?>'); 7 | }); 8 | }); -------------------------------------------------------------------------------- /src/test/compiler_auth.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Auth Statements', () => { 5 | test('else auth statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@auth("api") 8 | breeze 9 | @elseauth("standard") 10 | wheeze 11 | @endauth`), 12 | `guard("api")->check()): ?> 13 | breeze 14 | guard()->check()): ?> 15 | wheeze 16 | ` 17 | ); 18 | }); 19 | 20 | test('plain else auth statements are compiled', () => { 21 | assert.strictEqual( 22 | PhpCompiler.compileString(`@auth("api") 23 | breeze 24 | @elseauth 25 | wheeze 26 | @endauth`), 27 | `guard("api")->check()): ?> 28 | breeze 29 | guard()->check()): ?> 30 | wheeze 31 | ` 32 | ); 33 | }) 34 | }); -------------------------------------------------------------------------------- /src/test/compiler_can.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Can Statements', () => { 5 | test('can statements are compiled', () => { 6 | assert.strictEqual(PhpCompiler.compileString(`@can ('update', [$post]) 7 | breeze 8 | @elsecan('delete', [$post]) 9 | sneeze 10 | @endcan`), `check('update', [$post])): ?> 11 | breeze 12 | check('delete', [$post])): ?> 13 | sneeze 14 | `); 15 | }); 16 | }); -------------------------------------------------------------------------------- /src/test/compiler_canany.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Canany Statement', () => { 5 | test('canany statements are compiled', () => { 6 | assert.strictEqual(PhpCompiler.compileString(`@canany (['create', 'update'], [$post]) 7 | breeze 8 | @elsecanany(['delete', 'approve'], [$post]) 9 | sneeze 10 | @endcan`), `any(['create', 'update'], [$post])): ?> 11 | breeze 12 | any(['delete', 'approve'], [$post])): ?> 13 | sneeze 14 | `); 15 | }); 16 | }) -------------------------------------------------------------------------------- /src/test/compiler_cannot.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Cannot Statements', () => { 5 | test('cannot statements are compiled', () => { 6 | assert.strictEqual(PhpCompiler.compileString(`@cannot ('update', [$post]) 7 | breeze 8 | @elsecannot('delete', [$post]) 9 | sneeze 10 | @endcannot`), `denies('update', [$post])): ?> 11 | breeze 12 | denies('delete', [$post])): ?> 13 | sneeze 14 | `); 15 | }); 16 | }); -------------------------------------------------------------------------------- /src/test/compiler_checked.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Checked Statements', () => { 5 | test('selected statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(``), 8 | "/>" 9 | ); 10 | }); 11 | 12 | test('checked statements are compiled', () => { 13 | assert.strictEqual( 14 | PhpCompiler.compileString(``), 15 | "/>" 16 | ); 17 | }); 18 | 19 | test('disabled statements are compiled', () => { 20 | assert.strictEqual( 21 | PhpCompiler.compileString(``), 22 | "" 23 | ); 24 | }); 25 | }); -------------------------------------------------------------------------------- /src/test/compiler_class.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Class', () => { 5 | test('classes are conditionally compiled from array', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(` true, 'mr-2' => false])>`), 8 | `` 9 | ); 10 | }); 11 | }); -------------------------------------------------------------------------------- /src/test/compiler_comments.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Comments', () => { 5 | test('comments are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString('{{--this is a comment--}}'), 8 | '' 9 | ); 10 | 11 | let longComment = '{{-- this is an ' + 'extremely '.repeat(1000) + 'long comment --}}'; 12 | assert.strictEqual( 13 | PhpCompiler.compileString(longComment), 14 | '' 15 | ); 16 | }); 17 | 18 | test('blade code inside comments is not compiled', () => { 19 | assert.strictEqual( 20 | PhpCompiler.compileString('{{-- @foreach() --}}'), 21 | '' 22 | ); 23 | }); 24 | }) -------------------------------------------------------------------------------- /src/test/compiler_componentfirst.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Component First', () => { 5 | test('component firsts are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@componentFirst(["one", "two"])`), 8 | `startComponentFirst(["one", "two"]); ?>` 9 | ); 10 | 11 | assert.strictEqual( 12 | PhpCompiler.compileString(`@componentFirst(["one", "two"], ["foo" => "bar"])`), 13 | `startComponentFirst(["one", "two"], ["foo" => "bar"]); ?>` 14 | ); 15 | }); 16 | }); -------------------------------------------------------------------------------- /src/test/compiler_else.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Else Statements', () => { 5 | test('else statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@if (name(foo(bar))) 8 | breeze 9 | @else 10 | boom 11 | @endif`), 12 | ` 13 | breeze 14 | 15 | boom 16 | ` 17 | ); 18 | }); 19 | 20 | test('else if statements are compiled', () => { 21 | assert.strictEqual( 22 | PhpCompiler.compileString(`@if(name(foo(bar))) 23 | breeze 24 | @elseif(boom(breeze)) 25 | boom 26 | @endif`), 27 | ` 28 | breeze 29 | 30 | boom 31 | ` 32 | ); 33 | }); 34 | }); -------------------------------------------------------------------------------- /src/test/compiler_elseif.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade ElseIf Statements', () => { 5 | test('else if statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@if(name(foo(bar))) 8 | breeze 9 | @elseif(boom(breeze)) 10 | boom 11 | @endif`), 12 | ` 13 | breeze 14 | 15 | boom 16 | ` 17 | ); 18 | }); 19 | }); -------------------------------------------------------------------------------- /src/test/compiler_endsection.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade End Sections', () => { 5 | test('end sections are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString('@endsection'), 8 | 'stopSection(); ?>' 9 | ); 10 | }); 11 | }); -------------------------------------------------------------------------------- /src/test/compiler_escaped.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Escaped', () => { 5 | test('escaped with at directives are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString('@@foreach'), 8 | '@foreach' 9 | ); 10 | 11 | assert.strictEqual( 12 | PhpCompiler.compileString('@@verbatim @@continue @@endverbatim'), 13 | '@verbatim @continue @endverbatim' 14 | ); 15 | 16 | assert.strictEqual( 17 | PhpCompiler.compileString('@@foreach($i as $x)'), 18 | '@foreach($i as $x)' 19 | ); 20 | 21 | assert.strictEqual( 22 | PhpCompiler.compileString('@@continue @@break'), 23 | '@continue @break' 24 | ); 25 | 26 | assert.strictEqual( 27 | PhpCompiler.compileString(`@@foreach( 28 | $i as $x 29 | )`), 30 | `@foreach( 31 | $i as $x 32 | )` 33 | ); 34 | }); 35 | }); -------------------------------------------------------------------------------- /src/test/compiler_expression.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Expression Test', () => { 5 | test('expressions on the same line', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString('@lang(foo(bar(baz(qux(breeze()))))) space () @lang(foo(bar))'), 8 | `get(foo(bar(baz(qux(breeze()))))); ?> space () get(foo(bar)); ?>` 9 | ); 10 | }); 11 | 12 | test('expression within html', () => { 13 | assert.strictEqual( 14 | PhpCompiler.compileString(''), 15 | '>' 16 | ); 17 | 18 | assert.strictEqual( 19 | PhpCompiler.compileString(''), 20 | '>' 21 | ); 22 | 23 | assert.strictEqual( 24 | PhpCompiler.compileString(``), 25 | ' get(\'foo\'); ?>>' 26 | ) 27 | }); 28 | }); -------------------------------------------------------------------------------- /src/test/compiler_extends.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Extends', () => { 5 | test('extends are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@extends('foo') 8 | test`), 9 | `make('foo', \\Illuminate\\Support\\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?> 10 | test` 11 | ); 12 | assert.strictEqual( 13 | PhpCompiler.compileString(`@extends(nameof(foo)) 14 | test`), 15 | `make(nameof(foo), \\Illuminate\\Support\\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?> 16 | test` 17 | ); 18 | }); 19 | }); -------------------------------------------------------------------------------- /src/test/compiler_for.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade For Statements', () => { 5 | test('for statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@for ($i = 0; $i < 10; $i++) 8 | test 9 | @endfor`), 10 | ` 11 | test 12 | ` 13 | ); 14 | }); 15 | 16 | test('nested for statements are compiled', () => { 17 | assert.strictEqual( 18 | PhpCompiler.compileString(`@for ($i = 0; $i < 10; $i++) 19 | @for ($j = 0; $j < 20; $j++) 20 | test 21 | @endfor 22 | @endfor`), 23 | ` 24 | 25 | test 26 | 27 | ` 28 | ); 29 | }); 30 | }); -------------------------------------------------------------------------------- /src/test/compiler_guest.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Else Guest Statements', () => { 5 | test('guest if statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@guest("api") 8 | breeze 9 | @elseguest("standard") 10 | wheeze 11 | @endguest`), 12 | `guard("api")->guest()): ?> 13 | breeze 14 | guard("standard")->guest()): ?> 15 | wheeze 16 | ` 17 | ); 18 | }); 19 | }); -------------------------------------------------------------------------------- /src/test/compiler_hassection.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Has Section', () => { 5 | test('has section statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@hasSection("section") 8 | breeze 9 | @endif`), 10 | `yieldContent("section")))): ?> 11 | breeze 12 | ` 13 | ); 14 | }); 15 | }); -------------------------------------------------------------------------------- /src/test/compiler_if.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade If Statements', () => { 5 | test('if statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@if (name(foo(bar))) 8 | breeze 9 | @endif`), 10 | ` 11 | breeze 12 | ` 13 | ); 14 | }); 15 | 16 | test('switch statements are compiled', () => { 17 | assert.strictEqual( 18 | PhpCompiler.compileString(`@switch(true) 19 | @case(1) 20 | foo 21 | 22 | @case(2) 23 | bar 24 | @endswitch 25 | 26 | foo 27 | 28 | @switch(true) 29 | @case(1) 30 | foo 31 | 32 | @case(2) 33 | bar 34 | @endswitch`), 35 | ` 37 | 38 | foo 39 | 40 | 41 | bar 42 | 43 | 44 | foo 45 | 46 | 48 | 49 | foo 50 | 51 | 52 | bar 53 | ` 54 | ); 55 | }); 56 | }); -------------------------------------------------------------------------------- /src/test/compiler_ifauth.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade If Auth Statements', () => { 5 | test('if statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@auth("api") 8 | breeze 9 | @endauth`), 10 | `guard("api")->check()): ?> 11 | breeze 12 | ` 13 | ); 14 | }); 15 | 16 | test('plain if statements are compiled', () => { 17 | assert.strictEqual( 18 | PhpCompiler.compileString(`@auth 19 | breeze 20 | @endauth`), 21 | `guard()->check()): ?> 22 | breeze 23 | ` 24 | ); 25 | }); 26 | }); -------------------------------------------------------------------------------- /src/test/compiler_ifempty.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade If Empty Statements', () => { 5 | test('if statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@empty ($test) 8 | breeze 9 | @endempty`), 10 | ` 11 | breeze 12 | ` 13 | ); 14 | }); 15 | }); -------------------------------------------------------------------------------- /src/test/compiler_ifguest.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade If Guest Statements', () => { 5 | test('if statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@guest("api") 8 | breeze 9 | @endguest`), 10 | `guard("api")->guest()): ?> 11 | breeze 12 | ` 13 | ); 14 | }); 15 | }); -------------------------------------------------------------------------------- /src/test/compiler_ifisset.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade if Isset Statements', () => { 5 | test('if statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@isset ($test) 8 | breeze 9 | @endisset`), 10 | ` 11 | breeze 12 | ` 13 | ); 14 | }); 15 | }); -------------------------------------------------------------------------------- /src/test/compiler_js.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Js', () => { 5 | test('statement is compiled without any options', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString('
'), 8 | '
' 9 | ); 10 | }); 11 | 12 | test('json flags can be set', () => { 13 | assert.strictEqual( 14 | PhpCompiler.compileString('
'), 15 | '
' 16 | ); 17 | }); 18 | 19 | test('encoding depth can be set', () => { 20 | assert.strictEqual( 21 | PhpCompiler.compileString('
'), 22 | '
' 23 | ); 24 | }); 25 | }); -------------------------------------------------------------------------------- /src/test/compiler_json.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Json', () => { 5 | test('statement is compiled with safe default encoding options', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString('var foo = @json($var);'), 8 | 'var foo = ;' 9 | ); 10 | }); 11 | 12 | test('encoding options can be overwritten', () => { 13 | assert.strictEqual( 14 | PhpCompiler.compileString('var foo = @json($var, JSON_HEX_TAG);'), 15 | 'var foo = ;' 16 | ); 17 | }); 18 | }); -------------------------------------------------------------------------------- /src/test/compiler_lang.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Lang', () => { 5 | test('statement that contains non consecutive parenthesis are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString("Foo @lang(function_call('foo(blah)')) bar"), 8 | "Foo get(function_call('foo(blah)')); ?> bar" 9 | ); 10 | }); 11 | 12 | test('language and choices are compiled', () => { 13 | assert.strictEqual( 14 | PhpCompiler.compileString("@lang('foo')"), 15 | 'get(\'foo\'); ?>' 16 | ); 17 | 18 | assert.strictEqual( 19 | PhpCompiler.compileString("@choice('foo', 1)"), 20 | 'choice(\'foo\', 1); ?>' 21 | ); 22 | }); 23 | }); -------------------------------------------------------------------------------- /src/test/compiler_overwrite.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Overwrite Section', () => { 5 | test('overwrite sections are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString('@overwrite'), 8 | 'stopSection(true); ?>' 9 | ); 10 | }); 11 | }); -------------------------------------------------------------------------------- /src/test/compiler_props.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Props', () => { 5 | test('props are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@props(['one' => true, 'two' => 'string'])`), 8 | `onlyProps(['one' => true, 'two' => 'string']) as $__key => $__value) { 9 | $$__key = $$__key ?? $__value; 10 | } ?> 11 | exceptProps(['one' => true, 'two' => 'string']); ?> 12 | true, 'two' => 'string']), 'is_string', ARRAY_FILTER_USE_KEY) as $__key => $__value) { 13 | $$__key = $$__key ?? $__value; 14 | } ?> 15 | 16 | $__value) { 17 | if (array_key_exists($__key, $__defined_vars)) unset($$__key); 18 | } ?> 19 | ` 20 | ); 21 | }); 22 | }); -------------------------------------------------------------------------------- /src/test/compiler_section.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Section', () => { 5 | test('section starts are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@section('foo')`), 8 | `startSection('foo'); ?>` 9 | ); 10 | assert.strictEqual( 11 | PhpCompiler.compileString(`@section(name(foo))`), 12 | `startSection(name(foo)); ?>` 13 | ); 14 | }); 15 | }); -------------------------------------------------------------------------------- /src/test/compiler_sectionmissing.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Section Missing', () => { 5 | test('section missing statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@sectionMissing("section") 8 | breeze 9 | @endif`), 10 | `yieldContent("section")))): ?> 11 | breeze 12 | ` 13 | ); 14 | }); 15 | }); -------------------------------------------------------------------------------- /src/test/compiler_show.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Show', () => { 5 | test('shows are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString('@show'), 8 | `yieldSection(); ?>` 9 | ); 10 | }); 11 | }); -------------------------------------------------------------------------------- /src/test/compiler_stack.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Stack', () => { 5 | test('stacks is compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@stack('foo')`), 8 | `yieldPushContent('foo'); ?>` 9 | ); 10 | 11 | assert.strictEqual( 12 | PhpCompiler.compileString(`@stack(name(foo))`), 13 | `yieldPushContent(name(foo)); ?>` 14 | ); 15 | }); 16 | }); -------------------------------------------------------------------------------- /src/test/compiler_stopsection.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Stop Section', () => { 5 | test('stop sections are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString('@stop'), 8 | 'stopSection(); ?>' 9 | ); 10 | }); 11 | }); -------------------------------------------------------------------------------- /src/test/compiler_unknown.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | import { BladeDocument } from '../document/bladeDocument.js'; 4 | import { DirectiveNode } from '../nodes/nodes.js'; 5 | 6 | suite('Unknown Directives Test', () => { 7 | test('unknown directive compiler', () => { 8 | const compiler = new PhpCompiler(); 9 | compiler.setUnknownDirectiveCompiler({ 10 | compile(node) { 11 | const directive = node as DirectiveNode; 12 | return `Unknown directive: ${directive.name}`; 13 | }, 14 | }); 15 | 16 | assert.strictEqual( 17 | compiler.compile(BladeDocument.fromText('@unknownOne @unknownTwo')), 18 | 'Unknown directive: unknownOne Unknown directive: unknownTwo' 19 | ); 20 | }); 21 | }); -------------------------------------------------------------------------------- /src/test/compiler_unless.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Unless Statements', () => { 5 | test('unless statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@unless (name(foo(bar))) 8 | breeze 9 | @endunless`), 10 | ` 11 | breeze 12 | ` 13 | ); 14 | }); 15 | }); -------------------------------------------------------------------------------- /src/test/compiler_unset.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Unset Statements', () => { 5 | test('unset statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@unset($unset)`), 8 | `` 9 | ); 10 | }); 11 | }); -------------------------------------------------------------------------------- /src/test/compiler_while.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade While Statements', () => { 5 | test('while statements are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@while ($foo) 8 | test 9 | @endwhile`), 10 | ` 11 | test 12 | ` 13 | ); 14 | }); 15 | 16 | test('nested while statements are compiled', () => { 17 | assert.strictEqual( 18 | PhpCompiler.compileString(`@while ($foo) 19 | @while ($bar) 20 | test 21 | @endwhile 22 | @endwhile`), 23 | ` 24 | 25 | test 26 | 27 | ` 28 | ); 29 | }); 30 | }); -------------------------------------------------------------------------------- /src/test/compiler_yield.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpCompiler } from '../compiler/phpCompiler.js'; 3 | 4 | suite('Blade Yield', () => { 5 | test('yields are compiled', () => { 6 | assert.strictEqual( 7 | PhpCompiler.compileString(`@yield('foo')`), 8 | `yieldContent('foo'); ?>` 9 | ); 10 | 11 | assert.strictEqual( 12 | PhpCompiler.compileString(`@yield('foo', 'bar')`), 13 | `yieldContent('foo', 'bar'); ?>` 14 | ); 15 | 16 | assert.strictEqual( 17 | PhpCompiler.compileString(`@yield(name(foo))`), 18 | `yieldContent(name(foo)); ?>` 19 | ); 20 | }); 21 | }); -------------------------------------------------------------------------------- /src/test/custom_ifs.test.ts: -------------------------------------------------------------------------------- 1 | import { BladeDocument } from '../document/bladeDocument.js'; 2 | import { ConditionNode, LiteralNode } from '../nodes/nodes.js'; 3 | import { ParserOptions } from '../parser/parserOptions.js'; 4 | import { assertCount, assertInstanceOf } from './testUtils/assertions.js'; 5 | 6 | suite('Custom If Statements', () => { 7 | test('it can parse configured custom ifs', () => { 8 | const options: ParserOptions = { 9 | ignoreDirectives: [], 10 | customIfs: ['otherDisk'], 11 | directives: [] 12 | }; 13 | 14 | const doc = new BladeDocument(); 15 | doc.getParser().withParserOptions(options); 16 | 17 | const nodes = doc.loadString(` 18 | 19 | @otherDisk($test) 20 | 21 | 22 | @endotherDisk 23 | 24 | `).getRenderNodes(); 25 | 26 | assertCount(3, nodes); 27 | assertInstanceOf(LiteralNode, nodes[0]); 28 | assertInstanceOf(ConditionNode, nodes[1]); 29 | assertInstanceOf(LiteralNode, nodes[2]); 30 | }); 31 | }); -------------------------------------------------------------------------------- /src/test/error_printer.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { BladeDocument } from '../document/bladeDocument.js'; 3 | import { ErrorPrinter } from '../document/printers/errorPrinter.js'; 4 | 5 | suite('Error Printer Test', () => { 6 | test('it can pretty print error messages', () => { 7 | const doc = BladeDocument.fromText(`asdf 8 | asdfasdf 9 | asdfasdffasdf 10 | 11 | asdfasdffasdf 12 | asdfasdf 13 | asdf 14 | 15 | @if ($something) 16 | asdfasdf 17 | asdf`), 18 | firstError = doc.errors.getFirstStructureError(), 19 | lines = doc.getLinesAround((firstError.node?.startPosition?.line) ?? 1), 20 | printed = ErrorPrinter.printError(firstError, lines); 21 | 22 | assert.strictEqual( 23 | printed.trim(), 24 | `Unpaired condition control structure 25 | 26 | 06| asdfasdf 27 | 07| asdf 28 | 08| 29 | >09| @if ($something) 30 | 10| asdfasdf 31 | 11| asdf` 32 | ); 33 | }); 34 | }); -------------------------------------------------------------------------------- /src/test/formatter_can.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeString } from '../formatting/prettier/utils.js'; 3 | 4 | suite('Can Directive Formatting', () => { 5 | test('it can format can directive without errors', async () => { 6 | const template = `{{-- foo.blade.php --}} 7 | 8 | @props([ 9 | "model", 10 | ]) 11 | 12 | @can('update', $model) 13 | update 14 | @else 15 | any 16 | @endcan`; 17 | const expected = `{{-- foo.blade.php --}} 18 | 19 | @props([ 20 | "model", 21 | ]) 22 | 23 | @can("update", $model) 24 | update 25 | @else 26 | any 27 | @endcan`; 28 | assert.strictEqual((await formatBladeString(template)).trim(), expected.trim()); 29 | }); 30 | }); -------------------------------------------------------------------------------- /src/test/formatter_conditional_element_unless.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeString } from '../formatting/prettier/utils.js'; 3 | 4 | suite('Conditional Element Unless Statements', () => { 5 | test('it can detect and format conditional unless statements as HTML tags', async () => { 6 | assert.strictEqual( 7 | (await formatBladeString(` <@unless($something)here @endunless class="something"> 8 |

SOme {{ $text }} text

9 | <@unless($something)here @endunless class="something"> 10 |

SOme {{ $text }} text

11 |
12 | 13 |
14 | `)).trim(), 15 | `<@unless($something)here @endunless class="something"> 16 |
17 |

SOme {{ $text }} text

18 | <@unless($something)here @endunless class="something"> 19 |

SOme {{ $text }} text

20 | 21 |
22 | ` 23 | ); 24 | }); 25 | }); -------------------------------------------------------------------------------- /src/test/formatter_literals.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeString } from '../formatting/prettier/utils.js'; 3 | 4 | suite('Format Literals', () => { 5 | test('simple text is returned', async () => { 6 | assert.strictEqual(await formatBladeString('just some text'), "just some text\n"); 7 | }); 8 | 9 | test('simple HTML is returned', async () => { 10 | assert.strictEqual(await formatBladeString('

Some HTML

'), "

Some HTML

\n"); 11 | }); 12 | }); -------------------------------------------------------------------------------- /src/test/formatter_pint_can.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../formatting/prettier/utils.js'; 3 | 4 | suite('Pint Transformer: Can Nodes', () => { 5 | test('pint: it can format can directive without errors', async () => { 6 | const template = `{{-- foo.blade.php --}} 7 | 8 | @props([ 9 | "model", 10 | ]) 11 | 12 | @can('update', $model) 13 | update 14 | @else 15 | any 16 | @endcan`; 17 | const expected = `{{-- foo.blade.php --}} 18 | 19 | @props([ 20 | 'model', 21 | ]) 22 | 23 | @can('update', $model) 24 | update 25 | @else 26 | any 27 | @endcan`; 28 | assert.strictEqual((await formatBladeStringWithPint(template)).trim(), expected.trim()); 29 | }); 30 | }); -------------------------------------------------------------------------------- /src/test/formatter_pint_conditional_element_unless.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../formatting/prettier/utils.js'; 3 | 4 | suite('Pint Transformer: Conditional Element Unless', () => { 5 | test('pint: it can detect and format conditional unless statements as HTML tags', async () => { 6 | assert.strictEqual( 7 | (await formatBladeStringWithPint(` <@unless($something)here @endunless class="something"> 8 |

SOme {{ $text }} text

9 | <@unless($something)here @endunless class="something"> 10 |

SOme {{ $text }} text

11 |
12 | 13 |
14 | `)).trim(), 15 | `<@unless($something)here @endunless class="something"> 16 |
17 |

SOme {{ $text }} text

18 | <@unless($something)here @endunless class="something"> 19 |

SOme {{ $text }} text

20 | 21 |
22 | ` 23 | ); 24 | }); 25 | }); -------------------------------------------------------------------------------- /src/test/formatter_pint_for.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../formatting/prettier/utils.js'; 3 | 4 | suite('Pint Transformer: for Nodes', () => { 5 | test('pint: it correctly pairs and formats for nodes', async () => { 6 | assert.strictEqual( 7 | (await formatBladeStringWithPint(`

8 | Message 9 | @if($one) 10 | One 11 | @elseif($two) 12 |

    13 | 14 | @for ($i = 0; $i < 10; $i++) 15 | The current value is {{ $i }} 16 | @endfor 17 | Something here. 18 | @else 19 | Nope! 20 | @endif 21 |

    `)).trim(), 22 | `

    23 | Message 24 | @if ($one) 25 | One 26 | @elseif ($two) 27 |

      28 | 29 | @for ($i = 0; $i < 10; $i++) 30 | The current value is {{ $i }} 31 | @endfor 32 | Something here. 33 | @else 34 | Nope! 35 | @endif 36 |

      ` 37 | ) 38 | }); 39 | }); -------------------------------------------------------------------------------- /src/test/formatter_pint_literals.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeStringWithPint } from '../formatting/prettier/utils.js'; 3 | 4 | suite('Pint Transformer: Literals', () => { 5 | test('pint: simple text is returned', async () => { 6 | assert.strictEqual(await formatBladeStringWithPint('just some text'), "just some text\n"); 7 | }); 8 | 9 | test('pint: simple HTML is returned', async () => { 10 | assert.strictEqual(await formatBladeStringWithPint('

      Some HTML

      '), "

      Some HTML

      \n"); 11 | }); 12 | }); -------------------------------------------------------------------------------- /src/test/formatter_syntax_reflow.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeString } from '../formatting/prettier/utils.js'; 3 | 4 | suite('Directives Formatting', () => { 5 | test('it reflows arrow functions', async () => { 6 | const expected = `{{ fn () => "foo" }}`; 7 | assert.strictEqual((await formatBladeString(`{{ fn () => 'foo' }}`)).trim(), expected); 8 | assert.strictEqual((await formatBladeString(`{{ fn() => 'foo' }}`)).trim(), expected); 9 | assert.strictEqual((await formatBladeString(`{{ fn()=> 'foo' }}`)).trim(), expected); 10 | }); 11 | }); -------------------------------------------------------------------------------- /src/test/formatting_for.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { formatBladeString } from '../formatting/prettier/utils.js'; 3 | 4 | suite('Formatting Blade For', () => { 5 | test('it correctly pairs and formats for nodes', async () => { 6 | assert.strictEqual( 7 | (await formatBladeString(`

      8 | Message 9 | @if($one) 10 | One 11 | @elseif($two) 12 |

        13 | 14 | @for ($i = 0; $i < 10; $i++) 15 | The current value is {{ $i }} 16 | @endfor 17 | Something here. 18 | @else 19 | Nope! 20 | @endif 21 |

        `)).trim(), 22 | `

        23 | Message 24 | @if ($one) 25 | One 26 | @elseif ($two) 27 |

          28 | 29 | @for ($i = 0; $i < 10; $i++) 30 | The current value is {{ $i }} 31 | @endfor 32 | Something here. 33 | @else 34 | Nope! 35 | @endif 36 |

          ` 37 | ) 38 | }); 39 | }); -------------------------------------------------------------------------------- /src/test/ignored_directives.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { BladeDocument } from '../document/bladeDocument.js'; 3 | import { DirectiveNode, LiteralNode } from '../nodes/nodes.js'; 4 | import { assertCount, assertInstanceOf, assertLiteralContent } from './testUtils/assertions.js'; 5 | 6 | suite('Ignored Directives', () => { 7 | test('it can ignore CSS media', () => { 8 | const nodes = BladeDocument.fromText(` 9 | @media() 10 | 11 | @mediaThing()`).getAllNodes(); 12 | assertCount(2, nodes); 13 | assertInstanceOf(LiteralNode, nodes[0]); 14 | assertInstanceOf(DirectiveNode, nodes[1]); 15 | assertLiteralContent("\n@media()\n\n", nodes[0]); 16 | 17 | const directive = nodes[1] as DirectiveNode; 18 | assert.strictEqual(directive.directiveName, 'mediaThing'); 19 | }); 20 | 21 | test('it does not get confused with whitespace', () => { 22 | const nodes = BladeDocument.fromText(` 23 | @media () @charset 24 | @media 25 | @media () @keyframes( 26 | 27 | ) 28 | @media`).getAllNodes(); 29 | assertCount(1, nodes); 30 | assertInstanceOf(LiteralNode, nodes[0]); 31 | }); 32 | }); -------------------------------------------------------------------------------- /src/test/paren_unwrapper.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { ParenUnwrapper } from '../parser/parenUnwrapper.js'; 3 | 4 | suite('Parenthesis Unwrapper', () => { 5 | test('it removes trailing/leading parens', () => { 6 | const unwrapper = new ParenUnwrapper(); 7 | 8 | assert.strictEqual(unwrapper.unwrap('(test)'), 'test'); 9 | assert.strictEqual(unwrapper.unwrap('((test))'), 'test'); 10 | assert.strictEqual(unwrapper.unwrap('((test) || (test))'), '(test) || (test)'); 11 | assert.strictEqual(unwrapper.unwrap('(("test") || (\'(test\'))'), '("test") || (\'(test\')'); 12 | }); 13 | }); -------------------------------------------------------------------------------- /src/test/php_validator.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { PhpParserPhpValidator } from '../parser/php/phpParserPhpValidator.js'; 3 | import { assertNotNull } from './testUtils/assertions.js'; 4 | 5 | suite('PHP Validator', () => { 6 | test('it detects invalid php', () => { 7 | const validator = new PhpParserPhpValidator(), 8 | isValid = validator.isValid(` $this+++++DS_F`), 9 | error = validator.getLastError(); 10 | 11 | assertNotNull(error); 12 | assert.strictEqual(isValid, false); 13 | assert.strictEqual(error?.message, "Parse Error : syntax error, unexpected '++' (T_INC), expecting ';' on line 1"); 14 | }); 15 | 16 | test('it detects valid php', () => { 17 | const validator = new PhpParserPhpValidator(); 18 | 19 | assert.strictEqual(validator.isValid('$attributes'), true); 20 | assert.strictEqual(validator.getLastError(), null); 21 | }); 22 | }); -------------------------------------------------------------------------------- /src/test/remove_blade_transformer.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { BladeDocument } from '../document/bladeDocument.js'; 3 | 4 | 5 | suite('Transformer Remove Blade', () => { 6 | test('it can remove blade', () => { 7 | const result = BladeDocument.fromText(` 8 | 9 | Transformer Test 10 | 11 | 12 | before 13 | @if (count($records) === 1) 14 | I have one record! 15 | @elseif (count($records) > 1) 16 | I have multiple records! 17 | @else 18 | I don't have any records! 19 | @endif after 20 | 21 | 22 | `).transform().removeBlade(); 23 | assert.strictEqual(result, "\n \n Transformer Test\n \n \n before\n \n I have one record!\n \n I have multiple records!\n \n I don't have any records!\n after\n \n\n"); 24 | }); 25 | }); -------------------------------------------------------------------------------- /src/test/testUtils/formatting.ts: -------------------------------------------------------------------------------- 1 | import * as tailwind from 'prettier-plugin-tailwindcss'; 2 | import { addHtmlPlugin, clearAdditionalHtmlPlugins } from '../../formatting/prettier/utils.js'; 3 | import { afterEach, beforeEach } from 'mocha'; 4 | 5 | function addTailwindPlugin() { 6 | addHtmlPlugin(tailwind); 7 | } 8 | 9 | export function setupTestHooks() { 10 | beforeEach(function () { 11 | addTailwindPlugin(); 12 | }); 13 | 14 | afterEach(() => { 15 | clearAdditionalHtmlPlugins(); 16 | }); 17 | } -------------------------------------------------------------------------------- /src/test/testUtils/transform.ts: -------------------------------------------------------------------------------- 1 | import { BladeDocument } from '../../document/bladeDocument.js'; 2 | 3 | export function transformString(text: string): Promise { 4 | const doc = BladeDocument.fromText(text), 5 | transformed = doc.transform().toStructure(); 6 | 7 | return doc.transform().fromStructure(transformed); 8 | } -------------------------------------------------------------------------------- /src/test/transformer_component_tags.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('Component Tag Transform', () => { 5 | test('it can transform component tags', async () => { 6 | assert.strictEqual( 7 | (await transformString(` 10 |

          Content

          11 |
          `)).trim(), 12 | ` 13 |

          Content

          14 | ` 15 | ); 16 | }); 17 | 18 | test('it transforms inline echos', async () => { 19 | assert.strictEqual( 20 | (await transformString(``)).trim(), 24 | `` 28 | ); 29 | }); 30 | 31 | test('it transforms merged attributes', async () => { 32 | assert.strictEqual( 33 | (await transformString(`
          class(['p-4', 'bg-red' => $hasError]) }}> 34 | {{ $message }} 35 |
          `)).trim(), 36 | `
          class(['p-4', 'bg-red' => $hasError]) }}> 37 | {{ $message }} 38 |
          ` 39 | ); 40 | }); 41 | }); -------------------------------------------------------------------------------- /src/test/transformer_conditional_element_directive_pair.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('Conditional Element Pair Transform', () => { 5 | test('it can transform element pairs', async () => { 6 | assert.strictEqual( 7 | (await transformString(` <@pair Test @endpair class="something"> 8 |

          SOme {{ $title }} text

          9 |

          10 | @pair

          Something

          @endpair 11 |

          12 |
          13 | `)).trim(), 14 | `<@pair Test @endpair class="something"> 15 |

          SOme {{ $title }} text

          16 |

          17 | @pair 18 |

          Something

          @endpair 19 | 20 |

          21 |
          22 | ` 23 | ); 24 | }); 25 | }); -------------------------------------------------------------------------------- /src/test/transformer_echos.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('Echo Transformer', () => { 5 | test('it transforms echos', async () => { 6 | assert.strictEqual( 7 | (await transformString(` 8 |

          test {{ $title }} test 9 | 10 | asdfasdf

          11 | 12 |

          13 | {{ $test }} 14 |

          `)).trim(), 15 | `

          test {{ $title }} test 16 | 17 | asdfasdf

          18 | 19 |

          20 | {{ $test }} 21 |

          ` 22 | ); 23 | }); 24 | }); -------------------------------------------------------------------------------- /src/test/transformer_element_unless.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('Element Unless Transformer', () => { 5 | test('it transforms element unless', async () => { 6 | assert.strictEqual( 7 | (await transformString(`<@unless($something)here @endunless class="something"> 8 |

          SOme {{ $text }} text

          9 | <@unless($something)here @endunless class="something"> 10 |

          SOme {{ $text }} text

          11 |
          12 | 13 |
          14 | `)).trim(), 15 | `<@unless($something)here @endunless class="something"> 16 |

          SOme {{ $text }} text

          17 | <@unless($something)here @endunless class="something"> 18 |

          SOme {{ $text }} text

          19 |
          20 | 21 |
          22 | ` 23 | ); 24 | }); 25 | }); -------------------------------------------------------------------------------- /src/test/transformer_if_statements.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('If Statements Transformer', () => { 5 | test('it can transform if statements', async () => { 6 | assert.strictEqual( 7 | (await transformString(`@if($true) 8 | Thing 9 | @elseif($anotherValue) 10 | More Things 11 | @else 12 | @if($true) 13 | Thing 14 | @elseif($anotherValue) 15 | More Things 16 | @else 17 | Another Thing 18 | @endif 19 | @endif`)).trim(), 20 | `@if ($true) 21 | Thing 22 | @elseif ($anotherValue) 23 | More Things 24 | @else 25 | 26 | @if ($true) 27 | Thing 28 | @elseif ($anotherValue) 29 | More Things 30 | @else 31 | Another Thing 32 | @endif 33 | @endif` 34 | ); 35 | }); 36 | }); -------------------------------------------------------------------------------- /src/test/transformer_inline_php.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('Inline PHP Transformer', () => { 5 | test('it can transform inline PHP', async () => { 6 | assert.strictEqual( 7 | (await transformString(`<> 8 | 9 |

          Text here.

          10 | > 11 | 12 | <> 13 | 14 |

          Text here.

          15 | >`)).trim(), 16 | `<> 17 | 18 | 19 | 20 |

          Text here.

          21 | > 22 | 23 | <> 24 | 25 | 26 | 27 |

          Text here.

          28 | >` 29 | ); 30 | }); 31 | }); -------------------------------------------------------------------------------- /src/test/transformer_json_params.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('JSON Parameter Transformer', () => { 5 | test('it can transform directives with JSON parameters', async () => { 6 | assert.strictEqual( 7 | (await transformString(`@varSet({ 8 | "logo": 9 | 10 | "logo", 11 | "width": ::::: 78, 12 | "height": 13 | 22 14 | }) 15 | 16 | @varSet($test + $thing + $another - ($that + $something))`)).trim(), 17 | `@varSet({ 18 | "logo": 19 | 20 | "logo", 21 | "width": ::::: 78, 22 | "height": 23 | 22 24 | }) 25 | 26 | @varSet($test + $thing + $another - ($that + $something))` 27 | ); 28 | }); 29 | }); -------------------------------------------------------------------------------- /src/test/transformer_props_directive.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('Props Transformer', () => { 5 | test('it can transform documents with props', async () => { 6 | assert.strictEqual( 7 | (await transformString(` 16 | 17 | @props( 18 | 19 | [ 'icon' 20 | 21 | 22 | 23 | ] 24 | 25 | 26 | ) 27 | 28 |
          29 | 31 | {{ $slot }} 32 | 33 | 34 | 35 | 36 |
          `)).trim(), 37 | ` 38 | 39 | 40 | 41 | @props( 42 | 43 | [ 'icon' 44 | 45 | 46 | 47 | ] 48 | 49 | 50 | ) 51 | 52 |
          53 | 54 | {{ $slot }} 55 | 56 | 57 | 58 | 59 |
          ` 60 | ); 61 | }); 62 | }); -------------------------------------------------------------------------------- /src/test/transformer_unless.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('Unless Transformer', () => { 5 | test('it can transform unless statements', async () => { 6 | assert.strictEqual( 7 | (await transformString(`@unless($something) 8 | @unless($somethingTwo) 9 | @unless($somethingThree) 10 | @unless($somethingFour) 11 |
          12 |

          I am just some {{ $text }}

          13 |
          14 | @endunless 15 | @endunless 16 | @endunless 17 | @endunless`)).trim(), 18 | `@unless ($something) 19 | 20 | @unless ($somethingTwo) 21 | 22 | @unless ($somethingThree) 23 | 24 | @unless ($somethingFour) 25 | 26 |
          27 |

          I am just some {{ $text }}

          28 |
          29 | @endunless 30 | @endunless 31 | @endunless 32 | @endunless` 33 | ); 34 | }); 35 | }); -------------------------------------------------------------------------------- /src/test/transformer_verbatim.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { transformString } from './testUtils/transform.js'; 3 | 4 | suite('Verbatim Transformer', () => { 5 | test('it can transform verbatim', async () => { 6 | assert.strictEqual( 7 | (await transformString(`
          8 | @verbatim 9 | 10 | 11 |
          12 | Hello, {{ 13 | name }}. 14 |
          15 | 16 | 17 | @endverbatim 18 |
          `)).trim(), 19 | `
          20 | @verbatim 21 |
          22 | Hello, {{ 23 | name }}. 24 |
          25 | 26 | 27 | 28 | @endverbatim 29 |
          ` 30 | ); 31 | }); 32 | }); -------------------------------------------------------------------------------- /src/utilities/arrayHelpers.ts: -------------------------------------------------------------------------------- 1 | export function intersect(a: any[], b: any[]) { 2 | const setA = new Set(a), 3 | setB = new Set(b), 4 | intersection = new Set([...setA].filter(x => setB.has(x))); 5 | 6 | return Array.from(intersection); 7 | } -------------------------------------------------------------------------------- /src/utilities/isNumeric.ts: -------------------------------------------------------------------------------- 1 | // Source: https://github.com/locutusjs/locutus/blob/master/src/php/var/is_numeric.js 2 | 3 | const whitespace = [ 4 | ' ', 5 | '\n', 6 | '\r', 7 | '\t', 8 | '\f', 9 | '\x0b', 10 | '\xa0', 11 | '\u2000', 12 | '\u2001', 13 | '\u2002', 14 | '\u2003', 15 | '\u2004', 16 | '\u2005', 17 | '\u2006', 18 | '\u2007', 19 | '\u2008', 20 | '\u2009', 21 | '\u200a', 22 | '\u200b', 23 | '\u2028', 24 | '\u2029', 25 | '\u3000' 26 | ].join(''); 27 | 28 | export function is_numeric(char: string): boolean { 29 | return (typeof char === 'number' || 30 | (typeof char === 'string' && 31 | whitespace.indexOf(char.slice(-1)) === -1)) && 32 | char !== '' && 33 | !isNaN(char as any); 34 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "lib": [ 5 | "ES2020", 6 | "ES2020.String" 7 | ], 8 | "module": "ESNext", 9 | "moduleResolution": "node", 10 | "esModuleInterop": true, 11 | "sourceMap": true, 12 | "strict": true, 13 | "outDir": "out", 14 | "rootDir": "src", 15 | "declaration": true, 16 | "declarationMap": true, 17 | "skipLibCheck": true 18 | }, 19 | "include": [ 20 | "src" 21 | ], 22 | "exclude": [ 23 | "node_modules" 24 | ] 25 | } --------------------------------------------------------------------------------