index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /**
  2. * @fileoverview highlight 插件
  3. * Include prismjs (https://prismjs.com)
  4. */
  5. import prism from './prism.min'
  6. import config from './config'
  7. import Parser from '../parser'
  8. function Highlight (vm) {
  9. this.vm = vm
  10. }
  11. Highlight.prototype.onParse = function (node, vm) {
  12. if (node.name === 'pre') {
  13. if (vm.options.editable) {
  14. node.attrs.class = (node.attrs.class || '') + ' hl-pre'
  15. return
  16. }
  17. let i
  18. for (i = node.children.length; i--;) {
  19. if (node.children[i].name === 'code') break
  20. }
  21. if (i === -1) return
  22. const code = node.children[i]
  23. let className = code.attrs.class + ' ' + node.attrs.class
  24. i = className.indexOf('language-')
  25. if (i === -1) {
  26. i = className.indexOf('lang-')
  27. if (i === -1) {
  28. className = 'language-text'
  29. i = 9
  30. } else {
  31. i += 5
  32. }
  33. } else {
  34. i += 9
  35. }
  36. let j
  37. for (j = i; j < className.length; j++) {
  38. if (className[j] === ' ') break
  39. }
  40. const lang = className.substring(i, j)
  41. if (code.children.length) {
  42. const text = this.vm.getText(code.children).replace(/&amp;/g, '&')
  43. if (!text) return
  44. if (node.c) {
  45. node.c = undefined
  46. }
  47. if (prism.languages[lang]) {
  48. code.children = (new Parser(this.vm).parse(
  49. // 加一层 pre 保留空白符
  50. '<pre>' + prism.highlight(text, prism.languages[lang], lang).replace(/token /g, 'hl-') + '</pre>'))[0].children
  51. }
  52. node.attrs.class = 'hl-pre'
  53. code.attrs.class = 'hl-code'
  54. code.attrs.style ='display:block;overflow: auto;'
  55. if (config.showLanguageName) {
  56. node.children.push({
  57. name: 'div',
  58. attrs: {
  59. class: 'hl-language',
  60. style: 'user-select:none;position:absolute;top:0;right:2px;font-size:10px;'
  61. },
  62. children: [{
  63. type: 'text',
  64. text: '复制 '
  65. },
  66. {
  67. type: 'text',
  68. text: lang
  69. }]
  70. })
  71. }
  72. if (config.copyByClickCode) {
  73. node.attrs.style += (node.attrs.style || '') + ';user-select:none;'
  74. node.attrs['data-content'] = text
  75. node.children.push({
  76. name: 'div',
  77. attrs: {
  78. class: 'hl-copy',
  79. style: 'user-select:none;position:absolute;top:0;right:3px;font-size:10px;'
  80. },
  81. // children: [{
  82. // type: 'text',
  83. // text: '复制'
  84. // }]
  85. })
  86. vm.expose()
  87. // console.log('vm',node,vm)
  88. }
  89. if (config.showLineNumber) {
  90. const line = text.split('\n').length; const children = []
  91. for (let k = line; k--;) {
  92. children.push({
  93. name: 'span',
  94. attrs: {
  95. class: 'span'
  96. }
  97. })
  98. }
  99. node.children.push({
  100. name: 'span',
  101. attrs: {
  102. class: 'line-numbers-rows'
  103. },
  104. children
  105. })
  106. }
  107. }
  108. }
  109. }
  110. export default Highlight