@massimo-cassandro/create-favicons 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.mjs ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+
3
+ /* eslint-disable no-console */
4
+ /* eslint-env node */
5
+
6
+
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+
10
+ import chalk from 'chalk';
11
+
12
+ import { createFavicons } from './src/create-favicons.mjs';
13
+ import { defaults } from './src/defaults.mjs';
14
+ import { init } from './src/init.mjs';
15
+
16
+ // nome del file di configurazione, se utilizzato
17
+ const cfg_filename = 'create-favicons-cfg.mjs';
18
+
19
+ try {
20
+
21
+ // init: creazione file cfg base
22
+ if(process.argv.indexOf('init') !== -1) {
23
+
24
+ init();
25
+
26
+ } else {
27
+
28
+ let params = {};
29
+ const dir_param_idx = process.argv.findIndex(el => /^--dir/.test(el) );
30
+
31
+ if(dir_param_idx !== -1) {
32
+ [, params.work_dir] = process.argv[dir_param_idx].split('=');
33
+
34
+ } else {
35
+ params.work_dir = './';
36
+ }
37
+
38
+ if(fs.existsSync(path.resolve(params.work_dir, cfg_filename))) {
39
+
40
+ import(path.resolve(params.work_dir, cfg_filename))
41
+ .then((custom_params) => {
42
+
43
+ if(Array.isArray(custom_params.default)) {
44
+
45
+ custom_params.default.forEach(item => {
46
+ createFavicons({ ...defaults, ...params, ...item });
47
+ });
48
+
49
+ } else {
50
+ createFavicons({ ...defaults, ...params, ...custom_params.default });
51
+ }
52
+ });
53
+
54
+ } else if(fs.existsSync(path.resolve(params.work_dir, defaults.src_img))) {
55
+
56
+ createFavicons({...defaults, ...params});
57
+
58
+ } else {
59
+
60
+ throw `'${cfg_filename}' e '${defaults.src_img}' non presenti`;
61
+ }
62
+
63
+ }
64
+
65
+
66
+
67
+ } catch(err) {
68
+ console.error(chalk.bgRed(`\n ${err} \n`));
69
+ }
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@massimo-cassandro/create-favicons",
3
+ "version": "1.1.0",
4
+ "description": "Favicon files builder",
5
+ "bin": {
6
+ "create-favicons": "./index.mjs"
7
+ },
8
+ "type": "module",
9
+ "scripts": {
10
+ "update-version": "node ./src/update-version/index.mjs",
11
+ "upd@m": "node ./src/upd@m/index.mjs",
12
+ "npm-publish": "npm publish"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+
18
+ "author": "Massimo Cassandro",
19
+ "license": "MIT",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/massimo-cassandro/create-favicons.git#main"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/massimo-cassandro/create-favicons/issues"
26
+ },
27
+ "homepage": "https://github.com/massimo-cassandro/create-favicons/tree/main#readme",
28
+ "eslintConfig": {
29
+ "extends": [
30
+ "./node_modules/@massimo-cassandro/linters-config/eslintrc.js"
31
+ ]
32
+ },
33
+ "stylelint": {
34
+ "extends": "@massimo-cassandro/linters-config/stylelintrc.js"
35
+ },
36
+ "files": [
37
+ "src/**/*",
38
+ "index.mjs"
39
+ ],
40
+ "engines": {
41
+ "node": ">= 18.0.0",
42
+ "npm": ">= 9.0.0"
43
+ },
44
+ "dependencies": {
45
+ "chalk": "^5.3.0",
46
+ "imagemin": "^8.0.1",
47
+ "imagemin-jpegtran": "^7.0.0",
48
+ "imagemin-pngquant": "^9.0.2",
49
+ "sharp": "^0.32.6",
50
+ "svgo": "^3.0.4",
51
+ "to-ico": "^1.1.5"
52
+ },
53
+ "devDependencies": {
54
+ "@massimo-cassandro/linters-config": "^1.6.1"
55
+ }
56
+ }
package/readme.md ADDED
@@ -0,0 +1,86 @@
1
+ # Create favicons
2
+
3
+ Crea i file favicons come descritto in [How to Favicon in 2024](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs).
4
+
5
+ Utilizzo:
6
+
7
+ ```bash
8
+ npx create-favicons [--dir=./path/to/dir]
9
+ ```
10
+
11
+ Lo script agisce normalmente nella directory corrente, ma, utilizzando il parametro opzionale `--dir`,
12
+ è possibile specificare una directory alternativa (percorso relativo alla dir di esecuzione).
13
+
14
+ Lo script in prima battuta cerca nella dir di lavoro il file `create-favicons-cfg.mjs` che contiene un oggetto
15
+ con tutti i parametri necessari (vedi di seguito).
16
+
17
+ In sua assenza, cerca il file `favicon-src.svg` da utilizzare come sorgente per tutte le immagini, e assumendo i valori di default (vedi dopo) per tutti gli altri parametri.
18
+
19
+ Tra gli altri, è possibile spcificare il parametro `small_src_img` nel caso sia necessario specificare un'immagine ottimizzata per le piccole dimensioni (32px).
20
+
21
+ Il formato migliore per i file sorgenti è SVG, o in alternativa PNG.
22
+
23
+ In assenza di entrambi i file viene restituito un errore.
24
+
25
+ I parametri di default sono elencati in dettaglio nel file `src/create-favicons/src/defaults.mjs`,
26
+ e possono essere personalizzati nel file di configurazione, che deve avere questa forma:
27
+
28
+ ```javascript
29
+ // file create-favicons-cfg.mjs
30
+ const params = [{ /* ... */ }];
31
+
32
+ export default params;
33
+ ```
34
+
35
+ `params` può essere un ogetto o un array. In quest'ultimo caso, ogni elemento dell'array corrisponde ad un diverso set di favicons.
36
+
37
+ Per creare un file di cfg di esempio **nella directory corrente** (con tutti i valori di default e la loro descrizione),
38
+ utilizzare il comando:
39
+
40
+ ```bash
41
+ npx create-favicons init
42
+ ```
43
+
44
+ ## Utilizzo da remoto
45
+
46
+ I comandi possono essere eseguiti anche senza installare preventivamente il package:
47
+
48
+ ```
49
+ npx --package=@massimo-cassandro/dev-utilities create-favicons init
50
+ npx --package=@massimo-cassandro/dev-utilities create-favicons [--dir=...]
51
+
52
+ ```
53
+
54
+ ## Esecuzione
55
+
56
+ Lo script produce le varie immagini png ed svg, il file `manifest.webmanifest` e uno snippet html (o nel linguaggio indicato nel parametro `snippet_language`).
57
+ Tutte le immagini vengono ottimizzate con [SVGO](https://github.com/svg/svgo) e [imagemin](https://github.com/imagemin/imagemin).
58
+
59
+ Tutti file vengono salvati nella dir indicata in `output_dir` (default: directory corrente).
60
+
61
+ Opzionalmente il file snippet può essere salvato in una directory differente (`snippet_path`) o si può decidere di non crearlo,
62
+ impostando il valore `snippet_name` a `null`.
63
+
64
+ Nel file di configurazione è anche possibile impostare il parametro `webmanifest_extra`, che permette di aggiungere voci aggiuntive al file *manifest*.
65
+ Per ulteriori info: <https://developer.mozilla.org/en-US/docs/Web/Manifest>
66
+
67
+ File generati:
68
+
69
+ ```html
70
+ <link rel="icon" href="/favicon.ico" sizes="any"> <!-- 32×32 + 16x16 -->
71
+ <link rel="icon" href="/icon.svg" type="image/svg+xml">
72
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png"> <!-- 180×180 -->
73
+ <link rel="manifest" href="/manifest.webmanifest">
74
+ ```
75
+
76
+ ```javascript
77
+ // manifest.webmanifest
78
+ {
79
+ "icons": [
80
+ { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
81
+ { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
82
+ ]
83
+ }
84
+ ```
85
+
86
+ Vedi anche esempio in <https://github.com/massimo-cassandro/dev-utilities/tree/main/test/test/create-favicons-test>.
@@ -0,0 +1,201 @@
1
+ /* eslint-disable no-console */
2
+
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import chalk from 'chalk';
6
+
7
+ import sharp from 'sharp';
8
+ import toIco from 'to-ico';
9
+ import { optimize } from 'svgo';
10
+ import imagemin from 'imagemin';
11
+ import imageminJpegtran from 'imagemin-jpegtran';
12
+ import imageminPngquant from 'imagemin-pngquant';
13
+
14
+ import { printFrame } from './print-frame.mjs';
15
+ import { remove_homedir_string } from './remove-homedir-string.mjs';
16
+
17
+
18
+ export function createFavicons(params) {
19
+
20
+ try {
21
+
22
+ const output_dir = path.resolve(params.work_dir, params.output_dir);
23
+
24
+ if (!fs.existsSync(output_dir)){
25
+ fs.mkdirSync(output_dir);
26
+ }
27
+
28
+
29
+ // https://sharp.pixelplumbing.com/api-constructor
30
+ Promise.all([
31
+ ['apple-touch-icon.png', 180],
32
+ ['icon-192.png', 192],
33
+ ['icon-512.png', 512]
34
+ ].map(size => {
35
+ sharp(path.resolve(params.work_dir, params.src_img))
36
+ .resize({ width: size[1], fit: 'inside' })
37
+ .png()
38
+ // .then(info => console.log(info))
39
+ // .toFile(`${output_dir}/${size[0]}`)
40
+ .toBuffer()
41
+ .then(bufferData => {
42
+
43
+ // ottimizzazione PNG / JPG
44
+ // https://github.com/imagemin/imagemin
45
+ // https://github.com/imagemin/imagemin-pngquant
46
+ // https://github.com/imagemin/imagemin-jpegtran
47
+ // https://web.dev/use-imagemin-to-compress-images/
48
+
49
+ imagemin.buffer(bufferData, {
50
+ plugins: [
51
+ imageminJpegtran(),
52
+ imageminPngquant({
53
+ quality: params.imagemin_png_quality,
54
+ dithering: false,
55
+ strip: true,
56
+ verbose: true
57
+ })
58
+ ]
59
+ }).then( result => {
60
+ fs.writeFileSync(`${output_dir}/${size[0]}`, result);
61
+ });
62
+
63
+ })
64
+ .catch(err => { throw err; });
65
+
66
+ }));
67
+
68
+ // favicon.ico
69
+ // https://github.com/kevva/to-ico
70
+ // alternativa: https://github.com/steambap/png-to-ico
71
+
72
+ // const ico_source = fs.readFileSync(`${output_dir}/apple-touch-icon.png`);
73
+
74
+ sharp(path.resolve(params.work_dir, params.small_src_img?? params.src_img))
75
+ .png()
76
+ // .then(info => console.log(info))
77
+ .toBuffer()
78
+ .then(bufferData => {
79
+
80
+ toIco([bufferData], {
81
+ sizes: [16, 32],
82
+ resize: true
83
+ }).then( result => {
84
+ fs.writeFileSync(`${output_dir}/favicon.ico`, result);
85
+ });
86
+
87
+ })
88
+ .catch(err => { throw err; });
89
+
90
+
91
+ // favicon.svg (SVGO)
92
+ // TODO add extra config ???
93
+ const svgString = fs.readFileSync(path.resolve(params.work_dir, params.small_src_img?? params.src_img), 'utf8');
94
+ const svg_result = optimize(svgString, {
95
+ multipass: true,
96
+ });
97
+ fs.writeFileSync(`${output_dir}/favicon.svg`, svg_result.data, {force: true});
98
+
99
+ // web manifest
100
+ const manifest = {
101
+ icons: [192, 512].map( size => {
102
+ return { src: `./icon-${size}.png`, type: 'image/png', sizes: `${size}x${size}` };
103
+ }),
104
+ ...(params.webmanifest_extra?? {})
105
+ };
106
+
107
+ fs.writeFileSync(`${output_dir}/manifest.webmanifest`, JSON.stringify(manifest, null, ' '));
108
+
109
+
110
+ const snippet_path = params.snippet_path? path.resolve(params.work_dir, params.snippet_path) : output_dir;
111
+
112
+ // snippet
113
+ if(params.snippet_name || params.snippet_target_file) {
114
+
115
+ if (!params.snippet_target_file && !fs.existsSync(snippet_path)){
116
+ fs.mkdirSync(snippet_path);
117
+ }
118
+
119
+ params.snippet_language = params.snippet_language.toLowerCase();
120
+
121
+ const cache_buster = params.add_cache_buster? `?_=${Date.now()}` : '',
122
+ create_href = nome_file => params.href_template.replace('%_file_name_%', nome_file)
123
+ .replace('%_cache_buster_%', cache_buster);
124
+
125
+
126
+ let snippet_content = `<link rel="icon" href="${create_href('favicon.ico')}" sizes="any">\n` +
127
+ `<link rel="icon" href="${create_href('favicon.svg')}" type="image/svg+xml">\n` +
128
+ `<link rel="apple-touch-icon" href="${create_href('apple-touch-icon.png')}">\n` +
129
+ `<link rel="manifest" href="${create_href('manifest.webmanifest')}">`;
130
+
131
+ if (params.snippet_language === 'pug') {
132
+ snippet_content = snippet_content.replace(/<link (.*?)>/g, 'link($1)');
133
+ }
134
+
135
+ snippet_content = params.snippet_template.replace('%_link_tags_%', snippet_content);
136
+
137
+ if (params.snippet_target_file) {
138
+
139
+ params.snippet_target_file = path.resolve(params.work_dir, params.snippet_target_file);
140
+
141
+ if (fs.existsSync(params.snippet_target_file)) {
142
+ const targetFileContent = fs.readFileSync(path.resolve(params.snippet_target_file), 'utf8'),
143
+ regexp = /<!-- ?favicon-snippet-start ?-->(.*?)<!-- ?favicon-snippet-end ?-->/mis;
144
+
145
+ fs.writeFileSync(params.snippet_target_file,
146
+ targetFileContent.replace(regexp,
147
+ `<!-- favicon-snippet-start -->\n${snippet_content}\n<!-- favicon-snippet-end -->`
148
+ )
149
+ );
150
+
151
+ } else {
152
+ throw `Il file '${params.snippet_target_file}' non esiste`;
153
+ }
154
+
155
+ } else {
156
+
157
+ fs.writeFileSync(
158
+ `${snippet_path}/${params.snippet_name}`,
159
+ snippet_content
160
+ );
161
+
162
+ }
163
+ }
164
+
165
+ // print result
166
+ let extra_strings = [];
167
+
168
+ if(snippet_path !== output_dir && params.snippet_name !== null) {
169
+ extra_strings = [
170
+ {string: ''},
171
+ {string: `Il file snippet '${params.snippet_name}' è stato salvato nella directory:`, color: 'green'},
172
+ {string: remove_homedir_string(snippet_path), color: 'yellow'},
173
+ ];
174
+
175
+ } else if(params.snippet_name === null) {
176
+ extra_strings = [
177
+ {string: ''},
178
+ {string: 'Il file snippet non è stato generato', color: 'magentaBright'},
179
+ ];
180
+ }
181
+
182
+
183
+ printFrame({
184
+ strings: [
185
+ {string: '** Creazione favicons completata **', color: 'bgGreen'},
186
+ {string: ''},
187
+ {string: 'I file generati sono nella directory:', color: 'green'},
188
+ {string: remove_homedir_string(output_dir), color: 'yellow'},
189
+ ...extra_strings
190
+ ],
191
+ frameColor: 'green',
192
+ frameType: 'single'
193
+ });
194
+
195
+
196
+ } catch(err) {
197
+
198
+ console.error(chalk.bgRed(` ${err} `));
199
+ }
200
+
201
+ }
@@ -0,0 +1,90 @@
1
+ export const defaults = {
2
+
3
+ // delimitazione porzione da copiare nel file init
4
+ /*** INIT START ***/
5
+
6
+ // tutti i percorsi sono relativi alla dir di lavoro
7
+
8
+ // immagine sorgente SVG o PNG 512x512
9
+ src_img: 'favicon-src.svg',
10
+
11
+ // sorgente opzionale per immagini piccole (32px)
12
+ small_src_img: null,
13
+
14
+ // directory output (percorso relativo alla dir di lavoro)
15
+ // se la dir non esiste, viene creata
16
+ output_dir: 'favicons-output',
17
+
18
+
19
+ // WEBMANIFEST
20
+ //****************************************************************************
21
+ // chiavi aggiuntive per webmanifest, normalmente non necessarie per il browser
22
+ // vedi https://developer.mozilla.org/en-US/docs/Web/Manifest
23
+ // esempio:
24
+ // webmanifest_extra: {
25
+ // name: "my Application",
26
+ // short_name: "my app",
27
+ // background_color: "#ffffff",
28
+ // theme_color: "#ffffff",
29
+ // display: "fullscreen"
30
+ // }
31
+ webmanifest_extra: null,
32
+
33
+
34
+ // SNIPPET
35
+ //****************************************************************************
36
+
37
+ // nome del file snippet, compresa l'estensione
38
+ // se questo parametro è null e anche `snippet_target_file` lo è, lo snippet non viene generato
39
+ snippet_name: 'favicon.html',
40
+
41
+ // path (relativo a questo file) in cui salvare lo snippet
42
+ // se null, viene utilizzato lo stesso percorso indicato in `output_dir`
43
+ // se la dir non esiste, viene creata
44
+ snippet_path: null,
45
+
46
+ // path del file in cui scrivere le righe dello snippet
47
+ // questa impostazione è alternativa alle due precedenti e, se presente, queste
48
+ // ultime vengono ignorate.
49
+ // Per utilizzarla, le va assegnato il percorso del file (già esistente) nel quale
50
+ // scrivere le righe delle snippet.
51
+ // Il file deve contenere dei segnaposti per contrassegnare lo spazio entro il quale
52
+ // scrivere lo snippets
53
+ // <!-- favicon-snippet-start --><!-- favicon-snippet-end -->
54
+ snippet_target_file: null,
55
+
56
+ // linguaggio da utilizzare per la sintassi dello snippet html
57
+ // html o pug
58
+ snippet_language: 'html',
59
+
60
+ // template per la costruzione dello snippet.
61
+ // si tratta di una stringa (anche su più righe) in cui deve essere presente
62
+ // '%_link_tags_%', che verrà sostituito con i tag links dei vari file
63
+ snippet_template: '%_link_tags_%',
64
+
65
+ // template per la costruzione di ogni singolo attributo `href` dei tag link.
66
+ // deve contenere la stringa '%_file_name_%', che conterrà il nome del file,
67
+ // e la stringa '%_cache_buster_%' (se attivata)', che conterrà `?_=xxxx`, dove
68
+ // 'xxxx' rappresenta il timestamp generato per annullare la cache.
69
+ // Va scritto tenendo conto del linguaggio utilizzato.
70
+ href_template: '/%_file_name_%%_cache_buster_%',
71
+
72
+ // se true aggiunge allo snippet una query string per ovviare ad eventuali
73
+ // problemi di caching del browser
74
+ add_cache_buster: false,
75
+
76
+
77
+ // IMAGEMIN PARAMETERS
78
+ //****************************************************************************
79
+ // parametri per i file PNG
80
+ // vedi https://www.npmjs.com/package/imagemin-pngquant
81
+ // Instructs pngquant to use the least amount of colors required to meet or
82
+ // exceed the max quality. If conversion results in quality below the min quality
83
+ // the image won't be saved.
84
+ // Min and max are numbers in range 0 (worst) to 1 (perfect), similar to JPEG.
85
+ imagemin_png_quality: [0.3, 0.6]
86
+
87
+
88
+ /*** INIT END ***/
89
+
90
+ };
@@ -0,0 +1,16 @@
1
+ /*
2
+ File di configurazione per `create-favicons`.
3
+
4
+ I valori indicati sono quelli di default.
5
+ Per avviare la generazione delle favicon digitare
6
+
7
+ npx create-favicons
8
+
9
+ dalla directory che contiene questo file.
10
+
11
+ Creazione favicons (senza installare il package nel progetto):
12
+ npx --package=@massimo-cassandro/create-favicons create-favicons (dalla dir corrente)
13
+
14
+ Altre info: https://github.com/massimo-cassandro/create-favicons
15
+
16
+ */
package/src/init.mjs ADDED
@@ -0,0 +1,51 @@
1
+ /* eslint-env node */
2
+
3
+ import { URL } from 'url';
4
+ import * as fs from 'fs';
5
+
6
+
7
+ import { printFrame } from './print-frame.mjs';
8
+ import { remove_homedir_string } from './remove-homedir-string.mjs';
9
+
10
+ export function init() {
11
+ // const __filename = new URL('', import.meta.url).pathname;
12
+ // Will contain trailing slash
13
+ const src_dir = new URL('.', import.meta.url).pathname,
14
+ cfg_sample_file = process.cwd() + '/create-favicons-cfg.mjs';
15
+
16
+ if(fs.existsSync(cfg_sample_file)) {
17
+ throw `${cfg_sample_file} già presente`;
18
+ }
19
+
20
+
21
+ let default_params = fs.readFileSync(src_dir + './defaults.mjs', 'UTF8');
22
+
23
+ const start_string = '/*** INIT START ***/',
24
+ end_string = '/*** INIT END ***/',
25
+ init_start_text = fs.readFileSync(src_dir +'./init-start.txt', 'utf8');
26
+
27
+
28
+
29
+ default_params = default_params.substring(
30
+ default_params.indexOf(start_string) + start_string.length, //from
31
+ default_params.indexOf(end_string)
32
+ );
33
+
34
+ fs.writeFileSync(
35
+ cfg_sample_file,
36
+ init_start_text.trim() + '\n\n' +
37
+ 'const params = [{\n' +
38
+ default_params +
39
+ '\n}];\n\n' +
40
+ 'export default params;'
41
+ );
42
+
43
+ printFrame({
44
+ strings: [
45
+ {string: 'File di configurazione di generato:', color: 'green'},
46
+ {string: remove_homedir_string(cfg_sample_file), color: 'bgGreen'},
47
+ ],
48
+ frameColor: 'green',
49
+ frameType: 'double'
50
+ });
51
+ }
@@ -0,0 +1,51 @@
1
+ /* eslint-disable no-console */
2
+ import chalk from 'chalk';
3
+
4
+ export function printFrame(options) {
5
+
6
+ /*
7
+ stringsArray = [
8
+ {string: '__string__', color: 'green', bg: false, bold: false, underline: false},
9
+ {...}
10
+ ]
11
+ */
12
+
13
+ const defaults = {
14
+ strings: [],
15
+ frameColor: 'green',
16
+ frametype: 'single'
17
+ },
18
+ string_defaults = { string: '', color: 'green', bg: false, bold: false, underline: false},
19
+ frame_lines = {
20
+ single: ['┌', '┐', '└', '┘', '┈', '│'],
21
+ double: ['╔', '╗', '╚', '╝', '═', '║']
22
+ };
23
+
24
+ options = {...defaults, ...options};
25
+
26
+ const frames_elements = frame_lines[options.frametype];
27
+
28
+ options.strings = options.strings.map(item => {return {...string_defaults, ...item }; });
29
+
30
+ // TODO bold underline ecc...
31
+ // aggiunta spazi sulle righe `bg`
32
+ options.strings.forEach(item => {
33
+ if(/^bg/.test(item.color)) {
34
+ item.string = ` ${item.string} `;
35
+ }
36
+ });
37
+
38
+ const total_length = Math.max( ...(options.strings.map(item => item.string.length)) ) + 2;
39
+
40
+ console.log( chalk[options.frameColor]( `\n${frames_elements[0]}` + frames_elements[4].repeat(total_length) + frames_elements[1]) );
41
+
42
+ options.strings.forEach(item => {
43
+ console.log(
44
+ chalk[options.frameColor](`${frames_elements[5]} `) +
45
+ chalk[item.color](item.string) + ' '.repeat(total_length - item.string.length - 2) +
46
+ chalk[options.frameColor](` ${frames_elements[5]}`)
47
+ );
48
+ });
49
+
50
+ console.log( chalk[options.frameColor]( frames_elements[2] + frames_elements[4].repeat(total_length) + `${frames_elements[3]}\n` ) );
51
+ }
@@ -0,0 +1,9 @@
1
+ // rimuove la porzione homedir da un path e la sostituisce con '~'
2
+
3
+ import {homedir} from 'os';
4
+
5
+ export function remove_homedir_string(path) {
6
+ const homeDirRegex = new RegExp('^' + homedir());
7
+
8
+ return path.replace(homeDirRegex, '~');
9
+ }