index.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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>" +
  51. prism
  52. .highlight(text, prism.languages[lang], lang)
  53. .replace(/token /g, "hl-") +
  54. "</pre>"
  55. )[0].children;
  56. }
  57. node.attrs.class = "hl-pre";
  58. code.attrs.class = "hl-code";
  59. code.attrs.style = "display:block;overflow: auto;";
  60. if (config.showLanguageName) {
  61. node.children.push({
  62. name: "div",
  63. attrs: {
  64. class: "hl-language",
  65. style:
  66. "user-select:none;position:absolute;top:0;right:2px;font-size:10px;",
  67. },
  68. children: [
  69. {
  70. type: "text",
  71. text: lang,
  72. },
  73. ],
  74. });
  75. }
  76. if (config.copyByClickCode) {
  77. node.attrs.style += (node.attrs.style || "") + ";user-select:none";
  78. node.attrs["data-content"] = text;
  79. node.children.push({
  80. name: "div",
  81. attrs: {
  82. class: "hl-copy",
  83. style:
  84. "user-select:none;position:absolute;top:0;right:3px;font-size:10px;",
  85. },
  86. // children: [{
  87. // type: 'text',
  88. // text: '复制'
  89. // }]
  90. });
  91. vm.expose();
  92. }
  93. if (config.showLineNumber) {
  94. const line = text.split("\n").length;
  95. const children = [];
  96. for (let k = line; k--; ) {
  97. children.push({
  98. name: "span",
  99. attrs: {
  100. class: "span",
  101. },
  102. });
  103. }
  104. node.children.push({
  105. name: "span",
  106. attrs: {
  107. class: "line-numbers-rows",
  108. },
  109. children,
  110. });
  111. }
  112. }
  113. }
  114. };
  115. export default Highlight;