bitwrench 2.0.25 → 2.0.31

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.
Files changed (75) hide show
  1. package/README.md +10 -4
  2. package/dist/bitwrench-bccl.cjs.js +1 -1
  3. package/dist/bitwrench-bccl.cjs.min.js +1 -1
  4. package/dist/bitwrench-bccl.cjs.min.js.gz +0 -0
  5. package/dist/bitwrench-bccl.esm.js +1 -1
  6. package/dist/bitwrench-bccl.esm.min.js +1 -1
  7. package/dist/bitwrench-bccl.esm.min.js.gz +0 -0
  8. package/dist/bitwrench-bccl.umd.js +1 -1
  9. package/dist/bitwrench-bccl.umd.min.js +1 -1
  10. package/dist/bitwrench-bccl.umd.min.js.gz +0 -0
  11. package/dist/bitwrench-code-edit.cjs.js +1 -1
  12. package/dist/bitwrench-code-edit.cjs.min.js +1 -1
  13. package/dist/bitwrench-code-edit.es5.js +1 -1
  14. package/dist/bitwrench-code-edit.es5.min.js +1 -1
  15. package/dist/bitwrench-code-edit.esm.js +1 -1
  16. package/dist/bitwrench-code-edit.esm.min.js +1 -1
  17. package/dist/bitwrench-code-edit.umd.js +1 -1
  18. package/dist/bitwrench-code-edit.umd.min.js +1 -1
  19. package/dist/bitwrench-code-edit.umd.min.js.gz +0 -0
  20. package/dist/bitwrench-debug.js +1 -1
  21. package/dist/bitwrench-debug.min.js +1 -1
  22. package/dist/bitwrench-lean.cjs.js +623 -155
  23. package/dist/bitwrench-lean.cjs.min.js +7 -7
  24. package/dist/bitwrench-lean.cjs.min.js.gz +0 -0
  25. package/dist/bitwrench-lean.es5.js +650 -157
  26. package/dist/bitwrench-lean.es5.min.js +5 -5
  27. package/dist/bitwrench-lean.es5.min.js.gz +0 -0
  28. package/dist/bitwrench-lean.esm.js +623 -155
  29. package/dist/bitwrench-lean.esm.min.js +6 -6
  30. package/dist/bitwrench-lean.esm.min.js.gz +0 -0
  31. package/dist/bitwrench-lean.umd.js +623 -155
  32. package/dist/bitwrench-lean.umd.min.js +7 -7
  33. package/dist/bitwrench-lean.umd.min.js.gz +0 -0
  34. package/dist/bitwrench-util-css.cjs.js +1 -1
  35. package/dist/bitwrench-util-css.cjs.min.js +1 -1
  36. package/dist/bitwrench-util-css.es5.js +1 -1
  37. package/dist/bitwrench-util-css.es5.min.js +1 -1
  38. package/dist/bitwrench-util-css.esm.js +1 -1
  39. package/dist/bitwrench-util-css.esm.min.js +1 -1
  40. package/dist/bitwrench-util-css.umd.js +1 -1
  41. package/dist/bitwrench-util-css.umd.min.js +1 -1
  42. package/dist/bitwrench-util-css.umd.min.js.gz +0 -0
  43. package/dist/bitwrench.cjs.js +621 -153
  44. package/dist/bitwrench.cjs.min.js +6 -6
  45. package/dist/bitwrench.cjs.min.js.gz +0 -0
  46. package/dist/bitwrench.css +1 -1
  47. package/dist/bitwrench.d.ts +18 -11
  48. package/dist/bitwrench.es5.js +647 -154
  49. package/dist/bitwrench.es5.min.js +6 -6
  50. package/dist/bitwrench.es5.min.js.gz +0 -0
  51. package/dist/bitwrench.esm.js +621 -153
  52. package/dist/bitwrench.esm.min.js +5 -5
  53. package/dist/bitwrench.esm.min.js.gz +0 -0
  54. package/dist/bitwrench.umd.js +621 -153
  55. package/dist/bitwrench.umd.min.js +6 -6
  56. package/dist/bitwrench.umd.min.js.gz +0 -0
  57. package/dist/builds.json +92 -92
  58. package/dist/bwserve.cjs.js +140 -7
  59. package/dist/bwserve.esm.js +141 -8
  60. package/dist/sri.json +45 -45
  61. package/docs/bitwrench-for-wasm.md +851 -0
  62. package/docs/bitwrench_api.md +133 -23
  63. package/docs/llm-bitwrench-guide.md +6 -5
  64. package/docs/state-management.md +27 -3
  65. package/docs/thinking-in-bitwrench.md +3 -2
  66. package/package.json +11 -9
  67. package/readme.html +17 -8
  68. package/src/bitwrench.d.ts +18 -11
  69. package/src/bitwrench.js +617 -148
  70. package/src/bwserve/bwclient.js +3 -3
  71. package/src/bwserve/client.js +26 -0
  72. package/src/bwserve/index.js +110 -3
  73. package/src/cli/attach.js +7 -5
  74. package/src/cli/serve.js +53 -10
  75. package/src/version.js +3 -3
@@ -1,4 +1,4 @@
1
- /*! bwserve v2.0.25 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
1
+ /*! bwserve v2.0.31 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
2
2
  'use strict';
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
@@ -14,7 +14,7 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
14
14
  * DO NOT EDIT DIRECTLY - Use npm run generate-version
15
15
  */
16
16
 
17
- const VERSION = '2.0.25';
17
+ const VERSION = '2.0.31';
18
18
 
19
19
  /**
20
20
  * BwServeClient — per-client connection for bwserve.
@@ -280,6 +280,32 @@ class BwServeClient {
280
280
  return pend.promise;
281
281
  }
282
282
 
283
+ // ── Inspect ──
284
+
285
+ /**
286
+ * Inspect the DOM tree of the connected client.
287
+ *
288
+ * Calls the `_bw_tree` builtin on the client which delegates to
289
+ * `bw.inspect()` when available, returning a plain-object tree with
290
+ * bitwrench metadata (tag, uuid, type, handles, state, children).
291
+ *
292
+ * @param {string} [selector='body'] - CSS selector of root element
293
+ * @param {Object} [options]
294
+ * @param {number} [options.depth=3] - Max recursion depth
295
+ * @param {number} [options.timeout=10000] - Timeout in ms
296
+ * @returns {Promise<Object|null>} Tree object, or null if element not found
297
+ */
298
+ inspect(selector, options) {
299
+ var opts = options || {};
300
+ var pend = this._pend(opts.timeout || 10000);
301
+ this.call('_bw_tree', {
302
+ selector: selector || 'body',
303
+ depth: opts.depth || 3,
304
+ requestId: pend.requestId
305
+ });
306
+ return pend.promise;
307
+ }
308
+
283
309
  // ── Screenshot ──
284
310
 
