koa-classic-server 3.0.1 → 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 (106) hide show
  1. package/README.md +44 -120
  2. package/index.cjs +200 -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__/head-method.test.js +0 -160
  24. package/__tests__/hidden-fixtures/.dot-dir/inside.txt +0 -1
  25. package/__tests__/hidden-fixtures/.env +0 -2
  26. package/__tests__/hidden-fixtures/.well-known/acme-challenge.txt +0 -1
  27. package/__tests__/hidden-fixtures/config/secrets/password.txt +0 -1
  28. package/__tests__/hidden-fixtures/data.key +0 -1
  29. package/__tests__/hidden-fixtures/file.secret +0 -1
  30. package/__tests__/hidden-fixtures/index.html +0 -1
  31. package/__tests__/hidden-fixtures/normal.txt +0 -1
  32. package/__tests__/hidden-fixtures/subdir/.env +0 -1
  33. package/__tests__/hidden-fixtures/subdir/regular.txt +0 -1
  34. package/__tests__/hidden-option.test.js +0 -407
  35. package/__tests__/hideExtension.test.js +0 -607
  36. package/__tests__/index-option.test.js +0 -449
  37. package/__tests__/index.test.js +0 -345
  38. package/__tests__/listing.test.js +0 -437
  39. package/__tests__/logger.test.js +0 -232
  40. package/__tests__/performance.test.js +0 -370
  41. package/__tests__/publicWwwTest/cartella/sottocartella/ciao.html +0 -11
  42. package/__tests__/publicWwwTest/cartella/sottocartella/provaEjs/testEjs.ejs +0 -11
  43. package/__tests__/publicWwwTest/cartella vuota con spazi nel nome/file con spazio nel nome .txt +0 -1
  44. package/__tests__/publicWwwTest/cartella vuota con spazi nel nome /file con spazio nel nome .txt +0 -1
  45. package/__tests__/publicWwwTest/ejs-templates/complex.ejs +0 -56
  46. package/__tests__/publicWwwTest/ejs-templates/index.ejs +0 -30
  47. package/__tests__/publicWwwTest/ejs-templates/simple.ejs +0 -13
  48. package/__tests__/publicWwwTest/ejs-templates/with-conditional.ejs +0 -28
  49. package/__tests__/publicWwwTest/ejs-templates/with-escaping.ejs +0 -26
  50. package/__tests__/publicWwwTest/ejs-templates/with-loop.ejs +0 -16
  51. package/__tests__/publicWwwTest/hideext-test/about/index.html +0 -1
  52. package/__tests__/publicWwwTest/hideext-test/about.EJS +0 -1
  53. package/__tests__/publicWwwTest/hideext-test/about.ejs +0 -2
  54. package/__tests__/publicWwwTest/hideext-test/blog/articolo.ejs +0 -2
  55. package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina +0 -1
  56. package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina.ejs +0 -1
  57. package/__tests__/publicWwwTest/hideext-test/file.ejs.bak +0 -1
  58. package/__tests__/publicWwwTest/hideext-test/index.ejs +0 -2
  59. package/__tests__/publicWwwTest/hideext-test/photo.txt +0 -1
  60. package/__tests__/publicWwwTest/hideext-test/sezione/index.ejs +0 -1
  61. package/__tests__/publicWwwTest/hideext-test/style.css +0 -1
  62. package/__tests__/publicWwwTest/ile_vuoto.txt +0 -0
  63. package/__tests__/publicWwwTest/index.html +0 -11
  64. package/__tests__/publicWwwTest/prova file .txt +0 -2
  65. package/__tests__/publicWwwTest/semplicetxt.txt +0 -1
  66. package/__tests__/publicWwwTest/test-page.html +0 -1
  67. package/__tests__/publicWwwTest/test.txt +0 -1
  68. package/__tests__/range-fixtures/sample.txt +0 -1
  69. package/__tests__/range.test.js +0 -223
  70. package/__tests__/security-headers.test.js +0 -165
  71. package/__tests__/security.test.js +0 -322
  72. package/__tests__/server-cache-fixtures/large.txt +0 -1
  73. package/__tests__/server-cache-fixtures/small.txt +0 -1
  74. package/__tests__/server-cache.test.js +0 -594
  75. package/__tests__/setup-benchmark.js +0 -178
  76. package/__tests__/symlink.test.js +0 -441
  77. package/__tests__/template-timeout.test.js +0 -321
  78. package/__tests__/test-regex-quick.js +0 -158
  79. package/__tests__/useOriginalUrl.test.js +0 -213
  80. package/docs/ACTION_PLAN.md +0 -293
  81. package/docs/BENCHMARKS.md +0 -317
  82. package/docs/CHANGELOG.md +0 -906
  83. package/docs/CODE_REVIEW.md +0 -300
  84. package/docs/DEBUG_REPORT.md +0 -593
  85. package/docs/DOCUMENTATION.md +0 -1864
  86. package/docs/EXAMPLES_INDEX_OPTION.md +0 -395
  87. package/docs/FLOW_DIAGRAM.md +0 -954
  88. package/docs/INDEX_OPTION_PRIORITY.md +0 -527
  89. package/docs/OPTIMIZATION_HTTP_CACHING.md +0 -689
  90. package/docs/OPTIMIZATION_ROADMAP_for_V3.md +0 -864
  91. package/docs/PERFORMANCE_ANALYSIS.md +0 -839
  92. package/docs/PERFORMANCE_COMPARISON.md +0 -388
  93. package/docs/noteExports.md +0 -148
  94. package/docs/security_improvement_for_V3.md +0 -421
  95. package/docs/template-engine/TEMPLATE_ENGINE_GUIDE.md +0 -1734
  96. package/docs/template-engine/esempi-incrementali.js +0 -192
  97. package/docs/template-engine/examples/esempio1-nessun-dato.ejs +0 -12
  98. package/docs/template-engine/examples/esempio2-una-variabile.ejs +0 -11
  99. package/docs/template-engine/examples/esempio3-piu-variabili.ejs +0 -15
  100. package/docs/template-engine/examples/esempio4-condizionale.ejs +0 -18
  101. package/docs/template-engine/examples/esempio5-loop.ejs +0 -18
  102. package/docs/template-engine/examples/index-esempi.html +0 -181
  103. package/docs/template-engine/examples/index.html +0 -40
  104. package/docs/template-engine/examples/test.ejs +0 -64
  105. package/eslint.config.mjs +0 -17
  106. 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