Part of [ED-24401] [ED-24401]: https://elementor.atlassian.net/browse/ED-24401?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!--start_gitstream_placeholder--> ### ✨ PR Description ## 1. Problem & Context Implements CSS-to-atomic conversion infrastructure (ED-24441) to bridge LLM-generated raw CSS with Elementor's style schema. Replaces style PropValue system with a server-side CSS parser that converts declarations to native styles, storing unconvertible rules as `custom_css`. Defers real telemetry to Phase 4. ## 2. What Changed (Where) | Component | Purpose | |-----------|---------| | **PHP Backend** | `css-converter/` module: parser, registry factory, REST API endpoint at `POST /elementor/v1/css-to-atomic` | | **TypeScript Frontend** | `convert-css-to-atomic.ts`: client calling REST API; integrated into `build-composition` and `configure-element` tools | | **Removed** | `STYLE_SCHEMA_URI` and style PropValue schema resources; `styles-schema` MCP resource; `stylePropertiesToChange` parameter | | **Updated Prompts** | Docs now describe styling as raw CSS `property: value` maps instead of PropValue objects | ## 3. How It Works 1. **Ingestion**: LLM provides raw CSS (`color: red; gap: 4px`) via `style` parameter (build-composition, configure-element) 2. **Conversion**: `convertCssToAtomic()` calls REST endpoint; PHP parses, blocks malicious patterns (behavior, javascript:, expression()), routes to registry 3. **Registry Pattern**: `Converter_Registry` iterates converters in order; first to claim property wins (try-until-success); Phase 1 uses no-ops, fallback to `customCss` 4. **Result**: Returns split `{ props: {...}, customCss: "..." }`; unconvertible declarations preserved; exceptions caught and reported to `Conversion_Failure_Reporter` ## 4. Risks - **Naive CSS parsing**: splits on `;` and first `:` only—breaks on values with colons/semicolons (mitigated: acceptable for LLM input per comments) - **Security**: blocks hardcoded patterns (behavior, -moz-binding, javascript:, expression()) but may miss edge cases in untrusted input - **Phase 1 limitation**: all converters are no-ops; nothing actually converts until real converters added (intentional per coverage test design) - **No telemetry yet**: null reporter swallows failures; real channel/payload undefined for Phase 4 _Generated by LinearB AI and added by gitStream._ <sub>AI-generated content may contain inaccuracies. Please verify before using. 💡 **Tip:** You can customize your AI Description using **Guidelines** [Learn how](https://docs.gitstream.cm/automation-actions/#describe-changes)</sub> <!--end_gitstream_placeholder--> --------- Co-authored-by: Netanel Baba <50736016+Ntnelbaba@users.noreply.github.com>
6.5 KiB
Vendored
Agent and cloud environment guide
Short reference for Cursor Cloud and other non-interactive agents. For full human onboarding use CONTRIBUTING.md and tests/test-environment-setup.md.
Choosing a WordPress environment
| Runtime | When to use | Ports / URL |
|---|---|---|
| wp-lite-env (Docker) | Same stack as Playwright in CI (.github/workflows/playwright.yml). Full PHP/MySQL containers, two WP instances. |
http://localhost:8888 and http://localhost:8889 |
WP Playground CLI (npm run wp-playground) |
No Docker. WordPress in WASM; quick editor and blueprint-driven setup. Default listen address matches local Playwright dev base URL. | http://127.0.0.1:9400 |
wp-env (npm run wp-env, .wp-env.json) |
Alternative Docker-based @wordpress/env setup used in other workflows and docs. |
See @wordpress/env defaults after wp-env start |
Use wp-lite-env when you need Docker parity with CI (full Playwright against 8888/8889, setup.sh, theme on disk). Use WP Playground when Docker is missing or broken; it is sufficient for many editor checks and aligns with tests/playwright/playwright.config.ts local localDevServer / localTestServer (both http://127.0.0.1:9400 when not in CI). WP Playground still uses a blueprint (tests/playwright/blueprints/local.json) so PHP/WordPress versions may differ from tests/playwright/.playwright-wp-lite-env.json.
Cursor Cloud specifics
System requirements (typical VM image)
- Node.js version from .nvmrc (via nvm; PATH in
~/.bashrc) - PHP >= 7.4 with extensions: mbstring, xml, zip, curl, dom, bcmath (see composer.json)
- Composer 2.x
- Docker only if you use wp-lite-env or wp-env (often needs fuse-overlayfs and iptables-legacy in nested setups)
PATH
The image may ship a system Node under /exec-daemon/node that does not match .nvmrc. If installs or engines fail, confirm which node points at the nvm-managed binary.
Common commands
| Action | Command |
|---|---|
| Install deps | npm ci --ignore-scripts && composer install |
| Build packages | npm run build:packages |
| Build styles | npx grunt styles |
| Build scripts | npx grunt scripts |
| Full dev watch | npm run watch |
| Lint JS/TS (root) | npx eslint . |
| Lint JS/TS (packages) | cd packages && npx eslint . --report-unused-disable-directives-severity error |
| Lint PHP | vendor/bin/phpcs --extensions=php --standard=./ruleset.xml . |
| Jest (main) | npm run test:jest |
| Jest (packages) | npm run test:packages |
| All Jest | npm run test |
| Fast DB-less PHPUnit (single/few files) | tests/phpunit/run-unit.sh <test-file.php> [<test-file.php> ...] [--filter <pattern>] |
Fast DB-less PHPUnit for local dev
tests/phpunit/run-unit.sh runs a small set of PHPUnit files without WordPress or MySQL for a quick inner loop. It uses tests/phpunit/unit-bootstrap.php, which only defines ABSPATH and registers an Elementor\ autoloader (same name->path transform as includes/autoloader.php), and ignores the project phpunit.xml. Pass any number of test-*.php files (added to a generated testsuite, which sidesteps PHPUnit's test-*.php ↔ Test_* filename/classname assumption) plus optional pass-through args like --filter.
tests/phpunit/run-unit.sh tests/phpunit/elementor/modules/atomic-widgets/css-converter/test-css-converter.php
tests/phpunit/run-unit.sh tests/phpunit/.../test-css-converter.php --filter test_convert
Only works for tests whose subjects don't touch WordPress at load/run time. Tests needing WordPress/MySQL (e.g. REST endpoints with act_as_admin/WP_REST_Server, or anything pulling Style_Schema) must use the full suite (npm run test:setup:playwright env, or the wp-lite-env setup below).
wp-lite-env (Docker): full setup
Non-interactive one-shot (skips container cleanup prompt):
SKIP_CONFIRMATION=true npm run env:setup
That script installs deps, builds, downloads Hello Elementor, runs npm run start-local-server (8888 and 8889), then npm run test:setup:playwright. Do not start only 8888 and then run npm run test:setup:playwright alone; package.json expects both ports.
Manual equivalent: see tests/test-environment-setup.md (steps: npm run start-local-server then npm run test:setup:playwright).
If Docker is not running on the VM yet, a typical pattern is sudo dockerd &>/tmp/dockerd.log & in the background, then ensure the Docker socket is usable for the agent user (for example sudo chmod 666 /var/run/docker.sock in disposable environments only). For a manual plugin tree under ./build/ without the setup script, flows often use composer install --no-scripts --no-dev && composer dump-autoload && npx grunt copy, then npm run setup-templates, then start both wp-lite-env instances (see npm run start-local-server in package.json).
Admin: http://localhost:8888/wp-admin/ — user admin, password password (see test environment doc).
WP Playground CLI (no Docker)
After npm ci (or full install per repo):
npm run wp-playground
Wait until the CLI prints that WordPress is running, then open http://127.0.0.1:9400 . This flow was smoke-tested with the same CLI flags as package.json wp-playground in a clean agent-style environment without Docker.
For CI-style mounted build output use npm run wp-playground:ci (expects ./build).
Gotchas
npm run lintruns ESLint at the repo root and in theelementor-packagesworkspace (npm run lint -w elementor-packages); both must pass.- PHPCS may report warnings without errors on the current tree; treat policy from maintainers, not only the exit summary.
composer installpost-install can run php-scoper (Twig prefixing); dev dependencyhumbug/php-scopermust be present for a full dev install.- For a production-like plugin tree under
./build, many flows usecomposer install --no-scripts --no-devfirst, thennpx grunt copy. Dev dependencies must be restored afterward withcomposer install. - package.json
enginesand.nvmrcdefine the Node version; keep them aligned when troubleshooting. - Husky pre-commit runs
lint-stagedwithNODE_OPTIONS=--max-old-space-size=8192(see .husky/pre-commit).