@codigodoleo/wp-kit 3.1.1 → 3.3.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 (112) hide show
  1. package/lib/commands/init.js +19 -10
  2. package/lib/config/versions.js +5 -5
  3. package/lib/core/infer-ci-capabilities.js +17 -0
  4. package/lib/prompts/index.js +27 -17
  5. package/lib/utils/git.js +50 -13
  6. package/modules/blank-theme/index.js +71 -0
  7. package/modules/blank-theme/lint/.prettierrc.json +12 -0
  8. package/modules/blank-theme/lint/.stylelintrc.json +7 -0
  9. package/modules/{lint → blank-theme/lint}/eslint.config.mjs +2 -8
  10. package/modules/blank-theme/lint/pint.json +11 -0
  11. package/modules/blank-theme/prompts.js +36 -0
  12. package/modules/blank-theme/templates/.lando.yml.hbs +26 -0
  13. package/modules/blank-theme/templates/functions.php.hbs +46 -0
  14. package/modules/blank-theme/templates/package.json.hbs +16 -0
  15. package/modules/blank-theme/templates/style.css.hbs +7 -0
  16. package/modules/blank-theme/templates/vite.config.js.hbs +23 -0
  17. package/modules/deploy/.github/workflows/deploy-docker.yml +104 -0
  18. package/modules/deploy/.github/workflows/deploy-ssh.yml +128 -0
  19. package/modules/deploy/.github/workflows/release.yml +57 -0
  20. package/modules/deploy/index.js +77 -0
  21. package/modules/deploy/prompts.js +1 -3
  22. package/modules/deploy/templates/.github/workflows/ci.yml.hbs +29 -1
  23. package/modules/deploy/templates/.gitlab/ci/deploy-docker.yml.hbs +35 -0
  24. package/modules/deploy/templates/.gitlab/ci/deploy-ssh.yml.hbs +83 -0
  25. package/modules/deploy/templates/.gitlab/ci/lint-blank-theme.yml.hbs +35 -0
  26. package/modules/deploy/templates/.gitlab/ci/lint-mu-plugin.yml.hbs +19 -0
  27. package/modules/deploy/templates/.gitlab/ci/lint-plugin.yml.hbs +19 -0
  28. package/modules/deploy/templates/.gitlab/ci/lint-sage.yml.hbs +47 -0
  29. package/modules/deploy/templates/.gitlab/ci/release.yml.hbs +26 -0
  30. package/modules/git/.husky/commit-msg +8 -4
  31. package/modules/git/.husky/pre-commit +0 -3
  32. package/modules/git/templates/package.json.hbs +4 -4
  33. package/modules/git/templates/workspace.json.hbs +1 -1
  34. package/modules/lint/.commitlintrc.json +21 -0
  35. package/modules/lint/.prettierignore +15 -25
  36. package/modules/lint/.prettierrc.json +5 -16
  37. package/modules/lint/index.js +75 -8
  38. package/modules/lint/prompts.js +1 -8
  39. package/modules/lint/templates/.lando.yml.hbs +3 -8
  40. package/modules/lint/templates/package.json.hbs +4 -4
  41. package/modules/lint/templates/workspace.json.hbs +3 -3
  42. package/modules/mu-plugin/index.js +49 -0
  43. package/modules/mu-plugin/lint/.prettierrc.json +7 -0
  44. package/modules/mu-plugin/lint/eslint.config.mjs +30 -0
  45. package/modules/mu-plugin/lint/pint.json +11 -0
  46. package/modules/mu-plugin/prompts.js +29 -0
  47. package/modules/mu-plugin/templates/.lando.yml.hbs +15 -0
  48. package/modules/mu-plugin/templates/composer.json.hbs +14 -0
  49. package/modules/mu-plugin/templates/plugin.php.hbs +15 -0
  50. package/modules/php/templates/composer.json.hbs +15 -1
  51. package/modules/plugin/index.js +45 -0
  52. package/modules/plugin/lint/.prettierrc.json +7 -0
  53. package/modules/plugin/lint/eslint.config.mjs +30 -0
  54. package/modules/plugin/lint/pint.json +11 -0
  55. package/modules/plugin/prompts.js +29 -0
  56. package/modules/plugin/templates/.lando.yml.hbs +15 -0
  57. package/modules/plugin/templates/composer.json.hbs +14 -0
  58. package/modules/plugin/templates/plugin.php.hbs +15 -0
  59. package/modules/sage/index.js +139 -15
  60. package/modules/sage/lint/.prettierrc.json +12 -0
  61. package/modules/sage/lint/.stylelintrc.json +7 -0
  62. package/modules/sage/lint/eslint.config.mjs +30 -0
  63. package/modules/sage/lint/pint.json +11 -0
  64. package/modules/sage/prompts.js +22 -1
  65. package/modules/sage/templates/.devcontainer/devcontainer.json.hbs +7 -0
  66. package/modules/sage/templates/.devcontainer/docker-compose.override.yml.hbs +6 -0
  67. package/modules/sage/templates/.devcontainer/post-create.sh.hbs +11 -0
  68. package/modules/sage/templates/.lando.yml.hbs +43 -45
  69. package/modules/sage/templates/server/cmd/setup-sage-node.sh.hbs +23 -0
  70. package/modules/sage/templates/server/cmd/setup-sage-php.sh.hbs +24 -0
  71. package/modules/sage/templates/theme/app/Blocks/.gitkeep.hbs +0 -0
  72. package/modules/sage/templates/theme/app/Fields/.gitkeep.hbs +0 -0
  73. package/modules/sage/templates/theme/composer.json.hbs +25 -3
  74. package/modules/sage/templates/theme/package.json.hbs +15 -3
  75. package/modules/sage/templates/theme/resources/views/blocks/.gitkeep.hbs +0 -0
  76. package/modules/sage/templates/theme/vite.config.js.hbs +55 -13
  77. package/modules/sage/templates/workspace.json.hbs +94 -6
  78. package/modules/skills/index.js +18 -0
  79. package/modules/skills/prompts.js +21 -0
  80. package/modules/test/index.js +19 -0
  81. package/modules/test/prompts.js +8 -0
  82. package/modules/test/templates/composer.json.hbs +16 -0
  83. package/modules/test/templates/package.json.hbs +11 -0
  84. package/modules/test/templates/playwright.config.js.hbs +29 -0
  85. package/modules/test/tests/Pest.php +39 -0
  86. package/modules/test/tests/SmokeTest.php +15 -0
  87. package/modules/test/tests/e2e/example.spec.js +11 -0
  88. package/modules/test/tests/e2e/helpers/loginHelper.js +40 -0
  89. package/package.json +1 -1
  90. package/templates/.devcontainer/Dockerfile.hbs +24 -0
  91. package/templates/.devcontainer/config/nginx.conf +23 -0
  92. package/templates/.devcontainer/config/nginx.conf.hbs +23 -0
  93. package/templates/.devcontainer/devcontainer.json.hbs +29 -0
  94. package/templates/.devcontainer/docker-compose.yml.hbs +73 -0
  95. package/templates/.devcontainer/setup.sh.hbs +17 -0
  96. package/templates/.env.hbs +38 -15
  97. package/templates/.gitignore.hbs +84 -13
  98. package/templates/.lando.yml.hbs +61 -17
  99. package/templates/README.md.hbs +23 -7
  100. package/templates/composer.json.hbs +60 -12
  101. package/templates/package.json.hbs +0 -2
  102. package/templates/server/cmd/install-wp.sh.hbs +54 -43
  103. package/templates/server/cmd/setup-node.sh.hbs +11 -0
  104. package/templates/server/cmd/setup-php.sh.hbs +14 -0
  105. package/templates/server/www/vhosts.conf.hbs +54 -17
  106. package/templates/workspace.json.hbs +57 -1
  107. package/templates/wp-cli.yml.hbs +1 -0
  108. package/modules/lint/.eslintignore +0 -36
  109. package/modules/lint/.eslintrc.json +0 -8
  110. package/modules/lint/.stylelintignore +0 -19
  111. package/modules/lint/.stylelintrc.json +0 -9
  112. package/modules/lint/pint.json +0 -26
