@trebor/buildhtml 1.0.2 → 1.0.4

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 (3) hide show
  1. package/README.md +89 -29
  2. package/index.js +16 -57
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,7 +1,6 @@
1
- # BuildHTML
1
+ # @trebor/buildhtml
2
2
 
3
- **High-performance, server-side rendering (SSR) library for Node.js.**
4
- *"Build HTML at lightning speed with reactive state management."*
3
+ **High-performance, server-side rendering (SSR) library for Node.js.** *"Build HTML at lightning speed with reactive state management."*
5
4
 
6
5
  ---
7
6
 
@@ -9,20 +8,20 @@
9
8
 
10
9
  BuildHTML is a lightweight SSR library for Node.js featuring object pooling, reactive state management, and CSS-in-JS capabilities. Build HTML on the server with minimal memory usage and blazing-fast performance.
11
10
 
12
- - **Zero dependencies** – Only Node.js required
13
- - **High Performance** – Object pooling and LRU caching (1-5ms render time)
14
- - **Reactive State** – Built-in state management with automatic UI updates
15
- - **CSS-in-JS** – Scoped and global styling with automatic CSS generation
16
- - **Security** – XSS protection, CSS sanitization, and CSP nonce support
17
- - **Production Ready** – HTML minification, compression, and metrics
18
- - **JSON Export** – Save/restore pages with optional obfuscation
11
+ - **Zero dependencies** – Only Node.js required.
12
+ - **High Performance** – Object pooling and LRU caching (1-5ms render time).
13
+ - **Reactive State** – Built-in state management with automatic UI updates.
14
+ - **CSS-in-JS** – Scoped and global styling with automatic CSS generation.
15
+ - **Security** – XSS protection, CSS sanitization, and CSP nonce support.
16
+ - **Production Ready** – HTML minification, compression, and metrics.
17
+ - **JSON Export** – Save/restore pages with optional obfuscation.
19
18
 
20
19
  ---
21
20
 
22
21
  ## Installation
23
22
 
24
23
  ```bash
25
- npm install buildhtml
24
+ npm install @trebor/buildhtml
26
25
  ```
27
26
 
28
27
  ---
@@ -30,7 +29,7 @@ npm install buildhtml
30
29
  ## Quick Start
31
30
 
32
31
  ```javascript
33
- const { Document } = require('buildhtml');
32
+ const { Document } = require('@trebor/buildhtml');
34
33
 
35
34
  // Create a document
36
35
  const doc = new Document();
@@ -257,7 +256,7 @@ const {
257
256
  resetPools, // Reset object pools
258
257
  healthCheck, // Health check data
259
258
  metrics // Performance metrics
260
- } = require('buildhtml');
259
+ } = require('@trebor/buildhtml');
261
260
  ```
262
261
 
263
262
  ---
