vivth 1.5.8 → 1.5.10

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/README.md CHANGED
@@ -770,6 +770,9 @@ body {
770
770
  - files extention:
771
771
  > - `js`/`ts` files will be compiled with `vivth/node.EsWathcer`, using `option.esbuild` as argument;
772
772
  > - `sass`/`scss` it will be compiled to `css` first;
773
+ > - `html` will be checked for `script`;
774
+ > > - has `[type="module]"`: will be processed as `esm`;
775
+ > > - has `[minify="true"]`: will be minified;
773
776
  > - other than those files, they will be just copied to `targetPaths`;
774
777
  - for runtime example see file `/dev/auto/` on source code;
775
778
 
@@ -5383,9 +5386,7 @@ A type-safe `typeof` helper.
5383
5386
  ```js
5384
5387
  /**
5385
5388
  * @template {keyof typeof TypeMap} K
5386
- * @param {unknown} object - The value to check.
5387
- * @param {K} type - The type string to compare against.
5388
- * @returns {object is typeof TypeMap[K]} - Returns true if the type matches, narrowing the type.
5389
+ * @typedef {import('./IsTypeOf.mts').IsTypeOf<K>} IsTypeOf
5389
5390
  */
5390
5391
  ```
5391
5392
 
@@ -6113,48 +6114,33 @@ const effer = newDerived(async ({ subscribe }) => {
6113
6114
 
6114
6115
  #### reference: `VivthyNeinth_instance.onMutate`
6115
6116
 
6117
+ - manually registering object celeanup;
6118
+
6116
6119
  ```js
6117
6120
  /**
6118
- * @type {Set<()=>Promise<void>>}
6121
+ * @param {()=>Promise<void>} callback
6122
+ * @returns {void}
6119
6123
  */
6120
6124
  ```
6121
6125
 
6122
6126
  - <i>example</i>:
6123
6127
 
6124
6128
  ```js
6125
- import { watch } from "chokidar";
6126
- /// on VivthyNeinth arg callback scope
6127
- const { onCleanups } = this;
6128
- const watcher = watch('/src/');
6129
- watcher.addListener('all', (...args)=>{
6130
- // listener code;
6131
- });
6132
- onCleanups.add(async()=>{
6133
- watcher.removeAllListeners();
6134
- watcher.close();
6135
- })
6136
- ///
6137
- / #onCleanups = new Set(); /
6138
- @description
6139
- - manually registering object celeanup;
6140
- @param {()=>Promise<void>} callback
6141
- @returns {void}
6142
- @example
6143
- import { watch } from 'chokidar';
6144
- /// on VivthyNeinth export callback scope
6145
- const watcher = watch('D://my/dir/path');
6146
- // preferably to declare the cleanup right bellow it's object creation;
6147
- // set 'I__the_developer__have_provided_onFileMutations_cleanupCallbacks_for_every_long_running_object_in_this_file' to false if you might want to save before full cleanup is written;
6148
- this.onMutate(async () => {
6149
- watcher.removeAllListeners();
6150
- watcher.close();
6151
- });
6152
- watcher.addListener('all', (eventName, path, stats) => {
6153
- //
6154
- })
6155
- ///
6156
- // alternative: use vivth `modules` that returns object that implements `VivthCleanup`;
6157
- // and call uses `registerObjectWithAutoCleanup`;
6129
+ import { watch } from "chokidar";
6130
+ /// on VivthyNeinth export callback scope
6131
+ const watcher = watch("D://my/dir/path");
6132
+ // preferably to declare the cleanup right bellow it's object creation;
6133
+ // set 'I__the_developer__have_provided_onFileMutations_cleanupCallbacks_for_every_long_running_object_in_this_file' to false if you might want to save before full cleanup is written;
6134
+ this.onMutate(async () => {
6135
+ watcher.removeAllListeners();
6136
+ watcher.close();
6137
+ });
6138
+ watcher.addListener("all", (eventName, path, stats) => {
6139
+ //
6140
+ });
6141
+ ///
6142
+ // alternative: use vivth `modules` that returns object that implements `VivthCleanup`;
6143
+ // and call uses `registerObjectWithAutoCleanup`;
6158
6144
  ```
6159
6145
 
6160
6146
  #### reference: `VivthyNeinth_instance.onExit`
@@ -0,0 +1 @@
1
+ export { FileSelfMapper } from "../../../src/bundler/FileSelfMapper.mjs";
@@ -31,11 +31,23 @@
31
31
  * - files extention:
32
32
  * >- `js`/`ts` files will be compiled with `vivth/node.EsWathcer`, using `option.esbuild` as argument;
33
33
  * >- `sass`/`scss` it will be compiled to `css` first;
34
+ * >- `html` will be checked for `script`;
35
+ * >>- has `[type="module]"`: will be processed as `esm`;
36
+ * >>- has `[minify="true"]`: will be minified;
34
37
  * >- other than those files, they will be just copied to `targetPaths`;
35
38
  * - for runtime example see file `/dev/auto/` on source code;
36
39
  * @implements {VivthCleanup}
37
40
  */
38
41
  export class FileSelfMapper implements VivthCleanup {
42
+ /**
43
+ * @param { string } path
44
+ * @param { (path:{mapTo:string, src:string}, content:string)=>(string|false) } [postprosess]
45
+ * @returns { Promise<void> }
46
+ */
47
+ static #writeHTML: (path: string, postprosess?: (path: {
48
+ mapTo: string;
49
+ src: string;
50
+ }, content: string) => (string | false)) => Promise<void>;
39
51
  /**
40
52
  * @param { string } path
41
53
  * @param { (path:{mapTo:string, src:string}, content:string)=>(string|false) } [postprosess]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vivth",
3
- "version": "1.5.8",
3
+ "version": "1.5.10",
4
4
  "description": "library primitives",
5
5
  "devDependencies": {
6
6
  "@types/bun": "^1.3.3",
@@ -3,8 +3,10 @@
3
3
  import { dirname, extname, relative } from 'node:path';
4
4
  import { readFile } from 'node:fs/promises';
5
5
 
6
+ import { build } from 'esbuild';
6
7
  import { watch } from 'chokidar';
7
8
  import { compileAsync } from 'sass';
9
+ import { createDocument } from 'domino';
8
10
 
9
11
  import { Paths } from '../class/Paths.mjs';
10
12
  import { QChannel } from '../class/QChannel.mjs';
@@ -57,6 +59,9 @@ import { LazyFactory } from '../function/LazyFactory.mjs';
57
59
  * - files extention:
58
60
  * >- `js`/`ts` files will be compiled with `vivth/node.EsWathcer`, using `option.esbuild` as argument;
59
61
  * >- `sass`/`scss` it will be compiled to `css` first;
62
+ * >- `html` will be checked for `script`;
63
+ * >>- has `[type="module]"`: will be processed as `esm`;
64
+ * >>- has `[minify="true"]`: will be minified;
60
65
  * >- other than those files, they will be just copied to `targetPaths`;
61
66
  * - for runtime example see file `/dev/auto/` on source code;
62
67
  * @implements {VivthCleanup}
@@ -92,8 +97,8 @@ export class FileSelfMapper {
92
97
  constructor(watchPath, options) {
93
98
  SafeExit.instance?.addCallback(this.vivthCleanup);
94
99
  const watcherFullPath = Paths.diskAbsolute(watchPath);
95
- const watcher = watch(watcherFullPath, { ignoreInitial: false });
96
- watcher.addListener('all', async (eventName, path, stats) => {
100
+ this.#watcher = watch(watcherFullPath, { ignoreInitial: false });
101
+ this.#watcher.addListener('all', async (eventName, path, stats) => {
97
102
  path = Paths.normalize(path);
98
103
  const [, errorWatcherListener] = await this.#q.callback(path, async ({ isLastOnQ }) => {
99
104
  await this.#listenerQ(isLastOnQ, eventName, path, watcherFullPath, options, stats);
@@ -111,6 +116,7 @@ export class FileSelfMapper {
111
116
  );
112
117
  });
113
118
  }
119
+ #watcher;
114
120
  /**
115
121
  * @type {QChannel<string>}
116
122
  */
@@ -127,6 +133,8 @@ export class FileSelfMapper {
127
133
  await this.#runCleanupOfSpecificPath(path);
128
134
  })[0],
