Git Product home page Git Product logo

hexo-util's Introduction

hexo-util

Build Status NPM version Coverage Status

Utilities for Hexo.

Table of contents

Installation

$ npm install hexo-util --save

Usage

var util = require('hexo-util');

Cache()

A simple plain object cache

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

// size()
cache.size();
// 3

// dump()
cache.dump();
/*
{
  foo: 'bar',
  baz: 123,
  qux: 456
}
*/

// del(key)
cache.del('baz');
cache.has('baz');
// false

// flush()
cache.flush();
cache.has('foo');
// false
cache.size();
// 0

CacheStream()

Caches contents piped to the stream.

var stream = new CacheStream();

fs.createReadStream('/path/to/file').pipe(stream);

stream.on('finish', function(){
  // Read cache piped to the stream
  console.log(stream.getCache());

  // Destroy cache
  stream.destroy();
});

camelCaseKeys(obj, options)

Convert object keys to camelCase. Original keys will be converted to getter/setter and sync to the camelCase keys.

camelCaseKeys({
  foo_bar: 'test'
});
// { fooBar: 'test', foo_bar: 'test' }

createSha1Hash()

return SHA1 hash object. This is the same as calling createHash('utf8') in the node.js native module crypto.

const sha1 = createSha1Hash();
fs.createReadStream('/path/to/file')
 .pipe(sha1)
 .on('finish', () => {
   console.log(sha1.read());
 });

decodeURL(str)

Decode encoded URL or path. An alternative to the native decodeURI() function, with added ability to decode punycoded domain.

decodeURL('http://foo.com/b%C3%A1r')
// http://foo.com/bár

decodeURL('http://xn--br-mia.com/baz')
// http://bár.com/baz

decodeURL('/foo/b%C3%A1r/')
// /foo/bár/

/* Alternatively, Node 10+ offers native API to decode punycoded domain */
const {format} = require('url')
decodeURI(format(new URL('http://xn--br-mia.com.com/b%C3%A1r'), {unicode: true}))
// http://bár.com/báz

deepMerge(target, source)

Merges the enumerable properties of two objects deeply. target and source remain untouched.

// Merge deeply
const obj1 = {a: {b: 1, c: 1, d: {e: 1, f: 1}}};
const obj2 = {a: {b: 2, d: {f: 'f'} }};

deepMerge(obj1, obj2);
// {a: {b: 2, c: 1, d: {e: 1, f: 'f'} }}
// Arrays will be combined in the same property, similar to lodash.merge
const obj1 = { 'a': [{ 'b': 2 }, { 'd': 4 }] };
const obj2 = { 'a': [{ 'c': 3 }, { 'e': 5 }] };

deepMerge(obj1, obj2);
// { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] };

encodeURL(str)

Encode URL or path into a safe format.

encodeURL('http://foo.com/bár')
// http://foo.com/b%C3%A1r

encodeURL('/foo/bár/')
// /foo/b%C3%A1r/

escapeDiacritic(str)

Escapes diacritic characters in a string.

escapeHTML(str)

Escapes HTML entities in a string.

escapeHTML('<p>Hello "world".</p>')
// &lt;p&gt;Hello &quot;world&quot;.&lt;&#x2F;p&gt;

/* support escaped characters */
escapeHTML('&lt;foo>bar</foo&gt;')
// &lt;foo&gt;bar&lt;&#x2F;foo&gt;

escapeRegex(str)

Escapes special characters in a regular expression.

full_url_for(path)

Returns a url with the config.url prefixed. Output is encoded automatically. Requires bind(hexo).

_config.yml
url: https://example.com/blog # example
full_url_for('/a/path')
// https://example.com/blog/a/path

gravatar(str, [options])

Returns the gravatar image url from an email.

If you didn't specify the [options] parameter, the default options will apply. Otherwise, you can set it to a number which will then be passed on as the size parameter to Gravatar. Finally, if you set it to an object, it will be converted into a query string of parameters for Gravatar.

Option Description Default
s Output image size 80
d Default image
f Force default
r Rating

More info: Gravatar

gravatar('[email protected]')
// https://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787
gravatar('[email protected]', 40)
// https://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40
gravatar('[email protected]' {s: 40, d: 'https://via.placeholder.com/150'})
// https://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40&d=https%3A%2F%2Fvia.placeholder.com%2F150

hash(str)

Generates SHA1 hash.

hash('123456');
// <Buffer 7c 4a 8d 09 ca 37 62 af 61 e5 95 20 94 3d c2 64 94 f8 94 1b>

highlight(str, [options])

Syntax highlighting for a code block.

Option Description Default
gutter Whether to show line numbers true
wrap Whether to wrap the code block in <table> true
firstLine First line number 1
hljs Whether to use the hljs-* prefix for CSS classes false
lang Language
caption Caption
tab Replace tabs
autoDetect Detect language automatically (warning: slow)
Sublanguage highlight requires autoDetect to be enabled and lang to be unset
false
mark Line highlight specific line(s)
languageAttr Output code language into data-language attr false
stripIndent Whether to strip leading whitespace via strip-indent true

htmlTag(tag, attrs, text, escape)

Creates a html tag.

Option Description Default
tag Tag / element name
attrs Attribute(s) and its value.
Value is always escaped, URL is always encoded.
text Text, the value is always escaped
(except for <style> tag)
escape Whether to escape the text true
htmlTag('img', {src: 'example.png'})
// <img src="example.png">

htmlTag('a', {href: 'http://hexo.io/'}, 'Hexo')
// <a href="http://hexo.io/">Hexo</a>

htmlTag('link', {href: 'http://foo.com/'}, '<a>bar</a>')
// <a href="http://foo.com/">&lt;bar&gt;</a>

htmlTag('a', {href: 'http://foo.com/'}, '<b>bold</b>', false)
// <a href="http://foo.com/"><b>bold</b></a>

/* text value of <style> won't be escaped, url is still encoded */
htmlTag('style', {}, 'p { content: "<"; background: url("bár.jpg"); }')
// <style>p { content: "<"; background: url("b%C3%A1r.jpg"); }</style>