285
311
  /**
@@ -435,8 +461,8 @@ var BWCLIENT_SOURCE = '(function(bw) {\n'
435
461
  + ' // ── Register built-in functions ──\n'
436
462
  + ' _client._registerBuiltins = function() {\n'
437
463
  + ' var builtins = {\n'
438
- + ' scrollTo: "function(sel){var el=bw._el(sel);if(el)el.scrollTop=el.scrollHeight;}",\n'
439
- + ' focus: "function(sel){var el=bw._el(sel);if(el&&typeof el.focus===\\"function\\")el.focus();}",\n'
464
+ + ' scrollTo: "function(sel){var el=bw.el(sel);if(el)el.scrollTop=el.scrollHeight;}",\n'
465
+ + ' focus: "function(sel){var el=bw.el(sel);if(el&&typeof el.focus===\\"function\\")el.focus();}",\n'
440
466
  + ' download: "function(fn,c,m){if(typeof document===\\"undefined\\")return;var b=new Blob([c],{type:m||\\"text/plain\\"});var a=document.createElement(\\"a\\");a.href=URL.createObjectURL(b);a.download=fn;a.click();URL.revokeObjectURL(a.href);}",\n'
441
467
  + ' clipboard: "function(t){if(typeof navigator!==\\"undefined\\"&&navigator.clipboard)navigator.clipboard.writeText(t);}",\n'
442
468
  + ' redirect: "function(u){if(typeof window!==\\"undefined\\")window.location.href=u;}",\n'
@@ -444,7 +470,7 @@ var BWCLIENT_SOURCE = '(function(bw) {\n'
444
470
  + ' _bw_query: "function(opts){if(!bw._bwClient)return;try{var r=new Function(opts.code)();if(r&&typeof r.then===\\"function\\"){r.then(function(v){bw._bwClient.respond(\\"query\\",opts.requestId,v);}).catch(function(e){bw._bwClient.respond(\\"query\\",opts.requestId,null,e.message);});}else{bw._bwClient.respond(\\"query\\",opts.requestId,r);}}catch(e){bw._bwClient.respond(\\"query\\",opts.requestId,null,e.message);}}",\n'
445
471
  + ' _bw_mount: "function(opts){if(!bw._bwClient)return;try{var taco;var f=opts.factory;var n=f.replace(/-([a-z])/g,function(_,c){return c.toUpperCase();});if(bw.BCCL&&bw.BCCL[n]){taco=bw.make(n,opts.props||{});}else if(bw._allowExec){taco=new Function(\\"props\\",f)(opts.props||{});}else{throw new Error(\\"Unknown component and allowExec disabled\\");}bw.DOM(opts.target,taco);bw._bwClient.respond(\\"mount\\",opts.requestId,{mounted:true});}catch(e){bw._bwClient.respond(\\"mount\\",opts.requestId,null,e.message);}}",\n'
446
472
  + ' _bw_screenshot: "function(opts){if(!bw._bwClient)return;var sel=opts.selector||\\"body\\";var el=document.querySelector(sel);if(!el){bw._bwClient.respond(\\"screenshot\\",opts.requestId,null,\\"Element not found: \\"+sel);return;}function _ls(url){return new Promise(function(res,rej){var s=document.createElement(\\"script\\");s.src=url;s.onload=function(){res(window.html2canvas);};s.onerror=function(){rej(new Error(\\"Failed to load html2canvas\\"));};document.head.appendChild(s);});}var p=window.html2canvas?Promise.resolve(window.html2canvas):_ls(opts.captureUrl||\\"/bw/lib/vendor/html2canvas.min.js\\");p.then(function(h2c){return h2c(el,{scale:opts.scale||1,useCORS:true});}).then(function(canvas){var out=canvas;var mw=opts.maxWidth;var mh=opts.maxHeight;if((mw&&canvas.width>mw)||(mh&&canvas.height>mh)){var sw=mw?mw/canvas.width:1;var sh=mh?mh/canvas.height:1;var sc=Math.min(sw,sh);out=document.createElement(\\"canvas\\");out.width=Math.round(canvas.width*sc);out.height=Math.round(canvas.height*sc);out.getContext(\\"2d\\").drawImage(canvas,0,0,out.width,out.height);}var fmt=opts.format===\\"jpeg\\"?\\"image/jpeg\\":\\"image/png\\";var q=opts.format===\\"jpeg\\"?(opts.quality||0.85):undefined;var dataUrl=out.toDataURL(fmt,q);bw._bwClient.respond(\\"screenshot\\",opts.requestId,{data:dataUrl,width:out.width,height:out.height,format:opts.format||\\"png\\"});}).catch(function(err){bw._bwClient.respond(\\"screenshot\\",opts.requestId,null,err.message||String(err));});}",\n'
447
- + ' _bw_tree: "function(opts){if(!bw._bwClient)return;var sel=opts.selector||\\"body\\";var depth=opts.depth||3;function walk(el,d){if(!el||d>depth)return null;var info={tag:el.tagName?el.tagName.toLowerCase():\\"#text\\"};if(el.id)info.id=el.id;if(el.className&&typeof el.className===\\"string\\")info.cls=el.className.split(\\" \\").slice(0,5).join(\\" \\");if(el.children&&el.children.length>0&&d<depth){info.children=[];for(var i=0;i<Math.min(el.children.length,20);i++){var c=walk(el.children[i],d+1);if(c)info.children.push(c);}}return info;}var root=document.querySelector(sel);bw._bwClient.respond(\\"query\\",opts.requestId,walk(root,0));}",\n'
473
+ + ' _bw_tree: "function(opts){if(!bw._bwClient)return;var sel=opts.selector||\\"body\\";var depth=opts.depth||3;var root=document.querySelector(sel);if(typeof bw.inspect===\\"function\\"&&bw.inspect.length===2){bw._bwClient.respond(\\"query\\",opts.requestId,bw.inspect(root,depth));return;}function walk(el,d){if(!el||d>depth)return null;var info={tag:el.tagName?el.tagName.toLowerCase():\\"#text\\"};if(el.id)info.id=el.id;if(el.className&&typeof el.className===\\"string\\")info.cls=el.className.split(\\" \\").slice(0,5).join(\\" \\");if(el.children&&el.children.length>0&&d<depth){info.children=[];for(var i=0;i<Math.min(el.children.length,20);i++){var c=walk(el.children[i],d+1);if(c)info.children.push(c);}}return info;}bw._bwClient.respond(\\"query\\",opts.requestId,walk(root,0));}",\n'
448
474
  + ' _bw_listen: "function(opts){if(!bw._bwClient)return;if(!bw._bwClient._listeners)bw._bwClient._listeners={};var key=opts.selector+\\":::\\"+opts.event;if(bw._bwClient._listeners[key])return;var fn=function(e){var el=e.target.closest?e.target.closest(opts.selector):null;if(!el)return;bw._bwClient.respond(\\"event\\",null,{event:opts.event,selector:opts.selector,tagName:el.tagName,id:el.id||null,text:(el.textContent||\\"\\").slice(0,100)});};document.addEventListener(opts.event,fn,true);bw._bwClient._listeners[key]={fn:fn,event:opts.event};}",\n'
449
475
  + ' _bw_unlisten: "function(opts){if(!bw._bwClient||!bw._bwClient._listeners)return;var key=opts.selector+\\":::\\"+opts.event;var entry=bw._bwClient._listeners[key];if(!entry)return;document.removeEventListener(entry.event,entry.fn,true);delete bw._bwClient._listeners[key];}"\n'
450
476
  + ' };\n'
@@ -692,7 +718,21 @@ var MIME_TYPES = {
692
718
  '.woff': 'font/woff',
693
719
  '.woff2': 'font/woff2',
694
720
  '.ttf': 'font/ttf',
695
- '.map': 'application/json'
721
+ '.map': 'application/json',
722
+ '.txt': 'text/plain; charset=utf-8',
723
+ '.xml': 'application/xml; charset=utf-8',
724
+ '.pdf': 'application/pdf',
725
+ '.zip': 'application/zip',
726
+ '.gz': 'application/gzip',
727
+ '.mp3': 'audio/mpeg',
728
+ '.mp4': 'video/mp4',
729
+ '.webm': 'video/webm',
730
+ '.webp': 'image/webp',
731
+ '.avif': 'image/avif',
732
+ '.wasm': 'application/wasm',
733
+ '.csv': 'text/csv; charset=utf-8',
734
+ '.md': 'text/markdown; charset=utf-8',
735
+ '.mjs': 'application/javascript; charset=utf-8'
696
736
  };
697
737
 
698
738
  /**
@@ -705,6 +745,8 @@ var MIME_TYPES = {
705
745
  * @param {boolean} [opts.injectBitwrench=true] - Auto-inject bitwrench client JS
706
746
  * @param {string|Object} [opts.theme] - Theme preset name or config object
707
747
  * @param {boolean} [opts.allowScreenshot=false] - Enable client.screenshot() capability
748
+ * @param {boolean} [opts.dirList=true] - Enable directory listings when no index.html
749
+ * @param {string} [opts.host='0.0.0.0'] - Host/address to bind to
708
750
  * @returns {BwServeApp} Application instance
709
751
  */
