Snippet.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <template>
  2. <div class="stack-main">
  3. <div class="stack-main-header">
  4. <div class="grid cols-auto gap-2 justify-start items-center">
  5. <ExceptionClass
  6. :name="selectedFrame.class || ''"
  7. :method="selectedFrame.method || ''"
  8. />
  9. </div>
  10. <FilePath
  11. v-if="selectedFrame.file"
  12. class="mt-1"
  13. :line-number="selectedFrame.line_number"
  14. :file="selectedFrame.file"
  15. :editable="true"
  16. ></FilePath>
  17. </div>
  18. <div class="stack-main-content">
  19. <div class="stack-viewer scrollbar">
  20. <div class="stack-ruler">
  21. <div class="stack-lines">
  22. <p
  23. v-for="(code, line_number) in selectedFrame.code_snippet"
  24. :key="line_number"
  25. class="stack-line cursor-pointer"
  26. :class="{
  27. 'stack-line-selected': withinSelectedRange(parseInt(line_number)),
  28. 'stack-line-highlight':
  29. parseInt(line_number) === selectedFrame.line_number,
  30. }"
  31. @click="handleLineNumberClick($event, parseInt(line_number))"
  32. >
  33. {{ line_number }}
  34. </p>
  35. </div>
  36. </div>
  37. <pre :class="highlightTheme" class="stack-code" ref="codeContainer"><p
  38. v-for="(code, line_number) in selectedFrame.code_snippet"
  39. :key="line_number"
  40. :class="{
  41. 'stack-code-line-highlight': parseInt(line_number) === selectedFrame.line_number,
  42. 'stack-code-line-selected': withinSelectedRange(parseInt(line_number)),
  43. }"
  44. class="stack-code-line"
  45. ><span v-html="highlightedCode(code)"></span><a :href="editorUrl(line_number)" class="editor-link"><Icon name="pencil" /></a></p>
  46. </pre>
  47. </div>
  48. </div>
  49. </div>
  50. </template>
  51. <script>
  52. import hljs from 'highlight.js/lib/core';
  53. hljs.registerLanguage('php', require('highlight.js/lib/languages/php'));
  54. import ExceptionClass from '../Shared/ExceptionClass.vue';
  55. import FilePath from '../Shared/FilePath.vue';
  56. import LineNumber from '../Shared/LineNumber.vue';
  57. import editorUrl from '../Shared/editorUrl';
  58. export default {
  59. inject: ['config'],
  60. props: {
  61. selectedFrame: { required: true },
  62. selectedRange: { default: [null, null] },
  63. },
  64. components: {
  65. ExceptionClass,
  66. FilePath,
  67. LineNumber,
  68. },
  69. data() {
  70. const mediaQuery = matchMedia('(prefers-color-scheme: dark)');
  71. return {
  72. mediaQuery,
  73. detectedTheme: mediaQuery.matches ? 'dark' : 'light',
  74. firstSelectedLineNumber: null,
  75. };
  76. },
  77. created() {
  78. this.highlightState = null;
  79. },
  80. watch: {
  81. selectedFrame() {
  82. this.highlightState = null;
  83. },
  84. },
  85. mounted() {
  86. this.mediaQuery.addEventListener('change', e => {
  87. this.detectedTheme = e.matches ? 'dark' : 'light';
  88. });
  89. },
  90. computed: {
  91. highlightTheme() {
  92. if (this.config.theme === 'auto') {
  93. return this.detectedTheme;
  94. }
  95. return this.config.theme;
  96. },
  97. },
  98. methods: {
  99. handleLineNumberClick(event, lineNumber) {
  100. if (event.shiftKey && this.firstSelectedLineNumber !== null) {
  101. this.$emit(
  102. 'select-range',
  103. [this.firstSelectedLineNumber, lineNumber].sort((a, b) => a - b),
  104. );
  105. } else {
  106. this.firstSelectedLineNumber = lineNumber;
  107. this.$emit('select-range', [lineNumber, lineNumber]);
  108. }
  109. },
  110. withinSelectedRange(lineNumber) {
  111. if (!this.selectedRange) {
  112. return false;
  113. }
  114. return lineNumber >= this.selectedRange[0] && lineNumber <= this.selectedRange[1];
  115. },
  116. editorUrl(lineNumber) {
  117. return editorUrl(this.config, this.selectedFrame.file, lineNumber);
  118. },
  119. highlightedCode(code) {
  120. const result = hljs.highlight('php', code || '', true, this.highlightState);
  121. this.highlightState = result.top;
  122. return result.value || '&nbsp;';
  123. },
  124. },
  125. };
  126. </script>