/* support script tag with async/defer */
htmlTag('script', {src: '/foo.js', async: true}, '')
// <script src="/foo.js" async></script>

isExternalLink(url, sitehost, [exclude])

Option Description Default
url The input URL.
sitehost The hostname / url of website. You can also pass hexo.config.url.
exclude Exclude hostnames. Specific subdomain is required when applicable, including www. []

Returns if a given url is external link relative to given sitehost and [exclude].

// 'sitehost' can be a domain or url
isExternalLink('https://example.com', 'example.com');
// false
isExternalLink('https://example.com', 'https://example.com');
// false
isExternalLink('https://example.com', '//example.com/blog/');
// false
isExternalLink('/archives/foo.html', 'example.com');
// false
isExternalLink('https://foo.com/', 'example.com');
// true
isExternalLink('https://foo.com', 'example.com', ['foo.com', 'bar.com']);
// false
isExternalLink('https://bar.com', 'example.com', ['foo.com', 'bar.com']);
// false
isExternalLink('https://baz.com/', 'example.com', ['foo.com', 'bar.com']);
// true

Pattern(rule)

Parses the string and tests if the string matches the rule. rule can be a string, a regular expression or a function.

var pattern = new Pattern('posts/:id');

pattern.match('posts/89');
// {0: 'posts/89', 1: '89', id: '89'}
var pattern = new Pattern('posts/*path');

pattern.match('posts/2013/hello-world');
// {0: 'posts/2013/hello-world', 1: '2013/hello-world', path: '2013/hello-world'}

Permalink(rule, [options])

Parses a permalink.

Option Description
segments Customize the rule of a segment in the permalink
var permalink = new Permalink(':year/:month/:day/:title', {
  segments: {
    year: /(\d{4})/,
    month: /(\d{2})/,
    day: /(\d{2})/
  }
});

permalink.parse('2014/01/31/test');
// {year: '2014', month: '01', day: '31', title: 'test'}

permalink.test('2014/01/31/test');
// true

permalink.stringify({year: '2014', month: '01', day: '31', title: 'test'})
// 2014/01/31/test

prettyUrls(url, [options])

Rewrite urls to pretty URLs.

Option Description Default
trailing_index /about/index.html -> /about/ when false true
trailing_html /about.html -> /about when false true

Note: trailing_html ignores any link with a trailing index.html. (will not be rewritten to index).

prettyUrls('/foo/bar.html');
// /foo/bar.html
prettyUrls('/foo/bar/index.html');
// /foo/bar/index.html

prettyUrls('/foo/bar.html', { trailing_index: false });
// /foo/bar.html
prettyUrls('/foo/bar/index.html', { trailing_index: false });
// /foo/bar/

prettyUrls('/foo/bar.html', { trailing_html: false });
// /foo/bar
prettyUrls('/foo/bar/index.html', { trailing_html: false });
// /foo/bar/index.html

prettyUrls('/foo/bar.html', { trailing_index: false, trailing_html: false });
// /foo/bar
prettyUrls('/foo/bar/index.html', { trailing_index: false, trailing_html: false });
// /foo/bar/

prismHighlight(str, [options])

Syntax highlighting for a code block using PrismJS.

Option Description Default
lineNumber Whether to show line numbers true
lang Language 'none'
tab Replace tabs
isPreprocess Enable preprocess or not true
mark Highlight specific line
firstLine First line number
caption Caption
stripIndent Whether to strip leading whitespace via strip-indent true

When isPreprocess is enabled, prismHighlight() will return PrismJS processed HTML snippet. Otherwise str will only be escaped and prismHighlight() will return the HTML snippet that is suitable for prism.js working in the Browser.

mark and firstLine options will have effect only when isPreprocess is disabled.

relative_url(from, to)

Returns the relative URL from from to to. Output is encoded automatically. Requires bind(hexo).

relative_url('foo/bar/', 'css/style.css')
// ../../css/style.css

slugize(str, [options])

Transforms a string into a clean URL-friendly string.

Option Description Default
separator Separator -
transform Transform the string into lower case (1) or upper case (2)
slugize('Hello World') = 'Hello-World'
slugize('Hellô Wòrld') = 'Hello-World'
slugize('Hello World', {separator: '_'}) = 'Hello_World'
slugize('Hello World', {transform: 1}) = 'hello-world'
slugize('Hello World', {transform: 2}) = 'HELLO-WORLD'

spawn(command, [args], [options])

Launches a new process with the given command. This method returns a promise.

Option Description Default
cwd Current working directory of the child process
env Environment key-value pairs
stdio Child's stdio configuration pipe
detached The child will be a process group leader
uid Sets the user identity of the process
gid Sets the group identity of the process
verbose Display messages on the console false
encoding Sets the encoding of the output string utf8

More info: child_process.spawn()

spawn('cat', 'test.txt').then((content) => {
  console.log(content);
});

// $ cd "/target/folder"
// $ cat "foo.txt" "bar.txt"
spawn('cat', ['foo.txt', 'bar.txt'], { cwd: '/target/folder' }).then((content) => {
  console.log(content);
});

stripHTML(str)

Removes HTML tags in a string.

stripIndent(str)

Strip leading whitespace from each line in a string. The line with the least number of leading whitespace, ignoring empty lines, determines the number to remove. Useful for removing redundant indentation.

wordWrap(str, [options])

Wraps the string no longer than line width. This method breaks on the first whitespace character that does not exceed line width.

Option Description Default
width Line width 80
wordWrap('Once upon a time')
// Once upon a time

wordWrap('Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding a successor to the throne turned out to be more trouble than anyone could have imagined...')
// Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding\na successor to the throne turned out to be more trouble than anyone could have\nimagined...

wordWrap('Once upon a time', {width: 8})
// Once\nupon a\ntime

wordWrap('Once upon a time', {width: 1})
// Once\nupon\na\ntime

tocObj(str, [options])

Generate a table of contents in JSON format based on the given html string. Headings with attribute data-toc-unnumbered="true" will be marked as unnumbered.