710
752
  function create(opts) {
@@ -725,6 +767,8 @@ class BwServeApp {
725
767
  this.theme = opts.theme || null;
726
768
  this.allowExec = opts.allowExec || false;
727
769
  this.allowScreenshot = opts.allowScreenshot || false;
770
+ this.dirList = opts.dirList !== false;
771
+ this.host = opts.host || '0.0.0.0';
728
772
  this.keepAliveInterval = opts.keepAliveInterval || 15000;
729
773
  this._pages = new Map();
730
774
  this._clients = new Map();
@@ -758,7 +802,7 @@ class BwServeApp {
758
802
  self._handleRequest(req, rawRes);
759
803
  });
760
804
 
761
- self._server.listen(self.port, function() {
805
+ self._server.listen(self.port, self.host, function() {
762
806
  if (callback) callback();
763
807
  res();
764
808
  });
@@ -922,6 +966,32 @@ class BwServeApp {
922
966
  res.end(content);
923
967
  return;
924
968
  }
969
+ // Directory index resolution: /foo/ => /foo/index.html
970
+ if (path$1.endsWith('/')) {
971
+ var indexPath = path.join(this.staticDir, path$1, 'index.html');
972
+ if (fs.existsSync(indexPath) && fs.statSync(indexPath).isFile()) {
973
+ var indexContent = fs.readFileSync(indexPath);
974
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
975
+ res.end(indexContent);
976
+ return;
977
+ }
978
+ // Directory listing when no index.html
979
+ var dirPath = path.join(this.staticDir, path$1);
980
+ if (this.dirList && fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
981
+ var listing = this._generateDirListing(path$1, dirPath);
982
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
983
+ res.end(listing);
984
+ return;
985
+ }
986
+ }
987
+ // Bare directory without trailing slash: /foo => 301 to /foo/
988
+ if (!path$1.endsWith('/') && fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
989
+ var qs = url.split('?')[1];
990
+ var location = path$1 + '/' + (qs ? '?' + qs : '');
991
+ res.writeHead(301, { 'Location': location });
992
+ res.end();
993
+ return;
994
+ }
925
995
  }
926
996
 
927
997
  // 404
@@ -1091,6 +1161,69 @@ class BwServeApp {
1091
1161
  });
1092
1162
  res.end(content);
1093
1163
  }
1164
+
1165
+ /**
1166
+ * Generate an HTML directory listing page.
1167
+ * @private
1168
+ * @param {string} urlPath - URL path (with trailing slash)
1169
+ * @param {string} dirPath - Filesystem path to the directory
1170
+ * @returns {string} HTML page
1171
+ */
1172
+ _generateDirListing(urlPath, dirPath) {
1173
+ var entries = fs.readdirSync(dirPath);
1174
+ var dirs = [];
1175
+ var files = [];
1176
+
1177
+ for (var i = 0; i < entries.length; i++) {
1178
+ var name = entries[i];
1179
+ var fullPath = path.join(dirPath, name);
1180
+ try {
1181
+ var st = fs.statSync(fullPath);
1182
+ if (st.isDirectory()) {
1183
+ dirs.push({ name: name + '/', size: '-' });
1184
+ } else {
1185
+ files.push({ name: name, size: _formatSize(st.size) });
1186
+ }
1187
+ } catch (e) {
1188
+ // Skip entries we cannot stat
1189
+ }
1190
+ }
1191
+
1192
+ // Sort alphabetically
1193
+ dirs.sort(function(a, b) { return a.name.localeCompare(b.name); });
1194
+ files.sort(function(a, b) { return a.name.localeCompare(b.name); });
1195
+
1196
+ var all = dirs.concat(files);
1197
+
1198
+ var rows = '';
1199
+ // Parent directory link (unless at root)
1200
+ if (urlPath !== '/') {
1201
+ rows += '<tr><td><a href="../">..</a></td><td>-</td></tr>\n';
1202
+ }
1203
+ for (var j = 0; j < all.length; j++) {
1204
+ var entry = all[j];
1205
+ var escaped = entry.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
1206
+ rows += '<tr><td><a href="' + encodeURIComponent(entry.name.replace(/\/$/, '')) + (entry.size === '-' ? '/' : '') + '">' + escaped + '</a></td><td>' + entry.size + '</td></tr>\n';
1207
+ }
1208
+
1209
+ var escapedPath = urlPath.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
1210
+ return '<!DOCTYPE html>\n<html><head><meta charset="utf-8"><title>Index of ' + escapedPath + '</title>' +
1211
+ '<style>body{font-family:monospace;margin:2em}table{border-collapse:collapse}td,th{text-align:left;padding:4px 16px}a{text-decoration:none}a:hover{text-decoration:underline}</style>' +
1212
+ '</head><body><h1>Index of ' + escapedPath + '</h1><table><tr><th>Name</th><th>Size</th></tr>\n' +
1213
+ rows + '</table></body></html>';
1214
+ }
1215
+ }
1216
+
1217
+ /**
1218
+ * Format a byte size as a human-readable string.
1219
+ * @param {number} bytes
1220
+ * @returns {string}
1221
+ */
1222
+ function _formatSize(bytes) {
1223
+ if (bytes < 1024) return bytes + ' B';
1224
+ if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
1225
+ if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
1226
+ return (bytes / (1024 * 1024 * 1024)).toFixed(1) + ' GB';
1094
1227
  }
1095
1228
 
1096
1229
  var version = VERSION;
