=== CanAI ===
Contributors: ihsanberahim
Tags: page builder, tailwind css, alpine.js, twig, woocommerce
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 1.68.23
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.txt

Build single, semantic-HTML pages powered by Tailwind CSS, Alpine.js, and Lucide icons, with WooCommerce support.

== Description ==

CanAI lets you author a WordPress page or reusable template as one semantic-HTML document,
templated with Twig, styled with Tailwind CSS, and made interactive with Alpine.js and Lucide
icons. Templates can target archives, singular content, and WooCommerce shop/cart/checkout/account
screens.

It also ships a Model Context Protocol (MCP) server so AI agents can create and edit templates,
pages, and settings programmatically, mirroring everything available in the admin UI.

Key features:

* Single-file HTML/CSS/JS authoring per page or template, rendered through Twig.
* Self-hosted Tailwind CSS, Alpine.js, and Lucide icon assets (no third-party CDN
  dependency by default).
* WooCommerce-aware template types (shop, product, cart, checkout, my-account, and more).
* Multilingual content overrides via Polylang integration.
* MCP server for AI-agent-driven template/page/settings management.
* Export/import and snapshot tooling for backing up and restoring template content.

== Installation ==

1. Upload the `wpcanai` folder to the `/wp-content/plugins/` directory, or install the plugin
   through the WordPress plugins screen directly.
2. Activate the plugin through the "Plugins" screen in WordPress.
3. Go to the CanAI menu in wp-admin to create your first template or page.

== Frequently Asked Questions ==

= Does this plugin load anything from a third-party CDN? =

No. Tailwind CSS, Alpine.js, and the bundled icon libraries are served from the plugin's own
`assets/lib/` directory by default. CDN delivery is available as an explicit opt-in for icon
libraries only.

= Does CanAI work with WooCommerce? =

Yes. CanAI ships template types for shop, product, cart, checkout, my-account, and related
WooCommerce endpoints, along with a WooCommerce-aware template context.

== Changelog ==

= 1.68.23 =
* Fix: Keep the WordPress.org stable tag in sync with the plugin version.

= 1.68.18 =
* MCP scan reports semantic landmarks with missing or invalid `Type / Short Label` Twig navigation comments.
* Tweak: Structure displays only concise Atomic Design navigation comments and omits ordinary developer comments.

= 1.68.16 =
* Fix: Typed singular rendering, asset preparation, and diagnostics consistently use the queried post rather than a configured delegate, and author archive helpers safely reject deleted user IDs.

= 1.68.15 =
* Feature: Typed singular templates expose a safe `post.author` surface, enriched post queries accept `wpcanai_include: author`, and Twig provides `author_url()` and `author_posts_url()` helpers.

= 1.68.14 =
* AI Agent → Skills now leads with copyable prompts that ask an AI client to install the essential canai-mcp and canai-prepare skills. Specialized canai-blocks, canai-replicate, and high-risk canai-yolo remain explicit opt-ins, with manual terminal commands available as a fallback.

= 1.68.13 =
* Tweak: Publish box shows "CanAI Template: Saved/Unsaved" with a document icon, matching the Status row.

= 1.68.12 =
* Tweak: Codes Guide search has equal space above and below the input.

= 1.68.11 =
* Tweak: Template types can no longer be created or deleted in wp-admin. Assign the plugin-seeded types only.

= 1.68.10 =
* Tweak: CanAI templates are no longer publicly permalinked (no /wpcanai_template/ URL or edit-screen permalink row). Internal slugs still work for Twig includes.

= 1.68.9 =
* Tweak: Codes Guide closes from the header × only; the footer Close button is gone.

= 1.68.8 =
* Tweak: Codes Guide search sits flush under the modal header when sticky.

= 1.68.7 =
* Tweak: Structure Refresh sits at the bottom of the meta box, after the outline.

= 1.68.6 =
* Tweak: Structure hides decorative --- separators in comment labels.

= 1.68.5 =
* Tweak: Structure lists line numbers first so they stay easy to scan.

= 1.68.4 =
* Tweak: Structure uses a WordPress secondary Refresh button instead of an icon-only control.

= 1.68.3 =
* Tweak: Structure sits immediately below Publish on post.php.

= 1.68.2 =
* Tweak: on post.php, the Structure outline is a side meta box next to Publish (always visible). The standalone editor keeps the slide-out Structure button.