Option Description Default
min_depth The minimum level of TOC 1
max_depth The maximum level of TOC 6
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 },
]
*/

tocObj('<h1 id="reference" data-toc-unnumbered="true">Reference</h1>')
/*
[
  { text: 'Reference', id: 'reference', level: 1, unnumbered: true }
]
*/

truncate(str, [options])

Truncates a given text after a given length if text is longer than length. The last characters will be replaced with the omission option for a total length not exceeding length.

Option Description Default
length Max length of the string 30
omission Omission text ...
separator truncate text at a natural break
truncate('Once upon a time in a world far far away')
// "Once upon a time in a world..."

truncate('Once upon a time in a world far far away', {length: 17})
// "Once upon a ti..."

truncate('Once upon a time in a world far far away', {length: 17, separator: ' '})
// "Once upon a..."

truncate('And they found that many people were sleeping better.', {length: 25, omission: '... (continued)'})
// "And they f... (continued)"

unescapeHTML(str)

Unescapes HTML entities in a string.

unescapeHTML('&lt;p&gt;Hello &quot;world&quot;.&lt;&#x2F;p&gt;')
// <p>Hello "world".</p>

url_for(path, [option])

Returns a url with the root path prefixed. Output is encoded automatically. Requires bind(hexo).

Option Description Default
relative Output relative link Value of config.relative_link
_config.yml
root: /blog/ # example
url_for('/a/path')
// /blog/a/path

Relative link, follows relative_link option by default e.g. post/page path is '/foo/bar/index.html'

_config.yml
relative_link: true
url_for('/css/style.css')
// ../../css/style.css

/* Override option
 * you could also disable it to output a non-relative link,
 * even when `relative_link` is enabled and vice versa.
 */
url_for('/css/style.css', {relative: false})
// /css/style.css

bind(hexo)

Following utilities require bind(hexo) / bind(this) / call(hexo, input) / call(this, input) to parse the user config when initializing:

Below examples demonstrate different approaches to creating a helper (each example is separated by /******/),

// Single function
const url_for = require('hexo-util').url_for.bind(hexo);

hexo.extend.helper.register('test_url', (str) => {
  return url_for(str);
})


/******/
// Multiple functions
const url_for = require('hexo-util').url_for.bind(hexo)

function testurlHelper(str) {
  return url_for(str);
}

hexo.extend.helper.register('test_url', testurlHelper);


/******/
// Functions separated into different files.
// test_url.js
module.exports = function(str) {
  const url_for = require('hexo-util').url_for.bind(this);
  return url_for(str);
}

// index.js
hexo.extend.helper.register('test_url', require('./test_url'));


/******/
// Function.call() approach also works
const {url_for} = require('hexo-util');
module.exports = function(str) {
  return url_for.call(this, str);
}

hexo.extend.helper.register('test_url', require('./test_url'));


/******/
// Separating functions into individual files
// Each file has multiple functions
// test_url.js
function testurlHelper(str) {
  const url_for = require('hexo-util').url_for.bind(this);
  return url_for(str);
}

module.exports =  {
  testurlHelper: testurlHelper
}

// index.js
hexo.extend.helper.register('test_url', require('./test_url').testurlHelper);

License

MIT

hexo-util's People

Contributors

alxbl avatar curbengh avatar d-sketon avatar dailyrandomphoto avatar demurgos avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar dimaslanjaka avatar greg-js avatar hcoona avatar imaginezz avatar jlhwung avatar kentaroutakeda avatar l-vo avatar leesei avatar liby avatar lzjqsdd avatar noahdragon avatar ppwwyyxx avatar seaoak avatar segayuu avatar stevenjoezhang avatar sukkaw avatar tomap avatar tommy351 avatar uiolee avatar xaviju avatar yoshinorin avatar zkqiang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hexo-util's Issues

stripHTML() undefined

Possibly unhandled TypeError: c:\gh\celsomiranda.github.io\themes\hexlog\layout\index.jade:25
    23|           .post-content
    24|             != truncate(article.content, {length: 186, omission: '&hellip;', separator: ' '}
)
  > 25|             p=stripHTML(article.content)
    26|
    27|         footer.post-footer
    28|           a(href=config.root + article.path).more= __('index.more')

undefined is not a function
    at jade_debug.unshift.lineno (eval at <anonymous> (c:\gh\celsomiranda.github.io\node_modules\hex
o-renderer-jade\node_modules\jade\lib\index.js:218:8), <anonymous>:402:54)
    at eval (eval at <anonymous> (c:\gh\celsomiranda.github.io\node_modules\hexo-renderer-jade\node_
modules\jade\lib\index.js:218:8), <anonymous>:538:4)
    at eval (eval at <anonymous> (c:\gh\celsomiranda.github.io\node_modules\hexo-renderer-jade\node_
modules\jade\lib\index.js:218:8), <anonymous>:609:22)
    at res (c:\gh\celsomiranda.github.io\node_modules\hexo-renderer-jade\node_modules\jade\lib\index
.js:219:38)
    at Hexo.<anonymous> (c:\gh\celsomiranda.github.io\node_modules\hexo-renderer-jade\index.js:4:56)

    at Hexo.tryCatcher (c:\Users\celso_000\AppData\Roaming\npm\node_modules\hexo\node_modules\bluebi
rd\js\main\util.js:24:31)
    at Hexo.<anonymous> (c:\Users\celso_000\AppData\Roaming\npm\node_modules\hexo\node_modules\blueb
ird\js\main\method.js:15:34)
    at Promise.then.then.output (c:\Users\celso_000\AppData\Roaming\npm\node_modules\hexo\lib\hexo\r
ender.js:51:21)
    at tryCatcher (c:\Users\celso_000\AppData\Roaming\npm\node_modules\hexo\node_modules\bluebird\js
\main\util.js:24:31)
    at Promise._settlePromiseFromHandler (c:\Users\celso_000\AppData\Roaming\npm\node_modules\hexo\n
ode_modules\bluebird\js\main\promise.js:466:31)
    at Promise._settlePromiseAt (c:\Users\celso_000\AppData\Roaming\npm\node_modules\hexo\node_modul
es\bluebird\js\main\promise.js:545:18)
    at Promise._settlePromiseAtPostResolution (c:\Users\celso_000\AppData\Roaming\npm\node_modules\h
exo\node_modules\bluebird\js\main\promise.js:229:10)
    at Async._drainQueue (c:\Users\celso_000\AppData\Roaming\npm\node_modules\hexo\node_modules\blue
bird\js\main\async.js:84:12)
    at Async._drainQueues (c:\Users\celso_000\AppData\Roaming\npm\node_modules\hexo\node_modules\blu
ebird\js\main\async.js:89:10)
    at Async.drainQueues (c:\Users\celso_000\AppData\Roaming\npm\node_modules\hexo\node_modules\blue
bird\js\main\async.js:14:14)
    at process._tickCallback (node.js:442:13)

