UNPKG

14.9 kBMarkdownView Raw
1# hexo-util
2
3[![Build Status](https://travis-ci.com/hexojs/hexo-util.svg?branch=master)](https://travis-ci.com/hexojs/hexo-util)
4[![NPM version](https://badge.fury.io/js/hexo-util.svg)](https://www.npmjs.com/package/hexo-util)
5[![Coverage Status](https://coveralls.io/repos/hexojs/hexo-util/badge.svg?branch=master&service=github)](https://coveralls.io/github/hexojs/hexo-util?branch=master)
6[![dependencies Status](https://david-dm.org/hexojs/hexo-util/status.svg)](https://david-dm.org/hexojs/hexo-util)
7[![devDependencies Status](https://david-dm.org/hexojs/hexo-util/dev-status.svg)](https://david-dm.org/hexojs/hexo-util?type=dev)
8
9Utilities for [Hexo].
10
11## Table of contents
12
13- [Installation](#installation)
14- [Usage](#usage)
15- [CacheStream](#cachestream)
16- [camelCaseKeys](#camelcasekeysobj-options)
17- [createSha1Hash](#createsha1hash)
18- [decodeURL](#decodeurlstr)
19- [encodeURL](#encodeurlstr)
20- [escapeDiacritic](#escapediacriticstr)
21- [escapeHTML](#escapehtmlstr)
22- [escapeRegex](#escaperegexstr)
23- [full_url_for](#full_url_forpath)
24- [gravatar](#gravatarstr-options)
25- [hash](#hashstr)
26- [highlight](#highlightstr-options)
27- [htmlTag](#htmltagtag-attrs-text-escape)
28- [isExternalLink](#isexternallinkurl-sitehost-exclude)
29- [Pattern](#patternrule)
30- [Permalink](#permalinkrule-options)
31- [relative_url](#relative_urlfrom-to)
32- [slugize](#slugizestr-options)
33- [spawn](#spawncommand-args-options)
34- [stripHTML](#striphtmlstr)
35- [wordWrap](#wordwrapstr-options)
36- [truncate](#truncatestr-options)
37- [unescapeHTML](#unescapehtmlstr)
38- [url_for](#url_forpath-option)
39- [bind(hexo)](#bindhexo)
40
41## Installation
42
43``` bash
44$ npm install hexo-util --save
45```
46
47## Usage
48
49``` js
50var util = require('hexo-util');
51```
52
53### CacheStream()
54
55Caches contents piped to the stream.
56
57``` js
58var stream = new CacheStream();
59
60fs.createReadStream('/path/to/file').pipe(stream);
61
62stream.on('finish', function(){
63 // Read cache piped to the stream
64 console.log(stream.getCache());
65
66 // Destroy cache
67 stream.destroy();
68});
69```
70
71### camelCaseKeys(obj, options)
72
73Convert object keys to camelCase. Original keys will be converted to getter/setter and sync to the camelCase keys.
74
75``` js
76camelCaseKeys({
77 foo_bar: 'test'
78});
79// { fooBar: 'test', foo_bar: 'test' }
80```
81
82### createSha1Hash()
83return SHA1 hash object.
84 This is the same as calling `createHash('utf8')` in the node.js native module crypto.
85 ``` js
86const sha1 = createSha1Hash();
87 fs.createReadStream('/path/to/file')
88 .pipe(sha1)
89 .on('finish', () => {
90 console.log(sha1.read());
91 });
92```
93
94### decodeURL(str)
95
96Decode [encoded](https://en.wikipedia.org/wiki/Percent-encoding) URL or path. An alternative to the native [`decodeURI()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURI) function, with added ability to decode [punycoded](https://en.wikipedia.org/wiki/Punycode) domain.
97
98``` js
99decodeURL('http://foo.com/b%C3%A1r')
100// http://foo.com/bár
101
102decodeURL('http://xn--br-mia.com/baz')
103// http://bár.com/baz
104
105decodeURL('/foo/b%C3%A1r/')
106// /foo/bár/
107
108/* Alternatively, Node 10+ offers native API to decode punycoded domain */
109const {format} = require('url')
110decodeURI(format(new URL('http://xn--br-mia.com.com/b%C3%A1r'), {unicode: true}))
111// http://bár.com/báz
112```
113
114### encodeURL(str)
115
116Encode URL or path into a [safe format](https://en.wikipedia.org/wiki/Percent-encoding).
117
118``` js
119encodeURL('http://foo.com/bár')
120// http://foo.com/b%C3%A1r
121
122encodeURL('/foo/bár/')
123// /foo/b%C3%A1r/
124```
125
126### escapeDiacritic(str)
127
128Escapes diacritic characters in a string.
129
130### escapeHTML(str)
131
132Escapes HTML entities in a string.
133
134``` js
135escapeHTML('<p>Hello "world".</p>')
136// &lt;p&gt;Hello &quot;world&quot;.&lt;&#x2F;p&gt;
137
138/* support escaped characters */
139escapeHTML('&lt;foo>bar</foo&gt;')
140// &lt;foo&gt;bar&lt;&#x2F;foo&gt;
141```
142
143### escapeRegex(str)
144
145Escapes special characters in a regular expression.
146
147### full_url_for(path)
148
149Returns a url with the config.url prefixed. Output is [encoded](#encodeurlstr) automatically. Requires [`bind(hexo)`](#bindhexo).
150
151``` yml
152_config.yml
153url: https://example.com/blog # example
154```
155
156``` js
157full_url_for('/a/path')
158// https://example.com/blog/a/path
159```
160
161### gravatar(str, [options])
162
163Returns the gravatar image url from an email.
164
165If 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.
166
167Option | Description | Default
168--- | --- | ---
169`s` | Output image size | 80
170`d` | Default image |
171`f` | Force default |
172`r` | Rating |
173
174More info: [Gravatar](https://en.gravatar.com/site/implement/images/)
175
176``` js
177gravatar('a@abc.com')
178// https://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787
179gravatar('a@abc.com', 40)
180// https://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40
181gravatar('a@abc.com' {s: 40, d: 'https://via.placeholder.com/150'})
182// https://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40&d=https%3A%2F%2Fvia.placeholder.com%2F150
183```
184
185### hash(str)
186
187Generates SHA1 hash.
188
189``` js
190hash('123456');
191// <Buffer 7c 4a 8d 09 ca 37 62 af 61 e5 95 20 94 3d c2 64 94 f8 94 1b>
192```
193
194### HashStream()
195**\[deprecated\]** use [`createSha1Hash()`](#createsha1hash).
196
197Generates SHA1 hash with a transform stream.
198
199``` js
200var stream = new HashStream();
201
202fs.createReadStream('/path/to/file')
203 .pipe(stream)
204 .on('finish', function(){
205 console.log(stream.read());
206 });
207```
208
209### highlight(str, [options])
210
211Syntax highlighting for a code block.
212
213Option | Description | Default
214--- | --- | ---
215`gutter` | Whether to show line numbers | true
216`wrap` | Whether to wrap the code block in [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table) | true
217`firstLine` | First line number | 1
218`hljs` | Whether to use the `hljs-*` prefix for CSS classes | false
219`lang` | Language |
220`caption` | Caption |
221`tab`| Replace tabs |
222`autoDetect` | Detect language automatically | false
223`mark` | Line highlight specific line(s) |
224
225### htmlTag(tag, attrs, text, escape)
226
227Creates a html tag.
228
229Option | Description | Default
230--- | --- | ---
231`tag` | Tag / element name |
232`attrs` | Attribute(s) and its value.<br>Value is always [escaped](#escapehtmlstr), URL is always [encoded](#encodeurlstr). |
233`text` | Text, the value is always escaped<br>_(except for `<style>` tag)_ |
234`escape` | Whether to escape the text | true
235
236``` js
237htmlTag('img', {src: 'example.png'})
238// <img src="example.png">
239
240htmlTag('a', {href: 'http://hexo.io/'}, 'Hexo')
241// <a href="http://hexo.io/">Hexo</a>
242
243htmlTag('link', {href: 'http://foo.com/'}, '<a>bar</a>')
244// <a href="http://foo.com/">&lt;bar&gt;</a>
245
246htmlTag('a', {href: 'http://foo.com/'}, '<b>bold</b>', false)
247// <a href="http://foo.com/"><b>bold</b></a>
248
249/* text value of <style> won't be escaped, url is still encoded */
250htmlTag('style', {}, 'p { content: "<"; background: url("bár.jpg"); }')
251// <style>p { content: "<"; background: url("b%C3%A1r.jpg"); }</style>
252
253/* support script tag with async/defer */
254htmlTag('script', {src: '/foo.js', async: true}, '')
255// <script src="/foo.js" async></script>
256```
257
258### isExternalLink(url, sitehost, [exclude])
259
260Option | Description | Default
261--- | --- | ---
262`url` | The input URL. |
263`sitehost` | The hostname / url of website. You can also pass `hexo.config.url`. |
264`exclude` | Exclude hostnames. Specific subdomain is required when applicable, including www. | `[]`
265
266Returns if a given url is external link relative to given `sitehost` and `[exclude]`.
267
268``` js
269// 'sitehost' can be a domain or url
270isExternalLink('https://example.com', 'example.com');
271// false
272isExternalLink('https://example.com', 'https://example.com');
273// false
274isExternalLink('https://example.com', '//example.com/blog/');
275// false
276```
277
278``` js
279isExternalLink('/archives/foo.html', 'example.com');
280// false
281isExternalLink('https://foo.com/', 'example.com');
282// true
283```
284
285``` js
286isExternalLink('https://foo.com', 'example.com', ['foo.com', 'bar.com']);
287// false
288isExternalLink('https://bar.com', 'example.com', ['foo.com', 'bar.com']);
289// false
290isExternalLink('https://baz.com/', 'example.com', ['foo.com', 'bar.com']);
291// true
292```
293
294
295### Pattern(rule)
296
297Parses the string and tests if the string matches the rule. `rule` can be a string, a regular expression or a function.
298
299``` js
300var pattern = new Pattern('posts/:id');
301
302pattern.match('posts/89');
303// {0: 'posts/89', 1: '89', id: '89'}
304```
305
306``` js
307var pattern = new Pattern('posts/*path');
308
309pattern.match('posts/2013/hello-world');
310// {0: 'posts/2013/hello-world', 1: '2013/hello-world', path: '2013/hello-world'}
311```
312
313### Permalink(rule, [options])
314
315Parses a permalink.
316
317Option | Description
318--- | ---
319`segments` | Customize the rule of a segment in the permalink
320
321``` js
322var permalink = new Permalink(':year/:month/:day/:title', {
323 segments: {
324 year: /(\d{4})/,
325 month: /(\d{2})/,
326 day: /(\d{2})/
327 }
328});
329
330permalink.parse('2014/01/31/test');
331// {year: '2014', month: '01', day: '31', title: 'test'}
332
333permalink.test('2014/01/31/test');
334// true
335
336permalink.stringify({year: '2014', month: '01', day: '31', title: 'test'})
337// 2014/01/31/test
338```
339
340### relative_url(from, to)
341
342Returns the relative URL from `from` to `to`. Output is [encoded](#encodeurlstr) automatically. Requires [`bind(hexo)`](#bindhexo).
343
344``` js
345relative_url('foo/bar/', 'css/style.css')
346// ../../css/style.css
347```
348
349### slugize(str, [options])
350
351Transforms a string into a clean URL-friendly string.
352
353Option | Description | Default
354--- | --- | ---
355`separator` | Separator | -
356`transform` | Transform the string into lower case (`1`) or upper case (`2`) |
357
358``` js
359slugize('Hello World') = 'Hello-World'
360slugize('Hellô Wòrld') = 'Hello-World'
361slugize('Hello World', {separator: '_'}) = 'Hello_World'
362slugize('Hello World', {transform: 1}) = 'hello-world'
363slugize('Hello World', {transform: 2}) = 'HELLO-WORLD'
364```
365
366### spawn(command, [args], [options])
367
368Launches a new process with the given `command`. This method returns a promise.
369
370Option | Description | Default
371--- | --- | ---
372`cwd` | Current working directory of the child process |
373`env` | Environment key-value pairs |
374`stdio` | Child's stdio configuration |
375`detached` | The child will be a process group leader |
376`uid` | Sets the user identity of the process |
377`gid` | Sets the group identity of the process |
378`verbose` | Display messages on the console | `false`
379`encoding` | Sets the encoding of the output string | `utf8`
380
381``` js
382spawn('cat', 'test.txt').then(function(content){
383 console.log(content);
384});
385```
386
387### stripHTML(str)
388
389Removes HTML tags in a string.
390
391### wordWrap(str, [options])
392
393Wraps the string no longer than line width. This method breaks on the first whitespace character that does not exceed line width.
394
395Option | Description | Default
396--- | --- | ---
397`width` | Line width | 80
398
399``` js
400wordWrap('Once upon a time')
401// Once upon a time
402
403wordWrap('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...')
404// 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...
405
406wordWrap('Once upon a time', {width: 8})
407// Once\nupon a\ntime
408
409wordWrap('Once upon a time', {width: 1})
410// Once\nupon\na\ntime
411```
412
413### truncate(str, [options])
414
415Truncates 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`.
416
417Option | Description | Default
418--- | --- | ---
419`length` | Max length of the string | 30
420`omission` | Omission text | ...
421`separator` | truncate text at a natural break |
422
423``` js
424truncate('Once upon a time in a world far far away')
425// "Once upon a time in a world..."
426
427truncate('Once upon a time in a world far far away', {length: 17})
428// "Once upon a ti..."
429
430truncate('Once upon a time in a world far far away', {length: 17, separator: ' '})
431// "Once upon a..."
432
433truncate('And they found that many people were sleeping better.', {length: 25, omission: '... (continued)'})
434// "And they f... (continued)"
435```
436
437### unescapeHTML(str)
438
439Unescapes HTML entities in a string.
440
441``` js
442unescapeHTML('&lt;p&gt;Hello &quot;world&quot;.&lt;&#x2F;p&gt;')
443// <p>Hello "world".</p>
444```
445
446### url_for(path, [option])
447
448Returns a url with the root path prefixed. Output is [encoded](#encodeurlstr) automatically. Requires [`bind(hexo)`](#bindhexo).
449
450Option | Description | Default
451--- | --- | ---
452`relative` | Output relative link | Value of `config.relative_link`
453
454``` yml
455_config.yml
456root: /blog/ # example
457```
458
459``` js
460url_for('/a/path')
461// /blog/a/path
462```
463
464Relative link, follows `relative_link` option by default
465e.g. post/page path is '/foo/bar/index.html'
466
467``` yml
468_config.yml
469relative_link: true
470```
471
472``` js
473url_for('/css/style.css')
474// ../../css/style.css
475
476/* Override option
477 * you could also disable it to output a non-relative link,
478 * even when `relative_link` is enabled and vice versa.
479 */
480url_for('/css/style.css', {relative: false})
481// /css/style.css
482```
483
484## bind(hexo)
485
486Following utilities require `bind(hexo)` / `bind(this)` / `call(hexo, input)` / `call(this, input)` to parse the user config when initializing:
487- [`full_url_for()`](#full_url_forpath)
488- [`url_for()`](#url_forpath)
489- [`relative_url()`](#relative_urlfrom-to)
490
491Below examples demonstrate different approaches to creating a [helper](https://hexo.io/api/helper) (each example is separated by `/******/`),
492
493``` js
494// Single function
495const url_for = require('hexo-util').url_for.bind(hexo);
496
497hexo.extend.helper.register('test_url', (str) => {
498 return url_for(str);
499})
500
501
502/******/
503// Multiple functions
504const url_for = require('hexo-util').url_for.bind(hexo)
505
506function testurlHelper(str) {
507 return url_for(str);
508}
509
510hexo.extend.helper.register('test_url', testurlHelper);
511
512
513/******/
514// Functions separated into different files.
515// test_url.js
516module.exports = function(str) {
517 const url_for = require('hexo-util').url_for.bind(this);
518 return url_for(str);
519}
520
521// index.js
522hexo.extend.helper.register('test_url', require('./test_url'));
523
524
525/******/
526// Function.call() approach also works
527const {url_for} = require('hexo-util');
528module.exports = function(str) {
529 return url_for.call(this, str);
530}
531
532hexo.extend.helper.register('test_url', require('./test_url'));
533
534
535/******/
536// Separating functions into individual files
537// Each file has multiple functions
538// test_url.js
539function testurlHelper(str) {
540 const url_for = require('hexo-util').url_for.bind(this);
541 return url_for(str);
542}
543
544module.exports = {
545 testurlHelper: testurlHelper
546}
547
548// index.js
549hexo.extend.helper.register('test_url', require('./test_url').testurlHelper);
550```
551
552## License
553
554MIT
555
556[Hexo]: http://hexo.io/