{"version":3,"sources":["webpack:///./behaviors/markdown/paste_markdown_table.js","webpack:///./dropzone_input.js","webpack:///./gl_form.js","webpack:///./lib/utils/file_upload.js","webpack:///./lib/utils/file_utility.js","webpack:///./lib/utils/vector.js","webpack:///./lib/utils/image_utils.js","webpack:///./lib/utils/text_markdown.js","webpack:///./behaviors/shortcuts/shortcuts.js"],"names":["PasteMarkdownTable","constructor","clipboardData","this","data","columnWidths","rows","tableFound","parseTable","isTable","convertToTableMarkdown","_this","calculateColumnWidths","markdownRows","map","row","column","index","formatColumn","join","splice","generateHeaderBreak","types","includes","htmlData","getData","doc","DOMParser","parseFromString","querySelectorAll","length","splitRows","trim","split","normalizeRows","columnCountsMatch","rowLengths","maxLength","Math","max","forEach","push","_this2","_column","columnIndex","maxColumnWidth","textColumnCount","htmlColumnCount","cells","Array","_this3","width","dropzoneInput","form","config","parallelUploads","_form$get$querySelect","iconPaperclip","spriteIcon","$attachingFileMessage","find","$cancelButton","$retryLink","$uploadProgress","$uploadingErrorContainer","$uploadingErrorMessage","$uploadingProgressContainer","uploadsPath","window","uploads_path","maxFileSize","gon","max_file_size","formTextarea","handlePaste","pasteText","addFileToForm","updateAttachingMessage","uploadFile","hasPlainText","wrap","$mdArea","closest","$formDropzone","parent","addClass","append","on","event","dropzone","url","dictDefaultMessage","clickable","get","querySelector","paramName","maxFilesize","uploadMultiple","headers","csrf","previewContainer","dragover","css","dragleave","removeClass","drop","focus","success","header","response","shouldPad","getQueuedFiles","getUploadingFiles","link","size","markdown","error","file","errorMessage","__","xhr","message","res","responseText","html","totaluploadprogress","totalUploadProgress","files","text","round","sending","removedfile","queuecomplete","$","remove","trigger","child","children","e","preventDefault","stopPropagation","Dropzone","forElement","removeAllFiles","dropzoneInstance","target","failedFiles","failedFile","status","ERROR","undefined","accepted","addFile","pasteEvent","originalEvent","items","converter","type","indexOf","MAX_FILE_NAME_LENGTH","filename","getFilename","truncateFilename","truncate","some","item","formattedText","textarea","caretStart","selectionStart","caretEnd","selectionEnd","textEnd","val","beforeSelection","substring","afterSelection","setSelectionRange","style","height","scrollHeight","dispatchEvent","Event","path","_escape","closeSpinner","handleAttachFile","click","formData","FormData","axios","post","then","async","md","getRetinaDimensions","$child","replace","insertToTextArea","catch","messageContainer","filesCount","filter","attachingMessage","n__","$attachFileButton","addEventListener","autoDiscover","GLForm","enableGFM","forceNew","gfmDataSources","defaultAutocompleteConfig","dataSources","gl","GfmAutoComplete","_isEmpty","Object","keys","destroy","setupForm","clearEventListeners","autoComplete","formDropzone","isNewForm","is","disableButtonIfEmptyField","setup","autosize","addEventListeners","addMarkdownListeners","show","isAutosizeable","setupAutosize","updateAutocompleteDataSources","updateDataSources","off","setHeightData","bind","destroyAutosize","setTimeout","outerHeight","removeMarkdownListeners","Boolean","buttonSelector","fileSelector","btn","document","fileInput","textContent","value","fileName","name","validateImageName","test","validateFileFromAllowList","allowList","parts","ext","readFileAsDataURL","Promise","resolve","reader","FileReader","result","once","readAsDataURL","Vector","x","y","eq","x1","y1","neq","gte","gt","lte","lt","fn","mul","scalar","div","add","sub","floor","ceil","toSize","vector","stringToUInt32","str","buffer","char","charCodeAt","pngFile","pngImage","dataUrl","atob","fileToPngImage","pixelsPerInch","physPosition","phys","getPixelsPerInch","ihdrPosition","ihdr","domElementToBlob","domElement","domToBlob","LIST_LINE_HEAD_PATTERN","HR_PATTERN","compositioningNoteText","addBlockTags","blockTag","selected","lineAfterSelection","textArea","linesFromSelection","startPos","lastIndexOf","endPos","lines","setNewSelectionRange","lineStart","firstLineChange","totalChanged","newStart","newEnd","getEditorSelectionRange","editor","start","sel","getSelection","startLineNumber","startColumn","end","endLineNumber","endColumn","insertMarkdownText","tag","cursorOffset","select","editorSelectionStart","editorSelectionEnd","lastNewLine","textToInsert","removedLastNewLine","removedFirstNewLine","currentLineEmpty","toString","selectionRange","URL","origin","selectedSplit","getValue","substr","isBeginning","startChar","lastLine","rangeWithBlockTags","Range","editorBlockTagText","lineBefore","lineBeforeSelection","blockTagText","String","replaceSelectedText","insertText","positionBetweenTags","pos","startPosition","endPosition","selectWithinSelection","moveCursor","updateText","tagContent","$textArea","selectedText","handleContinueList","markdown_automatic_lists","key","altKey","ctrlKey","metaKey","shiftKey","selectedLines","firstSelectedLine","listLineMatch","match","leader","indent","content","isOl","groups","emptyListItem","prefixLength","itemToInsert","nextLineMatch","_nextLineMatch$groups","nextIndent","nextIsOl","numStr","postfix","incrementBy","parseInt","continueOlText","keypressNoteText","_$$atwho","_$","atwho","call","markdown_surround_selection","_","handleSurroundSelectedText","compositionStartNoteText","compositionEndNoteText","updateTextForToolbarBtn","$toolbarBtn","shiftedLines","totalAdded","line","repeat","indentLines","totalRemoved","removedFromFirstline","removedFromLine","slice","outdentLines","attr","each","Shortcuts","initMarkdownEditorShortcuts","addEditorMarkdownListeners","mdTag","mdBlock","mdPrepend","mdSelect","currentTarget","getSelectedText","removeMarkdownEditorShortcuts","resolveSelectedImage","markdownPreviewPath","selectedLine","lineSelectionStart","preExlm","postClose","imageMarkdown","imageURL","body","getAttribute","repeatCodeBackticks","_content$match","numBackticks","sort","a","b","LOCAL_MOUSETRAP_DATA_KEY","getToolbarBtnToShortcutsMap","$textarea","$allToolbarBtns","Map","keyboardShortcuts","set","_gon","extensions","onToggleHelp","helpModalElement","helpModalVueInstance","addAll","TOGGLE_KEYBOARD_SHORTCUTS_DIALOG","START_SEARCH_PROJECT_FILE","focusSearchFile","START_SEARCH","focusSearch","FOCUS_FILTER_BAR","focusFilter","TOGGLE_PERFORMANCE_BAR","onTogglePerfBar","HIDE_APPEARING_CONTENT","hideAppearingContent","TOGGLE_CANARY","onToggleCanary","GO_TO_YOUR_TODO_LIST","findAndFollowLink","GO_TO_ACTIVITY_FEED","GO_TO_YOUR_ISSUES","GO_TO_YOUR_MERGE_REQUESTS","GO_TO_YOUR_REVIEW_REQUESTS","GO_TO_YOUR_PROJECTS","GO_TO_YOUR_GROUPS","GO_TO_MILESTONE_LIST","GO_TO_YOUR_SNIPPETS","TOGGLE_MARKDOWN_PREVIEW","toggleMarkdownPreview","addStopCallback","element","combo","keysFor","features","findAndReplace","FIND_AND_REPLACE","toggleFindAndReplaceBar","shouldDisableShortcuts","disableShortcuts","addExtension","Extension","args","extensionsCurrentlyLoading","Set","instance","Dep","_Extension$dependenci","dependencies","has","delete","command","callback","Mousetrap","commandsAndCallbacks","commandAndCallback","$destroy","createElement","Vue","el","components","ShortcutsHelp","render","hidden","parseBoolean","getCookie","setCookie","refreshCurrentPage","currentValue","expires","triggerHandler","filterInput","_document$querySelect","InternalEvents","trackEvent","_document$querySelect2","_document$querySelect3","FIND_FILE_SHORTCUT_CLICK","searchInput","waitForElement","currentPath","dataset","display","handler","toolbarBtnToShortcutsMap","localMousetrap","allShortcuts","_flatten","values","originalStopCallback","prototype","stopCallback","unbind"],"mappings":"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","file":"6.a12f171e.chunk.js","sourcesContent":["const maxColumnWidth = (rows, columnIndex) =>\n Math.max(...rows.map((row) => row[columnIndex].length));\n\nexport default class PasteMarkdownTable {\n constructor(clipboardData) {\n this.data = clipboardData;\n this.columnWidths = [];\n this.rows = [];\n this.tableFound = this.parseTable();\n }\n\n isTable() {\n return this.tableFound;\n }\n\n convertToTableMarkdown() {\n this.calculateColumnWidths();\n\n const markdownRows = this.rows.map(\n (row) =>\n // | Name | Title | Email Address |\n // |--------------|-------|----------------|\n // | Jane Atler | CEO | jane@acme.com |\n // | John Doherty | CTO | john@acme.com |\n // | Sally Smith | CFO | sally@acme.com |\n `| ${row.map((column, index) => this.formatColumn(column, index)).join(' | ')} |`,\n );\n\n // Insert a header break (e.g. -----) to the second row\n markdownRows.splice(1, 0, this.generateHeaderBreak());\n\n return markdownRows.join('\\n');\n }\n\n // Private methods below\n\n // To determine whether the cut data is a table, the following criteria\n // must be satisfied with the clipboard data:\n //\n // 1. MIME types \"text/plain\" and \"text/html\" exist\n // 2. The \"text/html\" data must have a single element\n // 3. The number of rows in the \"text/plain\" data matches that of the \"text/html\" data\n // 4. The max number of columns in \"text/plain\" matches that of the \"text/html\" data\n parseTable() {\n if (!this.data.types.includes('text/html') || !this.data.types.includes('text/plain')) {\n return false;\n }\n\n const htmlData = this.data.getData('text/html');\n this.doc = new DOMParser().parseFromString(htmlData, 'text/html');\n // Avoid formatting lines that were copied from a diff\n const tables = this.doc.querySelectorAll('table:not(.diff-wrap-lines)');\n\n // We're only looking for exactly one table. If there happens to be\n // multiple tables, it's possible an application copied data into\n // the clipboard that is not related to a simple table. It may also be\n // complicated converting multiple tables into Markdown.\n if (tables.length !== 1) {\n return false;\n }\n\n const text = this.data.getData('text/plain').trim();\n const splitRows = text.split(/[\\n\\u0085\\u2028\\u2029]|\\r\\n?/g);\n\n // Now check that the number of rows matches between HTML and text\n if (this.doc.querySelectorAll('tr').length !== splitRows.length) {\n return false;\n }\n\n this.rows = splitRows.map((row) => row.split('\\t'));\n this.normalizeRows();\n\n // Check that the max number of columns in the HTML matches the number of\n // columns in the text. GitHub, for example, copies a line number and the\n // line itself into the HTML data.\n if (!this.columnCountsMatch()) {\n return false;\n }\n\n return true;\n }\n\n // Ensure each row has the same number of columns\n normalizeRows() {\n const rowLengths = this.rows.map((row) => row.length);\n const maxLength = Math.max(...rowLengths);\n\n this.rows.forEach((row) => {\n while (row.length < maxLength) {\n row.push('');\n }\n });\n }\n\n calculateColumnWidths() {\n this.columnWidths = this.rows[0].map((_column, columnIndex) =>\n maxColumnWidth(this.rows, columnIndex),\n );\n }\n\n columnCountsMatch() {\n const textColumnCount = this.rows[0].length;\n let htmlColumnCount = 0;\n\n this.doc.querySelectorAll('table tr').forEach((row) => {\n htmlColumnCount = Math.max(row.cells.length, htmlColumnCount);\n });\n\n return textColumnCount === htmlColumnCount;\n }\n\n formatColumn(column, index) {\n const spaces = Array(this.columnWidths[index] - column.length + 1).join(' ');\n return column + spaces;\n }\n\n generateHeaderBreak() {\n // Add 3 dashes to line things up: there is additional spacing for the pipe characters\n const dashes = this.columnWidths.map((width, index) =>\n Array(this.columnWidths[index] + 3).join('-'),\n );\n return `|${dashes.join('|')}|`;\n }\n}\n","import Dropzone from 'dropzone';\nimport $ from 'jquery';\nimport { escape } from 'lodash';\nimport './behaviors/preview_markdown';\nimport { spriteIcon } from '~/lib/utils/common_utils';\nimport { getFilename } from '~/lib/utils/file_upload';\nimport { truncate } from '~/lib/utils/text_utility';\nimport { n__, __ } from '~/locale';\nimport { getRetinaDimensions } from '~/lib/utils/image_utils';\nimport PasteMarkdownTable from './behaviors/markdown/paste_markdown_table';\nimport axios from './lib/utils/axios_utils';\nimport csrf from './lib/utils/csrf';\n\nDropzone.autoDiscover = false;\n\n/**\n * Return the error message string from the given response.\n *\n * @param {String|Object} res\n */\nfunction getErrorMessage(res) {\n if (!res || typeof res === 'string') {\n return res;\n }\n\n return res.message;\n}\n\nexport default function dropzoneInput(form, config = { parallelUploads: 2 }) {\n const divHover = '
';\n const iconPaperclip = spriteIcon('paperclip', 'div-dropzone-icon s24');\n const $attachingFileMessage = form.find('.attaching-file-message');\n const $cancelButton = form.find('.button-cancel-uploading-files');\n const $retryLink = form.find('.retry-uploading-link');\n const $uploadProgress = form.find('.uploading-progress');\n const $uploadingErrorContainer = form.find('.uploading-error-container');\n const $uploadingErrorMessage = form.find('.uploading-error-message');\n const $uploadingProgressContainer = form.find('.uploading-progress-container');\n const uploadsPath = form.data('uploads-path') || window.uploads_path || null;\n const maxFileSize = gon.max_file_size || 10;\n const formTextarea = form.find('.js-gfm-input');\n let handlePaste;\n let pasteText;\n let addFileToForm;\n let updateAttachingMessage;\n let uploadFile;\n let hasPlainText;\n\n formTextarea.wrap('
');\n\n // Add dropzone area to the form.\n const $mdArea = formTextarea.closest('.md-area');\n const $formDropzone = form.find('.div-dropzone');\n $formDropzone.parent().addClass('div-dropzone-wrapper');\n $formDropzone.append(divHover);\n $formDropzone.find('.div-dropzone-hover').append(iconPaperclip);\n\n if (!uploadsPath) {\n $formDropzone.addClass('js-invalid-dropzone');\n return null;\n }\n\n formTextarea.on('paste', (event) => handlePaste(event));\n\n const dropzone = $formDropzone.dropzone({\n url: uploadsPath,\n dictDefaultMessage: '',\n clickable: form.get(0).querySelector('[data-button-type=\"attach-file\"]') ?? true,\n paramName: 'file',\n maxFilesize: maxFileSize,\n uploadMultiple: false,\n headers: csrf.headers,\n previewContainer: false,\n ...config,\n dragover: () => {\n $mdArea.addClass('is-dropzone-hover');\n form.find('.div-dropzone-hover').css('opacity', 0.7);\n },\n dragleave: () => {\n $mdArea.removeClass('is-dropzone-hover');\n form.find('.div-dropzone-hover').css('opacity', 0);\n },\n drop: () => {\n $mdArea.removeClass('is-dropzone-hover');\n form.find('.div-dropzone-hover').css('opacity', 0);\n formTextarea.focus();\n },\n success(header, response) {\n const processingFileCount = this.getQueuedFiles().length + this.getUploadingFiles().length;\n const shouldPad = processingFileCount >= 1;\n\n addFileToForm(response.link.url, header.size);\n pasteText(response.link.markdown, shouldPad);\n },\n error: (file, errorMessage = __('Attaching the file failed.'), xhr) => {\n // If 'error' event is fired by dropzone, the second parameter is error message.\n // If the 'errorMessage' parameter is empty, the default error message is set.\n // If the 'error' event is fired by backend (xhr) error response, the third parameter is\n // xhr object (xhr.responseText is error message).\n // On error we hide the 'Attach' and 'Cancel' buttons\n // and show an error.\n const message = getErrorMessage(errorMessage || xhr.responseText);\n\n $uploadingErrorContainer.removeClass('hide');\n $uploadingErrorMessage.html(message);\n $cancelButton.addClass('hide');\n },\n totaluploadprogress(totalUploadProgress) {\n updateAttachingMessage(this.files, $attachingFileMessage);\n $uploadProgress.text(`${Math.round(totalUploadProgress)}%`);\n },\n sending: () => {\n // DOM elements already exist.\n // Instead of dynamically generating them,\n // we just either hide or show them.\n $uploadingErrorContainer.addClass('hide');\n $uploadingProgressContainer.removeClass('hide');\n $cancelButton.removeClass('hide');\n },\n removedfile: () => {\n $cancelButton.addClass('hide');\n $uploadingProgressContainer.addClass('hide');\n $uploadingErrorContainer.addClass('hide');\n },\n queuecomplete: () => {\n $('.dz-preview').remove();\n $('.markdown-area').trigger('input');\n\n $uploadingProgressContainer.addClass('hide');\n $cancelButton.addClass('hide');\n },\n });\n\n const child = $(dropzone[0]).children('textarea');\n\n // removeAllFiles(true) stops uploading files (if any)\n // and remove them from dropzone files queue.\n $cancelButton.on('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n Dropzone.forElement($formDropzone.get(0)).removeAllFiles(true);\n });\n\n // If 'error' event is fired, we store a failed files,\n // clear dropzone files queue, change status of failed files to undefined,\n // and add that files to the dropzone files queue again.\n // addFile() adds file to dropzone files queue and upload it.\n $retryLink.on('click', (e) => {\n const dropzoneInstance = Dropzone.forElement(\n e.target.closest('.js-main-target-form').querySelector('.div-dropzone'),\n );\n const failedFiles = dropzoneInstance.files;\n\n e.preventDefault();\n\n // 'true' parameter of removeAllFiles() cancels\n // uploading of files that are being uploaded at the moment.\n dropzoneInstance.removeAllFiles(true);\n\n failedFiles.map((failedFile) => {\n const file = failedFile;\n\n if (file.status === Dropzone.ERROR) {\n file.status = undefined;\n file.accepted = undefined;\n }\n\n return dropzoneInstance.addFile(file);\n });\n });\n\n handlePaste = (event) => {\n const pasteEvent = event.originalEvent;\n const { clipboardData } = pasteEvent;\n if (clipboardData && clipboardData.items) {\n const converter = new PasteMarkdownTable(clipboardData);\n // Apple Numbers copies a table as an image, HTML, and text, so\n // we need to check for the presence of a table first.\n if (converter.isTable()) {\n event.preventDefault();\n const text = converter.convertToTableMarkdown();\n pasteText(text);\n } else if (!hasPlainText(pasteEvent)) {\n const fileList = [...clipboardData.files];\n fileList.forEach((file) => {\n if (file.type.indexOf('image') !== -1) {\n event.preventDefault();\n const MAX_FILE_NAME_LENGTH = 246;\n\n const filename = getFilename(file) || 'image.png';\n const truncateFilename = truncate(filename, MAX_FILE_NAME_LENGTH);\n const text = `{{${truncateFilename}}}`;\n pasteText(text);\n\n uploadFile(file, truncateFilename);\n }\n });\n }\n }\n };\n\n hasPlainText = (data) => {\n const clipboardDataList = [...data.clipboardData.items];\n return clipboardDataList.some((item) => item.type === 'text/plain');\n };\n\n pasteText = (text, shouldPad) => {\n let formattedText = text;\n if (shouldPad) {\n formattedText += '\\n\\n';\n }\n const textarea = child.get(0);\n const caretStart = textarea.selectionStart;\n const caretEnd = textarea.selectionEnd;\n const textEnd = $(child).val().length;\n const beforeSelection = $(child).val().substring(0, caretStart);\n const afterSelection = $(child).val().substring(caretEnd, textEnd);\n $(child).val(beforeSelection + formattedText + afterSelection);\n textarea.setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length);\n textarea.style.height = `${textarea.scrollHeight}px`;\n formTextarea.get(0).dispatchEvent(new Event('input'));\n return formTextarea.trigger('input');\n };\n\n addFileToForm = (path) => {\n $(form).append(``);\n };\n\n const showSpinner = () => $uploadingProgressContainer.removeClass('hide');\n\n const closeSpinner = () => $uploadingProgressContainer.addClass('hide');\n\n const showError = (message) => {\n $uploadingErrorContainer.removeClass('hide');\n $uploadingErrorMessage.html(message);\n };\n\n const insertToTextArea = (filename, url) => {\n const $child = $(child);\n const textarea = $child.get(0);\n const caretStart = textarea.selectionStart;\n const caretEnd = textarea.selectionEnd;\n const formattedText = `{{${filename}}}`;\n $child.val((index, val) => val.replace(formattedText, url));\n textarea.setSelectionRange(\n caretStart - formattedText.length + url.length,\n caretEnd - formattedText.length + url.length,\n );\n $child.trigger('change');\n };\n\n uploadFile = (item, filename) => {\n const formData = new FormData();\n formData.append('file', item, filename);\n\n showSpinner();\n\n axios\n .post(uploadsPath, formData)\n .then(async ({ data }) => {\n let md = data.link.markdown;\n\n const { width, height } = (await getRetinaDimensions(item)) || {};\n if (width && height) {\n // eslint-disable-next-line @gitlab/require-i18n-strings\n md += `{width=${width} height=${height}}`;\n }\n\n insertToTextArea(filename, md);\n closeSpinner();\n })\n .catch((e) => {\n showError(e.response.data.message);\n closeSpinner();\n });\n };\n\n updateAttachingMessage = (files, messageContainer) => {\n const filesCount = files.filter(\n (file) => file.status === 'uploading' || file.status === 'queued',\n ).length;\n const attachingMessage = n__('Attaching a file', 'Attaching %d files', filesCount);\n\n messageContainer.text(`${attachingMessage} -`);\n };\n\n function handleAttachFile(e) {\n e.preventDefault();\n $(this).closest('.gfm-form').find('.div-dropzone').click();\n formTextarea.focus();\n }\n\n form.find('.markdown-selector').click(handleAttachFile);\n\n const $attachFileButton = form.find('.js-attach-file-button');\n if ($attachFileButton.length) {\n $attachFileButton.get(0).addEventListener('click', handleAttachFile);\n }\n\n return $formDropzone.get(0) ? Dropzone.forElement($formDropzone.get(0)) : null;\n}\n","import autosize from 'autosize';\nimport $ from 'jquery';\nimport { isEmpty } from 'lodash';\nimport GfmAutoComplete, { defaultAutocompleteConfig } from 'ee_else_ce/gfm_auto_complete';\nimport { disableButtonIfEmptyField } from '~/lib/utils/common_utils';\nimport dropzoneInput from './dropzone_input';\nimport { addMarkdownListeners, removeMarkdownListeners } from './lib/utils/text_markdown';\n\nexport default class GLForm {\n /**\n * Create a GLForm\n *\n * @param {jQuery} form Root element of the GLForm\n * @param {Object} enableGFM Which autocomplete features should be enabled?\n * @param {Boolean} forceNew If true, treat the element as a **new** form even if `gfm-form` class already exists.\n * @param {Object} gfmDataSources The paths of the autocomplete data sources to use for GfmAutoComplete\n * By default, the backend embeds these in the global object gl.GfmAutocomplete.dataSources.\n * Use this param to override them.\n */\n // eslint-disable-next-line max-params\n constructor(form, enableGFM = {}, forceNew = false, gfmDataSources = {}) {\n this.form = form;\n this.textarea = this.form.find('textarea.js-gfm-input');\n this.enableGFM = { ...defaultAutocompleteConfig, ...enableGFM };\n\n // Disable autocomplete for keywords which do not have dataSources available\n let dataSources = (gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources) || {};\n\n if (!isEmpty(gfmDataSources)) {\n dataSources = gfmDataSources;\n }\n\n Object.keys(this.enableGFM).forEach((item) => {\n if (item !== 'emojis' && !dataSources[item]) {\n this.enableGFM[item] = false;\n }\n });\n\n // Before we start, we should clean up any previous data for this form\n this.destroy();\n // Set up the form\n this.setupForm(dataSources, forceNew);\n this.form.data('glForm', this);\n }\n\n destroy() {\n // Clean form listeners\n this.clearEventListeners();\n if (this.autoComplete) {\n this.autoComplete.destroy();\n }\n if (this.formDropzone) {\n this.formDropzone.destroy();\n }\n\n this.form.data('glForm', null);\n }\n\n setupForm(dataSources, forceNew = false) {\n const isNewForm = this.form.is(':not(.gfm-form)') || forceNew;\n this.form.removeClass('js-new-note-form');\n if (isNewForm) {\n this.form.find('.div-dropzone').remove();\n this.form.addClass('gfm-form');\n // remove notify commit author checkbox for non-commit notes\n disableButtonIfEmptyField(\n this.form.find('.js-note-text'),\n this.form.find('.js-comment-button, .js-note-new-discussion'),\n );\n this.autoComplete = new GfmAutoComplete(dataSources);\n this.autoComplete.setup(this.form.find('.js-gfm-input'), this.enableGFM);\n this.formDropzone = dropzoneInput(this.form, { parallelUploads: 1 });\n\n if (this.form.is(':not(.js-no-autosize)')) {\n autosize(this.textarea);\n }\n }\n // form and textarea event listeners\n this.addEventListeners();\n addMarkdownListeners(this.form);\n this.form.show();\n if (this.isAutosizeable) this.setupAutosize();\n if (this.textarea.data('autofocus') === true) this.textarea.focus();\n }\n\n updateAutocompleteDataSources(dataSources) {\n if (this.autoComplete) {\n this.autoComplete.updateDataSources(dataSources);\n }\n }\n\n setupAutosize() {\n // eslint-disable-next-line @gitlab/no-global-event-off\n this.textarea.off('autosize:resized').on('autosize:resized', this.setHeightData.bind(this));\n\n // eslint-disable-next-line @gitlab/no-global-event-off\n this.textarea.off('mouseup.autosize').on('mouseup.autosize', this.destroyAutosize.bind(this));\n\n setTimeout(() => {\n autosize(this.textarea);\n this.textarea.css('resize', 'vertical');\n }, 0);\n }\n\n setHeightData() {\n this.textarea.data('height', this.textarea.outerHeight());\n }\n\n destroyAutosize() {\n const outerHeight = this.textarea.outerHeight();\n\n if (this.textarea.data('height') === outerHeight) return;\n\n autosize.destroy(this.textarea);\n\n this.textarea.data('height', outerHeight);\n this.textarea.outerHeight(outerHeight);\n this.textarea.css('max-height', window.outerHeight);\n }\n\n clearEventListeners() {\n // eslint-disable-next-line @gitlab/no-global-event-off\n this.textarea.off('focus');\n // eslint-disable-next-line @gitlab/no-global-event-off\n this.textarea.off('blur');\n removeMarkdownListeners(this.form);\n }\n\n addEventListeners() {\n this.textarea.on('focus', function focusTextArea() {\n $(this).closest('.md-area').addClass('is-focused');\n });\n this.textarea.on('blur', function blurTextArea() {\n $(this).closest('.md-area').removeClass('is-focused');\n });\n }\n\n get supportsQuickActions() {\n return Boolean(this.textarea.data('supports-quick-actions'));\n }\n}\n","export default (buttonSelector, fileSelector) => {\n const btn = document.querySelector(buttonSelector);\n const fileInput = document.querySelector(fileSelector);\n\n if (!btn || !fileInput) return;\n\n const form = btn.closest('form');\n\n btn.addEventListener('click', () => {\n fileInput.click();\n });\n\n fileInput.addEventListener('change', () => {\n form.querySelector('.js-filename').textContent = fileInput.value.replace(/^.*[\\\\\\/]/, ''); // eslint-disable-line no-useless-escape\n });\n};\n\nexport const getFilename = (file) => {\n let fileName;\n if (file) {\n fileName = file.name;\n }\n\n return fileName;\n};\n\nexport const validateImageName = (file) => {\n const fileName = file.name ? file.name : 'image.png';\n const legalImageRegex = /^[\\w.\\-+]+\\.(png|jpg|jpeg|gif|bmp|tiff|ico|webp)$/;\n return legalImageRegex.test(fileName) ? fileName : 'image.png';\n};\n\nexport const validateFileFromAllowList = (fileName, allowList) => {\n const parts = fileName.split('.');\n const ext = `.${parts[parts.length - 1]}`;\n\n return allowList.includes(ext);\n};\n","/**\n * Takes a file object and returns a data uri of its contents.\n *\n * @param {File} file\n */\nexport function readFileAsDataURL(file) {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.addEventListener('load', (e) => resolve(e.target.result), { once: true });\n reader.readAsDataURL(file);\n });\n}\n","class Vector {\n constructor(x, y) {\n this.x = x;\n this.y = y;\n }\n\n eq(x1, y1) {\n return this.x === x1 && this.y === y1;\n }\n\n neq(x1, y1) {\n return this.x !== x1 || this.y !== y1;\n }\n\n gte(x1, y1) {\n return this.x >= x1 && this.y >= y1;\n }\n\n gt(x1, y1) {\n return this.x > x1 && this.y > y1;\n }\n\n lte(x1, y1) {\n return this.x <= x1 && this.y <= y1;\n }\n\n lt(x1, y1) {\n return this.x < x1 && this.y < y1;\n }\n\n map(fn) {\n return new Vector(fn(this.x), fn(this.y));\n }\n\n mul(scalar) {\n return new Vector(this.x * scalar, this.y * scalar);\n }\n\n div(scalar) {\n return new Vector(this.x / scalar, this.y / scalar);\n }\n\n add(x1, y1) {\n return new Vector(this.x + x1, this.y + y1);\n }\n\n sub(x1, y1) {\n return new Vector(this.x - x1, this.y - y1);\n }\n\n round() {\n return new Vector(Math.round(this.x), Math.round(this.y));\n }\n\n floor() {\n return new Vector(Math.floor(this.x), Math.floor(this.y));\n }\n\n ceil() {\n return new Vector(Math.ceil(this.x), Math.ceil(this.y));\n }\n\n toSize() {\n return { width: this.x, height: this.y };\n }\n}\n\nconst vector = (x, y) => new Vector(x, y);\n\nexport default vector;\n","import { domToBlob } from 'modern-screenshot';\nimport vector from './vector';\nimport { readFileAsDataURL } from './file_utility';\n\n// 1 meter = 39.3701 inches\nconst METER_TO_INCHES = 39.3701;\nconst UNIT_METERS = 1;\nconst PNG_DEFAULT_PPI = 72;\n\nconst stringToUInt32 = (str) => {\n const buffer = str.split('').map((char) => char.charCodeAt(0));\n // eslint-disable-next-line no-bitwise\n return (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];\n};\n\nconst getPixelsPerInch = (pngImage) => {\n // pHYs is a chunk that specifies the intended pixel size or aspect ratio of the image\n // See https://www.w3.org/TR/PNG-Chunks.html#C.pHYs\n const physPosition = pngImage.indexOf('pHYs');\n if (physPosition === -1) return null;\n\n // p H Y s x x x x y y y y u\n // - - - - 0 1 2 3 4 5 6 7 8\n // ^ width ^ height ^ unit\n const phys = pngImage.substring(physPosition + 4, physPosition + 4 + 9);\n if (phys.charCodeAt(8) !== UNIT_METERS) return null;\n\n return vector(phys.substring(0, 4), phys.substring(4, 8))\n .map(stringToUInt32)\n .div(METER_TO_INCHES)\n .round();\n};\n\nconst fileToPngImage = async (file) => {\n if (file.type !== 'image/png') return null;\n\n const dataUrl = await readFileAsDataURL(file);\n return atob(dataUrl.split(',')[1]).split('IDAT')[0];\n};\n\nexport const getRetinaDimensions = async (pngFile) => {\n try {\n const pngImage = await fileToPngImage(pngFile);\n const pixelsPerInch = getPixelsPerInch(pngImage);\n if (pixelsPerInch.lte(PNG_DEFAULT_PPI, PNG_DEFAULT_PPI)) return null;\n\n // IHDR is the first chunk in a PNG file\n // It contains the image dimensions\n // See https://www.w3.org/TR/PNG-Chunks.html#C.IHDR\n const ihdrPosition = pngImage.substring(0, 30).indexOf('IHDR');\n if (ihdrPosition === -1) return null;\n\n // I H D R x x x x y y y y\n // - - - - 0 1 2 3 4 5 6 7\n // ^ width ^ height\n const ihdr = pngImage.substring(ihdrPosition + 4, ihdrPosition + 4 + 8);\n\n return vector(ihdr.substring(0, 4), ihdr.substring(4, 8))\n .map(stringToUInt32)\n .mul(PNG_DEFAULT_PPI)\n .div(Math.max(pixelsPerInch.x, pixelsPerInch.y))\n .ceil()\n .toSize();\n } catch (e) {\n return null;\n }\n};\n\nexport function domElementToBlob(domElement) {\n return domToBlob(domElement);\n}\n","/* eslint-disable func-names, no-param-reassign, operator-assignment, consistent-return */\nimport $ from 'jquery';\nimport Shortcuts from '~/behaviors/shortcuts/shortcuts';\nimport { insertText } from '~/lib/utils/common_utils';\nimport axios from '~/lib/utils/axios_utils';\n\nconst LINK_TAG_PATTERN = '[{text}](url)';\nconst INDENT_CHAR = ' ';\nconst INDENT_LENGTH = 2;\n\n// at the start of a line, find any amount of whitespace followed by\n// a bullet point character (*+-) and an optional checkbox ([ ] [x])\n// OR a number with a . after it and an optional checkbox ([ ] [x])\n// followed by one or more whitespace characters\nconst LIST_LINE_HEAD_PATTERN =\n /^(?\\s*)(?((?[*+-])|(?\\d+\\.))( \\[([xX~\\s])\\])?\\s)(?.)?/;\n\n// detect a horizontal rule that might be mistaken for a list item (not full pattern for an
)\nconst HR_PATTERN = /^((\\s{0,3}-+\\s*-+\\s*-+\\s*[\\s-]*)|(\\s{0,3}\\*+\\s*\\*+\\s*\\*+\\s*[\\s*]*))$/;\n\nlet compositioningNoteText = false;\n\nfunction selectedText(text, textarea) {\n return text.substring(textarea.selectionStart, textarea.selectionEnd);\n}\n\nfunction addBlockTags(blockTag, selected) {\n return `${blockTag}\\n${selected}\\n${blockTag}`;\n}\n\n/**\n * Returns the line of text that is before the first line\n * of the current selection\n *\n * @param {String} text - the text of the targeted text area\n * @param {Object} textArea - the targeted text area\n * @returns {String}\n */\nfunction lineBeforeSelection(text, textArea) {\n let split = text.substring(0, textArea.selectionStart);\n\n split = split.split('\\n');\n\n // Last item, at -1, is the line where the start of selection is.\n // Line before selection is therefore at -2\n const lineBefore = split[split.length - 2];\n\n return lineBefore === undefined ? '' : lineBefore;\n}\n\n/**\n * Returns the line of text that is after the last line\n * of the current selection\n *\n * @param {String} text - the text of the targeted text area\n * @param {Object} textArea - the targeted text area\n * @returns {String}\n */\nfunction lineAfterSelection(text, textArea) {\n let split = text.substring(textArea.selectionEnd);\n\n // remove possible leading newline to get at the real line\n split = split.replace(/^\\n/, '');\n split = split.split('\\n');\n\n return split[0];\n}\n\n/**\n * Returns the text lines that encompass the current selection\n *\n * @param {Object} textArea - the targeted text area\n * @returns {Object}\n */\nfunction linesFromSelection(textArea) {\n const text = textArea.value;\n const { selectionStart, selectionEnd } = textArea;\n\n let startPos = text[selectionStart] === '\\n' ? selectionStart - 1 : selectionStart;\n startPos = text.lastIndexOf('\\n', startPos) + 1;\n\n let endPos = selectionEnd === selectionStart ? selectionEnd : selectionEnd - 1;\n endPos = text.indexOf('\\n', endPos);\n if (endPos < 0) endPos = text.length;\n\n const selectedRange = text.substring(startPos, endPos);\n const lines = selectedRange.split('\\n');\n\n return {\n lines,\n selectionStart,\n selectionEnd,\n startPos,\n endPos,\n };\n}\n\n/**\n * Set the selection of a textarea such that it maintains the\n * previous selection before the lines were indented/outdented\n *\n * @param {Object} textArea - the targeted text area\n * @param {Number} selectionStart - start position of original selection\n * @param {Number} selectionEnd - end position of original selection\n * @param {Number} lineStart - start pos of first line\n * @param {Number} firstLineChange - number of characters changed on first line\n * @param {Number} totalChanged - total number of characters changed\n */\n// eslint-disable-next-line max-params\nfunction setNewSelectionRange(\n textArea,\n selectionStart,\n selectionEnd,\n lineStart,\n firstLineChange,\n totalChanged,\n) {\n let newStart = Math.max(lineStart, selectionStart + firstLineChange);\n let newEnd = Math.max(lineStart, selectionEnd + totalChanged);\n\n if (selectionStart === selectionEnd) {\n newEnd = newStart;\n } else if (selectionStart === lineStart) {\n newStart = lineStart;\n }\n\n textArea.setSelectionRange(newStart, newEnd);\n}\n\nfunction convertMonacoSelectionToAceFormat(sel) {\n return {\n start: {\n row: sel.startLineNumber,\n column: sel.startColumn,\n },\n end: {\n row: sel.endLineNumber,\n column: sel.endColumn,\n },\n };\n}\n\nfunction getEditorSelectionRange(editor) {\n return convertMonacoSelectionToAceFormat(editor.getSelection());\n}\n\n// eslint-disable-next-line max-params\nfunction editorBlockTagText(text, blockTag, selected, editor) {\n const lines = text.split('\\n');\n const selectionRange = getEditorSelectionRange(editor);\n const shouldRemoveBlock =\n lines[selectionRange.start.row - 1] === blockTag &&\n lines[selectionRange.end.row + 1] === blockTag;\n\n if (shouldRemoveBlock) {\n if (blockTag !== null) {\n const lastLine = lines[selectionRange.end.row + 1];\n const rangeWithBlockTags = new Range(\n lines[selectionRange.start.row - 1],\n 0,\n selectionRange.end.row + 1,\n lastLine.length,\n );\n editor.getSelection().setSelectionRange(rangeWithBlockTags);\n }\n return selected;\n }\n return addBlockTags(blockTag, selected);\n}\n\n// eslint-disable-next-line max-params\nfunction blockTagText(text, textArea, blockTag, selected) {\n const shouldRemoveBlock =\n lineBeforeSelection(text, textArea) === blockTag &&\n lineAfterSelection(text, textArea) === blockTag;\n\n if (shouldRemoveBlock) {\n // To remove the block tag we have to select the line before & after\n if (blockTag != null) {\n textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1);\n textArea.selectionEnd = textArea.selectionEnd + (blockTag.length + 1);\n }\n return selected;\n }\n return addBlockTags(blockTag, selected);\n}\n\nfunction moveCursor({\n textArea,\n tag,\n cursorOffset,\n positionBetweenTags,\n removedLastNewLine,\n select,\n editor,\n editorSelectionStart,\n editorSelectionEnd,\n}) {\n let pos;\n if (textArea && !textArea.setSelectionRange) {\n return;\n }\n if (select && select.length > 0) {\n if (textArea) {\n // calculate the part of the text to be selected\n const startPosition = textArea.selectionStart - (tag.length - tag.indexOf(select));\n const endPosition = startPosition + select.length;\n return textArea.setSelectionRange(startPosition, endPosition);\n }\n if (editor) {\n editor.selectWithinSelection(select, tag);\n return;\n }\n }\n if (textArea) {\n if (textArea.selectionStart === textArea.selectionEnd) {\n if (positionBetweenTags) {\n pos = textArea.selectionStart - tag.length;\n } else {\n pos = textArea.selectionStart;\n }\n\n if (removedLastNewLine) {\n pos -= 1;\n }\n\n if (cursorOffset) {\n pos -= cursorOffset;\n }\n\n return textArea.setSelectionRange(pos, pos);\n }\n } else if (editor && editorSelectionStart.row === editorSelectionEnd.row) {\n if (positionBetweenTags) {\n editor.moveCursor(tag.length * -1);\n }\n }\n}\n\n/**\n * Inserts the given MarkdownText into the given textArea or editor\n *\n * WARNING: This is a bit of legacy code that has some complicated logic.\n * There are a lot of hidden contexts to consider here. Please proceed with caution.\n *\n * We've tried to document the parameter responsibilities as best as possible.\n * Please look for actual usage in the code to verify any assumptions.\n *\n * @param {Object} options - Named parameters\n * @param {HTMLTextAreaElement} options.textArea - The relevant text area\n * @param {String} options.text - The current text of the text area\n * @param {String} options.tag - The markdown tag we want to enter (Example: `- [ ] ` for lists)\n * @param {Number} options.cursorOffset - Applied to the position after we insert the text (moves backward)\n * @param {String} options.blockTag - The markdown tag to use if a block is detected (Example ` ``` ` vs. ` ` `)\n * @param {Boolean} options.wrap - Flag for whether the tag is a wrapping tag (Example `**text**` vs `* text`)\n * @param {String} options.select - The text to select after inserting (Example `url` of `({text})[url]`)\n * @param {Object} options.editor - The instance of the SourceEditor which we are inserting MarkdownText into. This should be mutually exclusive with textArea.\n */\nexport function insertMarkdownText({\n textArea,\n text,\n tag,\n cursorOffset,\n blockTag,\n selected = '',\n wrap,\n select,\n editor,\n}) {\n // If we aren't really inserting anything, let's just noop.\n // Let's check for `selected` too because there might be hidden logic that actually\n // is expected to run for this case.\n if (!tag && !blockTag && !selected) {\n return;\n }\n\n let removedLastNewLine = false;\n let removedFirstNewLine = false;\n let currentLineEmpty = false;\n let editorSelectionStart;\n let editorSelectionEnd;\n let lastNewLine;\n let textToInsert;\n selected = selected.toString();\n\n if (editor) {\n const selectionRange = getEditorSelectionRange(editor);\n\n editorSelectionStart = selectionRange.start;\n editorSelectionEnd = selectionRange.end;\n }\n\n // check for link pattern and selected text is an URL\n // if so fill in the url part instead of the text part of the pattern.\n if (tag === LINK_TAG_PATTERN) {\n if (URL) {\n try {\n const url = new URL(selected);\n\n if (url.origin !== 'null' || url.origin === null) {\n tag = '[text]({text})';\n select = 'text';\n }\n } catch (e) {\n // ignore - no valid url\n }\n }\n }\n\n // Remove the first newline\n if (selected.indexOf('\\n') === 0) {\n removedFirstNewLine = true;\n selected = selected.replace(/\\n+/, '');\n }\n\n // Remove the last newline\n if (textArea) {\n if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\\n$/, '').length) {\n removedLastNewLine = true;\n selected = selected.replace(/\\n$/, '');\n }\n } else if (editor) {\n if (editorSelectionStart.row !== editorSelectionEnd.row) {\n removedLastNewLine = true;\n selected = selected.replace(/\\n$/, '');\n }\n }\n\n const selectedSplit = selected.split('\\n');\n\n if (editor && !wrap) {\n lastNewLine = editor.getValue().split('\\n')[editorSelectionStart.row];\n\n if (/^\\s*$/.test(lastNewLine)) {\n currentLineEmpty = true;\n }\n } else if (textArea && !wrap) {\n lastNewLine = textArea.value.substr(0, textArea.selectionStart).lastIndexOf('\\n');\n\n // Check whether the current line is empty or consists only of spaces(=handle as empty)\n if (/^\\s*$/.test(textArea.value.substring(lastNewLine, textArea.selectionStart))) {\n currentLineEmpty = true;\n }\n }\n\n const isBeginning =\n (textArea && textArea.selectionStart === 0) ||\n (editor && editorSelectionStart.column === 0 && editorSelectionStart.row === 0);\n\n const startChar = !wrap && !currentLineEmpty && !isBeginning ? '\\n' : '';\n const textPlaceholder = '{text}';\n\n if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) {\n if (blockTag != null && blockTag !== '') {\n textToInsert = editor\n ? editorBlockTagText(text, blockTag, selected, editor)\n : blockTagText(text, textArea, blockTag, selected);\n } else {\n textToInsert = selectedSplit\n .map((val) => {\n if (tag.indexOf(textPlaceholder) > -1) {\n return tag.replace(textPlaceholder, val);\n }\n if (val.indexOf(tag) === 0) {\n return String(val.replace(tag, ''));\n }\n return String(tag) + val;\n })\n .join('\\n');\n }\n } else if (tag.indexOf(textPlaceholder) > -1) {\n textToInsert = tag.replace(textPlaceholder, () =>\n selected.replace(/\\\\n/g, '\\n').replace(/%br/g, '\\\\n'),\n );\n } else {\n textToInsert = String(startChar) + tag + selected + (wrap ? tag : '');\n }\n\n if (removedFirstNewLine) {\n textToInsert = `\\n${textToInsert}`;\n }\n\n if (removedLastNewLine) {\n textToInsert += '\\n';\n }\n\n if (editor) {\n editor.replaceSelectedText(textToInsert, select);\n } else {\n insertText(textArea, textToInsert);\n }\n\n moveCursor({\n textArea,\n tag: tag.replace(textPlaceholder, selected),\n cursorOffset,\n positionBetweenTags: wrap && selected.length === 0,\n removedLastNewLine,\n select,\n editor,\n editorSelectionStart,\n editorSelectionEnd,\n });\n}\n\nexport function updateText({ textArea, tag, cursorOffset, blockTag, wrap, select, tagContent }) {\n const $textArea = $(textArea);\n textArea = $textArea.get(0);\n const text = $textArea.val();\n const selected = selectedText(text, textArea) || tagContent;\n textArea.focus();\n insertMarkdownText({\n textArea,\n text,\n tag,\n cursorOffset,\n blockTag,\n selected,\n wrap,\n select,\n });\n textArea.click();\n}\n\n/**\n * Indents selected lines to the right by 2 spaces\n *\n * @param {Object} textArea - jQuery object with the targeted text area\n */\nfunction indentLines($textArea) {\n const textArea = $textArea.get(0);\n const { lines, selectionStart, selectionEnd, startPos, endPos } = linesFromSelection(textArea);\n const shiftedLines = [];\n let totalAdded = 0;\n\n textArea.focus();\n textArea.setSelectionRange(startPos, endPos);\n\n lines.forEach((line) => {\n line = INDENT_CHAR.repeat(INDENT_LENGTH) + line;\n totalAdded += INDENT_LENGTH;\n\n shiftedLines.push(line);\n });\n\n const textToInsert = shiftedLines.join('\\n');\n\n insertText(textArea, textToInsert);\n setNewSelectionRange(textArea, selectionStart, selectionEnd, startPos, INDENT_LENGTH, totalAdded);\n}\n\n/**\n * Outdents selected lines to the left by 2 spaces\n *\n * @param {Object} textArea - the targeted text area\n */\nfunction outdentLines($textArea) {\n const textArea = $textArea.get(0);\n const { lines, selectionStart, selectionEnd, startPos, endPos } = linesFromSelection(textArea);\n const shiftedLines = [];\n let totalRemoved = 0;\n let removedFromFirstline = -1;\n let removedFromLine = 0;\n\n textArea.focus();\n textArea.setSelectionRange(startPos, endPos);\n\n lines.forEach((line) => {\n removedFromLine = 0;\n\n if (line.length > 0) {\n // need to count how many spaces are actually removed, so can't use `replace`\n while (removedFromLine < INDENT_LENGTH && line[removedFromLine] === INDENT_CHAR) {\n removedFromLine += 1;\n }\n\n if (removedFromLine > 0) {\n line = line.slice(removedFromLine);\n totalRemoved += removedFromLine;\n }\n }\n\n if (removedFromFirstline === -1) removedFromFirstline = removedFromLine;\n shiftedLines.push(line);\n });\n\n const textToInsert = shiftedLines.join('\\n');\n\n if (totalRemoved > 0) insertText(textArea, textToInsert);\n\n setNewSelectionRange(\n textArea,\n selectionStart,\n selectionEnd,\n startPos,\n -removedFromFirstline,\n -totalRemoved,\n );\n}\n\n/* eslint-disable @gitlab/require-i18n-strings */\nfunction handleSurroundSelectedText(e, textArea) {\n if (!gon.markdown_surround_selection) return;\n if (e.metaKey || e.ctrlKey) return;\n if (textArea.selectionStart === textArea.selectionEnd) return;\n\n const keys = {\n '*': '**{text}**', // wraps with bold character\n _: '_{text}_', // wraps with italic character\n '`': '`{text}`', // wraps with inline character\n \"'\": \"'{text}'\", // single quotes\n '\"': '\"{text}\"', // double quotes\n '[': '[{text}]', // brackets\n '{': '{{text}}', // braces\n '(': '({text})', // parentheses\n '<': '<{text}>', // angle brackets\n };\n const tag = keys[e.key];\n\n if (tag) {\n e.preventDefault();\n\n updateText({\n tag,\n textArea,\n blockTag: '',\n wrap: true,\n select: '',\n tagContent: '',\n });\n }\n}\n/* eslint-enable @gitlab/require-i18n-strings */\n\n/**\n * Returns the content for a new line following a list item.\n *\n * @param {Object} listLineMatch - regex match of the current line\n * @param {Object?} nextLineMatch - regex match of the next line\n * @returns string with the new list item\n */\nfunction continueOlText(listLineMatch, nextLineMatch) {\n const { indent, leader } = listLineMatch.groups;\n const { indent: nextIndent, isOl: nextIsOl } = nextLineMatch?.groups ?? {};\n\n const [numStr, postfix = ''] = leader.split('.');\n\n const incrementBy = nextIsOl && nextIndent === indent ? 0 : 1;\n const num = parseInt(numStr, 10) + incrementBy;\n\n return `${indent}${num}.${postfix}`;\n}\n\nfunction handleContinueList(e, textArea) {\n if (!gon.markdown_automatic_lists) return;\n if (!(e.key === 'Enter')) return;\n if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;\n if (textArea.selectionStart !== textArea.selectionEnd) return;\n\n // prevent unintended line breaks inserted using Japanese IME on MacOS\n if (compositioningNoteText) return;\n\n const selectedLines = linesFromSelection(textArea);\n const firstSelectedLine = selectedLines.lines[0];\n const listLineMatch = firstSelectedLine.match(LIST_LINE_HEAD_PATTERN);\n\n if (listLineMatch) {\n const { leader, indent, content, isOl } = listLineMatch.groups;\n const emptyListItem = !content;\n const prefixLength = leader.length + indent.length;\n\n if (selectedLines.selectionStart - selectedLines.startPos < prefixLength) {\n // cursor in the indent/leader area, allow the natural line feed to be added\n return;\n }\n\n if (emptyListItem) {\n // erase empty list item - select the text and allow the\n // natural line feed to erase the text\n textArea.selectionStart = textArea.selectionStart - listLineMatch[0].length;\n return;\n }\n\n let itemToInsert;\n\n // Behaviors specific to either `ol` or `ul`\n if (isOl) {\n const nextLine = lineAfterSelection(textArea.value, textArea);\n const nextLineMatch = nextLine.match(LIST_LINE_HEAD_PATTERN);\n\n itemToInsert = continueOlText(listLineMatch, nextLineMatch);\n } else {\n if (firstSelectedLine.match(HR_PATTERN)) return;\n\n itemToInsert = `${indent}${leader}`;\n }\n\n itemToInsert = itemToInsert.replace(/\\[[x~]\\]/i, '[ ]');\n\n e.preventDefault();\n\n updateText({\n tag: itemToInsert,\n textArea,\n blockTag: '',\n wrap: false,\n select: '',\n tagContent: '',\n });\n }\n}\n\nexport function keypressNoteText(e) {\n const textArea = this;\n\n if ($(textArea).atwho?.('isSelecting')) return;\n\n handleContinueList(e, textArea);\n handleSurroundSelectedText(e, textArea);\n}\n\nexport function compositionStartNoteText() {\n compositioningNoteText = true;\n}\n\nexport function compositionEndNoteText() {\n compositioningNoteText = false;\n}\n\nexport function updateTextForToolbarBtn($toolbarBtn) {\n const $textArea = $toolbarBtn.closest('.md-area').find('textarea');\n if (!$textArea.length) return;\n\n switch ($toolbarBtn.data('mdCommand')) {\n case 'indentLines':\n indentLines($textArea);\n break;\n case 'outdentLines':\n outdentLines($textArea);\n break;\n default:\n return updateText({\n textArea: $textArea,\n tag: $toolbarBtn.data('mdTag'),\n cursorOffset: $toolbarBtn.data('mdCursorOffset'),\n blockTag: $toolbarBtn.data('mdBlock'),\n wrap: !$toolbarBtn.data('mdPrepend'),\n select: $toolbarBtn.data('mdSelect'),\n tagContent: $toolbarBtn.attr('data-md-tag-content'),\n });\n }\n}\n\nexport function addMarkdownListeners(form) {\n $('.markdown-area', form)\n .on('keydown', keypressNoteText)\n .on('compositionstart', compositionStartNoteText)\n .on('compositionend', compositionEndNoteText)\n .each(function attachTextareaShortcutHandlers() {\n Shortcuts.initMarkdownEditorShortcuts($(this), updateTextForToolbarBtn);\n });\n\n const $allToolbarBtns = $(form)\n .off('click', '.js-md')\n .on('click', '.js-md', function () {\n const $toolbarBtn = $(this);\n\n return updateTextForToolbarBtn($toolbarBtn);\n });\n\n return $allToolbarBtns;\n}\n\nexport function addEditorMarkdownListeners(editor) {\n // eslint-disable-next-line @gitlab/no-global-event-off\n $('.js-md')\n .off('click')\n .on('click', (e) => {\n const { mdTag, mdBlock, mdPrepend, mdSelect } = $(e.currentTarget).data();\n\n insertMarkdownText({\n tag: mdTag,\n blockTag: mdBlock,\n wrap: !mdPrepend,\n select: mdSelect,\n selected: editor.getSelectedText(),\n text: editor.getValue(),\n editor,\n });\n editor.focus();\n });\n}\n\nexport function removeMarkdownListeners(form) {\n $('.markdown-area', form)\n .off('keydown', keypressNoteText)\n .off('compositionstart', compositionStartNoteText)\n .off('compositionend', compositionEndNoteText)\n .each(function removeTextareaShortcutHandlers() {\n Shortcuts.removeMarkdownEditorShortcuts($(this));\n });\n\n // eslint-disable-next-line @gitlab/no-global-event-off\n return $('.js-md', form).off('click');\n}\n\n/**\n * If the textarea cursor is positioned in a Markdown image declaration,\n * it uses the Markdown API to resolve the image’s absolute URL.\n * @param {Object} textarea Textarea DOM element\n * @param {String} markdownPreviewPath Markdown API path\n * @returns {Object} an object containing the image’s absolute URL, filename,\n * and the markdown declaration. If the textarea cursor is not positioned\n * in an image, it returns null.\n */\nexport const resolveSelectedImage = async (textArea, markdownPreviewPath = '') => {\n const { lines, startPos } = linesFromSelection(textArea);\n\n // image declarations can’t span more than one line in Markdown\n if (lines > 0) {\n return null;\n }\n\n const selectedLine = lines[0];\n\n if (!/!\\[.+?\\]\\(.+?\\)/.test(selectedLine)) return null;\n\n const lineSelectionStart = textArea.selectionStart - startPos;\n const preExlm = selectedLine.substring(0, lineSelectionStart).lastIndexOf('!');\n const postClose = selectedLine.substring(lineSelectionStart).indexOf(')');\n\n if (preExlm >= 0 && postClose >= 0) {\n const imageMarkdown = selectedLine.substring(preExlm, lineSelectionStart + postClose + 1);\n const { data } = await axios.post(markdownPreviewPath, { text: imageMarkdown });\n const parser = new DOMParser();\n\n const dom = parser.parseFromString(data.body, 'text/html');\n const imageURL = dom.body.querySelector('a').getAttribute('href');\n\n if (imageURL) {\n const filename = imageURL.substring(imageURL.lastIndexOf('/') + 1);\n\n return {\n imageMarkdown,\n imageURL,\n filename,\n };\n }\n }\n\n return null;\n};\n\nexport const repeatCodeBackticks = (content) => {\n const numBackticks =\n Math.max(2, content.match(/```+/g)?.sort((a, b) => b.length - a.length)[0]?.length || 0) + 1;\n return '`'.repeat(numBackticks);\n};\n","import $ from 'jquery';\nimport { flatten } from 'lodash';\nimport Vue from 'vue';\nimport { InternalEvents } from '~/tracking';\nimport { FIND_FILE_SHORTCUT_CLICK } from '~/tracking/constants';\nimport { Mousetrap, addStopCallback } from '~/lib/mousetrap';\nimport { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils';\nimport { waitForElement } from '~/lib/utils/dom_utils';\nimport findAndFollowLink from '~/lib/utils/navigation_utility';\nimport { refreshCurrentPage } from '~/lib/utils/url_utility';\nimport {\n keysFor,\n TOGGLE_KEYBOARD_SHORTCUTS_DIALOG,\n START_SEARCH,\n START_SEARCH_PROJECT_FILE,\n FOCUS_FILTER_BAR,\n TOGGLE_PERFORMANCE_BAR,\n HIDE_APPEARING_CONTENT,\n TOGGLE_CANARY,\n TOGGLE_MARKDOWN_PREVIEW,\n FIND_AND_REPLACE,\n GO_TO_YOUR_TODO_LIST,\n GO_TO_ACTIVITY_FEED,\n GO_TO_YOUR_ISSUES,\n GO_TO_YOUR_MERGE_REQUESTS,\n GO_TO_YOUR_PROJECTS,\n GO_TO_YOUR_GROUPS,\n GO_TO_MILESTONE_LIST,\n GO_TO_YOUR_SNIPPETS,\n GO_TO_YOUR_REVIEW_REQUESTS,\n} from './keybindings';\nimport { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';\n\n/**\n * The key used to save and fetch the local Mousetrap instance\n * attached to a `