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