diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/markdown')
6 files changed, 88 insertions, 31 deletions
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue index 6df0119c3db..a48c279d0e3 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/field.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue @@ -1,14 +1,15 @@ <script> +/* eslint-disable vue/no-v-html */ import $ from 'jquery'; import '~/behaviors/markdown/render_gfm'; import { unescape } from 'lodash'; +import { GlIcon } from '@gitlab/ui'; import { __, sprintf } from '~/locale'; import { stripHtml } from '~/lib/utils/text_utility'; import { deprecatedCreateFlash as Flash } from '~/flash'; import GLForm from '~/gl_form'; import MarkdownHeader from './header.vue'; import MarkdownToolbar from './toolbar.vue'; -import Icon from '../icon.vue'; import GlMentions from '~/vue_shared/components/gl_mentions.vue'; import Suggestions from '~/vue_shared/components/markdown/suggestions.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; @@ -19,7 +20,7 @@ export default { GlMentions, MarkdownHeader, MarkdownToolbar, - Icon, + GlIcon, Suggestions, }, mixins: [glFeatureFlagsMixin()], @@ -168,11 +169,12 @@ export default { emojis: this.enableAutocomplete, members: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete, issues: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete, - mergeRequests: this.enableAutocomplete, + mergeRequests: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete, epics: this.enableAutocomplete, milestones: this.enableAutocomplete, labels: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete, snippets: this.enableAutocomplete, + vulnerabilities: this.enableAutocomplete, }); }, beforeDestroy() { @@ -254,7 +256,7 @@ export default { href="#" :aria-label="__('Leave zen mode')" > - <icon :size="16" name="screen-normal" /> + <gl-icon :size="16" name="minimize" /> </a> <markdown-toolbar :markdown-docs-path="markdownDocsPath" diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue index 7e6edcfbd25..d0a0560846a 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/header.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue @@ -1,15 +1,15 @@ <script> import $ from 'jquery'; -import { GlPopover, GlButton, GlTooltipDirective } from '@gitlab/ui'; +import { GlPopover, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui'; +import { s__ } from '~/locale'; import { getSelectedFragment } from '~/lib/utils/common_utils'; import { CopyAsGFM } from '../../../behaviors/markdown/copy_as_gfm'; import ToolbarButton from './toolbar_button.vue'; -import Icon from '../icon.vue'; export default { components: { ToolbarButton, - Icon, + GlIcon, GlPopover, GlButton, }, @@ -55,6 +55,15 @@ export default { mdSuggestion() { return ['```suggestion:-0+0', `{text}`, '```'].join('\n'); }, + isMac() { + // Accessing properties using ?. to allow tests to use + // this component without setting up window.gl.client. + // In production, window.gl.client should always be present. + return Boolean(window.gl?.client?.isMac); + }, + modifierKey() { + return this.isMac ? '⌘' : s__('KeyboardKey|Ctrl+'); + }, }, mounted() { $(document).on('markdown-preview:show.vue', this.previewMarkdownTab); @@ -129,8 +138,22 @@ export default { </li> <li :class="{ active: !previewMarkdown }" class="md-header-toolbar"> <div class="d-inline-block"> - <toolbar-button tag="**" :button-title="__('Add bold text')" icon="bold" /> - <toolbar-button tag="*" :button-title="__('Add italic text')" icon="italic" /> + <toolbar-button + tag="**" + :button-title=" + sprintf(s__('MarkdownEditor|Add bold text (%{modifierKey}B)'), { modifierKey }) + " + shortcuts="mod+b" + icon="bold" + /> + <toolbar-button + tag="_" + :button-title=" + sprintf(s__('MarkdownEditor|Add italic text (%{modifierKey}I)'), { modifierKey }) + " + shortcuts="mod+i" + icon="italic" + /> <toolbar-button :prepend="true" :tag="tag" @@ -181,7 +204,10 @@ export default { <toolbar-button tag="[{text}](url)" tag-select="url" - :button-title="__('Add a link')" + :button-title=" + sprintf(s__('MarkdownEditor|Add a link (%{modifierKey}K)'), { modifierKey }) + " + shortcuts="mod+k" icon="link" /> </div> @@ -221,7 +247,7 @@ export default { :title="__('Go full screen')" type="button" > - <icon name="screen-full" /> + <gl-icon name="maximize" /> </button> </div> </li> diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue index 4de80e9b4c2..1fc54d2f52e 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue @@ -1,11 +1,10 @@ <script> -import { GlDeprecatedButton, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui'; -import Icon from '~/vue_shared/components/icon.vue'; +import { GlButton, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui'; import { __ } from '~/locale'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; export default { - components: { Icon, GlDeprecatedButton, GlLoadingIcon }, + components: { GlIcon, GlButton, GlLoadingIcon }, directives: { 'gl-tooltip': GlTooltipDirective }, mixins: [glFeatureFlagsMixin()], props: { @@ -97,7 +96,7 @@ export default { <div class="qa-suggestion-diff-header js-suggestion-diff-header font-weight-bold"> {{ __('Suggested change') }} <a v-if="helpPagePath" :href="helpPagePath" :aria-label="__('Help')" class="js-help-btn"> - <icon name="question-o" css-classes="link-highlight" /> + <gl-icon name="question-o" css-classes="link-highlight" /> </a> </div> <div v-if="isApplied" class="badge badge-success">{{ __('Applied') }}</div> @@ -106,14 +105,14 @@ export default { <span>{{ applyingSuggestionsMessage }}</span> </div> <div v-else-if="canApply && canBeBatched && isBatched" class="d-flex align-items-center"> - <gl-deprecated-button + <gl-button class="btn-inverted js-remove-from-batch-btn btn-grouped" :disabled="isApplying" @click="removeSuggestionFromBatch" > {{ __('Remove from batch') }} - </gl-deprecated-button> - <gl-deprecated-button + </gl-button> + <gl-button v-gl-tooltip.viewport="__('This also resolves all related threads')" class="btn-inverted js-apply-batch-btn btn-grouped" :disabled="isApplying" @@ -124,26 +123,26 @@ export default { <span class="badge badge-pill badge-pill-success"> {{ batchSuggestionsCount }} </span> - </gl-deprecated-button> + </gl-button> </div> <div v-else class="d-flex align-items-center"> - <gl-deprecated-button + <gl-button v-if="canBeBatched && !isDisableButton" class="btn-inverted js-add-to-batch-btn btn-grouped" :disabled="isDisableButton" @click="addSuggestionToBatch" > {{ __('Add suggestion to batch') }} - </gl-deprecated-button> + </gl-button> <span v-gl-tooltip.viewport="tooltipMessage" tabindex="0"> - <gl-deprecated-button + <gl-button class="btn-inverted js-apply-btn btn-grouped" :disabled="isDisableButton" variant="success" @click="applySuggestion" > {{ __('Apply suggestion') }} - </gl-deprecated-button> + </gl-button> </span> </div> </div> diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue index 112bd03b49b..9059f0d2a8b 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue @@ -1,4 +1,5 @@ <script> +/* eslint-disable vue/no-v-html */ export default { name: 'SuggestionDiffRow', props: { @@ -26,9 +27,14 @@ export default { <td class="diff-line-num new_line border-top-0 border-bottom-0" :class="lineType"> {{ line.new_line }} </td> - <td class="line_content" :class="[{ 'd-table-cell': displayAsCell }, lineType]"> - <span v-if="line.rich_text" v-html="line.rich_text"></span> - <span v-else-if="line.text">{{ line.text }}</span> + <td + class="line_content" + :class="[{ 'd-table-cell': displayAsCell }, lineType]" + data-testid="suggestion-diff-content" + > + <span v-if="line.rich_text" class="line" v-html="line.rich_text"></span> + <span v-else-if="line.text" class="line">{{ line.text }}</span> + <span v-else class="line"></span> </td> </tr> </template> diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue index 1216484b35f..083f581af05 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue @@ -1,10 +1,14 @@ <script> import Vue from 'vue'; +import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui'; import { __ } from '~/locale'; import SuggestionDiff from './suggestion_diff.vue'; import { deprecatedCreateFlash as Flash } from '~/flash'; export default { + directives: { + SafeHtml, + }, props: { lineType: { type: String, @@ -115,6 +119,6 @@ export default { <template> <div> <div class="flash-container js-suggestions-flash"></div> - <div v-show="isRendered" ref="container" class="md" v-html="noteHtml"></div> + <div v-show="isRendered" ref="container" v-safe-html="noteHtml" class="md"></div> </div> </template> diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue index f37dd9e171c..6c35741e7e5 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue @@ -1,10 +1,9 @@ <script> -import { GlTooltipDirective } from '@gitlab/ui'; -import Icon from '../icon.vue'; +import { GlTooltipDirective, GlIcon } from '@gitlab/ui'; export default { components: { - Icon, + GlIcon, }, directives: { GlTooltip: GlTooltipDirective, @@ -47,6 +46,26 @@ export default { required: false, default: 0, }, + + /** + * A string (or an array of strings) of + * [mousetrap](https://craig.is/killing/mice) keyboard shortcuts + * that should be attached to this button. For example: + * "command+k" + * ...or... + * ["command+k", "ctrl+k"] + */ + shortcuts: { + type: [String, Array], + required: false, + default: () => [], + }, + }, + computed: { + shortcutsString() { + const shortcutArray = Array.isArray(this.shortcuts) ? this.shortcuts : [this.shortcuts]; + return JSON.stringify(shortcutArray); + }, }, }; </script> @@ -60,6 +79,7 @@ export default { :data-md-block="tagBlock" :data-md-tag-content="tagContent" :data-md-prepend="prepend" + :data-md-shortcuts="shortcutsString" :title="buttonTitle" :aria-label="buttonTitle" type="button" @@ -67,6 +87,6 @@ export default { data-container="body" @click="() => $emit('click')" > - <icon :name="icon" /> + <gl-icon :name="icon" /> </button> </template> |