@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,26 @@
1
+ # Job reutilizável — Semantic Release
2
+ #
3
+ # Como usar no .gitlab-ci.yml principal:
4
+ #
5
+ # include:
6
+ # - local: '.gitlab/ci/release.yml'
7
+ #
8
+ # stages:
9
+ # - release
10
+ #
11
+ # Variáveis necessárias (Settings → CI/CD → Variables):
12
+ # GITLAB_TOKEN — Personal/Project Access Token com scope "api"
13
+ # NPM_TOKEN — Token npm (omita se o projeto não publicar no npm)
14
+
15
+ semantic-release:
16
+ stage: release
17
+ image: node:{{nodeVersion}}-alpine
18
+ rules:
19
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
20
+ before_script:
21
+ - npm ci
22
+ script:
23
+ - npx semantic-release
24
+ variables:
25
+ GITLAB_TOKEN: $GITLAB_TOKEN
26
+ NPM_TOKEN: $NPM_TOKEN
@@ -1,4 +1,8 @@
1
- #!/bin/sh
2
- . "$(dirname "$0")/_/husky.sh"
3
-
4
- npx --no -- commitlint --edit "$1"
1
+ echo "🔍 Validating commit message..."
2
+ if command -v lando >/dev/null 2>&1 && lando info >/dev/null 2>&1; then
3
+ echo "🐳 Using Lando environment..."
4
+ lando commitlint --edit "$1"
5
+ else
6
+ echo "🏠 Using local environment..."
7
+ npx --no commitlint --edit "$1"
8
+ fi
@@ -1,6 +1,3 @@
1
- #!/bin/sh
2
- . "$(dirname "$0")/_/husky.sh"
3
-
4
1
  echo "🔍 Running pre-commit checks..."
5
2
 
6
3
  # Check if lint-staged config exists
