chore: 公开发布准备 - 脱敏与规范对齐
CI / ci (push) Has been cancelled

- 截图敏感信息打码(测试邮箱、内网 IP)
- plugin.yaml 地址改为 GitHub,author 对齐 GitHub 账号,补 version 占位
- 新增 GitHub Actions(halo-sigs plugin-ci/cd 工作流)与 .editorconfig
- console 前端产物纳入仓库(CI skip-node-setup)
- AGENTS.md 移出公开仓库(保留本地)
- README 增加安装说明
This commit is contained in:
shirainbown
2026-08-03 00:32:48 +08:00
parent aa4befa0ff
commit 173a2575fb
14 changed files with 575 additions and 46 deletions
+520
View File
@@ -0,0 +1,520 @@
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = false
max_line_length = 120
tab_width = 4
ij_continuation_indent_size = 8
ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on
ij_formatter_tags_enabled = false
ij_smart_tabs = false
ij_wrap_on_typing = false
[*.java]
max_line_length = 100
ij_continuation_indent_size = 4
ij_java_align_consecutive_assignments = false
ij_java_align_consecutive_variable_declarations = false
ij_java_align_group_field_declarations = false
ij_java_align_multiline_annotation_parameters = false
ij_java_align_multiline_array_initializer_expression = false
ij_java_align_multiline_assignment = false
ij_java_align_multiline_binary_operation = false
ij_java_align_multiline_chained_methods = false
ij_java_align_multiline_extends_list = false
ij_java_align_multiline_for = true
ij_java_align_multiline_method_parentheses = false
ij_java_align_multiline_parameters = false
ij_java_align_multiline_parameters_in_calls = false
ij_java_align_multiline_parenthesized_expression = false
ij_java_align_multiline_records = true
ij_java_align_multiline_resources = true
ij_java_align_multiline_ternary_operation = false
ij_java_align_multiline_text_blocks = false
ij_java_align_multiline_throws_list = false
ij_java_align_subsequent_simple_methods = false
ij_java_align_throws_keyword = false
ij_java_annotation_parameter_wrap = off
ij_java_array_initializer_new_line_after_left_brace = false
ij_java_array_initializer_right_brace_on_new_line = false
ij_java_array_initializer_wrap = normal
ij_java_assert_statement_colon_on_next_line = false
ij_java_assert_statement_wrap = normal
ij_java_assignment_wrap = normal
ij_java_binary_operation_sign_on_next_line = true
ij_java_binary_operation_wrap = normal
ij_java_blank_lines_after_anonymous_class_header = 0
ij_java_blank_lines_after_class_header = 0
ij_java_blank_lines_after_imports = 1
ij_java_blank_lines_after_package = 1
ij_java_blank_lines_around_class = 1
ij_java_blank_lines_around_field = 0
ij_java_blank_lines_around_field_in_interface = 0
ij_java_blank_lines_around_initializer = 1
ij_java_blank_lines_around_method = 1
ij_java_blank_lines_around_method_in_interface = 1
ij_java_blank_lines_before_class_end = 0
ij_java_blank_lines_before_imports = 0
ij_java_blank_lines_before_method_body = 0
ij_java_blank_lines_before_package = 1
ij_java_block_brace_style = end_of_line
ij_java_block_comment_at_first_column = false
ij_java_call_parameters_new_line_after_left_paren = false
ij_java_call_parameters_right_paren_on_new_line = false
ij_java_call_parameters_wrap = normal
ij_java_case_statement_on_separate_line = true
ij_java_catch_on_new_line = false
ij_java_class_annotation_wrap = split_into_lines
ij_java_class_brace_style = end_of_line
ij_java_class_count_to_use_import_on_demand = 999
ij_java_class_names_in_javadoc = 1
ij_java_do_not_indent_top_level_class_members = false
ij_java_do_not_wrap_after_single_annotation = false
ij_java_do_while_brace_force = always
ij_java_doc_add_blank_line_after_description = true
ij_java_doc_add_blank_line_after_param_comments = false
ij_java_doc_add_blank_line_after_return = false
ij_java_doc_add_p_tag_on_empty_lines = true
ij_java_doc_align_exception_comments = true
ij_java_doc_align_param_comments = false
ij_java_doc_do_not_wrap_if_one_line = false
ij_java_doc_enable_formatting = true
ij_java_doc_enable_leading_asterisks = true
ij_java_doc_indent_on_continuation = false
ij_java_doc_keep_empty_lines = true
ij_java_doc_keep_empty_parameter_tag = true
ij_java_doc_keep_empty_return_tag = true
ij_java_doc_keep_empty_throws_tag = true
ij_java_doc_keep_invalid_tags = true
ij_java_doc_param_description_on_new_line = false
ij_java_doc_preserve_line_breaks = false
ij_java_doc_use_throws_not_exception_tag = true
ij_java_else_on_new_line = false
ij_java_enum_constants_wrap = normal
ij_java_extends_keyword_wrap = normal
ij_java_extends_list_wrap = normal
ij_java_field_annotation_wrap = split_into_lines
ij_java_finally_on_new_line = false
ij_java_for_brace_force = always
ij_java_for_statement_new_line_after_left_paren = false
ij_java_for_statement_right_paren_on_new_line = false
ij_java_for_statement_wrap = normal
ij_java_generate_final_locals = false
ij_java_generate_final_parameters = false
ij_java_if_brace_force = always
ij_java_imports_layout = $*, |, *, |, *
ij_java_indent_case_from_switch = true
ij_java_insert_inner_class_imports = false
ij_java_insert_override_annotation = true
ij_java_keep_blank_lines_before_right_brace = 2
ij_java_keep_blank_lines_between_package_declaration_and_header = 2
ij_java_keep_blank_lines_in_code = 2
ij_java_keep_blank_lines_in_declarations = 2
ij_java_keep_control_statement_in_one_line = true
ij_java_keep_first_column_comment = true
ij_java_keep_indents_on_empty_lines = false
ij_java_keep_line_breaks = true
ij_java_keep_multiple_expressions_in_one_line = false
ij_java_keep_simple_blocks_in_one_line = false
ij_java_keep_simple_classes_in_one_line = false
ij_java_keep_simple_lambdas_in_one_line = false
ij_java_keep_simple_methods_in_one_line = false
ij_java_label_indent_absolute = false
ij_java_label_indent_size = 0
ij_java_lambda_brace_style = end_of_line
ij_java_layout_static_imports_separately = true
ij_java_line_comment_add_space = true
ij_java_line_comment_at_first_column = false
ij_java_method_annotation_wrap = split_into_lines
ij_java_method_brace_style = end_of_line
ij_java_method_call_chain_wrap = normal
ij_java_method_parameters_new_line_after_left_paren = false
ij_java_method_parameters_right_paren_on_new_line = false
ij_java_method_parameters_wrap = normal
ij_java_modifier_list_wrap = false
ij_java_names_count_to_use_import_on_demand = 999
ij_java_new_line_after_lparen_in_record_header = false
ij_java_parameter_annotation_wrap = normal
ij_java_parentheses_expression_new_line_after_left_paren = false
ij_java_parentheses_expression_right_paren_on_new_line = false
ij_java_place_assignment_sign_on_next_line = false
ij_java_prefer_longer_names = true
ij_java_prefer_parameters_wrap = false
ij_java_record_components_wrap = normal
ij_java_repeat_synchronized = true
ij_java_replace_instanceof_and_cast = false
ij_java_replace_null_check = true
ij_java_replace_sum_lambda_with_method_ref = true
ij_java_resource_list_new_line_after_left_paren = false
ij_java_resource_list_right_paren_on_new_line = false
ij_java_resource_list_wrap = normal
ij_java_rparen_on_new_line_in_record_header = false
ij_java_space_after_closing_angle_bracket_in_type_argument = false
ij_java_space_after_colon = true
ij_java_space_after_comma = true
ij_java_space_after_comma_in_type_arguments = true
ij_java_space_after_for_semicolon = true
ij_java_space_after_quest = true
ij_java_space_after_type_cast = true
ij_java_space_before_annotation_array_initializer_left_brace = false
ij_java_space_before_annotation_parameter_list = false
ij_java_space_before_array_initializer_left_brace = true
ij_java_space_before_catch_keyword = true
ij_java_space_before_catch_left_brace = true
ij_java_space_before_catch_parentheses = true
ij_java_space_before_class_left_brace = true
ij_java_space_before_colon = true
ij_java_space_before_colon_in_foreach = true
ij_java_space_before_comma = false
ij_java_space_before_do_left_brace = true
ij_java_space_before_else_keyword = true
ij_java_space_before_else_left_brace = true
ij_java_space_before_finally_keyword = true
ij_java_space_before_finally_left_brace = true
ij_java_space_before_for_left_brace = true
ij_java_space_before_for_parentheses = true
ij_java_space_before_for_semicolon = false
ij_java_space_before_if_left_brace = true
ij_java_space_before_if_parentheses = true
ij_java_space_before_method_call_parentheses = false
ij_java_space_before_method_left_brace = true
ij_java_space_before_method_parentheses = false
ij_java_space_before_opening_angle_bracket_in_type_parameter = false
ij_java_space_before_quest = true
ij_java_space_before_switch_left_brace = true
ij_java_space_before_switch_parentheses = true
ij_java_space_before_synchronized_left_brace = true
ij_java_space_before_synchronized_parentheses = true
ij_java_space_before_try_left_brace = true
ij_java_space_before_try_parentheses = true
ij_java_space_before_type_parameter_list = false
ij_java_space_before_while_keyword = true
ij_java_space_before_while_left_brace = true
ij_java_space_before_while_parentheses = true
ij_java_space_inside_one_line_enum_braces = false
ij_java_space_within_empty_array_initializer_braces = false
ij_java_space_within_empty_method_call_parentheses = false
ij_java_space_within_empty_method_parentheses = false
ij_java_spaces_around_additive_operators = true
ij_java_spaces_around_assignment_operators = true
ij_java_spaces_around_bitwise_operators = true
ij_java_spaces_around_equality_operators = true
ij_java_spaces_around_lambda_arrow = true
ij_java_spaces_around_logical_operators = true
ij_java_spaces_around_method_ref_dbl_colon = false
ij_java_spaces_around_multiplicative_operators = true
ij_java_spaces_around_relational_operators = true
ij_java_spaces_around_shift_operators = true
ij_java_spaces_around_type_bounds_in_type_parameters = true
ij_java_spaces_around_unary_operator = false
ij_java_spaces_within_angle_brackets = false
ij_java_spaces_within_annotation_parentheses = false
ij_java_spaces_within_array_initializer_braces = false
ij_java_spaces_within_braces = false
ij_java_spaces_within_brackets = false
ij_java_spaces_within_cast_parentheses = false
ij_java_spaces_within_catch_parentheses = false
ij_java_spaces_within_for_parentheses = false
ij_java_spaces_within_if_parentheses = false
ij_java_spaces_within_method_call_parentheses = false
ij_java_spaces_within_method_parentheses = false
ij_java_spaces_within_parentheses = false
ij_java_spaces_within_switch_parentheses = false
ij_java_spaces_within_synchronized_parentheses = false
ij_java_spaces_within_try_parentheses = false
ij_java_spaces_within_while_parentheses = false
ij_java_special_else_if_treatment = true
ij_java_subclass_name_suffix = Impl
ij_java_ternary_operation_signs_on_next_line = true
ij_java_ternary_operation_wrap = normal
ij_java_test_name_suffix = Test
ij_java_throws_keyword_wrap = normal
ij_java_throws_list_wrap = normal
ij_java_use_external_annotations = false
ij_java_use_fq_class_names = false
ij_java_use_relative_indents = false
ij_java_use_single_class_imports = true
ij_java_variable_annotation_wrap = normal
ij_java_visibility = public
ij_java_while_brace_force = always
ij_java_while_on_new_line = false
ij_java_wrap_comments = false
ij_java_wrap_first_method_in_call_chain = false
ij_java_wrap_long_lines = true
[*.properties]
ij_properties_align_group_field_declarations = false
ij_properties_keep_blank_lines = false
ij_properties_key_value_delimiter = equals
ij_properties_spaces_around_key_value_delimiter = false
[.editorconfig]
ij_editorconfig_align_group_field_declarations = false
ij_editorconfig_space_after_colon = false
ij_editorconfig_space_after_comma = true
ij_editorconfig_space_before_colon = false
ij_editorconfig_space_before_comma = false
ij_editorconfig_spaces_around_assignment_operators = true
[{*.ant, *.fxml, *.jhm, *.jnlp, *.jrxml, *.jspx, *.pom, *.rng, *.tagx, *.tld, *.wsdl, *.xml, *.xsd, *.xsl, *.xslt, *.xul}]
ij_xml_align_attributes = true
ij_xml_align_text = false
ij_xml_attribute_wrap = normal
ij_xml_block_comment_at_first_column = true
ij_xml_keep_blank_lines = 2
ij_xml_keep_indents_on_empty_lines = false
ij_xml_keep_line_breaks = true
ij_xml_keep_line_breaks_in_text = true
ij_xml_keep_whitespaces = false
ij_xml_keep_whitespaces_around_cdata = preserve
ij_xml_keep_whitespaces_inside_cdata = false
ij_xml_line_comment_at_first_column = true
ij_xml_space_after_tag_name = false
ij_xml_space_around_equals_in_attribute = false
ij_xml_space_inside_empty_tag = false
ij_xml_text_wrap = normal
[{*.bash, *.sh, *.zsh}]
indent_size = 2
tab_width = 2
ij_shell_binary_ops_start_line = false
ij_shell_keep_column_alignment_padding = false
ij_shell_minify_program = false
ij_shell_redirect_followed_by_space = false
ij_shell_switch_cases_indented = false
[{*.gant, *.gradle, *.groovy, *.gy}]
ij_groovy_align_group_field_declarations = false
ij_groovy_align_multiline_array_initializer_expression = false
ij_groovy_align_multiline_assignment = false
ij_groovy_align_multiline_binary_operation = false
ij_groovy_align_multiline_chained_methods = false
ij_groovy_align_multiline_extends_list = false
ij_groovy_align_multiline_for = true
ij_groovy_align_multiline_list_or_map = true
ij_groovy_align_multiline_method_parentheses = false
ij_groovy_align_multiline_parameters = true
ij_groovy_align_multiline_parameters_in_calls = false
ij_groovy_align_multiline_resources = true
ij_groovy_align_multiline_ternary_operation = false
ij_groovy_align_multiline_throws_list = false
ij_groovy_align_named_args_in_map = true
ij_groovy_align_throws_keyword = false
ij_groovy_array_initializer_new_line_after_left_brace = false
ij_groovy_array_initializer_right_brace_on_new_line = false
ij_groovy_array_initializer_wrap = off
ij_groovy_assert_statement_wrap = off
ij_groovy_assignment_wrap = off
ij_groovy_binary_operation_wrap = off
ij_groovy_blank_lines_after_class_header = 0
ij_groovy_blank_lines_after_imports = 1
ij_groovy_blank_lines_after_package = 1
ij_groovy_blank_lines_around_class = 1
ij_groovy_blank_lines_around_field = 0
ij_groovy_blank_lines_around_field_in_interface = 0
ij_groovy_blank_lines_around_method = 1
ij_groovy_blank_lines_around_method_in_interface = 1
ij_groovy_blank_lines_before_imports = 1
ij_groovy_blank_lines_before_method_body = 0
ij_groovy_blank_lines_before_package = 0
ij_groovy_block_brace_style = end_of_line
ij_groovy_block_comment_at_first_column = true
ij_groovy_call_parameters_new_line_after_left_paren = false
ij_groovy_call_parameters_right_paren_on_new_line = false
ij_groovy_call_parameters_wrap = off
ij_groovy_catch_on_new_line = false
ij_groovy_class_annotation_wrap = split_into_lines
ij_groovy_class_brace_style = end_of_line
ij_groovy_class_count_to_use_import_on_demand = 5
ij_groovy_do_while_brace_force = never
ij_groovy_else_on_new_line = false
ij_groovy_enum_constants_wrap = off
ij_groovy_extends_keyword_wrap = off
ij_groovy_extends_list_wrap = off
ij_groovy_field_annotation_wrap = split_into_lines
ij_groovy_finally_on_new_line = false
ij_groovy_for_brace_force = never
ij_groovy_for_statement_new_line_after_left_paren = false
ij_groovy_for_statement_right_paren_on_new_line = false
ij_groovy_for_statement_wrap = off
ij_groovy_if_brace_force = never
ij_groovy_import_annotation_wrap = 2
ij_groovy_indent_case_from_switch = true
ij_groovy_indent_label_blocks = true
ij_groovy_insert_inner_class_imports = false
ij_groovy_keep_blank_lines_before_right_brace = 2
ij_groovy_keep_blank_lines_in_code = 2
ij_groovy_keep_blank_lines_in_declarations = 2
ij_groovy_keep_control_statement_in_one_line = true
ij_groovy_keep_first_column_comment = true
ij_groovy_keep_indents_on_empty_lines = false
ij_groovy_keep_line_breaks = true
ij_groovy_keep_multiple_expressions_in_one_line = false
ij_groovy_keep_simple_blocks_in_one_line = false
ij_groovy_keep_simple_classes_in_one_line = true
ij_groovy_keep_simple_lambdas_in_one_line = true
ij_groovy_keep_simple_methods_in_one_line = true
ij_groovy_label_indent_absolute = false
ij_groovy_label_indent_size = 0
ij_groovy_lambda_brace_style = end_of_line
ij_groovy_layout_static_imports_separately = true
ij_groovy_line_comment_add_space = false
ij_groovy_line_comment_at_first_column = true
ij_groovy_method_annotation_wrap = split_into_lines
ij_groovy_method_brace_style = end_of_line
ij_groovy_method_call_chain_wrap = off
ij_groovy_method_parameters_new_line_after_left_paren = false
ij_groovy_method_parameters_right_paren_on_new_line = false
ij_groovy_method_parameters_wrap = off
ij_groovy_modifier_list_wrap = false
ij_groovy_names_count_to_use_import_on_demand = 3
ij_groovy_parameter_annotation_wrap = off
ij_groovy_parentheses_expression_new_line_after_left_paren = false
ij_groovy_parentheses_expression_right_paren_on_new_line = false
ij_groovy_prefer_parameters_wrap = false
ij_groovy_resource_list_new_line_after_left_paren = false
ij_groovy_resource_list_right_paren_on_new_line = false
ij_groovy_resource_list_wrap = off
ij_groovy_space_after_assert_separator = true
ij_groovy_space_after_colon = true
ij_groovy_space_after_comma = true
ij_groovy_space_after_comma_in_type_arguments = true
ij_groovy_space_after_for_semicolon = true
ij_groovy_space_after_quest = true
ij_groovy_space_after_type_cast = true
ij_groovy_space_before_annotation_parameter_list = false
ij_groovy_space_before_array_initializer_left_brace = false
ij_groovy_space_before_assert_separator = false
ij_groovy_space_before_catch_keyword = true
ij_groovy_space_before_catch_left_brace = true
ij_groovy_space_before_catch_parentheses = true
ij_groovy_space_before_class_left_brace = true
ij_groovy_space_before_closure_left_brace = true
ij_groovy_space_before_colon = true
ij_groovy_space_before_comma = false
ij_groovy_space_before_do_left_brace = true
ij_groovy_space_before_else_keyword = true
ij_groovy_space_before_else_left_brace = true
ij_groovy_space_before_finally_keyword = true
ij_groovy_space_before_finally_left_brace = true
ij_groovy_space_before_for_left_brace = true
ij_groovy_space_before_for_parentheses = true
ij_groovy_space_before_for_semicolon = false
ij_groovy_space_before_if_left_brace = true
ij_groovy_space_before_if_parentheses = true
ij_groovy_space_before_method_call_parentheses = false
ij_groovy_space_before_method_left_brace = true
ij_groovy_space_before_method_parentheses = false
ij_groovy_space_before_quest = true
ij_groovy_space_before_switch_left_brace = true
ij_groovy_space_before_switch_parentheses = true
ij_groovy_space_before_synchronized_left_brace = true
ij_groovy_space_before_synchronized_parentheses = true
ij_groovy_space_before_try_left_brace = true
ij_groovy_space_before_try_parentheses = true
ij_groovy_space_before_while_keyword = true
ij_groovy_space_before_while_left_brace = true
ij_groovy_space_before_while_parentheses = true
ij_groovy_space_in_named_argument = true
ij_groovy_space_in_named_argument_before_colon = false
ij_groovy_space_within_empty_array_initializer_braces = false
ij_groovy_space_within_empty_method_call_parentheses = false
ij_groovy_spaces_around_additive_operators = true
ij_groovy_spaces_around_assignment_operators = true
ij_groovy_spaces_around_bitwise_operators = true
ij_groovy_spaces_around_equality_operators = true
ij_groovy_spaces_around_lambda_arrow = true
ij_groovy_spaces_around_logical_operators = true
ij_groovy_spaces_around_multiplicative_operators = true
ij_groovy_spaces_around_regex_operators = true
ij_groovy_spaces_around_relational_operators = true
ij_groovy_spaces_around_shift_operators = true
ij_groovy_spaces_within_annotation_parentheses = false
ij_groovy_spaces_within_array_initializer_braces = false
ij_groovy_spaces_within_braces = true
ij_groovy_spaces_within_brackets = false
ij_groovy_spaces_within_cast_parentheses = false
ij_groovy_spaces_within_catch_parentheses = false
ij_groovy_spaces_within_for_parentheses = false
ij_groovy_spaces_within_gstring_injection_braces = false
ij_groovy_spaces_within_if_parentheses = false
ij_groovy_spaces_within_list_or_map = false
ij_groovy_spaces_within_method_call_parentheses = false
ij_groovy_spaces_within_method_parentheses = false
ij_groovy_spaces_within_parentheses = false
ij_groovy_spaces_within_switch_parentheses = false
ij_groovy_spaces_within_synchronized_parentheses = false
ij_groovy_spaces_within_try_parentheses = false
ij_groovy_spaces_within_tuple_expression = false
ij_groovy_spaces_within_while_parentheses = false
ij_groovy_special_else_if_treatment = true
ij_groovy_ternary_operation_wrap = off
ij_groovy_throws_keyword_wrap = off
ij_groovy_throws_list_wrap = off
ij_groovy_use_flying_geese_braces = false
ij_groovy_use_fq_class_names = false
ij_groovy_use_fq_class_names_in_javadoc = true
ij_groovy_use_relative_indents = false
ij_groovy_use_single_class_imports = true
ij_groovy_variable_annotation_wrap = off
ij_groovy_while_brace_force = never
ij_groovy_while_on_new_line = false
ij_groovy_wrap_long_lines = false
[{*.har, *.json}]
indent_size = 2
ij_json_keep_blank_lines_in_code = 0
ij_json_keep_indents_on_empty_lines = false
ij_json_keep_line_breaks = true
ij_json_space_after_colon = true
ij_json_space_after_comma = true
ij_json_space_before_colon = true
ij_json_space_before_comma = false
ij_json_spaces_within_braces = false
ij_json_spaces_within_brackets = false
ij_json_wrap_long_lines = false
[{*.htm, *.html, *.sht, *.shtm, *.shtml}]
ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3
ij_html_align_attributes = true
ij_html_align_text = false
ij_html_attribute_wrap = normal
ij_html_block_comment_at_first_column = true
ij_html_do_not_align_children_of_min_lines = 0
ij_html_do_not_break_if_inline_tags = title, h1, h2, h3, h4, h5, h6, p
ij_html_do_not_indent_children_of_tags = html, body, thead, tbody, tfoot
ij_html_enforce_quotes = false
ij_html_inline_tags = a, abbr, acronym, b, basefont, bdo, big, br, cite, cite, code, dfn, em, font, i, img, input, kbd, label, q, s, samp, select, small, span, strike, strong, sub, sup, textarea, tt, u, var
ij_html_keep_blank_lines = 2
ij_html_keep_indents_on_empty_lines = false
ij_html_keep_line_breaks = true
ij_html_keep_line_breaks_in_text = true
ij_html_keep_whitespaces = false
ij_html_keep_whitespaces_inside = span, pre, textarea
ij_html_line_comment_at_first_column = true
ij_html_new_line_after_last_attribute = never
ij_html_new_line_before_first_attribute = never
ij_html_quote_style = double
ij_html_remove_new_line_before_tags = br
ij_html_space_after_tag_name = false
ij_html_space_around_equality_in_attribute = false
ij_html_space_inside_empty_tag = false
ij_html_text_wrap = normal
[{*.yaml, *.yml}]
indent_size = 2
ij_yaml_keep_indents_on_empty_lines = false
ij_yaml_keep_line_breaks = true
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
max_line_length = 100
+18
View File
@@ -0,0 +1,18 @@
name: CD
on:
release:
types:
- published
jobs:
cd:
uses: halo-sigs/reusable-workflows/.github/workflows/plugin-cd.yaml@v4
permissions:
contents: write
with:
ui-path: "ui"
# 前端产物已提交进仓库,CI 无需安装 Node/pnpm(否则 setup-node 缓存保存会失败)
skip-node-setup: true
# 首次上架审核通过前,仅上传 GitHub Release 资产,不同步应用市场
skip-appstore-release: true
+17
View File
@@ -0,0 +1,17 @@
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
ci:
uses: halo-sigs/reusable-workflows/.github/workflows/plugin-ci.yaml@v4
with:
ui-path: "ui"
# 前端产物已提交进仓库,CI 无需安装 Node/pnpm(否则 setup-node 缓存保存会失败)
skip-node-setup: true
+4 -2
View File
@@ -6,8 +6,10 @@ build/
# ---- 前端(ui ----
node_modules/
ui/node_modules/
# console 产物由 `pnpm -C ui build` 生成,勿提交
src/main/resources/console/
# console 产物提交进仓库(CI skip-node-setup),由 `pnpm -C ui build` 更新,勿手改
# ---- 内部文档(不进公开仓库) ----
AGENTS.md
# ---- IDE ----
.idea/
-39
View File
@@ -1,39 +0,0 @@
# AGENTS.md — sharelinkHalo 资源下载管理插件)
## 项目概述
Halo 2.x>=2.22,目标实例 Halo Pro 2.25.4)插件。管理文章中的资源下载链接:按资源的下载统计、邮箱验证、防附件直链、文章引用扫描。邮箱验证体系复制改造自 `~/Documents/Code/Ai/blog-comment`plugin-comment-widget fork 的 emailcode/guard 包)。
## 结构
- `src/main/java/run/halo/sharelink/`
- `model/` 自定义 Extension@GVK group `sharelink.halo.run`):DownloadResourcespec.slug 唯一索引)、DownloadRecordspec.resourceSlug 索引)、VerifiedDownloadername=SHA-256(归一化邮箱)
- `emailcode/` 验证码:Guava 内存缓存、限流、NotificationCenter 发信(REASON_TYPE `sharelink-download-verification`,模板在 `resources/extensions/notification.yaml`
- `verify/` 公开端点 `api.sharelink.halo.run/v1alpha1`email-verify/-/send|/-/check+ VerifiedEmailService(本插件 VerifiedDownloader 评论插件 VerifiedCommenter,后者运行时 Unstructured fetch,缺席自动降级)
- `download/` RouterFunction Bean`GET /download/{slug}`(自包含 HTML 页)、`GET /download/{slug}/file`(一次性 token 核销 → 记录 → 流式下载);FileStreamer 本地附件直接读盘(`halo.work-dir`/attachments + `storage.halo.run/local-relative-path` 注解),外部存储回环 HTTP(带 `X-Sharelink-Internal` 头)
- `protect/UploadProtectFilter` AdditionalWebFilterGET/HEAD `/upload/**` 命中受保护附件 → 404
- `reference/PostReferenceService` 扫描已发布文章 releaseSnapshot 内容匹配 `/download/{slug}`5min 缓存
- `console/ConsoleEndpoint` `console.api.sharelink.halo.run/v1alpha1`:资源 CRUD(body 为扁平 spec)、记录分页/删除/CSV、references 查询/刷新
- `src/main/resources/extensions/` settings.yaml、notification.yaml、role-templates.yaml(匿名放行公开 APIconsole view/manage 角色,`ui-permissions: plugin:sharelink:view/manage`
- `ui/` console 前端:Vue 3 + @halo-dev/ui-shared + ui-plugin-bundler-kitrsbuild),产物输出到 `src/main/resources/console/`(**构建前会覆盖该目录,勿手改**)。API 层 `ui/src/api/index.ts``normalizeResource()` 把后端扁平 ResourceVo 转成 Halo 风格结构
## 构建 / 部署
```bash
pnpm -C ui install && pnpm -C ui build
export JAVA_HOME=~/.gradle/jdks/jdk-21.0.12+8/Contents/Home # 本机无系统 JDK
./gradlew build -x test # build/libs/sharelink-<version>.jar
```
关键经验(踩过的坑):
1. 改代码后发布必须递增 `gradle.properties` 的 version——console 静态资源按 `?version=` 缓存,不递增浏览器会用旧包。
2. Console UI 升级插件会弹「插件已存在,是否升级?」确认框,不点确定不会真正替换 jar。
3. 插件数据存 ExtensionStoreMySQL),卸载/重装插件不丢数据;但 Halo 的插件静态资源目录在重装时才重新解压。
4. 计数在「token 核销 + 附件可流式输出」之后才写入,下载失败不计数;免验证资源按 slug+IP 内存窗口去重。
5. UI 安装有两条路:①「远程下载」需要 Halo 服务器能反向访问本机 jar 服务(本机换网/IP 变化后会失败);②「本地上传」用 webbridge 时 CDP `setFileInputFiles` 被浏览器禁用,可用兜底方案:分块 base64 经 `evaluate` 推到页面 `window.__jarB64` → JS 构造 `File` + `DataTransfer` → 对 `.uppy-Dashboard-inner` 派发合成 `dragenter/dragover/drop` 事件触发 Uppy 上传 → 再点升级确认框「确定」。
6. 下载页自包含 HTML 里若给元素自定义了 `display`(如 flex),必须补 `[hidden] { display: none !important; }`,否则 `hidden` 属性失效导致元素误显示。
## 测试
端到端验证依赖目标实例(http://192.168.3.2:8090)。公开 API 可用 curl 匿名测试:
`POST /apis/api.sharelink.halo.run/v1alpha1/downloads/-/token {"slug":"..."}``GET /download/{slug}/file?token=...`
+7
View File
@@ -4,6 +4,13 @@
📖 **[详细配置指南与使用说明(含截图)](docs/使用指南.md)**
## 安装
要求 Halo 2.22+。
1. 从 [Releases](https://github.com/shirainbown/plugin-sharelink/releases) 下载最新的 `sharelink-*.jar`
2. Halo Console → 左侧「插件」→ 右上角「安装」→ 上传 jar 并启用
## 功能
- **下载资源管理**(Console「内容 → 下载管理」):选择附件创建下载资源,生成 `/download/{slug}` 下载链接,复制后粘贴到文章即可。
Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 KiB

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 KiB

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 72 KiB

File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
.resource-form[data-v-e4a7554b]{flex-direction:column;gap:14px;display:flex}.form-item[data-v-e4a7554b]{justify-content:space-between;align-items:center;gap:12px;display:flex}.form-item--column[data-v-e4a7554b]{flex-direction:column;align-items:stretch;gap:6px}.form-label[data-v-e4a7554b]{color:#374151;font-size:14px}.required[data-v-e4a7554b]{color:#dc2626}.form-input[data-v-e4a7554b]{box-sizing:border-box;border:1px solid #d1d5db;border-radius:4px;outline:none;width:100%;padding:6px 10px;font-size:14px}.form-input[data-v-e4a7554b]:focus{border-color:#2563eb}.form-input[data-v-e4a7554b]:disabled{color:#6b7280;cursor:not-allowed;background:#f3f4f6}.form-hint[data-v-e4a7554b]{color:#9ca3af;font-size:12px}.attachment-picker[data-v-e4a7554b]{align-items:center;gap:10px;display:flex}.attachment-name[data-v-e4a7554b]{color:#374151;text-overflow:ellipsis;white-space:nowrap;max-width:380px;font-size:13px;overflow:hidden}.records-toolbar[data-v-0f8276c1]{justify-content:space-between;align-items:center;margin-bottom:12px;display:flex}.table-wrapper[data-v-0f8276c1]{overflow-x:auto}.records-table[data-v-0f8276c1]{border-collapse:collapse;width:100%;font-size:14px}.records-table th[data-v-0f8276c1],.records-table td[data-v-0f8276c1]{text-align:left;white-space:nowrap;border-bottom:1px solid #f0f0f0;padding:8px 12px}.records-table th[data-v-0f8276c1]{color:#6b7280;background:#fafafa;font-weight:500}.ua-cell[data-v-0f8276c1]{text-overflow:ellipsis;max-width:260px;overflow:hidden}.records-pagination[data-v-0f8276c1]{justify-content:flex-end;margin-top:12px;display:flex}.card-toolbar[data-v-323caff7]{justify-content:space-between;align-items:center;margin-bottom:12px;display:flex}.table-wrapper[data-v-323caff7]{overflow-x:auto}.resource-table[data-v-323caff7]{border-collapse:collapse;width:100%;font-size:14px}.resource-table th[data-v-323caff7],.resource-table td[data-v-323caff7]{text-align:left;vertical-align:middle;white-space:nowrap;border-bottom:1px solid #f0f0f0;padding:10px 12px}.resource-table th[data-v-323caff7]{color:#6b7280;background:#fafafa;font-weight:500}.link-cell[data-v-323caff7]{align-items:center;gap:8px;display:flex}.link-code[data-v-323caff7]{background:#f3f4f6;border-radius:4px;padding:2px 6px;font-size:12px}.cell-ellipsis[data-v-323caff7]{text-overflow:ellipsis;max-width:180px;overflow:hidden}.desc-line[data-v-323caff7]{text-overflow:ellipsis;white-space:nowrap;max-width:200px;overflow:hidden}.refs-row td[data-v-323caff7]{white-space:normal;background:#fafafa}.refs-empty[data-v-323caff7]{padding:4px 0}.refs-list[data-v-323caff7]{margin:0;padding:0;list-style:none}.refs-list li[data-v-323caff7]{align-items:center;gap:12px;padding:4px 0;display:flex}.refs-title[data-v-323caff7]{font-weight:500}.refs-link[data-v-323caff7]{color:#2563eb;align-items:center;gap:2px;font-size:13px;text-decoration:none;display:inline-flex}.refs-link[data-v-323caff7]:hover{text-decoration:underline}
+1
View File
@@ -0,0 +1 @@
(()=>{"use strict";var e,n,t,r,o,i={"./src/index.ts"(e,n,t){t.d(n,{default:()=>a});var r=t("@halo-dev/components"),o=window.HaloUiShared,i=t("vue"),a=(0,o.definePlugin)({components:{},routes:[{parentName:"Root",route:{path:"/download-manager",name:"DownloadManager",component:()=>t.e(155).then(t.bind(t,"./src/views/DownloadManager.vue")),meta:{title:"下载管理",permissions:["plugin:sharelink:view"],menu:{name:"下载管理",group:"content",icon:(0,i.markRaw)(r.IconArrowDownCircleLine),priority:52}}}}],extensionPoints:{}})},"@halo-dev/api-client"(e){e.exports=window.HaloApiClient},"@halo-dev/components"(e){e.exports=window.HaloComponents},vue(e){e.exports=window.Vue}},a={};function s(e){var n=a[e];if(void 0!==n)return n.exports;var t=a[e]={exports:{}};return i[e](t,t.exports,s),t.exports}if(s.m=i,s.d=(e,n,t)=>{var r=(n,t)=>{for(var r in n)s.o(n,r)&&!s.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,[t]:n[r]})};r(n,"get"),r(t,"value")},s.f={},s.e=e=>Promise.all(Object.keys(s.f).reduce((n,t)=>(s.f[t](e,n),n),[])),s.u=e=>155===e?"chunks/155.a50c3903.js":""+e+".javascript",s.miniCssF=e=>155===e?"chunks/155.c8ed3587.css":""+e+".css",s.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),e={},n="sharelink:",s.l=function(t,r,o,i){if(e[t])return void e[t].push(r);if(void 0!==o)for(var a,l,u=document.getElementsByTagName("script"),d=0;d<u.length;d++){var c=u[d];if(c.getAttribute("src")==t||c.getAttribute("data-rspack")==n+o){a=c;break}}a||(l=!0,(a=document.createElement("script")).timeout=120,s.nc&&a.setAttribute("nonce",s.nc),a.setAttribute("data-rspack",n+o),a.src=t),e[t]=[r];var p=function(n,r){a.onerror=a.onload=null,clearTimeout(f);var o=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),o&&o.forEach(function(e){return e(r)}),n)return n(r)},f=setTimeout(p.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=p.bind(null,a.onerror),a.onload=p.bind(null,a.onload),l&&document.head.appendChild(a)},s.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.p="/plugins/sharelink/assets/console/","u">typeof document){var l=function(e,n,t,r,o,i){var a=document.createElement("link");return a.rel="stylesheet",a.type="text/css",s.nc&&(a.nonce=s.nc),a.href=n,a.onerror=a.onload=function(t){if(a.onerror=a.onload=null,"load"===t.type)r();else{var i=t&&("load"===t.type?"missing":t.type),s=t&&t.target&&t.target.href||n,l=Error("Loading CSS chunk "+e+" failed.\\n("+s+")");l.code="CSS_CHUNK_LOAD_FAILED",l.type=i,l.request=s,a.parentNode&&a.parentNode.removeChild(a),o(l)}},t?t.parentNode.insertBefore(a,t.nextSibling):document.head.appendChild(a),a},u=function(e,n){for(var t=document.getElementsByTagName("link"),r=0;r<t.length;r++){var o=t[r],i=o.getAttribute("data-href")||o.getAttribute("href");if(i&&(i=i.split("?")[0]),"stylesheet"===o.rel&&(i===e||i===n))return o}for(var a=document.getElementsByTagName("style"),r=0;r<a.length;r++){var o=a[r],i=o.getAttribute("data-href");if(i===e||i===n)return o}},d={889:0};s.f.miniCss=function(e,n,t){if(d[e])n.push(d[e]);else 0!==d[e]&&({155:1})[e]&&n.push(d[e]=new Promise(function(n,r){var o=s.miniCssF(e),i=s.p+o;if(u(o,i))return n();l(e,i,null,n,r,t)}).then(function(){d[e]=0},function(n){throw delete d[e],n}))}}t={889:0},s.f.j=function(e,n){var r=s.o(t,e)?t[e]:void 0;if(0!==r)if(r)n.push(r[2]);else{var o=new Promise((n,o)=>r=t[e]=[n,o]);n.push(r[2]=o);var i=s.p+s.u(e),a=Error();s.l(i,function(n){if(s.o(t,e)&&(0!==(r=t[e])&&(t[e]=void 0),r)){var o=n&&("load"===n.type?"missing":n.type),i=n&&n.target&&n.target.src;a.message="Loading chunk "+e+" failed.\n("+o+": "+i+")",a.name="ChunkLoadError",a.type=o,a.request=i,r[1](a)}},"chunk-"+e,e)}},r=(e,n)=>{var r,o,[i,a,l]=n,u=0;if(i.some(e=>0!==t[e])){for(r in a)s.o(a,r)&&(s.m[r]=a[r]);l&&l(s)}for(e&&e(n);u<i.length;u++)o=i[u],s.o(t,o)&&t[o]&&t[o][0](),t[o]=0},(o=window.rspackChunksharelink=window.rspackChunksharelink||[]).forEach(r.bind(null,0)),o.push=r.bind(null,o.push.bind(o));var c=s("./src/index.ts");window.sharelink=c.default})();
+6 -5
View File
@@ -6,14 +6,15 @@ spec:
enabled: true
requires: ">=2.22.0"
author:
name: ssy
website: https://git.ali.songshiyu.cn/ssy
name: shirainbown
website: https://github.com/shirainbown
logo: logo.svg
homepage: https://git.ali.songshiyu.cn/ssy/sharelink
repo: https://git.ali.songshiyu.cn/ssy/sharelink
issues: https://git.ali.songshiyu.cn/ssy/sharelink/issues
homepage: https://github.com/shirainbown/plugin-sharelink
repo: https://github.com/shirainbown/plugin-sharelink
issues: https://github.com/shirainbown/plugin-sharelink/issues
displayName: "资源下载管理"
description: "管理文章中的资源下载链接:下载统计、按资源的邮箱验证、防止附件直链下载、文章引用扫描。"
version: "@version@"
configMapName: sharelink-configmap
settingName: sharelink-settings
license: