1 |
|
2 |
|
3 |
|
4 | 'use strict';
|
5 |
|
6 | const chalk = require('chalk');
|
7 | const deepKeys = require('deep-keys');
|
8 | const log = require('fancy-log');
|
9 | const plumber = require('gulp-plumber');
|
10 | const without = require('lodash.without');
|
11 | const merge = require('merge-stream');
|
12 | const emoji = require('node-emoji');
|
13 | const prettyBytes = require('pretty-bytes');
|
14 | const stream = require('stream');
|
15 | const Vinyl = require('vinyl');
|
16 | const fss = require('@absolunet/fss');
|
17 | const { terminal } = require('@absolunet/terminal');
|
18 |
|
19 |
|
20 | class Toolbox {
|
21 |
|
22 |
|
23 | vinylStream(filename, string) {
|
24 | const source = stream.Readable({ objectMode: true });
|
25 |
|
26 | source._read = function() {
|
27 | this.push(new Vinyl({
|
28 | path: filename,
|
29 | contents: Buffer.from(string)
|
30 | }));
|
31 | this.push(null);
|
32 | };
|
33 |
|
34 | return source;
|
35 | }
|
36 |
|
37 |
|
38 |
|
39 | mergeStreams(streams) {
|
40 | return streams.length !== 0 ? merge(...streams) : this.selfClosingStream();
|
41 | }
|
42 |
|
43 |
|
44 |
|
45 | fakeStream(callback) {
|
46 | const fake = stream.Writable({ write: (chunk, encoding, callback2) => { callback2(); } });
|
47 |
|
48 | callback(() => {
|
49 | fake.end('End fake stream');
|
50 | });
|
51 |
|
52 | return fake;
|
53 | }
|
54 |
|
55 |
|
56 |
|
57 | selfClosingStream() {
|
58 | const selfClosing = stream.Writable({ write: (chunk, encoding, callback) => { callback(); } });
|
59 | selfClosing.end('End self-closing stream');
|
60 |
|
61 | return selfClosing;
|
62 | }
|
63 |
|
64 |
|
65 |
|
66 | gmOptimization(gmfile, info) {
|
67 | if (info.format === 'JPG') {
|
68 | gmfile.noProfile().quality(95);
|
69 | }
|
70 |
|
71 | if (info.format === 'PNG' && info.depth === 8) {
|
72 | gmfile.dither(false).colors(256);
|
73 | }
|
74 |
|
75 | return gmfile;
|
76 | }
|
77 |
|
78 |
|
79 |
|
80 | filesize(file) {
|
81 | return prettyBytes(fss.stat(file).size);
|
82 | }
|
83 |
|
84 |
|
85 |
|
86 | log(task, message, extra) {
|
87 | log(`${task}: ${message} ${extra ? chalk.dim(`(${extra})`) : ''}`);
|
88 | }
|
89 |
|
90 |
|
91 |
|
92 | plumber() {
|
93 | return plumber((error) => {
|
94 | terminal.spacer(2);
|
95 | terminal.echo(`${emoji.get('monkey')} ${error.toString()}`);
|
96 | terminal.exit();
|
97 | });
|
98 | }
|
99 |
|
100 |
|
101 |
|
102 | compareLists(assertion, expectation) {
|
103 | const superfluous = without(assertion, ...expectation);
|
104 | const missing = without(expectation, ...assertion);
|
105 |
|
106 | return {
|
107 | pass: superfluous.length === 0 && missing.length === 0,
|
108 | superfluous: superfluous,
|
109 | missing: missing
|
110 | };
|
111 | }
|
112 |
|
113 |
|
114 |
|
115 | flattenKeys(data, { depth = '' } = {}) {
|
116 | return deepKeys(data, true).filter((key) => {
|
117 | return new RegExp(`^[a-z0-9-]+(\\.[a-z0-9-]+){0,${depth}}$`, 'ui').test(key);
|
118 | });
|
119 | }
|
120 |
|
121 |
|
122 |
|
123 | isKebabCase(text) {
|
124 | return (/^(?<kebab1>[a-z][a-z0-9]*)(?<kebab2>-[a-z0-9]+)*$/u).test(text);
|
125 | }
|
126 |
|
127 | }
|
128 |
|
129 |
|
130 | module.exports = new Toolbox();
|