{"version":3,"sources":["webpack:///./blob/line_highlighter.js","webpack:///./blob/utils.js","webpack:///./blob/blob_fork_suggestion.js","webpack:///./pages/projects/init_blob.js","webpack:///./blob/blob_line_permalink_updater.js","webpack:///./behaviors/shortcuts/shortcuts_blob.js","webpack:///./blame/blame_redirect.js","webpack:///./pages/projects/blame/show/index.js","webpack:////build/source/ee/app/assets/javascripts/pages/projects/blame/show/index.js","webpack:///./repository/utils/title.js","webpack:////build/source/ee/app/assets/javascripts/pages/projects/shared/init_blob.js","webpack:////build/source/ee/app/assets/javascripts/path_locks.js"],"names":["LineHighlighter","options","highlightLineClass","fileHolderSelector","scrollFileHolder","hash","window","location","scrollBehavior","this","_hash","setHash","bind","highlightLine","clickHandler","highlightHash","bindEvents","prototype","_this","fileHolder","document","querySelector","addEventListener","e","target","newHash","scrollEnabled","range","clearHighlight","hashToRange","highlightRange","lineSelector","scrollToElement","offset","behavior","event","matches","preventDefault","lineNumber","parseInt","dataset","current","shiftKey","highlightedLines","getElementsByClassName","Array","from","forEach","line","classList","remove","match","length","lineElement","getElementById","add","results","ref","reverse","push","firstLineNumber","lastLineNumber","__setLocationHash__","value","history","pushState","url","title","blameLinesPerPage","_document$querySelect","blamePerPage","getPageParamValue","lineNum","page","Math","ceil","getPageSearchString","path","URL","getBaseURL","searchParams","set","search","moveToFilePermalink","fileBlobPermalinkUrlElement","permalink","getAttribute","urlIsDifferent","updateHistory","urlContainsSha","updateRefPortionOfTitle","getShaFromUrl","shortcircuitPermalinkButton","ctrlKey","metaKey","defaults","openButtons","forkButtons","cancelButtons","suggestionSections","actionTextPieces","BlobForkSuggestion","constructor","elementMap","onOpenButtonClick","onCancelButtonClick","init","$","on","showSuggestionSection","forkPath","action","removeClass","attr","text","hideSuggestionSection","addClass","currentTarget","destroy","off","BlobLinePermalinkUpdater","querySelectorAll","addShortcutsExtension","ShortcutsNavigation","ShortcutsBlob","lineNumberRe","blobContentHolder","lineNumberSelector","elementsToUpdate","updateBlameAndBlobPermalinkCb","setTimeout","linksToUpdate","getLocationHash","test","hashUrlString","concat","slice","call","permalinkButton","baseHref","originalHref","href","split","searchString","setAttribute","updateLineNumbersOnBlobPermalinks","shortcuts","PROJECT_FILES_GO_TO_PERMALINK","linesPerPage","perPage","params","URLSearchParams","currentPage","get","isPaginationDisabled","pageToRedirect","createAlert","message","__","setUrlParams","redirectToCorrectPage","initBlob","setTitle","pathMatch","project","replace","isEmpty","sha","doc","titleParts","join","dataEl","toggle_path","JSON","parse","innerHTML","async","state","confirmAction","sprintf","axios","post","then","reload","catch","initPathLocks"],"mappings":"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","file":"pages.projects.blame.show.6e00abf6.chunk.js","sourcesContent":["/* eslint-disable func-names, no-underscore-dangle, no-param-reassign, consistent-return */\n\nimport { scrollToElement } from '~/lib/utils/common_utils';\n\n// LineHighlighter\n//\n// Handles single- and multi-line selection and highlight for blob views.\n//\n//\n// ### Example Markup\n//\n// <div id=\"blob-content-holder\">\n// <div class=\"file-content\">\n// <div class=\"line-numbers\">\n// <a href=\"#L1\" id=\"L1\" data-line-number=\"1\">1</a>\n// <a href=\"#L2\" id=\"L2\" data-line-number=\"2\">2</a>\n// <a href=\"#L3\" id=\"L3\" data-line-number=\"3\">3</a>\n// <a href=\"#L4\" id=\"L4\" data-line-number=\"4\">4</a>\n// <a href=\"#L5\" id=\"L5\" data-line-number=\"5\">5</a>\n// </div>\n// <pre class=\"code highlight\">\n// <code>\n// <span id=\"LC1\" class=\"line\">...</span>\n// <span id=\"LC2\" class=\"line\">...</span>\n// <span id=\"LC3\" class=\"line\">...</span>\n// <span id=\"LC4\" class=\"line\">...</span>\n// <span id=\"LC5\" class=\"line\">...</span>\n// </code>\n// </pre>\n// </div>\n// </div>\n//\n\nconst LineHighlighter = function (options = {}) {\n options.highlightLineClass = options.highlightLineClass || 'hll';\n options.fileHolderSelector = options.fileHolderSelector || '.file-holder';\n options.scrollFileHolder = options.scrollFileHolder || false;\n options.hash = options.hash || window.location.hash;\n options.scrollBehavior = options.scrollBehavior || 'smooth';\n\n this.options = options;\n this._hash = options.hash;\n this.highlightLineClass = options.highlightLineClass;\n this.setHash = this.setHash.bind(this);\n this.highlightLine = this.highlightLine.bind(this);\n this.clickHandler = this.clickHandler.bind(this);\n this.highlightHash = this.highlightHash.bind(this);\n\n this.bindEvents();\n this.highlightHash();\n};\n\nLineHighlighter.prototype.bindEvents = function () {\n const fileHolder = document.querySelector(this.options.fileHolderSelector);\n if (fileHolder) {\n fileHolder.addEventListener('click', this.clickHandler);\n fileHolder.addEventListener('highlight:line', this.highlightHash);\n window.addEventListener('hashchange', (e) => this.highlightHash(e.target.location.hash));\n }\n};\n\nLineHighlighter.prototype.highlightHash = function (newHash, scrollEnabled = true) {\n let range;\n if (newHash && typeof newHash === 'string') this._hash = newHash;\n\n this.clearHighlight();\n\n if (this._hash !== '') {\n range = this.hashToRange(this._hash);\n if (range[0]) {\n this.highlightRange(range);\n const lineSelector = `#L${range[0]}`;\n\n if (scrollEnabled) {\n scrollToElement(lineSelector, {\n // Scroll to the first highlighted line on initial load\n // Add an offset of -100 for some context\n offset: -100,\n behavior: this.options.scrollBehavior,\n });\n }\n }\n }\n};\n\nLineHighlighter.prototype.clickHandler = function (event) {\n const isLine = event.target.matches('a[data-line-number]');\n if (isLine) {\n let range;\n event.preventDefault();\n this.clearHighlight();\n const lineNumber = parseInt(event.target.dataset.lineNumber, 10);\n const current = this.hashToRange(this._hash);\n if (!(current[0] && event.shiftKey)) {\n // If there's no current selection, or there is but Shift wasn't held,\n // treat this like a single-line selection.\n this.setHash(lineNumber);\n return this.highlightLine(lineNumber);\n }\n if (event.shiftKey) {\n if (lineNumber < current[0]) {\n range = [lineNumber, current[0]];\n } else {\n range = [current[0], lineNumber];\n }\n this.setHash(range[0], range[1]);\n return this.highlightRange(range);\n }\n }\n};\n\nLineHighlighter.prototype.clearHighlight = function () {\n const highlightedLines = document.getElementsByClassName(this.highlightLineClass);\n Array.from(highlightedLines).forEach(function (line) {\n line.classList.remove(this.highlightLineClass);\n }, this);\n};\n\n// Convert a URL hash String into line numbers\n//\n// hash - Hash String\n//\n// Examples:\n//\n// hashToRange('#L5') # => [5, null]\n// hashToRange('#L5-15') # => [5, 15]\n// hashToRange('#foo') # => [null, null]\n//\n// Returns an Array\nLineHighlighter.prototype.hashToRange = function (hash) {\n // ?L(\\d+)(?:-L?(\\d+))?$/)\n const matches = hash.match(/^#?L(\\d+)(?:-L?(\\d+))?$/);\n if (matches && matches.length) {\n const first = parseInt(matches[1], 10);\n const last = matches[2] ? parseInt(matches[2], 10) : null;\n return [first, last];\n }\n return [null, null];\n};\n\n// Highlight a single line\n//\n// lineNumber - Line number to highlight\nLineHighlighter.prototype.highlightLine = function (lineNumber) {\n const lineElement = document.getElementById(`LC${lineNumber}`);\n if (lineElement) {\n lineElement.classList.add(this.highlightLineClass);\n }\n};\n\n// Highlight all lines within a range\n//\n// range - Array containing the starting and ending line numbers\nLineHighlighter.prototype.highlightRange = function (range) {\n if (range[1]) {\n const results = [];\n const ref = range[0] <= range[1] ? range : range.reverse();\n\n for (let lineNumber = range[0]; lineNumber <= ref[1]; lineNumber += 1) {\n results.push(this.highlightLine(lineNumber));\n }\n\n return results;\n }\n return this.highlightLine(range[0]);\n};\n\n// Set the URL hash string\nLineHighlighter.prototype.setHash = function (firstLineNumber, lastLineNumber) {\n let hash;\n if (lastLineNumber) {\n hash = `#L${firstLineNumber}-${lastLineNumber}`;\n } else {\n hash = `#L${firstLineNumber}`;\n }\n this._hash = hash;\n return this.__setLocationHash__(hash);\n};\n\n// Make the actual hash change in the browser\n//\n// This method is stubbed in tests.\nLineHighlighter.prototype.__setLocationHash__ = function (value) {\n return window.history.pushState(\n {\n url: value,\n // We're using pushState instead of assigning location.hash directly to\n // prevent the page from scrolling on the hashchange event\n },\n document.title,\n value,\n );\n};\n\nexport default LineHighlighter;\n","import {\n getBaseURL,\n updateHistory,\n urlIsDifferent,\n urlContainsSha,\n getShaFromUrl,\n} from '~/lib/utils/url_utility';\nimport { updateRefPortionOfTitle } from '~/repository/utils/title';\n\nconst blameLinesPerPage = document.querySelector('.js-per-page')?.dataset?.blamePerPage;\n\nexport const getPageParamValue = (lineNum, blamePerPage = blameLinesPerPage) => {\n if (!blamePerPage) return '';\n const page = Math.ceil(parseInt(lineNum, 10) / parseInt(blamePerPage, 10));\n return page <= 1 ? '' : page;\n};\n\nexport const getPageSearchString = (path, page) => {\n if (!page) return '';\n const url = new URL(path, getBaseURL());\n url.searchParams.set('page', page);\n return url.search;\n};\n\nexport function moveToFilePermalink() {\n const fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url');\n const permalink = fileBlobPermalinkUrlElement?.getAttribute('href');\n\n if (!permalink) {\n return;\n }\n\n if (urlIsDifferent(permalink)) {\n updateHistory({\n url: permalink,\n title: document.title,\n });\n\n if (urlContainsSha({ url: permalink })) {\n updateRefPortionOfTitle(getShaFromUrl({ url: permalink }));\n }\n }\n}\n\nfunction eventHasModifierKeys(event) {\n // We ignore alt because I don't think alt clicks normally do anything special?\n return event.ctrlKey || event.metaKey || event.shiftKey;\n}\n\nexport function shortcircuitPermalinkButton() {\n const fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url');\n\n fileBlobPermalinkUrlElement?.addEventListener('click', (e) => {\n if (!eventHasModifierKeys(e)) {\n e.preventDefault();\n moveToFilePermalink();\n }\n });\n}\n\nexport default () => ({});\n","import $ from 'jquery';\n\nconst defaults = {\n // Buttons that will show the `suggestionSections`\n // has `data-fork-path`, and `data-action`\n openButtons: [],\n // Update the href(from `openButton` -> `data-fork-path`)\n // whenever a `openButton` is clicked\n forkButtons: [],\n // Buttons to hide the `suggestionSections`\n cancelButtons: [],\n // Section to show/hide\n suggestionSections: [],\n // Pieces of text that need updating depending on the action, `edit`, `replace`, `delete`\n actionTextPieces: [],\n};\n\nclass BlobForkSuggestion {\n constructor(options) {\n this.elementMap = { ...defaults, ...options };\n this.onOpenButtonClick = this.onOpenButtonClick.bind(this);\n this.onCancelButtonClick = this.onCancelButtonClick.bind(this);\n }\n\n init() {\n this.bindEvents();\n\n return this;\n }\n\n bindEvents() {\n $(this.elementMap.openButtons).on('click', this.onOpenButtonClick);\n $(this.elementMap.cancelButtons).on('click', this.onCancelButtonClick);\n }\n\n showSuggestionSection(forkPath, action = 'edit') {\n $(this.elementMap.suggestionSections).removeClass('hidden');\n $(this.elementMap.forkButtons).attr('href', forkPath);\n $(this.elementMap.actionTextPieces).text(action);\n }\n\n hideSuggestionSection() {\n $(this.elementMap.suggestionSections).addClass('hidden');\n }\n\n onOpenButtonClick(e) {\n const forkPath = $(e.currentTarget).attr('data-fork-path');\n const action = $(e.currentTarget).attr('data-action');\n this.showSuggestionSection(forkPath, action);\n }\n\n onCancelButtonClick() {\n this.hideSuggestionSection();\n }\n\n destroy() {\n $(this.elementMap.openButtons).off('click', this.onOpenButtonClick);\n $(this.elementMap.cancelButtons).off('click', this.onCancelButtonClick);\n }\n}\n\nexport default BlobForkSuggestion;\n","import { addShortcutsExtension } from '~/behaviors/shortcuts';\nimport ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob';\nimport { shortcircuitPermalinkButton } from '~/blob/utils';\nimport ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';\nimport BlobForkSuggestion from '~/blob/blob_fork_suggestion';\nimport BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';\nimport LineHighlighter from '~/blob/line_highlighter';\n\nexport default () => {\n new LineHighlighter(); // eslint-disable-line no-new\n\n // eslint-disable-next-line no-new\n new BlobLinePermalinkUpdater(\n document.querySelector('#blob-content-holder'),\n '.file-line-num[data-line-number], .file-line-num[data-line-number] *',\n document.querySelectorAll('.js-data-file-blob-permalink-url, .js-blob-blame-link'),\n );\n\n shortcircuitPermalinkButton();\n\n addShortcutsExtension(ShortcutsNavigation);\n addShortcutsExtension(ShortcutsBlob);\n\n new BlobForkSuggestion({\n openButtons: document.querySelectorAll('.js-edit-blob-link-fork-toggler'),\n forkButtons: document.querySelectorAll('.js-fork-suggestion-button'),\n cancelButtons: document.querySelectorAll('.js-cancel-fork-suggestion-button'),\n suggestionSections: document.querySelectorAll('.js-file-fork-suggestion-section'),\n actionTextPieces: document.querySelectorAll('.js-file-fork-suggestion-section-action'),\n }).init();\n};\n","import { getLocationHash } from '../lib/utils/url_utility';\nimport { getPageParamValue, getPageSearchString } from './utils';\n\nconst lineNumberRe = /^(L|LC)[0-9]+/;\n\nconst updateLineNumbersOnBlobPermalinks = (linksToUpdate) => {\n const hash = getLocationHash();\n if (hash && lineNumberRe.test(hash)) {\n const hashUrlString = `#${hash}`;\n\n [].concat(Array.prototype.slice.call(linksToUpdate)).forEach((permalinkButton) => {\n const baseHref =\n permalinkButton.dataset.originalHref ||\n (() => {\n const href = permalinkButton.getAttribute('href');\n // eslint-disable-next-line no-param-reassign\n permalinkButton.dataset.originalHref = href;\n return href;\n })();\n const lineNum = parseInt(hash.split('L')[1], 10);\n const page = getPageParamValue(lineNum);\n const searchString = getPageSearchString(baseHref, page);\n permalinkButton.setAttribute('href', `${baseHref}${searchString}${hashUrlString}`);\n });\n }\n};\n\nfunction BlobLinePermalinkUpdater(blobContentHolder, lineNumberSelector, elementsToUpdate) {\n if (!blobContentHolder) return;\n const updateBlameAndBlobPermalinkCb = () => {\n // Wait for the hash to update from the LineHighlighter callback\n setTimeout(() => {\n updateLineNumbersOnBlobPermalinks(elementsToUpdate);\n }, 0);\n };\n\n blobContentHolder.addEventListener('click', (e) => {\n if (e.target.matches(lineNumberSelector)) {\n updateBlameAndBlobPermalinkCb();\n }\n });\n updateBlameAndBlobPermalinkCb();\n}\n\nexport default BlobLinePermalinkUpdater;\n","import { PROJECT_FILES_GO_TO_PERMALINK } from '~/behaviors/shortcuts/keybindings';\nimport { moveToFilePermalink } from '~/blob/utils';\n\nexport default class ShortcutsBlob {\n constructor(shortcuts) {\n shortcuts.add(PROJECT_FILES_GO_TO_PERMALINK, moveToFilePermalink);\n }\n}\n","import { setUrlParams } from '~/lib/utils/url_utility';\nimport { createAlert } from '~/alert';\nimport { __ } from '~/locale';\n\nexport default function redirectToCorrectBlamePage() {\n const { hash } = window.location;\n const linesPerPage = parseInt(document.querySelector('.js-per-page').dataset.perPage, 10);\n const params = new URLSearchParams(window.location.search);\n const currentPage = parseInt(params.get('page'), 10);\n const isPaginationDisabled = params.get('no_pagination');\n if (hash && linesPerPage && !isPaginationDisabled) {\n const lineNumber = parseInt(hash.split('#L')[1], 10);\n const pageToRedirect = Math.ceil(lineNumber / linesPerPage);\n const isRedirectNeeded =\n (pageToRedirect > 1 && pageToRedirect !== currentPage) || pageToRedirect < currentPage;\n if (isRedirectNeeded) {\n createAlert({\n message: __('Please wait a few moments while we load the file history for this line.'),\n });\n window.location.href = setUrlParams({ page: pageToRedirect });\n }\n }\n}\n","import initBlob from '~/pages/projects/init_blob';\nimport redirectToCorrectPage from '~/blame/blame_redirect';\n\nredirectToCorrectPage();\ninitBlob();\n","import '~/pages/projects/blame/show/index';\nimport initBlob from '../../shared/init_blob';\n\ninitBlob();\n","const DEFAULT_TITLE = '· GitLab';\n\nexport const setTitle = (pathMatch, ref, project) => {\n if (!pathMatch) {\n document.title = `${project} ${DEFAULT_TITLE}`;\n return;\n }\n\n const path = pathMatch.replace(/^\\//, '');\n const isEmpty = path === '';\n\n /* eslint-disable-next-line @gitlab/require-i18n-strings */\n document.title = `${isEmpty ? 'Files' : path} · ${ref} · ${project} ${DEFAULT_TITLE}`;\n};\n\nexport function updateRefPortionOfTitle(sha, doc = document) {\n const { title = '' } = doc;\n const titleParts = title.split(' · ');\n\n if (titleParts.length > 1) {\n titleParts[1] = sha;\n\n /* eslint-disable-next-line no-param-reassign */\n doc.title = titleParts.join(' · ');\n }\n}\n","import initPathLocks from 'ee/path_locks';\n\nexport default () => {\n const dataEl = document.getElementById('js-file-lock');\n\n if (dataEl) {\n const { toggle_path, path } = JSON.parse(dataEl.innerHTML);\n\n initPathLocks(toggle_path, path);\n }\n};\n","import $ from 'jquery';\nimport { createAlert } from '~/alert';\nimport axios from '~/lib/utils/axios_utils';\nimport { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';\nimport { sprintf, __ } from '~/locale';\n\nexport default function initPathLocks(url, path) {\n $('a.path-lock').on('click', async (e) => {\n e.preventDefault();\n\n const { dataset } = e.target;\n const message =\n dataset.state === 'lock'\n ? __('Are you sure you want to lock %{path}?')\n : __('Are you sure you want to unlock %{path}?');\n\n const confirmed = await confirmAction(sprintf(message, { path }));\n if (!confirmed) {\n return;\n }\n\n axios\n .post(url, {\n path,\n })\n .then(() => {\n window.location.reload();\n })\n .catch(() =>\n createAlert({\n message: __('An error occurred while initializing path locks'),\n }),\n );\n });\n}\n"],"sourceRoot":""}