create-berna-stencil 2.0.14 → 2.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 (175) hide show
  1. package/README.md +1 -1
  2. package/bin/create.js +1 -1
  3. package/docs/Creating pages.md +20 -0
  4. package/package.json +63 -63
  5. package/src/backend/_core/index.php +10 -1
  6. package/src/backend/_core/init.php +4 -3
  7. package/src/backend/_core/modules/RateLimiter.php +31 -0
  8. package/src/backend/_core/vendor/composer/autoload_static.php +10 -10
  9. package/src/backend/_core/vendor/composer/installed.json +6 -6
  10. package/src/backend/_core/vendor/composer/installed.php +2 -2
  11. package/src/backend/_core/vendor/graham-campbell/result-type/.gitattributes +9 -0
  12. package/src/backend/_core/vendor/graham-campbell/result-type/.github/CODE_OF_CONDUCT.md +132 -0
  13. package/src/backend/_core/vendor/graham-campbell/result-type/.github/CONTRIBUTING.md +31 -0
  14. package/src/backend/_core/vendor/graham-campbell/result-type/.github/FUNDING.yml +2 -0
  15. package/src/backend/_core/vendor/graham-campbell/result-type/.github/SECURITY.md +14 -0
  16. package/src/backend/_core/vendor/graham-campbell/result-type/.github/workflows/stale.yml +11 -0
  17. package/src/backend/_core/vendor/graham-campbell/result-type/.github/workflows/tests.yml +40 -0
  18. package/src/backend/_core/vendor/graham-campbell/result-type/CHANGELOG.md +53 -0
  19. package/src/backend/_core/vendor/graham-campbell/result-type/LICENSE +21 -21
  20. package/src/backend/_core/vendor/graham-campbell/result-type/README.md +42 -0
  21. package/src/backend/_core/vendor/graham-campbell/result-type/composer.json +33 -33
  22. package/src/backend/_core/vendor/graham-campbell/result-type/phpunit.xml.dist +13 -0
  23. package/src/backend/_core/vendor/graham-campbell/result-type/src/Error.php +121 -121
  24. package/src/backend/_core/vendor/graham-campbell/result-type/src/Result.php +69 -69
  25. package/src/backend/_core/vendor/graham-campbell/result-type/src/Success.php +120 -120
  26. package/src/backend/_core/vendor/graham-campbell/result-type/tests/ResultTest.php +95 -0
  27. package/src/backend/_core/vendor/phpoption/phpoption/.gitattributes +13 -0
  28. package/src/backend/_core/vendor/phpoption/phpoption/.github/CODE_OF_CONDUCT.md +132 -0
  29. package/src/backend/_core/vendor/phpoption/phpoption/.github/CONTRIBUTING.md +30 -0
  30. package/src/backend/_core/vendor/phpoption/phpoption/.github/FUNDING.yml +2 -0
  31. package/src/backend/_core/vendor/phpoption/phpoption/.github/SECURITY.md +14 -0
  32. package/src/backend/_core/vendor/phpoption/phpoption/.github/workflows/static.yml +40 -0
  33. package/src/backend/_core/vendor/phpoption/phpoption/.github/workflows/tests.yml +40 -0
  34. package/src/backend/_core/vendor/phpoption/phpoption/LICENSE +200 -200
  35. package/src/backend/_core/vendor/phpoption/phpoption/Makefile +17 -0
  36. package/src/backend/_core/vendor/phpoption/phpoption/README.md +201 -0
  37. package/src/backend/_core/vendor/phpoption/phpoption/composer.json +50 -50
  38. package/src/backend/_core/vendor/phpoption/phpoption/phpstan-baseline.neon +44 -0
  39. package/src/backend/_core/vendor/phpoption/phpoption/phpstan.neon.dist +7 -0
  40. package/src/backend/_core/vendor/phpoption/phpoption/phpunit.xml.dist +13 -0
  41. package/src/backend/_core/vendor/phpoption/phpoption/src/PhpOption/LazyOption.php +175 -175
  42. package/src/backend/_core/vendor/phpoption/phpoption/src/PhpOption/None.php +136 -136
  43. package/src/backend/_core/vendor/phpoption/phpoption/src/PhpOption/Option.php +434 -434
  44. package/src/backend/_core/vendor/phpoption/phpoption/src/PhpOption/Some.php +169 -169
  45. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/EnsureTest.php +72 -0
  46. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/LazyOptionTest.php +357 -0
  47. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/NoneTest.php +153 -0
  48. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/OptionTest.php +166 -0
  49. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/SomeTest.php +194 -0
  50. package/src/backend/_core/vendor/phpoption/phpoption/tests/bootstrap.php +8 -0
  51. package/src/backend/_core/vendor/phpoption/phpoption/vendor-bin/phpstan/composer.json +8 -0
  52. package/src/backend/_core/vendor/symfony/polyfill-ctype/Ctype.php +232 -232
  53. package/src/backend/_core/vendor/symfony/polyfill-ctype/LICENSE +19 -19
  54. package/src/backend/_core/vendor/symfony/polyfill-ctype/README.md +12 -12
  55. package/src/backend/_core/vendor/symfony/polyfill-ctype/bootstrap.php +50 -50
  56. package/src/backend/_core/vendor/symfony/polyfill-ctype/bootstrap80.php +46 -46
  57. package/src/backend/_core/vendor/symfony/polyfill-ctype/composer.json +38 -38
  58. package/src/backend/_core/vendor/symfony/polyfill-mbstring/LICENSE +19 -19
  59. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Mbstring.php +1077 -1077
  60. package/src/backend/_core/vendor/symfony/polyfill-mbstring/README.md +13 -13
  61. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php +119 -119
  62. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php +1397 -1397
  63. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php +5 -5
  64. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php +1489 -1489
  65. package/src/backend/_core/vendor/symfony/polyfill-mbstring/bootstrap.php +171 -171
  66. package/src/backend/_core/vendor/symfony/polyfill-mbstring/bootstrap80.php +167 -167
  67. package/src/backend/_core/vendor/symfony/polyfill-mbstring/composer.json +39 -39
  68. package/src/backend/_core/vendor/symfony/polyfill-php80/LICENSE +19 -19
  69. package/src/backend/_core/vendor/symfony/polyfill-php80/Php80.php +115 -115
  70. package/src/backend/_core/vendor/symfony/polyfill-php80/PhpToken.php +106 -106
  71. package/src/backend/_core/vendor/symfony/polyfill-php80/README.md +25 -25
  72. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php +31 -31
  73. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php +16 -16
  74. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php +20 -20
  75. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php +16 -16
  76. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php +16 -16
  77. package/src/backend/_core/vendor/symfony/polyfill-php80/bootstrap.php +42 -42
  78. package/src/backend/_core/vendor/symfony/polyfill-php80/composer.json +37 -37
  79. package/src/backend/_core/vendor/vlucas/phpdotenv/.editorconfig +15 -0
  80. package/src/backend/_core/vendor/vlucas/phpdotenv/.gitattributes +15 -0
  81. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/CODE_OF_CONDUCT.md +132 -0
  82. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/CONTRIBUTING.md +30 -0
  83. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/FUNDING.yml +2 -0
  84. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/SECURITY.md +14 -0
  85. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/workflows/static.yml +40 -0
  86. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/workflows/tests.yml +70 -0
  87. package/src/backend/_core/vendor/vlucas/phpdotenv/LICENSE +30 -30
  88. package/src/backend/_core/vendor/vlucas/phpdotenv/Makefile +17 -0
  89. package/src/backend/_core/vendor/vlucas/phpdotenv/README.md +370 -0
  90. package/src/backend/_core/vendor/vlucas/phpdotenv/UPGRADING.md +196 -0
  91. package/src/backend/_core/vendor/vlucas/phpdotenv/composer.json +60 -60
  92. package/src/backend/_core/vendor/vlucas/phpdotenv/phpstan-baseline.neon +157 -0
  93. package/src/backend/_core/vendor/vlucas/phpdotenv/phpstan.neon.dist +7 -0
  94. package/src/backend/_core/vendor/vlucas/phpdotenv/phpunit.xml.dist +13 -0
  95. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Dotenv.php +267 -267
  96. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/ExceptionInterface.php +12 -12
  97. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/InvalidEncodingException.php +12 -12
  98. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/InvalidFileException.php +12 -12
  99. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/InvalidPathException.php +12 -12
  100. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/ValidationException.php +12 -12
  101. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Loader/Loader.php +48 -48
  102. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Loader/LoaderInterface.php +20 -20
  103. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Loader/Resolver.php +65 -65
  104. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Entry.php +59 -59
  105. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/EntryParser.php +299 -299
  106. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Lexer.php +58 -58
  107. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Lines.php +127 -127
  108. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Parser.php +53 -53
  109. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/ParserInterface.php +19 -19
  110. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Value.php +88 -88
  111. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/AdapterInterface.php +15 -15
  112. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ApacheAdapter.php +89 -89
  113. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ArrayAdapter.php +80 -80
  114. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/EnvConstAdapter.php +88 -88
  115. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/GuardedWriter.php +85 -85
  116. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ImmutableWriter.php +110 -110
  117. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiReader.php +48 -48
  118. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiWriter.php +64 -64
  119. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/PutenvAdapter.php +91 -91
  120. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReaderInterface.php +17 -17
  121. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReplacingWriter.php +104 -104
  122. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ServerConstAdapter.php +88 -88
  123. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/WriterInterface.php +27 -27
  124. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/AdapterRepository.php +107 -107
  125. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/RepositoryBuilder.php +272 -272
  126. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/RepositoryInterface.php +51 -51
  127. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/File/Paths.php +44 -44
  128. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/File/Reader.php +81 -81
  129. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/FileStore.php +72 -72
  130. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/StoreBuilder.php +141 -141
  131. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/StoreInterface.php +17 -17
  132. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/StringStore.php +37 -37
  133. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Util/Regex.php +112 -112
  134. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Util/Str.php +108 -108
  135. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Validator.php +207 -207
  136. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/DotenvTest.php +387 -0
  137. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Loader/LoaderTest.php +86 -0
  138. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Parser/EntryParserTest.php +234 -0
  139. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Parser/LexerTest.php +40 -0
  140. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Parser/LinesTest.php +53 -0
  141. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Parser/ParserTest.php +98 -0
  142. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/Adapter/ArrayAdapterTest.php +57 -0
  143. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/Adapter/EnvConstAdapterTest.php +75 -0
  144. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/Adapter/PutenvAdapterTest.php +52 -0
  145. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/Adapter/ServerConstAdapterTest.php +75 -0
  146. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/RepositoryTest.php +305 -0
  147. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Store/StoreTest.php +141 -0
  148. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/ValidatorTest.php +479 -0
  149. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/.env +5 -0
  150. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/assertions.env +18 -0
  151. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/booleans.env +33 -0
  152. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/commented.env +15 -0
  153. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/empty.env +1 -0
  154. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/example.env +1 -0
  155. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/exported.env +7 -0
  156. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/immutable.env +1 -0
  157. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/integers.env +17 -0
  158. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/large.env +2 -0
  159. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/multibyte.env +3 -0
  160. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/multiline.env +14 -0
  161. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/multiple.env +4 -0
  162. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/mutable.env +1 -0
  163. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/nested.env +15 -0
  164. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/quoted.env +11 -0
  165. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/specialchars.env +8 -0
  166. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/unicodevarnames.env +2 -0
  167. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/utf8-with-bom-encoding.env +3 -0
  168. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/windows.env +1 -0
  169. package/src/backend/_core/vendor/vlucas/phpdotenv/vendor-bin/phpstan/composer.json +15 -0
  170. package/src/backend/api/protected/example-protected.php +1 -1
  171. package/src/backend/api/public/example-public.php +1 -1
  172. package/src/backend/config.php +19 -0
  173. package/src/backend/web.config +2 -5
  174. package/src/frontend/.htaccess +4 -1
  175. package/src/frontend/web.config +21 -30
