index.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * @fileoverview highlight 插件
  3. * Include prismjs (https://prismjs.com)
  4. */
  5. const prism = require('./prism.min')
  6. const config = require('./config')
  7. const Parser = require('../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. if (config.showLanguageName) {
  55. node.children.push({
  56. name: 'div',
  57. attrs: {
  58. class: 'hl-language',
  59. style: 'user-select:none'
  60. },
  61. children: [{
  62. type: 'text',
  63. text: lang
  64. }]
  65. })
  66. }
  67. if (config.copyByLongPress) {
  68. node.attrs.style += (node.attrs.style || '') + ';user-select:none'
  69. node.attrs['data-content'] = text
  70. vm.expose()
  71. }
  72. if (config.showLineNumber) {
  73. const line = text.split('\n').length; const children = []
  74. for (let k = line; k--;) {
  75. children.push({
  76. name: 'span',
  77. attrs: {
  78. class: 'span'
  79. }
  80. })
  81. }
  82. node.children.push({
  83. name: 'span',
  84. attrs: {
  85. class: 'line-numbers-rows'
  86. },
  87. children
  88. })
  89. }
  90. }
  91. }
  92. }
  93. module.exports = Highlight