tocObj Issues

When contents likes this

<h2><span id="title_1">title 1</span></h2>

tocObj won't parse the correct id, So I edit the getId function, then work.

const getId = ele => {
  const { id } = ele.attribs;
  const { children } = ele;
  return id || (!children[0] ? null : getId(children[0]));
};

Highlighting breaks multiline statements

Say we have a code block in a language that supports multiline comments or strings, such as Coffeescript:

myFunc """
  This is a
  string that
  spans multiple
  lines.
"""

Hexo will render the following html:

<figure class="highlight coffeescript">
  <table>
    <tbody>
      <tr>
        <td class="code">
          <pre>
            <span class="line">myFunc <span class="string">"""</span><br>
            <span class="line">  This is a</span><br>
            <span class="line">  string that</span><br>
            <span class="line">  spans multiple</span><br>
            <span class="line">  lines.</span><br>
            <span class="line">"""</span></span><br>
          </pre>
        </td>
      </tr>
    </tbody>
  </table>
</figure>

This seems to prevent hljs from properly inserting <span> elements. I'll admit I don't understand what this line, which adds the .line spans, is supposed to accomplish (ie, why do we want each line wrapped in its own span in the first place), but it's doing it in a naive way that doesn't account for existing span elements that span more than one line. What it should produce is:

<figure class="highlight coffeescript">
  <table>
    <tbody>
      <tr>
        <td class="code">
          <pre>
            <span class="line">myFunc <span class="string">"""</span></span><br>
            <span class="line string">  This is a</span><br>
            <span class="line string">  string that</span><br>
            <span class="line string">  spans multiple</span><br>
            <span class="line string">  lines.</span><br>
            <span class="line string">"""</span><br>
          </pre>
        </td>
      </tr>
    </tbody>
  </table>
</figure>

...which would be correctly highlighted.

`highlight.js` generates no HTML class name when "wrap: false" and "hljs: false"

This issue is the behavior of lib/highlight.js.

In case of wrap: false:
If hljs: true, an HTML class name hljs appears in the output.
If hljs: false, no HTML class name appears in the output.

It is a lack of consistency.

I think an HTML class name highlight should appear as well as when wrap: true.

And also, the output for hljs: false lacks a PRE element and a CODE element.
That is, no HTML element appears around the output.
It is a lack of consistency, too.

Expected behavior

The output of util.highlight('alert("foobar")', {wrap: false}) is:

<pre><code class="highlight">alert(&quot;foobar&quot;)</code></pre>

Actual behavior

alert(&quot;foobar&quot;)

How to reproduce?

$ node
> const util = require('.')
undefined
> util.highlight('alert("foobar")', {wrap: false})
'alert(&quot;foobar&quot;)'
> util.highlight('alert("foobar")', {wrap: false, hljs: true})
'<pre><code class="hljs undefined">alert(&quot;foobar&quot;)</code></pre>'
>

Environment & Settings

$ node -v
v8.16.2

$ npm -v
6.4.1

$ git log --oneline --decorate -1
b292332 (HEAD -> master, upstream/master, origin/master, origin/HEAD) Merge pull request #109 from curbengh/toc

can't install hexo-util on ubuntu

Here is the log

8839 error Linux 4.4.0-57-generic
8840 error argv "/usr/bin/nodejs" "/usr/bin/npm" "install" "-g" "hexo-cli"
8841 error node v4.2.6
8842 error npm  v3.5.2
8843 error code ELIFECYCLE
8844 error [email protected] postinstall: `npm run build:highlight`
8844 error Exit status 1
8845 error Failed at the [email protected] postinstall script 'npm run build:highlight'.
8845 error Make sure you have the latest version of node.js and npm installed.
8845 error If you do, this is most likely a problem with the hexo-util package,
8845 error not with npm itself.
8845 error Tell the author that this fails on your system:
8845 error     npm run build:highlight
8845 error You can get information on how to open an issue for this project with:
8845 error     npm bugs hexo-util
8845 error Or if that isn't available, you can get their info via:
8845 error     npm owner ls hexo-util
8845 error There is likely additional logging output above.

Setting highlight: gutter to false in the config doesn't work

Disabling the gutter should make it so that highlightjs doesn't include line numbers.
The highlightUtil function expects a string of 'gutter':

var gutter = options.hasOwnProperty('gutter') ? options.gutter : true;

But even when you disable it in the config it somehow doesn't work. Changing other settings like hljs work just fine, but gutter won't.

highlight:
  hljs: true
  gutter: false

Not sure why the config remembers some settings like hljs but not gutter. Right now I have to go into node_modules and find this file and manually set gutter to false in order to get rid of it.

Add mark support to highlight()

When writing codes, sometimes we'll need to highlight some lines like:

selection_035

As for how to specify the lines, we could follow octpress' rules, i.e.

mark:#,#-# - Mark one or more lines of code with the class name "marked". Accepts one number, numbers separated by commas, and number ranges. Example mark:1,5-8 will mark lines 1,5,6,7,8. Note: If you've changed the beginning line number be sure these match rendered line numbers

As hexo depends on hexo-util for highlighting, we should add mark support into hexo-util. The syntax part can later be added into hexo's tag plugin.

