Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
143 changes: 126 additions & 17 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,94 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Core Principles

### Skills-First Workflow

**EVERY user request follows this sequence:**

Request → Load Skills → Gather Context → Execute

Skills contain critical workflows and protocols not in base context.
Loading them first prevents missing key instructions.

### Planning

When creating plans, always save them to: ./claude/plans/YYYY-MM-DD-<topic>.md
Never use the default plan location. Use the ./claude/plans/ directory.

### Context Management Strategy

**Central AI should conserve context to extend pre-compaction capacity**:

- Delegate file explorations and low-lift tasks to sub-agents
- Reserve context for coordination, user communication, and strategic decisions
- For straightforward tasks with clear scope: skip heavy orchestration, execute directly

**Sub-agents should maximize context collection**:

- Sub-agent context windows are temporary
- After execution, unused capacity = wasted opportunity
- Instruct sub-agents to read all relevant files, load skills, and gather examples

### Routing Decision

**Direct Execution**:

- Simple/bounded task with clear scope
- Single-component changes
- Quick fixes and trivial modifications

**Sub-Agent Delegation**:

- Complex/multi-phase implementations
- Tasks requiring specialized domain expertise
- Work that benefits from isolated context

**Master Orchestrator**:

- Ambiguous requirements needing research
- Architectural decisions with wide impact
- Multi-day features requiring session management

### Operational Protocols

#### Agent Coordination

**Parallel** (REQUIRED when applicable):

- Multiple Task tool invocations in single message
- Independent tasks execute simultaneously
- Bash commands run in parallel

**Sequential** (ENFORCE for dependencies):

- Database → API → Frontend
- Research → Planning → Implementation
- Implementation → Testing → Security

#### Quality Self-Checks

Before finalizing code, verify:

- All inputs have validation
- Authentication/authorization checks exist
- All external calls have error handling
- Import paths verified against existing codebase examples

### Coding Best Practices

**Priority Order** (when trade-offs arise):
Correctness > Maintainability > Performance > Brevity

#### Task Complexity Assessment

Before starting, classify:

- **Trivial** (single file, obvious fix) → execute directly
- **Moderate** (2-5 files, clear scope) → brief planning then execute
- **Complex** (architectural impact, ambiguous requirements) → full research first

Match effort to complexity. Don't over-engineer trivial tasks or under-plan complex ones.

## Project Overview

Expand All @@ -11,35 +99,55 @@ Gravity PDF is a WordPress plugin that generates PDF documents from Gravity Form
### JavaScript

```bash
yarn dev # Start webpack dev server with hot reload
yarn build # Production webpack build
yarn test:js # Run Jest unit tests
yarn dev # Start webpack dev server with hot reload
yarn dev:build # One-shot webpack build without watching
yarn build # Production webpack build
yarn test:js # Run Jest unit tests
yarn test:js:watch # Run Jest in watch mode
yarn test:js -- tests/js-unit/react/sagas/fontManager.test.js # Run single test file
yarn test:js -- --testNamePattern="test name" # Run single test by name
yarn lint:js # ESLint check
yarn lint:css # Sass/CSS lint check
yarn format # Auto-fix JS/CSS/PHP formatting
yarn lint:js # ESLint check
yarn lint:js --fix # Auto-fix ESLint errors (e.g. JSDoc alignment)
yarn lint:css # Sass/CSS lint check
yarn format # Auto-fix JS/CSS/PHP formatting
```

### PHP

```bash
npm run test:php # Run PHPUnit in Docker (wp-env required)
npm run test:php -- --filter TestClassName # Run single test class
npm run test:php -- --filter testMethod # Run single test method
npm run test:php:multisite # Run multisite PHPUnit tests
yarn test:php # Run PHPUnit in Docker (`yarn wp-env:integration start` required)
yarn test:php -- --filter TestClassName # Run single test class
yarn test:php -- --filter testMethod # Run single test method
yarn test:php:multisite # Run multisite PHPUnit tests
composer lint # PHPCS check
composer lint:fix # PHPCS auto-fix
```

PHP tests run inside a Docker container via `wp-env` — you cannot run PHPUnit directly. Start the environment first with `yarn wp-env start`.
PHP tests run inside a Docker container via `wp-env` — you cannot run PHPUnit directly. Start the environment first with `yarn wp-env:integration start`.

### E2E Tests (Playwright)

```bash
yarn wp-env:e2e start && yarn wp-env:e2e:permalinks start # Start dedicated E2E environment (port 8702 and 8703)
yarn test:e2e # Run all Playwright tests (headless)
yarn test:e2e:debug # Open Playwright UI for interactive debugging
```

E2E tests live in `tests/playwright/` and are split into two projects:
- `core/` — tests against the standard environment (port 8702, plain permalinks)
- `permalinks/` — tests against an environment with pretty permalinks (port 8703, started automatically)

Artifacts (screenshots, traces) are written to `tmp/artifacts/`.

### Environment

```bash
yarn wp-env start # Start Docker WordPress dev environment
yarn wp-env stop # Stop Docker environment
yarn start # Start environment + hot reload dev server
yarn wp-env start # Start dev environment (port 8700)
yarn wp-env:integration start # Start PHP test environment (port 8701)
yarn wp-env:e2e start # Start E2E test environment (port 8702)
yarn wp-env:e2e:permalinks start # Start E2E test environment with pretty permalinks enabled (port 8703)
yarn wp-env stop # Stop the default dev environment
yarn start # Start dev environment + hot reload dev server
```

## Architecture
Expand Down Expand Up @@ -80,11 +188,12 @@ Legacy jQuery code coexists with the React app; they are separate bundles and do

