chokibasic 1.1.10 → 1.1.12
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.d.ts +11 -1
- package/package.json +1 -1
- package/src/buildjs.js +1 -0
- package/src/export.js +99 -44
package/index.d.ts
CHANGED
|
@@ -87,6 +87,13 @@ declare namespace chokibasic {
|
|
|
87
87
|
skipped: number;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
export interface ExportDistOptions {
|
|
91
|
+
ignore?: string[];
|
|
92
|
+
include?: string[];
|
|
93
|
+
debug?: boolean;
|
|
94
|
+
filter?: (relPath: string) => boolean;
|
|
95
|
+
}
|
|
96
|
+
|
|
90
97
|
/** Options forwardées à esbuild.build() */
|
|
91
98
|
export type BuildJSOptions = Parameters<typeof import("esbuild").build>[0];
|
|
92
99
|
|
|
@@ -107,9 +114,12 @@ declare namespace chokibasic {
|
|
|
107
114
|
export function exportDist(
|
|
108
115
|
src: string,
|
|
109
116
|
dist: string,
|
|
110
|
-
banner?: string | null
|
|
117
|
+
banner?: string | null,
|
|
118
|
+
options?: ExportDistOptions
|
|
111
119
|
): Promise<ExportDistStats>;
|
|
112
120
|
|
|
121
|
+
|
|
122
|
+
|
|
113
123
|
/**
|
|
114
124
|
* Compile SCSS -> CSS minifié (csso), écrit dans outCssMin.
|
|
115
125
|
*/
|
package/package.json
CHANGED
package/src/buildjs.js
CHANGED
package/src/export.js
CHANGED
|
@@ -5,14 +5,14 @@ const path = require("path");
|
|
|
5
5
|
|
|
6
6
|
const ROOT = process.cwd();
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
async function emptyDir(dir) {
|
|
10
9
|
await fsprom.mkdir(dir, { recursive: true });
|
|
11
10
|
const entries = await fsprom.readdir(dir, { withFileTypes: true });
|
|
12
|
-
await Promise.all(entries.map((e) =>
|
|
11
|
+
await Promise.all(entries.map((e) =>
|
|
12
|
+
fsprom.rm(path.join(dir, e.name), { recursive: true, force: true })
|
|
13
|
+
));
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
|
|
16
16
|
function formatFrDate(dateInput = new Date(), timeZone = 'America/Toronto') {
|
|
17
17
|
const d = (dateInput instanceof Date) ? dateInput : new Date(dateInput);
|
|
18
18
|
const fmt = new Intl.DateTimeFormat('fr-CA', {
|
|
@@ -26,109 +26,164 @@ function formatFrDate(dateInput = new Date(), timeZone = 'America/Toronto') {
|
|
|
26
26
|
timeZone
|
|
27
27
|
});
|
|
28
28
|
const parts = Object.fromEntries(fmt.formatToParts(d).map(p => [p.type, p.value]));
|
|
29
|
-
const weekday = parts.weekday.charAt(0).toUpperCase() + parts.weekday.slice(1);
|
|
29
|
+
const weekday = parts.weekday.charAt(0).toUpperCase() + parts.weekday.slice(1);
|
|
30
30
|
return `${weekday} le ${parts.day} ${parts.month} ${parts.year} à ${parts.hour} h ${parts.minute}`;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
34
33
|
function norm(p) {
|
|
35
|
-
// normalise en chemin POSIX pour compat .gitignore
|
|
36
34
|
return p.split(path.sep).join('/');
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
async function loadGitignore() {
|
|
37
|
+
async function loadGitignore(src, extraPatterns = []) {
|
|
40
38
|
const ig = ignore();
|
|
41
39
|
const giPath = path.join(ROOT, '.gitignore');
|
|
40
|
+
|
|
42
41
|
if (fs.existsSync(giPath)) {
|
|
43
42
|
const txt = await fsprom.readFile(giPath, 'utf8');
|
|
44
|
-
|
|
43
|
+
|
|
44
|
+
// ⚠️ IMPORTANT: on convert les patterns ROOT → relatifs à src
|
|
45
|
+
const lines = txt.split('\n')
|
|
46
|
+
.map(l => l.trim())
|
|
47
|
+
.filter(l => l && !l.startsWith('#'))
|
|
48
|
+
.map(l => {
|
|
49
|
+
// enlever "/" initial si présent
|
|
50
|
+
return l.replace(/^\//, '');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
ig.add(lines);
|
|
45
54
|
}
|
|
46
|
-
|
|
55
|
+
|
|
56
|
+
// Toujours ignorer dist (relatif ROOT → on garde tel quel)
|
|
47
57
|
ig.add('dist/');
|
|
48
|
-
return ig;
|
|
49
|
-
}
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
// 👇 Patterns custom (déjà relatifs à src)
|
|
60
|
+
if (Array.isArray(extraPatterns)) {
|
|
61
|
+
ig.add(extraPatterns);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return ig;
|
|
54
65
|
}
|
|
55
66
|
|
|
56
|
-
function shouldExcludeFile(
|
|
57
|
-
// Exclusions de type/extension
|
|
67
|
+
function shouldExcludeFile(relFromSrc, absPath) {
|
|
58
68
|
const lower = absPath.toLowerCase();
|
|
69
|
+
|
|
59
70
|
if (path.basename(lower).startsWith('_')) return true;
|
|
60
71
|
if (lower.endsWith('.scss')) return true;
|
|
61
72
|
if (lower.endsWith('.js') && !lower.endsWith('.min.js')) return true;
|
|
73
|
+
|
|
62
74
|
return false;
|
|
63
75
|
}
|
|
64
76
|
|
|
65
77
|
async function copyFilePreserveTree(absSrc, src, dist, ig) {
|
|
66
78
|
const relFromSrc = path.relative(src, absSrc);
|
|
67
|
-
const
|
|
68
|
-
const relPosix = norm(relFromRoot);
|
|
79
|
+
const relPosix = norm(relFromSrc);
|
|
69
80
|
|
|
70
|
-
// 1)
|
|
81
|
+
// 1) ignore basé sur src
|
|
71
82
|
if (ig.ignores(relPosix)) return false;
|
|
72
83
|
|
|
73
|
-
// 2)
|
|
84
|
+
// 2) exclusions internes
|
|
74
85
|
if (shouldExcludeFile(relPosix, absSrc)) return false;
|
|
75
86
|
|
|
76
87
|
const absDst = path.join(dist, relFromSrc);
|
|
77
|
-
|
|
88
|
+
|
|
78
89
|
await fsprom.mkdir(path.dirname(absDst), { recursive: true });
|
|
79
90
|
await fsprom.copyFile(absSrc, absDst);
|
|
91
|
+
|
|
80
92
|
return absDst;
|
|
81
93
|
}
|
|
82
94
|
|
|
83
95
|
async function walkAndCopy(dir, src, dest, ig, stats, banner = null) {
|
|
84
96
|
const entries = await fsprom.readdir(dir, { withFileTypes: true });
|
|
85
|
-
|
|
86
|
-
const
|
|
97
|
+
|
|
98
|
+
const bannerContent = (await fsprom.readFile(
|
|
99
|
+
banner || path.join(__dirname, 'banner.txt'),
|
|
100
|
+
'utf8'
|
|
101
|
+
)).replace(/###DATE###/, formatFrDate());
|
|
102
|
+
|
|
103
|
+
const today = (d =>
|
|
104
|
+
`${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`
|
|
105
|
+
)(new Date());
|
|
87
106
|
|
|
88
107
|
for (const de of entries) {
|
|
89
108
|
const abs = path.join(dir, de.name);
|
|
90
|
-
const
|
|
91
|
-
const relPosix = norm(
|
|
109
|
+
const relFromSrc = path.relative(src, abs);
|
|
110
|
+
const relPosix = norm(relFromSrc);
|
|
92
111
|
|
|
93
112
|
if (de.isDirectory()) {
|
|
94
|
-
// Si le dossier est ignoré par .gitignore, on ne descend pas
|
|
95
113
|
if (ig.ignores(relPosix + '/')) continue;
|
|
96
|
-
if(de.name.startsWith('_')) continue;
|
|
114
|
+
if (de.name.startsWith('_')) continue;
|
|
115
|
+
|
|
97
116
|
await walkAndCopy(abs, src, dest, ig, stats, banner);
|
|
98
|
-
}
|
|
117
|
+
}
|
|
118
|
+
else if (de.isFile()) {
|
|
99
119
|
const copied = await copyFilePreserveTree(abs, src, dest, ig);
|
|
120
|
+
|
|
100
121
|
if (copied) {
|
|
101
122
|
const lower = abs.toLowerCase();
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
123
|
+
|
|
124
|
+
if (lower.endsWith('.js')) {
|
|
125
|
+
await fsprom.writeFile(
|
|
126
|
+
copied,
|
|
127
|
+
"/*!\n\n" + bannerContent + "\n\n*/\n" +
|
|
128
|
+
(await fsprom.readFile(copied, 'utf8')),
|
|
129
|
+
"utf8"
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
else if (lower.endsWith('.css')) {
|
|
133
|
+
await fsprom.writeFile(
|
|
134
|
+
copied,
|
|
135
|
+
"/*!\n\n" + bannerContent + "\n\n*/\n" +
|
|
136
|
+
(await fsprom.readFile(copied, 'utf8')),
|
|
137
|
+
"utf8"
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
else if (lower.endsWith('.html')) {
|
|
141
|
+
await fsprom.writeFile(
|
|
142
|
+
copied,
|
|
143
|
+
"<!--\n\n" + bannerContent + "\n\n-->\n" +
|
|
144
|
+
(await fsprom.readFile(copied, 'utf8'))
|
|
145
|
+
.replaceAll(/###YEAR###/g, (new Date).getFullYear())
|
|
146
|
+
.replaceAll(/###TIMESTAMP###/g, Math.floor(Date.now() / 1000)),
|
|
147
|
+
"utf8"
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
else if (lower.endsWith('sitemap.xml')) {
|
|
151
|
+
await fsprom.writeFile(
|
|
152
|
+
copied,
|
|
153
|
+
(await fsprom.readFile(copied, 'utf8'))
|
|
154
|
+
.replaceAll(/###TODAY###/g, today),
|
|
155
|
+
"utf8"
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
108
159
|
stats.copied++;
|
|
109
160
|
}
|
|
110
|
-
else
|
|
161
|
+
else {
|
|
162
|
+
stats.skipped++;
|
|
163
|
+
}
|
|
111
164
|
}
|
|
112
|
-
// (symlinks & autres: ignorés)
|
|
113
165
|
}
|
|
114
166
|
}
|
|
115
167
|
|
|
116
|
-
|
|
117
|
-
const exportDist = async (src, dist, banner = null) => {
|
|
168
|
+
const exportDist = async (src, dist, banner = null, options = {}) => {
|
|
118
169
|
try {
|
|
119
|
-
const ig = await loadGitignore();
|
|
170
|
+
const ig = await loadGitignore(src, options.ignore || []);
|
|
120
171
|
|
|
121
172
|
await emptyDir(dist);
|
|
122
|
-
|
|
173
|
+
|
|
174
|
+
if (!fs.existsSync(src)) {
|
|
175
|
+
throw new Error('Folder src is invalid.');
|
|
176
|
+
}
|
|
123
177
|
|
|
124
178
|
const stats = { copied: 0, skipped: 0 };
|
|
179
|
+
|
|
125
180
|
await walkAndCopy(src, src, dist, ig, stats, banner);
|
|
126
181
|
|
|
127
182
|
return stats;
|
|
183
|
+
|
|
128
184
|
} catch (err) {
|
|
129
|
-
throw new
|
|
185
|
+
throw new Error(err);
|
|
130
186
|
}
|
|
131
|
-
}
|
|
132
|
-
|
|
187
|
+
};
|
|
133
188
|
|
|
134
|
-
module.exports = { exportDist };
|
|
189
|
+
module.exports = { exportDist };
|