encodeURL() will lose hash in URL

const { encodeURL } = require("hexo-util");
console.log(encodeURL('https://example.com/blog/#test'));
// "https://example.test/blog/"
const { encodeURL } = require("hexo-util");
encodeURL('https://example.com/#test');
// "https://example.com/"

pathname: encodeURI(decodeURI(parse(str).pathname))

pathname doesn't include hash. parse(str).href should be used in this case.

@curbengh

ERROR Plugin load failed: hexo-generator-json-content

PS D:\file\blog\blog> hexo clean
INFO  Validating config
ERROR Plugin load failed: hexo-generator-json-content
Error: Cannot find module 'D:\file\blog\blog\node_modules\hexo-generator-json-content\node_modules\hexo-util\lib\index'. Please verify that the package.json has a valid "main" entry
    at tryPackage (internal/modules/cjs/loader.js:323:19)
    at Function.Module._findPath (internal/modules/cjs/loader.js:680:18)
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:1001:27)
    at Function.Module._load (internal/modules/cjs/loader.js:884:27)
    at Module.require (internal/modules/cjs/loader.js:1074:19)
    at req (D:\file\blog\blog\node_modules\hexo\lib\hexo\index.js:292:23)
    at D:\file\blog\blog\node_modules\hexo-generator-json-content\dist\main.js:7:16
    at D:\file\blog\blog\node_modules\hexo\lib\hexo\index.js:305:14
    at tryCatcher (D:\file\blog\blog\node_modules\hexo-fs\node_modules\bluebird\js\release\util.js:16:23)
    at Promise._settlePromiseFromHandler (D:\file\blog\blog\node_modules\hexo-fs\node_modules\bluebird\js\release\promise.js:547:31)
    at Promise._settlePromise (D:\file\blog\blog\node_modules\hexo-fs\node_modules\bluebird\js\release\promise.js:604:18)
    at Promise._settlePromise0 (D:\file\blog\blog\node_modules\hexo-fs\node_modules\bluebird\js\release\promise.js:649:10)
    at Promise._settlePromises (D:\file\blog\blog\node_modules\hexo-fs\node_modules\bluebird\js\release\promise.js:729:18)
    at _drainQueueStep (D:\file\blog\blog\node_modules\hexo-fs\node_modules\bluebird\js\release\async.js:93:12)
    at _drainQueue (D:\file\blog\blog\node_modules\hexo-fs\node_modules\bluebird\js\release\async.js:86:9)
    at Async._drainQueues (D:\file\blog\blog\node_modules\hexo-fs\node_modules\bluebird\js\release\async.js:102:5)
    at Immediate.Async.drainQueues [as _onImmediate] (D:\file\blog\blog\node_modules\hexo-fs\node_modules\bluebird\js\release\async.js:15:14)
    at processImmediate (internal/timers.js:456:21)

image

Missing support for highlighting F# code

Hello :)

So far I saw this is the plugin which provides the syntax highlighting for Hexo.
I noticed during using it that F# syntax highlighting is only supported for some usual keywords.

How could this be improved effectively?

Highlight not working correctly

It seems that highlighter removes every single empty line but when calculating line_number they're taken into consideration. So I get more lines of numbers than codes.

Highlighting broken for multi-line constructs

When highlighting multi-line constructs, e.g. block comments or ES2015 template strings, highlight.js outputs a single <span> that contains newlines. For example:

var string = `
  I am multiline
`

Is converted to:

<span class="keyword">var</span> string = <span class="string">`
  i am multilne
`</span>

In https://github.com/hexojs/hexo-util/blob/master/lib/highlight.js#L32, hexo wraps each line with an extra <span>, which closes the <span class="string"> early, and causes the rest of that string to be highlighted incorrectly:

<span class="line"><span class="keyword">var</span> string = <span class="string">`</span><br>
<span class="line">  i am multilne</span><br>
<span class="line">`</span></span><br>

In addition, it also creates a .line span that is in fact multiple lines high.