@@ -1,15 +1,15 @@
1
- /*! bwserve v2.0.25 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
1
+ /*! bwserve v2.0.31 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
2
2
  import { fileURLToPath } from 'url';
3
3
  import { dirname, resolve, join, extname } from 'path';
4
4
  import { createServer } from 'http';
5
- import { existsSync, statSync, readFileSync } from 'fs';
5
+ import { existsSync, statSync, readFileSync, readdirSync } from 'fs';
6
6
 
7
7
  /**
8
8
  * Auto-generated version file from package.json
9
9
  * DO NOT EDIT DIRECTLY - Use npm run generate-version
10
10
  */
11
11
 
12
- const VERSION = '2.0.25';
12
+ const VERSION = '2.0.31';
13
13
 
14
14
  /**
15
15
  * BwServeClient — per-client connection for bwserve.
@@ -275,6 +275,32 @@ class BwServeClient {
275
275
  return pend.promise;
276
276
  }
277
277
 
278
+ // ── Inspect ──
279
+
280
+ /**
281
+ * Inspect the DOM tree of the connected client.
282
+ *
283
+ * Calls the `_bw_tree` builtin on the client which delegates to
284
+ * `bw.inspect()` when available, returning a plain-object tree with
285
+ * bitwrench metadata (tag, uuid, type, handles, state, children).
286
+ *
287
+ * @param {string} [selector='body'] - CSS selector of root element
288
+ * @param {Object} [options]
289
+ * @param {number} [options.depth=3] - Max recursion depth
290
+ * @param {number} [options.timeout=10000] - Timeout in ms
291
+ * @returns {Promise<Object|null>} Tree object, or null if element not found
292
+ */
293
+ inspect(selector, options) {
294
+ var opts = options || {};
295
+ var pend = this._pend(opts.timeout || 10000);
296
+ this.call('_bw_tree', {
297
+ selector: selector || 'body',
298
+ depth: opts.depth || 3,
299
+ requestId: pend.requestId
300
+ });
301
+ return pend.promise;
302
+ }
303
+
278
304
  // ── Screenshot ──
279
305
 
280
306
  /**
@@ -430,8 +456,8 @@ var BWCLIENT_SOURCE = '(function(bw) {\n'
430
456
  + ' // ── Register built-in functions ──\n'
431
457
  + ' _client._registerBuiltins = function() {\n'
432
458
  + ' var builtins = {\n'
433
- + ' scrollTo: "function(sel){var el=bw._el(sel);if(el)el.scrollTop=el.scrollHeight;}",\n'
434
- + ' focus: "function(sel){var el=bw._el(sel);if(el&&typeof el.focus===\\"function\\")el.focus();}",\n'
459
+ + ' scrollTo: "function(sel){var el=bw.el(sel);if(el)el.scrollTop=el.scrollHeight;}",\n'
460
+ + ' focus: "function(sel){var el=bw.el(sel);if(el&&typeof el.focus===\\"function\\")el.focus();}",\n'
435
461
  + ' download: "function(fn,c,m){if(typeof document===\\"undefined\\")return;var b=new Blob([c],{type:m||\\"text/plain\\"});var a=document.createElement(\\"a\\");a.href=URL.createObjectURL(b);a.download=fn;a.click();URL.revokeObjectURL(a.href);}",\n'
436
462
  + ' clipboard: "function(t){if(typeof navigator!==\\"undefined\\"&&navigator.clipboard)navigator.clipboard.writeText(t);}",\n'
437
463
  + ' redirect: "function(u){if(typeof window!==\\"undefined\\")window.location.href=u;}",\n'
@@ -439,7 +465,7 @@ var BWCLIENT_SOURCE = '(function(bw) {\n'
439
465
  + ' _bw_query: "function(opts){if(!bw._bwClient)return;try{var r=new Function(opts.code)();if(r&&typeof r.then===\\"function\\"){r.then(function(v){bw._bwClient.respond(\\"query\\",opts.requestId,v);}).catch(function(e){bw._bwClient.respond(\\"query\\",opts.requestId,null,e.message);});}else{bw._bwClient.respond(\\"query\\",opts.requestId,r);}}catch(e){bw._bwClient.respond(\\"query\\",opts.requestId,null,e.message);}}",\n'
440
466
  + ' _bw_mount: "function(opts){if(!bw._bwClient)return;try{var taco;var f=opts.factory;var n=f.replace(/-([a-z])/g,function(_,c){return c.toUpperCase();});if(bw.BCCL&&bw.BCCL[n]){taco=bw.make(n,opts.props||{});}else if(bw._allowExec){taco=new Function(\\"props\\",f)(opts.props||{});}else{throw new Error(\\"Unknown component and allowExec disabled\\");}bw.DOM(opts.target,taco);bw._bwClient.respond(\\"mount\\",opts.requestId,{mounted:true});}catch(e){bw._bwClient.respond(\\"mount\\",opts.requestId,null,e.message);}}",\n'
441
467
  + ' _bw_screenshot: "function(opts){if(!bw._bwClient)return;var sel=opts.selector||\\"body\\";var el=document.querySelector(sel);if(!el){bw._bwClient.respond(\\"screenshot\\",opts.requestId,null,\\"Element not found: \\"+sel);return;}function _ls(url){return new Promise(function(res,rej){var s=document.createElement(\\"script\\");s.src=url;s.onload=function(){res(window.html2canvas);};s.onerror=function(){rej(new Error(\\"Failed to load html2canvas\\"));};document.head.appendChild(s);});}var p=window.html2canvas?Promise.resolve(window.html2canvas):_ls(opts.captureUrl||\\"/bw/lib/vendor/html2canvas.min.js\\");p.then(function(h2c){return h2c(el,{scale:opts.scale||1,useCORS:true});}).then(function(canvas){var out=canvas;var mw=opts.maxWidth;var mh=opts.maxHeight;if((mw&&canvas.width>mw)||(mh&&canvas.height>mh)){var sw=mw?mw/canvas.width:1;var sh=mh?mh/canvas.height:1;var sc=Math.min(sw,sh);out=document.createElement(\\"canvas\\");out.width=Math.round(canvas.width*sc);out.height=Math.round(canvas.height*sc);out.getContext(\\"2d\\").drawImage(canvas,0,0,out.width,out.height);}var fmt=opts.format===\\"jpeg\\"?\\"image/jpeg\\":\\"image/png\\";var q=opts.format===\\"jpeg\\"?(opts.quality||0.85):undefined;var dataUrl=out.toDataURL(fmt,q);bw._bwClient.respond(\\"screenshot\\",opts.requestId,{data:dataUrl,width:out.width,height:out.height,format:opts.format||\\"png\\"});}).catch(function(err){bw._bwClient.respond(\\"screenshot\\",opts.requestId,null,err.message||String(err));});}",\n'
442
- + ' _bw_tree: "function(opts){if(!bw._bwClient)return;var sel=opts.selector||\\"body\\";var depth=opts.depth||3;function walk(el,d){if(!el||d>depth)return null;var info={tag:el.tagName?el.tagName.toLowerCase():\\"#text\\"};if(el.id)info.id=el.id;if(el.className&&typeof el.className===\\"string\\")info.cls=el.className.split(\\" \\").slice(0,5).join(\\" \\");if(el.children&&el.children.length>0&&d<depth){info.children=[];for(var i=0;i<Math.min(el.children.length,20);i++){var c=walk(el.children[i],d+1);if(c)info.children.push(c);}}return info;}var root=document.querySelector(sel);bw._bwClient.respond(\\"query\\",opts.requestId,walk(root,0));}",\n'
468
+ + ' _bw_tree: "function(opts){if(!bw._bwClient)return;var sel=opts.selector||\\"body\\";var depth=opts.depth||3;var root=document.querySelector(sel);if(typeof bw.inspect===\\"function\\"&&bw.inspect.length===2){bw._bwClient.respond(\\"query\\",opts.requestId,bw.inspect(root,depth));return;}function walk(el,d){if(!el||d>depth)return null;var info={tag:el.tagName?el.tagName.toLowerCase():\\"#text\\"};if(el.id)info.id=el.id;if(el.className&&typeof el.className===\\"string\\")info.cls=el.className.split(\\" \\").slice(0,5).join(\\" \\");if(el.children&&el.children.length>0&&d<depth){info.children=[];for(var i=0;i<Math.min(el.children.length,20);i++){var c=walk(el.children[i],d+1);if(c)info.children.push(c);}}return info;}bw._bwClient.respond(\\"query\\",opts.requestId,walk(root,0));}",\n'
443
469
  + ' _bw_listen: "function(opts){if(!bw._bwClient)return;if(!bw._bwClient._listeners)bw._bwClient._listeners={};var key=opts.selector+\\":::\\"+opts.event;if(bw._bwClient._listeners[key])return;var fn=function(e){var el=e.target.closest?e.target.closest(opts.selector):null;if(!el)return;bw._bwClient.respond(\\"event\\",null,{event:opts.event,selector:opts.selector,tagName:el.tagName,id:el.id||null,text:(el.textContent||\\"\\").slice(0,100)});};document.addEventListener(opts.event,fn,true);bw._bwClient._listeners[key]={fn:fn,event:opts.event};}",\n'
444
470
  + ' _bw_unlisten: "function(opts){if(!bw._bwClient||!bw._bwClient._listeners)return;var key=opts.selector+\\":::\\"+opts.event;var entry=bw._bwClient._listeners[key];if(!entry)return;document.removeEventListener(entry.event,entry.fn,true);delete bw._bwClient._listeners[key];}"\n'
445
471
  + ' };\n'
@@ -687,7 +713,21 @@ var MIME_TYPES = {
687
713
  '.woff': 'font/woff',
688
714
  '.woff2': 'font/woff2',
689
715
  '.ttf': 'font/ttf',
690
- '.map': 'application/json'
716
+ '.map': 'application/json',
717
+ '.txt': 'text/plain; charset=utf-8',
718
+ '.xml': 'application/xml; charset=utf-8',
719
+ '.pdf': 'application/pdf',
720
+ '.zip': 'application/zip',
721
+ '.gz': 'application/gzip',
722
+ '.mp3': 'audio/mpeg',
723
+ '.mp4': 'video/mp4',
724
+ '.webm': 'video/webm',
725
+ '.webp': 'image/webp',
726
+ '.avif': 'image/avif',
727
+ '.wasm': 'application/wasm',
728
+ '.csv': 'text/csv; charset=utf-8',
729
+ '.md': 'text/markdown; charset=utf-8',
730
+ '.mjs': 'application/javascript; charset=utf-8'
691
731
  };
692
732
 
693
733
  /**
@@ -700,6 +740,8 @@ var MIME_TYPES = {
700
740
  * @param {boolean} [opts.injectBitwrench=true] - Auto-inject bitwrench client JS
701
741
  * @param {string|Object} [opts.theme] - Theme preset name or config object
702
742
  * @param {boolean} [opts.allowScreenshot=false] - Enable client.screenshot() capability
743
+ * @param {boolean} [opts.dirList=true] - Enable directory listings when no index.html
744
+ * @param {string} [opts.host='0.0.0.0'] - Host/address to bind to
703
745
  * @returns {BwServeApp} Application instance
704
746
  */