@@ -1,4 +1,4 @@
1
- { "scripts": { "prepare": "husky install", "commit": "lando git-cz" }, "devDependencies": {
2
- "@commitlint/cli": "^18.4.3", "@commitlint/config-conventional": "^18.4.3", "@commitlint/prompt":
3
- "^18.4.3", "commitizen": "^4.3.0", "conventional-changelog-cli": "^4.1.0", "husky": "^8.0.3",
4
- "lint-staged": "^15.2.1" } }
1
+ { "scripts": { "prepare": "husky", "commit": "lando git-cz" }, "devDependencies": {
2
+ "@commitlint/cli": "^19.7.1", "@commitlint/config-conventional": "^19.7.1", "@commitlint/prompt":
3
+ "^19.5.0", "commitizen": "^4.3.1", "husky": "^9.0.11",
4
+ "lint-staged": "^15.5.0" } }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "settings": {
3
- "git.inputValidation": "always",
3
+ "git.inputValidation": true,
4
4
  "git.inputValidationSubjectLength": 72,
5
5
  "git.inputValidationLength": 72,
6
6
  "git.verboseCommit": true,
@@ -0,0 +1,21 @@
1
+ {
2
+ "extends": ["@commitlint/config-conventional"],
3
+ "rules": {
4
+ "type-enum": [
5
+ 2,
6
+ "always",
7
+ ["feat", "fix", "docs", "style", "refactor", "perf", "test", "chore", "ci", "build", "revert"]
8
+ ],
9
+ "type-case": [2, "always", "lower-case"],
10
+ "type-empty": [2, "never"],
11
+ "scope-case": [2, "always", "lower-case"],
12
+ "subject-case": [2, "never", ["sentence-case", "start-case", "pascal-case", "upper-case"]],
13
+ "subject-empty": [2, "never"],
14
+ "subject-full-stop": [2, "never", "."],
15
+ "header-max-length": [2, "always", 72],
16
+ "body-leading-blank": [1, "always"],
17
+ "body-max-line-length": [2, "always", 100],
18
+ "footer-leading-blank": [1, "always"],
19
+ "footer-max-line-length": [2, "always", 100]
20
+ }
21
+ }
@@ -1,36 +1,26 @@
1
- # Ignore node_modules and build directories
1
+ # Node & Composer
2
2
  node_modules/
3
- dist/
4
- build/
5
-
6
- # Ignore WordPress core
7
- wp/
8
- wp-content/plugins/
9
- wp-content/mu-plugins/
10
- wp-content/uploads/
11
- wp-content/upgrade/
3
+ vendor/
12
4
 
13
- content/plugins/
5
+ # Development module folders — each has its own lint config
6
+ content/themes/
14
7
  content/mu-plugins/
8
+ content/plugins/
9
+
10
+ # WordPress core and uploads
11
+ wp/
15
12
  content/uploads/
16
13
  content/upgrade/
14
+ content/cache/
17
15
 
18
- # Ignore Composer dependencies
19
- vendor/
16
+ # Build outputs
17
+ public/build/
18
+ dist/
19
+ .lando/
20
20
 
21
- # Ignore logs and environment
22
- *.log
21
+ # Env and logs
23
22
  .env
24
23
  .env.*
25
-
26
- # Ignore IDE and system files
27
- .DS_Store
28
- Thumbs.db
29
-
30
- # Ignore Lando config cache
31
- .lando/
32
-
33
- # Ignore anything temporary
24
+ *.log
34
25
  *.tmp
35
- *.temp
36
26
  *.bak
@@ -1,29 +1,18 @@
1
1
  {
2
2
  "semi": true,
3
3
  "singleQuote": true,
4
- "trailingComma": "es5",
5
4
  "tabWidth": 2,
6
5
  "printWidth": 100,
6
+ "trailingComma": "es5",
7
7
  "bracketSpacing": true,
8
- "arrowParens": "avoid",
9
8
  "overrides": [
10
9
  {
11
- "files": ["*.scss", "*.css", "*.sass"],
12
- "options": {
13
- "singleQuote": false
14
- }
15
- },
16
- {
17
- "files": ["*.json", "*.yml", "*.yaml"],
18
- "options": {
19
- "tabWidth": 2
20
- }
10
+ "files": ["*.yml", "*.yaml"],
11
+ "options": { "tabWidth": 2 }
21
12
  },
22
13
  {
23
- "files": "*.html",
24
- "options": {
25
- "htmlWhitespaceSensitivity": "ignore"
26
- }
14
+ "files": "*.md",
15
+ "options": { "proseWrap": "always" }
27
16
  }
28
17
  ]
29
18
  }
@@ -1,14 +1,81 @@
1
+ import path from 'path';
2
+
3
+ import fs from 'fs-extra';
4
+
5
+ /**
6
+ * Builds the lint-staged entries object from active development modules.
7
+ * Each dev module contributes globs pointing to its own directory.
8
+ */
9
+ function buildLintStagedEntries(context) {
10
+ const entries = {};
11
+
12
+ // Infra: YAML, JSON, Markdown at root (never touching module folders)
13
+ entries['*.{yml,yaml}'] = ['prettier --write'];
14
+ entries['*.{json,md}'] = ['prettier --write'];
15
+
16
+ // Sage
17
+ if (context.enable_sage) {
18
+ const dir = `content/themes/${context.projectName}`;
19
+ if (context.sage_lint_eslint !== false) {
20
+ entries[`${dir}/resources/**/*.{js,ts,vue,mjs}`] = ['eslint --fix'];
21
+ }
22
+ if (context.sage_lint_stylelint !== false) {
23
+ entries[`${dir}/resources/**/*.{css,scss}`] = ['stylelint --fix'];
24
+ }
25
+ if (context.sage_lint_pint !== false) {
26
+ entries[`${dir}/app/**/*.php`] = ['pint'];
27
+ }
28
+ }
29
+
30
+ // MU-Plugin
31
+ if (context.enable_mu_plugin) {
32
+ const dir = `content/mu-plugins/${context.mu_plugin_name || `${context.projectName}-core`}`;
33
+ if (context.mu_plugin_lint_eslint !== false) {
34
+ entries[`${dir}/resources/**/*.{js,ts}`] = ['eslint --fix'];
35
+ }
36
+ if (context.mu_plugin_lint_pint !== false) {
37
+ entries[`${dir}/src/**/*.php`] = ['pint'];
38
+ }
39
+ }
40
+
41
+ // Plugin
42
+ if (context.enable_plugin) {
43
+ const dir = `content/plugins/${context.plugin_name || `${context.projectName}-plugin`}`;
44
+ if (context.plugin_lint_eslint !== false) {
45
+ entries[`${dir}/resources/**/*.{js,ts}`] = ['eslint --fix'];
46
+ }
47
+ if (context.plugin_lint_pint !== false) {
48
+ entries[`${dir}/src/**/*.php`] = ['pint'];
49
+ }
50
+ }
51
+
52
+ // Blank Theme
53
+ if (context.enable_blank_theme) {
54
+ const dir = `content/themes/${context.blank_theme_name || `${context.projectName}-theme`}`;
55
+ if (context.blank_theme_lint_eslint !== false) {
56
+ entries[`${dir}/src/**/*.{js,ts}`] = ['eslint --fix'];
57
+ }
58
+ if (context.blank_theme_lint_stylelint !== false) {
59
+ entries[`${dir}/src/**/*.{css,scss}`] = ['stylelint --fix'];
60
+ }
61
+ if (context.blank_theme_lint_pint !== false) {
62
+ entries[`${dir}/src/**/*.php`] = ['pint'];
63
+ }
64
+ }
65
+
66
+ return entries;
67
+ }
68
+
1
69
  export async function setupModule(context, generator) {
2
- await generator.copyFile('eslint.config.mjs', 'lint');
3
- await generator.copyFile('.prettierrc.json', 'lint');
70
+ if (!context.enable_lint) return;
4
71
 
72
+ // Root developer tooling (always present when lint is enabled)
73
+ await generator.copyFile('.commitlintrc.json', 'lint');
5
74
  await generator.copyFile('.prettierrc.json', 'lint');
6
75
  await generator.copyFile('.prettierignore', 'lint');
7
76
 
8
- await generator.copyFile('pint.json', 'lint');
9
-
10
- if (context.enable_stylelint) {
11
- await generator.copyFile('.stylelintrc.json', 'lint');
12
- await generator.copyFile('.stylelintignore', 'lint');
13
- }
77
+ // Compose .lintstagedrc.json from active modules
78
+ const entries = buildLintStagedEntries(context);
79
+ const lintStagedPath = path.join(generator.cwd, '.lintstagedrc.json');
80
+ await fs.outputFile(lintStagedPath, JSON.stringify(entries, null, 2) + '\n');
14
81
  }
@@ -3,14 +3,7 @@ export default [
3
3
  {
4
4
  type: 'confirm',
5
5
  name: 'enable_lint',
6
- message: 'Enable linting and formatting tools (ESLint + Prettier)?',
6
+ message: 'Enable developer tooling (Husky, commitlint, Prettier for infra files)?',
7
7
  default: true,
8
8
  },
9
- {
10
- type: 'confirm',
11
- name: 'enable_stylelint',
12
- message: 'Include Stylelint config?',
13
- default: true,
14
- when: answers => answers.enable_lint,
15
- },
16
9
  ];
@@ -1,10 +1,5 @@
1
1
  tooling:
2
- eslint:
2
+ commitlint:
3
3
  service: appserver
4
- cmd: yarn eslint
5
- prettier:
6
- service: appserver
7
- cmd: yarn prettier
8
- stylelint:
9
- service: appserver
10
- cmd: yarn stylelint **/*.{css,scss,vue}
4
+ description: Validate commit message format
5
+ cmd: npx commitlint --edit
@@ -1,4 +1,4 @@
1
- { "scripts": { "format": "prettier --write .", "lint": "lando eslint . --ext .js,.ts", "lint:fix":
2
- "lando eslint . --ext .js,.ts --fix" }, "devDependencies": { "globals": "^16.3.0",
3
- "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.30.1", "eslint": "^8.56.0",
4
- "eslint-config-prettier": "^8.10.0", "eslint-plugin-prettier": "^4.2.1", "prettier": "^2.8.8" } }
1
+ { "scripts": { "format": "prettier --write .", "lint": "lando eslint .", "lint:fix":
2
+ "lando eslint . --fix" }, "devDependencies": { "globals": "^16.3.0",
3
+ "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.30.1", "eslint": "^9.30.1",
4
+ "eslint-config-prettier": "^10.1.5", "eslint-plugin-prettier": "^5.3.1", "prettier": "^3.6.2" } }
@@ -3,9 +3,9 @@
3
3
  "editor.defaultFormatter": "esbenp.prettier-vscode",
4
4
  "editor.formatOnSave": false,
5
5
  "editor.codeActionsOnSave": {
6
- "source.fixAll": true,
7
- "source.fixAll.eslint": true,
8
- "source.organizeImports": true
6
+ "source.fixAll": "explicit",
7
+ "source.fixAll.eslint": "explicit",
8
+ "source.organizeImports": "explicit"
9
9
  },
10
10
  "prettier.requireConfig": true,
11
11
  "prettier.useEditorConfig": true,
@@ -0,0 +1,49 @@
1
+ import path from 'path';
2
+
3
+ import fs from 'fs-extra';
4
+
5
+ import { log, color } from '../../lib/utils/logger.js';
6
+
7
+ export async function setupModule(context, generator) {
8
+ const pluginName = context.mu_plugin_name || `${context.projectName}-core`;
9
+ const pluginDir = `content/mu-plugins/${pluginName}`;
10
+ const absolutePluginDir = path.join(generator.cwd, pluginDir);
11
+
12
+ log(color.blue, `[mu-plugin] 📂 Scaffolding MU plugin: ${pluginDir}`);
13
+
14
+ // 1. Ensure directory exists
15
+ await fs.ensureDir(absolutePluginDir);
16
+
17
+ // 2. Generate main plugin entry file
18
+ await generator.generateFile(
19
+ 'plugin.php',
20
+ { ...context, mu_plugin_name: pluginName },
21
+ 'mu-plugin',
22
+ `${pluginDir}/${pluginName}.php`
23
+ );
24
+
25
+ // 3. Generate composer.json
26
+ await generator.generateFile(
27
+ 'composer.json',
28
+ { ...context, mu_plugin_name: pluginName },
29
+ 'mu-plugin',
30
+ `${pluginDir}/composer.json`
31
+ );
32
+
33
+ // 4. Create src/ scaffold
34
+ await fs.ensureFile(path.join(absolutePluginDir, 'src', '.gitkeep'));
35
+
36
+ // 5. Lint configs co-located in plugin — always installed (IDE/editor support)
37
+ log(color.blue, '[mu-plugin] 🔧 Installing lint configurations...');
38
+ await generator.copyFile('lint/.prettierrc.json', 'mu-plugin', `${pluginDir}/.prettierrc.json`);
39
+ await generator.copyFile('lint/pint.json', 'mu-plugin', `${pluginDir}/pint.json`);
40
+ if (context.mu_plugin_lint_eslint === true) {
41
+ await generator.copyFile(
42
+ 'lint/eslint.config.mjs',
43
+ 'mu-plugin',
44
+ `${pluginDir}/eslint.config.mjs`
45
+ );
46
+ }
47
+
48
+ log(color.green, `[mu-plugin] ✅ MU plugin scaffolded: ${pluginDir}`);
49
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "es5",
5
+ "printWidth": 100,
6
+ "tabWidth": 2
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/**', 'dist/**'],
9
+ },
10
+ js.configs.recommended,
11
+ {
12
+ files: ['resources/**/*.{js,mjs,ts}'],
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
+ }
@@ -0,0 +1,29 @@
1
+ export default [
2
+ {
3
+ type: 'confirm',
4
+ name: 'enable_mu_plugin',
5
+ message: 'Enable MU Plugin scaffold?',
6
+ default: false,
7
+ },
8
+ {
9
+ type: 'input',
10
+ name: 'mu_plugin_name',
11
+ message: 'MU Plugin slug (used as directory name):',
12
+ default: (answers) => `${answers.projectName || 'wordpress'}-core`,
13
+ when: (answers) => answers.enable_mu_plugin,
14
+ },
15
+ {
16
+ type: 'confirm',
17
+ name: 'mu_plugin_lint_pint',
18
+ message: 'MU Plugin: enable Pint for PHP?',
19
+ default: true,
20
+ when: (answers) => answers.enable_mu_plugin && answers.enable_lint,
21
+ },
22
+ {
23
+ type: 'confirm',
24
+ name: 'mu_plugin_lint_eslint',
25
+ message: 'MU Plugin: enable ESLint for JS/TS?',
26
+ default: false,
27
+ when: (answers) => answers.enable_mu_plugin && answers.enable_lint,
28
+ },
29
+ ];
@@ -0,0 +1,15 @@
1
+ tooling:
2
+ {{#if enable_lint}}
3
+ mu-pint:
4
+ service: appserver
5
+ description: Lint PHP in the MU plugin
6
+ dir: /app/content/mu-plugins/{{mu_plugin_name}}
7
+ cmd: ./vendor/bin/pint
8
+ {{#if mu_plugin_lint_eslint}}
9
+ mu-eslint:
10
+ service: build
11
+ description: Lint JS/TS in the MU plugin
12
+ dir: /app/content/mu-plugins/{{mu_plugin_name}}
13
+ cmd: npx eslint --fix resources/
14
+ {{/if}}
15
+ {{/if}}
@@ -0,0 +1,14 @@
1
+ {
2
+ "description": "{{projectDescription}} — MU Plugin",
3
+ "autoload": {
4
+ "psr-4": {
5
+ "App\\MuPlugins\\": "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: {{mu_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
+ }
@@ -1 +1,15 @@
1
- { "require-dev": { "laravel/pint": "^1.23", "phpunit/phpunit": "^9.5" } }
1
+ {
2
+ "require-dev": {
3
+ "laravel/pint": "^1.29",
4
+ "phpunit/phpunit": "^12.5",
5
+ "phpstan/phpstan": "^2.1",
6
+ "phpstan/extension-installer": "^1.4",
7
+ "szepeviktor/phpstan-wordpress": "^2.0",
8
+ "php-stubs/wordpress-stubs": "^6.8"
9
+ },
10
+ "config": {
11
+ "allow-plugins": {
12
+ "phpstan/extension-installer": true
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,45 @@
1
+ import path from 'path';
2
+
3
+ import fs from 'fs-extra';
4
+
5
+ import { log, color } from '../../lib/utils/logger.js';
6
+
7
+ export async function setupModule(context, generator) {
8
+ const pluginName = context.plugin_name || `${context.projectName}-plugin`;
9
+ const pluginDir = `content/plugins/${pluginName}`;
10
+ const absolutePluginDir = path.join(generator.cwd, pluginDir);
11
+
12
+ log(color.blue, `[plugin] 📂 Scaffolding plugin: ${pluginDir}`);
13
+
14
+ // 1. Ensure directory exists
15
+ await fs.ensureDir(absolutePluginDir);
16
+
17
+ // 2. Generate main plugin entry file
18
+ await generator.generateFile(
19
+ 'plugin.php',
20
+ { ...context, plugin_name: pluginName },
21
+ 'plugin',
22
+ `${pluginDir}/${pluginName}.php`
23
+ );
24
+
25
+ // 3. Generate composer.json
26
+ await generator.generateFile(
27
+ 'composer.json',
28
+ { ...context, plugin_name: pluginName },
29
+ 'plugin',
30
+ `${pluginDir}/composer.json`
31
+ );
32
+
33
+ // 4. Create src/ scaffold
34
+ await fs.ensureFile(path.join(absolutePluginDir, 'src', '.gitkeep'));
35
+
36
+ // 5. Lint configs co-located in plugin — always installed (IDE/editor support)
37
+ log(color.blue, '[plugin] 🔧 Installing lint configurations...');
38
+ await generator.copyFile('lint/.prettierrc.json', 'plugin', `${pluginDir}/.prettierrc.json`);
39
+ await generator.copyFile('lint/pint.json', 'plugin', `${pluginDir}/pint.json`);
40
+ if (context.plugin_lint_eslint === true) {
41
+ await generator.copyFile('lint/eslint.config.mjs', 'plugin', `${pluginDir}/eslint.config.mjs`);
42
+ }
43
+
44
+ log(color.green, `[plugin] ✅ Plugin scaffolded: ${pluginDir}`);
45
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "es5",
5
+ "printWidth": 100,
6
+ "tabWidth": 2
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/**', 'dist/**'],
9
+ },
10
+ js.configs.recommended,
11
+ {
12
+ files: ['resources/**/*.{js,mjs,ts}'],
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
+ }
@@ -0,0 +1,29 @@
1
+ export default [
2
+ {
3
+ type: 'confirm',
4
+ name: 'enable_plugin',
5
+ message: 'Enable Plugin scaffold?',
6
+ default: false,
7
+ },
8
+ {
9
+ type: 'input',
10
+ name: 'plugin_name',
11
+ message: 'Plugin slug (used as directory name):',
12
+ default: (answers) => `${answers.projectName || 'wordpress'}-plugin`,
13
+ when: (answers) => answers.enable_plugin,
14
+ },
15
+ {
16
+ type: 'confirm',
17
+ name: 'plugin_lint_pint',
18
+ message: 'Plugin: enable Pint for PHP?',
19
+ default: true,
20
+ when: (answers) => answers.enable_plugin && answers.enable_lint,
21
+ },
22
+ {
23
+ type: 'confirm',
24
+ name: 'plugin_lint_eslint',
25
+ message: 'Plugin: enable ESLint for JS/TS?',
26
+ default: false,
27
+ when: (answers) => answers.enable_plugin && answers.enable_lint,
28
+ },
29
+ ];