=== R2 SEO ===
Contributors: rise2studio
Requires at least: 6.5
Tested up to: 6.7
Requires PHP: 8.1
Stable tag: 1.7.4
License: GPL-2.0-or-later

Add-on for Slim SEO: per-language meta for the contexts Slim SEO keeps global.

== Description ==

Slim SEO stores one title and description per post-type archive for the whole
site. On a multilingual project that means one language's text ends up on every
language's archive. R2 SEO adds a per-language field for each of those
contexts and hands the value to Slim SEO through its own filters.

Slim SEO remains the SEO plugin. This add-on only fills gaps: where it has no
value for the current language it returns Slim SEO's value untouched, so
deactivating the add-on returns the site to plain Slim SEO with nothing left
behind in the HTML.

Requires Slim SEO 4.10.0 or newer. Without it the add-on registers no filters
and shows an admin notice.

== Changelog ==

= 1.7.4 =
* Fixed a false positive in the page check: an image with alt="" was counted as missing its alt. An empty alt is the author marking a decorative image, which is correct for an image inside a link that already has text — and it made the checker accuse a correctly built site on every page. Only a missing alt attribute, or a file name used as one, is reported now.

= 1.7.3 =
* Saving any R2 SEO screen now purges the page cache. Without it a cached site kept serving the old <head> and the settings looked like they had done nothing — which is exactly what happened on the pilot site.
* llms.txt entries now cut their note at 200 characters. One unit's meta description is 545 characters long, which turned the list into prose.

= 1.7.2 =
* Fixed: the launch checks' "Measured …" note and its Check again button were missing on the first view of the Coverage tab — the very view that paid for the measurement.

= 1.7.1 =
* Security: llms.txt no longer lists password-protected posts, nor post types the admin set to noindex; ?r2seo_llms=1 can no longer force a 404 or serve the document on any other URL.
* Security: the ACF description fallback no longer publishes a password-protected post's content — which, because of the bug below, was the only page it ever reached.
* Fixed: the description fallback never fired on a normal page. Slim SEO passes its unrendered auto-description template, not an empty string, so the gap test was wrong.
* Fixed: a redirect CSV mixing absolute and relative URLs for the same path wrote a rule that redirected the URL to itself.
* Fixed: a CSV without an object_type column silently wrote term rows onto unrelated posts. The file is now rejected.
* Fixed: duplicate rows for one object corrupted the undo snapshot, so restoring left the imported value in place.
* Fixed: exporting and re-importing wrote a stray apostrophe from the spreadsheet-formula guard into Slim SEO's meta.
* Fixed: the self-hosted updater was constructed with the wrong key — updates never appeared and every request logged a PHP warning.
* Fixed: launch checks made three to four blocking loopback requests on every render of the Coverage tab; now cached for ten minutes with a "Check again" button.
* Fixed: the hand-written llms.txt lost percent-encoded characters from URLs on save.
* Fixed: deactivating the plugin left the /llms.txt rewrite rule behind, serving the blog index at 200.
* Fixed: lazy-load placeholders were counted as separate images, doubling the reported missing-alt count.

= 1.7.0 =
* Meta CSV round-trip: export every page and term, fill the file in outside WordPress, import it back into Slim SEO's own fields. Empty cells never clear a value, and the last import can be undone.
* Coverage report and launch checks: what Slim SEO would actually output for every object, flagged, with a CSV export and an optional page check for H1s, hreflang and image alt.
* llms.txt, off by default, generated per language and served from a rewrite rule.
* Redirect import from a plain from,to CSV into Slim SEO Redirection.
* Fallbacks: per-page social image from a nominated ACF gallery, after Slim SEO's own chain, and a description composed from ACF fields for pages whose post content is empty.
* Fixed: /llms.txt no longer 301s to /llms.txt/, and its output no longer carries HTML entities.
* Fixed: a redirect preview no longer over-counts a source URL listed twice in the same file.

= 1.6.0 =
* Export now covers every language, not just the admin's current one. Each row records its language.

= 1.5.1 =
* Fixed: containedInPlace pointed at a node typed Organization, which is not a Place. Caught by validator.schema.org.

= 1.5.0 =
* Site entity gains numberOfRooms and a per-language amenity list.

= 1.4.0 =
* containsPlace: the site entity can list the mapped items, on the home page and optionally each archive.

= 1.3.0 =
* Per-post schema type override, for a content type that holds genuinely different things.
* Verified end to end on the pilot site: one connected graph, per-language, no duplication.

= 1.2.0 =
* Schema layer B: per-post entities from a type template, not from a per-project field mapping.
* JSON export/import so the values can be filled in outside WordPress; the plugin never calls out.

= 1.1.0 =
* Site entity (schema layer A): merged into Slim SEO's existing organisation node instead of a second detached block.
* Single-subject and split operator/venue modes, per-language name and description, home-page-only scope.

= 1.0.0 =
* First release: per-language title, meta description and og:image for post-type archives, taxonomy archives, the blog home, search results and 404.
