diff --git a/CHANGELOG.md b/CHANGELOG.md index ee7ba9a..b29fb33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to the Nynaeve theme will be documented in this file. +## [4.1.0] - 2026-10-05 + +### Added + +- `imagewize/cta` `woocommerce` variant: a third button, **Run the Free Store Checkup**, linking to `/woocommerce-checkup/`. It sends visitors and internal link value from every WooCommerce post to the free checkup tool. The checkup tool had stored only 9 scans in 90 days, 5 of them internal test runs. The button is appended **last** on purpose. The block uses `templateLock: "contentOnly"`, and Gutenberg re-syncs placed instances to the template by position (`use-inner-block-template-sync.js`). Inserted mid-list, the new button would make an existing post show the services link twice when opened in the editor. Placed last, an old post gains the checkup button the next time it is opened and saved. +- The `woocommerce-de` variant is unchanged, because the checkup's on-page report is English only. + +### Technical + +- Added `@imwz/wp-pattern-sentinel` as a dev dependency, plus `npm run test:patterns`. It round-trips the fixtures in `tests/sentinel/` through the local editor (`imagewize.test`, Trellis credentials) and reports block-validation errors or content drift. The first fixture, `cta-woocommerce.html`, is the WooCommerce CTA as serialized in posts. `.html` fixtures need Sentinel 1.2.0 or later. + +### Notes + +- **Existing posts don't change on the frontend** until their stored markup is migrated: a static block's saved HTML is what renders. Append the button to placed `is-variant-woocommerce` instances on production with a scripted update (a database export first). Opening and saving a post in the editor also works, one post at a time. + ## [4.0.1] - 2026-09-03 ### Technical diff --git a/package-lock.json b/package-lock.json index 306d1e8..3b8ca62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "classnames": "^2.5.1" }, "devDependencies": { + "@imwz/wp-pattern-sentinel": "^1.2.0", "@roots/vite-plugin": "^2.0.2", "@tailwindcss/vite": "^4.0.9", "@wordpress/icons": "^10.9.0", @@ -30,6 +31,24 @@ "node": ">=6.9.0" } }, + "node_modules/@imwz/wp-pattern-sentinel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@imwz/wp-pattern-sentinel/-/wp-pattern-sentinel-1.2.0.tgz", + "integrity": "sha512-AlUY68LfhHs/a1RbsC7CsExoG0lAdFi+YrZb+XBfltnWb/pv5nUSXCxcYH7Qd1GgzeJ/WbJVwWaWrdWb+lWf5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-yaml": "^4.3.1", + "p-queue": "^8.0.1", + "playwright": "^1.44.0" + }, + "bin": { + "sentinel": "bin/sentinel.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1142,6 +1161,13 @@ "ajv": "^8.8.2" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, "node_modules/baseline-browser-mapping": { "version": "2.11.20", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.20.tgz", @@ -1381,6 +1407,13 @@ "node": ">=6" } }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -1523,6 +1556,29 @@ "dev": true, "license": "MIT" }, + "node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -2001,6 +2057,36 @@ "node": ">=18" } }, + "node_modules/p-queue": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", + "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", + "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -2054,6 +2140,35 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.63.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz", + "integrity": "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.63.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/playwright-core": { + "version": "1.63.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.63.0.tgz", + "integrity": "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/postcss": { "version": "8.5.26", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", diff --git a/package.json b/package.json index c98811c..1661b43 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,11 @@ "translate:update": "for file in ./resources/lang/*.po; do wp i18n update-po ./resources/lang/nynaeve.pot $file; done", "translate:compile": "npm run translate:mo && npm run translate:js", "translate:js": "wp i18n make-json ./resources/lang --pretty-print", - "translate:mo": "wp i18n make-mo ./resources/lang ./resources/lang" + "translate:mo": "wp i18n make-mo ./resources/lang ./resources/lang", + "test:patterns": "sentinel --trellis --trellis-dir=../imagewize.com/trellis --site=imagewize.com tests/sentinel/" }, "devDependencies": { + "@imwz/wp-pattern-sentinel": "^1.2.0", "@roots/vite-plugin": "^2.0.2", "@tailwindcss/vite": "^4.0.9", "@wordpress/icons": "^10.9.0", diff --git a/readme.txt b/readme.txt index 55b75a2..9ff5f55 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: jasperfrumau Requires at least: 6.6 Tested up to: 6.9 Requires PHP: 8.3 -Stable tag: 4.0.1 +Stable tag: 4.1.0 License: MIT License License URI: https://opensource.org/licenses/MIT @@ -24,6 +24,9 @@ Export the database first and verify each dry-run count before dropping --dry-ru == Changelog == += 4.1.0 - 10/05/26 = +* FEATURE: The WooCommerce CTA variant gains a third button, Run the Free Store Checkup, linking to /woocommerce-checkup/. It is appended last so existing posts re-sync cleanly when opened in the editor. Already-published posts need their stored markup updated to show it on the frontend. + = 4.0.1 - 09/03/26 = * TECHNICAL: npm dependencies updated - tailwindcss and @tailwindcss/vite 4.3.1 to 4.3.3, laravel-vite-plugin 3.1.0 to 3.2.0, vite 8.0.16 to 8.2.2, plus transitive dependency bumps. No code changes. diff --git a/resources/js/blocks/cta/block.json b/resources/js/blocks/cta/block.json index 617fe7f..61afd4f 100644 --- a/resources/js/blocks/cta/block.json +++ b/resources/js/blocks/cta/block.json @@ -2,7 +2,7 @@ "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 3, "name": "imagewize/cta", - "version": "1.0.0", + "version": "1.1.0", "title": "CTA", "category": "nynaeve/cta", "icon": "megaphone", diff --git a/resources/js/blocks/cta/templates.js b/resources/js/blocks/cta/templates.js index 7f1a9f2..a224d21 100644 --- a/resources/js/blocks/cta/templates.js +++ b/resources/js/blocks/cta/templates.js @@ -14,7 +14,7 @@ /** * Build an InnerBlocks template from a variant's copy. * - * The first button is the filled call, the second the outline one. Variants + * The first button is the filled call, every later one outline. Variants * that lead with a different call (performance-partnership) express that by * ordering `buttons`, not by changing the structure. */ @@ -155,6 +155,10 @@ export const VARIANTS = { buttons: [ ['Get a Quote', '/contact/?service=woocommerce'], ['View WooCommerce Services', '/services/woocommerce/'], + // Must stay last: contentOnly re-syncs placed instances to this + // template by position, so a button inserted mid-list would shift + // existing ones and duplicate the services link on open. + ['Run the Free Store Checkup', '/woocommerce-checkup/'], ], }), }, diff --git a/style.css b/style.css index e02cb9d..7c58b3a 100644 --- a/style.css +++ b/style.css @@ -2,7 +2,7 @@ Theme Name: Nynaeve Theme URI: https://imagewize.com Description: Modern WordPress theme built on Sage 11 with reusable custom blocks using WordPress native tools and the Roots.io stack. -Version: 4.0.1 +Version: 4.1.0 Author: Jasper Frumau Author URI: https://magewize.com Text Domain: nynaeve diff --git a/tests/sentinel/cta-woocommerce.html b/tests/sentinel/cta-woocommerce.html new file mode 100644 index 0000000..f207ee2 --- /dev/null +++ b/tests/sentinel/cta-woocommerce.html @@ -0,0 +1,48 @@ + + +
We build and optimize WooCommerce stores for SMEs — from custom checkout flows and payment integrations to performance tuning and ongoing maintenance. Fixed-price quotes available.
+ + + +