renderer.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. 'use strict';
  2. var marked = require('marked');
  3. var assign = require('object-assign');
  4. var stripIndent = require('strip-indent');
  5. var util = require('hexo-util');
  6. var highlight = util.highlight;
  7. var stripHTML = util.stripHTML;
  8. var MarkedRenderer = marked.Renderer;
  9. function Renderer() {
  10. MarkedRenderer.apply(this);
  11. this._headingId = {};
  12. }
  13. require('util').inherits(Renderer, MarkedRenderer);
  14. // Support To-Do List
  15. Renderer.prototype.listitem = function(text) {
  16. var result;
  17. if (/^\s*\[[x ]\]\s*/.test(text)) {
  18. text = text.replace(/^\s*\[ \]\s*/, '<input type="checkbox"></input> ').replace(/^\s*\[x\]\s*/, '<input type="checkbox" checked></input> ');
  19. result = '<li style="list-style: none">' + text + '</li>\n';
  20. } else {
  21. result = '<li>' + text + '</li>\n';
  22. }
  23. return result;
  24. };
  25. // Add id attribute to headings
  26. Renderer.prototype.heading = function(text, level) {
  27. var transformOption = this.options.modifyAnchors;
  28. var id = anchorId(stripHTML(text), transformOption);
  29. var headingId = this._headingId;
  30. // Add a number after id if repeated
  31. if (headingId[id]) {
  32. id += '-' + headingId[id]++;
  33. } else {
  34. headingId[id] = 1;
  35. }
  36. // add headerlink
  37. return '<h' + level + ' id="' + id + '"><a href="#' + id + '" class="headerlink" title="' + stripHTML(text) + '"></a>' + text + '</h' + level + '>';
  38. };
  39. function anchorId(str, transformOption) {
  40. return util.slugize(str.trim(), {transform: transformOption});
  41. }
  42. // Support AutoLink option
  43. Renderer.prototype.link = function(href, title, text) {
  44. var prot;
  45. if (this.options.sanitize) {
  46. try {
  47. prot = decodeURIComponent(unescape(href))
  48. .replace(/[^\w:]/g, '')
  49. .toLowerCase();
  50. } catch (e) {
  51. return '';
  52. }
  53. if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
  54. return '';
  55. }
  56. }
  57. if (!this.options.autolink && href === text && title == null) {
  58. return href;
  59. }
  60. var out = '<a href="' + href + '"';
  61. if (title) {
  62. out += ' title="' + title + '"';
  63. }
  64. out += '>' + text + '</a>';
  65. return out;
  66. };
  67. marked.setOptions({
  68. langPrefix: '',
  69. highlight: function(code, lang) {
  70. return highlight(stripIndent(code), {
  71. lang: lang,
  72. gutter: false,
  73. wrap: false
  74. });
  75. }
  76. });
  77. module.exports = function(data, options) {
  78. return marked(data.text, assign({
  79. renderer: new Renderer()
  80. }, this.config.marked, options));
  81. };