129
135
  );
136
+ this.#watcher.removeAllListeners();
137
+ this.#watcher.close();
130
138
  };
131
139
 
132
140
  /**
@@ -172,6 +180,10 @@ export class FileSelfMapper {
172
180
  return;
173
181
  }
174
182
  const extension = extname(path);
183
+ if (extension === '.html') {
184
+ await FileSelfMapper.#writeHTML(path, options.postProcessDirectCopy);
185
+ return;
186
+ }
175
187
  if (
176
188
  extension !== '.scss' &&
177
189
  extension !== '.sass' &&
@@ -188,6 +200,78 @@ export class FileSelfMapper {
188
200
  }
189
201
  await this.#bundleJS(watcherFullPath, path, options);
190
202
  };
203
+ /**
204
+ * @param { string } path
205
+ * @param { (path:{mapTo:string, src:string}, content:string)=>(string|false) } [postprosess]
206
+ * @returns { Promise<void> }
207
+ */
208
+ static #writeHTML = async (path, postprosess) => {
209
+ const { content: originalContent, targetPaths } = await FileSelfMapper.#getTargetPath(path);
210
+ let newContent = originalContent;
211
+ const resDocument = createDocument(originalContent);
212
+ const handledScripts = Array.from(resDocument.querySelectorAll(`script`));
213
+ await Promise.all(
214
+ ForOfSync(handledScripts, async (scriptElement) => {
215
+ const hasMinifyTrue = (scriptElement.getAttribute('minify') ?? '') === 'true';
216
+ const hasTypeModule = (scriptElement.getAttribute('type') ?? '') === 'module';
217
+ if (!hasMinifyTrue && !hasTypeModule) {
218
+ return;
219
+ }
220
+ const inner = scriptElement.innerHTML;
221
+ const res = await build({
222
+ write: false,
223
+ stdin: {
224
+ contents: inner,
225
+ loader: 'js',
226
+ resolveDir: dirname(path),
227
+ },
228
+ bundle: false,
229
+ logLevel: 'silent',
230
+ minify: hasMinifyTrue,
231
+ format: hasTypeModule ? 'esm' : undefined,
232
+ });
233
+ if (res.errors.length) {
234
+ Console.error({
235
+ errorBuildingInlineScript: {
236
+ outer: scriptElement.outerHTML,
237
+ message: 'failed to build using esbuild.build',
238
+ },
239
+ });
240
+ return;
241
+ }
242
+ const minified = res.outputFiles[0]?.text.trim();
243
+ newContent = newContent.replace(
244
+ inner,
245
+ // @ts-expect-error
246
+ minified,
247
+ );
248
+ })[0],
249
+ );
250
+ await Promise.all(
251
+ ForOfSync(targetPaths, async (target) => {
252
+ let processedContent;
253
+ if (postprosess) {
254
+ postprosess({ mapTo: target, src: path }, newContent);
255
+ }
256
+ const [, errorWriteHTML] = await FileSafe.write(
257
+ target,
258
+ (!!processedContent ? processedContent : newContent).replace(
259
+ /\s*minify\="[\s\S]*?"\s*/g,
260
+ '',
261
+ ),
262
+ {
263
+ encoding: Preferrence.encoding,
264
+ },
265
+ );
266
+ if (errorWriteHTML) {
267
+ Console.error({ errorWriteHTML }, { now: true });
268
+ return;
269
+ }
270
+ Console.info(`✅ Successfully map:'${path}' to:'${target}'`, { now: true });
271
+ })[0],
272
+ );
273
+ };
274
+
191
275
  /**
192
276
  * @param { string } path
193
277
  * @param { (path:{mapTo:string, src:string}, content:string)=>(string|false) } [postprosess]
@@ -333,22 +333,7 @@ export class VivthyNeinth {
333
333
  );
334
334
 
335
335
  /**
336
- * @description
337
336
  * @type {Set<()=>Promise<void>>}
338
- * @example
339
- * import { watch } from "chokidar";
340
- *
341
- * /// on VivthyNeinth arg callback scope
342
- * const { onCleanups } = this;
343
- * const watcher = watch('/src/');
344
- * watcher.addListener('all', (...args)=>{
345
- * // listener code;
346
- * });
347
- * onCleanups.add(async()=>{
348
- * watcher.removeAllListeners();
349
- * watcher.close();
350
- * })
351
- * ///
352
337
  */
353
338
  #onCleanups = new Set();
354
339
 
@@ -115,7 +115,6 @@ export class IsInViewPortSignal extends Signal {
115
115
  );
116
116
  }
117
117
  /**
118
- *
119
118
  * @param {boolean} newValue
120
119
  */
121
120
  #setSuperValue(newValue) {