{"version":3,"sources":["webpack:///./code_navigation/utils/dom_utils.js","webpack:///./code_navigation/utils/index.js","webpack:///./vue_shared/components/source_viewer/source_viewer.vue","webpack:///./blob/blob_links_tracking.js","webpack:///./vue_shared/components/source_viewer/components/chunk.vue?a0a8","webpack:///vue_shared/components/source_viewer/components/chunk.vue","webpack:///./vue_shared/components/source_viewer/components/chunk.vue?2787","webpack:///./vue_shared/components/source_viewer/components/chunk.vue","webpack:///./vue_shared/components/source_viewer/source_viewer.vue?b684","webpack:///vue_shared/components/source_viewer/source_viewer.vue","webpack:///./vue_shared/components/source_viewer/source_viewer.vue?0240"],"names":["isTextNode","nodeType","createSpan","content","classList","span","document","createElement","innerText","wrapNodes","text","dataset","wrapper","innerHTML","replace","outerHTML","wrapSpacesWithSpans","childNodes","forEach","el","s1","textContent","s2","str","test","trim","newEl","Object","assign","replaceWith","wrapTextWithSpan","cachedData","Map","wrappedLines","WeakSet","getCurrentHoverElement","get","setCurrentHoverElement","set","addInteractionClass","path","d","wrapTextNodes","lineNumber","start_line","lines","querySelector","querySelectorAll","length","line","undefined","end_line","charCount","elm","add","find","start_char","charIndex","lineIndex","closest","deprecatedNodeUpdate","walker","createTreeWalker","NodeFilter","SHOW_TEXT","startCharIndex","currentNode","nextNode","end_char","textLength","startIndex","slice","eventsToTrack","selector","property","addBlobLinksTracking","containerEl","addEventListener","e","event","target","matches","Tracking","label","components","GlIntersectionObserver","directives","SafeHtml","props","isHighlighted","type","Boolean","required","chunkIndex","Number","default","rawContent","String","highlightedContent","totalLines","startingFrom","blamePath","blobPath","data","number","hasAppeared","computed","mapState","shouldHighlight","pageSearchString","page","getPageParamValue","getPageSearchString","codeStyling","_this$$refs$lineNumbe","marginLeft","$refs","lineNumbers","offsetWidth","watch","handler","newVal","_this$blobs","_this","blobs","addCodeNavigationClasses","codeNavigationDataWatcher","$watch","immediate","methods","handleChunkAppear","$emit","calculateLineNumber","index","_this2","$nextTick","keys","key","startLine","split","_vm","this","_c","_self","staticClass","_l","n","attrs","_v","_s","ref","on","name","rawName","value","expression","style","_m","domProps","Chunk","Blame","CodeownersValidation","mixins","mixin","blob","chunks","Array","showBlame","projectPath","currentRef","lineHighlighter","LineHighlighter","blameData","renderedChunks","blameInfo","reduce","result","blame","shouldRender","push","blameOffset","calculateBlameOffset","lineno","isCodeownersFile","CODEOWNERS_FILE_NAME","isVisible","toggleBlameClasses","requestBlameInfo","selectLine","mounted","created","handleAppear","_debounce","DEFAULT_DEBOUNCE_AND_THROTTLE_MS","track","EVENT_ACTION","EVENT_LABEL_VIEWER","language","handleOverlappingChunk","includes","_data$project","_blob$blame","chunk","$apollo","query","blameDataQuery","variables","fullPath","filePath","fromLine","toLine","project","repository","nodes","blameGroups","groups","isDuplicate","highlightHash","$route","hash","userColorScheme","window","gon","user_color_scheme","_e","class","$options"],"mappings":"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","file":"1337.5970ee2d.chunk.js","sourcesContent":["const TEXT_NODE = 3;\n\nconst isTextNode = ({ nodeType }) => nodeType === TEXT_NODE;\n\nconst isBlank = (str) => !str || /^\\s*$/.test(str);\n\nconst isMatch = (s1, s2) => !isBlank(s1) && s1.trim() === s2.trim();\n\nconst createSpan = (content, classList) => {\n  const span = document.createElement('span');\n  span.innerText = content;\n  span.classList = classList || '';\n  return span;\n};\n\nconst wrapSpacesWithSpans = (text) =>\n  text.replace(/ /g, createSpan(' ').outerHTML).replace(/\\t/g, createSpan('\t').outerHTML);\n\n// eslint-disable-next-line max-params\nconst wrapTextWithSpan = (el, text, classList, dataset) => {\n  if (isTextNode(el) && isMatch(el.textContent, text)) {\n    const newEl = createSpan(text.trim(), classList);\n    Object.assign(newEl.dataset, dataset);\n    el.replaceWith(newEl);\n  }\n};\n\nconst wrapNodes = (text, classList, dataset) => {\n  const wrapper = createSpan();\n  // eslint-disable-next-line no-unsanitized/property\n  wrapper.innerHTML = wrapSpacesWithSpans(text);\n  wrapper.childNodes.forEach((el) => wrapTextWithSpan(el, text, classList, dataset));\n  return wrapper.childNodes;\n};\n\nexport { wrapNodes, isTextNode };\n","import { wrapNodes, isTextNode } from './dom_utils';\n\nexport const cachedData = new Map();\n\nconst wrappedLines = new WeakSet();\n\nexport const getCurrentHoverElement = () => cachedData.get('current');\nexport const setCurrentHoverElement = (el) => cachedData.set('current', el);\n\nconst deprecatedNodeUpdate = ({ d, line, wrapTextNodes }) => {\n  let charCount = 0;\n\n  if (wrapTextNodes) {\n    line.childNodes.forEach((elm) => {\n      // Highlight.js does not wrap all text nodes by default\n      // We need all text nodes to be wrapped in order to append code nav attributes\n      elm.replaceWith(...wrapNodes(elm.textContent, elm.classList, elm.dataset));\n    });\n    wrappedLines.add(line);\n  }\n\n  const el = [...line.childNodes].find(({ textContent }) => {\n    if (charCount === d.start_char) return true;\n    charCount += textContent.length;\n    return false;\n  });\n\n  if (el && !isTextNode(el)) {\n    el.dataset.charIndex = d.start_char;\n    el.dataset.lineIndex = d.start_line;\n    el.classList.add('cursor-pointer', 'code-navigation', 'js-code-navigation');\n    el.closest('.line').classList.add('code-navigation-line');\n  }\n};\n\nexport const addInteractionClass = ({ path, d, wrapTextNodes }) => {\n  const lineNumber = d.start_line + 1;\n  const lines = document\n    .querySelector(`[data-path=\"${path}\"]`)\n    .querySelectorAll(`.blob-content #LC${lineNumber}, .line_content:not(.old) #LC${lineNumber}`);\n  if (!lines?.length) return;\n\n  lines.forEach((line) => {\n    if (d.end_line === undefined) {\n      // For old cached data we should use the old way of parsing\n      deprecatedNodeUpdate({ d, line, wrapTextNodes });\n    } else {\n      // For new data we can parse slightly differently\n      const walker = document.createTreeWalker(line, NodeFilter.SHOW_TEXT);\n      let startCharIndex = 0;\n      let currentNode = walker.nextNode();\n      while (currentNode) {\n        if (\n          d.start_char >= startCharIndex &&\n          d.end_char <= startCharIndex + currentNode.textContent.length\n        ) {\n          break;\n        }\n        startCharIndex += currentNode.textContent.length;\n        currentNode = walker.nextNode();\n      }\n\n      if (currentNode && d.start_char !== d.end_char) {\n        const text = currentNode.textContent;\n        const textLength = d.end_char - d.start_char;\n        const startIndex = d.start_char - startCharIndex;\n        const span = document.createElement('span');\n\n        span.textContent = text.slice(startIndex, startIndex + textLength);\n        span.dataset.charIndex = d.start_char;\n        span.dataset.lineIndex = d.start_line;\n        span.classList.add('gl-cursor-pointer', 'code-navigation', 'js-code-navigation');\n\n        currentNode.replaceWith(\n          text.slice(0, startIndex),\n          span,\n          text.slice(startIndex + textLength),\n        );\n\n        line.classList.add('code-navigation-line');\n      }\n    }\n  });\n};\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"gl-flex\"},[(_vm.showBlame && _vm.blameInfo.length)?_c('blame',{attrs:{\"blame-info\":_vm.blameInfo}}):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"file-content code js-syntax-highlight blob-content blob-viewer gl-flex gl-w-full gl-flex-col gl-overflow-auto\",class:_vm.$options.userColorScheme,attrs:{\"data-type\":\"simple\",\"data-path\":_vm.blob.path,\"data-testid\":\"blob-viewer-file-content\"}},[(_vm.isCodeownersFile)?_c('codeowners-validation',{staticClass:\"gl-text-default\",attrs:{\"current-ref\":_vm.currentRef,\"project-path\":_vm.projectPath,\"file-path\":_vm.blob.path}}):_vm._e(),_vm._v(\" \"),_vm._l((_vm.chunks),function(chunk,index){return _c('chunk',{key:index,attrs:{\"chunk-index\":index,\"is-highlighted\":Boolean(chunk.isHighlighted),\"raw-content\":chunk.rawContent,\"highlighted-content\":chunk.highlightedContent,\"total-lines\":chunk.totalLines,\"starting-from\":chunk.startingFrom,\"blame-path\":_vm.blob.blamePath,\"blob-path\":_vm.blob.path},on:{\"appear\":() => _vm.handleAppear(index)}})})],2)],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import Tracking from '~/tracking';\n\nconst eventsToTrack = [\n  { selector: '.file-line-blame', property: 'blame' },\n  { selector: '.file-line-num', property: 'link' },\n];\n\nfunction addBlobLinksTracking() {\n  const containerEl = document.querySelector('.file-holder');\n\n  if (!containerEl) {\n    return;\n  }\n\n  const eventName = 'click_link';\n  const label = 'file_line_action';\n\n  containerEl.addEventListener('click', (e) => {\n    eventsToTrack.forEach((event) => {\n      if (e.target.matches(event.selector)) {\n        Tracking.event(undefined, eventName, {\n          label,\n          property: event.property,\n        });\n      }\n    });\n  });\n}\n\nexport default addBlobLinksTracking;\n","import mod from \"-!../../../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./chunk.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./chunk.vue?vue&type=script&lang=js\"","<!-- eslint-disable vue/multi-word-component-names -->\n<script>\n// eslint-disable-next-line no-restricted-imports\nimport { mapState } from 'vuex';\nimport { GlIntersectionObserver } from '@gitlab/ui';\nimport SafeHtml from '~/vue_shared/directives/safe_html';\nimport { getPageParamValue, getPageSearchString } from '~/blob/utils';\nimport { addInteractionClass } from '~/code_navigation/utils';\n\n/*\n * We only highlight the chunk that is currently visible to the user.\n * By making use of the Intersection Observer API we can determine when a chunk becomes visible and highlight it accordingly.\n *\n * Content that is not visible to the user (i.e. not highlighted) does not need to look nice,\n * so by rendering raw (non-highlighted) text, the browser spends less resources on painting\n * content that is not immediately relevant.\n * Why use plaintext as opposed to hiding content entirely?\n * If content is hidden entirely, native find text (⌘ + F) won't work.\n */\nexport default {\n  components: {\n    GlIntersectionObserver,\n  },\n  directives: {\n    SafeHtml,\n  },\n  props: {\n    isHighlighted: {\n      type: Boolean,\n      required: true,\n    },\n    chunkIndex: {\n      type: Number,\n      required: false,\n      default: 0,\n    },\n    rawContent: {\n      type: String,\n      required: true,\n    },\n    highlightedContent: {\n      type: String,\n      required: true,\n    },\n    totalLines: {\n      type: Number,\n      required: false,\n      default: 0,\n    },\n    startingFrom: {\n      type: Number,\n      required: false,\n      default: 0,\n    },\n    blamePath: {\n      type: String,\n      required: true,\n    },\n    blobPath: {\n      type: String,\n      required: true,\n    },\n  },\n  data() {\n    return {\n      number: undefined,\n      hasAppeared: false,\n    };\n  },\n  computed: {\n    ...mapState(['data', 'blobs']),\n    shouldHighlight() {\n      return Boolean(this.highlightedContent) && (this.hasAppeared || this.isHighlighted);\n    },\n    pageSearchString() {\n      const page = getPageParamValue(this.number);\n      return getPageSearchString(this.blamePath, page);\n    },\n    codeStyling() {\n      const defaultGutterWidth = 96;\n      return { marginLeft: `${this.$refs.lineNumbers?.offsetWidth || defaultGutterWidth}px` };\n    },\n  },\n  watch: {\n    shouldHighlight: {\n      handler(newVal) {\n        if (!this.blobs?.length) return;\n\n        if (newVal) {\n          if (this.data) {\n            this.addCodeNavigationClasses();\n          } else {\n            // If there the code navigation hasn't loaded yet we need to watch\n            // for the data to be set in the state\n            this.codeNavigationDataWatcher = this.$watch('data', () => {\n              this.addCodeNavigationClasses();\n              this.codeNavigationDataWatcher();\n            });\n          }\n        }\n      },\n      immediate: true,\n    },\n  },\n  methods: {\n    handleChunkAppear() {\n      this.hasAppeared = true;\n      this.$emit('appear');\n    },\n    calculateLineNumber(index) {\n      return this.startingFrom + index + 1;\n    },\n    async addCodeNavigationClasses() {\n      await this.$nextTick();\n\n      Object.keys(this.data[this.blobPath]).forEach((key) => {\n        const startLine = Number(key.split(':')[0]);\n\n        if (startLine >= this.startingFrom && startLine < this.startingFrom + this.totalLines + 1) {\n          addInteractionClass({\n            path: this.blobPath,\n            d: this.data[this.blobPath][key],\n          });\n        }\n      });\n    },\n  },\n};\n</script>\n<template>\n  <div class=\"gl-flex\">\n    <div v-if=\"shouldHighlight\" class=\"gl-absolute gl-flex gl-flex-col\">\n      <div\n        v-for=\"(n, index) in totalLines\"\n        :key=\"index\"\n        data-testid=\"line-numbers\"\n        class=\"diff-line-num line-links line-numbers gl-border-r gl-z-3 gl-flex !gl-p-0\"\n      >\n        <a\n          class=\"file-line-blame gl-select-none !gl-shadow-none\"\n          data-event-tracking=\"click_chunk_blame_on_blob_page\"\n          :href=\"`${blamePath}${pageSearchString}#L${calculateLineNumber(index)}`\"\n        ></a>\n        <a\n          :id=\"`L${calculateLineNumber(index)}`\"\n          class=\"file-line-num gl-select-none !gl-shadow-none\"\n          :href=\"`#L${calculateLineNumber(index)}`\"\n          :data-line-number=\"calculateLineNumber(index)\"\n        >\n          {{ calculateLineNumber(index) }}\n        </a>\n      </div>\n    </div>\n\n    <div v-else ref=\"lineNumbers\" class=\"line-numbers gl-mr-3 !gl-p-0 gl-text-transparent\">\n      <!-- Placeholder for line numbers while content is not highlighted -->\n    </div>\n\n    <gl-intersection-observer class=\"gl-w-full\" @appear=\"handleChunkAppear\">\n      <pre\n        class=\"code highlight gl-m-0 gl-w-full !gl-overflow-visible !gl-border-none !gl-p-0 gl-leading-0\"\n      ><code v-if=\"shouldHighlight\" v-safe-html=\"highlightedContent\" :style=\"codeStyling\" data-testid=\"content\"></code><code v-else v-once class=\"line !gl-whitespace-pre-wrap gl-ml-1\" data-testid=\"content\" v-text=\"rawContent\"></code></pre>\n    </gl-intersection-observer>\n  </div>\n</template>\n","import { render, staticRenderFns } from \"./chunk.vue?vue&type=template&id=3313057a\"\nimport script from \"./chunk.vue?vue&type=script&lang=js\"\nexport * from \"./chunk.vue?vue&type=script&lang=js\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n  script,\n  render,\n  staticRenderFns,\n  false,\n  null,\n  null,\n  null\n  \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"gl-flex\"},[(_vm.shouldHighlight)?_c('div',{staticClass:\"gl-absolute gl-flex gl-flex-col\"},_vm._l((_vm.totalLines),function(n,index){return _c('div',{key:index,staticClass:\"diff-line-num line-links line-numbers gl-border-r gl-z-3 gl-flex !gl-p-0\",attrs:{\"data-testid\":\"line-numbers\"}},[_c('a',{staticClass:\"file-line-blame gl-select-none !gl-shadow-none\",attrs:{\"data-event-tracking\":\"click_chunk_blame_on_blob_page\",\"href\":`${_vm.blamePath}${_vm.pageSearchString}#L${_vm.calculateLineNumber(index)}`}}),_vm._v(\" \"),_c('a',{staticClass:\"file-line-num gl-select-none !gl-shadow-none\",attrs:{\"id\":`L${_vm.calculateLineNumber(index)}`,\"href\":`#L${_vm.calculateLineNumber(index)}`,\"data-line-number\":_vm.calculateLineNumber(index)}},[_vm._v(\"\\n        \"+_vm._s(_vm.calculateLineNumber(index))+\"\\n      \")])])}),0):_c('div',{ref:\"lineNumbers\",staticClass:\"line-numbers gl-mr-3 !gl-p-0 gl-text-transparent\"}),_vm._v(\" \"),_c('gl-intersection-observer',{staticClass:\"gl-w-full\",on:{\"appear\":_vm.handleChunkAppear}},[_c('pre',{staticClass:\"code highlight gl-m-0 gl-w-full !gl-overflow-visible !gl-border-none !gl-p-0 gl-leading-0\"},[(_vm.shouldHighlight)?_c('code',{directives:[{name:\"safe-html\",rawName:\"v-safe-html\",value:(_vm.highlightedContent),expression:\"highlightedContent\"}],style:(_vm.codeStyling),attrs:{\"data-testid\":\"content\"}}):_vm._m(0)])])],1)\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('code',{staticClass:\"line !gl-whitespace-pre-wrap gl-ml-1\",attrs:{\"data-testid\":\"content\"},domProps:{\"textContent\":_vm._s(_vm.rawContent)}})\n}]\n\nexport { render, staticRenderFns }","import mod from \"-!../../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./source_viewer.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../../../../node_modules/thread-loader/dist/cjs.js??ref--13-0!../../../../../../node_modules/babel-loader/lib/index.js??ref--13-1!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./source_viewer.vue?vue&type=script&lang=js\"","<script>\nimport { debounce } from 'lodash';\nimport { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';\nimport SafeHtml from '~/vue_shared/directives/safe_html';\nimport Tracking from '~/tracking';\nimport addBlobLinksTracking from '~/blob/blob_links_tracking';\nimport LineHighlighter from '~/blob/line_highlighter';\nimport { EVENT_ACTION, EVENT_LABEL_VIEWER, CODEOWNERS_FILE_NAME } from './constants';\nimport Chunk from './components/chunk.vue';\nimport Blame from './components/blame_info.vue';\nimport { calculateBlameOffset, shouldRender, toggleBlameClasses } from './utils';\nimport blameDataQuery from './queries/blame_data.query.graphql';\n\nexport default {\n  name: 'SourceViewer',\n  components: {\n    Chunk,\n    Blame,\n    CodeownersValidation: () => import('ee_component/blob/components/codeowners_validation.vue'),\n  },\n  directives: {\n    SafeHtml,\n  },\n  mixins: [Tracking.mixin()],\n  props: {\n    blob: {\n      type: Object,\n      required: true,\n    },\n    chunks: {\n      type: Array,\n      required: false,\n      default: () => [],\n    },\n    showBlame: {\n      type: Boolean,\n      required: false,\n      default: false,\n    },\n    projectPath: {\n      type: String,\n      required: true,\n    },\n    currentRef: {\n      type: String,\n      required: true,\n    },\n  },\n  data() {\n    return {\n      lineHighlighter: new LineHighlighter(),\n      blameData: [],\n      renderedChunks: [],\n    };\n  },\n  computed: {\n    blameInfo() {\n      return this.blameData.reduce((result, blame, index) => {\n        if (shouldRender(this.blameData, index)) {\n          result.push({\n            ...blame,\n            blameOffset: calculateBlameOffset(blame.lineno, index),\n          });\n        }\n\n        return result;\n      }, []);\n    },\n    isCodeownersFile() {\n      return this.blob.name === CODEOWNERS_FILE_NAME;\n    },\n  },\n  watch: {\n    showBlame: {\n      handler(isVisible) {\n        toggleBlameClasses(this.blameData, isVisible);\n        this.requestBlameInfo(this.renderedChunks[0]);\n      },\n      immediate: true,\n    },\n    blameData: {\n      handler(blameData) {\n        if (!this.showBlame) return;\n        toggleBlameClasses(blameData, true);\n      },\n      immediate: true,\n    },\n    chunks: {\n      handler() {\n        this.selectLine();\n      },\n    },\n  },\n  mounted() {\n    this.selectLine();\n  },\n  created() {\n    this.handleAppear = debounce(this.handleChunkAppear, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);\n    this.track(EVENT_ACTION, { label: EVENT_LABEL_VIEWER, property: this.blob.language });\n    addBlobLinksTracking();\n  },\n  methods: {\n    async handleChunkAppear(chunkIndex, handleOverlappingChunk = true) {\n      if (!this.renderedChunks.includes(chunkIndex)) {\n        this.renderedChunks.push(chunkIndex);\n        await this.requestBlameInfo(chunkIndex);\n\n        if (chunkIndex > 0 && handleOverlappingChunk) {\n          // request the blame information for overlapping chunk incase it is visible in the DOM\n          this.handleChunkAppear(chunkIndex - 1, false);\n        }\n      }\n    },\n    async requestBlameInfo(chunkIndex) {\n      const chunk = this.chunks[chunkIndex];\n      if (!this.showBlame || !chunk) return;\n\n      const { data } = await this.$apollo.query({\n        query: blameDataQuery,\n        variables: {\n          ref: this.currentRef,\n          fullPath: this.projectPath,\n          filePath: this.blob.path,\n          fromLine: chunk.startingFrom + 1,\n          toLine: chunk.startingFrom + chunk.totalLines,\n        },\n      });\n\n      const blob = data?.project?.repository?.blobs?.nodes[0];\n      const blameGroups = blob?.blame?.groups;\n      const isDuplicate = this.blameData.includes(blameGroups[0]);\n      if (blameGroups && !isDuplicate) this.blameData.push(...blameGroups);\n    },\n    async selectLine() {\n      await this.$nextTick();\n      this.lineHighlighter.highlightHash(this.$route.hash);\n    },\n  },\n  userColorScheme: window.gon.user_color_scheme,\n};\n</script>\n\n<template>\n  <div class=\"gl-flex\">\n    <blame v-if=\"showBlame && blameInfo.length\" :blame-info=\"blameInfo\" />\n\n    <div\n      class=\"file-content code js-syntax-highlight blob-content blob-viewer gl-flex gl-w-full gl-flex-col gl-overflow-auto\"\n      :class=\"$options.userColorScheme\"\n      data-type=\"simple\"\n      :data-path=\"blob.path\"\n      data-testid=\"blob-viewer-file-content\"\n    >\n      <codeowners-validation\n        v-if=\"isCodeownersFile\"\n        class=\"gl-text-default\"\n        :current-ref=\"currentRef\"\n        :project-path=\"projectPath\"\n        :file-path=\"blob.path\"\n      />\n      <chunk\n        v-for=\"(chunk, index) in chunks\"\n        :key=\"index\"\n        :chunk-index=\"index\"\n        :is-highlighted=\"Boolean(chunk.isHighlighted)\"\n        :raw-content=\"chunk.rawContent\"\n        :highlighted-content=\"chunk.highlightedContent\"\n        :total-lines=\"chunk.totalLines\"\n        :starting-from=\"chunk.startingFrom\"\n        :blame-path=\"blob.blamePath\"\n        :blob-path=\"blob.path\"\n        @appear=\"() => handleAppear(index)\"\n      />\n    </div>\n  </div>\n</template>\n","import { render, staticRenderFns } from \"./source_viewer.vue?vue&type=template&id=4ca5a803\"\nimport script from \"./source_viewer.vue?vue&type=script&lang=js\"\nexport * from \"./source_viewer.vue?vue&type=script&lang=js\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n  script,\n  render,\n  staticRenderFns,\n  false,\n  null,\n  null,\n  null\n  \n)\n\nexport default component.exports"],"sourceRoot":""}