svelteesp32 2.2.2 → 2.3.1

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
@@ -79,8 +79,7 @@ void setup() {
79
79
 
80
80
  ## What's New
81
81
 
82
- - **v2.2.2** — `static const` data/ETag arrays prevent multi-TU linker collisions; `SVELTEESP32_MAX_URI_HANDLERS` define added for psychic engine; default exclude patterns removed (now explicit-only)
83
- - **v2.2.1** — Enhanced `--dryrun` output: engine/ETag/gzip/SPA summary header + aligned route table with MIME types, sizes, and tags (`[default]`, `[no gzip]`, `[SPA catch-all]`)
82
+ - **v2.3.0** — `--cachetime-html` and `--cachetime-assets` for per-type cache control (e.g. `no-cache` for HTML, 1-year for content-hashed JS/CSS)
84
83
  - **v2.2.0** — SPA routing catch-all (`--spa`) for client-side routers on all four engines
85
84
  - **v2.1.0** — New Arduino WebServer engine (`-e webserver`), dependency updates
86
85
  - **v2.0.0** — **BREAKING**: PsychicHttpServer V2 is now the default `psychic` engine. The `psychic2` engine has been removed. Dry run mode, C++ identifier validation, improved MIME type warnings
@@ -321,6 +320,22 @@ Fine-tune how browsers cache your content:
321
320
 
322
321
  - **Default:** `no-cache` — browsers always validate with server (ETag check)
323
322
  - **Long-term caching:** `--cachetime=86400` — cache for 24 hours without any server requests
323
+ - **Per-type caching:** Use `--cachetime-html` and `--cachetime-assets` independently
324
+
325
+ Vite and webpack produce content-hashed filenames for JS/CSS (e.g., `app.a1b2c3.js`). Those can be cached for up to a year because the hash changes with every build, but `index.html` must stay `no-cache` since it's the entry point that references them:
326
+
327
+ ```bash
328
+ npx svelteesp32 -e psychic -s ./dist -o ./output.h \
329
+ --etag=true --cachetime-html=0 --cachetime-assets=31536000
330
+ ```
331
+
332
+ This emits `Cache-Control: no-cache` for every `text/html` file and `Cache-Control: max-age=31536000` for all other assets in the same header, with no per-file configuration needed.
333
+
334
+ | Option | Applies to | Falls back to |
335
+ | -------------------- | -------------------------------- | -------------- |
336
+ | `--cachetime-html` | `text/html` only | `--cachetime` |
337
+ | `--cachetime-assets` | everything else | `--cachetime` |
338
+ | `--cachetime` | all files (when no override set) | `0` (no-cache) |
324
339
 
325
340
  ### Automatic Index Handling
326
341
 
@@ -447,26 +462,28 @@ Called for every response (200 = content served, 304 = cache hit).
447
462
 
448
463
  ## CLI Reference
449
464
 
450
- | Option | Description | Default |
451
- | ---------------- | --------------------------------------------------- | ----------------------- |
452
- | `-s` | Source folder with compiled web files | (required) |
453
- | `-e` | Web server engine (psychic/async/espidf/webserver) | `psychic` |
454
- | `-o` | Output header file path | `svelteesp32.h` |
455
- | `--etag` | ETag caching (true/false/compiler) | `false` |
456
- | `--gzip` | Gzip compression (true/false/compiler) | `true` |
457
- | `--exclude` | Exclude files by glob pattern | System files |
458
- | `--basepath` | URL prefix for all routes | (none) |
459
- | `--maxsize` | Max total uncompressed size (e.g., `400k`, `1m`) | (none) |
460
- | `--maxgzipsize` | Max total gzip size (e.g., `150k`, `500k`) | (none) |
461
- | `--cachetime` | Cache-Control max-age in seconds | `0` |
462
- | `--version` | Version string in header | (none) |
463
- | `--define` | C++ define prefix | `SVELTEESP32` |
464
- | `--espmethod` | Init function name | `initSvelteStaticFiles` |
465
- | `--config` | Custom RC file path | `.svelteesp32rc.json` |
466
- | `--dryrun` | Show route table + summary without writing output | `false` |
467
- | `--spa` | Serve index.html for unmatched routes (SPA routing) | `false` |
468
- | `--noindexcheck` | Skip index.html validation | `false` |
469
- | `-h` | Show help | |
465
+ | Option | Description | Default |
466
+ | -------------------- | ---------------------------------------------------- | ----------------------- |
467
+ | `-s` | Source folder with compiled web files | (required) |
468
+ | `-e` | Web server engine (psychic/async/espidf/webserver) | `psychic` |
469
+ | `-o` | Output header file path | `svelteesp32.h` |
470
+ | `--etag` | ETag caching (true/false/compiler) | `false` |
471
+ | `--gzip` | Gzip compression (true/false/compiler) | `true` |
472
+ | `--exclude` | Exclude files by glob pattern | (none) |
473
+ | `--basepath` | URL prefix for all routes | (none) |
474
+ | `--maxsize` | Max total uncompressed size (e.g., `400k`, `1m`) | (none) |
475
+ | `--maxgzipsize` | Max total gzip size (e.g., `150k`, `500k`) | (none) |
476
+ | `--cachetime` | Cache-Control max-age in seconds (all files) | `0` |
477
+ | `--cachetime-html` | max-age for HTML files (overrides `--cachetime`) | (unset) |
478
+ | `--cachetime-assets` | max-age for non-HTML files (overrides `--cachetime`) | (unset) |
479
+ | `--version` | Version string in header | (none) |
480
+ | `--define` | C++ define prefix | `SVELTEESP32` |
481
+ | `--espmethod` | Init function name | `initSvelteStaticFiles` |
482
+ | `--config` | Custom RC file path | `.svelteesp32rc.json` |
483
+ | `--dryrun` | Show route table + summary without writing output | `false` |
484
+ | `--spa` | Serve index.html for unmatched routes (SPA routing) | `false` |
485
+ | `--noindexcheck` | Skip index.html validation | `false` |
486
+ | `-h` | Show help | |
470
487
 
471
488
  ---
472
489
 
@@ -485,6 +502,9 @@ Store your settings in `.svelteesp32rc.json` for zero-argument builds:
485
502
  "basepath": "/ui",
486
503
  "maxsize": "400k",
487
504
  "maxgzipsize": "150k",
505
+ "cachetime": 0,
506
+ "cachetimehtml": 0,
507
+ "cachetimeassets": 31536000,
488
508
  "noindexcheck": false,
489
509
  "dryrun": false,
490
510
  "spa": false
@@ -7,6 +7,8 @@ interface ICopyFilesArguments {
7
7
  gzip: 'true' | 'false' | 'compiler';
8
8
  etag: 'true' | 'false' | 'compiler';
9
9
  cachetime: number;
10
+ cachetimeHtml?: number;
11
+ cachetimeAssets?: number;
10
12
  created: boolean;
11
13
  version: string;
12
14
  exclude: string[];
@@ -27,6 +29,8 @@ interface IRcFileConfig {
27
29
  gzip?: 'true' | 'false' | 'compiler';
28
30
  etag?: 'true' | 'false' | 'compiler';
29
31
  cachetime?: number;
32
+ cachetimehtml?: number;
33
+ cachetimeassets?: number;
30
34
  created?: boolean;
31
35
  version?: string;
32
36
  exclude?: string[];
@@ -34,6 +34,8 @@ Options:
34
34
  --espmethod <name> Name of generated method (default: "initSvelteStaticFiles")
35
35
  --define <prefix> Prefix of c++ defines (default: "SVELTEESP32")
36
36
  --cachetime <seconds> max-age cache time in seconds (default: 0)
37
+ --cachetime-html <sec> Cache-Control max-age for HTML files (overrides --cachetime)
38
+ --cachetime-assets <sec> Cache-Control max-age for non-HTML assets (overrides --cachetime)
37
39
  --exclude <pattern> Exclude files matching glob pattern (repeatable or comma-separated)
38
40
  Examples: --exclude="*.map" --exclude="test/**/*.ts"
39
41
  --basepath <path> URL prefix for all routes (e.g., "/ui") (default: "")
@@ -92,6 +94,15 @@ function validateBasePath(value) {
92
94
  throw new Error(`basePath must not end with /: ${value}`);
93
95
  if (value.includes('//'))
94
96
  throw new Error(`basePath must not contain //: ${value}`);
97
+ if (value.includes('"'))
98
+ throw new Error(`basePath must not contain double quotes: ${value}`);
99
+ if (value.includes('\\'))
100
+ throw new Error(`basePath must not contain backslashes: ${value}`);
101
+ return value;
102
+ }
103
+ function validateVersion(value) {
104
+ if (!/^[\w+.-]+$/.test(value))
105
+ throw new Error(`version must only contain word characters, dots, hyphens, and plus signs: ${value}`);
95
106
  return value;
96
107
  }
97
108
  function parseSize(value, name) {
@@ -266,6 +277,8 @@ function validateRcConfig(config, rcPath) {
266
277
  'gzip',
267
278
  'etag',
268
279
  'cachetime',
280
+ 'cachetimehtml',
281
+ 'cachetimeassets',
269
282
  'created',
270
283
  'version',
271
284
  'exclude',
@@ -295,6 +308,18 @@ function validateRcConfig(config, rcPath) {
295
308
  if (configObject['cachetime'] < 0)
296
309
  throw new TypeError(`Invalid cachetime in RC file: ${configObject['cachetime']} (must be non-negative)`);
297
310
  }
311
+ if (configObject['cachetimehtml'] !== undefined) {
312
+ if (typeof configObject['cachetimehtml'] !== 'number' || Number.isNaN(configObject['cachetimehtml']))
313
+ throw new TypeError(`Invalid cachetimehtml in RC file: ${configObject['cachetimehtml']}`);
314
+ if (configObject['cachetimehtml'] < 0)
315
+ throw new TypeError(`Invalid cachetimehtml in RC file: ${configObject['cachetimehtml']} (must be non-negative)`);
316
+ }
317
+ if (configObject['cachetimeassets'] !== undefined) {
318
+ if (typeof configObject['cachetimeassets'] !== 'number' || Number.isNaN(configObject['cachetimeassets']))
319
+ throw new TypeError(`Invalid cachetimeassets in RC file: ${configObject['cachetimeassets']}`);
320
+ if (configObject['cachetimeassets'] < 0)
321
+ throw new TypeError(`Invalid cachetimeassets in RC file: ${configObject['cachetimeassets']} (must be non-negative)`);
322
+ }
298
323
  if (configObject['exclude'] !== undefined) {
299
324
  if (!Array.isArray(configObject['exclude']))
300
325
  throw new TypeError("'exclude' in RC file must be an array");
@@ -357,6 +382,10 @@ function parseArguments() {
357
382
  result.gzip = rcConfig.gzip;
358
383
  if (rcConfig.cachetime !== undefined)
359
384
  result.cachetime = rcConfig.cachetime;
385
+ if (rcConfig.cachetimehtml !== undefined)
386
+ result.cachetimeHtml = rcConfig.cachetimehtml;
387
+ if (rcConfig.cachetimeassets !== undefined)
388
+ result.cachetimeAssets = rcConfig.cachetimeassets;
360
389
  if (rcConfig.created !== undefined)
361
390
  result.created = rcConfig.created;
362
391
  if (rcConfig.version)
@@ -400,7 +429,7 @@ function parseArguments() {
400
429
  result.gzip = validateTriState(value, 'gzip');
401
430
  break;
402
431
  case 'version':
403
- result.version = value;
432
+ result.version = validateVersion(value);
404
433
  break;
405
434
  case 'espmethod':
406
435
  result.espmethod = validateCppIdentifier(value, 'espmethod');
@@ -415,6 +444,22 @@ function parseArguments() {
415
444
  if (result.cachetime < 0)
416
445
  throw new TypeError(`Invalid cachetime: ${value} (must be non-negative)`);
417
446
  break;
447
+ case 'cachetime-html': {
448
+ result.cachetimeHtml = Number.parseInt(value, 10);
449
+ if (Number.isNaN(result.cachetimeHtml))
450
+ throw new TypeError(`Invalid cachetime-html: ${value}`);
451
+ if (result.cachetimeHtml < 0)
452
+ throw new TypeError(`Invalid cachetime-html: ${value} (must be non-negative)`);
453
+ break;
454
+ }
455
+ case 'cachetime-assets': {
456
+ result.cachetimeAssets = Number.parseInt(value, 10);
457
+ if (Number.isNaN(result.cachetimeAssets))
458
+ throw new TypeError(`Invalid cachetime-assets: ${value}`);
459
+ if (result.cachetimeAssets < 0)
460
+ throw new TypeError(`Invalid cachetime-assets: ${value} (must be non-negative)`);
461
+ break;
462
+ }
418
463
  case 'exclude': {
419
464
  const patterns = value
420
465
  .split(',')
@@ -518,6 +563,10 @@ function formatConfiguration(cmdLine) {
518
563
  `gzip=${cmdLine.gzip}`,
519
564
  `cachetime=${cmdLine.cachetime}`
520
565
  ];
566
+ if (cmdLine.cachetimeHtml !== undefined)
567
+ parts.push(`cachetimeHtml=${cmdLine.cachetimeHtml}`);
568
+ if (cmdLine.cachetimeAssets !== undefined)
569
+ parts.push(`cachetimeAssets=${cmdLine.cachetimeAssets}`);
521
570
  if (cmdLine.created)
522
571
  parts.push(`created=${cmdLine.created}`);
523
572
  if (cmdLine.version)
@@ -536,7 +585,7 @@ function formatConfiguration(cmdLine) {
536
585
  parts.push(`spa=${cmdLine.spa}`);
537
586
  if (cmdLine.exclude.length > 0)
538
587
  parts.push(`exclude=[${cmdLine.exclude.join(', ')}]`);
539
- return parts.join(' ');
588
+ return parts.join(' ').replace(/[\n\r]/g, ' ');
540
589
  }
541
590
  exports.cmdLine = parseArguments();
542
591
  if (!(0, node_fs_1.existsSync)(exports.cmdLine.sourcepath)) {
package/dist/cppCode.js CHANGED
@@ -192,22 +192,22 @@ void {{methodName}}(PsychicHttpServer * server) {
192
192
 
193
193
  {{#switch ../etag}}
194
194
  {{#case "true"}}
195
- {{#../cacheTime}}
195
+ {{#this.cacheTime}}
196
196
  response->addHeader("Cache-Control", "max-age={{value}}");
197
- {{/../cacheTime}}
198
- {{^../cacheTime}}
197
+ {{/this.cacheTime}}
198
+ {{^this.cacheTime}}
199
199
  response->addHeader("Cache-Control", "no-cache");
200
- {{/../cacheTime}}
200
+ {{/this.cacheTime}}
201
201
  response->addHeader("ETag", etag_{{this.dataname}});
202
202
  {{/case}}
203
203
  {{#case "compiler"}}
204
204
  #ifdef {{../definePrefix}}_ENABLE_ETAG
205
- {{#../cacheTime}}
205
+ {{#this.cacheTime}}
206
206
  response->addHeader("Cache-Control", "max-age={{value}}");
207
- {{/../cacheTime}}
208
- {{^../cacheTime}}
207
+ {{/this.cacheTime}}
208
+ {{^this.cacheTime}}
209
209
  response->addHeader("Cache-Control", "no-cache");
210
- {{/../cacheTime}}
210
+ {{/this.cacheTime}}
211
211
  response->addHeader("ETag", etag_{{this.dataname}});
212
212
  #endif
213
213
  {{/case}}
@@ -275,22 +275,22 @@ void {{methodName}}(PsychicHttpServer * server) {
275
275
 
276
276
  {{#switch ../etag}}
277
277
  {{#case "true"}}
278
- {{#../cacheTime}}
278
+ {{#this.cacheTime}}
279
279
  response->addHeader("Cache-Control", "max-age={{value}}");
280
- {{/../cacheTime}}
281
- {{^../cacheTime}}
280
+ {{/this.cacheTime}}
281
+ {{^this.cacheTime}}
282
282
  response->addHeader("Cache-Control", "no-cache");
283
- {{/../cacheTime}}
283
+ {{/this.cacheTime}}
284
284
  response->addHeader("ETag", etag_{{this.dataname}});
285
285
  {{/case}}
286
286
  {{#case "compiler"}}
287
287
  #ifdef {{../definePrefix}}_ENABLE_ETAG
288
- {{#../cacheTime}}
288
+ {{#this.cacheTime}}
289
289
  response->addHeader("Cache-Control", "max-age={{value}}");
290
- {{/../cacheTime}}
291
- {{^../cacheTime}}
290
+ {{/this.cacheTime}}
291
+ {{^this.cacheTime}}
292
292
  response->addHeader("Cache-Control", "no-cache");
293
- {{/../cacheTime}}
293
+ {{/this.cacheTime}}
294
294
  response->addHeader("ETag", etag_{{this.dataname}});
295
295
  #endif
296
296
  {{/case}}
@@ -363,22 +363,22 @@ void {{methodName}}(PsychicHttpServer * server) {
363
363
 
364
364
  {{#switch ../etag}}
365
365
  {{#case "true"}}
366
- {{#../cacheTime}}
366
+ {{#this.cacheTime}}
367
367
  response->addHeader("Cache-Control", "max-age={{value}}");
368
- {{/../cacheTime}}
369
- {{^../cacheTime}}
368
+ {{/this.cacheTime}}
369
+ {{^this.cacheTime}}
370
370
  response->addHeader("Cache-Control", "no-cache");
371
- {{/../cacheTime}}
371
+ {{/this.cacheTime}}
372
372
  response->addHeader("ETag", etag_{{this.dataname}});
373
373
  {{/case}}
374
374
  {{#case "compiler"}}
375
375
  #ifdef {{../definePrefix}}_ENABLE_ETAG
376
- {{#../cacheTime}}
376
+ {{#this.cacheTime}}
377
377
  response->addHeader("Cache-Control", "max-age={{value}}");
378
- {{/../cacheTime}}
379
- {{^../cacheTime}}
378
+ {{/this.cacheTime}}
379
+ {{^this.cacheTime}}
380
380
  response->addHeader("Cache-Control", "no-cache");
381
- {{/../cacheTime}}
381
+ {{/this.cacheTime}}
382
382
  response->addHeader("ETag", etag_{{this.dataname}});
383
383
  #endif
384
384
  {{/case}}
@@ -485,22 +485,22 @@ void {{methodName}}(AsyncWebServer * server) {
485
485
 
486
486
  {{#switch ../etag}}
487
487
  {{#case "true"}}
488
- {{#../cacheTime}}
488
+ {{#this.cacheTime}}
489
489
  response->addHeader("Cache-Control", "max-age={{value}}");
490
- {{/../cacheTime}}
491
- {{^../cacheTime}}
490
+ {{/this.cacheTime}}
491
+ {{^this.cacheTime}}
492
492
  response->addHeader("Cache-Control", "no-cache");
493
- {{/../cacheTime}}
493
+ {{/this.cacheTime}}
494
494
  response->addHeader("ETag", etag_{{this.dataname}});
495
495
  {{/case}}
496
496
  {{#case "compiler"}}
497
497
  #ifdef {{../definePrefix}}_ENABLE_ETAG
498
- {{#../cacheTime}}
498
+ {{#this.cacheTime}}
499
499
  response->addHeader("Cache-Control", "max-age={{value}}");
500
- {{/../cacheTime}}
501
- {{^../cacheTime}}
500
+ {{/this.cacheTime}}
501
+ {{^this.cacheTime}}
502
502
  response->addHeader("Cache-Control", "no-cache");
503
- {{/../cacheTime}}
503
+ {{/this.cacheTime}}
504
504
  response->addHeader("ETag", etag_{{this.dataname}});
505
505
  #endif
506
506
  {{/case}}
@@ -557,22 +557,22 @@ void {{methodName}}(AsyncWebServer * server) {
557
557
 
558
558
  {{#switch ../etag}}
559
559
  {{#case "true"}}
560
- {{#../cacheTime}}
560
+ {{#this.cacheTime}}
561
561
  response->addHeader("Cache-Control", "max-age={{value}}");
562
- {{/../cacheTime}}
563
- {{^../cacheTime}}
562
+ {{/this.cacheTime}}
563
+ {{^this.cacheTime}}
564
564
  response->addHeader("Cache-Control", "no-cache");
565
- {{/../cacheTime}}
565
+ {{/this.cacheTime}}
566
566
  response->addHeader("ETag", etag_{{this.dataname}});
567
567
  {{/case}}
568
568
  {{#case "compiler"}}
569
569
  #ifdef {{../definePrefix}}_ENABLE_ETAG
570
- {{#../cacheTime}}
570
+ {{#this.cacheTime}}
571
571
  response->addHeader("Cache-Control", "max-age={{value}}");
572
- {{/../cacheTime}}
573
- {{^../cacheTime}}
572
+ {{/this.cacheTime}}
573
+ {{^this.cacheTime}}
574
574
  response->addHeader("Cache-Control", "no-cache");
575
- {{/../cacheTime}}
575
+ {{/this.cacheTime}}
576
576
  response->addHeader("ETag", etag_{{this.dataname}});
577
577
  #endif
578
578
  {{/case}}
@@ -639,22 +639,22 @@ void {{methodName}}(AsyncWebServer * server) {
639
639
 
640
640
  {{#switch ../etag}}
641
641
  {{#case "true"}}
642
- {{#../cacheTime}}
642
+ {{#this.cacheTime}}
643
643
  response->addHeader("Cache-Control", "max-age={{value}}");
644
- {{/../cacheTime}}
645
- {{^../cacheTime}}
644
+ {{/this.cacheTime}}
645
+ {{^this.cacheTime}}
646
646
  response->addHeader("Cache-Control", "no-cache");
647
- {{/../cacheTime}}
647
+ {{/this.cacheTime}}
648
648
  response->addHeader("ETag", etag_{{this.dataname}});
649
649
  {{/case}}
650
650
  {{#case "compiler"}}
651
651
  #ifdef {{../definePrefix}}_ENABLE_ETAG
652
- {{#../cacheTime}}
652
+ {{#this.cacheTime}}
653
653
  response->addHeader("Cache-Control", "max-age={{value}}");
654
- {{/../cacheTime}}
655
- {{^../cacheTime}}
654
+ {{/this.cacheTime}}
655
+ {{^this.cacheTime}}
656
656
  response->addHeader("Cache-Control", "no-cache");
657
- {{/../cacheTime}}
657
+ {{/this.cacheTime}}
658
658
  response->addHeader("ETag", etag_{{this.dataname}});
659
659
  #endif
660
660
  {{/case}}
@@ -731,22 +731,22 @@ void {{methodName}}(WebServer * server) {
731
731
 
732
732
  {{#switch ../etag}}
733
733
  {{#case "true"}}
734
- {{#../cacheTime}}
734
+ {{#this.cacheTime}}
735
735
  server->sendHeader("Cache-Control", "max-age={{value}}");
736
- {{/../cacheTime}}
737
- {{^../cacheTime}}
736
+ {{/this.cacheTime}}
737
+ {{^this.cacheTime}}
738
738
  server->sendHeader("Cache-Control", "no-cache");
739
- {{/../cacheTime}}
739
+ {{/this.cacheTime}}
740
740
  server->sendHeader("ETag", etag_{{this.dataname}});
741
741
  {{/case}}
742
742
  {{#case "compiler"}}
743
743
  #ifdef {{../definePrefix}}_ENABLE_ETAG
744
- {{#../cacheTime}}
744
+ {{#this.cacheTime}}
745
745
  server->sendHeader("Cache-Control", "max-age={{value}}");
746
- {{/../cacheTime}}
747
- {{^../cacheTime}}
746
+ {{/this.cacheTime}}
747
+ {{^this.cacheTime}}
748
748
  server->sendHeader("Cache-Control", "no-cache");
749
- {{/../cacheTime}}
749
+ {{/this.cacheTime}}
750
750
  server->sendHeader("ETag", etag_{{this.dataname}});
751
751
  #endif
752
752
  {{/case}}
@@ -808,22 +808,22 @@ void {{methodName}}(WebServer * server) {
808
808
 
809
809
  {{#switch ../etag}}
810
810
  {{#case "true"}}
811
- {{#../cacheTime}}
811
+ {{#this.cacheTime}}
812
812
  server->sendHeader("Cache-Control", "max-age={{value}}");
813
- {{/../cacheTime}}
814
- {{^../cacheTime}}
813
+ {{/this.cacheTime}}
814
+ {{^this.cacheTime}}
815
815
  server->sendHeader("Cache-Control", "no-cache");
816
- {{/../cacheTime}}
816
+ {{/this.cacheTime}}
817
817
  server->sendHeader("ETag", etag_{{this.dataname}});
818
818
  {{/case}}
819
819
  {{#case "compiler"}}
820
820
  #ifdef {{../definePrefix}}_ENABLE_ETAG
821
- {{#../cacheTime}}
821
+ {{#this.cacheTime}}
822
822
  server->sendHeader("Cache-Control", "max-age={{value}}");
823
- {{/../cacheTime}}
824
- {{^../cacheTime}}
823
+ {{/this.cacheTime}}
824
+ {{^this.cacheTime}}
825
825
  server->sendHeader("Cache-Control", "no-cache");
826
- {{/../cacheTime}}
826
+ {{/this.cacheTime}}
827
827
  server->sendHeader("ETag", etag_{{this.dataname}});
828
828
  #endif
829
829
  {{/case}}
@@ -895,22 +895,22 @@ void {{methodName}}(WebServer * server) {
895
895
 
896
896
  {{#switch ../etag}}
897
897
  {{#case "true"}}
898
- {{#../cacheTime}}
898
+ {{#this.cacheTime}}
899
899
  server->sendHeader("Cache-Control", "max-age={{value}}");
900
- {{/../cacheTime}}
901
- {{^../cacheTime}}
900
+ {{/this.cacheTime}}
901
+ {{^this.cacheTime}}
902
902
  server->sendHeader("Cache-Control", "no-cache");
903
- {{/../cacheTime}}
903
+ {{/this.cacheTime}}
904
904
  server->sendHeader("ETag", etag_{{this.dataname}});
905
905
  {{/case}}
906
906
  {{#case "compiler"}}
907
907
  #ifdef {{../definePrefix}}_ENABLE_ETAG
908
- {{#../cacheTime}}
908
+ {{#this.cacheTime}}
909
909
  server->sendHeader("Cache-Control", "max-age={{value}}");
910
- {{/../cacheTime}}
911
- {{^../cacheTime}}
910
+ {{/this.cacheTime}}
911
+ {{^this.cacheTime}}
912
912
  server->sendHeader("Cache-Control", "no-cache");
913
- {{/../cacheTime}}
913
+ {{/this.cacheTime}}
914
914
  server->sendHeader("ETag", etag_{{this.dataname}});
915
915
  #endif
916
916
  {{/case}}
@@ -973,7 +973,7 @@ const bufferToByteString = (buffer) => {
973
973
  result += ',' + buffer[index].toString(10);
974
974
  return result;
975
975
  };
976
- const transformSourceToTemplateData = (s, etag) => ({
976
+ const transformSourceToTemplateData = (s, etag, effectiveCacheTime) => ({
977
977
  ...s,
978
978
  length: s.content.length,
979
979
  bytes: bufferToByteString(s.content),
@@ -981,7 +981,8 @@ const transformSourceToTemplateData = (s, etag) => ({
981
981
  bytesGzip: bufferToByteString(s.contentGzip),
982
982
  isDefault: s.filename === 'index.html' || s.filename === 'index.htm',
983
983
  gzipSizeForManifest: s.isGzip ? s.contentGzip.length : 0,
984
- etagForManifest: etag === 'false' ? 'NULL' : `etag_${s.dataname}`
984
+ etagForManifest: etag === 'false' ? 'NULL' : `etag_${s.dataname}`,
985
+ cacheTime: effectiveCacheTime ? { value: effectiveCacheTime } : undefined
985
986
  });
986
987
  const postProcessCppCode = (code) => code
987
988
  .split('\n')
@@ -1011,7 +1012,12 @@ const createHandlebarsHelpers = () => {
1011
1012
  };
1012
1013
  const getCppCode = (sources, filesByExtension) => {
1013
1014
  const template = (0, handlebars_1.compile)(getTemplate(commandLine_1.cmdLine.engine));
1014
- const transformedSources = sources.map((s) => transformSourceToTemplateData(s, commandLine_1.cmdLine.etag));
1015
+ const transformedSources = sources.map((s) => {
1016
+ const effectiveCacheTime = s.mime === 'text/html'
1017
+ ? (commandLine_1.cmdLine.cachetimeHtml ?? commandLine_1.cmdLine.cachetime)
1018
+ : (commandLine_1.cmdLine.cachetimeAssets ?? commandLine_1.cmdLine.cachetime);
1019
+ return transformSourceToTemplateData(s, commandLine_1.cmdLine.etag, effectiveCacheTime);
1020
+ });
1015
1021
  const spaSource = commandLine_1.cmdLine.spa ? transformedSources.find((s) => s.isDefault) : undefined;
1016
1022
  const templateData = {
1017
1023
  config: (0, commandLine_1.formatConfiguration)(commandLine_1.cmdLine),
@@ -1029,7 +1035,6 @@ const getCppCode = (sources, filesByExtension) => {
1029
1035
  created: commandLine_1.cmdLine.created,
1030
1036
  version: commandLine_1.cmdLine.version,
1031
1037
  methodName: commandLine_1.cmdLine.espmethod,
1032
- cacheTime: commandLine_1.cmdLine.cachetime ? { value: commandLine_1.cmdLine.cachetime } : undefined,
1033
1038
  definePrefix: commandLine_1.cmdLine.define,
1034
1039
  basePath: commandLine_1.cmdLine.basePath,
1035
1040
  spa: !!commandLine_1.cmdLine.spa,
@@ -1 +1 @@
1
- export declare const espidfTemplate = "\n//engine: espidf\n//config: {{{config}}}\n{{#if created }}\n//created: {{now}}\n{{/if}}\n//\n\n{{#switch etag}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n{{#switch gzip}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n//\n{{#if version }}\n#define {{definePrefix}}_VERSION \"{{version}}\"\n{{/if}}\n#define {{definePrefix}}_COUNT {{fileCount}}\n#define {{definePrefix}}_SIZE {{fileSize}}\n#define {{definePrefix}}_SIZE_GZIP {{fileGzipSize}}\n\n//\n{{#each sources}}\n#define {{../definePrefix}}_FILE_{{this.datanameUpperCase}}\n{{/each}}\n\n//\n{{#each filesByExtension}}\n#define {{../definePrefix}}_{{this.extension}}_FILES {{this.count}}\n{{/each}}\n\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n#include <esp_err.h>\n#include <esp_http_server.h>\n\n//\n{{#switch gzip}}\n{{#case \"true\"}}\n {{#each sources}}\nstatic const unsigned char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n {{#each sources}}\nstatic const unsigned char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n {{#each sources}}\nstatic const unsigned char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n#else\n {{#each sources}}\nstatic const unsigned char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n#endif \n{{/case}}\n{{/switch}}\n\n//\n{{#switch etag}}\n{{#case \"true\"}}\n {{#each sources}}\nstatic const char etag_{{this.dataname}}[] = \"{{this.sha256}}\";\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n {{#each sources}}\nstatic const char etag_{{this.dataname}}[] = \"{{this.sha256}}\";\n {{/each}}\n#endif\n{{/case}}\n{{/switch}}\n\n// File manifest struct (C-compatible typedef)\ntypedef struct {\n const char* path;\n uint32_t size;\n uint32_t gzipSize;\n const char* etag;\n const char* contentType;\n} {{definePrefix}}_FileInfo;\n\n// File manifest array\nstatic const {{definePrefix}}_FileInfo {{definePrefix}}_FILES[] = {\n{{#each sources}}\n { \"{{../basePath}}/{{this.filename}}\", {{this.length}}, {{this.gzipSizeForManifest}}, {{this.etagForManifest}}, \"{{this.mime}}\" },\n{{/each}}\n};\nstatic const size_t {{definePrefix}}_FILE_COUNT = sizeof({{definePrefix}}_FILES) / sizeof({{definePrefix}}_FILES[0]);\n\n// File served hook - override with your own implementation\n__attribute__((weak)) void {{definePrefix}}_onFileServed(const char* path, int statusCode) {}\n\n{{#each sources}}\n\nstatic esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)\n{\n{{#switch ../etag}}\n{{#case \"true\"}}\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (hdr_value == NULL) { httpd_resp_send_500(req); return ESP_FAIL; }\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 304);\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (hdr_value == NULL) { httpd_resp_send_500(req); return ESP_FAIL; }\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 304);\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n #endif\n{{/case}}\n{{/switch}}\n httpd_resp_set_type(req, \"{{this.mime}}\");\n{{#switch ../gzip}}\n{{#case \"true\"}}\n{{#if this.isGzip}}\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n{{/if}}\n{{/case}}\n{{#case \"compiler\"}}\n {{#if this.isGzip}}\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n #endif \n {{/if}}\n{{/case}}\n{{/switch}}\n\n{{#switch ../etag}}\n{{#case \"true\"}}\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n #endif \n{{/case}}\n{{/switch}}\n\n{{#switch ../gzip}}\n{{#case \"true\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n httpd_resp_send(req, (const char *)datagzip_{{this.dataname}}, {{this.lengthGzip}});\n{{/case}}\n{{#case \"false\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n httpd_resp_send(req, (const char *)data_{{this.dataname}}, {{this.length}});\n{{/case}}\n{{#case \"compiler\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_send(req, (const char *)datagzip_{{this.dataname}}, {{this.lengthGzip}});\n #else\n httpd_resp_send(req, (const char *)data_{{this.dataname}}, {{this.length}});\n #endif\n{{/case}}\n{{/switch}}\n return ESP_OK;\n}\n\n{{#if this.isDefault}}\nstatic const httpd_uri_t route_def_{{this.datanameUpperCase}} = {\n .uri = \"{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n{{/if}}\n\nstatic const httpd_uri_t route_{{this.datanameUpperCase}} = {\n .uri = \"{{../basePath}}/{{this.filename}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n\n{{/each}}\n\n{{#if spa}}\n{{#with spaSource}}\nstatic esp_err_t spa_handler_{{this.datanameUpperCase}}(httpd_req_t *req, httpd_err_code_t err) {\n{{#if ../basePath}}\n const char* prefix = \"{{../basePath}}/\";\n if (strncmp(req->uri, prefix, strlen(prefix)) != 0 && strcmp(req->uri, \"{{../basePath}}\") != 0) {\n httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, \"Not found\");\n return ESP_FAIL;\n }\n{{/if}}\n return file_handler_{{this.datanameUpperCase}}(req);\n}\n{{/with}}\n{{/if}}\n\n\nstatic inline void {{methodName}}(httpd_handle_t server) {\n{{#each sources}}\n{{#if this.isDefault}}\n httpd_register_uri_handler(server, &route_def_{{this.datanameUpperCase}});\n{{/if}}\n httpd_register_uri_handler(server, &route_{{this.datanameUpperCase}});\n{{/each}}\n{{#if spa}}\n{{#with spaSource}}\n httpd_register_err_handler(server, HTTPD_404_NOT_FOUND, spa_handler_{{this.datanameUpperCase}});\n{{/with}}\n{{/if}}\n\n}";
1
+ export declare const espidfTemplate = "\n//engine: espidf\n//config: {{{config}}}\n{{#if created }}\n//created: {{now}}\n{{/if}}\n//\n\n{{#switch etag}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n{{#switch gzip}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n//\n{{#if version }}\n#define {{definePrefix}}_VERSION \"{{version}}\"\n{{/if}}\n#define {{definePrefix}}_COUNT {{fileCount}}\n#define {{definePrefix}}_SIZE {{fileSize}}\n#define {{definePrefix}}_SIZE_GZIP {{fileGzipSize}}\n\n//\n{{#each sources}}\n#define {{../definePrefix}}_FILE_{{this.datanameUpperCase}}\n{{/each}}\n\n//\n{{#each filesByExtension}}\n#define {{../definePrefix}}_{{this.extension}}_FILES {{this.count}}\n{{/each}}\n\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n#include <esp_err.h>\n#include <esp_http_server.h>\n\n//\n{{#switch gzip}}\n{{#case \"true\"}}\n {{#each sources}}\nstatic const unsigned char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n {{#each sources}}\nstatic const unsigned char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n {{#each sources}}\nstatic const unsigned char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n#else\n {{#each sources}}\nstatic const unsigned char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n#endif \n{{/case}}\n{{/switch}}\n\n//\n{{#switch etag}}\n{{#case \"true\"}}\n {{#each sources}}\nstatic const char etag_{{this.dataname}}[] = \"{{this.sha256}}\";\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n {{#each sources}}\nstatic const char etag_{{this.dataname}}[] = \"{{this.sha256}}\";\n {{/each}}\n#endif\n{{/case}}\n{{/switch}}\n\n// File manifest struct (C-compatible typedef)\ntypedef struct {\n const char* path;\n uint32_t size;\n uint32_t gzipSize;\n const char* etag;\n const char* contentType;\n} {{definePrefix}}_FileInfo;\n\n// File manifest array\nstatic const {{definePrefix}}_FileInfo {{definePrefix}}_FILES[] = {\n{{#each sources}}\n { \"{{../basePath}}/{{this.filename}}\", {{this.length}}, {{this.gzipSizeForManifest}}, {{this.etagForManifest}}, \"{{this.mime}}\" },\n{{/each}}\n};\nstatic const size_t {{definePrefix}}_FILE_COUNT = sizeof({{definePrefix}}_FILES) / sizeof({{definePrefix}}_FILES[0]);\n\n// File served hook - override with your own implementation\n__attribute__((weak)) void {{definePrefix}}_onFileServed(const char* path, int statusCode) {}\n\n{{#each sources}}\n\nstatic esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)\n{\n{{#switch ../etag}}\n{{#case \"true\"}}\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (hdr_value == NULL) { httpd_resp_send_500(req); return ESP_FAIL; }\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 304);\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (hdr_value == NULL) { httpd_resp_send_500(req); return ESP_FAIL; }\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 304);\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n #endif\n{{/case}}\n{{/switch}}\n httpd_resp_set_type(req, \"{{this.mime}}\");\n{{#switch ../gzip}}\n{{#case \"true\"}}\n{{#if this.isGzip}}\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n{{/if}}\n{{/case}}\n{{#case \"compiler\"}}\n {{#if this.isGzip}}\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n #endif \n {{/if}}\n{{/case}}\n{{/switch}}\n\n{{#switch ../etag}}\n{{#case \"true\"}}\n{{#this.cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/this.cacheTime}}\n{{^this.cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/this.cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n{{#this.cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/this.cacheTime}}\n{{^this.cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/this.cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n #endif \n{{/case}}\n{{/switch}}\n\n{{#switch ../gzip}}\n{{#case \"true\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n httpd_resp_send(req, (const char *)datagzip_{{this.dataname}}, {{this.lengthGzip}});\n{{/case}}\n{{#case \"false\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n httpd_resp_send(req, (const char *)data_{{this.dataname}}, {{this.length}});\n{{/case}}\n{{#case \"compiler\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_send(req, (const char *)datagzip_{{this.dataname}}, {{this.lengthGzip}});\n #else\n httpd_resp_send(req, (const char *)data_{{this.dataname}}, {{this.length}});\n #endif\n{{/case}}\n{{/switch}}\n return ESP_OK;\n}\n\n{{#if this.isDefault}}\nstatic const httpd_uri_t route_def_{{this.datanameUpperCase}} = {\n .uri = \"{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n{{/if}}\n\nstatic const httpd_uri_t route_{{this.datanameUpperCase}} = {\n .uri = \"{{../basePath}}/{{this.filename}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n\n{{/each}}\n\n{{#if spa}}\n{{#with spaSource}}\nstatic esp_err_t spa_handler_{{this.datanameUpperCase}}(httpd_req_t *req, httpd_err_code_t err) {\n{{#if ../basePath}}\n const char* prefix = \"{{../basePath}}/\";\n if (strncmp(req->uri, prefix, strlen(prefix)) != 0 && strcmp(req->uri, \"{{../basePath}}\") != 0) {\n httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, \"Not found\");\n return ESP_FAIL;\n }\n{{/if}}\n return file_handler_{{this.datanameUpperCase}}(req);\n}\n{{/with}}\n{{/if}}\n\n\nstatic inline void {{methodName}}(httpd_handle_t server) {\n{{#each sources}}\n{{#if this.isDefault}}\n httpd_register_uri_handler(server, &route_def_{{this.datanameUpperCase}});\n{{/if}}\n httpd_register_uri_handler(server, &route_{{this.datanameUpperCase}});\n{{/each}}\n{{#if spa}}\n{{#with spaSource}}\n httpd_register_err_handler(server, HTTPD_404_NOT_FOUND, spa_handler_{{this.datanameUpperCase}});\n{{/with}}\n{{/if}}\n\n}";
@@ -182,22 +182,22 @@ static esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)
182
182
 
183
183
  {{#switch ../etag}}
184
184
  {{#case "true"}}
185
- {{#../cacheTime}}
185
+ {{#this.cacheTime}}
186
186
  httpd_resp_set_hdr(req, "Cache-Control", "max-age={{value}}");
187
- {{/../cacheTime}}
188
- {{^../cacheTime}}
187
+ {{/this.cacheTime}}
188
+ {{^this.cacheTime}}
189
189
  httpd_resp_set_hdr(req, "Cache-Control", "no-cache");
190
- {{/../cacheTime}}
190
+ {{/this.cacheTime}}
191
191
  httpd_resp_set_hdr(req, "ETag", etag_{{this.dataname}});
192
192
  {{/case}}
193
193
  {{#case "compiler"}}
194
194
  #ifdef {{../definePrefix}}_ENABLE_ETAG
195
- {{#../cacheTime}}
195
+ {{#this.cacheTime}}
196
196
  httpd_resp_set_hdr(req, "Cache-Control", "max-age={{value}}");
197
- {{/../cacheTime}}
198
- {{^../cacheTime}}
197
+ {{/this.cacheTime}}
198
+ {{^this.cacheTime}}
199
199
  httpd_resp_set_hdr(req, "Cache-Control", "no-cache");
200
- {{/../cacheTime}}
200
+ {{/this.cacheTime}}
201
201
  httpd_resp_set_hdr(req, "ETag", etag_{{this.dataname}});
202
202
  #endif
203
203
  {{/case}}
package/dist/index.js CHANGED
@@ -115,9 +115,10 @@ function main() {
115
115
  const longestFilename = [...files.keys()].reduce((p, c) => Math.max(c.length, p), 0);
116
116
  for (const [originalFilename, fileData] of files) {
117
117
  const { content, hash: sha256 } = fileData;
118
- const mimeType = (0, mime_types_1.lookup)(originalFilename) || 'text/plain';
119
- if (!(0, mime_types_1.lookup)(originalFilename))
118
+ const rawMime = (0, mime_types_1.lookup)(originalFilename);
119
+ if (!rawMime)
120
120
  console.log((0, consoleColor_1.yellowLog)(` [${originalFilename}] unknown MIME type for extension '${node_path_1.default.extname(originalFilename)}', using text/plain`));
121
+ const mimeType = rawMime || 'text/plain';
121
122
  summary.filecount++;
122
123
  const filename = originalFilename.replace(/\\/g, '/');
123
124
  let dataname = filename.replace(/\W/g, '_');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelteesp32",
3
- "version": "2.2.2",
3
+ "version": "2.3.1",
4
4
  "description": "Convert Svelte (or any frontend) JS application to serve it from ESP32 webserver (PsychicHttp)",
5
5
  "author": "BCsabaEngine",
6
6
  "license": "ISC",