Comparing version 1.7.0 to 1.8.0
@@ -275,3 +275,5 @@ 'use strict'; | ||
if (!s) { | ||
this.r = this.g = this.b = l * 255; | ||
this.r = l * 255; | ||
this.g = this.r; | ||
this.b = this.r; | ||
} | ||
@@ -278,0 +280,0 @@ |
@@ -6,3 +6,3 @@ 'use strict'; | ||
const safeDecodeURI = (str) => { | ||
const safeDecodeURI = str => { | ||
try { | ||
@@ -15,3 +15,3 @@ return decodeURI(str); | ||
const decodeURL = (str) => { | ||
const decodeURL = str => { | ||
if (parse(str).protocol) { | ||
@@ -18,0 +18,0 @@ const parsed = new URL(str); |
@@ -6,3 +6,3 @@ 'use strict'; | ||
const safeDecodeURI = (str) => { | ||
const safeDecodeURI = str => { | ||
try { | ||
@@ -15,3 +15,3 @@ return decodeURI(str); | ||
const encodeURL = (str) => { | ||
const encodeURL = str => { | ||
if (parse(str).protocol) { | ||
@@ -18,0 +18,0 @@ const parsed = new URL(str); |
@@ -7,2 +7,5 @@ 'use strict'; | ||
const Cache = require('./cache'); | ||
const cache = new Cache(); | ||
function fullUrlForHelper(path = '/') { | ||
@@ -13,10 +16,2 @@ const pathRegex = /^(\/\/|http(s)?:)/; | ||
const { config } = this; | ||
const sitehost = parse(config.url).hostname || config.url; | ||
const data = new URL(path, `http://${sitehost}`); | ||
// Exit if input is an external link or a data url | ||
if (data.hostname !== sitehost || data.origin === 'null') return path; | ||
path = encodeURL(config.url + `/${path}`.replace(/\/{2,}/g, '/')); | ||
const prettyUrlsOptions = Object.assign({ | ||
@@ -27,7 +22,17 @@ trailing_index: true, | ||
path = prettyUrls(path, prettyUrlsOptions); | ||
// cacheId is designed to works across different hexo.config & options | ||
return cache.apply(`${config.url}-${prettyUrlsOptions.trailing_index}-${prettyUrlsOptions.trailing_html}-${path}`, () => { | ||
const sitehost = parse(config.url).hostname || config.url; | ||
const data = new URL(path, `http://${sitehost}`); | ||
return path; | ||
// Exit if input is an external link or a data url | ||
if (data.hostname !== sitehost || data.origin === 'null') return path; | ||
path = encodeURL(config.url + `/${path}`.replace(/\/{2,}/g, '/')); | ||
path = prettyUrls(path, prettyUrlsOptions); | ||
return path; | ||
}); | ||
} | ||
module.exports = fullUrlForHelper; |
@@ -6,2 +6,5 @@ 'use strict'; | ||
const Cache = require('./cache'); | ||
const cache = new Cache(); | ||
function md5(str) { | ||
@@ -16,3 +19,5 @@ return createHash('md5').update(str).digest('hex'); | ||
let str = `https://www.gravatar.com/avatar/${md5(email.toLowerCase())}`; | ||
const hash = cache.has(email) ? cache.get(email) : md5(email.toLowerCase()); | ||
let str = `https://www.gravatar.com/avatar/${hash}`; | ||
const qs = stringify(options); | ||
@@ -22,2 +27,4 @@ | ||
cache.set('email', hash); | ||
return str; | ||
@@ -24,0 +31,0 @@ } |
@@ -6,2 +6,3 @@ 'use strict'; | ||
const regexUrl = /(cite|download|href|src|url)$/i; | ||
const regexMeta = /^(og:|twitter:)(audio|image|url|video)(:secure_url)?$/i; | ||
@@ -13,3 +14,3 @@ function encSrcset(str) { | ||
subStr = subStr.trim(); | ||
str = str.replace(subStr, encodeURI(subStr)); | ||
str = str.replace(subStr, encodeURL(subStr)); | ||
} | ||
@@ -26,6 +27,8 @@ }); | ||
for (const i in attrs) { | ||
if (attrs[i] === null || typeof attrs[i] === 'undefined') result += ''; | ||
if (attrs[i] == null) result += ''; | ||
else { | ||
if (i.match(regexUrl)) result += ` ${escapeHTML(i)}="${encodeURL(attrs[i])}"`; | ||
else if (attrs[i] === true || i === attrs[i]) result += ` ${escapeHTML(i)}`; | ||
if (i.match(regexUrl) | ||
|| (tag === 'meta' && !attrs[i].match(regexMeta) && Object.values(attrs)[0].match(regexMeta))) { | ||
result += ` ${escapeHTML(i)}="${encodeURL(attrs[i])}"`; | ||
} else if (attrs[i] === true || i === attrs[i]) result += ` ${escapeHTML(i)}`; | ||
else if (i.match(/srcset$/i)) result += ` ${escapeHTML(i)}="${encSrcset(attrs[i])}"`; | ||
@@ -43,3 +46,3 @@ else result += ` ${escapeHTML(i)}="${escapeHTML(String(attrs[i]))}"`; | ||
if (text === null || typeof text === 'undefined') result += '>'; | ||
if (text == null) result += '>'; | ||
else result += `>${text}</${escapeHTML(tag)}>`; | ||
@@ -46,0 +49,0 @@ |
@@ -5,2 +5,3 @@ 'use strict'; | ||
exports.Cache = require('./cache'); | ||
exports.CacheStream = require('./cache_stream'); | ||
@@ -30,2 +31,3 @@ exports.camelCaseKeys = require('./camel_case_keys'); | ||
exports.stripHTML = require('./strip_html'); | ||
exports.tocObj = require('./toc_obj'); | ||
exports.truncate = require('./truncate'); | ||
@@ -32,0 +34,0 @@ exports.unescapeHTML = require('./unescape_html'); |
@@ -5,2 +5,5 @@ 'use strict'; | ||
const Cache = require('./cache'); | ||
const cache = new Cache(); | ||
/** | ||
@@ -17,25 +20,27 @@ * Check whether the link is external | ||
// handle relative url | ||
const data = new URL(input, `http://${sitehost}`); | ||
return cache.apply(`${input}-${sitehost}-${exclude}`, () => { | ||
// handle relative url | ||
const data = new URL(input, `http://${sitehost}`); | ||
// handle mailto: javascript: vbscript: and so on | ||
if (data.origin === 'null') return false; | ||
// handle mailto: javascript: vbscript: and so on | ||
if (data.origin === 'null') return false; | ||
const host = data.hostname; | ||
const host = data.hostname; | ||
if (exclude) { | ||
exclude = Array.isArray(exclude) ? exclude : [exclude]; | ||
if (exclude) { | ||
exclude = Array.isArray(exclude) ? exclude : [exclude]; | ||
if (exclude && exclude.length) { | ||
for (const i of exclude) { | ||
if (host === i) return false; | ||
if (exclude && exclude.length) { | ||
for (const i of exclude) { | ||
if (host === i) return false; | ||
} | ||
} | ||
} | ||
} | ||
if (host !== sitehost) return true; | ||
if (host !== sitehost) return true; | ||
return false; | ||
return false; | ||
}); | ||
} | ||
module.exports = isExternalLink; |
@@ -5,28 +5,33 @@ 'use strict'; | ||
const Cache = require('./cache'); | ||
const cache = new Cache(); | ||
function relativeUrlHelper(from = '', to = '') { | ||
const fromParts = from.split('/'); | ||
const toParts = to.split('/'); | ||
const length = Math.min(fromParts.length, toParts.length); | ||
let i = 0; | ||
return cache.apply(`${from}-${to}`, () => { | ||
const fromParts = from.split('/'); | ||
const toParts = to.split('/'); | ||
const length = Math.min(fromParts.length, toParts.length); | ||
let i = 0; | ||
for (; i < length; i++) { | ||
if (fromParts[i] !== toParts[i]) break; | ||
} | ||
for (; i < length; i++) { | ||
if (fromParts[i] !== toParts[i]) break; | ||
} | ||
let out = toParts.slice(i); | ||
let out = toParts.slice(i); | ||
for (let j = fromParts.length - i - 1; j > 0; j--) { | ||
out.unshift('..'); | ||
} | ||
for (let j = fromParts.length - i - 1; j > 0; j--) { | ||
out.unshift('..'); | ||
} | ||
const outLength = out.length; | ||
const outLength = out.length; | ||
// If the last 2 elements of `out` is empty strings, replace them with `index.html`. | ||
if (outLength > 1 && !out[outLength - 1] && !out[outLength - 2]) { | ||
out = out.slice(0, outLength - 2).concat('index.html'); | ||
} | ||
// If the last 2 elements of `out` is empty strings, replace them with `index.html`. | ||
if (outLength > 1 && !out[outLength - 1] && !out[outLength - 2]) { | ||
out = out.slice(0, outLength - 2).concat('index.html'); | ||
} | ||
return encodeURL(out.join('/').replace(/\/{2,}/g, '/')); | ||
return encodeURL(out.join('/').replace(/\/{2,}/g, '/')); | ||
}); | ||
} | ||
module.exports = relativeUrlHelper; |
@@ -16,3 +16,3 @@ 'use strict'; | ||
const unescapeHTML = (str) => { | ||
const unescapeHTML = str => { | ||
if (typeof str !== 'string') throw new TypeError('str must be a string!'); | ||
@@ -19,0 +19,0 @@ |
@@ -8,14 +8,8 @@ 'use strict'; | ||
const Cache = require('./cache'); | ||
const cache = new Cache(); | ||
function urlForHelper(path = '/', options) { | ||
const pathRegex = /^(#|\/\/|http(s)?:)/; | ||
if (pathRegex.test(path)) return path; | ||
const { config } = this; | ||
const { root } = config; | ||
const sitehost = parse(config.url).hostname || config.url; | ||
const data = new URL(path, `http://${sitehost}`); | ||
// Exit if input is an external link or a data url | ||
if (data.hostname !== sitehost || data.origin === 'null') return path; | ||
options = Object.assign({ | ||
@@ -30,5 +24,3 @@ relative: config.relative_link | ||
// Prepend root path | ||
path = encodeURL((root + path).replace(/\/{2,}/g, '/')); | ||
const { root } = config; | ||
const prettyUrlsOptions = Object.assign({ | ||
@@ -39,7 +31,26 @@ trailing_index: true, | ||
path = prettyUrls(path, prettyUrlsOptions); | ||
// cacheId is designed to works across different hexo.config & options | ||
return cache.apply(`${config.url}-${root}-${prettyUrlsOptions.trailing_index}-${prettyUrlsOptions.trailing_html}-${path}`, () => { | ||
const pathRegex = /^(#|\/\/|http(s)?:)/; | ||
if (pathRegex.test(path)) { | ||
return path; | ||
} | ||
return path; | ||
const sitehost = parse(config.url).hostname || config.url; | ||
const data = new URL(path, `http://${sitehost}`); | ||
// Exit if input is an external link or a data url | ||
if (data.hostname !== sitehost || data.origin === 'null') { | ||
return path; | ||
} | ||
// Prepend root path | ||
path = encodeURL((root + path).replace(/\/{2,}/g, '/')); | ||
path = prettyUrls(path, prettyUrlsOptions); | ||
return path; | ||
}); | ||
} | ||
module.exports = urlForHelper; |
{ | ||
"name": "hexo-util", | ||
"version": "1.7.0", | ||
"version": "1.8.0", | ||
"description": "Utilities for Hexo.", | ||
@@ -38,3 +38,3 @@ "main": "lib/index", | ||
"eslint": "^6.0.1", | ||
"eslint-config-hexo": "^3.0.0", | ||
"eslint-config-hexo": "^4.0.0", | ||
"html-entities": "^1.2.1", | ||
@@ -52,2 +52,3 @@ "html-tag-validator": "^1.5.0", | ||
"highlight.js": "^9.13.1", | ||
"htmlparser2": "^4.0.0", | ||
"punycode.js": "^2.1.0", | ||
@@ -54,0 +55,0 @@ "striptags": "^3.1.1" |
104
README.md
@@ -15,2 +15,3 @@ # hexo-util | ||
- [Usage](#usage) | ||
- [Cache](#cache) | ||
- [CacheStream](#cachestream) | ||
@@ -39,2 +40,3 @@ - [camelCaseKeys](#camelcasekeysobj-options) | ||
- [wordWrap](#wordwrapstr-options) | ||
- [tocObj](#tocobjstr-options) | ||
- [truncate](#truncatestr-options) | ||
@@ -57,2 +59,43 @@ - [unescapeHTML](#unescapehtmlstr) | ||
### Cache() | ||
A simple plain object cache | ||
``` js | ||
const cache = new Cache(); | ||
// set(key, value) | ||
cache.set('foo', 'bar'); | ||
// get(key) => value | ||
cache.get('foo'); | ||
// 'bar' | ||
// has(key) => Boolean | ||
cache.has('foo'); | ||
// true | ||
cache.has('bar'); | ||
// false | ||
// apply(key. value) | ||
cache.apply('baz', () => 123); | ||
// 123 | ||
cache.apply('baz', () => 456); | ||
// 123 | ||
cache.apply('qux', 456); | ||
// 456 | ||
cache.apply('qux', '789'); | ||
// 456 | ||
// del(key) | ||
cache.del('baz'); | ||
cache.has('baz'); | ||
// false | ||
// flush() | ||
cache.flush(); | ||
cache.has('foo'); | ||
// false | ||
``` | ||
### CacheStream() | ||
@@ -473,2 +516,63 @@ | ||
### tocObj(str, [options]) | ||
Generate a table of contents in JSON format based on the given html string. | ||
Option | Description | Default | ||
--- | --- | --- | ||
`min_depth` | The minimum level of TOC | 1 | ||
`max_depth` | The maximum level of TOC | 6 | ||
``` js | ||
const html = [ | ||
'<h1 id="title_1">Title 1</h1>', | ||
'<div id="title_1_1"><h2>Title 1.1</h2></div>', | ||
'<h3 id="title_1_1_1">Title 1.1.1</h3>', | ||
'<h2 id="title_1_2">Title 1.2</h2>', | ||
'<h2 id="title_1_3">Title 1.3</h2>', | ||
'<h3 id="title_1_3_1">Title 1.3.1</h3>', | ||
'<h1 id="title_2">Title 2</h1>', | ||
'<h2 id="title_2_1">Title 2.1</h2>' | ||
].join('\n'); | ||
tocObj(html); | ||
/* | ||
[ | ||
{ text: 'Title 1', id: 'title_1', level: 1 }, | ||
{ text: 'Title 1.1', id: 'title_1_1', level: 2 }, | ||
{ text: 'Title 1.1.1', id: 'title_1_1_1', level: 3 }, | ||
{ text: 'Title 1.2', id: 'title_1_2', level: 2 }, | ||
{ text: 'Title 1.3', id: 'title_1_3', level: 2 }, | ||
{ text: 'Title 1.3.1', id: 'title_1_3_1', level: 3 }, | ||
{ text: 'Title 2', id: 'title_2', level: 1 }, | ||
{ text: 'Title 2.1', id: 'title_2_1', level: 2 }, | ||
] | ||
*/ | ||
tocObj(html, { min_depth: 2 }); | ||
/* | ||
[ | ||
{ text: 'Title 1.1', id: 'title_1_1', level: 2 }, | ||
{ text: 'Title 1.1.1', id: 'title_1_1_1', level: 3 }, | ||
{ text: 'Title 1.2', id: 'title_1_2', level: 2 }, | ||
{ text: 'Title 1.3', id: 'title_1_3', level: 2 }, | ||
{ text: 'Title 1.3.1', id: 'title_1_3_1', level: 3 }, | ||
{ text: 'Title 2.1', id: 'title_2_1', level: 2 }, | ||
] | ||
*/ | ||
tocObj(html, { max_depth: 2 }); | ||
/* | ||
[ | ||
{ text: 'Title 1', id: 'title_1', level: 1 }, | ||
{ text: 'Title 1.1', id: 'title_1_1', level: 2 }, | ||
{ text: 'Title 1.2', id: 'title_1_2', level: 2 }, | ||
{ text: 'Title 1.3', id: 'title_1_3', level: 2 }, | ||
{ text: 'Title 2', id: 'title_2', level: 1 }, | ||
{ text: 'Title 2.1', id: 'title_2_1', level: 2 }, | ||
] | ||
*/ | ||
``` | ||
### truncate(str, [options]) | ||
@@ -475,0 +579,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
74589
34
1240
718
8
+ Addedhtmlparser2@^4.0.0
+ Addeddom-serializer@1.4.1(transitive)
+ Addeddomelementtype@2.3.0(transitive)
+ Addeddomhandler@3.3.04.3.1(transitive)
+ Addeddomutils@2.8.0(transitive)
+ Addedentities@2.2.0(transitive)
+ Addedhtmlparser2@4.1.0(transitive)