koa-classic-server 3.0.0 → 3.1.0

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 (105) hide show
  1. package/README.md +44 -120
  2. package/index.cjs +236 -21
  3. package/package.json +10 -5
  4. package/.github/workflows/npm-publish.yml +0 -98
  5. package/CLAUDE.md +0 -101
  6. package/__tests__/benchmark-results-baseline-v1.2.0.txt +0 -354
  7. package/__tests__/benchmark-results-optimized-v2.0.0.txt +0 -354
  8. package/__tests__/benchmark-results-v3.0.0.txt +0 -372
  9. package/__tests__/benchmark.js +0 -239
  10. package/__tests__/caching-headers.test.js +0 -556
  11. package/__tests__/compression-fixtures/data.json +0 -1
  12. package/__tests__/compression-fixtures/large.txt +0 -1
  13. package/__tests__/compression-fixtures/small.txt +0 -1
  14. package/__tests__/compression.test.js +0 -284
  15. package/__tests__/customTest/README.md +0 -6
  16. package/__tests__/customTest/loadConfig.util.js +0 -41
  17. package/__tests__/customTest/serversToLoad.util.js +0 -93
  18. package/__tests__/demo-regex-index.js +0 -140
  19. package/__tests__/deprecation-warnings.test.js +0 -105
  20. package/__tests__/directory-sorting-links.test.js +0 -135
  21. package/__tests__/dt-unknown.test.js +0 -635
  22. package/__tests__/ejs.test.js +0 -299
  23. package/__tests__/hidden-fixtures/.dot-dir/inside.txt +0 -1
  24. package/__tests__/hidden-fixtures/.env +0 -2
  25. package/__tests__/hidden-fixtures/.well-known/acme-challenge.txt +0 -1
  26. package/__tests__/hidden-fixtures/config/secrets/password.txt +0 -1
  27. package/__tests__/hidden-fixtures/data.key +0 -1
  28. package/__tests__/hidden-fixtures/file.secret +0 -1
  29. package/__tests__/hidden-fixtures/index.html +0 -1
  30. package/__tests__/hidden-fixtures/normal.txt +0 -1
  31. package/__tests__/hidden-fixtures/subdir/.env +0 -1
  32. package/__tests__/hidden-fixtures/subdir/regular.txt +0 -1
  33. package/__tests__/hidden-option.test.js +0 -407
  34. package/__tests__/hideExtension.test.js +0 -607
  35. package/__tests__/index-option.test.js +0 -449
  36. package/__tests__/index.test.js +0 -345
  37. package/__tests__/listing.test.js +0 -437
  38. package/__tests__/logger.test.js +0 -232
  39. package/__tests__/performance.test.js +0 -370
  40. package/__tests__/publicWwwTest/cartella/sottocartella/ciao.html +0 -11
  41. package/__tests__/publicWwwTest/cartella/sottocartella/provaEjs/testEjs.ejs +0 -11
  42. package/__tests__/publicWwwTest/cartella vuota con spazi nel nome/file con spazio nel nome .txt +0 -1
  43. package/__tests__/publicWwwTest/cartella vuota con spazi nel nome /file con spazio nel nome .txt +0 -1
  44. package/__tests__/publicWwwTest/ejs-templates/complex.ejs +0 -56
  45. package/__tests__/publicWwwTest/ejs-templates/index.ejs +0 -30
  46. package/__tests__/publicWwwTest/ejs-templates/simple.ejs +0 -13
  47. package/__tests__/publicWwwTest/ejs-templates/with-conditional.ejs +0 -28
  48. package/__tests__/publicWwwTest/ejs-templates/with-escaping.ejs +0 -26
  49. package/__tests__/publicWwwTest/ejs-templates/with-loop.ejs +0 -16
  50. package/__tests__/publicWwwTest/hideext-test/about/index.html +0 -1
  51. package/__tests__/publicWwwTest/hideext-test/about.EJS +0 -1
  52. package/__tests__/publicWwwTest/hideext-test/about.ejs +0 -2
  53. package/__tests__/publicWwwTest/hideext-test/blog/articolo.ejs +0 -2
  54. package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina +0 -1
  55. package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina.ejs +0 -1
  56. package/__tests__/publicWwwTest/hideext-test/file.ejs.bak +0 -1
  57. package/__tests__/publicWwwTest/hideext-test/index.ejs +0 -2
  58. package/__tests__/publicWwwTest/hideext-test/photo.txt +0 -1
  59. package/__tests__/publicWwwTest/hideext-test/sezione/index.ejs +0 -1
  60. package/__tests__/publicWwwTest/hideext-test/style.css +0 -1
  61. package/__tests__/publicWwwTest/ile_vuoto.txt +0 -0
  62. package/__tests__/publicWwwTest/index.html +0 -11
  63. package/__tests__/publicWwwTest/prova file .txt +0 -2
  64. package/__tests__/publicWwwTest/semplicetxt.txt +0 -1
  65. package/__tests__/publicWwwTest/test-page.html +0 -1
  66. package/__tests__/publicWwwTest/test.txt +0 -1
  67. package/__tests__/range-fixtures/sample.txt +0 -1
  68. package/__tests__/range.test.js +0 -223
  69. package/__tests__/security-headers.test.js +0 -165
  70. package/__tests__/security.test.js +0 -322
  71. package/__tests__/server-cache-fixtures/large.txt +0 -1
  72. package/__tests__/server-cache-fixtures/small.txt +0 -1
  73. package/__tests__/server-cache.test.js +0 -594
  74. package/__tests__/setup-benchmark.js +0 -178
  75. package/__tests__/symlink.test.js +0 -441
  76. package/__tests__/template-timeout.test.js +0 -321
  77. package/__tests__/test-regex-quick.js +0 -158
  78. package/__tests__/useOriginalUrl.test.js +0 -213
  79. package/docs/ACTION_PLAN.md +0 -293
  80. package/docs/BENCHMARKS.md +0 -317
  81. package/docs/CHANGELOG.md +0 -880
  82. package/docs/CODE_REVIEW.md +0 -300
  83. package/docs/DEBUG_REPORT.md +0 -593
  84. package/docs/DOCUMENTATION.md +0 -1864
  85. package/docs/EXAMPLES_INDEX_OPTION.md +0 -395
  86. package/docs/FLOW_DIAGRAM.md +0 -954
  87. package/docs/INDEX_OPTION_PRIORITY.md +0 -527
  88. package/docs/OPTIMIZATION_HTTP_CACHING.md +0 -689
  89. package/docs/OPTIMIZATION_ROADMAP_for_V3.md +0 -864
  90. package/docs/PERFORMANCE_ANALYSIS.md +0 -839
  91. package/docs/PERFORMANCE_COMPARISON.md +0 -388
  92. package/docs/noteExports.md +0 -148
  93. package/docs/security_improvement_for_V3.md +0 -421
  94. package/docs/template-engine/TEMPLATE_ENGINE_GUIDE.md +0 -1734
  95. package/docs/template-engine/esempi-incrementali.js +0 -192
  96. package/docs/template-engine/examples/esempio1-nessun-dato.ejs +0 -12
  97. package/docs/template-engine/examples/esempio2-una-variabile.ejs +0 -11
  98. package/docs/template-engine/examples/esempio3-piu-variabili.ejs +0 -15
  99. package/docs/template-engine/examples/esempio4-condizionale.ejs +0 -18
  100. package/docs/template-engine/examples/esempio5-loop.ejs +0 -18
  101. package/docs/template-engine/examples/index-esempi.html +0 -181
  102. package/docs/template-engine/examples/index.html +0 -40
  103. package/docs/template-engine/examples/test.ejs +0 -64
  104. package/eslint.config.mjs +0 -17
  105. package/jest.config.js +0 -18