package/README.md CHANGED
@@ -12,7 +12,7 @@ Building a website from scratch involves a lot of moving parts: templating engin
12
12
  - 📁 **Scalable structure** — a clean, opinionated project layout that grows with your needs
13
13
  - 🌍 **Open source** — free to use, free to modify, free to share
14
14
 
15
- ![Version](https://img.shields.io/badge/version-2.0.14-blue)
15
+ ![Version](https://img.shields.io/badge/version-2.1.0-blue)
16
16
  ![License](https://img.shields.io/badge/license-Apache--2.0-blue)
17
17
  ![Eleventy](https://img.shields.io/badge/11ty-v3.1.2-black)
18
18
 
package/bin/create.js CHANGED
@@ -75,7 +75,7 @@ const FRAMEWORKS = {
75
75
 
76
76
  const PROJECT_PACKAGE = {
77
77
  name: path.basename(targetDir),
78
- version: '2.0.14',
78
+ version: '2.1.0',
79
79
  private: true,
80
80
  scripts: {
81
81
  "build:css": "sass src/frontend/scss:out/css --no-source-map --style=compressed --quiet --load-path=node_modules",
@@ -27,6 +27,26 @@ See **Components** DOC file for more info
27
27
 
28
28
  The URL is the kebab-case name (`/my-page/`). The `title` in the front matter is camelCase (`myPage`) and is used internally to load the correct CSS and JS files — do not change it.
29
29
 
30
+ ## Subpages (nested URLs)
31
+
32
+ To create a URL like `domain.it/about/team`, edit the `permalink` in `src/frontend/_routes/team.njk` and add the parent segment before the final slash:
33
+
34
+ ```njk
35
+ ---
36
+ title: "team"
37
+ permalink: "about/team/"
38
+ layout: includes.njk
39
+ ---
40
+ ```
41
+
42
+ The parent path (`about`) does **not** need to exist as a real page — it's just a URL prefix. Only the last segment (`team`) must match the filename and the `title` in the front matter.
43
+
44
+ | Goal URL | permalink value | File |
45
+ |---|---|---|
46
+ | `/team/` | `/team/` | `_routes/team.njk` |
47
+ | `/about/team/` | `/about/team/` | `_routes/team.njk` |
48
+ | `/company/about/team/` | `/company/about/team/` | `_routes/team.njk` |
49
+
30
50
  ## SEO
31
51
 
32
52
  The CLI creates a stub entry in `src/frontend/data/site.json`. Fill it in:
package/package.json CHANGED
@@ -1,63 +1,63 @@
1
- {
2
- "name": "create-berna-stencil",
3
- "version": "2.0.14",
4
- "description": "Eleventy boilerplate with per-page SCSS/JS pipeline, esbuild bundling, multi-framework CSS support and a built-in page management CLI",
5
- "keywords": [],
6
- "author": "Michele Garofalo",
7
- "license": "Apache-2.0",
8
- "repository": {
9
- "type": "git",
10
- "url": "https://github.com/rhaastrake/berna-stencil"
11
- },
12
- "homepage": "https://github.com/rhaastrake/berna-stencil#readme",
13
- "bugs": {
14
- "url": "https://github.com/rhaastrake/berna-stencil/issues"
15
- },
16
- "bin": {
17
- "create-berna-stencil": "bin/create.js"
18
- },
19
- "files": [
20
- "bin/",
21
- "docs/",
22
- "src/",
23
- "_tools/",
24
- ".eleventy.js",
25
- ".eleventyignore",
26
- ".gitignore",
27
- "LICENSE",
28
- "NOTICE"
29
- ],
30
- "engines": {
31
- "node": ">=18.0.0"
32
- },
33
- "dependencies": {
34
- "@11ty/eleventy": "^3.1.2",
35
- "@11ty/eleventy-img": "^6.0.4",
36
- "bootstrap": "^5.3.8",
37
- "bootstrap-icons": "^1.13.1",
38
- "bulma": "^1.0.4",
39
- "foundation-sites": "^6.9.0",
40
- "github-markdown-css": "^5.9.0",
41
- "glob": "^13.0.6",
42
- "markdown-it": "^14.2.0",
43
- "uikit": "^3.25.13"
44
- },
45
- "devDependencies": {
46
- "concurrently": "^9.2.1",
47
- "esbuild": "^0.27.3",
48
- "sass": "^1.77.0"
49
- },
50
- "scripts": {
51
- "build:css": "sass src/frontend/scss:out/css --no-source-map --style=compressed --quiet",
52
- "build:js": "esbuild \"src/frontend/js/pages/*.js\" --bundle --outdir=out/js/pages --minify",
53
- "build:11ty": "eleventy",
54
- "build": "npm run clean && npm run build:css && npm run build:js && npm run build:11ty",
55
- "serve:css": "sass --watch src/frontend/scss:out/css --no-source-map --quiet",
56
- "serve:js": "esbuild \"src/frontend/js/pages/*.js\" --bundle --outdir=out/js/pages --watch",
57
- "serve:11ty": "eleventy --serve --quiet",
58
- "clean": "node _tools/cleanOutput.js",
59
- "serve": "npm run clean && concurrently \"npm run serve:11ty\" \"npm run serve:css\" \"npm run serve:js\"",
60
- "assistant": "node _tools/assistant.js",
61
- "postinstall": "cd src/backend/_core && composer install --quiet"
62
- }
63
- }
1
+ {
2
+ "name": "create-berna-stencil",
3
+ "version": "2.1.0",
4
+ "description": "Eleventy boilerplate with per-page SCSS/JS pipeline, esbuild bundling, multi-framework CSS support and a built-in page management CLI",
5
+ "keywords": [],
6
+ "author": "Michele Garofalo",
7
+ "license": "Apache-2.0",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/rhaastrake/berna-stencil"
11
+ },
12
+ "homepage": "https://github.com/rhaastrake/berna-stencil#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/rhaastrake/berna-stencil/issues"
15
+ },
16
+ "bin": {
17
+ "create-berna-stencil": "bin/create.js"
18
+ },
19
+ "files": [
20
+ "bin/",
21
+ "docs/",
22
+ "src/",
23
+ "_tools/",
24
+ ".eleventy.js",
25
+ ".eleventyignore",
26
+ ".gitignore",
27
+ "LICENSE",
28
+ "NOTICE"
29
+ ],
30
+ "engines": {
31
+ "node": ">=18.0.0"
32
+ },
33
+ "dependencies": {
34
+ "@11ty/eleventy": "^3.1.2",
35
+ "@11ty/eleventy-img": "^6.0.4",
36
+ "bootstrap": "^5.3.8",
37
+ "bootstrap-icons": "^1.13.1",
38
+ "bulma": "^1.0.4",
39
+ "foundation-sites": "^6.9.0",
40
+ "github-markdown-css": "^5.9.0",
41
+ "glob": "^13.0.6",
42
+ "markdown-it": "^14.2.0",
43
+ "uikit": "^3.25.13"
44
+ },
45
+ "devDependencies": {
46
+ "concurrently": "^9.2.1",
47
+ "esbuild": "^0.27.3",
48
+ "sass": "^1.77.0"
49
+ },
50
+ "scripts": {
51
+ "build:css": "sass src/frontend/scss:out/css --no-source-map --style=compressed --quiet",
52
+ "build:js": "esbuild \"src/frontend/js/pages/*.js\" --bundle --outdir=out/js/pages --minify",
53
+ "build:11ty": "eleventy",
54
+ "build": "npm run clean && npm run build:css && npm run build:js && npm run build:11ty",
55
+ "serve:css": "sass --watch src/frontend/scss:out/css --no-source-map --quiet",
56
+ "serve:js": "esbuild \"src/frontend/js/pages/*.js\" --bundle --outdir=out/js/pages --watch",
57
+ "serve:11ty": "eleventy --serve --quiet",
58
+ "clean": "node _tools/cleanOutput.js",
59
+ "serve": "npm run clean && concurrently \"npm run serve:11ty\" \"npm run serve:css\" \"npm run serve:js\"",
60
+ "assistant": "node _tools/assistant.js",
61
+ "postinstall": "cd src/backend/_core && composer install --quiet"
62
+ }
63
+ }
@@ -21,6 +21,12 @@ $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
21
21
  $uri = rtrim(preg_replace('#^/api#', '', $uri), '/') ?: '/';
22
22
  $parts = array_values(array_filter(explode('/', $uri)));
23
23
 
24
+ foreach ($parts as $part) {
25
+ if ($part === '..' || $part === '.') {
26
+ Response::error('Bad Request', 400);
27
+ }
28
+ }
29
+
24
30
  // =====================================================
25
31
  // 2. ENDPOINT RESOLUTION (ROUTING WITH SUBDIRECTORIES)
26
32
  // =====================================================
@@ -95,6 +101,9 @@ if ($method === 'OPTIONS') {
95
101
  exit;
96
102
  }
97
103
 
104
+ require_once __DIR__ . '/modules/RateLimiter.php';
105
+ RateLimiter::check($_SERVER['REMOTE_ADDR'] ?? '', 60, 60);
106
+
98
107
  // =====================================================
99
108
  // 4. AUTHENTICATION GUARD
100
109
  // =====================================================
@@ -106,7 +115,7 @@ if ($isProtected) {
106
115
  $validKey = $config['ENDPOINT_KEYS'][$relPath] ?? $config['API_KEY'] ?? '';
107
116
  $apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
108
117
 
109
- if ($validKey === '' || $apiKey !== $validKey) {
118
+ if ($validKey === '' || !hash_equals($validKey, $apiKey)) {
110
119
  Response::error('Unauthorized. X_API_KEY is incorrect or missing', 401);
111
120
  }
112
121
  }
@@ -6,11 +6,12 @@ require_once __DIR__ . '/vendor/autoload.php';
6
6
  require_once __DIR__ . '/modules/Response.php';
7
7
 
8
8
  // --- GESTORE GLOBALE ERRORI E ECCEZIONI ---
9
- set_exception_handler(function ($exception) {
9
+ set_exception_handler(function ($exception) use (&$config) {
10
+ $isDebug = ($config['APP_ENV'] ?? 'production') !== 'production';
10
11
  Response::error(
11
- $exception->getMessage(),
12
+ $isDebug ? $exception->getMessage() : 'Internal server error',
12
13
  500,
13
- ['file' => $exception->getFile(), 'line' => $exception->getLine()]
14
+ $isDebug ? ['file' => $exception->getFile(), 'line' => $exception->getLine()] : null
14
15
  );
15
16
  });
16
17
 
@@ -0,0 +1,31 @@
1
+ <?php
2
+
3
+ declare(strict_types=1);
4
+
5
+ class RateLimiter {
6
+ public static function check(string $ip, int $maxRequests = 60, int $windowSeconds = 60): void {
7
+ $cacheDir = __DIR__ . '/../../cache';
8
+
9
+ if (!is_dir($cacheDir)) {
10
+ mkdir($cacheDir, 0755, true);
11
+ }
12
+
13
+ $cacheFile = $cacheDir . '/rl_' . md5($ip) . '.json';
14
+ $now = time();
15
+ $data = [];
16
+
17
+ if (file_exists($cacheFile)) {
18
+ $data = json_decode(file_get_contents($cacheFile), true) ?: [];
19
+ }
20
+
21
+ $data = array_filter($data, fn($ts) => $ts > ($now - $windowSeconds));
22
+ $data[] = $now;
23
+
24
+ file_put_contents($cacheFile, json_encode(array_values($data)), LOCK_EX);
25
+
26
+ if (count($data) > $maxRequests) {
27
+ header('Retry-After: ' . $windowSeconds);
28
+ Response::error('Too Many Requests', 429);
29
+ }
30
+ }
31
+ }
@@ -13,48 +13,48 @@ class ComposerStaticInit108be68e4e2b97fed51d36a10eed0849
13
13
  );
14
14
 
15
15
  public static $prefixLengthsPsr4 = array (
16
- 'S' =>
16
+ 'S' =>
17
17
  array (
18
18
  'Symfony\\Polyfill\\Php80\\' => 23,
19
19
  'Symfony\\Polyfill\\Mbstring\\' => 26,
20
20
  'Symfony\\Polyfill\\Ctype\\' => 23,
21
21
  ),
22
- 'P' =>
22
+ 'P' =>
23
23
  array (
24
24
  'PhpOption\\' => 10,
25
25
  ),
26
- 'G' =>
26
+ 'G' =>
27
27
  array (
28
28
  'GrahamCampbell\\ResultType\\' => 26,
29
29
  ),
30
- 'D' =>
30
+ 'D' =>
31
31
  array (
32
32
  'Dotenv\\' => 7,
33
33
  ),
34
34
  );
35
35
 
36
36
  public static $prefixDirsPsr4 = array (
37
- 'Symfony\\Polyfill\\Php80\\' =>
37
+ 'Symfony\\Polyfill\\Php80\\' =>
38
38
  array (
39
39
  0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
40
40
  ),
41
- 'Symfony\\Polyfill\\Mbstring\\' =>
41
+ 'Symfony\\Polyfill\\Mbstring\\' =>
42
42
  array (
43
43
  0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
44
44
  ),
45
- 'Symfony\\Polyfill\\Ctype\\' =>
45
+ 'Symfony\\Polyfill\\Ctype\\' =>
46
46
  array (
47
47
  0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
48
48
  ),
49
- 'PhpOption\\' =>
49
+ 'PhpOption\\' =>
50
50
  array (
51
51
  0 => __DIR__ . '/..' . '/phpoption/phpoption/src/PhpOption',
52
52
  ),
53
- 'GrahamCampbell\\ResultType\\' =>
53
+ 'GrahamCampbell\\ResultType\\' =>
54
54
  array (
55
55
  0 => __DIR__ . '/..' . '/graham-campbell/result-type/src',
56
56
  ),
57
- 'Dotenv\\' =>
57
+ 'Dotenv\\' =>
58
58
  array (
59
59
  0 => __DIR__ . '/..' . '/vlucas/phpdotenv/src',
60
60
  ),
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "time": "2025-12-27T19:43:20+00:00",
26
26
  "type": "library",
27
- "installation-source": "dist",
27
+ "installation-source": "source",
28
28
  "autoload": {
29
29
  "psr-4": {
30
30
  "GrahamCampbell\\ResultType\\": "src/"
@@ -98,7 +98,7 @@
98
98
  "dev-master": "1.9-dev"
99
99
  }
100
100
  },
101
- "installation-source": "dist",
101
+ "installation-source": "source",
102
102
  "autoload": {
103
103
  "psr-4": {
104
104
  "PhpOption\\": "src/PhpOption/"
@@ -175,7 +175,7 @@
175
175
  "name": "symfony/polyfill"
176
176
  }
177
177
  },
178
- "installation-source": "dist",
178
+ "installation-source": "source",
179
179
  "autoload": {
180
180
  "files": [
181
181
  "bootstrap.php"
@@ -262,7 +262,7 @@
262
262
  "name": "symfony/polyfill"
263
263
  }
264
264
  },
265
- "installation-source": "dist",
265
+ "installation-source": "source",
266
266
  "autoload": {
267
267
  "files": [
268
268
  "bootstrap.php"
@@ -343,7 +343,7 @@
343
343
  "name": "symfony/polyfill"
344
344
  }
345
345
  },
346
- "installation-source": "dist",
346
+ "installation-source": "source",
347
347
  "autoload": {
348
348
  "files": [
349
349
  "bootstrap.php"
@@ -447,7 +447,7 @@
447
447
  "dev-master": "5.6-dev"
448
448
  }
449
449
  },
450
- "installation-source": "dist",
450
+ "installation-source": "source",
451
451
  "autoload": {
452
452
  "psr-4": {
453
453
  "Dotenv\\": "src/"
@@ -3,7 +3,7 @@
3
3
  'name' => '__root__',
4
4
  'pretty_version' => 'dev-main',
5
5
  'version' => 'dev-main',
6
- 'reference' => '1914258c0d42371ce0d441bf14d8d5c68fbb542f',
6
+ 'reference' => '4da27b8f50bb1a801f88ad46a9e9eafa51c1bb34',
7
7
  'type' => 'library',
8
8
  'install_path' => __DIR__ . '/../../',
9
9
  'aliases' => array(),
@@ -13,7 +13,7 @@
13
13
  '__root__' => array(
14
14
  'pretty_version' => 'dev-main',
15
15
  'version' => 'dev-main',
16
- 'reference' => '1914258c0d42371ce0d441bf14d8d5c68fbb542f',
16
+ 'reference' => '4da27b8f50bb1a801f88ad46a9e9eafa51c1bb34',
17
17
  'type' => 'library',
18
18
  'install_path' => __DIR__ . '/../../',
19
19
  'aliases' => array(),
@@ -0,0 +1,9 @@
1
+ * text=auto
2
+
3
+ /tests export-ignore
4
+ /.gitattributes export-ignore
5
+ /.github export-ignore
6
+ /.gitignore export-ignore
7
+ /phpunit.xml.dist export-ignore
8
+ /CHANGELOG.md export-ignore
9
+ /README.md export-ignore
@@ -0,0 +1,132 @@
1
+ # CONTRIBUTOR COVENANT CODE OF CONDUCT
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual identity
10
+ and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the
26
+ overall community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or
31
+ advances of any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email
35
+ address, without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ hello@gjcampbell.co.uk.
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series
86
+ of actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or
93
+ permanent ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within
113
+ the community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.1, available at
119
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120
+
121
+ Community Impact Guidelines were inspired by
122
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123
+
124
+ For answers to common questions about this code of conduct, see the FAQ at
125
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available
126
+ at [https://www.contributor-covenant.org/translations][translations].
127
+
128
+ [homepage]: https://www.contributor-covenant.org
129
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130
+ [Mozilla CoC]: https://github.com/mozilla/diversity
131
+ [FAQ]: https://www.contributor-covenant.org/faq
132
+ [translations]: https://www.contributor-covenant.org/translations
@@ -0,0 +1,31 @@
1
+ # CONTRIBUTION GUIDELINES
2
+
3
+ Contributions are **welcome** and will be fully **credited**.
4
+
5
+ We accept contributions via pull requests on GitHub. Please review these guidelines before continuing.
6
+
7
+ ## Guidelines
8
+
9
+ * Please follow the [PSR-12 Coding Style Guide](https://www.php-fig.org/psr/psr-12/), enforced by [StyleCI](https://styleci.io/).
10
+ * Ensure that the current tests pass, and if you've added something new, add the tests where relevant.
11
+ * Send a coherent commit history, making sure each commit in your pull request is meaningful.
12
+ * You may need to [rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) to avoid merge conflicts.
13
+ * If you are changing or adding to the behaviour or public API, you may need to update the docs.
14
+ * Please remember that we follow [Semantic Versioning](https://semver.org/).
15
+
16
+ ## Running Tests
17
+
18
+ First, install the dependencies using [Composer](https://getcomposer.org/):
19
+
20
+ ```bash
21
+ $ composer install
22
+ ```
23
+
24
+ Then run [PHPUnit](https://phpunit.de/):
25
+
26
+ ```bash
27
+ $ vendor/bin/phpunit
28
+ ```
29
+
30
+ * The tests will be automatically run by [GitHub Actions](https://github.com/features/actions) against pull requests.
31
+ * We also have [StyleCI](https://styleci.io/) set up to automatically fix any code style issues.
@@ -0,0 +1,2 @@
1
+ github: GrahamCampbell
2
+ tidelift: "packagist/graham-campbell/result-type"
@@ -0,0 +1,14 @@
1
+ # SECURITY POLICY
2
+
3
+ ## Supported Versions
4
+
5
+ After each new major release, the previous release will be supported for no
6
+ less than 2 years, unless explicitly stated otherwise. This may mean that there
7
+ are multiple supported versions at any given time.
8
+
9
+ ## Reporting a Vulnerability
10
+
11
+ If you discover a security vulnerability within this package, please send an
12
+ email to security@tidelift.com. All security vulnerabilities will be promptly
13
+ addressed. Please do not disclose security-related issues publicly until a fix
14
+ has been announced.
@@ -0,0 +1,11 @@
1
+ name: Stale
2
+
3
+ on:
4
+ schedule:
5
+ - cron: '08 1 2-30/2 * *' # every even day at 01:08
6
+
7
+ jobs:
8
+ stale:
9
+ runs-on: ubuntu-24.04
10
+ steps:
11
+ - uses: actions/stale@v10
@@ -0,0 +1,40 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ tests:
9
+ name: PHP ${{ matrix.php }}
10
+ runs-on: ubuntu-24.04
11
+
12
+ strategy:
13
+ matrix:
14
+ php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
15
+
16
+ steps:
17
+ - name: Checkout Code
18
+ uses: actions/checkout@v6
19
+
20
+ - name: Setup PHP
21
+ uses: shivammathur/setup-php@v2
22
+ with:
23
+ php-version: ${{ matrix.php }}
24
+ tools: composer:v2
25
+ coverage: none
26
+ env:
27
+ update: true
28
+
29
+ - name: Setup Problem Matchers
30
+ run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
31
+
32
+ - name: Install PHP Dependencies
33
+ uses: nick-fields/retry@v3
34
+ with:
35
+ timeout_minutes: 5
36
+ max_attempts: 5
37
+ command: composer update --no-interaction --no-progress
38
+
39
+ - name: Execute PHPUnit
40
+ run: vendor/bin/phpunit