Skip to content

Commit 52d58f0

Browse files
authored
Merge pull request #5 from lightspeedwp/audit/updates
Standardize PHP naming conventions and improve theme generator
2 parents afbd263 + 9ddbb3b commit 52d58f0

18 files changed

+486
-400
lines changed

.github/README.md

Lines changed: 88 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,96 @@
11
---
2-
title: GitHub Configuration
3-
description: GitHub-specific configuration and workflow files
4-
category: Project
5-
type: Index
2+
title: Block Theme Scaffold
3+
description: Generate a block theme for WordPress
4+
category: Tool
5+
type: Generate
66
audience: Developers
7-
date: 2025-12-01
7+
date: 2026-01-10
88
---
99

10-
# GitHub Configuration
10+
## Getting Started
11+
12+
Advanced documentation on the theme generation is provided [here](../docs/GENERATE_THEME.md)
13+
14+
### Visual Studio Code
15+
16+
This tool is meant to be used on its own, and not inside a WordPress install. We suggest creating a "tools" folder at the root of your hosting applications folder (where all the sites are housed).
17+
You can then clone your it to your tools folder, and re-use it everytime you need a new theme.
18+
19+
### Prerequisites
20+
Make sure you have the following installed:
21+
22+
- Node.js (check .nvmrc for the required version)
23+
- Composer (for PHP dependencies)
24+
- A WordPress environment with a database.
25+
26+
### Installation Steps
27+
28+
#### 1. Clone the Repository
29+
```bash
30+
git clone https://github.com/lightspeedwp/block-theme-scaffold.git
31+
cd block-theme-scaffold
32+
```
33+
34+
#### 2. Install Dependencies
35+
```bash
36+
# Install Node.js dependencies
37+
npm install
38+
39+
# Install PHP/Composer dependencies
40+
composer install
41+
```
42+
43+
#### 3. Generate your theme
44+
45+
**Interactive prompts (easiest)**
46+
47+
Add the folder to the chat to your IDE, and select the "Generate Theme Agent" from the agent dropdown,
48+
49+
Then simply ask the agent to generate a theme, it will prompt you for the basic placeholder replacements.
50+
51+
```bash
52+
Please generate a theme for me
53+
```
54+
55+
If you cannot see it in the dropdown, add the js file to the chat as well.
56+
Agent Location: `scripts/agents/generate-theme.agent.js`
57+
58+
```bash
59+
Please use the attached agent and folder, and generate a theme for me.
60+
```
1161

12-
This directory contains GitHub-specific configuration files for the {{theme_name}} theme.
1362

14-
## Contents
1563

