Adjust editor config (#976)
* Adjust editor config Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de> Co-authored-by: Erik Michelson <github@erik.michelson.eu>
|
@ -57,6 +57,14 @@ ij_scss_space_before_opening_brace = true
|
||||||
ij_scss_use_double_quotes = true
|
ij_scss_use_double_quotes = true
|
||||||
ij_scss_value_alignment = 0
|
ij_scss_value_alignment = 0
|
||||||
|
|
||||||
|
[.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
|
||||||
|
|
||||||
[{*.ats, *.ts, *.tsx}]
|
[{*.ats, *.ts, *.tsx}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
tab_width = 2
|
tab_width = 2
|
||||||
|
@ -64,18 +72,18 @@ ij_continuation_indent_size = 2
|
||||||
ij_typescript_align_imports = false
|
ij_typescript_align_imports = false
|
||||||
ij_typescript_align_multiline_array_initializer_expression = false
|
ij_typescript_align_multiline_array_initializer_expression = false
|
||||||
ij_typescript_align_multiline_binary_operation = false
|
ij_typescript_align_multiline_binary_operation = false
|
||||||
ij_typescript_align_multiline_chained_methods = false
|
ij_typescript_align_multiline_chained_methods = true
|
||||||
ij_typescript_align_multiline_extends_list = false
|
ij_typescript_align_multiline_extends_list = false
|
||||||
ij_typescript_align_multiline_for = true
|
ij_typescript_align_multiline_for = true
|
||||||
ij_typescript_align_multiline_parameters = true
|
ij_typescript_align_multiline_parameters = false
|
||||||
ij_typescript_align_multiline_parameters_in_calls = false
|
ij_typescript_align_multiline_parameters_in_calls = false
|
||||||
ij_typescript_align_multiline_ternary_operation = false
|
ij_typescript_align_multiline_ternary_operation = false
|
||||||
ij_typescript_align_object_properties = 0
|
ij_typescript_align_object_properties = 0
|
||||||
ij_typescript_align_union_types = false
|
ij_typescript_align_union_types = true
|
||||||
ij_typescript_align_var_statements = 0
|
ij_typescript_align_var_statements = 0
|
||||||
ij_typescript_array_initializer_new_line_after_left_brace = false
|
ij_typescript_array_initializer_new_line_after_left_brace = false
|
||||||
ij_typescript_array_initializer_right_brace_on_new_line = false
|
ij_typescript_array_initializer_right_brace_on_new_line = false
|
||||||
ij_typescript_array_initializer_wrap = off
|
ij_typescript_array_initializer_wrap = normal
|
||||||
ij_typescript_assignment_wrap = off
|
ij_typescript_assignment_wrap = off
|
||||||
ij_typescript_binary_operation_sign_on_next_line = false
|
ij_typescript_binary_operation_sign_on_next_line = false
|
||||||
ij_typescript_binary_operation_wrap = off
|
ij_typescript_binary_operation_wrap = off
|
||||||
|
@ -95,26 +103,26 @@ ij_typescript_catch_on_new_line = false
|
||||||
ij_typescript_chained_call_dot_on_new_line = true
|
ij_typescript_chained_call_dot_on_new_line = true
|
||||||
ij_typescript_class_brace_style = end_of_line
|
ij_typescript_class_brace_style = end_of_line
|
||||||
ij_typescript_comma_on_new_line = false
|
ij_typescript_comma_on_new_line = false
|
||||||
ij_typescript_do_while_brace_force = never
|
ij_typescript_do_while_brace_force = always
|
||||||
ij_typescript_else_on_new_line = false
|
ij_typescript_else_on_new_line = false
|
||||||
ij_typescript_enforce_trailing_comma = keep
|
ij_typescript_enforce_trailing_comma = remove
|
||||||
ij_typescript_extends_keyword_wrap = off
|
ij_typescript_extends_keyword_wrap = off
|
||||||
ij_typescript_extends_list_wrap = off
|
ij_typescript_extends_list_wrap = off
|
||||||
ij_typescript_field_prefix = _
|
ij_typescript_field_prefix = _
|
||||||
ij_typescript_file_name_style = relaxed
|
ij_typescript_file_name_style = relaxed
|
||||||
ij_typescript_finally_on_new_line = false
|
ij_typescript_finally_on_new_line = false
|
||||||
ij_typescript_for_brace_force = never
|
ij_typescript_for_brace_force = always
|
||||||
ij_typescript_for_statement_new_line_after_left_paren = false
|
ij_typescript_for_statement_new_line_after_left_paren = false
|
||||||
ij_typescript_for_statement_right_paren_on_new_line = false
|
ij_typescript_for_statement_right_paren_on_new_line = false
|
||||||
ij_typescript_for_statement_wrap = off
|
ij_typescript_for_statement_wrap = off
|
||||||
ij_typescript_force_quote_style = false
|
ij_typescript_force_quote_style = true
|
||||||
ij_typescript_force_semicolon_style = true
|
ij_typescript_force_semicolon_style = true
|
||||||
ij_typescript_function_expression_brace_style = end_of_line
|
ij_typescript_function_expression_brace_style = end_of_line
|
||||||
ij_typescript_if_brace_force = never
|
ij_typescript_if_brace_force = always
|
||||||
ij_typescript_import_merge_members = global
|
ij_typescript_import_merge_members = global
|
||||||
ij_typescript_import_prefer_absolute_path = global
|
ij_typescript_import_prefer_absolute_path = global
|
||||||
ij_typescript_import_sort_members = true
|
ij_typescript_import_sort_members = true
|
||||||
ij_typescript_import_sort_module_name = true
|
ij_typescript_import_sort_module_name = false
|
||||||
ij_typescript_import_use_node_resolution = true
|
ij_typescript_import_use_node_resolution = true
|
||||||
ij_typescript_imports_wrap = on_every_item
|
ij_typescript_imports_wrap = on_every_item
|
||||||
ij_typescript_indent_case_from_switch = true
|
ij_typescript_indent_case_from_switch = true
|
||||||
|
@ -122,7 +130,7 @@ ij_typescript_indent_chained_calls = true
|
||||||
ij_typescript_indent_package_children = 0
|
ij_typescript_indent_package_children = 0
|
||||||
ij_typescript_jsdoc_include_types = false
|
ij_typescript_jsdoc_include_types = false
|
||||||
ij_typescript_jsx_attribute_value = braces
|
ij_typescript_jsx_attribute_value = braces
|
||||||
ij_typescript_keep_blank_lines_in_code = 1
|
ij_typescript_keep_blank_lines_in_code = 2
|
||||||
ij_typescript_keep_first_column_comment = true
|
ij_typescript_keep_first_column_comment = true
|
||||||
ij_typescript_keep_indents_on_empty_lines = false
|
ij_typescript_keep_indents_on_empty_lines = false
|
||||||
ij_typescript_keep_line_breaks = true
|
ij_typescript_keep_line_breaks = true
|
||||||
|
@ -131,11 +139,11 @@ ij_typescript_keep_simple_methods_in_one_line = false
|
||||||
ij_typescript_line_comment_add_space = true
|
ij_typescript_line_comment_add_space = true
|
||||||
ij_typescript_line_comment_at_first_column = false
|
ij_typescript_line_comment_at_first_column = false
|
||||||
ij_typescript_method_brace_style = end_of_line
|
ij_typescript_method_brace_style = end_of_line
|
||||||
ij_typescript_method_call_chain_wrap = off
|
ij_typescript_method_call_chain_wrap = split_into_lines
|
||||||
ij_typescript_method_parameters_new_line_after_left_paren = false
|
ij_typescript_method_parameters_new_line_after_left_paren = false
|
||||||
ij_typescript_method_parameters_right_paren_on_new_line = false
|
ij_typescript_method_parameters_right_paren_on_new_line = false
|
||||||
ij_typescript_method_parameters_wrap = off
|
ij_typescript_method_parameters_wrap = off
|
||||||
ij_typescript_object_literal_wrap = on_every_item
|
ij_typescript_object_literal_wrap = off
|
||||||
ij_typescript_parentheses_expression_new_line_after_left_paren = false
|
ij_typescript_parentheses_expression_new_line_after_left_paren = false
|
||||||
ij_typescript_parentheses_expression_right_paren_on_new_line = false
|
ij_typescript_parentheses_expression_right_paren_on_new_line = false
|
||||||
ij_typescript_place_assignment_sign_on_next_line = false
|
ij_typescript_place_assignment_sign_on_next_line = false
|
||||||
|
@ -144,7 +152,7 @@ ij_typescript_prefer_explicit_types_function_expression_returns = false
|
||||||
ij_typescript_prefer_explicit_types_function_returns = false
|
ij_typescript_prefer_explicit_types_function_returns = false
|
||||||
ij_typescript_prefer_explicit_types_vars_fields = false
|
ij_typescript_prefer_explicit_types_vars_fields = false
|
||||||
ij_typescript_prefer_parameters_wrap = false
|
ij_typescript_prefer_parameters_wrap = false
|
||||||
ij_typescript_reformat_c_style_comments = false
|
ij_typescript_reformat_c_style_comments = true
|
||||||
ij_typescript_space_after_colon = true
|
ij_typescript_space_after_colon = true
|
||||||
ij_typescript_space_after_comma = true
|
ij_typescript_space_after_comma = true
|
||||||
ij_typescript_space_after_dots_in_rest_parameter = false
|
ij_typescript_space_after_dots_in_rest_parameter = false
|
||||||
|
@ -175,7 +183,7 @@ ij_typescript_space_before_if_left_brace = true
|
||||||
ij_typescript_space_before_if_parentheses = true
|
ij_typescript_space_before_if_parentheses = true
|
||||||
ij_typescript_space_before_method_call_parentheses = false
|
ij_typescript_space_before_method_call_parentheses = false
|
||||||
ij_typescript_space_before_method_left_brace = true
|
ij_typescript_space_before_method_left_brace = true
|
||||||
ij_typescript_space_before_method_parentheses = true
|
ij_typescript_space_before_method_parentheses = false
|
||||||
ij_typescript_space_before_property_colon = false
|
ij_typescript_space_before_property_colon = false
|
||||||
ij_typescript_space_before_quest = true
|
ij_typescript_space_before_quest = true
|
||||||
ij_typescript_space_before_switch_left_brace = true
|
ij_typescript_space_before_switch_left_brace = true
|
||||||
|
@ -202,7 +210,7 @@ ij_typescript_spaces_within_catch_parentheses = false
|
||||||
ij_typescript_spaces_within_for_parentheses = false
|
ij_typescript_spaces_within_for_parentheses = false
|
||||||
ij_typescript_spaces_within_if_parentheses = false
|
ij_typescript_spaces_within_if_parentheses = false
|
||||||
ij_typescript_spaces_within_imports = true
|
ij_typescript_spaces_within_imports = true
|
||||||
ij_typescript_spaces_within_interpolation_expressions = false
|
ij_typescript_spaces_within_interpolation_expressions = true
|
||||||
ij_typescript_spaces_within_method_call_parentheses = false
|
ij_typescript_spaces_within_method_call_parentheses = false
|
||||||
ij_typescript_spaces_within_method_parentheses = false
|
ij_typescript_spaces_within_method_parentheses = false
|
||||||
ij_typescript_spaces_within_object_literal_braces = true
|
ij_typescript_spaces_within_object_literal_braces = true
|
||||||
|
@ -215,15 +223,15 @@ ij_typescript_spaces_within_while_parentheses = false
|
||||||
ij_typescript_special_else_if_treatment = true
|
ij_typescript_special_else_if_treatment = true
|
||||||
ij_typescript_ternary_operation_signs_on_next_line = false
|
ij_typescript_ternary_operation_signs_on_next_line = false
|
||||||
ij_typescript_ternary_operation_wrap = off
|
ij_typescript_ternary_operation_wrap = off
|
||||||
ij_typescript_union_types_wrap = on_every_item
|
ij_typescript_union_types_wrap = normal
|
||||||
ij_typescript_use_chained_calls_group_indents = false
|
ij_typescript_use_chained_calls_group_indents = false
|
||||||
ij_typescript_use_double_quotes = false
|
ij_typescript_use_double_quotes = false
|
||||||
ij_typescript_use_explicit_js_extension = global
|
ij_typescript_use_explicit_js_extension = global
|
||||||
ij_typescript_use_path_mapping = always
|
ij_typescript_use_path_mapping = always
|
||||||
ij_typescript_use_public_modifier = false
|
ij_typescript_use_public_modifier = false
|
||||||
ij_typescript_use_semicolon_after_statement = false
|
ij_typescript_use_semicolon_after_statement = false
|
||||||
ij_typescript_var_declaration_wrap = normal
|
ij_typescript_var_declaration_wrap = on_every_item
|
||||||
ij_typescript_while_brace_force = never
|
ij_typescript_while_brace_force = always
|
||||||
ij_typescript_while_on_new_line = false
|
ij_typescript_while_on_new_line = false
|
||||||
ij_typescript_wrap_comments = false
|
ij_typescript_wrap_comments = false
|
||||||
|
|
||||||
|
@ -275,8 +283,8 @@ ij_javascript_for_brace_force = never
|
||||||
ij_javascript_for_statement_new_line_after_left_paren = false
|
ij_javascript_for_statement_new_line_after_left_paren = false
|
||||||
ij_javascript_for_statement_right_paren_on_new_line = false
|
ij_javascript_for_statement_right_paren_on_new_line = false
|
||||||
ij_javascript_for_statement_wrap = off
|
ij_javascript_for_statement_wrap = off
|
||||||
ij_javascript_force_quote_style = true
|
ij_javascript_force_quote_style = false
|
||||||
ij_javascript_force_semicolon_style = true
|
ij_javascript_force_semicolon_style = false
|
||||||
ij_javascript_function_expression_brace_style = end_of_line
|
ij_javascript_function_expression_brace_style = end_of_line
|
||||||
ij_javascript_if_brace_force = never
|
ij_javascript_if_brace_force = never
|
||||||
ij_javascript_import_merge_members = global
|
ij_javascript_import_merge_members = global
|
||||||
|
@ -289,12 +297,12 @@ ij_javascript_indent_case_from_switch = true
|
||||||
ij_javascript_indent_chained_calls = true
|
ij_javascript_indent_chained_calls = true
|
||||||
ij_javascript_indent_package_children = 0
|
ij_javascript_indent_package_children = 0
|
||||||
ij_javascript_jsx_attribute_value = braces
|
ij_javascript_jsx_attribute_value = braces
|
||||||
ij_javascript_keep_blank_lines_in_code = 1
|
ij_javascript_keep_blank_lines_in_code = 2
|
||||||
ij_javascript_keep_first_column_comment = true
|
ij_javascript_keep_first_column_comment = true
|
||||||
ij_javascript_keep_indents_on_empty_lines = false
|
ij_javascript_keep_indents_on_empty_lines = false
|
||||||
ij_javascript_keep_line_breaks = true
|
ij_javascript_keep_line_breaks = true
|
||||||
ij_javascript_keep_simple_blocks_in_one_line = true
|
ij_javascript_keep_simple_blocks_in_one_line = false
|
||||||
ij_javascript_keep_simple_methods_in_one_line = true
|
ij_javascript_keep_simple_methods_in_one_line = false
|
||||||
ij_javascript_line_comment_add_space = true
|
ij_javascript_line_comment_add_space = true
|
||||||
ij_javascript_line_comment_at_first_column = false
|
ij_javascript_line_comment_at_first_column = false
|
||||||
ij_javascript_method_brace_style = end_of_line
|
ij_javascript_method_brace_style = end_of_line
|
||||||
|
@ -337,12 +345,12 @@ ij_javascript_space_before_for_left_brace = true
|
||||||
ij_javascript_space_before_for_parentheses = true
|
ij_javascript_space_before_for_parentheses = true
|
||||||
ij_javascript_space_before_for_semicolon = false
|
ij_javascript_space_before_for_semicolon = false
|
||||||
ij_javascript_space_before_function_left_parenth = true
|
ij_javascript_space_before_function_left_parenth = true
|
||||||
ij_javascript_space_before_generator_mult = true
|
ij_javascript_space_before_generator_mult = false
|
||||||
ij_javascript_space_before_if_left_brace = true
|
ij_javascript_space_before_if_left_brace = true
|
||||||
ij_javascript_space_before_if_parentheses = true
|
ij_javascript_space_before_if_parentheses = true
|
||||||
ij_javascript_space_before_method_call_parentheses = false
|
ij_javascript_space_before_method_call_parentheses = false
|
||||||
ij_javascript_space_before_method_left_brace = true
|
ij_javascript_space_before_method_left_brace = true
|
||||||
ij_javascript_space_before_method_parentheses = true
|
ij_javascript_space_before_method_parentheses = false
|
||||||
ij_javascript_space_before_property_colon = false
|
ij_javascript_space_before_property_colon = false
|
||||||
ij_javascript_space_before_quest = true
|
ij_javascript_space_before_quest = true
|
||||||
ij_javascript_space_before_switch_left_brace = true
|
ij_javascript_space_before_switch_left_brace = true
|
||||||
|
@ -368,11 +376,11 @@ ij_javascript_spaces_within_brackets = false
|
||||||
ij_javascript_spaces_within_catch_parentheses = false
|
ij_javascript_spaces_within_catch_parentheses = false
|
||||||
ij_javascript_spaces_within_for_parentheses = false
|
ij_javascript_spaces_within_for_parentheses = false
|
||||||
ij_javascript_spaces_within_if_parentheses = false
|
ij_javascript_spaces_within_if_parentheses = false
|
||||||
ij_javascript_spaces_within_imports = true
|
ij_javascript_spaces_within_imports = false
|
||||||
ij_javascript_spaces_within_interpolation_expressions = false
|
ij_javascript_spaces_within_interpolation_expressions = false
|
||||||
ij_javascript_spaces_within_method_call_parentheses = false
|
ij_javascript_spaces_within_method_call_parentheses = false
|
||||||
ij_javascript_spaces_within_method_parentheses = false
|
ij_javascript_spaces_within_method_parentheses = false
|
||||||
ij_javascript_spaces_within_object_literal_braces = true
|
ij_javascript_spaces_within_object_literal_braces = false
|
||||||
ij_javascript_spaces_within_object_type_braces = true
|
ij_javascript_spaces_within_object_type_braces = true
|
||||||
ij_javascript_spaces_within_parentheses = false
|
ij_javascript_spaces_within_parentheses = false
|
||||||
ij_javascript_spaces_within_switch_parentheses = false
|
ij_javascript_spaces_within_switch_parentheses = false
|
||||||
|
@ -380,22 +388,22 @@ ij_javascript_spaces_within_type_assertion = false
|
||||||
ij_javascript_spaces_within_union_types = true
|
ij_javascript_spaces_within_union_types = true
|
||||||
ij_javascript_spaces_within_while_parentheses = false
|
ij_javascript_spaces_within_while_parentheses = false
|
||||||
ij_javascript_special_else_if_treatment = true
|
ij_javascript_special_else_if_treatment = true
|
||||||
ij_javascript_ternary_operation_signs_on_next_line = true
|
ij_javascript_ternary_operation_signs_on_next_line = false
|
||||||
ij_javascript_ternary_operation_wrap = off
|
ij_javascript_ternary_operation_wrap = off
|
||||||
ij_javascript_union_types_wrap = on_every_item
|
ij_javascript_union_types_wrap = on_every_item
|
||||||
ij_javascript_use_chained_calls_group_indents = false
|
ij_javascript_use_chained_calls_group_indents = false
|
||||||
ij_javascript_use_double_quotes = false
|
ij_javascript_use_double_quotes = true
|
||||||
ij_javascript_use_explicit_js_extension = global
|
ij_javascript_use_explicit_js_extension = global
|
||||||
ij_javascript_use_path_mapping = always
|
ij_javascript_use_path_mapping = always
|
||||||
ij_javascript_use_public_modifier = false
|
ij_javascript_use_public_modifier = false
|
||||||
ij_javascript_use_semicolon_after_statement = false
|
ij_javascript_use_semicolon_after_statement = true
|
||||||
ij_javascript_var_declaration_wrap = normal
|
ij_javascript_var_declaration_wrap = normal
|
||||||
ij_javascript_while_brace_force = never
|
ij_javascript_while_brace_force = never
|
||||||
ij_javascript_while_on_new_line = false
|
ij_javascript_while_on_new_line = false
|
||||||
ij_javascript_wrap_comments = false
|
ij_javascript_wrap_comments = false
|
||||||
|
|
||||||
[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
|
[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
|
||||||
indent_size = 4
|
indent_size = 2
|
||||||
ij_json_keep_blank_lines_in_code = 0
|
ij_json_keep_blank_lines_in_code = 0
|
||||||
ij_json_keep_indents_on_empty_lines = false
|
ij_json_keep_indents_on_empty_lines = false
|
||||||
ij_json_keep_line_breaks = true
|
ij_json_keep_line_breaks = true
|
||||||
|
@ -433,9 +441,30 @@ ij_html_space_after_tag_name = false
|
||||||
ij_html_space_around_equality_in_attribute = false
|
ij_html_space_around_equality_in_attribute = false
|
||||||
ij_html_space_inside_empty_tag = false
|
ij_html_space_inside_empty_tag = false
|
||||||
ij_html_text_wrap = normal
|
ij_html_text_wrap = normal
|
||||||
|
ij_html_uniform_ident = false
|
||||||
|
|
||||||
|
[{*.markdown, *.md}]
|
||||||
|
ij_markdown_force_one_space_after_blockquote_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_header_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_list_bullet = true
|
||||||
|
ij_markdown_force_one_space_between_words = true
|
||||||
|
ij_markdown_keep_indents_on_empty_lines = false
|
||||||
|
ij_markdown_max_lines_around_block_elements = 1
|
||||||
|
ij_markdown_max_lines_around_header = 1
|
||||||
|
ij_markdown_max_lines_between_paragraphs = 1
|
||||||
|
ij_markdown_min_lines_around_block_elements = 1
|
||||||
|
ij_markdown_min_lines_around_header = 1
|
||||||
|
ij_markdown_min_lines_between_paragraphs = 1
|
||||||
|
|
||||||
[{*.yaml, *.yml}]
|
[{*.yaml, *.yml}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
ij_yaml_align_values_properties = do_not_align
|
||||||
|
ij_yaml_autoinsert_sequence_marker = true
|
||||||
|
ij_yaml_block_mapping_on_new_line = false
|
||||||
|
ij_yaml_indent_sequence_value = true
|
||||||
ij_yaml_keep_indents_on_empty_lines = false
|
ij_yaml_keep_indents_on_empty_lines = false
|
||||||
ij_yaml_keep_line_breaks = true
|
ij_yaml_keep_line_breaks = true
|
||||||
|
ij_yaml_sequence_on_new_line = false
|
||||||
|
ij_yaml_space_before_colon = false
|
||||||
|
ij_yaml_spaces_within_braces = true
|
||||||
|
ij_yaml_spaces_within_brackets = true
|
||||||
|
|
|
@ -24,7 +24,9 @@ describe('Banner', () => {
|
||||||
.find('.fa-times')
|
.find('.fa-times')
|
||||||
.click()
|
.click()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
expect(localStorage.getItem('bannerTimeStamp')).to.equal(banner.timestamp)
|
expect(localStorage.getItem('bannerTimeStamp'))
|
||||||
|
.to
|
||||||
|
.equal(banner.timestamp)
|
||||||
})
|
})
|
||||||
cy.get('.alert-primary.show')
|
cy.get('.alert-primary.show')
|
||||||
.should('not.exist')
|
.should('not.exist')
|
||||||
|
|
|
@ -49,28 +49,33 @@ describe('File upload', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('via paste', () => {
|
it('via paste', () => {
|
||||||
cy.fixture('acme.png').then((image: string) => {
|
cy.fixture('acme.png')
|
||||||
|
.then((image: string) => {
|
||||||
const pasteEvent = {
|
const pasteEvent = {
|
||||||
clipboardData: {
|
clipboardData: {
|
||||||
files: [Cypress.Blob.base64StringToBlob(image, 'image/png')]
|
files: [Cypress.Blob.base64StringToBlob(image, 'image/png')]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cy.get('.CodeMirror-scroll').trigger('paste', pasteEvent)
|
cy.get('.CodeMirror-scroll')
|
||||||
|
.trigger('paste', pasteEvent)
|
||||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||||
.should('have.text', `![](${ imageUrl })`)
|
.should('have.text', `![](${ imageUrl })`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('via drag and drop', () => {
|
it('via drag and drop', () => {
|
||||||
cy.fixture('acme.png').then((image: string) => {
|
cy.fixture('acme.png')
|
||||||
|
.then((image: string) => {
|
||||||
const dropEvent = {
|
const dropEvent = {
|
||||||
dataTransfer: {
|
dataTransfer: {
|
||||||
files: [Cypress.Blob.base64StringToBlob(image, 'image/png')],
|
files: [Cypress.Blob.base64StringToBlob(image, 'image/png')],
|
||||||
effectAllowed: 'uninitialized'
|
effectAllowed: 'uninitialized'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cy.get('.CodeMirror-scroll').trigger('dragenter', dropEvent)
|
cy.get('.CodeMirror-scroll')
|
||||||
cy.get('.CodeMirror-scroll').trigger('drop', dropEvent)
|
.trigger('dragenter', dropEvent)
|
||||||
|
cy.get('.CodeMirror-scroll')
|
||||||
|
.trigger('drop', dropEvent)
|
||||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||||
.should('have.text', `![](${ imageUrl })`)
|
.should('have.text', `![](${ imageUrl })`)
|
||||||
})
|
})
|
||||||
|
@ -86,7 +91,8 @@ describe('File upload', () => {
|
||||||
})
|
})
|
||||||
cy.get('.fa-upload')
|
cy.get('.fa-upload')
|
||||||
.click()
|
.click()
|
||||||
cy.fixture('acme.png').then(() => {
|
cy.fixture('acme.png')
|
||||||
|
.then(() => {
|
||||||
cy.get('input[type=file]')
|
cy.get('input[type=file]')
|
||||||
.attachFile({ filePath: 'acme.png', mimeType: 'image/png' })
|
.attachFile({ filePath: 'acme.png', mimeType: 'image/png' })
|
||||||
})
|
})
|
||||||
|
@ -101,7 +107,8 @@ describe('File upload', () => {
|
||||||
getData: (type = 'text') => testText
|
getData: (type = 'text') => testText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cy.get('.CodeMirror-scroll').trigger('paste', pasteEvent)
|
cy.get('.CodeMirror-scroll')
|
||||||
|
.trigger('paste', pasteEvent)
|
||||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||||
.should('have.text', `${ testText }`)
|
.should('have.text', `${ testText }`)
|
||||||
})
|
})
|
||||||
|
|
|
@ -160,14 +160,15 @@ describe('Code', () => {
|
||||||
return cy.wrap(null)
|
return cy.wrap(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
cy.spy(frame.contentWindow.navigator.clipboard, 'writeText').as("copy")
|
cy.spy(frame.contentWindow.navigator.clipboard, 'writeText')
|
||||||
|
.as('copy')
|
||||||
})
|
})
|
||||||
|
|
||||||
cy.getMarkdownRenderer()
|
cy.getMarkdownRenderer()
|
||||||
.find('[data-cy="copy-code-button"]')
|
.find('[data-cy="copy-code-button"]')
|
||||||
.click()
|
.click()
|
||||||
|
|
||||||
cy.get("@copy")
|
cy.get('@copy')
|
||||||
.should('be.calledWithExactly', 'let x = 0\n')
|
.should('be.calledWithExactly', 'let x = 0\n')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,7 +17,8 @@ describe('Languages', () => {
|
||||||
cy.get('@languages')
|
cy.get('@languages')
|
||||||
.should('have.length', 28)
|
.should('have.length', 28)
|
||||||
languages.forEach(language => {
|
languages.forEach(language => {
|
||||||
cy.get('@languages').contains(language)
|
cy.get('@languages')
|
||||||
|
.contains(language)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -64,14 +64,16 @@ describe('Links Intro', () => {
|
||||||
|
|
||||||
describe('Menu Buttons logged in', () => {
|
describe('Menu Buttons logged in', () => {
|
||||||
it('New note', () => {
|
it('New note', () => {
|
||||||
cy.get('.d-inline-flex.btn-primary').click()
|
cy.get('.d-inline-flex.btn-primary')
|
||||||
|
.click()
|
||||||
cy.url()
|
cy.url()
|
||||||
.should('include', '/new')
|
.should('include', '/new')
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('User Menu', () => {
|
describe('User Menu', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.get('#dropdown-user').click()
|
cy.get('#dropdown-user')
|
||||||
|
.click()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Features', () => {
|
it('Features', () => {
|
||||||
|
|
|
@ -12,7 +12,7 @@ describe('profile page', () => {
|
||||||
}, {
|
}, {
|
||||||
body: [
|
body: [
|
||||||
{
|
{
|
||||||
label: "cypress-App",
|
label: 'cypress-App',
|
||||||
created: 1601991518
|
created: 1601991518
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,7 +21,7 @@ describe('Toolbar Buttons', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.codemirrorFill(testText)
|
cy.codemirrorFill(testText)
|
||||||
cy.get('.CodeMirror-line > span')
|
cy.get('.CodeMirror-line > span')
|
||||||
.should("exist")
|
.should('exist')
|
||||||
.should('have.text', testText)
|
.should('have.text', testText)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ describe('Toolbar Buttons', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.codemirrorFill(testLink)
|
cy.codemirrorFill(testLink)
|
||||||
cy.get('.CodeMirror-line > span')
|
cy.get('.CodeMirror-line > span')
|
||||||
.should("exist")
|
.should('exist')
|
||||||
.should('have.text', testLink)
|
.should('have.text', testLink)
|
||||||
cy.get('@codeinput')
|
cy.get('@codeinput')
|
||||||
.type('{ctrl}a')
|
.type('{ctrl}a')
|
||||||
|
|
|
@ -16,6 +16,7 @@ declare namespace Cypress {
|
||||||
}
|
}
|
||||||
|
|
||||||
Cypress.Commands.add('checkExternalLink', { prevSubject: 'element' }, ($element: JQuery, url: string) => {
|
Cypress.Commands.add('checkExternalLink', { prevSubject: 'element' }, ($element: JQuery, url: string) => {
|
||||||
cy.wrap($element).should('have.attr', 'href', url)
|
cy.wrap($element)
|
||||||
|
.should('have.attr', 'href', url)
|
||||||
.should('have.attr', 'target', '_blank')
|
.should('have.attr', 'target', '_blank')
|
||||||
})
|
})
|
||||||
|
|
|
@ -50,9 +50,9 @@ beforeEach(() => {
|
||||||
sourceCodeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
sourceCodeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
||||||
issueTrackerUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
|
issueTrackerUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
|
||||||
},
|
},
|
||||||
"iframeCommunication": {
|
'iframeCommunication': {
|
||||||
"editorOrigin": "http://127.0.0.1:3001",
|
'editorOrigin': 'http://127.0.0.1:3001',
|
||||||
"rendererOrigin": "http://127.0.0.1:3001"
|
'rendererOrigin': 'http://127.0.0.1:3001'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,6 +12,7 @@ declare namespace Cypress {
|
||||||
* @example cy.get(input).fill('content')
|
* @example cy.get(input).fill('content')
|
||||||
*/
|
*/
|
||||||
fill(value: string): Chainable<Element>
|
fill(value: string): Chainable<Element>
|
||||||
|
|
||||||
codemirrorFill(value: string): Chainable<Element>
|
codemirrorFill(value: string): Chainable<Element>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +26,8 @@ Cypress.Commands.add('fill', {
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add('codemirrorFill', (content: string) => {
|
Cypress.Commands.add('codemirrorFill', (content: string) => {
|
||||||
const line = content.split("\n").find(value => value !== '');
|
const line = content.split('\n')
|
||||||
|
.find(value => value !== '')
|
||||||
cy.get('.CodeMirror')
|
cy.get('.CodeMirror')
|
||||||
.click()
|
.click()
|
||||||
.get('textarea')
|
.get('textarea')
|
||||||
|
|
|
@ -16,6 +16,8 @@ declare namespace Cypress {
|
||||||
}
|
}
|
||||||
|
|
||||||
Cypress.Commands.add('logout', () => {
|
Cypress.Commands.add('logout', () => {
|
||||||
cy.get('#dropdown-user').click()
|
cy.get('#dropdown-user')
|
||||||
cy.get('.fa-sign-out').click()
|
.click()
|
||||||
|
cy.get('.fa-sign-out')
|
||||||
|
.click()
|
||||||
})
|
})
|
||||||
|
|
|
@ -18,16 +18,16 @@ Cypress.Commands.add('visitTestEditor', (query?: string) => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.intercept(`/api/v2/notes/${ testNoteId }-get`, {
|
cy.intercept(`/api/v2/notes/${ testNoteId }-get`, {
|
||||||
"id": "ABC123",
|
'id': 'ABC123',
|
||||||
"alias": "banner",
|
'alias': 'banner',
|
||||||
"lastChange": {
|
'lastChange': {
|
||||||
"userId": "test",
|
'userId': 'test',
|
||||||
"timestamp": 1600033920
|
'timestamp': 1600033920
|
||||||
},
|
},
|
||||||
"viewCount": 0,
|
'viewCount': 0,
|
||||||
"createTime": 1600033920,
|
'createTime': 1600033920,
|
||||||
"content": "",
|
'content': '',
|
||||||
"authorship": [],
|
'authorship': [],
|
||||||
"preVersionTwoNote": true
|
'preVersionTwoNote': true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,8 +3,15 @@
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"baseUrl": "../node_modules",
|
"baseUrl": "../node_modules",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"lib": ["es6", "dom"],
|
"lib": [
|
||||||
"types": ["cypress" ,"cypress-commands", "cypress-file-upload"]
|
"es6",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"cypress",
|
||||||
|
"cypress-commands",
|
||||||
|
"cypress-file-upload"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"**/*.ts"
|
"**/*.ts"
|
||||||
|
|
|
@ -6,32 +6,72 @@
|
||||||
|
|
||||||
.loader {
|
.loader {
|
||||||
@keyframes animation-roll {
|
@keyframes animation-roll {
|
||||||
0% { transform: translateX(calc(-100vw / 2 - 100%)) rotateZ(0deg); }
|
0% {
|
||||||
100% { transform: translateX(calc(100vw / 2 + 100%)) rotateZ(720deg); }
|
transform: translateX(calc(-100vw / 2 - 100%)) rotateZ(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(calc(100vw / 2 + 100%)) rotateZ(720deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes animation-jump {
|
@keyframes animation-jump {
|
||||||
0% { transform: scale(1,1) translateY(0); }
|
0% {
|
||||||
10% { transform: scale(1.1,.9) translateY(0); }
|
transform: scale(1, 1) translateY(0);
|
||||||
30% { transform: scale(.9,1.1) translateY(-100px); }
|
}
|
||||||
50% { transform: scale(1.05,.95) translateY(0); }
|
10% {
|
||||||
57% { transform: scale(1,1) translateY(-7px); }
|
transform: scale(1.1, .9) translateY(0);
|
||||||
64% { transform: scale(1,1) translateY(0); }
|
}
|
||||||
100% { transform: scale(1,1) translateY(0); }
|
30% {
|
||||||
|
transform: scale(.9, 1.1) translateY(-100px);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.05, .95) translateY(0);
|
||||||
|
}
|
||||||
|
57% {
|
||||||
|
transform: scale(1, 1) translateY(-7px);
|
||||||
|
}
|
||||||
|
64% {
|
||||||
|
transform: scale(1, 1) translateY(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1, 1) translateY(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes animation-shake {
|
@keyframes animation-shake {
|
||||||
0% { transform: translate(1px, 1px) rotate(0deg); }
|
0% {
|
||||||
10% { transform: translate(-1px, -2px) rotate(-1deg); }
|
transform: translate(1px, 1px) rotate(0deg);
|
||||||
20% { transform: translate(-3px, 0px) rotate(1deg); }
|
}
|
||||||
30% { transform: translate(3px, 2px) rotate(0deg); }
|
10% {
|
||||||
40% { transform: translate(1px, -1px) rotate(1deg); }
|
transform: translate(-1px, -2px) rotate(-1deg);
|
||||||
50% { transform: translate(-1px, 2px) rotate(-1deg); }
|
}
|
||||||
60% { transform: translate(-3px, 1px) rotate(0deg); }
|
20% {
|
||||||
70% { transform: translate(3px, 1px) rotate(-1deg); }
|
transform: translate(-3px, 0px) rotate(1deg);
|
||||||
80% { transform: translate(-1px, -1px) rotate(1deg); }
|
}
|
||||||
90% { transform: translate(1px, 2px) rotate(0deg); }
|
30% {
|
||||||
100% { transform: translate(1px, -2px) rotate(-1deg); }
|
transform: translate(3px, 2px) rotate(0deg);
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
transform: translate(1px, -1px) rotate(1deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translate(-1px, 2px) rotate(-1deg);
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
transform: translate(-3px, 1px) rotate(0deg);
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
transform: translate(3px, 1px) rotate(-1deg);
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: translate(-1px, -1px) rotate(1deg);
|
||||||
|
}
|
||||||
|
90% {
|
||||||
|
transform: translate(1px, 2px) rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(1px, -2px) rotate(-1deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.animation-roll {
|
.animation-roll {
|
||||||
|
|
|
@ -30,7 +30,8 @@ export const ApplicationLoader: React.FC = ({ children }) => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
for (const task of initTasks) {
|
for (const task of initTasks) {
|
||||||
runTask(task.task).catch((reason: Error) => {
|
runTask(task.task)
|
||||||
|
.catch((reason: Error) => {
|
||||||
console.error(reason)
|
console.error(reason)
|
||||||
setFailedTitle(task.name)
|
setFailedTitle(task.name)
|
||||||
})
|
})
|
||||||
|
|
60
src/components/common/cache/cache.test.ts
vendored
|
@ -16,68 +16,88 @@ describe('Test caching functionality', () => {
|
||||||
it('initialize with right lifetime, no entry limit', () => {
|
it('initialize with right lifetime, no entry limit', () => {
|
||||||
const lifetime = 1000
|
const lifetime = 1000
|
||||||
const lifetimedCache = new Cache<string, string>(lifetime)
|
const lifetimedCache = new Cache<string, string>(lifetime)
|
||||||
expect(lifetimedCache.entryLifetime).toEqual(lifetime)
|
expect(lifetimedCache.entryLifetime)
|
||||||
expect(lifetimedCache.maxEntries).toEqual(0)
|
.toEqual(lifetime)
|
||||||
|
expect(lifetimedCache.maxEntries)
|
||||||
|
.toEqual(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('initialize with right lifetime, given entry limit', () => {
|
it('initialize with right lifetime, given entry limit', () => {
|
||||||
const lifetime = 1000
|
const lifetime = 1000
|
||||||
const maxEntries = 10
|
const maxEntries = 10
|
||||||
const limitedCache = new Cache<string, string>(lifetime, maxEntries)
|
const limitedCache = new Cache<string, string>(lifetime, maxEntries)
|
||||||
expect(limitedCache.entryLifetime).toEqual(lifetime)
|
expect(limitedCache.entryLifetime)
|
||||||
expect(limitedCache.maxEntries).toEqual(maxEntries)
|
.toEqual(lifetime)
|
||||||
|
expect(limitedCache.maxEntries)
|
||||||
|
.toEqual(maxEntries)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('entry exists after inserting', () => {
|
it('entry exists after inserting', () => {
|
||||||
testCache.put('test', 123)
|
testCache.put('test', 123)
|
||||||
expect(testCache.has('test')).toBe(true)
|
expect(testCache.has('test'))
|
||||||
|
.toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('entry does not exist prior inserting', () => {
|
it('entry does not exist prior inserting', () => {
|
||||||
expect(testCache.has('test')).toBe(false)
|
expect(testCache.has('test'))
|
||||||
|
.toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('entry does expire', () => {
|
it('entry does expire', () => {
|
||||||
const shortLivingCache = new Cache<string, number>(2)
|
const shortLivingCache = new Cache<string, number>(2)
|
||||||
shortLivingCache.put('test', 123)
|
shortLivingCache.put('test', 123)
|
||||||
expect(shortLivingCache.has('test')).toBe(true)
|
expect(shortLivingCache.has('test'))
|
||||||
|
.toBe(true)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
expect(shortLivingCache.has('test')).toBe(false)
|
expect(shortLivingCache.has('test'))
|
||||||
|
.toBe(false)
|
||||||
}, 2000)
|
}, 2000)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('entry value does not change', () => {
|
it('entry value does not change', () => {
|
||||||
const testValue = Date.now()
|
const testValue = Date.now()
|
||||||
testCache.put('test', testValue)
|
testCache.put('test', testValue)
|
||||||
expect(testCache.get('test')).toEqual(testValue)
|
expect(testCache.get('test'))
|
||||||
|
.toEqual(testValue)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('error is thrown on non-existent entry', () => {
|
it('error is thrown on non-existent entry', () => {
|
||||||
const accessNonExistentEntry = () => {
|
const accessNonExistentEntry = () => {
|
||||||
testCache.get('test')
|
testCache.get('test')
|
||||||
}
|
}
|
||||||
expect(accessNonExistentEntry).toThrow(Error)
|
expect(accessNonExistentEntry)
|
||||||
|
.toThrow(Error)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('newer item replaces older item', () => {
|
it('newer item replaces older item', () => {
|
||||||
testCache.put('test', 123)
|
testCache.put('test', 123)
|
||||||
testCache.put('test', 456)
|
testCache.put('test', 456)
|
||||||
expect(testCache.get('test')).toEqual(456)
|
expect(testCache.get('test'))
|
||||||
|
.toEqual(456)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('entry limit is respected', () => {
|
it('entry limit is respected', () => {
|
||||||
const limitedCache = new Cache<string, number>(1000, 2)
|
const limitedCache = new Cache<string, number>(1000, 2)
|
||||||
limitedCache.put('first', 1)
|
limitedCache.put('first', 1)
|
||||||
expect(limitedCache.has('first')).toBe(true)
|
expect(limitedCache.has('first'))
|
||||||
expect(limitedCache.has('second')).toBe(false)
|
.toBe(true)
|
||||||
expect(limitedCache.has('third')).toBe(false)
|
expect(limitedCache.has('second'))
|
||||||
|
.toBe(false)
|
||||||
|
expect(limitedCache.has('third'))
|
||||||
|
.toBe(false)
|
||||||
limitedCache.put('second', 2)
|
limitedCache.put('second', 2)
|
||||||
expect(limitedCache.has('first')).toBe(true)
|
expect(limitedCache.has('first'))
|
||||||
expect(limitedCache.has('second')).toBe(true)
|
.toBe(true)
|
||||||
expect(limitedCache.has('third')).toBe(false)
|
expect(limitedCache.has('second'))
|
||||||
|
.toBe(true)
|
||||||
|
expect(limitedCache.has('third'))
|
||||||
|
.toBe(false)
|
||||||
limitedCache.put('third', 3)
|
limitedCache.put('third', 3)
|
||||||
expect(limitedCache.has('first')).toBe(false)
|
expect(limitedCache.has('first'))
|
||||||
expect(limitedCache.has('second')).toBe(true)
|
.toBe(false)
|
||||||
expect(limitedCache.has('third')).toBe(true)
|
expect(limitedCache.has('second'))
|
||||||
|
.toBe(true)
|
||||||
|
expect(limitedCache.has('third'))
|
||||||
|
.toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
6
src/components/common/cache/cache.ts
vendored
|
@ -10,10 +10,9 @@ export interface CacheEntry<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Cache<K, V> {
|
export class Cache<K, V> {
|
||||||
private store = new Map<K, CacheEntry<V>>()
|
|
||||||
|
|
||||||
readonly entryLifetime: number
|
readonly entryLifetime: number
|
||||||
readonly maxEntries: number
|
readonly maxEntries: number
|
||||||
|
private store = new Map<K, CacheEntry<V>>()
|
||||||
|
|
||||||
constructor(lifetime: number, maxEntries = 0) {
|
constructor(lifetime: number, maxEntries = 0) {
|
||||||
if (lifetime < 0) {
|
if (lifetime < 0) {
|
||||||
|
@ -41,7 +40,8 @@ export class Cache<K, V> {
|
||||||
|
|
||||||
put(key: K, value: V): void {
|
put(key: K, value: V): void {
|
||||||
if (this.maxEntries > 0 && this.store.size === this.maxEntries) {
|
if (this.maxEntries > 0 && this.store.size === this.maxEntries) {
|
||||||
this.store.delete(this.store.keys().next().value)
|
this.store.delete(this.store.keys()
|
||||||
|
.next().value)
|
||||||
}
|
}
|
||||||
this.store.set(key, {
|
this.store.set(key, {
|
||||||
entryCreated: Date.now(),
|
entryCreated: Date.now(),
|
||||||
|
|
|
@ -22,14 +22,19 @@ export const CopyOverlay: React.FC<CopyOverlayProps> = ({ content, clickComponen
|
||||||
const [tooltipId] = useState<string>(() => uuid())
|
const [tooltipId] = useState<string>(() => uuid())
|
||||||
|
|
||||||
const copyToClipboard = useCallback((content: string) => {
|
const copyToClipboard = useCallback((content: string) => {
|
||||||
navigator.clipboard.writeText(content).then(() => {
|
navigator.clipboard.writeText(content)
|
||||||
|
.then(() => {
|
||||||
setError(false)
|
setError(false)
|
||||||
}).catch(() => {
|
})
|
||||||
|
.catch(() => {
|
||||||
setError(true)
|
setError(true)
|
||||||
console.error("couldn't copy")
|
console.error('couldn\'t copy')
|
||||||
}).finally(() => {
|
})
|
||||||
|
.finally(() => {
|
||||||
setShowCopiedTooltip(true)
|
setShowCopiedTooltip(true)
|
||||||
setTimeout(() => { setShowCopiedTooltip(false) }, 2000)
|
setTimeout(() => {
|
||||||
|
setShowCopiedTooltip(false)
|
||||||
|
}, 2000)
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ export interface CopyToClipboardButtonProps {
|
||||||
content: string
|
content: string
|
||||||
size?: 'sm' | 'lg'
|
size?: 'sm' | 'lg'
|
||||||
variant?: Variant
|
variant?: Variant
|
||||||
"data-cy"?: string
|
'data-cy'?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({
|
export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({
|
||||||
|
@ -30,7 +30,7 @@ export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Button ref={ button } size={ size } variant={ variant } title={ t('renderer.highlightCode.copyCode') }
|
<Button ref={ button } size={ size } variant={ variant } title={ t('renderer.highlightCode.copyCode') }
|
||||||
data-cy={props["data-cy"]}>
|
data-cy={ props['data-cy'] }>
|
||||||
<ForkAwesomeIcon icon='files-o'/>
|
<ForkAwesomeIcon icon='files-o'/>
|
||||||
</Button>
|
</Button>
|
||||||
<CopyOverlay content={ content } clickComponent={ button }/>
|
<CopyOverlay content={ content } clickComponent={ button }/>
|
||||||
|
|
|
@ -25,7 +25,8 @@ export const CopyableField: React.FC<CopyableFieldProps> = ({ content, nativeSha
|
||||||
navigator.share({
|
navigator.share({
|
||||||
text: content,
|
text: content,
|
||||||
url: url
|
url: url
|
||||||
}).catch(err => {
|
})
|
||||||
|
.catch(err => {
|
||||||
console.error('Native sharing failed: ', err)
|
console.error('Native sharing failed: ', err)
|
||||||
})
|
})
|
||||||
}, [content, url])
|
}, [content, url])
|
||||||
|
|
120
src/components/common/fork-awesome/types.d.ts
vendored
|
@ -1 +1,29 @@
|
||||||
<svg clip-rule="evenodd" fill-rule="evenodd" height="1486" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 1486 1486" width="1486" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(200 -420 420 200 660 1340)" gradientUnits="userSpaceOnUse" x1="0" x2="1" y1="0" y2="0"><stop offset="0" stop-color="#fcca8c"/><stop offset="1" stop-color="#dca055"/></linearGradient><g fill-rule="nonzero" transform="translate(-142.756 -142.754)"><path d="m1553.66 961.083 75.25-75.258-75.25-75.246 56.61-90.096-90.1-56.616 35.15-100.446-100.44-35.142 11.91-105.746-105.74-11.912-11.92-105.75-105.74 11.912-35.15-100.445-100.43 35.145-56.63-90.1-90.107 56.617-75.242-75.246-75.242 75.25-90.104-56.612-56.612 90.096-100.442-35.15-35.142 100.441-105.75-11.916-11.912 105.741-105.742 11.913 11.917 105.741-100.454 35.15 35.145 100.438-90.1 56.612 56.621 90.117-75.258 75.25 75.25 75.258-56.613 90.107 90.1 56.61-35.145 100.44 100.45 35.15-11.913 105.73 105.742 11.92 11.912 105.74 105.75-11.91 35.142 100.43 100.437-35.13 56.617 90.1 90.096-56.62 75.25 74.55 75.25-74.53 90.099 56.61 56.61-90.11 100.45 35.15 35.14-100.44 105.75 11.91 11.91-105.75 105.75-11.91-11.92-105.74 100.45-35.15-35.15-100.45 90.1-56.61z" fill="#b51f08"/><path d="m1401.3 1004.78c0-145.437-117.9-263.341-263.34-263.341-72.24 0-137.68 29.112-185.252 76.225l-.033-.034-67.096 67.1-54.862-54.862c-48.267-55.067-119.071-89.879-198.042-89.879-145.442 0-263.342 117.904-263.342 263.341 0 76 32.23 144.43 83.721 192.49l432.779 432.55 423.217-423.49c52.88-49.77 92.25-120 92.25-200.1" fill="#fcca8c"/><path d="m885.579 884.73-54.862-54.862c-48.267-55.067-119.071-89.879-198.042-89.879-145.442 0-263.342 117.904-263.342 263.341 0 76 32.23 144.43 83.721 192.49l432.779 432.55" fill="url(#a)"/></g><path d="m743.077 1485.616-.254-743.64" fill="none"/><g fill-rule="nonzero" transform="translate(-142.756 -142.754)"><path d="m961.011 1553.59c-19.279-19.35-45.917-31.31-75.325-31.31-29.417 0-56.046 11.96-75.329 31.31.308 41.34 33.908 74.76 75.325 74.76 41.416 0 75.02-33.43 75.329-74.76" fill="#010007"/><path d="m797.707 1098.22c0 31.8-25.767 57.57-57.571 57.57-31.787 0-57.558-25.77-57.558-57.57s25.771-57.57 57.558-57.57c31.804 0 57.571 25.77 57.571 57.57" fill="#010007"/><path d="m777.962 1089.59c0 8.82-7.146 15.94-15.95 15.94-8.808 0-15.958-7.12-15.958-15.94 0-8.81 7.15-15.96 15.958-15.96 8.804 0 15.95 7.15 15.95 15.96" fill="#fffffa"/><path d="m1089.65 1098.22c0 31.8-25.77 57.57-57.57 57.57-31.79 0-57.567-25.77-57.567-57.57s25.777-57.57 57.567-57.57c31.8 0 57.57 25.77 57.57 57.57" fill="#010007"/><path d="m1069.9 1089.59c0 8.82-7.15 15.94-15.95 15.94-8.81 0-15.96-7.12-15.96-15.94 0-8.81 7.15-15.96 15.96-15.96 8.8 0 15.95 7.15 15.95 15.96" fill="#fffffa"/></g></svg>
|
<svg clip-rule="evenodd" fill-rule="evenodd" height="1486" stroke-linejoin="round" stroke-miterlimit="2"
|
||||||
|
viewBox="0 0 1486 1486" width="1486" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<linearGradient id="a" gradientTransform="matrix(200 -420 420 200 660 1340)" gradientUnits="userSpaceOnUse" x1="0"
|
||||||
|
x2="1" y1="0" y2="0">
|
||||||
|
<stop offset="0" stop-color="#fcca8c"/>
|
||||||
|
<stop offset="1" stop-color="#dca055"/>
|
||||||
|
</linearGradient>
|
||||||
|
<g fill-rule="nonzero" transform="translate(-142.756 -142.754)">
|
||||||
|
<path d="m1553.66 961.083 75.25-75.258-75.25-75.246 56.61-90.096-90.1-56.616 35.15-100.446-100.44-35.142 11.91-105.746-105.74-11.912-11.92-105.75-105.74 11.912-35.15-100.445-100.43 35.145-56.63-90.1-90.107 56.617-75.242-75.246-75.242 75.25-90.104-56.612-56.612 90.096-100.442-35.15-35.142 100.441-105.75-11.916-11.912 105.741-105.742 11.913 11.917 105.741-100.454 35.15 35.145 100.438-90.1 56.612 56.621 90.117-75.258 75.25 75.25 75.258-56.613 90.107 90.1 56.61-35.145 100.44 100.45 35.15-11.913 105.73 105.742 11.92 11.912 105.74 105.75-11.91 35.142 100.43 100.437-35.13 56.617 90.1 90.096-56.62 75.25 74.55 75.25-74.53 90.099 56.61 56.61-90.11 100.45 35.15 35.14-100.44 105.75 11.91 11.91-105.75 105.75-11.91-11.92-105.74 100.45-35.15-35.15-100.45 90.1-56.61z"
|
||||||
|
fill="#b51f08"/>
|
||||||
|
<path d="m1401.3 1004.78c0-145.437-117.9-263.341-263.34-263.341-72.24 0-137.68 29.112-185.252 76.225l-.033-.034-67.096 67.1-54.862-54.862c-48.267-55.067-119.071-89.879-198.042-89.879-145.442 0-263.342 117.904-263.342 263.341 0 76 32.23 144.43 83.721 192.49l432.779 432.55 423.217-423.49c52.88-49.77 92.25-120 92.25-200.1"
|
||||||
|
fill="#fcca8c"/>
|
||||||
|
<path d="m885.579 884.73-54.862-54.862c-48.267-55.067-119.071-89.879-198.042-89.879-145.442 0-263.342 117.904-263.342 263.341 0 76 32.23 144.43 83.721 192.49l432.779 432.55"
|
||||||
|
fill="url(#a)"/>
|
||||||
|
</g>
|
||||||
|
<path d="m743.077 1485.616-.254-743.64" fill="none"/>
|
||||||
|
<g fill-rule="nonzero" transform="translate(-142.756 -142.754)">
|
||||||
|
<path d="m961.011 1553.59c-19.279-19.35-45.917-31.31-75.325-31.31-29.417 0-56.046 11.96-75.329 31.31.308 41.34 33.908 74.76 75.325 74.76 41.416 0 75.02-33.43 75.329-74.76"
|
||||||
|
fill="#010007"/>
|
||||||
|
<path d="m797.707 1098.22c0 31.8-25.767 57.57-57.571 57.57-31.787 0-57.558-25.77-57.558-57.57s25.771-57.57 57.558-57.57c31.804 0 57.571 25.77 57.571 57.57"
|
||||||
|
fill="#010007"/>
|
||||||
|
<path d="m777.962 1089.59c0 8.82-7.146 15.94-15.95 15.94-8.808 0-15.958-7.12-15.958-15.94 0-8.81 7.15-15.96 15.958-15.96 8.804 0 15.95 7.15 15.95 15.96"
|
||||||
|
fill="#fffffa"/>
|
||||||
|
<path d="m1089.65 1098.22c0 31.8-25.77 57.57-57.57 57.57-31.79 0-57.567-25.77-57.567-57.57s25.777-57.57 57.567-57.57c31.8 0 57.57 25.77 57.57 57.57"
|
||||||
|
fill="#010007"/>
|
||||||
|
<path d="m1069.9 1089.59c0 8.82-7.15 15.94-15.95 15.94-8.81 0-15.96-7.12-15.96-15.94 0-8.81 7.15-15.96 15.96-15.96 8.8 0 15.95 7.15 15.95 15.96"
|
||||||
|
fill="#fffffa"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.8 KiB |
|
@ -3,7 +3,7 @@ SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import hljs from 'highlight.js/lib/core';
|
import hljs from 'highlight.js/lib/core'
|
||||||
import abnf from 'highlight.js/lib/languages/abnf'
|
import abnf from 'highlight.js/lib/languages/abnf'
|
||||||
import accesslog from 'highlight.js/lib/languages/accesslog'
|
import accesslog from 'highlight.js/lib/languages/accesslog'
|
||||||
import actionscript from 'highlight.js/lib/languages/actionscript'
|
import actionscript from 'highlight.js/lib/languages/actionscript'
|
||||||
|
@ -194,196 +194,196 @@ import xl from 'highlight.js/lib/languages/xl'
|
||||||
import xquery from 'highlight.js/lib/languages/xquery'
|
import xquery from 'highlight.js/lib/languages/xquery'
|
||||||
import zephir from 'highlight.js/lib/languages/zephir'
|
import zephir from 'highlight.js/lib/languages/zephir'
|
||||||
|
|
||||||
hljs.registerLanguage('abnf', abnf);
|
hljs.registerLanguage('abnf', abnf)
|
||||||
hljs.registerLanguage('accesslog', accesslog);
|
hljs.registerLanguage('accesslog', accesslog)
|
||||||
hljs.registerLanguage('actionscript', actionscript);
|
hljs.registerLanguage('actionscript', actionscript)
|
||||||
hljs.registerLanguage('ada', ada);
|
hljs.registerLanguage('ada', ada)
|
||||||
hljs.registerLanguage('angelscript', angelscript);
|
hljs.registerLanguage('angelscript', angelscript)
|
||||||
hljs.registerLanguage('apache', apache);
|
hljs.registerLanguage('apache', apache)
|
||||||
hljs.registerLanguage('applescript', applescript);
|
hljs.registerLanguage('applescript', applescript)
|
||||||
hljs.registerLanguage('arcade', arcade);
|
hljs.registerLanguage('arcade', arcade)
|
||||||
hljs.registerLanguage('arduino', arduino);
|
hljs.registerLanguage('arduino', arduino)
|
||||||
hljs.registerLanguage('armasm', armasm);
|
hljs.registerLanguage('armasm', armasm)
|
||||||
hljs.registerLanguage('xml', xml);
|
hljs.registerLanguage('xml', xml)
|
||||||
hljs.registerLanguage('asciidoc', asciidoc);
|
hljs.registerLanguage('asciidoc', asciidoc)
|
||||||
hljs.registerLanguage('aspectj', aspectj);
|
hljs.registerLanguage('aspectj', aspectj)
|
||||||
hljs.registerLanguage('autohotkey', autohotkey);
|
hljs.registerLanguage('autohotkey', autohotkey)
|
||||||
hljs.registerLanguage('autoit', autoit);
|
hljs.registerLanguage('autoit', autoit)
|
||||||
hljs.registerLanguage('avrasm', avrasm);
|
hljs.registerLanguage('avrasm', avrasm)
|
||||||
hljs.registerLanguage('awk', awk);
|
hljs.registerLanguage('awk', awk)
|
||||||
hljs.registerLanguage('axapta', axapta);
|
hljs.registerLanguage('axapta', axapta)
|
||||||
hljs.registerLanguage('bash', bash);
|
hljs.registerLanguage('bash', bash)
|
||||||
hljs.registerLanguage('basic', basic);
|
hljs.registerLanguage('basic', basic)
|
||||||
hljs.registerLanguage('bnf', bnf);
|
hljs.registerLanguage('bnf', bnf)
|
||||||
hljs.registerLanguage('brainfuck', brainfuck);
|
hljs.registerLanguage('brainfuck', brainfuck)
|
||||||
hljs.registerLanguage('c-like', c_like);
|
hljs.registerLanguage('c-like', c_like)
|
||||||
hljs.registerLanguage('c', c);
|
hljs.registerLanguage('c', c)
|
||||||
hljs.registerLanguage('cal', cal);
|
hljs.registerLanguage('cal', cal)
|
||||||
hljs.registerLanguage('capnproto', capnproto);
|
hljs.registerLanguage('capnproto', capnproto)
|
||||||
hljs.registerLanguage('ceylon', ceylon);
|
hljs.registerLanguage('ceylon', ceylon)
|
||||||
hljs.registerLanguage('clean', clean);
|
hljs.registerLanguage('clean', clean)
|
||||||
hljs.registerLanguage('clojure', clojure);
|
hljs.registerLanguage('clojure', clojure)
|
||||||
hljs.registerLanguage('clojure-repl', clojure_repl);
|
hljs.registerLanguage('clojure-repl', clojure_repl)
|
||||||
hljs.registerLanguage('cmake', cmake);
|
hljs.registerLanguage('cmake', cmake)
|
||||||
hljs.registerLanguage('coffeescript', coffeescript);
|
hljs.registerLanguage('coffeescript', coffeescript)
|
||||||
hljs.registerLanguage('coq', coq);
|
hljs.registerLanguage('coq', coq)
|
||||||
hljs.registerLanguage('cos', cos);
|
hljs.registerLanguage('cos', cos)
|
||||||
hljs.registerLanguage('cpp', cpp);
|
hljs.registerLanguage('cpp', cpp)
|
||||||
hljs.registerLanguage('crmsh', crmsh);
|
hljs.registerLanguage('crmsh', crmsh)
|
||||||
hljs.registerLanguage('crystal', crystal);
|
hljs.registerLanguage('crystal', crystal)
|
||||||
hljs.registerLanguage('csharp', csharp);
|
hljs.registerLanguage('csharp', csharp)
|
||||||
hljs.registerLanguage('csp', csp);
|
hljs.registerLanguage('csp', csp)
|
||||||
hljs.registerLanguage('css', css);
|
hljs.registerLanguage('css', css)
|
||||||
hljs.registerLanguage('d', d);
|
hljs.registerLanguage('d', d)
|
||||||
hljs.registerLanguage('markdown', markdown);
|
hljs.registerLanguage('markdown', markdown)
|
||||||
hljs.registerLanguage('dart', dart);
|
hljs.registerLanguage('dart', dart)
|
||||||
hljs.registerLanguage('delphi', delphi);
|
hljs.registerLanguage('delphi', delphi)
|
||||||
hljs.registerLanguage('diff', diff);
|
hljs.registerLanguage('diff', diff)
|
||||||
hljs.registerLanguage('django', django);
|
hljs.registerLanguage('django', django)
|
||||||
hljs.registerLanguage('dns', dns);
|
hljs.registerLanguage('dns', dns)
|
||||||
hljs.registerLanguage('dockerfile', dockerfile);
|
hljs.registerLanguage('dockerfile', dockerfile)
|
||||||
hljs.registerLanguage('dos', dos);
|
hljs.registerLanguage('dos', dos)
|
||||||
hljs.registerLanguage('dsconfig', dsconfig);
|
hljs.registerLanguage('dsconfig', dsconfig)
|
||||||
hljs.registerLanguage('dts', dts);
|
hljs.registerLanguage('dts', dts)
|
||||||
hljs.registerLanguage('dust', dust);
|
hljs.registerLanguage('dust', dust)
|
||||||
hljs.registerLanguage('ebnf', ebnf);
|
hljs.registerLanguage('ebnf', ebnf)
|
||||||
hljs.registerLanguage('elixir', elixir);
|
hljs.registerLanguage('elixir', elixir)
|
||||||
hljs.registerLanguage('elm', elm);
|
hljs.registerLanguage('elm', elm)
|
||||||
hljs.registerLanguage('ruby', ruby);
|
hljs.registerLanguage('ruby', ruby)
|
||||||
hljs.registerLanguage('erb', erb);
|
hljs.registerLanguage('erb', erb)
|
||||||
hljs.registerLanguage('erlang-repl', erlang_repl);
|
hljs.registerLanguage('erlang-repl', erlang_repl)
|
||||||
hljs.registerLanguage('erlang', erlang);
|
hljs.registerLanguage('erlang', erlang)
|
||||||
hljs.registerLanguage('excel', excel);
|
hljs.registerLanguage('excel', excel)
|
||||||
hljs.registerLanguage('fix', fix);
|
hljs.registerLanguage('fix', fix)
|
||||||
hljs.registerLanguage('flix', flix);
|
hljs.registerLanguage('flix', flix)
|
||||||
hljs.registerLanguage('fortran', fortran);
|
hljs.registerLanguage('fortran', fortran)
|
||||||
hljs.registerLanguage('fsharp', fsharp);
|
hljs.registerLanguage('fsharp', fsharp)
|
||||||
hljs.registerLanguage('gams', gams);
|
hljs.registerLanguage('gams', gams)
|
||||||
hljs.registerLanguage('gauss', gauss);
|
hljs.registerLanguage('gauss', gauss)
|
||||||
hljs.registerLanguage('gcode', gcode);
|
hljs.registerLanguage('gcode', gcode)
|
||||||
hljs.registerLanguage('gherkin', gherkin);
|
hljs.registerLanguage('gherkin', gherkin)
|
||||||
hljs.registerLanguage('glsl', glsl);
|
hljs.registerLanguage('glsl', glsl)
|
||||||
hljs.registerLanguage('gml', gml);
|
hljs.registerLanguage('gml', gml)
|
||||||
hljs.registerLanguage('go', go);
|
hljs.registerLanguage('go', go)
|
||||||
hljs.registerLanguage('golo', golo);
|
hljs.registerLanguage('golo', golo)
|
||||||
hljs.registerLanguage('gradle', gradle);
|
hljs.registerLanguage('gradle', gradle)
|
||||||
hljs.registerLanguage('groovy', groovy);
|
hljs.registerLanguage('groovy', groovy)
|
||||||
hljs.registerLanguage('haml', haml);
|
hljs.registerLanguage('haml', haml)
|
||||||
hljs.registerLanguage('handlebars', handlebars);
|
hljs.registerLanguage('handlebars', handlebars)
|
||||||
hljs.registerLanguage('haskell', haskell);
|
hljs.registerLanguage('haskell', haskell)
|
||||||
hljs.registerLanguage('haxe', haxe);
|
hljs.registerLanguage('haxe', haxe)
|
||||||
hljs.registerLanguage('hsp', hsp);
|
hljs.registerLanguage('hsp', hsp)
|
||||||
hljs.registerLanguage('html', xml);
|
hljs.registerLanguage('html', xml)
|
||||||
hljs.registerLanguage('htmlbars', htmlbars);
|
hljs.registerLanguage('htmlbars', htmlbars)
|
||||||
hljs.registerLanguage('http', http);
|
hljs.registerLanguage('http', http)
|
||||||
hljs.registerLanguage('hy', hy);
|
hljs.registerLanguage('hy', hy)
|
||||||
hljs.registerLanguage('inform7', inform7);
|
hljs.registerLanguage('inform7', inform7)
|
||||||
hljs.registerLanguage('ini', ini);
|
hljs.registerLanguage('ini', ini)
|
||||||
hljs.registerLanguage('irpf90', irpf90);
|
hljs.registerLanguage('irpf90', irpf90)
|
||||||
hljs.registerLanguage('isbl', isbl);
|
hljs.registerLanguage('isbl', isbl)
|
||||||
hljs.registerLanguage('java', java);
|
hljs.registerLanguage('java', java)
|
||||||
hljs.registerLanguage('javascript', javascript);
|
hljs.registerLanguage('javascript', javascript)
|
||||||
hljs.registerLanguage('jboss-cli', jboss_cli);
|
hljs.registerLanguage('jboss-cli', jboss_cli)
|
||||||
hljs.registerLanguage('js', javascript);
|
hljs.registerLanguage('js', javascript)
|
||||||
hljs.registerLanguage('json', json);
|
hljs.registerLanguage('json', json)
|
||||||
hljs.registerLanguage('julia', julia);
|
hljs.registerLanguage('julia', julia)
|
||||||
hljs.registerLanguage('julia-repl', julia_repl);
|
hljs.registerLanguage('julia-repl', julia_repl)
|
||||||
hljs.registerLanguage('kotlin', kotlin);
|
hljs.registerLanguage('kotlin', kotlin)
|
||||||
hljs.registerLanguage('lasso', lasso);
|
hljs.registerLanguage('lasso', lasso)
|
||||||
hljs.registerLanguage('latex', latex);
|
hljs.registerLanguage('latex', latex)
|
||||||
hljs.registerLanguage('ldif', ldif);
|
hljs.registerLanguage('ldif', ldif)
|
||||||
hljs.registerLanguage('leaf', leaf);
|
hljs.registerLanguage('leaf', leaf)
|
||||||
hljs.registerLanguage('less', less);
|
hljs.registerLanguage('less', less)
|
||||||
hljs.registerLanguage('lisp', lisp);
|
hljs.registerLanguage('lisp', lisp)
|
||||||
hljs.registerLanguage('livecodeserver', livecodeserver);
|
hljs.registerLanguage('livecodeserver', livecodeserver)
|
||||||
hljs.registerLanguage('livescript', livescript);
|
hljs.registerLanguage('livescript', livescript)
|
||||||
hljs.registerLanguage('llvm', llvm);
|
hljs.registerLanguage('llvm', llvm)
|
||||||
hljs.registerLanguage('lsl', lsl);
|
hljs.registerLanguage('lsl', lsl)
|
||||||
hljs.registerLanguage('lua', lua);
|
hljs.registerLanguage('lua', lua)
|
||||||
hljs.registerLanguage('makefile', makefile);
|
hljs.registerLanguage('makefile', makefile)
|
||||||
hljs.registerLanguage('mathematica', mathematica);
|
hljs.registerLanguage('mathematica', mathematica)
|
||||||
hljs.registerLanguage('matlab', matlab);
|
hljs.registerLanguage('matlab', matlab)
|
||||||
hljs.registerLanguage('maxima', maxima);
|
hljs.registerLanguage('maxima', maxima)
|
||||||
hljs.registerLanguage('mel', mel);
|
hljs.registerLanguage('mel', mel)
|
||||||
hljs.registerLanguage('mercury', mercury);
|
hljs.registerLanguage('mercury', mercury)
|
||||||
hljs.registerLanguage('mipsasm', mipsasm);
|
hljs.registerLanguage('mipsasm', mipsasm)
|
||||||
hljs.registerLanguage('mizar', mizar);
|
hljs.registerLanguage('mizar', mizar)
|
||||||
hljs.registerLanguage('perl', perl);
|
hljs.registerLanguage('perl', perl)
|
||||||
hljs.registerLanguage('mojolicious', mojolicious);
|
hljs.registerLanguage('mojolicious', mojolicious)
|
||||||
hljs.registerLanguage('monkey', monkey);
|
hljs.registerLanguage('monkey', monkey)
|
||||||
hljs.registerLanguage('moonscript', moonscript);
|
hljs.registerLanguage('moonscript', moonscript)
|
||||||
hljs.registerLanguage('n1ql', n1ql);
|
hljs.registerLanguage('n1ql', n1ql)
|
||||||
hljs.registerLanguage('nginx', nginx);
|
hljs.registerLanguage('nginx', nginx)
|
||||||
hljs.registerLanguage('nim', nim);
|
hljs.registerLanguage('nim', nim)
|
||||||
hljs.registerLanguage('nix', nix);
|
hljs.registerLanguage('nix', nix)
|
||||||
hljs.registerLanguage('node-repl', node_repl);
|
hljs.registerLanguage('node-repl', node_repl)
|
||||||
hljs.registerLanguage('nsis', nsis);
|
hljs.registerLanguage('nsis', nsis)
|
||||||
hljs.registerLanguage('objectivec', objectivec);
|
hljs.registerLanguage('objectivec', objectivec)
|
||||||
hljs.registerLanguage('ocaml', ocaml);
|
hljs.registerLanguage('ocaml', ocaml)
|
||||||
hljs.registerLanguage('openscad', openscad);
|
hljs.registerLanguage('openscad', openscad)
|
||||||
hljs.registerLanguage('oxygene', oxygene);
|
hljs.registerLanguage('oxygene', oxygene)
|
||||||
hljs.registerLanguage('parser3', parser3);
|
hljs.registerLanguage('parser3', parser3)
|
||||||
hljs.registerLanguage('pf', pf);
|
hljs.registerLanguage('pf', pf)
|
||||||
hljs.registerLanguage('pgsql', pgsql);
|
hljs.registerLanguage('pgsql', pgsql)
|
||||||
hljs.registerLanguage('php', php);
|
hljs.registerLanguage('php', php)
|
||||||
hljs.registerLanguage('php-template', php_template);
|
hljs.registerLanguage('php-template', php_template)
|
||||||
hljs.registerLanguage('plaintext', plaintext);
|
hljs.registerLanguage('plaintext', plaintext)
|
||||||
hljs.registerLanguage('pony', pony);
|
hljs.registerLanguage('pony', pony)
|
||||||
hljs.registerLanguage('powershell', powershell);
|
hljs.registerLanguage('powershell', powershell)
|
||||||
hljs.registerLanguage('processing', processing);
|
hljs.registerLanguage('processing', processing)
|
||||||
hljs.registerLanguage('profile', profile);
|
hljs.registerLanguage('profile', profile)
|
||||||
hljs.registerLanguage('prolog', prolog);
|
hljs.registerLanguage('prolog', prolog)
|
||||||
hljs.registerLanguage('properties', properties);
|
hljs.registerLanguage('properties', properties)
|
||||||
hljs.registerLanguage('protobuf', protobuf);
|
hljs.registerLanguage('protobuf', protobuf)
|
||||||
hljs.registerLanguage('puppet', puppet);
|
hljs.registerLanguage('puppet', puppet)
|
||||||
hljs.registerLanguage('purebasic', purebasic);
|
hljs.registerLanguage('purebasic', purebasic)
|
||||||
hljs.registerLanguage('python', python);
|
hljs.registerLanguage('python', python)
|
||||||
hljs.registerLanguage('python-repl', python_repl);
|
hljs.registerLanguage('python-repl', python_repl)
|
||||||
hljs.registerLanguage('q', q);
|
hljs.registerLanguage('q', q)
|
||||||
hljs.registerLanguage('qml', qml);
|
hljs.registerLanguage('qml', qml)
|
||||||
hljs.registerLanguage('r', r);
|
hljs.registerLanguage('r', r)
|
||||||
hljs.registerLanguage('reasonml', reasonml);
|
hljs.registerLanguage('reasonml', reasonml)
|
||||||
hljs.registerLanguage('rib', rib);
|
hljs.registerLanguage('rib', rib)
|
||||||
hljs.registerLanguage('roboconf', roboconf);
|
hljs.registerLanguage('roboconf', roboconf)
|
||||||
hljs.registerLanguage('routeros', routeros);
|
hljs.registerLanguage('routeros', routeros)
|
||||||
hljs.registerLanguage('rsl', rsl);
|
hljs.registerLanguage('rsl', rsl)
|
||||||
hljs.registerLanguage('ruleslanguage', ruleslanguage);
|
hljs.registerLanguage('ruleslanguage', ruleslanguage)
|
||||||
hljs.registerLanguage('rust', rust);
|
hljs.registerLanguage('rust', rust)
|
||||||
hljs.registerLanguage('sas', sas);
|
hljs.registerLanguage('sas', sas)
|
||||||
hljs.registerLanguage('scala', scala);
|
hljs.registerLanguage('scala', scala)
|
||||||
hljs.registerLanguage('scheme', scheme);
|
hljs.registerLanguage('scheme', scheme)
|
||||||
hljs.registerLanguage('scilab', scilab);
|
hljs.registerLanguage('scilab', scilab)
|
||||||
hljs.registerLanguage('scss', scss);
|
hljs.registerLanguage('scss', scss)
|
||||||
hljs.registerLanguage('shell', shell);
|
hljs.registerLanguage('shell', shell)
|
||||||
hljs.registerLanguage('smali', smali);
|
hljs.registerLanguage('smali', smali)
|
||||||
hljs.registerLanguage('smalltalk', smalltalk);
|
hljs.registerLanguage('smalltalk', smalltalk)
|
||||||
hljs.registerLanguage('sml', sml);
|
hljs.registerLanguage('sml', sml)
|
||||||
hljs.registerLanguage('sqf', sqf);
|
hljs.registerLanguage('sqf', sqf)
|
||||||
hljs.registerLanguage('sql', sql);
|
hljs.registerLanguage('sql', sql)
|
||||||
hljs.registerLanguage('stan', stan);
|
hljs.registerLanguage('stan', stan)
|
||||||
hljs.registerLanguage('stata', stata);
|
hljs.registerLanguage('stata', stata)
|
||||||
hljs.registerLanguage('step21', step21);
|
hljs.registerLanguage('step21', step21)
|
||||||
hljs.registerLanguage('stylus', stylus);
|
hljs.registerLanguage('stylus', stylus)
|
||||||
hljs.registerLanguage('subunit', subunit);
|
hljs.registerLanguage('subunit', subunit)
|
||||||
hljs.registerLanguage('swift', swift);
|
hljs.registerLanguage('swift', swift)
|
||||||
hljs.registerLanguage('taggerscript', taggerscript);
|
hljs.registerLanguage('taggerscript', taggerscript)
|
||||||
hljs.registerLanguage('yaml', yaml);
|
hljs.registerLanguage('yaml', yaml)
|
||||||
hljs.registerLanguage('tap', tap);
|
hljs.registerLanguage('tap', tap)
|
||||||
hljs.registerLanguage('tcl', tcl);
|
hljs.registerLanguage('tcl', tcl)
|
||||||
hljs.registerLanguage('thrift', thrift);
|
hljs.registerLanguage('thrift', thrift)
|
||||||
hljs.registerLanguage('tp', tp);
|
hljs.registerLanguage('tp', tp)
|
||||||
hljs.registerLanguage('twig', twig);
|
hljs.registerLanguage('twig', twig)
|
||||||
hljs.registerLanguage('typescript', typescript);
|
hljs.registerLanguage('typescript', typescript)
|
||||||
hljs.registerLanguage('vala', vala);
|
hljs.registerLanguage('vala', vala)
|
||||||
hljs.registerLanguage('vbnet', vbnet);
|
hljs.registerLanguage('vbnet', vbnet)
|
||||||
hljs.registerLanguage('vbscript', vbscript);
|
hljs.registerLanguage('vbscript', vbscript)
|
||||||
hljs.registerLanguage('vbscript-html', vbscript_html);
|
hljs.registerLanguage('vbscript-html', vbscript_html)
|
||||||
hljs.registerLanguage('verilog', verilog);
|
hljs.registerLanguage('verilog', verilog)
|
||||||
hljs.registerLanguage('vhdl', vhdl);
|
hljs.registerLanguage('vhdl', vhdl)
|
||||||
hljs.registerLanguage('vim', vim);
|
hljs.registerLanguage('vim', vim)
|
||||||
hljs.registerLanguage('x86asm', x86asm);
|
hljs.registerLanguage('x86asm', x86asm)
|
||||||
hljs.registerLanguage('xl', xl);
|
hljs.registerLanguage('xl', xl)
|
||||||
hljs.registerLanguage('xquery', xquery);
|
hljs.registerLanguage('xquery', xquery)
|
||||||
hljs.registerLanguage('zephir', zephir);
|
hljs.registerLanguage('zephir', zephir)
|
||||||
|
|
||||||
export default hljs;
|
export default hljs
|
||||||
|
|
|
@ -19,7 +19,8 @@ export interface IconButtonProps extends ButtonProps {
|
||||||
|
|
||||||
export const IconButton: React.FC<IconButtonProps> = ({ icon, children, border = false, ...props }) => {
|
export const IconButton: React.FC<IconButtonProps> = ({ icon, children, border = false, ...props }) => {
|
||||||
return (
|
return (
|
||||||
<Button {...props} className={`btn-icon p-0 d-inline-flex align-items-stretch ${border ? 'with-border' : ''}`}>
|
<Button { ...props }
|
||||||
|
className={ `btn-icon p-0 d-inline-flex align-items-stretch ${ border ? 'with-border' : '' }` }>
|
||||||
<span className="icon-part d-flex align-items-center">
|
<span className="icon-part d-flex align-items-center">
|
||||||
<ForkAwesomeIcon icon={ icon } className={ 'icon' }/>
|
<ForkAwesomeIcon icon={ icon } className={ 'icon' }/>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -26,7 +26,8 @@ export const CommonModal: React.FC<CommonModalProps> = ({ show, onHide, titleI18
|
||||||
useTranslation()
|
useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal data-cy={'limitReachedModal'} show={show} onHide={onHide} animation={true} dialogClassName={`text-dark ${additionalClasses ?? ''}`} size={size}>
|
<Modal data-cy={ 'limitReachedModal' } show={ show } onHide={ onHide } animation={ true }
|
||||||
|
dialogClassName={ `text-dark ${ additionalClasses ?? '' }` } size={ size }>
|
||||||
<Modal.Header closeButton={ !!closeButton }>
|
<Modal.Header closeButton={ !!closeButton }>
|
||||||
<Modal.Title>
|
<Modal.Title>
|
||||||
<ShowIf condition={ !!icon }>
|
<ShowIf condition={ !!icon }>
|
||||||
|
|
|
@ -5,5 +5,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const createNumberRangeArray = (length: number): number[] => {
|
export const createNumberRangeArray = (length: number): number[] => {
|
||||||
return Array.from(Array(length).keys())
|
return Array.from(Array(length)
|
||||||
|
.keys())
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,12 +53,15 @@ export const PagerPagination: React.FC<PaginationProps> = ({ numberOfPageButtons
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
|
|
||||||
const paginationItemsBefore = Array.from(new Array(correctedPageIndex - correctedLowerPageIndex)).map((k, index) => {
|
const paginationItemsBefore = Array.from(new Array(correctedPageIndex - correctedLowerPageIndex))
|
||||||
|
.map((k, index) => {
|
||||||
const itemIndex = correctedLowerPageIndex + index
|
const itemIndex = correctedLowerPageIndex + index
|
||||||
return <PagerItem key={itemIndex} index={itemIndex} onClick={setPageIndex}/>
|
return <PagerItem key={ itemIndex } index={ itemIndex }
|
||||||
|
onClick={ setPageIndex }/>
|
||||||
})
|
})
|
||||||
|
|
||||||
const paginationItemsAfter = Array.from(new Array(correctedUpperPageIndex - correctedPageIndex)).map((k, index) => {
|
const paginationItemsAfter = Array.from(new Array(correctedUpperPageIndex - correctedPageIndex))
|
||||||
|
.map((k, index) => {
|
||||||
const itemIndex = correctedPageIndex + index + 1
|
const itemIndex = correctedPageIndex + index + 1
|
||||||
return <PagerItem key={ itemIndex } index={ itemIndex } onClick={ setPageIndex }/>
|
return <PagerItem key={ itemIndex } index={ itemIndex } onClick={ setPageIndex }/>
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,7 +22,8 @@ export const Pager: React.FC<PagerPageProps> = ({ children, numberOfElementsPerP
|
||||||
|
|
||||||
return <Fragment>
|
return <Fragment>
|
||||||
{
|
{
|
||||||
React.Children.toArray(children).filter((value, index) => {
|
React.Children.toArray(children)
|
||||||
|
.filter((value, index) => {
|
||||||
const pageOfElement = Math.floor((index) / numberOfElementsPerPage)
|
const pageOfElement = Math.floor((index) / numberOfElementsPerPage)
|
||||||
return (pageOfElement === correctedPageIndex)
|
return (pageOfElement === correctedPageIndex)
|
||||||
})
|
})
|
||||||
|
|
|
@ -56,7 +56,9 @@ export const DocumentInfobar: React.FC<DocumentInfobarProps> = ({
|
||||||
<span className={ 'ml-auto' }>
|
<span className={ 'ml-auto' }>
|
||||||
{ viewCount } <Trans i18nKey={ 'views.readOnly.viewCount' }/>
|
{ viewCount } <Trans i18nKey={ 'views.readOnly.viewCount' }/>
|
||||||
<ShowIf condition={ editable }>
|
<ShowIf condition={ editable }>
|
||||||
<InternalLink text={''} href={`/n/${noteId}`} icon={'pencil'} className={'text-primary text-decoration-none mx-1'} title={t('views.readOnly.editNote')}/>
|
<InternalLink text={ '' } href={ `/n/${ noteId }` } icon={ 'pencil' }
|
||||||
|
className={ 'text-primary text-decoration-none mx-1' }
|
||||||
|
title={ t('views.readOnly.editNote') }/>
|
||||||
</ShowIf>
|
</ShowIf>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -55,7 +55,7 @@ export const DocumentReadOnlyPage: React.FC = () => {
|
||||||
noteId={ id }
|
noteId={ id }
|
||||||
viewCount={ noteDetails.viewCount }
|
viewCount={ noteDetails.viewCount }
|
||||||
/>
|
/>
|
||||||
<RenderIframe extraClasses={"flex-fill"}
|
<RenderIframe extraClasses={ 'flex-fill' }
|
||||||
markdownContent={ markdownContent }
|
markdownContent={ markdownContent }
|
||||||
onFirstHeadingChange={ onFirstHeadingChange }
|
onFirstHeadingChange={ onFirstHeadingChange }
|
||||||
onFrontmatterChange={ onFrontmatterChange }/>
|
onFrontmatterChange={ onFrontmatterChange }/>
|
||||||
|
|
|
@ -46,7 +46,8 @@ export const AppBar: React.FC<AppBarProps> = ({ mode }) => {
|
||||||
</ShowIf>
|
</ShowIf>
|
||||||
<DarkModeButton/>
|
<DarkModeButton/>
|
||||||
<Link to={ `/p/${ id }` } target='_blank'>
|
<Link to={ `/p/${ id }` } target='_blank'>
|
||||||
<Button title={t('editor.documentBar.slideMode')} className="ml-2 text-secondary" size="sm" variant="outline-light">
|
<Button title={ t('editor.documentBar.slideMode') } className="ml-2 text-secondary" size="sm"
|
||||||
|
variant="outline-light">
|
||||||
<ForkAwesomeIcon icon="television"/>
|
<ForkAwesomeIcon icon="television"/>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
@ -43,22 +43,26 @@ export const HelpButton: React.FC = () => {
|
||||||
<Modal show={ show } onHide={ () => setShow(false) } animation={ true } className='text-dark' size='lg'>
|
<Modal show={ show } onHide={ () => setShow(false) } animation={ true } className='text-dark' size='lg'>
|
||||||
<Modal.Header closeButton>
|
<Modal.Header closeButton>
|
||||||
<Modal.Title>
|
<Modal.Title>
|
||||||
<ForkAwesomeIcon icon='question-circle'/> <Trans i18nKey={'editor.documentBar.help'}/> – <Trans i18nKey={`editor.help.${tab}`}/>
|
<ForkAwesomeIcon icon='question-circle'/> <Trans i18nKey={ 'editor.documentBar.help' }/> – <Trans
|
||||||
|
i18nKey={ `editor.help.${ tab }` }/>
|
||||||
</Modal.Title>
|
</Modal.Title>
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
<nav className='nav nav-tabs'>
|
<nav className='nav nav-tabs'>
|
||||||
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Cheatsheet ? 'active' : ''}`}
|
<Button variant={ 'light' }
|
||||||
|
className={ `nav-link nav-item ${ tab === HelpTabStatus.Cheatsheet ? 'active' : '' }` }
|
||||||
onClick={ () => setTab(HelpTabStatus.Cheatsheet) }
|
onClick={ () => setTab(HelpTabStatus.Cheatsheet) }
|
||||||
>
|
>
|
||||||
<Trans i18nKey={ 'editor.help.cheatsheet.title' }/>
|
<Trans i18nKey={ 'editor.help.cheatsheet.title' }/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Shortcuts ? 'active' : ''}`}
|
<Button variant={ 'light' }
|
||||||
|
className={ `nav-link nav-item ${ tab === HelpTabStatus.Shortcuts ? 'active' : '' }` }
|
||||||
onClick={ () => setTab(HelpTabStatus.Shortcuts) }
|
onClick={ () => setTab(HelpTabStatus.Shortcuts) }
|
||||||
>
|
>
|
||||||
<Trans i18nKey={ 'editor.help.shortcuts.title' }/>
|
<Trans i18nKey={ 'editor.help.shortcuts.title' }/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Links ? 'active' : ''}`}
|
<Button variant={ 'light' }
|
||||||
|
className={ `nav-link nav-item ${ tab === HelpTabStatus.Links ? 'active' : '' }` }
|
||||||
onClick={ () => setTab(HelpTabStatus.Links) }
|
onClick={ () => setTab(HelpTabStatus.Links) }
|
||||||
>
|
>
|
||||||
<Trans i18nKey={ 'editor.help.links.title' }/>
|
<Trans i18nKey={ 'editor.help.links.title' }/>
|
||||||
|
|
|
@ -30,12 +30,14 @@ export const Shortcut: React.FC = () => {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Row className={ 'justify-content-center pt-4' }>
|
<Row className={ 'justify-content-center pt-4' }>
|
||||||
{Object.keys(shortcutMap).map(category => {
|
{ Object.keys(shortcutMap)
|
||||||
|
.map(category => {
|
||||||
return (
|
return (
|
||||||
<Card key={ category } className={ 'm-2 w-50' }>
|
<Card key={ category } className={ 'm-2 w-50' }>
|
||||||
<Card.Header>{ category }</Card.Header>
|
<Card.Header>{ category }</Card.Header>
|
||||||
<ListGroup variant="flush">
|
<ListGroup variant="flush">
|
||||||
{Object.entries(shortcutMap[category]).map(([functionName, shortcuts]) => {
|
{ Object.entries(shortcutMap[category])
|
||||||
|
.map(([functionName, shortcuts]) => {
|
||||||
return (
|
return (
|
||||||
<ListGroup.Item key={ functionName } className={ 'd-flex justify-content-between' }>
|
<ListGroup.Item key={ functionName } className={ 'd-flex justify-content-between' }>
|
||||||
<span><Trans i18nKey={ functionName }/></span>
|
<span><Trans i18nKey={ functionName }/></span>
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="512"
|
width="512"
|
||||||
height="512"
|
height="512"
|
||||||
viewBox="0 0 135.46666 135.46666"
|
viewBox="0 0 135.46666 135.46666"
|
||||||
|
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 9.4 KiB |
|
@ -9,6 +9,7 @@
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
svg g {
|
svg g {
|
||||||
@import "../../../../style/variables.light";
|
@import "../../../../style/variables.light";
|
||||||
|
|
|
@ -31,7 +31,8 @@ export const DocumentInfoModal: React.FC<DocumentInfoModalProps> = ({show, onHid
|
||||||
<DocumentInfoTimeLine
|
<DocumentInfoTimeLine
|
||||||
size={ '2x' }
|
size={ '2x' }
|
||||||
mode={ DocumentInfoLineWithTimeMode.CREATED }
|
mode={ DocumentInfoLineWithTimeMode.CREATED }
|
||||||
time={DateTime.local().minus({ days: 11 })}
|
time={ DateTime.local()
|
||||||
|
.minus({ days: 11 }) }
|
||||||
userName={ 'Tilman' }
|
userName={ 'Tilman' }
|
||||||
profileImageSrc={ '/img/avatar.png' }/>
|
profileImageSrc={ '/img/avatar.png' }/>
|
||||||
</ListGroup.Item>
|
</ListGroup.Item>
|
||||||
|
@ -39,7 +40,8 @@ export const DocumentInfoModal: React.FC<DocumentInfoModalProps> = ({show, onHid
|
||||||
<DocumentInfoTimeLine
|
<DocumentInfoTimeLine
|
||||||
size={ '2x' }
|
size={ '2x' }
|
||||||
mode={ DocumentInfoLineWithTimeMode.EDITED }
|
mode={ DocumentInfoLineWithTimeMode.EDITED }
|
||||||
time={DateTime.local().minus({ minutes: 3 })}
|
time={ DateTime.local()
|
||||||
|
.minus({ minutes: 3 }) }
|
||||||
userName={ 'Philip' }
|
userName={ 'Philip' }
|
||||||
profileImageSrc={ '/img/avatar.png' }/>
|
profileImageSrc={ '/img/avatar.png' }/>
|
||||||
</ListGroup.Item>
|
</ListGroup.Item>
|
||||||
|
@ -60,5 +62,5 @@ export const DocumentInfoModal: React.FC<DocumentInfoModalProps> = ({show, onHid
|
||||||
</ListGroup>
|
</ListGroup>
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
</CommonModal>
|
</CommonModal>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,8 @@ export const DocumentInfoTimeLine: React.FC<DocumentInfoLineWithTimeProps> = ({
|
||||||
return (
|
return (
|
||||||
<DocumentInfoLine icon={ icon } size={ size }>
|
<DocumentInfoLine icon={ icon } size={ size }>
|
||||||
<Trans i18nKey={ i18nKey }>
|
<Trans i18nKey={ i18nKey }>
|
||||||
<UserAvatar photo={profileImageSrc} additionalClasses={'font-style-normal bold font-weight-bold'} name={userName} size={size ? 'lg' : undefined}/>
|
<UserAvatar photo={ profileImageSrc } additionalClasses={ 'font-style-normal bold font-weight-bold' }
|
||||||
|
name={ userName } size={ size ? 'lg' : undefined }/>
|
||||||
<TimeFromNow time={ time }/>
|
<TimeFromNow time={ time }/>
|
||||||
</Trans>
|
</Trans>
|
||||||
</DocumentInfoLine>
|
</DocumentInfoLine>
|
||||||
|
|
|
@ -14,6 +14,7 @@ export interface TimeFromNowProps {
|
||||||
|
|
||||||
export const TimeFromNow: React.FC<TimeFromNowProps> = ({ time }) => {
|
export const TimeFromNow: React.FC<TimeFromNowProps> = ({ time }) => {
|
||||||
return (
|
return (
|
||||||
<time className={'mx-1'} title={time.toFormat('DDDD T')} dateTime={time.toString()}>{time.toRelative()}</time>
|
<time className={ 'mx-1' } title={ time.toFormat('DDDD T') }
|
||||||
|
dateTime={ time.toString() }>{ time.toRelative() }</time>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,22 +69,26 @@ export const PermissionModal: React.FC<PermissionsModalProps> = ({ show, onHide
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// set owner
|
// set owner
|
||||||
getUserById(permissionsApiResponse.owner).then(response => {
|
getUserById(permissionsApiResponse.owner)
|
||||||
|
.then(response => {
|
||||||
setOwner({
|
setOwner({
|
||||||
name: response.name,
|
name: response.name,
|
||||||
photo: response.photo
|
photo: response.photo
|
||||||
})
|
})
|
||||||
}).catch(() => setError(true))
|
})
|
||||||
|
.catch(() => setError(true))
|
||||||
// set user List
|
// set user List
|
||||||
permissionsApiResponse.sharedTo.forEach(shareUser => {
|
permissionsApiResponse.sharedTo.forEach(shareUser => {
|
||||||
getUserById(shareUser.username).then(response => {
|
getUserById(shareUser.username)
|
||||||
|
.then(response => {
|
||||||
setUserList(list => list.concat([{
|
setUserList(list => list.concat([{
|
||||||
id: response.id,
|
id: response.id,
|
||||||
name: response.name,
|
name: response.name,
|
||||||
photo: response.photo,
|
photo: response.photo,
|
||||||
canEdit: shareUser.canEdit
|
canEdit: shareUser.canEdit
|
||||||
}]))
|
}]))
|
||||||
}).catch(() => setError(true))
|
})
|
||||||
|
.catch(() => setError(true))
|
||||||
})
|
})
|
||||||
// set group List
|
// set group List
|
||||||
permissionsApiResponse.sharedToGroup.forEach(sharedGroup => {
|
permissionsApiResponse.sharedToGroup.forEach(sharedGroup => {
|
||||||
|
|
|
@ -29,7 +29,8 @@ export const RevisionModalListEntry: React.FC<RevisionModalListEntryProps> = ({
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
<ForkAwesomeIcon icon={ 'clock-o' } className='mx-2'/>
|
<ForkAwesomeIcon icon={ 'clock-o' } className='mx-2'/>
|
||||||
{DateTime.fromMillis(revision.timestamp * 1000).toFormat('DDDD T')}
|
{ DateTime.fromMillis(revision.timestamp * 1000)
|
||||||
|
.toFormat('DDDD T') }
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<ForkAwesomeIcon icon={ 'file-text-o' } className='mx-2'/>
|
<ForkAwesomeIcon icon={ 'file-text-o' } className='mx-2'/>
|
||||||
|
@ -38,9 +39,11 @@ export const RevisionModalListEntry: React.FC<RevisionModalListEntryProps> = ({
|
||||||
<span className={ 'd-flex flex-row my-1 align-items-center' }>
|
<span className={ 'd-flex flex-row my-1 align-items-center' }>
|
||||||
<ForkAwesomeIcon icon={ 'user-o' } className={ 'mx-2' }/>
|
<ForkAwesomeIcon icon={ 'user-o' } className={ 'mx-2' }/>
|
||||||
{
|
{
|
||||||
revisionAuthorListMap.get(revision.timestamp)?.map((user, index) => {
|
revisionAuthorListMap.get(revision.timestamp)
|
||||||
|
?.map((user, index) => {
|
||||||
return (
|
return (
|
||||||
<UserAvatar name={user.name} photo={user.photo} showName={false} additionalClasses={'mx-1'} key={index}/>
|
<UserAvatar name={ user.name } photo={ user.photo } showName={ false }
|
||||||
|
additionalClasses={ 'mx-1' } key={ index }/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,8 @@ export const RevisionModal: React.FC<PermissionsModalProps> = ({ show, onHide })
|
||||||
const { id } = useParams<{ id: string }>()
|
const { id } = useParams<{ id: string }>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getAllRevisions(id).then(fetchedRevisions => {
|
getAllRevisions(id)
|
||||||
|
.then(fetchedRevisions => {
|
||||||
fetchedRevisions.forEach(revision => {
|
fetchedRevisions.forEach(revision => {
|
||||||
const authorData = getUserDataForRevision(revision.authors)
|
const authorData = getUserDataForRevision(revision.authors)
|
||||||
revisionAuthorListMap.current.set(revision.timestamp, authorData)
|
revisionAuthorListMap.current.set(revision.timestamp, authorData)
|
||||||
|
@ -45,22 +46,26 @@ export const RevisionModal: React.FC<PermissionsModalProps> = ({ show, onHide })
|
||||||
if (fetchedRevisions.length >= 1) {
|
if (fetchedRevisions.length >= 1) {
|
||||||
setSelectedRevisionTimestamp(fetchedRevisions[0].timestamp)
|
setSelectedRevisionTimestamp(fetchedRevisions[0].timestamp)
|
||||||
}
|
}
|
||||||
}).catch(() => setError(true))
|
})
|
||||||
|
.catch(() => setError(true))
|
||||||
}, [setRevisions, setError, id])
|
}, [setRevisions, setError, id])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedRevisionTimestamp === null) {
|
if (selectedRevisionTimestamp === null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
getRevision(id, selectedRevisionTimestamp).then(fetchedRevision => {
|
getRevision(id, selectedRevisionTimestamp)
|
||||||
|
.then(fetchedRevision => {
|
||||||
setSelectedRevision(fetchedRevision)
|
setSelectedRevision(fetchedRevision)
|
||||||
}).catch(() => setError(true))
|
})
|
||||||
|
.catch(() => setError(true))
|
||||||
}, [selectedRevisionTimestamp, id])
|
}, [selectedRevisionTimestamp, id])
|
||||||
|
|
||||||
const markdownContent = useNoteMarkdownContent()
|
const markdownContent = useNoteMarkdownContent()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommonModal show={show} onHide={onHide} titleI18nKey={'editor.modal.revision.title'} icon={'history'} closeButton={true} size={'xl'} additionalClasses='revision-modal'>
|
<CommonModal show={ show } onHide={ onHide } titleI18nKey={ 'editor.modal.revision.title' } icon={ 'history' }
|
||||||
|
closeButton={ true } size={ 'xl' } additionalClasses='revision-modal'>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
<Row>
|
<Row>
|
||||||
<Col lg={ 4 } className={ 'scroll-col' }>
|
<Col lg={ 4 } className={ 'scroll-col' }>
|
||||||
|
|
|
@ -41,11 +41,13 @@ export const ShareModal: React.FC<ShareModalProps> = ({ show, onHide }) => {
|
||||||
url={ `${ baseUrl }/n/${ id }?${ editorMode }` }/>
|
url={ `${ baseUrl }/n/${ id }?${ editorMode }` }/>
|
||||||
<ShowIf condition={ noteFrontmatter.type === 'slide' }>
|
<ShowIf condition={ noteFrontmatter.type === 'slide' }>
|
||||||
<Trans i18nKey={ 'editor.modal.shareLink.slidesDescription' }/>
|
<Trans i18nKey={ 'editor.modal.shareLink.slidesDescription' }/>
|
||||||
<CopyableField content={`${baseUrl}/p/${id}`} nativeShareButton={true} url={`${baseUrl}/p/${id}`}/>
|
<CopyableField content={ `${ baseUrl }/p/${ id }` } nativeShareButton={ true }
|
||||||
|
url={ `${ baseUrl }/p/${ id }` }/>
|
||||||
</ShowIf>
|
</ShowIf>
|
||||||
<ShowIf condition={ noteFrontmatter.type === '' }>
|
<ShowIf condition={ noteFrontmatter.type === '' }>
|
||||||
<Trans i18nKey={ 'editor.modal.shareLink.viewOnlyDescription' }/>
|
<Trans i18nKey={ 'editor.modal.shareLink.viewOnlyDescription' }/>
|
||||||
<CopyableField content={`${baseUrl}/s/${id}`} nativeShareButton={true} url={`${baseUrl}/s/${id}`}/>
|
<CopyableField content={ `${ baseUrl }/s/${ id }` } nativeShareButton={ true }
|
||||||
|
url={ `${ baseUrl }/s/${ id }` }/>
|
||||||
</ShowIf>
|
</ShowIf>
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
</CommonModal>
|
</CommonModal>
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const useOnIframeLoad = (frameReference: RefObject<HTMLIFrameElement>, if
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
onNavigateAway()
|
onNavigateAway()
|
||||||
console.error("Navigated away from unknown URL")
|
console.error('Navigated away from unknown URL')
|
||||||
frame.src = renderPageUrl
|
frame.src = renderPageUrl
|
||||||
sendToRenderPage.current = true
|
sendToRenderPage.current = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,8 @@ export const MaxLengthWarningModal: React.FC<MaxLengthWarningModalProps> = ({ sh
|
||||||
useTranslation()
|
useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommonModal data-cy={'limitReachedModal'} show={show} onHide={onHide} titleI18nKey={'editor.error.limitReached.title'} closeButton={true}>
|
<CommonModal data-cy={ 'limitReachedModal' } show={ show } onHide={ onHide }
|
||||||
|
titleI18nKey={ 'editor.error.limitReached.title' } closeButton={ true }>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
<Trans i18nKey={ 'editor.error.limitReached.description' } values={ { maxLength } }/>
|
<Trans i18nKey={ 'editor.error.limitReached.description' } values={ { maxLength } }/>
|
||||||
<strong className='mt-2 d-block'><Trans i18nKey={ 'editor.error.limitReached.advice' }/></strong>
|
<strong className='mt-2 d-block'><Trans i18nKey={ 'editor.error.limitReached.advice' }/></strong>
|
||||||
|
|
|
@ -58,7 +58,8 @@ export const EditorPage: React.FC = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const requestedMode = search.substr(1)
|
const requestedMode = search.substr(1)
|
||||||
const mode = Object.values(EditorMode).find(mode => mode === requestedMode)
|
const mode = Object.values(EditorMode)
|
||||||
|
.find(mode => mode === requestedMode)
|
||||||
if (mode) {
|
if (mode) {
|
||||||
setEditorMode(mode)
|
setEditorMode(mode)
|
||||||
}
|
}
|
||||||
|
@ -100,7 +101,7 @@ export const EditorPage: React.FC = () => {
|
||||||
<LoadingNoteAlert show={ loading }/>
|
<LoadingNoteAlert show={ loading }/>
|
||||||
</div>
|
</div>
|
||||||
<ShowIf condition={ !error && !loading }>
|
<ShowIf condition={ !error && !loading }>
|
||||||
<div className={"flex-fill d-flex h-100 w-100 overflow-hidden flex-row"}>
|
<div className={ 'flex-fill d-flex h-100 w-100 overflow-hidden flex-row' }>
|
||||||
<Splitter
|
<Splitter
|
||||||
showLeft={ editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH }
|
showLeft={ editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH }
|
||||||
left={
|
left={
|
||||||
|
|
|
@ -21,7 +21,8 @@ const codeBlockHint = (editor: Editor): Promise< Hints| null > => {
|
||||||
}
|
}
|
||||||
const term = searchResult[1]
|
const term = searchResult[1]
|
||||||
if (allSupportedLanguages.length === 0) {
|
if (allSupportedLanguages.length === 0) {
|
||||||
allSupportedLanguages = hljs.default.listLanguages().concat('csv', 'flow', 'html', 'js', 'markmap', 'abc', 'graphviz', 'mermaid', 'vega-lite')
|
allSupportedLanguages = hljs.default.listLanguages()
|
||||||
|
.concat('csv', 'flow', 'html', 'js', 'markmap', 'abc', 'graphviz', 'mermaid', 'vega-lite')
|
||||||
}
|
}
|
||||||
const suggestions = search(term, allSupportedLanguages)
|
const suggestions = search(term, allSupportedLanguages)
|
||||||
const cursor = editor.getCursor()
|
const cursor = editor.getCursor()
|
||||||
|
|
|
@ -16,7 +16,8 @@ const spoilerSuggestion: Hint = {
|
||||||
const suggestions = validAlertLevels.map((suggestion: string): Hint => ({
|
const suggestions = validAlertLevels.map((suggestion: string): Hint => ({
|
||||||
text: ':::' + suggestion + '\n\n::: \n',
|
text: ':::' + suggestion + '\n\n::: \n',
|
||||||
displayText: suggestion
|
displayText: suggestion
|
||||||
})).concat(spoilerSuggestion)
|
}))
|
||||||
|
.concat(spoilerSuggestion)
|
||||||
|
|
||||||
const containerHint = (editor: Editor): Promise<Hints | null> => {
|
const containerHint = (editor: Editor): Promise<Hints | null> => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
|
|
@ -40,7 +40,8 @@ export const findWordAtCursor = (editor: Editor): findWordAtCursorResponse => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text: line.slice(start, end).toLowerCase(),
|
text: line.slice(start, end)
|
||||||
|
.toLowerCase(),
|
||||||
start: start,
|
start: start,
|
||||||
end: end
|
end: end
|
||||||
}
|
}
|
||||||
|
@ -49,7 +50,8 @@ export const findWordAtCursor = (editor: Editor): findWordAtCursorResponse => {
|
||||||
export const search = (term: string, list: string[]): string[] => {
|
export const search = (term: string, list: string[]): string[] => {
|
||||||
const suggestions: string[] = []
|
const suggestions: string[] = []
|
||||||
list.forEach(item => {
|
list.forEach(item => {
|
||||||
if (item.toLowerCase().startsWith(term.toLowerCase())) {
|
if (item.toLowerCase()
|
||||||
|
.startsWith(term.toLowerCase())) {
|
||||||
suggestions.push(item)
|
suggestions.push(item)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -64,5 +66,5 @@ export const allHinters: Hinter[] = [
|
||||||
ImageHinter,
|
ImageHinter,
|
||||||
LinkAndExtraTagHinter,
|
LinkAndExtraTagHinter,
|
||||||
PDFHinter,
|
PDFHinter,
|
||||||
CollapsableBlockHinter,
|
CollapsableBlockHinter
|
||||||
]
|
]
|
||||||
|
|
|
@ -51,7 +51,8 @@ const linkAndExtraTagHint = (editor: Editor): Promise< Hints| null > => {
|
||||||
case 'time':
|
case 'time':
|
||||||
// show the current time when the autocompletion is opened and not when the function is loaded
|
// show the current time when the autocompletion is opened and not when the function is loaded
|
||||||
return {
|
return {
|
||||||
text: `[time=${DateTime.local().toFormat('DDDD T')}]`
|
text: `[time=${ DateTime.local()
|
||||||
|
.toFormat('DDDD T') }]`
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
.CodeMirror-line, .CodeMirror-line-like {
|
.CodeMirror-line, .CodeMirror-line-like {
|
||||||
font-feature-settings: inherit;
|
font-feature-settings: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-line, .CodeMirror-line-like {
|
.CodeMirror-line, .CodeMirror-line-like {
|
||||||
font-variant-ligatures: none;
|
font-variant-ligatures: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ const tab = (editor: Editor) => {
|
||||||
const tab = '\t'
|
const tab = '\t'
|
||||||
|
|
||||||
// contruct x length spaces
|
// contruct x length spaces
|
||||||
const spaces = Array((editor.getOption('indentUnit') ?? 0) + 1).join(' ')
|
const spaces = Array((editor.getOption('indentUnit') ?? 0) + 1)
|
||||||
|
.join(' ')
|
||||||
|
|
||||||
// auto indent whole line when in list or blockquote
|
// auto indent whole line when in list or blockquote
|
||||||
const cursor = editor.getCursor()
|
const cursor = editor.getCursor()
|
||||||
|
@ -43,7 +44,8 @@ const tab = (editor: Editor) => {
|
||||||
const regex = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))/
|
const regex = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))/
|
||||||
|
|
||||||
let match
|
let match
|
||||||
const multiple = editor.getSelection().split('\n').length > 1 ||
|
const multiple = editor.getSelection()
|
||||||
|
.split('\n').length > 1 ||
|
||||||
editor.getSelections().length > 1
|
editor.getSelections().length > 1
|
||||||
|
|
||||||
if (multiple) {
|
if (multiple) {
|
||||||
|
|
|
@ -17,32 +17,39 @@ borrow some color from tomorrow-night-eighties
|
||||||
.dark #main-toolbar {
|
.dark #main-toolbar {
|
||||||
background: #1d222a;
|
background: #1d222a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark #working-set-list-container,
|
.dark #working-set-list-container,
|
||||||
.dark #editor-holder .pane-header {
|
.dark #editor-holder .pane-header {
|
||||||
background: #15181e;
|
background: #15181e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .working-set-header,
|
.dark .working-set-header,
|
||||||
.dark #project-files-header .btn-alt-quiet {
|
.dark #project-files-header .btn-alt-quiet {
|
||||||
background: rgba(204, 217, 255, 0.05);
|
background: rgba(204, 217, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .working-set-header > span {
|
.dark .working-set-header > span {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .sidebar-selection,
|
.dark .sidebar-selection,
|
||||||
.dark .filetree-selection,
|
.dark .filetree-selection,
|
||||||
.dark .sidebar-selection-extension,
|
.dark .sidebar-selection-extension,
|
||||||
.dark .filetree-selection-extension {
|
.dark .filetree-selection-extension {
|
||||||
background: #282c34;
|
background: #282c34;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark #status-bar,
|
.dark #status-bar,
|
||||||
.dark #status-indicators {
|
.dark #status-indicators {
|
||||||
background: #15181e;
|
background: #15181e;
|
||||||
border-top-color: #1d222a;
|
border-top-color: #1d222a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark a,
|
.dark a,
|
||||||
.dark .open-files-container li.selected a {
|
.dark .open-files-container li.selected a {
|
||||||
color: #528bff;
|
color: #528bff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Code Styling */
|
/* Code Styling */
|
||||||
.cm-s-one-dark.CodeMirror,
|
.cm-s-one-dark.CodeMirror,
|
||||||
.cm-s-one-dark .CodeMirror-scroll {
|
.cm-s-one-dark .CodeMirror-scroll {
|
||||||
|
@ -50,26 +57,33 @@ borrow some color from tomorrow-night-eighties
|
||||||
background-color: #1e2126;
|
background-color: #1e2126;
|
||||||
color: #abb2bf;
|
color: #abb2bf;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-activeline-background {
|
.cm-s-one-dark .CodeMirror-activeline-background {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline-background {
|
.cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline-background {
|
||||||
background: rgba(204, 217, 255, 0.05);
|
background: rgba(204, 217, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-line-padding .cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline-background {
|
.show-line-padding .cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline-background {
|
||||||
box-shadow: inset 15px 0 0 0 #000;
|
box-shadow: inset 15px 0 0 0 #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline .CodeMirror-gutter-elt {
|
.cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline .CodeMirror-gutter-elt {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #5c6370;
|
color: #5c6370;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline .inline-widget .CodeMirror-gutter-elt {
|
.cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline .inline-widget .CodeMirror-gutter-elt {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-string-2,
|
.cm-s-one-dark .cm-string-2,
|
||||||
.cm-s-one-dark .cm-hr {
|
.cm-s-one-dark .cm-hr {
|
||||||
color: #56b6c2;
|
color: #56b6c2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-number,
|
.cm-s-one-dark .cm-number,
|
||||||
.cm-s-one-dark .cm-attribute,
|
.cm-s-one-dark .cm-attribute,
|
||||||
.cm-s-one-dark .cm-qualifier,
|
.cm-s-one-dark .cm-qualifier,
|
||||||
|
@ -77,9 +91,11 @@ borrow some color from tomorrow-night-eighties
|
||||||
.cm-s-one-dark .cm-atom {
|
.cm-s-one-dark .cm-atom {
|
||||||
color: #eda35e;
|
color: #eda35e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-def {
|
.cm-s-one-dark .cm-def {
|
||||||
color: #c678dd;
|
color: #c678dd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-property,
|
.cm-s-one-dark .cm-property,
|
||||||
.cm-s-one-dark .cm-variable,
|
.cm-s-one-dark .cm-variable,
|
||||||
.cm-s-one-dark .cm-variable-2,
|
.cm-s-one-dark .cm-variable-2,
|
||||||
|
@ -89,10 +105,12 @@ borrow some color from tomorrow-night-eighties
|
||||||
.cm-s-one-dark .cm-bracket {
|
.cm-s-one-dark .cm-bracket {
|
||||||
color: #f76e79;
|
color: #f76e79;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*borrow from tomorrow-night-eighties*/
|
/*borrow from tomorrow-night-eighties*/
|
||||||
.cm-s-one-dark .cm-variable {
|
.cm-s-one-dark .cm-variable {
|
||||||
color: #99cc99;
|
color: #99cc99;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-variable-2 {
|
.cm-s-one-dark .cm-variable-2 {
|
||||||
color: #6699cc;
|
color: #6699cc;
|
||||||
}
|
}
|
||||||
|
@ -101,34 +119,42 @@ borrow some color from tomorrow-night-eighties
|
||||||
color: #5c6370;
|
color: #5c6370;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-error,
|
.cm-s-one-dark .cm-error,
|
||||||
.cm-s-one-dark .cm-minus {
|
.cm-s-one-dark .cm-minus {
|
||||||
color: #be5046;
|
color: #be5046;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-header {
|
.cm-s-one-dark .cm-header {
|
||||||
color: #eda35e;
|
color: #eda35e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-link {
|
.cm-s-one-dark .cm-link {
|
||||||
color: #98c379;
|
color: #98c379;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-rangeinfo {
|
.cm-s-one-dark .cm-rangeinfo {
|
||||||
color: #c678dd;
|
color: #c678dd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-keyword,
|
.cm-s-one-dark .cm-keyword,
|
||||||
.cm-s-one-dark .cm-builtin,
|
.cm-s-one-dark .cm-builtin,
|
||||||
.cm-s-one-dark .cm-tag {
|
.cm-s-one-dark .cm-tag {
|
||||||
color: #e06c75;
|
color: #e06c75;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-m-markdown.cm-keyword,
|
.cm-s-one-dark .cm-m-markdown.cm-keyword,
|
||||||
.cm-s-one-dark .cm-m-markdown.cm-builtin,
|
.cm-s-one-dark .cm-m-markdown.cm-builtin,
|
||||||
.cm-s-one-dark .cm-m-markdown.cm-tag {
|
.cm-s-one-dark .cm-m-markdown.cm-tag {
|
||||||
color: #98c379;
|
color: #98c379;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .cm-string {
|
.cm-s-one-dark .cm-string {
|
||||||
/* color: #98c379;*/
|
/* color: #98c379;*/
|
||||||
color: #6699cc;
|
color: #6699cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extra CSS */
|
/* Extra CSS */
|
||||||
.cm-s-one-dark .CodeMirror-searching {
|
.cm-s-one-dark .CodeMirror-searching {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
|
@ -137,32 +163,40 @@ borrow some color from tomorrow-night-eighties
|
||||||
background-color: rgba(204, 217, 255, 0.09);
|
background-color: rgba(204, 217, 255, 0.09);
|
||||||
box-shadow: 0px 0px 6px rgba(66, 133, 244, 0.4);
|
box-shadow: 0px 0px 6px rgba(66, 133, 244, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-searching.searching-current-match {
|
.cm-s-one-dark .CodeMirror-searching.searching-current-match {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #528bff;
|
background-color: #528bff;
|
||||||
box-shadow: 0px 0px 6px rgba(66, 133, 244, 0.8);
|
box-shadow: 0px 0px 6px rgba(66, 133, 244, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-cursor {
|
.cm-s-one-dark .CodeMirror-cursor {
|
||||||
border-left: 2px solid #528bff !important;
|
border-left: 2px solid #528bff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-fat-cursor .CodeMirror-cursor {
|
.cm-fat-cursor .CodeMirror-cursor {
|
||||||
border-left: 2px solid #3C5B9E !important;
|
border-left: 2px solid #3C5B9E !important;
|
||||||
background: #3C5B9E;
|
background: #3C5B9E;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-gutters {
|
.cm-s-one-dark .CodeMirror-gutters {
|
||||||
/* background-color: #282c34;*/
|
/* background-color: #282c34;*/
|
||||||
background-color: #1e2126;
|
background-color: #1e2126;
|
||||||
border-right: 1px solid rgba(204, 217, 255, 0.05);
|
border-right: 1px solid rgba(204, 217, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-linenumber {
|
.cm-s-one-dark .CodeMirror-linenumber {
|
||||||
color: #393e46;
|
color: #393e46;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror .CodeMirror-selected {
|
.cm-s-one-dark.CodeMirror .CodeMirror-selected {
|
||||||
background: rgba(204, 217, 255, 0.05);
|
background: rgba(204, 217, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror-focused .CodeMirror-selected {
|
.cm-s-one-dark.CodeMirror-focused .CodeMirror-selected {
|
||||||
background: rgba(204, 217, 255, 0.09);
|
background: rgba(204, 217, 255, 0.09);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-matchingbracket,
|
.cm-s-one-dark .CodeMirror-matchingbracket,
|
||||||
.cm-s-one-dark .CodeMirror-matchingtag {
|
.cm-s-one-dark .CodeMirror-matchingtag {
|
||||||
/* Ensure visibility against gray inline editor background */
|
/* Ensure visibility against gray inline editor background */
|
||||||
|
@ -170,52 +204,65 @@ borrow some color from tomorrow-night-eighties
|
||||||
color: #abb2bf !important;
|
color: #abb2bf !important;
|
||||||
border-bottom: 1px solid #528bff;
|
border-bottom: 1px solid #528bff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-overwrite .CodeMirror-cursor {
|
.cm-s-one-dark .CodeMirror-overwrite .CodeMirror-cursor {
|
||||||
border-left: none !important;
|
border-left: none !important;
|
||||||
border-bottom: 1px solid #fff;
|
border-bottom: 1px solid #fff;
|
||||||
width: 0.5em;
|
width: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror .CodeMirror {
|
.cm-s-one-dark.CodeMirror .CodeMirror {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror .CodeMirror .CodeMirror-gutters {
|
.cm-s-one-dark.CodeMirror .CodeMirror .CodeMirror-gutters {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror .CodeMirror .CodeMirror-activeline-background {
|
.cm-s-one-dark.CodeMirror .CodeMirror .CodeMirror-activeline-background {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror .CodeMirror .CodeMirror-activeline .CodeMirror-gutter-elt {
|
.cm-s-one-dark.CodeMirror .CodeMirror .CodeMirror-activeline .CodeMirror-gutter-elt {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #5c6370;
|
color: #5c6370;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror .CodeMirror-focused .CodeMirror-activeline-background {
|
.cm-s-one-dark.CodeMirror .CodeMirror-focused .CodeMirror-activeline-background {
|
||||||
background: #000;
|
background: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark.CodeMirror .CodeMirror-focused .CodeMirror-activeline .CodeMirror-gutter-elt {
|
.cm-s-one-dark.CodeMirror .CodeMirror-focused .CodeMirror-activeline .CodeMirror-gutter-elt {
|
||||||
background: rgba(204, 217, 255, 0.05);
|
background: rgba(204, 217, 255, 0.05);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-foldgutter-open:after {
|
.cm-s-one-dark .CodeMirror-foldgutter-open:after {
|
||||||
color: #393e46;
|
color: #393e46;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-foldgutter-folded:after {
|
.cm-s-one-dark .CodeMirror-foldgutter-folded:after {
|
||||||
color: #5c6370;
|
color: #5c6370;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror.over-gutter .CodeMirror-foldgutter-open:after,
|
.cm-s-one-dark .CodeMirror.over-gutter .CodeMirror-foldgutter-open:after,
|
||||||
.cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline .CodeMirror-foldgutter-open:after {
|
.cm-s-one-dark.CodeMirror-focused .CodeMirror-activeline .CodeMirror-foldgutter-open:after {
|
||||||
color: #5c6370;
|
color: #5c6370;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-one-dark .CodeMirror-foldmarker {
|
.cm-s-one-dark .CodeMirror-foldmarker {
|
||||||
border-color: #393e46;
|
border-color: #393e46;
|
||||||
color: #abb2bf;
|
color: #abb2bf;
|
||||||
background: rgba(204, 217, 255, 0.05);
|
background: rgba(204, 217, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Non-editor styling */
|
/* Non-editor styling */
|
||||||
.image-view,
|
.image-view,
|
||||||
.not-editor {
|
.not-editor {
|
||||||
background-color: #282c34;
|
background-color: #282c34;
|
||||||
}
|
}
|
||||||
|
|
||||||
.view-pane .image-view {
|
.view-pane .image-view {
|
||||||
color: #abb2bf;
|
color: #abb2bf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,8 @@ export const createStatusInfo = (editor: Editor, maxDocumentLength: number): Sta
|
||||||
remainingCharacters: maxDocumentLength - editor.getValue().length,
|
remainingCharacters: maxDocumentLength - editor.getValue().length,
|
||||||
linesInDocument: editor.lineCount(),
|
linesInDocument: editor.lineCount(),
|
||||||
selectedColumns: editor.getSelection().length,
|
selectedColumns: editor.getSelection().length,
|
||||||
selectedLines: editor.getSelection().split('\n').length
|
selectedLines: editor.getSelection()
|
||||||
|
.split('\n').length
|
||||||
})
|
})
|
||||||
|
|
||||||
export const StatusBar: React.FC<StatusBarInfo> = ({ position, selectedColumns, selectedLines, charactersInDocument, linesInDocument, remainingCharacters }) => {
|
export const StatusBar: React.FC<StatusBarInfo> = ({ position, selectedColumns, selectedLines, charactersInDocument, linesInDocument, remainingCharacters }) => {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EditorConfiguration } from 'codemirror'
|
import { EditorConfiguration } from 'codemirror'
|
||||||
import equal from "fast-deep-equal"
|
import equal from 'fast-deep-equal'
|
||||||
import React, { ChangeEvent, useCallback } from 'react'
|
import React, { ChangeEvent, useCallback } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
@ -33,7 +33,8 @@ export const EditorPreferenceBooleanProperty: React.FC<EditorPreferenceBooleanPr
|
||||||
const i18nPrefix = `editor.modal.preferences.${ property }`
|
const i18nPrefix = `editor.modal.preferences.${ property }`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditorPreferenceInput onChange={selectItem} property={property} type={EditorPreferenceInputType.SELECT} value={preference}>
|
<EditorPreferenceInput onChange={ selectItem } property={ property } type={ EditorPreferenceInputType.SELECT }
|
||||||
|
value={ preference }>
|
||||||
<option value={ 'true' }>
|
<option value={ 'true' }>
|
||||||
{ t(`${ i18nPrefix }.on`) }
|
{ t(`${ i18nPrefix }.on`) }
|
||||||
</option>
|
</option>
|
||||||
|
|
|
@ -25,7 +25,8 @@ export const EditorPreferenceInput: React.FC<EditorPreferenceInputProps> = ({ pr
|
||||||
return (
|
return (
|
||||||
<Form.Group controlId={ `editor-pref-${ property }` }>
|
<Form.Group controlId={ `editor-pref-${ property }` }>
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
<Trans i18nKey={`editor.modal.preferences.${property}${type===EditorPreferenceInputType.NUMBER ? '' : '.label'}`}/>
|
<Trans
|
||||||
|
i18nKey={ `editor.modal.preferences.${ property }${ type === EditorPreferenceInputType.NUMBER ? '' : '.label' }` }/>
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
as={ type === EditorPreferenceInputType.NUMBER ? 'input' : 'select' }
|
as={ type === EditorPreferenceInputType.NUMBER ? 'input' : 'select' }
|
||||||
|
|
|
@ -11,7 +11,8 @@ import { setEditorLigatures } from '../../../../../redux/editor/methods'
|
||||||
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
||||||
|
|
||||||
export const EditorPreferenceLigaturesSelect: React.FC = () => {
|
export const EditorPreferenceLigaturesSelect: React.FC = () => {
|
||||||
const ligaturesEnabled = useSelector((state: ApplicationState) => Boolean(state.editorConfig.ligatures).toString())
|
const ligaturesEnabled = useSelector((state: ApplicationState) => Boolean(state.editorConfig.ligatures)
|
||||||
|
.toString())
|
||||||
const saveLigatures = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
const saveLigatures = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
||||||
const ligaturesActivated: boolean = event.target.value === 'true'
|
const ligaturesActivated: boolean = event.target.value === 'true'
|
||||||
setEditorLigatures(ligaturesActivated)
|
setEditorLigatures(ligaturesActivated)
|
||||||
|
@ -19,7 +20,7 @@ export const EditorPreferenceLigaturesSelect: React.FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditorPreferenceInput onChange={saveLigatures} value={ligaturesEnabled} property={"ligatures"}
|
<EditorPreferenceInput onChange={ saveLigatures } value={ ligaturesEnabled } property={ 'ligatures' }
|
||||||
type={ EditorPreferenceInputType.BOOLEAN }>
|
type={ EditorPreferenceInputType.BOOLEAN }>
|
||||||
<option value='true'>{ t(`common.yes`) }</option>
|
<option value='true'>{ t(`common.yes`) }</option>
|
||||||
<option value='false'>{ t(`common.no`) }</option>
|
<option value='false'>{ t(`common.no`) }</option>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EditorConfiguration } from 'codemirror'
|
import { EditorConfiguration } from 'codemirror'
|
||||||
import equal from "fast-deep-equal"
|
import equal from 'fast-deep-equal'
|
||||||
import React, { ChangeEvent, useCallback } from 'react'
|
import React, { ChangeEvent, useCallback } from 'react'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { ApplicationState } from '../../../../../redux'
|
import { ApplicationState } from '../../../../../redux'
|
||||||
|
@ -29,6 +29,7 @@ export const EditorPreferenceNumberProperty: React.FC<EditorPreferenceNumberProp
|
||||||
}, [property])
|
}, [property])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditorPreferenceInput onChange={selectItem} property={property} type={EditorPreferenceInputType.NUMBER} value={preference}/>
|
<EditorPreferenceInput onChange={ selectItem } property={ property } type={ EditorPreferenceInputType.NUMBER }
|
||||||
|
value={ preference }/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EditorConfiguration } from 'codemirror'
|
import { EditorConfiguration } from 'codemirror'
|
||||||
import equal from "fast-deep-equal"
|
import equal from 'fast-deep-equal'
|
||||||
import React, { ChangeEvent, useCallback } from 'react'
|
import React, { ChangeEvent, useCallback } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
@ -35,7 +35,8 @@ export const EditorPreferenceSelectProperty: React.FC<EditorPreferenceSelectProp
|
||||||
const i18nPrefix = `editor.modal.preferences.${ property }`
|
const i18nPrefix = `editor.modal.preferences.${ property }`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditorPreferenceInput onChange={selectItem} property={property} type={EditorPreferenceInputType.SELECT} value={preference}>
|
<EditorPreferenceInput onChange={ selectItem } property={ property } type={ EditorPreferenceInputType.SELECT }
|
||||||
|
value={ preference }>
|
||||||
{ selections.map(selection =>
|
{ selections.map(selection =>
|
||||||
<option key={ selection } value={ selection }>
|
<option key={ selection } value={ selection }>
|
||||||
{ t(`${ i18nPrefix }.${ selection }`) }
|
{ t(`${ i18nPrefix }.${ selection }`) }
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import equal from "fast-deep-equal"
|
import equal from 'fast-deep-equal'
|
||||||
import React, { Fragment, useState } from 'react'
|
import React, { Fragment, useState } from 'react'
|
||||||
import { Button, Form, ListGroup } from 'react-bootstrap'
|
import { Button, Form, ListGroup } from 'react-bootstrap'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
@ -17,8 +17,8 @@ import { EditorPreferenceBooleanProperty } from './editor-preference-boolean-pro
|
||||||
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
||||||
import { EditorPreferenceLigaturesSelect } from './editor-preference-ligatures-select'
|
import { EditorPreferenceLigaturesSelect } from './editor-preference-ligatures-select'
|
||||||
import { EditorPreferenceNumberProperty } from './editor-preference-number-property'
|
import { EditorPreferenceNumberProperty } from './editor-preference-number-property'
|
||||||
import { EditorPreferenceProperty } from "./editor-preference-property"
|
import { EditorPreferenceProperty } from './editor-preference-property'
|
||||||
import { EditorPreferenceSelectProperty } from "./editor-preference-select-property"
|
import { EditorPreferenceSelectProperty } from './editor-preference-select-property'
|
||||||
|
|
||||||
export const EditorPreferences: React.FC = () => {
|
export const EditorPreferences: React.FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
@ -39,10 +39,12 @@ export const EditorPreferences: React.FC = () => {
|
||||||
<Form>
|
<Form>
|
||||||
<ListGroup>
|
<ListGroup>
|
||||||
<ListGroup.Item>
|
<ListGroup.Item>
|
||||||
<EditorPreferenceSelectProperty property={EditorPreferenceProperty.THEME} selections={['one-dark', 'neat']}/>
|
<EditorPreferenceSelectProperty property={ EditorPreferenceProperty.THEME }
|
||||||
|
selections={ ['one-dark', 'neat'] }/>
|
||||||
</ListGroup.Item>
|
</ListGroup.Item>
|
||||||
<ListGroup.Item>
|
<ListGroup.Item>
|
||||||
<EditorPreferenceSelectProperty property={EditorPreferenceProperty.KEYMAP} selections={['sublime', 'emacs', 'vim']}/>
|
<EditorPreferenceSelectProperty property={ EditorPreferenceProperty.KEYMAP }
|
||||||
|
selections={ ['sublime', 'emacs', 'vim'] }/>
|
||||||
</ListGroup.Item>
|
</ListGroup.Item>
|
||||||
<ListGroup.Item>
|
<ListGroup.Item>
|
||||||
<EditorPreferenceBooleanProperty property={ EditorPreferenceProperty.INDENT_WITH_TABS }/>
|
<EditorPreferenceBooleanProperty property={ EditorPreferenceProperty.INDENT_WITH_TABS }/>
|
||||||
|
@ -56,7 +58,9 @@ export const EditorPreferences: React.FC = () => {
|
||||||
<EditorPreferenceLigaturesSelect/>
|
<EditorPreferenceLigaturesSelect/>
|
||||||
</ListGroup.Item>
|
</ListGroup.Item>
|
||||||
<ListGroup.Item>
|
<ListGroup.Item>
|
||||||
<EditorPreferenceInput onChange={() => alert('This feature is not yet implemented.')} property={EditorPreferenceProperty.SPELL_CHECK} type={EditorPreferenceInputType.SELECT}>
|
<EditorPreferenceInput onChange={ () => alert('This feature is not yet implemented.') }
|
||||||
|
property={ EditorPreferenceProperty.SPELL_CHECK }
|
||||||
|
type={ EditorPreferenceInputType.SELECT }>
|
||||||
<option value='off'>Off</option>
|
<option value='off'>Off</option>
|
||||||
<option value='en'>English</option>
|
<option value='en'>English</option>
|
||||||
</EditorPreferenceInput>
|
</EditorPreferenceInput>
|
||||||
|
|
|
@ -29,7 +29,8 @@ export const EmojiPickerButton: React.FC<EmojiPickerButtonProps> = ({ editor })
|
||||||
addEmoji(emoji, editor)
|
addEmoji(emoji, editor)
|
||||||
} }
|
} }
|
||||||
onDismiss={ () => setShowEmojiPicker(false) }/>
|
onDismiss={ () => setShowEmojiPicker(false) }/>
|
||||||
<Button data-cy={'show-emoji-picker'} variant='light' onClick={() => setShowEmojiPicker(old => !old)} title={t('editor.editorToolbar.emoji')}>
|
<Button data-cy={ 'show-emoji-picker' } variant='light' onClick={ () => setShowEmojiPicker(old => !old) }
|
||||||
|
title={ t('editor.editorToolbar.emoji') }>
|
||||||
<ForkAwesomeIcon icon="smile-o"/>
|
<ForkAwesomeIcon icon="smile-o"/>
|
||||||
</Button>
|
</Button>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
@ -19,7 +19,8 @@ export interface EmojiPickerProps {
|
||||||
onDismiss: () => void
|
onDismiss: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const customEmojis: CustomEmoji[] = Object.keys(ForkAwesomeIcons).map((name) => ({
|
export const customEmojis: CustomEmoji[] = Object.keys(ForkAwesomeIcons)
|
||||||
|
.map((name) => ({
|
||||||
name: `fa-${ name }`,
|
name: `fa-${ name }`,
|
||||||
shortcodes: [`fa-${ name.toLowerCase() }`],
|
shortcodes: [`fa-${ name.toLowerCase() }`],
|
||||||
url: forkawesomeIcon,
|
url: forkawesomeIcon,
|
||||||
|
@ -92,6 +93,7 @@ export const EmojiPicker: React.FC<EmojiPickerProps> = ({ show, onEmojiSelected,
|
||||||
}, [darkModeEnabled])
|
}, [darkModeEnabled])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`position-absolute emoji-picker-container ${!show ? 'd-none' : ''}`} ref={pickerContainerRef}/>
|
<div className={ `position-absolute emoji-picker-container ${ !show ? 'd-none' : '' }` }
|
||||||
|
ref={ pickerContainerRef }/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ export const TablePickerButton: React.FC<TablePickerButtonProps> = ({ editor })
|
||||||
addTable(editor, rows, cols)
|
addTable(editor, rows, cols)
|
||||||
} }
|
} }
|
||||||
/>
|
/>
|
||||||
<Button data-cy={'show-table-overlay'} variant='light' onClick={() => setShowTablePicker(old => !old)} title={t('editor.editorToolbar.table.title')}>
|
<Button data-cy={ 'show-table-overlay' } variant='light' onClick={ () => setShowTablePicker(old => !old) }
|
||||||
|
title={ t('editor.editorToolbar.table.title') }>
|
||||||
<ForkAwesomeIcon icon="table"/>
|
<ForkAwesomeIcon icon="table"/>
|
||||||
</Button>
|
</Button>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.table-picker-container {
|
.table-picker-container {
|
||||||
z-index: 1111;
|
z-index: 1111;
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,8 @@ export const TablePicker: React.FC<TablePickerProps> = ({ show, onDismiss, onTab
|
||||||
}, [onTablePicked, tableSize])
|
}, [onTablePicked, tableSize])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`position-absolute table-picker-container p-2 ${!show || showDialog ? 'd-none' : ''} bg-light`} ref={containerRef} role="grid">
|
<div className={ `position-absolute table-picker-container p-2 ${ !show || showDialog ? 'd-none' : '' } bg-light` }
|
||||||
|
ref={ containerRef } role="grid">
|
||||||
<p className={ 'lead' }>
|
<p className={ 'lead' }>
|
||||||
{ tableSize
|
{ tableSize
|
||||||
? t('editor.editorToolbar.table.size', { cols: tableSize?.columns, rows: tableSize.rows })
|
? t('editor.editorToolbar.table.size', { cols: tableSize?.columns, rows: tableSize.rows })
|
||||||
|
@ -53,8 +54,10 @@ export const TablePicker: React.FC<TablePickerProps> = ({ show, onDismiss, onTab
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
<div className={ 'table-container' }>
|
<div className={ 'table-container' }>
|
||||||
{createNumberRangeArray(8).map((row: number) => (
|
{ createNumberRangeArray(8)
|
||||||
createNumberRangeArray(10).map((col: number) => (
|
.map((row: number) => (
|
||||||
|
createNumberRangeArray(10)
|
||||||
|
.map((col: number) => (
|
||||||
<div
|
<div
|
||||||
key={ `${ row }_${ col }` }
|
key={ `${ row }_${ col }` }
|
||||||
className={ `table-cell ${ tableSize && row < tableSize.rows && col < tableSize.columns ? 'bg-primary' : '' }` }
|
className={ `table-cell ${ tableSize && row < tableSize.rows && col < tableSize.columns ? 'bg-primary' : '' }` }
|
||||||
|
|
|
@ -48,63 +48,80 @@ export const ToolBar: React.FC<ToolBarProps> = ({ editor }) => {
|
||||||
return (
|
return (
|
||||||
<ButtonToolbar className='bg-light'>
|
<ButtonToolbar className='bg-light'>
|
||||||
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
||||||
<Button data-cy={'format-bold'} variant='light' onClick={() => makeSelectionBold(editor)} title={t('editor.editorToolbar.bold')}>
|
<Button data-cy={ 'format-bold' } variant='light' onClick={ () => makeSelectionBold(editor) }
|
||||||
|
title={ t('editor.editorToolbar.bold') }>
|
||||||
<ForkAwesomeIcon icon="bold"/>
|
<ForkAwesomeIcon icon="bold"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-italic'} variant='light' onClick={() => makeSelectionItalic(editor)} title={t('editor.editorToolbar.italic')}>
|
<Button data-cy={ 'format-italic' } variant='light' onClick={ () => makeSelectionItalic(editor) }
|
||||||
|
title={ t('editor.editorToolbar.italic') }>
|
||||||
<ForkAwesomeIcon icon="italic"/>
|
<ForkAwesomeIcon icon="italic"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-underline'} variant='light' onClick={() => underlineSelection(editor)} title={t('editor.editorToolbar.underline')}>
|
<Button data-cy={ 'format-underline' } variant='light' onClick={ () => underlineSelection(editor) }
|
||||||
|
title={ t('editor.editorToolbar.underline') }>
|
||||||
<ForkAwesomeIcon icon="underline"/>
|
<ForkAwesomeIcon icon="underline"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-strikethrough'} variant='light' onClick={() => strikeThroughSelection(editor)} title={t('editor.editorToolbar.strikethrough')}>
|
<Button data-cy={ 'format-strikethrough' } variant='light' onClick={ () => strikeThroughSelection(editor) }
|
||||||
|
title={ t('editor.editorToolbar.strikethrough') }>
|
||||||
<ForkAwesomeIcon icon="strikethrough"/>
|
<ForkAwesomeIcon icon="strikethrough"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-subscript'} variant='light' onClick={() => subscriptSelection(editor)} title={t('editor.editorToolbar.subscript')}>
|
<Button data-cy={ 'format-subscript' } variant='light' onClick={ () => subscriptSelection(editor) }
|
||||||
|
title={ t('editor.editorToolbar.subscript') }>
|
||||||
<ForkAwesomeIcon icon="subscript"/>
|
<ForkAwesomeIcon icon="subscript"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-superscript'} variant='light' onClick={() => superscriptSelection(editor)} title={t('editor.editorToolbar.superscript')}>
|
<Button data-cy={ 'format-superscript' } variant='light' onClick={ () => superscriptSelection(editor) }
|
||||||
|
title={ t('editor.editorToolbar.superscript') }>
|
||||||
<ForkAwesomeIcon icon="superscript"/>
|
<ForkAwesomeIcon icon="superscript"/>
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
||||||
<Button data-cy={'format-heading'} variant='light' onClick={() => addHeaderLevel(editor)} title={t('editor.editorToolbar.header')}>
|
<Button data-cy={ 'format-heading' } variant='light' onClick={ () => addHeaderLevel(editor) }
|
||||||
|
title={ t('editor.editorToolbar.header') }>
|
||||||
<ForkAwesomeIcon icon="header"/>
|
<ForkAwesomeIcon icon="header"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-code-block'} variant='light' onClick={() => addCodeFences(editor)} title={t('editor.editorToolbar.code')}>
|
<Button data-cy={ 'format-code-block' } variant='light' onClick={ () => addCodeFences(editor) }
|
||||||
|
title={ t('editor.editorToolbar.code') }>
|
||||||
<ForkAwesomeIcon icon="code"/>
|
<ForkAwesomeIcon icon="code"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-block-quote'} variant='light' onClick={() => addQuotes(editor)} title={t('editor.editorToolbar.blockquote')}>
|
<Button data-cy={ 'format-block-quote' } variant='light' onClick={ () => addQuotes(editor) }
|
||||||
|
title={ t('editor.editorToolbar.blockquote') }>
|
||||||
<ForkAwesomeIcon icon="quote-right"/>
|
<ForkAwesomeIcon icon="quote-right"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-unordered-list'} variant='light' onClick={() => addList(editor)} title={t('editor.editorToolbar.unorderedList')}>
|
<Button data-cy={ 'format-unordered-list' } variant='light' onClick={ () => addList(editor) }
|
||||||
|
title={ t('editor.editorToolbar.unorderedList') }>
|
||||||
<ForkAwesomeIcon icon="list"/>
|
<ForkAwesomeIcon icon="list"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-ordered-list'} variant='light' onClick={() => addOrderedList(editor)} title={t('editor.editorToolbar.orderedList')}>
|
<Button data-cy={ 'format-ordered-list' } variant='light' onClick={ () => addOrderedList(editor) }
|
||||||
|
title={ t('editor.editorToolbar.orderedList') }>
|
||||||
<ForkAwesomeIcon icon="list-ol"/>
|
<ForkAwesomeIcon icon="list-ol"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-check-list'} variant='light' onClick={() => addTaskList(editor)} title={t('editor.editorToolbar.checkList')}>
|
<Button data-cy={ 'format-check-list' } variant='light' onClick={ () => addTaskList(editor) }
|
||||||
|
title={ t('editor.editorToolbar.checkList') }>
|
||||||
<ForkAwesomeIcon icon="check-square"/>
|
<ForkAwesomeIcon icon="check-square"/>
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
||||||
<Button data-cy={'format-link'} variant='light' onClick={() => addLink(editor)} title={t('editor.editorToolbar.link')}>
|
<Button data-cy={ 'format-link' } variant='light' onClick={ () => addLink(editor) }
|
||||||
|
title={ t('editor.editorToolbar.link') }>
|
||||||
<ForkAwesomeIcon icon="link"/>
|
<ForkAwesomeIcon icon="link"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-image'} variant='light' onClick={() => addImage(editor)} title={t('editor.editorToolbar.image')}>
|
<Button data-cy={ 'format-image' } variant='light' onClick={ () => addImage(editor) }
|
||||||
|
title={ t('editor.editorToolbar.image') }>
|
||||||
<ForkAwesomeIcon icon="picture-o"/>
|
<ForkAwesomeIcon icon="picture-o"/>
|
||||||
</Button>
|
</Button>
|
||||||
<UploadImageButton editor={ editor }/>
|
<UploadImageButton editor={ editor }/>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
||||||
<TablePickerButton editor={ editor }/>
|
<TablePickerButton editor={ editor }/>
|
||||||
<Button data-cy={'format-add-line'} variant='light' onClick={() => addLine(editor)} title={t('editor.editorToolbar.line')}>
|
<Button data-cy={ 'format-add-line' } variant='light' onClick={ () => addLine(editor) }
|
||||||
|
title={ t('editor.editorToolbar.line') }>
|
||||||
<ForkAwesomeIcon icon="minus"/>
|
<ForkAwesomeIcon icon="minus"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-collapsable-block'} variant='light' onClick={() => addCollapsableBlock(editor)} title={t('editor.editorToolbar.collapsableBlock')}>
|
<Button data-cy={ 'format-collapsable-block' } variant='light' onClick={ () => addCollapsableBlock(editor) }
|
||||||
|
title={ t('editor.editorToolbar.collapsableBlock') }>
|
||||||
<ForkAwesomeIcon icon="caret-square-o-down"/>
|
<ForkAwesomeIcon icon="caret-square-o-down"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button data-cy={'format-add-comment'} variant='light' onClick={() => addComment(editor)} title={t('editor.editorToolbar.comment')}>
|
<Button data-cy={ 'format-add-comment' } variant='light' onClick={ () => addComment(editor) }
|
||||||
|
title={ t('editor.editorToolbar.comment') }>
|
||||||
<ForkAwesomeIcon icon="comment"/>
|
<ForkAwesomeIcon icon="comment"/>
|
||||||
</Button>
|
</Button>
|
||||||
<EmojiPickerButton editor={ editor }/>
|
<EmojiPickerButton editor={ editor }/>
|
||||||
|
|
|
@ -119,9 +119,12 @@ const mockListSelections = (positions: FromTo, empty: boolean): (() => CodeMirro
|
||||||
|
|
||||||
const expectFromToReplacement = (position: FromTo, expectedReplacement: string, done: () => void): ((replacement: string | string[], from: CodeMirror.Position, to?: CodeMirror.Position) => void) => {
|
const expectFromToReplacement = (position: FromTo, expectedReplacement: string, done: () => void): ((replacement: string | string[], from: CodeMirror.Position, to?: CodeMirror.Position) => void) => {
|
||||||
return (replacement: string | string[], from: CodeMirror.Position, to?: CodeMirror.Position) => {
|
return (replacement: string | string[], from: CodeMirror.Position, to?: CodeMirror.Position) => {
|
||||||
expect(from).toEqual(position.from)
|
expect(from)
|
||||||
expect(to).toEqual(position.to)
|
.toEqual(position.from)
|
||||||
expect(replacement).toEqual(expectedReplacement)
|
expect(to)
|
||||||
|
.toEqual(position.to)
|
||||||
|
expect(replacement)
|
||||||
|
.toEqual(expectedReplacement)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,7 +424,8 @@ describe('test addHeaderLevel', () => {
|
||||||
getCursor: () => cursor.from,
|
getCursor: () => cursor.from,
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(firstHeading)
|
expect(replacement)
|
||||||
|
.toEqual(firstHeading)
|
||||||
done()
|
done()
|
||||||
},
|
},
|
||||||
getLine: (): string => (noHeading)
|
getLine: (): string => (noHeading)
|
||||||
|
@ -434,7 +438,8 @@ describe('test addHeaderLevel', () => {
|
||||||
getCursor: () => cursor.from,
|
getCursor: () => cursor.from,
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(secondHeading)
|
expect(replacement)
|
||||||
|
.toEqual(secondHeading)
|
||||||
done()
|
done()
|
||||||
},
|
},
|
||||||
getLine: (): string => (firstHeading)
|
getLine: (): string => (firstHeading)
|
||||||
|
@ -447,7 +452,8 @@ describe('test addHeaderLevel', () => {
|
||||||
getCursor: () => cursor.from,
|
getCursor: () => cursor.from,
|
||||||
listSelections: mockListSelections(firstLine, false),
|
listSelections: mockListSelections(firstLine, false),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(firstLineFirstHeading)
|
expect(replacement)
|
||||||
|
.toEqual(firstLineFirstHeading)
|
||||||
done()
|
done()
|
||||||
},
|
},
|
||||||
getLine: (): string => (firstLineNoHeading)
|
getLine: (): string => (firstLineNoHeading)
|
||||||
|
@ -460,7 +466,8 @@ describe('test addHeaderLevel', () => {
|
||||||
getCursor: () => cursor.from,
|
getCursor: () => cursor.from,
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(firstLineFirstHeading)
|
expect(replacement)
|
||||||
|
.toEqual(firstLineFirstHeading)
|
||||||
done()
|
done()
|
||||||
},
|
},
|
||||||
getLine: (): string => (firstLineNoHeading)
|
getLine: (): string => (firstLineNoHeading)
|
||||||
|
@ -473,7 +480,8 @@ describe('test addHeaderLevel', () => {
|
||||||
getCursor: () => cursor.from,
|
getCursor: () => cursor.from,
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(firstLineFirstHeading)
|
expect(replacement)
|
||||||
|
.toEqual(firstLineFirstHeading)
|
||||||
done()
|
done()
|
||||||
},
|
},
|
||||||
getLine: (): string => (firstLineNoHeading)
|
getLine: (): string => (firstLineNoHeading)
|
||||||
|
@ -492,7 +500,8 @@ describe('test addCodeFences', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => '',
|
getLine: (): string => '',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('```\n\n```')
|
expect(replacement)
|
||||||
|
.toEqual('```\n\n```')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -506,7 +515,8 @@ describe('test addCodeFences', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => '1st line',
|
getLine: (): string => '1st line',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('```\n1st line\n```')
|
expect(replacement)
|
||||||
|
.toEqual('```\n1st line\n```')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -555,7 +565,8 @@ describe('test addQuotes', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`> ${textFirstLine}`)
|
expect(replacement)
|
||||||
|
.toEqual(`> ${ textFirstLine }`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -602,7 +613,8 @@ describe('test unordered list', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`- ${textFirstLine}`)
|
expect(replacement)
|
||||||
|
.toEqual(`- ${ textFirstLine }`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -625,7 +637,8 @@ describe('test unordered list', () => {
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('- 2nd line3rd line')
|
expect(replacement)
|
||||||
|
.toEqual('- 2nd line3rd line')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -638,7 +651,8 @@ describe('test unordered list', () => {
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('- line3rd ')
|
expect(replacement)
|
||||||
|
.toEqual('- line3rd ')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -655,7 +669,8 @@ describe('test ordered list', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`1. ${textFirstLine}`)
|
expect(replacement)
|
||||||
|
.toEqual(`1. ${ textFirstLine }`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -678,7 +693,8 @@ describe('test ordered list', () => {
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('1. 2nd line3rd line')
|
expect(replacement)
|
||||||
|
.toEqual('1. 2nd line3rd line')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -691,7 +707,8 @@ describe('test ordered list', () => {
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('1. line3rd ')
|
expect(replacement)
|
||||||
|
.toEqual('1. line3rd ')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -709,7 +726,8 @@ describe('test todo list', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`- [ ] ${textFirstLine}`)
|
expect(replacement)
|
||||||
|
.toEqual(`- [ ] ${ textFirstLine }`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -732,7 +750,8 @@ describe('test todo list', () => {
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('- [ ] 2nd line3rd line')
|
expect(replacement)
|
||||||
|
.toEqual('- [ ] 2nd line3rd line')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -745,7 +764,8 @@ describe('test todo list', () => {
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('- [ ] line3rd ')
|
expect(replacement)
|
||||||
|
.toEqual('- [ ] line3rd ')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -764,7 +784,8 @@ describe('test addLink', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('[](https://)')
|
expect(replacement)
|
||||||
|
.toEqual('[](https://)')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -787,7 +808,8 @@ describe('test addLink', () => {
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('[2nd line3rd line](https://)')
|
expect(replacement)
|
||||||
|
.toEqual('[2nd line3rd line](https://)')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -800,7 +822,8 @@ describe('test addLink', () => {
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('[line3rd ](https://)')
|
expect(replacement)
|
||||||
|
.toEqual('[line3rd ](https://)')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -819,7 +842,8 @@ describe('test addImage', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('![](https://)')
|
expect(replacement)
|
||||||
|
.toEqual('![](https://)')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -842,7 +866,8 @@ describe('test addImage', () => {
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('![2nd line3rd line](https://)')
|
expect(replacement)
|
||||||
|
.toEqual('![2nd line3rd line](https://)')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -855,7 +880,8 @@ describe('test addImage', () => {
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('![line3rd ](https://)')
|
expect(replacement)
|
||||||
|
.toEqual('![line3rd ](https://)')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -874,7 +900,8 @@ describe('test addLine', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`${textFirstLine}\n----`)
|
expect(replacement)
|
||||||
|
.toEqual(`${ textFirstLine }\n----`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -897,7 +924,8 @@ describe('test addLine', () => {
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
getLine: (): string => '2nd line',
|
getLine: (): string => '2nd line',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('2nd line\n----')
|
expect(replacement)
|
||||||
|
.toEqual('2nd line\n----')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -910,7 +938,8 @@ describe('test addLine', () => {
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
getLine: (): string => '2nd line',
|
getLine: (): string => '2nd line',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('2nd line\n----')
|
expect(replacement)
|
||||||
|
.toEqual('2nd line\n----')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -929,7 +958,8 @@ describe('test collapsable block', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`${textFirstLine}\n:::spoiler Toggle label\n Toggled content\n:::`)
|
expect(replacement)
|
||||||
|
.toEqual(`${ textFirstLine }\n:::spoiler Toggle label\n Toggled content\n:::`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -952,7 +982,8 @@ describe('test collapsable block', () => {
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
getLine: (): string => '2nd line',
|
getLine: (): string => '2nd line',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('2nd line\n:::spoiler Toggle label\n Toggled content\n:::')
|
expect(replacement)
|
||||||
|
.toEqual('2nd line\n:::spoiler Toggle label\n Toggled content\n:::')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -965,7 +996,8 @@ describe('test collapsable block', () => {
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
getLine: (): string => '2nd line',
|
getLine: (): string => '2nd line',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('2nd line\n:::spoiler Toggle label\n Toggled content\n:::')
|
expect(replacement)
|
||||||
|
.toEqual('2nd line\n:::spoiler Toggle label\n Toggled content\n:::')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -984,7 +1016,8 @@ describe('test addComment', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`${textFirstLine}\n> []`)
|
expect(replacement)
|
||||||
|
.toEqual(`${ textFirstLine }\n> []`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1007,7 +1040,8 @@ describe('test addComment', () => {
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
getLine: (): string => '2nd line',
|
getLine: (): string => '2nd line',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('2nd line\n> []')
|
expect(replacement)
|
||||||
|
.toEqual('2nd line\n> []')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1020,7 +1054,8 @@ describe('test addComment', () => {
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
getLine: (): string => '2nd line',
|
getLine: (): string => '2nd line',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual('2nd line\n> []')
|
expect(replacement)
|
||||||
|
.toEqual('2nd line\n> []')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1039,7 +1074,8 @@ describe('test addTable', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`${textFirstLine}\n${table}`)
|
expect(replacement)
|
||||||
|
.toEqual(`${ textFirstLine }\n${ table }`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1062,7 +1098,8 @@ describe('test addTable', () => {
|
||||||
listSelections: mockListSelections(multiline, false),
|
listSelections: mockListSelections(multiline, false),
|
||||||
getLine: (): string => '2nd line',
|
getLine: (): string => '2nd line',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`2nd line\n${table}`)
|
expect(replacement)
|
||||||
|
.toEqual(`2nd line\n${ table }`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1075,7 +1112,8 @@ describe('test addTable', () => {
|
||||||
listSelections: mockListSelections(multilineOffset, false),
|
listSelections: mockListSelections(multilineOffset, false),
|
||||||
getLine: (): string => '2nd line',
|
getLine: (): string => '2nd line',
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(`2nd line\n${table}`)
|
expect(replacement)
|
||||||
|
.toEqual(`2nd line\n${ table }`)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1112,7 +1150,8 @@ describe('test addEmoji with native emoji', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(':1234:')
|
expect(replacement)
|
||||||
|
.toEqual(':1234:')
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1173,7 +1212,8 @@ describe('test addEmoji with native emoji', () => {
|
||||||
listSelections: mockListSelections(cursor, true),
|
listSelections: mockListSelections(cursor, true),
|
||||||
getLine: (): string => (textFirstLine),
|
getLine: (): string => (textFirstLine),
|
||||||
replaceRange: (replacement: string | string[]) => {
|
replaceRange: (replacement: string | string[]) => {
|
||||||
expect(replacement).toEqual(forkAwesomeIcon)
|
expect(replacement)
|
||||||
|
.toEqual(forkAwesomeIcon)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -32,10 +32,14 @@ export const addCollapsableBlock = (editor: Editor): void => changeLines(editor,
|
||||||
export const addComment = (editor: Editor): void => changeLines(editor, line => `${ line }\n> []`)
|
export const addComment = (editor: Editor): void => changeLines(editor, line => `${ line }\n> []`)
|
||||||
export const addTable = (editor: Editor, rows: number, columns: number): void => {
|
export const addTable = (editor: Editor, rows: number, columns: number): void => {
|
||||||
const rowArray = createNumberRangeArray(rows)
|
const rowArray = createNumberRangeArray(rows)
|
||||||
const colArray = createNumberRangeArray(columns).map(col => col + 1)
|
const colArray = createNumberRangeArray(columns)
|
||||||
|
.map(col => col + 1)
|
||||||
const head = '| # ' + colArray.join(' | # ') + ' |'
|
const head = '| # ' + colArray.join(' | # ') + ' |'
|
||||||
const divider = '| ' + colArray.map(() => '----').join(' | ') + ' |'
|
const divider = '| ' + colArray.map(() => '----')
|
||||||
const body = rowArray.map(() => '| ' + colArray.map(() => 'Text').join(' | ') + ' |').join('\n')
|
.join(' | ') + ' |'
|
||||||
|
const body = rowArray.map(() => '| ' + colArray.map(() => 'Text')
|
||||||
|
.join(' | ') + ' |')
|
||||||
|
.join('\n')
|
||||||
const table = `${ head }\n${ divider }\n${ body }`
|
const table = `${ head }\n${ divider }\n${ body }`
|
||||||
changeLines(editor, line => `${ line }\n${ table }`)
|
changeLines(editor, line => `${ line }\n${ table }`)
|
||||||
}
|
}
|
||||||
|
@ -89,7 +93,8 @@ export const insertOnStartOfLines = (editor: Editor, symbol: string): void => {
|
||||||
const to = range.empty() ? { line: cursor.line, ch: editor.getLine(cursor.line).length } : range.to()
|
const to = range.empty() ? { line: cursor.line, ch: editor.getLine(cursor.line).length } : range.to()
|
||||||
const selection = editor.getRange(from, to)
|
const selection = editor.getRange(from, to)
|
||||||
const lines = selection.split('\n')
|
const lines = selection.split('\n')
|
||||||
editor.replaceRange(lines.map(line => `${symbol}${line}`).join('\n'), from, to, '+input')
|
editor.replaceRange(lines.map(line => `${ symbol }${ line }`)
|
||||||
|
.join('\n'), from, to, '+input')
|
||||||
}
|
}
|
||||||
editor.setSelections(ranges)
|
editor.setSelections(ranges)
|
||||||
}
|
}
|
||||||
|
@ -117,7 +122,8 @@ export const createList = (editor: Editor, listMark: (i: number) => string): voi
|
||||||
|
|
||||||
const selection = editor.getRange(from, to)
|
const selection = editor.getRange(from, to)
|
||||||
const lines = selection.split('\n')
|
const lines = selection.split('\n')
|
||||||
editor.replaceRange(lines.map((line, i) => `${listMark(i + 1)}${line}`).join('\n'), from, to, '+input')
|
editor.replaceRange(lines.map((line, i) => `${ listMark(i + 1) }${ line }`)
|
||||||
|
.join('\n'), from, to, '+input')
|
||||||
}
|
}
|
||||||
editor.setSelections(ranges)
|
editor.setSelections(ranges)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,16 @@ describe('yaml frontmatter tests', () => {
|
||||||
|
|
||||||
const testFrontmatter = (input: string, expectedRaw: Partial<RawNoteFrontmatter>, expectedFinished: Partial<NoteFrontmatter>) => {
|
const testFrontmatter = (input: string, expectedRaw: Partial<RawNoteFrontmatter>, expectedFinished: Partial<NoteFrontmatter>) => {
|
||||||
md.render(input)
|
md.render(input)
|
||||||
expect(raw).not.toBe(undefined)
|
expect(raw)
|
||||||
expect(raw).toEqual(expectedRaw)
|
.not
|
||||||
expect(finished).not.toBe(undefined)
|
.toBe(undefined)
|
||||||
expect(finished).toEqual({
|
expect(raw)
|
||||||
|
.toEqual(expectedRaw)
|
||||||
|
expect(finished)
|
||||||
|
.not
|
||||||
|
.toBe(undefined)
|
||||||
|
expect(finished)
|
||||||
|
.toEqual({
|
||||||
...defaultYAML,
|
...defaultYAML,
|
||||||
...expectedFinished
|
...expectedFinished
|
||||||
})
|
})
|
||||||
|
|
|
@ -257,7 +257,8 @@ export class NoteFrontmatter {
|
||||||
theme: 'white'
|
theme: 'white'
|
||||||
} */
|
} */
|
||||||
if (typeof rawData?.tags === 'string') {
|
if (typeof rawData?.tags === 'string') {
|
||||||
this.tags = rawData?.tags?.split(',').map(entry => entry.trim()) ?? []
|
this.tags = rawData?.tags?.split(',')
|
||||||
|
.map(entry => entry.trim()) ?? []
|
||||||
this.deprecatedTagsSyntax = true
|
this.deprecatedTagsSyntax = true
|
||||||
} else if (typeof rawData?.tags === 'object') {
|
} else if (typeof rawData?.tags === 'object') {
|
||||||
this.tags = rawData?.tags?.filter(tag => tag !== null) ?? []
|
this.tags = rawData?.tags?.filter(tag => tag !== null) ?? []
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const useOnIframeLoad = (frameReference: RefObject<HTMLIFrameElement>, if
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
onNavigateAway()
|
onNavigateAway()
|
||||||
console.error("Navigated away from unknown URL")
|
console.error('Navigated away from unknown URL')
|
||||||
frame.src = renderPageUrl
|
frame.src = renderPageUrl
|
||||||
sendToRenderPage.current = true
|
sendToRenderPage.current = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,13 +39,18 @@ export const RenderIframe: React.FC<MarkdownDocumentProps> = (
|
||||||
const onIframeLoad = useOnIframeLoad(frameReference, iframeCommunicator, rendererOrigin, renderPageUrl, resetRendererReady)
|
const onIframeLoad = useOnIframeLoad(frameReference, iframeCommunicator, rendererOrigin, renderPageUrl, resetRendererReady)
|
||||||
|
|
||||||
useEffect(() => () => iframeCommunicator.unregisterEventListener(), [iframeCommunicator])
|
useEffect(() => () => iframeCommunicator.unregisterEventListener(), [iframeCommunicator])
|
||||||
useEffect(() => iframeCommunicator.onFirstHeadingChange(onFirstHeadingChange), [iframeCommunicator, onFirstHeadingChange])
|
useEffect(() => iframeCommunicator.onFirstHeadingChange(onFirstHeadingChange), [iframeCommunicator,
|
||||||
useEffect(() => iframeCommunicator.onFrontmatterChange(onFrontmatterChange), [iframeCommunicator, onFrontmatterChange])
|
onFirstHeadingChange])
|
||||||
|
useEffect(() => iframeCommunicator.onFrontmatterChange(onFrontmatterChange), [iframeCommunicator,
|
||||||
|
onFrontmatterChange])
|
||||||
useEffect(() => iframeCommunicator.onSetScrollState(onScroll), [iframeCommunicator, onScroll])
|
useEffect(() => iframeCommunicator.onSetScrollState(onScroll), [iframeCommunicator, onScroll])
|
||||||
useEffect(() => iframeCommunicator.onSetScrollSourceToRenderer(onMakeScrollSource), [iframeCommunicator, onMakeScrollSource])
|
useEffect(() => iframeCommunicator.onSetScrollSourceToRenderer(onMakeScrollSource), [iframeCommunicator,
|
||||||
useEffect(() => iframeCommunicator.onTaskCheckboxChange(onTaskCheckedChange), [iframeCommunicator, onTaskCheckedChange])
|
onMakeScrollSource])
|
||||||
|
useEffect(() => iframeCommunicator.onTaskCheckboxChange(onTaskCheckedChange), [iframeCommunicator,
|
||||||
|
onTaskCheckedChange])
|
||||||
useEffect(() => iframeCommunicator.onImageClicked(setLightboxDetails), [iframeCommunicator])
|
useEffect(() => iframeCommunicator.onImageClicked(setLightboxDetails), [iframeCommunicator])
|
||||||
useEffect(() => iframeCommunicator.onRendererReady(() => setRendererReady(true)), [darkMode, iframeCommunicator, scrollState])
|
useEffect(() => iframeCommunicator.onRendererReady(() => setRendererReady(true)), [darkMode, iframeCommunicator,
|
||||||
|
scrollState])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (rendererReady) {
|
if (rendererReady) {
|
||||||
iframeCommunicator.sendSetDarkmode(darkMode)
|
iframeCommunicator.sendSetDarkmode(darkMode)
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const DeleteNoteSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ hi
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SidebarButton icon={"trash"} className={className} hide={hide} onClick={() => setShowDialog(true)}>
|
<SidebarButton icon={ 'trash' } className={ className } hide={ hide } onClick={ () => setShowDialog(true) }>
|
||||||
<Trans i18nKey={ 'landing.history.menu.deleteNote' }/>
|
<Trans i18nKey={ 'landing.history.menu.deleteNote' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<DeletionModal
|
<DeletionModal
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const DocumentInfoSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({c
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SidebarButton hide={hide} className={className} icon={"line-chart"} onClick={() => setShowModal(true)}>
|
<SidebarButton hide={ hide } className={ className } icon={ 'line-chart' } onClick={ () => setShowModal(true) }>
|
||||||
<Trans i18nKey={ 'editor.modal.documentInfo.title' }/>
|
<Trans i18nKey={ 'editor.modal.documentInfo.title' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<DocumentInfoModal show={ showModal } onHide={ () => setShowModal(false) }/>
|
<DocumentInfoModal show={ showModal } onHide={ () => setShowModal(false) }/>
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const ExportMarkdownSidebarEntry: React.FC = () => {
|
||||||
}, [markdownContent])
|
}, [markdownContent])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarButton data-cy={"menu-export-markdown"} onClick={onClick} icon={'file-text'}>
|
<SidebarButton data-cy={ 'menu-export-markdown' } onClick={ onClick } icon={ 'file-text' }>
|
||||||
<Trans i18nKey={ 'editor.export.markdown-file' }/>
|
<Trans i18nKey={ 'editor.export.markdown-file' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,28 +29,29 @@ export const ExportMenuSidebarMenu: React.FC<SpecificSidebarMenuProps> = (
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SidebarButton data-cy={"menu-export"} hide={hide} icon={expand ? "arrow-left" : "cloud-download"}
|
<SidebarButton data-cy={ 'menu-export' } hide={ hide } icon={ expand ? 'arrow-left' : 'cloud-download' }
|
||||||
className={ className } onClick={ onClickHandler }>
|
className={ className } onClick={ onClickHandler }>
|
||||||
<Trans i18nKey={ 'editor.documentBar.export' }/>
|
<Trans i18nKey={ 'editor.documentBar.export' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<SidebarMenu expand={ expand }>
|
<SidebarMenu expand={ expand }>
|
||||||
<SidebarButton icon={"github"}>
|
<SidebarButton icon={ 'github' }>
|
||||||
Gist
|
Gist
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<SidebarButton icon={"gitlab"}>
|
<SidebarButton icon={ 'gitlab' }>
|
||||||
Gitlab Snippet
|
Gitlab Snippet
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
|
|
||||||
<ExportMarkdownSidebarEntry/>
|
<ExportMarkdownSidebarEntry/>
|
||||||
|
|
||||||
<SidebarButton icon={"file-code-o"}>
|
<SidebarButton icon={ 'file-code-o' }>
|
||||||
HTML
|
HTML
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<SidebarButton icon={"file-code-o"}>
|
<SidebarButton icon={ 'file-code-o' }>
|
||||||
<Trans i18nKey='editor.export.rawHtml'/>
|
<Trans i18nKey='editor.export.rawHtml'/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<SidebarButton icon={"file-pdf-o"}>
|
<SidebarButton icon={ 'file-pdf-o' }>
|
||||||
<a className='small text-muted' dir={'auto'} href={links.faq} target={'_blank'} rel='noopener noreferrer'>
|
<a className='small text-muted' dir={ 'auto' } href={ links.faq } target={ '_blank' }
|
||||||
|
rel='noopener noreferrer'>
|
||||||
<Trans i18nKey={ 'editor.export.pdf' }/>
|
<Trans i18nKey={ 'editor.export.pdf' }/>
|
||||||
|
|
||||||
<span className={ 'text-primary' }>
|
<span className={ 'text-primary' }>
|
||||||
|
|
|
@ -39,10 +39,10 @@ export const ImportMarkdownSidebarEntry: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SidebarButton data-cy={"menu-import-markdown"} icon={"file-text-o"} onClick={buttonClick}>
|
<SidebarButton data-cy={ 'menu-import-markdown' } icon={ 'file-text-o' } onClick={ buttonClick }>
|
||||||
<Trans i18nKey={ 'editor.import.file' }/>
|
<Trans i18nKey={ 'editor.import.file' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<UploadInput onLoad={onImportMarkdown} data-cy={"menu-import-markdown-input"}
|
<UploadInput onLoad={ onImportMarkdown } data-cy={ 'menu-import-markdown-input' }
|
||||||
acceptedFiles={ '.md, text/markdown, text/plain' } onClickRef={ clickRef }/>
|
acceptedFiles={ '.md, text/markdown, text/plain' } onClickRef={ clickRef }/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,18 +29,18 @@ export const ImportMenuSidebarMenu: React.FC<SpecificSidebarMenuProps> = (
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SidebarButton data-cy={"menu-import"} hide={hide} icon={expand ? "arrow-left" : "cloud-upload"}
|
<SidebarButton data-cy={ 'menu-import' } hide={ hide } icon={ expand ? 'arrow-left' : 'cloud-upload' }
|
||||||
className={ className } onClick={ onClickHandler }>
|
className={ className } onClick={ onClickHandler }>
|
||||||
<Trans i18nKey={ 'editor.documentBar.import' }/>
|
<Trans i18nKey={ 'editor.documentBar.import' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<SidebarMenu expand={ expand }>
|
<SidebarMenu expand={ expand }>
|
||||||
<SidebarButton icon={"github"}>
|
<SidebarButton icon={ 'github' }>
|
||||||
Gist
|
Gist
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<SidebarButton icon={"gitlab"}>
|
<SidebarButton icon={ 'gitlab' }>
|
||||||
Gitlab Snippet
|
Gitlab Snippet
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<SidebarButton icon={"clipboard"}>
|
<SidebarButton icon={ 'clipboard' }>
|
||||||
<Trans i18nKey={ 'editor.import.clipboard' }/>
|
<Trans i18nKey={ 'editor.import.clipboard' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<ImportMarkdownSidebarEntry/>
|
<ImportMarkdownSidebarEntry/>
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const PermissionsSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({cl
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SidebarButton hide={hide} className={className} icon={"lock"} onClick={() => setShowModal(true)}>
|
<SidebarButton hide={ hide } className={ className } icon={ 'lock' } onClick={ () => setShowModal(true) }>
|
||||||
<Trans i18nKey={ 'editor.modal.permissions.title' }/>
|
<Trans i18nKey={ 'editor.modal.permissions.title' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<PermissionModal show={ showModal } onHide={ () => setShowModal(false) }/>
|
<PermissionModal show={ showModal } onHide={ () => setShowModal(false) }/>
|
||||||
|
|
|
@ -15,7 +15,7 @@ export const RevisionSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({class
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SidebarButton hide={hide} className={className} icon={"history"} onClick={() => setShowModal(true)}>
|
<SidebarButton hide={ hide } className={ className } icon={ 'history' } onClick={ () => setShowModal(true) }>
|
||||||
<Trans i18nKey={ 'editor.modal.revision.title' }/>
|
<Trans i18nKey={ 'editor.modal.revision.title' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<RevisionModal show={ showModal } onHide={ () => setShowModal(false) }/>
|
<RevisionModal show={ showModal } onHide={ () => setShowModal(false) }/>
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const ShareSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({classNam
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SidebarButton hide={hide} className={className} icon={"share"} onClick={() => setShowModal(true)}>
|
<SidebarButton hide={ hide } className={ className } icon={ 'share' } onClick={ () => setShowModal(true) }>
|
||||||
<Trans i18nKey={ 'editor.modal.shareLink.title' }/>
|
<Trans i18nKey={ 'editor.modal.shareLink.title' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<ShareModal show={ showModal } onHide={ () => setShowModal(false) }/>
|
<ShareModal show={ showModal } onHide={ () => setShowModal(false) }/>
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { IconName } from '../../common/fork-awesome/types'
|
||||||
import { ShowIf } from '../../common/show-if/show-if'
|
import { ShowIf } from '../../common/show-if/show-if'
|
||||||
import { SidebarEntryProps } from './types'
|
import { SidebarEntryProps } from './types'
|
||||||
|
|
||||||
export type SidebarEntryVariant = "primary"
|
export type SidebarEntryVariant = 'primary'
|
||||||
|
|
||||||
export const SidebarButton: React.FC<SidebarEntryProps> = ({ children, icon, className, variant, buttonRef, hide, ...props }) => {
|
export const SidebarButton: React.FC<SidebarEntryProps> = ({ children, icon, className, variant, buttonRef, hide, ...props }) => {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -14,5 +14,5 @@ export const SidebarMenu: React.FC<SidebarMenuProps> = ({children, expand}) => {
|
||||||
{ children }
|
{ children }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { PermissionsSidebarEntry } from './permissions-sidebar-entry'
|
||||||
import { PinNoteSidebarEntry } from './pin-note-sidebar-entry'
|
import { PinNoteSidebarEntry } from './pin-note-sidebar-entry'
|
||||||
import { RevisionSidebarEntry } from './revision-sidebar-entry'
|
import { RevisionSidebarEntry } from './revision-sidebar-entry'
|
||||||
import { ShareSidebarEntry } from './share-sidebar-entry'
|
import { ShareSidebarEntry } from './share-sidebar-entry'
|
||||||
import "./style/theme.scss"
|
import './style/theme.scss'
|
||||||
import { DocumentSidebarMenuSelection } from './types'
|
import { DocumentSidebarMenuSelection } from './types'
|
||||||
import { UsersOnlineSidebarMenu } from './users-online-sidebar-menu/users-online-sidebar-menu'
|
import { UsersOnlineSidebarMenu } from './users-online-sidebar-menu/users-online-sidebar-menu'
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export interface SidebarEntryProps {
|
||||||
hide?: boolean
|
hide?: boolean
|
||||||
className?: string
|
className?: string
|
||||||
onClick?: () => void
|
onClick?: () => void
|
||||||
"data-cy"?: string
|
'data-cy'?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SidebarMenuProps {
|
export interface SidebarMenuProps {
|
||||||
|
|
|
@ -10,7 +10,7 @@ export interface UploadInputProps {
|
||||||
onLoad: (file: File) => Promise<void>
|
onLoad: (file: File) => Promise<void>
|
||||||
acceptedFiles: string
|
acceptedFiles: string
|
||||||
onClickRef: MutableRefObject<(() => void) | undefined>
|
onClickRef: MutableRefObject<(() => void) | undefined>
|
||||||
"data-cy"?: string
|
'data-cy'?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UploadInput: React.FC<UploadInputProps> = ({ onLoad, acceptedFiles, onClickRef, ...props }) => {
|
export const UploadInput: React.FC<UploadInputProps> = ({ onLoad, acceptedFiles, onClickRef, ...props }) => {
|
||||||
|
@ -25,9 +25,11 @@ export const UploadInput: React.FC<UploadInputProps> = ({ onLoad, acceptedFiles,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const file = fileInput.files[0]
|
const file = fileInput.files[0]
|
||||||
onLoad(file).then(() => {
|
onLoad(file)
|
||||||
|
.then(() => {
|
||||||
fileInput.value = ''
|
fileInput.value = ''
|
||||||
}).catch((error) => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -39,6 +41,7 @@ export const UploadInput: React.FC<UploadInputProps> = ({ onLoad, acceptedFiles,
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<input data-cy={props["data-cy"]} type='file' ref={fileInputReference} className='d-none' accept={acceptedFiles}/>
|
<input data-cy={ props['data-cy'] } type='file' ref={ fileInputReference } className='d-none'
|
||||||
|
accept={ acceptedFiles }/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,9 @@ export const UserLine: React.FC<UserLineProps> = ({ name, photo, color, status }
|
||||||
return (
|
return (
|
||||||
<div className={ 'd-flex align-items-center h-100 w-100' }>
|
<div className={ 'd-flex align-items-center h-100 w-100' }>
|
||||||
<div className='d-inline-flex align-items-bottom user-line-color-indicator' style={ { borderLeftColor: color } }/>
|
<div className='d-inline-flex align-items-bottom user-line-color-indicator' style={ { borderLeftColor: color } }/>
|
||||||
<UserAvatar photo={photo} name={name} additionalClasses={'flex-fill overflow-hidden px-2 text-nowrap w-100'}/>
|
<UserAvatar photo={ photo } name={ name }
|
||||||
<div className={"active-indicator-container"}>
|
additionalClasses={ 'flex-fill overflow-hidden px-2 text-nowrap w-100' }/>
|
||||||
|
<div className={ 'active-indicator-container' }>
|
||||||
<ActiveIndicator status={ status }/>
|
<ActiveIndicator status={ status }/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -36,16 +36,19 @@ export const UsersOnlineSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SidebarButton hide={hide} buttonRef={buttonRef} onClick={onClickHandler} icon={expand ? "arrow-left" : "users"}
|
<SidebarButton hide={ hide } buttonRef={ buttonRef } onClick={ onClickHandler }
|
||||||
|
icon={ expand ? 'arrow-left' : 'users' }
|
||||||
variant={ 'primary' } className={ `online-entry ${ className ?? '' }` }>
|
variant={ 'primary' } className={ `online-entry ${ className ?? '' }` }>
|
||||||
<Trans i18nKey={ 'editor.onlineStatus.online' }/>
|
<Trans i18nKey={ 'editor.onlineStatus.online' }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<SidebarMenu expand={ expand }>
|
<SidebarMenu expand={ expand }>
|
||||||
<SidebarButton>
|
<SidebarButton>
|
||||||
<UserLine name="Philip Molares" photo="/img/avatar.png" color="red" status={ActiveIndicatorStatus.INACTIVE}/>
|
<UserLine name="Philip Molares" photo="/img/avatar.png" color="red"
|
||||||
|
status={ ActiveIndicatorStatus.INACTIVE }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
<SidebarButton>
|
<SidebarButton>
|
||||||
<UserLine name="Tilman Vatteroth" photo="/img/avatar.png" color="blue" status={ActiveIndicatorStatus.ACTIVE}/>
|
<UserLine name="Tilman Vatteroth" photo="/img/avatar.png" color="blue"
|
||||||
|
status={ ActiveIndicatorStatus.ACTIVE }/>
|
||||||
</SidebarButton>
|
</SidebarButton>
|
||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
@ -56,7 +56,8 @@ export const Splitter: React.FC<SplitterProps> = ({ containerClassName, left, ri
|
||||||
return (
|
return (
|
||||||
<div ref={ splitContainer } className={ `flex-fill flex-row d-flex ${ containerClassName || '' }` }
|
<div ref={ splitContainer } className={ `flex-fill flex-row d-flex ${ containerClassName || '' }` }
|
||||||
onMouseUp={ stopResizing } onTouchEnd={ stopResizing } onMouseMove={ onMouseMove } onTouchMove={ onTouchMove }>
|
onMouseUp={ stopResizing } onTouchEnd={ stopResizing } onMouseMove={ onMouseMove } onTouchMove={ onTouchMove }>
|
||||||
<div className={`splitter left ${!showLeft ? 'd-none' : ''}`} style={{ flexBasis: `calc(${realSplit}% - 5px)` }}>
|
<div className={ `splitter left ${ !showLeft ? 'd-none' : '' }` }
|
||||||
|
style={ { flexBasis: `calc(${ realSplit }% - 5px)` } }>
|
||||||
{ left }
|
{ left }
|
||||||
</div>
|
</div>
|
||||||
<ShowIf condition={ showLeft && showRight }>
|
<ShowIf condition={ showLeft && showRight }>
|
||||||
|
|
|
@ -19,7 +19,9 @@ export interface TableOfContentsProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const slugify = (content: string): string => {
|
export const slugify = (content: string): string => {
|
||||||
return encodeURIComponent(content.trim().toLowerCase().replace(/\s+/g, '-'))
|
return encodeURIComponent(content.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, '-'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const convertLevel = (toc: TocAst, levelsToShowUnderThis: number, headerCounts: Map<string, number>,
|
const convertLevel = (toc: TocAst, levelsToShowUnderThis: number, headerCounts: Map<string, number>,
|
||||||
|
@ -38,7 +40,8 @@ const convertLevel = (toc: TocAst, levelsToShowUnderThis: number, headerCounts:
|
||||||
const content = (
|
const content = (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<ShowIf condition={ toc.l > 0 }>
|
<ShowIf condition={ toc.l > 0 }>
|
||||||
<a href={headlineUrl} title={rawName} onClick={createJumpToMarkClickEventHandler(slug.substr(1))}>{rawName}</a>
|
<a href={ headlineUrl } title={ rawName }
|
||||||
|
onClick={ createJumpToMarkClickEventHandler(slug.substr(1)) }>{ rawName }</a>
|
||||||
</ShowIf>
|
</ShowIf>
|
||||||
<ShowIf condition={ toc.c.length > 0 }>
|
<ShowIf condition={ toc.c.length > 0 }>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -69,7 +72,8 @@ export const TableOfContents: React.FC<TableOfContentsProps> = ({
|
||||||
baseUrl
|
baseUrl
|
||||||
}) => {
|
}) => {
|
||||||
useTranslation()
|
useTranslation()
|
||||||
const tocTree = useMemo(() => convertLevel(ast, maxDepth, new Map<string, number>(), false, baseUrl), [ast, maxDepth, baseUrl])
|
const tocTree = useMemo(() => convertLevel(ast, maxDepth, new Map<string, number>(), false, baseUrl), [ast, maxDepth,
|
||||||
|
baseUrl])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ `markdown-toc ${ className ?? '' }` }>
|
<div className={ `markdown-toc ${ className ?? '' }` }>
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const isMac = navigator.platform.toLowerCase().includes('mac')
|
export const isMac = navigator.platform.toLowerCase()
|
||||||
|
.includes('mac')
|
||||||
|
|
|
@ -41,9 +41,11 @@ export class ErrorBoundary extends Component {
|
||||||
<Container className="text-light d-flex flex-column mvh-100">
|
<Container className="text-light d-flex flex-column mvh-100">
|
||||||
<div className='text-light d-flex flex-column align-items-center justify-content-center my-5'>
|
<div className='text-light d-flex flex-column align-items-center justify-content-center my-5'>
|
||||||
<h1>An unknown error occurred</h1>
|
<h1>An unknown error occurred</h1>
|
||||||
<p>Don't worry, this happens sometimes. If this is the first time you see this page then try reloading the app.</p>
|
<p>Don't worry, this happens sometimes. If this is the first time you see this page then try reloading the
|
||||||
|
app.</p>
|
||||||
If you can reproduce this error, then we would be glad if you 
|
If you can reproduce this error, then we would be glad if you 
|
||||||
<ExternalLink text={'open an issue on github'} href={frontendVersion.issueTrackerUrl} className={'text-primary'}/> 
|
<ExternalLink text={ 'open an issue on github' } href={ frontendVersion.issueTrackerUrl }
|
||||||
|
className={ 'text-primary' }/> 
|
||||||
or <ExternalLink text={ 'contact us on matrix.' } href={ links.chat } className={ 'text-primary' }/>
|
or <ExternalLink text={ 'contact us on matrix.' } href={ links.chat } className={ 'text-primary' }/>
|
||||||
<Button onClick={ () => this.refreshPage() } title={ 'Reload App' } className={ 'mt-4' }>
|
<Button onClick={ () => this.refreshPage() } title={ 'Reload App' } className={ 'mt-4' }>
|
||||||
<ForkAwesomeIcon icon={ 'refresh' }/> Reload App
|
<ForkAwesomeIcon icon={ 'refresh' }/> Reload App
|
||||||
|
|
|
@ -29,7 +29,8 @@ export const EntryMenu: React.FC<EntryMenuProps> = ({ id, title, location, isDar
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown className={ `d-inline-flex ${ className || '' }` }>
|
<Dropdown className={ `d-inline-flex ${ className || '' }` }>
|
||||||
<Dropdown.Toggle variant={isDark ? 'secondary' : 'light'} id={`dropdown-card-${id}`} className='no-arrow history-menu d-inline-flex align-items-center'>
|
<Dropdown.Toggle variant={ isDark ? 'secondary' : 'light' } id={ `dropdown-card-${ id }` }
|
||||||
|
className='no-arrow history-menu d-inline-flex align-items-center'>
|
||||||
<ForkAwesomeIcon icon="ellipsis-v" fixedWidth={ true }/>
|
<ForkAwesomeIcon icon="ellipsis-v" fixedWidth={ true }/>
|
||||||
</Dropdown.Toggle>
|
</Dropdown.Toggle>
|
||||||
|
|
||||||
|
|
|
@ -21,19 +21,22 @@ export const HistoryCard: React.FC<HistoryEntryProps> = ({ entry, onPinClick, on
|
||||||
<Card className="card-min-height" text={ 'dark' } bg={ 'light' }>
|
<Card className="card-min-height" text={ 'dark' } bg={ 'light' }>
|
||||||
<Card.Body className="p-2 d-flex flex-row justify-content-between">
|
<Card.Body className="p-2 d-flex flex-row justify-content-between">
|
||||||
<div className={ 'd-flex flex-column' }>
|
<div className={ 'd-flex flex-column' }>
|
||||||
<PinButton isDark={false} isPinned={entry.pinned} onPinClick={() => onPinClick(entry.id, entry.location)}/>
|
<PinButton isDark={ false } isPinned={ entry.pinned }
|
||||||
|
onPinClick={ () => onPinClick(entry.id, entry.location) }/>
|
||||||
</div>
|
</div>
|
||||||
<Link to={ `/n/${ entry.id }` } className="text-decoration-none flex-fill text-dark">
|
<Link to={ `/n/${ entry.id }` } className="text-decoration-none flex-fill text-dark">
|
||||||
<div className={ 'd-flex flex-column justify-content-between' }>
|
<div className={ 'd-flex flex-column justify-content-between' }>
|
||||||
<Card.Title className="m-0 mt-1dot5">{ entry.title }</Card.Title>
|
<Card.Title className="m-0 mt-1dot5">{ entry.title }</Card.Title>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-black-50 mt-2">
|
<div className="text-black-50 mt-2">
|
||||||
<ForkAwesomeIcon icon="clock-o"/> {DateTime.fromISO(entry.lastVisited).toRelative()}<br/>
|
<ForkAwesomeIcon icon="clock-o"/> { DateTime.fromISO(entry.lastVisited)
|
||||||
|
.toRelative() }<br/>
|
||||||
{ formatHistoryDate(entry.lastVisited) }
|
{ formatHistoryDate(entry.lastVisited) }
|
||||||
</div>
|
</div>
|
||||||
<div className={ 'card-footer-min-height p-0' }>
|
<div className={ 'card-footer-min-height p-0' }>
|
||||||
{
|
{
|
||||||
entry.tags.map((tag) => <Badge variant={'dark'} className={'mr-1 mb-1'} key={tag}>{tag}</Badge>)
|
entry.tags.map((tag) => <Badge variant={ 'dark' } className={ 'mr-1 mb-1' }
|
||||||
|
key={ tag }>{ tag }</Badge>)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,7 +28,8 @@ export const HistoryTableRow: React.FC<HistoryEntryProps> = ({ entry, onPinClick
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<PinButton isDark={true} isPinned={entry.pinned} onPinClick={() => onPinClick(entry.id, entry.location)} className={'mb-1 mr-1'}/>
|
<PinButton isDark={ true } isPinned={ entry.pinned } onPinClick={ () => onPinClick(entry.id, entry.location) }
|
||||||
|
className={ 'mb-1 mr-1' }/>
|
||||||
<EntryMenu
|
<EntryMenu
|
||||||
id={ entry.id }
|
id={ entry.id }
|
||||||
title={ entry.title }
|
title={ entry.title }
|
||||||
|
|
|
@ -92,7 +92,8 @@ export const HistoryToolbar: React.FC<HistoryToolbarProps> = ({ onSettingsChange
|
||||||
return (
|
return (
|
||||||
<Form inline={ true }>
|
<Form inline={ true }>
|
||||||
<InputGroup className={ 'mr-1 mb-1' }>
|
<InputGroup className={ 'mr-1 mb-1' }>
|
||||||
<Typeahead id={'tagsSelection'} options={tags} multiple={true} placeholder={t('landing.history.toolbar.selectTags')}
|
<Typeahead id={ 'tagsSelection' } options={ tags } multiple={ true }
|
||||||
|
placeholder={ t('landing.history.toolbar.selectTags') }
|
||||||
onChange={ selectedTagsChanged }/>
|
onChange={ selectedTagsChanged }/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<InputGroup className={ 'mr-1 mb-1' }>
|
<InputGroup className={ 'mr-1 mb-1' }>
|
||||||
|
@ -103,7 +104,8 @@ export const HistoryToolbar: React.FC<HistoryToolbarProps> = ({ onSettingsChange
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<InputGroup className={ 'mr-1 mb-1' }>
|
<InputGroup className={ 'mr-1 mb-1' }>
|
||||||
<SortButton onDirectionChange={titleSortChanged} direction={state.titleSortDirection} variant={'light'}><Trans
|
<SortButton onDirectionChange={ titleSortChanged } direction={ state.titleSortDirection }
|
||||||
|
variant={ 'light' }><Trans
|
||||||
i18nKey={ 'landing.history.toolbar.sortByTitle' }/></SortButton>
|
i18nKey={ 'landing.history.toolbar.sortByTitle' }/></SortButton>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<InputGroup className={ 'mr-1 mb-1' }>
|
<InputGroup className={ 'mr-1 mb-1' }>
|
||||||
|
@ -136,10 +138,12 @@ export const HistoryToolbar: React.FC<HistoryToolbarProps> = ({ onSettingsChange
|
||||||
onChange={ (newViewState: ViewStateEnum) => {
|
onChange={ (newViewState: ViewStateEnum) => {
|
||||||
toggleViewChanged(newViewState)
|
toggleViewChanged(newViewState)
|
||||||
} }>
|
} }>
|
||||||
<ToggleButton className={'btn-light'} value={ViewStateEnum.CARD} title={t('landing.history.toolbar.cards')}>
|
<ToggleButton className={ 'btn-light' } value={ ViewStateEnum.CARD }
|
||||||
|
title={ t('landing.history.toolbar.cards') }>
|
||||||
<ForkAwesomeIcon icon={ 'sticky-note' } className={ 'fa-fix-line-height' }/>
|
<ForkAwesomeIcon icon={ 'sticky-note' } className={ 'fa-fix-line-height' }/>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
<ToggleButton className={'btn-light'} value={ViewStateEnum.TABLE} title={t('landing.history.toolbar.table')}>
|
<ToggleButton className={ 'btn-light' } value={ ViewStateEnum.TABLE }
|
||||||
|
title={ t('landing.history.toolbar.table') }>
|
||||||
<ForkAwesomeIcon icon={ 'table' } className={ 'fa-fix-line-height' }/>
|
<ForkAwesomeIcon icon={ 'table' } className={ 'fa-fix-line-height' }/>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
</ToggleButtonGroup>
|
</ToggleButtonGroup>
|
||||||
|
|
|
@ -50,5 +50,6 @@ export const SortButton: React.FC<SortButtonProps> = ({ children, variant, onDir
|
||||||
onDirectionChange(toggleDirection(direction))
|
onDirectionChange(toggleDirection(direction))
|
||||||
}
|
}
|
||||||
|
|
||||||
return <IconButton onClick={toggleSort} variant={variant} icon={getIcon(direction)} border={true}>{children}</IconButton>
|
return <IconButton onClick={ toggleSort } variant={ variant } icon={ getIcon(direction) }
|
||||||
|
border={ true }>{ children }</IconButton>
|
||||||
}
|
}
|
||||||
|
|