705
747
  function create(opts) {
@@ -720,6 +762,8 @@ class BwServeApp {
720
762
  this.theme = opts.theme || null;
721
763
  this.allowExec = opts.allowExec || false;
722
764
  this.allowScreenshot = opts.allowScreenshot || false;
765
+ this.dirList = opts.dirList !== false;
766
+ this.host = opts.host || '0.0.0.0';
723
767
  this.keepAliveInterval = opts.keepAliveInterval || 15000;
724
768
  this._pages = new Map();
725
769
  this._clients = new Map();
@@ -753,7 +797,7 @@ class BwServeApp {
753
797
  self._handleRequest(req, rawRes);
754
798
  });
755
799
 
756
- self._server.listen(self.port, function() {
800
+ self._server.listen(self.port, self.host, function() {
757
801
  if (callback) callback();
758
802
  res();
759
803
  });
@@ -917,6 +961,32 @@ class BwServeApp {
917
961
  res.end(content);
918
962
  return;
919
963
  }
964
+ // Directory index resolution: /foo/ => /foo/index.html
965
+ if (path.endsWith('/')) {
966
+ var indexPath = join(this.staticDir, path, 'index.html');
967
+ if (existsSync(indexPath) && statSync(indexPath).isFile()) {
968
+ var indexContent = readFileSync(indexPath);
969
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
970
+ res.end(indexContent);
971
+ return;
972
+ }
973
+ // Directory listing when no index.html
974
+ var dirPath = join(this.staticDir, path);
975
+ if (this.dirList && existsSync(dirPath) && statSync(dirPath).isDirectory()) {
976
+ var listing = this._generateDirListing(path, dirPath);
977
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
978
+ res.end(listing);
979
+ return;
980
+ }
981
+ }
982
+ // Bare directory without trailing slash: /foo => 301 to /foo/
983
+ if (!path.endsWith('/') && existsSync(filePath) && statSync(filePath).isDirectory()) {
984
+ var qs = url.split('?')[1];
985
+ var location = path + '/' + (qs ? '?' + qs : '');
986
+ res.writeHead(301, { 'Location': location });
987
+ res.end();
988
+ return;
989
+ }
920
990
  }
921
991
 
922
992
  // 404
@@ -1086,6 +1156,69 @@ class BwServeApp {
1086
1156
  });
1087
1157
  res.end(content);
1088
1158
  }