64+
**CLI Mode**
65+
```bash
66+
node scripts/generate-theme.js --slug my-theme --name "My Theme" --author "Your Name" ...
67+
```
68+
69+
**JSON Mode**
70+
```bash
71+
node scripts/generate-theme.js --config theme-config.json
72+
```
73+
74+
#### 4. Copy the theme to your site.
75+
Copy the `output-theme` directory that will be generated in your repository and copy and paste that in your `themes` directory.
76+
77+
Make sure to rename it to the same value as your Theme Slug.
78+
79+
### Available Scripts
80+
- `npm run build` - Build for development
81+
- `npm run watch` - Watch for changes during development
82+
- `npm run lint` - Run linters
83+
- `npm test` - Run tests
84+
85+
86+
## Importing Design Tokens
87+
88+
🚧 **Coming Soon** 🚧
89+
90+
## GitHub Configuration
91+
This directory contains GitHub-specific configuration files for the {{theme_name}} theme.
92+
93+
### Contents
1694
- **agents/** - AI agent configurations for automated development tasks
1795
- **instructions/** - Development instructions and guidelines for AI tools
1896
- **projects/** - Active Copilot projects and in-progress work
@@ -23,31 +101,14 @@ This directory contains GitHub-specific configuration files for the {{theme_name
23101
- `copilot-tasks.md` - Copilot task definitions and specifications
24102
- `custom-instructions.md` - Custom AI instructions for Copilot
25103

26-
## Documentation
27-
104+
### Documentation
28105
Permanent user-facing documentation is stored in the [docs/](../docs/) folder. See [docs/FILE_ORGANIZATION.md](../docs/FILE_ORGANIZATION.md) for the complete file organization guide.
29106

30-
## Workflows
107+
### Workflows
31108

32109
| Workflow | Description |
33110
|----------|-------------|
34111
| `ci-cd.yml` | Main CI/CD pipeline (lint, test, security audit, E2E) |
35112
| `code-quality.yml` | Code coverage, quality gates, bundle analysis |
36113
| `deploy-wporg.yml` | Automated WordPress.org theme directory deployment |
37114
| `release.yml` | Version bumping, changelog generation, releases |
38-
39-
## Purpose
40-
41-
These files enable:
42-
43-
- Automated build and test workflows
44-
- Code coverage tracking with Codecov
45-
- Quality gates for PRs
46-
- AI-assisted development with context-specific instructions
47-
- Consistent code review and quality checks
48-
- Automated release and deployment processes
49-
- WordPress.org theme directory deployment
50-
51-
## Usage
52-
53-
These files are automatically used by GitHub Actions and compatible AI development tools. They are excluded from theme distribution packages via `.distignore`.

.github/schemas/theme-config.schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,13 @@
459459
"minimum": 20,
460460
"maximum": 200
461461
},
462+
"archive_excerpt_length": {
463+
"type": "integer",
464+
"description": "Number of words in archive/listing excerpts",
465+
"default": 40,
466+
"minimum": 20,
467+
"maximum": 200
468+
},
462469
"excerpt_more": {
463470
"type": "string",
464471
"description": "Excerpt 'more' text",

CHANGELOG.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,68 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616

1717
## [Unreleased]
1818

19+
### Changed
20+
21+
- **PHP Naming Convention Standardization**: All theme functions and hooks now use `{{theme_slug|phpCase}}` placeholder filter for consistent snake_case naming
22+
- Updated `functions.php` - theme setup, asset enqueue, and utility functions
23+
- Updated `inc/block-patterns.php` - pattern registration functions
24+
- Updated `inc/block-styles.php` - block style registration functions
25+
- Updated `inc/template-functions.php` - template helper functions
26+
- All function names now follow WordPress coding standards (e.g., `my_theme_setup()` instead of `my-theme_setup()`)
27+
28+
- **Asset Handle Unification**: Standardized all asset handles to use `{{theme_slug}}` prefix
29+
- Style handles: `{{theme_slug}}-style`, `{{theme_slug}}-editor-style`
30+
- Script handles: `{{theme_slug}}-script`, `{{theme_slug}}-editor-script`
31+
- Image size names: `{{theme_slug}}-featured`, `{{theme_slug}}-thumbnail`, `{{theme_slug}}-gallery`
32+
33+
- **Theme Generator Improvements**: Enhanced placeholder replacement system in `scripts/generate-theme.js`
34+
- Added support for multiple filter types: `upper`, `snakeCase`, `phpCase`, `pascalCase`, `camelCase`
35+
- Consolidated placeholder replacement into single-pass regex for better performance
36+
- Improved error handling and validation for theme slug and author URI
37+
- Better error messages for invalid inputs
38+
- Protocol validation for author URIs (must start with http:// or https://)
39+
40+
- **theme.json Structure Updates**: Improved typography configuration
41+
- Font families now use proper object structure with `slug`, `fontFamily`, and `name` properties
42+
- Changed from array of strings to array of objects for better WordPress compatibility
43+
- Removed redundant top-level `color` setting
44+
45+
- **Test Suite Modernization**: Updated all PHPUnit tests to reflect new naming conventions
46+
- Updated test discovery to use `Test_` prefix in `phpunit.xml`
47+
- Fixed block style registry method calls to use `get_registered_styles_for_block()`
48+
- Updated theme.json version assertion from 2 to 3
49+
- Aligned test structure with WordPress coding standards
50+
1951
### Added
2052

53+
- **New Placeholder Variables**:
54+
- `{{logo_width}}` - Logo width dimension (default: 250)
55+
- `{{logo_height}}` - Logo height dimension (default: 100)
56+
- `{{archive_excerpt_length}}` - Excerpt length for archive/listing pages (default: 40)
57+
- `{{content_width_num}}` - Numeric content width without units
58+
59+
- **Schema Enhancements**: Added `archive_excerpt_length` configuration option
60+
- Type: integer, default: 40, range: 20-200
61+
- Controls excerpt length specifically for archive and listing pages
62+
63+
- **Documentation Improvements**: Enhanced `.github/README.md`
64+
- Clearer installation instructions
65+
- Multiple theme generation methods (Interactive, CLI, JSON)
66+
- Available scripts reference
67+
- Prerequisites section
68+
- Better structure and organization
69+
70+
### Fixed
71+
72+
- **Content Width Type Bug**: Fixed critical bug where `$GLOBALS['content_width']` was incorrectly set as string instead of integer
73+
- Changed from `'{{content_width_px}}'` to `{{content_width_num}}`
74+
- Now properly passes integer value to WordPress for embed/media width calculations
75+
- Fixes PHPUnit test assertions for `assertIsInt($content_width)`
76+
77+
- **Placeholder Type Consistency**: Improved type handling in theme generator
78+
- Added string coercion for `content_width_num` calculation to prevent errors when config value is numeric
79+
- Better handling of missing or invalid placeholder values
80+
2181
- Automated mustache variable registry scan, update, and reporting:
2282
- Recursively scans all source, config, and documentation files for `{{mustache}}` variables.
2383
- Compares discovered variables to the canonical registry (`scripts/mustache-variables-registry.json`).

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.0
1+
1.0.1

functions.php

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
/**
2020
* Theme setup.
2121
*/
22-
function {{theme_slug}}_setup() {
22+
function {{theme_slug|snakeCase}}_setup() {
2323
// Make theme available for translation.
2424
load_theme_textdomain( '{{theme_slug}}', get_template_directory() . '/languages' );
2525

@@ -37,20 +37,20 @@ function {{theme_slug}}_setup() {
3737
add_editor_style( 'build/css/editor-style.css' );
3838

3939
// Set content width.
40-
$GLOBALS['content_width'] = apply_filters( '{{theme_slug}}_content_width', {{content_width_px}} );
40+
$GLOBALS['content_width'] = apply_filters( '{{theme_slug}}_content_width', {{content_width_num}} );
4141
}
42-
add_action( 'after_setup_theme', '{{theme_slug}}_setup' );
42+
add_action( 'after_setup_theme', '{{theme_slug|snakeCase}}_setup' );
4343

4444
/**
4545
* Enqueue theme assets.
4646
*/
47-
function {{theme_slug}}_enqueue_assets() {
47+
function {{theme_slug|snakeCase}}_enqueue_assets() {
4848
// Main stylesheet.
4949
$asset_file = get_theme_file_path( 'build/css/style.asset.php' );
5050
if ( file_exists( $asset_file ) ) {
5151
$asset = include $asset_file;
5252
wp_enqueue_style(
53-
'{{asset_slug}}-style',
53+
'{{theme_slug}}-style',
5454
get_theme_file_uri( 'build/css/style.css' ),
5555
$asset['dependencies'] ?? array(),
5656
$asset['version'] ?? {{theme_slug|upper}}_VERSION
@@ -62,7 +62,7 @@ function {{theme_slug}}_enqueue_assets() {
6262
if ( file_exists( $js_asset_file ) ) {
6363
$js_asset = include $js_asset_file;
6464
wp_enqueue_script(
65-
'{{asset_slug}}-script',
65+
'{{theme_slug}}-script',
6666
get_theme_file_uri( 'build/js/theme.js' ),
6767
$js_asset['dependencies'] ?? array(),
6868
$js_asset['version'] ?? {{theme_slug|upper}}_VERSION,
@@ -71,23 +71,23 @@ function {{theme_slug}}_enqueue_assets() {
7171

7272
// Set script translations.
7373
wp_set_script_translations(
74-
'{{asset_slug}}-script',
74+
'{{theme_slug}}-script',
7575
'{{theme_slug}}',
7676
get_theme_file_path( 'languages' )
7777
);
7878
}
7979
}
80-
add_action( 'wp_enqueue_scripts', '{{theme_slug}}_enqueue_assets' );
80+
add_action( 'wp_enqueue_scripts', '{{theme_slug|snakeCase}}_enqueue_assets' );
8181

8282
/**
8383
* Enqueue editor assets.
8484
*/
85-
function {{theme_slug}}_enqueue_editor_assets() {
85+
function {{theme_slug|snakeCase}}_enqueue_editor_assets() {
8686
$editor_asset_file = get_theme_file_path( 'build/css/editor-style.asset.php' );
8787
if ( file_exists( $editor_asset_file ) ) {
8888
$editor_asset = include $editor_asset_file;
8989
wp_enqueue_style(
90-
'{{asset_slug}}-editor-style',
90+
'{{theme_slug}}-editor-style',
9191
get_theme_file_uri( 'build/css/editor-style.css' ),
9292
$editor_asset['dependencies'] ?? array(),
9393
$editor_asset['version'] ?? {{theme_slug|upper}}_VERSION
@@ -99,7 +99,7 @@ function {{theme_slug}}_enqueue_editor_assets() {
9999
if ( file_exists( $editor_js_asset_file ) ) {
100100
$editor_js_asset = include $editor_js_asset_file;
101101
wp_enqueue_script(
102-
'{{asset_slug}}-editor-script',
102+
'{{theme_slug}}-editor-script',
103103
get_theme_file_uri( 'build/js/editor.js' ),
104104
$editor_js_asset['dependencies'] ?? array(),
105105
$editor_js_asset['version'] ?? {{theme_slug|upper}}_VERSION,
@@ -108,32 +108,32 @@ function {{theme_slug}}_enqueue_editor_assets() {
108108

109109
// Set script translations for editor.
110110
wp_set_script_translations(
111-
'{{asset_slug}}-editor-script',
111+
'{{theme_slug}}-editor-script',
112112
'{{theme_slug}}',
113113
get_theme_file_path( 'languages' )
114114
);
115115
}
116116
}
117-
add_action( 'enqueue_block_editor_assets', '{{theme_slug}}_enqueue_editor_assets' );
117+
add_action( 'enqueue_block_editor_assets', '{{theme_slug|snakeCase}}_enqueue_editor_assets' );
118118

119119
/**
120120
* Register block pattern categories.
121121
*/
122-
function {{theme_slug}}_register_pattern_categories() {
122+
function {{theme_slug|snakeCase}}_register_pattern_categories() {
123123
$categories = array(
124-
'{{pattern_slug}}-hero' => array( 'label' => __( '{{theme_name}} Hero', '{{theme_slug}}' ) ),
125-
'{{pattern_slug}}-about' => array( 'label' => __( '{{theme_name}} About', '{{theme_slug}}' ) ),
126-
'{{pattern_slug}}-contact' => array( 'label' => __( '{{theme_name}} Contact', '{{theme_slug}}' ) ),
127-
'{{pattern_slug}}-cta' => array( 'label' => __( '{{theme_name}} Call to Action', '{{theme_slug}}' ) ),
128-
'{{pattern_slug}}-gallery' => array( 'label' => __( '{{theme_name}} Gallery', '{{theme_slug}}' ) ),
129-
'{{pattern_slug}}-team' => array( 'label' => __( '{{theme_name}} Team', '{{theme_slug}}' ) ),
124+
'{{theme_slug}}-hero' => array( 'label' => __( '{{theme_name}} Hero', '{{theme_slug}}' ) ),
125+
'{{theme_slug}}-about' => array( 'label' => __( '{{theme_name}} About', '{{theme_slug}}' ) ),
126+
'{{theme_slug}}-contact' => array( 'label' => __( '{{theme_name}} Contact', '{{theme_slug}}' ) ),
127+
'{{theme_slug}}-cta' => array( 'label' => __( '{{theme_name}} Call to Action', '{{theme_slug}}' ) ),
128+
'{{theme_slug}}-gallery' => array( 'label' => __( '{{theme_name}} Gallery', '{{theme_slug}}' ) ),
129+
'{{theme_slug}}-team' => array( 'label' => __( '{{theme_name}} Team', '{{theme_slug}}' ) ),
130130
);
131131

132132
foreach ( $categories as $slug => $args ) {
133133
register_block_pattern_category( $slug, $args );
134134
}
135135
}
136-
add_action( 'init', '{{theme_slug}}_register_pattern_categories' );
136+
add_action( 'init', '{{theme_slug|snakeCase}}_register_pattern_categories' );
137137

138138
/**
139139
* Load theme includes.
@@ -154,25 +154,25 @@ function {{theme_slug}}_register_pattern_categories() {
154154
/**
155155
* Add custom image sizes.
156156
*/
157-
function {{theme_slug}}_add_image_sizes() {
158-
add_image_size( '{{asset_slug}}-featured', {{featured_image_width}}, {{featured_image_height}}, true );
159-
add_image_size( '{{asset_slug}}-thumbnail', {{thumbnail_width}}, {{thumbnail_height}}, true );
160-
add_image_size( '{{asset_slug}}-gallery', {{gallery_image_width}}, {{gallery_image_height}}, true );
157+
function {{theme_slug|snakeCase}}_add_image_sizes() {
158+
add_image_size( '{{theme_slug}}-featured', {{featured_image_width}}, {{featured_image_height}}, true );
159+
add_image_size( '{{theme_slug}}-thumbnail', {{thumbnail_width}}, {{thumbnail_height}}, true );
160+
add_image_size( '{{theme_slug}}-gallery', {{gallery_image_width}}, {{gallery_image_height}}, true );
161161
}
162-
add_action( 'after_setup_theme', '{{theme_slug}}_add_image_sizes' );
162+
add_action( 'after_setup_theme', '{{theme_slug|snakeCase}}_add_image_sizes' );
163163

164164
/**
165165
* Modify excerpt length.
166166
*/
167-
function {{theme_slug}}_excerpt_length( $length ) {
167+
function {{theme_slug|snakeCase}}_excerpt_length( $length ) {
168168
return {{excerpt_length}};
169169
}
170-
add_filter( 'excerpt_length', '{{theme_slug}}_excerpt_length' );
170+
add_filter( 'excerpt_length', '{{theme_slug|snakeCase}}_excerpt_length' );
171171

172172
/**
173173
* Modify excerpt more.
174174
*/
175-
function {{theme_slug}}_excerpt_more( $more ) {
175+
function {{theme_slug|snakeCase}}_excerpt_more( $more ) {
176176
return '{{excerpt_more}}';
177177
}
178-
add_filter( 'excerpt_more', '{{theme_slug}}_excerpt_more' );
178+
add_filter( 'excerpt_more', '{{theme_slug|snakeCase}}_excerpt_more' );

0 commit comments

Comments
 (0)