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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chokibasic",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "description": "Basic chokidar watcher + pxpros + esbuild + sass + csso helpers",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/src/buildjs.js CHANGED
@@ -14,6 +14,7 @@ const buildJS = async (entry, outfile, options = {}) => {
14
14
  supported: { "template-literal": false },
15
15
  target: ["es2020"],
16
16
  legalComments: "none",
17
+ loader: { '.json': 'json' },
17
18
  ...options
18
19
  });
19
20
  console.log(`✅ JS generated: ${outfile}`);
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) => fsprom.rm(path.join(dir, e.name), { recursive: true, force: true })));
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); // "Samedi"
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
- ig.add(txt);
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
- // on ignore aussi le dossier dist par sécurité (pas nécessaire mais sain)
55
+
56
+ // Toujours ignorer dist (relatif ROOT → on garde tel quel)
47
57
  ig.add('dist/');
48
- return ig;
49
- }
50
58
 
51
- async function rmDir(dir) {
52
- await fsprom.rm(dir, { recursive: true, force: true });
53
- await fsprom.mkdir(dir, { recursive: true });
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(relFromRoot, absPath) {
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 relFromRoot = path.relative(ROOT, absSrc);
68
- const relPosix = norm(relFromRoot);
79
+ const relPosix = norm(relFromSrc);
69
80
 
70
- // 1) Exclusions via .gitignore
81
+ // 1) ignore basé sur src
71
82
  if (ig.ignores(relPosix)) return false;
72
83
 
73
- // 2) Exclusions spécifiques (scss, js non minifiés)
84
+ // 2) exclusions internes
74
85
  if (shouldExcludeFile(relPosix, absSrc)) return false;
75
86
 
76
87
  const absDst = path.join(dist, relFromSrc);
77
- // console.log(absDst);
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
- const bannerContent = (await fsprom.readFile(banner || path.join(__dirname, 'banner.txt'), 'utf8')).replace(/###DATE###/, formatFrDate());
86
- const today = (d => `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`)(new Date());
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 relFromRoot = path.relative(ROOT, abs);
91
- const relPosix = norm(relFromRoot);
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
- } else if (de.isFile()) {
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
- if (lower.endsWith('.js')) await fsprom.writeFile(copied, "/*!\n\n" + bannerContent + "\n\n*/\n" + (await fsprom.readFile(copied, 'utf8')), "utf8");
103
- else if (lower.endsWith('.css')) await fsprom.writeFile(copied, "/*!\n\n" + bannerContent + "\n\n*/\n" + (await fsprom.readFile(copied, 'utf8')), "utf8");
104
- else if (lower.endsWith('.html')) await fsprom.writeFile(copied, "<!--\n\n" + bannerContent + "\n\n\-->\n" + (await fsprom.readFile(copied, 'utf8'))
105
- .replaceAll(/###YEAR###/g, (new Date).getFullYear())
106
- .replaceAll(/###TIMESTAMP###/g, Math.floor(Date.now() / 1000)), "utf8");
107
- else if (lower.endsWith('sitemap.xml')) await fsprom.writeFile(copied, (await fsprom.readFile(copied, 'utf8')).replaceAll(/###TODAY###/g, today), "utf8");
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 stats.skipped++;
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
- if (!fs.existsSync(src)) throw new error('Folder src is invalid.');
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 error(err);
185
+ throw new Error(err);
130
186
  }
131
- }
132
-
187
+ };
133
188
 
134
- module.exports = { exportDist };
189
+ module.exports = { exportDist };