@@ -1,370 +0,0 @@
1
- /**
2
- * Performance Benchmark Tests
3
- *
4
- * These tests measure current performance to establish a baseline.
5
- * After optimizations, run these tests again to measure improvements.
6
- *
7
- * Usage:
8
- * npm run test:performance
9
- *
10
- * To save results:
11
- * npm run test:performance > benchmark-results-v1.2.0.txt
12
- */
13
-
14
- const Koa = require('koa');
15
- const supertest = require('supertest');
16
- const koaClassicServer = require('../index.cjs');
17
- const path = require('path');
18
- const fs = require('fs');
19
-
20
- const BENCHMARK_DIR = path.join(__dirname, 'benchmark-data');
21
-
22
- // Auto-setup benchmark data if not exists
23
- function setupBenchmarkData() {
24
- if (fs.existsSync(BENCHMARK_DIR)) {
25
- return; // Data already exists
26
- }
27
-
28
- console.log('\n🔧 Setting up benchmark data automatically...\n');
29
-
30
- // Create benchmark directory
31
- fs.mkdirSync(BENCHMARK_DIR, { recursive: true });
32
-
33
- // Create small files (1KB each)
34
- console.log(' Creating 100 small files (1KB each)...');
35
- const smallDir = path.join(BENCHMARK_DIR, 'small-files');
36
- fs.mkdirSync(smallDir);
37
- for (let i = 1; i <= 100; i++) {
38
- const content = 'X'.repeat(1024);
39
- fs.writeFileSync(path.join(smallDir, `file-${i}.txt`), content);
40
- }
41
-
42
- // Create medium files (100KB each)
43
- console.log(' Creating 50 medium files (100KB each)...');
44
- const mediumDir = path.join(BENCHMARK_DIR, 'medium-files');
45
- fs.mkdirSync(mediumDir);
46
- for (let i = 1; i <= 50; i++) {
47
- const content = 'X'.repeat(100 * 1024);
48
- fs.writeFileSync(path.join(mediumDir, `file-${i}.txt`), content);
49
- }
50
-
51
- // Create large files (1MB each)
52
- console.log(' Creating 10 large files (1MB each)...');
53
- const largeDir = path.join(BENCHMARK_DIR, 'large-files');
54
- fs.mkdirSync(largeDir);
55
- for (let i = 1; i <= 10; i++) {
56
- const content = 'X'.repeat(1024 * 1024);
57
- fs.writeFileSync(path.join(largeDir, `file-${i}.txt`), content);
58
- }
59
-
60
- // Create directory with 1000 files
61
- console.log(' Creating directory with 1000 files...');
62
- const largeDirListing = path.join(BENCHMARK_DIR, 'large-directory');
63
- fs.mkdirSync(largeDirListing);
64
- for (let i = 1; i <= 1000; i++) {
65
- const content = `File number ${i}\n`;
66
- fs.writeFileSync(path.join(largeDirListing, `item-${String(i).padStart(4, '0')}.txt`), content);
67
- }
68
-
69
- // Create directory with 10,000 files
70
- console.log(' Creating directory with 10,000 files (this may take a moment)...');
71
- const veryLargeDirListing = path.join(BENCHMARK_DIR, 'very-large-directory');
72
- fs.mkdirSync(veryLargeDirListing);
73
- for (let i = 1; i <= 10000; i++) {
74
- const content = `File number ${i}\n`;
75
- fs.writeFileSync(path.join(veryLargeDirListing, `item-${String(i).padStart(5, '0')}.txt`), content);
76
- }
77
-
78
- // Create HTML file for caching test
79
- const htmlContent = `<!DOCTYPE html>
80
- <html>
81
- <head>
82
- <meta charset="UTF-8">
83
- <title>Benchmark Test</title>
84
- </head>
85
- <body>
86
- <h1>Benchmark Test Page</h1>
87
- <p>${'Lorem ipsum dolor sit amet. '.repeat(100)}</p>
88
- </body>
89
- </html>`;
90
- fs.writeFileSync(path.join(BENCHMARK_DIR, 'test.html'), htmlContent);
91
-
92
- console.log('\n✅ Benchmark data setup complete!\n');
93
- }
94
-
95
- // Setup benchmark data automatically if needed
96
- setupBenchmarkData();
97
-
98
- // Helper to measure execution time
99
- function measureTime(fn) {
100
- const start = process.hrtime.bigint();
101
- const result = fn();
102
- const end = process.hrtime.bigint();
103
- const durationMs = Number(end - start) / 1000000; // Convert to ms
104
- return { result, durationMs };
105
- }
106
-
107
- async function measureTimeAsync(fn) {
108
- const start = process.hrtime.bigint();
109
- const result = await fn();
110
- const end = process.hrtime.bigint();
111
- const durationMs = Number(end - start) / 1000000;
112
- return { result, durationMs };
113
- }
114
-
115
- // Helper to run multiple iterations and get statistics
116
- async function benchmark(name, fn, iterations = 10) {
117
- const times = [];
118
-
119
- for (let i = 0; i < iterations; i++) {
120
- const { durationMs } = await measureTimeAsync(fn);
121
- times.push(durationMs);
122
- }
123
-
124
- const avg = times.reduce((a, b) => a + b, 0) / times.length;
125
- const min = Math.min(...times);
126
- const max = Math.max(...times);
127
- const median = times.sort((a, b) => a - b)[Math.floor(times.length / 2)];
128
-
129
- return { name, avg, min, max, median, times };
130
- }
131
-
132
- describe('Performance Benchmarks - BASELINE (v1.2.0)', () => {
133
- let app;
134
- let server;
135
- let request;
136
-
137
- beforeAll(() => {
138
- app = new Koa();
139
- app.use(koaClassicServer(BENCHMARK_DIR));
140
- server = app.listen();
141
- request = supertest(server);
142
- });
143
-
144
- afterAll(() => {
145
- server.close();
146
- });
147
-
148
- describe('File Serving Performance', () => {
149
- test('Benchmark: Small file (1KB) - 100 iterations', async () => {
150
- const stats = await benchmark(
151
- 'Small file (1KB)',
152
- async () => {
153
- const res = await request.get('/small-files/file-1.txt');
154
- expect(res.status).toBe(200);
155
- },
156
- 100
157
- );
158
-
159
- console.log('\n📊 Small File (1KB) Benchmark:');
160
- console.log(` Average: ${stats.avg.toFixed(2)}ms`);
161
- console.log(` Median: ${stats.median.toFixed(2)}ms`);
162
- console.log(` Min: ${stats.min.toFixed(2)}ms`);
163
- console.log(` Max: ${stats.max.toFixed(2)}ms`);
164
-
165
- expect(stats.avg).toBeLessThan(50); // Should be fast
166
- }, 30000);
167
-
168
- test('Benchmark: Medium file (100KB) - 50 iterations', async () => {
169
- const stats = await benchmark(
170
- 'Medium file (100KB)',
171
- async () => {
172
- const res = await request.get('/medium-files/file-1.txt');
173
- expect(res.status).toBe(200);
174
- },
175
- 50
176
- );
177
-
178
- console.log('\n📊 Medium File (100KB) Benchmark:');
179
- console.log(` Average: ${stats.avg.toFixed(2)}ms`);
180
- console.log(` Median: ${stats.median.toFixed(2)}ms`);
181
- console.log(` Min: ${stats.min.toFixed(2)}ms`);
182
- console.log(` Max: ${stats.max.toFixed(2)}ms`);
183
-
184
- expect(stats.avg).toBeLessThan(100);
185
- }, 30000);
186
-
187
- test('Benchmark: Large file (1MB) - 20 iterations', async () => {
188
- const stats = await benchmark(
189
- 'Large file (1MB)',
190
- async () => {
191
- const res = await request.get('/large-files/file-1.txt');
192
- expect(res.status).toBe(200);
193
- },
194
- 20
195
- );
196
-
197
- console.log('\n📊 Large File (1MB) Benchmark:');
198
- console.log(` Average: ${stats.avg.toFixed(2)}ms`);
199
- console.log(` Median: ${stats.median.toFixed(2)}ms`);
200
- console.log(` Min: ${stats.min.toFixed(2)}ms`);
201
- console.log(` Max: ${stats.max.toFixed(2)}ms`);
202
-
203
- expect(stats.avg).toBeLessThan(500);
204
- }, 30000);
205
- });
206
-
207
- describe('Directory Listing Performance', () => {
208
- test('Benchmark: Small directory (100 files) - 50 iterations', async () => {
209
- const stats = await benchmark(
210
- 'Directory listing (100 files)',
211
- async () => {
212
- const res = await request.get('/small-files/');
213
- expect(res.status).toBe(200);
214
- expect(res.text).toContain('file-1.txt');
215
- },
216
- 50
217
- );
218
-
219
- console.log('\n📊 Small Directory (100 files) Benchmark:');
220
- console.log(` Average: ${stats.avg.toFixed(2)}ms`);
221
- console.log(` Median: ${stats.median.toFixed(2)}ms`);
222
- console.log(` Min: ${stats.min.toFixed(2)}ms`);
223
- console.log(` Max: ${stats.max.toFixed(2)}ms`);
224
- }, 30000);
225
-
226
- test('Benchmark: Large directory (1,000 files) - 20 iterations', async () => {
227
- const stats = await benchmark(
228
- 'Directory listing (1,000 files)',
229
- async () => {
230
- const res = await request.get('/large-directory/');
231
- expect(res.status).toBe(200);
232
- expect(res.text).toContain('item-0001.txt');
233
- },
234
- 20
235
- );
236
-
237
- console.log('\n📊 Large Directory (1,000 files) Benchmark:');
238
- console.log(` Average: ${stats.avg.toFixed(2)}ms`);
239
- console.log(` Median: ${stats.median.toFixed(2)}ms`);
240
- console.log(` Min: ${stats.min.toFixed(2)}ms`);
241
- console.log(` Max: ${stats.max.toFixed(2)}ms`);
242
-
243
- // This is expected to be slow with current sync implementation
244
- console.log(` ⚠️ WARNING: This will be MUCH faster after async optimization`);
245
- }, 60000);
246
-
247
- test('Benchmark: Very large directory (10,000 files) - 5 iterations', async () => {
248
- const stats = await benchmark(
249
- 'Directory listing (10,000 files)',
250
- async () => {
251
- const res = await request.get('/very-large-directory/');
252
- expect(res.status).toBe(200);
253
- expect(res.text).toContain('item-00001.txt');
254
- },
255
- 5
256
- );
257
-
258
- console.log('\n📊 Very Large Directory (10,000 files) Benchmark:');
259
- console.log(` Average: ${stats.avg.toFixed(2)}ms`);
260
- console.log(` Median: ${stats.median.toFixed(2)}ms`);
261
- console.log(` Min: ${stats.min.toFixed(2)}ms`);
262
- console.log(` Max: ${stats.max.toFixed(2)}ms`);
263
- console.log(` ⚠️ WARNING: Event loop BLOCKED during this operation!`);
264
- console.log(` ⚠️ Expected to drop to ~${(stats.avg * 0.3).toFixed(2)}ms after optimization`);
265
- }, 120000);
266
- });
267
-
268
- describe('Concurrent Request Performance', () => {
269
- test('Benchmark: 10 concurrent small file requests', async () => {
270
- const start = process.hrtime.bigint();
271
-
272
- const promises = Array.from({ length: 10 }, (_, i) =>
273
- request.get(`/small-files/file-${i + 1}.txt`)
274
- );
275
-
276
- const results = await Promise.all(promises);
277
-
278
- const end = process.hrtime.bigint();
279
- const totalTime = Number(end - start) / 1000000;
280
-
281
- console.log('\n📊 10 Concurrent Small Files:');
282
- console.log(` Total time: ${totalTime.toFixed(2)}ms`);
283
- console.log(` Avg per request: ${(totalTime / 10).toFixed(2)}ms`);
284
-
285
- results.forEach(res => expect(res.status).toBe(200));
286
- }, 10000);
287
-
288
- test('Benchmark: 5 concurrent directory listings (100 files each)', async () => {
289
- const start = process.hrtime.bigint();
290
-
291
- const promises = Array.from({ length: 5 }, () =>
292
- request.get('/small-files/')
293
- );
294
-
295
- const results = await Promise.all(promises);
296
-
297
- const end = process.hrtime.bigint();
298
- const totalTime = Number(end - start) / 1000000;
299
-
300
- console.log('\n📊 5 Concurrent Directory Listings (100 files):');
301
- console.log(` Total time: ${totalTime.toFixed(2)}ms`);
302
- console.log(` Avg per request: ${(totalTime / 5).toFixed(2)}ms`);
303
- console.log(` ⚠️ With current sync code, these run SEQUENTIALLY`);
304
- console.log(` ⚠️ After async optimization, will run in PARALLEL`);
305
-
306
- results.forEach(res => expect(res.status).toBe(200));
307
- }, 30000);
308
- });
309
-
310
- describe('404 Not Found Performance', () => {
311
- test('Benchmark: Non-existent file - 50 iterations', async () => {
312
- const stats = await benchmark(
313
- '404 Not Found',
314
- async () => {
315
- const res = await request.get('/does-not-exist-12345.txt');
316
- expect(res.status).toBe(404);
317
- },
318
- 50
319
- );
320
-
321
- console.log('\n📊 404 Not Found Benchmark:');
322
- console.log(` Average: ${stats.avg.toFixed(2)}ms`);
323
- console.log(` Median: ${stats.median.toFixed(2)}ms`);
324
- console.log(` Min: ${stats.min.toFixed(2)}ms`);
325
- console.log(` Max: ${stats.max.toFixed(2)}ms`);
326
- }, 10000);
327
- });
328
-
329
- describe('Memory Usage (Informational)', () => {
330
- test('Memory usage during large directory listing', async () => {
331
- // Force garbage collection if available
332
- if (global.gc) {
333
- global.gc();
334
- }
335
-
336
- const memBefore = process.memoryUsage();
337
-
338
- // Request large directory
339
- const res = await request.get('/very-large-directory/');
340
- expect(res.status).toBe(200);
341
-
342
- const memAfter = process.memoryUsage();
343
-
344
- const heapUsedDiff = (memAfter.heapUsed - memBefore.heapUsed) / 1024 / 1024;
345
- const externalDiff = (memAfter.external - memBefore.external) / 1024 / 1024;
346
-
347
- console.log('\n📊 Memory Usage (10,000 files directory):');
348
- console.log(` Heap used increase: ${heapUsedDiff.toFixed(2)} MB`);
349
- console.log(` External increase: ${externalDiff.toFixed(2)} MB`);
350
- console.log(` Response size: ${(res.text.length / 1024 / 1024).toFixed(2)} MB`);
351
- console.log(` ⚠️ Expected to reduce by ~30-40% after optimization`);
352
- }, 30000);
353
- });
354
- });
355
-
356
- // Summary report
357
- afterAll(() => {
358
- console.log('\n' + '='.repeat(70));
359
- console.log('📋 BASELINE BENCHMARK SUMMARY');
360
- console.log('='.repeat(70));
361
- console.log('\nThese results represent the CURRENT performance (v1.2.0)');
362
- console.log('After implementing optimizations, run this test again to see improvements.\n');
363
- console.log('Expected improvements after optimization:');
364
- console.log(' ✓ Small files: 10-20% faster (async operations)');
365
- console.log(' ✓ Large directories: 50-70% faster (async + array join)');
366
- console.log(' ✓ Concurrent requests: 5-10x faster (non-blocking event loop)');
367
- console.log(' ✓ Memory usage: 30-40% reduction (array join vs concatenation)');
368
- console.log(' ✓ With HTTP caching: 80-95% faster (304 responses)');
369
- console.log('='.repeat(70) + '\n');
370
- });
@@ -1,11 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Document</title>
7
- </head>
8
- <body>
9
- <h1>hello world</h1>
10
- </body>
11
- </html>
@@ -1,11 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Document</title>
7
- </head>
8
- <body>
9
- <h1><%= "hello world" %></h1>
10
- </body>
11
- </html>
@@ -1,56 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="it">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title><%= pageTitle %></title>
6
- <style>
7
- .product { border: 1px solid #ccc; padding: 10px; margin: 10px 0; }
8
- .price { color: green; font-weight: bold; }
9
- .discount { color: red; }
10
- </style>
11
- </head>
12
- <body>
13
- <h1><%= pageTitle %></h1>
14
-
15
- <% if (user) { %>
16
- <div class="user-info">
17
- <p>Ciao, <%= user.name %>!</p>
18
- </div>
19
- <% } %>
20
-
21
- <h2>Prodotti Disponibili</h2>
22
-
23
- <% if (products && products.length > 0) { %>
24
- <div class="products">
25
- <% products.forEach(function(product) { %>
26
- <div class="product" data-id="<%= product.id %>">
27
- <h3><%= product.name %></h3>
28
- <p><%= product.description %></p>
29
- <p class="price">Prezzo: €<%= product.price.toFixed(2) %></p>
30
-
31
- <% if (product.discount > 0) { %>
32
- <p class="discount">Sconto: <%= product.discount %>%</p>
33
- <p class="final-price">
34
- Prezzo finale: €<%= (product.price * (1 - product.discount / 100)).toFixed(2) %>
35
- </p>
36
- <% } %>
37
-
38
- <% if (product.inStock) { %>
39
- <button>Aggiungi al carrello</button>
40
- <% } else { %>
41
- <p class="out-of-stock">Non disponibile</p>
42
- <% } %>
43
- </div>
44
- <% }); %>
45
- </div>
46
-
47
- <p>Totale prodotti: <%= products.length %></p>
48
- <% } else { %>
49
- <p>Nessun prodotto disponibile al momento.</p>
50
- <% } %>
51
-
52
- <footer>
53
- <p>Generato il: <%= new Date().toLocaleDateString('it-IT') %></p>
54
- </footer>
55
- </body>
56
- </html>
@@ -1,30 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="it">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>EJS Templates - Index</title>
7
- <style>
8
- body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
9
- h1 { color: #333; }
10
- ul { list-style: none; padding: 0; }
11
- li { margin: 10px 0; }
12
- a { color: #007bff; text-decoration: none; padding: 8px 12px; display: inline-block; border: 1px solid #007bff; border-radius: 4px; }
13
- a:hover { background: #007bff; color: white; }
14
- </style>
15
- </head>
16
- <body>
17
- <h1>Test Templates EJS</h1>
18
- <p>Questa directory contiene vari template EJS per testare diverse funzionalità:</p>
19
-
20
- <ul>
21
- <li><a href="simple.ejs">simple.ejs</a> - Template semplice con variabili</li>
22
- <li><a href="with-loop.ejs">with-loop.ejs</a> - Template con cicli forEach</li>
23
- <li><a href="with-conditional.ejs">with-conditional.ejs</a> - Template con condizionali if/else</li>
24
- <li><a href="with-escaping.ejs">with-escaping.ejs</a> - Template con HTML escaping</li>
25
- <li><a href="complex.ejs">complex.ejs</a> - Template complesso con tutto combinato</li>
26
- </ul>
27
-
28
- <p><strong>Nota:</strong> Questi template richiedono che il server passi i dati appropriati tramite la funzione render.</p>
29
- </body>
30
- </html>
@@ -1,13 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="it">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title><%= title %></title>
7
- </head>
8
- <body>
9
- <h1><%= heading %></h1>
10
- <p><%= message %></p>
11
- <p>Timestamp: <%= timestamp %></p>
12
- </body>
13
- </html>
@@ -1,28 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="it">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>EJS Conditional Test</title>
6
- </head>
7
- <body>
8
- <h1>Test Condizionali</h1>
9
-
10
- <% if (isLoggedIn) { %>
11
- <div class="user-panel">
12
- <p>Benvenuto, <%= username %>!</p>
13
- <p>Ruolo: <%= role %></p>
14
- </div>
15
- <% } else { %>
16
- <div class="guest-panel">
17
- <p>Benvenuto, ospite!</p>
18
- <a href="/login">Login</a>
19
- </div>
20
- <% } %>
21
-
22
- <% if (notifications > 0) { %>
23
- <div class="notifications">
24
- <p>Hai <%= notifications %> nuove notifiche</p>
25
- </div>
26
- <% } %>
27
- </body>
28
- </html>
@@ -1,26 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="it">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>EJS Escaping Test</title>
6
- </head>
7
- <body>
8
- <h1>Test HTML Escaping</h1>
9
-
10
- <div class="escaped">
11
- <h2>HTML Escaped (safe):</h2>
12
- <p><%= userInput %></p>
13
- </div>
14
-
15
- <div class="unescaped">
16
- <h2>HTML Unescaped (unsafe - solo per test):</h2>
17
- <p><%- htmlContent %></p>
18
- </div>
19
-
20
- <div class="mixed">
21
- <h2>Mixed Content:</h2>
22
- <p>Safe: <%= safeText %></p>
23
- <p>HTML: <%- allowedHtml %></p>
24
- </div>
25
- </body>
26
- </html>
@@ -1,16 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="it">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>EJS Loop Test</title>
6
- </head>
7
- <body>
8
- <h1>Lista di Items</h1>
9
- <ul>
10
- <% items.forEach(function(item, index) { %>
11
- <li data-index="<%= index %>"><%= item.name %> - <%= item.value %></li>
12
- <% }); %>
13
- </ul>
14
- <p>Totale items: <%= items.length %></p>
15
- </body>
16
- </html>
@@ -1 +0,0 @@
1
- <h1>About Directory Index</h1>
@@ -1 +0,0 @@
1
- <h1>About UPPERCASE</h1>
@@ -1,2 +0,0 @@
1
- <h1>About Page</h1>
2
- <p>This is the about page rendered from about.ejs</p>
@@ -1,2 +0,0 @@
1
- <h1>Blog Article</h1>
2
- <p>This is a blog article rendered from blog/articolo.ejs</p>
@@ -1 +0,0 @@
1
- plain pagina file
@@ -1 +0,0 @@
1
- <h1>Pagina EJS</h1>
@@ -1 +0,0 @@
1
- backup file
@@ -1,2 +0,0 @@
1
- <h1>Home Page</h1>
2
- <p>This is the index page</p>
@@ -1 +0,0 @@
1
- This is a photo description file
@@ -1 +0,0 @@
1
- <h1>Sezione Index</h1>
@@ -1 +0,0 @@
1
- body { color: red; }
File without changes
@@ -1,11 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Document</title>
7
- </head>
8
- <body>
9
- <h1>hello world</h1>
10
- </body>
11
- </html>
@@ -1,2 +0,0 @@
1
-
2
- hello world
@@ -1 +0,0 @@
1
- hello world
@@ -1 +0,0 @@
1
- <!DOCTYPE html><html><head><title>Test Page</title></head><body><h1>Test Page</h1></body></html>
@@ -1 +0,0 @@
1
- hello world
@@ -1 +0,0 @@
1
- 0123456789abcdefghij