create-berna-stencil 1.0.24 → 1.0.26

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 (37) hide show
  1. package/.eleventy.js +1 -0
  2. package/.gitignore +2 -2
  3. package/_tools/assistant.js +6 -6
  4. package/_tools/modules/updateOutputPath.js +1 -4
  5. package/_tools/modules/updatePage.js +33 -72
  6. package/_tools/res/templates/template.js +23 -0
  7. package/_tools/res/templates/template.njk +8 -0
  8. package/_tools/res/templates/template.scss +17 -0
  9. package/bin/create.js +1 -1
  10. package/package.json +1 -1
  11. package/src/api/.htaccess +6 -11
  12. package/src/api/config.example.php +5 -20
  13. package/src/api/config.php +5 -20
  14. package/src/api/core/composer.lock +492 -492
  15. package/src/api/{index.php → core/index.php} +53 -24
  16. package/src/api/core/init.php +0 -13
  17. package/src/api/core/vendor/composer/installed.php +2 -2
  18. package/src/api/database/Database.php +24 -0
  19. package/src/api/database/migrations/create_example_db.sql +1 -0
  20. package/src/api/database/migrations/create_users_table.sql +9 -0
  21. package/src/api/database/models/User.php +61 -0
  22. package/src/api/database/seeds/users.php +0 -0
  23. package/src/api/database/services/UserService.php +0 -0
  24. package/src/api/endpoints/protected/auth-system.php +63 -0
  25. package/src/api/endpoints/protected/example-protected.php +17 -0
  26. package/src/api/endpoints/public/auth/login.php +34 -0
  27. package/src/api/endpoints/public/auth/register.php +39 -0
  28. package/src/api/endpoints/public/example-public.php +17 -0
  29. package/src/api/web.config +6 -24
  30. package/src/components/exampleComponent.njk +5 -2
  31. package/src/components/layouts/base.njk +26 -1
  32. package/src/data/site.json +53 -53
  33. package/src/js/modules/langSwitcher.js +1 -1
  34. package/src/web.config +30 -33
  35. package/_tools/res/templates.json +0 -56
  36. package/src/api/endpoints/protected/example-protected-endpoint.php +0 -28
  37. package/src/api/endpoints/public/example-public-endpoint.php +0 -28