1159
+
1160
+ /**
1161
+ * Generate an HTML directory listing page.
1162
+ * @private
1163
+ * @param {string} urlPath - URL path (with trailing slash)
1164
+ * @param {string} dirPath - Filesystem path to the directory
1165
+ * @returns {string} HTML page
1166
+ */
1167
+ _generateDirListing(urlPath, dirPath) {
1168
+ var entries = readdirSync(dirPath);
1169
+ var dirs = [];
1170
+ var files = [];
1171
+
1172
+ for (var i = 0; i < entries.length; i++) {
1173
+ var name = entries[i];
1174
+ var fullPath = join(dirPath, name);
1175
+ try {
1176
+ var st = statSync(fullPath);
1177
+ if (st.isDirectory()) {
1178
+ dirs.push({ name: name + '/', size: '-' });
1179
+ } else {
1180
+ files.push({ name: name, size: _formatSize(st.size) });
1181
+ }
1182
+ } catch (e) {
1183
+ // Skip entries we cannot stat
1184
+ }
1185
+ }
1186
+
1187
+ // Sort alphabetically
1188
+ dirs.sort(function(a, b) { return a.name.localeCompare(b.name); });
1189
+ files.sort(function(a, b) { return a.name.localeCompare(b.name); });
1190
+
1191
+ var all = dirs.concat(files);
1192
+
1193
+ var rows = '';
1194
+ // Parent directory link (unless at root)
1195
+ if (urlPath !== '/') {
1196
+ rows += '<tr><td><a href="../">..</a></td><td>-</td></tr>\n';
1197
+ }
1198
+ for (var j = 0; j < all.length; j++) {
1199
+ var entry = all[j];
1200
+ var escaped = entry.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
1201
+ rows += '<tr><td><a href="' + encodeURIComponent(entry.name.replace(/\/$/, '')) + (entry.size === '-' ? '/' : '') + '">' + escaped + '</a></td><td>' + entry.size + '</td></tr>\n';
1202
+ }
1203
+
1204
+ var escapedPath = urlPath.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
1205
+ return '<!DOCTYPE html>\n<html><head><meta charset="utf-8"><title>Index of ' + escapedPath + '</title>' +
1206
+ '<style>body{font-family:monospace;margin:2em}table{border-collapse:collapse}td,th{text-align:left;padding:4px 16px}a{text-decoration:none}a:hover{text-decoration:underline}</style>' +
1207
+ '</head><body><h1>Index of ' + escapedPath + '</h1><table><tr><th>Name</th><th>Size</th></tr>\n' +
1208
+ rows + '</table></body></html>';
1209
+ }
1210
+ }
1211
+
1212
+ /**
1213
+ * Format a byte size as a human-readable string.
1214
+ * @param {number} bytes
1215
+ * @returns {string}
1216
+ */
1217
+ function _formatSize(bytes) {
1218
+ if (bytes < 1024) return bytes + ' B';
1219
+ if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
1220
+ if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
1221
+ return (bytes / (1024 * 1024 * 1024)).toFixed(1) + ' GB';
1089
1222
  }
1090
1223
 
1091
1224
  var version = VERSION;