@@ -268,7 +267,7 @@ const {
268
267
 
269
268
  ```javascript
270
269
  const express = require('express');
271
- const { Document } = require('buildhtml');
270
+ const { Document } = require('@trebor/buildhtml');
272
271
 
273
272
  const app = express();
274
273
 
@@ -400,7 +399,7 @@ app.get('/spa', (req, res) => {
400
399
  ## Configuration
401
400
 
402
401
  ```javascript
403
- const { CONFIG } = require('buildhtml');
402
+ const { CONFIG } = require('@trebor/buildhtml');
404
403
 
405
404
  CONFIG.mode = 'prod'; // 'prod' or 'dev'
406
405
  CONFIG.poolSize = 150; // Max pooled elements
@@ -436,14 +435,14 @@ clearCache('user-'); // Clear all keys containing 'user-'
436
435
  ### enableCompression()
437
436
 
438
437
  ```javascript
439
- const { enableCompression } = require('buildhtml');
438
+ const { enableCompression } = require('@trebor/buildhtml');
440
439
  app.use(enableCompression());
441
440
  ```
442
441
 
443
442
  ### warmupCache(routes)
444
443
 
445
444
  ```javascript
446
- const { warmupCache } = require('buildhtml');
445
+ const { warmupCache } = require('@trebor/buildhtml');
447
446
 
448
447
  await warmupCache([
449
448
  { key: 'home', builder: () => buildHomePage() },
@@ -479,7 +478,7 @@ const html = doc.render();
479
478
 
480
479
  ```javascript
481
480
  // Render with JSON embedded in HTML
482
- const html = doc.renderJSON({ encrypt: true });
481
+ const html = doc.renderJSON({ obfuscate: true });
483
482
 
484
483
  // In browser:
485
484
  console.log(window.__SCULPTOR_DATA__);
@@ -490,31 +489,92 @@ console.log(window.__SCULPTOR_DATA__);
490
489
 
491
490
  ## Security
492
491
 
493
- ### XSS Protection
494
-
495
- All text is automatically escaped:
492
+ ### Built-in Security Features
496
493
 
494
+ **Automatic XSS Protection**
497
495
  ```javascript
498
496
  doc.create('div').text('<script>alert("XSS")</script>');
499
497
  // Output: &lt;script&gt;alert("XSS")&lt;/script&gt;
500
498
  ```
501
499
 
502
- ### CSS Injection Protection
503
-
504
- Dangerous CSS characters are sanitized:
505
-
500
+ **CSS Injection Prevention**
506
501
  ```javascript
507
502
  el.css({ background: 'red; } body { display: none; }' });
508
503
  // Sanitized automatically
509
504
  ```
510
505
 
511
- ### CSP Nonce Support
512
-
506
+ **CSP Nonce Support**
513
507
  ```javascript
514
508
  const doc = new Document({ nonce: 'abc123' });
515
509
  // All inline scripts/styles get nonce attribute
516
510
  ```
517
511
 
512
+ ### Enhanced Security Features (NEW!)
513
+
514
+ **Security Headers Middleware**
515
+ ```javascript
516
+ const { securityHeaders } = require('@trebor/buildhtml');
517
+
518
+ app.use(securityHeaders({
519
+ enableCSP: true,
520
+ enableHSTS: true,
521
+ enableXFrameOptions: true,
522
+ cspNonce: (req) => req.nonce
523
+ }));
524
+ ```
525
+
526
+ **Input Sanitization**
527
+ ```javascript
528
+ const { sanitize } = require('@trebor/buildhtml');
529
+
530
+ // Text sanitization
531
+ const safe = sanitize.text('<script>bad</script>');
532
+
533
+ // URL sanitization (blocks javascript:, data:, vbscript:)
534
+ const url = sanitize.url('javascript:alert(1)'); // Returns ''
535
+
536
+ // Email validation
537
+ const email = sanitize.email('user@example.com');
538
+
539
+ // Filename sanitization (prevents path traversal)
540
+ const filename = sanitize.filename('../../../etc/passwd');
541
+ ```
542
+
543
+ **CSRF Protection**
544
+ ```javascript
545
+ const { csrf } = require('@trebor/buildhtml');
546
+
547
+ app.use(csrf.middleware());
548
+
549
+ app.post('/submit', (req, res) => {
550
+ // CSRF token automatically validated
551
+ // Request blocked if invalid
552
+ });
553
+ ```
554
+
555
+ **Rate Limiting**
556
+ ```javascript
557
+ const { createRateLimiter } = require('@trebor/buildhtml');
558
+
559
+ app.use('/api', createRateLimiter({
560
+ windowMs: 15 * 60 * 1000, // 15 minutes
561
+ maxRequests: 100
562
+ }));
563
+ ```
564
+
565
+ **CSP Header Generation**
566
+ ```javascript
567
+ const { generateCSP } = require('@trebor/buildhtml');
568
+
569
+ const csp = generateCSP({
570
+ scriptSrc: ["'self'", "'nonce-abc123'"],
571
+ styleSrc: ["'self'"],
572
+ imgSrc: ["'self'", 'data:', 'https:']
573
+ });
574
+ ```
575
+
576
+ 📖 **See [SECURITY.md](./SECURITY.md) for complete security documentation**
577
+
518
578
  ---
519
579
 
520
580
  ## Advanced Features
@@ -546,7 +606,7 @@ doc.oncreate(() => {
546
606
  ```javascript
547
607
  process.env.ENABLE_METRICS = 'true';
548
608
 
549
- const { metrics } = require('buildhtml');
609
+ const { metrics } = require('@trebor/buildhtml');
550
610
 
551
611
  // After some requests...
552
612
  console.log(metrics.getStats());
@@ -663,7 +723,7 @@ const html = doc.render();
663
723
 
664
724
  ```javascript
665
725
  const express = require('express');
666
- const { Document, createCachedRenderer } = require('buildhtml');
726
+ const { Document, createCachedRenderer } = require('@trebor/buildhtml');
667
727
 
668
728
  const app = express();
669
729
 
package/index.js CHANGED
@@ -688,25 +688,20 @@ class LRUCache {
688
688
  const responseCache = new LRUCache(CONFIG.cacheLimit);
689
689
  const inFlightCache = new Map();
690
690
 
691
- /* ---------------- ENCRYPTION ---------------- */
691
+ /* ---------------- OBFUSCATION (NOT ENCRYPTION) ---------------- */
692
692
  // Simple Base64 obfuscation for JSON data
693
- // NOTE: This is obfuscation, NOT cryptographic security!
694
- function generateEncryptionKey() {
695
- // Not needed for Base64, but kept for API compatibility
696
- return 1;
697
- }
698
-
699
- function encryptString(str, key) {
693
+ // WARNING: This is obfuscation ONLY, NOT cryptographic security!
694
+ // It only reduces payload size and makes data less human-readable.
695
+ function obfuscateString(str) {
700
696
  // Simple Base64 is fast and sufficient for obfuscation.
701
- // Reversing large strings is too expensive for the client.
702
697
  if (typeof Buffer !== 'undefined') {
703
698
  return Buffer.from(str, 'utf-8').toString('base64');
704
699
  }
705
700
  return btoa(unescape(encodeURIComponent(str)));
706
701
  }
707
702
 
708
- function getDecryptScript() {
709
- // Optimized decoder: Just decode Base64 (O(1) complexity relative to string ops)
703
+ function getDeobfuscateScript() {
704
+ // Optimized decoder: Just decode Base64
710
705
  return `var _d=function(e){return decodeURIComponent(escape(atob(e)));};`;
711
706
  }
712
707
 
@@ -962,23 +957,13 @@ class Document {
962
957
  doc.head.globalStyles = json.globalStyles || [];
963
958
  doc.head.classStyles = json.classStyles || {};
964
959
 
965
- // Restore global state
960
+ // Restore global state (data only)
966
961
  doc._globalState = json.globalState || {};
967
962
 
968
- // Restore oncreate callbacks
969
- if (json.oncreateCallbacks && Array.isArray(json.oncreateCallbacks)) {
970
- for (const fnStr of json.oncreateCallbacks) {
971
- try {
972
- // eslint-disable-next-line no-eval
973
- const fn = eval(`(${fnStr})`);
974
- doc._oncreateCallbacks.push(fn);
975
- } catch (err) {
976
- if (CONFIG.mode === 'dev') {
977
- console.error('Failed to restore oncreate callback:', err);
978
- }
979
- }
980
- }
981
- }
963
+ // WARNING: Functions cannot be restored from JSON for security reasons.
964
+ // oncreate callbacks, computed functions, and event handlers are NOT restored.
965
+ // This method is intended for server-side data restoration only.
966
+ // For client-side hydration with functions, use renderJSON() instead.
982
967
 
983
968
  // Restore body
984
969
  const deserializeElement = (node) => {
@@ -1009,35 +994,9 @@ class Document {
1009
994
  el._stateBindings = node.stateBindings;
1010
995
  }
1011
996
 
1012
- if (node.computed) {
1013
- try {
1014
- // eslint-disable-next-line no-eval
1015
- el._computed = eval(`(${node.computed})`);
1016
- } catch (err) {
1017
- if (CONFIG.mode === 'dev') {
1018
- console.error('Failed to restore computed function:', err);
1019
- }
1020
- }
1021
- }
1022
-
1023
- if (node.events && Array.isArray(node.events)) {
1024
- for (const evt of node.events) {
1025
- try {
1026
- // eslint-disable-next-line no-eval
1027
- const fn = eval(`(${evt.fn})`);
1028
- el.events.push({
1029
- event: evt.event,
1030
- id: evt.id,
1031
- targetId: evt.targetId,
1032
- fn: fn
1033
- });
1034
- } catch (err) {
1035
- if (CONFIG.mode === 'dev') {
1036
- console.error('Failed to restore event handler:', err);
1037
- }
1038
- }
1039
- }
1040
- }
997
+ // NOTE: Functions (computed, events, oncreate) are NOT restored from JSON
998
+ // for security reasons. This method is for data restoration only.
999
+ // For full client-side hydration with functions, use renderJSON() instead.
1041
1000
 
1042
1001
  el.hydrate = node.hydrate || false;
1043
1002
 
@@ -1206,8 +1165,8 @@ class Document {
1206
1165
 
1207
1166
  // Inject JSON Data (Fast Decode)
1208
1167
  if (obfuscate) {
1209
- const obfuscated = encryptString(jsonStr, true);
1210
- parts.push(getDecryptScript(), `window.${jsonVarName}=JSON.parse(_d("${obfuscated}"));`);
1168
+ const obfuscated = obfuscateString(jsonStr);
1169
+ parts.push(getDeobfuscateScript(), `window.${jsonVarName}=JSON.parse(_d("${obfuscated}"));`);
1211
1170
  } else {
1212
1171
  parts.push(`window.${jsonVarName}=${jsonStr};`);
1213
1172
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trebor/buildhtml",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Zero-dependency, ultra-fast HTML builder for server-side rendering (SSR).",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -35,4 +35,4 @@
35
35
  "url": "https://github.com/0trebor0/buildhtml/issues"
36
36
  },
37
37
  "homepage": "https://github.com/0trebor0/buildhtml#readme"
38
- }
38
+ }