I personally use a custom theme that does not make use of the .line class at all, so I simply removed that wrapping span and everything works properly. However it seems many existing themes rely on the .line class for styling :(

url_for helper doesn't work for mailto link

https://github.com/hexojs/hexo-util/blob/master/lib/url_for.js#L28-L31

it will return origin path when met external link like http://example.com, but will not return origin path for mailto: [email protected]. and lead to an issue when relative_link was set.

url_for('/category') => /relative_link/category <= OK!
url_for('http://example.com') => http://example.com <= OK!
url_for('mailto:[email protected]') => /relative_link/mailto:[email protected] <= Ops!

Update highlight.js til 9.3.0

Currently there are some limitations on C# syntax when using generics in class or interface declarings - this should be improved in 9.3.0, but hexo-util is running 9.0.0.

Some content is outdated

The 'parse' function of the 'url' package in 'url_for. ts' is outdated, and Nodejs has been deprecated in v10. Please use the URL class

Trying to get in touch regarding a security issue

Hey there!

I'd like to report a security issue but cannot find contact instructions on your repository.

If not a hassle, might you kindly add a SECURITY.md file with an email, or another contact method? GitHub recommends this best practice to ensure security issues are responsibly disclosed, and it would serve as a simple instruction for security researchers in the future.

Thank you for your consideration, and I look forward to hearing from you!

(cc @huntr-helper)

unescape_html.js 反转义出现了问题

(我就直接写中文了)

我再更新了 hexo 之后,发现了和 hexojs/hexo#4253 一样的问题。

然后追溯了一下,发现是 toc API 转义的时候除了问题,把已经转义的中文字符,例如 &#x6301;,中的 & 转义成了 &amp; 然后中文字符就出问题了。然后看了一下代码发现 https://github.com/hexojs/hexo-util/blob/master/lib/escape_html.js 里面进行了一遍反转义,然后又转义了一遍。而 https://github.com/hexojs/hexo-util/blob/2.0.0/lib/unescape_html.js 里面反转义,只是机械性的将特定内容进行了转义,而没有管中文字符。 最后导致 &#x6301; 被转变成了 &amp;#x6301;

Lazy loading in highlight.js may break some languages highlighting

Hello,
The lazy loading behavior in lib/highlight.js introduced in 7f6469e may break some languages highlighting such as shell.

The shell language highlighting relies on the bash language, if bash language is not registered yet, you will get an unexpected highlighting result.

Input:

var str = '$ echo "Hello World"';

Expected result:

'<span class="meta">$</span><span class="bash"> <span class="built_in">echo</span> <span class="string">"Hello World"</span></span>'

Only shell is registered:

'<span class="meta">$</span> echo "Hello World"'

error Invalid version: "https://registry.npmjs.org/hexo-util/-/hexo-util-0.6.0.tgz"

On previously working Hexo install, I do rm -rf node_modules/ && npm install and I get:

0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/Cellar/node/8.1.3/bin/node',
1 verbose cli   '/usr/local/bin/npm',
1 verbose cli   'run',
1 verbose cli   'build:highlight' ]
2 info using [email protected]
3 info using [email protected]
4 verbose stack Error: Invalid version: "https://registry.npmjs.org/hexo-util/-/hexo-util-0.6.0.tgz"
4 verbose stack     at Object.fixVersionField (/usr/local/lib/node_modules/npm/node_modules/normalize-package-data/lib/fixer.js:191:13)
4 verbose stack     at /usr/local/lib/node_modules/npm/node_modules/normalize-package-data/lib/normalize.js:32:38
4 verbose stack     at Array.forEach (native)
4 verbose stack     at normalize (/usr/local/lib/node_modules/npm/node_modules/normalize-package-data/lib/normalize.js:31:15)
4 verbose stack     at final (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:349:5)
4 verbose stack     at then (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:124:5)
4 verbose stack     at /usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:243:12
4 verbose stack     at /usr/local/lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:78:16
4 verbose stack     at tryToString (fs.js:512:3)
4 verbose stack     at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:500:12)
5 verbose cwd /scm/devops/node_modules/hexo-util
6 verbose Darwin 16.6.0
7 verbose argv "/usr/local/Cellar/node/8.1.3/bin/node" "/usr/local/bin/npm" "run" "build:highlight"
8 verbose node v8.1.3
9 verbose npm  v5.0.3
10 error Invalid version: "https://registry.npmjs.org/hexo-util/-/hexo-util-0.6.0.tgz"
11 verbose exit [ 1, true ]

Yeah, I've no idea what is invalid about the version number.

I'm on a Mac, with homebrew.

there bug in code react jsx

There are some problems with the react jsx

The following code

import React from "react";
import ReactDOM from "react-dom";

let el = (
    <div>
        <h1>hello</h1>
        <label htmlFor="username">username</label>
        <input type="text" id="username"/>
    </div>
);

ReactDOM.render(el, window.root);

hexo install failed

log:
0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'run', 'build:highlight' ]
2 info using [email protected]
3 info using [email protected]
4 verbose config Skipping project config: /home/shea/.npmrc. (matches userconfig)
5 verbose stack Error: ENOENT: no such file or directory, open '/home/shea/package.json'
6 verbose cwd /home/shea
7 verbose Linux 4.9.16-1-MANJARO
8 verbose argv "/usr/bin/node" "/usr/bin/npm" "run" "build:highlight"
9 verbose node v7.7.3
10 verbose npm v4.4.1
11 error path /home/shea/package.json
12 error code ENOENT
13 error errno -2
14 error syscall open
15 error enoent ENOENT: no such file or directory, open '/home/shea/package.json'
16 error enoent ENOENT: no such file or directory, open '/home/shea/package.json'
16 error enoent This is most likely not a problem with npm itself
16 error enoent and is related to npm not being able to find a file.
17 verbose exit [ -2, true ]

OS: manjaro i3 17.0

RangeError: Maximum call stack size exceeded

just run hexo generate in my hexo site with more than 1.7k posts

RangeError: Maximum call stack size exceeded
    at String.replace (<anonymous>)
    at escapeRegExp (/home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/hexo/node_modules/hexo-util/lib/escape_regexp.js:7:14)
    at slugize (/home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/hexo/node_modules/hexo-util/lib/slugize.js:13:22)
    at _Document.<anonymous> (/home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/hexo/lib/models/tag.js:21:12)
    at _Document.slug (/home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/hexo/node_modules/warehouse/lib/types/virtual.js:59:24)
    at JSON.stringify (<anonymous>)
    at JSON.stringifyWithCircularRefs (/home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/sbg-utility/dist/utils/JSON.js:56:25)
    at jsonStringifyWithCircularRefs (/home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/sbg-utility/dist/utils/JSON.js:69:17)
    at /home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/hexo-renderers/dist/helper/collector.js:161:122
    at step (/home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/hexo-renderers/dist/helper/collector.js:56:23)
    at Object.next (/home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/hexo-renderers/dist/helper/collector.js:37:53)
    at fulfilled (/home/runner/work/static-blog-generator-hexo/static-blog-generator-hexo/site/node_modules/hexo-renderers/dist/helper/collector.js:28:58)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Error: Process completed with exit code 2.

Error spawn tests on windows 10 Pro

error like below screenshot

5 failing

  1) spawn
       default:
     Error: C:\cygwin64\bin\type: line 2: type: D:\Repositories\hexo\packages\hexo-util\test\spawn_test.txt: not found

      at ChildProcess.<anonymous> (lib\spawn.ts:43:19)
      at ChildProcess.emit (domain.js:475:12)
      at ChildProcess.cp.emit (node_modules\cross-spawn\dist\lib\enoent.js:35:29)
      at maybeClose (internal/child_process.js:1088:16)
      at Process.ChildProcess._handle.onexit (internal/child_process.js:296:5)

  2) spawn
       default - string:
     Error: C:\cygwin64\bin\type: line 2: type: D:\Repositories\hexo\packages\hexo-util\test\spawn_test.txt: not found

      at ChildProcess.<anonymous> (lib\spawn.ts:43:19)
      at ChildProcess.emit (domain.js:475:12)
      at ChildProcess.cp.emit (node_modules\cross-spawn\dist\lib\enoent.js:35:29)
      at maybeClose (internal/child_process.js:1088:16)
      at Process.ChildProcess._handle.onexit (internal/child_process.js:296:5)

  3) spawn
       error:

      AssertionError: expected promise to be rejected with an error including 'spawn type ENOENT' 