= 1.68.1 =
* Tweak: on post.php, Saved and CanAI Preview sit in the Publish box; the redundant “Editing …” toolbar and WordPress Preview Changes are gone. The standalone editor page is unchanged.

= 1.68.0 =
* New: the CanAI editor (HTML/CSS/JS tabs, Structure, History, Format, Codes Guide, Preview) now lives on the WordPress edit screen for templates and Twig pages; Publish/Update saves code and post fields together.
* New: Twig pages open on the classic edit screen instead of the block editor.
* Changed: the standalone CanAI Editor page shares its markup and saver with post.php.
* Removed: the automatic post.php → CanAI Editor redirect.

= 1.67.5 =
* Tweak: the post.php / post-new.php bounce to the CanAI editor is commented out so
  templates and Twig pages stay on the native WordPress screen. The redirect function
  is unchanged; restore the two `add_action` lines to turn it back on.

= 1.67.4 =
* Refactor: post.php notice copy/URL logic (`wpcanai_secondary_editor_notice_data()`) moves out of
  `canai.php` into `WPCanAI\Admin\EditorSurfaces::notice_data()`, per code review. `canai.php` keeps
  only the global lookup and capability check; the class method now has unit test coverage.
* Refactor: a redundant guard in `EditorSurfaces::should_skip_redirect()` is removed (an empty
  action string can never match the trash/untrash/delete check, so the extra condition was a no-op).

= 1.67.3 =
* Fix: WooCommerce products that already have CanAI markup get an Edit with CanAI
  side box and an info notice on the product screen. The product editor is not
  redirected, so price, stock, and variations stay visible.
* Fix: opening post.php via the existing no_wpcanai_redirect escape hatch now
  explains that HTML, CSS, and JavaScript are edited in the CanAI editor.

= 1.67.2 =
* Fix: the per-upgrade maintenance runs on `init` instead of `admin_init`. The stale compiled
  builds it guards against are served to anonymous visitors, where `admin_init` never fires, so a
  site updated by WP-CLI or auto-update kept serving them until someone opened wp-admin.
* Fix: the Tailwind source-epoch bump is now the one-time migration it was meant to be, applied
  only when upgrading from a version below 1.67.1. It previously fired on every release, dropping
  every site from inline compiled CSS to the runtime Play CDN on each update.
* Fix: `wpcanai/write-page`'s `css` slot gets the protections the same meta already had through
  `write-meta` — a snapshot before the write, `confirm_truncate` on a destructive shrink, and an
  optional `expected_hash` lock. `_canai_css` has no post revisions behind it, so an over-writing
  call was unrecoverable.
* Fix: the page-body emptiness test in the asset path matches the render path again, so the two
  cannot disagree about whether a body is Twig.
* Refactor: the raw HTML/CSS/JS capability rule moves to `WPCanAI\Mcp\RawMetaGuard`. It was
  reached through a trait that silently shadowed seven of the importing class's own methods.

= 1.67.1 =
* Security: `wpcanai/write-page`'s `css` argument is now gated on the `unfiltered_html`
  capability, like every other route into `_canai_css`. It writes meta that is echoed unescaped
  into the page head, so a caller with `manage_options` but not `unfiltered_html` (a multisite
  site administrator, or any install defining `DISALLOW_UNFILTERED_HTML`) could store markup
  through `write-page` that `write-meta` refuses. The refusal happens before any write.
* Fix: upgrading now marks every Tailwind build compiled by an older version stale, so a block
  page falls back to the always-correct Play CDN until it is recompiled. Without this, a build
  made before 1.67.0 — by a compile that never scanned block bodies — was judged fresh and
  served, leaving the page essentially unstyled.
* Fix: a whitespace-only `_canai_html` made a page emit its CSS twice, once through Twig and once
  raw. The two branches now use the same emptiness test.
* Docs: the changelog entries for 1.66.0 and 1.66.1 were missing; they are restored below.

