Title: Spintax
Author: Franky
Published: <strong>11 de Maio, 2026</strong>
Last modified: 12 de Maio, 2026

---

Buscar plugins

![](https://ps.w.org/spintax/assets/banner-772x250.png?rev=3528366)

![](https://ps.w.org/spintax/assets/icon.svg?rev=3528366)

# Spintax

 Por [Franky](https://profiles.wordpress.org/301st/)

[Descargar](https://downloads.wordpress.org/plugin/spintax.2.0.3.zip)

 * [Detalles](https://gl.wordpress.org/plugins/spintax/#description)
 * [Valoracións](https://gl.wordpress.org/plugins/spintax/#reviews)
 *  [Instalación](https://gl.wordpress.org/plugins/spintax/#installation)
 * [Desenvolvemento](https://gl.wordpress.org/plugins/spintax/#developers)

 [Soporte](https://wordpress.org/support/plugin/spintax/)

## Descrición

Spintax is a WordPress plugin for template-based content generation using spintax
markup. Create reusable templates with randomised text variants, variable substitution,
and permutation logic — then embed them anywhere on your site via shortcodes or 
PHP.

**Key features:**

 * **Enumerations** `{a|b|c}` — randomly pick one option, with nesting support
 * **Permutations** `[<config>a|b|c]` — pick N elements, shuffle, join with custom
   separators
 * **Variables** `%var%` — global, local (`#set`), and shortcode-level variable 
   scopes
 * **Conditionals** `{?VAR?then|else}` — render a branch based on whether a variable
   is set (also `{?!VAR?then}` inverted)
 * **Plural agreement** `{plural <count>: form1|form2|form3}` — pick grammatically
   correct noun form by count. RU/UK/BE 3-form (one|few|many), EN-style 2-form (
   one|many). First spintax engine with first-class plurals.
 * **Nested templates** — embed templates within templates via `#include` or `[spintax]`
 * **ACF / post-meta bindings (NEW in 2.0)** — configure once per post type, render
   Spintax templates into ACF text/textarea/wysiwyg fields or post-meta keys on 
   every matching post. Auto-seed empty fields, preserve manual edits, Bulk Apply
   via Action Scheduler.
 * **Object cache** — rendered output cached via WP Object Cache API (Redis/Memcached
   ready)
 * **Cron regeneration** — optional scheduled cache refresh per template, plus per-
   binding cron walks
 * **WP-CLI** — `wp spintax bindings list|apply|test|export|import`
 * **Validation** — bracket matching, circular reference detection, syntax checking
 * **Admin UI** — code editor, live preview, shortcode copy, settings page, bindings
   list

**Syntax based on the GTW (Generating The Web) standard.**

### External services

This plugin does **not** connect to any external services, APIs, or third-party 
servers.

All content generation happens locally on your WordPress server. No data is sent
externally. No remote requests are made during activation, rendering, or caching.

### Privacy Policy

This plugin does not collect, store, or transmit any personal user data. It does
not use cookies, tracking pixels, analytics, or any form of telemetry.

Templates and their rendered output are stored entirely within your WordPress database
and object cache.

### Credits

 * Syntax based on the [GTW (Generating The Web)](https://spintax.net) standard
 * Developed by [301st](https://301.st)

## Capturas

 * [[
 * Template editor with spintax markup and live preview.
 * [[
 * Settings page with global variables editor.
 * [[
 * Template list with shortcode, cache status, and cron schedule.

## Instalación

 1. Upload the `spintax` folder to `/wp-content/plugins/`
 2. Activate the plugin through the ‘Plugins’ menu in WordPress
 3. Create templates under the “Spintax” menu in the admin sidebar
 4. Embed templates using `[spintax slug="my-template"]` in posts/pages or `spintax_render('
    my-template')` in theme files

**Recommended optional dependency:** install [Action Scheduler](https://wordpress.org/plugins/action-scheduler/)
if you plan to use the “Bulk Apply” button on ACF / post-meta bindings, or schedule
bindings via per-binding cron on a site with many matching posts. The plugin works
without it — Bulk Apply falls back to a WP-CLI command and cron walks run synchronously—
but Action Scheduler gives you one-click admin Bulk Apply and chunked async cron
walks. If you already use WooCommerce or another plugin that bundles Action Scheduler,
you’re already set; the Bindings page only shows the install notice when AS isn’t
loaded.

## Preguntas frecuentes

### How do I create a template?

Go to Spintax > Add New in the WordPress admin. Enter a title and your spintax markup
in the editor.

### What syntax does the plugin use?

 * `{a|b|c}` — randomly picks one option
 * `[a|b|c]` — permutation: picks N elements, shuffles, joins with space
 * `[<minsize=2;maxsize=3;sep=", ";lastsep=" and "> a|b|c|d]` — configured permutation
 * `%variable%` — variable reference
 * `#set %var% = value` — local variable definition
 * `{?VAR?then|else}` — conditional: render a branch by truthiness of `%VAR%` (also`{?!
   VAR?then}` inverted)
 * `{plural %Count%: form1|form2|form3}` — plural agreement: picks the correct grammatical
   form by count (RU 3-form, EN 2-form)
 * `/#comment#/` — block comment (stripped from output)
 * `#include "slug"` — embed another template

Full syntax reference with examples and a live playground: https://spintax.net/docs/
syntax

### Where can I learn more?

 * **Documentation hub:** https://spintax.net/docs/ — guides, reference, recipes
 * **Compact syntax reference:** https://spintax.net/docs/syntax — all primitives
   in one page (13 languages)
 * **Plural agreement guide:** https://spintax.net/docs/plural-spintax/ — `{plural
   N: form1|form2|form3}` in depth (EN/RU)
 * **Conditional spintax guide:** https://spintax.net/docs/conditional-spintax/ —`{?
   VAR?then|else}` value-driven branching (EN/RU)
 * **Authoring mindset:** https://spintax.net/docs/authoring-mindset/ — write the
   final text first, add markup last (EN/RU)
 * **Live playground:** https://spintax.net/play/ — write a template, set variables,
   render N variants in your browser (EN/RU)

### Does caching require Redis or Memcached?

The plugin uses the WordPress Object Cache API. With a persistent backend (Redis,
Memcached), cached output persists across requests. Without one, templates are re-
rendered on each page load.

### Can I pass variables through shortcodes?

Yes: `[spintax slug="greeting" name="Alice" city="Moscow"]` makes `%name%` and `%
city%` available inside the template.

### What are ACF / post-meta bindings?

A binding pairs a Spintax template (or a per-post inline source) with one target
field on one post type — for example “Posts  ACF: hero_subtitle”. Configure it once
under Spintax  Bindings and the plugin populates the field on every matching post
on save, on a cron schedule, or on demand via Bulk Apply. Manual edits are preserved
by default (hash-tracked); flags control whether the binding auto-seeds empty fields,
regenerates on every save, or clears the field when the template renders to empty.

### Can I bind to ACF fields?

Yes. Bindings support both ACF (text / textarea / wysiwyg, top-level fields) and
plain post-meta keys. ACF Free and Pro are both supported; nested fields (repeater/
flexible_content rows) are not supported in 2.0 — that lands in a later release.
The form-side field picker auto-fills the stable ACF field key so writes work on
the first save without ACF’s reference-meta handshake.

### Do I need Action Scheduler?

It’s a recommended optional dependency for binding-heavy sites. The plugin works
without it, but two features degrade:

 * The admin **Bulk Apply** button uses Action Scheduler to dispatch chunked async
   jobs. Without AS, the button returns an error pointing at the WP-CLI fallback(`
   wp spintax bindings apply --binding=<id> --all`).
 * Per-binding cron schedules still fire, but the cron callback runs the walk synchronously
   instead of enqueueing an async job. On large catalogues that risks PHP-FPM timeouts
   on the cron worker.

Many WP shops already ship Action Scheduler bundled with WooCommerce or other plugins—
check Plugins  Installed Plugins for “Action Scheduler” before installing it separately.
If the Bindings admin page shows an “Action Scheduler is not installed” notice at
the top, you don’t have it loaded yet; install [Action Scheduler](https://wordpress.org/plugins/action-scheduler/)
to make one-click admin Bulk Apply and async cron walks available.

### What WP-CLI commands does the plugin add?

Five subcommands under `wp spintax bindings`:

 * `wp spintax bindings list [--format=table|json|csv]` — list all bindings on the
   site.
 * `wp spintax bindings apply --binding=<id> [--all|--post=<id>] [--dry-run]` — 
   run a binding against all matching posts (or a single post), with optional dry-
   run. This is the no-Action-Scheduler fallback path for Bulk Apply.
 * `wp spintax bindings test --binding=<id> --post=<id>` — dry-run a binding against
   one post and report what `BindingApplier::plan()` would do (`would_write`, current
   value, rendered preview, skip reason). Same logic as the admin Test panel.
 * `wp spintax bindings export [--format=json] [> bindings.json]` — emit the full
   bindings store as JSON, deduped by `(post_type, target.key)`.
 * `wp spintax bindings import --file=bindings.json [--overwrite] [--dry-run]` —
   import bindings from JSON. `--overwrite` updates matches on the same target triple;
   without it, duplicates are skipped. Use `--dry-run` to preview the plan without
   writing.

The export/import pair is the recommended stagingproduction sync path; bindings 
are not exposed over REST in 2.0.

### What variables can I use inside a bound template?

A binding template renders with four layered variable sources (later layers override
earlier ones — see spec §4.3):

 * **Global variables** — the `#set` block in Settings  Spintax  Global Variables.
   Site-wide.
 * **Per-binding overrides** — a `#set` block in the binding’s Variables  “Per-binding#
   set overrides” textarea. Applies to that binding only.
 * **Post context** (opt-in via the binding’s “Expose post context as %vars%” checkbox)—`%
   post_id%`, `%post_title%`, `%post_url%`, `%post_slug%`, `%post_date%`, `%post_modified%`,`%
   author_id%`, `%author_name%`.
 * **ACF sibling fields** (opt-in via “Expose ACF sibling fields as %acf_%”) — every
   top-level ACF text/textarea/wysiwyg field in the binding’s post type group, available
   as `%acf_<field_name>%`. Reads happen after ACF persists its values (save_post
   priority 20 hook), so siblings are always fresh on save_post triggers. Only meaningful
   for ACF-target bindings.

A binding’s source can also use the rest of the Spintax syntax (`{a|b|c}`, `[a|b]`,`{?
VAR?then|else}`, `{plural %N%: ...}`, `#include "slug"`, `/#comment#/`).

### How do I schedule bindings to run automatically?

Two trigger paths, both configurable per binding under “Triggers”:

 * **Fire on post save** (checkbox, default on) — hooks `save_post` priority 20.
   Runs after ACF persists its own field values, so sibling reads see fresh data.
   Skipped during autosave / bulk-edit / REST batch imports / revisions / trash 
   flips.
 * **Cron schedule** (dropdown: disabled / hourly / twicedaily / daily) — each binding
   gets its own WP-Cron hook `spintax_binding_cron_<binding_id>`. On the scheduled
   tick, the callback enqueues an Action Scheduler walk (or runs synchronously if
   AS isn’t installed — see the Action Scheduler FAQ above). Independent of save_post;
   use this to refresh content periodically without an editor touch.

For one-off “apply now” operations, click **Bulk Apply** on the binding card. The
button needs Action Scheduler; without it, the admin notice points at the WP-CLI
fallback.

### How does the plugin handle manual edits to bound fields?

Each binding tracks a SHA-1 signature of its last-rendered value in post-meta `_spintax_last_render_sig_
<binding_id>`. On every subsequent run with `Preserve manual edits` enabled (default),
it compares the current target value’s hash to the stored signature:

 * If the hashes match, the value hasn’t been touched outside the binding — safe
   to regenerate.
 * If they differ, treat it as a manual edit; skip with `SKIP_MANUAL_EDIT_DETECTED`
   and log the skip.

Combined with `Regenerate on every save`, this gives a “refresh on save unless edited”
workflow. With `Auto-seed empty fields` instead, the binding only writes when the
target is empty — manual edits are preserved by definition because they’re never
overwritten.

There is a “cold-start” exception: when a binding first sees a post with non-empty
target content and no signature yet, it treats the existing value as an unwritten
manual baseline and skips (`SKIP_COLD_START_MANUAL`) until the editor clicks the
binding’s “Initialize from current value” path (a later UI addition) or accepts 
the regeneration by clearing the field first.

### I edited a template. Why aren’t the changes showing up on the front end?

Bindings are a **pre-generation** system, not a render-on-read layer. The rendered
string is stored in the target field; consumers (themes, blocks, REST readers) get
that stored value directly. Editing the source template doesn’t propagate to existing
posts until a trigger writes a fresh value to each one.

When you edit a template that has bindings pointing at it, the plugin:

 1. Bumps an internal render-cache version on each affected binding.
 2. Surfaces an admin notice on the template-edit screen (“N bindings depend on this
    template”).
 3. Shows a “Stale: source template edited” badge on each affected binding’s card.

To push the new content to existing posts, click **Bulk Apply** on each affected
binding (or run `wp spintax bindings apply --binding=<id> --all` from the CLI). 
The Stale badge only clears when the entire walk completes with zero failures — 
partial-failure walks keep the badge so you notice the divergence and retry.

### Is there a hard cap on bindings?

200 bindings per site. The store is a single autoloaded option (~500 bytes per binding),
and the cap keeps autoload memory bounded. If you genuinely need more, please open
an issue with your use case.

### Which fields can’t I bind to?

The form rejects five tiers of reserved keys at save time:

 * **WordPress-internal meta** — keys starting with `_wp_`, `_edit_`, `_oembed_`,
   plus `_pingme`, `_encloseme`, `_thumbnail_id`.
 * **Plugin-internal meta** — `_spintax_*` prefixes (source, signature, cache-version
   slots used by other bindings).
 * **wp_posts columns** — `post_title`, `post_content`, `post_excerpt`, `post_name`,`
   post_status`, `post_date`, `post_modified`, `post_parent`, `post_author`, `post_type`,`
   post_password`, etc. These aren’t post-meta and writing to them via `update_post_meta()`
   silently creates shadow rows.
 * **Cross-binding uniqueness** — only one binding per `(post type, target key)`,
   regardless of whether the kind is ACF or post_meta (they share the same database
   row).
 * **ACF field key validity** — when binding to an ACF field, the stable field key(
   e.g. `field_5f8a1234abcd`) is required, and verified against `acf_get_field()`
   when ACF is loaded.

### On multisite, are bindings shared across the network?

No — bindings are per-site. Each subsite manages its own. Use `wp --url=site2 spintax
bindings import --file=site1-bindings.json` to copy bindings between subsites via
the WP-CLI export/import round-trip.

### Can I manage bindings via REST?

Not in 2.0; bindings are admin-only. The `wp spintax bindings` WP-CLI surface covers
stagingproduction sync scenarios. REST API exposure is tracked for a later release.

### I’m coming from `nested-spintax-for-acf`. Is there a migration path?

Yes. After activating Spintax 2.0, a dismissible admin banner points to **Tools  
Spintax Migration**. The wizard scans for predecessor data, shows a per-row preview,
and creates bindings deduped by `(post type, target field)`. Per-post sources and
variables are copied non-destructively — the old plugin’s data stays in place until
you delete it.

## Comentarios

Non hai recensións para este plugin.

## Colaboradores e desenvolvedores

“Spintax” é un software de código aberto. As seguintes persoas colaboraron con este
plugin.

Colaboradores

 *   [ Franky ](https://profiles.wordpress.org/301st/)

[Traduce “Spintax” ao teu idioma.](https://translate.wordpress.org/projects/wp-plugins/spintax)

### Interesado no desenvolvemento?

[Revisa o código](https://plugins.trac.wordpress.org/browser/spintax/), bota unha
ollada ao[repositorio SVN](https://plugins.svn.wordpress.org/spintax/), ou subscríbete
ao [log de desenvolvemento](https://plugins.trac.wordpress.org/log/spintax/) por
[RSS](https://plugins.trac.wordpress.org/log/spintax/?limit=100&mode=stop_on_copy&format=rss).

## Rexistro de cambios

#### 2.0.3

 * Fix: ACF target validation now runs on every apply, not just at form save. `BindingApplier::
   plan()` rejects bindings whose stored `target.field_key` no longer resolves to
   a field with the expected name (deleted, renamed, or re-assigned in ACF). Two
   new return codes: `skip_acf_not_loaded` (ACF deactivated since the binding was
   saved) and `skip_invalid_acf_field` (key + name disagreement). Closes a path 
   where CLI-imported or imported-while-ACF-inactive bindings could write through`
   update_field()` to the wrong field.
 * Fix: `BindingApplier::read_target()` and `::write_target()` no longer fall back
   to plain `update_post_meta()` / `get_post_meta()` for `kind = acf_field` when
   ACF isn’t loaded. The applier short-circuits at the runtime guard above, so the
   low-level methods are the sole writer for verified targets. Pre-2.0.3 the silent
   fallback could write the rendered value to a post-meta row ACF would never see
   again.
 * Fix: Bulk Apply now tracks failures cumulatively across chunks via a persistent`
   _spintax_binding_walk_failed_v_<id>` flag. The final chunk gates `stamp_last_applied_version()`
   on the cumulative flag. 2.0.1 only checked the current chunk, so a multi-chunk
   walk that failed in chunk 1 and succeeded in the final chunk would still clear
   the Stale badge.
 * Fix: Concurrent Bulk Apply walks on the same binding are now refused with `WP_Error'
   walk_in_progress'`. Both `enqueue()` and `run_synchronously()` acquire a per-
   binding lock (option `_spintax_binding_walk_lock_<id>`) at walk start; stale 
   locks older than one hour are auto-overwritten so a crashed walk doesn’t permanently
   jam the binding.
 * Internal: 11 new PHPUnit cases — runtime ACF guard, multi-chunk failure tracking,
   walk-lock acquisition / release, stale-lock recovery. 441 tests total (was 430).
 * Tooling: `npm run lint:php` and `lint:php:fix` moved to `scripts/lint-php.sh`/`
   scripts/lint-php-fix.sh`. The inline command tripped over bash-c quoting on Windows.`.
   gitattributes` enforces LF endings on shipped text files.
 * Internal: CLI `wp spintax bindings import --overwrite` help text updated to reflect
   the 2.0.1 `(post_type, target.key)` uniqueness contract.

#### 2.0.2

 * Docs: new FAQ entries — Action Scheduler dependency, full `wp spintax bindings`
   WP-CLI surface, variable scopes (global / per-binding / post context / ACF siblings),
   trigger options (save_post + per-binding cron), manual edit detection, template-
   edit propagation, reserved-key tiers.
 * Docs: Installation section now flags Action Scheduler as a recommended optional
   dependency with the specific features it enables.
 * UX: Spintax  Bindings shows an info notice at the top of the page when Action
   Scheduler isn’t loaded, explaining the two features that degrade (admin Bulk 
   Apply, async cron walks) and linking to the install screen. Notice disappears
   when AS is loaded by any source (direct install, WooCommerce / Jetpack bundle,
   mu-plugin, etc.).
 * Internal: no functional changes to the bindings engine or core spintax engine—
   patch is documentation + a single admin-page notice.

#### 2.0.1

 * Fix: ACF and post-meta bindings on the same `(post_type, field name)` no longer
   coexist — they wrote to the same database row and silently raced. Tier 4 uniqueness
   now ignores `target.kind`. Existing pre-2.0.1 conflicts remain in the data store
   but the next save of either binding will reject.
 * Fix: ACF bindings now require a non-empty `target.field_key` and validate it 
   against the live ACF field when ACF is loaded. Previously a missing or mistyped
   field key could route `update_field()` writes to a different field.
 * Fix: Test panel and Bulk Apply now report `skip_out_of_scope_type` / `skip_out_of_scope_status`
   for posts that wouldn’t match the binding’s scope in live triggers. Two new applier
   return codes — total now 11 instead of 9.
 * Fix: Bulk Apply only clears the Stale badge when the walk had zero failures. 
   Partial-failure walks keep the binding flagged so editors notice the divergence
   and retry.
 * Fix: Binding form validation errors no longer throw the editor back to the list
   view — the form re-renders with submitted values via a short-lived transient 
   flash, with the specific error inline.
 * Internal: 21 new PHPUnit cases covering each fix path; bindings unit suite is
   now exhaustive on scope-filter, cross-kind dedup, ACF field_key validation, and
   Bulk Apply stamp gating.

#### 2.0.0

 * **ACF / post-meta bindings** — a Spintax template (or a per-post inline source)
   can now be bound to any ACF text/textarea/wysiwyg field or post-meta key on a
   post type. Configure once under Spintax  Bindings and the plugin populates the
   field on save, cron, or via Bulk Apply.
 * Decision-tree write behaviour with four flags: `auto_seed_empty` (default on;
   never clobbers existing content), `regenerate_on_save`, `preserve_manual_edits`(
   hash-tracks the last rendered value so external edits are detected), `clear_on_empty`.
   Cold-start behaviour documented to avoid false manual-edit positives.
 * Per-binding cron schedules (hourly / twicedaily / daily) registered as individual`
   wp_schedule_event` hooks per binding.
 * Bulk Apply via Action Scheduler with chunked processing; a clean WP-CLI fallback
   when Action Scheduler isn’t installed.
 * New `%post_id%`, `%post_title%`, `%post_url%`, `%post_slug%`, `%post_date%`, `%
   post_modified%`, `%author_id%`, `%author_name%` post-context variables — opt-
   in per binding.
 * New `%acf_<field_name>%` variables — opt-in per binding, exposes ACF sibling 
   fields in the same group.
 * Template-edit cascade — editing a Spintax template that is referenced by bindings
   bumps an internal cache version and surfaces a notice telling the editor that
   stored target fields will refresh on the next Bulk Apply / cron / save_post.
 * `wp spintax bindings list|apply|test|export|import` — full WP-CLI surface for
   stagingproduction workflows and Action-Scheduler-less environments.
 * One-shot migration helper at **Tools  Spintax Migration** for users coming from
   the predecessor plugin `nested-spintax-for-acf`. Detects, previews, and imports
   legacy data deduped by `(post_type, target.key)`. Original predecessor data is
   never deleted by the migration.
 * Reserved-key guard rejects WP-internal meta keys, plugin-internal `_spintax_*`
   prefixes, wp_posts column names, and duplicate `(post_type, target.kind, target.
   key)` triples at form save.
 * Hard cap of 200 bindings per site (single autoloaded option size budget).
 * Per-binding chunk size override in the Advanced form section.
 * Uninstall cleans every bindings option family and sibling post-meta — no orphan
   rows left behind.
 * Internal: 398+ PHPUnit tests, including exhaustive decision-tree coverage and
   migration import edge cases.

#### 1.5.0

 * Add: plural agreement primitive `{plural <count>: form1|form2|form3}` — pick 
   the correct grammatical form by count. RU/UK/BE = 3 forms (`one|few|many`); EN/
   ES/PT/DE etc. = 2 forms (`one|many`). Count is a `%var%` reference or literal
   integer (resolved after variable expansion, so helper-var patterns via `#set`
   work). Locale comes from per-template post meta `_spintax_locale` or the WordPress
   site locale. Lenient at runtime: malformed constructs render verbatim with fullwidth
   braces instead of crashing the page. First spintax engine to treat plural as 
   a first-class primitive.
 * Add: validator surface for plural blocks — structural check (form slot rejects
   nested `{}`, `[]`) always on; arity check (RU expects 3, EN expects 2) when locale
   is known.
 * Internal: 74 PHPUnit cases mirroring the canonical TS implementation (`spintax-
   plurals.test.ts` in casino-platform). Engine classes `Plurals`, `PluralArityError`,`
   PluralFormError` ship alongside `Conditionals` from 1.4.0.

#### 1.4.0

 * Add: conditional syntax `{?VAR?then|else}` — render a branch based on whether
   a variable is set/non-empty (also `{?!VAR?then}` for inverted, optional else).
   Resolves both before and after `%var%` expansion, so conditionals inside variable
   values work too.
 * Add: single-token abbreviation whitelist in post-processing — known shorthands
   like `соц.`, `эл.`, `Mr.`, `Inc.` no longer trigger sentence-end capitalisation
   of the next word. Covers Russian editorial/address/unit shorthands plus English
   titles and business suffixes.
 * Fix: `#set` directive with an empty value (`#set %x% =`) no longer silently swallows
   the next directive on the following line.
 * Fix: HTML start tags inside permutation alternatives (e.g. `[<li>item</li>|<li
   >...]`) are no longer mis-parsed as a `<config>` block.
 * Improve: cache description in template meta box and global settings now explains
   that visitors see the same generated variant per runtime context until expiry
   or regeneration.
 * Internal: regression tests for IDN domains flanked by Cyrillic letters and for
   randomisation behaviour across renders.

#### 1.1.0

 * Add: per-element permutation separators — assign custom separator to each element
   via `< sep >` before `|`
 * Add: auto-spacing for purely alphabetic word separators (e.g. `<and>`, `<или>`)
 * Security: sanitize raw spintax input with custom sanitize_spintax() — strips 
   invalid UTF-8, null bytes, and control characters while preserving angle-bracket
   syntax

#### 1.0.1

 * Fix: permutation minsize/maxsize logic when only one parameter is specified
 * Fix: preview rendering no longer strips spintax config from template input
 * Fix: child templates no longer inherit parent’s local #set variables
 * Improve: global variables editor now uses #set textarea (paste full blocks)
 * Improve: validation errors displayed on template edit screen with line numbers
 * Improve: “Regenerate Public Cache” now forces fresh subtree render
 * Add: demo template created on first activation
 * Add: SECURITY.md with responsible disclosure policy
 * Add: Privacy Policy and External Services sections in readme.txt
 * Code: PHPCS 0 errors, full WP.org review compliance

#### 1.0.0

 * Initial release
 * GTW-compatible spintax engine with nested enumerations and permutations
 * Template CPT with code editor and admin preview
 * Shortcode and PHP rendering API
 * Object cache with versioned keys and cascade invalidation
 * Per-template cron regeneration
 * Global and local variable scopes
 * Settings page with global variables editor

## Meta

 *  Versión **2.0.3**
 *  Última actualización **Fai 16 horas**
 *  Instalacións activas **Menos de 10**
 *  Versión de WordPress ** 6.2 ou superior **
 *  Probado ata **6.9.4**
 *  Versión de PHP ** 8.0 ou superior **
 *  Idioma
 * [English (US)](https://wordpress.org/plugins/spintax/)
 * Etiquetas
 * [content generation](https://gl.wordpress.org/plugins/tags/content-generation/)
   [dynamic content](https://gl.wordpress.org/plugins/tags/dynamic-content/)[seo](https://gl.wordpress.org/plugins/tags/seo/)
   [spintax](https://gl.wordpress.org/plugins/tags/spintax/)[templates](https://gl.wordpress.org/plugins/tags/templates/)
 *  [Vista avanzada](https://gl.wordpress.org/plugins/spintax/advanced/)

## Valoracións

Aínda non se enviaron valoracións.

[Your review](https://wordpress.org/support/plugin/spintax/reviews/#new-post)

[Ver todas as valoracións](https://wordpress.org/support/plugin/spintax/reviews/)

## Colaboradores

 *   [ Franky ](https://profiles.wordpress.org/301st/)

## Soporte

Tes algo que dicir? Necesitas axuda?

 [Ver o foro de soporte](https://wordpress.org/support/plugin/spintax/)