but got 'C:\cygwin64\bin\type: line 2: type: n…'
      + expected - actual

      -C:\cygwin64\bin\type: line 2: type: nothing: not found
      +spawn type ENOENT



  4) spawn
       custom encoding:
     Error: 433a5c63796777696e36345c62696e5c747970653a206c696e6520323a20747970653a20443a5c5265706f7369746f726965735c6865786f5c7061636b616765735c6865786f2d7574696c5c746573745c737061776e5f746573742e7478743a206e6f7420666f756e640a
      at ChildProcess.<anonymous> (lib\spawn.ts:43:19)
      at ChildProcess.emit (domain.js:475:12)
      at ChildProcess.cp.emit (node_modules\cross-spawn\dist\lib\enoent.js:35:29)
      at maybeClose (internal/child_process.js:1088:16)
      at Process.ChildProcess._handle.onexit (internal/child_process.js:296:5)

  5) spawn
       encoding = null:
     Error: C:\cygwin64\bin\type: line 2: type: D:\Repositories\hexo\packages\hexo-util\test\spawn_test.txt: not found

      at ChildProcess.<anonymous> (lib\spawn.ts:43:19)
      at ChildProcess.emit (domain.js:475:12)
      at ChildProcess.cp.emit (node_modules\cross-spawn\dist\lib\enoent.js:35:29)
      at maybeClose (internal/child_process.js:1088:16)
      at Process.ChildProcess._handle.onexit (internal/child_process.js:296:5)



npm ERR! Lifecycle script `test` failed with error:
npm ERR! Error: command failed
npm ERR!   in workspace: [email protected]
npm ERR!   at location: D:\Repositories\hexo\packages\hexo-util

image

but succesfull in CI https://github.com/dimaslanjaka/hexo-util/actions
image

npm run build:highlight failed

─ns@ns-HP-Pavilion-Notebook ~
╰─➤ sudo npm install -g hexo-cli 1 ↵
/usr/local/bin/hexo -> /usr/local/lib/node_modules/hexo-cli/bin/hexo

[email protected] install /usr/local/lib/node_modules/hexo-cli/node_modules/dtrace-provider
node scripts/install.js

sh: 1: node: not found
npm WARN install:[email protected] [email protected] install: node scripts/install.js
npm WARN install:[email protected] spawn ENOENT

[email protected] postinstall /usr/local/lib/node_modules/hexo-cli/node_modules/hexo-util
npm run build:highlight

[email protected] build:highlight /usr/local/lib/node_modules/hexo-cli/node_modules/hexo-util
node scripts/build_highlight_alias.js > highlight_alias.json

sh: 1: node: not found

npm ERR! Linux 4.4.0-21-generic
npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "run" "build:highlight"
npm ERR! node v4.2.6
npm ERR! npm v3.5.2
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! [email protected] build:highlight: node scripts/build_highlight_alias.js > highlight_alias.json
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the [email protected] build:highlight script 'node scripts/build_highlight_alias.js > highlight_alias.json'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the hexo-util package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node scripts/build_highlight_alias.js > highlight_alias.json
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs hexo-util
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls hexo-util
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /usr/local/lib/node_modules/hexo-cli/node_modules/hexo-util/npm-debug.log
/usr/local/lib
└── (empty)

npm WARN optional Skipping failed optional dependency /hexo-cli/chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: [email protected]
npm ERR! Linux 4.4.0-21-generic
npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "install" "-g" "hexo-cli"
npm ERR! node v4.2.6
npm ERR! npm v3.5.2
npm ERR! code ELIFECYCLE

npm ERR! [email protected] postinstall: npm run build:highlight
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script 'npm run build:highlight'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the hexo-util package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! npm run build:highlight
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs hexo-util
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls hexo-util
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /home/ns/npm-debug.log
npm ERR! code 1

****

Feature Request: TOC

If we are going to address something like hexojs/hexo#3287, we will have duplicated dom process code in toc helper and toc tag plugin.

So maybe we can address a function that could parse titles from HTML string into JSON object. Then we can use this json to build either toc helper or toc tag plugin. I might name this function to tocObj().

I have came up an idea of the format:

<div id="para-1">
    <h1>Paragraph 1</h1>
</div>
<h2 id="para-1-1">Paragraph 1.1</h2>
<h1 id="para-2">Paragraph 2</h1>
<h2 id="para-2-1">Paragraph 2.1</h2>
<div id="para-2-2">
    <div>
        <h2>Paragraph 2.2</h2>
    </div>
</div>
<h3 id="para-2-2-1">Paragraph 2.2.1</h3>
[
    {
        "name": "Paragraph 1",
        "level": 1,
        "id": "para-1",
        "children": [
            {
                "name": "Paragraph 1.1",
                "level": 2,
                "id": "para-1-1",
                "children": []
            }
        ]
    },
    {
        "name": "Paragraph 2",
        "level": 1,
        "id": "para-2",
        "children": [
            {
                "name": "Paragraph 2.1",
                "level": 2,
                "id": "para-2-1",
                "children": []
            },
            {
                "name": "Paragraph 2.2",
                "level": 2,
                "id": "para-2-3",
                "children": [
                    {
                        "name": "Paragraph 2.2.1",
                        "level": 3,
                        "id": "para-2-2-1",
                        "children": []
                    }
                ]
            }
        ]
    }
]

or simpler:

[ { name: 'Paragraph 1', id: 'para-1', lvl: 1 },
  { name: 'Paragraph 2', id: 'para-2', lvl: 1 },
  { name: 'Paragraph 2.1', id: 'para-2-1', lvl: 2 },
  { name: 'Paragraph 2.2', id: 'para-2-2', lvl: 2 },
  { name: 'Paragraph 2.2.1', id: 'para-2-2-1', lvl: 3 } ]