package/.eleventy.js CHANGED
@@ -25,6 +25,7 @@ module.exports = function (eleventyConfig) {
25
25
  // PASSTHROUGH — Static files
26
26
  // =====================================================
27
27
  eleventyConfig.addPassthroughCopy("src/.htaccess");
28
+ eleventyConfig.addPassthroughCopy("src/web.config");
28
29
  eleventyConfig.addPassthroughCopy("src/api");
29
30
  eleventyConfig.addPassthroughCopy("src/assets");
30
31
  eleventyConfig.addPassthroughCopy("src/robots.txt");
package/.gitignore CHANGED
@@ -1,4 +1,4 @@
1
1
  node_modules/
2
+ src/api/core/vendor/
2
3
  out/
3
- src/api/config.php
4
- src/api/core/vendor/
4
+ src/api/config.php
@@ -77,9 +77,9 @@ function handleRemoveRequest() {
77
77
 
78
78
  function handleOutputPathRequest() {
79
79
  const current = getCurrentOutputPath();
80
- const currentLabel = current ? ` (current: "${current}")` : '';
80
+ const currentLabel = current ? ` Current path: "${current}"` : '';
81
81
 
82
- readerInterface.question(`\n> Enter the new output path${currentLabel}\n (e.g. C:/laragon/www or . for root): `, (inputPath) => {
82
+ readerInterface.question(`${currentLabel}\n Enter the new output path: `, (inputPath) => {
83
83
  if (!inputPath.trim()) {
84
84
  console.log('(!) Invalid path.');
85
85
  } else {
@@ -94,8 +94,8 @@ function displayMainMenu() {
94
94
  console.log(' Berna-Stencil CLI ');
95
95
  console.log('========================\n');
96
96
  console.log('1. Create page');
97
- console.log('2. Rename page');
98
- console.log('3. Remove page');
97
+ console.log('2. Remove page');
98
+ console.log('3. Rename page');
99
99
  console.log('4. Configure output path');
100
100
  console.log('\nCTRL/CMD + C to exit');
101
101
 
@@ -104,9 +104,9 @@ function displayMainMenu() {
104
104
  if (cleanChoice === '1') {
105
105
  handleCreateRequest();
106
106
  } else if (cleanChoice === '2') {
107
- handleRenameRequest();
108
- } else if (cleanChoice === '3') {
109
107
  handleRemoveRequest();
108
+ } else if (cleanChoice === '3') {
109
+ handleRenameRequest();
110
110
  } else if (cleanChoice === '4') {
111
111
  handleOutputPathRequest();
112
112
  } else if (cleanChoice === '0') {
@@ -75,10 +75,7 @@ function getCurrentOutputPath() {
75
75
 
76
76
  const outputDir = match[1];
77
77
 
78
- if (!path.isAbsolute(outputDir)) {
79
- return 'project root/out';
80
- }
81
-
78
+
82
79
  const parent = path.dirname(outputDir);
83
80
  const projectName = path.basename(outputDir);
84
81
 
@@ -4,7 +4,7 @@ const path = require("path");
4
4
  const { addSiteData, removeSiteData } = require("./updateData");
5
5
  const { addLayout, removeLayout } = require("./updateIncludes");
6
6
 
7
- const TEMPLATE_FILE_PATH = path.join(__dirname, '..', 'res', 'templates.json');
7
+ const TEMPLATES_DIR = path.join(__dirname, '..', 'res', 'templates');
8
8
 
9
9
  function toCamelCase(str) {
10
10
  return str.toLowerCase().replace(/[-_][a-z0-9]/g, (group) =>
@@ -12,56 +12,33 @@ function toCamelCase(str) {
12
12
  );
13
13
  }
14
14
 
15
- function getFileInitialContent(pageName, extension) {
16
- try {
17
- const rawData = fileSystem.readFileSync(TEMPLATE_FILE_PATH, "utf8");
18
- const templates = JSON.parse(rawData);
19
- let selectedTemplate = templates[extension];
20
- if (!selectedTemplate) return "";
21
-
22
- const content = Array.isArray(selectedTemplate) ? selectedTemplate.join("\n") : selectedTemplate;
23
-
24
- const kebabName = pageName;
25
- const camelName = toCamelCase(pageName);
26
-
27
- let processedContent = content
28
- .replace(/{{pageName}}/g, kebabName)
29
- .replace(/{{camelName}}/g, camelName);
30
-
31
- if (extension === '.njk') {
32
- processedContent = processedContent.replace(/^title:\s*.*$/m, `title: "${camelName}"`);
33
-
34
- if (processedContent.includes('permalink:')) {
35
- processedContent = processedContent.replace(/^permalink:\s*.*$/m, `permalink: "/${kebabName}/"`);
36
- } else {
37
- processedContent = processedContent.replace(`title: "${camelName}"`, `title: "${camelName}"\npermalink: "/${kebabName}/"`);
38
- }
39
- }
40
-
41
- return processedContent;
42
- } catch (error) {
43
- console.error(`[error] ${error.message}`);
44
- return "";
45
- }
46
- }
47
-
48
15
  function addPage(pageName) {
49
16
  const camelName = toCamelCase(pageName);
50
-
17
+
51
18
  const targets = [
52
- { folder: "src/scss/pages", extension: ".scss", fileName: camelName },
53
- { folder: "src/js/pages", extension: ".js", fileName: camelName },
54
- { folder: "src/_routes", extension: ".njk", fileName: pageName },
19
+ { folder: "src/scss/pages", templateFile: "template.scss", fileName: `${camelName}.scss` },
20
+ { folder: "src/js/pages", templateFile: "template.js", fileName: `${camelName}.js` },
21
+ { folder: "src/_routes", templateFile: "template.njk", fileName: `${pageName}.njk` },
55
22
  ];
56
23
 
57
- targets.forEach((target) => {
58
- const filePath = path.join(target.folder, `${target.fileName}${target.extension}`);
59
- fileSystem.mkdirSync(target.folder, { recursive: true });
60
-
61
- if (!fileSystem.existsSync(filePath)) {
62
- const fileContent = getFileInitialContent(pageName, target.extension);
63
- fileSystem.writeFileSync(filePath, fileContent);
64
- console.log(`[created file] ${filePath}`);
24
+ targets.forEach(({ folder, templateFile, fileName }) => {
25
+ const destPath = path.join(folder, fileName);
26
+ fileSystem.mkdirSync(folder, { recursive: true });
27
+
28
+ if (!fileSystem.existsSync(destPath)) {
29
+ const srcPath = path.join(TEMPLATES_DIR, templateFile);
30
+
31
+ if (templateFile === "template.njk") {
32
+ let content = fileSystem.readFileSync(srcPath, 'utf8');
33
+ content = content
34
+ .replace(/^title:.*$/m, `title: "${camelName}"`)
35
+ .replace(/^permalink:.*$/m, `permalink: "/${pageName}/"`);
36
+ fileSystem.writeFileSync(destPath, content);
37
+ } else {
38
+ fileSystem.copyFileSync(srcPath, destPath);
39
+ }
40
+
41
+ console.log(`[created file] ${destPath}`);
65
42
  }
66
43
  });
67
44
 
@@ -74,18 +51,9 @@ function renamePage(oldName, newName) {
74
51
  const newCamel = toCamelCase(newName);
75
52
 
76
53
  const filesToRename = [
77
- {
78
- src: `src/scss/pages/${oldCamel}.scss`,
79
- dest: `src/scss/pages/${newCamel}.scss`,
80
- },
81
- {
82
- src: `src/js/pages/${oldCamel}.js`,
83
- dest: `src/js/pages/${newCamel}.js`,
84
- },
85
- {
86
- src: `src/_routes/${oldName}.njk`,
87
- dest: `src/_routes/${newName}.njk`,
88
- },
54
+ { src: `src/scss/pages/${oldCamel}.scss`, dest: `src/scss/pages/${newCamel}.scss` },
55
+ { src: `src/js/pages/${oldCamel}.js`, dest: `src/js/pages/${newCamel}.js` },
56
+ { src: `src/_routes/${oldName}.njk`, dest: `src/_routes/${newName}.njk` },
89
57
  ];
90
58
 
91
59
  filesToRename.forEach(({ src, dest }) => {
@@ -93,12 +61,7 @@ function renamePage(oldName, newName) {
93
61
  console.log(`[skip] not found: ${src}`);
94
62
  return;
95
63
  }
96
- let content = fileSystem.readFileSync(src, 'utf8');
97
- content = content
98
- .replace(new RegExp(oldName, 'g'), newName)
99
- .replace(new RegExp(oldCamel, 'g'), newCamel);
100
- fileSystem.writeFileSync(dest, content);
101
- fileSystem.unlinkSync(src);
64
+ fileSystem.renameSync(src, dest);
102
65
  console.log(`[renamed] ${src} → ${dest}`);
103
66
  });
104
67
 
@@ -111,27 +74,25 @@ function renamePage(oldName, newName) {
111
74
  function removePage(pageName) {
112
75
  const camelName = toCamelCase(pageName);
113
76
  const OUTPUT_DIR = "out";
114
-
77
+
115
78
  const filesToDelete = [
116
79
  `src/scss/pages/${camelName}.scss`,
117
80
  `src/js/pages/${camelName}.js`,
118
81
  `src/_routes/${pageName}.njk`,
119
-
120
- path.join(OUTPUT_DIR, "js/pages", `${camelName}.js`),
82
+ path.join(OUTPUT_DIR, "js/pages", `${camelName}.js`),
121
83
  path.join(OUTPUT_DIR, "css/pages", `${camelName}.css`),
122
-
123
84
  path.join(OUTPUT_DIR, `${pageName}.html`),
124
- path.join(OUTPUT_DIR, "pages", `${pageName}.html`)
85
+ path.join(OUTPUT_DIR, "pages", `${pageName}.html`),
125
86
  ];
126
87
 
127
88
  const foldersToDelete = [
128
89
  path.join(OUTPUT_DIR, pageName),
129
- path.join(OUTPUT_DIR, "pages", pageName)
90
+ path.join(OUTPUT_DIR, "pages", pageName),
130
91
  ];
131
92
 
132
- filesToDelete.forEach(f => {
93
+ filesToDelete.forEach(f => {
133
94
  if (fileSystem.existsSync(f)) {
134
- fileSystem.unlinkSync(f);
95
+ fileSystem.unlinkSync(f);
135
96
  console.log(`[deleted file] ${f}`);
136
97
  }
137
98
  });
@@ -0,0 +1,23 @@
1
+ //==========================
2
+ // JAVASCRIPT MODULES IMPORTS
3
+ //==========================
4
+
5
+ // Call inside DOMContentLoaded
6
+ import { initLangSwitcher } from '../modules/langSwitcher.js';
7
+
8
+ // Call anywhere
9
+ import { showNotification } from '../modules/notification.js';
10
+
11
+ // Uncomment to enable optional modules (call inside DOMContentLoaded)
12
+ // import { initTextAreaAutoExpand } from '../modules/forms/textAreaAutoExpand.js';
13
+ // import { initNormalizePhoneNumber } from '../modules/forms/normalizePhoneNumber.js';
14
+
15
+ //==========================
16
+ // PAGE CUSTOM JAVASCRIPT
17
+ //==========================
18
+
19
+ document.addEventListener("DOMContentLoaded", () => {
20
+ initLangSwitcher();
21
+ });
22
+
23
+ showNotification("prova notification", "success", 3000);
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: ""
3
+ permalink: ""
4
+ layout: includes.njk
5
+ ---
6
+
7
+ <!-- Add content via components in src/components/, not directly here.
8
+ Register them in src/layouts/includes.njk. -->
@@ -0,0 +1,17 @@
1
+ //==========================
2
+ // CSS MODULES IMPORTS
3
+ //==========================
4
+
5
+ @use "../modules/root" as root;
6
+
7
+ @import "../modules/global";
8
+ // Import any other module you need by import down here
9
+ @import "../modules/notification";
10
+
11
+ //==========================
12
+ // PAGE CUSTOM CSS RULES
13
+ //==========================
14
+
15
+ // body {
16
+ // background-color: root.$primary;
17
+ // }
package/bin/create.js CHANGED
@@ -17,7 +17,7 @@ const COPY_TARGETS = [
17
17
 
18
18
  const PROJECT_PACKAGE = {
19
19
  name: path.basename(targetDir),
20
- version: '1.0.24',
20
+ version: '1.0.26',
21
21
  private: true,
22
22
  scripts: {
23
23
  "build:css": "sass src/scss:c:/laragon/www/Berna-Stencil-out/css --no-source-map --style=compressed --quiet",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-berna-stencil",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
4
4
  "description": "Eleventy boilerplate with per-page SCSS/JS pipeline, esbuild bundling, multi-framework CSS support and a built-in page management CLI",
5
5
  "keywords": [
6
6
  "eleventy",
package/src/api/.htaccess CHANGED
@@ -2,16 +2,11 @@
2
2
  RewriteEngine On
3
3
  RewriteBase /api/
4
4
 
5
- # 1. Permetti index.php
6
- RewriteRule ^index\.php$ - [L]
5
+ # 1. Se la richiesta è esattamente per index.php, servilo e fermati qui.
6
+ RewriteRule ^core/index\.php$ - [L]
7
7
 
8
- # 2. Invece di dare Forbidden [F], manda tutto a index.php
9
- # Questo copre config.php e tutte le sottocartelle
10
- RewriteRule \.php$ index.php [L]
11
- RewriteRule ^(core|endpoints|modules|vendor)($|/) index.php [L]
12
-
13
- # 3. Regola per gli endpoint
14
- RewriteCond %{REQUEST_FILENAME} !-f
15
- RewriteCond %{REQUEST_FILENAME} !-d
16
- RewriteRule ^(.*)$ index.php [QSA,L]
8
+ # 2. Invia TUTTO il resto a index.php
9
+ # Non controlliamo più se il file esiste (-f) o meno.
10
+ # Qualsiasi cosa scrivano dopo /api/ va a finire nel router PHP.
11
+ RewriteRule ^(.*)$ core/index.php [QSA,L]
17
12
  </IfModule>
@@ -1,27 +1,12 @@
1
1
  <?php
2
2
  declare(strict_types=1);
3
3
 
4
- if (!defined('CORE_ACCESS')) {
5
- $errorPage = $_SERVER['DOCUMENT_ROOT'] . '/404.html';
6
- http_response_code(404);
7
- if (file_exists($errorPage)) {
8
- header('Content-Type: text/html; charset=UTF-8');
9
- echo file_get_contents($errorPage);
10
- } else {
11
- echo "404 Not Found";
12
- }
13
- exit;
14
- }
15
-
16
4
  return [
17
- // Configurazioni di base
18
- 'API_KEY' => 'TOKEN',
5
+ 'API_KEY' => 'YOUR_TOKEN', // This must be give only to trusted clients to access protected endpoints directly
19
6
  'CORS_ALLOWED_ORIGINS' => '*',
20
7
 
21
- // Configurazioni per l'invio delle Email
22
- 'MAIL_HOST' => 'smtp.gmail.com',
23
- 'MAIL_PORT' => 587, // Per i numeri puoi omettere gli apici
24
- 'MAIL_USERNAME' => 'YOUR_EMAIL',
25
- 'MAIL_PASSWORD' => 'APP_PASSWORD',
26
- 'MAIL_TO_ADDRESS' => 'EMAIL_TO_ADDRESS',
8
+ 'DB_HOST' => '127.0.0.1',
9
+ 'DB_NAME' => 'example_db',
10
+ 'DB_USER' => 'root',
11
+ 'DB_PASS' => '',
27
12
  ];
@@ -1,27 +1,12 @@
1
1
  <?php
2
2
  declare(strict_types=1);
3
3
 
4
- if (!defined('CORE_ACCESS')) {
5
- $errorPage = $_SERVER['DOCUMENT_ROOT'] . '/404.html';
6
- http_response_code(404);
7
- if (file_exists($errorPage)) {
8
- header('Content-Type: text/html; charset=UTF-8');
9
- echo file_get_contents($errorPage);
10
- } else {
11
- echo "404 Not Found";
12
- }
13
- exit;
14
- }
15
-
16
4
  return [
17
- // Configurazioni di base
18
- 'API_KEY' => 'TOKEN',
5
+ 'API_KEY' => 'YOUR_TOKEN', // This must be give only to trusted clients to access protected endpoints directly
19
6
  'CORS_ALLOWED_ORIGINS' => '*',
20
7
 
21
- // Configurazioni per l'invio delle Email
22
- 'MAIL_HOST' => 'smtp.gmail.com',
23
- 'MAIL_PORT' => 587, // Per i numeri puoi omettere gli apici
24
- 'MAIL_USERNAME' => 'YOUR_EMAIL',
25
- 'MAIL_PASSWORD' => 'APP_PASSWORD',
26
- 'MAIL_TO_ADDRESS' => 'EMAIL_TO_ADDRESS',
8
+ 'DB_HOST' => '127.0.0.1',
9
+ 'DB_NAME' => 'example_db',
10
+ 'DB_USER' => 'root',
11
+ 'DB_PASS' => '',
27
12
  ];