@@ -0,0 +1,15 @@
1
+ tooling:
2
+ {{#if enable_lint}}
3
+ plugin-pint:
4
+ service: appserver
5
+ description: Lint PHP in the plugin
6
+ dir: /app/content/plugins/{{plugin_name}}
7
+ cmd: ./vendor/bin/pint
8
+ {{#if plugin_lint_eslint}}
9
+ plugin-eslint:
10
+ service: build
11
+ description: Lint JS/TS in the plugin
12
+ dir: /app/content/plugins/{{plugin_name}}
13
+ cmd: npx eslint --fix resources/
14
+ {{/if}}
15
+ {{/if}}
@@ -0,0 +1,14 @@
1
+ {
2
+ "description": "{{projectDescription}} — Plugin",
3
+ "autoload": {
4
+ "psr-4": {
5
+ "App\\Plugins\\": "src/"
6
+ }
7
+ },
8
+ "require-dev": {
9
+ "laravel/pint": "^1.21"
10
+ },
11
+ "scripts": {
12
+ "lint": ["./vendor/bin/pint --test"]
13
+ }
14
+ }
@@ -0,0 +1,15 @@
1
+ <?php
2
+ /**
3
+ * Plugin Name: {{plugin_name}}
4
+ * Description: {{projectDescription}}
5
+ * Version: {{projectVersion}}
6
+ */
7
+
8
+ if (!defined('ABSPATH')) {
9
+ exit;
10
+ }
11
+
12
+ // Autoload via Composer
13
+ if (file_exists(__DIR__ . '/vendor/autoload.php')) {
14
+ require_once __DIR__ . '/vendor/autoload.php';
15
+ }
@@ -16,6 +16,7 @@ import { VERSION_REGISTRY, validateVersionCompatibility } from '../../lib/config
16
16
  export async function setupModule(context, generator) {
17
17
  const themeDir = path.join(context.cwd, 'content', 'themes', context.projectName);
18
18
  const relativeThemeDir = `content/themes/${context.projectName}`;
19
+ const relativeDevcontainerDir = '.devcontainer';
19
20
 
20
21
  try {
21
22
  // 1. Validate version compatibility
@@ -46,11 +47,17 @@ export async function setupModule(context, generator) {
46
47
  // 3. Prepare and validate directory
47
48
  await fs.ensureDir(themeDir);
48
49
  const files = await fs.readdir(themeDir);
50
+ let shouldInstallSage = true;
51
+
49
52
  if (files.length > 0) {
50
- log(
51
- color.orange,
52
- `⚠️ Warning: ${themeDir} is not empty. Existing files may be overwritten.`
53
- );
53
+ const alreadyInstalled = await isSageThemeInstalled(themeDir);
54
+ if (alreadyInstalled) {
55
+ shouldInstallSage = false;
56
+ log(color.blue, '[sage] ♻️ Existing Sage theme detected. Reusing installation.');
57
+ } else {
58
+ log(color.orange, `⚠️ ${themeDir} has stale files. Cleaning before installation.`);
59
+ await fs.emptyDir(themeDir);
60
+ }
54
61
  }
55
62
 
56
63
  // 4. Build composer command with proper error handling
@@ -63,32 +70,139 @@ export async function setupModule(context, generator) {
63
70
  '--ignore-platform-reqs',
64
71
  ].join(' ');
65
72
 
66
- log(color.blue, `[sage] 📦 Installing Sage ${context.sageVersion} (${sageConfig.tag})...`);
67
- log(color.blue, `[sage] 📍 Location: ${relativeThemeDir}`);
68
-
69
- // 5. Execute installation
70
- execSync(cmd, { stdio: 'inherit', cwd: context.cwd });
73
+ if (shouldInstallSage) {
74
+ log(color.blue, `[sage] 📦 Installing Sage ${context.sageVersion} (${sageConfig.tag})...`);
75
+ log(color.blue, `[sage] 📍 Location: ${relativeThemeDir}`);
76
+ execSync(cmd, { stdio: 'inherit', cwd: context.cwd });
77
+ }
71
78
 
72
79
  // 6. Validate theme installation
73
80
  await validateThemeInstallation(themeDir, sageConfig);
74
81
  log(color.green, `[sage] ✅ Theme installation verified`);
75
82
 
76
83
  // 7. Generate customizations
77
- log(color.blue, `[sage] 📝 Generating theme customizations...`);
84
+ log(color.blue, '[sage] 🛠️ Applying advanced Sage DX customizations...');
85
+ if (context.sageVersion === '11') {
86
+ await generator.generateFile(
87
+ 'theme/vite.config.js',
88
+ context,
89
+ 'sage',
90
+ `${relativeThemeDir}/vite.config.js`
91
+ );
92
+ } else {
93
+ log(color.blue, '[sage] ℹ️ Keeping default Vite config for Sage 10 compatibility.');
94
+ }
78
95
  await generator.generateFile(
79
- 'theme/vite.config.js',
96
+ 'theme/style.css',
80
97
  context,
81
98
  'sage',
82
- `${relativeThemeDir}/vite.config.js`
99
+ `${relativeThemeDir}/style.css`
83
100
  );
101
+
84
102
  await generator.generateFile(
85
- 'theme/style.css',
103
+ 'theme/app/Blocks/.gitkeep',
86
104
  context,
87
105
  'sage',
88
- `${relativeThemeDir}/style.css`
106
+ `${relativeThemeDir}/app/Blocks/.gitkeep`
107
+ );
108
+ await generator.generateFile(
109
+ 'theme/app/Fields/.gitkeep',
110
+ context,
111
+ 'sage',
112
+ `${relativeThemeDir}/app/Fields/.gitkeep`
89
113
  );
114
+ await generator.generateFile(
115
+ 'theme/resources/views/blocks/.gitkeep',
116
+ context,
117
+ 'sage',
118
+ `${relativeThemeDir}/resources/views/blocks/.gitkeep`
119
+ );
120
+
121
+ await generator.mergeWithExistingFile({
122
+ existingFile: `${relativeThemeDir}/package.json`,
123
+ moduleTemplatePath: 'theme/package.json',
124
+ context,
125
+ format: 'json',
126
+ moduleName: 'sage',
127
+ mergeStrategy: 'replace',
128
+ });
129
+
130
+ await generator.mergeWithExistingFile({
131
+ existingFile: `${relativeThemeDir}/composer.json`,
132
+ moduleTemplatePath: 'theme/composer.json',
133
+ context,
134
+ format: 'json',
135
+ moduleName: 'sage',
136
+ mergeStrategy: 'replace',
137
+ });
90
138
 
91
- log(color.green, `[sage] ✅ Sage theme setup completed successfully`);
139
+ await generator.generateFile(
140
+ '.devcontainer/docker-compose.override.yml',
141
+ context,
142
+ 'sage',
143
+ `${relativeDevcontainerDir}/docker-compose.override.yml`
144
+ );
145
+ await generator.generateFile(
146
+ '.devcontainer/post-create.sh',
147
+ context,
148
+ 'sage',
149
+ `${relativeDevcontainerDir}/post-create.sh`
150
+ );
151
+ await fs.chmod(path.join(context.cwd, relativeDevcontainerDir, 'post-create.sh'), 0o755);
152
+
153
+ // Unified setup scripts for Sage — shared between Lando, devcontainer and CI/CD
154
+ await generator.generateFile(
155
+ 'server/cmd/setup-sage-php.sh',
156
+ context,
157
+ 'sage',
158
+ 'server/cmd/setup-sage-php.sh'
159
+ );
160
+ await generator.generateFile(
161
+ 'server/cmd/setup-sage-node.sh',
162
+ context,
163
+ 'sage',
164
+ 'server/cmd/setup-sage-node.sh'
165
+ );
166
+ await fs.chmod(path.join(context.cwd, 'server/cmd/setup-sage-php.sh'), 0o755);
167
+ await fs.chmod(path.join(context.cwd, 'server/cmd/setup-sage-node.sh'), 0o755);
168
+
169
+ await generator.mergeWithExistingFile({
170
+ existingFile: `${relativeDevcontainerDir}/devcontainer.json`,
171
+ moduleTemplatePath: '.devcontainer/devcontainer.json',
172
+ context,
173
+ format: 'json',
174
+ moduleName: 'sage',
175
+ mergeStrategy: 'replace',
176
+ });
177
+
178
+ // 8. Lint configs co-located in theme — always installed (IDE/editor support)
179
+ log(color.blue, '[sage] 🔧 Installing lint configurations...');
180
+ await generator.copyFile(
181
+ 'lint/.prettierrc.json',
182
+ 'sage',
183
+ `${relativeThemeDir}/.prettierrc.json`
184
+ );
185
+ if (context.sage_lint_eslint !== false) {
186
+ await generator.copyFile(
187
+ 'lint/eslint.config.mjs',
188
+ 'sage',
189
+ `${relativeThemeDir}/eslint.config.mjs`
190
+ );
191
+ }
192
+ if (context.sage_lint_pint !== false) {
193
+ await generator.copyFile('lint/pint.json', 'sage', `${relativeThemeDir}/pint.json`);
194
+ }
195
+ if (context.sage_lint_stylelint !== false) {
196
+ await generator.copyFile(
197
+ 'lint/.stylelintrc.json',
198
+ 'sage',
199
+ `${relativeThemeDir}/.stylelintrc.json`
200
+ );
201
+ }
202
+
203
+ log(color.green, '[sage] ✅ Advanced Sage setup completed successfully');
204
+ log(color.green, `[sage] ✅ Theme directory: ${relativeThemeDir}`);
205
+ log(color.green, '[sage] ✅ Lando + Devcontainer command parity enabled');
92
206
  } catch (error) {
93
207
  log(color.red, `[sage] ❌ Installation failed: ${error.message}`);
94
208
  throw error;
@@ -126,3 +240,13 @@ async function validateThemeInstallation(themeDir, sageConfig) {
126
240
 
127
241
  log(color.blue, `[sage] ℹ️ Theme info: ${packageJson.name} v${packageJson.version || '1.0.0'}`);
128
242
  }
243
+
244
+ async function isSageThemeInstalled(themeDir) {
245
+ const requiredFiles = ['package.json', 'composer.json', 'theme.json'];
246
+ for (const file of requiredFiles) {
247
+ if (!(await fs.pathExists(path.join(themeDir, file)))) {
248
+ return false;
249
+ }
250
+ }
251
+ return true;
252
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "es5",
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "overrides": [
8
+ { "files": "*.blade.php", "options": { "parser": "html" } },
9
+ { "files": "*.vue", "options": { "parser": "vue" } },
10
+ { "files": "*.scss", "options": { "singleQuote": false } }
11
+ ]
12
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": ["stylelint-config-standard-scss"],
3
+ "rules": {
4
+ "color-hex-length": "short",
5
+ "string-quotes": "double"
6
+ }
7
+ }
@@ -0,0 +1,30 @@
1
+ import js from '@eslint/js';
2
+ import eslintConfigPrettier from 'eslint-config-prettier/flat';
3
+ import prettierPlugin from 'eslint-plugin-prettier';
4
+ import globals from 'globals';
5
+
6
+ export default [
7
+ {
8
+ ignores: ['node_modules/**', 'vendor/**', 'public/build/**'],
9
+ },
10
+ js.configs.recommended,
11
+ {
12
+ files: ['resources/**/*.{js,mjs,ts,vue}'],
13
+ languageOptions: {
14
+ ecmaVersion: 2022,
15
+ sourceType: 'module',
16
+ globals: {
17
+ ...globals.browser,
18
+ ...globals.node,
19
+ },
20
+ },
21
+ plugins: {
22
+ prettier: prettierPlugin,
23
+ },
24
+ rules: {
25
+ 'prettier/prettier': 'error',
26
+ 'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
27
+ },
28
+ },
29
+ eslintConfigPrettier,
30
+ ];
@@ -0,0 +1,11 @@
1
+ {
2
+ "preset": "psr12",
3
+ "rules": {
4
+ "array_syntax": {
5
+ "syntax": "short"
6
+ },
7
+ "binary_operator_spaces": {
8
+ "default": "single_space"
9
+ }
10
+ }
11
+ }
@@ -2,7 +2,7 @@ export default [
2
2
  {
3
3
  type: 'confirm',
4
4
  name: 'enable_sage',
5
- message: 'Enable Sage theme?',
5
+ message: 'Enable Sage theme (advanced setup is automatic)?',
6
6
  default: true,
7
7
  },
8
8
  {
@@ -13,4 +13,25 @@ export default [
13
13
  default: '11',
14
14
  when: (answers) => answers.enable_sage,
15
15
  },
16
+ {
17
+ type: 'confirm',
18
+ name: 'sage_lint_eslint',
19
+ message: 'Sage: enable ESLint for JS/TS/Vue?',
20
+ default: true,
21
+ when: (answers) => answers.enable_sage && answers.enable_lint,
22
+ },
23
+ {
24
+ type: 'confirm',
25
+ name: 'sage_lint_stylelint',
26
+ message: 'Sage: enable Stylelint for CSS/SCSS?',
27
+ default: true,
28
+ when: (answers) => answers.enable_sage && answers.enable_lint,
29
+ },
30
+ {
31
+ type: 'confirm',
32
+ name: 'sage_lint_pint',
33
+ message: 'Sage: enable Pint for PHP?',
34
+ default: true,
35
+ when: (answers) => answers.enable_sage && answers.enable_lint,
36
+ },
16
37
  ];
@@ -0,0 +1,7 @@
1
+ {
2
+ "dockerComposeFile": [
3
+ "docker-compose.yml",
4
+ "docker-compose.override.yml"
5
+ ],
6
+ "postCreateCommand": "bash .devcontainer/setup.sh && bash .devcontainer/post-create.sh"
7
+ }
@@ -0,0 +1,6 @@
1
+ services:
2
+ wordpress:
3
+ environment:
4
+ SAGE_THEME_DIR: /workspace/content/themes/{{projectName}}
5
+ ports:
6
+ - "3009:3009"
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env bash
2
+ # Sage devcontainer post-create — delegates to unified setup scripts.
3
+ # Invoked from: devcontainer.json postCreateCommand.
4
+ set -euo pipefail
5
+
6
+ PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.."; pwd)"
7
+
8
+ bash "${PROJECT_ROOT}/server/cmd/setup-sage-php.sh"
9
+ bash "${PROJECT_ROOT}/server/cmd/setup-sage-node.sh"
10
+
11
+ echo "Sage post-create bootstrap completed."
@@ -1,63 +1,61 @@
1
+ services:
2
+ build:
3
+ type: node:24
4
+ ssl: true
5
+ build:
6
+ - bash /app/server/cmd/setup-sage-node.sh
7
+ scanner: false
1
8
  events:
2
9
  post-start:
3
- - cd /app/content/themes/{{projectName}} && composer install --no-interaction --no-progress --optimize-autoloader
4
- - cd /app/content/themes/{{projectName}} && yarn install && yarn build
10
+ - bash ./server/cmd/setup-sage-php.sh
11
+ - bash ./server/cmd/setup-sage-node.sh
5
12
  - wp theme activate {{projectName}}
6
- - cd /app/content/themes/{{projectName}} && wp acorn optimize:clear && wp acorn optimize
13
+ - cd /app/content/themes/{{projectName}} && wp acorn optimize:clear
7
14
  tooling:
8
- theme-build:
15
+ dev:
16
+ service: build
17
+ description: Run the Sage/Vite development server
18
+ cmd: npm run dev --prefix /app/content/themes/{{projectName}}
19
+ theme-bootstrap:
9
20
  service: appserver
10
- description: "Build the Sage theme"
21
+ description: Install theme dependencies
11
22
  dir: /app/content/themes/{{projectName}}
12
23
  cmd:
13
- - composer install --no-interaction --no-progress --optimize-autoloader
14
- - yarn install
15
- - yarn build
24
+ - appserver: bash /app/server/cmd/setup-sage-php.sh
25
+ - build: bash /app/server/cmd/setup-sage-node.sh
26
+ theme-build:
27
+ service: build
28
+ description: Build the Sage theme
29
+ cmd: npm run build --prefix /app/content/themes/{{projectName}}
16
30
  theme-lint:
31
+ service: build
32
+ description: Lint the Sage theme (JS/TS/Vue)
33
+ cmd: npm run lint --prefix /app/content/themes/{{projectName}}
34
+ {{#if enable_lint}}
35
+ pint:
17
36
  service: appserver
18
- description: "Lint the Sage theme"
37
+ description: Lint PHP in the Sage theme
19
38
  dir: /app/content/themes/{{projectName}}
20
- cmd:
21
- - yarn lint
22
- - pint --test
23
- theme-dev:
24
- service: appserver
25
- description: "Dev the Sage theme"
39
+ cmd: ./vendor/bin/pint
40
+ stylelint:
41
+ service: build
42
+ description: Lint CSS/SCSS in the Sage theme
43
+ cmd: npx stylelint --fix "resources/**/*.{css,scss}" --config /app/content/themes/{{projectName}}/.stylelintrc.json
26
44
  dir: /app/content/themes/{{projectName}}
27
- cmd:
28
- - yarn dev
29
- acorn-make:
45
+ {{/if}}
46
+ acorn:
30
47
  service: appserver
31
- description: Create new Acorn classes interactively
48
+ description: Run Acorn artisan commands
32
49
  dir: /app/content/themes/{{projectName}}
33
- cmd: wp acorn make:$ACORN_TYPE $ACORN_NAME
50
+ cmd: wp acorn $ACORN_COMMAND
34
51
  options:
35
- type:
52
+ command:
36
53
  passthrough: true
37
54
  alias:
38
- - t
39
- describe: Type of class to create
40
- interactive:
41
- type: list
42
- message: What type of class would you like to create?
43
- choices:
44
- - name: Command (Artisan command)
45
- value: command
46
- - name: Component (View component class)
47
- value: component
48
- - name: Composer (View composer class)
49
- value: composer
50
- - name: Provider (Service provider class)
51
- value: provider
52
- weight: 100
53
- env: ACORN_TYPE
54
- filename:
55
- passthrough: true
56
- alias:
57
- - n
58
- describe: Name of the class to create
55
+ - c
56
+ describe: Acorn command to execute
59
57
  interactive:
60
58
  type: input
61
- message: What is the name of the class?
62
- weight: 200
63
- env: ACORN_NAME
59
+ message: "Acorn command (example: make:component Hero)"
60
+ weight: 100
61
+ env: ACORN_COMMAND
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bash
2
+ # Installs and builds Sage theme Node.js dependencies.
3
+ # Invoked from: Lando (build service build step + post-start), Devcontainer (post-create.sh), CI/CD.
4
+ set -euo pipefail
5
+
6
+ PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
7
+ THEME_DIR="${PROJECT_ROOT}/content/themes/{{projectName}}"
8
+
9
+ if [ ! -d "${THEME_DIR}" ]; then
10
+ echo "Theme directory not found: ${THEME_DIR}" && exit 0
11
+ fi
12
+
13
+ if [ ! -d "${THEME_DIR}/node_modules" ]; then
14
+ echo "Installing Sage theme Node.js dependencies..."
15
+ npm install --prefix "${THEME_DIR}"
16
+ fi
17
+
18
+ if [ ! -f "${THEME_DIR}/public/build/manifest.json" ]; then
19
+ echo "Building Sage theme..."
20
+ npm run build --prefix "${THEME_DIR}"
21
+ fi
22
+
23
+ echo "Sage theme Node.js setup complete."
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env bash
2
+ # Installs Sage theme PHP dependencies via Composer.
3
+ # Invoked from: Lando (post-start), Devcontainer (post-create.sh), CI/CD.
4
+ set -euo pipefail
5
+
6
+ PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
7
+ THEME_DIR="${PROJECT_ROOT}/content/themes/{{projectName}}"
8
+
9
+ if [ ! -d "${THEME_DIR}" ]; then
10
+ echo "Theme directory not found: ${THEME_DIR}" && exit 0
11
+ fi
12
+
13
+ if [ -f "${THEME_DIR}/vendor/autoload.php" ]; then
14
+ echo "Sage PHP dependencies already installed, skipping."
15
+ exit 0
16
+ fi
17
+
18
+ echo "Installing Sage theme PHP dependencies..."
19
+ composer install \
20
+ --working-dir="${THEME_DIR}" \
21
+ --no-interaction \
22
+ --no-progress \
23
+ --optimize-autoloader
24
+ echo "Sage PHP dependencies installed."
@@ -1,3 +1,25 @@
1
- { "name": "{{projectName}}/wordpress", "type": "wordpress-theme", "license": "MIT", "description": "{{projectDescription}}",
2
- "authors": [ { "name": "{{author}}", "email": "{{authorEmail}}" } ], "support": { }, "require": {
3
- "php": ">={{phpVersion}}", "roots/acorn": "^5.0", "log1x/sage-directives": "^2.0" } }
1
+ {
2
+ "description": "{{projectDescription}}",
3
+ "authors": [
4
+ {
5
+ "name": "{{author}}",
6
+ "email": "{{authorEmail}}"
7
+ }
8
+ ],
9
+ "require": {
10
+ "php": ">={{phpVersion}}",
11
+ "log1x/sage-directives": "^2.0",
12
+ "log1x/acf-composer": "^2.0 || ^3.0"
13
+ },
14
+ "require-dev": {
15
+ "laravel/pint": "^1.21"
16
+ },
17
+ "scripts": {
18
+ "lint": [
19
+ "./vendor/bin/pint --test"
20
+ ],
21
+ "acorn:optimize": [
22
+ "wp acorn optimize"
23
+ ]
24
+ }
25
+ }
@@ -1,3 +1,15 @@
1
- { "name": "{{projectName}}", "author": "{{author}}", "description": "{{projectDescription}}",
2
- "version": "{{projectVersion}}", "license": "MIT", "repository": { "type": "git", "url": "{{gitRepository}}"
3
- } }
1
+ {
2
+ "author": "{{author}}",
3
+ "description": "{{projectDescription}}",
4
+ "version": "{{projectVersion}}",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "{{gitRepository}}"
9
+ },
10
+ "scripts": {
11
+ "dev": "vite",
12
+ "build": "vite build",
13
+ "lint": "eslint resources --ext .js,.ts,.vue"
14
+ }
15
+ }
@@ -1,13 +1,55 @@
1
- import fs from 'fs'; import { defineConfig } from 'vite'; import tailwindcss from
2
- '@tailwindcss/vite'; import laravel from 'laravel-vite-plugin'; import { wordpressPlugin,
3
- wordpressThemeJson } from '@roots/vite-plugin'; export default defineConfig({ base:
4
- '/app/content/themes/{{projectName}}/', plugins: [ tailwindcss(), laravel({ input: [
5
- 'resources/css/app.css', 'resources/js/app.js', 'resources/css/editor.css',
6
- 'resources/js/editor.js', ], refresh: true, watch: { usePolling: true, interval: 1000, ignored:
7
- ['node_modules', 'public/build/hot'], }, }), wordpressPlugin(), // Generate the theme.json file in
8
- the public/build/assets directory // based on the Tailwind config and the theme.json file from base
9
- theme folder wordpressThemeJson({ disableTailwindColors: false, disableTailwindFonts: false,
10
- disableTailwindFontSizes: false, }), ], resolve: { alias: { '@scripts': '/resources/js', '@styles':
11
- '/resources/css', '@fonts': '/resources/fonts', '@images': '/resources/images', }, }, server: {
12
- https: { key: fs.readFileSync('/certs/cert.key'), cert: fs.readFileSync('/certs/cert.crt'), }, host:
13
- true, port: 3009, hmr: { host: 'localhost', protocol: 'wss' }, }, });
1
+ import { wordpressPlugin, wordpressThemeJson } from '@roots/vite-plugin';
2
+ import tailwindcss from '@tailwindcss/vite';
3
+ import fs from 'fs';
4
+ import laravel from 'laravel-vite-plugin';
5
+ import { defineConfig } from 'vite';
6
+
7
+ export default defineConfig({
8
+ base: '/app/content/themes/{{projectName}}/',
9
+ plugins: [
10
+ tailwindcss(),
11
+ laravel({
12
+ input: [
13
+ 'resources/css/app.css',
14
+ 'resources/js/app.js',
15
+ 'resources/css/editor.css',
16
+ 'resources/js/editor.js',
17
+ ],
18
+ refresh: true,
19
+ watch: {
20
+ usePolling: true,
21
+ interval: 1000,
22
+ ignored: ['node_modules', 'public/build/hot'],
23
+ },
24
+ }),
25
+ wordpressPlugin(),
26
+ wordpressThemeJson({
27
+ disableTailwindColors: false,
28
+ disableTailwindFonts: false,
29
+ disableTailwindFontSizes: false,
30
+ }),
31
+ ],
32
+ resolve: {
33
+ alias: {
34
+ '@scripts': '/resources/js',
35
+ '@styles': '/resources/css',
36
+ '@fonts': '/resources/fonts',
37
+ '@images': '/resources/images',
38
+ '@blocks': '/app/Blocks',
39
+ '@fields': '/app/Fields',
40
+ },
41
+ },
42
+ server: {
43
+ https: {
44
+ key: fs.readFileSync('/certs/cert.key'),
45
+ cert: fs.readFileSync('/certs/cert.crt'),
46
+ },
47
+ host: true,
48
+ port: 5173,
49
+ strictPort: true,
50
+ hmr: {
51
+ host: 'localhost',
52
+ protocol: 'wss',
53
+ },
54
+ },
55
+ });