= 1.67.0 =
* Feature: block pages get a plain-CSS slot. `wpcanai/write-page` accepts `css` (stored in
  `_canai_css`, emitted raw in the head after the layout's CSS) and `wpcanai/write-meta` writes
  `css` onto a blocks page without converting it; `html`/`js` are still guarded.
* Feature: block pages are served from the compiled layout Tailwind build. The `block_page`
  Play-CDN bypass is gone; a changed block body (Gutenberg save or write-page) or a change to the
  page-format mark bumps the source epoch so the build is marked stale until the next compile.

= 1.66.1 =
* Docs: the AI Agent page's description of the `canai-blocks` skill no longer claims blog posts.
  `wpcanai/write-post` belongs to `canai-mcp` (a blog post is block content by nature, not a
  blocks-vs-Twig choice); `canai-blocks` is the opt-in skill for block-authored pages. Admin copy
  only — no behaviour change.

= 1.66.0 =
* Docs: the block-page workflow moved to its own companion skill, `canai-blocks`. The
  convert-format prompt and the `write-page` sample on the AI Agent page now point at
  `/canai-blocks` instead of `/canai-mcp`, and `canai-blocks` was added to that page's
  published-skills list and its `npx skills add/remove` commands. Pointer and copy changes only —
  no behaviour change.

= 1.65.0 =
* Feature: pages can be authored with blocks. A `_canai_format` mark (set only through MCP)
  routes "Edit with CanAI" to the block editor, the CanAI editor and its AJAX save refuse the page,
  and the body renders inside the page's CanAI layout as before. Block pages always load the
  Tailwind Play CDN.
* Feature: new `wpcanai/write-page` ability; `wpcanai/create-page` accepts `format: "blocks"`;
  `read-meta` returns `format` and can read `blocks`; `list-pages` lists block pages; `write-meta`
  refuses Twig onto a block page unless `convert: true`.
* Feature: `BlockBuilder` gains group, columns, buttons, cover, media_text, spacer and html (the
  last gated on unfiltered_html), nesting to 4 levels, and `className` on every type except embed
  and html.
* Fix: readme Stable tag had drifted to 1.61.1; it now tracks Version again.

= 1.61.1 =
* Simplify: the admin-impersonation block and the manage_options-or-API-key permission check in
  `PostAbilities` now reuse the shared `AbilityGuards` trait instead of a duplicated copy; the
  `list`/`quote` block builders share one inner-block-assembly helper instead of two near-identical
  loops; an image block's featured-image lookup no longer refetches the full-size URL it already
  has. No behavior change — internal cleanup only.

= 1.61.0 =
* New MCP ability `wpcanai/write-post`: create or update blog posts as native block-editor content
  from a structured block list. Nine block types (paragraph, heading, list, quote, image, code,
  separator, embed, table) are emitted in exactly the shapes the block editor writes, so the post
  opens with no "unexpected or invalid content" prompt. Posts land as drafts by default; images are
  referenced by attachment id (sideload first with `wpcanai/sideload-url`).

= 1.60.6 =
* Fix: the CanAI Editor crashed with a critical error when opened on a template/page whose
  `_canai_context` held a nested value for one of its keys (e.g. written directly via the MCP
  `write-meta` tool) instead of a plain query-string. The Context panel's "CPT" box now shows
  such a value as JSON instead of fataling — the crash truncated the page before the editor's
  CodeMirror panes could initialize, which looked like "CodeMirror won't load."

= 1.60.5 =
* Clicking the CanAI menu in wp-admin now opens All Templates directly instead of the Welcome
  page. Welcome is still in the sidebar, just no longer the default landing page.

= 1.60.4 =
* Fix: Stable tag had drifted to 1.59.5 while Version stood at 1.60.3 (Plugin Check:
  "Mismatched Stable Tag"), a WordPress.org submission blocker — a mismatch stops users
  downloading the correct release. Stable tag now tracks Version on every push.

= 1.60.3 =
* Fix: the takeover check ElementorIntegration and LanguageManager use with no explicit post id
  never recognized the blog kit's Posts page, so Elementor's own CSS/JS stayed loaded there even
  when CanAI was fully rendering it. It now uses the same request-to-post rule the rest of the
  plugin does.
* Simplify: the blog-journal preset's category/tag/author/search pages were four separate,
  near-identical templates; consolidated into one, matching how the bundled woo-bookstore pack
  already handles shop + product-category.
* Internal: assorted cleanup from a code-simplification pass (deduped a Tailwind-plugin allowlist,
  a repeated enrichment guard, and an enrich+paginate helper; added per-request memoization to
  `TemplateResolver::current_request_post_id()`). No other behaviour changes.

= 1.60.2 =
* Changelog: backfill the entries for 1.58.6 and 1.59.0-1.59.6, which shipped without one. The
  1.59.0 entry in particular covers the rename to CanAI and the removal of the `wpcanai/eval` MCP
  tool, both of which affect existing installs. No code changes.

= 1.60.1 =
* Fix: the `cpt-corporate`, `single-freelancer` and `woo-bookstore` preset layouts wrote
  `<body {{ body_class() }}>`, which dropped every WordPress body class (each parsed as a
  valueless HTML attribute). Theme, admin-bar and plugin selectors such as `.logged-in`,
  `.admin-bar` and `.single-post` never matched on pages using those packs. The Twig
  `body_class()` returns class names, not an attribute, so it now sits inside `class="…"`.
  `blog-journal` already shipped correct in 1.60.0.

= 1.60.0 =
* Blog kit: the page selected under Settings → Reading → "Posts page" is now rendered by CanAI
  when it carries CanAI content, with the paged post listing injected as `posts` + `pagination`.
  (Behaviour change: a posts page that already had CanAI HTML previously fell through to the theme.)
* New `single-post` template type is pre-seeded; typed `single-*` takeovers now expose
  `post.featured_image.*`.
* New bundled preset `blog-journal` (layout, header, footer, Blog page, single post with comments,
  category / tag / author / search / 404) — `wp wpcanai preset install blog-journal`.
* Presets: new `settings.posts_page` (sets `page_for_posts`, never `show_on_front`) and
  `settings.tailwind_plugins`; both are backed up and restored on uninstall.
* Internal: `TemplateResolver::current_request_post_id()` replaces five copies of the
  request-to-post rule.

= 1.59.6 =
* Internal: the 22 remaining WordPress.org Plugin Check `SlowDBQuery` warnings — the ones
  recorded as accepted risk in 1.58.4 — now each carry a `phpcs:ignore` note explaining why that
  query is the right one there and has no faster equivalent. Most sit on admin screens, MCP tool
  calls and one-shot install or uninstall sweeps; the few on the front end are the indexed
  archive and shop lookups WordPress and WooCommerce build for those pages themselves, plus a
  taxonomy filter a template asks for by name. Comments only — no query was rewritten and
  nothing changes on a live site.

= 1.59.5 =
* Declare compatibility with WordPress 7.1 (bump "Tested up to").

= 1.59.4 =
* The `canai-localwp` agent skill has been retired and is gone from the `usewp/canai` catalogue, so
  the `--skill canai-localwp` install command wp-admin used to advertise no longer resolves. The
  Skill list under CanAI → AI Agent → Skills now shows `canai-mcp`, `canai-prepare` and
  `canai-replicate` only; if you already installed the old skill, remove it with
  `npx skills remove canai-localwp` — everything it covered is available through the MCP tools.
* The "no compiled Tailwind CSS" notice on a layout now points at `canai-mcp` alone as the skill to
  run "compile tailwind" through.
* Regenerated `languages/canai.pot`, which had not been rebuilt since v1.58.2: it still declared
  `CanAI 1.58.2`, cited the pre-rename `wpcanai.php` as the source of every plugin-header string,
  and still listed strings left behind by the removed `eval` ability, so translators were working
  from an out-of-date list.

= 1.59.3 =
* Phosphor icons were advertised as a bundled option but were never actually wired up — there was
  no setting, no admin control and nothing that enqueued them. The claim is dropped from the
  feature list and the unused `assets/lib/phosphor/phosphor-icons.min.js` file is removed from the
  plugin, so any hand-written link to that file's URL will now 404. Lucide icons are unaffected.
* Internal: deletes the unused `IconManager` class, superseded long ago by `LucideManager` and with
  no callers, hooks or admin page anywhere in the plugin. Its hardcoded `unpkg.com` URLs were the
  last remaining WordPress.org Plugin Check "offloaded content" finding; the live Lucide, Alpine
  and Tailwind self-hosted/CDN toggles are untouched.

= 1.59.2 =
* Internal: the two maintainer-only scripts under `tools/` (the HPOS-safety scan and the Tailwind
  bundle builder) were moved out of the plugin repository, and the matching `hpos-check` entry in
  `composer.json` was dropped. Neither ever ran at runtime and both were already excluded from the
  released package, so nothing changes for your site.

= 1.59.1 =
* Security hardening: the bundled starter theme's `index.php`, `header.php`, `footer.php` and
  `404.php`, plus `src/Compat/FunctionShims.php`, now abort when requested directly instead of
  executing outside WordPress.
* The bundled starter theme is now named "CanAI Starter" wherever it is shown — its `style.css`
  header, the CanAI Settings page, and the `wpcanai/setup` ability's description and install
  messages — finishing the rename that v1.59.0 had left reading "WPCanAi Starter"; the
  `woo-bookstore` preset description picked up the same fix. The theme directory is still
  `wpcanai-empty`, so a copy already installed in `wp-content/themes` is untouched and keeps the
  old name in Appearance → Themes until it is reinstalled.

= 1.59.0 =
* The plugin is now called CanAI (it was WPCanAI) and its main file is `canai.php` instead of
  `wpcanai.php`, so it now reads "CanAI" on the Plugins screen and throughout wp-admin — a few
  strings, such as the bundled "WPCanAi Starter" theme, still show the old name. Nothing on your
  site changes with it: the `wpcanai_*` options, the `wpcanai_template` post type, the admin page
  URLs, the `wpcanai/*` MCP tool names, the `/wp-json/mcp/wpcanai` endpoint and the
  `X-WPCanAI-API-Key` header are all unchanged, so no content, settings or MCP client config needs
  touching. Because the main file moved, an install updated in place may need reactivating on the
  Plugins screen.
* Breaking: the `wpcanai/eval` MCP tool is gone. It ran arbitrary PHP and only worked when
  `WPCANAI_ENABLE_EVAL` was defined true in `wp-config.php`; that constant now does nothing, and
  55 abilities remain. It is planned to return as a separate opt-in add-on plugin. Everything the
  admin pages can do already has its own dedicated MCP tool, so no CanAI capability is lost — but
  running arbitrary PHP over MCP is.
* The text domain changed from `wpcanai` to `canai` and `languages/wpcanai.pot` is now
  `languages/canai.pot`, so any custom translation files need renaming to `canai-<locale>.po/.mo`.

= 1.58.6 =
* The template editor now uses the CodeMirror that ships with WordPress core (the `wp-codemirror`
  handle) instead of a second copy bundled in the plugin, which the Plugin Directory disallows.
  Syntax highlighting in the HTML, CSS and JS boxes is unchanged, and the plugin is ~224KB smaller.
* MCP ability registration now checks that `wp_register_ability()` exists before calling it, so
  registration is skipped cleanly rather than fataling on a site where neither WordPress 6.9+
  core nor the bundled Abilities API polyfill provides it. All `wpcanai/*` abilities and the
  `wpcanai` category still register as before.
* Fix two more `phpcs:ignore` suppressions the previous pass left ineffective: the translators
  comment in `TranslationsPage.php` now sits directly above its `printf()`, and the nonce-check
  ignore in `LanguageManager.php` brackets the whole `$_GET['lang']` block instead of one line.

= 1.58.5 =
* Fix DirectDatabaseQuery/NoCaching phpcs:ignore comments that were nested one level too deep
  (above the inner $wpdb->prepare() call instead of the outer $wpdb query-method call), so
  suppressions on SnapshotRepository.php and MediaManager.php now actually apply.
* Fix two more misplaced NonceVerification ignore/translators comment orderings
  (LanguageManager.php, TranslationsPage.php).

= 1.58.4 =
* Fix phpcs:ignore/translators comments left in the wrong position by the previous pass, so the
  intended suppressions actually take effect.
* Flip get_posts() suppress_filters to false in 4 admin-side queries (onboarding checklist,
  Tailwind build scan, slug resolution) for correct multisite/filter behavior.
* Justify remaining direct-DB and non-enqueued-script findings that are false positives or
  architecturally required; document SlowDBQuery/PostNotIn_exclude VIP advisories as accepted risk.

= 1.58.3 =
* Security hardening: nonce verification, input unslashing/sanitization, and output escaping
  across ~270 WordPress.org Plugin Check findings.
* Add languages/wpcanai.pot so the Domain Path header resolves.
* Justify direct-DB-query and packaging findings; add .distignore for SVN packaging hygiene.
* Swap discouraged PHP functions for WordPress equivalents; gate debug logging behind WP_DEBUG.

= 1.58.2 =
* Default Tailwind CSS and Alpine.js to self-hosted assets instead of third-party CDNs.
* Vendor js-beautify locally for the template editor instead of loading it from a CDN.
* Add readme.txt for WordPress.org directory submission.

= 1.58.1 =
* Maintenance release.

== Upgrade Notice ==

= 1.58.2 =
Fixes third-party CDN usage on the frontend and in the template editor.