- **PHP tests**: `tests/phpunit/` mirrors `src/` structure. Extends `WP_UnitTestCase`. Mock data in `tests/phpunit/unit-tests/Mocks/`.
- **JS tests**: `tests/js-unit/` mirrors React source structure. Uses Jest + Enzyme. Coverage threshold: 75%.
- **E2E tests**: `tests/e2e/` uses TestCafe against a running WordPress instance.
- **E2E tests (Playwright)**: `yarn test:e2e` — config at `tools/playwright/config.ts`. Use `yarn test:e2e:playwright` for the interactive UI mode.

### Key Constraints

- PRs must target the `development` branch (not `main`)
- Each PR should contain a single commit
- Minimum PHP 7.3 compatibility required
- jQuery is an external (provided by WordPress); never bundle it
- Run `composer prefix` after adding new Composer dependencies to namespace them via php-scoper
- Run `composer prefix` after adding new Composer dependencies to namespace them via php-scoper
8 changes: 4 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Add a valid Gravity Forms license key. To run PHPUnit locally you will need an Elite License.
GF_LICENSE=00000000000000000000000000000000
WP_BASE_URL=http://localhost
WP_ENV_TESTS_PORT=8889
# Enable AI Translations
# Usage:
# composer run translate
POTOMATIC_OPENAI_API_KEY=
6 changes: 3 additions & 3 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.cache
build
node_modules
.cache
build
node_modules
vendor
14 changes: 13 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,19 @@ module.exports = {
rules: {
'no-alert': 'off',
'jest/no-done-callback': 'off',
camelcase: 'off',
'camelcase': 'off',
'jsdoc/empty-tags': ['off', { tags: ['package'] }],
'@typescript-eslint/no-unused-vars': 'off'
},
settings: {
jsdoc: {
mode: 'closure',
},
"import/resolver": {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
"typescript": {}
}
},
};
14 changes: 1 addition & 13 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,16 +1,4 @@
/.coveralls.yml export-ignore
/.eslintrc export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.github export-ignore
/.docker export-ignore
/jest.config.js export-ignore
/node_modules export-ignore
/phpcs.xml.dist export-ignore
/phpcompat.xml.dist export-ignore
/phpunit.xml.dist export-ignore
/.env.example export-ignore
/tests export-ignore
/tmp export-ignore

*.sh eol=lf
*.sh eol=lf
73 changes: 21 additions & 52 deletions .github/workflows/coding-standards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,92 +10,59 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
cancel-in-progress: true


jobs:
# Runs PHP coding standards checks.
#
# Violations are reported inline with annotations.
#
# Performs the following steps:
# - Checks out the repository.
# - Configures caching for Composer.
# - Sets up PHP.
# - Logs debug information.
# - Installs Composer dependencies (from cache if possible).
# - Logs PHP_CodeSniffer debug information.
# - Runs PHPCS on the full codebase with warnings suppressed.
# - Runs PHPCS on the `tests` directory without warnings suppressed.
# Only run this action if a Pull Request contains the label 'run-tests'
check_for_string_in_pull_request_comment:
name: Should workflow run?
runs-on: ubuntu-latest
steps:
- if: ${{ github.event_name == 'pull_request' && ! contains(github.event.pull_request.labels.*.name, 'run-tests') }}
uses: action-pack/cancel@v1

phpcs:
name: PHP coding standards
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
tools: composer, cs2pr
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Log debug information
run: |
php --version
composer --version

- name: Add auth details for private composer packages
run: composer config http-basic.composer.gravity.io ${{ secrets.GF_LICENSE }} http://localhost

- name: Install Composer dependencies
run: |
composer install --prefer-dist --no-suggest --no-progress --no-ansi --no-interaction --no-scripts
echo "${PWD}/vendor/bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Log PHPCS debug information
run: composer run lint -- -i
run: composer run phpcs:lint .

- name: Run PHP compatibility tests
run: composer run lint -- --standard=phpcompat.xml.dist -q --report=checkstyle | cs2pr

- name: Run PHPCS on all plugin files
run: composer run lint -- -q -n --report=checkstyle | cs2pr

# Runs the JavaScript coding standards checks.
#
# Performs the following steps:
# - Checks out the repository.
# - Logs debug information about the runner container.
# - Installs NodeJS
# - Sets up caching for NPM.
# - Logs updated debug information.
# _ Installs NPM dependencies using install-changed to hash the `package.json` file.
# - Run the Run ESLint checks.
run: composer run phpcs:compatibility .

jshint:
name: JavaScript coding standards
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Setup Node JS
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT

- name: Cache node modules
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-

- name: Log debug information
run: |
npm --version
Expand All @@ -106,8 +73,10 @@ jobs:
locale -a

- name: Install Dependencies
if: steps.cache-nodemodules.outputs.cache-hit != 'true'
run: yarn install
run: yarn install --frozen-lockfile

- name: Run ESLint
run: yarn lint:js

- name: Run CSS Lint
run: yarn lint:css
16 changes: 3 additions & 13 deletions .github/workflows/deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Setup PHP
uses: shivammathur/setup-php@v2
Expand All @@ -25,22 +25,12 @@ jobs:
uses: devops-actions/action-get-tag@v1.0.2

- name: Setup Node JS
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'

- name: General debug information
run: |
npm --version
node --version
yarn --version
curl --version
git --version
php --version
composer --version

- name: Gravity PDF Build
run: bash ./bin/build.sh $SOURCE_TAG
run: bash ./tools/release/build.sh $SOURCE_TAG
env:
SOURCE_TAG: ${{steps.tag.outputs.tag}}

Expand Down
Loading
Loading