New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

hexo-renderer-marked

Package Overview
Dependencies
Maintainers
8
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hexo-renderer-marked - npm Package Compare versions

Comparing version 2.0.0 to 3.0.0

13

index.js

@@ -5,3 +5,3 @@ /* global hexo */

var renderer = require('./lib/renderer');
const renderer = require('./lib/renderer');

@@ -14,6 +14,13 @@ hexo.config.marked = Object.assign({

smartypants: true,
modifyAnchors: '',
modifyAnchors: 0,
autolink: true,
sanitizeUrl: false,
headerIds: true
headerIds: true,
// TODO: enable prependRoot by default in v3
prependRoot: false,
external_link: {
enable: false,
exclude: [],
nofollow: false
}
}, hexo.config.marked);

@@ -20,0 +27,0 @@

'use strict';
const marked = require('marked');
const stripIndent = require('strip-indent');
const { stripHTML, highlight, slugize } = require('hexo-util');
const { encodeURL, slugize, stripHTML, url_for, isExternalLink } = require('hexo-util');
const MarkedRenderer = marked.Renderer;
const { parse } = require('url');
function Renderer() {
MarkedRenderer.apply(this);
const anchorId = (str, transformOption) => {
return slugize(str.trim(), {transform: transformOption});
};
this._headingId = {};
}
class Renderer extends MarkedRenderer {
constructor() {
super();
this._headingId = {};
}
require('util').inherits(Renderer, MarkedRenderer);
// Add id attribute to headings
heading(text, level) {
if (!this.options.headerIds) {
return `<h${level}>${text}</h${level}>`;
}
const transformOption = this.options.modifyAnchors;
let id = anchorId(stripHTML(text), transformOption);
const headingId = this._headingId;
// Add id attribute to headings
Renderer.prototype.heading = function(text, level) {
if (!this.options.headerIds) {
return `<h${level}>${text}</h${level}>`;
}
// Add a number after id if repeated
if (headingId[id]) {
id += `-${headingId[id]++}`;
} else {
headingId[id] = 1;
}
const transformOption = this.options.modifyAnchors;
let id = anchorId(stripHTML(text), transformOption);
const headingId = this._headingId;
// Add a number after id if repeated
if (headingId[id]) {
id += `-${headingId[id]++}`;
} else {
headingId[id] = 1;
// add headerlink
return `<h${level} id="${id}"><a href="#${id}" class="headerlink" title="${stripHTML(text)}"></a>${text}</h${level}>`;
}
// add headerlink
return `<h${level} id="${id}"><a href="#${id}" class="headerlink" title="${stripHTML(text)}"></a>${text}</h${level}>`;
};
function anchorId(str, transformOption) {
return slugize(str.trim(), {transform: transformOption});
}
// Support AutoLink option
Renderer.prototype.link = function(href, title, text) {
if (this.options.sanitizeUrl) {
let prot;
try {
prot = decodeURIComponent(unescape(href))
.replace(/[^\w:]/g, '')
.toLowerCase();
} catch (e) {
return '';
// Support AutoLink option
link(href, title, text) {
const { options } = this;
const { external_link } = options;
if (options.sanitizeUrl) {
if (href.startsWith('javascript:') || href.startsWith('vbscript:') || href.startsWith('data:')) {
href = '';
}
}
if (!options.autolink && href === text && title == null) {
return href;
}
if (prot.startsWith('javascript:') || prot.startsWith('vbscript:') || prot.startsWith('data:')) {
return '';
let out = `<a href="${encodeURL(href)}"`;
if (title) {
out += ` title="${title}"`;
}
}
if (external_link) {
const target = ' target="_blank"';
const noopener = ' rel="noopener"';
const nofollowTag = ' rel="noopener external nofollow noreferrer"';
if (isExternalLink(href, options.config.url, external_link.exclude)) {
if (external_link.enable && external_link.nofollow) {
out += target + nofollowTag;
} else if (external_link.enable) {
out += target + noopener;
} else if (external_link.nofollow) {
out += nofollowTag;
}
}
}
if (!this.options.autolink && href === text && title == null) {
return href;
out += `>${text}</a>`;
return out;
}
let out = `<a href="${href}"`;
if (title) {
out += ` title="${title}"`;
// Support Basic Description Lists
paragraph(text) {
const dlTest = /(?:^|\s)(\S.+)<br>:\s+(\S.+)/;
const dl = '<dl><dt>$1</dt><dd>$2</dd></dl>';
if (dlTest.test(text)) {
return text.replace(dlTest, dl);
}
return `<p>${text}</p>\n`;
}
out += `>${text}</a>`;
return out;
};
// Prepend root to image path
image(href, title, text) {
const { options } = this;
// Support Basic Description Lists
Renderer.prototype.paragraph = text => {
const dlTest = /(?:^|\s)(\S.+)<br>:\s+(\S.+)/;
if (!parse(href).hostname && !options.config.relative_link
&& options.prependRoot) {
href = url_for.call(options, href);
}
const dl = '<dl><dt>$1</dt><dd>$2</dd></dl>';
let out = `<img src="${encodeURL(href)}"`;
if (text) out += ` alt="${text}"`;
if (title) out += ` title="${title}"`;
if (dlTest.test(text)) {
return text.replace(dlTest, dl);
out += '>';
return out;
}
}
return `<p>${text}</p>\n`;
};
marked.setOptions({
langPrefix: '',
highlight(code, lang) {
return highlight(stripIndent(code), {
lang,
gutter: false,
wrap: false
});
}
langPrefix: ''
});
module.exports = function(data, options) {
const siteCfg = Object.assign({}, {
config: {
url: this.config.url,
root: this.config.root,
relative_link: this.config.relative_link
}
});
// exec filter to extend renderer.
const renderer = new Renderer();
this.execFilterSync('marked:renderer', renderer, {context: this});
return marked(data.text, Object.assign({
renderer: new Renderer()
}, this.config.marked, options));
renderer
}, this.config.marked, options, siteCfg));
};
{
"name": "hexo-renderer-marked",
"version": "2.0.0",
"version": "3.0.0",
"description": "Markdown renderer plugin for Hexo",

@@ -31,17 +31,16 @@ "main": "index",

"dependencies": {
"hexo-util": "1.0.0",
"marked": "^0.7.0",
"strip-indent": "^3.0.0"
"hexo-util": "^2.1.0",
"marked": "^1.0.0"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^6.0.1",
"babel-eslint": "^10.0.1",
"eslint-config-hexo": "^3.0.0",
"mocha": "^6.1.4",
"nyc": "^14.1.1"
"eslint": "^7.2.0",
"eslint-config-hexo": "^4.1.0",
"hexo": "^4.2.0",
"mocha": "^8.0.1",
"nyc": "^15.0.0"
},
"engines": {
"node": ">=8.6.0"
"node": ">=10.13.0"
}
}

@@ -30,6 +30,11 @@ # hexo-renderer-marked

smartypants: true
modifyAnchors: ''
modifyAnchors: 0
autolink: true
sanitizeUrl: false
headerIds: true
prependRoot: false
external_link:
enable: false
exclude: []
nofollow: false
```

@@ -42,6 +47,18 @@

- **smartypants** - Use "smart" typograhic punctuation for things like quotes and dashes.
- **modifyAnchors** - Use for transform anchorIds. if `1` to lowerCase and if `2` to upperCase. **Must be integer**.
- **modifyAnchors** - Transform the anchorIds into lower case (`1`) or upper case (`2`).
- **autolink** - Enable autolink for URLs. E.g. `https://hexo.io` will become `<a href="https://hexo.io">https://hexo.io</a>`.
- **sanitizeUrl** - Remove URLs that start with `javascript:`, `vbscript:` and `data:`.
- **headerIds** - Insert header id, e.g. `<h1 id="value">text</h1>`. Useful for inserting anchor link to each paragraph with a heading.
- **prependRoot** - Prepend root value to (internal) image path.
* Example `_config.yml`:
``` yml
root: /blog/
```
* `![text](/path/to/image.jpg)` becomes `<img src="/blog/path/to/image.jpg" alt="text">`
- **external_link**
* **enable** - Open external links in a new tab.
* **exclude** - Exclude hostname. Specify subdomain when applicable, including `www`.
- Example: `[foo](http://bar.com)` becomes `<a href="http://bar.com" target="_blank" rel="noopener">foo</a>`
* **nofollow** - Add `rel="noopener external nofollow noreferrer"` to all external links for security, privacy and SEO. [Read more](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types). _This can be enabled regardless of `external_link.enable`_
- Example: `[foo](http://bar.com)` becomes `<a href="http://bar.com" rel="noopener external nofollow noreferrer">foo</a>`

@@ -61,3 +78,3 @@ ## Extras

will generate this html:
will generate this HTML:

@@ -92,4 +109,29 @@ ```html

### Extensibility
This plugin overrides some default behaviours of how [marked] plugin renders the markdown into html, to integrate with the Hexo ecosystem. It is possible to override this plugin too, without resorting to forking the whole thing.
For example, to override how heading like `# heading text` is rendered:
``` js
hexo.extend.filter.register('marked:renderer', function(renderer) {
const { config } = this; // Skip this line if you don't need user config from _config.yml
renderer.heading = function(text, level) {
// Default behaviour
// return `<h${level}>${text}</h${level}>`;
// outputs <h1>heading text</h1>
// If you want to insert custom class name
return `<h${level} class="headerlink">${text}</h${level}>`;
// outputs <h1 class="headerlink">heading text</h1>
}
})
```
Save the file in "scripts/" folder and run Hexo as usual.
Notice `renderer.heading = function (text, level) {` corresponds to [this line](https://github.com/hexojs/hexo-renderer-marked/blob/a93ebeb1e8cc11e754630c0a1506da9a1489b2b0/lib/renderer.js#L21). Refer to [renderer.js](https://github.com/hexojs/hexo-renderer-marked/blob/master/lib/renderer.js) on how this plugin overrides the default methods. For other methods not covered by this plugin, refer to marked's [documentation](https://marked.js.org/#/USING_PRO.md).
[Markdown]: https://daringfireball.net/projects/markdown/
[marked]: https://github.com/chjj/marked
[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/#def-list

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc