vivth 1.5.8 → 1.5.9

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
@@ -5383,9 +5383,7 @@ A type-safe `typeof` helper.
5383
5383
  ```js
5384
5384
  /**
5385
5385
  * @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.
5386
+ * @typedef {import('./IsTypeOf.mts').IsTypeOf<K>} IsTypeOf
5389
5387
  */
5390
5388
  ```
5391
5389
 
@@ -6113,48 +6111,33 @@ const effer = newDerived(async ({ subscribe }) => {
6113
6111
 
6114
6112
  #### reference: `VivthyNeinth_instance.onMutate`
6115
6113
 
6114
+ - manually registering object celeanup;
6115
+
6116
6116
  ```js
6117
6117
  /**
6118
- * @type {Set<()=>Promise<void>>}
6118
+ * @param {()=>Promise<void>} callback
6119
+ * @returns {void}
6119
6120
  */
6120
6121
  ```
6121
6122
 
6122
6123
  - <i>example</i>:
6123
6124
 
6124
6125
  ```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`;
6126
+ import { watch } from "chokidar";
6127
+ /// on VivthyNeinth export callback scope
6128
+ const watcher = watch("D://my/dir/path");
6129
+ // preferably to declare the cleanup right bellow it's object creation;
6130
+ // 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;
6131
+ this.onMutate(async () => {
6132
+ watcher.removeAllListeners();
6133
+ watcher.close();
6134
+ });
6135
+ watcher.addListener("all", (eventName, path, stats) => {
6136
+ //
6137
+ });
6138
+ ///
6139
+ // alternative: use vivth `modules` that returns object that implements `VivthCleanup`;
6140
+ // and call uses `registerObjectWithAutoCleanup`;
6158
6141
  ```
6159
6142
 
6160
6143
  #### reference: `VivthyNeinth_instance.onExit`
@@ -0,0 +1 @@
1
+ export { FileSelfMapper } from "../../../src/bundler/FileSelfMapper.mjs";
@@ -36,6 +36,15 @@
36
36
  * @implements {VivthCleanup}
37
37
  */
38
38
  export class FileSelfMapper implements VivthCleanup {
39
+ /**
40
+ * @param { string } path
41
+ * @param { (path:{mapTo:string, src:string}, content:string)=>(string|false) } [postprosess]
42
+ * @returns { Promise<void> }
43
+ */
44
+ static #writeHTML: (path: string, postprosess?: (path: {
45
+ mapTo: string;
46
+ src: string;
47
+ }, content: string) => (string | false)) => Promise<void>;
39
48
  /**
40
49
  * @param { string } path
41
50
  * @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.9",
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';
@@ -92,8 +94,8 @@ export class FileSelfMapper {
92
94
  constructor(watchPath, options) {
93
95
  SafeExit.instance?.addCallback(this.vivthCleanup);
94
96
  const watcherFullPath = Paths.diskAbsolute(watchPath);
95
- const watcher = watch(watcherFullPath, { ignoreInitial: false });
96
- watcher.addListener('all', async (eventName, path, stats) => {
97
+ this.#watcher = watch(watcherFullPath, { ignoreInitial: false });
98
+ this.#watcher.addListener('all', async (eventName, path, stats) => {
97
99
  path = Paths.normalize(path);
98
100
  const [, errorWatcherListener] = await this.#q.callback(path, async ({ isLastOnQ }) => {
99
101
  await this.#listenerQ(isLastOnQ, eventName, path, watcherFullPath, options, stats);
@@ -111,6 +113,7 @@ export class FileSelfMapper {
111
113
  );
112
114
  });
113
115
  }
116
+ #watcher;
114
117
  /**
115
118
  * @type {QChannel<string>}
116
119
  */
@@ -127,6 +130,8 @@ export class FileSelfMapper {
127
130
  await this.#runCleanupOfSpecificPath(path);
128
131
  })[0],
129
132
  );
133
+ this.#watcher.removeAllListeners();
134
+ this.#watcher.close();
130
135
  };
131
136
 
132
137
  /**
@@ -172,6 +177,10 @@ export class FileSelfMapper {
172
177
  return;
173
178
  }
174
179
  const extension = extname(path);
180
+ if (extension === '.html') {
181
+ await FileSelfMapper.#writeHTML(path, options.postProcessDirectCopy);
182
+ return;
183
+ }
175
184
  if (
176
185
  extension !== '.scss' &&
177
186
  extension !== '.sass' &&
@@ -188,6 +197,84 @@ export class FileSelfMapper {
188
197
  }
189
198
  await this.#bundleJS(watcherFullPath, path, options);
190
199
  };
200
+ /**
201
+ * @param { string } path
202
+ * @param { (path:{mapTo:string, src:string}, content:string)=>(string|false) } [postprosess]
203
+ * @returns { Promise<void> }
204
+ */
205
+ static #writeHTML = async (path, postprosess) => {
206
+ const { content: originalContent, targetPaths } = await FileSelfMapper.#getTargetPath(path);
207
+ let newContent = originalContent;
208
+ const resDocument = createDocument(originalContent);
209
+ const fileSelfMapperAttribute = 'vivth-file-self-mapper';
210
+ const handledScripts = resDocument.querySelectorAll(`script[${fileSelfMapperAttribute}]`);
211
+ await Promise.all(
212
+ ForOfSync(handledScripts, async (scriptElement) => {
213
+ const directionsString = scriptElement.getAttribute(fileSelfMapperAttribute);
214
+ scriptElement.removeAttribute(fileSelfMapperAttribute);
215
+ if (!directionsString) return;
216
+ const directions = new Set(directionsString.split(';'));
217
+ const hasMin = directions.has('min');
218
+ const inner = scriptElement.innerHTML;
219
+ const res = await build({
220
+ write: false,
221
+ stdin: {
222
+ contents: inner,
223
+ loader: 'js',
224
+ resolveDir: dirname(path),
225
+ },
226
+ bundle: false,
227
+ logLevel: 'silent',
228
+ minify: hasMin,
229
+ format: directions.has('iife')
230
+ ? 'iife'
231
+ : scriptElement.getAttribute('type') === 'module'
232
+ ? 'esm'
233
+ : undefined,
234
+ });
235
+ if (res.errors.length) {
236
+ Console.error({
237
+ errorBuildingInlineScript: {
238
+ outer: scriptElement.outerHTML,
239
+ message: 'failed to build using esbuild.build',
240
+ },
241
+ });
242
+ return;
243
+ }
244
+
245
+ const minified = res.outputFiles[0]?.text;
246
+ newContent = newContent.replace(
247
+ inner,
248
+ // @ts-expect-error
249
+ minified,
250
+ );
251
+ })[0],
252
+ );
253
+ await Promise.all(
254
+ ForOfSync(targetPaths, async (target) => {
255
+ let processedContent;
256
+ if (postprosess) {
257
+ postprosess({ mapTo: target, src: path }, newContent);
258
+ }
259
+ const [, errorWriteHTML] = await FileSafe.write(
260
+ target,
261
+ (!!processedContent ? processedContent : newContent).replace(
262
+ /\s*vivth-file-self-mapper\="[\s\S]*?"\s*/g,
263
+ '',
264
+ ),
265
+ {
266
+ encoding: Preferrence.encoding,
267
+ },
268
+ );
269
+ if (errorWriteHTML) {
270
+ Console.error({ errorWriteHTML }, { now: true });
271
+ return;
272
+ }
273
+ Console.info(`✅ Successfully map:'${path}' to:'${target}'`, { now: true });
274
+ })[0],
275
+ );
276
+ };
277
+
191
278
  /**
192
279
  * @param { string } path
193
280
  * @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) {