package/dist/sri.json CHANGED
@@ -1,51 +1,51 @@
1
1
  {
2
- "version": "2.0.25",
2
+ "version": "2.0.31",
3
3
  "algorithm": "sha384",
4
- "generated": "2026-03-31",
4
+ "generated": "2026-04-12",
5
5
  "files": {
6
- "bitwrench-bccl.cjs.js": "sha384-RA66j3cZJmQZMYv4wHTmYJFMZHnCCQw1Zn8UcAia7WI4NmGZA3RxLMCHg5IcpQSy",
7
- "bitwrench-bccl.cjs.min.js": "sha384-UVKyX6Ep7ITUok4aQ5SpAo56pr/unOqNX1rg0Nqd5TdFRfS/QLsvdpB5i00k/Lp8",
8
- "bitwrench-bccl.esm.js": "sha384-urwgpnwC8IpMjqShHzGgKjBVghNko0neSy1fkECY7MgFU3auHC2Bcn3MoK9E9BGU",
9
- "bitwrench-bccl.esm.min.js": "sha384-oZNyOQt9pSv6MeG/1EbkcJjZimSHC+ObW3F6wbixFY2n9wgT+4kEjrBHUW7xah21",
10
- "bitwrench-bccl.umd.js": "sha384-VGLCy3tnpKpvnjY/RvARW8mVoHZwycIk0fPbgbh//6xXC3rQEs/tntbqnAWw1oTa",
11
- "bitwrench-bccl.umd.min.js": "sha384-o2IJV021qMlcfCCogT9BUCq7XGz5GkigYSnQfvybRx6kYNJC8txz5x/v5DjuqUUI",
12
- "bitwrench-code-edit.cjs.js": "sha384-qhWEjthIXdWPGKz1CULfIbI4hv8m/n5ys7kXE0fIQYf4jsYCC1L4GukM5KRqRToS",
13
- "bitwrench-code-edit.cjs.min.js": "sha384-HRxcDwX9dGKq0OghPsK8ZLiVEzzw1fiEU46qw8btM5hMqdv4x5EFnfkCWDW5LuV+",
14
- "bitwrench-code-edit.es5.js": "sha384-M7p1KKOG1JGQeW0tQglvyTAUpqSLiDVMCr/CHpasi9/fWWukLBipQ/pDFUggtq86",
15
- "bitwrench-code-edit.es5.min.js": "sha384-SImIBlVcBZ9Ex5jUsWpOAgtIBe+b8lnMGF1Ym8veGeD0VlY51s4i3u42eymJMjM1",
16
- "bitwrench-code-edit.esm.js": "sha384-h0fE0qWyEVmYoOY/nqJX6bfWlKllg1wTyU7E3N2A8820ZICJ2KZPhDRCp7/BTz+o",
17
- "bitwrench-code-edit.esm.min.js": "sha384-HtIhxNiVOUuAm33FYQkXAUJvSz33TqAKD6Uqv1iwyXlEJi1DrNd43glgL2VjNp7G",
18
- "bitwrench-code-edit.umd.js": "sha384-jlE6Tns6Lr10JEWXHZUks8IyvsBYik0hWFynXOm6LXxE8jXrpPAEuTNTaa9VAOqY",
19
- "bitwrench-code-edit.umd.min.js": "sha384-M6F7F7tqxV8EykfZrRv9bDOYZOwkHw9bH0znMHRnJo6MbwklnrY10rb808z4FcQF",
20
- "bitwrench-debug.js": "sha384-dFXWL/RA55mOHgt9WtpcN2EUi5FP1NEdOXffQhTMg7HYQLjjDm+vfihwbHne4qpb",
21
- "bitwrench-debug.min.js": "sha384-9xekM72GEadAZz/xeh3MmazFmS8lAyXOt9M5fLzjINPaIvk2Tyfr29a9e44GJGci",
22
- "bitwrench-lean.cjs.js": "sha384-g/xiDIMH6SyLwVQZ4kBw7vd5mwItjwsFm7tt7lagmMPv1GLeq7TRnysAF7NYu1D/",
23
- "bitwrench-lean.cjs.min.js": "sha384-NAu0XZcYl9esPSv9usftOKo0gKP3WFfITkErF4/F/nTeRss5HZEoP24OQTHJ0PIb",
24
- "bitwrench-lean.es5.js": "sha384-md3746BNl73qHbL3qxHW9lJkSXxfl0iNtad8+ueyiNMMYmQtwqmgqcr5wv2Ifidh",
25
- "bitwrench-lean.es5.min.js": "sha384-6eZcoh9giHgNLfx3dl8L/ZFNUyqYJRbiQtdEi1QPgD38A6Xu6oY/mNEHLgNdxAqY",
26
- "bitwrench-lean.esm.js": "sha384-6mJxNfGQWSX5wZDHUfDQtoQop5J8r6mVTmpav2ro61Fc8nyPe91Mf06czeSGTzYB",
27
- "bitwrench-lean.esm.min.js": "sha384-A6fDCS7onP178iZA98Ioi7WFmgANXK4gD7TGZTX4E/3FINGtgNJifn8ScEunwlKf",
28
- "bitwrench-lean.umd.js": "sha384-tI59nJNwNFyhZOSX1uoGLVto0WQk0feHQx+GI71ahwyVbxhufS3mqSzXDLg6eCEY",
29
- "bitwrench-lean.umd.min.js": "sha384-Lk1yDDqJbSTh3QoWl9t9WQqnOf3RqUdDswVgUPWFHbirBt77ZJF6v/MfT5cwWHFd",
30
- "bitwrench-util-css.cjs.js": "sha384-eAabzZqdE8Cxj8XFWjOVQmpflXsxaPqFRMklbljSm8QgIUf03ll12xMNrnRdNQ00",
31
- "bitwrench-util-css.cjs.min.js": "sha384-0eZt3OMTcA9V74g6Fo/udBm9jFTTT5/cHIa8UQ47z65hJKVpskOr95+l6La8VhxM",
32
- "bitwrench-util-css.es5.js": "sha384-lF7JM6zgkGRpiPmHdBG08yUBlJjfGNEb5il9CRAkM4DfFaWcPuhG57K7JIcFsNf4",
33
- "bitwrench-util-css.es5.min.js": "sha384-vPGI+zh9/gE2hyhlN2NeBxZzNpFuMB/CmQABBD8MOgbL5etd3iaq4UYGIjLBesmW",
34
- "bitwrench-util-css.esm.js": "sha384-I/xcJwIp202GKLwIKIUqkiAWkoUQRFn7fNSorTv/DZe6WovBwpzWWAIr3A1o0ine",
35
- "bitwrench-util-css.esm.min.js": "sha384-uY+4TDPxWPDWlpfnKP/0SYHZRx4XqxjSQPth1iKoG+uJ34UhiYmPu8Da+lDqXXd8",
36
- "bitwrench-util-css.umd.js": "sha384-Dz9fjqZlIpFd68LNP1GQyTXt6VzwIsM19oxf9I8OQz/pqgO5+bvOjPleHnAd6AcG",
37
- "bitwrench-util-css.umd.min.js": "sha384-RCuWraavRluQ5MEtVYWgtrEzSj8FanNT20plj0aYTP+60IHIlAeULwYYu6UkNt1i",
38
- "bitwrench.cjs.js": "sha384-+6wWDHXlpihbUCMcfyuXx6JQn/xmUYFzsIykalbLVHALcWY/00J0dkE9ghNBwWsg",
39
- "bitwrench.cjs.min.js": "sha384-um4doW2b9QMWnZFNeN75A12u7MgaxXqfTDD8RRY98TY9aB+Pp8wrOwVQSvYVcy8w",
40
- "bitwrench.css": "sha384-y0YMF2B2xZF3TReu5KAuetdM7I/yFjJ7ATB9/pM//70PbXnn9+NBcb4fsb3cS2pe",
41
- "bitwrench.es5.js": "sha384-ydqqwDi8AY8C9Ns7NughmVlzA7ZMpTIyYB+0+ZWghf1j5btx5Y0Rptx4wU7rxYGJ",
42
- "bitwrench.es5.min.js": "sha384-LvrzQJLd5klWf3HVzRoDO8UNNSz3FXJ1WYhwdq4rZA70jqCSVH1kr1qOmqsc/dXB",
43
- "bitwrench.esm.js": "sha384-lPKbGfBkur2VHJ2kzM11S9koP682I6roeITvEmRzm+R1A+YIqpHa3NWSj92p9w9k",
44
- "bitwrench.esm.min.js": "sha384-JsRZBx7Iu4030QDS+5g9EIx3wHonD3rtvuFElKBCQVXgyKsCHsvuQIFVqnS4dcOb",
6
+ "bitwrench-bccl.cjs.js": "sha384-g+bREqoEZobSTDOItkmaoOIh4P9mf1GQCAKRRtI/j6SEycBq/ruD0EsxniaOPamZ",
7
+ "bitwrench-bccl.cjs.min.js": "sha384-3mEr1QPj1kMr6xILZRZmlLNLYpEOkiAM/NGBCoxZFUtGX6atcOxzplW+Fl2y7+0N",
8
+ "bitwrench-bccl.esm.js": "sha384-67aNfMHkggJSQa5N7+8cEYYihmYRmNybS+CqQVRien4+uMGPBxCHC4w76H1yjtZw",
9
+ "bitwrench-bccl.esm.min.js": "sha384-jmhO+xdKNGc13zmpYSu4UAiRnHbeBgEfHpgtrm376pJ+Bq4elgmAkIrqtr5nRbQp",
10
+ "bitwrench-bccl.umd.js": "sha384-7euK145GD8glzY1722Tc5AcMLftkUcnElt4QWxHTRynKFTmMLKVINAsCXxgMfVaQ",
11
+ "bitwrench-bccl.umd.min.js": "sha384-h1B+7k8xaoAWnFYfTXbSljkU9qTJb9nMYFWBhS/lXLkf90yu8ynzrC5ORoYqevi/",
12
+ "bitwrench-code-edit.cjs.js": "sha384-Ekls5sTQn5J+AZHydpz9L41kvojclPk2Xjgf9q3bAcu+w31sYIgUFWCRXwNjBb9r",
13
+ "bitwrench-code-edit.cjs.min.js": "sha384-ay5kEd9OnDQeSCeAZuDqUaZYmdI+8KXyUMWxVU1Ks3NUgCsuszk+eIt4gUgahqqb",
14
+ "bitwrench-code-edit.es5.js": "sha384-gzUHN64sJj9ROmEZuqsoWFp6i/V4L6gDy5TKuLLir+5scfnopxZLaSwwXzxG08CP",
15
+ "bitwrench-code-edit.es5.min.js": "sha384-2TIS1ABSa0cn0P7LE3vgkHM4RDMttfzOIxyqgyCWY56G6g68jd3rJJ22zgcbdojm",
16
+ "bitwrench-code-edit.esm.js": "sha384-Jnlrp+W1Osrtmv81vYJ/1OgvICgaekEb9DCpmmZVr1KKPzGGrzfJBocmoBvwWPyB",
17
+ "bitwrench-code-edit.esm.min.js": "sha384-/rGVBJaZqCOHT2BIwvW9wX2QZ6Mb+WO3Q8URi8zrkG4yoB+Sguj/5V4XAsifMmG4",
18
+ "bitwrench-code-edit.umd.js": "sha384-I0lPZhUKsBZZR8CzgA7bPHRVUBEG4EGAISudQv7Y17j/4dbdiNzqUeMlDDl596Lt",
19
+ "bitwrench-code-edit.umd.min.js": "sha384-+/fx7WThOnpKiAnGftDIKyw+jgUE0mHXOpeLOg92hXkJ9db+JX7kdYKt3+NZdgUs",
20
+ "bitwrench-debug.js": "sha384-Y4XKfgz6PTTaFH2Dix2s8LHrF3LYjqSxb4HL5BJbeJCsTXxUtiJtL2iXK9Q1Jjjm",
21
+ "bitwrench-debug.min.js": "sha384-Oq6Ifg/M2kNLPm/PU+G9lGz7k+mrfnwbb682OZo0vcwmW0mqD6kQRgZsSzvs3Zk3",
22
+ "bitwrench-lean.cjs.js": "sha384-tDE21mhY4wK2IKVSr8RTUXmALY1PzWkGtOaaP+j/2hyq9D5fWRqlwSeZuzchpzBE",
23
+ "bitwrench-lean.cjs.min.js": "sha384-HMV724gyzbWQIeZqCA7hKOldeKmeXGC0qRCjU0O+vwOE6NOYdh2QoUHfC2XrLFq0",
24
+ "bitwrench-lean.es5.js": "sha384-emU2M7HoqzSSZpTkIxE/WLTr+NyJJY2NWPy0yZ/m0SK0Tsi+07v+Ga48gQ0w6Zki",
25
+ "bitwrench-lean.es5.min.js": "sha384-azY3Ra//NFHnz9GWSFHU7+ykX0IFfuSMUcQzYGJMOxIkntluEvEStEWSC8zmMUU7",
26
+ "bitwrench-lean.esm.js": "sha384-4rgwMYIs+8F8YO91pUhvTdYNQQTwK9kFbLte0+IA5epp0vhypWAW91XeV4mif7Ht",
27
+ "bitwrench-lean.esm.min.js": "sha384-vzJjHbJjhMoNDV77pv6jUIxa54y0RcKVya/YfJjwU9P3vwbd9whO16GFcvrH2lXS",
28
+ "bitwrench-lean.umd.js": "sha384-HcoLWkzFGUrrXF0vb6NbpSxRT31+BZCuIWnF6PjHiGzli9m1F972Djt5bw4/U94T",
29
+ "bitwrench-lean.umd.min.js": "sha384-MwB/y0yT93N6uVLv6XHNPGRRkhhOJlhZuNK93dWm0Rfk+W3v/Ue1Wpyfe2SMJ6ec",
30
+ "bitwrench-util-css.cjs.js": "sha384-AOtO0LmNIlM0Db6JjwiXJXkqJXcYgAFOgXZRg2DsVPadOujTqSyu+0xW/hBUtX9y",
31
+ "bitwrench-util-css.cjs.min.js": "sha384-C/u6y4Ku3mKi/TYi8BsqXLHH+QOJGapjgfbuFnO/+6n2GRpdqLveN3kETWmRsnYr",
32
+ "bitwrench-util-css.es5.js": "sha384-07y+w3Vfsja7aysfVHQ70Wflwa8XjCpzkgamrkJfLhDVNwF9Hav3xWS8eNLSRjuu",
33
+ "bitwrench-util-css.es5.min.js": "sha384-XzcN9nNXn5ZWpVSgmg7TJZjtpp3i3e+gk8mZ7rDuDC83EgmEXoNBFhwJWbI2wsHX",
34
+ "bitwrench-util-css.esm.js": "sha384-mrmE9DDsN1kHxW7Dlh/1N6GlmbvDwVomn4Bjakkb0fDdTYOy/0dymp2DyxPS0HTP",
35
+ "bitwrench-util-css.esm.min.js": "sha384-MMn/HvHKZASAddOU2zD0MwdHH+fkcd5dx7eF2PpEhokAVo1+aY8pgZ+f+GkIiBgx",
36
+ "bitwrench-util-css.umd.js": "sha384-MKtAXDkkAX9gHfh9t2FikS0DQ9R4otG7JNyzInauZS2nb7tsd/ZGh//dwO+ob1ca",
37
+ "bitwrench-util-css.umd.min.js": "sha384-PHuLiNKRvvR0/nqHLkMZ+E3nh4VMKtOPppvjBhhjlI9baFECtT8gl0Hxgy2GkdPx",
38
+ "bitwrench.cjs.js": "sha384-glfbsEhz4gaiy8shr2Gu+XpByoxQ+WcO3NeBkPrTxSihsCmH053oLXlFhsC3hUPK",
39
+ "bitwrench.cjs.min.js": "sha384-wq9oSyr7/fdTolPFSV+EbdmgJU4djEnSAXgzJTFGrzKZJS9nDtJnY0m+uCBMtTiN",
40
+ "bitwrench.css": "sha384-gVfREIu0p9E0gp0cqKrIavfHDMPgay9pDctK2/BEtchIcViIJSSw7devR52ubWqr",
41
+ "bitwrench.es5.js": "sha384-RBjH+7YnynSh2EQ8OyhOeQv5cKZ0vwyqfCAIhn5/oOJxcP6vM/sxqUZRO751v4F/",
42
+ "bitwrench.es5.min.js": "sha384-vdBw8nOsqshb4g5cygdBZOQzFHsu1Z8FlBmj/RPel/sZt9CUD6/lz1XCN6VxXtVR",
43
+ "bitwrench.esm.js": "sha384-VJP0xOXk5d7pnhASh2XmgW8dhCe6df8b9bVVtNzp7NyPPLYaG6TwcsvSwf4AMDhR",
44
+ "bitwrench.esm.min.js": "sha384-WKh0HlTypEUTiv50VV5A/jvjV63zRGGg2mp2oA1tfD+t3d/Ab6EUB8AIN+Q/PVRx",
45
45
  "bitwrench.min.css": "sha384-4ymUTaU2kwrsPLCsEGReVJe2rGzsHkNG1BjrHB7EGAOqMK+SgRvaHPoYUFk7tXSE",
46
- "bitwrench.umd.js": "sha384-trTM4NoRCWS6uVju/sVT/+qrQqAWc2ykIiIJ6EgdqKKWMfWLSj7A63egxbuaesZC",
47
- "bitwrench.umd.min.js": "sha384-uYz9u6YCCcaYyJ5SFjvgLo3j+ThD6WgciFEFtlk6t36dgp2d9rsxvVPG5QTLC8Sy",
48
- "bwserve.cjs.js": "sha384-fs6zRLlgLSMl167JZR29LNzjOcOhNjXtJpfpg8Y2xDRmGMJNKK6fBMfSXxnD58Ed",
49
- "bwserve.esm.js": "sha384-ZXn4aIBNgPdwr6QaDGqV9WTCqFIAgWgndQpHs6wZbR9WrErO12kifamD3qaZONOb"
46
+ "bitwrench.umd.js": "sha384-LynAfOeVKIZ4kjlFhnZF62qGdv+WPAjOc397YebvINS5eOhfyW3vs+ADIIrZut3H",
47
+ "bitwrench.umd.min.js": "sha384-vWftG5Z0Xnd2aMbiYBtkrpswWUsrkJ6rTLohn9ZWIhssjy76iWeJaEnSifE9/V7J",
48
+ "bwserve.cjs.js": "sha384-Vm1L58xaNNymEJhthSNr7HbJTBa8HeA6+H5SlPD3ED0PXDXd1dTZXcH5Q+fvRo4u",
49
+ "bwserve.esm.js": "sha384-jrJao6NSXHoZnkV1CkAWbCs1y9dDBQWXiW5B66vN8NogNP3WOtVYFsLSd+S0nTAU"
50
50
  }
51
51
  }