3.0.0 Error: Cannot find module

08:57:18.372 | internal/modules/cjs/loader.js:330
-- | --
08:57:18.372 | throw err;
08:57:18.372 | ^
08:57:18.373 |  
08:57:18.373 | Error: Cannot find module '/opt/buildhome/repo/node_modules/hexo-util/lib/index'. Please verify that the package.json has a valid "main" entry
08:57:18.373 | at tryPackage (internal/modules/cjs/loader.js:322:19)
08:57:18.373 | at Function.Module._findPath (internal/modules/cjs/loader.js:683:18)
08:57:18.373 | at Function.Module._resolveFilename (internal/modules/cjs/loader.js:953:27)
08:57:18.373 | at Function.Module._load (internal/modules/cjs/loader.js:842:27)
08:57:18.373 | at Module.require (internal/modules/cjs/loader.js:1026:19)
08:57:18.375 | at require (internal/modules/cjs/helpers.js:72:18)
08:57:18.375 | at Object.<anonymous> (/opt/buildhome/repo/node_modules/hexo-fs/lib/fs.js:8:26)
08:57:18.375 | at Module._compile (internal/modules/cjs/loader.js:1138:30)
08:57:18.375 | at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
08:57:18.375 | at Module.load (internal/modules/cjs/loader.js:986:32)
08:57:18.376 | at Function.Module._load (internal/modules/cjs/loader.js:879:14)
08:57:18.376 | at Module.require (internal/modules/cjs/loader.js:1026:19)
08:57:18.376 | at require (internal/modules/cjs/helpers.js:72:18)
08:57:18.376 | at Object.<anonymous> (/opt/buildhome/repo/node_modules/hexo-cli/lib/find_pkg.js:4:22)
08:57:18.376 | at Module._compile (internal/modules/cjs/loader.js:1138:30)
08:57:18.376 | at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10) {
08:57:18.377 | code: 'MODULE_NOT_FOUND',
08:57:18.377 | path: '/opt/buildhome/repo/node_modules/hexo-util/package.json',
08:57:18.377 | requestPath: 'hexo-util'
08:57:18.377 | }

`highlight()` is inconsistent when code is illegal syntax

Generally the result of highlight() contains lauguage name as HTML class name.

If code is illegal syntax for the specified language,
the HTML class name is added or not (inconsistent).

option lang illegal syntax? option hljs class name of outer <figure> class name of inner <code>
java no false highlight java N/A (none)
java no true highlight java hljs java
java yes false highlight N/A (none)
java yes true highlight hljs java
none - false highlight plain N/A (none)
none - true highlight plain hljs plain

I think we have three options:

  1. always add laugage name even if illegal syntax.
  2. never add language name if illegal syntax.
  3. add the language name plain if illegal syntax.

I think Option 1 might be best because users will intend to be.

Please advice!


I think this inconsistency is caused by undocumented behavior of highlight() of highlightjs package.

The API document of highlightjs package is:
https://highlightjs.readthedocs.io/en/latest/api.html#highlight-languagename-code-ignore-illegals-continuation

According to above API document, highlight() throws an exception in case of detecting illegal syntax for the language.
But actually not throw any exception (regardless ignore_illegals parameter).
Instead, illegal property of the return value is set to true and
language property of the return value does not exist.

Current code of lib/highlight.js considers the exception halfway.
And the lack of lanaguage property is not expected.

Anyway the code should be modified to keep consistency.

p.s. This issue is derived from hexojs/hexo#3984

ghost dependency domhandler

import type { Element } from 'domhandler';

domhandler is not defined in package.json but used in code.

build failed

 % pnpm tsc -b -f -v
[下午10:30:39] Projects in this build: 
    * tsconfig.json

[下午10:30:39] Project 'tsconfig.json' is being forcibly rebuilt

[下午10:30:39] Building project 'D:/hexo-util/tsconfig.json'...

lib/toc_obj.ts:3:30 - error TS2307: Cannot find module 'domhandler' or its corresponding type declarations.

3 import type { Element } from 'domhandler';
                               ~~~~~~~~~~~~


Found 1 error.

eslint & ts-check

vscode

this fails on your system: npm ERR! npm run build:highlight

npm WARN optional Skipping failed optional dependency /hexo-cli/chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: [email protected]
npm ERR! Linux 4.8.0-45-generic
npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "install" "hexo-cli" "-g"
npm ERR! node v4.2.6
npm ERR! npm v3.5.2
npm ERR! code ELIFECYCLE

npm ERR! [email protected] postinstall: npm run build:highlight
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script 'npm run build:highlight'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the hexo-util package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! npm run build:highlight

npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs hexo-util
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls hexo-util
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /home/jeffrey/github/codeleague.github.io/npm-debug.log
npm ERR! code 1

Having trouble getting highlightjs working in hexo-util

I've been trying to incorporate Highlightjs into my hexo project and discovered that it's a part of hexo-util. I installed the plugin via npm but the readme doesn't give a lot of info as to how I'm supposed to get it up and running, outside of running var util = require('hexo-util'), which I have in a js file in my scripts folder. I've scoured the Internet for a tutorial or another project that will show me how to activate Highlightjs, but I haven't had a clear cut answer.

The readme says that the syntax for highlight in hexo-util is highlight(str, [options]), but it's unclear where that command goes. I've found conflicting info that it might go in a js file in the script directory, inside the post's md file itself, or even in _config.yml?

Also unclear what the str parameter in highlight is supposed to be either. Is this the code block that you're formatting? If that's the case, then should the highlight call go in the md file? I tried that, but to no avail. I currently have this test code in one of my posts:

` ` `csharp
public int test = 1 + 1;
` ` `

It shows up in my post without any syntax highlighting, even though the highlight class does show up in the HTML. I know newer versions of Highlightjs actually use the hljs class, but no amount of prodding with these keywords has gotten me anywhere.

I would love some help with this!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.