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>
103
.editorconfig
|
@ -51,31 +51,39 @@ ij_scss_hex_color_upper_case = false
|
|||
ij_scss_keep_blank_lines_in_code = 2
|
||||
ij_scss_keep_indents_on_empty_lines = false
|
||||
ij_scss_keep_single_line_blocks = false
|
||||
ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||
ij_scss_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow
|
||||
ij_scss_space_after_colon = true
|
||||
ij_scss_space_before_opening_brace = true
|
||||
ij_scss_use_double_quotes = true
|
||||
ij_scss_value_alignment = 0
|
||||
|
||||
[{*.ats,*.ts,*.tsx}]
|
||||
[.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}]
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
ij_continuation_indent_size = 2
|
||||
ij_typescript_align_imports = false
|
||||
ij_typescript_align_multiline_array_initializer_expression = 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_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_ternary_operation = false
|
||||
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_array_initializer_new_line_after_left_brace = 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_binary_operation_sign_on_next_line = false
|
||||
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_class_brace_style = end_of_line
|
||||
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_enforce_trailing_comma = keep
|
||||
ij_typescript_enforce_trailing_comma = remove
|
||||
ij_typescript_extends_keyword_wrap = off
|
||||
ij_typescript_extends_list_wrap = off
|
||||
ij_typescript_field_prefix = _
|
||||
ij_typescript_file_name_style = relaxed
|
||||
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_right_paren_on_new_line = false
|
||||
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_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_prefer_absolute_path = global
|
||||
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_imports_wrap = on_every_item
|
||||
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_jsdoc_include_types = false
|
||||
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_indents_on_empty_lines = false
|
||||
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_at_first_column = false
|
||||
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_right_paren_on_new_line = false
|
||||
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_right_paren_on_new_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_vars_fields = 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_comma = true
|
||||
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_method_call_parentheses = false
|
||||
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_quest = 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_if_parentheses = false
|
||||
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_parentheses = false
|
||||
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_ternary_operation_signs_on_next_line = false
|
||||
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_double_quotes = false
|
||||
ij_typescript_use_explicit_js_extension = global
|
||||
ij_typescript_use_path_mapping = always
|
||||
ij_typescript_use_public_modifier = false
|
||||
ij_typescript_use_semicolon_after_statement = false
|
||||
ij_typescript_var_declaration_wrap = normal
|
||||
ij_typescript_while_brace_force = never
|
||||
ij_typescript_var_declaration_wrap = on_every_item
|
||||
ij_typescript_while_brace_force = always
|
||||
ij_typescript_while_on_new_line = 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_right_paren_on_new_line = false
|
||||
ij_javascript_for_statement_wrap = off
|
||||
ij_javascript_force_quote_style = true
|
||||
ij_javascript_force_semicolon_style = true
|
||||
ij_javascript_force_quote_style = false
|
||||
ij_javascript_force_semicolon_style = false
|
||||
ij_javascript_function_expression_brace_style = end_of_line
|
||||
ij_javascript_if_brace_force = never
|
||||
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_package_children = 0
|
||||
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_indents_on_empty_lines = false
|
||||
ij_javascript_keep_line_breaks = true
|
||||
ij_javascript_keep_simple_blocks_in_one_line = true
|
||||
ij_javascript_keep_simple_methods_in_one_line = true
|
||||
ij_javascript_keep_simple_blocks_in_one_line = false
|
||||
ij_javascript_keep_simple_methods_in_one_line = false
|
||||
ij_javascript_line_comment_add_space = true
|
||||
ij_javascript_line_comment_at_first_column = false
|
||||
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_semicolon = false
|
||||
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_parentheses = true
|
||||
ij_javascript_space_before_method_call_parentheses = false
|
||||
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_quest = 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_for_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_method_call_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_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_while_parentheses = false
|
||||
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_union_types_wrap = on_every_item
|
||||
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_path_mapping = always
|
||||
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_while_brace_force = never
|
||||
ij_javascript_while_on_new_line = false
|
||||
ij_javascript_wrap_comments = false
|
||||
|
||||
[{*.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_indents_on_empty_lines = false
|
||||
ij_json_keep_line_breaks = true
|
||||
|
@ -423,7 +431,7 @@ ij_html_keep_indents_on_empty_lines = false
|
|||
ij_html_keep_line_breaks = true
|
||||
ij_html_keep_line_breaks_in_text = true
|
||||
ij_html_keep_whitespaces = false
|
||||
ij_html_keep_whitespaces_inside = span,pre,textarea
|
||||
ij_html_keep_whitespaces_inside = span, pre, textarea
|
||||
ij_html_line_comment_at_first_column = true
|
||||
ij_html_new_line_after_last_attribute = never
|
||||
ij_html_new_line_before_first_attribute = never
|
||||
|
@ -433,9 +441,30 @@ ij_html_space_after_tag_name = false
|
|||
ij_html_space_around_equality_in_attribute = false
|
||||
ij_html_space_inside_empty_tag = false
|
||||
ij_html_text_wrap = normal
|
||||
ij_html_uniform_ident = false
|
||||
|
||||
[{*.yaml,*.yml}]
|
||||
[{*.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}]
|
||||
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_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')
|
||||
.click()
|
||||
.then(() => {
|
||||
expect(localStorage.getItem('bannerTimeStamp')).to.equal(banner.timestamp)
|
||||
expect(localStorage.getItem('bannerTimeStamp'))
|
||||
.to
|
||||
.equal(banner.timestamp)
|
||||
})
|
||||
cy.get('.alert-primary.show')
|
||||
.should('not.exist')
|
||||
|
|
|
@ -16,73 +16,73 @@ describe('Document Title', () => {
|
|||
|
||||
describe('title should be yaml metadata title', () => {
|
||||
it('just yaml metadata title', () => {
|
||||
cy.codemirrorFill(`---\ntitle: ${title}\n---`)
|
||||
cy.codemirrorFill(`---\ntitle: ${ title }\n---`)
|
||||
cy.title()
|
||||
.should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
|
||||
it('yaml metadata title and opengraph title', () => {
|
||||
cy.codemirrorFill(`---\ntitle: ${title}\nopengraph:\n title: False title\n---`)
|
||||
cy.codemirrorFill(`---\ntitle: ${ title }\nopengraph:\n title: False title\n---`)
|
||||
cy.title()
|
||||
.should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
|
||||
it('yaml metadata title, opengraph title and first heading', () => {
|
||||
cy.codemirrorFill(`---\ntitle: ${title}\nopengraph:\n title: False title\n---\n# a first title`)
|
||||
cy.codemirrorFill(`---\ntitle: ${ title }\nopengraph:\n title: False title\n---\n# a first title`)
|
||||
cy.title()
|
||||
.should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('title should be opengraph title', () => {
|
||||
it('just opengraph title', () => {
|
||||
cy.codemirrorFill(`---\nopengraph:\n title: ${title}\n---`)
|
||||
cy.codemirrorFill(`---\nopengraph:\n title: ${ title }\n---`)
|
||||
cy.title()
|
||||
.should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
|
||||
it('opengraph title and first heading', () => {
|
||||
cy.codemirrorFill(`---\nopengraph:\n title: ${title}\n---\n# a first title`)
|
||||
cy.codemirrorFill(`---\nopengraph:\n title: ${ title }\n---\n# a first title`)
|
||||
cy.title()
|
||||
.should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('title should be first heading', () => {
|
||||
it('just first heading', () => {
|
||||
cy.codemirrorFill(`# ${title}`)
|
||||
cy.codemirrorFill(`# ${ title }`)
|
||||
cy.title()
|
||||
.should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
|
||||
it('just first heading with alt-text instead of image', () => {
|
||||
cy.codemirrorFill(`# ${title} ![abc](https://dummyimage.com/48)`)
|
||||
cy.codemirrorFill(`# ${ title } ![abc](https://dummyimage.com/48)`)
|
||||
cy.title()
|
||||
.should('eq', `${title} abc - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } abc - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
|
||||
it('just first heading without link syntax', () => {
|
||||
cy.codemirrorFill(`# ${title} [link](https://hedgedoc.org)`)
|
||||
cy.codemirrorFill(`# ${ title } [link](https://hedgedoc.org)`)
|
||||
cy.title()
|
||||
.should('eq', `${title} link - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } link - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
|
||||
it('markdown syntax removed first', () => {
|
||||
cy.codemirrorFill(`# ${title} 1*2*3 4*5**`)
|
||||
cy.codemirrorFill(`# ${ title } 1*2*3 4*5**`)
|
||||
cy.title()
|
||||
.should('eq', `${title} 123 4*5** - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } 123 4*5** - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
|
||||
it('markdown syntax removed second', () => {
|
||||
cy.codemirrorFill(`# ${title} **1 2*`)
|
||||
cy.codemirrorFill(`# ${ title } **1 2*`)
|
||||
cy.title()
|
||||
.should('eq', `${title} *1 2 - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } *1 2 - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
|
||||
it('markdown syntax removed third', () => {
|
||||
cy.codemirrorFill(`# ${title} _asd_`)
|
||||
cy.codemirrorFill(`# ${ title } _asd_`)
|
||||
cy.title()
|
||||
.should('eq', `${title} asd - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `${ title } asd - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
|
||||
it('katex code looks right', () => {
|
||||
|
@ -93,7 +93,7 @@ describe('Document Title', () => {
|
|||
cy.get('.CodeMirror textarea')
|
||||
.type('{Enter}{Enter}{Enter}{Enter}{Enter}') //This is a workaround because I don't know how to make sure, that the title gets updated in time.
|
||||
cy.title()
|
||||
.should('eq', `α-foo - HedgeDoc @ ${branding.name}`)
|
||||
.should('eq', `α-foo - HedgeDoc @ ${ branding.name }`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
describe('Export', () => {
|
||||
const testTitle = 'testContent'
|
||||
const testContent = `---\ntitle: ${testTitle}\n---\nThis is some test content`
|
||||
const testContent = `---\ntitle: ${ testTitle }\n---\nThis is some test content`
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visitTestEditor()
|
||||
|
|
|
@ -45,35 +45,40 @@ describe('File upload', () => {
|
|||
cy.get('div.btn-group > input[type=file]')
|
||||
.attachFile({ filePath: 'acme.png', mimeType: 'image/png' })
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `![](${imageUrl})`)
|
||||
.should('have.text', `![](${ imageUrl })`)
|
||||
})
|
||||
|
||||
it('via paste', () => {
|
||||
cy.fixture('acme.png').then((image: string) => {
|
||||
const pasteEvent = {
|
||||
clipboardData: {
|
||||
files: [Cypress.Blob.base64StringToBlob(image, 'image/png')]
|
||||
cy.fixture('acme.png')
|
||||
.then((image: string) => {
|
||||
const pasteEvent = {
|
||||
clipboardData: {
|
||||
files: [Cypress.Blob.base64StringToBlob(image, 'image/png')]
|
||||
}
|
||||
}
|
||||
}
|
||||
cy.get('.CodeMirror-scroll').trigger('paste', pasteEvent)
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `![](${imageUrl})`)
|
||||
})
|
||||
cy.get('.CodeMirror-scroll')
|
||||
.trigger('paste', pasteEvent)
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `![](${ imageUrl })`)
|
||||
})
|
||||
})
|
||||
|
||||
it('via drag and drop', () => {
|
||||
cy.fixture('acme.png').then((image: string) => {
|
||||
const dropEvent = {
|
||||
dataTransfer: {
|
||||
files: [Cypress.Blob.base64StringToBlob(image, 'image/png')],
|
||||
effectAllowed: 'uninitialized'
|
||||
cy.fixture('acme.png')
|
||||
.then((image: string) => {
|
||||
const dropEvent = {
|
||||
dataTransfer: {
|
||||
files: [Cypress.Blob.base64StringToBlob(image, 'image/png')],
|
||||
effectAllowed: 'uninitialized'
|
||||
}
|
||||
}
|
||||
}
|
||||
cy.get('.CodeMirror-scroll').trigger('dragenter', dropEvent)
|
||||
cy.get('.CodeMirror-scroll').trigger('drop', dropEvent)
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `![](${imageUrl})`)
|
||||
})
|
||||
cy.get('.CodeMirror-scroll')
|
||||
.trigger('dragenter', dropEvent)
|
||||
cy.get('.CodeMirror-scroll')
|
||||
.trigger('drop', dropEvent)
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `![](${ imageUrl })`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -86,10 +91,11 @@ describe('File upload', () => {
|
|||
})
|
||||
cy.get('.fa-upload')
|
||||
.click()
|
||||
cy.fixture('acme.png').then(() => {
|
||||
cy.get('input[type=file]')
|
||||
.attachFile({ filePath: 'acme.png', mimeType: 'image/png' })
|
||||
})
|
||||
cy.fixture('acme.png')
|
||||
.then(() => {
|
||||
cy.get('input[type=file]')
|
||||
.attachFile({ filePath: 'acme.png', mimeType: 'image/png' })
|
||||
})
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span > span')
|
||||
.should('have.text', String.fromCharCode(8203)) //thanks codemirror....
|
||||
})
|
||||
|
@ -101,8 +107,9 @@ describe('File upload', () => {
|
|||
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')
|
||||
.should('have.text', `${testText}`)
|
||||
.should('have.text', `${ testText }`)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
const findHljsCodeBlock = () => {
|
||||
return cy.getMarkdownBody()
|
||||
.find('pre > code.hljs')
|
||||
.should('be.visible')
|
||||
.find('pre > code.hljs')
|
||||
.should('be.visible')
|
||||
}
|
||||
|
||||
describe('Code', () => {
|
||||
|
@ -160,14 +160,15 @@ describe('Code', () => {
|
|||
return cy.wrap(null)
|
||||
}
|
||||
|
||||
cy.spy(frame.contentWindow.navigator.clipboard, 'writeText').as("copy")
|
||||
cy.spy(frame.contentWindow.navigator.clipboard, 'writeText')
|
||||
.as('copy')
|
||||
})
|
||||
|
||||
cy.getMarkdownRenderer()
|
||||
.find('[data-cy="copy-code-button"]')
|
||||
.click()
|
||||
|
||||
cy.get("@copy")
|
||||
cy.get('@copy')
|
||||
.should('be.calledWithExactly', 'let x = 0\n')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -17,7 +17,8 @@ describe('Languages', () => {
|
|||
cy.get('@languages')
|
||||
.should('have.length', 28)
|
||||
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', () => {
|
||||
it('New note', () => {
|
||||
cy.get('.d-inline-flex.btn-primary').click()
|
||||
cy.get('.d-inline-flex.btn-primary')
|
||||
.click()
|
||||
cy.url()
|
||||
.should('include', '/new')
|
||||
})
|
||||
|
||||
describe('User Menu', () => {
|
||||
beforeEach(() => {
|
||||
cy.get('#dropdown-user').click()
|
||||
cy.get('#dropdown-user')
|
||||
.click()
|
||||
})
|
||||
|
||||
it('Features', () => {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
describe('The status bar text length info', () => {
|
||||
const warningTestContent = ('0123456789'.repeat(10))
|
||||
const dangerTestContent = ('0123456789'.repeat(20))
|
||||
const tooMuchTestContent = `${dangerTestContent}a`
|
||||
const tooMuchTestContent = `${ dangerTestContent }a`
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visitTestEditor()
|
||||
|
|
|
@ -12,7 +12,7 @@ describe('profile page', () => {
|
|||
}, {
|
||||
body: [
|
||||
{
|
||||
label: "cypress-App",
|
||||
label: 'cypress-App',
|
||||
created: 1601991518
|
||||
}
|
||||
]
|
||||
|
|
|
@ -21,7 +21,7 @@ describe('Toolbar Buttons', () => {
|
|||
beforeEach(() => {
|
||||
cy.codemirrorFill(testText)
|
||||
cy.get('.CodeMirror-line > span')
|
||||
.should("exist")
|
||||
.should('exist')
|
||||
.should('have.text', testText)
|
||||
})
|
||||
|
||||
|
@ -35,42 +35,42 @@ describe('Toolbar Buttons', () => {
|
|||
cy.get('.btn-toolbar [data-cy="format-bold"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `**${testText}**`)
|
||||
.should('have.text', `**${ testText }**`)
|
||||
})
|
||||
|
||||
it('should format as italic', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-italic"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `*${testText}*`)
|
||||
.should('have.text', `*${ testText }*`)
|
||||
})
|
||||
|
||||
it('should format as underline', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-underline"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `++${testText}++`)
|
||||
.should('have.text', `++${ testText }++`)
|
||||
})
|
||||
|
||||
it('should format as strikethrough', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-strikethrough"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `~~${testText}~~`)
|
||||
.should('have.text', `~~${ testText }~~`)
|
||||
})
|
||||
|
||||
it('should format as subscript', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-subscript"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `~${testText}~`)
|
||||
.should('have.text', `~${ testText }~`)
|
||||
})
|
||||
|
||||
it('should format as superscript', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-superscript"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `^${testText}^`)
|
||||
.should('have.text', `^${ testText }^`)
|
||||
})
|
||||
|
||||
it('should format the line as code block', () => {
|
||||
|
@ -88,14 +88,14 @@ describe('Toolbar Buttons', () => {
|
|||
cy.get('.btn-toolbar [data-cy="format-link"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `[${testText}](https://)`)
|
||||
.should('have.text', `[${ testText }](https://)`)
|
||||
})
|
||||
|
||||
it('should format as image', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-image"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `![${testText}](https://)`)
|
||||
.should('have.text', `![${ testText }](https://)`)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -103,11 +103,11 @@ describe('Toolbar Buttons', () => {
|
|||
cy.get('.btn-toolbar [data-cy="format-heading"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `# ${testText}`)
|
||||
.should('have.text', `# ${ testText }`)
|
||||
cy.get('.fa-header')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `## ${testText}`)
|
||||
.should('have.text', `## ${ testText }`)
|
||||
})
|
||||
|
||||
it('should format the line as code', () => {
|
||||
|
@ -125,58 +125,58 @@ describe('Toolbar Buttons', () => {
|
|||
cy.get('.btn-toolbar [data-cy="format-block-quote"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `> ${testText}`)
|
||||
.should('have.text', `> ${ testText }`)
|
||||
cy.get('.btn-toolbar [data-cy="format-block-quote"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `> > ${testText}`)
|
||||
.should('have.text', `> > ${ testText }`)
|
||||
})
|
||||
|
||||
it('should format as unordered list', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-unordered-list"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `- ${testText}`)
|
||||
.should('have.text', `- ${ testText }`)
|
||||
cy.get('.btn-toolbar [data-cy="format-unordered-list"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `- - ${testText}`)
|
||||
.should('have.text', `- - ${ testText }`)
|
||||
})
|
||||
|
||||
it('should format as ordered list', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-ordered-list"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `1. ${testText}`)
|
||||
.should('have.text', `1. ${ testText }`)
|
||||
cy.get('.btn-toolbar [data-cy="format-ordered-list"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `1. 1. ${testText}`)
|
||||
.should('have.text', `1. 1. ${ testText }`)
|
||||
})
|
||||
|
||||
it('should format as check list', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-check-list"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `- [ ] ${testText}`)
|
||||
.should('have.text', `- [ ] ${ testText }`)
|
||||
cy.get('.btn-toolbar [data-cy="format-check-list"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `- [ ] - [ ] ${testText}`)
|
||||
.should('have.text', `- [ ] - [ ] ${ testText }`)
|
||||
})
|
||||
|
||||
it('should insert links', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-link"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `${testText}[](https://)`)
|
||||
.should('have.text', `${ testText }[](https://)`)
|
||||
})
|
||||
|
||||
it('should insert an empty image link', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-image"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `${testText}![](https://)`)
|
||||
.should('have.text', `${ testText }![](https://)`)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -184,7 +184,7 @@ describe('Toolbar Buttons', () => {
|
|||
beforeEach(() => {
|
||||
cy.codemirrorFill(testLink)
|
||||
cy.get('.CodeMirror-line > span')
|
||||
.should("exist")
|
||||
.should('exist')
|
||||
.should('have.text', testLink)
|
||||
cy.get('@codeinput')
|
||||
.type('{ctrl}a')
|
||||
|
@ -194,14 +194,14 @@ describe('Toolbar Buttons', () => {
|
|||
cy.get('.btn-toolbar [data-cy="format-link"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `[](${testLink})`)
|
||||
.should('have.text', `[](${ testLink })`)
|
||||
})
|
||||
|
||||
it('should format as image', () => {
|
||||
cy.get('.btn-toolbar [data-cy="format-image"]')
|
||||
.click()
|
||||
cy.get('.CodeMirror-activeline > .CodeMirror-line > span')
|
||||
.should('have.text', `![](${testLink})`)
|
||||
.should('have.text', `![](${ testLink })`)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -11,11 +11,12 @@ declare namespace Cypress {
|
|||
* Custom command to check an external Link.
|
||||
* @example cy.get(a#extern).checkExternalLink('http://example.com')
|
||||
*/
|
||||
checkExternalLink (url: string): Chainable<Element>
|
||||
checkExternalLink(url: string): Chainable<Element>
|
||||
}
|
||||
}
|
||||
|
||||
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')
|
||||
})
|
||||
|
|
|
@ -50,9 +50,9 @@ beforeEach(() => {
|
|||
sourceCodeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
||||
issueTrackerUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
|
||||
},
|
||||
"iframeCommunication": {
|
||||
"editorOrigin": "http://127.0.0.1:3001",
|
||||
"rendererOrigin": "http://127.0.0.1:3001"
|
||||
'iframeCommunication': {
|
||||
'editorOrigin': 'http://127.0.0.1:3001',
|
||||
'rendererOrigin': 'http://127.0.0.1:3001'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -11,8 +11,9 @@ declare namespace Cypress {
|
|||
* Custom command to fill an input field with text and trigger a change event.
|
||||
* @example cy.get(input).fill('content')
|
||||
*/
|
||||
fill (value: string): Chainable<Element>
|
||||
codemirrorFill (value: string): Chainable<Element>
|
||||
fill(value: string): Chainable<Element>
|
||||
|
||||
codemirrorFill(value: string): Chainable<Element>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,17 +21,18 @@ Cypress.Commands.add('fill', {
|
|||
prevSubject: 'element'
|
||||
}, (subject, value) => {
|
||||
return cy.wrap(subject)
|
||||
.invoke('val', value)
|
||||
.trigger('change', { force: true })
|
||||
.invoke('val', value)
|
||||
.trigger('change', { force: true })
|
||||
})
|
||||
|
||||
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')
|
||||
.click()
|
||||
.get('textarea')
|
||||
.fill(content)
|
||||
if(line) {
|
||||
if (line) {
|
||||
cy.get('.CodeMirror')
|
||||
.contains('.CodeMirror-line', line)
|
||||
}
|
||||
|
|
|
@ -6,22 +6,22 @@
|
|||
|
||||
declare namespace Cypress {
|
||||
interface Chainable {
|
||||
getMarkdownRenderer (): Chainable<Element>
|
||||
getMarkdownRenderer(): Chainable<Element>
|
||||
|
||||
getMarkdownBody (): Chainable<Element>
|
||||
getMarkdownBody(): Chainable<Element>
|
||||
}
|
||||
}
|
||||
|
||||
Cypress.Commands.add('getMarkdownRenderer', () => {
|
||||
return cy.get(`iframe[data-cy="documentIframe"]`)
|
||||
.its('0.contentDocument')
|
||||
.should('exist')
|
||||
.its('body')
|
||||
.should('not.be.undefined')
|
||||
.then(cy.wrap.bind(cy))
|
||||
.its('0.contentDocument')
|
||||
.should('exist')
|
||||
.its('body')
|
||||
.should('not.be.undefined')
|
||||
.then(cy.wrap.bind(cy))
|
||||
})
|
||||
|
||||
Cypress.Commands.add('getMarkdownBody', () => {
|
||||
return cy.getMarkdownRenderer()
|
||||
.find('.markdown-body')
|
||||
.find('.markdown-body')
|
||||
})
|
||||
|
|
|
@ -11,11 +11,13 @@ declare namespace Cypress {
|
|||
* Custom command to log the user out.
|
||||
* @example cy.logout()
|
||||
*/
|
||||
logout (): Chainable<Window>
|
||||
logout(): Chainable<Window>
|
||||
}
|
||||
}
|
||||
|
||||
Cypress.Commands.add('logout', () => {
|
||||
cy.get('#dropdown-user').click()
|
||||
cy.get('.fa-sign-out').click()
|
||||
cy.get('#dropdown-user')
|
||||
.click()
|
||||
cy.get('.fa-sign-out')
|
||||
.click()
|
||||
})
|
||||
|
|
|
@ -6,28 +6,28 @@
|
|||
|
||||
declare namespace Cypress {
|
||||
interface Chainable {
|
||||
visitTestEditor (query?: string): Chainable<Cypress.AUTWindow>
|
||||
visitTestEditor(query?: string): Chainable<Cypress.AUTWindow>
|
||||
}
|
||||
}
|
||||
|
||||
export const testNoteId = 'test'
|
||||
|
||||
Cypress.Commands.add('visitTestEditor', (query?: string) => {
|
||||
return cy.visit(`/n/${testNoteId}${query ? `?${query}` : ''}`)
|
||||
return cy.visit(`/n/${ testNoteId }${ query ? `?${ query }` : '' }`)
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
cy.intercept(`/api/v2/notes/${testNoteId}-get`, {
|
||||
"id": "ABC123",
|
||||
"alias": "banner",
|
||||
"lastChange": {
|
||||
"userId": "test",
|
||||
"timestamp": 1600033920
|
||||
cy.intercept(`/api/v2/notes/${ testNoteId }-get`, {
|
||||
'id': 'ABC123',
|
||||
'alias': 'banner',
|
||||
'lastChange': {
|
||||
'userId': 'test',
|
||||
'timestamp': 1600033920
|
||||
},
|
||||
"viewCount": 0,
|
||||
"createTime": 1600033920,
|
||||
"content": "",
|
||||
"authorship": [],
|
||||
"preVersionTwoNote": true
|
||||
'viewCount': 0,
|
||||
'createTime': 1600033920,
|
||||
'content': '',
|
||||
'authorship': [],
|
||||
'preVersionTwoNote': true
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3,8 +3,15 @@
|
|||
"strict": true,
|
||||
"baseUrl": "../node_modules",
|
||||
"target": "es6",
|
||||
"lib": ["es6", "dom"],
|
||||
"types": ["cypress" ,"cypress-commands", "cypress-file-upload"]
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"types": [
|
||||
"cypress",
|
||||
"cypress-commands",
|
||||
"cypress-file-upload"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
|
|
|
@ -25,7 +25,7 @@ export interface Note {
|
|||
export const getNote = async (noteId: string): Promise<Note> => {
|
||||
// The "-get" suffix is necessary, because in our mock api (filesystem) the note id might already be a folder.
|
||||
// TODO: [mrdrogdrog] replace -get with actual api route as soon as api backend is ready.
|
||||
const response = await fetch(getApiUrl() + `/notes/${noteId}-get`, {
|
||||
const response = await fetch(getApiUrl() + `/notes/${ noteId }-get`, {
|
||||
...defaultFetchConfig
|
||||
})
|
||||
expectResponseCode(response)
|
||||
|
@ -33,7 +33,7 @@ export const getNote = async (noteId: string): Promise<Note> => {
|
|||
}
|
||||
|
||||
export const deleteNote = async (noteId: string): Promise<void> => {
|
||||
const response = await fetch(getApiUrl() + `/notes/${noteId}`, {
|
||||
const response = await fetch(getApiUrl() + `/notes/${ noteId }`, {
|
||||
...defaultFetchConfig,
|
||||
method: 'DELETE'
|
||||
})
|
||||
|
|
|
@ -11,11 +11,11 @@ import { Revision, RevisionListEntry } from './types'
|
|||
const revisionCache = new Cache<string, Revision>(3600)
|
||||
|
||||
export const getRevision = async (noteId: string, timestamp: number): Promise<Revision> => {
|
||||
const cacheKey = `${noteId}:${timestamp}`
|
||||
const cacheKey = `${ noteId }:${ timestamp }`
|
||||
if (revisionCache.has(cacheKey)) {
|
||||
return revisionCache.get(cacheKey)
|
||||
}
|
||||
const response = await fetch(getApiUrl() + `/notes/${noteId}/revisions/${timestamp}`, {
|
||||
const response = await fetch(getApiUrl() + `/notes/${ noteId }/revisions/${ timestamp }`, {
|
||||
...defaultFetchConfig
|
||||
})
|
||||
expectResponseCode(response)
|
||||
|
@ -26,7 +26,7 @@ export const getRevision = async (noteId: string, timestamp: number): Promise<Re
|
|||
|
||||
export const getAllRevisions = async (noteId: string): Promise<RevisionListEntry[]> => {
|
||||
// TODO Change 'revisions-list' to 'revisions' as soon as the backend is ready to serve some data!
|
||||
const response = await fetch(getApiUrl() + `/notes/${noteId}/revisions-list`, {
|
||||
const response = await fetch(getApiUrl() + `/notes/${ noteId }/revisions-list`, {
|
||||
...defaultFetchConfig
|
||||
})
|
||||
expectResponseCode(response)
|
||||
|
|
|
@ -8,7 +8,7 @@ import { defaultFetchConfig, expectResponseCode, getApiUrl } from '../utils'
|
|||
import { AccessToken, AccessTokenSecret } from './types'
|
||||
|
||||
export const getAccessTokenList = async (): Promise<AccessToken[]> => {
|
||||
const response = await fetch(`${getApiUrl()}/tokens`, {
|
||||
const response = await fetch(`${ getApiUrl() }/tokens`, {
|
||||
...defaultFetchConfig
|
||||
})
|
||||
expectResponseCode(response)
|
||||
|
@ -16,7 +16,7 @@ export const getAccessTokenList = async (): Promise<AccessToken[]> => {
|
|||
}
|
||||
|
||||
export const postNewAccessToken = async (label: string): Promise<AccessToken & AccessTokenSecret> => {
|
||||
const response = await fetch(`${getApiUrl()}/tokens`, {
|
||||
const response = await fetch(`${ getApiUrl() }/tokens`, {
|
||||
...defaultFetchConfig,
|
||||
method: 'POST',
|
||||
body: label
|
||||
|
@ -26,7 +26,7 @@ export const postNewAccessToken = async (label: string): Promise<AccessToken & A
|
|||
}
|
||||
|
||||
export const deleteAccessToken = async (timestamp: number): Promise<void> => {
|
||||
const response = await fetch(`${getApiUrl()}/tokens/${timestamp}`, {
|
||||
const response = await fetch(`${ getApiUrl() }/tokens/${ timestamp }`, {
|
||||
...defaultFetchConfig,
|
||||
method: 'DELETE'
|
||||
})
|
||||
|
|
|
@ -14,7 +14,7 @@ export const getUserById = async (userid: string): Promise<UserResponse> => {
|
|||
if (cache.has(userid)) {
|
||||
return cache.get(userid)
|
||||
}
|
||||
const response = await fetch(`${getApiUrl()}/users/${userid}`, {
|
||||
const response = await fetch(`${ getApiUrl() }/users/${ userid }`, {
|
||||
...defaultFetchConfig
|
||||
})
|
||||
expectResponseCode(response)
|
||||
|
|
|
@ -24,6 +24,6 @@ export const getApiUrl = (): string => {
|
|||
|
||||
export const expectResponseCode = (response: Response, code = 200): void => {
|
||||
if (response.status !== code) {
|
||||
throw new Error(`response code is not ${code}`)
|
||||
throw new Error(`response code is not ${ code }`)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,32 +6,72 @@
|
|||
|
||||
.loader {
|
||||
@keyframes animation-roll {
|
||||
0% { transform: translateX(calc(-100vw / 2 - 100%)) rotateZ(0deg); }
|
||||
100% { transform: translateX(calc(100vw / 2 + 100%)) rotateZ(720deg); }
|
||||
0% {
|
||||
transform: translateX(calc(-100vw / 2 - 100%)) rotateZ(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(calc(100vw / 2 + 100%)) rotateZ(720deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation-jump {
|
||||
0% { transform: scale(1,1) translateY(0); }
|
||||
10% { transform: scale(1.1,.9) 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); }
|
||||
0% {
|
||||
transform: scale(1, 1) translateY(0);
|
||||
}
|
||||
10% {
|
||||
transform: scale(1.1, .9) 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 {
|
||||
0% { transform: translate(1px, 1px) rotate(0deg); }
|
||||
10% { transform: translate(-1px, -2px) rotate(-1deg); }
|
||||
20% { transform: translate(-3px, 0px) rotate(1deg); }
|
||||
30% { 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); }
|
||||
0% {
|
||||
transform: translate(1px, 1px) rotate(0deg);
|
||||
}
|
||||
10% {
|
||||
transform: translate(-1px, -2px) rotate(-1deg);
|
||||
}
|
||||
20% {
|
||||
transform: translate(-3px, 0px) rotate(1deg);
|
||||
}
|
||||
30% {
|
||||
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 {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Suspense, useCallback, useEffect, useState } from 'react'
|
||||
import { useFrontendBaseUrl } from '../../hooks/common/use-frontend-base-url'
|
||||
|
@ -30,20 +30,21 @@ export const ApplicationLoader: React.FC = ({ children }) => {
|
|||
|
||||
useEffect(() => {
|
||||
for (const task of initTasks) {
|
||||
runTask(task.task).catch((reason: Error) => {
|
||||
console.error(reason)
|
||||
setFailedTitle(task.name)
|
||||
})
|
||||
runTask(task.task)
|
||||
.catch((reason: Error) => {
|
||||
console.error(reason)
|
||||
setFailedTitle(task.name)
|
||||
})
|
||||
}
|
||||
}, [initTasks, runTask])
|
||||
|
||||
const tasksAreRunning = doneTasks < initTasks.length || initTasks.length === 0
|
||||
|
||||
if (tasksAreRunning) {
|
||||
return <LoadingScreen failedTitle={failedTitle}/>
|
||||
return <LoadingScreen failedTitle={ failedTitle }/>
|
||||
} else {
|
||||
return <Suspense fallback={(<LoadingScreen/>)}>
|
||||
{children}
|
||||
return <Suspense fallback={ (<LoadingScreen/>) }>
|
||||
{ children }
|
||||
</Suspense>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { Alert } from 'react-bootstrap'
|
||||
|
@ -17,13 +17,13 @@ export const LoadingScreen: React.FC<LoadingScreenProps> = ({ failedTitle }) =>
|
|||
return (
|
||||
<div className="loader middle text-light overflow-hidden">
|
||||
<div className="mb-3 text-light">
|
||||
<span className={`d-block ${failedTitle ? 'animation-shake' : 'animation-jump'}`}>
|
||||
<HedgeDocLogo size={HedgeDocLogoSize.BIG}/>
|
||||
<span className={ `d-block ${ failedTitle ? 'animation-shake' : 'animation-jump' }` }>
|
||||
<HedgeDocLogo size={ HedgeDocLogoSize.BIG }/>
|
||||
</span>
|
||||
</div>
|
||||
<ShowIf condition={!!failedTitle}>
|
||||
<Alert variant={'danger'}>
|
||||
The task '{failedTitle}' failed.<br/>
|
||||
<ShowIf condition={ !!failedTitle }>
|
||||
<Alert variant={ 'danger' }>
|
||||
The task '{ failedTitle }' failed.<br/>
|
||||
For further information look into the browser console.
|
||||
</Alert>
|
||||
</ShowIf>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import equal from 'fast-deep-equal'
|
||||
import React from 'react'
|
||||
|
@ -21,18 +21,18 @@ export const Branding: React.FC<BrandingProps> = ({ inline = false, delimiter =
|
|||
const showBranding = !!branding.name || !!branding.logo
|
||||
|
||||
return (
|
||||
<ShowIf condition={showBranding}>
|
||||
<ShowIf condition={delimiter}>
|
||||
<strong className={`mx-1 ${inline ? 'inline-size' : 'regular-size'}`}>@</strong>
|
||||
<ShowIf condition={ showBranding }>
|
||||
<ShowIf condition={ delimiter }>
|
||||
<strong className={ `mx-1 ${ inline ? 'inline-size' : 'regular-size' }` }>@</strong>
|
||||
</ShowIf>
|
||||
{
|
||||
branding.logo
|
||||
? <img
|
||||
src={branding.logo}
|
||||
alt={branding.name}
|
||||
title={branding.name}
|
||||
className={inline ? 'inline-size' : 'regular-size'}
|
||||
/>
|
||||
src={ branding.logo }
|
||||
alt={ branding.name }
|
||||
title={ branding.name }
|
||||
className={ inline ? 'inline-size' : 'regular-size' }
|
||||
/>
|
||||
: branding.name
|
||||
}
|
||||
</ShowIf>
|
||||
|
|
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', () => {
|
||||
const lifetime = 1000
|
||||
const lifetimedCache = new Cache<string, string>(lifetime)
|
||||
expect(lifetimedCache.entryLifetime).toEqual(lifetime)
|
||||
expect(lifetimedCache.maxEntries).toEqual(0)
|
||||
expect(lifetimedCache.entryLifetime)
|
||||
.toEqual(lifetime)
|
||||
expect(lifetimedCache.maxEntries)
|
||||
.toEqual(0)
|
||||
})
|
||||
|
||||
it('initialize with right lifetime, given entry limit', () => {
|
||||
const lifetime = 1000
|
||||
const maxEntries = 10
|
||||
const limitedCache = new Cache<string, string>(lifetime, maxEntries)
|
||||
expect(limitedCache.entryLifetime).toEqual(lifetime)
|
||||
expect(limitedCache.maxEntries).toEqual(maxEntries)
|
||||
expect(limitedCache.entryLifetime)
|
||||
.toEqual(lifetime)
|
||||
expect(limitedCache.maxEntries)
|
||||
.toEqual(maxEntries)
|
||||
})
|
||||
|
||||
it('entry exists after inserting', () => {
|
||||
testCache.put('test', 123)
|
||||
expect(testCache.has('test')).toBe(true)
|
||||
expect(testCache.has('test'))
|
||||
.toBe(true)
|
||||
})
|
||||
|
||||
it('entry does not exist prior inserting', () => {
|
||||
expect(testCache.has('test')).toBe(false)
|
||||
expect(testCache.has('test'))
|
||||
.toBe(false)
|
||||
})
|
||||
|
||||
it('entry does expire', () => {
|
||||
const shortLivingCache = new Cache<string, number>(2)
|
||||
shortLivingCache.put('test', 123)
|
||||
expect(shortLivingCache.has('test')).toBe(true)
|
||||
expect(shortLivingCache.has('test'))
|
||||
.toBe(true)
|
||||
setTimeout(() => {
|
||||
expect(shortLivingCache.has('test')).toBe(false)
|
||||
expect(shortLivingCache.has('test'))
|
||||
.toBe(false)
|
||||
}, 2000)
|
||||
})
|
||||
|
||||
it('entry value does not change', () => {
|
||||
const testValue = Date.now()
|
||||
testCache.put('test', testValue)
|
||||
expect(testCache.get('test')).toEqual(testValue)
|
||||
expect(testCache.get('test'))
|
||||
.toEqual(testValue)
|
||||
})
|
||||
|
||||
it('error is thrown on non-existent entry', () => {
|
||||
const accessNonExistentEntry = () => {
|
||||
testCache.get('test')
|
||||
}
|
||||
expect(accessNonExistentEntry).toThrow(Error)
|
||||
expect(accessNonExistentEntry)
|
||||
.toThrow(Error)
|
||||
})
|
||||
|
||||
it('newer item replaces older item', () => {
|
||||
testCache.put('test', 123)
|
||||
testCache.put('test', 456)
|
||||
expect(testCache.get('test')).toEqual(456)
|
||||
expect(testCache.get('test'))
|
||||
.toEqual(456)
|
||||
})
|
||||
|
||||
it('entry limit is respected', () => {
|
||||
const limitedCache = new Cache<string, number>(1000, 2)
|
||||
limitedCache.put('first', 1)
|
||||
expect(limitedCache.has('first')).toBe(true)
|
||||
expect(limitedCache.has('second')).toBe(false)
|
||||
expect(limitedCache.has('third')).toBe(false)
|
||||
expect(limitedCache.has('first'))
|
||||
.toBe(true)
|
||||
expect(limitedCache.has('second'))
|
||||
.toBe(false)
|
||||
expect(limitedCache.has('third'))
|
||||
.toBe(false)
|
||||
limitedCache.put('second', 2)
|
||||
expect(limitedCache.has('first')).toBe(true)
|
||||
expect(limitedCache.has('second')).toBe(true)
|
||||
expect(limitedCache.has('third')).toBe(false)
|
||||
expect(limitedCache.has('first'))
|
||||
.toBe(true)
|
||||
expect(limitedCache.has('second'))
|
||||
.toBe(true)
|
||||
expect(limitedCache.has('third'))
|
||||
.toBe(false)
|
||||
limitedCache.put('third', 3)
|
||||
expect(limitedCache.has('first')).toBe(false)
|
||||
expect(limitedCache.has('second')).toBe(true)
|
||||
expect(limitedCache.has('third')).toBe(true)
|
||||
expect(limitedCache.has('first'))
|
||||
.toBe(false)
|
||||
expect(limitedCache.has('second'))
|
||||
.toBe(true)
|
||||
expect(limitedCache.has('third'))
|
||||
.toBe(true)
|
||||
})
|
||||
})
|
||||
|
|
14
src/components/common/cache/cache.ts
vendored
|
@ -10,12 +10,11 @@ export interface CacheEntry<T> {
|
|||
}
|
||||
|
||||
export class Cache<K, V> {
|
||||
private store = new Map<K, CacheEntry<V>>()
|
||||
|
||||
readonly entryLifetime: number
|
||||
readonly maxEntries: number
|
||||
private store = new Map<K, CacheEntry<V>>()
|
||||
|
||||
constructor (lifetime: number, maxEntries = 0) {
|
||||
constructor(lifetime: number, maxEntries = 0) {
|
||||
if (lifetime < 0) {
|
||||
throw new Error('Cache entry lifetime can not be less than 0 seconds.')
|
||||
}
|
||||
|
@ -23,7 +22,7 @@ export class Cache<K, V> {
|
|||
this.maxEntries = maxEntries
|
||||
}
|
||||
|
||||
has (key: K): boolean {
|
||||
has(key: K): boolean {
|
||||
if (!this.store.has(key)) {
|
||||
return false
|
||||
}
|
||||
|
@ -31,7 +30,7 @@ export class Cache<K, V> {
|
|||
return (!!entry && entry.entryCreated >= (Date.now() - this.entryLifetime * 1000))
|
||||
}
|
||||
|
||||
get (key: K): V {
|
||||
get(key: K): V {
|
||||
const entry = this.store.get(key)
|
||||
if (!entry) {
|
||||
throw new Error('This cache entry does not exist. Check with ".has()" before using ".get()".')
|
||||
|
@ -39,9 +38,10 @@ export class Cache<K, V> {
|
|||
return entry.data
|
||||
}
|
||||
|
||||
put (key: K, value: V): void {
|
||||
put(key: K, value: V): void {
|
||||
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, {
|
||||
entryCreated: Date.now(),
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { RefObject, useCallback, useEffect, useState } from 'react'
|
||||
import { Overlay, Tooltip } from 'react-bootstrap'
|
||||
|
@ -22,15 +22,20 @@ export const CopyOverlay: React.FC<CopyOverlayProps> = ({ content, clickComponen
|
|||
const [tooltipId] = useState<string>(() => uuid())
|
||||
|
||||
const copyToClipboard = useCallback((content: string) => {
|
||||
navigator.clipboard.writeText(content).then(() => {
|
||||
setError(false)
|
||||
}).catch(() => {
|
||||
setError(true)
|
||||
console.error("couldn't copy")
|
||||
}).finally(() => {
|
||||
setShowCopiedTooltip(true)
|
||||
setTimeout(() => { setShowCopiedTooltip(false) }, 2000)
|
||||
})
|
||||
navigator.clipboard.writeText(content)
|
||||
.then(() => {
|
||||
setError(false)
|
||||
})
|
||||
.catch(() => {
|
||||
setError(true)
|
||||
console.error('couldn\'t copy')
|
||||
})
|
||||
.finally(() => {
|
||||
setShowCopiedTooltip(true)
|
||||
setTimeout(() => {
|
||||
setShowCopiedTooltip(false)
|
||||
}, 2000)
|
||||
})
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -46,17 +51,17 @@ export const CopyOverlay: React.FC<CopyOverlayProps> = ({ content, clickComponen
|
|||
}, [clickComponent, copyToClipboard, content])
|
||||
|
||||
return (
|
||||
<Overlay target={clickComponent} show={showCopiedTooltip} placement="top">
|
||||
{(props) => (
|
||||
<Tooltip id={`copied_${tooltipId}`} {...props}>
|
||||
<ShowIf condition={error}>
|
||||
<Trans i18nKey={'common.copyError'}/>
|
||||
<Overlay target={ clickComponent } show={ showCopiedTooltip } placement="top">
|
||||
{ (props) => (
|
||||
<Tooltip id={ `copied_${ tooltipId }` } { ...props }>
|
||||
<ShowIf condition={ error }>
|
||||
<Trans i18nKey={ 'common.copyError' }/>
|
||||
</ShowIf>
|
||||
<ShowIf condition={!error}>
|
||||
<Trans i18nKey={'common.successfullyCopied'}/>
|
||||
<ShowIf condition={ !error }>
|
||||
<Trans i18nKey={ 'common.successfullyCopied' }/>
|
||||
</ShowIf>
|
||||
</Tooltip>
|
||||
)}
|
||||
) }
|
||||
</Overlay>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -15,25 +15,25 @@ export interface CopyToClipboardButtonProps {
|
|||
content: string
|
||||
size?: 'sm' | 'lg'
|
||||
variant?: Variant
|
||||
"data-cy"?: string
|
||||
'data-cy'?: string
|
||||
}
|
||||
|
||||
export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({
|
||||
content,
|
||||
size = 'sm',
|
||||
variant = 'dark',
|
||||
...props
|
||||
}) => {
|
||||
content,
|
||||
size = 'sm',
|
||||
variant = 'dark',
|
||||
...props
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const button = useRef<HTMLButtonElement>(null)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Button ref={button} size={size} variant={variant} title={t('renderer.highlightCode.copyCode')}
|
||||
data-cy={props["data-cy"]}>
|
||||
<Button ref={ button } size={ size } variant={ variant } title={ t('renderer.highlightCode.copyCode') }
|
||||
data-cy={ props['data-cy'] }>
|
||||
<ForkAwesomeIcon icon='files-o'/>
|
||||
</Button>
|
||||
<CopyOverlay content={content} clickComponent={button}/>
|
||||
<CopyOverlay content={ content } clickComponent={ button }/>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useCallback, useRef } from 'react'
|
||||
import { Button, FormControl, InputGroup } from 'react-bootstrap'
|
||||
|
@ -25,9 +25,10 @@ export const CopyableField: React.FC<CopyableFieldProps> = ({ content, nativeSha
|
|||
navigator.share({
|
||||
text: content,
|
||||
url: url
|
||||
}).catch(err => {
|
||||
console.error('Native sharing failed: ', err)
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Native sharing failed: ', err)
|
||||
})
|
||||
}, [content, url])
|
||||
|
||||
const sharingSupported = typeof navigator.share === 'function'
|
||||
|
@ -35,21 +36,21 @@ export const CopyableField: React.FC<CopyableFieldProps> = ({ content, nativeSha
|
|||
return (
|
||||
<Fragment>
|
||||
<InputGroup className="my-3">
|
||||
<FormControl readOnly={true} className={'text-center'} value={content} />
|
||||
<FormControl readOnly={ true } className={ 'text-center' } value={ content }/>
|
||||
<InputGroup.Append>
|
||||
<Button variant="outline-secondary" ref={copyButton} title={'Copy'}>
|
||||
<Button variant="outline-secondary" ref={ copyButton } title={ 'Copy' }>
|
||||
<ForkAwesomeIcon icon='files-o'/>
|
||||
</Button>
|
||||
</InputGroup.Append>
|
||||
<ShowIf condition={!!nativeShareButton && sharingSupported}>
|
||||
<ShowIf condition={ !!nativeShareButton && sharingSupported }>
|
||||
<InputGroup.Append>
|
||||
<Button variant="outline-secondary" title={'Share'} onClick={doShareAction}>
|
||||
<Button variant="outline-secondary" title={ 'Share' } onClick={ doShareAction }>
|
||||
<ForkAwesomeIcon icon='share-alt'/>
|
||||
</Button>
|
||||
</InputGroup.Append>
|
||||
</ShowIf>
|
||||
</InputGroup>
|
||||
<CopyOverlay content={content} clickComponent={copyButton}/>
|
||||
<CopyOverlay content={ content } clickComponent={ copyButton }/>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { IconName, IconSize } from './types'
|
||||
|
@ -17,10 +17,10 @@ export interface ForkAwesomeIconProps {
|
|||
|
||||
export const ForkAwesomeIcon: React.FC<ForkAwesomeIconProps> = ({ icon, fixedWidth = false, size, className, stacked = false }) => {
|
||||
const fixedWithClass = fixedWidth ? 'fa-fw' : ''
|
||||
const sizeClass = size ? `-${size}` : (stacked ? '-1x' : '')
|
||||
const sizeClass = size ? `-${ size }` : (stacked ? '-1x' : '')
|
||||
const stackClass = stacked ? '-stack' : ''
|
||||
const extraClasses = `${className ?? ''} ${sizeClass || stackClass ? `fa${stackClass}${sizeClass}` : ''}`
|
||||
const extraClasses = `${ className ?? '' } ${ sizeClass || stackClass ? `fa${ stackClass }${ sizeClass }` : '' }`
|
||||
return (
|
||||
<i className={`fa ${fixedWithClass} fa-${icon} ${extraClasses}`}/>
|
||||
<i className={ `fa ${ fixedWithClass } fa-${ icon } ${ extraClasses }` }/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { ReactElement } from 'react'
|
||||
import { ForkAwesomeIcon, ForkAwesomeIconProps } from './fork-awesome-icon'
|
||||
|
@ -15,13 +15,13 @@ export interface ForkAwesomeStackProps {
|
|||
|
||||
export const ForkAwesomeStack: React.FC<ForkAwesomeStackProps> = ({ size, children }) => {
|
||||
return (
|
||||
<span className={`fa-stack ${size ? 'fa-' : ''}${size ?? ''}`}>
|
||||
<span className={ `fa-stack ${ size ? 'fa-' : '' }${ size ?? '' }` }>
|
||||
{
|
||||
React.Children.map(children, (child) => {
|
||||
if (!React.isValidElement<ForkAwesomeIconProps>(child)) {
|
||||
return null
|
||||
}
|
||||
return <ForkAwesomeIcon {...child.props} stacked={true}/>
|
||||
return <ForkAwesomeIcon { ...child.props } stacked={ true }/>
|
||||
})
|
||||
}
|
||||
</span>
|
||||
|
|
122
src/components/common/fork-awesome/types.d.ts
vendored
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { ReactComponent as LogoBwHorizontal } from './logo_text_bw_horizontal.svg'
|
||||
|
@ -12,7 +12,7 @@ import { ReactComponent as LogoWbHorizontal } from './logo_text_wb_horizontal.sv
|
|||
export enum HedgeDocLogoSize {
|
||||
SMALL = 32,
|
||||
MEDIUM = 64,
|
||||
BIG= 256
|
||||
BIG = 256
|
||||
}
|
||||
|
||||
export interface HedgeDocLogoProps {
|
||||
|
@ -29,11 +29,11 @@ export enum HedgeDocLogoType {
|
|||
export const HedgeDocLogoWithText: React.FC<HedgeDocLogoProps> = ({ size = HedgeDocLogoSize.MEDIUM, logoType }) => {
|
||||
switch (logoType) {
|
||||
case HedgeDocLogoType.COLOR_VERTICAL:
|
||||
return <LogoColorVertical className={'w-auto'} title={'HedgeDoc logo with text'} style={{ height: size }}/>
|
||||
return <LogoColorVertical className={ 'w-auto' } title={ 'HedgeDoc logo with text' } style={ { height: size } }/>
|
||||
case HedgeDocLogoType.BW_HORIZONTAL:
|
||||
return <LogoBwHorizontal className={'w-auto'} title={'HedgeDoc logo with text'} style={{ height: size }}/>
|
||||
return <LogoBwHorizontal className={ 'w-auto' } title={ 'HedgeDoc logo with text' } style={ { height: size } }/>
|
||||
case HedgeDocLogoType.WB_HORIZONTAL:
|
||||
return <LogoWbHorizontal className={'w-auto'} title={'HedgeDoc logo with text'} style={{ height: size }}/>
|
||||
return <LogoWbHorizontal className={ 'w-auto' } title={ 'HedgeDoc logo with text' } style={ { height: size } }/>
|
||||
default:
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { ReactComponent as LogoColor } from './logo_color.svg'
|
||||
|
@ -18,5 +18,5 @@ export interface HedgeDocLogoProps {
|
|||
}
|
||||
|
||||
export const HedgeDocLogo: React.FC<HedgeDocLogoProps> = ({ size = HedgeDocLogoSize.MEDIUM }) => {
|
||||
return <LogoColor className={'w-auto'} title={'HedgeDoc logo with text'} style={{ height: size }}/>
|
||||
return <LogoColor className={ 'w-auto' } title={ 'HedgeDoc logo with text' } style={ { height: size } }/>
|
||||
}
|
||||
|
|
|
@ -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 |
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import hljs from 'highlight.js/lib/core';
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import hljs from 'highlight.js/lib/core'
|
||||
import abnf from 'highlight.js/lib/languages/abnf'
|
||||
import accesslog from 'highlight.js/lib/languages/accesslog'
|
||||
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 zephir from 'highlight.js/lib/languages/zephir'
|
||||
|
||||
hljs.registerLanguage('abnf', abnf);
|
||||
hljs.registerLanguage('accesslog', accesslog);
|
||||
hljs.registerLanguage('actionscript', actionscript);
|
||||
hljs.registerLanguage('ada', ada);
|
||||
hljs.registerLanguage('angelscript', angelscript);
|
||||
hljs.registerLanguage('apache', apache);
|
||||
hljs.registerLanguage('applescript', applescript);
|
||||
hljs.registerLanguage('arcade', arcade);
|
||||
hljs.registerLanguage('arduino', arduino);
|
||||
hljs.registerLanguage('armasm', armasm);
|
||||
hljs.registerLanguage('xml', xml);
|
||||
hljs.registerLanguage('asciidoc', asciidoc);
|
||||
hljs.registerLanguage('aspectj', aspectj);
|
||||
hljs.registerLanguage('autohotkey', autohotkey);
|
||||
hljs.registerLanguage('autoit', autoit);
|
||||
hljs.registerLanguage('avrasm', avrasm);
|
||||
hljs.registerLanguage('awk', awk);
|
||||
hljs.registerLanguage('axapta', axapta);
|
||||
hljs.registerLanguage('bash', bash);
|
||||
hljs.registerLanguage('basic', basic);
|
||||
hljs.registerLanguage('bnf', bnf);
|
||||
hljs.registerLanguage('brainfuck', brainfuck);
|
||||
hljs.registerLanguage('c-like', c_like);
|
||||
hljs.registerLanguage('c', c);
|
||||
hljs.registerLanguage('cal', cal);
|
||||
hljs.registerLanguage('capnproto', capnproto);
|
||||
hljs.registerLanguage('ceylon', ceylon);
|
||||
hljs.registerLanguage('clean', clean);
|
||||
hljs.registerLanguage('clojure', clojure);
|
||||
hljs.registerLanguage('clojure-repl', clojure_repl);
|
||||
hljs.registerLanguage('cmake', cmake);
|
||||
hljs.registerLanguage('coffeescript', coffeescript);
|
||||
hljs.registerLanguage('coq', coq);
|
||||
hljs.registerLanguage('cos', cos);
|
||||
hljs.registerLanguage('cpp', cpp);
|
||||
hljs.registerLanguage('crmsh', crmsh);
|
||||
hljs.registerLanguage('crystal', crystal);
|
||||
hljs.registerLanguage('csharp', csharp);
|
||||
hljs.registerLanguage('csp', csp);
|
||||
hljs.registerLanguage('css', css);
|
||||
hljs.registerLanguage('d', d);
|
||||
hljs.registerLanguage('markdown', markdown);
|
||||
hljs.registerLanguage('dart', dart);
|
||||
hljs.registerLanguage('delphi', delphi);
|
||||
hljs.registerLanguage('diff', diff);
|
||||
hljs.registerLanguage('django', django);
|
||||
hljs.registerLanguage('dns', dns);
|
||||
hljs.registerLanguage('dockerfile', dockerfile);
|
||||
hljs.registerLanguage('dos', dos);
|
||||
hljs.registerLanguage('dsconfig', dsconfig);
|
||||
hljs.registerLanguage('dts', dts);
|
||||
hljs.registerLanguage('dust', dust);
|
||||
hljs.registerLanguage('ebnf', ebnf);
|
||||
hljs.registerLanguage('elixir', elixir);
|
||||
hljs.registerLanguage('elm', elm);
|
||||
hljs.registerLanguage('ruby', ruby);
|
||||
hljs.registerLanguage('erb', erb);
|
||||
hljs.registerLanguage('erlang-repl', erlang_repl);
|
||||
hljs.registerLanguage('erlang', erlang);
|
||||
hljs.registerLanguage('excel', excel);
|
||||
hljs.registerLanguage('fix', fix);
|
||||
hljs.registerLanguage('flix', flix);
|
||||
hljs.registerLanguage('fortran', fortran);
|
||||
hljs.registerLanguage('fsharp', fsharp);
|
||||
hljs.registerLanguage('gams', gams);
|
||||
hljs.registerLanguage('gauss', gauss);
|
||||
hljs.registerLanguage('gcode', gcode);
|
||||
hljs.registerLanguage('gherkin', gherkin);
|
||||
hljs.registerLanguage('glsl', glsl);
|
||||
hljs.registerLanguage('gml', gml);
|
||||
hljs.registerLanguage('go', go);
|
||||
hljs.registerLanguage('golo', golo);
|
||||
hljs.registerLanguage('gradle', gradle);
|
||||
hljs.registerLanguage('groovy', groovy);
|
||||
hljs.registerLanguage('haml', haml);
|
||||
hljs.registerLanguage('handlebars', handlebars);
|
||||
hljs.registerLanguage('haskell', haskell);
|
||||
hljs.registerLanguage('haxe', haxe);
|
||||
hljs.registerLanguage('hsp', hsp);
|
||||
hljs.registerLanguage('html', xml);
|
||||
hljs.registerLanguage('htmlbars', htmlbars);
|
||||
hljs.registerLanguage('http', http);
|
||||
hljs.registerLanguage('hy', hy);
|
||||
hljs.registerLanguage('inform7', inform7);
|
||||
hljs.registerLanguage('ini', ini);
|
||||
hljs.registerLanguage('irpf90', irpf90);
|
||||
hljs.registerLanguage('isbl', isbl);
|
||||
hljs.registerLanguage('java', java);
|
||||
hljs.registerLanguage('javascript', javascript);
|
||||
hljs.registerLanguage('jboss-cli', jboss_cli);
|
||||
hljs.registerLanguage('js', javascript);
|
||||
hljs.registerLanguage('json', json);
|
||||
hljs.registerLanguage('julia', julia);
|
||||
hljs.registerLanguage('julia-repl', julia_repl);
|
||||
hljs.registerLanguage('kotlin', kotlin);
|
||||
hljs.registerLanguage('lasso', lasso);
|
||||
hljs.registerLanguage('latex', latex);
|
||||
hljs.registerLanguage('ldif', ldif);
|
||||
hljs.registerLanguage('leaf', leaf);
|
||||
hljs.registerLanguage('less', less);
|
||||
hljs.registerLanguage('lisp', lisp);
|
||||
hljs.registerLanguage('livecodeserver', livecodeserver);
|
||||
hljs.registerLanguage('livescript', livescript);
|
||||
hljs.registerLanguage('llvm', llvm);
|
||||
hljs.registerLanguage('lsl', lsl);
|
||||
hljs.registerLanguage('lua', lua);
|
||||
hljs.registerLanguage('makefile', makefile);
|
||||
hljs.registerLanguage('mathematica', mathematica);
|
||||
hljs.registerLanguage('matlab', matlab);
|
||||
hljs.registerLanguage('maxima', maxima);
|
||||
hljs.registerLanguage('mel', mel);
|
||||
hljs.registerLanguage('mercury', mercury);
|
||||
hljs.registerLanguage('mipsasm', mipsasm);
|
||||
hljs.registerLanguage('mizar', mizar);
|
||||
hljs.registerLanguage('perl', perl);
|
||||
hljs.registerLanguage('mojolicious', mojolicious);
|
||||
hljs.registerLanguage('monkey', monkey);
|
||||
hljs.registerLanguage('moonscript', moonscript);
|
||||
hljs.registerLanguage('n1ql', n1ql);
|
||||
hljs.registerLanguage('nginx', nginx);
|
||||
hljs.registerLanguage('nim', nim);
|
||||
hljs.registerLanguage('nix', nix);
|
||||
hljs.registerLanguage('node-repl', node_repl);
|
||||
hljs.registerLanguage('nsis', nsis);
|
||||
hljs.registerLanguage('objectivec', objectivec);
|
||||
hljs.registerLanguage('ocaml', ocaml);
|
||||
hljs.registerLanguage('openscad', openscad);
|
||||
hljs.registerLanguage('oxygene', oxygene);
|
||||
hljs.registerLanguage('parser3', parser3);
|
||||
hljs.registerLanguage('pf', pf);
|
||||
hljs.registerLanguage('pgsql', pgsql);
|
||||
hljs.registerLanguage('php', php);
|
||||
hljs.registerLanguage('php-template', php_template);
|
||||
hljs.registerLanguage('plaintext', plaintext);
|
||||
hljs.registerLanguage('pony', pony);
|
||||
hljs.registerLanguage('powershell', powershell);
|
||||
hljs.registerLanguage('processing', processing);
|
||||
hljs.registerLanguage('profile', profile);
|
||||
hljs.registerLanguage('prolog', prolog);
|
||||
hljs.registerLanguage('properties', properties);
|
||||
hljs.registerLanguage('protobuf', protobuf);
|
||||
hljs.registerLanguage('puppet', puppet);
|
||||
hljs.registerLanguage('purebasic', purebasic);
|
||||
hljs.registerLanguage('python', python);
|
||||
hljs.registerLanguage('python-repl', python_repl);
|
||||
hljs.registerLanguage('q', q);
|
||||
hljs.registerLanguage('qml', qml);
|
||||
hljs.registerLanguage('r', r);
|
||||
hljs.registerLanguage('reasonml', reasonml);
|
||||
hljs.registerLanguage('rib', rib);
|
||||
hljs.registerLanguage('roboconf', roboconf);
|
||||
hljs.registerLanguage('routeros', routeros);
|
||||
hljs.registerLanguage('rsl', rsl);
|
||||
hljs.registerLanguage('ruleslanguage', ruleslanguage);
|
||||
hljs.registerLanguage('rust', rust);
|
||||
hljs.registerLanguage('sas', sas);
|
||||
hljs.registerLanguage('scala', scala);
|
||||
hljs.registerLanguage('scheme', scheme);
|
||||
hljs.registerLanguage('scilab', scilab);
|
||||
hljs.registerLanguage('scss', scss);
|
||||
hljs.registerLanguage('shell', shell);
|
||||
hljs.registerLanguage('smali', smali);
|
||||
hljs.registerLanguage('smalltalk', smalltalk);
|
||||
hljs.registerLanguage('sml', sml);
|
||||
hljs.registerLanguage('sqf', sqf);
|
||||
hljs.registerLanguage('sql', sql);
|
||||
hljs.registerLanguage('stan', stan);
|
||||
hljs.registerLanguage('stata', stata);
|
||||
hljs.registerLanguage('step21', step21);
|
||||
hljs.registerLanguage('stylus', stylus);
|
||||
hljs.registerLanguage('subunit', subunit);
|
||||
hljs.registerLanguage('swift', swift);
|
||||
hljs.registerLanguage('taggerscript', taggerscript);
|
||||
hljs.registerLanguage('yaml', yaml);
|
||||
hljs.registerLanguage('tap', tap);
|
||||
hljs.registerLanguage('tcl', tcl);
|
||||
hljs.registerLanguage('thrift', thrift);
|
||||
hljs.registerLanguage('tp', tp);
|
||||
hljs.registerLanguage('twig', twig);
|
||||
hljs.registerLanguage('typescript', typescript);
|
||||
hljs.registerLanguage('vala', vala);
|
||||
hljs.registerLanguage('vbnet', vbnet);
|
||||
hljs.registerLanguage('vbscript', vbscript);
|
||||
hljs.registerLanguage('vbscript-html', vbscript_html);
|
||||
hljs.registerLanguage('verilog', verilog);
|
||||
hljs.registerLanguage('vhdl', vhdl);
|
||||
hljs.registerLanguage('vim', vim);
|
||||
hljs.registerLanguage('x86asm', x86asm);
|
||||
hljs.registerLanguage('xl', xl);
|
||||
hljs.registerLanguage('xquery', xquery);
|
||||
hljs.registerLanguage('zephir', zephir);
|
||||
hljs.registerLanguage('abnf', abnf)
|
||||
hljs.registerLanguage('accesslog', accesslog)
|
||||
hljs.registerLanguage('actionscript', actionscript)
|
||||
hljs.registerLanguage('ada', ada)
|
||||
hljs.registerLanguage('angelscript', angelscript)
|
||||
hljs.registerLanguage('apache', apache)
|
||||
hljs.registerLanguage('applescript', applescript)
|
||||
hljs.registerLanguage('arcade', arcade)
|
||||
hljs.registerLanguage('arduino', arduino)
|
||||
hljs.registerLanguage('armasm', armasm)
|
||||
hljs.registerLanguage('xml', xml)
|
||||
hljs.registerLanguage('asciidoc', asciidoc)
|
||||
hljs.registerLanguage('aspectj', aspectj)
|
||||
hljs.registerLanguage('autohotkey', autohotkey)
|
||||
hljs.registerLanguage('autoit', autoit)
|
||||
hljs.registerLanguage('avrasm', avrasm)
|
||||
hljs.registerLanguage('awk', awk)
|
||||
hljs.registerLanguage('axapta', axapta)
|
||||
hljs.registerLanguage('bash', bash)
|
||||
hljs.registerLanguage('basic', basic)
|
||||
hljs.registerLanguage('bnf', bnf)
|
||||
hljs.registerLanguage('brainfuck', brainfuck)
|
||||
hljs.registerLanguage('c-like', c_like)
|
||||
hljs.registerLanguage('c', c)
|
||||
hljs.registerLanguage('cal', cal)
|
||||
hljs.registerLanguage('capnproto', capnproto)
|
||||
hljs.registerLanguage('ceylon', ceylon)
|
||||
hljs.registerLanguage('clean', clean)
|
||||
hljs.registerLanguage('clojure', clojure)
|
||||
hljs.registerLanguage('clojure-repl', clojure_repl)
|
||||
hljs.registerLanguage('cmake', cmake)
|
||||
hljs.registerLanguage('coffeescript', coffeescript)
|
||||
hljs.registerLanguage('coq', coq)
|
||||
hljs.registerLanguage('cos', cos)
|
||||
hljs.registerLanguage('cpp', cpp)
|
||||
hljs.registerLanguage('crmsh', crmsh)
|
||||
hljs.registerLanguage('crystal', crystal)
|
||||
hljs.registerLanguage('csharp', csharp)
|
||||
hljs.registerLanguage('csp', csp)
|
||||
hljs.registerLanguage('css', css)
|
||||
hljs.registerLanguage('d', d)
|
||||
hljs.registerLanguage('markdown', markdown)
|
||||
hljs.registerLanguage('dart', dart)
|
||||
hljs.registerLanguage('delphi', delphi)
|
||||
hljs.registerLanguage('diff', diff)
|
||||
hljs.registerLanguage('django', django)
|
||||
hljs.registerLanguage('dns', dns)
|
||||
hljs.registerLanguage('dockerfile', dockerfile)
|
||||
hljs.registerLanguage('dos', dos)
|
||||
hljs.registerLanguage('dsconfig', dsconfig)
|
||||
hljs.registerLanguage('dts', dts)
|
||||
hljs.registerLanguage('dust', dust)
|
||||
hljs.registerLanguage('ebnf', ebnf)
|
||||
hljs.registerLanguage('elixir', elixir)
|
||||
hljs.registerLanguage('elm', elm)
|
||||
hljs.registerLanguage('ruby', ruby)
|
||||
hljs.registerLanguage('erb', erb)
|
||||
hljs.registerLanguage('erlang-repl', erlang_repl)
|
||||
hljs.registerLanguage('erlang', erlang)
|
||||
hljs.registerLanguage('excel', excel)
|
||||
hljs.registerLanguage('fix', fix)
|
||||
hljs.registerLanguage('flix', flix)
|
||||
hljs.registerLanguage('fortran', fortran)
|
||||
hljs.registerLanguage('fsharp', fsharp)
|
||||
hljs.registerLanguage('gams', gams)
|
||||
hljs.registerLanguage('gauss', gauss)
|
||||
hljs.registerLanguage('gcode', gcode)
|
||||
hljs.registerLanguage('gherkin', gherkin)
|
||||
hljs.registerLanguage('glsl', glsl)
|
||||
hljs.registerLanguage('gml', gml)
|
||||
hljs.registerLanguage('go', go)
|
||||
hljs.registerLanguage('golo', golo)
|
||||
hljs.registerLanguage('gradle', gradle)
|
||||
hljs.registerLanguage('groovy', groovy)
|
||||
hljs.registerLanguage('haml', haml)
|
||||
hljs.registerLanguage('handlebars', handlebars)
|
||||
hljs.registerLanguage('haskell', haskell)
|
||||
hljs.registerLanguage('haxe', haxe)
|
||||
hljs.registerLanguage('hsp', hsp)
|
||||
hljs.registerLanguage('html', xml)
|
||||
hljs.registerLanguage('htmlbars', htmlbars)
|
||||
hljs.registerLanguage('http', http)
|
||||
hljs.registerLanguage('hy', hy)
|
||||
hljs.registerLanguage('inform7', inform7)
|
||||
hljs.registerLanguage('ini', ini)
|
||||
hljs.registerLanguage('irpf90', irpf90)
|
||||
hljs.registerLanguage('isbl', isbl)
|
||||
hljs.registerLanguage('java', java)
|
||||
hljs.registerLanguage('javascript', javascript)
|
||||
hljs.registerLanguage('jboss-cli', jboss_cli)
|
||||
hljs.registerLanguage('js', javascript)
|
||||
hljs.registerLanguage('json', json)
|
||||
hljs.registerLanguage('julia', julia)
|
||||
hljs.registerLanguage('julia-repl', julia_repl)
|
||||
hljs.registerLanguage('kotlin', kotlin)
|
||||
hljs.registerLanguage('lasso', lasso)
|
||||
hljs.registerLanguage('latex', latex)
|
||||
hljs.registerLanguage('ldif', ldif)
|
||||
hljs.registerLanguage('leaf', leaf)
|
||||
hljs.registerLanguage('less', less)
|
||||
hljs.registerLanguage('lisp', lisp)
|
||||
hljs.registerLanguage('livecodeserver', livecodeserver)
|
||||
hljs.registerLanguage('livescript', livescript)
|
||||
hljs.registerLanguage('llvm', llvm)
|
||||
hljs.registerLanguage('lsl', lsl)
|
||||
hljs.registerLanguage('lua', lua)
|
||||
hljs.registerLanguage('makefile', makefile)
|
||||
hljs.registerLanguage('mathematica', mathematica)
|
||||
hljs.registerLanguage('matlab', matlab)
|
||||
hljs.registerLanguage('maxima', maxima)
|
||||
hljs.registerLanguage('mel', mel)
|
||||
hljs.registerLanguage('mercury', mercury)
|
||||
hljs.registerLanguage('mipsasm', mipsasm)
|
||||
hljs.registerLanguage('mizar', mizar)
|
||||
hljs.registerLanguage('perl', perl)
|
||||
hljs.registerLanguage('mojolicious', mojolicious)
|
||||
hljs.registerLanguage('monkey', monkey)
|
||||
hljs.registerLanguage('moonscript', moonscript)
|
||||
hljs.registerLanguage('n1ql', n1ql)
|
||||
hljs.registerLanguage('nginx', nginx)
|
||||
hljs.registerLanguage('nim', nim)
|
||||
hljs.registerLanguage('nix', nix)
|
||||
hljs.registerLanguage('node-repl', node_repl)
|
||||
hljs.registerLanguage('nsis', nsis)
|
||||
hljs.registerLanguage('objectivec', objectivec)
|
||||
hljs.registerLanguage('ocaml', ocaml)
|
||||
hljs.registerLanguage('openscad', openscad)
|
||||
hljs.registerLanguage('oxygene', oxygene)
|
||||
hljs.registerLanguage('parser3', parser3)
|
||||
hljs.registerLanguage('pf', pf)
|
||||
hljs.registerLanguage('pgsql', pgsql)
|
||||
hljs.registerLanguage('php', php)
|
||||
hljs.registerLanguage('php-template', php_template)
|
||||
hljs.registerLanguage('plaintext', plaintext)
|
||||
hljs.registerLanguage('pony', pony)
|
||||
hljs.registerLanguage('powershell', powershell)
|
||||
hljs.registerLanguage('processing', processing)
|
||||
hljs.registerLanguage('profile', profile)
|
||||
hljs.registerLanguage('prolog', prolog)
|
||||
hljs.registerLanguage('properties', properties)
|
||||
hljs.registerLanguage('protobuf', protobuf)
|
||||
hljs.registerLanguage('puppet', puppet)
|
||||
hljs.registerLanguage('purebasic', purebasic)
|
||||
hljs.registerLanguage('python', python)
|
||||
hljs.registerLanguage('python-repl', python_repl)
|
||||
hljs.registerLanguage('q', q)
|
||||
hljs.registerLanguage('qml', qml)
|
||||
hljs.registerLanguage('r', r)
|
||||
hljs.registerLanguage('reasonml', reasonml)
|
||||
hljs.registerLanguage('rib', rib)
|
||||
hljs.registerLanguage('roboconf', roboconf)
|
||||
hljs.registerLanguage('routeros', routeros)
|
||||
hljs.registerLanguage('rsl', rsl)
|
||||
hljs.registerLanguage('ruleslanguage', ruleslanguage)
|
||||
hljs.registerLanguage('rust', rust)
|
||||
hljs.registerLanguage('sas', sas)
|
||||
hljs.registerLanguage('scala', scala)
|
||||
hljs.registerLanguage('scheme', scheme)
|
||||
hljs.registerLanguage('scilab', scilab)
|
||||
hljs.registerLanguage('scss', scss)
|
||||
hljs.registerLanguage('shell', shell)
|
||||
hljs.registerLanguage('smali', smali)
|
||||
hljs.registerLanguage('smalltalk', smalltalk)
|
||||
hljs.registerLanguage('sml', sml)
|
||||
hljs.registerLanguage('sqf', sqf)
|
||||
hljs.registerLanguage('sql', sql)
|
||||
hljs.registerLanguage('stan', stan)
|
||||
hljs.registerLanguage('stata', stata)
|
||||
hljs.registerLanguage('step21', step21)
|
||||
hljs.registerLanguage('stylus', stylus)
|
||||
hljs.registerLanguage('subunit', subunit)
|
||||
hljs.registerLanguage('swift', swift)
|
||||
hljs.registerLanguage('taggerscript', taggerscript)
|
||||
hljs.registerLanguage('yaml', yaml)
|
||||
hljs.registerLanguage('tap', tap)
|
||||
hljs.registerLanguage('tcl', tcl)
|
||||
hljs.registerLanguage('thrift', thrift)
|
||||
hljs.registerLanguage('tp', tp)
|
||||
hljs.registerLanguage('twig', twig)
|
||||
hljs.registerLanguage('typescript', typescript)
|
||||
hljs.registerLanguage('vala', vala)
|
||||
hljs.registerLanguage('vbnet', vbnet)
|
||||
hljs.registerLanguage('vbscript', vbscript)
|
||||
hljs.registerLanguage('vbscript-html', vbscript_html)
|
||||
hljs.registerLanguage('verilog', verilog)
|
||||
hljs.registerLanguage('vhdl', vhdl)
|
||||
hljs.registerLanguage('vim', vim)
|
||||
hljs.registerLanguage('x86asm', x86asm)
|
||||
hljs.registerLanguage('xl', xl)
|
||||
hljs.registerLanguage('xquery', xquery)
|
||||
hljs.registerLanguage('zephir', zephir)
|
||||
|
||||
export default hljs;
|
||||
export default hljs
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { Button, ButtonProps } from 'react-bootstrap'
|
||||
|
@ -19,13 +19,14 @@ export interface IconButtonProps extends ButtonProps {
|
|||
|
||||
export const IconButton: React.FC<IconButtonProps> = ({ icon, children, border = false, ...props }) => {
|
||||
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">
|
||||
<ForkAwesomeIcon icon={icon} className={'icon'}/>
|
||||
<ForkAwesomeIcon icon={ icon } className={ 'icon' }/>
|
||||
</span>
|
||||
<ShowIf condition={!!children}>
|
||||
<ShowIf condition={ !!children }>
|
||||
<span className="text-part d-flex align-items-center">
|
||||
{children}
|
||||
{ children }
|
||||
</span>
|
||||
</ShowIf>
|
||||
</Button>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { Trans } from 'react-i18next'
|
||||
|
@ -14,8 +14,8 @@ export interface TranslatedIconButtonProps extends IconButtonProps {
|
|||
|
||||
export const TranslatedIconButton: React.FC<TranslatedIconButtonProps> = ({ i18nKey, ...props }) => {
|
||||
return (
|
||||
<IconButton {...props}>
|
||||
<Trans i18nKey={i18nKey}/>
|
||||
<IconButton { ...props }>
|
||||
<Trans i18nKey={ i18nKey }/>
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { ForkAwesomeIcon } from '../fork-awesome/fork-awesome-icon'
|
||||
|
@ -12,18 +12,18 @@ import { LinkWithTextProps } from './types'
|
|||
|
||||
export const ExternalLink: React.FC<LinkWithTextProps> = ({ href, text, icon, id, className = 'text-light', title }) => {
|
||||
return (
|
||||
<a href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
id={id}
|
||||
className={className}
|
||||
title={title}
|
||||
dir='auto'
|
||||
<a href={ href }
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
id={ id }
|
||||
className={ className }
|
||||
title={ title }
|
||||
dir='auto'
|
||||
>
|
||||
<ShowIf condition={!!icon}>
|
||||
<ForkAwesomeIcon icon={icon as IconName} fixedWidth={true}/>
|
||||
<ShowIf condition={ !!icon }>
|
||||
<ForkAwesomeIcon icon={ icon as IconName } fixedWidth={ true }/>
|
||||
</ShowIf>
|
||||
{text}
|
||||
{ text }
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
@ -13,15 +13,15 @@ import { LinkWithTextProps } from './types'
|
|||
|
||||
export const InternalLink: React.FC<LinkWithTextProps> = ({ href, text, icon, id, className = 'text-light', title }) => {
|
||||
return (
|
||||
<Link to={href}
|
||||
className={className}
|
||||
id={id}
|
||||
title={title}
|
||||
<Link to={ href }
|
||||
className={ className }
|
||||
id={ id }
|
||||
title={ title }
|
||||
>
|
||||
<ShowIf condition={!!icon}>
|
||||
<ForkAwesomeIcon icon={icon as IconName} fixedWidth={true}/>
|
||||
<ShowIf condition={ !!icon }>
|
||||
<ForkAwesomeIcon icon={ icon as IconName } fixedWidth={ true }/>
|
||||
</ShowIf>
|
||||
{text}
|
||||
{ text }
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
@ -12,6 +12,6 @@ import { TranslatedLinkProps } from './types'
|
|||
export const TranslatedExternalLink: React.FC<TranslatedLinkProps> = ({ i18nKey, i18nOption, ...props }) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<ExternalLink text={t(i18nKey, i18nOption)} {...props}/>
|
||||
<ExternalLink text={ t(i18nKey, i18nOption) } { ...props }/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
@ -12,6 +12,6 @@ import { TranslatedLinkProps } from './types'
|
|||
export const TranslatedInternalLink: React.FC<TranslatedLinkProps> = ({ i18nKey, i18nOption, ...props }) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<InternalLink text={t(i18nKey, i18nOption)} {...props}/>
|
||||
<InternalLink text={ t(i18nKey, i18nOption) } { ...props }/>
|
||||
)
|
||||
}
|
||||
|
|
2
src/components/common/links/types.d.ts
vendored
|
@ -19,7 +19,7 @@ export interface LinkWithTextProps extends GeneralLinkProp {
|
|||
text: string
|
||||
}
|
||||
|
||||
export interface TranslatedLinkProps extends GeneralLinkProp{
|
||||
export interface TranslatedLinkProps extends GeneralLinkProp {
|
||||
i18nKey: string
|
||||
i18nOption?: (TOptionsBase & StringMap) | string
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
|
@ -16,7 +16,7 @@ export interface LockButtonProps {
|
|||
|
||||
export const LockButton: React.FC<LockButtonProps> = ({ locked, onLockedChanged, title }) => {
|
||||
return (
|
||||
<Button variant='dark' size='sm' onClick={() => onLockedChanged(!locked)} title={title}>
|
||||
<Button variant='dark' size='sm' onClick={ () => onLockedChanged(!locked) } title={ title }>
|
||||
{ locked
|
||||
? <ForkAwesomeIcon icon='lock'/>
|
||||
: <ForkAwesomeIcon icon='unlock'/>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { Modal } from 'react-bootstrap'
|
||||
|
@ -26,15 +26,16 @@ export const CommonModal: React.FC<CommonModalProps> = ({ show, onHide, titleI18
|
|||
useTranslation()
|
||||
|
||||
return (
|
||||
<Modal data-cy={'limitReachedModal'} show={show} onHide={onHide} animation={true} dialogClassName={`text-dark ${additionalClasses ?? ''}`} size={size}>
|
||||
<Modal.Header closeButton={!!closeButton}>
|
||||
<Modal data-cy={ 'limitReachedModal' } show={ show } onHide={ onHide } animation={ true }
|
||||
dialogClassName={ `text-dark ${ additionalClasses ?? '' }` } size={ size }>
|
||||
<Modal.Header closeButton={ !!closeButton }>
|
||||
<Modal.Title>
|
||||
<ShowIf condition={!!icon}>
|
||||
<ForkAwesomeIcon icon={icon as IconName}/>
|
||||
<ShowIf condition={ !!icon }>
|
||||
<ForkAwesomeIcon icon={ icon as IconName }/>
|
||||
</ShowIf>
|
||||
{ titleI18nKey
|
||||
? <Trans i18nKey={titleI18nKey}/>
|
||||
: <span>{title}</span>
|
||||
? <Trans i18nKey={ titleI18nKey }/>
|
||||
: <span>{ title }</span>
|
||||
}
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { Button, Modal } from 'react-bootstrap'
|
||||
|
@ -18,13 +18,13 @@ export const DeletionModal: React.FC<DeletionModalProps> = ({ show, onHide, titl
|
|||
useTranslation()
|
||||
|
||||
return (
|
||||
<CommonModal show={show} onHide={onHide} titleI18nKey={titleI18nKey} icon={icon} closeButton={true}>
|
||||
<CommonModal show={ show } onHide={ onHide } titleI18nKey={ titleI18nKey } icon={ icon } closeButton={ true }>
|
||||
<Modal.Body className="text-dark">
|
||||
{ children }
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button variant="danger" onClick={onConfirm}>
|
||||
<Trans i18nKey={deletionButtonI18nKey}/>
|
||||
<Button variant="danger" onClick={ onConfirm }>
|
||||
<Trans i18nKey={ deletionButtonI18nKey }/>
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</CommonModal>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { Modal } from 'react-bootstrap'
|
||||
|
@ -10,7 +10,7 @@ import { CommonModal, CommonModalProps } from './common-modal'
|
|||
|
||||
export const ErrorModal: React.FC<CommonModalProps> = ({ show, onHide, titleI18nKey, icon, children }) => {
|
||||
return (
|
||||
<CommonModal show={show} onHide={onHide} titleI18nKey={titleI18nKey} icon={icon} closeButton={true}>
|
||||
<CommonModal show={ show } onHide={ onHide } titleI18nKey={ titleI18nKey } icon={ icon } closeButton={ true }>
|
||||
<Modal.Body className="text-dark text-center">
|
||||
{ children }
|
||||
</Modal.Body>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import equal from 'fast-deep-equal'
|
||||
import React from 'react'
|
||||
|
@ -23,16 +23,16 @@ export const MotdBanner: React.FC = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<ShowIf condition={bannerState.show}>
|
||||
<ShowIf condition={ bannerState.show }>
|
||||
<Alert variant='primary' dir='auto' className='mb-0 text-center d-flex flex-row justify-content-center'>
|
||||
<Link to='/s/banner' className='flex-grow-1 align-self-center text-black'>
|
||||
{bannerState.text}
|
||||
{ bannerState.text }
|
||||
</Link>
|
||||
<Button
|
||||
variant='outline-primary'
|
||||
size='sm'
|
||||
className='mx-2'
|
||||
onClick={dismissBanner}>
|
||||
onClick={ dismissBanner }>
|
||||
<ForkAwesomeIcon icon='times'/>
|
||||
</Button>
|
||||
</Alert>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export const createNumberRangeArray = (length: number) : number[] => {
|
||||
return Array.from(Array(length).keys())
|
||||
export const createNumberRangeArray = (length: number): number[] => {
|
||||
return Array.from(Array(length)
|
||||
.keys())
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
|
||||
export interface PageItemProps {
|
||||
onClick: (index: number) => void
|
||||
index: number
|
||||
onClick: (index: number) => void
|
||||
index: number
|
||||
}
|
||||
|
||||
export const PagerItem: React.FC<PageItemProps> = ({ index, onClick }) => {
|
||||
return (
|
||||
<li className="page-item">
|
||||
<span className="page-link" role="button" onClick={() => onClick(index)}>
|
||||
{index + 1}
|
||||
<span className="page-link" role="button" onClick={ () => onClick(index) }>
|
||||
{ index + 1 }
|
||||
</span>
|
||||
</li>
|
||||
)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Pagination } from 'react-bootstrap'
|
||||
|
@ -53,28 +53,31 @@ export const PagerPagination: React.FC<PaginationProps> = ({ numberOfPageButtons
|
|||
0
|
||||
)
|
||||
|
||||
const paginationItemsBefore = Array.from(new Array(correctedPageIndex - correctedLowerPageIndex)).map((k, index) => {
|
||||
const itemIndex = correctedLowerPageIndex + index
|
||||
return <PagerItem key={itemIndex} index={itemIndex} onClick={setPageIndex}/>
|
||||
})
|
||||
const paginationItemsBefore = Array.from(new Array(correctedPageIndex - correctedLowerPageIndex))
|
||||
.map((k, index) => {
|
||||
const itemIndex = correctedLowerPageIndex + index
|
||||
return <PagerItem key={ itemIndex } index={ itemIndex }
|
||||
onClick={ setPageIndex }/>
|
||||
})
|
||||
|
||||
const paginationItemsAfter = Array.from(new Array(correctedUpperPageIndex - correctedPageIndex)).map((k, index) => {
|
||||
const itemIndex = correctedPageIndex + index + 1
|
||||
return <PagerItem key={itemIndex} index={itemIndex} onClick={setPageIndex}/>
|
||||
})
|
||||
const paginationItemsAfter = Array.from(new Array(correctedUpperPageIndex - correctedPageIndex))
|
||||
.map((k, index) => {
|
||||
const itemIndex = correctedPageIndex + index + 1
|
||||
return <PagerItem key={ itemIndex } index={ itemIndex } onClick={ setPageIndex }/>
|
||||
})
|
||||
|
||||
return (
|
||||
<Pagination dir='ltr'>
|
||||
<ShowIf condition={correctedLowerPageIndex > 0}>
|
||||
<PagerItem key={0} index={0} onClick={setPageIndex}/>
|
||||
<ShowIf condition={ correctedLowerPageIndex > 0 }>
|
||||
<PagerItem key={ 0 } index={ 0 } onClick={ setPageIndex }/>
|
||||
<Pagination.Ellipsis disabled/>
|
||||
</ShowIf>
|
||||
{paginationItemsBefore}
|
||||
<Pagination.Item active>{correctedPageIndex + 1}</Pagination.Item>
|
||||
{paginationItemsAfter}
|
||||
<ShowIf condition={correctedUpperPageIndex < lastPageIndex}>
|
||||
{ paginationItemsBefore }
|
||||
<Pagination.Item active>{ correctedPageIndex + 1 }</Pagination.Item>
|
||||
{ paginationItemsAfter }
|
||||
<ShowIf condition={ correctedUpperPageIndex < lastPageIndex }>
|
||||
<Pagination.Ellipsis disabled/>
|
||||
<PagerItem key={lastPageIndex} index={lastPageIndex} onClick={setPageIndex}/>
|
||||
<PagerItem key={ lastPageIndex } index={ lastPageIndex } onClick={ setPageIndex }/>
|
||||
</ShowIf>
|
||||
</Pagination>
|
||||
)
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment, useEffect } from 'react'
|
||||
|
||||
export interface PagerPageProps {
|
||||
pageIndex: number
|
||||
numberOfElementsPerPage: number
|
||||
onLastPageIndexChange: (lastPageIndex: number) => void
|
||||
pageIndex: number
|
||||
numberOfElementsPerPage: number
|
||||
onLastPageIndexChange: (lastPageIndex: number) => void
|
||||
}
|
||||
|
||||
export const Pager: React.FC<PagerPageProps> = ({ children, numberOfElementsPerPage, pageIndex, onLastPageIndexChange }) => {
|
||||
|
@ -22,10 +22,11 @@ export const Pager: React.FC<PagerPageProps> = ({ children, numberOfElementsPerP
|
|||
|
||||
return <Fragment>
|
||||
{
|
||||
React.Children.toArray(children).filter((value, index) => {
|
||||
const pageOfElement = Math.floor((index) / numberOfElementsPerPage)
|
||||
return (pageOfElement === correctedPageIndex)
|
||||
})
|
||||
React.Children.toArray(children)
|
||||
.filter((value, index) => {
|
||||
const pageOfElement = Math.floor((index) / numberOfElementsPerPage)
|
||||
return (pageOfElement === correctedPageIndex)
|
||||
})
|
||||
}
|
||||
</Fragment>
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { LandingLayout } from '../../landing-layout/landing-layout'
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Redirect } from 'react-router'
|
||||
|
@ -27,7 +27,7 @@ export const Redirector: React.FC = () => {
|
|||
if (error) {
|
||||
return (<NotFoundErrorScreen/>)
|
||||
} else if (!error && error != null) {
|
||||
return (<Redirect to={`/n/${id}`}/>)
|
||||
return (<Redirect to={ `/n/${ id }` }/>)
|
||||
} else {
|
||||
return (<span>Loading</span>)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
|
@ -11,5 +11,5 @@ export interface ShowIfProps {
|
|||
}
|
||||
|
||||
export const ShowIf: React.FC<ShowIfProps> = ({ children, condition }) => {
|
||||
return condition ? <Fragment>{children}</Fragment> : null
|
||||
return condition ? <Fragment>{ children }</Fragment> : null
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
@ -21,15 +21,15 @@ const UserAvatar: React.FC<UserAvatarProps> = ({ name, photo, size, additionalCl
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<span className={'d-inline-flex align-items-center ' + additionalClasses}>
|
||||
<span className={ 'd-inline-flex align-items-center ' + additionalClasses }>
|
||||
<img
|
||||
src={photo}
|
||||
className={`user-avatar rounded mr-1 ${size ?? ''}`}
|
||||
alt={t('common.avatarOf', { name })}
|
||||
title={name}
|
||||
src={ photo }
|
||||
className={ `user-avatar rounded mr-1 ${ size ?? '' }` }
|
||||
alt={ t('common.avatarOf', { name }) }
|
||||
title={ name }
|
||||
/>
|
||||
<ShowIf condition={showName}>
|
||||
<span className="mx-1 user-line-name">{name}</span>
|
||||
<ShowIf condition={ showName }>
|
||||
<span className="mx-1 user-line-name">{ name }</span>
|
||||
</ShowIf>
|
||||
</span>
|
||||
)
|
||||
|
|
|
@ -17,11 +17,11 @@ export const ErrorWhileLoadingNoteAlert: React.FC<ErrorWhileLoadingNoteAlertProp
|
|||
useTranslation()
|
||||
|
||||
return (
|
||||
<ShowIf condition={show}>
|
||||
<Alert variant={'danger'} className={'my-2'}>
|
||||
<b><Trans i18nKey={'views.readOnly.error.title'}/></b>
|
||||
<ShowIf condition={ show }>
|
||||
<Alert variant={ 'danger' } className={ 'my-2' }>
|
||||
<b><Trans i18nKey={ 'views.readOnly.error.title' }/></b>
|
||||
<br/>
|
||||
<Trans i18nKey={'views.readOnly.error.description'}/>
|
||||
<Trans i18nKey={ 'views.readOnly.error.description' }/>
|
||||
</Alert>
|
||||
</ShowIf>
|
||||
)
|
||||
|
|
|
@ -15,9 +15,9 @@ export interface LoadingNoteAlertProps {
|
|||
|
||||
export const LoadingNoteAlert: React.FC<LoadingNoteAlertProps> = ({ show }) => {
|
||||
return (
|
||||
<ShowIf condition={show}>
|
||||
<Alert variant={'info'} className={'my-2'}>
|
||||
<Trans i18nKey={'views.readOnly.loading'}/>
|
||||
<ShowIf condition={ show }>
|
||||
<Alert variant={ 'info' } className={ 'my-2' }>
|
||||
<Trans i18nKey={ 'views.readOnly.loading' }/>
|
||||
</Alert>
|
||||
</ShowIf>
|
||||
)
|
||||
|
|
|
@ -37,30 +37,32 @@ export const DocumentInfobar: React.FC<DocumentInfobarProps> = ({
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={'d-flex flex-row my-3 document-infobar'}>
|
||||
<div className={'col-md'}> </div>
|
||||
<div className={'d-flex flex-fill'}>
|
||||
<div className={'d-flex flex-column'}>
|
||||
<div className={ 'd-flex flex-row my-3 document-infobar' }>
|
||||
<div className={ 'col-md' }> </div>
|
||||
<div className={ 'd-flex flex-fill' }>
|
||||
<div className={ 'd-flex flex-column' }>
|
||||
<DocumentInfoTimeLine
|
||||
mode={DocumentInfoLineWithTimeMode.CREATED}
|
||||
time={createdTime}
|
||||
userName={createdAuthor}
|
||||
profileImageSrc={'/img/avatar.png'}/>
|
||||
mode={ DocumentInfoLineWithTimeMode.CREATED }
|
||||
time={ createdTime }
|
||||
userName={ createdAuthor }
|
||||
profileImageSrc={ '/img/avatar.png' }/>
|
||||
<DocumentInfoTimeLine
|
||||
mode={DocumentInfoLineWithTimeMode.EDITED}
|
||||
time={changedTime}
|
||||
userName={changedAuthor}
|
||||
profileImageSrc={'/img/avatar.png'}/>
|
||||
mode={ DocumentInfoLineWithTimeMode.EDITED }
|
||||
time={ changedTime }
|
||||
userName={ changedAuthor }
|
||||
profileImageSrc={ '/img/avatar.png' }/>
|
||||
<hr/>
|
||||
</div>
|
||||
<span className={'ml-auto'}>
|
||||
{ viewCount } <Trans i18nKey={'views.readOnly.viewCount'}/>
|
||||
<ShowIf condition={editable}>
|
||||
<InternalLink text={''} href={`/n/${noteId}`} icon={'pencil'} className={'text-primary text-decoration-none mx-1'} title={t('views.readOnly.editNote')}/>
|
||||
<span className={ 'ml-auto' }>
|
||||
{ viewCount } <Trans i18nKey={ 'views.readOnly.viewCount' }/>
|
||||
<ShowIf condition={ editable }>
|
||||
<InternalLink text={ '' } href={ `/n/${ noteId }` } icon={ 'pencil' }
|
||||
className={ 'text-primary text-decoration-none mx-1' }
|
||||
title={ t('views.readOnly.editNote') }/>
|
||||
</ShowIf>
|
||||
</span>
|
||||
</div>
|
||||
<div className={'col-md'}> </div>
|
||||
<div className={ 'col-md' }> </div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -38,27 +38,27 @@ export const DocumentReadOnlyPage: React.FC = () => {
|
|||
const noteDetails = useSelector((state: ApplicationState) => state.noteDetails)
|
||||
|
||||
return (
|
||||
<div className={'d-flex flex-column mvh-100 bg-light'}>
|
||||
<div className={ 'd-flex flex-column mvh-100 bg-light' }>
|
||||
<MotdBanner/>
|
||||
<AppBar mode={AppBarMode.BASIC}/>
|
||||
<div className={'container'}>
|
||||
<ErrorWhileLoadingNoteAlert show={error}/>
|
||||
<LoadingNoteAlert show={loading}/>
|
||||
<AppBar mode={ AppBarMode.BASIC }/>
|
||||
<div className={ 'container' }>
|
||||
<ErrorWhileLoadingNoteAlert show={ error }/>
|
||||
<LoadingNoteAlert show={ loading }/>
|
||||
</div>
|
||||
<ShowIf condition={!error && !loading}>
|
||||
<ShowIf condition={ !error && !loading }>
|
||||
<DocumentInfobar
|
||||
changedAuthor={noteDetails.lastChange.userId ?? ''}
|
||||
changedTime={noteDetails.lastChange.timestamp}
|
||||
createdAuthor={'Test'}
|
||||
createdTime={noteDetails.createTime}
|
||||
editable={true}
|
||||
noteId={id}
|
||||
viewCount={noteDetails.viewCount}
|
||||
changedAuthor={ noteDetails.lastChange.userId ?? '' }
|
||||
changedTime={ noteDetails.lastChange.timestamp }
|
||||
createdAuthor={ 'Test' }
|
||||
createdTime={ noteDetails.createTime }
|
||||
editable={ true }
|
||||
noteId={ id }
|
||||
viewCount={ noteDetails.viewCount }
|
||||
/>
|
||||
<RenderIframe extraClasses={"flex-fill"}
|
||||
markdownContent={markdownContent}
|
||||
onFirstHeadingChange={onFirstHeadingChange}
|
||||
onFrontmatterChange={onFrontmatterChange}/>
|
||||
<RenderIframe extraClasses={ 'flex-fill' }
|
||||
markdownContent={ markdownContent }
|
||||
onFirstHeadingChange={ onFirstHeadingChange }
|
||||
onFrontmatterChange={ onFrontmatterChange }/>
|
||||
</ShowIf>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -37,20 +37,21 @@ export const AppBar: React.FC<AppBarProps> = ({ mode }) => {
|
|||
const userExists = useSelector((state: ApplicationState) => !!state.user)
|
||||
|
||||
return (
|
||||
<Navbar bg={'light'}>
|
||||
<Navbar bg={ 'light' }>
|
||||
<Nav className="mr-auto d-flex align-items-center">
|
||||
<NavbarBranding/>
|
||||
<ShowIf condition={mode === AppBarMode.EDITOR}>
|
||||
<ShowIf condition={ mode === AppBarMode.EDITOR }>
|
||||
<EditorViewMode/>
|
||||
<SyncScrollButtons/>
|
||||
</ShowIf>
|
||||
<DarkModeButton/>
|
||||
<Link to={`/p/${id}`} target='_blank'>
|
||||
<Button title={t('editor.documentBar.slideMode')} className="ml-2 text-secondary" size="sm" variant="outline-light">
|
||||
<Link to={ `/p/${ id }` } target='_blank'>
|
||||
<Button title={ t('editor.documentBar.slideMode') } className="ml-2 text-secondary" size="sm"
|
||||
variant="outline-light">
|
||||
<ForkAwesomeIcon icon="television"/>
|
||||
</Button>
|
||||
</Link>
|
||||
<ShowIf condition={mode === AppBarMode.EDITOR}>
|
||||
<ShowIf condition={ mode === AppBarMode.EDITOR }>
|
||||
<HelpButton/>
|
||||
</ShowIf>
|
||||
</Nav>
|
||||
|
@ -58,11 +59,11 @@ export const AppBar: React.FC<AppBarProps> = ({ mode }) => {
|
|||
<Button className="mx-2" size="sm" variant="primary">
|
||||
<ForkAwesomeIcon icon="plus"/> <Trans i18nKey="editor.appBar.new"/>
|
||||
</Button>
|
||||
<ShowIf condition={!userExists}>
|
||||
<SignInButton size={'sm'} />
|
||||
<ShowIf condition={ !userExists }>
|
||||
<SignInButton size={ 'sm' }/>
|
||||
</ShowIf>
|
||||
<ShowIf condition={userExists}>
|
||||
<UserDropdown />
|
||||
<ShowIf condition={ userExists }>
|
||||
<UserDropdown/>
|
||||
</ShowIf>
|
||||
</Nav>
|
||||
</Navbar>
|
||||
|
|
|
@ -24,22 +24,22 @@ const DarkModeButton: React.FC = () => {
|
|||
<ToggleButtonGroup
|
||||
type="radio"
|
||||
name="dark-mode"
|
||||
value={darkModeEnabled}
|
||||
value={ darkModeEnabled }
|
||||
className="ml-2"
|
||||
>
|
||||
<ToggleButton
|
||||
value={DarkModeState.DARK}
|
||||
value={ DarkModeState.DARK }
|
||||
variant="outline-secondary"
|
||||
title={t('editor.darkMode.switchToDark')}
|
||||
onChange={() => setDarkMode(true)}
|
||||
title={ t('editor.darkMode.switchToDark') }
|
||||
onChange={ () => setDarkMode(true) }
|
||||
>
|
||||
<ForkAwesomeIcon icon="moon"/>
|
||||
</ToggleButton>
|
||||
<ToggleButton
|
||||
value={DarkModeState.LIGHT}
|
||||
value={ DarkModeState.LIGHT }
|
||||
variant="outline-secondary"
|
||||
title={t('editor.darkMode.switchToLight')}
|
||||
onChange={() => setDarkMode(false)}
|
||||
title={ t('editor.darkMode.switchToLight') }
|
||||
onChange={ () => setDarkMode(false) }
|
||||
>
|
||||
<ForkAwesomeIcon icon="sun-o"/>
|
||||
</ToggleButton>
|
||||
|
|
|
@ -25,17 +25,17 @@ export const EditorViewMode: React.FC = () => {
|
|||
<ToggleButtonGroup
|
||||
type="radio"
|
||||
name="options"
|
||||
value={editorMode}
|
||||
onChange={(value: EditorMode) => {
|
||||
value={ editorMode }
|
||||
onChange={ (value: EditorMode) => {
|
||||
setEditorMode(value)
|
||||
}}>
|
||||
<ToggleButton value={EditorMode.PREVIEW} variant="outline-secondary" title={t('editor.viewMode.view')}>
|
||||
} }>
|
||||
<ToggleButton value={ EditorMode.PREVIEW } variant="outline-secondary" title={ t('editor.viewMode.view') }>
|
||||
<ForkAwesomeIcon icon="eye"/>
|
||||
</ToggleButton>
|
||||
<ToggleButton value={EditorMode.BOTH} variant="outline-secondary" title={t('editor.viewMode.both')}>
|
||||
<ToggleButton value={ EditorMode.BOTH } variant="outline-secondary" title={ t('editor.viewMode.both') }>
|
||||
<ForkAwesomeIcon icon="columns"/>
|
||||
</ToggleButton>
|
||||
<ToggleButton value={EditorMode.EDITOR} variant="outline-secondary" title={t('editor.viewMode.edit')}>
|
||||
<ToggleButton value={ EditorMode.EDITOR } variant="outline-secondary" title={ t('editor.viewMode.edit') }>
|
||||
<ForkAwesomeIcon icon="pencil"/>
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
|
|
|
@ -15,24 +15,24 @@ import './cheatsheet.scss'
|
|||
export const Cheatsheet: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const codes = [
|
||||
`**${t('editor.editorToolbar.bold')}**`,
|
||||
`*${t('editor.editorToolbar.italic')}*`,
|
||||
`++${t('editor.editorToolbar.underline')}++`,
|
||||
`~~${t('editor.editorToolbar.strikethrough')}~~`,
|
||||
`**${ t('editor.editorToolbar.bold') }**`,
|
||||
`*${ t('editor.editorToolbar.italic') }*`,
|
||||
`++${ t('editor.editorToolbar.underline') }++`,
|
||||
`~~${ t('editor.editorToolbar.strikethrough') }~~`,
|
||||
'H~2~O',
|
||||
'19^th^',
|
||||
`==${t('editor.help.cheatsheet.highlightedText')}==`,
|
||||
`# ${t('editor.editorToolbar.header')}`,
|
||||
`\`${t('editor.editorToolbar.code')}\``,
|
||||
`==${ t('editor.help.cheatsheet.highlightedText') }==`,
|
||||
`# ${ t('editor.editorToolbar.header') }`,
|
||||
`\`${ t('editor.editorToolbar.code') }\``,
|
||||
'```javascript=\nvar x = 5;\n```',
|
||||
`> ${t('editor.editorToolbar.blockquote')}`,
|
||||
`- ${t('editor.editorToolbar.unorderedList')}`,
|
||||
`1. ${t('editor.editorToolbar.orderedList')}`,
|
||||
`- [ ] ${t('editor.editorToolbar.checkList')}`,
|
||||
`[${t('editor.editorToolbar.link')}](https://example.com)`,
|
||||
`![${t('editor.editorToolbar.image')}](/icons/mstile-70x70.png)`,
|
||||
`> ${ t('editor.editorToolbar.blockquote') }`,
|
||||
`- ${ t('editor.editorToolbar.unorderedList') }`,
|
||||
`1. ${ t('editor.editorToolbar.orderedList') }`,
|
||||
`- [ ] ${ t('editor.editorToolbar.checkList') }`,
|
||||
`[${ t('editor.editorToolbar.link') }](https://example.com)`,
|
||||
`![${ t('editor.editorToolbar.image') }](/icons/mstile-70x70.png)`,
|
||||
':smile:',
|
||||
`:::info\n${t('editor.help.cheatsheet.exampleAlert')}\n:::`
|
||||
`:::info\n${ t('editor.help.cheatsheet.exampleAlert') }\n:::`
|
||||
]
|
||||
|
||||
const markdownIt = useMemo(() => {
|
||||
|
@ -43,26 +43,26 @@ export const Cheatsheet: React.FC = () => {
|
|||
return (
|
||||
<Table className="table-condensed table-cheatsheet">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><Trans i18nKey='editor.help.cheatsheet.example'/></th>
|
||||
<th><Trans i18nKey='editor.help.cheatsheet.syntax'/></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><Trans i18nKey='editor.help.cheatsheet.example'/></th>
|
||||
<th><Trans i18nKey='editor.help.cheatsheet.syntax'/></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{codes.map((code, key) => {
|
||||
return (
|
||||
<tr key={key}>
|
||||
<td>
|
||||
<BasicMarkdownRenderer
|
||||
content={code}
|
||||
markdownIt={markdownIt}/>
|
||||
</td>
|
||||
<td className={'markdown-body'}>
|
||||
<HighlightedCode code={code} wrapLines={true} startLineNumber={1} language={'markdown'}/>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
{ codes.map((code, key) => {
|
||||
return (
|
||||
<tr key={ key }>
|
||||
<td>
|
||||
<BasicMarkdownRenderer
|
||||
content={ code }
|
||||
markdownIt={ markdownIt }/>
|
||||
</td>
|
||||
<td className={ 'markdown-body' }>
|
||||
<HighlightedCode code={ code } wrapLines={ true } startLineNumber={ 1 } language={ 'markdown' }/>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
}) }
|
||||
</tbody>
|
||||
</Table>
|
||||
)
|
||||
|
|
|
@ -13,9 +13,9 @@ import { Links } from './links'
|
|||
import { Shortcut } from './shortcuts'
|
||||
|
||||
export enum HelpTabStatus {
|
||||
Cheatsheet='cheatsheet.title',
|
||||
Shortcuts='shortcuts.title',
|
||||
Links='links.title'
|
||||
Cheatsheet = 'cheatsheet.title',
|
||||
Shortcuts = 'shortcuts.title',
|
||||
Links = 'links.title'
|
||||
}
|
||||
|
||||
export const HelpButton: React.FC = () => {
|
||||
|
@ -36,35 +36,39 @@ export const HelpButton: React.FC = () => {
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
<Button title={t('editor.documentBar.help')} className='ml-2 text-secondary' size='sm' variant='outline-light'
|
||||
onClick={() => setShow(true)}>
|
||||
<Button title={ t('editor.documentBar.help') } className='ml-2 text-secondary' size='sm' variant='outline-light'
|
||||
onClick={ () => setShow(true) }>
|
||||
<ForkAwesomeIcon icon="question-circle"/>
|
||||
</Button>
|
||||
<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.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.Header>
|
||||
<Modal.Body>
|
||||
<nav className='nav nav-tabs'>
|
||||
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Cheatsheet ? 'active' : ''}`}
|
||||
onClick={() => setTab(HelpTabStatus.Cheatsheet)}
|
||||
<Button variant={ 'light' }
|
||||
className={ `nav-link nav-item ${ tab === HelpTabStatus.Cheatsheet ? 'active' : '' }` }
|
||||
onClick={ () => setTab(HelpTabStatus.Cheatsheet) }
|
||||
>
|
||||
<Trans i18nKey={'editor.help.cheatsheet.title'}/>
|
||||
<Trans i18nKey={ 'editor.help.cheatsheet.title' }/>
|
||||
</Button>
|
||||
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Shortcuts ? 'active' : ''}`}
|
||||
onClick={() => setTab(HelpTabStatus.Shortcuts)}
|
||||
<Button variant={ 'light' }
|
||||
className={ `nav-link nav-item ${ tab === HelpTabStatus.Shortcuts ? 'active' : '' }` }
|
||||
onClick={ () => setTab(HelpTabStatus.Shortcuts) }
|
||||
>
|
||||
<Trans i18nKey={'editor.help.shortcuts.title'}/>
|
||||
<Trans i18nKey={ 'editor.help.shortcuts.title' }/>
|
||||
</Button>
|
||||
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Links ? 'active' : ''}`}
|
||||
onClick={() => setTab(HelpTabStatus.Links)}
|
||||
<Button variant={ 'light' }
|
||||
className={ `nav-link nav-item ${ tab === HelpTabStatus.Links ? 'active' : '' }` }
|
||||
onClick={ () => setTab(HelpTabStatus.Links) }
|
||||
>
|
||||
<Trans i18nKey={'editor.help.links.title'}/>
|
||||
<Trans i18nKey={ 'editor.help.links.title' }/>
|
||||
</Button>
|
||||
</nav>
|
||||
{tabContent()}
|
||||
{ tabContent() }
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</Fragment>
|
||||
|
|
|
@ -18,15 +18,15 @@ export const Links: React.FC = () => {
|
|||
|
||||
const backendIssueTracker = useSelector((state: ApplicationState) => state.config.version.issueTrackerUrl)
|
||||
return (
|
||||
<Row className={'justify-content-center pt-4'}>
|
||||
<Col lg={4}>
|
||||
<Row className={ 'justify-content-center pt-4' }>
|
||||
<Col lg={ 4 }>
|
||||
<h3><Trans i18nKey='editor.help.contacts.title'/></h3>
|
||||
<div>
|
||||
<ul className="list-unstyled">
|
||||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.contacts.community'
|
||||
href={links.community}
|
||||
href={ links.community }
|
||||
icon='users'
|
||||
className='text-primary'
|
||||
/>
|
||||
|
@ -34,8 +34,8 @@ export const Links: React.FC = () => {
|
|||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.contacts.meetUsOn'
|
||||
i18nOption={{ service: 'Matrix' }}
|
||||
href={links.chat}
|
||||
i18nOption={ { service: 'Matrix' } }
|
||||
href={ links.chat }
|
||||
icon='hashtag'
|
||||
className='text-primary'
|
||||
/>
|
||||
|
@ -43,7 +43,7 @@ export const Links: React.FC = () => {
|
|||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.contacts.reportIssue'
|
||||
href={backendIssueTracker}
|
||||
href={ backendIssueTracker }
|
||||
icon='tag'
|
||||
className='text-primary'
|
||||
/>
|
||||
|
@ -51,7 +51,7 @@ export const Links: React.FC = () => {
|
|||
<li>
|
||||
<TranslatedExternalLink
|
||||
i18nKey='editor.help.contacts.helpTranslating'
|
||||
href={links.translate}
|
||||
href={ links.translate }
|
||||
icon='language'
|
||||
className='text-primary'
|
||||
/>
|
||||
|
@ -59,7 +59,7 @@ export const Links: React.FC = () => {
|
|||
</ul>
|
||||
</div>
|
||||
</Col>
|
||||
<Col lg={4}>
|
||||
<Col lg={ 4 }>
|
||||
<h3><Trans i18nKey='editor.help.documents.title'/></h3>
|
||||
<div>
|
||||
<ul className="list-unstyled">
|
||||
|
|
|
@ -13,7 +13,7 @@ export const Shortcut: React.FC = () => {
|
|||
const modifierKey = isMac ? <kbd>⌘</kbd> : <kbd>Ctrl</kbd>
|
||||
const altKey = isMac ? <kbd>⌥</kbd> : <kbd>Alt</kbd>
|
||||
|
||||
const shortcutMap: {[category: string]: { [functionName: string]: JSX.Element[] }} = {
|
||||
const shortcutMap: { [category: string]: { [functionName: string]: JSX.Element[] } } = {
|
||||
'View Mode': {
|
||||
'editor.help.shortcuts.view': [<kbd>Ctrl</kbd>, <> + </>, altKey, <> + </>, <kbd>V</kbd>],
|
||||
'editor.help.shortcuts.both': [<kbd>Ctrl</kbd>, <> + </>, altKey, <> + </>, <kbd>B</kbd>],
|
||||
|
@ -29,28 +29,30 @@ export const Shortcut: React.FC = () => {
|
|||
}
|
||||
}
|
||||
return (
|
||||
<Row className={'justify-content-center pt-4'}>
|
||||
{Object.keys(shortcutMap).map(category => {
|
||||
return (
|
||||
<Card key={category} className={'m-2 w-50'}>
|
||||
<Card.Header>{category}</Card.Header>
|
||||
<ListGroup variant="flush">
|
||||
{Object.entries(shortcutMap[category]).map(([functionName, shortcuts]) => {
|
||||
<Row className={ 'justify-content-center pt-4' }>
|
||||
{ Object.keys(shortcutMap)
|
||||
.map(category => {
|
||||
return (
|
||||
<ListGroup.Item key={functionName} className={'d-flex justify-content-between'}>
|
||||
<span><Trans i18nKey={functionName}/></span>
|
||||
<span>
|
||||
<Card key={ category } className={ 'm-2 w-50' }>
|
||||
<Card.Header>{ category }</Card.Header>
|
||||
<ListGroup variant="flush">
|
||||
{ Object.entries(shortcutMap[category])
|
||||
.map(([functionName, shortcuts]) => {
|
||||
return (
|
||||
<ListGroup.Item key={ functionName } className={ 'd-flex justify-content-between' }>
|
||||
<span><Trans i18nKey={ functionName }/></span>
|
||||
<span>
|
||||
{
|
||||
shortcuts.map((shortcut, shortcutIndex) =>
|
||||
<Fragment key={shortcutIndex}>{shortcut}</Fragment>)
|
||||
<Fragment key={ shortcutIndex }>{ shortcut }</Fragment>)
|
||||
}
|
||||
</span>
|
||||
</ListGroup.Item>
|
||||
)
|
||||
})}
|
||||
</ListGroup>
|
||||
</Card>)
|
||||
})
|
||||
</ListGroup.Item>
|
||||
)
|
||||
}) }
|
||||
</ListGroup>
|
||||
</Card>)
|
||||
})
|
||||
}
|
||||
</Row>
|
||||
)
|
||||
|
|
|
@ -22,9 +22,9 @@ export const NavbarBranding: React.FC = () => {
|
|||
<Navbar.Brand>
|
||||
<Link to="/intro" className="text-secondary text-decoration-none d-flex align-items-center">
|
||||
<HedgeDocLogoWithText
|
||||
logoType={darkModeActivated ? HedgeDocLogoType.WB_HORIZONTAL : HedgeDocLogoType.BW_HORIZONTAL}
|
||||
size={HedgeDocLogoSize.SMALL}/>
|
||||
<Branding inline={true}/>
|
||||
logoType={ darkModeActivated ? HedgeDocLogoType.WB_HORIZONTAL : HedgeDocLogoType.BW_HORIZONTAL }
|
||||
size={ HedgeDocLogoSize.SMALL }/>
|
||||
<Branding inline={ true }/>
|
||||
</Link>
|
||||
</Navbar.Brand>
|
||||
)
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/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:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 135.46666 135.46666"
|
||||
|
@ -13,75 +13,75 @@
|
|||
id="svg8"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||
sodipodi:docname="buttonIcon.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
fit-margin-bottom="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-top="0"
|
||||
id="base"
|
||||
pagecolor="#545b62"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="151.94971"
|
||||
inkscape:cy="220.06486"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="3434"
|
||||
inkscape:window-height="1321"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="84"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:pagecheckerboard="false" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(253.17277,890.86874)"
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
id="path864"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000"
|
||||
d="m -185.5862,-882.45881 c -1.05348,0.0354 -2.05943,0.44876 -2.83393,1.16582 l -17.37672,16.08016 c -1.77986,1.64837 -1.89553,4.45148 -0.25787,6.24199 1.63744,1.79079 4.43758,1.90901 6.21875,0.262 l 14.39653,-13.32218 14.39654,13.32218 c 1.78118,1.64702 4.5813,1.5288 6.21874,-0.262 1.63691,-1.79129 1.52077,-4.59444 -0.25993,-6.24199 l -17.37465,-16.08016 c -0.84861,-0.78564 -1.97318,-1.20418 -3.12746,-1.16582 z" />
|
||||
<path
|
||||
id="path851"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000"
|
||||
d="m -202.99806,-788.72004 c -1.12724,0.0475 -2.23794,0.52467 -3.05666,1.42007 -1.63766,1.79051 -1.52199,4.59363 0.25787,6.24199 l 17.37672,16.08016 c 0.7745,0.71706 1.78045,1.13042 2.83393,1.16582 1.15428,0.0384 2.27885,-0.38018 3.12746,-1.16582 l 17.37465,-16.08016 c 1.7807,-1.64754 1.89684,-4.4507 0.25993,-6.24199 -1.63744,-1.79081 -4.43756,-1.90902 -6.21874,-0.262 l -14.39654,13.32218 -14.39653,-13.32218 c -0.89058,-0.8235 -2.03485,-1.20561 -3.16209,-1.15807 z" />
|
||||
<circle
|
||||
r="16"
|
||||
cy="-823.13544"
|
||||
cx="-185.43944"
|
||||
id="path845"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.565;stroke-linecap:round;stroke-linejoin:round" />
|
||||
<defs
|
||||
id="defs2"/>
|
||||
<sodipodi:namedview
|
||||
fit-margin-bottom="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-top="0"
|
||||
id="base"
|
||||
pagecolor="#545b62"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="151.94971"
|
||||
inkscape:cy="220.06486"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="3434"
|
||||
inkscape:window-height="1321"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="84"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:pagecheckerboard="false"/>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
style="display:inline;opacity:1;stroke:none;stroke-opacity:1"
|
||||
id="g855">
|
||||
<path
|
||||
id="path858"
|
||||
d="m -128.54012,-883.40784 -121.89532,111.71083 8.0967,8.83405 121.89531,-111.71083 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.565;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1" />
|
||||
<path
|
||||
id="path860"
|
||||
d="m -128.61914,-886.18945 a 2.7827783,2.7827783 0 0 0 -1.80078,0.73047 l -121.89453,111.71093 a 2.7827783,2.7827783 0 0 0 -0.17188,3.93164 l 8.09571,8.83399 a 2.7827783,2.7827783 0 0 0 3.93164,0.16992 l 121.89648,-111.70898 a 2.7827783,2.7827783 0 0 0 0.16992,-3.93164 l -8.0957,-8.83399 a 2.7827783,2.7827783 0 0 0 -2.13086,-0.90234 z m -0.0937,6.71289 4.33789,4.73047 -117.79297,107.95117 -4.33594,-4.73047 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#545b62;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.565;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1" />
|
||||
transform="translate(253.17277,890.86874)"
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
id="path864"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000"
|
||||
d="m -185.5862,-882.45881 c -1.05348,0.0354 -2.05943,0.44876 -2.83393,1.16582 l -17.37672,16.08016 c -1.77986,1.64837 -1.89553,4.45148 -0.25787,6.24199 1.63744,1.79079 4.43758,1.90901 6.21875,0.262 l 14.39653,-13.32218 14.39654,13.32218 c 1.78118,1.64702 4.5813,1.5288 6.21874,-0.262 1.63691,-1.79129 1.52077,-4.59444 -0.25993,-6.24199 l -17.37465,-16.08016 c -0.84861,-0.78564 -1.97318,-1.20418 -3.12746,-1.16582 z"/>
|
||||
<path
|
||||
id="path851"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000"
|
||||
d="m -202.99806,-788.72004 c -1.12724,0.0475 -2.23794,0.52467 -3.05666,1.42007 -1.63766,1.79051 -1.52199,4.59363 0.25787,6.24199 l 17.37672,16.08016 c 0.7745,0.71706 1.78045,1.13042 2.83393,1.16582 1.15428,0.0384 2.27885,-0.38018 3.12746,-1.16582 l 17.37465,-16.08016 c 1.7807,-1.64754 1.89684,-4.4507 0.25993,-6.24199 -1.63744,-1.79081 -4.43756,-1.90902 -6.21874,-0.262 l -14.39654,13.32218 -14.39653,-13.32218 c -0.89058,-0.8235 -2.03485,-1.20561 -3.16209,-1.15807 z"/>
|
||||
<circle
|
||||
r="16"
|
||||
cy="-823.13544"
|
||||
cx="-185.43944"
|
||||
id="path845"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.565;stroke-linecap:round;stroke-linejoin:round"/>
|
||||
<g
|
||||
style="display:inline;opacity:1;stroke:none;stroke-opacity:1"
|
||||
id="g855">
|
||||
<path
|
||||
id="path858"
|
||||
d="m -128.54012,-883.40784 -121.89532,111.71083 8.0967,8.83405 121.89531,-111.71083 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.565;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"/>
|
||||
<path
|
||||
id="path860"
|
||||
d="m -128.61914,-886.18945 a 2.7827783,2.7827783 0 0 0 -1.80078,0.73047 l -121.89453,111.71093 a 2.7827783,2.7827783 0 0 0 -0.17188,3.93164 l 8.09571,8.83399 a 2.7827783,2.7827783 0 0 0 3.93164,0.16992 l 121.89648,-111.70898 a 2.7827783,2.7827783 0 0 0 0.16992,-3.93164 l -8.0957,-8.83399 a 2.7827783,2.7827783 0 0 0 -2.13086,-0.90234 z m -0.0937,6.71289 4.33789,4.73047 -117.79297,107.95117 -4.33594,-4.73047 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#545b62;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.565;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 9.4 KiB |
|
@ -9,6 +9,7 @@
|
|||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
svg g {
|
||||
@import "../../../../style/variables.light";
|
||||
|
|
|
@ -24,21 +24,21 @@ export const SyncScrollButtons: React.FC = () => {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<ToggleButtonGroup type="radio" defaultValue={[]} name="sync-scroll" className={'ml-2 sync-scroll-buttons'}
|
||||
value={syncScrollEnabled}>
|
||||
<ToggleButtonGroup type="radio" defaultValue={ [] } name="sync-scroll" className={ 'ml-2 sync-scroll-buttons' }
|
||||
value={ syncScrollEnabled }>
|
||||
<ToggleButton
|
||||
variant={'outline-secondary'}
|
||||
title={t('editor.appBar.syncScroll.enable')}
|
||||
onChange={() => setEditorSyncScroll(true)}
|
||||
value={SyncScrollState.SYNCED}
|
||||
variant={ 'outline-secondary' }
|
||||
title={ t('editor.appBar.syncScroll.enable') }
|
||||
onChange={ () => setEditorSyncScroll(true) }
|
||||
value={ SyncScrollState.SYNCED }
|
||||
>
|
||||
<EnabledScrollIcon/>
|
||||
</ToggleButton>
|
||||
<ToggleButton
|
||||
variant={'outline-secondary'}
|
||||
title={t('editor.appBar.syncScroll.disable')}
|
||||
onChange={() => setEditorSyncScroll(false)}
|
||||
value={SyncScrollState.UNSYNCED}
|
||||
variant={ 'outline-secondary' }
|
||||
title={ t('editor.appBar.syncScroll.disable') }
|
||||
onChange={ () => setEditorSyncScroll(false) }
|
||||
value={ SyncScrollState.UNSYNCED }
|
||||
>
|
||||
<DisabledScrollIcon/>
|
||||
</ToggleButton>
|
||||
|
|
|
@ -15,10 +15,10 @@ export interface DocumentInfoLineProps {
|
|||
|
||||
export const DocumentInfoLine: React.FC<DocumentInfoLineProps> = ({ icon, size, children }) => {
|
||||
return (
|
||||
<span className={'d-flex align-items-center'}>
|
||||
<ForkAwesomeIcon icon={icon} size={size} fixedWidth={true} className={'mx-2'}/>
|
||||
<i className={'d-flex align-items-center'}>
|
||||
{children}
|
||||
<span className={ 'd-flex align-items-center' }>
|
||||
<ForkAwesomeIcon icon={ icon } size={ size } fixedWidth={ true } className={ 'mx-2' }/>
|
||||
<i className={ 'd-flex align-items-center' }>
|
||||
{ children }
|
||||
</i>
|
||||
</span>
|
||||
)
|
||||
|
|
|
@ -18,47 +18,49 @@ export interface DocumentInfoModalProps {
|
|||
onHide: () => void
|
||||
}
|
||||
|
||||
export const DocumentInfoModal: React.FC<DocumentInfoModalProps> = ({show, onHide}) => {
|
||||
return (
|
||||
<CommonModal
|
||||
show={show}
|
||||
onHide={onHide}
|
||||
closeButton={true}
|
||||
titleI18nKey={'editor.modal.documentInfo.title'}>
|
||||
<Modal.Body>
|
||||
<ListGroup>
|
||||
<ListGroup.Item>
|
||||
<DocumentInfoTimeLine
|
||||
size={'2x'}
|
||||
mode={DocumentInfoLineWithTimeMode.CREATED}
|
||||
time={DateTime.local().minus({ days: 11 })}
|
||||
userName={'Tilman'}
|
||||
profileImageSrc={'/img/avatar.png'}/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<DocumentInfoTimeLine
|
||||
size={'2x'}
|
||||
mode={DocumentInfoLineWithTimeMode.EDITED}
|
||||
time={DateTime.local().minus({ minutes: 3 })}
|
||||
userName={'Philip'}
|
||||
profileImageSrc={'/img/avatar.png'}/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<DocumentInfoLine icon={'users'} size={'2x'}>
|
||||
<Trans i18nKey='editor.modal.documentInfo.usersContributed'>
|
||||
<UnitalicBoldText text={'42'}/>
|
||||
</Trans>
|
||||
</DocumentInfoLine>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<DocumentInfoLine icon={'history'} size={'2x'}>
|
||||
<Trans i18nKey='editor.modal.documentInfo.revisions'>
|
||||
<UnitalicBoldText text={'192'}/>
|
||||
</Trans>
|
||||
</DocumentInfoLine>
|
||||
</ListGroup.Item>
|
||||
</ListGroup>
|
||||
</Modal.Body>
|
||||
</CommonModal>
|
||||
);
|
||||
export const DocumentInfoModal: React.FC<DocumentInfoModalProps> = ({ show, onHide }) => {
|
||||
return (
|
||||
<CommonModal
|
||||
show={ show }
|
||||
onHide={ onHide }
|
||||
closeButton={ true }
|
||||
titleI18nKey={ 'editor.modal.documentInfo.title' }>
|
||||
<Modal.Body>
|
||||
<ListGroup>
|
||||
<ListGroup.Item>
|
||||
<DocumentInfoTimeLine
|
||||
size={ '2x' }
|
||||
mode={ DocumentInfoLineWithTimeMode.CREATED }
|
||||
time={ DateTime.local()
|
||||
.minus({ days: 11 }) }
|
||||
userName={ 'Tilman' }
|
||||
profileImageSrc={ '/img/avatar.png' }/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<DocumentInfoTimeLine
|
||||
size={ '2x' }
|
||||
mode={ DocumentInfoLineWithTimeMode.EDITED }
|
||||
time={ DateTime.local()
|
||||
.minus({ minutes: 3 }) }
|
||||
userName={ 'Philip' }
|
||||
profileImageSrc={ '/img/avatar.png' }/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<DocumentInfoLine icon={ 'users' } size={ '2x' }>
|
||||
<Trans i18nKey='editor.modal.documentInfo.usersContributed'>
|
||||
<UnitalicBoldText text={ '42' }/>
|
||||
</Trans>
|
||||
</DocumentInfoLine>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<DocumentInfoLine icon={ 'history' } size={ '2x' }>
|
||||
<Trans i18nKey='editor.modal.documentInfo.revisions'>
|
||||
<UnitalicBoldText text={ '192' }/>
|
||||
</Trans>
|
||||
</DocumentInfoLine>
|
||||
</ListGroup.Item>
|
||||
</ListGroup>
|
||||
</Modal.Body>
|
||||
</CommonModal>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -32,10 +32,11 @@ export const DocumentInfoTimeLine: React.FC<DocumentInfoLineWithTimeProps> = ({
|
|||
const icon: IconName = mode === DocumentInfoLineWithTimeMode.CREATED ? 'plus' : 'pencil'
|
||||
|
||||
return (
|
||||
<DocumentInfoLine icon={icon} size={size}>
|
||||
<Trans i18nKey={i18nKey} >
|
||||
<UserAvatar photo={profileImageSrc} additionalClasses={'font-style-normal bold font-weight-bold'} name={userName} size={size ? 'lg' : undefined}/>
|
||||
<TimeFromNow time={time}/>
|
||||
<DocumentInfoLine icon={ icon } size={ size }>
|
||||
<Trans i18nKey={ i18nKey }>
|
||||
<UserAvatar photo={ profileImageSrc } additionalClasses={ 'font-style-normal bold font-weight-bold' }
|
||||
name={ userName } size={ size ? 'lg' : undefined }/>
|
||||
<TimeFromNow time={ time }/>
|
||||
</Trans>
|
||||
</DocumentInfoLine>
|
||||
)
|
||||
|
|
|
@ -14,6 +14,7 @@ export interface TimeFromNowProps {
|
|||
|
||||
export const TimeFromNow: React.FC<TimeFromNowProps> = ({ time }) => {
|
||||
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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
import React from 'react'
|
||||
|
||||
export interface UnitalicBoldTextProps {
|
||||
text: string ;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export const UnitalicBoldText: React.FC<UnitalicBoldTextProps> = ({ text }) => {
|
||||
return <b className={'font-style-normal mr-1'}>{text}</b>
|
||||
return <b className={ 'font-style-normal mr-1' }>{ text }</b>
|
||||
}
|
||||
|
|
|
@ -25,35 +25,35 @@ export const PermissionGroupEntry: React.FC<PermissionGroupEntryProps> = ({ titl
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<li className={'list-group-item d-flex flex-row justify-content-between align-items-center'}>
|
||||
<Trans i18nKey={title}/>
|
||||
<li className={ 'list-group-item d-flex flex-row justify-content-between align-items-center' }>
|
||||
<Trans i18nKey={ title }/>
|
||||
<ToggleButtonGroup
|
||||
type='radio'
|
||||
name='edit-mode'
|
||||
value={editMode}
|
||||
onChange={onChangeEditMode}
|
||||
value={ editMode }
|
||||
onChange={ onChangeEditMode }
|
||||
>
|
||||
<ToggleButton
|
||||
title={ t('editor.modal.permissions.denyGroup', { name: t(title) })}
|
||||
variant={'light'}
|
||||
className={'text-secondary'}
|
||||
value={GroupMode.NONE}
|
||||
title={ t('editor.modal.permissions.denyGroup', { name: t(title) }) }
|
||||
variant={ 'light' }
|
||||
className={ 'text-secondary' }
|
||||
value={ GroupMode.NONE }
|
||||
>
|
||||
<ForkAwesomeIcon icon='ban'/>
|
||||
</ToggleButton>
|
||||
<ToggleButton
|
||||
title={ t('editor.modal.permissions.viewOnlyGroup', { name: t(title) })}
|
||||
variant={'light'}
|
||||
className={'text-secondary'}
|
||||
value={GroupMode.VIEW}
|
||||
title={ t('editor.modal.permissions.viewOnlyGroup', { name: t(title) }) }
|
||||
variant={ 'light' }
|
||||
className={ 'text-secondary' }
|
||||
value={ GroupMode.VIEW }
|
||||
>
|
||||
<ForkAwesomeIcon icon='eye'/>
|
||||
</ToggleButton>
|
||||
<ToggleButton
|
||||
title={t('editor.modal.permissions.editGroup', { name: t(title) })}
|
||||
variant={'light'}
|
||||
className={'text-secondary'}
|
||||
value={GroupMode.EDIT}
|
||||
title={ t('editor.modal.permissions.editGroup', { name: t(title) }) }
|
||||
variant={ 'light' }
|
||||
className={ 'text-secondary' }
|
||||
value={ GroupMode.EDIT }
|
||||
>
|
||||
<ForkAwesomeIcon icon='pencil'/>
|
||||
</ToggleButton>
|
||||
|
|
|
@ -37,64 +37,64 @@ export const PermissionList: React.FC<PermissionListProps> = ({ list, identifier
|
|||
}
|
||||
|
||||
return (
|
||||
<ul className={'list-group'}>
|
||||
{list.map(entry => (
|
||||
<li key={entry.id} className={'list-group-item d-flex flex-row justify-content-between align-items-center'}>
|
||||
{identifier(entry)}
|
||||
<ul className={ 'list-group' }>
|
||||
{ list.map(entry => (
|
||||
<li key={ entry.id } className={ 'list-group-item d-flex flex-row justify-content-between align-items-center' }>
|
||||
{ identifier(entry) }
|
||||
<div>
|
||||
<Button
|
||||
variant='light'
|
||||
className={'text-danger mr-2'}
|
||||
title={t(removeI18nKey, { name: entry.name })}
|
||||
onClick={() => removeEntry(entry.id)}
|
||||
className={ 'text-danger mr-2' }
|
||||
title={ t(removeI18nKey, { name: entry.name }) }
|
||||
onClick={ () => removeEntry(entry.id) }
|
||||
>
|
||||
<ForkAwesomeIcon icon={'times'}/>
|
||||
<ForkAwesomeIcon icon={ 'times' }/>
|
||||
</Button>
|
||||
<ToggleButtonGroup
|
||||
type='radio'
|
||||
name='edit-mode'
|
||||
value={entry.canEdit ? EditMode.EDIT : EditMode.VIEW}
|
||||
onChange={(value: EditMode) => changeEditMode(entry.id, value === EditMode.EDIT)}
|
||||
value={ entry.canEdit ? EditMode.EDIT : EditMode.VIEW }
|
||||
onChange={ (value: EditMode) => changeEditMode(entry.id, value === EditMode.EDIT) }
|
||||
>
|
||||
<ToggleButton
|
||||
title={ t(viewI18nKey, { name: entry.name })}
|
||||
variant={'light'}
|
||||
className={'text-secondary'}
|
||||
value={EditMode.VIEW}
|
||||
title={ t(viewI18nKey, { name: entry.name }) }
|
||||
variant={ 'light' }
|
||||
className={ 'text-secondary' }
|
||||
value={ EditMode.VIEW }
|
||||
>
|
||||
<ForkAwesomeIcon icon='eye'/>
|
||||
</ToggleButton>
|
||||
<ToggleButton
|
||||
title={t(editI18nKey, { name: entry.name })}
|
||||
variant={'light'}
|
||||
className={'text-secondary'}
|
||||
value={EditMode.EDIT}
|
||||
title={ t(editI18nKey, { name: entry.name }) }
|
||||
variant={ 'light' }
|
||||
className={ 'text-secondary' }
|
||||
value={ EditMode.EDIT }
|
||||
>
|
||||
<ForkAwesomeIcon icon='pencil'/>
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
<li className={'list-group-item'}>
|
||||
<form onSubmit={event => {
|
||||
)) }
|
||||
<li className={ 'list-group-item' }>
|
||||
<form onSubmit={ event => {
|
||||
event.preventDefault()
|
||||
addEntry()
|
||||
}}>
|
||||
<InputGroup className={'mr-1 mb-1'}>
|
||||
} }>
|
||||
<InputGroup className={ 'mr-1 mb-1' }>
|
||||
<FormControl
|
||||
value={newEntry}
|
||||
placeholder={t(addI18nKey)}
|
||||
aria-label={t(addI18nKey)}
|
||||
onChange={event => setNewEntry(event.currentTarget.value)}
|
||||
value={ newEntry }
|
||||
placeholder={ t(addI18nKey) }
|
||||
aria-label={ t(addI18nKey) }
|
||||
onChange={ event => setNewEntry(event.currentTarget.value) }
|
||||
/>
|
||||
<Button
|
||||
variant='light'
|
||||
className={'text-secondary ml-2'}
|
||||
title={t(addI18nKey)}
|
||||
onClick={addEntry}
|
||||
className={ 'text-secondary ml-2' }
|
||||
title={ t(addI18nKey) }
|
||||
onClick={ addEntry }
|
||||
>
|
||||
<ForkAwesomeIcon icon={'plus'}/>
|
||||
<ForkAwesomeIcon icon={ 'plus' }/>
|
||||
</Button>
|
||||
</InputGroup>
|
||||
</form>
|
||||
|
|
|
@ -69,22 +69,26 @@ export const PermissionModal: React.FC<PermissionsModalProps> = ({ show, onHide
|
|||
|
||||
useEffect(() => {
|
||||
// set owner
|
||||
getUserById(permissionsApiResponse.owner).then(response => {
|
||||
setOwner({
|
||||
name: response.name,
|
||||
photo: response.photo
|
||||
getUserById(permissionsApiResponse.owner)
|
||||
.then(response => {
|
||||
setOwner({
|
||||
name: response.name,
|
||||
photo: response.photo
|
||||
})
|
||||
})
|
||||
}).catch(() => setError(true))
|
||||
.catch(() => setError(true))
|
||||
// set user List
|
||||
permissionsApiResponse.sharedTo.forEach(shareUser => {
|
||||
getUserById(shareUser.username).then(response => {
|
||||
setUserList(list => list.concat([{
|
||||
id: response.id,
|
||||
name: response.name,
|
||||
photo: response.photo,
|
||||
canEdit: shareUser.canEdit
|
||||
}]))
|
||||
}).catch(() => setError(true))
|
||||
getUserById(shareUser.username)
|
||||
.then(response => {
|
||||
setUserList(list => list.concat([{
|
||||
id: response.id,
|
||||
name: response.name,
|
||||
photo: response.photo,
|
||||
canEdit: shareUser.canEdit
|
||||
}]))
|
||||
})
|
||||
.catch(() => setError(true))
|
||||
})
|
||||
// set group List
|
||||
permissionsApiResponse.sharedToGroup.forEach(sharedGroup => {
|
||||
|
@ -122,45 +126,45 @@ export const PermissionModal: React.FC<PermissionsModalProps> = ({ show, onHide
|
|||
|
||||
return (
|
||||
<CommonModal
|
||||
show={show}
|
||||
onHide={onHide}
|
||||
closeButton={true}
|
||||
titleI18nKey={'editor.modal.permissions.title'}>
|
||||
show={ show }
|
||||
onHide={ onHide }
|
||||
closeButton={ true }
|
||||
titleI18nKey={ 'editor.modal.permissions.title' }>
|
||||
<Modal.Body>
|
||||
<h5 className={'mb-3'}><Trans i18nKey={'editor.modal.permissions.owner'}/></h5>
|
||||
<ShowIf condition={error}>
|
||||
<h5 className={ 'mb-3' }><Trans i18nKey={ 'editor.modal.permissions.owner' }/></h5>
|
||||
<ShowIf condition={ error }>
|
||||
<Alert variant='danger'>
|
||||
<Trans i18nKey='editor.modal.permissions.error'/>
|
||||
</Alert>
|
||||
</ShowIf>
|
||||
<ul className={'list-group'}>
|
||||
<li className={'list-group-item d-flex flex-row align-items-center'}>
|
||||
<UserAvatar name={owner?.name ?? ''} photo={owner?.photo ?? ''}/>
|
||||
<ul className={ 'list-group' }>
|
||||
<li className={ 'list-group-item d-flex flex-row align-items-center' }>
|
||||
<UserAvatar name={ owner?.name ?? '' } photo={ owner?.photo ?? '' }/>
|
||||
</li>
|
||||
</ul>
|
||||
<h5 className={'my-3'}><Trans i18nKey={'editor.modal.permissions.sharedWithUsers'}/></h5>
|
||||
<h5 className={ 'my-3' }><Trans i18nKey={ 'editor.modal.permissions.sharedWithUsers' }/></h5>
|
||||
<PermissionList
|
||||
list={userList}
|
||||
identifier={entry => (<UserAvatar name={entry.name} photo={entry.photo}/>)}
|
||||
changeEditMode={changeUserMode}
|
||||
removeEntry={removeUser}
|
||||
createEntry={addUser}
|
||||
editI18nKey={'editor.modal.permissions.editUser'}
|
||||
viewI18nKey={'editor.modal.permissions.viewOnlyUser'}
|
||||
removeI18nKey={'editor.modal.permissions.removeUser'}
|
||||
addI18nKey={'editor.modal.permissions.addUser'}
|
||||
list={ userList }
|
||||
identifier={ entry => (<UserAvatar name={ entry.name } photo={ entry.photo }/>) }
|
||||
changeEditMode={ changeUserMode }
|
||||
removeEntry={ removeUser }
|
||||
createEntry={ addUser }
|
||||
editI18nKey={ 'editor.modal.permissions.editUser' }
|
||||
viewI18nKey={ 'editor.modal.permissions.viewOnlyUser' }
|
||||
removeI18nKey={ 'editor.modal.permissions.removeUser' }
|
||||
addI18nKey={ 'editor.modal.permissions.addUser' }
|
||||
/>
|
||||
<h5 className={'my-3'}><Trans i18nKey={'editor.modal.permissions.sharedWithGroups'}/></h5>
|
||||
<ul className={'list-group'}>
|
||||
<h5 className={ 'my-3' }><Trans i18nKey={ 'editor.modal.permissions.sharedWithGroups' }/></h5>
|
||||
<ul className={ 'list-group' }>
|
||||
<PermissionGroupEntry
|
||||
title={'editor.modal.permissions.allUser'}
|
||||
editMode={allUserPermissions}
|
||||
onChangeEditMode={setAllUserPermissions}
|
||||
title={ 'editor.modal.permissions.allUser' }
|
||||
editMode={ allUserPermissions }
|
||||
onChangeEditMode={ setAllUserPermissions }
|
||||
/>
|
||||
<PermissionGroupEntry
|
||||
title={'editor.modal.permissions.allLoggedInUser'}
|
||||
editMode={allLoggedInUserPermissions}
|
||||
onChangeEditMode={setAllLoggedInUserPermissions}
|
||||
title={ 'editor.modal.permissions.allLoggedInUser' }
|
||||
editMode={ allLoggedInUserPermissions }
|
||||
onChangeEditMode={ setAllLoggedInUserPermissions }
|
||||
/>
|
||||
</ul>
|
||||
</Modal.Body>
|
||||
|
|
|
@ -23,26 +23,29 @@ export interface RevisionModalListEntryProps {
|
|||
export const RevisionModalListEntry: React.FC<RevisionModalListEntryProps> = ({ active, onClick, revision, revisionAuthorListMap }) => (
|
||||
<ListGroup.Item
|
||||
as='li'
|
||||
active={active}
|
||||
onClick={onClick}
|
||||
active={ active }
|
||||
onClick={ onClick }
|
||||
className='user-select-none revision-item d-flex flex-column'
|
||||
>
|
||||
<span>
|
||||
<ForkAwesomeIcon icon={'clock-o'} className='mx-2'/>
|
||||
{DateTime.fromMillis(revision.timestamp * 1000).toFormat('DDDD T')}
|
||||
<ForkAwesomeIcon icon={ 'clock-o' } className='mx-2'/>
|
||||
{ DateTime.fromMillis(revision.timestamp * 1000)
|
||||
.toFormat('DDDD T') }
|
||||
</span>
|
||||
<span>
|
||||
<ForkAwesomeIcon icon={'file-text-o'} className='mx-2'/>
|
||||
<Trans i18nKey={'editor.modal.revision.length'}/>: {revision.length}
|
||||
<ForkAwesomeIcon icon={ 'file-text-o' } className='mx-2'/>
|
||||
<Trans i18nKey={ 'editor.modal.revision.length' }/>: { revision.length }
|
||||
</span>
|
||||
<span className={'d-flex flex-row my-1 align-items-center'}>
|
||||
<ForkAwesomeIcon icon={'user-o'} className={'mx-2'}/>
|
||||
<span className={ 'd-flex flex-row my-1 align-items-center' }>
|
||||
<ForkAwesomeIcon icon={ 'user-o' } className={ 'mx-2' }/>
|
||||
{
|
||||
revisionAuthorListMap.get(revision.timestamp)?.map((user, index) => {
|
||||
return (
|
||||
<UserAvatar name={user.name} photo={user.photo} showName={false} additionalClasses={'mx-1'} key={index}/>
|
||||
)
|
||||
})
|
||||
revisionAuthorListMap.get(revision.timestamp)
|
||||
?.map((user, index) => {
|
||||
return (
|
||||
<UserAvatar name={ user.name } photo={ user.photo } showName={ false }
|
||||
additionalClasses={ 'mx-1' } key={ index }/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</span>
|
||||
</ListGroup.Item>
|
||||
|
|
|
@ -36,61 +36,66 @@ export const RevisionModal: React.FC<PermissionsModalProps> = ({ show, onHide })
|
|||
const { id } = useParams<{ id: string }>()
|
||||
|
||||
useEffect(() => {
|
||||
getAllRevisions(id).then(fetchedRevisions => {
|
||||
fetchedRevisions.forEach(revision => {
|
||||
const authorData = getUserDataForRevision(revision.authors)
|
||||
revisionAuthorListMap.current.set(revision.timestamp, authorData)
|
||||
getAllRevisions(id)
|
||||
.then(fetchedRevisions => {
|
||||
fetchedRevisions.forEach(revision => {
|
||||
const authorData = getUserDataForRevision(revision.authors)
|
||||
revisionAuthorListMap.current.set(revision.timestamp, authorData)
|
||||
})
|
||||
setRevisions(fetchedRevisions)
|
||||
if (fetchedRevisions.length >= 1) {
|
||||
setSelectedRevisionTimestamp(fetchedRevisions[0].timestamp)
|
||||
}
|
||||
})
|
||||
setRevisions(fetchedRevisions)
|
||||
if (fetchedRevisions.length >= 1) {
|
||||
setSelectedRevisionTimestamp(fetchedRevisions[0].timestamp)
|
||||
}
|
||||
}).catch(() => setError(true))
|
||||
.catch(() => setError(true))
|
||||
}, [setRevisions, setError, id])
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedRevisionTimestamp === null) {
|
||||
return
|
||||
}
|
||||
getRevision(id, selectedRevisionTimestamp).then(fetchedRevision => {
|
||||
setSelectedRevision(fetchedRevision)
|
||||
}).catch(() => setError(true))
|
||||
getRevision(id, selectedRevisionTimestamp)
|
||||
.then(fetchedRevision => {
|
||||
setSelectedRevision(fetchedRevision)
|
||||
})
|
||||
.catch(() => setError(true))
|
||||
}, [selectedRevisionTimestamp, id])
|
||||
|
||||
const markdownContent = useNoteMarkdownContent()
|
||||
|
||||
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>
|
||||
<Row>
|
||||
<Col lg={4} className={'scroll-col'}>
|
||||
<Col lg={ 4 } className={ 'scroll-col' }>
|
||||
<ListGroup as='ul'>
|
||||
{
|
||||
revisions.map((revision, revisionIndex) => (
|
||||
<RevisionModalListEntry
|
||||
key={revisionIndex}
|
||||
active={selectedRevisionTimestamp === revision.timestamp}
|
||||
revision={revision}
|
||||
revisionAuthorListMap={revisionAuthorListMap.current}
|
||||
onClick={() => setSelectedRevisionTimestamp(revision.timestamp)}
|
||||
key={ revisionIndex }
|
||||
active={ selectedRevisionTimestamp === revision.timestamp }
|
||||
revision={ revision }
|
||||
revisionAuthorListMap={ revisionAuthorListMap.current }
|
||||
onClick={ () => setSelectedRevisionTimestamp(revision.timestamp) }
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ListGroup>
|
||||
</Col>
|
||||
<Col lg={8} className={'scroll-col'}>
|
||||
<ShowIf condition={error}>
|
||||
<Col lg={ 8 } className={ 'scroll-col' }>
|
||||
<ShowIf condition={ error }>
|
||||
<Alert variant='danger'>
|
||||
<Trans i18nKey='editor.modal.revision.error'/>
|
||||
</Alert>
|
||||
</ShowIf>
|
||||
<ShowIf condition={!error && !!selectedRevision}>
|
||||
<ShowIf condition={ !error && !!selectedRevision }>
|
||||
<ReactDiffViewer
|
||||
oldValue={selectedRevision?.content}
|
||||
newValue={markdownContent}
|
||||
splitView={false}
|
||||
compareMethod={DiffMethod.WORDS}
|
||||
useDarkTheme={darkModeEnabled}
|
||||
oldValue={ selectedRevision?.content }
|
||||
newValue={ markdownContent }
|
||||
splitView={ false }
|
||||
compareMethod={ DiffMethod.WORDS }
|
||||
useDarkTheme={ darkModeEnabled }
|
||||
/>
|
||||
</ShowIf>
|
||||
</Col>
|
||||
|
@ -99,20 +104,20 @@ export const RevisionModal: React.FC<PermissionsModalProps> = ({ show, onHide })
|
|||
<Modal.Footer>
|
||||
<Button
|
||||
variant='secondary'
|
||||
onClick={onHide}>
|
||||
<Trans i18nKey={'common.close'}/>
|
||||
onClick={ onHide }>
|
||||
<Trans i18nKey={ 'common.close' }/>
|
||||
</Button>
|
||||
<Button
|
||||
variant='danger'
|
||||
disabled={!selectedRevisionTimestamp}
|
||||
onClick={() => window.alert('Not yet implemented. Requires websocket.')}>
|
||||
<Trans i18nKey={'editor.modal.revision.revertButton'}/>
|
||||
disabled={ !selectedRevisionTimestamp }
|
||||
onClick={ () => window.alert('Not yet implemented. Requires websocket.') }>
|
||||
<Trans i18nKey={ 'editor.modal.revision.revertButton' }/>
|
||||
</Button>
|
||||
<Button
|
||||
variant='primary'
|
||||
disabled={!selectedRevisionTimestamp}
|
||||
onClick={() => downloadRevision(id, selectedRevision)}>
|
||||
<Trans i18nKey={'editor.modal.revision.download'}/>
|
||||
disabled={ !selectedRevisionTimestamp }
|
||||
onClick={ () => downloadRevision(id, selectedRevision) }>
|
||||
<Trans i18nKey={ 'editor.modal.revision.download' }/>
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</CommonModal>
|
||||
|
|
|
@ -13,7 +13,7 @@ export const downloadRevision = (noteId: string, revision: Revision | null): voi
|
|||
if (!revision) {
|
||||
return
|
||||
}
|
||||
download(revision.content, `${noteId}-${revision.timestamp}.md`, 'text/markdown')
|
||||
download(revision.content, `${ noteId }-${ revision.timestamp }.md`, 'text/markdown')
|
||||
}
|
||||
|
||||
export const getUserDataForRevision = (authors: string[]): UserResponse[] => {
|
||||
|
|
|
@ -31,21 +31,23 @@ export const ShareModal: React.FC<ShareModalProps> = ({ show, onHide }) => {
|
|||
|
||||
return (
|
||||
<CommonModal
|
||||
show={show}
|
||||
onHide={onHide}
|
||||
closeButton={true}
|
||||
titleI18nKey={'editor.modal.shareLink.title'}>
|
||||
show={ show }
|
||||
onHide={ onHide }
|
||||
closeButton={ true }
|
||||
titleI18nKey={ 'editor.modal.shareLink.title' }>
|
||||
<Modal.Body>
|
||||
<Trans i18nKey={'editor.modal.shareLink.editorDescription'}/>
|
||||
<CopyableField content={`${baseUrl}/n/${id}?${editorMode}`} nativeShareButton={true}
|
||||
url={`${baseUrl}/n/${id}?${editorMode}`}/>
|
||||
<ShowIf condition={noteFrontmatter.type === 'slide'}>
|
||||
<Trans i18nKey={'editor.modal.shareLink.slidesDescription'}/>
|
||||
<CopyableField content={`${baseUrl}/p/${id}`} nativeShareButton={true} url={`${baseUrl}/p/${id}`}/>
|
||||
<Trans i18nKey={ 'editor.modal.shareLink.editorDescription' }/>
|
||||
<CopyableField content={ `${ baseUrl }/n/${ id }?${ editorMode }` } nativeShareButton={ true }
|
||||
url={ `${ baseUrl }/n/${ id }?${ editorMode }` }/>
|
||||
<ShowIf condition={ noteFrontmatter.type === 'slide' }>
|
||||
<Trans i18nKey={ 'editor.modal.shareLink.slidesDescription' }/>
|
||||
<CopyableField content={ `${ baseUrl }/p/${ id }` } nativeShareButton={ true }
|
||||
url={ `${ baseUrl }/p/${ id }` }/>
|
||||
</ShowIf>
|
||||
<ShowIf condition={noteFrontmatter.type === ''}>
|
||||
<Trans i18nKey={'editor.modal.shareLink.viewOnlyDescription'}/>
|
||||
<CopyableField content={`${baseUrl}/s/${id}`} nativeShareButton={true} url={`${baseUrl}/s/${id}`}/>
|
||||
<ShowIf condition={ noteFrontmatter.type === '' }>
|
||||
<Trans i18nKey={ 'editor.modal.shareLink.viewOnlyDescription' }/>
|
||||
<CopyableField content={ `${ baseUrl }/s/${ id }` } nativeShareButton={ true }
|
||||
url={ `${ baseUrl }/s/${ id }` }/>
|
||||
</ShowIf>
|
||||
</Modal.Body>
|
||||
</CommonModal>
|
||||
|
|
|
@ -8,8 +8,8 @@ import { RefObject, useCallback } from 'react'
|
|||
import { LineMarkerPosition } from '../../../markdown-renderer/types'
|
||||
|
||||
export const useAdaptedLineMarkerCallback = (documentRenderPaneRef: RefObject<HTMLDivElement> | undefined,
|
||||
rendererRef: RefObject<HTMLDivElement>,
|
||||
onLineMarkerPositionChanged: ((lineMarkerPosition: LineMarkerPosition[]) => void) | undefined): ((lineMarkerPosition: LineMarkerPosition[]) => void) => {
|
||||
rendererRef: RefObject<HTMLDivElement>,
|
||||
onLineMarkerPositionChanged: ((lineMarkerPosition: LineMarkerPosition[]) => void) | undefined): ((lineMarkerPosition: LineMarkerPosition[]) => void) => {
|
||||
return useCallback((linkMarkerPositions) => {
|
||||
if (!onLineMarkerPositionChanged || !documentRenderPaneRef || !documentRenderPaneRef.current || !rendererRef.current) {
|
||||
return
|
||||
|
|
|
@ -8,7 +8,7 @@ import { RefObject, useCallback, useRef } from 'react'
|
|||
import { IframeEditorToRendererCommunicator } from '../../../render-page/iframe-editor-to-renderer-communicator'
|
||||
|
||||
export const useOnIframeLoad = (frameReference: RefObject<HTMLIFrameElement>, iframeCommunicator: IframeEditorToRendererCommunicator,
|
||||
rendererOrigin: string, renderPageUrl: string, onNavigateAway: () => void): () => void => {
|
||||
rendererOrigin: string, renderPageUrl: string, onNavigateAway: () => void): () => void => {
|
||||
const sendToRenderPage = useRef<boolean>(true)
|
||||
|
||||
return useCallback(() => {
|
||||
|
@ -24,7 +24,7 @@ export const useOnIframeLoad = (frameReference: RefObject<HTMLIFrameElement>, if
|
|||
return
|
||||
} else {
|
||||
onNavigateAway()
|
||||
console.error("Navigated away from unknown URL")
|
||||
console.error('Navigated away from unknown URL')
|
||||
frame.src = renderPageUrl
|
||||
sendToRenderPage.current = true
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ export const ShowOnPropChangeImageLightbox: React.FC<ShowOnPropChangeImageLightb
|
|||
}, [details])
|
||||
|
||||
return (
|
||||
<ImageLightboxModal show={show} onHide={hideLightbox} src={details?.src}
|
||||
alt={details?.alt} title={details?.title}/>
|
||||
<ImageLightboxModal show={ show } onHide={ hideLightbox } src={ details?.src }
|
||||
alt={ details?.alt } title={ details?.title }/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,13 +19,14 @@ export const MaxLengthWarningModal: React.FC<MaxLengthWarningModalProps> = ({ sh
|
|||
useTranslation()
|
||||
|
||||
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>
|
||||
<Trans i18nKey={'editor.error.limitReached.description'} values={{ maxLength }} />
|
||||
<strong className='mt-2 d-block'><Trans i18nKey={'editor.error.limitReached.advice'}/></strong>
|
||||
<Trans i18nKey={ 'editor.error.limitReached.description' } values={ { maxLength } }/>
|
||||
<strong className='mt-2 d-block'><Trans i18nKey={ 'editor.error.limitReached.advice' }/></strong>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button onClick={onHide}><Trans i18nKey={'common.close'}/></Button>
|
||||
<Button onClick={ onHide }><Trans i18nKey={ 'common.close' }/></Button>
|
||||
</Modal.Footer>
|
||||
</CommonModal>
|
||||
)
|
||||
|
|
|
@ -58,7 +58,8 @@ export const EditorPage: React.FC = () => {
|
|||
|
||||
useEffect(() => {
|
||||
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) {
|
||||
setEditorMode(mode)
|
||||
}
|
||||
|
@ -92,37 +93,37 @@ export const EditorPage: React.FC = () => {
|
|||
return (
|
||||
<Fragment>
|
||||
<MotdBanner/>
|
||||
<div className={'d-flex flex-column vh-100'}>
|
||||
<AppBar mode={AppBarMode.EDITOR}/>
|
||||
<div className={ 'd-flex flex-column vh-100' }>
|
||||
<AppBar mode={ AppBarMode.EDITOR }/>
|
||||
|
||||
<div className={'container'}>
|
||||
<ErrorWhileLoadingNoteAlert show={error}/>
|
||||
<LoadingNoteAlert show={loading}/>
|
||||
<div className={ 'container' }>
|
||||
<ErrorWhileLoadingNoteAlert show={ error }/>
|
||||
<LoadingNoteAlert show={ loading }/>
|
||||
</div>
|
||||
<ShowIf condition={!error && !loading}>
|
||||
<div className={"flex-fill d-flex h-100 w-100 overflow-hidden flex-row"}>
|
||||
<ShowIf condition={ !error && !loading }>
|
||||
<div className={ 'flex-fill d-flex h-100 w-100 overflow-hidden flex-row' }>
|
||||
<Splitter
|
||||
showLeft={editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH}
|
||||
showLeft={ editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH }
|
||||
left={
|
||||
<EditorPane
|
||||
onContentChange={setNoteMarkdownContent}
|
||||
content={markdownContent}
|
||||
scrollState={scrollState.editorScrollState}
|
||||
onScroll={onEditorScroll}
|
||||
onMakeScrollSource={setEditorToScrollSource}/>
|
||||
onContentChange={ setNoteMarkdownContent }
|
||||
content={ markdownContent }
|
||||
scrollState={ scrollState.editorScrollState }
|
||||
onScroll={ onEditorScroll }
|
||||
onMakeScrollSource={ setEditorToScrollSource }/>
|
||||
}
|
||||
showRight={editorMode === EditorMode.PREVIEW || editorMode === EditorMode.BOTH}
|
||||
showRight={ editorMode === EditorMode.PREVIEW || editorMode === EditorMode.BOTH }
|
||||
right={
|
||||
<RenderIframe
|
||||
markdownContent={markdownContent}
|
||||
onMakeScrollSource={setRendererToScrollSource}
|
||||
onFirstHeadingChange={updateNoteTitleByFirstHeading}
|
||||
onTaskCheckedChange={SetCheckboxInMarkdownContent}
|
||||
onFrontmatterChange={setNoteFrontmatter}
|
||||
onScroll={onMarkdownRendererScroll}
|
||||
scrollState={scrollState.rendererScrollState}/>
|
||||
markdownContent={ markdownContent }
|
||||
onMakeScrollSource={ setRendererToScrollSource }
|
||||
onFirstHeadingChange={ updateNoteTitleByFirstHeading }
|
||||
onTaskCheckedChange={ SetCheckboxInMarkdownContent }
|
||||
onFrontmatterChange={ setNoteFrontmatter }
|
||||
onScroll={ onMarkdownRendererScroll }
|
||||
scrollState={ scrollState.rendererScrollState }/>
|
||||
}
|
||||
containerClassName={'overflow-hidden'}/>
|
||||
containerClassName={ 'overflow-hidden' }/>
|
||||
<Sidebar/>
|
||||
</div>
|
||||
</ShowIf>
|
||||
|
|
|
@ -10,7 +10,7 @@ import { findWordAtCursor, Hinter, search } from './index'
|
|||
const wordRegExp = /^```((\w|-|_|\+)*)$/
|
||||
let allSupportedLanguages: string[] = []
|
||||
|
||||
const codeBlockHint = (editor: Editor): Promise< Hints| null > => {
|
||||
const codeBlockHint = (editor: Editor): Promise<Hints | null> => {
|
||||
return import(/* webpackChunkName: "highlight.js" */ '../../../common/hljs/hljs').then((hljs) =>
|
||||
new Promise((resolve) => {
|
||||
const searchTerm = findWordAtCursor(editor)
|
||||
|
@ -21,7 +21,8 @@ const codeBlockHint = (editor: Editor): Promise< Hints| null > => {
|
|||
}
|
||||
const term = searchResult[1]
|
||||
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 cursor = editor.getCursor()
|
||||
|
|
|
@ -9,7 +9,7 @@ import { findWordAtCursor, Hinter } from './index'
|
|||
|
||||
const wordRegExp = /^(<d(?:e|et|eta|etai|etail|etails)?)$/
|
||||
|
||||
const collapsableBlockHint = (editor: Editor): Promise< Hints| null > => {
|
||||
const collapsableBlockHint = (editor: Editor): Promise<Hints | null> => {
|
||||
return new Promise((resolve) => {
|
||||
const searchTerm = findWordAtCursor(editor)
|
||||
const searchResult = wordRegExp.exec(searchTerm.text)
|
||||
|
|
|
@ -16,7 +16,8 @@ const spoilerSuggestion: Hint = {
|
|||
const suggestions = validAlertLevels.map((suggestion: string): Hint => ({
|
||||
text: ':::' + suggestion + '\n\n::: \n',
|
||||
displayText: suggestion
|
||||
})).concat(spoilerSuggestion)
|
||||
}))
|
||||
.concat(spoilerSuggestion)
|
||||
|
||||
const containerHint = (editor: Editor): Promise<Hints | null> => {
|
||||
return new Promise((resolve) => {
|
||||
|
|
|
@ -31,7 +31,7 @@ const findEmojiInDatabase = async (emojiIndex: Database, term: string): Promise<
|
|||
}
|
||||
}
|
||||
|
||||
const convertEmojiEventToHint = (emojiData:EmojiClickEventDetail): Hint | undefined => {
|
||||
const convertEmojiEventToHint = (emojiData: EmojiClickEventDetail): Hint | undefined => {
|
||||
const shortCode = getEmojiShortCode(emojiData)
|
||||
if (!shortCode) {
|
||||
return undefined
|
||||
|
@ -40,7 +40,7 @@ const convertEmojiEventToHint = (emojiData:EmojiClickEventDetail): Hint | undefi
|
|||
text: shortCode,
|
||||
render: (parent: HTMLLIElement) => {
|
||||
const wrapper = document.createElement('div')
|
||||
wrapper.innerHTML = `${getEmojiIcon(emojiData)} ${shortCode}`
|
||||
wrapper.innerHTML = `${ getEmojiIcon(emojiData) } ${ shortCode }`
|
||||
parent.appendChild(wrapper)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ const wordRegExp = /^(\s{0,3})(#{1,6})$/
|
|||
const allSupportedHeaders = ['# h1', '## h2', '### h3', '#### h4', '##### h5', '###### h6', '###### tags: `example`']
|
||||
const allSupportedHeadersTextToInsert = ['# ', '## ', '### ', '#### ', '##### ', '###### ', '###### tags: `example`']
|
||||
|
||||
const headerHint = (editor: Editor): Promise< Hints| null > => {
|
||||
const headerHint = (editor: Editor): Promise<Hints | null> => {
|
||||
return new Promise((resolve) => {
|
||||
const searchTerm = findWordAtCursor(editor)
|
||||
const searchResult = wordRegExp.exec(searchTerm.text)
|
||||
|
|
|
@ -14,7 +14,7 @@ const allSupportedImages = [
|
|||
'![image alt][reference]'
|
||||
]
|
||||
|
||||
const imageHint = (editor: Editor): Promise< Hints| null > => {
|
||||
const imageHint = (editor: Editor): Promise<Hints | null> => {
|
||||
return new Promise((resolve) => {
|
||||
const searchTerm = findWordAtCursor(editor)
|
||||
const searchResult = wordRegExp.exec(searchTerm.text)
|
||||
|
|