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 |
|
9 | Utilities for [Hexo].
|
10 |
|
11 | ## Table of contents
|
12 |
|
13 | - [Installation](#installation)
|
14 | - [Usage](#usage)
|
15 | - [Cache](#cache)
|
16 | - [CacheStream](#cachestream)
|
17 | - [camelCaseKeys](#camelcasekeysobj-options)
|
18 | - [createSha1Hash](#createsha1hash)
|
19 | - [decodeURL](#decodeurlstr)
|
20 | - [deepMerge](#deepmergetarget-source)
|
21 | - [encodeURL](#encodeurlstr)
|
22 | - [escapeDiacritic](#escapediacriticstr)
|
23 | - [escapeHTML](#escapehtmlstr)
|
24 | - [escapeRegex](#escaperegexstr)
|
25 | - [full_url_for](#full_url_forpath)
|
26 | - [gravatar](#gravatarstr-options)
|
27 | - [hash](#hashstr)
|
28 | - [highlight](#highlightstr-options)
|
29 | - [htmlTag](#htmltagtag-attrs-text-escape)
|
30 | - [isExternalLink](#isexternallinkurl-sitehost-exclude)
|
31 | - [Pattern](#patternrule)
|
32 | - [Permalink](#permalinkrule-options)
|
33 | - [prettyUrls](#prettyurlsurl-options)
|
34 | - [relative_url](#relative_urlfrom-to)
|
35 | - [slugize](#slugizestr-options)
|
36 | - [spawn](#spawncommand-args-options)
|
37 | - [stripHTML](#striphtmlstr)
|
38 | - [wordWrap](#wordwrapstr-options)
|
39 | - [tocObj](#tocobjstr-options)
|
40 | - [truncate](#truncatestr-options)
|
41 | - [unescapeHTML](#unescapehtmlstr)
|
42 | - [url_for](#url_forpath-option)
|
43 | - [bind(hexo)](#bindhexo)
|
44 |
|
45 | ## Installation
|
46 |
|
47 | ``` bash
|
48 | $ npm install hexo-util --save
|
49 | ```
|
50 |
|
51 | ## Usage
|
52 |
|
53 | ``` js
|
54 | var util = require('hexo-util');
|
55 | ```
|
56 |
|
57 | ### Cache()
|
58 |
|
59 | A simple plain object cache
|
60 |
|
61 | ``` js
|
62 | const cache = new Cache();
|
63 |
|
64 | // set(key, value)
|
65 | cache.set('foo', 'bar');
|
66 |
|
67 | // get(key) => value
|
68 | cache.get('foo');
|
69 | // 'bar'
|
70 |
|
71 | // has(key) => Boolean
|
72 | cache.has('foo');
|
73 | // true
|
74 | cache.has('bar');
|
75 | // false
|
76 |
|
77 | // apply(key. value)
|
78 | cache.apply('baz', () => 123);
|
79 | // 123
|
80 | cache.apply('baz', () => 456);
|
81 | // 123
|
82 | cache.apply('qux', 456);
|
83 | // 456
|
84 | cache.apply('qux', '789');
|
85 | // 456
|
86 |
|
87 | // del(key)
|
88 | cache.del('baz');
|
89 | cache.has('baz');
|
90 | // false
|
91 |
|
92 | // flush()
|
93 | cache.flush();
|
94 | cache.has('foo');
|
95 | // false
|
96 | ```
|
97 |
|
98 | ### CacheStream()
|
99 |
|
100 | Caches contents piped to the stream.
|
101 |
|
102 | ``` js
|
103 | var stream = new CacheStream();
|
104 |
|
105 | fs.createReadStream('/path/to/file').pipe(stream);
|
106 |
|
107 | stream.on('finish', function(){
|
108 | // Read cache piped to the stream
|
109 | console.log(stream.getCache());
|
110 |
|
111 | // Destroy cache
|
112 | stream.destroy();
|
113 | });
|
114 | ```
|
115 |
|
116 | ### camelCaseKeys(obj, options)
|
117 |
|
118 | Convert object keys to camelCase. Original keys will be converted to getter/setter and sync to the camelCase keys.
|
119 |
|
120 | ``` js
|
121 | camelCaseKeys({
|
122 | foo_bar: 'test'
|
123 | });
|
124 | // { fooBar: 'test', foo_bar: 'test' }
|
125 | ```
|
126 |
|
127 | ### createSha1Hash()
|
128 | return SHA1 hash object.
|
129 | This is the same as calling `createHash('utf8')` in the node.js native module crypto.
|
130 | ``` js
|
131 | const sha1 = createSha1Hash();
|
132 | fs.createReadStream('/path/to/file')
|
133 | .pipe(sha1)
|
134 | .on('finish', () => {
|
135 | console.log(sha1.read());
|
136 | });
|
137 | ```
|
138 |
|
139 | ### decodeURL(str)
|
140 |
|
141 | Decode [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.
|
142 |
|
143 | ``` js
|
144 | decodeURL('http://foo.com/b%C3%A1r')
|
145 | // http://foo.com/bár
|
146 |
|
147 | decodeURL('http://xn--br-mia.com/baz')
|
148 | // http://bár.com/baz
|
149 |
|
150 | decodeURL('/foo/b%C3%A1r/')
|
151 | // /foo/bár/
|
152 |
|
153 | /* Alternatively, Node 10+ offers native API to decode punycoded domain */
|
154 | const {format} = require('url')
|
155 | decodeURI(format(new URL('http://xn--br-mia.com.com/b%C3%A1r'), {unicode: true}))
|
156 | // http://bár.com/báz
|
157 | ```
|
158 |
|
159 | ### deepMerge(target, source)
|
160 |
|
161 | Merges the enumerable properties of two objects deeply. `target` and `source` remain untouched.
|
162 |
|
163 | ``` js
|
164 | // Merge deeply
|
165 | const obj1 = {a: {b: 1, c: 1, d: {e: 1, f: 1}}};
|
166 | const obj2 = {a: {b: 2, d: {f: 'f'} }};
|
167 |
|
168 | deepMerge(obj1, obj2);
|
169 | // {a: {b: 2, c: 1, d: {e: 1, f: 'f'} }}
|
170 | ```
|
171 |
|
172 | ``` js
|
173 | // Arrays will be combined in the same property, similar to lodash.merge
|
174 | const obj1 = { 'a': [{ 'b': 2 }, { 'd': 4 }] };
|
175 | const obj2 = { 'a': [{ 'c': 3 }, { 'e': 5 }] };
|
176 |
|
177 | deepMerge(obj1, obj2);
|
178 | // { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] };
|
179 | ```
|
180 |
|
181 | ### encodeURL(str)
|
182 |
|
183 | Encode URL or path into a [safe format](https://en.wikipedia.org/wiki/Percent-encoding).
|
184 |
|
185 | ``` js
|
186 | encodeURL('http://foo.com/bár')
|
187 | // http://foo.com/b%C3%A1r
|
188 |
|
189 | encodeURL('/foo/bár/')
|
190 | // /foo/b%C3%A1r/
|
191 | ```
|
192 |
|
193 | ### escapeDiacritic(str)
|
194 |
|
195 | Escapes diacritic characters in a string.
|
196 |
|
197 | ### escapeHTML(str)
|
198 |
|
199 | Escapes HTML entities in a string.
|
200 |
|
201 | ``` js
|
202 | escapeHTML('<p>Hello "world".</p>')
|
203 | // <p>Hello "world".</p>
|
204 |
|
205 | /* support escaped characters */
|
206 | escapeHTML('<foo>bar</foo>')
|
207 | // <foo>bar</foo>
|
208 | ```
|
209 |
|
210 | ### escapeRegex(str)
|
211 |
|
212 | Escapes special characters in a regular expression.
|
213 |
|
214 | ### full_url_for(path)
|
215 |
|
216 | Returns a url with the config.url prefixed. Output is [encoded](#encodeurlstr) automatically. Requires [`bind(hexo)`](#bindhexo).
|
217 |
|
218 | ``` yml
|
219 | _config.yml
|
220 | url: https://example.com/blog # example
|
221 | ```
|
222 |
|
223 | ``` js
|
224 | full_url_for('/a/path')
|
225 | // https://example.com/blog/a/path
|
226 | ```
|
227 |
|
228 | ### gravatar(str, [options])
|
229 |
|
230 | Returns the gravatar image url from an email.
|
231 |
|
232 | 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.
|
233 |
|
234 | Option | Description | Default
|
235 | --- | --- | ---
|
236 | `s` | Output image size | 80
|
237 | `d` | Default image |
|
238 | `f` | Force default |
|
239 | `r` | Rating |
|
240 |
|
241 | More info: [Gravatar](https://en.gravatar.com/site/implement/images/)
|
242 |
|
243 | ``` js
|
244 | gravatar('a@abc.com')
|
245 | // https://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787
|
246 | gravatar('a@abc.com', 40)
|
247 | // https://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40
|
248 | gravatar('a@abc.com' {s: 40, d: 'https://via.placeholder.com/150'})
|
249 | // https://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40&d=https%3A%2F%2Fvia.placeholder.com%2F150
|
250 | ```
|
251 |
|
252 | ### hash(str)
|
253 |
|
254 | Generates SHA1 hash.
|
255 |
|
256 | ``` js
|
257 | hash('123456');
|
258 | // <Buffer 7c 4a 8d 09 ca 37 62 af 61 e5 95 20 94 3d c2 64 94 f8 94 1b>
|
259 | ```
|
260 |
|
261 | ### HashStream()
|
262 | **\[deprecated\]** use [`createSha1Hash()`](#createsha1hash).
|
263 |
|
264 | Generates SHA1 hash with a transform stream.
|
265 |
|
266 | ``` js
|
267 | var stream = new HashStream();
|
268 |
|
269 | fs.createReadStream('/path/to/file')
|
270 | .pipe(stream)
|
271 | .on('finish', function(){
|
272 | console.log(stream.read());
|
273 | });
|
274 | ```
|
275 |
|
276 | ### highlight(str, [options])
|
277 |
|
278 | Syntax highlighting for a code block.
|
279 |
|
280 | Option | Description | Default
|
281 | --- | --- | ---
|
282 | `gutter` | Whether to show line numbers | true
|
283 | `wrap` | Whether to wrap the code block in [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table) | true
|
284 | `firstLine` | First line number | 1
|
285 | `hljs` | Whether to use the `hljs-*` prefix for CSS classes | false
|
286 | `lang` | Language |
|
287 | `caption` | Caption |
|
288 | `tab`| Replace tabs |
|
289 | `autoDetect` | Detect language automatically | false
|
290 | `mark` | Line highlight specific line(s) |
|
291 |
|
292 | ### htmlTag(tag, attrs, text, escape)
|
293 |
|
294 | Creates a html tag.
|
295 |
|
296 | Option | Description | Default
|
297 | --- | --- | ---
|
298 | `tag` | Tag / element name |
|
299 | `attrs` | Attribute(s) and its value.<br>Value is always [escaped](#escapehtmlstr), URL is always [encoded](#encodeurlstr). |
|
300 | `text` | Text, the value is always escaped<br>_(except for `<style>` tag)_ |
|
301 | `escape` | Whether to escape the text | true
|
302 |
|
303 | ``` js
|
304 | htmlTag('img', {src: 'example.png'})
|
305 | // <img src="example.png">
|
306 |
|
307 | htmlTag('a', {href: 'http://hexo.io/'}, 'Hexo')
|
308 | // <a href="http://hexo.io/">Hexo</a>
|
309 |
|
310 | htmlTag('link', {href: 'http://foo.com/'}, '<a>bar</a>')
|
311 | // <a href="http://foo.com/"><bar></a>
|
312 |
|
313 | htmlTag('a', {href: 'http://foo.com/'}, '<b>bold</b>', false)
|
314 | // <a href="http://foo.com/"><b>bold</b></a>
|
315 |
|
316 | /* text value of <style> won't be escaped, url is still encoded */
|
317 | htmlTag('style', {}, 'p { content: "<"; background: url("bár.jpg"); }')
|
318 | // <style>p { content: "<"; background: url("b%C3%A1r.jpg"); }</style>
|
319 |
|
320 | /* support script tag with async/defer */
|
321 | htmlTag('script', {src: '/foo.js', async: true}, '')
|
322 | // <script src="/foo.js" async></script>
|
323 | ```
|
324 |
|
325 | ### isExternalLink(url, sitehost, [exclude])
|
326 |
|
327 | Option | Description | Default
|
328 | --- | --- | ---
|
329 | `url` | The input URL. |
|
330 | `sitehost` | The hostname / url of website. You can also pass `hexo.config.url`. |
|
331 | `exclude` | Exclude hostnames. Specific subdomain is required when applicable, including www. | `[]`
|
332 |
|
333 | Returns if a given url is external link relative to given `sitehost` and `[exclude]`.
|
334 |
|
335 | ``` js
|
336 | // 'sitehost' can be a domain or url
|
337 | isExternalLink('https://example.com', 'example.com');
|
338 | // false
|
339 | isExternalLink('https://example.com', 'https://example.com');
|
340 | // false
|
341 | isExternalLink('https://example.com', '//example.com/blog/');
|
342 | // false
|
343 | ```
|
344 |
|
345 | ``` js
|
346 | isExternalLink('/archives/foo.html', 'example.com');
|
347 | // false
|
348 | isExternalLink('https://foo.com/', 'example.com');
|
349 | // true
|
350 | ```
|
351 |
|
352 | ``` js
|
353 | isExternalLink('https://foo.com', 'example.com', ['foo.com', 'bar.com']);
|
354 | // false
|
355 | isExternalLink('https://bar.com', 'example.com', ['foo.com', 'bar.com']);
|
356 | // false
|
357 | isExternalLink('https://baz.com/', 'example.com', ['foo.com', 'bar.com']);
|
358 | // true
|
359 | ```
|
360 |
|
361 |
|
362 | ### Pattern(rule)
|
363 |
|
364 | Parses the string and tests if the string matches the rule. `rule` can be a string, a regular expression or a function.
|
365 |
|
366 | ``` js
|
367 | var pattern = new Pattern('posts/:id');
|
368 |
|
369 | pattern.match('posts/89');
|
370 | // {0: 'posts/89', 1: '89', id: '89'}
|
371 | ```
|
372 |
|
373 | ``` js
|
374 | var pattern = new Pattern('posts/*path');
|
375 |
|
376 | pattern.match('posts/2013/hello-world');
|
377 | // {0: 'posts/2013/hello-world', 1: '2013/hello-world', path: '2013/hello-world'}
|
378 | ```
|
379 |
|
380 | ### Permalink(rule, [options])
|
381 |
|
382 | Parses a permalink.
|
383 |
|
384 | Option | Description
|
385 | --- | ---
|
386 | `segments` | Customize the rule of a segment in the permalink
|
387 |
|
388 | ``` js
|
389 | var permalink = new Permalink(':year/:month/:day/:title', {
|
390 | segments: {
|
391 | year: /(\d{4})/,
|
392 | month: /(\d{2})/,
|
393 | day: /(\d{2})/
|
394 | }
|
395 | });
|
396 |
|
397 | permalink.parse('2014/01/31/test');
|
398 | // {year: '2014', month: '01', day: '31', title: 'test'}
|
399 |
|
400 | permalink.test('2014/01/31/test');
|
401 | // true
|
402 |
|
403 | permalink.stringify({year: '2014', month: '01', day: '31', title: 'test'})
|
404 | // 2014/01/31/test
|
405 | ```
|
406 |
|
407 | ### prettyUrls(url, [options])
|
408 |
|
409 | Rewrite urls to pretty URLs.
|
410 |
|
411 | Option | Description | Default
|
412 | --- | --- | ---
|
413 | `trailing_index` | `/about/index.html -> /about/` when `false` | `true`
|
414 | `trailing_html` | `/about.html -> /about` when `false` | `true`
|
415 |
|
416 | Note: `trailing_html` ignores any link with a trailing `index.html`. (will not be rewritten to `index`).
|
417 |
|
418 | ``` js
|
419 | prettyUrls('/foo/bar.html');
|
420 | // /foo/bar.html
|
421 | prettyUrls('/foo/bar/index.html');
|
422 | // /foo/bar/index.html
|
423 |
|
424 | prettyUrls('/foo/bar.html', { trailing_index: false });
|
425 | // /foo/bar.html
|
426 | prettyUrls('/foo/bar/index.html', { trailing_index: false });
|
427 | // /foo/bar/
|
428 |
|
429 | prettyUrls('/foo/bar.html', { trailing_html: false });
|
430 | // /foo/bar
|
431 | prettyUrls('/foo/bar/index.html', { trailing_html: false });
|
432 | // /foo/bar/index.html
|
433 |
|
434 | prettyUrls('/foo/bar.html', { trailing_index: false, trailing_html: false });
|
435 | // /foo/bar
|
436 | prettyUrls('/foo/bar/index.html', { trailing_index: false, trailing_html: false });
|
437 | // /foo/bar/
|
438 | ```
|
439 |
|
440 | ### relative_url(from, to)
|
441 |
|
442 | Returns the relative URL from `from` to `to`. Output is [encoded](#encodeurlstr) automatically. Requires [`bind(hexo)`](#bindhexo).
|
443 |
|
444 | ``` js
|
445 | relative_url('foo/bar/', 'css/style.css')
|
446 | // ../../css/style.css
|
447 | ```
|
448 |
|
449 | ### slugize(str, [options])
|
450 |
|
451 | Transforms a string into a clean URL-friendly string.
|
452 |
|
453 | Option | Description | Default
|
454 | --- | --- | ---
|
455 | `separator` | Separator | -
|
456 | `transform` | Transform the string into lower case (`1`) or upper case (`2`) |
|
457 |
|
458 | ``` js
|
459 | slugize('Hello World') = 'Hello-World'
|
460 | slugize('Hellô Wòrld') = 'Hello-World'
|
461 | slugize('Hello World', {separator: '_'}) = 'Hello_World'
|
462 | slugize('Hello World', {transform: 1}) = 'hello-world'
|
463 | slugize('Hello World', {transform: 2}) = 'HELLO-WORLD'
|
464 | ```
|
465 |
|
466 | ### spawn(command, [args], [options])
|
467 |
|
468 | Launches a new process with the given `command`. This method returns a promise.
|
469 |
|
470 | Option | Description | Default
|
471 | --- | --- | ---
|
472 | `cwd` | Current working directory of the child process |
|
473 | `env` | Environment key-value pairs |
|
474 | `stdio` | Child's stdio configuration |
|
475 | `detached` | The child will be a process group leader |
|
476 | `uid` | Sets the user identity of the process |
|
477 | `gid` | Sets the group identity of the process |
|
478 | `verbose` | Display messages on the console | `false`
|
479 | `encoding` | Sets the encoding of the output string | `utf8`
|
480 |
|
481 | ``` js
|
482 | spawn('cat', 'test.txt').then(function(content){
|
483 | console.log(content);
|
484 | });
|
485 | ```
|
486 |
|
487 | ### stripHTML(str)
|
488 |
|
489 | Removes HTML tags in a string.
|
490 |
|
491 | ### wordWrap(str, [options])
|
492 |
|
493 | Wraps the string no longer than line width. This method breaks on the first whitespace character that does not exceed line width.
|
494 |
|
495 | Option | Description | Default
|
496 | --- | --- | ---
|
497 | `width` | Line width | 80
|
498 |
|
499 | ``` js
|
500 | wordWrap('Once upon a time')
|
501 | // Once upon a time
|
502 |
|
503 | 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...')
|
504 | // 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...
|
505 |
|
506 | wordWrap('Once upon a time', {width: 8})
|
507 | // Once\nupon a\ntime
|
508 |
|
509 | wordWrap('Once upon a time', {width: 1})
|
510 | // Once\nupon\na\ntime
|
511 | ```
|
512 |
|
513 | ### tocObj(str, [options])
|
514 |
|
515 | Generate a table of contents in JSON format based on the given html string.
|
516 |
|
517 | Option | Description | Default
|
518 | --- | --- | ---
|
519 | `min_depth` | The minimum level of TOC | 1
|
520 | `max_depth` | The maximum level of TOC | 6
|
521 |
|
522 |
|
523 | ``` js
|
524 | const html = [
|
525 | '<h1 id="title_1">Title 1</h1>',
|
526 | '<div id="title_1_1"><h2>Title 1.1</h2></div>',
|
527 | '<h3 id="title_1_1_1">Title 1.1.1</h3>',
|
528 | '<h2 id="title_1_2">Title 1.2</h2>',
|
529 | '<h2 id="title_1_3">Title 1.3</h2>',
|
530 | '<h3 id="title_1_3_1">Title 1.3.1</h3>',
|
531 | '<h1 id="title_2">Title 2</h1>',
|
532 | '<h2 id="title_2_1">Title 2.1</h2>'
|
533 | ].join('\n');
|
534 |
|
535 | tocObj(html);
|
536 | /*
|
537 | [
|
538 | { text: 'Title 1', id: 'title_1', level: 1 },
|
539 | { text: 'Title 1.1', id: 'title_1_1', level: 2 },
|
540 | { text: 'Title 1.1.1', id: 'title_1_1_1', level: 3 },
|
541 | { text: 'Title 1.2', id: 'title_1_2', level: 2 },
|
542 | { text: 'Title 1.3', id: 'title_1_3', level: 2 },
|
543 | { text: 'Title 1.3.1', id: 'title_1_3_1', level: 3 },
|
544 | { text: 'Title 2', id: 'title_2', level: 1 },
|
545 | { text: 'Title 2.1', id: 'title_2_1', level: 2 },
|
546 | ]
|
547 | */
|
548 |
|
549 | tocObj(html, { min_depth: 2 });
|
550 | /*
|
551 | [
|
552 | { text: 'Title 1.1', id: 'title_1_1', level: 2 },
|
553 | { text: 'Title 1.1.1', id: 'title_1_1_1', level: 3 },
|
554 | { text: 'Title 1.2', id: 'title_1_2', level: 2 },
|
555 | { text: 'Title 1.3', id: 'title_1_3', level: 2 },
|
556 | { text: 'Title 1.3.1', id: 'title_1_3_1', level: 3 },
|
557 | { text: 'Title 2.1', id: 'title_2_1', level: 2 },
|
558 | ]
|
559 | */
|
560 |
|
561 | tocObj(html, { max_depth: 2 });
|
562 | /*
|
563 | [
|
564 | { text: 'Title 1', id: 'title_1', level: 1 },
|
565 | { text: 'Title 1.1', id: 'title_1_1', level: 2 },
|
566 | { text: 'Title 1.2', id: 'title_1_2', level: 2 },
|
567 | { text: 'Title 1.3', id: 'title_1_3', level: 2 },
|
568 | { text: 'Title 2', id: 'title_2', level: 1 },
|
569 | { text: 'Title 2.1', id: 'title_2_1', level: 2 },
|
570 | ]
|
571 | */
|
572 | ```
|
573 |
|
574 | ### truncate(str, [options])
|
575 |
|
576 | 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`.
|
577 |
|
578 | Option | Description | Default
|
579 | --- | --- | ---
|
580 | `length` | Max length of the string | 30
|
581 | `omission` | Omission text | ...
|
582 | `separator` | truncate text at a natural break |
|
583 |
|
584 | ``` js
|
585 | truncate('Once upon a time in a world far far away')
|
586 | // "Once upon a time in a world..."
|
587 |
|
588 | truncate('Once upon a time in a world far far away', {length: 17})
|
589 | // "Once upon a ti..."
|
590 |
|
591 | truncate('Once upon a time in a world far far away', {length: 17, separator: ' '})
|
592 | // "Once upon a..."
|
593 |
|
594 | truncate('And they found that many people were sleeping better.', {length: 25, omission: '... (continued)'})
|
595 | // "And they f... (continued)"
|
596 | ```
|
597 |
|
598 | ### unescapeHTML(str)
|
599 |
|
600 | Unescapes HTML entities in a string.
|
601 |
|
602 | ``` js
|
603 | unescapeHTML('<p>Hello "world".</p>')
|
604 | // <p>Hello "world".</p>
|
605 | ```
|
606 |
|
607 | ### url_for(path, [option])
|
608 |
|
609 | Returns a url with the root path prefixed. Output is [encoded](#encodeurlstr) automatically. Requires [`bind(hexo)`](#bindhexo).
|
610 |
|
611 | Option | Description | Default
|
612 | --- | --- | ---
|
613 | `relative` | Output relative link | Value of `config.relative_link`
|
614 |
|
615 | ``` yml
|
616 | _config.yml
|
617 | root: /blog/ # example
|
618 | ```
|
619 |
|
620 | ``` js
|
621 | url_for('/a/path')
|
622 | // /blog/a/path
|
623 | ```
|
624 |
|
625 | Relative link, follows `relative_link` option by default
|
626 | e.g. post/page path is '/foo/bar/index.html'
|
627 |
|
628 | ``` yml
|
629 | _config.yml
|
630 | relative_link: true
|
631 | ```
|
632 |
|
633 | ``` js
|
634 | url_for('/css/style.css')
|
635 | // ../../css/style.css
|
636 |
|
637 | /* Override option
|
638 | * you could also disable it to output a non-relative link,
|
639 | * even when `relative_link` is enabled and vice versa.
|
640 | */
|
641 | url_for('/css/style.css', {relative: false})
|
642 | // /css/style.css
|
643 | ```
|
644 |
|
645 | ## bind(hexo)
|
646 |
|
647 | Following utilities require `bind(hexo)` / `bind(this)` / `call(hexo, input)` / `call(this, input)` to parse the user config when initializing:
|
648 | - [`full_url_for()`](#full_url_forpath)
|
649 | - [`url_for()`](#url_forpath)
|
650 | - [`relative_url()`](#relative_urlfrom-to)
|
651 |
|
652 | Below examples demonstrate different approaches to creating a [helper](https://hexo.io/api/helper) (each example is separated by `/******/`),
|
653 |
|
654 | ``` js
|
655 | // Single function
|
656 | const url_for = require('hexo-util').url_for.bind(hexo);
|
657 |
|
658 | hexo.extend.helper.register('test_url', (str) => {
|
659 | return url_for(str);
|
660 | })
|
661 |
|
662 |
|
663 | /******/
|
664 | // Multiple functions
|
665 | const url_for = require('hexo-util').url_for.bind(hexo)
|
666 |
|
667 | function testurlHelper(str) {
|
668 | return url_for(str);
|
669 | }
|
670 |
|
671 | hexo.extend.helper.register('test_url', testurlHelper);
|
672 |
|
673 |
|
674 | /******/
|
675 | // Functions separated into different files.
|
676 | // test_url.js
|
677 | module.exports = function(str) {
|
678 | const url_for = require('hexo-util').url_for.bind(this);
|
679 | return url_for(str);
|
680 | }
|
681 |
|
682 | // index.js
|
683 | hexo.extend.helper.register('test_url', require('./test_url'));
|
684 |
|
685 |
|
686 | /******/
|
687 | // Function.call() approach also works
|
688 | const {url_for} = require('hexo-util');
|
689 | module.exports = function(str) {
|
690 | return url_for.call(this, str);
|
691 | }
|
692 |
|
693 | hexo.extend.helper.register('test_url', require('./test_url'));
|
694 |
|
695 |
|
696 | /******/
|
697 | // Separating functions into individual files
|
698 | // Each file has multiple functions
|
699 | // test_url.js
|
700 | function testurlHelper(str) {
|
701 | const url_for = require('hexo-util').url_for.bind(this);
|
702 | return url_for(str);
|
703 | }
|
704 |
|
705 | module.exports = {
|
706 | testurlHelper: testurlHelper
|
707 | }
|
708 |
|
709 | // index.js
|
710 | hexo.extend.helper.register('test_url', require('./test_url').testurlHelper);
|
711 | ```
|
712 |
|
713 | ## License
|
714 |
|
715 | MIT
|
716 |
|
717 | [Hexo]: http://hexo.io/
|