highlight.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /* global hexo */
  2. const Prism = require('node-prismjs')
  3. const { decode } = require('he')
  4. const { promisify } = require('util')
  5. const readFile = promisify(require('fs').readFile)
  6. const path = require('path')
  7. const regex = /<pre><code class="(.*)?">([\s\S]*?)<\/code><\/pre>/igm
  8. const captionRegex = /<p><code>(?![\s\S]*<code)(.*?)\s(.*?)\n([\s\S]*)<\/code><\/p>/igm
  9. /**
  10. * Code transform for prism plugin.
  11. * @param {Object} data
  12. * @return {Object}
  13. */
  14. function prismify (data) {
  15. // Patch for caption support
  16. if (captionRegex.test(data.content)) {
  17. // Attempt to parse the code
  18. data.content = data.content.replace(captionRegex, (origin, lang, caption, code) => {
  19. if (!lang || !caption || !code) return origin
  20. return `<figcaption>${caption}</figcaption><pre><code class="${lang}">${code}</code></pre>`
  21. })
  22. }
  23. function replace (lang, code) {
  24. const startTag = `<figure class="highlight ${lang}"><table><tr><td class="code"><pre>`
  25. const endTag = `</pre></td></tr></table></figure>`
  26. code = decode(code)
  27. let parsedCode = ''
  28. if (Prism.languages[lang]) {
  29. parsedCode = Prism.highlight(code, Prism.languages[lang])
  30. } else {
  31. parsedCode = code
  32. }
  33. return startTag + parsedCode + endTag
  34. }
  35. data.content = data.content.replace(regex, (origin, lang, code) => replace(lang, code))
  36. return data
  37. }
  38. function code (args, content) {
  39. let lang = ''
  40. if (args[0].startsWith('lang:')) {
  41. lang = args.shift().replace(/^lang:/, '')
  42. }
  43. return `<pre><code class="${lang}">${content}</code></pre>`
  44. }
  45. function includeCode (args) {
  46. let lang = ''
  47. if (args[0].startsWith('lang:')) {
  48. lang = args.shift().replace(/^lang:/, '')
  49. }
  50. const file = path.join(hexo.source_dir, hexo.config.code_dir, args.join(' '))
  51. return readFile(file, 'utf8')
  52. .then((code) => code.trim())
  53. .then((code) => `<pre><code class="${lang}">${code}</code></pre>`)
  54. }
  55. hexo.extend.filter.register('after_post_render', prismify)
  56. hexo.extend.tag.register('codeblock', code, true)
  57. hexo.extend.tag.register('include_code', includeCode, { async: true })