From ed6523ebb1862ccb7437421a16e58e09ca356d6a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 20 Sep 2025 03:14:13 +0000
Subject: [PATCH 1/4] Initial plan
From 4a30a87759b2c04aa99db2b3726bd21fa9656c9f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 20 Sep 2025 03:20:01 +0000
Subject: [PATCH 2/4] Create comprehensive README.md files for all major
folders
Co-authored-by: ashleyshaw <1805352+ashleyshaw@users.noreply.github.com>
---
README.md | 79 ++++++++++++++++++-
block-themes/README.md | 40 ++++++++++
coding-standards/README.md | 67 ++++++++++++++++
.../inline-documentation-standards/README.md | 47 +++++++++++
.../wordpress-coding-standards/README.md | 62 +++++++++++++++
frontmatter/README.md | 48 +++++++++++
6 files changed, 342 insertions(+), 1 deletion(-)
create mode 100644 block-themes/README.md
create mode 100644 coding-standards/README.md
create mode 100644 coding-standards/inline-documentation-standards/README.md
create mode 100644 coding-standards/wordpress-coding-standards/README.md
create mode 100644 frontmatter/README.md
diff --git a/README.md b/README.md
index a59173e..1f497d0 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,78 @@
-# wp-docs
\ No newline at end of file
+# WordPress Documentation Hub
+
+A comprehensive collection of WordPress development documentation, coding standards, and best practices. This repository serves as a central resource for modern WordPress development workflows, from block themes to AI-assisted development patterns.
+
+## 📁 Documentation Sections
+
+### [🎨 Block Themes](block-themes/)
+Modern WordPress theme development with comprehensive guides for:
+- **Fluid Typography & Spacing** - Responsive design using clamp() and custom properties
+- **Design Systems** - Color palettes, spacing presets, and design tokens
+- **Theme Structure** - Templates, patterns, and global styles
+- **Best Practices** - CSS specificity, naming conventions, and optimization
+
+**Key Files:** [Fluid Typography](block-themes/fluid-typography.md) • [Global Styles](block-themes/global-styles.md) • [Theme Structure](block-themes/theme-structure-epi.md)
+
+### [📋 Coding Standards](coding-standards/)
+Comprehensive coding standards for WordPress development:
+- **[LightSpeed Standards](coding-standards/ash-research/)** - Enhanced WordPress standards (WPCS v3.2.0) with security-first approach
+- **[WordPress Core Standards](coding-standards/wordpress-coding-standards/)** - Official WordPress coding guidelines
+- **[Inline Documentation](coding-standards/inline-documentation-standards/)** - Code commenting and documentation practices
+
+**Key Features:** Security by default • WCAG 2.2 AA accessibility • Performance optimization • Maintainable code patterns
+
+### [⚙️ YAML Frontmatter](frontmatter/)
+Standardized frontmatter patterns for modern development workflows:
+- **GitHub Templates** - Issue forms, PR templates, and repository configuration
+- **AI Agent Configurations** - GitHub Copilot, Claude, and Gemini setups
+- **Copilot Space** - Complete AI-assisted development environment
+- **Schema Validation** - Consistent metadata patterns across all template types
+
+**Key Files:** [Frontmatter Cheat Sheet](frontmatter/YAML%20Frontmatter%20Cheat%20Sheet.md) • [Schema Guidelines](frontmatter/YAML-Frontmatter%20Schema-Guidelines.md) • [Copilot Space Instructions](frontmatter/YAML-Frontmatter-Copilot-Space-Instructions.md)
+
+### [🧱 Gutenberg Documentation](gutenberg/)
+Complete Gutenberg block editor documentation:
+- **[Getting Started](gutenberg/getting-started/)** - Development environment setup and tutorials
+- **[How-to Guides](gutenberg/how-to-guides/)** - Practical implementation guides
+- **[Reference Guides](gutenberg/reference-guides/)** - API references and technical documentation
+- **[Schemas](gutenberg/schemas/)** - Block and configuration schemas
+
+**Key Areas:** Block development • Editor extensibility • Theme integration • API references
+
+## 🚀 Quick Start
+
+### For Theme Developers
+1. Review [Block Themes documentation](block-themes/) for modern theme development
+2. Implement [Fluid Typography](block-themes/fluid-typography.md) and [Spacing](block-themes/fluid-spacing.md)
+3. Follow [LightSpeed Coding Standards](coding-standards/ash-research/) for best practices
+
+### For Plugin Developers
+1. Start with [WordPress Coding Standards](coding-standards/wordpress-coding-standards/)
+2. Review [Gutenberg How-to Guides](gutenberg/how-to-guides/) for block development
+3. Implement [Inline Documentation Standards](coding-standards/inline-documentation-standards/)
+
+### For AI-Assisted Development
+1. Set up [YAML Frontmatter](frontmatter/) for standardized templates
+2. Configure [Copilot Space](frontmatter/YAML-Frontmatter-Copilot-Space-Instructions.md) for AI workflows
+3. Use [Schema Guidelines](frontmatter/YAML-Frontmatter%20Schema-Guidelines.md) for validation
+
+## 🎯 Core Principles
+
+- **Security First**: All patterns emphasize WordPress security best practices
+- **Accessibility**: WCAG 2.2 Level AA compliance baseline across all documentation
+- **Performance**: Optimization-focused approaches in all recommendations
+- **Modern Standards**: Up-to-date with latest WordPress and web development practices
+- **AI Integration**: Documentation patterns optimized for AI-assisted development workflows
+
+## 🔧 Standards at a Glance
+
+| Area | Standard | Key Features |
+|------|----------|--------------|
+| **Theme Development** | Block-first, Fluid Design | Responsive typography, Design tokens, Performance optimization |
+| **Code Quality** | WordPress + LightSpeed Standards | Security by default, WCAG 2.2 AA, PHPDoc documentation |
+| **AI Integration** | YAML Frontmatter Schemas | GitHub templates, Copilot Space, Cross-platform AI configs |
+| **Block Development** | Gutenberg Best Practices | Modern JavaScript, React patterns, WordPress APIs |
+
+---
+
+This documentation hub ensures consistent, secure, and maintainable WordPress development across all project types and development workflows.
\ No newline at end of file
diff --git a/block-themes/README.md b/block-themes/README.md
new file mode 100644
index 0000000..074893a
--- /dev/null
+++ b/block-themes/README.md
@@ -0,0 +1,40 @@
+# Block Themes Documentation
+
+This folder contains comprehensive documentation for WordPress block themes, covering modern theme development practices, fluid design systems, and best practices for creating responsive, accessible themes.
+
+## Files
+
+### Core Theme Development
+- **[Theme Structure](theme-structure-epi.md)** - Guidelines for organizing block theme files and structure
+- **[Templates](templates.md)** - Working with block theme templates and template parts
+- **[Patterns](patterns.md)** - Creating and managing block patterns for themes
+- **[Global Styles](global-styles.md)** - Implementing theme.json and global styling systems
+
+### Design Systems & Styling
+- **[Fluid Typography](fluid-typography.md)** - Responsive typography using clamp() and custom properties
+- **[Fluid Spacing](fluid-spacing.md)** - Implementing fluid spacing systems for responsive layouts
+- **[Fluid Typography & Spacing Guidelines](FluidTypography-Fluid-Spacing-Guidelines.md)** - Comprehensive guide to fluid design principles
+- **[Spacing Presets](spacing-presets.md)** - Defining and using spacing scale in theme.json
+- **[Typesets](typesets.md)** - Typography system configuration and best practices
+
+### Color & Visual Design
+- **[Colour Palettes](colour-palettes.md)** - Setting up theme color systems and palettes
+- **[Style Variations](style-variations.md)** - Creating theme style variations
+- **[Block Styles](block-styles.md)** - Custom block styling approaches
+- **[Section Styles](section-styles.md)** - Styling theme sections and layouts
+
+### Development Best Practices
+- **[CSS Specificity](css-specificity.md)** - Managing CSS specificity in block themes
+- **[Naming Conventions](naming-conventions.md)** - Consistent naming patterns for theme development
+- **[Standardising Colours, Fonts & Spacing](standardising-colours-fonts-spacing.md)** - Creating consistent design tokens
+
+### Additional Resources
+- **[Best Practices (Fluid Spacing & Typography)](best-practices-fluid-spacing-and%20typography.md)** - Advanced fluid design techniques
+- **[theme-68.json](theme-68.json)** - Example theme.json configuration file
+
+## Key Concepts
+
+- **Fluid Design**: Modern responsive design using CSS clamp() and custom properties
+- **Design Tokens**: Systematic approach to colors, typography, and spacing
+- **Block-First**: Designing themes around the block editor experience
+- **Progressive Enhancement**: Building accessible, performant themes that work everywhere
\ No newline at end of file
diff --git a/coding-standards/README.md b/coding-standards/README.md
new file mode 100644
index 0000000..9116d77
--- /dev/null
+++ b/coding-standards/README.md
@@ -0,0 +1,67 @@
+# Coding Standards Documentation
+
+This folder contains comprehensive coding standards and style guides for WordPress development, covering multiple approaches and specialized areas of development practice.
+
+## Directories
+
+### [LightSpeed Coding Standards](ash-research/)
+Complete coding standards suite aligned with WordPress Coding Standards (WPCS v3.2.0), incorporating guidance from industry leaders like 10up, Human Made, and Dekode.
+
+**Key Features:**
+- Comprehensive coverage: PHP, JavaScript, CSS, HTML, Accessibility, and more
+- Security-first approach with escaping, sanitization, and nonce requirements
+- WCAG 2.2 Level AA accessibility baseline
+- Performance-focused guidelines
+- Fluid spacing and typography standards
+
+### [WordPress Coding Standards](wordpress-coding-standards/)
+Official WordPress coding standards covering core development practices and community guidelines.
+
+**Includes:**
+- PHP coding standards and best practices
+- HTML structure and semantic guidelines
+- CSS styling conventions
+- JavaScript development standards
+- Accessibility requirements
+
+### [Inline Documentation Standards](inline-documentation-standards/)
+Specialized documentation focusing on code commenting and inline documentation practices.
+
+**Covers:**
+- PHP documentation standards (PHPDoc-inspired)
+- JavaScript commenting conventions
+- Best practices for maintainable code documentation
+
+## Top-Level Files
+
+### Reference Materials
+- **[WordPress Coding Standards](wordpress-coding-standards.md)** - Overview of official WordPress standards
+- **[Inline Documentation Standards](inline-documentation-standards.md)** - Guide to code documentation practices
+- **[Idiomatic CSS](idiomatic-css.md)** - CSS writing principles and conventions
+- **[Style Guide](styleguide.md)** - General style and formatting guidelines
+- **[Index](index.md)** - Comprehensive index of all standards and guidelines
+
+## Standards Hierarchy
+
+1. **Security First**: All code must follow security best practices
+2. **Accessibility**: WCAG 2.2 Level AA compliance baseline
+3. **Performance**: Lean dependencies and optimization-focused approach
+4. **Maintainability**: Clear documentation and consistent patterns
+5. **WordPress Compatibility**: Alignment with core WordPress practices
+
+## Key Principles
+
+- **Tabs for indentation** (spaces for alignment only)
+- **Security by default** (escaping, sanitization, nonces)
+- **Accessibility**: WCAG 2.2 Level AA baseline
+- **Performance**: Keep dependencies lean; measure, then optimize
+- **Documentation**: Prioritize clarity and maintainability
+
+## Getting Started
+
+1. **New to WordPress?** Start with [WordPress Coding Standards](wordpress-coding-standards/)
+2. **Working on a LightSpeed project?** Use [LightSpeed Coding Standards](ash-research/)
+3. **Need documentation guidance?** Check [Inline Documentation Standards](inline-documentation-standards/)
+4. **Writing CSS?** Review [Idiomatic CSS](idiomatic-css.md) principles
+
+These standards ensure consistency, security, and maintainability across all WordPress development projects.
\ No newline at end of file
diff --git a/coding-standards/inline-documentation-standards/README.md b/coding-standards/inline-documentation-standards/README.md
new file mode 100644
index 0000000..ba7a1bc
--- /dev/null
+++ b/coding-standards/inline-documentation-standards/README.md
@@ -0,0 +1,47 @@
+# Inline Documentation Standards
+
+WordPress coding standards for inline documentation, ensuring code is well-documented, maintainable, and follows established patterns for commenting and documentation blocks.
+
+## Files
+
+- **[PHP Documentation Standards](php.md)** - Complete guide to PHP documentation in WordPress using PHPDoc-inspired standards
+- **[JavaScript Documentation Standards](javascript.md)** - JavaScript commenting conventions and documentation practices
+
+## Overview
+
+These standards cover how to properly document your code using inline comments and documentation blocks. WordPress uses a customized documentation schema that draws inspiration from PHPDoc for PHP and established JavaScript documentation patterns.
+
+## Key Areas Covered
+
+### PHP Documentation
+- Function and method documentation blocks
+- Class and interface documentation
+- Property documentation
+- Parameter and return value documentation
+- WordPress-specific hooks and filters documentation
+- File header documentation
+
+### JavaScript Documentation
+- Function and method commenting
+- Object and class documentation
+- Module documentation patterns
+- Parameter and return documentation
+- Event handler documentation
+
+## Documentation Principles
+
+- **Clarity**: Documentation should make code easier to understand
+- **Completeness**: All public functions, classes, and methods should be documented
+- **Consistency**: Follow established patterns across the codebase
+- **Accuracy**: Keep documentation updated with code changes
+- **Helpful Context**: Explain not just what, but why and how
+
+## WordPress-Specific Requirements
+
+- Use WordPress-specific tags for hooks, filters, and actions
+- Document all parameters and return values
+- Include @since tags for version tracking
+- Follow WordPress coding standards for formatting
+- Use proper escaping and sanitization in examples
+
+These documentation standards ensure that WordPress code is accessible to developers at all levels and maintains consistency across projects.
\ No newline at end of file
diff --git a/coding-standards/wordpress-coding-standards/README.md b/coding-standards/wordpress-coding-standards/README.md
new file mode 100644
index 0000000..b45cdfe
--- /dev/null
+++ b/coding-standards/wordpress-coding-standards/README.md
@@ -0,0 +1,62 @@
+# WordPress Coding Standards
+
+Official WordPress coding standards covering all aspects of development within the WordPress ecosystem. These standards are mandatory for WordPress Core and strongly recommended for themes and plugins.
+
+## Files
+
+- **[PHP Coding Standards](php.md)** - Comprehensive PHP coding standards for WordPress development
+- **[HTML Coding Standards](html.md)** - HTML structure, semantics, and accessibility guidelines
+- **[CSS Coding Standards](css.md)** - CSS writing conventions and organization practices
+- **[JavaScript Coding Standards](javascript.md)** - JavaScript development standards and best practices
+- **[Accessibility Standards](accessibility.md)** - WCAG compliance and accessibility requirements
+
+## Overview
+
+These coding standards are not just about code style, but encompass established best practices regarding interoperability, translatability, and security in the WordPress ecosystem. While themes and plugins may choose different coding styles, these standards represent critical best practices that should be followed regardless of style preferences.
+
+## Core Principles
+
+### Security First
+- Sanitization of all input data
+- Escaping of all output data
+- Proper use of nonces for form security
+- SQL injection prevention
+- XSS attack mitigation
+
+### Accessibility
+- WCAG 2.1 AA compliance baseline
+- Semantic HTML structure
+- Proper ARIA attributes
+- Keyboard navigation support
+- Screen reader compatibility
+
+### Performance
+- Efficient database queries
+- Optimized asset loading
+- Minimal HTTP requests
+- Proper caching strategies
+- Mobile-first responsive design
+
+### Internationalization
+- Translatable strings using WordPress i18n functions
+- Proper text domain usage
+- RTL language support
+- Cultural sensitivity in design
+
+### Interoperability
+- WordPress coding patterns and conventions
+- Hook and filter usage
+- Plugin/theme compatibility
+- Core WordPress function usage
+
+## Implementation
+
+While not all existing code may fully comply with these standards, **all newly committed and/or updated code should fully comply** with these coding standards. This ensures progressive improvement of code quality across the WordPress ecosystem.
+
+## Related Resources
+
+- See [Inline Documentation Standards](../inline-documentation-standards/) for code commenting guidelines
+- Review [LightSpeed Coding Standards](../ash-research/) for enhanced standards building on these foundations
+- Check WordPress Developer Handbook for additional implementation guidance
+
+These standards form the foundation for secure, accessible, and maintainable WordPress development.
\ No newline at end of file
diff --git a/frontmatter/README.md b/frontmatter/README.md
new file mode 100644
index 0000000..fa5e330
--- /dev/null
+++ b/frontmatter/README.md
@@ -0,0 +1,48 @@
+# YAML Frontmatter Documentation
+
+This folder contains comprehensive documentation for YAML frontmatter usage across GitHub templates, AI agent configurations, and Copilot Space setups. Essential for standardizing metadata and configuration patterns in WordPress development workflows.
+
+## Files
+
+### Core Documentation
+- **[YAML Frontmatter Cheat Sheet](YAML%20Frontmatter%20Cheat%20Sheet.md)** - Quick reference guide for GitHub templates and AI agent configurations
+- **[YAML Frontmatter Schema Guidelines](YAML-Frontmatter%20Schema-Guidelines.md)** - Comprehensive schema documentation and validation patterns
+- **[YAML Frontmatter Copilot Space Instructions](YAML-Frontmatter-Copilot-Space-Instructions.md)** - Complete setup guide for Copilot Space with frontmatter standards
+
+### Additional Resources
+- **[YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files](YAML%20Frontmatter%20Schemas%20for%20GitHub,%20Copilot,%20Claude,%20and%20Gemini%20Files1.md)** - Platform-specific schema documentation
+
+## What's Covered
+
+### GitHub Templates
+- **Issue Forms**: YAML frontmatter for GitHub issue templates with form fields, labels, and assignments
+- **Pull Request Templates**: Frontmatter configuration (though not processed by GitHub, useful for documentation)
+- **Repository Configuration**: Standardizing template metadata across projects
+
+### AI Agent Configurations
+- **GitHub Copilot**: Instructions, prompts, and chat modes with proper frontmatter
+- **Claude Subagents**: Configuration schemas for Claude-specific agents and tools
+- **Gemini Integration**: Frontmatter patterns for Gemini-based workflows
+- **Universal Agents**: Cross-platform AI agent configuration standards
+
+### Copilot Space Setup
+- **File Structure**: Organizing AI-related files in repositories
+- **Schema Validation**: Ensuring consistent frontmatter across all template types
+- **Best Practices**: WordPress-friendly Copilot Space configurations
+- **Integration Patterns**: Connecting frontmatter with development workflows
+
+## Key Benefits
+
+- **Standardization**: Consistent metadata patterns across all template types
+- **Validation**: Schema-based validation for frontmatter correctness
+- **Automation**: AI-friendly configurations that enhance development workflows
+- **WordPress Integration**: Templates and patterns optimized for WordPress development
+- **Cross-Platform**: Works with GitHub, Copilot, Claude, Gemini, and other AI tools
+
+## Getting Started
+
+1. Start with the **[YAML Frontmatter Cheat Sheet](YAML%20Frontmatter%20Cheat%20Sheet.md)** for quick reference
+2. Review **[Schema Guidelines](YAML-Frontmatter%20Schema-Guidelines.md)** for detailed implementation
+3. Follow **[Copilot Space Instructions](YAML-Frontmatter-Copilot-Space-Instructions.md)** for complete setup
+
+This documentation ensures your WordPress projects maintain consistent, validated frontmatter across all GitHub templates and AI configurations.
\ No newline at end of file
From efef4cf4fcbacd17002d2bce19d414d0ef02fd4a Mon Sep 17 00:00:00 2001
From: Ashley Shaw
Date: Thu, 23 Oct 2025 12:00:26 +0700
Subject: [PATCH 3/4] Commit staged changes: urgent commit, pre-commit hooks
suppressed to allow progress. Review required for any missed lint or test
issues.
---
.all-contributorsrc | 37 +
.babelrc | 7 +
.coderabbit.yml | 198 +-
.distignore | 18 +
.editorconfig | 38 +
.env | 19 +
.eslintignore | 18 +
.eslintrc.cjs | 16 +
.eslintrc.json | 22 +
.gitattributes | 13 +
.gitignore | 32 +
.husky/pre-commit | 6 +
.markdownlint.json | 19 +
.npmpackagejsonlintrc.json | 10 +
.npmrc | 5 +
.nvmrc | 1 +
.prettierignore | 18 +
.prettierrc | 9 +
.prettierrc.js | 29 +
.shellcheckrc | 12 +
.spectral-workflows.yaml | 8 +
.spectral.yaml | 6 +
.yamllint | 12 +
AGENTS.md | 106 +
CHANGELOG.md | 123 +
CLAUDE.md | 172 +
CODEOWNERS | 7 +
CODE_OF_CONDUCT.md | 68 +
CONTRIBUTING.md | 108 +
DEVELOPMENT.md | 104 +
GEMINI.md | 172 +
GOVERNANCE.md | 73 +
LICENSE | 681 ++++
README.md | 226 +-
SECURITY.md | 14 +
SUPPORT.md | 17 +
SUPPRESSIONS.md | 24 +
VERSION | 1 +
YAML Frontmatter Cheat Sheet.md | 525 ----
...Hub, Copilot, Claude, and Gemini Files1.md | 30 -
...-Frontmatter-Copilot-Space-Instructions.md | 628 ----
block-themes/_temp.txt | 348 ---
...-practices-fluid-spacing-and typography.md | 47 -
block-themes/css-specificity.md | 43 -
block-themes/theme-68.json | 2733 ----------------
block-themes/theme-structure-epi.md | 53 -
block-themes/typesets.md | 23 -
coding-standards/_temp.md | 167 -
.../9-fluid-spacing-typography.md | 43 -
copilot-todo.md | 0
docs/ai-copilot/README.md | 0
.../coding-standards}/README.md | 11 +-
docs/coding-standards/_temp.md | 167 +
.../ash-research/0-common-standards.md | 10 +-
.../ash-research/1-accessibility.md | 3 +
.../coding-standards}/ash-research/2-php.md | 22 +-
.../ash-research/4-javascript.md | 9 +-
.../coding-standards}/ash-research/5-css.md | 16 +-
.../ash-research/6-inline-documentation.md | 25 +-
.../ash-research/7-markdown.md | 12 +-
.../coding-standards}/ash-research/8-json.md | 20 +-
.../9-fluid-spacing-typography.md | 53 +
.../coding-standards}/ash-research/README.md | 16 +-
.../coding-standards}/idiomatic-css.md | 260 +-
.../coding-standards}/index.md | 19 +-
.../inline-documentation-standards.md | 7 +-
.../inline-documentation-standards/README.md | 4 +-
.../javascript.md | 162 +-
.../inline-documentation-standards/php.md | 139 +-
.../coding-standards}/styleguide.md | 8 +-
.../wordpress-coding-standards.md | 11 +-
.../wordpress-coding-standards/README.md | 11 +-
.../accessibility.md | 2 +-
.../wordpress-coding-standards/css.md | 131 +-
.../wordpress-coding-standards/html.md | 16 +-
.../inline-documentation-standards/README.md | 0
.../wordpress-coding-standards/javascript.md | 241 +-
.../wordpress-coding-standards/php.md | 11 +-
{frontmatter => docs/frontmatter}/README.md | 7 +-
.../YAML Frontmatter Cheat Sheet.md | 747 +++++
.../YAML-Frontmatter Schema-Guidelines.md | 2526 +++++++++++++++
...-Frontmatter-Copilot-Space-Instructions.md | 328 +-
.../gutenberg}/getting-started/README.md | 16 +-
.../getting-started/devenv/README.md | 18 +-
.../devenv/get-started-with-create-block.md | 29 +-
.../devenv/get-started-with-wp-env.md | 24 +-
.../devenv/get-started-with-wp-scripts.md | 42 +-
.../devenv/nodejs-development-environment.md | 11 +-
.../gutenberg}/getting-started/faq.md | 29 +-
.../getting-started/fundamentals/README.md | 0
.../fundamentals/block-in-the-editor.md | 163 +-
.../fundamentals/block-json.md | 65 +-
.../fundamentals/block-wrapper.md | 40 +-
.../fundamentals/file-structure-of-a-block.md | 15 +-
.../javascript-in-the-block-editor.md | 35 +-
.../markup-representation-block.md | 4 +-
.../fundamentals/registration-of-a-block.md | 36 +-
.../fundamentals/static-dynamic-rendering.md | 96 +-
.../gutenberg}/getting-started/glossary.md | 0
.../getting-started/quick-start-guide.md | 6 +-
.../gutenberg}/getting-started/tutorial.md | 585 ++--
.../gutenberg}/how-to-guides/README.md | 0
.../gutenberg}/how-to-guides/accessibility.md | 6 +-
.../how-to-guides/block-tutorial/README.md | 0
.../applying-styles-with-stylesheets.md | 114 +-
.../block-tutorial/creating-dynamic-blocks.md | 154 +-
.../extending-the-query-loop-block.md | 227 +-
.../nested-blocks-inner-blocks.md | 240 +-
.../curating-the-editor-experience/README.md | 6 +-
.../block-locking.md | 30 +-
.../disable-editor-functionality.md | 50 +-
.../filters-and-hooks.md | 79 +-
.../patterns.md | 18 +-
.../theme-json.md | 205 ++
.../data-basics/1-data-basics-setup.md | 175 +-
.../data-basics/2-building-a-list-of-pages.md | 422 ++-
.../data-basics/3-building-an-edit-form.md | 511 +++
.../4-building-a-create-page-form.md | 366 +++
.../data-basics/5-adding-a-delete-button.md | 437 +++
.../how-to-guides/data-basics/README.md | 3 +-
.../media/create-form/basic-create-form.png | Bin
.../media/create-form/create-button.png | Bin
.../create-form/create-form-with-text.png | Bin
.../media/create-form/create-saving.png | Bin
.../media/create-form/created-item.png | Bin
.../media/create-form/edit-page-form.png | Bin
.../media/delete-button/delete-button.png | Bin
.../delete-button/deleting-in-progress.png | Bin
.../media/delete-button/snackbar-error.png | Bin
.../media/delete-button/snackbar-example.png | Bin
.../media/delete-button/snackbar-success.png | Bin
.../media/delete-button/snackbar.png | Bin
.../media/edit-form/edit-button.png | Bin
.../media/edit-form/form-editable.png | Bin
.../media/edit-form/form-error.png | Bin
.../media/edit-form/form-finished.png | Bin
.../media/edit-form/form-inactive.png | Bin
.../media/edit-form/form-populated.png | Bin
.../media/edit-form/form-scaffold.png | Bin
.../media/edit-form/form-spinner.png | Bin
.../media/edit-form/modal-initial.png | Bin
.../data-basics/media/finished-app.jpg | Bin
.../media/list-of-pages/fetch-the-data.jpg | Bin
.../media/list-of-pages/filter-field.jpg | Bin
.../media/list-of-pages/filter.jpg | Bin
.../media/list-of-pages/indicator.jpg | Bin
.../media/list-of-pages/make-a-table.jpg | Bin
.../media/list-of-pages/no-results.jpg | Bin
.../media/list-of-pages/pages-list.jpg | Bin
.../media/list-of-pages/part1-finished.jpg | Bin
.../media/list-of-pages/simple-list.jpg | Bin
.../media/list-of-pages/unclear-status.jpg | Bin
.../data-basics/media/setup/hello-from-js.jpg | Bin
.../enqueueing-assets-in-the-editor.md | 2 +
.../gutenberg}/how-to-guides/feature-flags.md | 36 +-
.../gutenberg}/how-to-guides/format-api.md | 218 +-
.../how-to-guides/internationalization.md | 80 +-
.../gutenberg}/how-to-guides/metabox.md | 133 +-
.../how-to-guides/notices/README.md | 66 +-
.../notices/block-editor-notice.png | Bin
.../notices/classic-editor-notice.png | Bin
.../how-to-guides/platform/README.md | 15 +-
.../platform/custom-block-editor.md | 197 +-
.../how-to-guides/plugin-sidebar-0.md | 402 ++-
.../how-to-guides/propagating-updates.md | 12 +-
.../gutenberg}/how-to-guides/themes/README.md | 2 +-
.../themes/global-settings-and-styles.md | 1592 +++++-----
.../how-to-guides/themes/theme-support.md | 258 +-
.../gutenberg}/how-to-guides/thunks.md | 210 +-
.../how-to-guides/widgets/README.md | 0
.../widgets/legacy-widget-block.md | 150 +-
.../how-to-guides/widgets/opting-out.md | 10 +-
.../how-to-guides/widgets/overview.md | 0
docs/gutenberg/reference-guides/README.md | 71 +
.../reference-guides/block-api/README.md | 22 +
.../block-api/block-annotations.md | 30 +-
.../block-api/block-api-versions.md | 5 +-
.../block-api/block-attributes.md | 276 +-
.../block-api/block-bindings.md | 210 +-
.../block-api/block-context.md | 154 +-
.../block-api/block-deprecation.md | 234 +-
.../block-api/block-edit-save.md | 248 +-
.../block-api/block-metadata.md | 659 ++--
.../block-api/block-patterns.md | 113 +-
.../block-api/block-registration.md | 224 +-
.../block-api/block-selectors.md | 60 +-
.../block-api/block-styles.md | 40 +-
.../block-api/block-supports.md | 784 ++---
.../block-api/block-templates.md | 152 +-
.../block-api/block-transforms.md | 188 +-
.../block-api/block-variations.md | 206 +-
.../reference-guides/core-blocks.md | 958 +++---
.../gutenberg/reference-guides/data/README.md | 20 +
.../data/data-core-annotations.md | 0
.../data/data-core-block-directory.md | 82 +-
.../data/data-core-block-editor.md | 1912 ++++++++++++
.../reference-guides/data/data-core-blocks.md | 634 ++++
.../data/data-core-commands.md | 40 +-
.../data/data-core-customize-widgets.md | 49 +-
.../data/data-core-edit-post.md | 166 +-
.../data/data-core-edit-site.md | 118 +-
.../data/data-core-edit-widgets.md | 141 +-
.../reference-guides/data/data-core-editor.md | 658 ++--
.../data/data-core-keyboard-shortcuts.md | 403 +++
.../data/data-core-notices.md | 380 +++
.../reference-guides/data/data-core-nux.md | 28 +-
.../data/data-core-preferences.md | 34 +-
.../data/data-core-reusable-blocks.md | 1 +
.../data/data-core-rich-text.md | 69 +-
.../data/data-core-viewport.md | 19 +-
.../reference-guides/data/data-core.md | 920 ++++++
.../reference-guides/filters/README.md | 0
.../filters/autocomplete-filters.md | 44 +-
.../reference-guides/filters/block-filters.md | 469 ++-
.../filters/editor-filters.md | 114 +-
.../filters/global-styles-filters.md | 42 +-
.../reference-guides/filters/i18n-filters.md | 79 +-
.../filters/parser-filters.md | 0
.../interactivity-api/README.md | 48 +-
.../interactivity-api/api-reference.md | 1077 ++++---
.../interactivity-api/core-concepts/README.md | 0
.../core-concepts/server-side-rendering.md | 336 +-
.../the-reactive-and-declarative-mindset.md | 345 +--
...l-state-local-context-and-derived-state.md | 831 +++++
.../core-concepts/using-typescript.md | 695 +++--
.../interactivity-api/iapi-about.md | 39 +-
.../interactivity-api/iapi-faq.md | 7 +-
.../iapi-quick-start-guide.md | 3 -
.../gutenberg}/reference-guides/packages.md | 6 +-
.../gutenberg}/reference-guides/richtext.md | 76 +-
.../reference-guides/slotfills/README.md | 351 +++
.../slotfills/main-dashboard-button.md | 32 +-
.../plugin-block-settings-menu-item.md | 22 +-
.../plugin-document-setting-panel.md | 92 +
.../slotfills/plugin-more-menu-item.md | 18 +-
.../slotfills/plugin-post-publish-panel.md | 12 +-
.../slotfills/plugin-post-status-info.md | 8 +-
.../slotfills/plugin-pre-publish-panel.md | 12 +-
.../plugin-sidebar-more-menu-item.md | 61 +
.../slotfills/plugin-sidebar.md | 54 +
.../theme-json-reference/README.md | 11 +
.../theme-json-reference/styles-versions.md | 57 +
.../theme-json-reference/theme-json-living.md | 364 +++
.../gutenberg}/schemas/README.md | 20 +-
docs/gutenberg/schemas/json/block.json | 931 ++++++
.../schemas/json/font-collection.json | 146 +
docs/gutenberg/schemas/json/theme.json | 2585 ++++++++++++++++
docs/gutenberg/schemas/json/wp-env.json | 158 +
.../wordpress/block-themes}/README.md | 7 +-
.../wordpress/block-themes/docs.template.md | 5 +-
.../block-themes/patterns}/patterns.md | 7 +-
.../block-themes/theme.json}/block-styles.md | 29 +-
.../theme.json}/colour-palettes.md | 10 +-
.../theme.json/fluid-best-practices.md | 46 +
.../theme.json/fluid-guidelines.md | 250 +-
.../block-themes/theme.json}/fluid-spacing.md | 82 +-
.../theme.json}/fluid-typography.md | 15 +-
.../block-themes/theme.json}/global-styles.md | 11 +-
.../theme.json}/naming-conventions.md | 24 +-
.../section-styles-best-practices.md | 622 ++--
.../theme.json}/section-styles.md | 133 +-
.../theme.json}/spacing-presets.md | 35 +-
.../standardising-colours-fonts-spacing.md | 152 +-
.../theme.json}/style-variations.md | 4 +
.../block-themes/theme.json/theme-68.json | 2563 +++++++++++++++
.../block-themes/theme.json/typesets.md | 13 +
eslint.config.js | 17 +
eslint.config.mjs | 20 +
extensions.json | 56 +
frontmatter/YAML Frontmatter Cheat Sheet.md | 525 ----
...Hub, Copilot, Claude, and Gemini Files1.md | 30 -
.../YAML-Frontmatter Schema-Guidelines.md | 906 ------
.../theme-json.md | 206 --
.../data-basics/3-building-an-edit-form.md | 553 ----
.../4-building-a-create-page-form.md | 396 ---
.../data-basics/5-adding-a-delete-button.md | 449 ---
gutenberg/reference-guides/README.md | 71 -
.../reference-guides/block-api/README.md | 22 -
gutenberg/reference-guides/data/README.md | 20 -
.../data/data-core-block-editor.md | 1913 ------------
.../reference-guides/data/data-core-blocks.md | 721 -----
.../data/data-core-keyboard-shortcuts.md | 440 ---
.../data/data-core-notices.md | 404 ---
gutenberg/reference-guides/data/data-core.md | 912 ------
...l-state-local-context-and-derived-state.md | 842 -----
.../reference-guides/slotfills/README.md | 369 ---
.../plugin-document-setting-panel.md | 100 -
.../plugin-sidebar-more-menu-item.md | 80 -
.../slotfills/plugin-sidebar.md | 69 -
.../theme-json-reference/README.md | 11 -
.../theme-json-reference/styles-versions.md | 57 -
.../theme-json-reference/theme-json-living.md | 361 ---
gutenberg/schemas/json/block.json | 1000 ------
gutenberg/schemas/json/font-collection.json | 146 -
gutenberg/schemas/json/theme.json | 2755 -----------------
gutenberg/schemas/json/wp-env.json | 163 -
jest.config.js | 17 +
jest.config.json.bak | 9 +
launch.json | 50 +
mcp.json | 17 +
wp-docs.code-workspace | 3 +-
301 files changed, 29410 insertions(+), 27484 deletions(-)
create mode 100644 .all-contributorsrc
create mode 100644 .babelrc
create mode 100644 .distignore
create mode 100644 .editorconfig
create mode 100644 .env
create mode 100644 .eslintignore
create mode 100644 .eslintrc.cjs
create mode 100644 .eslintrc.json
create mode 100644 .gitattributes
create mode 100644 .gitignore
create mode 100755 .husky/pre-commit
create mode 100644 .markdownlint.json
create mode 100644 .npmpackagejsonlintrc.json
create mode 100644 .npmrc
create mode 100644 .nvmrc
create mode 100644 .prettierignore
create mode 100644 .prettierrc
create mode 100644 .prettierrc.js
create mode 100644 .shellcheckrc
create mode 100644 .spectral-workflows.yaml
create mode 100644 .spectral.yaml
create mode 100644 .yamllint
create mode 100644 AGENTS.md
create mode 100644 CHANGELOG.md
create mode 100644 CLAUDE.md
create mode 100644 CODEOWNERS
create mode 100644 CODE_OF_CONDUCT.md
create mode 100644 CONTRIBUTING.md
create mode 100644 DEVELOPMENT.md
create mode 100644 GEMINI.md
create mode 100644 GOVERNANCE.md
create mode 100644 LICENSE
create mode 100644 SECURITY.md
create mode 100644 SUPPORT.md
create mode 100644 SUPPRESSIONS.md
create mode 100644 VERSION
delete mode 100644 YAML Frontmatter Cheat Sheet.md
delete mode 100644 YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files1.md
delete mode 100644 YAML-Frontmatter-Copilot-Space-Instructions.md
delete mode 100644 block-themes/_temp.txt
delete mode 100644 block-themes/best-practices-fluid-spacing-and typography.md
delete mode 100644 block-themes/css-specificity.md
delete mode 100644 block-themes/theme-68.json
delete mode 100644 block-themes/theme-structure-epi.md
delete mode 100644 block-themes/typesets.md
delete mode 100644 coding-standards/_temp.md
delete mode 100644 coding-standards/ash-research/9-fluid-spacing-typography.md
create mode 100644 copilot-todo.md
create mode 100644 docs/ai-copilot/README.md
rename {coding-standards => docs/coding-standards}/README.md (96%)
create mode 100644 docs/coding-standards/_temp.md
rename {coding-standards => docs/coding-standards}/ash-research/0-common-standards.md (75%)
rename {coding-standards => docs/coding-standards}/ash-research/1-accessibility.md (99%)
rename {coding-standards => docs/coding-standards}/ash-research/2-php.md (90%)
rename {coding-standards => docs/coding-standards}/ash-research/4-javascript.md (93%)
rename {coding-standards => docs/coding-standards}/ash-research/5-css.md (75%)
rename {coding-standards => docs/coding-standards}/ash-research/6-inline-documentation.md (58%)
rename {coding-standards => docs/coding-standards}/ash-research/7-markdown.md (81%)
rename {coding-standards => docs/coding-standards}/ash-research/8-json.md (64%)
create mode 100644 docs/coding-standards/ash-research/9-fluid-spacing-typography.md
rename {coding-standards => docs/coding-standards}/ash-research/README.md (70%)
rename {coding-standards => docs/coding-standards}/idiomatic-css.md (61%)
rename {coding-standards => docs/coding-standards}/index.md (64%)
rename {coding-standards => docs/coding-standards}/inline-documentation-standards.md (87%)
rename {coding-standards => docs/coding-standards}/inline-documentation-standards/README.md (99%)
rename {coding-standards => docs/coding-standards}/inline-documentation-standards/javascript.md (87%)
rename {coding-standards => docs/coding-standards}/inline-documentation-standards/php.md (93%)
rename {coding-standards => docs/coding-standards}/styleguide.md (98%)
rename {coding-standards => docs/coding-standards}/wordpress-coding-standards.md (88%)
rename {coding-standards => docs/coding-standards}/wordpress-coding-standards/README.md (96%)
rename {coding-standards => docs/coding-standards}/wordpress-coding-standards/accessibility.md (99%)
rename {coding-standards => docs/coding-standards}/wordpress-coding-standards/css.md (84%)
rename {coding-standards => docs/coding-standards}/wordpress-coding-standards/html.md (92%)
create mode 100644 docs/coding-standards/wordpress-coding-standards/inline-documentation-standards/README.md
rename {coding-standards => docs/coding-standards}/wordpress-coding-standards/javascript.md (86%)
rename {coding-standards => docs/coding-standards}/wordpress-coding-standards/php.md (98%)
rename {frontmatter => docs/frontmatter}/README.md (99%)
create mode 100644 docs/frontmatter/YAML Frontmatter Cheat Sheet.md
create mode 100644 docs/frontmatter/YAML-Frontmatter Schema-Guidelines.md
rename {frontmatter => docs/frontmatter}/YAML-Frontmatter-Copilot-Space-Instructions.md (58%)
rename {gutenberg => docs/gutenberg}/getting-started/README.md (85%)
rename {gutenberg => docs/gutenberg}/getting-started/devenv/README.md (86%)
rename {gutenberg => docs/gutenberg}/getting-started/devenv/get-started-with-create-block.md (89%)
rename {gutenberg => docs/gutenberg}/getting-started/devenv/get-started-with-wp-env.md (88%)
rename {gutenberg => docs/gutenberg}/getting-started/devenv/get-started-with-wp-scripts.md (93%)
rename {gutenberg => docs/gutenberg}/getting-started/devenv/nodejs-development-environment.md (91%)
rename {gutenberg => docs/gutenberg}/getting-started/faq.md (91%)
rename {gutenberg => docs/gutenberg}/getting-started/fundamentals/README.md (100%)
rename {gutenberg => docs/gutenberg}/getting-started/fundamentals/block-in-the-editor.md (75%)
rename {gutenberg => docs/gutenberg}/getting-started/fundamentals/block-json.md (89%)
rename {gutenberg => docs/gutenberg}/getting-started/fundamentals/block-wrapper.md (91%)
rename {gutenberg => docs/gutenberg}/getting-started/fundamentals/file-structure-of-a-block.md (98%)
rename {gutenberg => docs/gutenberg}/getting-started/fundamentals/javascript-in-the-block-editor.md (93%)
rename {gutenberg => docs/gutenberg}/getting-started/fundamentals/markup-representation-block.md (98%)
rename {gutenberg => docs/gutenberg}/getting-started/fundamentals/registration-of-a-block.md (89%)
rename {gutenberg => docs/gutenberg}/getting-started/fundamentals/static-dynamic-rendering.md (88%)
rename {gutenberg => docs/gutenberg}/getting-started/glossary.md (100%)
rename {gutenberg => docs/gutenberg}/getting-started/quick-start-guide.md (96%)
rename {gutenberg => docs/gutenberg}/getting-started/tutorial.md (79%)
rename {gutenberg => docs/gutenberg}/how-to-guides/README.md (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/accessibility.md (66%)
rename {gutenberg => docs/gutenberg}/how-to-guides/block-tutorial/README.md (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md (75%)
rename {gutenberg => docs/gutenberg}/how-to-guides/block-tutorial/creating-dynamic-blocks.md (66%)
rename {gutenberg => docs/gutenberg}/how-to-guides/block-tutorial/extending-the-query-loop-block.md (79%)
rename {gutenberg => docs/gutenberg}/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md (74%)
rename {gutenberg => docs/gutenberg}/how-to-guides/curating-the-editor-experience/README.md (97%)
rename {gutenberg => docs/gutenberg}/how-to-guides/curating-the-editor-experience/block-locking.md (89%)
rename {gutenberg => docs/gutenberg}/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md (86%)
rename {gutenberg => docs/gutenberg}/how-to-guides/curating-the-editor-experience/filters-and-hooks.md (84%)
rename {gutenberg => docs/gutenberg}/how-to-guides/curating-the-editor-experience/patterns.md (93%)
create mode 100644 docs/gutenberg/how-to-guides/curating-the-editor-experience/theme-json.md
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/1-data-basics-setup.md (59%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/2-building-a-list-of-pages.md (66%)
create mode 100644 docs/gutenberg/how-to-guides/data-basics/3-building-an-edit-form.md
create mode 100644 docs/gutenberg/how-to-guides/data-basics/4-building-a-create-page-form.md
create mode 100644 docs/gutenberg/how-to-guides/data-basics/5-adding-a-delete-button.md
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/README.md (95%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/create-form/basic-create-form.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/create-form/create-button.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/create-form/create-form-with-text.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/create-form/create-saving.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/create-form/created-item.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/create-form/edit-page-form.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/delete-button/delete-button.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/delete-button/deleting-in-progress.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/delete-button/snackbar-error.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/delete-button/snackbar-example.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/delete-button/snackbar-success.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/delete-button/snackbar.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/edit-form/edit-button.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/edit-form/form-editable.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/edit-form/form-error.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/edit-form/form-finished.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/edit-form/form-inactive.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/edit-form/form-populated.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/edit-form/form-scaffold.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/edit-form/form-spinner.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/edit-form/modal-initial.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/finished-app.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/filter-field.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/filter.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/indicator.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/make-a-table.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/no-results.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/pages-list.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/part1-finished.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/simple-list.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/list-of-pages/unclear-status.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/data-basics/media/setup/hello-from-js.jpg (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/enqueueing-assets-in-the-editor.md (99%)
rename {gutenberg => docs/gutenberg}/how-to-guides/feature-flags.md (81%)
rename {gutenberg => docs/gutenberg}/how-to-guides/format-api.md (63%)
rename {gutenberg => docs/gutenberg}/how-to-guides/internationalization.md (84%)
rename {gutenberg => docs/gutenberg}/how-to-guides/metabox.md (85%)
rename {gutenberg => docs/gutenberg}/how-to-guides/notices/README.md (66%)
rename {gutenberg => docs/gutenberg}/how-to-guides/notices/block-editor-notice.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/notices/classic-editor-notice.png (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/platform/README.md (92%)
rename {gutenberg => docs/gutenberg}/how-to-guides/platform/custom-block-editor.md (81%)
rename {gutenberg => docs/gutenberg}/how-to-guides/plugin-sidebar-0.md (63%)
rename {gutenberg => docs/gutenberg}/how-to-guides/propagating-updates.md (81%)
rename {gutenberg => docs/gutenberg}/how-to-guides/themes/README.md (79%)
rename {gutenberg => docs/gutenberg}/how-to-guides/themes/global-settings-and-styles.md (60%)
rename {gutenberg => docs/gutenberg}/how-to-guides/themes/theme-support.md (79%)
rename {gutenberg => docs/gutenberg}/how-to-guides/thunks.md (56%)
rename {gutenberg => docs/gutenberg}/how-to-guides/widgets/README.md (100%)
rename {gutenberg => docs/gutenberg}/how-to-guides/widgets/legacy-widget-block.md (68%)
rename {gutenberg => docs/gutenberg}/how-to-guides/widgets/opting-out.md (90%)
rename {gutenberg => docs/gutenberg}/how-to-guides/widgets/overview.md (100%)
create mode 100644 docs/gutenberg/reference-guides/README.md
create mode 100644 docs/gutenberg/reference-guides/block-api/README.md
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-annotations.md (85%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-api-versions.md (63%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-attributes.md (78%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-bindings.md (67%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-context.md (73%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-deprecation.md (56%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-edit-save.md (73%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-metadata.md (69%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-patterns.md (61%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-registration.md (76%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-selectors.md (79%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-styles.md (86%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-supports.md (59%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-templates.md (57%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-transforms.md (56%)
rename {gutenberg => docs/gutenberg}/reference-guides/block-api/block-variations.md (64%)
rename {gutenberg => docs/gutenberg}/reference-guides/core-blocks.md (60%)
create mode 100644 docs/gutenberg/reference-guides/data/README.md
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-annotations.md (100%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-block-directory.md (57%)
create mode 100644 docs/gutenberg/reference-guides/data/data-core-block-editor.md
create mode 100644 docs/gutenberg/reference-guides/data/data-core-blocks.md
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-commands.md (59%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-customize-widgets.md (58%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-edit-post.md (63%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-edit-site.md (62%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-edit-widgets.md (54%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-editor.md (54%)
create mode 100644 docs/gutenberg/reference-guides/data/data-core-keyboard-shortcuts.md
create mode 100644 docs/gutenberg/reference-guides/data/data-core-notices.md
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-nux.md (70%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-preferences.md (58%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-reusable-blocks.md (99%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-rich-text.md (64%)
rename {gutenberg => docs/gutenberg}/reference-guides/data/data-core-viewport.md (67%)
create mode 100644 docs/gutenberg/reference-guides/data/data-core.md
rename {gutenberg => docs/gutenberg}/reference-guides/filters/README.md (100%)
rename {gutenberg => docs/gutenberg}/reference-guides/filters/autocomplete-filters.md (54%)
rename {gutenberg => docs/gutenberg}/reference-guides/filters/block-filters.md (68%)
rename {gutenberg => docs/gutenberg}/reference-guides/filters/editor-filters.md (81%)
rename {gutenberg => docs/gutenberg}/reference-guides/filters/global-styles-filters.md (70%)
rename {gutenberg => docs/gutenberg}/reference-guides/filters/i18n-filters.md (51%)
rename {gutenberg => docs/gutenberg}/reference-guides/filters/parser-filters.md (100%)
rename {gutenberg => docs/gutenberg}/reference-guides/interactivity-api/README.md (61%)
rename {gutenberg => docs/gutenberg}/reference-guides/interactivity-api/api-reference.md (63%)
rename {gutenberg => docs/gutenberg}/reference-guides/interactivity-api/core-concepts/README.md (100%)
rename {gutenberg => docs/gutenberg}/reference-guides/interactivity-api/core-concepts/server-side-rendering.md (73%)
rename {gutenberg => docs/gutenberg}/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md (55%)
create mode 100644 docs/gutenberg/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md
rename {gutenberg => docs/gutenberg}/reference-guides/interactivity-api/core-concepts/using-typescript.md (68%)
rename {gutenberg => docs/gutenberg}/reference-guides/interactivity-api/iapi-about.md (95%)
rename {gutenberg => docs/gutenberg}/reference-guides/interactivity-api/iapi-faq.md (99%)
rename {gutenberg => docs/gutenberg}/reference-guides/interactivity-api/iapi-quick-start-guide.md (99%)
rename {gutenberg => docs/gutenberg}/reference-guides/packages.md (93%)
rename {gutenberg => docs/gutenberg}/reference-guides/richtext.md (62%)
create mode 100644 docs/gutenberg/reference-guides/slotfills/README.md
rename {gutenberg => docs/gutenberg}/reference-guides/slotfills/main-dashboard-button.md (70%)
rename {gutenberg => docs/gutenberg}/reference-guides/slotfills/plugin-block-settings-menu-item.md (68%)
create mode 100644 docs/gutenberg/reference-guides/slotfills/plugin-document-setting-panel.md
rename {gutenberg => docs/gutenberg}/reference-guides/slotfills/plugin-more-menu-item.md (66%)
rename {gutenberg => docs/gutenberg}/reference-guides/slotfills/plugin-post-publish-panel.md (73%)
rename {gutenberg => docs/gutenberg}/reference-guides/slotfills/plugin-post-status-info.md (73%)
rename {gutenberg => docs/gutenberg}/reference-guides/slotfills/plugin-pre-publish-panel.md (74%)
create mode 100644 docs/gutenberg/reference-guides/slotfills/plugin-sidebar-more-menu-item.md
create mode 100644 docs/gutenberg/reference-guides/slotfills/plugin-sidebar.md
create mode 100644 docs/gutenberg/reference-guides/theme-json-reference/README.md
create mode 100644 docs/gutenberg/reference-guides/theme-json-reference/styles-versions.md
create mode 100644 docs/gutenberg/reference-guides/theme-json-reference/theme-json-living.md
rename {gutenberg => docs/gutenberg}/schemas/README.md (73%)
create mode 100644 docs/gutenberg/schemas/json/block.json
create mode 100644 docs/gutenberg/schemas/json/font-collection.json
create mode 100644 docs/gutenberg/schemas/json/theme.json
create mode 100644 docs/gutenberg/schemas/json/wp-env.json
rename {block-themes => docs/wordpress/block-themes}/README.md (98%)
rename block-themes/templates.md => docs/wordpress/block-themes/docs.template.md (97%)
rename {block-themes => docs/wordpress/block-themes/patterns}/patterns.md (93%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/block-styles.md (69%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/colour-palettes.md (95%)
create mode 100644 docs/wordpress/block-themes/theme.json/fluid-best-practices.md
rename block-themes/FluidTypography-Fluid-Spacing-Guidelines.md => docs/wordpress/block-themes/theme.json/fluid-guidelines.md (87%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/fluid-spacing.md (66%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/fluid-typography.md (95%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/global-styles.md (97%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/naming-conventions.md (91%)
rename block-themes/best-practices-best-practices-.md => docs/wordpress/block-themes/theme.json/section-styles-best-practices.md (72%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/section-styles.md (79%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/spacing-presets.md (72%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/standardising-colours-fonts-spacing.md (66%)
rename {block-themes => docs/wordpress/block-themes/theme.json}/style-variations.md (99%)
create mode 100644 docs/wordpress/block-themes/theme.json/theme-68.json
create mode 100644 docs/wordpress/block-themes/theme.json/typesets.md
create mode 100644 eslint.config.js
create mode 100644 eslint.config.mjs
create mode 100644 extensions.json
delete mode 100644 frontmatter/YAML Frontmatter Cheat Sheet.md
delete mode 100644 frontmatter/YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files1.md
delete mode 100644 frontmatter/YAML-Frontmatter Schema-Guidelines.md
delete mode 100644 gutenberg/how-to-guides/curating-the-editor-experience/theme-json.md
delete mode 100644 gutenberg/how-to-guides/data-basics/3-building-an-edit-form.md
delete mode 100644 gutenberg/how-to-guides/data-basics/4-building-a-create-page-form.md
delete mode 100644 gutenberg/how-to-guides/data-basics/5-adding-a-delete-button.md
delete mode 100644 gutenberg/reference-guides/README.md
delete mode 100644 gutenberg/reference-guides/block-api/README.md
delete mode 100644 gutenberg/reference-guides/data/README.md
delete mode 100644 gutenberg/reference-guides/data/data-core-block-editor.md
delete mode 100644 gutenberg/reference-guides/data/data-core-blocks.md
delete mode 100644 gutenberg/reference-guides/data/data-core-keyboard-shortcuts.md
delete mode 100644 gutenberg/reference-guides/data/data-core-notices.md
delete mode 100644 gutenberg/reference-guides/data/data-core.md
delete mode 100644 gutenberg/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md
delete mode 100644 gutenberg/reference-guides/slotfills/README.md
delete mode 100644 gutenberg/reference-guides/slotfills/plugin-document-setting-panel.md
delete mode 100644 gutenberg/reference-guides/slotfills/plugin-sidebar-more-menu-item.md
delete mode 100644 gutenberg/reference-guides/slotfills/plugin-sidebar.md
delete mode 100644 gutenberg/reference-guides/theme-json-reference/README.md
delete mode 100644 gutenberg/reference-guides/theme-json-reference/styles-versions.md
delete mode 100644 gutenberg/reference-guides/theme-json-reference/theme-json-living.md
delete mode 100644 gutenberg/schemas/json/block.json
delete mode 100644 gutenberg/schemas/json/font-collection.json
delete mode 100644 gutenberg/schemas/json/theme.json
delete mode 100644 gutenberg/schemas/json/wp-env.json
create mode 100644 jest.config.js
create mode 100644 jest.config.json.bak
create mode 100644 launch.json
create mode 100644 mcp.json
diff --git a/.all-contributorsrc b/.all-contributorsrc
new file mode 100644
index 0000000..75cd396
--- /dev/null
+++ b/.all-contributorsrc
@@ -0,0 +1,37 @@
+{
+ "projectName": ".github",
+ "projectOwner": "lightspeedwp",
+ "repoType": "github",
+ "repoHost": "https://github.com",
+ "projectDescription": "GitHub Community Health files for LightSpeedWP organization",
+ "projectWebsite": "https://lightspeedwp.agency",
+ "license": "GPL-3.0-or-later",
+ "files": [
+ "README.md"
+ ],
+ "imageSize": 100,
+ "commit": false,
+ "commitConvention": "conventional",
+ "contributors": [
+ {
+ "login": "lightspeedwp",
+ "name": "LightSpeedWP",
+ "avatar_url": "https://avatars.githubusercontent.com/u/13472139?v=4",
+ "profile": "https://github.com/lightspeedwp",
+ "contributions": [
+ "ideas",
+ "fundingFinding",
+ "projectManagement",
+ "business",
+ "code",
+ "design",
+ "doc",
+ "infra",
+ "maintenance",
+ "test"
+ ]
+ }
+ ],
+ "contributorsPerLine": 7,
+ "linkToUsage": true
+}
diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..469d3d5
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,7 @@
+{
+ "presets": [
+ "@babel/preset-env",
+ "@babel/preset-typescript",
+ "@babel/preset-react"
+ ]
+}
diff --git a/.coderabbit.yml b/.coderabbit.yml
index c47ca9f..254717f 100644
--- a/.coderabbit.yml
+++ b/.coderabbit.yml
@@ -1,16 +1,186 @@
+# yaml-language-server: $schema=[https://coderabbit.ai/integrations/coderabbit-overrides.v2.json](https://coderabbit.ai/integrations/coderabbit-overrides.v2.json)
+
+# yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json
+language: 'en-uk'
+chat:
+ auto_reply: true
reviews:
+ # === Review Workflow Settings ===
+ status_checks:
+ required:
+ - markdownlint
+ - Run Tests
+ - ShellCheck
+ - Changelog
+ - Release
+ required_approvals: 2
+ auto_labels:
+ enabled: true
+ rules:
+ - path: 'scripts/**/*.sh'
+ label: 'shell'
+ - path: '**/*.md'
+ label: 'docs'
+ - path: 'workflows/**/*.yml'
+ label: 'ci'
+ - path: 'tests/**/*.bats'
+ label: 'test'
+ - path: 'scripts/**/*.js'
+ label: 'js'
+ - path: 'scripts/**/*.py'
+ label: 'python'
+ auto_assign:
+ enabled: true
+ reviewers:
+ - 'ashleyshaw'
+ path_filters:
+ # === Path Filters (Exclude from Review) ===
+ - '!build/**'
+ - '!dist/**'
+ - '!node_modules/**'
+ - '!.cache/**'
+ - '!.DS_Store'
+ - '!vendor/**'
+ - '!composer.lock'
+ - '!package-lock.json'
+ - '!yarn.lock'
+ - '!.phpunit.result.cache'
+ - '!.idea/**'
+ - '!*.zip'
+ - '!bin/**'
+ - '!test-results/**'
+ - '!playwright-report/**'
+ - '!blob-report/**'
+ - '!*.map'
+ # Allow markdown, config, workflows, and docs to be reviewed
+ request_changes_workflow: true # Require workflow for requesting changes
+ high_level_summary: true # Provide high-level summary in reviews
+ poem: false # Disable poem output in reviews
+ review_status: true # Show review status in output
+ collapse_walkthrough: true # Collapse walkthroughs by default
+ # === Auto Review Settings ===
+ auto_review:
+ enabled: true
+ drafts: false
+ base_branches:
+ - 'main'
+ - 'develop'
+ - 'feature/*'
+ - 'fix/*'
+ - 'update/*'
+ # === Path-Specific Review Instructions ===
path_instructions:
- - path: "**/*.md"
- instructions: |
- Review the Markdown documentation for:
- - Clarity and conciseness of explanations
- - Consistent formatting and heading structure
- - Proper use of code blocks and inline code
- - Correct spelling, grammar, and punctuation
- - Accurate and up-to-date technical information
- - Useful internal and external links
- - Well-organized sections and logical flow
-
- Additional context:
- - The repository contains documentation focused on block theme and block plug-in development topics for WordPress and related technologies.
- - Please ensure that technical docs are developer-friendly, accurate, and up-to-date.
+ # 1. Copilot & AI Files
+ - path: '.github/custom-instructions.md'
+ instructions: |
+ Review custom-instructions.md:
+ - Ensure the file is easy to navigate and up to date with org standards.
+ - Ensure the file is a dynamic index of all major Copilot files and instructions.
+ - Validate YAML frontmatter for completeness and accuracy.
+ - Confirm references to chatmodes.md, prompts.md, agent.md, AGENTS.md, and all **/.github/instructions/*.instructions.md files.
+ - Check for up-to-date cross-references and clear documentation of Copilot usage.
+
+early_access: true
+auto_labels:
+ enabled: true
+ - A canonical list of org wide default labels exists in this file "https://github.com/lightspeedwp/.github/blob/develop/.github/labels.yml" https://github.com/lightspeedwp/.github/blob/develop/.github/labeler.yml
+ - A set of labeler rules exist in this file "https://github.com/lightspeedwp/.github/blob/develop/.github/labeler.yml"
+auto_assign:
+ enabled: true
+ reviewers:
+ - 'ashleyshaw'
+auto_review:
+ enabled: true
+ ignore_title_keywords:
+ - 'WIP'
+ - 'DO NOT MERGE'
+ - 'DRAFT'
+ drafts: false
+ base_branches:
+ - 'main'
+ - 'develop'
+ - 'feature/*'
+
+ path_instructions:
+ - path: 'scripts/**/*.sh'
+ instructions: |
+ "Review shell scripts for:
+ - Header comments and metadata
+ - Error handling (set -euo pipefail)
+ - ShellCheck compliance
+ - Test coverage with Bats
+ - Security best practices
+ - Documentation in README"
+ - path: 'scripts/**/*.js'
+ instructions: |
+ "Review JS scripts for:
+ - ESLint compliance
+ - Modular structure
+ - Test coverage
+ - Documentation and usage examples"
+ - path: 'scripts/**/*.py'
+ instructions: |
+ "Review Python scripts for:
+ - PEP8 compliance
+ - Test coverage
+ - Inline documentation and docstrings"
+ - path: 'workflows/**/*.yml'
+ instructions: |
+ "Review workflows for:
+ - Linting and test enforcement
+ - Required status checks
+ - Use of verified Marketplace actions
+ - Documentation and maintainability"
+ - path: 'CHANGELOG.md'
+ instructions: |
+ "Review changelog for:
+ - Accurate entries for all changes
+ - Customer-facing release notes
+ - Compliance with Keep a Changelog format"
+ - path: 'README.md'
+ instructions: |
+ "Review README for:
+ - Usage instructions
+ - Automation feature documentation
+ - Test coverage and status badges
+ - Compliance with documentation standards"
+ - path: 'scripts/product_dev_project.sh'
+ instructions: |
+ "Review project automation script for GitHub ProjectV2:
+ - Ensure script supports all automatable ProjectV2 actions (create project, add fields, add items/issues, link repositories/teams, update project/fields/items/status)
+ - Validate use of helper functions for each mutation and CLI/GraphQL integration
+ - Check for modular, maintainable, and well-documented code
+ - Confirm error handling and logging for automation steps
+ - Ensure script is tested with Bats and covers edge cases
+ - Verify script updates and syncs project meta/template files as required
+ - Confirm alignment with repo governance and automation standards"
+ - path: 'scripts/**/*.sh'
+ instructions: |
+ "Review shell scripts for automation and governance:
+ - Ensure script header includes metadata (name, description, usage, author, date)
+ - Validate error handling with set -euo pipefail
+ - Check for ShellCheck compliance
+ - Confirm test coverage with Bats
+ - Review for security best practices (input validation, least privilege)
+ - Ensure documentation is provided in README or inline comments"
+ - path: '**/*.md'
+ instructions: |
+ "Review markdown files for:
+ - Clarity and conciseness
+ - Proper formatting and structure
+ - Spelling and grammar
+ - Relevant links and references"
+ - path: 'workflows/**/*.yml'
+ instructions: |
+ "Review CI/CD workflows for:
+ - Correct triggers and conditions
+ - Proper job definitions and steps
+ - Use of secrets and environment variables
+ - Compliance with best practices and security guidelines"
+ - path: 'tests/**/*.bats'
+ instructions: |
+ "Reviewbats tests for:
+ - Comprehensive test coverage
+ - Clear and descriptive test names
+ - Proper setup and teardown procedures
+ - Use of assertions and validations"
diff --git a/.distignore b/.distignore
new file mode 100644
index 0000000..79ea2f9
--- /dev/null
+++ b/.distignore
@@ -0,0 +1,18 @@
+# Exclude from plugin/theme distribution packages
+/.git
+/.github
+/node_modules
+/vendor
+/tests
+/bin
+/.vscode
+/.DS_Store
+/*.zip
+/*.tar.gz
+/*.log
+composer.json
+composer.lock
+package.json
+package-lock.json
+pnpm-lock.yaml
+*.map
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..9a95228
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,38 @@
+# YAML files
+[*.yml]
+indent_style = space
+indent_size = 2
+
+[*.yaml]
+indent_style = space
+indent_size = 2
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+charset = utf-8
+
+# PHP files - WordPress coding standards use tabs
+[*.php]
+indent_style = tab
+indent_size = 4
+
+# HTML files
+[*.html]
+indent_style = space
+indent_size = 4
+
+# CSS, SCSS, JavaScript, and JSON files
+[*.{css,scss,js,json}]
+indent_style = space
+indent_size = 2
+
+# Markdown files
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.env b/.env
new file mode 100644
index 0000000..d81bdad
--- /dev/null
+++ b/.env
@@ -0,0 +1,19 @@
+# Example .env file for local development and CI
+# Do NOT commit secrets to public repositories
+
+# Node.js/CI/CD
+NODE_ENV=development
+PORT=3000
+
+# WordPress/Database (if relevant)
+# DB_HOST=localhost
+# DB_USER=your_db_user
+# DB_PASSWORD=your_db_password
+# DB_NAME=your_db_name
+
+# API Keys (replace with your actual keys, do not commit real secrets)
+# API_KEY=your_api_key_here
+# GITHUB_TOKEN=your_github_token_here
+
+# Feature flags or custom config
+# FEATURE_X_ENABLED=true
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..c19184f
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,18 @@
+# Ignore files and directories that should not be formatted by Eslint
+
+# Node modules
+node_modules
+
+# Build directories
+build
+dist
+
+# Log files
+
+# Vendor directories
+vendor
+
+# Test directories
+coverage
+playwright-report
+test-results
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..18df04f
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,16 @@
+module.exports = {
+ root: true,
+ env: { es2022: true, browser: true, node: true },
+ parser: '@typescript-eslint/parser',
+ parserOptions: { sourceType: 'module', ecmaVersion: 'latest' },
+ plugins: ['@typescript-eslint', 'prettier'],
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:prettier/recommended',
+ ],
+ ignorePatterns: ['node_modules/', 'build/', 'dist/'],
+ rules: {
+ 'prettier/prettier': 'warn'
+ }
+};
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..adec0c8
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,22 @@
+{
+ "env": {
+ "node": true,
+ "es2022": true,
+ "jest": true
+ },
+ "extends": ["eslint:recommended", "plugin:jest/recommended", "plugin:prettier/recommended"],
+ "plugins": ["jest", "prettier"],
+ "parserOptions": {
+ "ecmaVersion": "latest",
+ "sourceType": "module"
+ },
+ "rules": {
+ "prettier/prettier": "error",
+ "no-console": "warn",
+ "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
+ "jest/expect-expect": "error",
+ "jest/no-disabled-tests": "warn",
+ "jest/no-focused-tests": "error",
+ "jest/prefer-to-have-length": "warn"
+ }
+}
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..2a8e447
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,13 @@
+# Normalize line endings
+* text=auto eol=lf
+
+# Treat lock files as text
+*.lock text
+*.bat text eol=crlf
+
+# Linguist: docs and examples
+docs/** linguist-documentation
+*.md linguist-documentation
+
+# Zip-friendly export ignore
+*.zip export-ignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..07d93e6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,32 @@
+# Node.js
+node_modules/ # Node dependencies
+npm-debug.log* # npm debug logs
+.DS_Store # macOS system file
+
+# PHP / Composer
+vendor/ # Composer dependencies
+.phpunit.result.cache # PHPUnit cache
+.idea/ # JetBrains IDE config
+
+# Lock Files
+pnpm-lock.yaml # pnpm lock file
+composer.lock # Composer lock file
+package-lock.json # npm lock file
+yarn.lock # Yarn lock file
+
+# Build related files & folders
+dist/ # Build output
+build/ # Build output
+.cache/ # Build/cache
+coverage/ # Test coverage output
+.sass-cache/ # Sass cache
+.git/ # Git directory (should not be in dist)
+.gitattributes # Git attributes (should not be in dist)
+bin/ # Binary scripts/tools
+*.zip # Zipped packages
+*.map # Source maps
+
+# Tests
+test-results/ # Playwright test results
+playwright-report/ # Playwright HTML reports
+blob-report/ # Playwright blob reports
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 0000000..c9f5ca9
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,6 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npm run lint:fix
+npm run format
+npm test
diff --git a/.markdownlint.json b/.markdownlint.json
new file mode 100644
index 0000000..11714dc
--- /dev/null
+++ b/.markdownlint.json
@@ -0,0 +1,19 @@
+{
+ "default": true,
+ "MD013": false,
+ "MD003": false,
+ "MD024": false,
+ "MD033": false,
+ "MD041": false,
+ "MD046": {
+ "style": "fenced"
+ },
+ "MD040": false,
+ "MD036": false,
+ "MD001": false,
+ "MD022": false,
+ "MD025": false,
+ "MD051": false,
+ "MD052": false,
+ "MD012": false
+}
diff --git a/.npmpackagejsonlintrc.json b/.npmpackagejsonlintrc.json
new file mode 100644
index 0000000..babe5fd
--- /dev/null
+++ b/.npmpackagejsonlintrc.json
@@ -0,0 +1,10 @@
+{
+ "rules": {
+ "name-format": "error",
+ "valid-values-name-scope": ["error", ["@lightspeedwp"]],
+ "version-format": "error",
+ "require-author": "warning",
+ "prefer-repository": "error",
+ "require-license": "error"
+ }
+}
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..34a408f
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1,5 @@
+save-exact=true
+package-lock=true
+fund=false
+engine-strict=true
+# resolution-mode=highest # Remove or comment out for deterministic installs
\ No newline at end of file
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..209e3ef
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+20
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..df29803
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,18 @@
+# Ignore files and directories that should not be formatted by Prettier
+
+# Node modules
+node_modules
+
+# Build directories
+build
+dist
+
+# Log files
+
+# Vendor directories
+vendor
+
+# Test directories
+coverage
+playwright-report
+test-results
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..a2d42ed
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,9 @@
+{
+ "semi": true,
+ "trailingComma": "es5",
+ "singleQuote": true,
+ "printWidth": 100,
+ "tabWidth": 2,
+ "useTabs": false,
+ "endOfLine": "lf"
+}
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000..c29ff29
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,29 @@
+/**
+ * Prettier Configuration
+ *
+ * Copyright (C) 2024 LightSpeed WP
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+module.exports = {
+ tabWidth: 4,
+ useTabs: false,
+ endOfLine: 'lf',
+ printWidth: 80,
+ singleQuote: true,
+ trailingComma: 'es5',
+ bracketSpacing: true,
+ arrowParens: 'always',
+};
diff --git a/.shellcheckrc b/.shellcheckrc
new file mode 100644
index 0000000..7eb0911
--- /dev/null
+++ b/.shellcheckrc
@@ -0,0 +1,12 @@
+# .shellcheckrc - ShellCheck configuration for LightSpeedWP
+# See: https://github.com/koalaman/shellcheck/blob/master/shellcheckrc.example
+
+# Enable all recommended warnings
+severity=style
+shell=bash
+external-sources=true
+exclude=SC1091,SC2154 # Example: exclude sourcing and undefined var warnings
+
+# Custom project rules (uncomment as needed)
+# source-path=./scripts
+# enable=all
diff --git a/.spectral-workflows.yaml b/.spectral-workflows.yaml
new file mode 100644
index 0000000..1acf91b
--- /dev/null
+++ b/.spectral-workflows.yaml
@@ -0,0 +1,8 @@
+extends: "./.spectral.yaml"
+rules:
+ github-action-mandatory-name:
+ description: GitHub Action must have a name
+ given: "$"
+ then:
+ field: "name"
+ function: truthy
diff --git a/.spectral.yaml b/.spectral.yaml
new file mode 100644
index 0000000..6dd8fca
--- /dev/null
+++ b/.spectral.yaml
@@ -0,0 +1,6 @@
+extends: "spectral:recommended"
+rules:
+ document-defined: true
+ no-empty-keys: true
+ # Allow GitHub Actions style matrix expressions
+ no-unused-variables: false
diff --git a/.yamllint b/.yamllint
new file mode 100644
index 0000000..9643f27
--- /dev/null
+++ b/.yamllint
@@ -0,0 +1,12 @@
+---
+extends: default
+
+rules:
+ line-length:
+ max: 120
+ allow-non-breakable-words: true
+ indentation:
+ spaces: 2
+ indent-sequences: consistent
+ trailing-spaces: disable
+ document-start: disable
\ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..17c8484
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,106 @@
+# LightSpeed – Global AI Rules (AGENTS.md)
+
+- Use UK English; optimise for clarity, scalability, maintainability and profitable outcomes.
+- Prefer minimal, modular solutions; justify heavier tools with return on investment and maintenance cost.
+- Follow WordPress Coding Standards (CSS, HTML, JavaScript, PHP) and inline‑documentation standards at all times.
+- All code changes must include lint fixes, relevant tests and a short rationale summarising the change.
+- Never output secrets. Treat production and customer data as sensitive. Follow the OWASP top 10 for web security.
+- Accessibility and performance are non‑negotiable; highlight potential issues during reviews.
+- Prefer `theme.json` and block components over bespoke code when feasible to avoid vendor lock‑in.
+- When unsure, propose safe defaults and ask **one** focused question to clarify requirements.
+
+## Global Principles & Agent Rules
+
+| Principle / Rule | Guidance / Details |
+| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Language** | Use UK English; optimise for clarity, scalability, maintainability, and profitable outcomes. |
+| **Modularity** | Prefer minimal, modular solutions; justify heavier tools with ROI and maintenance cost. |
+| **Coding Standards** | Follow [Coding Standards Instructions](.github/instructions/coding-standards.instructions.md) and [Linting Instructions](.github/instructions/linting.instructions.md) for all code (CSS, HTML, JS, PHP, etc.). |
+| **Code Changes** | All code changes must include lint fixes, relevant tests, and a short rationale summarising the change. |
+| **Security** | Never output secrets. Treat production and customer data as sensitive. Follow OWASP top 10. |
+| **Accessibility & Performance** | Non-negotiable; highlight potential issues during reviews. |
+| **WordPress Block Usage** | Prefer `theme.json` and block components over bespoke code to avoid vendor lock-in. |
+| **Safe Defaults & Questions** | When unsure, propose safe defaults and ask one focused question to clarify requirements. |
+
+---
+
+## Contribution Guidelines & Indexes
+
+| Area | File Reference | Notes / Usage |
+| -------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
+| **Coding Standards** | [.github/instructions/coding-standards.instructions.md](.github/instructions/coding-standards.instructions.md) | Unified standards for all code |
+| **Linting Standards** | [.github/instructions/linting.instructions.md](.github/instructions/linting.instructions.md) | Main index for all linting rules |
+| **HTML Templates** | [.github/instructions/html-template.instructions.md](.github/instructions/html-template.instructions.md) | Markup standards |
+| **Pattern Development** | [.github/instructions/pattern-development.instructions.md](.github/instructions/pattern-development.instructions.md) | Block patterns for WordPress |
+| **PHP Block Instructions** | [.github/instructions/php-block.instructions.md](.github/instructions/php-block.instructions.md) | PHP block usage |
+| **Theme JSON** | [.github/instructions/theme-json.instructions.md](.github/instructions/theme-json.instructions.md) | Theme configuration standards |
+
+**Other Key Indexes:**
+
+- **Linting Index:** [.github/instructions/linting.instructions.md](.github/instructions/linting.instructions.md)
+- **Coding Standards Index:** [.github/instructions/coding-standards.instructions.md](.github/instructions/coding-standards.instructions.md)
+
+---
+
+## PR Templates
+
+- Use the default PR template: [.github/PULL_REQUEST_TEMPLATE.md](.github/PULL_REQUEST_TEMPLATE.md)
+- Additional PR templates are available in: [.github/PULL_REQUEST_TEMPLATES/](.github/PULL_REQUEST_TEMPLATES/)
+ - Use the template most relevant to your change (e.g. feature, fix, documentation, etc.)
+
+---
+
+## Core Index Instructions
+
+Start here for all key standards:
+
+- [Coding Standards Index](.github/instructions/coding-standards.instructions.md): Unified standards, best practices, and documentation for all LightSpeed projects.
+- [Linting Instructions Index](.github/instructions/linting.instructions.md): Primary index and guidance for all linting rules, tools, and file-type-specific standards.
+
+---
+
+## Cross-References & Discoverability
+
+| Resource Name | Reference | Purpose / Notes |
+| ----------------------- | ---------------------------------------------------------------- | -------------------------------------------------------- |
+| **Custom Instructions** | [.github/custom-instructions.md](.github/custom-instructions.md) | Central Copilot/org instructions, prompts, and standards |
+| **Main Agent Index** | [.github/agents/agent.md](.github/agents/agent.md) | Directory of agent specs, stubs, usage, implementation |
+| **Chat Modes Index** | [.github/chatmodes/chatmodes.md](.github/chatmodes/chatmodes.md) | List and guidance for all chat modes |
+| **Prompts Index** | [.github/prompts/prompts.md](.github/prompts/prompts.md) | Master prompt index and authoring conventions |
+
+---
+
+## Instruction Indexes (Recommended Reference Pattern)
+
+Reference main index files directly in your workflow or documentation:
+
+- `@lightspeedwp/.github/files/.github/instructions/coding-standards.instructions.md`
+- `@lightspeedwp/.github/files/.github/instructions/linting.instructions.md`
+- For file-type or topic-specific instructions, see all files in `.github/instructions/`.
+
+---
+
+> For up-to-date standards, always reference the index instruction files above.
+> See also: [.github/custom-instructions.md](.github/custom-instructions.md) for central org-wide Copilot and agent guidance.
+
+## Language Usage: UK English vs. Code Standards
+
+- **Documentation & Comments:** Use UK English spelling (e.g., "colour", "optimise", "organisation") in all documentation, inline comments, and prose.
+- **Code, APIs & Identifiers:** Always use the spelling and conventions required by the underlying technology or WordPress Coding Standards. For example:
+ - Use `color` (not `colour`) in CSS, JavaScript, PHP, and JSON keys.
+ - Use WordPress function names, hooks, and filters as published, even if they use US spelling.
+- **Automation:** If using language normalisation scripts (e.g., `npm run lang:en-gb`), ensure they exclude:
+ - Code blocks in Markdown
+ - CSS/JS/PHP identifiers
+ - Theme and block JSON keys
+
+> **Example:**
+>
+> - Documentation: "The primary colour palette is defined in `theme.json`."
+> - CSS: `color: #fff;` (not `colour`)
+> - JavaScript: `const backgroundColor = '#fff';`
+> - PHP: `$text_color = '#fff';`
+
+**Rationale:**
+
+- This approach ensures clarity for contributors, avoids breaking code, and aligns with both LightSpeed and WordPress standards.
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..31e221d
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,123 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased] - DD-MM-YYYY
+
+
+
+### Added
+
+### Changed
+
+- Removed build step from required scripts and pre-commit checklist (no build process required for this repo).
+- Resolved Jest configuration conflict (removed duplicate config file).
+
+### Deprecated
+
+### Documentation
+
+- Fixed markdownlint errors and improved accessibility (image alt text, code block style, ordered list prefixes).
+- Added and clarified language usage guidance (UK English vs. code standards) in `AGENTS.md`.
+- Updated documentation for clarity, maintainability, and compliance with WordPress and LightSpeed standards.
+
+### Fixed
+
+### Performance
+
+### Removed
+
+### Security
+
+-->
+
+## [0.1.0] - 2025-09-25
+
+### Added
+
+- Initial release of LightSpeed WordPress organization community health files
+- GitHub Copilot custom instructions and organization-wide guidelines
+- Comprehensive instruction files for WordPress development:
+ - `coding-standards.instructions.md` - WordPress coding standards for PHP, JS, CSS
+ - `html-template.instructions.md` - Block template and template part guidelines
+ - `pattern-development.instructions.md` - Block pattern creation and advanced usage
+ - `php-block.instructions.md` - PHP block development and theme setup
+ - `playwright-tests.instructions.md` - Browser automation and accessibility testing
+ - `theme-json.instructions.md` - Theme.json configuration and design tokens
+- AI prompt templates for:
+ - `accessibility-review.prompt.md` - Accessibility compliance review
+ - `dev-code-review.prompt.md` - Code review and standards verification
+ - `pattern-generation.prompt.md` - Block pattern generation assistance
+ - `refactor-theme-types.prompt.md` - WordPress theme refactoring guidance
+- Issue templates for comprehensive project management:
+ - Bug reports, feature requests, documentation requests
+ - Performance issues, UX feedback, integration issues
+ - Code refactoring, task management, custom instructions proposals
+- Pull request templates with WordPress-specific checklists
+- VS Code configuration optimized for WordPress development:
+ - MCP (Model Context Protocol) auto-start configuration
+ - WordPress-specific extensions and settings
+ - GitHub Copilot integration with custom instructions
+ - Proper file associations for instruction and prompt files
+- Example WordPress block structure following best practices
+- Comprehensive documentation and README files
+- GitHub Actions workflows for issue metrics and labeling
+- Saved replies for common support scenarios
+- Organization profile README showcasing LightSpeed projects
+
+### Deprecated
+
+- [placeholder]
+
+### Fixed
+
+- Standardized YAML frontmatter across all instruction files
+- Corrected indentation and formatting inconsistencies
+- Aligned VS Code settings with repository structure
+- Removed non-standard configuration keys for better compatibility
+
+### Changed
+
+- Updated author attribution to "LightSpeedWP Team" for consistency
+- Standardized related_links format as simple URL lists
+- Enhanced MCP configuration for WordPress development context
+- Improved file associations and discovery paths for AI tools
+
+### Documentation
+
+- Added comprehensive README files for instructions and prompts
+- Created implementation guide for WordPress block development
+- Established clear contribution guidelines and coding standards
+- Documented VS Code configuration and MCP setup procedures
+
+### Performance
+
+- [placeholder]
+
+### Removed
+
+- [placeholder]
+
+### Security
+
+- Implemented proper input sanitization and output escaping in examples
+- Added security guidelines in coding standards
+- Established secure development practices in instruction files
+
+## Reference
+
+- [Branching Strategy](.github/BRANCHING_STRATEGY.md): Org-wide branch naming, merge discipline, and automation mapping.
+- [CHANGELOG.md](./CHANGELOG.md): Changelog format, release notes, and versioning.
+- [CONTRIBUTING.md](./CONTRIBUTING.md): Contribution guidelines, templates, coding standards.
+- [AUTOMATION_GOVERNANCE.md](.github/AUTOMATION_GOVERNANCE.md): Org-wide automation, branching, labeling, and release strategy.
+- [Org-wide Issue Labels](.github/ISSUE_LABELS.md): Default labels and usage guidance.
+- [Pull Request Labels](.github/PR_LABELS.md): PR classification and automation standards.
+- [Issue Types Guide](.github/ISSUE_TYPES.md): Classification and usage of issue types.
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..9c11991
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,172 @@
+---
+title: 'CLAUDE.md Template'
+version: 'v1.1'
+last_updated: '2025-10-21'
+author: 'LightSpeed'
+maintainer: 'Ash Shaw'
+description: 'Root-level guidance for Claude agents, aligned with LightSpeed organisational standards.'
+tags: ['lightspeed', 'templates', 'copilot', 'agents', 'prompts', 'models']
+type: 'agent'
+references:
+ - 'https://github.com/lightspeedwp/.github/blob/master/.github/custom-instructions.md'
+ - 'https://github.com/lightspeedwp/.github/blob/master/AGENTS.md'
+ - 'https://github.com/lightspeedwp/.github/blob/master/.github/instructions/coding-standards.instructions.md'
+---
+
+# Role (required)
+
+You are a Claude agent operating within LightSpeed. Follow LightSpeed's [AGENTS.md](https://github.com/lightspeedwp/.github/blob/master/AGENTS.md), [custom instructions](https://github.com/lightspeedwp/.github/blob/master/.github/custom-instructions.md), and project-specific frameworks to deliver modular, maintainable WordPress solutions. Use UK English. Avoid non-WordPress tools, custom code, or exposing secrets unless explicitly directed.
+
+# Style (required)
+
+- Write modular, maintainable, and testable code and documentation.
+- Use semantic, accessible markup and descriptive comments per WordPress standards.
+- Optimise for performance, accessibility, and scalability.
+- Justify any tool or pattern outside LightSpeed defaults with clear rationale.
+
+# Purpose (required)
+
+- Deliver clear, secure, and scalable outcomes for LightSpeed WordPress projects.
+- Ensure all outputs meet LightSpeed’s standards for clarity, maintainability, security, and accessibility.
+- Support and automate workflows for efficient Figma → WordPress handoff.
+
+# Type of Task (required)
+
+- Coding, code review, documentation, prompt authoring, agentic workflow design, and process checklists for WordPress and web projects.
+- Validate outputs against [LightSpeed coding standards](https://github.com/lightspeedwp/.github/blob/master/.github/instructions/coding-standards.instructions.md), linting, and accessibility requirements.
+
+# How to ask for help (required)
+
+- Reference this Space and LightSpeed documentation first.
+- Ask a single, focused question if requirements or context are unclear.
+- Escalate blockers by tagging the maintainer and referencing relevant documentation or index files.
+
+# Conventions (optional)
+
+- Use YAML frontmatter in documentation.
+- Reference core index files for standards ([see AGENTS.md](https://github.com/lightspeedwp/.github/blob/master/AGENTS.md)).
+- Track issues and PRs via GitHub; reference/close issues in commit messages.
+
+# Process (required)
+
+- Start by checking AGENTS.md and custom-instructions.md for current org rules.
+- Confirm project scope and constraints before coding.
+- Use GitHub Issues and PRs for all changes; follow the [pull request template](https://github.com/lightspeedwp/.github/blob/master/.github/PULL_REQUEST_TEMPLATE.md).
+- Log rationale and testing coverage for every change.
+
+# Examples (optional)
+
+- See [prompts index](https://github.com/lightspeedwp/.github/blob/master/.github/prompts/prompts.md) for reusable prompt files.
+- Example outputs: accessible markup, modular WordPress block patterns, documented workflow YAML.
+
+# Important notes (optional)
+
+- Never expose secrets or sensitive data.
+- Accessibility and performance are non-negotiable.
+- Update documentation and rationale with every material change.
+
+# Who is this for (optional)
+
+- Claude agents, contributors, and maintainers working on LightSpeed WordPress projects.
+
+# Responsibilities (optional)
+
+- Validate code and outputs against LightSpeed standards.
+- Document decisions, tests, and rationale.
+- Promote safe and maintainable workflows.
+
+# Patterns or Frameworks to Follow (optional)
+
+- Use WordPress core blocks, theme.json, and native block patterns.
+- Reference LightSpeed’s pattern development and coding standards instructions.
+
+# Practices (optional)
+
+- Prefer safe defaults; modularity over complexity.
+- Use semantic CSS naming and ARIA roles for accessibility.
+- Automate linting and tests before merging PRs.
+
+# Tools (optional)
+
+- Use WordPress tools, GitHub Actions, Playwright for testing.
+- Avoid introducing bespoke tools unless justified.
+
+# Coverage (optional)
+
+- Ensure test coverage for new features and workflows.
+- Use Playwright, Jest, or equivalent per project language.
+
+# Constraints (required)
+
+- Follow UK English, WordPress coding standards, and OWASP top 10 security rules.
+- Accessibility and performance must be validated and documented.
+- Only use approved tools and frameworks unless justified.
+
+# What to do (required)
+
+- Reference core indexes and instructions before starting work.
+- Document rationale, tests, and accessibility for all changes.
+- Ask clarifying questions if requirements are ambiguous.
+
+# What not do (required)
+
+- Do not output secrets, credentials, or sensitive data.
+- Do not bypass linting, testing, or documentation standards.
+- Do not use non-WordPress or unapproved tools without approval.
+
+# Best Practices (required)
+
+- Adhere to WordPress and LightSpeed coding/documentation standards.
+- Promote accessibility and semantic markup.
+- Propose modular, maintainable solutions and safe defaults.
+
+# Guardrails (required)
+
+- Always validate outputs against LightSpeed coding, security, and accessibility standards.
+- Flag and document any deviations from best practice.
+- Reference AGENTS.md for global principles.
+
+# Checklist relevant to instructions (required)
+
+- [ ] Used UK English and WordPress standards.
+- [ ] Provided modular, maintainable code and documentation.
+- [ ] Automated linting and accessibility validation.
+- [ ] Documented rationale and tests.
+- [ ] Referenced relevant LightSpeed instruction/index files.
+- [ ] Avoided secrets and unapproved tools.
+
+# Outputs (required)
+
+- Modular code, accessible markup, documented workflows, rationale, and test results.
+- YAML frontmatter in documentation.
+- PRs and issues tracked via GitHub.
+
+# Contribution & Collaboration (optional)
+
+- Collaborate via GitHub Issues and PRs.
+- Reference AGENTS.md and custom-instructions.md for org-wide guidance.
+- Tag maintainers for blockers or review.
+
+# Non-goals (optional)
+
+- Do not provide generic, non-WordPress solutions.
+- Do not deviate from LightSpeed and WordPress standards.
+
+# Resource links (optional)
+
+- [LightSpeed Custom Instructions](https://github.com/lightspeedwp/.github/blob/master/.github/custom-instructions.md)
+- [AGENTS.md](https://github.com/lightspeedwp/.github/blob/master/AGENTS.md)
+- [Coding Standards](https://github.com/lightspeedwp/.github/blob/master/.github/instructions/coding-standards.instructions.md)
+- [Prompts Index](https://github.com/lightspeedwp/.github/blob/master/.github/prompts/prompts.md)
+- [Pull Request Template](https://github.com/lightspeedwp/.github/blob/master/.github/PULL_REQUEST_TEMPLATE.md)
+
+# Prompt (required — see D2)
+
+- Write a concise, actionable prompt tailored to the task, referencing relevant LightSpeed standards, instructions, and indexes.
+- Validate the output against coding, accessibility, and security requirements.
+
+---
+
+Provide safe defaults; mark optional flags clearly.
+Start by referencing any LightSpeed internal process, documentation, or best practice. This Space is your single source of truth for LightSpeed workflows.
+Aim for small, safe, well-documented steps that make the Figma → WordPress handoff effortless.
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 0000000..102b87b
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1,7 @@
+# CODEOWNERS for LightSpeed WP Scripts
+
+# See
+
+# All files in the repo
+
+* @ashleyshaw @lightspeedwp
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..dfb3980
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,68 @@
+# LightSpeed Code of Conduct (Aligned with the WordPress Community)
+
+## Our Pledge
+
+As contributors and maintainers of LightSpeed and the [lightspeedwp](https://github.com/lightspeedwp) GitHub organization, and as members of the broader WordPress community, we pledge to make participation in our project and community a welcoming, respectful, and harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community, in line with the [WordPress Community Code of Conduct](https://make.wordpress.org/community/handbook/code-of-conduct/).
+
+## Our Standards
+
+Examples of behavior that contribute to a positive environment for our community include:
+
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy and kindness toward other community members
+
+Examples of unacceptable behavior by participants include:
+
+- The use of sexualized language or imagery and unwelcome sexual attention or advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others’ private information, such as a physical or electronic address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Enforcement Responsibilities
+
+Project maintainers and community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
+
+Project maintainers and community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all LightSpeed and lightspeedwp community spaces, including GitHub repositories, issues, pull requests, and any public or private communication channels. It also applies when an individual is officially representing the project or community in public spaces, such as using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the LightSpeed community leaders at [support@lightspeedwp.agency](mailto:support@lightspeedwp.agency). All complaints will be reviewed and investigated promptly and fairly, and will be handled in accordance with the principles of the WordPress community.
+
+All LightSpeed community leaders are obligated to respect the privacy and security of the reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
+
+1. **Correction**
+ - _Community Impact_: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
+
+1. **Warning**
+ - _Community Impact_: A violation through a single incident or series of actions.
+
+1. **Temporary Ban**
+ - _Community Impact_: A serious violation of community standards, including sustained inappropriate behavior.
+
+1. **Permanent Ban**
+ - _Community Impact_: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
+ - _Consequence_: A permanent ban from any sort of public interaction within the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [WordPress Community Code of Conduct](https://make.wordpress.org/community/handbook/code-of-conduct/) and the [Contributor Covenant][homepage], version 2.0, available at , and customized for the LightSpeed and lightspeedwp GitHub community.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at . Translations are available at .
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..487c657
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,108 @@
+# Contributing
+
+**Last Updated:** 2025-10-21 • **Version:** v0.2.0
+
+Thank you for your interest in contributing to LightSpeed!
+To maintain a consistent, high-quality codebase and community, please follow these guidelines.
+
+---
+
+## Getting Started
+
+### 1. Start with a GitHub Issue
+
+- **Select the correct [Issue template](https://github.com/lightspeedwp/.github/issues/new/choose)** for your contribution type:
+ - Bug report, feature/enhancement, documentation, integration, performance, UX feedback, task, code refactor, instructions, prompts, saved replies, or support question.
+ - Templates are designed to collect all required information, labels, and metadata for automation and efficient triage.
+- **Provide thorough details:**
+ - For bugs: include reproduction steps, expected vs actual behavior, screenshots, logs, and environment info.
+ - For features/enhancements: describe the problem/opportunity, proposed solution, mockups/designs, and acceptance criteria.
+ - For other types: explain context, goals, action items, and impact.
+- **Reference relevant docs or standards:**
+ See [Coding Standards](.github/instructions/coding-standards.instructions.md), [Pattern Development](.github/instructions/pattern-development.instructions.md), [Theme JSON](.github/instructions/theme-json.instructions.md), etc.
+- **Outline your planned approach for complex issues** and request feedback before implementation.
+- **Automation:** Well-formed issues using the right template are automatically labeled, routed, and prioritized.
+
+### 2. Branching & Development
+
+- **Branch naming:**
+ Use `{type}/{scope}-{short-title}` format (e.g., `feat/cart-coupon-flow`, `fix/wp6-6-compat`, `docs/readme-install-steps`, `chore/deps-2025-09`).
+- **Allowed prefixes:**
+ `feat/`, `fix/`, `docs/`, `chore/`, `build/`, `refactor/`, `test/`, `perf/`, `ci/`, `release/`, `hotfix/`, `design/`, `research/`.
+- See [Org-wide Branching Strategy](.github/git-org-wide-branching-strategy.md) for full rules and automation mapping.
+- Ensure your branch maps to the correct issue type and PR template for automated labeling and changelog governance.
+
+### 3. Coding Standards
+
+- Follow [LightSpeed coding standards](.github/instructions/coding-standards.instructions.md) for PHP, JS, CSS, and other languages.
+- Use configured linters/formatters (e.g. ESLint, Prettier, PHPCS) and ensure all code passes checks.
+- Write clear, concise commit messages and document significant changes inline.
+
+---
+
+## Pull Requests
+
+### 4. Create a Pull Request (PR)
+
+- **Select the correct PR template:**
+ Bugfix, Feature, Chore, Docs, Build/CI, Dependencies/Maintenance, Hotfix, Release, Refactor, or General PR template.
+ - Your branch prefix should match the PR template (e.g., `fix/` → Bugfix PR, `feat/` → Feature PR).
+ - See [PR_LABELS.md](.github/PR_LABELS.md) for template-to-label mapping and automation.
+- **Required PR details:**
+ - Accurate, up-to-date description.
+ - Link to the related GitHub Issue.
+ - Testing instructions or demo (video/screenshots preferred for UI changes).
+ - Changelog entry following [CHANGELOG.md](./CHANGELOG.md) guidelines, grouped under the correct section.
+ - Document any skipped tests and provide justification.
+ - For version bumps, include release notes and summary.
+- **Draft PRs:** If not ready for review, open as Draft. Convert to ready once complete.
+
+### 5. Review & Merge
+
+- PRs are reviewed by maintainers, Copilot, or designated reviewers.
+- Respond to feedback and make requested changes.
+- Only maintainers can approve and merge PRs.
+- PRs must pass all CI checks/tests before merging.
+
+---
+
+## Additional Guidelines
+
+## VS Code Setup
+
+To ensure a consistent development experience and code quality, all contributors should:
+
+- Install all recommended extensions from `.vscode/extensions.json` (includes ESLint, Prettier, YAML, WordPress, PHP, AI, and GitHub workflow tools).
+- Use the workspace settings in `.vscode/settings.json` for code style, linting, and workflow automation. These settings align with `.editorconfig` and enforce 2-space indentation for YAML, JS, CSS, and JSON, and 4-space tabs for PHP.
+- Enable format-on-save and linting in your editor for best results.
+- Periodically review and update your extensions to match evolving project standards.
+
+Refer to `.vscode/extensions.json` and `.vscode/settings.json` for the authoritative list and configuration.
+
+- **Saved Replies:** Use [SAVED_REPLIES.md](.github/SAVED_REPLIES.md) for common responses and efficient communication.
+- **Documentation:** Update relevant docs (README, instructions) for any user-facing change.
+- **Automation & Labels:** Ensure your issue/PR complies with [AUTOMATION_GOVERNANCE.md](.github/AUTOMATION_GOVERNANCE.md), [ISSUE_LABELS.md](.github/ISSUE_LABELS.md), and [ISSUE_TYPES.md](.github/ISSUE_TYPES.md).
+- **Changelog:** All user-facing changes, fixes, and features must be entered in [CHANGELOG.md](./CHANGELOG.md) in Keep a Changelog format. See example sections in the changelog for proper grouping and linking.
+
+---
+
+## References
+
+- [BRANCHING_STRATEGY.md](.github/BRANCHING_STRATEGY.md): Org-wide branch naming, merge discipline, and automation mapping.
+- [CHANGELOG.md](./CHANGELOG.md): Changelog format, release notes, and versioning.
+- [AUTOMATION_GOVERNANCE.md](.github/AUTOMATION_GOVERNANCE.md): Org-wide automation, branching, label, and release strategy.
+- [ISSUE_TYPES.md](.github/ISSUE_TYPES.md): Issue type mapping and usage.
+- [ISSUE_LABELS.md](.github/ISSUE_LABELS.md): Label families, triage, and workflow.
+- [PR_LABELS.md](.github/PR_LABELS.md): PR labeling, templates, and automation.
+- [Org-wide Branching Strategy](.github/git-org-wide-branching-strategy.md): Full branching convention and rules.
+- [Coding Standards](.github/instructions/coding-standards.instructions.md)
+- [Pattern Development](.github/instructions/pattern-development.instructions.md)
+- [Theme JSON](.github/instructions/theme-json.instructions.md)
+
+---
+
+## License
+
+By contributing to this project, you agree that your contributions will be licensed under the GNU General Public License v3.0. See the [LICENSE](LICENSE) file for details.
+
+Thank you for helping us make LightSpeed better!
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
new file mode 100644
index 0000000..9584ab7
--- /dev/null
+++ b/DEVELOPMENT.md
@@ -0,0 +1,104 @@
+# Community Health Repository Setup
+
+This document provides guidance for contributing to and maintaining this community health repository for the [LightSpeed](https://github.com/lightspeedwp/) organization.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) (v18 or later)
+- [npm](https://www.npmjs.com/) (v9 or later)
+
+## Installation & Package Review
+
+1. Clone the repository:
+
+ ```bash
+ git clone https://github.com/lightspeedwp/.github.git
+ cd .github
+ ```
+
+2. Install dependencies:
+
+ ```bash
+ npm install
+ ```
+
+3. **Review `package.json`:**
+ Before getting started, check the `package.json` file to understand available scripts, dependencies, and tooling relevant to this repository.
+
+## Linting and Code Quality
+
+This repository provides linting tools for JavaScript, CSS, and other code standards, which can be run using Node scripts. These tools help maintain code quality and enforce organization standards.
+
+- Lint JavaScript:
+
+ ```bash
+ npm run lint:js
+ ```
+
+- Lint CSS:
+
+ ```bash
+ npm run lint:css
+ ```
+
+- Run all linters:
+
+ ```bash
+ npm run lint
+ ```
+
+## Agents & Shared Scripts
+
+A `scripts/` folder is used to contain shared functions for agents.
+Agents are written in JavaScript, and reusable logic or utilities should be placed here for maintainability and collaboration across the organization.
+
+## Git Workflow
+
+1. Create a feature branch for your work:
+
+ ```bash
+ git checkout -b feature/your-feature-name
+ ```
+
+2. Make your changes and commit them:
+
+ ```bash
+ git add .
+ git commit -m "Your descriptive commit message"
+ ```
+
+3. Push your changes and create a pull request:
+
+ ```bash
+ git push origin feature/your-feature-name
+ ```
+
+4. Reference any related issues in your pull request description. Please use the [pull request template](https://github.com/lightspeedwp/.github/blob/master/.github/PULL_REQUEST_TEMPLATE.md) for summaries.
+
+## Need Help?
+
+- Check the repository documentation and README files
+- Review the [GitHub Copilot custom instructions](./.github/custom-instructions.md)
+- Use the prompt files in `.github/prompts/` for guidance
+
+## Contributing and Code of Conduct
+
+We welcome contributions! Please review our [Contributing Guidelines](https://github.com/lightspeedwp/.github/blob/master/.github/CONTRIBUTING.md) and [Code of Conduct](https://github.com/lightspeedwp/.github/blob/master/.github/CODE_OF_CONDUCT.md).
+
+## License
+
+This project is licensed under the GNU General Public License v3.0 — see the [LICENSE](LICENSE) file for details.
+
+[](https://www.gnu.org/licenses/gpl-3.0)
+
+## Reference
+
+- [BRANCHING_STRATEGY.md](./BRANCHING_STRATEGY.md): Org-wide branch naming, merge discipline, and automation mapping.
+- [CHANGELOG.md](../CHANGELOG.md): Changelog format, release notes, and versioning.
+- [CONTRIBUTING.md](../CONTRIBUTING.md): Contribution guidelines, templates, coding standards.
+- [AUTOMATION_GOVERNANCE.md](./AUTOMATION_GOVERNANCE.md): Org-wide automation, branching, labeling, and release strategy.
+- [Org-wide Issue Labels](./ISSUE_LABELS.md): Default labels and usage guidance.
+- [Pull Request Labels](./PR_LABELS.md): PR classification labels and automation standards.
+- [Canonical Issue Types YAML](./issue-types.yml): Machine-readable issue types for workflow and automation.
+- [Canonical Label Definitions](./labels.yml): Label names, colours, and descriptions.
+- [Automated Label Assignment Rules](./labeler.yml): Automation for applying labels based on file changes and branch patterns.
diff --git a/GEMINI.md b/GEMINI.md
new file mode 100644
index 0000000..a9197f3
--- /dev/null
+++ b/GEMINI.md
@@ -0,0 +1,172 @@
+---
+title: 'CLAUDE.md Template'
+version: 'v1.1'
+last_updated: '2025-10-21'
+author: 'LightSpeed'
+maintainer: 'Ash Shaw'
+description: 'Root-level guidance for Claude agents, aligned with LightSpeed organisational standards.'
+tags: ['lightspeed', 'templates', 'copilot', 'agents', 'prompts', 'models']
+type: 'agent'
+references:
+ - 'https://github.com/lightspeedwp/.github/blob/master/.github/custom-instructions.md'
+ - 'https://github.com/lightspeedwp/.github/blob/master/AGENTS.md'
+ - 'https://github.com/lightspeedwp/.github/blob/master/.github/instructions/coding-standards.instructions.md'
+---
+
+# Role
+
+You are a Claude agent operating within LightSpeed. Follow LightSpeed's [AGENTS.md](https://github.com/lightspeedwp/.github/blob/master/AGENTS.md), [custom instructions](https://github.com/lightspeedwp/.github/blob/master/.github/custom-instructions.md), and project-specific frameworks to deliver modular, maintainable WordPress solutions. Use UK English. Avoid non-WordPress tools, custom code, or exposing secrets unless explicitly directed.
+
+# Style
+
+- Write modular, maintainable, and testable code and documentation.
+- Use semantic, accessible markup and descriptive comments per WordPress standards.
+- Optimise for performance, accessibility, and scalability.
+- Justify any tool or pattern outside LightSpeed defaults with clear rationale.
+
+# Purpose
+
+- Deliver clear, secure, and scalable outcomes for LightSpeed WordPress projects.
+- Ensure all outputs meet LightSpeed’s standards for clarity, maintainability, security, and accessibility.
+- Support and automate workflows for efficient Figma → WordPress handoff.
+
+# Type of Task
+
+- Coding, code review, documentation, prompt authoring, agentic workflow design, and process checklists for WordPress and web projects.
+- Validate outputs against [LightSpeed coding standards](https://github.com/lightspeedwp/.github/blob/master/.github/instructions/coding-standards.instructions.md), linting, and accessibility requirements.
+
+# How to ask for help
+
+- Reference this Space and LightSpeed documentation first.
+- Ask a single, focused question if requirements or context are unclear.
+- Escalate blockers by tagging the maintainer and referencing relevant documentation or index files.
+
+# Conventions
+
+- Use YAML frontmatter in documentation.
+- Reference core index files for standards ([see AGENTS.md](https://github.com/lightspeedwp/.github/blob/master/AGENTS.md)).
+- Track issues and PRs via GitHub; reference/close issues in commit messages.
+
+# Process
+
+- Start by checking AGENTS.md and custom-instructions.md for current org rules.
+- Confirm project scope and constraints before coding.
+- Use GitHub Issues and PRs for all changes; follow the [pull request template](https://github.com/lightspeedwp/.github/blob/master/.github/PULL_REQUEST_TEMPLATE.md).
+- Log rationale and testing coverage for every change.
+
+# Examples
+
+- See [prompts index](https://github.com/lightspeedwp/.github/blob/master/.github/prompts/prompts.md) for reusable prompt files.
+- Example outputs: accessible markup, modular WordPress block patterns, documented workflow YAML.
+
+# Important notes
+
+- Never expose secrets or sensitive data.
+- Accessibility and performance are non-negotiable.
+- Update documentation and rationale with every material change.
+
+# Who is this for
+
+- Claude agents, contributors, and maintainers working on LightSpeed WordPress projects.
+
+# Responsibilities
+
+- Validate code and outputs against LightSpeed standards.
+- Document decisions, tests, and rationale.
+- Promote safe and maintainable workflows.
+
+# Patterns or Frameworks to Follow
+
+- Use WordPress core blocks, theme.json, and native block patterns.
+- Reference LightSpeed’s pattern development and coding standards instructions.
+
+# Practices
+
+- Prefer safe defaults; modularity over complexity.
+- Use semantic CSS naming and ARIA roles for accessibility.
+- Automate linting and tests before merging PRs.
+
+# Tools
+
+- Use WordPress tools, GitHub Actions, Playwright for testing.
+- Avoid introducing bespoke tools unless justified.
+
+# Coverage
+
+- Ensure test coverage for new features and workflows.
+- Use Playwright, Jest, or equivalent per project language.
+
+# Constraints
+
+- Follow UK English, WordPress coding standards, and OWASP top 10 security rules.
+- Accessibility and performance must be validated and documented.
+- Only use approved tools and frameworks unless justified.
+
+# What to do
+
+- Reference core indexes and instructions before starting work.
+- Document rationale, tests, and accessibility for all changes.
+- Ask clarifying questions if requirements are ambiguous.
+
+# What not do
+
+- Do not output secrets, credentials, or sensitive data.
+- Do not bypass linting, testing, or documentation standards.
+- Do not use non-WordPress or unapproved tools without approval.
+
+# Best Practices
+
+- Adhere to WordPress and LightSpeed coding/documentation standards.
+- Promote accessibility and semantic markup.
+- Propose modular, maintainable solutions and safe defaults.
+
+# Guardrails
+
+- Always validate outputs against LightSpeed coding, security, and accessibility standards.
+- Flag and document any deviations from best practice.
+- Reference AGENTS.md for global principles.
+
+# Checklist relevant to instructions
+
+- [ ] Used UK English and WordPress standards.
+- [ ] Provided modular, maintainable code and documentation.
+- [ ] Automated linting and accessibility validation.
+- [ ] Documented rationale and tests.
+- [ ] Referenced relevant LightSpeed instruction/index files.
+- [ ] Avoided secrets and unapproved tools.
+
+# Outputs
+
+- Modular code, accessible markup, documented workflows, rationale, and test results.
+- YAML frontmatter in documentation.
+- PRs and issues tracked via GitHub.
+
+# Contribution & Collaboration
+
+- Collaborate via GitHub Issues and PRs.
+- Reference AGENTS.md and custom-instructions.md for org-wide guidance.
+- Tag maintainers for blockers or review.
+
+# Non-goals
+
+- Do not provide generic, non-WordPress solutions.
+- Do not deviate from LightSpeed and WordPress standards.
+
+# Resource links
+
+- [LightSpeed Custom Instructions](https://github.com/lightspeedwp/.github/blob/master/.github/custom-instructions.md)
+- [AGENTS.md](https://github.com/lightspeedwp/.github/blob/master/AGENTS.md)
+- [Coding Standards](https://github.com/lightspeedwp/.github/blob/master/.github/instructions/coding-standards.instructions.md)
+- [Prompts Index](https://github.com/lightspeedwp/.github/blob/master/.github/prompts/prompts.md)
+- [Pull Request Template](https://github.com/lightspeedwp/.github/blob/master/.github/PULL_REQUEST_TEMPLATE.md)
+
+# Prompt
+
+- Write a concise, actionable prompt tailored to the task, referencing relevant LightSpeed standards, instructions, and indexes.
+- Validate the output against coding, accessibility, and security requirements.
+
+---
+
+Provide safe defaults; mark optional flags clearly.
+Start by referencing any LightSpeed internal process, documentation, or best practice. This Space is your single source of truth for LightSpeed workflows.
+Aim for small, safe, well-documented steps that make the Figma → WordPress handoff effortless.
diff --git a/GOVERNANCE.md b/GOVERNANCE.md
new file mode 100644
index 0000000..14e880a
--- /dev/null
+++ b/GOVERNANCE.md
@@ -0,0 +1,73 @@
+# LightSpeed Community Health Repo Governance
+
+Defines maintainer/contributor roles and decision making.
+See [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
+
+## Overview
+
+This document explains how the LightSpeed community health repository is governed. It describes project roles, responsibilities, decision-making processes, and references key organisational standards and policies. The goal is to ensure a transparent, inclusive, and maintainable project.
+
+## Maintainers
+
+| Name | GitHub Username | Profile URL |
+| ---------------- | --------------- | --------------------------------------------- |
+| Ash Shaw | @ashleyshaw | [ashleyshaw](https://github.com/ashleyshaw) |
+| Warwick Booth | @krugazul | [krugazul](https://github.com/krugazul) |
+| Chris Vancoillie | @eleshar | [eleshar](https://github.com/eleshar) |
+| Zared Rogers | @ZaredRogers | [ZaredRogers](https://github.com/ZaredRogers) |
+
+## Decision Making
+
+- **Routine:** Maintainers review and merge PRs.
+- **Major:** Consensus among maintainers.
+
+## Roles & Responsibilities
+
+#### Responsibilities
+
+- Triage issues and pull requests
+- Review, merge, and release features and fixes
+- Ensure code quality, security, and documentation standards
+- Manage repo configuration and CI/CD
+- Promote contributors to maintainers
+- Update governance, automation, and workflow documents
+
+### Promotion criteria
+
+Contributors may be promoted to maintainer after a significant number of high-quality PRs, consistent engagement, and demonstration of LightSpeed standards. Promotion is at the discretion of existing maintainers.
+
+### Contributors
+
+- Anyone submitting code, content, or participating via issues or PRs.
+- Can triage issues and PRs, and have commit access once approved.
+- Expected to follow contribution guidelines and review requirements.
+
+## Decision Making
+
+- **Routine changes:** Maintainers review and merge PRs based on coding standards and contribution guidelines.
+- **Major changes:** Discussed openly, decided by consensus among maintainers. If consensus cannot be reached, lead maintainer decides.
+- **Conflict resolution:** Maintainers will mediate. Issues can be escalated via [contact methods](#reporting--contact).
+
+## Change Process
+
+- Governance changes are proposed via pull request and require review and approval from at least one maintainer.
+
+## Reporting & Contact
+
+- For governance or code of conduct concerns, open a GitHub issue or contact a maintainer directly.
+
+## Key Documents & Standards
+
+- [General Org Instructions](./.github/custom-instructions.md)
+- [Coding Standards](./.github/instructions/coding-standards.instructions.md)
+- [Contribution Guidelines](../CONTRIBUTING.md)
+- [Branching Strategy](../BRANCHING_STRATEGY.md)
+- [Automation Governance](../AUTOMATION_GOVERNANCE.md)
+- [Issue & PR Labels](../ISSUE_LABELS.md), [../PR_LABELS.md](../PR_LABELS.md), [../labels.yml](../labels.yml), [../labeler.yml](../labeler.yml)
+- [Issue Types YAML](../issue-types.yml)
+- [Pull Request Template](./.github/PULL_REQUEST_TEMPLATE.md)
+- [CHANGELOG](../CHANGELOG.md)
+
+---
+
+_This document is maintained by the LightSpeed community. Propose changes via pull request._
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..79fa908
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,681 @@
+
+ ```
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+ ```
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+1. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+2. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+3. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+4. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+5. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+6. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+7. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+8. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+9. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+10. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+11. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+12. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+13. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+14. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+15. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+16. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ ```
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ ```
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ ```
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+ ```
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/README.md b/README.md
index 1f497d0..86e29d5 100644
--- a/README.md
+++ b/README.md
@@ -1,78 +1,238 @@
-# WordPress Documentation Hub
+# lightspeedwp – WordPress Engineering & AI Assistant Docs
-A comprehensive collection of WordPress development documentation, coding standards, and best practices. This repository serves as a central resource for modern WordPress development workflows, from block themes to AI-assisted development patterns.
+Accelerating high‑quality WordPress development with reusable AI building blocks (prompts, instructions, chat modes, agent governance)
+and domain handbooks (block themes, coding standards, Gutenberg guides). Everything is tuned to produce fast, secure, accessible,
+internationalised, and maintainable solutions (themes, plugins, blocks, patterns).
+
+## Mission
+
+Empower WordPress developers to deliver production‑ready features at lightspeed while upholding coding standards,
+accessibility (WCAG 2.2), performance, security (OWASP), and sustainable long‑term maintainability.
+
+## Repository Structure
+
+| Area | Path | Summary |
+| -------------------- | ------------------------ | ------------------------------------------------------------------- |
+| Documentation Hub | `docs/` | Master index & cross-cutting conventions (see `docs/README.md`). |
+| Copilot / AI Assets | `docs/copilot-space/` | Prompts, instructions, chat modes, agent schemas & authoring rules. |
+| Block Theme Guidance | `docs/block-themes/` | Fluid spacing, typography scales, global styles, naming, patterns. |
+| Coding Standards | `docs/coding-standards/` | WordPress coding standards overlays, inline docs, research notes. |
+| Gutenberg Guides | `docs/gutenberg/` | Getting started, how‑tos, reference, schemas. |
+| Frontmatter Schemas | `docs/frontmatter/` | YAML frontmatter conventions & schemas. |
+| Agent Governance | `AGENTS.md` | Behavioural contract for AI assistants & personas. |
+| Automation Scripts | `.github/scripts/` | Generators, validators, normalisation tooling. |
+
+See also: `CHANGELOG.md` for historical evolution.
+
+## Why Keep Cross‑Technology Assets?
+
+Many engineering concerns (testing discipline, performance, security, accessibility, structured planning) transcend platform boundaries.
+We intentionally retain high‑quality “generic” or multi‑stack assets because they:
+
+1. Provide architectural clarity applicable to large WordPress installations (headless, API integrations, infrastructure).
+2. Reduce reinvention—reuse vetted language/framework guidance where analogous (e.g. performance patterns informing PHP + JS code paths).
+3. Enable mixed‑stack teams (WP + services) to align on shared standards.
+
+Future refinement: lightweight tagging (e.g. `wp-core`, `block-dev`, `generic`, `infra`) to improve discoverability without deleting value.
+
+## Quick Start (Using AI Assets)
+
+1. Install desired Copilot assets (Prompts / Chat Modes / Instructions) via VS Code badges in each catalog.
+2. Copy any custom instruction you want permanently into `.github/instructions/` (or merge into a project‑level `copilot-instructions.md`).
+3. Open Copilot Chat and select a lightspeedwp chat mode (or paste a prompt) to accelerate tasks.
+4. Iterate: refine instructions with project specifics (naming conventions, text domain, PHPCS rules).
+
+### Example: Generate a Block Scaffold
+
+1. Open your plugin or theme workspace.
+2. Use the “Implementation Plan” prompt to outline the block (attributes, render strategy, style variants, i18n extraction).
+3. Apply “Accessibility Review” prompt / chat mode to validate ARIA & keyboard flows.
+4. Use performance & security instructions to audit dynamic rendering and REST endpoints.
+
+### Example: Harden a Custom REST Endpoint
+
+1. Invoke security instructions (OWASP) + performance optimization guidelines.
+2. Provide the endpoint handler code to a “Security & Code Quality” chat mode.
+3. Request: “Suggest nonce, capability checks, caching & schema validation improvements.”
+
+## Schema Validation & Automation
+
+### YAML/JSON Schema Validation
+
+All configuration schemas (e.g. for `.coderabbit.yml`) are stored in the `schemas/` directory at the project root. This enables:
+
+- **Offline validation**: Always validate against the latest downloaded schema, even without internet access.
+- **Automated updates**: Keep schemas up to date with a single command.
+
+#### Validate `.coderabbit.yml`
+
+```sh
+npm run validate:coderabbit
+```
+
+or
+
+```sh
+node scripts/json-validation/validate-coderabbit-yml.cjs
+```
+
+#### Update the CodeRabbit schema
+
+```sh
+node scripts/json-validation/update-coderabbit-schema.cjs
+```
+
+This fetches the latest schema from the remote source and saves it to `schemas/coderabbit-overrides.v2.json`.
+
+**Tip:** Add this as a pre-commit, pre-push, or CI step to ensure your validation is always up to date.
+
+---
+
+## Contributing (Overview)
+
+See `CONTRIBUTING.md` for full process. Summary:
+
+1. Fork & branch.
+2. Add or update a prompt / instruction / chat mode (include frontmatter) or improve a WordPress guide.
+3. Keep scope tight; ensure examples are WP‑relevant where applicable.
+4. Run any validation/update scripts (if present) before PR.
+5. Provide rationale + before/after (if refactoring docs).
+
+### Quality Checklist (Abbreviated)
+
+- Clear purpose & actionable steps
+- WordPress alignment (or clearly marked cross‑tech)
+- Accessibility & security consciousness
+- No hard‑coded secrets / unsafe patterns
+- Consistent naming & formatting
+
+## Roadmap Snapshot
+
+High‑level items (see `CHANGELOG.md` for canonical history & upcoming):
+
+- Tagging taxonomy for AI assets & docs.
+- WordPress‑specialised chat modes (Theme JSON Refiner, Block Accessibility Auditor, Hook Strategy Advisor).
+- Collections curation once tagging lands.
+- Domain surfacing (stability, domain) in generated README tables.
+- Automated link & frontmatter validator.
+
+## Namespace & Badges
+
+Any legacy install badges still referencing upstream sources are intentionally preserved during transition;
+they will migrate once tagging + mirroring strategy finalises.
+
+## License
+
+This repository is licensed under the **GNU GPL v3** (see `LICENSE`). Documentation and AI asset text are distributed under the same license for simplicity.
+If you require alternative terms for specific reuse scenarios, open an issue to discuss.
+
+## Feedback & Improvements
+
+Open an issue with: context, goal, current friction, desired outcome.
+Evidence (snippets, diffs) speeds triage.
+
+---
+
+Crafted with accessibility, security, performance, and internationalisation in mind—manual review & testing still required.
## 📁 Documentation Sections
-### [🎨 Block Themes](block-themes/)
+### [🎨 Block Themes](docs/block-themes/)
+
Modern WordPress theme development with comprehensive guides for:
+
- **Fluid Typography & Spacing** - Responsive design using clamp() and custom properties
- **Design Systems** - Color palettes, spacing presets, and design tokens
- **Theme Structure** - Templates, patterns, and global styles
- **Best Practices** - CSS specificity, naming conventions, and optimization
-**Key Files:** [Fluid Typography](block-themes/fluid-typography.md) • [Global Styles](block-themes/global-styles.md) • [Theme Structure](block-themes/theme-structure-epi.md)
+**Key Files:** [Fluid Typography](docs/block-themes/fluid-typography.md) • [Global Styles](docs/block-themes/global-styles.md)
+
+- [Theme Structure](docs/block-themes/theme-structure-epi.md)
+
+### [📋 Coding Standards](docs/coding-standards/)
-### [📋 Coding Standards](coding-standards/)
Comprehensive coding standards for WordPress development:
-- **[LightSpeed Standards](coding-standards/ash-research/)** - Enhanced WordPress standards (WPCS v3.2.0) with security-first approach
-- **[WordPress Core Standards](coding-standards/wordpress-coding-standards/)** - Official WordPress coding guidelines
-- **[Inline Documentation](coding-standards/inline-documentation-standards/)** - Code commenting and documentation practices
+
+- **[LightSpeed Standards](docs/coding-standards/ash-research/)** - Enhanced WordPress standards (WPCS v3.2.0) with security-first approach
+- **[WordPress Core Standards](docs/coding-standards/wordpress-coding-standards/)** - Official WordPress coding guidelines
+- **[Inline Documentation](docs/coding-standards/inline-documentation-standards/)** - Code commenting and documentation practices
**Key Features:** Security by default • WCAG 2.2 AA accessibility • Performance optimization • Maintainable code patterns
-### [⚙️ YAML Frontmatter](frontmatter/)
+### [🤖 Copilot Space](docs/copilot-space/)
+
+AI-assisted development assets and configurations:
+
+- **Chat Modes** - Specialized AI conversation modes for WordPress development
+- **Prompt Libraries** - Reusable prompts for common development tasks
+- **Agent Instructions** - Behavioral contracts for AI assistants
+- **Schemas** - Structured templates for consistent AI interactions
+
+**Key Files:** [Agents](docs/copilot-space/agents-md.md) • [Chat Modes](docs/copilot-space/chatmodes.md)
+
+- [Instructions](docs/copilot-space/copilot-instructions.md)
+
+### [⚙️ YAML Frontmatter](docs/frontmatter/)
+
Standardized frontmatter patterns for modern development workflows:
+
- **GitHub Templates** - Issue forms, PR templates, and repository configuration
- **AI Agent Configurations** - GitHub Copilot, Claude, and Gemini setups
-- **Copilot Space** - Complete AI-assisted development environment
- **Schema Validation** - Consistent metadata patterns across all template types
-**Key Files:** [Frontmatter Cheat Sheet](frontmatter/YAML%20Frontmatter%20Cheat%20Sheet.md) • [Schema Guidelines](frontmatter/YAML-Frontmatter%20Schema-Guidelines.md) • [Copilot Space Instructions](frontmatter/YAML-Frontmatter-Copilot-Space-Instructions.md)
+**Key Files:** [Frontmatter Cheat Sheet](docs/frontmatter/YAML%20Frontmatter%20Cheat%20Sheet.md)
+
+- [Schema Guidelines](docs/frontmatter/YAML-Frontmatter%20Schema-Guidelines.md)
+
+### [🧱 Gutenberg Documentation](docs/gutenberg/)
-### [🧱 Gutenberg Documentation](gutenberg/)
Complete Gutenberg block editor documentation:
-- **[Getting Started](gutenberg/getting-started/)** - Development environment setup and tutorials
-- **[How-to Guides](gutenberg/how-to-guides/)** - Practical implementation guides
-- **[Reference Guides](gutenberg/reference-guides/)** - API references and technical documentation
-- **[Schemas](gutenberg/schemas/)** - Block and configuration schemas
+
+- **[Getting Started](docs/gutenberg/getting-started/)** - Development environment setup and tutorials
+- **[How-to Guides](docs/gutenberg/how-to-guides/)** - Practical implementation guides
+- **[Reference Guides](docs/gutenberg/reference-guides/)** - API references and technical documentation
+- **[Schemas](docs/gutenberg/schemas/)** - Block and configuration schemas
**Key Areas:** Block development • Editor extensibility • Theme integration • API references
## 🚀 Quick Start
### For Theme Developers
-1. Review [Block Themes documentation](block-themes/) for modern theme development
-2. Implement [Fluid Typography](block-themes/fluid-typography.md) and [Spacing](block-themes/fluid-spacing.md)
-3. Follow [LightSpeed Coding Standards](coding-standards/ash-research/) for best practices
+
+1. Review [Block Themes documentation](docs/block-themes/) for modern theme development
+2. Implement [Fluid Typography](docs/block-themes/fluid-typography.md) and [Spacing](docs/block-themes/fluid-spacing.md)
+3. Follow [LightSpeed Coding Standards](docs/coding-standards/ash-research/) for best practices
### For Plugin Developers
-1. Start with [WordPress Coding Standards](coding-standards/wordpress-coding-standards/)
-2. Review [Gutenberg How-to Guides](gutenberg/how-to-guides/) for block development
-3. Implement [Inline Documentation Standards](coding-standards/inline-documentation-standards/)
+
+1. Start with [WordPress Coding Standards](docs/coding-standards/wordpress-coding-standards/)
+2. Review [Gutenberg How-to Guides](docs/gutenberg/how-to-guides/) for block development
+3. Implement [Inline Documentation Standards](docs/coding-standards/inline-documentation-standards/)
### For AI-Assisted Development
-1. Set up [YAML Frontmatter](frontmatter/) for standardized templates
-2. Configure [Copilot Space](frontmatter/YAML-Frontmatter-Copilot-Space-Instructions.md) for AI workflows
-3. Use [Schema Guidelines](frontmatter/YAML-Frontmatter%20Schema-Guidelines.md) for validation
+
+1. Set up [YAML Frontmatter](docs/frontmatter/) for standardized templates
+2. Configure [Copilot Space](docs/copilot-space/) for AI workflows
+3. Use [Schema Guidelines](docs/frontmatter/YAML-Frontmatter%20Schema-Guidelines.md) for validation
## 🎯 Core Principles
- **Security First**: All patterns emphasize WordPress security best practices
- **Accessibility**: WCAG 2.2 Level AA compliance baseline across all documentation
-- **Performance**: Optimization-focused approaches in all recommendations
+- **Performance**: Optimization-focused approaches in all recommendations
- **Modern Standards**: Up-to-date with latest WordPress and web development practices
- **AI Integration**: Documentation patterns optimized for AI-assisted development workflows
## 🔧 Standards at a Glance
-| Area | Standard | Key Features |
-|------|----------|--------------|
-| **Theme Development** | Block-first, Fluid Design | Responsive typography, Design tokens, Performance optimization |
-| **Code Quality** | WordPress + LightSpeed Standards | Security by default, WCAG 2.2 AA, PHPDoc documentation |
-| **AI Integration** | YAML Frontmatter Schemas | GitHub templates, Copilot Space, Cross-platform AI configs |
-| **Block Development** | Gutenberg Best Practices | Modern JavaScript, React patterns, WordPress APIs |
+| Area | Standard | Key Features |
+| --------------------- | -------------------------------- | -------------------------------------------------------------- |
+| **Theme Development** | Block-first, Fluid Design | Responsive typography, Design tokens, Performance optimization |
+| **Code Quality** | WordPress + LightSpeed Standards | Security by default, WCAG 2.2 AA, PHPDoc documentation |
+| **AI Integration** | YAML Frontmatter Schemas | GitHub templates, Copilot Space, Cross-platform AI configs |
+| **Block Development** | Gutenberg Best Practices | Modern JavaScript, React patterns, WordPress APIs |
---
-This documentation hub ensures consistent, secure, and maintainable WordPress development across all project types and development workflows.
\ No newline at end of file
+This documentation hub ensures consistent, secure, and maintainable WordPress development across all project types and development workflows.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..1868390
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,14 @@
+# Security Policy
+
+If you discover a security vulnerability in this project, please report it responsibly.
+
+- **Contact:** [support@lightspeedwp.agency](mailto:support@lightspeedwp.agency)
+- Please provide as much detail as possible so we can address the issue quickly.
+
+We follow the [WordPress Security Best Practices](https://developer.wordpress.org/security) and adhere to the [WordPress Coding Standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/).
+
+We aim to respond to security reports within 3 business days.
+
+## License
+
+This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.
diff --git a/SUPPORT.md b/SUPPORT.md
new file mode 100644
index 0000000..76ea90d
--- /dev/null
+++ b/SUPPORT.md
@@ -0,0 +1,17 @@
+## Support
+
+**Please note:** We do not provide free support for our open source software. Support is available as a paid service.
+
+For bug reports or issues, please use the relevant issue template in our [GitHub Issues](https://github.com/lightspeedwp/repo-name/issues/new/choose) section.
+
+For paid support, contact our team:
+
+- **Email:** [support@lightspeedwp.agency](mailto:support@lightspeedwp.agency)
+
+We aim to respond to paid support requests within 2 business days.
+
+For more information, please refer to our documentation or FAQ if available.
+
+## License
+
+This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.
diff --git a/SUPPRESSIONS.md b/SUPPRESSIONS.md
new file mode 100644
index 0000000..6c2f58f
--- /dev/null
+++ b/SUPPRESSIONS.md
@@ -0,0 +1,24 @@
+# Markdown Lint Suppressions
+
+This file documents all global markdownlint suppressions applied in `.markdownlint.json` for the `wp-docs` repository. These suppressions are intended to balance code quality, maintainability, and practical constraints when working with legacy or complex documentation.
+
+## Suppressed Rules
+
+### MD013 – Line Length
+
+**Suppressed:** Yes (globally)
+**Rationale:** Many legacy documentation files contain long URLs, tables, or code examples that would be impractical to reflow. Enforcing this rule would create excessive diffs and reduce readability for technical content.
+
+### MD003 – Heading Style (Setext vs ATX)
+
+**Suppressed:** Yes (globally)
+**Rationale:** The documentation set includes a mix of Setext and ATX headings, and converting all Setext headings would be time-consuming and error-prone. Suppression avoids unnecessary churn and preserves original author intent.
+
+### MD040 – Fenced Code Block Language
+
+**Suppressed:** Yes (globally)
+**Rationale:** Many code blocks in legacy docs lack a specified language. Enforcing this rule would require manual review of hundreds of blocks, with little practical benefit for current usage.
+
+---
+
+> **Note:** These suppressions are reviewed periodically. If documentation is rewritten or significantly refactored, consider re-enabling these rules for new or heavily revised files.
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..b82608c
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+v0.1.0
diff --git a/YAML Frontmatter Cheat Sheet.md b/YAML Frontmatter Cheat Sheet.md
deleted file mode 100644
index 0b13ec8..0000000
--- a/YAML Frontmatter Cheat Sheet.md
+++ /dev/null
@@ -1,525 +0,0 @@
-# **YAML Frontmatter Cheat Sheet for GitHub Templates and AI Agent Configurations**
-
-## **GitHub Issue Template Frontmatter (Issue Forms)**
-
-GitHub **issue templates** can use a YAML frontmatter (especially for the new **Issue Forms**) to define metadata and form fields. All issue form files **must** begin with at least three keys: `name`, `description` (often called “about” in legacy templates), and `body`[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=All%20issue%20form%20configuration%20files,value%20pairs). Additional optional keys let you preassign labels, assignees, etc. Here are the top-level frontmatter fields for an issue form template[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,repository%2C%20it%20will%20not%20be)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,using%20this%20template%20to%20have):
-
-* **`name`** – Unique name for the template (appears in template picker UI) **(required)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,Required%20String).
-
-* **`description`** – Short explanation of the template’s purpose (shown in picker UI) **(required)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=templates%2C%20including%20Markdown%20templates,Required%20String).
-
-* **`body`** – An array defining the form fields and content blocks for the issue form **(required)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,assigned%20to%20issues%20created%20with).
-
-* **`title`** – Default title that will pre-fill in the new issue title input **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=template,Optional%20String).
-
-* **`labels`** – Labels to auto-apply on issue creation (array or comma-separated) **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,delimited%20string).
-
-* **`assignees`** – GitHub usernames to auto-assign the issue to (array or comma-separated) **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,repository%2C%20it%20will%20not%20be).
-
-* **`projects`** – GitHub Projects to auto-add the issue to (format `"OWNER/PROJECT-NUMBER"`) **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=to%20create%20a%20shared%20syntax,delimited%20string).
-
-* **`type`** – Issue type to assign (if your organization uses custom issue types) **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,created%20with%20this%20template%20will).
-
-Below is an **example** of a comprehensive issue form YAML frontmatter, including a variety of field types in the `body`. Comments (`# ...`) are added to explain each parameter and best practices:
-
-`---`
-`name: "Bug Report" # Template name (must be unique in repo)`
-`description: "Report a bug in the project." # Shown in the new issue template chooser`
-`title: "[Bug]: " # Default issue title prefix`
-`labels: ["bug", "needs-triage"] # Labels to apply automatically`
-`assignees: ["octocat"] # Users to assign by default`
-`projects: ["my-org/42"] # Add issue to project board (org/project-number)`
-`type: bug # Issue type (if using typed issues in org)`
-
-`body:`
- `- type: markdown`
- `attributes:`
- `value: "## Thank you for reporting a bug!\nPlease fill out the sections below."`
- `# ^ A static guidance section (Markdown instructions for the user).`
- `# Note: Use quotes for text containing '#' or special YAML chars:contentReference[oaicite:11]{index=11},`
- `# and use '|' for multi-line content as shown above.`
-
- `- type: input`
- `id: "contact"`
- `attributes:`
- `label: "Contact Details"`
- `description: "How can the team reach you for more info?"`
- `placeholder: "e.g. email@example.com"`
- `value: "" # default can be left blank`
- `validations:`
- `required: false # mark field optional (true would prevent submission if empty)`
-
- `- type: textarea`
- `id: "steps"`
- `attributes:`
- `label: "Steps to Reproduce"`
- `description: "Provide step-by-step instructions to reproduce the issue."`
- `placeholder: |`
- `1. Step one...`
- `2. Step two...`
- `3. *Feel free to add more steps as needed...*`
- `value: "" # you can pre-fill common steps or leave empty`
- `render: markdown # if provided, the submitted text will be formatted as a code block of this type (e.g. markdown, bash)`
- `validations:`
- `required: true # this textarea must be filled in`
-
- `- type: dropdown`
- `id: "browser"`
- `attributes:`
- `label: "Affected Browser(s)"`
- `description: "Which web browsers show the issue?"`
- `options:`
- `- "Firefox"`
- `- "Chrome"`
- `- "Safari"`
- `- "Edge"`
- `multiple: true # allow multiple selections`
- `validations:`
- `required: true # at least one option must be selected`
-
- `- type: checkboxes`
- `id: "agree"`
- `attributes:`
- `label: "Code of Conduct Agreement"`
- `description: "Please confirm:"`
- `options:`
- `- label: "I have searched for duplicate issues"`
- `required: true # this box must be checked to submit (ensures reporter did a search)`
- `- label: "I agree to follow the project’s Code of Conduct"`
- `required: true`
-`---`
-
-In the **`body`** array above, we demonstrated each supported input type:
-
-* **Markdown (`type: markdown`)** – Just static text guidance (not included in final issue content). Use this for instructions or banners. *Tip:* If using `#` in the text (for headings), wrap the value in quotes to prevent YAML treating it as a comment[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,if%20we%20need%20more%20info).
-
-* **Text Input (`type: input`)** – Single-line text field. Supports `label`, `description`, `placeholder`, `value` (default text), and validations like `required`[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=%23%23%23%20Current%20Behavior%3A%20%3C%21,)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=1.%20See%20error...%20).
-
-* **Textarea (`type: textarea`)** – Multi-line text field for longer input. Supports the same attributes as input, plus `render` (to automatically format user text as a code block of a given language)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=attributes%3A%20label%3A%20Relevant%20log%20output,attributes%3A%20label%3A%20Code%20of%20Conduct)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=description%3A%20Please%20copy%20and%20paste,Code%20of%20Conduct%5D%28https%3A%2F%2Fexample.com).
-
-* **Dropdown (`type: dropdown`)** – Single or multi-select from a list of options. Requires an `options` list. You can set `multiple: true` for multi-select. If you include a `default:` index (0-based) in attributes, that option will be pre-selected[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=id%3A%20version%20attributes%3A%20label%3A%20Version,3%20%28Edge%29%20default%3A%200%20validations). Validation `required: true` means the user must select at least one[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,type%3A%20dropdown).
-
-* **Checkboxes (`type: checkboxes`)** – A group of one or more checkbox items. Each option has a `label` (supports basic Markdown) and optionally `required: true` if that particular box must be checked[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=id%3A%20terms%20attributes%3A%20label%3A%20Code,Code%20of%20Conduct%20required%3A%20true). If any checkbox option is marked required, the form won’t submit until it’s checked (useful for “I agree” confirmations).
-
-**Best Practices:**
-
-* **Formatting:** Enclose the frontmatter between `---` lines at the top of the template file. Indentation is significant in YAML – use consistent two-space indents for nested fields.
-
-* **Quoting:** Quote strings that contain special characters (like `:` or `#`) or begin with square brackets. For instance, the `title` value `[Bug]:` is quoted in YAML[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=name%3A%20%20Bug%20description%3A%20File,already%20exists%20for%20the%20bug) to avoid parsing issues.
-
-* **Multiline Text:** Use the pipe `|` in YAML to input multiline default text or placeholders (as shown for the steps placeholder above) so that line breaks are preserved[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,if%20we%20need%20more%20info).
-
-* **Required Fields:** Use `validations: required: true` judiciously – only when the issue cannot be submitted without that info. Otherwise, leave as optional to not frustrate contributors.
-
-* **Unique IDs:** The `id` fields in inputs aren’t mandatory, but assigning them (alphanumeric, `-` or `_` only) can help reference responses programmatically (or for future automation).
-
-* **Keep it Short:** While you can include many fields, try not to overwhelm the contributor. Only ask for information that is necessary to triage the issue.
-
-## **GitHub Pull Request Template Frontmatter**
-
-Pull request templates are simpler – GitHub **does not currently support form-style PR templates with YAML-defined inputs** (issue forms are for issues only)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=Issue%20forms%20are%20not%20supported,request%20template%20for%20your%20repository)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=When%20a%20contributor%20fills%20out,issue%20created%20through%20other%20methods). However, you *can* include a YAML frontmatter at the top of a PR template file to pre-specify metadata like title, labels, etc., but as of now, **GitHub ignores these frontmatter fields for PRs** – any frontmatter will simply remain in the text of the PR body (not parsed out)[stackoverflow.com](https://stackoverflow.com/questions/66392676/github-pull-request-template-detect-yaml-front-matter-using-config-yml-and-apply#:~:text=5). In practice, this means the YAML block would just be visible to users opening the PR, which is usually undesirable. (There is no PR template picker UI, unlike issues.)
-
-For completeness, here are the **frontmatter keys** that parallel issue templates (even though they won’t be auto-applied by GitHub for PRs as of 2025):
-
-* **`name`** – Name of the PR template (if multiple templates via query parameter).
-
-* **`about`** – Description of the template’s use.
-
-* **`title`** – Default title for pull requests using this template.
-
-* **`labels`** – Labels to add to the PR.
-
-* **`assignees`** – Users to assign to the PR.
-
-These keys mirror the issue template keys (note: here it’s `about` instead of `description`). For example, a PR template might start like:
-
-`---`
-`name: "Feature PR Template"`
-`about: "Use this template for pull requests adding a new feature"`
-`title: "feat: "`
-`labels: enhancement, needs-review`
-`assignees: octocat`
-`---`
-
-*Even though you can include such a frontmatter in a PR template file, GitHub will currently just display it as text in the PR body[stackoverflow.com](https://stackoverflow.com/questions/66392676/github-pull-request-template-detect-yaml-front-matter-using-config-yml-and-apply#:~:text=5).* Therefore, many repositories omit YAML frontmatter in PR templates altogether, and instead just provide a structured markdown checklist or guidance for the contributor. A good pull request template includes sections like “Linked Issue”, “Summary of Changes”, “Testing Instructions”, etc., written as comments or headings in Markdown (since those will guide the PR author).
-
-**Best Practices:**
-
-* If you include a YAML header in a PR template, be aware it won’t be processed by GitHub (it might confuse contributors seeing raw `---` lines). It’s often better to stick to plain Markdown for PR templates.
-
-* Use HTML comments (``) in the template to provide guidance that won’t appear in the final PR description. For example, ``.
-
-* Encourage linking issues in the PR body (e.g., “Closes \#123”) and including screenshots or test output if applicable. These aren’t frontmatter parameters, but important content for PR quality.
-
-*(Note: GitHub might add support for parsing PR template frontmatter in the future, but at the time of writing it’s not implemented[stackoverflow.com](https://stackoverflow.com/questions/66392676/github-pull-request-template-detect-yaml-front-matter-using-config-yml-and-apply#:~:text=5).)*
-
-## **GitHub Saved Replies**
-
-GitHub **saved replies** are canned responses for commenting on issues and PRs. They **do not use file-based YAML frontmatter** at all – instead, they are created and managed via the GitHub web UI (under your profile’s **Saved replies** settings)[docs.github.com](https://docs.github.com/en/get-started/writing-on-github/working-with-saved-replies#:~:text=Creating%20a%20saved%20reply). Each saved reply simply has two pieces of metadata:
-
-* **Title** – a short name you give the saved reply (for your own reference in the UI).
-
-* **Body content** – the actual text (which can include Markdown formatting) that will be inserted when you use the saved reply.
-
-For example, you might have a saved reply titled “Duplicate Issue Response” with a body like:
-
-“Thank you for reporting this. We’re tracking this issue in \#XYZ, so I’ll close this as a duplicate. Please follow the other thread for updates.”
-
-When you insert that saved reply, GitHub will populate the comment box with that message.
-
-**Key points:**
-
-* **No frontmatter file:** Saved replies are not stored in a repository file. They’re tied to your GitHub account. (There is no native way to define them in code or config files, thus no YAML format to document here.)
-
-* **Usage:** You create/edit them via **Settings \> Saved replies**. Each reply’s title is just for your menu; it isn’t inserted into the comment. Only the body content gets inserted[docs.github.com](https://docs.github.com/en/get-started/writing-on-github/working-with-saved-replies#:~:text=Using%20saved%20replies).
-
-* **Markdown Support:** The body supports normal comment formatting (Markdown links, lists, etc.), so you can include checklists or bold text as part of the saved reply.
-
-* **Best Practices:** Keep saved replies concise and general. You can always customize the inserted text after picking it, so they serve best as starting templates. For instance, it’s fine to include a placeholder like “\[issue link\]” in the saved reply text that you replace with a real link after insertion.
-
-*(Since saved replies don’t utilize YAML, there are no frontmatter parameters to list here.)*
-
-## **GitHub Copilot – Repository & Path-Specific Custom Instructions**
-
-GitHub Copilot allows you to provide **custom instructions** to guide code suggestions. These can be set at different levels:
-
-* **Personal instructions** (via your GitHub Copilot settings in your account) – not a file, just text you save in your profile.
-
-* **Repository-wide instructions** – a special file in the repository.
-
-* **Path-specific instructions** – files that apply only to certain files/paths in a repo.
-
-For **repository-wide instructions**, create a Markdown file named **`.github/copilot-instructions.md`** at the root of your repo[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=Creating%20repository). This file contains plain Markdown text with whatever guidance you want Copilot to always consider for this repository. For example, you might describe coding style, architectural guidelines, or context about the project. There is *no YAML frontmatter needed or used* in this file – it’s just a Markdown document of instructions (whitespace and newlines don’t matter to Copilot; it treats it as one block of text)[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=2,the%20file%2C%20in%20Markdown%20format).
-
-For **path-specific instructions**, create a folder `.github/instructions/`, and inside it one or more files with names like `XYZ.instructions.md` (the name can indicate the context). These files **do use YAML frontmatter** to specify where they apply. At the very top, include an `applyTo` key with a glob pattern (or multiple patterns) matching file paths[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=3,directories%20the%20instructions%20apply%20to)[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=). For example:
-
-`---`
-`applyTo: "app/models/**/*.rb,app/controllers/**/*.rb" # apply to all Ruby files in app/models or app/controllers`
-`---`
-`# Rails Model/Controller Conventions`
-
-`- Follow Ruby on Rails idioms for models and controllers.`
-`- Ensure to include necessary unit tests for any new model methods.`
-
-**Frontmatter fields for `*.instructions.md`:**
-
-* **`applyTo`** – Glob pattern of files that this instructions file should apply to[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=3,directories%20the%20instructions%20apply%20to). Use Unix shell style globs (e.g. `"**/*.ts"` for all TypeScript files, or `"docs/**/*"` for anything under docs). You can specify multiple patterns by separating with commas[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=You%20can%20specify%20multiple%20patterns,use%20the%20following%20frontmatter%20block). For a file that should apply to all files in the repo, use `applyTo: "**"`[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=).
-
-* **`description`** – *(Optional)* A short description of these instructions. In VS Code’s Copilot Chat UI, this description will show on hover or in the list of available instruction files[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-instructions#:~:text=Instructions%20files%20use%20the%20,extension%20and%20have%20this%20structure). This is mainly for your own organization; Copilot itself doesn’t use the description content for suggestions.
-
-After the frontmatter, the rest of the file is just Markdown text describing the instructions (similar to the repo-wide file). **Whitespace or blank lines are ignored** by Copilot, so you can format the instructions for readability[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=2,the%20file%2C%20in%20Markdown%20format). You can even use Markdown links to reference other files or documentation within your instructions.
-
-**Example path-specific instructions file:**
-
-`---`
-`applyTo: "**/*.py" # apply to all Python files`
-`description: "Python code style guidelines for this repo"`
-`---`
-`# Python Coding Guidelines`
-
-``- Follow PEP 8 style guide for Python code (use `black` for formatting).``
-`- Use type hints for all functions and methods.`
-`- Prefer list comprehensions and generator expressions for simple loops.`
-``- Avoid using wildcard `import` statements; import only what is needed.``
-
-In the above, whenever Copilot is generating suggestions **while editing a `.py` file**, it will factor in these Python Coding Guidelines in addition to any repo-wide instructions. If multiple instruction files apply (say you had one for all backend code and one for Python specifically), all relevant instructions are combined.
-
-**Best Practices:**
-
-* Keep instruction statements **concise and in natural language** (Copilot works best with clear, high-level guidance). For example, “Use 4 spaces for indentation” or “All API calls must include error handling.”
-
-* Use **separate files for distinct domains** – e.g., language-specific guidelines, or testing guidelines vs. deployment guidelines. This modular approach makes it easier to maintain. You can have many instruction files as needed.
-
-* Name the files logically (the name before `.instructions.md` doesn’t affect function, but helps you identify it). For example, `python.instructions.md`, `frontend.instructions.md`, `security.instructions.md`, etc.
-
-* Leverage the `applyTo` glob to target precisely. Be careful that your pattern isn’t too broad or too narrow. (Multiple patterns can be combined in one file if the instructions are identical.)
-
-* **Tip:** In VS Code, you can manually attach an instructions file to a chat even if its pattern doesn’t auto-apply, via the *Add Context \> Instructions* option. This is useful if you want to use an instruction file in a one-off manner outside its auto scope.
-
-## **GitHub Copilot – Custom Prompt Files (`.prompt.md`)**
-
-Copilot also supports **reusable prompt files** (especially in VS Code’s Copilot Chat context). A prompt file is a Markdown file (with extension `.prompt.md`) that defines a specific prompt or task for the AI, which you can invoke easily. The file can include a YAML frontmatter header to configure how it runs[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=Prompt%20files%20are%20Markdown%20files,extension%20and%20have%20this%20structure). Here are the frontmatter fields for prompt files[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=):
-
-* **`description`** – A short description of what the prompt does. This is used as tooltip or help text in the UI.
-
-* **`mode`** – Which Copilot chat mode to execute the prompt in. Options: `"ask"`, `"edit"`, or `"agent"`.
-
- * **ask** \= default Q\&A chat mode,
-
- * **edit** \= the mode for modifying code,
-
- * **agent** \= the “agent” mode which can use tools.
- If not specified, it defaults to the normal (currently selected) mode, which is typically “agent” for prompt files[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=,If%20not%20specified).
-
-* **`model`** – The AI model to use for this prompt. If omitted, it uses whatever model is currently selected by the user. You can specify something like `"gpt-4"`, `"GPT-4 Code Assist"`, `"Claude 2"`, etc., depending on what models are available in your environment[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=,in%20model%20picker%20is%20used).
-
-* **`tools`** – A list of tools or tool-set names that this prompt is allowed to use (only applicable if running in agent mode and if tools are available). For example, you might list `['terminal', 'browser', 'search']` to allow those tools during the prompt execution[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=,If). If a listed tool isn’t actually available, it will be ignored. (If not running in agent mode, tools list is ignored.)
-
-After the frontmatter, the **body of the `.prompt.md` file** is where you write the actual prompt instructions, in Markdown. This can be multiple paragraphs, include code blocks, etc. You can also reference other files or other prompt/instruction files by relative Markdown links to avoid duplication[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=Reference%20other%20workspace%20files%2C%20prompt,location%20of%20the%20prompt%20file).
-
-**Example prompt file with frontmatter:**
-
-`---`
-`description: "Convert a code snippet into a well-documented function"`
-`mode: "edit" # use edit mode (applies changes to code)`
-`model: "GPT-4" # ensure a powerful model for better docs`
-`tools: [] # (no external tools needed for this prompt)`
-`---`
-`# Convert to Documented Function`
-
-`Take the selected code and refactor it into a self-contained function with a clear name.`
-
-`- The new function should have a concise docstring explaining its purpose, inputs, and output.`
-`- Add comments inside the function to explain complex logic, if any.`
-`- **Do not** change the external behavior of the code.`
-
-`If the selected code is not a complete snippet (e.g., part of a larger expression), make an assumption to create a valid function.`
-
-In this example, the prompt file (say we named it `refactor.prompt.md`) can be invoked in VS Code by typing `/refactor` in the Copilot chat, or by running a command. It tells Copilot (in edit mode) to transform the selected code into a documented function. The YAML header ensures it uses the edit mode and GPT-4 model.
-
-**Notes and Best Practices:**
-
-* When writing the prompt (body), clearly state the task and any format you expect in the answer. The AI will follow these instructions when you run the prompt.
-
-* You can include **placeholders or variables** in prompt files. For instance, VS Code supports placeholders like `${selection}` (the currently selected text), `${file}` (current filename), or custom inputs like `${input:variableName}` where the user can supply additional data[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=Within%20a%20prompt%20file%2C%20you,can%20reference%20the%20following%20variables). In our example, we implicitly rely on the selected code (since it’s an edit mode prompt).
-
-* **Link to instructions or other prompts:** You can compose prompt files by linking to other instruction files or prompt files. For example, you might have a general style guide in an instructions file and within your prompt say “Follow our Python style guide” to automatically bring in those rules[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=Reference%20other%20workspace%20files%2C%20prompt,location%20of%20the%20prompt%20file).
-
-* Keep the `description` concise – think of it as tooltip text. It should summarize the prompt’s action (e.g., “Generate a release notes summary from commit messages”).
-
-* The `mode` field is important: use *ask* for things that don’t involve editing code (just Q\&A or explanation), *edit* for code transformations, and *agent* if the prompt might require using tools (like browsing documentation, running tests, etc.)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=,If%20not%20specified).
-
-* Only list necessary `tools`. For instance, if your prompt needs to search the codebase or run a shell command, include those; otherwise leaving it empty (or omitting the field) is fine. Unnecessary tools can introduce side effects or extra context that might confuse the AI.
-
-## **GitHub Copilot – Custom Chat Modes (`.chatmode.md`)**
-
-**Custom chat modes** allow you to define an entirely new mode for Copilot Chat, with specialized behavior or purpose. Each mode is defined in a file with extension `.chatmode.md`. The structure is similar to prompt files: an optional YAML frontmatter header, followed by Markdown instructions in the body[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=Chat%20mode%20files%20are%20Markdown,extension%20and%20have%20this%20structure)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=).
-
-**YAML frontmatter fields for chat modes**[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=,in%20model%20picker%20is%20used):
-
-* **`description`** – A brief description of the chat mode’s purpose. This is displayed as placeholder text in the chat input when the mode is active and as a tooltip when hovering over the mode in the mode selector[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=,in%20model%20picker%20is%20used).
-
-* **`tools`** – A list of tool names or predefined tool sets that are available in this mode[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=displayed%20as%20placeholder%20text%20in,and%20instructions%20in%20Markdown%20format). You might include built-in tools like `'terminal'`, `'browser'`, `'search'`, or any extension-contributed tools. (This works just like the `tools` field in prompt files, but here it defines tools for any prompt in this mode.)
-
-* **`model`** – The AI model to use when this mode is active. If not specified, it will use whichever model the user has currently selected by default[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=contributed%20by%20extensions,in%20model%20picker%20is%20used). You can set this if the mode is best suited to a particular model (e.g., a lightweight model for quick responses, or a specific one like `"Claude Instant 1"` or `"GPT-4"` if available).
-
-The body of the file contains the **detailed instructions or persona for that mode**. These instructions will be *prepended* or considered alongside the user’s inputs whenever this mode is used in chat. Essentially, this is where you set the behavior. For example, a “SQL Assistant” mode might have instructions like “You are an expert SQL assistant. Answer all questions with SQL examples when possible,” etc. You can include whatever guidance needed, including sections, lists, or Markdown formatting.
-
-You may also **reference other instruction or prompt files** in the mode’s body via Markdown links if you want to pull in shared rules (the content of those files will be included when the mode runs)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=This%20is%20where%20you%20provide,when%20in%20this%20chat%20mode).
-
-**Example of a custom chat mode file:**
-
-`---`
-`description: "Plan new features without writing any code (outputs an implementation plan)"`
-`tools: ['search', 'codebase'] # allow searching the repository and codebase introspection`
-`model: "GPT-4" # use a powerful model for thorough analysis`
-`---`
-`# Planning Mode`
-
-`You are in **Planning Mode**. Your job is to help plan out implementations for new feature requests or major refactors, without writing actual code.`
-
-`When the user asks a question or provides a feature description in this mode:`
- `- Do **not** produce any source code.`
- `- Instead, break the problem down into a series of steps, considerations, or tasks.`
- `- Provide the output as a Markdown document with sections for "Overview", "Requirements", "Implementation Plan", and "Testing Strategy".`
-
-`Always ask for clarification if requirements are ambiguous. This mode is about high-level planning and clarification.`
-
-In this example, we set up a mode that helps with planning. We gave it a description (which would show up as placeholder text like “Plan new features without writing code…” in the chat input when selected). We limited tools to just `'search'` and `'codebase'` (so it can search the project, but not run terminal commands or web fetches, for instance). We also specified the model as GPT-4 for better quality. The body instructions clearly state the role and what the assistant should and shouldn’t do in this mode.
-
-**Using and creating chat modes:**
-
-* Chat mode files for a **workspace** are typically stored in `.github/chatmodes/` (you may need to create this folder). You can also keep personal modes in your user profile (outside of any repo)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=2,mode%20file%20should%20be%20created).
-
-* Once a mode is created and the file is present, it will appear in the Copilot Chat interface as a selectable mode (alongside default modes like “Ask”, “Edit”, etc.). The `description` will show as ghost text in the input box, guiding the user on what that mode is for[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=).
-
-* Provide a clear **name** for the mode by the file name itself. For example, `planning.chatmode.md` will create a mode named “planning” (VS Code will use the file name as the mode name).
-
-* The YAML frontmatter is optional; if you omit, the mode will just use the current model and no special tool restrictions (which might be fine in some cases). However, providing at least a description is recommended for clarity.
-
-* **Tool configuration:** Only list tools that are needed for the mode’s purpose. For instance, a “Web Research” mode might enable a browser or web search tool, whereas a “Code Cleanup” mode might only need access to the codebase and perhaps a terminal to run linters.
-
-* **Testing:** After writing a mode’s instructions, test it by switching to that mode and prompting the assistant. Tweak the instructions as needed if the output isn’t as expected. For complex modes, sometimes breaking the instructions into bullet points (as in the example) helps the AI follow them systematically.
-
-## **Unified Multi-Agent Instructions – `AGENTS.md`**
-
-There is an emerging convention (sometimes called the “Agent Rules standard”) to use a file named **`AGENTS.md`** at the root of a project to provide guidelines that apply to *all* AI assistants/agents working on the repository[github.com](https://github.com/continuedev/continue/issues/6716#:~:text=The%20Agent%20Rules%20initiative%20proposes,continue%2Frules%2F%20system)[github.com](https://github.com/continuedev/continue/issues/6716#:~:text=,as%20natural%20language%20if%20none). Think of it as a central place to define coding conventions, architectural overviews, or any rules that any AI (whether GitHub Copilot, Claude, Gemini, or others) should follow when generating content for this repo.
-
-In the context of **GitHub Copilot in VS Code**, an `AGENTS.md` file (if enabled in settings) will automatically be pulled into context for **all Copilot chat requests**, regardless of mode[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-instructions#:~:text=If%20you%20work%20with%20multiple,chat%20requests%20within%20this%20workspace). This is useful if you work with multiple AI backends (GitHub’s model, OpenAI’s, Anthropic’s, etc.) so they all get the same project-specific instructions.
-
-**Format:** The `AGENTS.md` file is simply a Markdown file. Typically, it does **not require any YAML frontmatter** – you can just start with normal text or Markdown headings. For example, your `AGENTS.md` might contain:
-
-`# Project AI Guidelines`
-
-`- All code must follow the style guide in [CONTRIBUTING.md](CONTRIBUTING.md).`
-`- Assume the user is familiar with the project’s domain; avoid explaining basic concepts.`
-`- Prioritize security and privacy: do not output secrets or credentials, and mention security implications of code changes.`
-`- Every generated function *must* have a docstring.`
-
-This would act as a set of universal instructions. Whenever Copilot (or other integrated agents) generate code or responses for this repository, they would ideally consider these guidelines. The **scope** of `AGENTS.md` is broad – by design it should hold rules that are generally applicable to any AI actions in the repo (akin to an `.editorconfig` but for AI).
-
-**Do’s and Don’ts:**
-
-* **Do include high-level or project-wide concerns**: e.g., “We use tabs, not spaces”, “No external library imports without approval”, “Follow OWASP security best practices”, etc.
-
-* **Don’t include extremely granular instructions** that might only apply in certain contexts – those might be better in the specific prompt or handled by an `.instructions.md` for that context. `AGENTS.md` should be relatively static and universal.
-
-* Typically, you don’t need `applyTo` patterns here, because it’s meant to always apply to everything (the tools or editors that support `AGENTS.md` treat it as global). Some tools or proposals allow YAML frontmatter in `AGENTS.md` to fine-tune applicability[github.com](https://github.com/continuedev/continue/issues/6716#:~:text=,as%20natural%20language%20if%20none), but generally you can omit it. The file is implicitly applied to all files/agents.
-
-* Keep it maintainable: since many AI tools now look for `AGENTS.md`, it’s a single source of truth. Update it as your practices evolve. If it gets too long, consider splitting certain parts into more targeted instruction files (and you can reference them from `AGENTS.md` if needed).
-
-**Note:** This concept is gaining traction to unify AI assistant behavior across different platforms. GitHub’s documentation notes that instead of multiple `.instructions.md` files, you can also use a single `AGENTS.md` (or model-specific files like `CLAUDE.md`, `GEMINI.md` as noted below) and the “nearest” such file up the directory tree will be used[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=,by%20AI%20agents). The goal is to avoid duplicating rules for each AI vendor.
-
-In summary, if you have a **mixed AI environment** or just want a one-stop config, `AGENTS.md` is the way to go. If you’re only using GitHub Copilot, `.github/copilot-instructions.md` plus selective instruction files might suffice, but there’s no harm in also having an `AGENTS.md` as a fallback for other tools (many third-party AI dev tools now check for this file).
-
-## **Anthropic Claude – Custom Instructions (`CLAUDE.md`)**
-
-Anthropic’s Claude (especially **Claude Code**, their coding assistant) allows project-specific customization via a file commonly named **`CLAUDE.md`**. This file serves a purpose similar to `AGENTS.md` but specifically for Claude. According to Anthropic, Claude will automatically look for a file named `CLAUDE.md` in your repository and load it as part of its system prompt (what Anthropic calls a “memory file”) every time you start a Claude session in that project[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=System%20prompt%20availability).
-
-**Format:** `CLAUDE.md` is a plain Markdown file. There is no required YAML frontmatter schema for it – you just fill it with any instructions or context you want Claude to always have. This could include things like coding style guidelines, a high-level overview of the project, important conventions, etc. Essentially, it’s a way to give Claude persistent knowledge or rules without having to repeat them in each prompt.
-
-For example, `CLAUDE.md` might contain:
-
-`# Claude Instructions for MyProject`
-
-`**Project Overview:** This is a web application for online book reviews. It uses a Python Flask backend and a React frontend.`
-
-`**Coding Style:** Follow PEP8 for Python code (use 4 spaces indentation, snake_case for functions). For JavaScript/React, follow Airbnb style guide.`
-
-`**Testing:** Whenever you write new code, include unit tests (PyTest for backend, Jest for frontend).`
-
-`**Do’s:**`
-`- Be concise in explanations.`
-`- Use docstrings in all public functions.`
-
-`**Don’ts:**`
-`- Don’t disclose any API keys or secrets that might be in the code.`
-`- Don’t make assumptions about user data; validate everything.`
-
-When you open Claude in the context of this repo, it will read that file and incorporate these points into its responses. This mechanism is powerful for shaping Claude’s behavior.
-
-**Tips:**
-
-* Think of `CLAUDE.md` as “setting the stage” for Claude. It’s loaded as part of Claude’s initial prompt. So it can contain a mix of factual info (project summary) and normative guidelines (style rules, etc.).
-
-* You can use Markdown formatting, but remember that it’s primarily for you – the formatting (bold, headings) might slightly influence Claude (it might assume bold means important), but mostly it’s to keep the file organized.
-
-* Keep it reasonably sized. Claude has context limits; a very large CLAUDE.md could consume a lot of tokens. Focus on the most important guidance.
-
-* If you have multiple Claude-specific files (though typically one is enough), Claude will by default load the one in the root. Anthropic’s tooling might also recognize `docs/claude.md` or similar, but **the standard is root-level `CLAUDE.md`**.
-
-**Note:** Claude also supports an **API for “sub-agents”** (discussed next) which use YAML frontmatter. But the top-level CLAUDE.md itself is straightforward Markdown. It’s essentially a special case of the more general `AGENTS.md` idea, dedicated just to Claude. GitHub’s Copilot integration notes that you can use a `CLAUDE.md` in combination with Copilot’s agent, presumably for when Copilot is backed by Claude or working alongside Claude[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=You%20can%20create%20one%20or,directory%20tree%20will%20take%20precedence).
-
-## **Anthropic Claude – Custom Sub-Agents (YAML Configuration)**
-
-Claude’s advanced **subagent** feature allows you to create multiple specialized AI “agents” under the main Claude agent. Each sub-agent is defined by a Markdown file with a YAML frontmatter header that Claude reads to configure that agent’s identity and permissions[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=Subagent%20configuration)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=Subagents%20are%20defined%20as%20Markdown,or%20from%20your%20user%20scope). These are usually stored in a `.claude/agents/` directory (for project-specific agents) or `~/.claude/agents/` (for user-wide agents)[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=Claude%20Code%20supports%20custom%20AI,Markdown%20files%20with%20YAML%20frontmatter).
-
-A subagent file’s **YAML frontmatter** typically includes:
-
-* **`name`** – The name of the subagent. This is how you will invoke it (Claude can be prompted to delegate tasks to an agent by name)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=,plus%20the%20system%20prompt).
-
-* **`description`** – A short description of what the subagent’s role or specialty is[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=,plus%20the%20system%20prompt). Claude may use this to decide when to auto-delegate tasks. It’s also useful documentation for you and your team.
-
-* **`tools`** – *(Optional)* A list of tools that this subagent is allowed to use[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=). Claude operates with a set of tools (like reading files, writing files, running shell commands, web search, etc.). By specifying `tools` here, you **whitelist** which ones the subagent can access. If you omit `tools`, the subagent inherits all the tools available to the main Claude session (which might be too permissive in some cases)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=%60Use%20the%20implementer,presets). For tighter control, list only what it needs (e.g., maybe a “DatabaseAgent” only gets read/write database access, nothing else).
-
-After the frontmatter, the rest of the file is the **subagent’s prompt/instructions** – essentially a dedicated system prompt for that subagent. This is where you describe in detail how the subagent should behave, its step-by-step approach, or any domain knowledge it should have.
-
-**Example subagent file (`architect-review.md`):**
-
-`---`
-`name: "architect-review"`
-`description: "Architect Agent – validates designs against constraints and produces an architecture decision record."`
-`tools: ["Read", "Search"] # e.g., can read files and search documentation, but not write code`
-`---`
-`You are the **Architect** sub-agent. Your goal is to review proposed software designs or feature specifications and ensure they meet the system's constraints and best practices.`
-
-`When activated, you will:`
-``- Read the feature specification from the repository (`specs/` directory).``
-`- Analyze it for compliance with our scalability and security requirements.`
-`- Output an **Architecture Decision Record (ADR)** with sections for Context, Decision, Rationale, and Consequences.`
-
-`You should not write any code. Focus only on architectural guidance. If the spec is unclear, list assumptions or ask for clarification.`
-
-In this file, the YAML header gives the subagent a name (“architect-review”), a description, and limits its tools. The body instructs it on exactly what to do when called. Claude’s main agent can be asked, *“Use the architect-review subagent on the new feature spec,”* and it will spin up this specialized agent with these instructions to perform that task[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=%2A%20Usage%3A%20Claude%20can%20auto,presets).
-
-**Key Points for Claude Subagents:**
-
-* Store project subagents in the repository under `.claude/agents/`. This makes them shareable with the team (and version controlled). User-level (global) agents go in `~/.claude/agents/` on your machine[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=Claude%20Code%20supports%20custom%20AI,Markdown%20files%20with%20YAML%20frontmatter).
-
-* The **filename** isn’t directly used as the name; it’s the `name:` in YAML that counts. However, by convention, you might name the file the same as the agent name for clarity.
-
-* The `description` should be action-oriented, because Claude can auto-select subagents based on descriptions. For instance, if the description says “writes unit tests”, Claude might automatically use that agent when a task is about testing.
-
-* If `tools` is not specified, the subagent can use any tool the main agent has, which might be fine for general-purpose agents. If you want to sandbox an agent, list only specific tools. For example, a “QA” agent might only need read access (to verify code) and perhaps run tests, but not write access.
-
-* You can define multiple subagents to form a pipeline. For example, one subagent could be “planner”, another “coder”, another “tester”, each with its own YAML config and instructions, and you orchestrate them (often using Claude’s **hooks** or by manual prompts)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=%2A%20Reproducibility%3A%20Stop%20re,and%20hooks%20codify%20repeatable%20steps)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=We%20started%20with%20a%20three,that%E2%80%99s%20generic%20to%20any%20stack).
-
-* **Best practices:** Give each subagent one clear responsibility (single responsibility principle)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=1%29%20Single). Keep their instructions focused on that role. This makes the overall AI workflow more reliable and easier to troubleshoot.
-
-* **Security:** Use the `tools` limitation to prevent a subagent from doing things it shouldn’t. For instance, a planning agent probably doesn’t need the `Execute` (shell command) tool. And as noted in Anthropic’s docs, if you want to exclude access to certain files entirely, you’d configure that in Claude’s permissions (which is outside the scope of the YAML, done in `.claude/settings.json`)[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=,working%20directories%20that%20Claude%20has)[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=,to%20prevent%20%60bypassPermissions).
-
-In summary, Claude’s subagents use YAML frontmatter for **metadata and permissions** and Markdown body for the **agent’s persona/instructions**. It’s a powerful system to split tasks among “expert” agents.
-
-## **Google Gemini – Custom Instructions (`GEMINI.md`)**
-
-Google’s **Gemini** (an AI model from Google) is still relatively new on the scene for code assistance, and detailed public documentation on project-specific config is sparse. However, we can draw parallels from patterns established by others and hints from tools:
-
-GitHub’s Copilot documentation and community standards suggest that you can use a **`GEMINI.md`** file at the root of your repository to provide custom instructions when using a Gemini-based AI assistant[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=You%20can%20create%20one%20or,directory%20tree%20will%20take%20precedence). This is analogous to `CLAUDE.md` for Claude. For example, if an AI extension or tool uses Google’s Gemini model to assist with your code, it could check for `GEMINI.md` to preload instructions.
-
-Since specifics aren’t officially published, we’ll assume **`GEMINI.md` is treated like a free-form instructions file**, just like `CLAUDE.md`. That means likely no required YAML keys, just Markdown content (unless a specific tool layer adds its own frontmatter options).
-
-What might you put in a `GEMINI.md`? Probably similar content to CLAUDE.md or AGENTS.md: high-level guidelines, project overview, dos/don’ts for the AI. For example:
-
-`# Gemini Instructions for MyProject`
-
-`This project is a machine learning pipeline for image classification.`
-
-`- The codebase is primarily TensorFlow (Python) and some C++ for performance-critical components.`
-`- **Style Guidelines:** Follow Google Python style guide. In C++ code, follow Google C++ style.`
-`- **Important:** Do not use external packages that are not already in the requirements.txt.`
-`- Focus on clarity and maintainability over cleverness.`
-
-`If asked to produce a solution, prefer simple implementations and add comments explaining any non-obvious steps.`
-
-If a Gemini-powered tool is being used, it would incorporate those notes.
-
-**Parameters for custom agents:** If in the future tools allow more structured config for Gemini, it would likely mirror the structure of subagents (name, description, etc.) if Gemini supports multiple specialized agents. There’s also mention that some CLI tools (Codex CLI, Aider, etc.) and potentially a “Gemini CLI” support the same **Agent Rules** standard (i.e., `AGENTS.md`)[github.com](https://github.com/continuedev/continue/issues/6716#:~:text=The%20Agent%20Rules%20initiative%20proposes,continue%2Frules%2F%20system). This means Gemini might already respect a unified format with YAML frontmatter if present. For now, though, a single `GEMINI.md` with plain text instructions is the safe bet.
-
-**Best Practices:**
-
-* Treat `GEMINI.md` much like `CLAUDE.md`: keep it concise and focused on things unique to your project or preferences.
-
-* Since Gemini is from Google and likely tuned with different data, be explicit about things like privacy or licensing constraints in your instructions (e.g., “Don’t suggest any solution that would violate our license terms” if relevant).
-
-* Update the file as the project evolves – if certain frameworks are deprecated or new conventions adopted, reflect that in the instructions.
-
-**Note:** If you’re not actively using any Gemini-based coding assistant, you don’t need a GEMINI.md yet. But some teams include it preemptively as part of adopting the `AGENTS.md` convention, in case collaborators use different AI tools. It doesn’t harm anything to have it there. In the future, we expect more concrete schemas or tools for Gemini; until then, stick to the general guidance approach.
-
----
-
-**Summary:** The table below recaps the **YAML frontmatter fields** discussed for each file type:
-
-* **Issue Template (YAML form)** – `name`, `description` (or `about`), `title`, `labels`, `assignees`, `projects`, `type`, and a structured `body` with `type`, `id`, `attributes`, and `validations` for each input[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,repository%2C%20it%20will%20not%20be)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,using%20this%20template%20to%20have).
-
-* **PR Template** – *(same fields as issue template, but not currently parsed by GitHub)*[stackoverflow.com](https://stackoverflow.com/questions/66392676/github-pull-request-template-detect-yaml-front-matter-using-config-yml-and-apply#:~:text=,request%20assignees%3A%20self).
-
-* **Saved Reply** – *no YAML (title & body managed via UI)*.
-
-* **Copilot Repo Instructions** – *no YAML needed (just markdown content in* `.github/copilot-instructions.md`*)*.
-
-* **Copilot Path Instructions** – `applyTo` (pattern) and optional `description` in frontmatter[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=3,directories%20the%20instructions%20apply%20to)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-instructions#:~:text=,Body%3A%20Instructions%20in%20Markdown%20format); body is markdown instructions.
-
-* **Copilot Prompt File** – `description`, `mode` (`ask|edit|agent`), `model`, `tools` in frontmatter[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=); body is the prompt text.
-
-* **Copilot Chat Mode** – `description`, `tools`, `model` in frontmatter[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=,in%20model%20picker%20is%20used); body is mode-specific instructions.
-
-* **AGENTS.md** – *generally no fixed fields; global instructions for all AIs (some tools may parse frontmatter if included, but typically just markdown content)*.
-
-* **Claude CLAUDE.md** – *no fixed fields; markdown instructions for Claude*[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=System%20prompt%20availability).
-
-* **Claude Subagent** – `name`, `description`, `tools` (optional) in frontmatter[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=,plus%20the%20system%20prompt); body is that agent’s system prompt.
-
-* **Gemini GEMINI.md** – *no known fixed schema; markdown instructions (analogous to CLAUDE.md)*[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=You%20can%20create%20one%20or,directory%20tree%20will%20take%20precedence).
-
-By using the above configurations, you can customize issue and PR workflows on GitHub, as well as tailor AI assistants (like Copilot, Claude, and eventually Gemini) to better suit your project’s needs. Each file has a specific role – from guiding human contributors (templates) to guiding AI behavior (instructions and prompts). Use them in combination for the best effect (for instance, an issue template can gather structured data from a user, and your Copilot instructions can remind the AI to utilize that data when generating code or responses).
-
diff --git a/YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files1.md b/YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files1.md
deleted file mode 100644
index d732a97..0000000
--- a/YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files1.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# **YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files**
-
-comprehensive breakdown of YAML frontmatter schemas for the following file types:
-
-* GitHub issue and PR templates
-
-* GitHub saved replies
-
-* GitHub Copilot: custom instructions, prompt files, `AGENTS.md`, and `.chatmode.md`
-
-* Claude agents (Anthropic YAML-based config)
-
-* Gemini agents (Google)
-
-For each, I’ll include:
-
-* Maximum parameter set and required vs optional fields
-
-* Example YAML frontmatter blocks
-
-* Best practices and caveats
-
-* Placeholder documentation next to each field
-
-* Recommended folder/filename conventions
-
-* YAML schema examples where available or inferred
-
-I’ll also reference the two zips you provided (`awesome-copilot-main` and the awesome-chat examples) and cross-check with the official docs.
-
diff --git a/YAML-Frontmatter-Copilot-Space-Instructions.md b/YAML-Frontmatter-Copilot-Space-Instructions.md
deleted file mode 100644
index a3ace17..0000000
--- a/YAML-Frontmatter-Copilot-Space-Instructions.md
+++ /dev/null
@@ -1,628 +0,0 @@
-# **Copilot Space Instructions v1**
-
-# **Build a "Copilot Space" with instructions for all frontmatter file types**
-
-Create directories:
-
-* .devcontainer
-* .copilot
-* .github
-* .github/agents
-* .github/chatmodes
-* .github/instructions
-* .github/prompts
-* .github/ISSUE\_TEMPLATES
-* .github/PULL\_REQUEST\_TEMPLATES
-* .github/workflows
-* .vscode
-* docs/copilot-space
-* docs/copilot-space/schemas
-
-# **Top-level README guiding to Copilot Space**
-
-readme \= """\# Copilot Space — Frontmatter & Agent Config Guide
-
-This repository contains a **Copilot Space**: a self-contained set of docs, prompts, and chat modes that teach GitHub Copilot (and other agents) how to use **YAML frontmatter** across common file types.
-
-**Start here:** `docs/copilot-space/INDEX.md`
-
-Contents:
-
-- Cheat sheets & examples for Issue/PR templates, Copilot instructions, prompt files, chat modes.
-- Claude subagents, AGENTS.md, CLAUDE.md, GEMINI.md conventions.
-- Ready-to-use Copilot prompt and chat mode for on-demand assistance. """
-
-index\_md \= """\# Copilot Space Index — YAML Frontmatter Playbook
-
-Use the links below for targeted guidance and copy-pasteable examples.
-
-## **GitHub Templates**
-
-- [Issue Templates (Issue Forms)](http://issue-templates.md)
-- [Pull Request Templates](http://pr-templates.md)
-- [Saved Replies (no frontmatter)](http://saved-replies.md)
-
-## **Copilot Customisation**
-
-- [Repo & Path Instructions (`copilot-instructions.md`, `*.instructions.md`)](http://copilot-instructions.md)
-- [Reusable Prompt Files (`*.prompt.md`)](http://prompt-files.md)
-- [Custom Chat Modes (`*.chatmode.md`)](http://chatmodes.md)
-- [AGENTS.md (universal rules)](http://agents-md.md)
-
-## **Claude & Gemini**
-
-- [Claude: `CLAUDE.md` & Subagents (`.github/agents/*.md`)](http://claude-agents.md)
-- [Gemini: `GEMINI.md` (conventions)](http://gemini-md.md)
-
-## **Schemas (reference)**
-
-- [Issue Form YAML keys](http://schemas/issue-form-schema.md)
-- [Copilot Prompt frontmatter](http://schemas/prompt-frontmatter-schema.md)
-- [Chat Mode frontmatter](http://schemas/chatmode-frontmatter-schema.md)
-- [Claude Subagent frontmatter](http://schemas/claude-subagent-schema.md) """
-
-issue\_templates\_md \= """\# Issue Templates (Issue Forms) — YAML Frontmatter
-
-**Location:** `.github/ISSUE_TEMPLATE/*.yml`
-
-**Required top-level keys:**
-
-- `name` *(string)* — Template name (shown in picker).
-- `description` *(string)* — What this template is for.
-- `body` *(array)* — Form blocks (markdown/input/textarea/dropdown/checkboxes).
-
-**Optional top-level keys:** `title`, `labels`, `assignees`, `projects`, `type`.
-
-### **Full Example**
-
-name: "🐛 Bug report" \# required
-
-description: "Report a bug to help us improve" \# required
-
-title: "\[Bug\]: " \# optional default issue title
-
-labels: \["bug","needs-triage"\] \# optional auto labels
-
-assignees: \[\] \# optional auto assignees
-
-projects: \["my-org/42"\] \# optional projects
-
-type: bug \# optional issue type
-
-body:
-
- \- type: markdown
-
- attributes:
-
- value: |
-
- \#\# Thanks for reporting\!
-
- Please provide enough detail to reproduce the issue.
-
- \- type: input
-
- id: version
-
- attributes:
-
- label: "Version"
-
- description: "Which version/commit?"
-
- placeholder: "v1.2.3 or SHA"
-
- validations:
-
- required: true
-
- \- type: textarea
-
- id: repro
-
- attributes:
-
- label: "Steps to reproduce"
-
- placeholder: |
-
- 1\. Go to '...'
-
- 2\. Click '...'
-
- 3\. See error
-
- validations:
-
- required: true
-
- \- type: dropdown
-
- id: env
-
- attributes:
-
- label: "Environment"
-
- options: \["macOS","Windows","Linux","Other"\]
-
- multiple: true
-
- validations:
-
- required: true
-
- \- type: checkboxes
-
- id: checks
-
- attributes:
-
- label: "Checks"
-
- options:
-
- \- label: "I searched for duplicates"
-
- required: true
-
- \- label: "I can reproduce with latest"
-
-**Do**
-
-* Use `|` for multiline text blocks.
-
-* Quote strings that include `#` or `:`.
-
-* Require only fields that truly block triage.
-
-**Don’t**
-
-* Overload forms with unnecessary inputs.
-
-* Use PR-style frontmatter here.
- """
-
-pr\_templates\_md \= """\# Pull Request Templates
-
-**Location:** `.github/PULL_REQUEST_TEMPLATE/*.md` (Markdown)
-
-PR templates **do not** support form-style YAML frontmatter. Keep the template in Markdown with headings and HTML comments for guidance.
-
-### **Example**
-
-Always show details
-`## Summary`
-``
-
-`## Related Issues`
-`Closes #123`
-
-`## Changes`
-`- [ ] Code`
-`- [ ] Tests`
-`- [ ] Docs`
-
-`## Screenshots`
-``
-
-`## Checklist`
-`- [ ] Read CONTRIBUTING`
-`- [ ] Ran tests`
-`- [ ] Followed style guides`
-
-"""
-
-saved\_replies\_md \= """\# Saved Replies (GitHub UI)
-
-Saved replies are managed in **GitHub Settings** (Profile → Saved replies).
- They have a **title** and **body**; there is **no file-based frontmatter**.
-
-**Tip:** Keep replies short and customise after insertion.
- """
-
-copilot\_instructions\_doc \= """\# Copilot Custom Instructions
-
-## **Repository-wide**
-
-**File:** `.github/copilot-instructions.md`
- Plain Markdown. No YAML required.
-
-Use this file for always-on guidance (style, patterns, security notes).
-
-## **Path-specific**
-
-**Folder:** `.github/instructions/`
- **File pattern:** `*.instructions.md` with YAML frontmatter.
-
-Always show details
-`---`
-`applyTo: "src/**/*.{js,ts,tsx}" # glob(s) for files this applies to`
-`description: "Frontend coding rules" # optional tooltip/label`
-`---`
-`# Frontend Guidelines`
-`- Prefer functional components and hooks`
-`- Add tests for new components`
-
-**Tips**
-
-* Combine globs with commas: `applyTo: "src/**/*.ts,tests/**/*.ts"`
-
-* Keep rules concise; whitespace is ignored by Copilot.
- """
-
-prompt\_files\_doc \= """\# Copilot Reusable Prompts (`*.prompt.md`)
-
-**Folder:** `.github/prompts/`
-
-**Frontmatter keys:**
-
-* `description` — tooltip text for the prompt.
-
-* `mode` — `"ask" | "edit" | "agent"`.
-
-* `model` — model name (else use current).
-
-* `tools` — allowed tools (agent mode).
-
-### **Example**
-
-Always show details
-`---`
-`description: "Refactor selected code into a documented function"`
-`mode: "edit"`
-`model: "GPT-4"`
-`tools: []`
-`---`
-`# Refactor to Function`
-`Convert the selected code into a self-contained function:`
-`- Add docstring`
-`- Preserve behaviour`
-
-**Do** reference shared guides via Markdown links to avoid duplication.
- """
-
-chatmodes\_doc \= """\# Custom Chat Modes (`*.chatmode.md`)
-
-**Folder:** `.github/chatmodes/`
-
-**Frontmatter keys:**
-
-* `description` — placeholder text & hover text.
-
-* `tools` — available tools.
-
-* `model` — model to pin (optional).
-
-### **Example**
-
-Always show details
-`---`
-`description: "Plan features without writing code; output an implementation plan."`
-`tools: ["search","codebase"]`
-`model: "GPT-4"`
-`---`
-`# Planning Mode`
-`- No source code in answers`
-`- Provide: Overview, Requirements, Plan, Risks, Tests`
-
-**Tip:** Name the file to reflect the mode: `planning.chatmode.md` → mode **Planning**.
- """
-
-agents\_md\_doc \= """\# AGENTS.md (Universal Rules)
-
-**File:** `AGENTS.md` at repo root.
- A vendor-neutral rulebook applied by many AI tools.
-
-**Content ideas**
-
-* Security & privacy (no secrets)
-
-* Style & testing expectations
-
-* Architectural patterns to follow/avoid
-
-* License and dependency policies
- """
-
-claude\_agents\_doc \= """\# Claude — `CLAUDE.md` & Subagents
-
-## **`CLAUDE.md`**
-
-Root-level Markdown file with persistent project instructions for Claude. No frontmatter needed.
-
-## **Subagents**
-
-**Folder:** `.github/agents/`
- Each subagent is a Markdown file with YAML frontmatter:
-
-Always show details
-`---`
-`name: "architect-review" # how Claude refers to this agent`
-`description: "Reviews designs and produces an ADR"`
-`tools: ["Read","Search"] # limit tool access (optional)`
-`---`
-`# Architect Review Agent`
-`Your task is to review specs and output an ADR (Context, Decision, Rationale, Consequences).`
-
-**Tips**
-
-* Single responsibility per subagent
-
-* Restrict tools to the minimum set
-
-* Keep the body focused and actionable
- """
-
-gemini\_doc \= """\# Gemini — `GEMINI.md` (Convention)
-
-**File:** `GEMINI.md` at repo root (conventional).
- Use as a persistent instruction file for Gemini-based tools.
-
-**Suggested content**
-
-* Tech stack and constraints
-
-* Style & testing expectations
-
-* Privacy and security notes
- """
-
-# **Schemas (concise)**
-
-issue\_schema \= """\# Issue Form — Frontmatter Keys
-
-Always show details
-`name: string # required`
-`description: string # required`
-`title: string # optional`
-`labels: [string] | string # optional`
-`assignees: [string] | string # optional`
-`projects: [string] # optional (OWNER/NUMBER)`
-`type: string # optional`
-`body: # required`
- `- type: markdown|input|textarea|dropdown|checkboxes`
- `id: string # optional`
- `attributes:`
- `label: string # required (except markdown)`
- `description: string # optional`
- `placeholder: string # optional`
- `value: string # optional`
- `options: [string] # required for dropdown/checkboxes`
- `multiple: boolean # dropdown only`
- `render: string # textarea (e.g., bash, markdown)`
- `validations:`
- `required: boolean`
-
-"""
-
-prompt\_schema \= """\# Prompt File — Frontmatter Keys
-
-Always show details
-`description: string # tooltip`
-`mode: ask|edit|agent # defaults to current`
-`model: string # optional`
-`tools: [string] # agent-only`
-
-"""
-
-chatmode\_schema \= """\# Chat Mode — Frontmatter Keys
-
-Always show details
-`description: string # placeholder & tooltip`
-`tools: [string] # optional tool allowlist`
-`model: string # optional pinned model`
-
-"""
-
-claude\_subagent\_schema \= """\# Claude Subagent — Frontmatter Keys
-
-Always show details
-`name: string # subagent handle`
-`description: string # purpose / when to use`
-`tools: [string] # optional tool allowlist`
-
-"""
-
-# **Copilot prompt to pull the guide content on demand**
-
-## **frontmatter\_prompt \= """---**
-
-## **description: "Frontmatter Guide: answer using docs in docs/copilot-space/\*"**
-
-## **mode: "ask"**
-
-## **model: ""**
-
-## **tools: \[\]**
-
-# **Frontmatter Guide Prompt**
-
-When asked about YAML frontmatter or AI agent config:
-
-* Consult the repository docs under `docs/copilot-space/`.
-
-* Provide short, actionable answers with code blocks.
-
-* Link to the exact doc path you used.
- """
-
-# **Chat mode to anchor behaviour**
-
-## **frontmatter\_chatmode \= """---**
-
-## **description: "Frontmatter mode: quick answers \+ examples from docs/copilot-space"**
-
-## **tools: \["codebase"\]**
-
-## **model: ""**
-
-# **Frontmatter Chat Mode**
-
-You specialise in YAML frontmatter and AI agent configuration for GitHub repos.
- Use examples from `docs/copilot-space/` and keep responses concise for developers.
- """
-
-# **Instruction file to bias markdown authoring**
-
-## **frontmatter\_instructions \= """---**
-
-## **applyTo: "\*\*/\*.md"**
-
-## **description: "Authoring guidance for frontmatter docs"**
-
-# **Authoring Guidance**
-
-* Prefer concise explanations next to examples.
-
-* Use fenced code blocks with language identifiers.
-
-* Include Do/Don’t lists where useful.
- """
-
-# **Agent example for this space**
-
-## **space\_agent \= """---**
-
-## **name: "frontmatter-librarian"**
-
-## **description: "Finds and cites the correct frontmatter pattern from docs/copilot-space"**
-
-## **tools: \["Read","Search"\]**
-
-# **Frontmatter Librarian Agent**
-
-* When queried, scan `docs/copilot-space/` for the most relevant example.
-
-* Return the example with a one-paragraph explanation and a short Do/Don’t list.
- """
-
-# **Write files**
-
-files \= {
- "README.md": readme,
- "docs/copilot-space/INDEX.md": index\_md,
- "docs/copilot-space/issue-templates.md": issue\_templates\_md,
- "docs/copilot-space/pr-templates.md": pr\_templates\_md,
- "docs/copilot-space/saved-replies.md": saved\_replies\_md,
- "docs/copilot-space/copilot-instructions.md": copilot\_instructions\_doc,
- "docs/copilot-space/prompt-files.md": prompt\_files\_doc,
- "docs/copilot-space/chatmodes.md": chatmodes\_doc,
- "docs/copilot-space/agents-md.md": agents\_md\_doc,
- "docs/copilot-space/claude-agents.md": claude\_agents\_doc,
- "docs/copilot-space/gemini-md.md": gemini\_doc,
- "docs/copilot-space/schemas/issue-form-schema.md": issue\_schema,
- "docs/copilot-space/schemas/prompt-frontmatter-schema.md": prompt\_schema,
- "docs/copilot-space/schemas/chatmode-frontmatter-schema.md": chatmode\_schema,
- "docs/copilot-space/schemas/claude-subagent-schema.md": claude\_subagent\_schema,
- ".github/prompts/frontmatter-guide.prompt.md": frontmatter\_prompt,
- ".github/chatmodes/frontmatter.chatmode.md": frontmatter\_chatmode,
- ".github/instructions/frontmatter.instructions.md": frontmatter\_instructions,
- ".github/agents/frontmatter-librarian.md": space\_agent,
- }
-
-for rel, content in files.items():
- p \= os.path.join(root, rel)
- os.makedirs(os.path.dirname(p), exist\_ok=True)
- with open(p, "w", encoding="utf-8", newline="\\n") as f:
- f.write(content)
-
-# **Optional VS Code settings to highlight markdown and enable word wrap**
-
-vscode\_settings \= {
- "editor.wordWrap": "on",
- "editor.defaultFormatter": "esbenp.prettier-vscode",
- "\[markdown\]": {
- "editor.wordWrap": "on"
- }
- }
- with open(os.path.join(root, ".vscode/settings.json"), "w", encoding="utf-8") as f:
- json.dump(vscode\_settings, f, indent=2)
-
-# **Zip it**
-
-zip\_path \= "/mnt/data/copilot-space-frontmatter.zip"
- with zipfile.ZipFile(zip\_path, "w", zipfile.ZIP\_DEFLATED) as z:
- for base, \_, files\_in in os.walk(root):
- for name in files\_in:
- full \= os.path.join(base, name)
- rel \= os.path.relpath(full, root)
- z.write(full, arcname=os.path.join("copilot-space", rel))
-
-zip\_path
-
-Always show details
-
-Alright Ash — I’ve generated a **Copilot Space** that teaches how to use every front-matter file you asked about, with docs, examples, schemas, and ready-to-run Copilot prompt/chat mode.
-
-Download the Copilot Space
-
-## **What’s inside**
-
-* **docs/copilot-space/**
-
- * **INDEX.md** → single place to start; links to everything.
-
- * **issue-templates.md** → YAML Issue Forms: required/optional keys \+ full example.
-
- * **pr-templates.md** → PR templates (Markdown-only, no YAML forms) \+ best practice template.
-
- * **saved-replies.md** → explains they’re UI-managed (no frontmatter).
-
- * **copilot-instructions.md** → repo-wide vs path-specific instructions, `applyTo` patterns.
-
- * **prompt-files.md** → `.prompt.md` frontmatter (`description`, `mode`, `model`, `tools`) \+ example.
-
- * **chatmodes.md** → `.chatmode.md` frontmatter \+ example “Planning Mode”.
-
- * **agents-md.md** → how to use `AGENTS.md` as universal rules.
-
- * **claude-agents.md** → `CLAUDE.md` \+ **Claude subagents** YAML (`name`, `description`, `tools`) \+ example.
-
- * **gemini-md.md** → `GEMINI.md` convention and what to include.
-
- * **schemas/** (quick reference)
-
- * **issue-form-schema.md**, **prompt-frontmatter-schema.md**, **chatmode-frontmatter-schema.md**, **claude-subagent-schema.md**.
-
-* **.github/**
-
- * **instructions/**
-
- * **frontmatter.instructions.md** → applies to all `*.md` (authoring guidance).
-
- * **prompts/**
-
- * **frontmatter-guide.prompt.md** → quick “Frontmatter Guide” prompt that tells Copilot to answer using the docs in `docs/copilot-space/`.
-
- * **chatmodes/**
-
- * **frontmatter.chatmode.md** → dedicated chat mode: fast answers \+ examples from this space.
-
- * **agents/**
-
- * **frontmatter-librarian.md** → Claude-style subagent with `name/description/tools`; it fetches the right example and returns a short Do/Don’t list.
-
-* **.vscode/settings.json** → basic markdown-friendly editor defaults (wrap on).
-
-## **How to use it**
-
-1. **Drop the folder into any repo** (or create a new one) and commit.
-
-2. Open Copilot Chat in VS Code:
-
- * Select **Frontmatter** from the chat mode dropdown (from `.github/chatmodes/frontmatter.chatmode.md`), **or**
-
- * Run the **Frontmatter Guide** prompt (`/frontmatter-guide`) to answer questions using the docs.
-
-3. Edit the examples to match your stack (WordPress/JS/TS/etc.). The Issue Forms and prompt/chat mode samples are ready to copy-paste.
-
-4. If you also use Claude/Gemini:
-
- * Add/trim **`AGENTS.md`**, **`CLAUDE.md`**, **`GEMINI.md`** at the repo root (or keep them in your main repo and link back here).
-
- * Define any project subagents in `.github/agents/`.
-
-Want me to merge this into the previous repo template I made for you so you’ve got a single combined starter?
-
diff --git a/block-themes/_temp.txt b/block-themes/_temp.txt
deleted file mode 100644
index cc195cf..0000000
--- a/block-themes/_temp.txt
+++ /dev/null
@@ -1,348 +0,0 @@
-# Standardising Colours, Spacing, and Typography in Block Themes
-
-A predictable, token-based system for **colours, spacing, and typography** helps ensure consistency across design, WordPress editor UI, and front-end rendering. WordPress provides **default presets**, which can be enabled, overridden, or extended to match your design system.
-
----
-
-## WordPress Default Font Size Slugs
-WordPress ships with four core font sizes:
-
-- `small`
-- `medium`
-- `large`
-- `x-large`
-
-## WordPress Default Spacing Slugs
-The default spacing scale is numeric and increments by 10:
-
-- `spacing-10`
-- `spacing-20`
-- `spacing-30`
-- `spacing-40`
-- `spacing-50`
-- `spacing-60`
-
-(These correspond to approximate values from `0.125rem` to `3rem`, though values may vary by theme implementation.)
-
-### Extended Spacing Scale
-
-We extend this with additional slugs to cover larger gaps, while **keeping naming consistent**:
-
-- `spacing-70` → `3.5rem` (56px)
-- `spacing-80` → `4rem` (64px)
-- `spacing-90` → `4.5rem` (72px)
-- `spacing-100` → `5rem` (80px)
-
-## Extended Spacing Scale
-
-We extend this with additional slugs to cover larger gaps, while **keeping naming consistent**:
-
-- `spacing-70` → `3.5rem` (56px)
-- `spacing-80` → `4rem` (64px)
-- `spacing-90` → `4.5rem` (72px)
-- `spacing-100` → `5rem` (80px)
-
----
-
-### Example JSON
-
-```json
-"spacing": {
- "spacingScale": {
- "steps": [
- { "slug": "spacing-10", "size": "0.625rem", "name": "10px" },
- { "slug": "spacing-20", "size": "1.25rem", "name": "20px" },
- { "slug": "spacing-30", "size": "1.875rem", "name": "30px" },
- { "slug": "spacing-40", "size": "2.5rem", "name": "40px" },
- { "slug": "spacing-50", "size": "3.125rem", "name": "50px" },
- { "slug": "spacing-60", "size": "3.75rem", "name": "60px" },
- { "slug": "spacing-70", "size": "3.5rem", "name": "56px" },
- { "slug": "spacing-80", "size": "4rem", "name": "64px" },
- { "slug": "spacing-90", "size": "4.5rem", "name": "72px" },
- { "slug": "spacing-100", "size": "5rem", "name": "80px" }
- ]
- }
-}
-```
-
----
-
-## Extending with Custom Tokens
-
-You can extend the defaults with **semantic tokens** (e.g. `brand-primary`, `gigantic`) while **keeping WP defaults enabled** for editor familiarity.
-
-Best practice:
-- **Keep slugs stable** (so editor UI remains predictable).
-- **Override values** (so the design system reflects your scale).
-- **Add extra sizes only where needed** (to avoid clutter).
-
----
-
-## Example `theme.json` Partial
-
-This example uses:
-
-- **Colour tokens**: semantic naming (`brand-primary`, `neutral-100`).
-- **Spacing scale**: multiples of 8px → `0.5rem`, `1rem`, `2rem`, etc.
-- **Typography scale**: includes extra sizes (`x-tiny`, `tiny`, `huge`, `gigantic`) also based on multiples of 8px.
-
-```json
-{
- "$schema": "https://schemas.wp.org/trunk/theme.json",
- "version": 3,
- "settings": {
- "color": {
- "palette": [
- { "slug": "brand-primary", "name": "Brand Primary", "color": "#0047AB" },
- { "slug": "brand-secondary", "name": "Brand Secondary", "color": "#FF6F00" },
- { "slug": "neutral-100", "name": "Neutral 100", "color": "#F5F5F5" },
- { "slug": "neutral-900", "name": "Neutral 900", "color": "#111111" }
- ]
- },
- "spacing": {
- "spacingScale": {
- "steps": [
- { "slug": "spacing-8", "size": "0.5rem", "name": "8px" },
- { "slug": "spacing-16", "size": "1rem", "name": "16px" },
- { "slug": "spacing-24", "size": "1.5rem", "name": "24px" },
- { "slug": "spacing-32", "size": "2rem", "name": "32px" },
- { "slug": "spacing-40", "size": "2.5rem", "name": "40px" },
- { "slug": "spacing-48", "size": "3rem", "name": "48px" },
- { "slug": "spacing-64", "size": "4rem", "name": "64px" },
- { "slug": "spacing-80", "size": "5rem", "name": "80px" }
- ]
- }
- },
- "typography": {
- "fontSizes": [
- { "slug": "x-tiny", "size": "0.5rem", "name": "X-Tiny (8px)" },
- { "slug": "tiny", "size": "0.75rem", "name": "Tiny (12px)" },
- { "slug": "small", "size": "0.875rem", "name": "Small (14px)" },
- { "slug": "medium", "size": "1rem", "name": "Medium (16px)" },
- { "slug": "large", "size": "1.25rem", "name": "Large (20px)" },
- { "slug": "x-large", "size": "1.5rem", "name": "X-Large (24px)" },
- { "slug": "huge", "size": "2rem", "name": "Huge (32px)" },
- { "slug": "gigantic", "size": "3rem", "name": "Gigantic (48px)" }
- ]
- }
- }
-}
-
-
----
-
-````markdown
-# Global Styles and theme.json
-
-Describes how to use `theme.json` for global styles, design tokens, and editor/front-end parity in block themes.
-
----
-
-## Best practices
-
-- Use `theme.json` as the single source of truth for **site-wide styles** and editor/front-end consistency.
-- Treat it as a **design system definition file** (colours, typography, spacing, layout, etc.).
-- Define **design tokens** in `settings` (e.g., font sizes, spacing presets, custom line-heights).
-- Use `styles` to apply global defaults, ensuring authors see the same result in both the Site Editor and front end.
-- Leverage `style variations` within `theme.json` to offer alternate themes/skins without extra CSS files.
-- Combine with **patterns** and **style variations** for modular theme composition.
-
-Example: adding custom line-height tokens
-
-```json
-{
- "settings": {
- "custom": {
- "lineHeight": { "sm": 1.625, "md": 1.6875, "lg": 1.5 }
- }
- }
-}
-````
-
----
-
-## When to use
-
-
----
-
-## Limitations
-
-
----
-
-## Key lessons from Rich Tabor’s “Full Site Editing”
-
-
----
-
-## Reference Links
-
-
-
-```
-
----
-
-Ash, do you want me to **split this into smaller `.md` docs** (e.g. `best-practices.md`, `limitations.md`, `when-to-use.md`) for modular GitHub documentation, or keep everything bundled in `global-styles.md`?
-```
-
-
-### Want me to scaffold the `.md` files now with these seeds and drop in your `/styles/block/section-1…9.json` as examples?
-
-[1]: https://developer.wordpress.org/news/2024/06/21/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/ "Styling sections, nested elements, and more with Block Style Variations in WordPress 6.6 – WordPress Developer Blog"
-[2]: https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/?utm_source=chatgpt.com "Styles – Block Editor Handbook | Developer.WordPress.org"
-[3]:
-[4]:
-
-
-Here’s a concise, structured roundup of Rich Tabor’s articles relevant to block‑theme development and `theme.json`. I’ve extracted insights on the key areas you flagged: block styles, style variations, palettes, typesets, section styles, global styles, and patterns.
-
----
-
-## Rich Tabor’s Theme.Log Articles — At a Glance
-
----
-
-### **Using a fluid type scale in block themes**
-
-* Explains applying a **fluid typographic scale** using CSS `clamp()` combined with a scale stored in `settings.custom.typography.scale` in `theme.json`.
-* Proposes creating **custom CSS variables** (e.g., `--wp--custom--typography--large`) and using `clamp()` in `settings.typography.fontSizes` to build fluid yet scaled typography.
- ([Rich Tabor][1])
-
-**Relevance:**
-
-* This is gold for **fluid typography** guidelines and for mapping Figma → theme.json with token-based, responsive sizing.
-
----
-
-### **Standardizing theme.json spacing sizes**
-
-* Introduces `settings.spacing.spacingScale` (operator, increment, steps, unit) to automate systematic spacing presets.
-* Alternatively, suggests `settings.spacing.spacingSizes` with explicit custom sizes (slugs, names, fluid expressions).
-* Mentions future support for `styles.spacing.blockGap` to style gaps between child blocks.
- ([Rich Tabor][2])
-
-**Relevance:**
-
-* Crucial for your **fluid spacing** documentation and consistent preset usage in section styles.
-
----
-
-### **Standardizing theme.json font sizes**
-
-* Proposes using consistent slugs like `small`, `medium`, `large`, `x-large`, each with optional `fluid` min/max properties, plus `size` fallback.
-* Illustrates how theme.json resolves into CSS variables (e.g., `--wp--preset--font-size--small`).
-* Warns that inconsistent slugs produce broken layouts when switching themes.
- ([Rich Tabor][1], [Rich Tabor][3])
-
-**Relevance:**
-
-* Forms the basis for your **fluid typography recommendations** and emphasizes standardization across themes.
-
----
-
-### **Standardizing theme.json color slugs**
-
-* Recommends core color slugs: `base`, `contrast`, and at least `primary`.
-* Shows how slug mismatch between themes breaks styles when switching themes.
-* Encourages neutral, functional slug names rather than descriptive color names (e.g. `green`).
- ([Rich Tabor][4])
-
-**Relevance:**
-
-* Vital input for the **colour palettes** and **style variations** sections of your documentation, promoting interoperability.
-
----
-
-### **How to build WordPress patterns**
-
-* Walks through designing block patterns: copying content, registering with `register_block_pattern()`, including title, description, block content, categories, keywords, viewportWidth, `blockTypes`.
-* Notes patterns are copied once inserted; changes to source don’t propagate.
- ([Rich Tabor][3], [Rich Tabor][5])
-
-**Relevance:**
-
-* Essential for your **Patterns** documentation: building, registering, and pattern vs style differences.
-
----
-
-### **Building WordPress block variations**
-
-* Clarifies **block variations** (configuration–changing variants shown when inserting blocks) are different from **block style variations**.
-* Provides example of registering a variation (`wp.blocks.registerBlockVariation`) for a form block, with `innerBlocks`, name, title, icon, etc.
- ([Rich Tabor][6])
-
-**Relevance:**
-
-* Great for your **style variations** vs **block variations** section—clarifies distinctions.
-
----
-
-### **A primer on WordPress full site editing**
-
-* Defines block‑based themes: `theme.json` + block templates/parts, minimal PHP.
-* Demonstrates how FSE uses `theme.json` to drive styles across editor and front‑end.
- ([Rich Tabor][7])
-
-**Relevance:**
-
-* Supports **global styles** framing and context for block‑theme direction.
-
----
-
-### **WordPress 6.6**
-
-* Highlights key enhancements: **colour palettes**, **typesets**, **block style variations** (i.e. section styles), reduced CSS specificity, responsive features like negative margins, Grid block, shadow presets, full‑site enhancements.
- ([Rich Tabor][3], [Rich Tabor][8])
-
-**Relevance:**
-
-* This ties directly into your **section styles**, **global styles**, and infrastructure expectations (like low specificity).
-
----
-
-## Summary Table
-
-| Topic | Key Contributions from Tabor’s Articles |
-| ---------------------------------- | ------------------------------------------------------------------------------------------------------------- |
-| **Fluid typography** | `clamp()` + scale via custom props; `theme.json` fontSizes with fluid presets ([Rich Tabor][1]) |
-| **Fluid spacing** | `spacingScale` or `spacingSizes`, blockGap support ([Rich Tabor][9]) |
-| **Typography standardization** | Common font-size slugs + fluid ranges, avoid slug inconsistencies ([Rich Tabor][10]) |
-| **Colour standardization** | `base`, `contrast`, `primary` slugs for cross-theme portability ([Rich Tabor][11]) |
-| **Patterns** | Building and registering block patterns; patterns vs style reuse ([Rich Tabor][12]) |
-| **Block variations** | Clarifies API & usage differ from style variations ([Rich Tabor][13]) |
-| **Full Site Editing / theme.json** | Context for block-based themes and `theme.json` roles ([Rich Tabor][14]) |
-| **WordPress 6.6 features** | Introduced section styles, reduced specificity, typesets, palettes, block style variations ([Rich Tabor][15]) |
-
----
-
-## What’s Next?
-
-Would you like me to slot these insights into the `.md` docs hierarchy? For example:
-
-* `fluid-spacing.md` → reference `spacingScale` article
-* `fluid-typography.md` → link to fluid type scale + standard font sizes
-* `colour-palettes.md` → based on color slugs article
-* `patterns.md` and `block-variations.md` → pattern vs variation context
-* `global-styles.md` → FSE + 6.6 overview
-
-I can also create inline link anchors (e.g. `[fluid type scale](https://rich.blog/fluid-type-scale-theme-json/)`) ready for copy-paste.
-
-Let me know how you’d like to proceed—happy to scaffold the docs directly.
-
-[1]: https://rich.blog/fluid-type-scale-theme-json/?utm_source=chatgpt.com "Using a fluid type scale in block themes – Rich Tabor"
-[2]: https://rich.blog/standardizing-theme-json-spacing/?utm_source=chatgpt.com "Standardizing theme.json spacing sizes – Rich Tabor"
-[3]: https://rich.blog/theme-json-font-sizes/?utm_source=chatgpt.com "Standardizing theme.json font sizes – Rich Tabor"
-[4]: https://rich.blog/standardizing-theme-json-colors/?utm_source=chatgpt.com "Standardizing theme.json color slugs – Rich Tabor"
-[5]: https://rich.blog/patterns/?utm_source=chatgpt.com "How to build WordPress patterns – Rich Tabor"
-[6]: https://rich.blog/block-variations/?utm_source=chatgpt.com "Building WordPress block variations – Rich Tabor"
-[7]: https://rich.blog/full-site-editing/?utm_source=chatgpt.com "A primer on WordPress full site editing – Rich Tabor"
-[8]: https://rich.blog/wordpress-6-6/?utm_source=chatgpt.com "WordPress 6.6 – Rich Tabor"
-[9]: https://rich.blog/standardizing-theme-json-spacing/ "Standardizing theme.json spacing sizes – Rich Tabor"
-[10]: https://rich.blog/theme-json-font-sizes/ "Standardizing theme.json font sizes – Rich Tabor"
-[11]: https://rich.blog/standardizing-theme-json-colors/ "Standardizing theme.json color slugs – Rich Tabor"
-[12]: https://rich.blog/patterns/ "How to build WordPress patterns – Rich Tabor"
-[13]: https://rich.blog/block-variations/ "Building WordPress block variations – Rich Tabor"
-[14]: https://rich.blog/full-site-editing/ "A primer on WordPress full site editing – Rich Tabor"
-[15]: https://rich.blog/wordpress-6-6/ "WordPress 6.6 – Rich Tabor"
diff --git a/block-themes/best-practices-fluid-spacing-and typography.md b/block-themes/best-practices-fluid-spacing-and typography.md
deleted file mode 100644
index 1ed6908..0000000
--- a/block-themes/best-practices-fluid-spacing-and typography.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# **Fluid Spacing Learnings**
-
-**Context Video** \- [WordPress Fluid Spacing - 18 August 2025](https://www.loom.com/share/f56e58ff587648df97f31247bf887744?sid=003d4168-98be-47e0-8e31-8aa9ffebda95)
-
-**Fluid spacin[https://www.loom.com/share/f56e58ff587648df97f31247bf887744?sid=003d4168-98be-47e0-8e31-8aa9ffebda95](https://www.loom.com/share/f56e58ff587648df97f31247bf887744?sid=003d4168-98be-47e0-8e31-8aa9ffebda95)g** uses `clamp(min, fluid, max)` so spacing (padding, margins, gaps) scales with the viewport width, but never goes smaller than `min` or larger than `max`.
-
-* **min**: the smallest allowed spacing (protects mobile).
-* **fluid**: a viewport-based value (typically `vw`) that grows/shrinks with screen width.
-* **max**: the largest allowed spacing (protects ultra-wide screens).
-
-### **What `vw` is (and why it’s important)**
-
-* `1vw` \= 1% of the **viewport width**.
-* As the viewport changes, the `vw` portion of `clamp()` scales smoothly—no media queries needed.
-* `min` and `max` act as guardrails: clamp picks the min on tiny screens, scales fluidly in the middle, and caps at the max on large screens.
-
-## **“Visual” table: when each part of `clamp()` applies**
-
-Using `clamp(10px, 2vw, 40px)`:
-
-| Viewport width | 2vw calculation | Result (chosen by `clamp`) | Why |
-| ----- | ----- | ----- | ----- |
-| 320px (small mobile) | 6.4px | **10px** | 6.4px \< min → use **min** |
-| 375px (mobile) | 7.5px | **10px** | 7.5px \< min → use **min** |
-| 768px (tablet) | 15.36px | **15.36px** | within min–max → **fluid** value |
-| 1024px (tablet/SM desktop) | 20.48px | **20.48px** | within min–max → **fluid** value |
-| 1440px (desktop) | 28.8px | **28.8px** | within min–max → **fluid** value |
-| 1920px (large desktop) | 38.4px | **38.4px** | within min–max → **fluid** value |
-| 2400px (ultra-wide) | 48px | **40px** | 48px \> max → use **max** |
-
-**Key idea:** **`vw` is not tied to a specific “device.”** It continuously scales with viewport width. `min` and `max` determine *when* scaling starts and stops.
-
-## **Understanding the impact VW has on a Mobile device.**
-
-## **480px Mobile (min/max fixed, vw adjusted)**
-
-### **Example: `clamp(10px, Xvw, 40px)`**
-
-| `vw` value | Calculation (Xvw @ 480px) | Result at 480px | Why |
-| ----- | ----- | ----- | ----- |
-| **1vw** | 4.8px | **10px** | 4.8 \< min → clamp uses min |
-| **2vw** | 9.6px | **10px** | 9.6 \< min → clamp uses min |
-| **2.5vw** | 12px | **12px** | Now ≥ min → clamp uses fluid |
-| **3vw** | 14.4px | **14.4px** | Within min–max → fluid applies |
-| **5vw** | 24px | **24px** | Within min–max → fluid applies |
-| **10vw** | 48px | **40px** | Above max → clamp caps at max |
-
diff --git a/block-themes/css-specificity.md b/block-themes/css-specificity.md
deleted file mode 100644
index d818a61..0000000
--- a/block-themes/css-specificity.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# CSS Specificity
- Details the CSS specificity model in WordPress 6.6+, its impact on block themes, and why low specificity enables reliable section and style variations.
-
----
-
-## Best practices
--
-
----
-
-## When to use
--
-
----
-
-## Limitations
--
-
----
-
-## Gutenberg Discussion #61810 — *“CSS Specificity for WordPress 6.6”*
-
-**What it is:** Deep dive + consensus thread on the **specificity overhaul** in 6.6 that underpins section styles.
-**Key points**
-
-* Core shifts to very **low specificity (e.g., `0-1-0` via `:where(...)`)** to keep the cascade predictable.
-* Enables section styles and nested variations to apply **without resorting to custom CSS**.
-* Highlights implications for themes that previously depended on higher-specificity rules. ([GitHub][2])
-
-**Why it matters**
-
-* Validates our “JSON-first” approach and explains **why moving rules into `blocks.*`/`elements.*`** inside the variation is the right fix for conflicts.
-
----
-
-## Reference Links
-- [CSS Specificity for WordPress 6.6 · WordPress gutenberg · Discussion #61810 · GitHub](https://github.com/WordPress/gutenberg/discussions/61810)
-- [Rich Tabor: Fluid Typography and Block Themes](https://rich.blog/fluid-typography-block-themes/)
-- [Rich Tabor: Full Site Editing](https://rich.blog/full-site-editing/)
-- [Rich Tabor: WordPress 6.6 Typeset Support](https://rich.blog/wordpress-6-6/)
-- [Rich Tabor: Standardizing theme.json spacing sizes](https://rich.blog/standardizing-theme-json-spacing/)
-- [Rich Tabor: Block Variations](https://rich.blog/block-variations/)
-- [Rich Tabor: Patterns](https://rich.blog/patterns/)
diff --git a/block-themes/theme-68.json b/block-themes/theme-68.json
deleted file mode 100644
index 158b72e..0000000
--- a/block-themes/theme-68.json
+++ /dev/null
@@ -1,2733 +0,0 @@
-{
- "title": "JSON schema for WordPress block theme global settings and styles",
- "$schema": "http://json-schema.org/draft-07/schema#",
- "definitions": {
- "//": {
- "explainer": "https://developer.wordpress.org/themes/advanced-topics/theme-json/",
- "createTheme": "https://developer.wordpress.org/themes/",
- "reference": "https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/"
- },
- "refComplete": {
- "type": "object",
- "properties": {
- "ref": {
- "description": "A reference to another property value. e.g. `styles.color.text`",
- "type": "string"
- }
- },
- "additionalProperties": false
- },
- "settingsAppearanceToolsProperties": {
- "type": "object",
- "properties": {
- "appearanceTools": {
- "description": "Setting that enables the following UI tools:\n\n- background: backgroundImage, backgroundSize\n- border: color, radius, style, width\n- color: link, heading, button, caption\n- dimensions: aspectRatio, minHeight\n- position: sticky\n- spacing: blockGap, margin, padding\n- typography: lineHeight",
- "type": "boolean",
- "default": false
- }
- }
- },
- "settingsBackgroundProperties": {
- "type": "object",
- "properties": {
- "background": {
- "description": "Settings related to background.",
- "type": "object",
- "properties": {
- "backgroundImage": {
- "description": "Allow users to set a background image.",
- "type": "boolean",
- "default": false
- },
- "backgroundSize": {
- "description": "Allow users to set values related to the size of a background image, including size, position, and repeat controls.",
- "type": "boolean",
- "default": false
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsBorderProperties": {
- "type": "object",
- "properties": {
- "border": {
- "description": "Settings related to borders.",
- "type": "object",
- "properties": {
- "color": {
- "description": "Allow users to set custom border colors.",
- "type": "boolean",
- "default": false
- },
- "radius": {
- "description": "Allow users to set custom border radius.",
- "type": "boolean",
- "default": false
- },
- "style": {
- "description": "Allow users to set custom border styles.",
- "type": "boolean",
- "default": false
- },
- "width": {
- "description": "Allow users to set custom border widths.",
- "type": "boolean",
- "default": false
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsColorProperties": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Settings related to colors.",
- "type": "object",
- "properties": {
- "background": {
- "description": "Allow users to set background colors.",
- "type": "boolean",
- "default": true
- },
- "custom": {
- "description": "Allow users to select custom colors.",
- "type": "boolean",
- "default": true
- },
- "customDuotone": {
- "description": "Allow users to create custom duotone filters.",
- "type": "boolean",
- "default": true
- },
- "customGradient": {
- "description": "Allow users to create custom gradients.",
- "type": "boolean",
- "default": true
- },
- "defaultDuotone": {
- "description": "Allow users to choose filters from the default duotone filter presets.",
- "type": "boolean",
- "default": true
- },
- "defaultGradients": {
- "description": "Allow users to choose colors from the default gradients.",
- "type": "boolean",
- "default": true
- },
- "defaultPalette": {
- "description": "Allow users to choose colors from the default palette.",
- "type": "boolean",
- "default": true
- },
- "duotone": {
- "description": "Duotone presets for the duotone picker.\nDoesn't generate classes or properties.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the duotone preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the duotone preset.",
- "type": "string"
- },
- "colors": {
- "description": "List of colors from dark to light.",
- "type": "array",
- "items": {
- "description": "CSS hex or rgb string.",
- "type": "string"
- }
- }
- },
- "required": [ "name", "slug", "colors" ],
- "additionalProperties": false
- }
- },
- "gradients": {
- "description": "Gradient presets for the gradient picker.\nGenerates a single class (`.has-{slug}-background`) and custom property (`--wp--preset--gradient--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the gradient preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the gradient preset.",
- "type": "string"
- },
- "gradient": {
- "description": "CSS gradient string.",
- "type": "string"
- }
- },
- "required": [ "name", "slug", "gradient" ],
- "additionalProperties": false
- }
- },
- "link": {
- "description": "Allow users to set link colors in a block.",
- "type": "boolean",
- "default": false
- },
- "palette": {
- "description": "Color palette presets for the color picker.\nGenerates three classes (`.has-{slug}-color`, `.has-{slug}-background-color`, and `.has-{slug}-border-color`) and a single custom property (`--wp--preset--color--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the color preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the color preset.",
- "type": "string"
- },
- "color": {
- "description": "CSS hex or rgb(a) string.",
- "type": "string"
- }
- },
- "required": [ "name", "slug", "color" ],
- "additionalProperties": false
- }
- },
- "text": {
- "description": "Allow users to set text colors in a block.",
- "type": "boolean",
- "default": true
- },
- "heading": {
- "description": "Allow users to set heading colors in a block.",
- "type": "boolean",
- "default": true
- },
- "button": {
- "description": "Allow users to set button colors in a block.",
- "type": "boolean",
- "default": true
- },
- "caption": {
- "description": "Allow users to set caption colors in a block.",
- "type": "boolean",
- "default": true
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsDimensionsProperties": {
- "type": "object",
- "properties": {
- "dimensions": {
- "description": "Settings related to dimensions.",
- "type": "object",
- "properties": {
- "aspectRatio": {
- "description": "Allow users to set an aspect ratio.",
- "type": "boolean",
- "default": false
- },
- "defaultAspectRatios": {
- "description": "Allow users to choose aspect ratios from the default set of aspect ratios.",
- "type": "boolean",
- "default": true
- },
- "aspectRatios": {
- "description": "Allow users to define aspect ratios for some blocks.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the aspect ratio preset.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the aspect ratio preset.",
- "type": "string"
- },
- "ratio": {
- "description": "Aspect ratio expressed as a division or decimal.",
- "type": "string"
- }
- }
- }
- },
- "minHeight": {
- "description": "Allow users to set custom minimum height.",
- "type": "boolean",
- "default": false
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsLayoutProperties": {
- "type": "object",
- "properties": {
- "layout": {
- "description": "Settings related to layout.",
- "type": "object",
- "properties": {
- "contentSize": {
- "description": "Sets the max-width of the content.",
- "type": "string"
- },
- "wideSize": {
- "description": "Sets the max-width of wide (`.alignwide`) content. Also used as the maximum viewport when calculating fluid font sizes",
- "type": "string"
- },
- "allowEditing": {
- "description": "Disable the layout UI controls.",
- "type": "boolean",
- "default": true
- },
- "allowCustomContentAndWideSize": {
- "description": "Enable or disable the custom content and wide size controls.",
- "type": "boolean",
- "default": true
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsLightboxProperties": {
- "type": "object",
- "properties": {
- "lightbox": {
- "description": "Settings related to the lightbox.",
- "type": "object",
- "properties": {
- "enabled": {
- "description": "Defines whether the lightbox is enabled or not.",
- "type": "boolean"
- },
- "allowEditing": {
- "description": "Defines whether to show the Lightbox UI in the block editor. If set to `false`, the user won't be able to change the lightbox settings in the block editor.",
- "type": "boolean"
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsPositionProperties": {
- "type": "object",
- "properties": {
- "position": {
- "description": "Settings related to position.",
- "type": "object",
- "properties": {
- "sticky": {
- "description": "Allow users to set sticky position.",
- "type": "boolean",
- "default": false
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsShadowProperties": {
- "type": "object",
- "properties": {
- "shadow": {
- "description": "Settings related to shadows.",
- "type": "object",
- "properties": {
- "defaultPresets": {
- "description": "Allow users to choose shadows from the default shadow presets.",
- "type": "boolean",
- "default": true
- },
- "presets": {
- "description": "Shadow presets for the shadow picker.\nGenerates a single custom property (`--wp--preset--shadow--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the shadow preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the shadow preset.",
- "type": "string"
- },
- "shadow": {
- "description": "CSS box-shadow value",
- "type": "string"
- }
- },
- "required": [ "name", "slug", "shadow" ],
- "additionalProperties": false
- }
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsSpacingProperties": {
- "type": "object",
- "properties": {
- "spacing": {
- "description": "Settings related to spacing.",
- "type": "object",
- "properties": {
- "blockGap": {
- "description": "Enables `--wp--style--block-gap` to be generated from styles.spacing.blockGap.\nA value of `null` instead of `false` further disables layout styles from being generated.",
- "oneOf": [
- { "type": "boolean" },
- { "type": "null" }
- ],
- "default": null
- },
- "margin": {
- "description": "Allow users to set a custom margin.",
- "type": "boolean",
- "default": false
- },
- "padding": {
- "description": "Allow users to set a custom padding.",
- "type": "boolean",
- "default": false
- },
- "units": {
- "description": "List of units the user can use for spacing values.",
- "type": "array",
- "items": {
- "type": "string"
- },
- "minItems": 1,
- "default": [ "px", "em", "rem", "vh", "vw", "%" ]
- },
- "customSpacingSize": {
- "description": "Allow users to set custom space sizes.",
- "type": "boolean",
- "default": true
- },
- "defaultSpacingSizes": {
- "description": "Allow users to choose space sizes from the default space size presets.",
- "type": "boolean",
- "default": true
- },
- "spacingSizes": {
- "description": "Space size presets for the space size selector.\nGenerates a custom property (`--wp--preset--spacing--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the space size preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Unique identifier for the space size preset. For best cross theme compatibility these should be in the form '10','20','30','40','50','60', etc. with '50' representing the 'Medium' size step. If all slugs begin with a number they will be merged with default and user slugs and sorted numerically.",
- "type": "string"
- },
- "size": {
- "description": "CSS space-size value, including units.",
- "type": "string"
- }
- },
- "additionalProperties": false
- }
- },
- "spacingScale": {
- "description": "Settings to auto-generate space size presets for the space size selector.\nGenerates a custom property (--wp--preset--spacing--{slug}`) per preset value.",
- "type": "object",
- "properties": {
- "operator": {
- "description": "With + or * depending on whether scale is generated by increment or multiplier.",
- "type": "string",
- "enum": [ "+", "*" ],
- "default": "*"
- },
- "increment": {
- "description": "The amount to increment each step by.",
- "type": "number",
- "exclusiveMinimum": 0,
- "default": 1.5
- },
- "steps": {
- "description": "Number of steps to generate in scale.",
- "type": "integer",
- "minimum": 1,
- "maximum": 10,
- "default": 7
- },
- "mediumStep": {
- "description": "The value to medium setting in the scale.",
- "type": "number",
- "exclusiveMinimum": 0,
- "default": 1.5
- },
- "unit": {
- "description": "Unit that the scale uses, eg. rem, em, px.",
- "type": "string",
- "enum": [
- "px",
- "em",
- "rem",
- "%",
- "vw",
- "svw",
- "lvw",
- "dvw",
- "vh",
- "svh",
- "lvh",
- "dvh",
- "vi",
- "svi",
- "lvi",
- "dvi",
- "vb",
- "svb",
- "lvb",
- "dvb",
- "vmin",
- "svmin",
- "lvmin",
- "dvmin",
- "vmax",
- "svmax",
- "lvmax",
- "dvmax"
- ],
- "default": "rem"
- }
- },
- "additionalProperties": false
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsTypographyProperties": {
- "type": "object",
- "properties": {
- "typography": {
- "description": "Settings related to typography.",
- "type": "object",
- "properties": {
- "defaultFontSizes": {
- "description": "Allow users to choose font sizes from the default font size presets.",
- "type": "boolean",
- "default": true
- },
- "customFontSize": {
- "description": "Allow users to set custom font sizes.",
- "type": "boolean",
- "default": true
- },
- "fontStyle": {
- "description": "Allow users to set custom font styles.",
- "type": "boolean",
- "default": true
- },
- "fontWeight": {
- "description": "Allow users to set custom font weights.",
- "type": "boolean",
- "default": true
- },
- "fluid": {
- "description": "Enables fluid typography and allows users to set global fluid typography parameters.",
- "oneOf": [
- {
- "type": "object",
- "properties": {
- "minFontSize": {
- "description": "Allow users to set a global minimum font size boundary in px, rem or em. Custom font sizes below this value will not be clamped, and all calculated minimum font sizes will be, at a minimum, this value.",
- "type": "string"
- },
- "maxViewportWidth": {
- "description": "Allow users to set custom a max viewport width in px, rem or em, used to set the maximum size boundary of a fluid font size.",
- "type": "string"
- },
- "minViewportWidth": {
- "description": "Allow users to set a custom min viewport width in px, rem or em, used to set the minimum size boundary of a fluid font size.",
- "type": "string"
- }
- },
- "additionalProperties": false
- },
- {
- "type": "boolean"
- }
- ],
- "default": false
- },
- "letterSpacing": {
- "description": "Allow users to set custom letter spacing.",
- "type": "boolean",
- "default": true
- },
- "lineHeight": {
- "description": "Allow users to set custom line height.",
- "type": "boolean",
- "default": false
- },
- "textAlign": {
- "description": "Allow users to set the text align.",
- "type": "boolean",
- "default": true
- },
- "textColumns": {
- "description": "Allow users to set the number of text columns.",
- "type": "boolean",
- "default": false
- },
- "textDecoration": {
- "description": "Allow users to set custom text decorations.",
- "type": "boolean",
- "default": true
- },
- "writingMode": {
- "description": "Allow users to set the writing mode.",
- "type": "boolean",
- "default": false
- },
- "textTransform": {
- "description": "Allow users to set custom text transforms.",
- "type": "boolean",
- "default": true
- },
- "dropCap": {
- "description": "Enable drop cap.",
- "type": "boolean",
- "default": true
- },
- "fontSizes": {
- "description": "Font size presets for the font size selector.\nGenerates a single class (`.has-{slug}-color`) and custom property (`--wp--preset--font-size--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the font size preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the font size preset.",
- "type": "string"
- },
- "size": {
- "description": "CSS font-size value, including units.",
- "type": "string"
- },
- "fluid": {
- "description": "Specifies the minimum and maximum font size value of a fluid font size. Set to `false` to bypass fluid calculations and use the static `size` value.",
- "oneOf": [
- {
- "type": "object",
- "properties": {
- "min": {
- "description": "A min font size for fluid font size calculations in px, rem or em.",
- "type": "string"
- },
- "max": {
- "description": "A max font size for fluid font size calculations in px, rem or em.",
- "type": "string"
- }
- },
- "additionalProperties": false
- },
- {
- "type": "boolean"
- }
- ]
- }
- },
- "additionalProperties": false
- }
- },
- "fontFamilies": {
- "description": "Font family presets for the font family selector.\nGenerates a single custom property (`--wp--preset--font-family--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "description": "Font family preset",
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the font family preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the font family preset.",
- "type": "string"
- },
- "fontFamily": {
- "description": "CSS font-family value.",
- "type": "string"
- },
- "fontFace": {
- "description": "Array of font-face declarations.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "fontFamily": {
- "description": "CSS font-family value.",
- "type": "string",
- "default": ""
- },
- "fontStyle": {
- "description": "CSS font-style value.",
- "type": "string",
- "default": "normal"
- },
- "fontWeight": {
- "description": "List of available font weights, separated by a space.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "integer"
- }
- ],
- "default": "400"
- },
- "fontDisplay": {
- "description": "CSS font-display value.",
- "type": "string",
- "enum": [
- "auto",
- "block",
- "fallback",
- "swap",
- "optional"
- ],
- "default": "fallback"
- },
- "src": {
- "description": "Paths or URLs to the font files.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ],
- "default": []
- },
- "fontStretch": {
- "description": "CSS font-stretch value.",
- "type": "string"
- },
- "ascentOverride": {
- "description": "CSS ascent-override value.",
- "type": "string"
- },
- "descentOverride": {
- "description": "CSS descent-override value.",
- "type": "string"
- },
- "fontVariant": {
- "description": "CSS font-variant value.",
- "type": "string"
- },
- "fontFeatureSettings": {
- "description": "CSS font-feature-settings value.",
- "type": "string"
- },
- "fontVariationSettings": {
- "description": "CSS font-variation-settings value.",
- "type": "string"
- },
- "lineGapOverride": {
- "description": "CSS line-gap-override value.",
- "type": "string"
- },
- "sizeAdjust": {
- "description": "CSS size-adjust value.",
- "type": "string"
- },
- "unicodeRange": {
- "description": "CSS unicode-range value.",
- "type": "string"
- }
- },
- "required": [ "fontFamily", "src" ],
- "additionalProperties": false
- }
- }
- },
- "additionalProperties": false
- }
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsCustomProperties": {
- "type": "object",
- "properties": {
- "custom": {
- "$ref": "#/definitions/settingsCustomAdditionalProperties"
- }
- }
- },
- "settingsProperties": {
- "allOf": [
- { "$ref": "#/definitions/settingsAppearanceToolsProperties" },
- { "$ref": "#/definitions/settingsBackgroundProperties" },
- { "$ref": "#/definitions/settingsBorderProperties" },
- { "$ref": "#/definitions/settingsColorProperties" },
- { "$ref": "#/definitions/settingsDimensionsProperties" },
- { "$ref": "#/definitions/settingsLayoutProperties" },
- { "$ref": "#/definitions/settingsLightboxProperties" },
- { "$ref": "#/definitions/settingsPositionProperties" },
- { "$ref": "#/definitions/settingsShadowProperties" },
- { "$ref": "#/definitions/settingsSpacingProperties" },
- { "$ref": "#/definitions/settingsTypographyProperties" },
- { "$ref": "#/definitions/settingsCustomProperties" }
- ]
- },
- "settingsPropertyNames": {
- "enum": [
- "appearanceTools",
- "background",
- "border",
- "color",
- "dimensions",
- "layout",
- "lightbox",
- "position",
- "shadow",
- "spacing",
- "typography",
- "custom"
- ]
- },
- "settingsPropertiesComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/settingsProperties"
- },
- {
- "type": "object",
- "propertyNames": {
- "$ref": "#/definitions/settingsPropertyNames"
- }
- }
- ]
- },
- "settingsBlocksPropertiesComplete": {
- "description": "Settings defined on a per-block basis.",
- "type": "object",
- "properties": {
- "core/archives": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/audio": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/avatar": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/block": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/button": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/buttons": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/calendar": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/categories": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/code": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/column": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/columns": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-author-avatar": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-author-name": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-content": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-date": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-edit-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-reply-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-pagination": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-pagination-next": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-pagination-numbers": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-pagination-previous": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-title": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-template": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/cover": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/details": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/embed": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/file": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/footnotes": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/freeform": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/gallery": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/group": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/heading": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/home-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/html": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/image": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/latest-comments": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/latest-posts": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/list": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/list-item": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/loginout": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/media-text": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/missing": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/more": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/navigation": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/navigation-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/navigation-submenu": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/nextpage": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/page-list": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/page-list-item": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/paragraph": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-author": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-author-biography": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-author-name": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-comment": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-comments-count": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-comments-form": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-comments-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-content": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-date": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-excerpt": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-featured-image": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-navigation-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-template": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-terms": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-title": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/preformatted": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/pullquote": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-no-results": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-pagination": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-pagination-next": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-pagination-numbers": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-pagination-previous": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-title": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-total": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/quote": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/read-more": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/rss": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/search": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/separator": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/shortcode": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/site-logo": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/site-tagline": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/site-title": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/social-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/social-links": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/spacer": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/table": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/tag-cloud": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/template-part": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/term-description": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/text-columns": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/verse": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/video": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/widget-area": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/legacy-widget": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/widget-group": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- }
- },
- "patternProperties": {
- "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- }
- },
- "additionalProperties": false
- },
- "settingsCustomAdditionalProperties": {
- "description": "Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name.",
- "type": "object",
- "additionalProperties": {
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "number"
- },
- {
- "$ref": "#/definitions/settingsCustomAdditionalProperties"
- }
- ]
- }
- },
- "stylesProperties": {
- "type": "object",
- "properties": {
- "background": {
- "description": "Background styles.",
- "type": "object",
- "properties": {
- "backgroundImage": {
- "description": "Sets the `background-image` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" },
- {
- "type": "object",
- "properties": {
- "url": {
- "description": "A URL to an image file, or a path to a file relative to the theme root directory, and prefixed with `file:`, e.g., 'file:./path/to/file.png'.",
- "type": "string"
- }
- },
- "additionalProperties": false
- }
- ]
- },
- "backgroundPosition": {
- "description": "Sets the `background-position` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "backgroundRepeat": {
- "description": "Sets the `background-repeat` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "backgroundSize": {
- "description": "Sets the `background-size` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "backgroundAttachment": {
- "description": "Sets the `background-attachment` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "border": {
- "description": "Border styles.",
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "radius": {
- "description": "Sets the `border-radius` CSS property.",
- "anyOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" },
- {
- "type": "object",
- "properties": {
- "topLeft": {
- "description": "Sets the `border-top-left-radius` CSS property.",
- "oneOf": [
- { "type": "string" },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- },
- "topRight": {
- "description": "Sets the `border-top-right-radius` CSS property.",
- "oneOf": [
- { "type": "string" },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- },
- "bottomLeft": {
- "description": "Sets the `border-bottom-left-radius` CSS property.",
- "oneOf": [
- { "type": "string" },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- },
- "bottomRight": {
- "description": "Sets the `border-bottom-right-radius` CSS property.",
- "oneOf": [
- { "type": "string" },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- }
- }
- }
- ]
- },
- "style": {
- "description": "Sets the `border-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "top": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-top-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `border-top-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-top-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "right": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-right-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `border-right-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-right-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "bottom": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-bottom-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `border-bottom-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-bottom-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "left": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-left-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `border-left-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-left-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- }
- },
- "additionalProperties": false
- },
- "color": {
- "description": "Color styles.",
- "type": "object",
- "properties": {
- "background": {
- "description": "Sets the `background-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "gradient": {
- "description": "Sets the `background` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "text": {
- "description": "Sets the `color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "css": {
- "description": "Sets custom CSS to apply styling not covered by other theme.json properties.",
- "type": "string"
- },
- "dimensions": {
- "description": "Dimensions styles.",
- "type": "object",
- "properties": {
- "aspectRatio": {
- "description": "Sets the `aspect-ratio` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "minHeight": {
- "description": "Sets the `min-height` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- }
- },
- "filter": {
- "description": "CSS and SVG filter styles.",
- "type": "object",
- "properties": {
- "duotone": {
- "description": "Sets the duotone filter.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "outline": {
- "description": "Outline styles.",
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `outline-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "offset": {
- "description": "Sets the `outline-offset` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `outline-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `outline-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "shadow": {
- "description": "Box shadow styles.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "spacing": {
- "description": "Spacing styles.",
- "type": "object",
- "properties": {
- "blockGap": {
- "description": "Sets the `--wp--style--block-gap` CSS custom property when settings.spacing.blockGap is true.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "margin": {
- "description": "Margin styles.",
- "type": "object",
- "properties": {
- "top": {
- "description": "Sets the `margin-top` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "right": {
- "description": "Sets the `margin-right` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "bottom": {
- "description": "Sets the `margin-bottom` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "left": {
- "description": "Sets the `margin-left` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "padding": {
- "description": "Padding styles.",
- "type": "object",
- "properties": {
- "top": {
- "description": "Sets the `padding-top` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "right": {
- "description": "Sets the `padding-right` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "bottom": {
- "description": "Sets the `padding-bottom` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "left": {
- "description": "Sets the `padding-left` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- }
- },
- "additionalProperties": false
- },
- "typography": {
- "description": "Typography styles.",
- "type": "object",
- "properties": {
- "fontFamily": {
- "description": "Sets the `font-family` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "fontSize": {
- "description": "Sets the `font-size` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "fontStyle": {
- "description": "Sets the `font-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "fontWeight": {
- "description": "Sets the `font-weight` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "letterSpacing": {
- "description": "Sets the `letter-spacing` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "lineHeight": {
- "description": "Sets the `line-height` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "textAlign": {
- "description": "Sets the `text-align` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "textColumns": {
- "description": "Sets the `column-count` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "textDecoration": {
- "description": "Sets the `text-decoration` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "writingMode": {
- "description": "Sets the `writing-mode` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "textTransform": {
- "description": "Sets the `text-transform` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- }
- }
- },
- "stylesPropertyNames": {
- "enum": [
- "background",
- "border",
- "color",
- "css",
- "dimensions",
- "filter",
- "outline",
- "shadow",
- "spacing",
- "typography"
- ]
- },
- "stylesPropertiesComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "propertyNames": {
- "$ref": "#/definitions/stylesPropertyNames"
- }
- }
- ]
- },
- "stylesElementsPseudoSelectorsProperties": {
- "type": "object",
- "properties": {
- ":active": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":any-link": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":focus": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":focus-visible": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":hover": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":link": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":visited": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- }
- }
- },
- "stylesElementsPseudoSelectorsPropertyNames": {
- "enum": [
- ":active",
- ":any-link",
- ":focus",
- ":focus-visible",
- ":hover",
- ":link",
- ":visited"
- ]
- },
- "stylesElementsPropertiesComplete": {
- "description": "Styles defined on a per-element basis using the element's selector.",
- "type": "object",
- "properties": {
- "button": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties"
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames"
- }
- ]
- }
- }
- ]
- },
- "link": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties"
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames"
- }
- ]
- }
- }
- ]
- },
- "heading": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h1": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h2": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h3": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h4": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h5": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h6": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "caption": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "cite": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- }
- },
- "additionalProperties": false
- },
- "stylesBlocksPropertiesComplete": {
- "description": "Styles defined on a per-block basis using the block's selector.",
- "type": "object",
- "properties": {
- "core/archives": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/audio": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/avatar": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/block": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/button": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/buttons": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/calendar": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/categories": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/code": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/column": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/columns": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-author-avatar": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-author-name": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-content": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-date": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-edit-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-reply-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-pagination": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-pagination-next": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-pagination-numbers": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-pagination-previous": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-title": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-template": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/cover": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/details": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/embed": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/file": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/footnotes": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/freeform": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/gallery": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/group": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/heading": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/home-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/html": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/image": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/latest-comments": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/latest-posts": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/list": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/list-item": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/loginout": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/media-text": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/missing": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/more": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/navigation": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/navigation-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/navigation-submenu": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/nextpage": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/page-list": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/page-list-item": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/paragraph": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-author": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-author-biography": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-author-name": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-comment": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-comments-count": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-comments-form": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-comments-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-content": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-date": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-excerpt": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-featured-image": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-navigation-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-template": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-terms": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-title": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/preformatted": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/pullquote": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-no-results": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-pagination": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-pagination-next": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-pagination-numbers": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-pagination-previous": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-title": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-total": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/quote": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/read-more": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/rss": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/search": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/separator": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/shortcode": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/site-logo": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/site-tagline": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/site-title": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/social-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/social-links": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/spacer": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/table": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/tag-cloud": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/template-part": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/term-description": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/text-columns": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/verse": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/video": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/widget-area": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/legacy-widget": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/widget-group": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- }
- },
- "patternProperties": {
- "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- }
- },
- "additionalProperties": false
- },
- "stylesPropertiesAndElementsComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- },
- "variations": {
- "$ref": "#/definitions/stylesVariationsPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements", "variations" ]
- }
- ]
- }
- }
- ]
- },
- "stylesVariationsProperties": {
- "type": "object",
- "patternProperties": {
- "^[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/stylesVariationProperties"
- }
- }
- },
- "stylesVariationProperties": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- },
- "blocks": {
- "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements", "blocks" ]
- }
- ]
- }
- }
- ]
- },
- "stylesVariationsPropertiesComplete": {
- "type": "object",
- "patternProperties": {
- "^[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/stylesVariationPropertiesComplete"
- }
- }
- },
- "stylesVariationPropertiesComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- },
- "blocks": {
- "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements", "blocks" ]
- }
- ]
- }
- }
- ]
- },
- "stylesVariationBlocksPropertiesComplete": {
- "type": "object",
- "properties": {
- "core/archives": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/audio": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/avatar": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/block": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/button": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/buttons": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/calendar": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/categories": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/code": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/column": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/columns": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-author-avatar": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-author-name": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-content": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-date": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-edit-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-reply-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-pagination": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-pagination-next": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-pagination-numbers": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-pagination-previous": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-title": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-template": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/cover": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/details": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/embed": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/file": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/footnotes": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/freeform": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/gallery": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/group": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/heading": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/home-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/html": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/image": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/latest-comments": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/latest-posts": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/list": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/list-item": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/loginout": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/media-text": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/missing": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/more": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/navigation": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/navigation-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/navigation-submenu": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/nextpage": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/page-list": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/page-list-item": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/paragraph": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-author": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-author-biography": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-author-name": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-comment": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-comments-count": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-comments-form": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-comments-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-content": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-date": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-excerpt": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-featured-image": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-navigation-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-template": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-terms": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-title": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/preformatted": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/pullquote": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-no-results": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-pagination": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-pagination-next": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-pagination-numbers": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-pagination-previous": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-title": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-total": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/quote": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/read-more": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/rss": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/search": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/separator": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/shortcode": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/site-logo": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/site-tagline": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/site-title": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/social-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/social-links": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/spacer": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/table": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/tag-cloud": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/template-part": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/term-description": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/text-columns": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/verse": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/video": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/widget-area": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/legacy-widget": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/widget-group": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- }
- },
- "patternProperties": {
- "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- }
- },
- "additionalProperties": false
- },
- "stylesVariationBlockPropertiesComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements" ]
- }
- ]
- }
- }
- ]
- }
- },
- "type": "object",
- "properties": {
- "$schema": {
- "description": "JSON schema URI for theme.json.",
- "type": "string"
- },
- "version": {
- "description": "Version of theme.json to use.",
- "type": "integer",
- "const": 3
- },
- "title": {
- "description": "Title of the global styles variation. If not defined, the file name will be used.",
- "type": "string"
- },
- "slug": {
- "description": "Slug of the global styles variation. If not defined, the kebab-case title will be used.",
- "type": "string"
- },
- "description": {
- "description": "Description of the global styles variation.",
- "type": "string"
- },
- "blockTypes": {
- "description": "List of block types that can use the block style variation this theme.json file represents.",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "settings": {
- "description": "Settings for the block editor and individual blocks. These include things like:\n- Which customization options should be available to the user. \n- The default colors, font sizes... available to the user. \n- CSS custom properties and class names used in styles.\n- And the default layout of the editor (widths and available alignments).",
- "allOf": [
- {
- "$ref": "#/definitions/settingsProperties"
- },
- {
- "type": "object",
- "properties": {
- "useRootPaddingAwareAlignments": {
- "description": "Enables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block.\n\nPlease note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately.",
- "type": "boolean",
- "default": false
- },
- "blocks": {
- "$ref": "#/definitions/settingsBlocksPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/settingsPropertyNames"
- },
- {
- "enum": [
- "useRootPaddingAwareAlignments",
- "blocks"
- ]
- }
- ]
- }
- }
- ]
- },
- "styles": {
- "description": "Organized way to set CSS properties. Styles in the top-level will be added in the `body` selector.",
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- },
- "blocks": {
- "$ref": "#/definitions/stylesBlocksPropertiesComplete"
- },
- "variations": {
- "$ref": "#/definitions/stylesVariationsProperties"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements", "blocks", "variations" ]
- }
- ]
- }
- }
- ]
- },
- "customTemplates": {
- "description": "Additional metadata for custom templates defined in the templates folder.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Filename, without extension, of the template in the templates folder.",
- "type": "string"
- },
- "title": {
- "description": "Title of the template, translatable.",
- "type": "string"
- },
- "postTypes": {
- "description": "List of post types that can use this custom template.",
- "type": "array",
- "items": {
- "type": "string"
- },
- "default": [ "page" ]
- }
- },
- "required": [ "name", "title" ],
- "additionalProperties": false
- }
- },
- "templateParts": {
- "description": "Additional metadata for template parts defined in the parts folder.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Filename, without extension, of the template in the parts folder.",
- "type": "string"
- },
- "title": {
- "description": "Title of the template, translatable.",
- "type": "string"
- },
- "area": {
- "description": "The area the template part is used for. Block variations for `header` and `footer` values exist and will be used when the area is set to one of those.",
- "type": "string",
- "default": "uncategorized"
- }
- },
- "required": [ "name" ],
- "additionalProperties": false
- }
- },
- "patterns": {
- "description": "An array of pattern slugs to be registered from the Pattern Directory.",
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- },
- "required": [ "version" ],
- "additionalProperties": false
-}
diff --git a/block-themes/theme-structure-epi.md b/block-themes/theme-structure-epi.md
deleted file mode 100644
index 4a55bf8..0000000
--- a/block-themes/theme-structure-epi.md
+++ /dev/null
@@ -1,53 +0,0 @@
----
-name: "Epic Issue"
-about: "Template for creating an EPIC issue to track a larger goal and its sub-tasks"
-title: "[EPIC] WordPress Block Theme Structure Implementation"
-labels: epic
-assignees:
----
-## Priority
-
-- High
-
-## Goal
-
-Establish the complete folder and file structure for the WordPress block theme according to WordPress best practices and standards, creating a solid foundation for theme development.
-
-## Description
-
-This epic covers the creation of all necessary folders and files required for a modern WordPress block theme that follows the Full Site Editing (FSE) approach. We will implement the standard theme structure as outlined in the WordPress Block Theme Structure & Development Guidelines, including required core files, primary theme directories, global styles, and proper asset organization.
-
-The theme will follow WordPress coding standards and best practices for block themes, ensuring it's well-structured, maintainable, and ready for development. This foundation will establish the framework upon which all theme features and functionality will be built.
-
-## Acceptance Criteria
-
-- [ ] All child issues are closed and their deliverables present in the repository.
-- [ ] File and folder structure matches project standards and guidelines.
-- [ ] All documentation is clear, up-to-date, and accessible for contributors and users.
-- [ ] The following directories are created with their appropriate initial files:
- - [ ] `/templates/` (with at least `index.html`)
- - [ ] `/parts/` (with header and footer parts)
- - [ ] `/patterns/` (directory created, ready for patterns)
- - [ ] `/styles/` (for style variations)
- - [ ] `/assets/` or `/src/` (for development files)
- - [ ] `/inc/` (for PHP includes if needed)
-- [ ] Core theme files are created:
- - [ ] `style.css` with proper theme metadata
- - [ ] `functions.php` with basic theme setup
- - [ ] `theme.json` with global styles configuration
- - [ ] `screenshot.png` for theme preview
- - [ ] `README.md` with theme documentation
- - [ ] Build configuration files (package.json, webpack.config.js)
-
-## Sub-Issues
-
-- [ ] [#] Create core theme files (style.css, functions.php)
-- [ ] [#] Set up template directory structure with index.html
-- [ ] [#] Create template parts directory with header and footer
-- [ ] [#] Configure theme.json for global styles and settings
-- [ ] [#] Set up asset/build pipeline with @wordpress/scripts
-- [ ] [#] Create README and documentation files
-- [ ] [#] Generate theme screenshot
-- [ ] [#] Establish patterns directory and initial patterns
-- [ ] [#] Create style variations directory and base variation
-- [ ] [#] Set up testing infrastructure
diff --git a/block-themes/typesets.md b/block-themes/typesets.md
deleted file mode 100644
index 9333798..0000000
--- a/block-themes/typesets.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Typesets (Font Size Presets)
-The file style-variations.md provides a concise guide to the differences between style variations and block variations in WordPress block development. It explains that style variations are visual alternatives for blocks defined via theme.json, while block variations are structural alternatives registered with JavaScript. The document outlines best practices, use cases, and limitations, emphasizing not to confuse the two APIs. It also includes a reference link for further reading.
----
-
-**Best practices**
-- Leverage new **typeset support** in WordPress 6.6 for consistent font-size presets. ([Rich Tabor](https://rich.blog/wordpress-6-6/?utm_source=chatgpt.com))
-
----
-
-## When to use
--
-
----
-
-## Limitations
-- Requires theme authoring in WP 6.6+ to make use of this feature.
-
----
-
-## Reference Links
-- [Rich Tabor: WordPress 6.6 Typeset Support](https://rich.blog/wordpress-6-6/)
-
----
diff --git a/coding-standards/_temp.md b/coding-standards/_temp.md
deleted file mode 100644
index b2f27f1..0000000
--- a/coding-standards/_temp.md
+++ /dev/null
@@ -1,167 +0,0 @@
-I need you to go through all of the links in the references below, and compile in markdown format comprehensive coding standard documents per language, there will be an individual document per language as per the numbering system below.
-
-The attached documentation and wordpress coding standards module should provide all of the information that you require to be able to compile LightSpeed specific coding standards.
-
-I also want you to review the following best practices and coding standards:
-https://github.com/DekodeInteraktiv/coding-standards
-https://10up.github.io/Engineering-Best-Practices/
-https://github.com/10up/Engineering-Best-Practices
-https://gutenberg.10up.com/
-http://github.com/10up/gutenberg-best-practices/
-https://github.com/humanmade/coding-standards
-https://packagist.org/packages/dekode/coding-standards
-
-The current version is 3.2.0 and was released on the 25th of July. The github repo is here - http://github.com/wordPress/WordPress-Coding-Standards/
-
-The development documentation portal can be found here - https://developer.wordpress.org/coding-standards/
-
-I would like you to define coding standard instructions to include clear details about the following:
-0. Common coding standards topics that should be defined for all languages:
- -- Why have coding standards:
- --- https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards.md
- -- Naming Conventions
- -- Spacing or indentation
- -- Commenting
- -- White space
- -- Formatting
- -- Inline documentation
- -- Best Practices
- -- Reference links
-1. Accessibility Coding Standards:
- -- Applying WCAG Conformance Levels
- -- WCAG 2.2 consists of 4 layers:
- --- Principles
- --- Guidance
- --- Success criteria
- --- Sufficient and advisory techniques
- -- Reference links:
- --- https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/accessibility.md
- --- https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/Test_your_skills/CSS_and_JavaScript
- --- https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/CSS_and_JavaScript
- --- https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/What_is_accessibility
- --- https://developer.wordpress.org/block-editor/how-to-guides/accessibility/
- --- https://github.com/WordPress/gutenberg/edit/trunk/docs/how-to-guides/accessibility.md
-2. php:
- -- General
- -- Spacing
- -- Naming Conventions
- -- Whitespace
- -- Declare Statements, Namespace, and Import Statements
- -- Object-Oriented Programming
- -- Singletons
- -- Control Structures
- -- Operators
- -- Database
- -- Recommendations
- -- Comments
- -- Formatting
- -- References:
- --- https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/
- --- https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/php.md
-3. html
- -- Validation
- -- Spacing
- -- Naming Conventions
- -- Comments
- -- Self-closing Elements
- -- Attributes and Tags
- -- Quotes
- -- Indentation
- -- Best practices
- -- References:
- --- https://developer.wordpress.org/coding-standards/wordpress-coding-standards/html/
- --- https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/html.md
-4. JavaScript
- -- Code Refactoring
- -- Spacing
- -- Semicolons
- -- Indentation and Line Breaks
- -- Multi-line Statements
- -- Chained Method Calls
- -- Assignments and Globals
- -- Naming Conventions
- -- Equality
- -- Type Checks
- -- Strings
- -- Switch Statements
- -- JSHint
- -- Best Practices
- -- Reference links
- --- https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/javascript.md
-5. CSS
- -- Structure
- -- Selectors
- -- Values
- -- Media Queries
- -- Naming connventions
- -- Best Practices
- -- References:
- --- https://developer.wordpress.org/coding-standards/wordpress-coding-standards/css/
- --- https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/css.md
- --- https://github.com/necolas/idiomatic-css/blob/master/README.md
-6. Inline Documentation Standards
- -- Reference links
- --- https://jjj.blog/2012/06/inline-documentation/
-6.1 PHP Documentation Standards
- -- What Should Be Documented
- --- Documenting Tips
- --- Formatting Guidelines
- -- DocBlock Formatting
- -- PHPDoc Tags
- -- References:
- --- https://developer.wordpress.org/coding-standards/inline-documentation-standards/php/
- --- https://github.com/WordPress/wpcs-docs/blob/master/inline-documentation-standards/php.md
-6.2 JavaScript Documentation Standards
- -- What Should Be Documented
- -- Documenting Tips
- -- Formatting Guidelines
- -- Functions
- -- Backbone classes
- -- Local functions
- -- Local ancestors
- -- Class members
- -- Namespaces
- -- Inline Comments
- -- File Headers
- -- Supported JSDoc Tags
- -- Unsupported JSDoc Tags
- -- References:
- --- https://developer.wordpress.org/coding-standards/inline-documentation-standards/javascript/
- --- https://developer.wordpress.org/coding-standards/wordpress-coding-standards/javascript/
- --- https://github.com/WordPress/wpcs-docs/blob/master/inline-documentation-standards/javascript.md
-7. Markdown format
- -- Headings (Note: h1 - h4 items will be automatically added to the Table of Contents.)
- -- Emphasis / formatting - italics, bold, strikethrough
- -- Links
- -- Blockquotes
- -- Lists - ordered, unordered & checkboxes
- -- Horizontal Rules
- -- Tables
- -- Example Code
- -- Reference links
- --- https://github.com/WordPress/wpcs-docs/blob/master/styleguide.md
-8. JSON
- -- Reference links:
- --- https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/theme-json-reference/styles-versions.md
- --- https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/theme-json-reference/theme-json-living.md
- --- https://developer.wordpress.org/block-editor/how-to-guides/themes/global-settings-and-styles/
- --- Block.json schema - https://github.com/WordPress/gutenberg/blob/trunk/schemas/json/block.json
- --- Theme.json schema - https://github.com/WordPress/gutenberg/blob/trunk/schemas/json/theme.json
- --- Font collection schema - https://github.com/WordPress/gutenberg/blob/trunk/schemas/json/font-collection.json
-8. Fluid spacing & typography
- -- Reference links
- --- Handling block spacing - https://github.com/10up/gutenberg-best-practices/blob/main/guides/handeling-block-spacing.md
- --- Different approaches to fluid typography and spacing - https://crinkles.dev/writing/different-approaches-to-fluid-typography-and-layouts/
- --- https://github.com/lightspeedwp/ls-handbooks/blob/main/docs/block-themes/fluid-spacing.md
- --- https://github.com/lightspeedwp/ls-handbooks/blob/main/docs/block-themes/fluid-typography.md
- --- https://css-tricks.com/linearly-scale-font-size-with-css-clamp-based-on-the-viewport/
- --- https://www.reddit.com/r/Wordpress/comments/1eaifh4/best_practices_for_measurements_ie_px_em_rem_vw_vh/
- --- https://developer.mozilla.org/en-US/docs/Web/CSS/clamp
- --- https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Values_and_units
- --- https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Values_and_Units
- --- https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Responsive_Design
- --- https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Introduction
- --- https://developer.mozilla.org/en-US/docs/Web/CSS/length
- --- https://developer.mozilla.org/en-US/docs/Glossary/Baseline/Typography
- --- https://www.designsystemscollective.com/fluid-typographic-scales-revolutionize-your-responsive-design-0d10ed7f740e
- --- https://gutenberg.10up.com/guides/handeling-block-spacing/
diff --git a/coding-standards/ash-research/9-fluid-spacing-typography.md b/coding-standards/ash-research/9-fluid-spacing-typography.md
deleted file mode 100644
index e00ec78..0000000
--- a/coding-standards/ash-research/9-fluid-spacing-typography.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# 9. Fluid Spacing & Typography
-
-## Goals
-- Scale type and spacing smoothly across viewports.
-- Reduce brittle breakpoint stacks; prefer fluid curves with sensible clamps.
-
-## Typography
-- Use `clamp(min, preferred, max)` to scale font sizes.
-- Base on `rem`; define a typographic scale (e.g., 1.125 or 1.2 ratio).
-- Maintain readable line length (45–85 chars) and line height (≈1.4–1.7).
-
-```css
-:root {
- /* Example scale */
- --step--1: clamp(0.875rem, 0.85rem + 0.2vw, 1rem);
- --step-0: clamp(1rem, 0.95rem + 0.5vw, 1.125rem);
- --step-1: clamp(1.125rem, 1rem + 1vw, 1.5rem);
-}
-h1 { font-size: var(--step-1); }
-```
-
-## Spacing
-- Prefer rem for space tokens; define a scale and expose via CSS vars or theme.json custom properties.
-- Use fluid clamp for key blocks when helpful; otherwise scale via responsive presets in theme.json.
-
-```css
-:root {
- --space-2xs: clamp(0.25rem, 0.2rem + 0.3vw, 0.5rem);
- --space-xs: clamp(0.5rem, 0.4rem + 0.4vw, 0.75rem);
- --space-s: clamp(0.75rem, 0.6rem + 0.6vw, 1rem);
-}
-.section { padding-block: var(--space-s); }
-```
-## Gutenberg / theme.json
-- Use Theme JSON typography and spacing presets for consistent tokens.
-- Avoid pixel-locked values; use presets + fluid scaling where appropriate.
-
-## References
-- LightSpeed: fluid spacing → https://github.com/lightspeedwp/ls-handbooks/blob/main/docs/block-themes/fluid-spacing.md
-- LightSpeed: fluid typography → https://github.com/lightspeedwp/ls-handbooks/blob/main/docs/block-themes/fluid-typography.md
-- CSS clamp intro: https://css-tricks.com/linearly-scale-font-size-with-css-clamp-based-on-the-viewport/
-- MDN clamp: https://developer.mozilla.org/en-US/docs/Web/CSS/clamp
-- 10up Gutenberg best practices: https://gutenberg.10up.com/guides/handeling-block-spacing/
diff --git a/copilot-todo.md b/copilot-todo.md
new file mode 100644
index 0000000..e69de29
diff --git a/docs/ai-copilot/README.md b/docs/ai-copilot/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/coding-standards/README.md b/docs/coding-standards/README.md
similarity index 96%
rename from coding-standards/README.md
rename to docs/coding-standards/README.md
index 9116d77..992b48c 100644
--- a/coding-standards/README.md
+++ b/docs/coding-standards/README.md
@@ -5,9 +5,11 @@ This folder contains comprehensive coding standards and style guides for WordPre
## Directories
### [LightSpeed Coding Standards](ash-research/)
+
Complete coding standards suite aligned with WordPress Coding Standards (WPCS v3.2.0), incorporating guidance from industry leaders like 10up, Human Made, and Dekode.
**Key Features:**
+
- Comprehensive coverage: PHP, JavaScript, CSS, HTML, Accessibility, and more
- Security-first approach with escaping, sanitization, and nonce requirements
- WCAG 2.2 Level AA accessibility baseline
@@ -15,19 +17,23 @@ Complete coding standards suite aligned with WordPress Coding Standards (WPCS v3
- Fluid spacing and typography standards
### [WordPress Coding Standards](wordpress-coding-standards/)
+
Official WordPress coding standards covering core development practices and community guidelines.
**Includes:**
+
- PHP coding standards and best practices
-- HTML structure and semantic guidelines
+- HTML structure and semantic guidelines
- CSS styling conventions
- JavaScript development standards
- Accessibility requirements
### [Inline Documentation Standards](inline-documentation-standards/)
+
Specialized documentation focusing on code commenting and inline documentation practices.
**Covers:**
+
- PHP documentation standards (PHPDoc-inspired)
- JavaScript commenting conventions
- Best practices for maintainable code documentation
@@ -35,6 +41,7 @@ Specialized documentation focusing on code commenting and inline documentation p
## Top-Level Files
### Reference Materials
+
- **[WordPress Coding Standards](wordpress-coding-standards.md)** - Overview of official WordPress standards
- **[Inline Documentation Standards](inline-documentation-standards.md)** - Guide to code documentation practices
- **[Idiomatic CSS](idiomatic-css.md)** - CSS writing principles and conventions
@@ -64,4 +71,4 @@ Specialized documentation focusing on code commenting and inline documentation p
3. **Need documentation guidance?** Check [Inline Documentation Standards](inline-documentation-standards/)
4. **Writing CSS?** Review [Idiomatic CSS](idiomatic-css.md) principles
-These standards ensure consistency, security, and maintainability across all WordPress development projects.
\ No newline at end of file
+These standards ensure consistency, security, and maintainability across all WordPress development projects.
diff --git a/docs/coding-standards/_temp.md b/docs/coding-standards/_temp.md
new file mode 100644
index 0000000..a1c8667
--- /dev/null
+++ b/docs/coding-standards/_temp.md
@@ -0,0 +1,167 @@
+I need you to go through all of the links in the references below, and compile in markdown format comprehensive coding standard documents per language, there will be an individual document per language as per the numbering system below.
+
+The attached documentation and wordpress coding standards module should provide all of the information that you require to be able to compile LightSpeed specific coding standards.
+
+I also want you to review the following best practices and coding standards:
+
+
+
+
+
+
+
+
+The current version is 3.2.0 and was released on the 25th of July. The github repo is here -
+
+The development documentation portal can be found here -
+
+I would like you to define coding standard instructions to include clear details about the following: 0. Common coding standards topics that should be defined for all languages:
+-- Why have coding standards:
+---
+-- Naming Conventions
+-- Spacing or indentation
+-- Commenting
+-- White space
+-- Formatting
+-- Inline documentation
+-- Best Practices
+-- Reference links
+
+1. Accessibility Coding Standards:
+ -- Applying WCAG Conformance Levels
+ -- WCAG 2.2 consists of 4 layers:
+ --- Principles
+ --- Guidance
+ --- Success criteria
+ --- Sufficient and advisory techniques
+ -- Reference links:
+ ---
+ ---
+ ---
+ ---
+ ---
+ ---
+2. php:
+ -- General
+ -- Spacing
+ -- Naming Conventions
+ -- Whitespace
+ -- Declare Statements, Namespace, and Import Statements
+ -- Object-Oriented Programming
+ -- Singletons
+ -- Control Structures
+ -- Operators
+ -- Database
+ -- Recommendations
+ -- Comments
+ -- Formatting
+ -- References:
+ ---
+ ---
+3. html
+ -- Validation
+ -- Spacing
+ -- Naming Conventions
+ -- Comments
+ -- Self-closing Elements
+ -- Attributes and Tags
+ -- Quotes
+ -- Indentation
+ -- Best practices
+ -- References:
+ ---
+ ---
+4. JavaScript
+ -- Code Refactoring
+ -- Spacing
+ -- Semicolons
+ -- Indentation and Line Breaks
+ -- Multi-line Statements
+ -- Chained Method Calls
+ -- Assignments and Globals
+ -- Naming Conventions
+ -- Equality
+ -- Type Checks
+ -- Strings
+ -- Switch Statements
+ -- JSHint
+ -- Best Practices
+ -- Reference links
+ ---
+5. CSS
+ -- Structure
+ -- Selectors
+ -- Values
+ -- Media Queries
+ -- Naming connventions
+ -- Best Practices
+ -- References:
+ ---
+ ---
+ ---
+6. Inline Documentation Standards
+ -- Reference links
+ ---
+ 6.1 PHP Documentation Standards
+ -- What Should Be Documented
+ --- Documenting Tips
+ --- Formatting Guidelines
+ -- DocBlock Formatting
+ -- PHPDoc Tags
+ -- References:
+ ---
+ ---
+ 6.2 JavaScript Documentation Standards
+ -- What Should Be Documented
+ -- Documenting Tips
+ -- Formatting Guidelines
+ -- Functions
+ -- Backbone classes
+ -- Local functions
+ -- Local ancestors
+ -- Class members
+ -- Namespaces
+ -- Inline Comments
+ -- File Headers
+ -- Supported JSDoc Tags
+ -- Unsupported JSDoc Tags
+ -- References:
+ ---
+ ---
+ ---
+7. Markdown format
+ -- Headings (Note: h1 - h4 items will be automatically added to the Table of Contents.)
+ -- Emphasis / formatting - italics, bold, strikethrough
+ -- Links
+ -- Blockquotes
+ -- Lists - ordered, unordered & checkboxes
+ -- Horizontal Rules
+ -- Tables
+ -- Example Code
+ -- Reference links
+ ---
+8. JSON
+ -- Reference links:
+ ---
+ ---
+ ---
+ --- Block.json schema -
+ --- Theme.json schema -
+ --- Font collection schema -
+9. Fluid spacing & typography
+ -- Reference links
+ --- Handling block spacing -
+ --- Different approaches to fluid typography and spacing -
+ ---
+ ---
+ ---
+ ---
+ ---
+ ---
+ ---
+ ---
+ ---
+ ---
+ ---
+ ---
+ ---
diff --git a/coding-standards/ash-research/0-common-standards.md b/docs/coding-standards/ash-research/0-common-standards.md
similarity index 75%
rename from coding-standards/ash-research/0-common-standards.md
rename to docs/coding-standards/ash-research/0-common-standards.md
index 23565fb..b4c4639 100644
--- a/coding-standards/ash-research/0-common-standards.md
+++ b/docs/coding-standards/ash-research/0-common-standards.md
@@ -3,6 +3,7 @@
**Why standards?** Consistency improves readability, onboarding, maintenance, and review velocity. It reduces cognitive load across projects and teams.
## Golden Rules
+
- **Indentation**: Use **tabs** to indent. Use **spaces only for alignment** (e.g., lining up parameters).
- **Line length**: Aim for ~80–100 chars where practical.
- **Whitespace**: No trailing spaces; single blank lines to separate logical sections.
@@ -11,12 +12,13 @@
- PHP: functions/vars `snake_case`; classes `UpperCamelCase`; constants `UPPER_SNAKE_CASE`.
- JS: variables/functions `camelCase`; classes `UpperCamelCase`.
- CSS: classes/IDs lowercase, hyphenated (`.product-card__title` is fine; prefer BEM-ish clarity).
-- **Comments & Docs**: Prefer clear code; document *why*, not just *what*. Use DocBlocks for public APIs.
+- **Comments & Docs**: Prefer clear code; document _why_, not just _what_. Use DocBlocks for public APIs.
- **Security**: Escape on output, sanitise on input, verify nonces/capabilities.
- **Performance**: Keep bundles small; lazy-load when useful; avoid unnecessary queries.
- **Accessibility**: WCAG 2.2 AA baseline; semantic markup; keyboard & screen-reader support.
## References
-- General WPCS overview: https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards.md
-- Dev Handbook: https://developer.wordpress.org/coding-standards/
-- 10up EBP: https://10up.github.io/Engineering-Best-Practices/
+
+- General WPCS overview:
+- Dev Handbook:
+- 10up EBP:
diff --git a/coding-standards/ash-research/1-accessibility.md b/docs/coding-standards/ash-research/1-accessibility.md
similarity index 99%
rename from coding-standards/ash-research/1-accessibility.md
rename to docs/coding-standards/ash-research/1-accessibility.md
index 706a065..62bb9ca 100644
--- a/coding-standards/ash-research/1-accessibility.md
+++ b/docs/coding-standards/ash-research/1-accessibility.md
@@ -3,12 +3,14 @@
LightSpeed targets **WCAG 2.2 Level AA** across products and content.
## WCAG 2.2 Layers
+
- **Principles**: Perceivable, Operable, Understandable, Robust.
- **Guidelines**: Human-centered rules that map to Success Criteria.
- **Success Criteria**: Testable checkpoints at A/AA/AAA.
- **Techniques**: Sufficient & advisory patterns to implement criteria.
## Practical Requirements
+
- **Semantics**: Use proper headings, lists, landmarks (``, `
```
In a block's `Edit` component, use the `useBlockProps()` hook to include additional classes and attributes by passing them as arguments. (See [example](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/stylesheets-79a4c3/src/edit.js))
@@ -71,8 +73,8 @@ const Edit = () =>
Hello World - Block Editor
;
const save = () =>
Hello World - Frontend
;
registerBlockType( ..., {
- edit: Edit,
- save,
+ edit: Edit,
+ save,
} );
```
@@ -89,13 +91,17 @@ If you want to add any additional classes or attributes to the `save` function o
When you add `supports` for any feature, the proper classes get added to the object returned by the `useBlockProps.save()` hook. Text and background color classes have been added to the Paragraph block in the example below.
```html
-
Hello World
+"
+>
+ Hello World
+
```
The [example block](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/block-supports-6aa4dd) that generated this HTML is available in the [Block Development Examples](https://github.com/WordPress/block-development-examples) repository.
@@ -106,6 +112,6 @@ In dynamic blocks, where the front-end markup is rendered server-side, you can u
```php
>
-
+
```
diff --git a/gutenberg/getting-started/fundamentals/file-structure-of-a-block.md b/docs/gutenberg/getting-started/fundamentals/file-structure-of-a-block.md
similarity index 98%
rename from gutenberg/getting-started/fundamentals/file-structure-of-a-block.md
rename to docs/gutenberg/getting-started/fundamentals/file-structure-of-a-block.md
index 24972b2..8c93035 100644
--- a/gutenberg/getting-started/fundamentals/file-structure-of-a-block.md
+++ b/docs/gutenberg/getting-started/fundamentals/file-structure-of-a-block.md
@@ -4,12 +4,11 @@ When developing custom blocks for WordPress, it's best practice to register them
Adhering to the `create-block` tool's structure is not mandatory, but it serves as a reliable reference. The files it generates encompass everything needed for a block's definition and registration. Following this structure can help maintain consistency and ensure your blocks are well-organized and easy to maintain.
-[](https://developer.wordpress.org/files/2023/11/file-structure-block.png "Open File Structure of a Block diagram image")
+[](https://developer.wordpress.org/files/2023/11/file-structure-block.png 'Open File Structure of a Block diagram image')
## `.php`
-
-When creating a block in a WordPress plugin, you usually register the block on the server in the main PHP file of the plugin. This is done using the [`register_block_type()`](https://developer.wordpress.org/reference/functions/register_block_type/) function.
+When creating a block in a WordPress plugin, you usually register the block on the server in the main PHP file of the plugin. This is done using the [`register_block_type()`](https://developer.wordpress.org/reference/functions/register_block_type/) function.
For more on creating a WordPress plugin, refer to the documentation on Plugin Basics and the Header Requirements for the main PHP file.
@@ -23,15 +22,15 @@ The `package.json` file is used to configure a Node.js project, which is technic
In a standard project, the `src` (source) folder contains the raw, uncompiled code, including JavaScript, CSS, and other assets necessary for developing the block. This is where you write and edit your block's source code, utilizing modern JavaScript features and JSX for React components.
-The [build process](docs/block-editor/getting-started/fundamentals/javascript-in-the-block-editor/#javascript-build-process.md) provided by `wp-scripts` will then take the files from this folder and generate the production-ready files in the project's `build` folder.
+The [build process](docs/block-editor/getting-started/fundamentals/javascript-in-the-block-editor/#javascript-build-process.md) provided by `wp-scripts` will then take the files from this folder and generate the production-ready files in the project's `build` folder.
### `block.json`
-The `block.json` file contains the [block's metadata](docs/block-editor/reference-guides/block-api/block-metadata/), streamlining its definition and registration across client-side and server-side environments.
+The `block.json` file contains the [block's metadata](docs/block-editor/reference-guides/block-api/block-metadata/), streamlining its definition and registration across client-side and server-side environments.
-This file includes the block name, description, [attributes](docs/block-editor/reference-guides/block-api/block-attributes/), [supports](docs/block-editor/reference-guides/block-api/block-supports/), and more, as well as the locations of essential files responsible for the block's functionality, appearance, and styling.
+This file includes the block name, description, [attributes](docs/block-editor/reference-guides/block-api/block-attributes/), [supports](docs/block-editor/reference-guides/block-api/block-supports/), and more, as well as the locations of essential files responsible for the block's functionality, appearance, and styling.
-When a build process is applied, the `block.json` file and the other generated files are moved to a designated folder, often the `build` folder. Consequently, the file paths specified within `block.json` point to these processed, bundled versions of the files.
+When a build process is applied, the `block.json` file and the other generated files are moved to a designated folder, often the `build` folder. Consequently, the file paths specified within `block.json` point to these processed, bundled versions of the files.
A few of the most important properties that can be defined in a `block.json` are:
@@ -41,7 +40,7 @@ A few of the most important properties that can be defined in a `block.json` are
- **[`render`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#render):** Usually set with the path of a bundled `render.php` that was copied from `src/render.php`.
- **[`viewScript`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#view-script):** Usually set with the path of a bundled `view.js` that was built from `src/view.js`.
-[](https://excalidraw.com/#json=c22LROgcG4JkD-7SkuE-N,rQW_ViJBq0Yk3qhCgqD6zQ "Open Build Output Diagram in excalidraw")
+[](https://excalidraw.com/#json=c22LROgcG4JkD-7SkuE-N,rQW_ViJBq0Yk3qhCgqD6zQ 'Open Build Output Diagram in excalidraw')
### `index.js`
diff --git a/gutenberg/getting-started/fundamentals/javascript-in-the-block-editor.md b/docs/gutenberg/getting-started/fundamentals/javascript-in-the-block-editor.md
similarity index 93%
rename from gutenberg/getting-started/fundamentals/javascript-in-the-block-editor.md
rename to docs/gutenberg/getting-started/fundamentals/javascript-in-the-block-editor.md
index 717626a..b98fc4a 100644
--- a/gutenberg/getting-started/fundamentals/javascript-in-the-block-editor.md
+++ b/docs/gutenberg/getting-started/fundamentals/javascript-in-the-block-editor.md
@@ -22,7 +22,7 @@ For an introduction, refer to the [Get started with wp-scripts](/docs/getting-st
The diagram below provides an overview of the build process when using the `wp-scripts` package. It's designed to work out of the box with [standard configurations](/docs/getting-started/devenv/get-started-with-wp-scripts.md#basic-usage) for development and production environments.
-[](https://developer.wordpress.org/files/2023/11/build-process.png "Open Build Process diagram image")
+[](https://developer.wordpress.org/files/2023/11/build-process.png 'Open Build Process diagram image')
- **Production Mode (`npm run build`):** In this mode, `wp-scripts` compiles your JavaScript, minifying the output to reduce file size and improve loading times in the browser. This is ideal for deploying your code to a live site.
@@ -46,13 +46,13 @@ In the following example, the `wp-blocks` dependency is defined when enqueuing t
```php
function example_enqueue_block_variations() {
- wp_enqueue_script(
- 'example-enqueue-block-variations',
- get_template_directory_uri() . '/assets/js/variations.js',
- array( 'wp-blocks' ),
- wp_get_theme()->get( 'Version' ),
- false
- );
+ wp_enqueue_script(
+ 'example-enqueue-block-variations',
+ get_template_directory_uri() . '/assets/js/variations.js',
+ array( 'wp-blocks' ),
+ wp_get_theme()->get( 'Version' ),
+ false
+ );
}
add_action( 'enqueue_block_editor_assets', 'example_enqueue_block_variations' );
```
@@ -60,17 +60,14 @@ add_action( 'enqueue_block_editor_assets', 'example_enqueue_block_variations' );
Then in the `variations.js` file, you can register a new variation for the Media & Text block like so:
```js
-wp.blocks.registerBlockVariation(
- 'core/media-text',
- {
- name: 'media-text-custom',
- title: 'Media & Text Custom',
- attributes: {
- align: 'wide',
- backgroundColor: 'tertiary'
- },
- }
-);
+wp.blocks.registerBlockVariation('core/media-text', {
+ name: 'media-text-custom',
+ title: 'Media & Text Custom',
+ attributes: {
+ align: 'wide',
+ backgroundColor: 'tertiary',
+ },
+});
```
For scripts that need to run in the Block Editor, make sure you use the [`enqueue_block_editor_assets`](https://developer.wordpress.org/reference/hooks/enqueue_block_editor_assets/) hook coupled with the standard [`wp_enqueue_script`](https://developer.wordpress.org/reference/functions/wp_enqueue_script/) function.
diff --git a/gutenberg/getting-started/fundamentals/markup-representation-block.md b/docs/gutenberg/getting-started/fundamentals/markup-representation-block.md
similarity index 98%
rename from gutenberg/getting-started/fundamentals/markup-representation-block.md
rename to docs/gutenberg/getting-started/fundamentals/markup-representation-block.md
index b9cbb52..4600eca 100644
--- a/gutenberg/getting-started/fundamentals/markup-representation-block.md
+++ b/docs/gutenberg/getting-started/fundamentals/markup-representation-block.md
@@ -14,7 +14,7 @@ The following is the simplified markup representation of an Image block:
```html
-
+
```
@@ -48,4 +48,4 @@ As the example above shows, the stored markup is minimal for dynamically rendere
- [Data Flow and Data Format](https://developer.wordpress.org/block-editor/explanations/architecture/data-flow/)
- [Static vs. dynamic blocks: What’s the difference?](https://developer.wordpress.org/news/2023/02/27/static-vs-dynamic-blocks-whats-the-difference/) | Developer Blog
- [Block deprecation – a tutorial](https://developer.wordpress.org/news/2023/03/10/block-deprecation-a-tutorial/) | Developer Blog
-- [Introduction to Templates > Block markup](https://developer.wordpress.org/themes/templates/introduction-to-templates/#block-markup) | Theme Handbook
\ No newline at end of file
+- [Introduction to Templates > Block markup](https://developer.wordpress.org/themes/templates/introduction-to-templates/#block-markup) | Theme Handbook
diff --git a/gutenberg/getting-started/fundamentals/registration-of-a-block.md b/docs/gutenberg/getting-started/fundamentals/registration-of-a-block.md
similarity index 89%
rename from gutenberg/getting-started/fundamentals/registration-of-a-block.md
rename to docs/gutenberg/getting-started/fundamentals/registration-of-a-block.md
index 63a7a90..39aa5b7 100644
--- a/gutenberg/getting-started/fundamentals/registration-of-a-block.md
+++ b/docs/gutenberg/getting-started/fundamentals/registration-of-a-block.md
@@ -8,7 +8,7 @@ For instance, if you want a block [to be styled via `theme.json`](https://develo
The following diagram details the registration process for a block.
-[](https://developer.wordpress.org/files/2023/11/block-registration-e1700493399839.png "Open Block Registration diagram image")
+[](https://developer.wordpress.org/files/2023/11/block-registration-e1700493399839.png 'Open Block Registration diagram image')
## Registering a block with PHP (server-side)
@@ -26,10 +26,10 @@ The `register_block_type()` function returns the registered block type (`WP_Bloc
```php
register_block_type(
- __DIR__ . '/build',
- array(
- 'render_callback' => 'render_block_core_notice',
- )
+ __DIR__ . '/build',
+ array(
+ 'render_callback' => 'render_block_core_notice',
+ )
);
```
@@ -37,12 +37,12 @@ Here is a more complete example, including the `init` hook.
```php
function minimal_block_ca6eda___register_block() {
- register_block_type( __DIR__ . '/build' );
+ register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'minimal_block_ca6eda___register_block' );
```
-_See the [full block example](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/minimal-block-ca6eda) of the [code above](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/minimal-block-ca6eda/plugin.php)_
+_See the [full block example](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/minimal-block-ca6eda) of the [code above](https://github.com/WordPress/block-development-examples/blob/trunk/plugins/minimal-block-ca6eda/plugin.php)_
## Registering a block with JavaScript (client-side)
@@ -51,10 +51,10 @@ When the block has already been registered on the server, you only need to regis
```js
import { registerBlockType } from '@wordpress/blocks';
-registerBlockType( 'my-plugin/notice', {
- edit: Edit,
- // ...other client-side settings
-} );
+registerBlockType('my-plugin/notice', {
+ edit: Edit,
+ // ...other client-side settings
+});
```
While it's generally advised to register blocks on the server using PHP for the benefits outlined in the ["Benefits using the metadata file"](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#benefits-using-the-metadata-file) section, you can opt to register a block solely on the client-side. The `registerBlockType` method allows you to register a block type using metadata.
@@ -65,7 +65,7 @@ The function accepts two parameters:
- **`settings` (`Object`):** This is an object containing the block's client-side settings.
- You can import the contents of the block.json file (or any other .json file) directly into your JavaScript files if you're using a build process, such as the one provided by wp-scripts.
+ You can import the contents of the block.json file (or any other .json file) directly into your JavaScript files if you're using a build process, such as the one provided by wp-scripts.
The `settings` object passed as the second parameter includes many properties, but these are the two most important ones:
@@ -80,13 +80,13 @@ import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
import metadata from './block.json';
-const Edit = () =>
You can use create-block to scaffold a block just about anywhere and then use wp-env inside the generated plugin folder. This will create a local WordPress development environment with your new block plugin installed and activated.
@@ -35,13 +35,13 @@ cd copyright-date-block && npm start
When `create-block` scaffolds the block, it installs `wp-scripts` and adds the most common scripts to the block’s `package.json` file. Refer to the [Get started with wp-scripts](https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-scripts/) article for an introduction to this package.
-The `npm start` command will start a development server and watch for changes in the block’s code, rebuilding the block whenever modifications are made.
+The `npm start` command will start a development server and watch for changes in the block’s code, rebuilding the block whenever modifications are made.
When you are finished making changes, run the `npm run build` command. This optimizes the block code and makes it production-ready.
## View the block in action
-You can use any local WordPress development environment to test your new block, but the scaffolded plugin includes configuration for `wp-env`. You must have [Docker](https://www.docker.com/products/docker-desktop) already installed and running on your machine, but if you do, run the `npx wp-env start` command.
+You can use any local WordPress development environment to test your new block, but the scaffolded plugin includes configuration for `wp-env`. You must have [Docker](https://www.docker.com/products/docker-desktop) already installed and running on your machine, but if you do, run the `npx wp-env start` command.
Once the script finishes running, you can access the local environment at: http://localhost:8888. Log into the WordPress dashboard using username `admin` and password `password`. The plugin will already be installed and activated. Open the Editor or Site Editor, and insert the Copyright Date Block as you would any other block.
diff --git a/gutenberg/getting-started/tutorial.md b/docs/gutenberg/getting-started/tutorial.md
similarity index 79%
rename from gutenberg/getting-started/tutorial.md
rename to docs/gutenberg/getting-started/tutorial.md
index e21ffde..5a9fbf4 100644
--- a/gutenberg/getting-started/tutorial.md
+++ b/docs/gutenberg/getting-started/tutorial.md
@@ -25,7 +25,7 @@ To complete this tutorial, you will need:
If you don't have one or more of these items, the [Block Development Environment](https://developer.wordpress.org/block-editor/getting-started/devenv/) documentation will help you get started. Come back here once you are all set up.
- This tutorial uses wp-env to create a local WordPress development environment. However, feel free to use any development environment that meets the abovementioned prerequisites.
+ This tutorial uses wp-env to create a local WordPress development environment. However, feel free to use any development environment that meets the abovementioned prerequisites.
## Scaffolding the block
@@ -33,7 +33,7 @@ If you don't have one or more of these items, the [Block Development Environment
The first step in creating the Copyright Date Block is to scaffold the initial block structure using the [`@wordpress/create-block`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/) package.
You can use `create-block` from just about any directory (folder) on your computer and then use `wp-env` to create a local WordPress development environment with your new block plugin installed and activated.
@@ -41,7 +41,7 @@ You can use `create-block` from just about any directory (folder) on your comput
Therefore, choose a directory to place the block plugin or optionally create a new folder called "Block Tutorial". Open your terminal and `cd` to this directory. Then run the following command.
- If you are not using wp-env, instead, navigate to the plugins/ folder in your local WordPress installation using the terminal and run the following command.
+ If you are not using wp-env, instead, navigate to the plugins/ folder in your local WordPress installation using the terminal and run the following command.
```bash
@@ -54,7 +54,7 @@ After executing this command, you'll find a new directory named `copyright-date-
This command also sets up the basic structure of your block, with `copyright-date-block` as its slug. This slug uniquely identifies your block within WordPress.
- You might have noticed that the command uses the --variant=dynamic flag. This tells create-block you want to scaffold a dynamically rendered block. Later in this tutorial, you will learn about dynamic and static rendering and add static rendering to this block.
+ You might have noticed that the command uses the --variant=dynamic flag. This tells create-block you want to scaffold a dynamically rendered block. Later in this tutorial, you will learn about dynamic and static rendering and add static rendering to this block.
Navigate to the Plugins page in the WordPress admin and confirm that the plugin is active. Then, create a new page or post and ensure you can insert the Copyright Date Block. It should look like this once inserted.
@@ -62,6 +62,7 @@ Navigate to the Plugins page in the WordPress admin and confirm that the plugin

## Reviewing the files
+
Before we begin modifying the scaffolded block, it's important to review the plugin's file structure. Open the plugin folder in your code editor.

@@ -69,7 +70,7 @@ Before we begin modifying the scaffolded block, it's important to review the plu
Next, look at the [File structure of a block](https://developer.wordpress.org/block-editor/getting-started/fundamentals/file-structure-of-a-block/) documentation for a thorough overview of what each file does. Don't worry if this is overwhelming right now. You will learn how to use each file throughout this tutorial.
- Since you scaffolded a dynamic block, you will not see a save.js file. Later in the tutorial, you will add this file to the plugin to enable static rendering, so stay tuned.
+ Since you scaffolded a dynamic block, you will not see a save.js file. Later in the tutorial, you will add this file to the plugin to enable static rendering, so stay tuned.
- Review the block.json documentation for an introduction to this file.
+ Review the block.json documentation for an introduction to this file.
Since this scaffolding process created this file, it requires some updating to suit the needs of the Copyright Date Block.
@@ -130,21 +131,21 @@ After you refresh the Editor, you should now see that the block no longer has th
Next, let's add a few [block supports](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/) so that the user can control the font size and text color of the block.
- You should always try to use native block supports before building custom functionality. This approach provides users with a consistent editing experience across blocks, and your block benefits from Core functionality with only a few lines of code.
+ You should always try to use native block supports before building custom functionality. This approach provides users with a consistent editing experience across blocks, and your block benefits from Core functionality with only a few lines of code.
Update the [`supports`](https://developer.wordpress.org/block-editor/getting-started/fundamentals/block-json/#enable-ui-settings-panels-for-the-block-with-supports) section of the `block.json` file to look like this.
```json
"supports": {
- "color": {
- "background": false,
- "text": true
- },
- "html": false,
- "typography": {
- "fontSize": true
- }
+ "color": {
+ "background": false,
+ "text": true
+ },
+ "html": false,
+ "typography": {
+ "fontSize": true
+ }
},
```
@@ -173,27 +174,27 @@ Your final `block.json` file should look like this:
```json
{
- "$schema": "https://schemas.wp.org/trunk/block.json",
- "apiVersion": 3,
- "name": "create-block/copyright-date-block",
- "version": "0.1.0",
- "title": "Copyright Date Block",
- "category": "widgets",
- "description": "Display your site's copyright date.",
- "example": {},
- "supports": {
- "color": {
- "background": false,
- "text": true
- },
- "html": false,
- "typography": {
- "fontSize": true
- }
- },
- "textdomain": "copyright-date-block",
- "editorScript": "file:./index.js",
- "render": "file:./render.php"
+ "$schema": "https://schemas.wp.org/trunk/block.json",
+ "apiVersion": 3,
+ "name": "create-block/copyright-date-block",
+ "version": "0.1.0",
+ "title": "Copyright Date Block",
+ "category": "widgets",
+ "description": "Display your site's copyright date.",
+ "example": {},
+ "supports": {
+ "color": {
+ "background": false,
+ "text": true
+ },
+ "html": false,
+ "typography": {
+ "fontSize": true
+ }
+ },
+ "textdomain": "copyright-date-block",
+ "editorScript": "file:./index.js",
+ "render": "file:./render.php"
}
```
@@ -209,9 +210,9 @@ Start by looking at the [`registerBlockType`](https://developer.wordpress.org/bl
import Edit from './edit';
import metadata from './block.json';
-registerBlockType( metadata.name, {
- edit: Edit,
-} );
+registerBlockType(metadata.name, {
+ edit: Edit,
+});
```
By default, the object just includes the `edit` property, but you can add many more, including `icon`. While most of these properties are already defined in `block.json`, you need to specify the icon here to use a custom SVG.
@@ -222,24 +223,19 @@ Using the calendar icon from the [Gutenberg Storybook](https://wordpress.github.
```js
const calendarIcon = (
-
+
);
-registerBlockType( metadata.name, {
- icon: calendarIcon,
- edit: Edit
-} );
+registerBlockType(metadata.name, {
+ icon: calendarIcon,
+ edit: Edit,
+});
```
- All block icons should be 24 pixels square. Note the viewBox parameter above.
+ All block icons should be 24 pixels square. Note the viewBox parameter above.
Save the `index.js` file and refresh the Editor. You will now see the calendar icon instead of the default.
@@ -256,14 +252,11 @@ Open the file and see that the `Edit()` function returns a paragraph tag with th
```js
export default function Edit() {
- return (
-
- { __(
- 'Copyright Date Block – hello from the editor!',
- 'copyright-date-block-demo'
- ) }
-
- );
+ return (
+
+ {__('Copyright Date Block – hello from the editor!', 'copyright-date-block-demo')}
+
+ );
}
```
@@ -273,7 +266,7 @@ It looks a bit more complicated than it is.
- [`__()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/) is used for the internationalization of text strings
- Review the block wrapper documentation for an introductory guide on how to ensure the block's markup wrapper has the proper attributes.
+ Review the block wrapper documentation for an introductory guide on how to ensure the block's markup wrapper has the proper attributes.
+ >
+ );
}
```
+
Save the file and refresh the Editor. When selecting the block, you should see the "Testing" message in the Settings Sidebar.

@@ -422,18 +412,16 @@ Then wrap the "Testing" message in the `PanelBody` component and set the `title`
```js
export default function Edit() {
- const currentYear = new Date().getFullYear().toString();
-
- return (
- <>
-
-
- Testing
-
-
-
+ >
+ );
}
```
@@ -454,12 +442,12 @@ Update the top of the `Edit()` function to look like this.
```js
export default function Edit( { attributes, setAttributes } ) {
- const { showStartingYear, startingYear } = attributes;
- ...
+ const { showStartingYear, startingYear } = attributes;
+ ...
```
- To see all the attributes associated with the Copyright Date Block, add console.log( attributes ); at the top of the Edit() function. This can be useful when building and testing a custom block.
+ To see all the attributes associated with the Copyright Date Block, add console.log( attributes ); at the top of the Edit() function. This can be useful when building and testing a custom block.
Now, you can remove the "Testing" message and add a `TextControl`. It should include:
@@ -471,36 +459,31 @@ Now, you can remove the "Testing" message and add a `TextControl`. It should inc
Putting it all together, the `Edit()` function should look like the following.
```js
-export default function Edit( { attributes, setAttributes } ) {
- const { showStartingYear, startingYear } = attributes;
- const currentYear = new Date().getFullYear().toString();
-
- return (
- <>
-
-
-
- setAttributes( { startingYear: value } )
- }
- />
-
-
-
- You may have noticed that the value property has a value of startingYear || ''. The symbol || is called the Logical OR (logical disjunction) operator. This prevents warnings in React when the startingYear is empty. See Controlled and uncontrolled components for details.
+ You may have noticed that the value property has a value of startingYear || ''. The symbol || is called the Logical OR (logical disjunction) operator. This prevents warnings in React when the startingYear is empty. See Controlled and uncontrolled components for details.
Save the file and refresh the Editor. Confirm that a text field now exists in the Settings panel. Add a starting year and confirm that when you update the page, the value is saved.
@@ -520,45 +503,37 @@ You can also update the "Starting year" text input so it's only displayed when `
The `Edit()` function should look like the following.
```js
-export default function Edit( { attributes, setAttributes } ) {
- const { showStartingYear, startingYear } = attributes;
- const currentYear = new Date().getFullYear().toString();
-
- return (
- <>
-
-
-
- setAttributes( {
- showStartingYear: ! showStartingYear,
- } )
- }
- />
- { showStartingYear && (
-
- setAttributes( { startingYear: value } )
- }
- />
- ) }
-
-
-
- When you declare a variable with let, it means that the variable may be reassigned later. Declaring a variable with const means that the variable will never change. You could rewrite this code using const. It's just a matter of personal preference.
+ When you declare a variable with let, it means that the variable may be reassigned later. Declaring a variable with const means that the variable will never change. You could rewrite this code using const. It's just a matter of personal preference.
Next, you just need to update the block content to use the `displayDate` instead of the `currentYear` variable.
@@ -593,51 +568,43 @@ Next, you just need to update the block content to use the `displayDate` instead
The `Edit()` function should look like the following.
```js
-export default function Edit( { attributes, setAttributes } ) {
- const { showStartingYear, startingYear } = attributes;
- const currentYear = new Date().getFullYear().toString();
-
- let displayDate;
-
- if ( showStartingYear && startingYear ) {
- displayDate = startingYear + '–' + currentYear;
- } else {
- displayDate = currentYear;
- }
-
- return (
- <>
-
-
-
- setAttributes( {
- showStartingYear: ! showStartingYear,
- } )
- }
- />
- { showStartingYear && (
-
- setAttributes( { startingYear: value } )
- }
- />
- ) }
-
-
-
+ >
+ );
}
```
@@ -654,21 +621,21 @@ Start by adding a variable called `$display_date` and replicate what you did in
This variable should display the value of the `startingYear` attribute and the `$current_year` variable separated by an em dash, or just the `$current_year` if the `showStartingYear` attribute is `false`.
-
Three variables are exposed in render.php, which you can use to customize the block's output:
-
-
$attributes (array): The block attributes.
-
$content (string): The block default content.
-
$block (WP_Block): The block instance.
-
+
Three variables are exposed in render.php, which you can use to customize the block's output:
>
@@ -741,11 +708,7 @@ Start by adding a new file named `save.js` to the `src/` folder. In this file, a
import { useBlockProps } from '@wordpress/block-editor';
export default function save() {
- return (
-
- { 'Copyright Date Block – hello from the saved content!' }
-
- );
+ return
{'Copyright Date Block – hello from the saved content!'}
;
}
```
@@ -759,14 +722,14 @@ import save from './save';
...
registerBlockType( metadata.name, {
- icon: calendarIcon,
- edit: Edit,
- save
+ icon: calendarIcon,
+ edit: Edit,
+ save
} );
```
- When defining properties of an object, if the property name and the variable name are the same, you can use shorthand property names. This is why the code above uses save instead of save: save.
+ When defining properties of an object, if the property name and the variable name are the same, you can use shorthand property names. This is why the code above uses save instead of save: save.
Save both `save.js` and `index.js` files and refresh the Editor. It should look like this.
@@ -789,7 +752,9 @@ After performing block recovery, open the Code editor and you will see the marku
```html
-
Copyright Date Block – hello from the saved content!
+
+ Copyright Date Block – hello from the saved content!
+
```
@@ -807,21 +772,19 @@ Next, let's update the output of the `save()` function to display the correct co
The result should look like this.
```js
-export default function save( { attributes } ) {
- const { showStartingYear, startingYear } = attributes;
- const currentYear = new Date().getFullYear().toString();
+export default function save({ attributes }) {
+ const { showStartingYear, startingYear } = attributes;
+ const currentYear = new Date().getFullYear().toString();
- let displayDate;
+ let displayDate;
- if ( showStartingYear && startingYear ) {
- displayDate = startingYear + '–' + currentYear;
- } else {
- displayDate = currentYear;
- }
+ if (showStartingYear && startingYear) {
+ displayDate = startingYear + '–' + currentYear;
+ } else {
+ displayDate = currentYear;
+ }
- return (
-
;
}
```
@@ -928,8 +887,8 @@ When the block loads in the Editor, the `currentYear` variable is defined. The f
Now, let's set the `fallbackCurrentYear` attribute to the `currentYear` when the block loads if the attribute is not already set.
```js
-if ( currentYear !== fallbackCurrentYear ) {
- setAttributes( { fallbackCurrentYear: currentYear } );
+if (currentYear !== fallbackCurrentYear) {
+ setAttributes({ fallbackCurrentYear: currentYear });
}
```
@@ -945,20 +904,20 @@ Then wrap the `setAttribute()` code above in a `useEffect` and place this code a
```js
export default function Edit( { attributes, setAttributes } ) {
- const { fallbackCurrentYear, showStartingYear, startingYear } = attributes;
+ const { fallbackCurrentYear, showStartingYear, startingYear } = attributes;
- // Get the current year and make sure it's a string.
- const currentYear = new Date().getFullYear().toString();
+ // Get the current year and make sure it's a string.
+ const currentYear = new Date().getFullYear().toString();
- // When the block loads, set the fallbackCurrentYear attribute to the
- // current year if it's not already set.
- useEffect( () => {
- if ( currentYear !== fallbackCurrentYear ) {
- setAttributes( { fallbackCurrentYear: currentYear } );
- }
- }, [ currentYear, fallbackCurrentYear, setAttributes ] );
+ // When the block loads, set the fallbackCurrentYear attribute to the
+ // current year if it's not already set.
+ useEffect( () => {
+ if ( currentYear !== fallbackCurrentYear ) {
+ setAttributes( { fallbackCurrentYear: currentYear } );
+ }
+ }, [ currentYear, fallbackCurrentYear, setAttributes ] );
- ...
+ ...
```
When the block is initialized in the Editor, the `fallbackCurrentYear` attribute will be immediately set. This value will then be available to the `save()` function, and the correct block content will be displayed without block validation errors.
@@ -969,7 +928,7 @@ You will not get any block validation errors, but the Editor will detect that ch
#### Optimizing render.php
-The final step is to optimize the `render.php` file. If the `currentYear` and the `fallbackCurrentYear` attribute are the same, then there is no need to dynamically create the block content. It is already saved in the database and is available in the `render.php` file via the `$content` variable.
+The final step is to optimize the `render.php` file. If the `currentYear` and the `fallbackCurrentYear` attribute are the same, then there is no need to dynamically create the block content. It is already saved in the database and is available in the `render.php` file via the `$content` variable.
Therefore, update the file to render the generated content if `currentYear` and `fallbackCurrentYear` do not match.
@@ -979,18 +938,18 @@ $current_year = date( "Y" );
// Determine which content to display.
if ( isset( $attributes['fallbackCurrentYear'] ) && $attributes['fallbackCurrentYear'] === $current_year ) {
- // The current year is the same as the fallback, so use the block content saved in the database (by the save.js function).
- $block_content = $content;
+ // The current year is the same as the fallback, so use the block content saved in the database (by the save.js function).
+ $block_content = $content;
} else {
- // The current year is different from the fallback, so render the updated block content.
- if ( ! empty( $attributes['startingYear'] ) && ! empty( $attributes['showStartingYear'] ) ) {
- $display_date = $attributes['startingYear'] . '–' . $current_year;
- } else {
- $display_date = $current_year;
- }
+ // The current year is different from the fallback, so render the updated block content.
+ if ( ! empty( $attributes['startingYear'] ) && ! empty( $attributes['showStartingYear'] ) ) {
+ $display_date = $attributes['startingYear'] . '–' . $current_year;
+ } else {
+ $display_date = $current_year;
+ }
- $block_content = '
';
}
echo wp_kses_post( $block_content );
diff --git a/gutenberg/how-to-guides/README.md b/docs/gutenberg/how-to-guides/README.md
similarity index 100%
rename from gutenberg/how-to-guides/README.md
rename to docs/gutenberg/how-to-guides/README.md
diff --git a/gutenberg/how-to-guides/accessibility.md b/docs/gutenberg/how-to-guides/accessibility.md
similarity index 66%
rename from gutenberg/how-to-guides/accessibility.md
rename to docs/gutenberg/how-to-guides/accessibility.md
index bdf9c97..7837ba9 100644
--- a/gutenberg/how-to-guides/accessibility.md
+++ b/docs/gutenberg/how-to-guides/accessibility.md
@@ -12,6 +12,6 @@ For setting up navigation between different regions, see the [navigateRegions pa
Read more regarding landmark design from W3C:
-- [General Principles of Landmark Design](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/#x4-2-general-principles-of-landmark-design)
-- [ARIA Landmarks Examples](https://www.w3.org/WAI/ARIA/apg/example-index/landmarks/)
-- [HTML5 elements that by default define ARIA landmarks](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/#x4-1-html-sectioning-elements)
+- [General Principles of Landmark Design](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/#x4-2-general-principles-of-landmark-design)
+- [ARIA Landmarks Examples](https://www.w3.org/WAI/ARIA/apg/example-index/landmarks/)
+- [HTML5 elements that by default define ARIA landmarks](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/#x4-1-html-sectioning-elements)
diff --git a/gutenberg/how-to-guides/block-tutorial/README.md b/docs/gutenberg/how-to-guides/block-tutorial/README.md
similarity index 100%
rename from gutenberg/how-to-guides/block-tutorial/README.md
rename to docs/gutenberg/how-to-guides/block-tutorial/README.md
diff --git a/gutenberg/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md b/docs/gutenberg/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md
similarity index 75%
rename from gutenberg/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md
rename to docs/gutenberg/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md
index 85ac956..37b3905 100644
--- a/gutenberg/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md
+++ b/docs/gutenberg/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md
@@ -22,34 +22,30 @@ The `useBlockProps` React hook is used to set and apply properties on the block'
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
-registerBlockType( 'gutenberg-examples/example-02-stylesheets', {
- edit() {
- const greenBackground = {
- backgroundColor: '#090',
- color: '#fff',
- padding: '20px',
- };
-
- const blockProps = useBlockProps( { style: greenBackground } );
-
- return (
-
;
+ },
+});
```
### Build or add dependency
@@ -87,6 +79,7 @@ registerBlockType( 'gutenberg-examples/example-02-stylesheets', {
In order to include the blockEditor as a dependency, make sure to run the build step, or update the asset php file.
Build the scripts and update the asset file which is used to keep track of dependencies and the build version.
+
```bash
npm run build
```
@@ -103,14 +96,14 @@ For example:
```json
{
- "apiVersion": 3,
- "name": "gutenberg-examples/example-02-stylesheets",
- "title": "Example: Stylesheets",
- "icon": "universal-access-alt",
- "category": "layout",
- "editorScript": "file:./block.js",
- "editorStyle": "file:./editor.css",
- "style": "file:./style.css"
+ "apiVersion": 3,
+ "name": "gutenberg-examples/example-02-stylesheets",
+ "title": "Example: Stylesheets",
+ "icon": "universal-access-alt",
+ "category": "layout",
+ "editorScript": "file:./block.js",
+ "editorStyle": "file:./editor.css",
+ "style": "file:./style.css"
}
```
@@ -119,9 +112,9 @@ So in your plugin directory, create an `editor.css` file to load in editor view:
```css
/* green background */
.wp-block-gutenberg-examples-example-02-stylesheets {
- background: #090;
- color: white;
- padding: 20px;
+ background: #090;
+ color: white;
+ padding: 20px;
}
```
@@ -130,9 +123,9 @@ And a `style.css` file to load on the frontend:
```css
/* red background */
.wp-block-gutenberg-examples-example-02-stylesheets {
- background: #900;
- color: white;
- padding: 20px;
+ background: #900;
+ color: white;
+ padding: 20px;
}
```
@@ -147,12 +140,13 @@ Example:
- In `edit.js` you would place `import './editor.scss';`
- In `index.js` you would place `import './style.scss';`
- In `view.js` you would place `import './view.scss';` (interactive block template)
+
**Note:** If you have multiple files to include, you can use standard `wp_enqueue_style` functions like any other plugin or theme. You will want to use the following hooks for the block editor:
-- `enqueue_block_editor_assets` - to load only in editor view
-- `enqueue_block_assets` - loads both on frontend and editor view
+- `enqueue_block_editor_assets` - to load only in editor view
+- `enqueue_block_assets` - loads both on frontend and editor view
## Conclusion
diff --git a/gutenberg/how-to-guides/block-tutorial/creating-dynamic-blocks.md b/docs/gutenberg/how-to-guides/block-tutorial/creating-dynamic-blocks.md
similarity index 66%
rename from gutenberg/how-to-guides/block-tutorial/creating-dynamic-blocks.md
rename to docs/gutenberg/how-to-guides/block-tutorial/creating-dynamic-blocks.md
index 89ef666..baa4085 100644
--- a/gutenberg/how-to-guides/block-tutorial/creating-dynamic-blocks.md
+++ b/docs/gutenberg/how-to-guides/block-tutorial/creating-dynamic-blocks.md
@@ -17,42 +17,34 @@ Block attributes can be used for any content or setting you want to save for tha
The following code example shows how to create a dynamic block that shows only the last post as a link.
-
-
```jsx
import { registerBlockType } from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
import { useBlockProps } from '@wordpress/block-editor';
-registerBlockType( 'gutenberg-examples/example-dynamic', {
- apiVersion: 3,
- title: 'Example: last post',
- icon: 'megaphone',
- category: 'widgets',
-
- edit: () => {
- const blockProps = useBlockProps();
- const posts = useSelect( ( select ) => {
- return select( 'core' ).getEntityRecords( 'postType', 'post' );
- }, [] );
-
- return (
-
+ );
+ },
+});
```
-
-
Because it is a dynamic block it doesn't need to override the default `save` implementation on the client. Instead, it needs a server component. The contents in the front of your site depend on the function called by the `render_callback` property of `register_block_type`.
```php
@@ -63,38 +55,38 @@ Because it is a dynamic block it doesn't need to override the default `save` imp
*/
function gutenberg_examples_dynamic_render_callback( $block_attributes, $content ) {
- $recent_posts = wp_get_recent_posts( array(
- 'numberposts' => 1,
- 'post_status' => 'publish',
- ) );
- if ( count( $recent_posts ) === 0 ) {
- return 'No posts';
- }
- $post = $recent_posts[ 0 ];
- $post_id = $post['ID'];
- return sprintf(
- '%2$s',
- esc_url( get_permalink( $post_id ) ),
- esc_html( get_the_title( $post_id ) )
- );
+ $recent_posts = wp_get_recent_posts( array(
+ 'numberposts' => 1,
+ 'post_status' => 'publish',
+ ) );
+ if ( count( $recent_posts ) === 0 ) {
+ return 'No posts';
+ }
+ $post = $recent_posts[ 0 ];
+ $post_id = $post['ID'];
+ return sprintf(
+ '%2$s',
+ esc_url( get_permalink( $post_id ) ),
+ esc_html( get_the_title( $post_id ) )
+ );
}
function gutenberg_examples_dynamic() {
- // automatically load dependencies and version
- $asset_file = include( plugin_dir_path( __FILE__ ) . 'build/index.asset.php');
-
- wp_register_script(
- 'gutenberg-examples-dynamic',
- plugins_url( 'build/block.js', __FILE__ ),
- $asset_file['dependencies'],
- $asset_file['version']
- );
-
- register_block_type( 'gutenberg-examples/example-dynamic', array(
- 'api_version' => 3,
- 'editor_script' => 'gutenberg-examples-dynamic',
- 'render_callback' => 'gutenberg_examples_dynamic_render_callback'
- ) );
+ // automatically load dependencies and version
+ $asset_file = include( plugin_dir_path( __FILE__ ) . 'build/index.asset.php');
+
+ wp_register_script(
+ 'gutenberg-examples-dynamic',
+ plugins_url( 'build/block.js', __FILE__ ),
+ $asset_file['dependencies'],
+ $asset_file['version']
+ );
+
+ register_block_type( 'gutenberg-examples/example-dynamic', array(
+ 'api_version' => 3,
+ 'editor_script' => 'gutenberg-examples-dynamic',
+ 'render_callback' => 'gutenberg_examples_dynamic_render_callback'
+ ) );
}
add_action( 'init', 'gutenberg_examples_dynamic' );
@@ -103,9 +95,9 @@ add_action( 'init', 'gutenberg_examples_dynamic' );
There are a few things to notice:
-- The `edit` function still shows a representation of the block in the editor's context (this could be very different from the rendered version, it's up to the block's author)
-- The built-in `save` function just returns `null` because the rendering is performed server-side.
-- The server-side rendering is a function taking the block and the block inner content as arguments, and returning the markup (quite similar to shortcodes)
+- The `edit` function still shows a representation of the block in the editor's context (this could be very different from the rendered version, it's up to the block's author)
+- The built-in `save` function just returns `null` because the rendering is performed server-side.
+- The server-side rendering is a function taking the block and the block inner content as arguments, and returning the markup (quite similar to shortcodes)
**Note :** For common customization settings including color, border, spacing customization and more, we will see on the [next chapter](/docs/how-to-guides/block-tutorial/block-supports-in-dynamic-blocks.md) how you can rely on block supports to provide such functionality in an efficient way.
@@ -115,33 +107,29 @@ Gutenberg 2.8 added the [``](/packages/server-side-render/READ
_Server-side render is meant as a fallback; client-side rendering in JavaScript is always preferred (client rendering is faster and allows better editor manipulation)._
-
-
```jsx
import { registerBlockType } from '@wordpress/blocks';
import ServerSideRender from '@wordpress/server-side-render';
import { useBlockProps } from '@wordpress/block-editor';
-registerBlockType( 'gutenberg-examples/example-dynamic', {
- apiVersion: 3,
- title: 'Example: last post',
- icon: 'megaphone',
- category: 'widgets',
-
- edit: function ( props ) {
- const blockProps = useBlockProps();
- return (
-
+ );
+ },
+});
```
-
-
Note that this code uses the `wp-server-side-render` package but not `wp-data`. Make sure to update the dependencies in the PHP code. You can use wp-scripts to automatically build dependencies (see the [block-development-examples repo](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/basic-esnext-a2ab62) for PHP code setup).
diff --git a/gutenberg/how-to-guides/block-tutorial/extending-the-query-loop-block.md b/docs/gutenberg/how-to-guides/block-tutorial/extending-the-query-loop-block.md
similarity index 79%
rename from gutenberg/how-to-guides/block-tutorial/extending-the-query-loop-block.md
rename to docs/gutenberg/how-to-guides/block-tutorial/extending-the-query-loop-block.md
index a59875a..c7a600d 100644
--- a/gutenberg/how-to-guides/block-tutorial/extending-the-query-loop-block.md
+++ b/docs/gutenberg/how-to-guides/block-tutorial/extending-the-query-loop-block.md
@@ -13,6 +13,7 @@ By registering your own block variation with some specific Query Loop block sett
With the block variations API you can provide the default settings that make the most sense for your use-case.
In order to have a Query Loop variation properly working, we'll need to:
+
- Register the block variation for the `core/query` block with some default values
- Define a layout for the block variation
- Use the `namespace` attribute in the `isActive` block variation property
@@ -27,34 +28,34 @@ Your first step would be to create a variation which will be set up in such a wa
const MY_VARIATION_NAME = 'my-plugin/books-list';
registerBlockVariation( 'core/query', {
- name: MY_VARIATION_NAME,
- title: 'Books List',
- description: 'Displays a list of books',
- isActive: ( { namespace, query } ) => {
- return (
- namespace === MY_VARIATION_NAME
- && query.postType === 'book'
- );
- },
- icon: /** An SVG icon can go here*/,
- attributes: {
- namespace: MY_VARIATION_NAME,
- query: {
- perPage: 6,
- pages: 0,
- offset: 0,
- postType: 'book',
- order: 'desc',
- orderBy: 'date',
- author: '',
- search: '',
- exclude: [],
- sticky: '',
- inherit: false,
- },
- },
- scope: [ 'inserter' ],
- }
+ name: MY_VARIATION_NAME,
+ title: 'Books List',
+ description: 'Displays a list of books',
+ isActive: ( { namespace, query } ) => {
+ return (
+ namespace === MY_VARIATION_NAME
+ && query.postType === 'book'
+ );
+ },
+ icon: /** An SVG icon can go here*/,
+ attributes: {
+ namespace: MY_VARIATION_NAME,
+ query: {
+ perPage: 6,
+ pages: 0,
+ offset: 0,
+ postType: 'book',
+ order: 'desc',
+ orderBy: 'date',
+ author: '',
+ search: '',
+ exclude: [],
+ sticky: '',
+ inherit: false,
+ },
+ },
+ scope: [ 'inserter' ],
+ }
);
```
@@ -63,23 +64,23 @@ If that sounds like a lot, don't fret, let's go through each of the properties h
Essentially, you would start with something like this:
```js
-registerBlockVariation( 'core/query', {
- name: 'my-plugin/books-list',
- attributes: {
- query: {
- /** ...more query settings if needed */
- postType: 'book',
- },
- },
-} );
+registerBlockVariation('core/query', {
+ name: 'my-plugin/books-list',
+ attributes: {
+ query: {
+ /** ...more query settings if needed */
+ postType: 'book',
+ },
+ },
+});
```
In this way, the users won't have to choose the custom `postType` from the dropdown, and be already presented with the correct configuration. However, you might ask, how is a user going to find and insert this variation? Good question! To enable this, you should add:
```js
{
- /** ...variation properties */
- scope: [ 'inserter' ],
+ /** ...variation properties */
+ scope: [ 'inserter' ],
}
```
@@ -87,10 +88,10 @@ In this way, your block will show up just like any other block while the user is
```js
{
- /** ...variation properties */
- title: 'Books List',
- description: 'Displays a list of books',
- icon: /* Your svg icon here */,
+ /** ...variation properties */
+ title: 'Books List',
+ description: 'Displays a list of books',
+ icon: /* Your svg icon here */,
}
```
@@ -108,13 +109,13 @@ To circumvent this, there two routes, the first one is to add your default `inne
```js
innerBlocks: [
- [
- 'core/post-template',
- {},
- [ [ 'core/post-title' ], [ 'core/post-excerpt' ] ],
- ],
- [ 'core/query-pagination' ],
- [ 'core/query-no-results' ],
+ [
+ 'core/post-template',
+ {},
+ [ [ 'core/post-title' ], [ 'core/post-excerpt' ] ],
+ ],
+ [ 'core/query-pagination' ],
+ [ 'core/query-no-results' ],
],
```
@@ -140,13 +141,13 @@ We need a way to tell the editor that this block is indeed your specific variati
```js
{
- /** ...variation properties */
- isActive: ( { namespace, query } ) => {
- return (
- namespace === MY_VARIATION_NAME
- && query.postType === 'book'
- );
- },
+ /** ...variation properties */
+ isActive: ( { namespace, query } ) => {
+ return (
+ namespace === MY_VARIATION_NAME
+ && query.postType === 'book'
+ );
+ },
}
```
@@ -156,12 +157,12 @@ That's why the Query Loop block exposes a special attribute called `namespace`.
```js
{
- /** ...variation properties */
- attributes: {
- /** ...variation attributes */
- namespace: 'my-plugin/books-list',
- },
- isActive: [ 'namespace' ],
+ /** ...variation properties */
+ attributes: {
+ /** ...variation attributes */
+ namespace: 'my-plugin/books-list',
+ },
+ isActive: [ 'namespace' ],
}
```
@@ -179,22 +180,22 @@ For this reason, the Query Loop block variations support a property called `allo
As of Gutenberg version 14.2, the following controls are available:
-- `inherit` - Shows the toggle switch for allowing the query to be inherited directly from the template.
-- `postType` - Shows a dropdown of available post types.
-- `order` - Shows a dropdown to select the order of the query.
-- `sticky` - Shows a dropdown to select how to handle sticky posts.
-- `taxQuery` - Shows available taxonomies filters for the currently selected post type.
-- `author` - Shows an input field to filter the query by author.
-- `search` - Shows an input field to filter the query by keywords.
-- `format` - Shows an input field to filter the query by array/collection of [formats](https://developer.wordpress.org/advanced-administration/wordpress/post-formats/#supported-formats).
-- `parents` - Shows an input field to filter the query using parent(s) entity.
+- `inherit` - Shows the toggle switch for allowing the query to be inherited directly from the template.
+- `postType` - Shows a dropdown of available post types.
+- `order` - Shows a dropdown to select the order of the query.
+- `sticky` - Shows a dropdown to select how to handle sticky posts.
+- `taxQuery` - Shows available taxonomies filters for the currently selected post type.
+- `author` - Shows an input field to filter the query by author.
+- `search` - Shows an input field to filter the query by keywords.
+- `format` - Shows an input field to filter the query by array/collection of [formats](https://developer.wordpress.org/advanced-administration/wordpress/post-formats/#supported-formats).
+- `parents` - Shows an input field to filter the query using parent(s) entity.
In our case, the property would look like this:
```js
{
- /** ...variation properties */
- allowedControls: [ 'inherit', 'order', 'taxQuery', 'search' ],
+ /** ...variation properties */
+ allowedControls: [ 'inherit', 'order', 'taxQuery', 'search' ],
}
```
@@ -209,25 +210,25 @@ Because our plugin uses custom attributes that we need to query, we want to add
```jsx
import { InspectorControls } from '@wordpress/block-editor';
-export const withBookQueryControls = ( BlockEdit ) => ( props ) => {
- // We only want to add these controls if it is our variation,
- // so here we can implement a custom logic to check for that, similar
- // to the `isActive` function described above.
- // The following assumes that you wrote a custom `isMyBooksVariation`
- // function to handle that.
- return isMyBooksVariation( props ) ? (
- <>
-
-
- { /** Our custom component */ }
-
- >
- ) : (
-
- );
+export const withBookQueryControls = (BlockEdit) => (props) => {
+ // We only want to add these controls if it is our variation,
+ // so here we can implement a custom logic to check for that, similar
+ // to the `isActive` function described above.
+ // The following assumes that you wrote a custom `isMyBooksVariation`
+ // function to handle that.
+ return isMyBooksVariation(props) ? (
+ <>
+
+
+ {/** Our custom component */}
+
+ >
+ ) : (
+
+ );
};
-addFilter( 'editor.BlockEdit', 'core/query', withBookQueryControls );
+addFilter('editor.BlockEdit', 'core/query', withBookQueryControls);
```
Of course, you'll be responsible for implementing the logic of your control (you might want to take a look at [`@wordpress/components`](https://www.npmjs.com/package/@wordpress/components) to make your controls fit seamlessly within the Gutenberg UI). Any extra parameter you assign within the `query` object inside the blocks attributes can be used to create a custom query according to your needs, with a little extra effort.
@@ -236,16 +237,16 @@ Currently, you'll likely have to implement slightly different paths to make the
```js
{
- /** ...variation properties */
- attributes: {
- /** ...variation attributes */
- query: {
- /** ...more query settings if needed */
- postType: 'book',
- /** Our custom query parameter */
- bookAuthor: 'J. R. R. Tolkien'
- }
- }
+ /** ...variation properties */
+ attributes: {
+ /** ...variation attributes */
+ query: {
+ /** ...more query settings if needed */
+ postType: 'book',
+ /** Our custom query parameter */
+ bookAuthor: 'J. R. R. Tolkien'
+ }
+ }
}
```
@@ -257,12 +258,12 @@ You can hook into that filter and modify your query accordingly. Just make sure
```php
if( 'my-plugin/books-list' === $block[ 'attrs' ][ 'namespace' ] ) {
- add_filter(
- 'query_loop_block_query_vars',
- function( $query ) {
- /** You can read your block custom query parameters here and build your query */
- },
- );
+ add_filter(
+ 'query_loop_block_query_vars',
+ function( $query ) {
+ /** You can read your block custom query parameters here and build your query */
+ },
+ );
}
```
@@ -276,12 +277,12 @@ The Query Loop block fetches its posts to show the preview using the [WordPress
```php
add_filter(
- 'rest_book_query',
- function( $args, $request ) {
- /** We can access our custom parameters from here */
- $book_author = $request->get_param( 'bookAuthor' );
- /** ...your custom query logic */
- }
+ 'rest_book_query',
+ function( $args, $request ) {
+ /** We can access our custom parameters from here */
+ $book_author = $request->get_param( 'bookAuthor' );
+ /** ...your custom query logic */
+ }
);
```
diff --git a/gutenberg/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md b/docs/gutenberg/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md
similarity index 74%
rename from gutenberg/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md
rename to docs/gutenberg/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md
index f935e51..eabffca 100644
--- a/gutenberg/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md
+++ b/docs/gutenberg/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md
@@ -6,34 +6,33 @@ Note: A single block can only contain one `InnerBlocks` component.
Here is the basic InnerBlocks usage.
-
```js
import { registerBlockType } from '@wordpress/blocks';
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
-registerBlockType( 'gutenberg-examples/example-06', {
- // ...
-
- edit: () => {
- const blockProps = useBlockProps();
-
- return (
-
+ );
+ },
+});
```
## Allowed blocks
@@ -43,7 +42,7 @@ Using the `allowedBlocks` prop, you can further limit, in addition to the `allow
```js
const { allowedBlocks } = attributes;
//...
-;
+;
```
If the list of allowed blocks is always the same, prefer the [`allowedBlocks` block setting](#defining-a-children-block-relationship) instead.
@@ -63,7 +62,7 @@ Specifying this prop does not affect the layout of the inner blocks, but results
By default `InnerBlocks` opens a list of permitted blocks via `allowedBlocks` when the block appender is clicked. You can modify the default block and its attributes that are inserted when the initial block appender is clicked by using the `defaultBlock` property. For example:
```js
-
+
```
By default this behavior is disabled until the `directInsert` prop is set to `true`. This allows you to specify conditions for when the default block should or should not be inserted.
@@ -72,27 +71,25 @@ By default this behavior is disabled until the `directInsert` prop is set to `tr
Use the template property to define a set of blocks that prefill the InnerBlocks component when it has no existing content.. You can set attributes on the blocks to define their use. The example below shows a book review template using InnerBlocks component and setting placeholders values to show the block usage.
-
```js
const MY_TEMPLATE = [
- [ 'core/image', {} ],
- [ 'core/heading', { placeholder: 'Book Title' } ],
- [ 'core/paragraph', { placeholder: 'Summary' } ],
+ [ 'core/image', {} ],
+ [ 'core/heading', { placeholder: 'Book Title' } ],
+ [ 'core/paragraph', { placeholder: 'Summary' } ],
];
//...
- edit: () => {
- return (
-
- );
- },
+ edit: () => {
+ return (
+
+ );
+ },
```
-
Use the `templateLock` property to lock down the template. Using `all` locks the template completely so no changes can be made. Using `insert` prevents additional blocks from being inserted, but existing blocks can be reordered. See [templateLock documentation](https://github.com/WordPress/gutenberg/tree/HEAD/packages/block-editor/src/components/inner-blocks/README.md#templatelock) for additional information.
### Post template
@@ -103,11 +100,11 @@ The `InnerBlocks` template is for the component in the single block that you cre
```php
add_action( 'init', function() {
- $post_type_object = get_post_type_object( 'post' );
- $post_type_object->template = array(
- array( 'core/image' ),
- array( 'core/heading' )
- );
+ $post_type_object = get_post_type_object( 'post' );
+ $post_type_object->template = array(
+ array( 'core/image' ),
+ array( 'core/heading' )
+ );
} );
```
@@ -115,9 +112,9 @@ add_action( 'init', function() {
A common pattern for using InnerBlocks is to create a custom block that will only be available if its parent block is inserted. This allows builders to establish a relationship between blocks, while limiting a nested block's discoverability. There are three relationships that builders can use: `parent`, `ancestor` and `allowedBlocks`. The differences are:
-- If you assign a `parent` then you’re stating that the nested block can only be used and inserted as a __direct descendant of the parent__.
-- If you assign an `ancestor` then you’re stating that the nested block can only be used and inserted as a __descendent of the parent__.
-- If you assign the `allowedBlocks` then you’re stating a relationship in the opposite direction, i.e., which blocks can be used and inserted as __direct descendants of this block__.
+- If you assign a `parent` then you’re stating that the nested block can only be used and inserted as a **direct descendant of the parent**.
+- If you assign an `ancestor` then you’re stating that the nested block can only be used and inserted as a **descendent of the parent**.
+- If you assign the `allowedBlocks` then you’re stating a relationship in the opposite direction, i.e., which blocks can be used and inserted as **direct descendants of this block**.
The key difference between `parent` and `ancestor` is `parent` has finer specificity, while an `ancestor` has greater flexibility in its nested hierarchy.
@@ -129,10 +126,10 @@ When defining a direct descendent block, use the `parent` block setting to defin
```json
{
- "title": "Column",
- "name": "core/column",
- "parent": [ "core/columns" ],
- // ...
+ "title": "Column",
+ "name": "core/column",
+ "parent": ["core/columns"]
+ // ...
}
```
@@ -146,10 +143,10 @@ When defining a descendent block, use the `ancestor` block setting. This prevent
```json
{
- "title": "Comment Author Name",
- "name": "core/comment-author-name",
- "ancestor": [ "core/comment-template" ],
- // ...
+ "title": "Comment Author Name",
+ "name": "core/comment-author-name",
+ "ancestor": ["core/comment-template"]
+ // ...
}
```
@@ -163,10 +160,16 @@ When defining a set of possible descendant blocks, use the `allowedBlocks` block
```json
{
- "title": "Navigation",
- "name": "core/navigation",
- "allowedBlocks": [ "core/navigation-link", "core/search", "core/social-links", "core/page-list", "core/spacer" ],
- // ...
+ "title": "Navigation",
+ "name": "core/navigation",
+ "allowedBlocks": [
+ "core/navigation-link",
+ "core/search",
+ "core/social-links",
+ "core/page-list",
+ "core/spacer"
+ ]
+ // ...
}
```
@@ -176,113 +179,102 @@ You can use a react hook called `useInnerBlocksProps` instead of the `InnerBlock
The `useInnerBlocksProps` is exported from the `@wordpress/block-editor` package same as the `InnerBlocks` component itself and supports everything the component does. It also works like the `useBlockProps` hook.
-It is important to note that `useBlockProps` hook must be called *before* `useInnerBlocksProps`, otherwise `useBlockProps` will return empty object.
+It is important to note that `useBlockProps` hook must be called _before_ `useInnerBlocksProps`, otherwise `useBlockProps` will return empty object.
Here is the basic `useInnerBlocksProps` hook usage.
-
-
```js
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
-registerBlockType( 'gutenberg-examples/example-06', {
- // ...
-
- edit: () => {
- const blockProps = useBlockProps();
- const innerBlocksProps = useInnerBlocksProps();
-
- return (
-
+ );
+ },
+});
```
This hook can also pass objects returned from the `useBlockProps` hook to the `useInnerBlocksProps` hook. This reduces the number of elements we need to create.
-
-
```js
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
-registerBlockType( 'gutenberg-examples/example-06', {
- // ...
+registerBlockType('gutenberg-examples/example-06', {
+ // ...
- edit: () => {
- const blockProps = useBlockProps();
- const innerBlocksProps = useInnerBlocksProps( blockProps );
+ edit: () => {
+ const blockProps = useBlockProps();
+ const innerBlocksProps = useInnerBlocksProps(blockProps);
- return (
-
- );
- },
+ return ;
+ },
- save: () => {
- const blockProps = useBlockProps.save();
- const innerBlocksProps = useInnerBlocksProps.save( blockProps );
+ save: () => {
+ const blockProps = useBlockProps.save();
+ const innerBlocksProps = useInnerBlocksProps.save(blockProps);
- return (
-
- );
- },
-} );
+ return ;
+ },
+});
```
-
The above code will render to the following markup in the editor:
```html
-
+
```
Another benefit to using the hook approach is using the returned value, which is just an object, and deconstruct to get the react children from the object. This property contains the actual child inner blocks thus we can place elements on the same level as our inner blocks.
-
```js
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
registerBlockType( 'gutenberg-examples/example-06', {
- // ...
+ // ...
- edit: () => {
- const blockProps = useBlockProps();
- const { children, ...innerBlocksProps } = useInnerBlocksProps( blockProps );
+ edit: () => {
+ const blockProps = useBlockProps();
+ const { children, ...innerBlocksProps } = useInnerBlocksProps( blockProps );
- return (
-
- { children }
-
-
- );
- },
+ return (
+
+ { children }
+
+
+ );
+ },
- // ...
+ // ...
} );
```
-
```html
-
-
+
+
```
diff --git a/gutenberg/how-to-guides/curating-the-editor-experience/README.md b/docs/gutenberg/how-to-guides/curating-the-editor-experience/README.md
similarity index 97%
rename from gutenberg/how-to-guides/curating-the-editor-experience/README.md
rename to docs/gutenberg/how-to-guides/curating-the-editor-experience/README.md
index 3b348d6..df7dc21 100644
--- a/gutenberg/how-to-guides/curating-the-editor-experience/README.md
+++ b/docs/gutenberg/how-to-guides/curating-the-editor-experience/README.md
@@ -2,7 +2,7 @@
Curating the editing experience in WordPress is important because it allows you to streamline the editing process, ensuring consistency and alignment with the site's style and branding guidelines. It also makes it easier for users to create and manage content effectively without accidental modifications or layout changes. This leads to a more efficient and personalized experience.
-The purpose of this guide is to offer various ways you can lock down and curate the experience of using WordPress, especially with the introduction of more design tools and the Site Editor.
+The purpose of this guide is to offer various ways you can lock down and curate the experience of using WordPress, especially with the introduction of more design tools and the Site Editor.
In this section, you will learn:
@@ -14,9 +14,9 @@ In this section, you will learn:
## Combining approaches
-Remember that the approaches provided in the documentation above can be combined as you see fit. For example, you can provide custom patterns to use when creating a new page while also limiting the amount of customization that can be done to aspects of them, like only allowing specific preset colors to be used for the background of a Cover block or locking down what blocks can be deleted.
+Remember that the approaches provided in the documentation above can be combined as you see fit. For example, you can provide custom patterns to use when creating a new page while also limiting the amount of customization that can be done to aspects of them, like only allowing specific preset colors to be used for the background of a Cover block or locking down what blocks can be deleted.
-When considering the approaches to take, think about the specific ways you might want to both open up the experience and curate it.
+When considering the approaches to take, think about the specific ways you might want to both open up the experience and curate it.
## Additional resources
diff --git a/gutenberg/how-to-guides/curating-the-editor-experience/block-locking.md b/docs/gutenberg/how-to-guides/curating-the-editor-experience/block-locking.md
similarity index 89%
rename from gutenberg/how-to-guides/curating-the-editor-experience/block-locking.md
rename to docs/gutenberg/how-to-guides/curating-the-editor-experience/block-locking.md
index 83f26ea..a395f9a 100644
--- a/gutenberg/how-to-guides/curating-the-editor-experience/block-locking.md
+++ b/docs/gutenberg/how-to-guides/curating-the-editor-experience/block-locking.md
@@ -12,7 +12,7 @@ Keep in mind that you can apply locking options to blocks nested inside of a con
## Lock the ability to edit certain blocks
-Alongside the ability to lock moving or removing blocks, the [Navigation Block](https://github.com/WordPress/gutenberg/pull/44739) and [Reusable block](https://github.com/WordPress/gutenberg/pull/39950) have an additional capability: lock the ability to edit the contents of the block. This locks the ability to make changes to any blocks inside of either block type.
+Alongside the ability to lock moving or removing blocks, the [Navigation Block](https://github.com/WordPress/gutenberg/pull/44739) and [Reusable block](https://github.com/WordPress/gutenberg/pull/39950) have an additional capability: lock the ability to edit the contents of the block. This locks the ability to make changes to any blocks inside of either block type.
## Apply block locking to patterns or templates
@@ -20,39 +20,39 @@ When building patterns or templates, theme authors can use these same UI tools t
## Apply content-only editing in patterns or templates
-This functionality was introduced in WordPress 6.1. In contrast to block locking, which disables the ability to move or remove blocks, content-only editing is both designed for use at the pattern or template level and hides all design tools, while still allowing for the ability to edit the content of the blocks. This provides a great way to simplify the interface for users and preserve a design. When this option is added, the following changes occur:
+This functionality was introduced in WordPress 6.1. In contrast to block locking, which disables the ability to move or remove blocks, content-only editing is both designed for use at the pattern or template level and hides all design tools, while still allowing for the ability to edit the content of the blocks. This provides a great way to simplify the interface for users and preserve a design. When this option is added, the following changes occur:
- Non-content child blocks (containers, spacers, columns, etc) are hidden from list view, un-clickable on the canvas, and entirely un-editable.
-- The Inspector will display a list of all child 'content' blocks. Clicking a block in this list reveals its settings panel.
+- The Inspector will display a list of all child 'content' blocks. Clicking a block in this list reveals its settings panel.
- The main List View only shows content blocks, all at the same level regardless of actual nesting.
- Children blocks within the overall content locked container are automatically move / remove locked.
- Additional child blocks cannot be inserted, further preserving the design and layout.
- There is a link in the block toolbar to ‘Modify’ that a user can toggle on/off to have access to the broader design tools. Currently, it's not possibly to programmatically remove this option.
-This option can be applied to Columns, Cover, and Group blocks as well as third-party blocks that have the templateLock attribute in its block.json. To adopt this functionality, you need to use `"templateLock":"contentOnly"`. [Here's an example of a pattern](https://gist.github.com/annezazu/d62acd2514cea558be6cea97fe28ff3c) with this functionality in place. For more information, please [review the relevant documentation](/docs/reference-guides/block-api/block-templates.md#locking).
+This option can be applied to Columns, Cover, and Group blocks as well as third-party blocks that have the templateLock attribute in its block.json. To adopt this functionality, you need to use `"templateLock":"contentOnly"`. [Here's an example of a pattern](https://gist.github.com/annezazu/d62acd2514cea558be6cea97fe28ff3c) with this functionality in place. For more information, please [review the relevant documentation](/docs/reference-guides/block-api/block-templates.md#locking).
-Note: There is no UI in place to manage content locking and it must be managed at the code level.
+Note: There is no UI in place to manage content locking and it must be managed at the code level.
## Change permissions to control locking ability
-Agencies and plugin authors can offer an even more curated experience by limiting which users have [permission to lock and unlock blocks](https://make.wordpress.org/core/2022/05/05/block-locking-settings-in-wordpress-6-0/). By default, anyone who is an administrator will have access to lock and unlock blocks.
+Agencies and plugin authors can offer an even more curated experience by limiting which users have [permission to lock and unlock blocks](https://make.wordpress.org/core/2022/05/05/block-locking-settings-in-wordpress-6-0/). By default, anyone who is an administrator will have access to lock and unlock blocks.
-Developers can add a filter to the [block_editor_settings_all](https://developer.wordpress.org/reference/hooks/block_editor_settings_all/) hook to configure permissions around locking blocks. The hook passes two parameters to the callback function:
+Developers can add a filter to the [block_editor_settings_all](https://developer.wordpress.org/reference/hooks/block_editor_settings_all/) hook to configure permissions around locking blocks. The hook passes two parameters to the callback function:
- `$settings` - An array of configurable settings for the Editor.
- `$context` - An instance of WP_Block_Editor_Context, an object that contains information about the current Editor.
-Specifically, developers can alter the `$settings['canLockBlocks']` value by setting it to `true` or `false`, typically by running through one or more conditional checks.
+Specifically, developers can alter the `$settings['canLockBlocks']` value by setting it to `true` or `false`, typically by running through one or more conditional checks.
The following example disables block locking permissions for all users when editing a page:
```php
add_filter( 'block_editor_settings_all', function( $settings, $context ) {
- if ( $context->post && 'page' === $context->post->post_type ) {
- $settings['canLockBlocks'] = false;
- }
+ if ( $context->post && 'page' === $context->post->post_type ) {
+ $settings['canLockBlocks'] = false;
+ }
- return $settings;
+ return $settings;
}, 10, 2 );
```
@@ -60,10 +60,10 @@ Another common use case may be to only allow users who can edit the visual desig
```php
add_filter( 'block_editor_settings_all', function( $settings ) {
- $settings['canLockBlocks'] = current_user_can( 'edit_theme_options' );
+ $settings['canLockBlocks'] = current_user_can( 'edit_theme_options' );
- return $settings;
+ return $settings;
} );
```
-Developers may use any type of conditional check to determine who can lock/unlock blocks. This is merely a small sampling of what is possible via the filter hook.
\ No newline at end of file
+Developers may use any type of conditional check to determine who can lock/unlock blocks. This is merely a small sampling of what is possible via the filter hook.
diff --git a/gutenberg/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md b/docs/gutenberg/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md
similarity index 86%
rename from gutenberg/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md
rename to docs/gutenberg/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md
index 81d6192..026ff50 100644
--- a/gutenberg/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md
+++ b/docs/gutenberg/how-to-guides/curating-the-editor-experience/disable-editor-functionality.md
@@ -25,14 +25,14 @@ You can also use [block filters](/docs/reference-guides/filters/block-filters.md
```php
function example_modify_heading_levels_globally( $args, $block_type ) {
- if ( 'core/heading' !== $block_type ) {
- return $args;
- }
+ if ( 'core/heading' !== $block_type ) {
+ return $args;
+ }
- // Remove H1, H2, and H6.
- $args['attributes']['levelOptions']['default'] = [ 3, 4, 5 ];
+ // Remove H1, H2, and H6.
+ $args['attributes']['levelOptions']['default'] = [ 3, 4, 5 ];
- return $args;
+ return $args;
}
add_filter( 'register_block_type_args', 'example_modify_heading_levels_globally', 10, 2 );
```
@@ -43,7 +43,7 @@ To fully remove patterns bundled with WordPress core from being accessed in the
```php
function example_theme_support() {
- remove_theme_support( 'core-block-patterns' );
+ remove_theme_support( 'core-block-patterns' );
}
add_action( 'after_setup_theme', 'example_theme_support' );
```
@@ -55,8 +55,8 @@ Some Core blocks are actually [block variations](https://developer.wordpress.org
Block variations are registered using JavaScript and need to be disabled with JavaScript. The code below will disable the Row variation.
```js
-wp.domReady( () => {
- wp.blocks.unregisterBlockVariation( 'core/group', 'group-row' );
+wp.domReady(() => {
+ wp.blocks.unregisterBlockVariation('core/group', 'group-row');
});
```
@@ -64,13 +64,13 @@ Assuming the code was placed in a `disable-variations.js` file located in the ro
```php
function example_disable_variations_script() {
- wp_enqueue_script(
- 'example-disable-variations-script',
- get_template_directory_uri() . '/disable-variations.js',
- array( 'wp-dom-ready' ),
- wp_get_theme()->get( 'Version' ),
- true
- );
+ wp_enqueue_script(
+ 'example-disable-variations-script',
+ get_template_directory_uri() . '/disable-variations.js',
+ array( 'wp-dom-ready' ),
+ wp_get_theme()->get( 'Version' ),
+ true
+ );
}
add_action( 'enqueue_block_editor_assets', 'example_disable_variations_script' );
```
@@ -84,8 +84,8 @@ Unlike block variations, you can register styles in either JavaScript or PHP. If
So, you would use the following code to disable the "Rounded" block style for the Image block.
```js
-wp.domReady( () => {
- wp.blocks.unregisterBlockStyle( 'core/image', 'rounded' );
+wp.domReady(() => {
+ wp.blocks.unregisterBlockStyle('core/image', 'rounded');
});
```
@@ -99,7 +99,7 @@ The Code Editor allows you to view the underlying block markup for a page or pos
function example_restrict_code_editor_access( $settings, $context ) {
$settings[ 'codeEditingEnabled' ] = false;
- return $settings;
+ return $settings;
}
add_filter( 'block_editor_settings_all', 'example_restrict_code_editor_access', 10, 2 );
```
@@ -113,12 +113,12 @@ Blocks that support [RichText](https://developer.wordpress.org/block-editor/refe
Formatting options need to be disabled with JavaScript using `unregisterFormatType`. The code below will globally disable the Inline Image, Language, Keyboard Input, Subscript, and Superscript options.
```js
-wp.domReady( () => {
- wp.richText.unregisterFormatType( 'core/image' );
- wp.richText.unregisterFormatType( 'core/language' );
- wp.richText.unregisterFormatType( 'core/keyboard' );
- wp.richText.unregisterFormatType( 'core/subscript' );
- wp.richText.unregisterFormatType( 'core/superscript' );
+wp.domReady(() => {
+ wp.richText.unregisterFormatType('core/image');
+ wp.richText.unregisterFormatType('core/language');
+ wp.richText.unregisterFormatType('core/keyboard');
+ wp.richText.unregisterFormatType('core/subscript');
+ wp.richText.unregisterFormatType('core/superscript');
});
```
diff --git a/gutenberg/how-to-guides/curating-the-editor-experience/filters-and-hooks.md b/docs/gutenberg/how-to-guides/curating-the-editor-experience/filters-and-hooks.md
similarity index 84%
rename from gutenberg/how-to-guides/curating-the-editor-experience/filters-and-hooks.md
rename to docs/gutenberg/how-to-guides/curating-the-editor-experience/filters-and-hooks.md
index b28fdf7..9b93628 100644
--- a/gutenberg/how-to-guides/curating-the-editor-experience/filters-and-hooks.md
+++ b/docs/gutenberg/how-to-guides/curating-the-editor-experience/filters-and-hooks.md
@@ -4,7 +4,7 @@ The Editor provides numerous filters and hooks that allow you to modify the edit
## Editor settings
-One of the most common ways to modify the Editor is through the [`block_editor_settings_all`](https://developer.wordpress.org/reference/hooks/block_editor_settings_all/) PHP filter, which is applied before settings are sent to the initialized Editor.
+One of the most common ways to modify the Editor is through the [`block_editor_settings_all`](https://developer.wordpress.org/reference/hooks/block_editor_settings_all/) PHP filter, which is applied before settings are sent to the initialized Editor.
The `block_editor_settings_all` hook passes two parameters to the callback function:
@@ -17,18 +17,18 @@ The following example disables the Code Editor for users who cannot activate plu
add_filter( 'block_editor_settings_all', 'example_restrict_code_editor' );
function example_restrict_code_editor( $settings ) {
- $can_active_plugins = current_user_can( 'activate_plugins' );
+ $can_active_plugins = current_user_can( 'activate_plugins' );
- // Disable the Code Editor for users that cannot activate plugins (Administrators).
- if ( ! $can_active_plugins ) {
- $settings[ 'codeEditingEnabled' ] = false;
- }
+ // Disable the Code Editor for users that cannot activate plugins (Administrators).
+ if ( ! $can_active_plugins ) {
+ $settings[ 'codeEditingEnabled' ] = false;
+ }
- return $settings;
+ return $settings;
}
```
-For more examples, check out the [Editor Hooks](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/) documentation that includes the following use cases:
+For more examples, check out the [Editor Hooks](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/) documentation that includes the following use cases:
- [Set a default image size](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/#set-a-default-image-size)
- [Disable Openverse](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/#disable-openverse)
@@ -39,7 +39,7 @@ For more examples, check out the [Editor Hooks](https://developer.wordpress.org/
The theme.json file is a great way to control interface options, but it only allows for global or block-level modifications, which can be limiting in some scenarios.
-For instance, in the previous section, color and typography controls were disabled globally using theme.json. But let's say you want to enable color settings for users who are Administrators.
+For instance, in the previous section, color and typography controls were disabled globally using theme.json. But let's say you want to enable color settings for users who are Administrators.
To provide more flexibility, WordPress 6.1 introduced server-side filters allowing you to customize theme.json data at four different data layers.
@@ -72,13 +72,12 @@ function example_filter_theme_json_data_theme( $theme_json ){
);
}
- return $theme_json->update_with( $new_data );
+ return $theme_json->update_with( $new_data );
}
add_filter( 'wp_theme_json_data_theme', 'example_filter_theme_json_data_theme' );
```
-The filter receives an instance of the `WP_Theme_JSON_Data class` with the data for the respective layer. Then, you pass new data in a valid theme.json-like structure to the `update_with( $new_data )` method. A theme.json version number is required in `$new_data`.
-
+The filter receives an instance of the `WP_Theme_JSON_Data class` with the data for the respective layer. Then, you pass new data in a valid theme.json-like structure to the `update_with( $new_data )` method. A theme.json version number is required in `$new_data`.
## Client-side (Editor) filters
@@ -93,14 +92,14 @@ import { addFilter } from '@wordpress/hooks';
* Limit the Column block's spacing options to pixels.
*/
addFilter(
- 'blockEditor.useSetting.before',
- 'example/useSetting.before',
- ( settingValue, settingName, clientId, blockName ) => {
- if ( blockName === 'core/column' && settingName === 'spacing.units' ) {
- return [ 'px' ];
- }
- return settingValue;
- }
+ 'blockEditor.useSetting.before',
+ 'example/useSetting.before',
+ (settingValue, settingName, clientId, blockName) => {
+ if (blockName === 'core/column' && settingName === 'spacing.units') {
+ return ['px'];
+ }
+ return settingValue;
+ }
);
```
@@ -111,28 +110,30 @@ However, the `blockEditor.useSetting.before` filter is unique because it allows
In the following example, text color controls are disabled for the Heading block whenever the block is placed inside of a Media & Text block.
```js
-import { select } from '@wordpress/data';
+import { select } from '@wordpress/data';
import { addFilter } from '@wordpress/hooks';
/**
* Disable text color controls on Heading blocks when placed inside of Media & Text blocks.
*/
addFilter(
- 'blockEditor.useSetting.before',
- 'example/useSetting.before',
- ( settingValue, settingName, clientId, blockName ) => {
- if ( blockName === 'core/heading' ) {
- const { getBlockParents, getBlockName } = select( 'core/block-editor' );
- const blockParents = getBlockParents( clientId, true );
- const inMediaText = blockParents.some( ( ancestorId ) => getBlockName( ancestorId ) === 'core/media-text' );
-
- if ( inMediaText && settingName === 'color.text' ) {
- return false;
- }
- }
-
- return settingValue;
- }
+ 'blockEditor.useSetting.before',
+ 'example/useSetting.before',
+ (settingValue, settingName, clientId, blockName) => {
+ if (blockName === 'core/heading') {
+ const { getBlockParents, getBlockName } = select('core/block-editor');
+ const blockParents = getBlockParents(clientId, true);
+ const inMediaText = blockParents.some(
+ (ancestorId) => getBlockName(ancestorId) === 'core/media-text'
+ );
+
+ if (inMediaText && settingName === 'color.text') {
+ return false;
+ }
+ }
+
+ return settingValue;
+ }
);
```
@@ -140,13 +141,13 @@ addFilter(
Beyond curating the Editor itself, there are many ways that you can modify individual blocks. Perhaps you want to disable particular block supports like background color or define which settings should be displayed by default on specific blocks.
-One of the most commonly used filters is [`block_type_metadata`](https://developer.wordpress.org/reference/hooks/block_type_metadata/). It allows you to filter the raw metadata loaded from a block's `block.json` file when a block type is registered on the server with PHP.
+One of the most commonly used filters is [`block_type_metadata`](https://developer.wordpress.org/reference/hooks/block_type_metadata/). It allows you to filter the raw metadata loaded from a block's `block.json` file when a block type is registered on the server with PHP.
The filter takes one parameter:
- `$metadata` (`array`) – metadata loaded from `block.json` for registering a block type.
-The `$metadata` array contains everything you might want to know about a block, from its description and [attributes](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/) to block [supports](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/).
+The `$metadata` array contains everything you might want to know about a block, from its description and [attributes](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/) to block [supports](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/).
In the following example, background color and gradient support are disabled for Heading blocks.
@@ -176,4 +177,4 @@ You can learn more about the available block filters in the [Block Filters](http
## Additional resources
- [How to modify theme.json data using server-side filters](https://developer.wordpress.org/news/2023/07/05/how-to-modify-theme-json-data-using-server-side-filters/) (WordPress Developer Blog)
-- [Curating the Editor experience with client-side filters](https://developer.wordpress.org/news/2023/05/24/curating-the-editor-experience-with-client-side-filters/) (WordPress Developer Blog)
\ No newline at end of file
+- [Curating the Editor experience with client-side filters](https://developer.wordpress.org/news/2023/05/24/curating-the-editor-experience-with-client-side-filters/) (WordPress Developer Blog)
diff --git a/gutenberg/how-to-guides/curating-the-editor-experience/patterns.md b/docs/gutenberg/how-to-guides/curating-the-editor-experience/patterns.md
similarity index 93%
rename from gutenberg/how-to-guides/curating-the-editor-experience/patterns.md
rename to docs/gutenberg/how-to-guides/curating-the-editor-experience/patterns.md
index abb7d13..be244ca 100644
--- a/gutenberg/how-to-guides/curating-the-editor-experience/patterns.md
+++ b/docs/gutenberg/how-to-guides/curating-the-editor-experience/patterns.md
@@ -1,12 +1,12 @@
# Patterns
-Block [patterns](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-patterns/) are one of the best ways to provide users with unique and curated editing experiences.
+Block [patterns](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-patterns/) are one of the best ways to provide users with unique and curated editing experiences.
## Prioritize starter patterns for any post type
-When a user creates new content, regardless of post type, they are met with an empty canvas. However, that experience can be improved thanks to the option to have patterns from a specific type prioritized upon creation of a new piece of content. The modal appears each time the user creates a new item when there are patterns on their website that declare support for the `core/post-content` block types. By default, WordPress does not include any of these patterns, so the modal will not appear without at least two of these post content patterns being added.
+When a user creates new content, regardless of post type, they are met with an empty canvas. However, that experience can be improved thanks to the option to have patterns from a specific type prioritized upon creation of a new piece of content. The modal appears each time the user creates a new item when there are patterns on their website that declare support for the `core/post-content` block types. By default, WordPress does not include any of these patterns, so the modal will not appear without at least two of these post content patterns being added.
-To opt into this, include `core/post-content` in the Block Types for your pattern. From there, you can control which post types the pattern should show up for via the Post Types option. Here's an example of a pattern that would appear when creating a new post.
+To opt into this, include `core/post-content` in the Block Types for your pattern. From there, you can control which post types the pattern should show up for via the Post Types option. Here's an example of a pattern that would appear when creating a new post.
```php
```
-Read more about this functionality in the [Page creation patterns in WordPress 6.0 dev note](https://make.wordpress.org/core/2022/05/03/page-creation-patterns-in-wordpress-6-0/) and [note that WordPress 6.1 brought this functionality to all post types](https://make.wordpress.org/core/2022/10/10/miscellaneous-editor-changes-for-wordpress-6-1/#start-content-patterns-for-all-post-types).
+Read more about this functionality in the [Page creation patterns in WordPress 6.0 dev note](https://make.wordpress.org/core/2022/05/03/page-creation-patterns-in-wordpress-6-0/) and [note that WordPress 6.1 brought this functionality to all post types](https://make.wordpress.org/core/2022/10/10/miscellaneous-editor-changes-for-wordpress-6-1/#start-content-patterns-for-all-post-types).
## Prioritize starter patterns for template creation
-In the same way patterns can be prioritized for new posts or pages, the same experience can be added to the template creation process. When patterns declare support for the 'templateTypes' property, the patterns will appear anytime a template that matches the designation is created, along with the options to start from a blank state or use the current fallback of the template. By default, WordPress does not include any of these patterns.
+In the same way patterns can be prioritized for new posts or pages, the same experience can be added to the template creation process. When patterns declare support for the 'templateTypes' property, the patterns will appear anytime a template that matches the designation is created, along with the options to start from a blank state or use the current fallback of the template. By default, WordPress does not include any of these patterns.
To opt into this, a pattern needs to specify a property called `templateTypes`, which is an array containing the templates where the patterns can be used as the full content. Here's an example of a pattern that would appear when creating a 404 template:
@@ -71,15 +71,15 @@ Read more about this functionality in the [Patterns on the create a new template
## Lock patterns
-As mentioned in the prior section on Locking APIs, aspects of patterns themselves can be locked so that the important aspects of the design can be preserved. [Here’s an example of a pattern](https://gist.github.com/annezazu/acee30f8b6e8995e1b1a52796e6ef805) with various blocks locked in different ways. You can build these patterns in the editor itself, including adding locking options, before [following the documentation to register them](/docs/reference-guides/block-api/block-patterns.md).
+As mentioned in the prior section on Locking APIs, aspects of patterns themselves can be locked so that the important aspects of the design can be preserved. [Here’s an example of a pattern](https://gist.github.com/annezazu/acee30f8b6e8995e1b1a52796e6ef805) with various blocks locked in different ways. You can build these patterns in the editor itself, including adding locking options, before [following the documentation to register them](/docs/reference-guides/block-api/block-patterns.md).
## Prioritize specific patterns from the Pattern Directory
-With WordPress 6.0 themes can register patterns from [Pattern Directory](https://wordpress.org/patterns/) through theme.json. To accomplish this, themes should use the new patterns top level key in theme.json. Within this field, themes can list patterns to register from the Pattern Directory. The patterns field is an array of pattern slugs from the Pattern Directory. Pattern slugs can be extracted by the url in a single pattern view at the Pattern Directory. Example: This url https://wordpress.org/patterns/pattern/partner-logos the slug is partner-logos.
+With WordPress 6.0 themes can register patterns from [Pattern Directory](https://wordpress.org/patterns/) through theme.json. To accomplish this, themes should use the new patterns top level key in theme.json. Within this field, themes can list patterns to register from the Pattern Directory. The patterns field is an array of pattern slugs from the Pattern Directory. Pattern slugs can be extracted by the url in a single pattern view at the Pattern Directory. Example: This url the slug is partner-logos.
```json
{
- "patterns": [ "short-text-surrounded-by-round-images", "partner-logos" ]
+ "patterns": ["short-text-surrounded-by-round-images", "partner-logos"]
}
```
@@ -87,4 +87,4 @@ The content creator will then find the respective Pattern in the inserter “Pat
## Additional resources
-- [Using template patterns to build multiple homepage designs](https://developer.wordpress.org/news/2023/04/13/using-template-patterns-to-build-multiple-homepage-designs/) (WordPress Developer Blog)
\ No newline at end of file
+- [Using template patterns to build multiple homepage designs](https://developer.wordpress.org/news/2023/04/13/using-template-patterns-to-build-multiple-homepage-designs/) (WordPress Developer Blog)
diff --git a/docs/gutenberg/how-to-guides/curating-the-editor-experience/theme-json.md b/docs/gutenberg/how-to-guides/curating-the-editor-experience/theme-json.md
new file mode 100644
index 0000000..f6237b4
--- /dev/null
+++ b/docs/gutenberg/how-to-guides/curating-the-editor-experience/theme-json.md
@@ -0,0 +1,205 @@
+# theme.json
+
+A theme's theme.json file is one of the best ways to curate the Editor experience and will likely be the first tool you use before reaching for more sophisticated solutions.
+
+## Providing default controls/options
+
+Since theme.json acts as a configuration tool, there are numerous ways to define at a granular level what options are available. This section will use duotone as an example since it showcases a feature that cuts across a few blocks and allows for varying levels of access.
+
+_Duotone with Core options and customization available for each image related block:_
+
+```json
+{
+ "version": 3,
+ "settings": {
+ "color": {
+ "customDuotone": true,
+ "duotone": []
+ }
+ }
+}
+```
+
+_Duotone with theme defined color options, Core options, and customization available for each image related block:_
+
+```json
+{
+ "version": 3,
+ "settings": {
+ "color": {
+ "duotone": [
+ {
+ "colors": ["#000000", "#ffffff"],
+ "slug": "foreground-and-background",
+ "name": "Foreground and background"
+ },
+ {
+ "colors": ["#000000", "#ff0200"],
+ "slug": "foreground-and-secondary",
+ "name": "Foreground and secondary"
+ },
+ {
+ "colors": ["#000000", "#7f5dee"],
+ "slug": "foreground-and-tertiary",
+ "name": "Foreground and tertiary"
+ }
+ ]
+ }
+ }
+}
+```
+
+_Duotone with defined default options and all customization available for the Post Featured Image block:_
+
+```json
+{
+ "version": 3,
+ "settings": {
+ "color": {
+ "custom": true,
+ "customDuotone": true
+ },
+ "blocks": {
+ "core/post-featured-image": {
+ "color": {
+ "duotone": [
+ {
+ "colors": ["#282828", "#ff5837"],
+ "slug": "black-and-orange",
+ "name": "Black and Orange"
+ },
+ {
+ "colors": ["#282828", "#0288d1"],
+ "slug": "black-and-blue",
+ "name": "Black and Blue"
+ }
+ ],
+ "customDuotone": true,
+ "custom": true
+ }
+ }
+ }
+ }
+}
+```
+
+_Duotone with only defined default options and core options available for the Post Featured Image block (no customization):_
+
+```json
+{
+ "version": 3,
+ "settings": {
+ "color": {
+ "custom": true,
+ "customDuotone": true
+ },
+ "blocks": {
+ "core/post-featured-image": {
+ "color": {
+ "duotone": [
+ {
+ "colors": ["#282828", "#ff5837"],
+ "slug": "black-and-orange",
+ "name": "Black and Orange"
+ },
+ {
+ "colors": ["#282828", "#0288d1"],
+ "slug": "black-and-blue",
+ "name": "Black and Blue"
+ }
+ ],
+ "customDuotone": false,
+ "custom": false
+ }
+ }
+ }
+ }
+}
+```
+
+## Limiting interface options with theme.json
+
+### Limit options on a per-block basis
+
+Beyond defining default values, using theme.json allows you to also remove options entirely and instead rely on what the theme has set in place. Below is a visual showing two extremes with the same paragraph block:
+
+
+
+Continuing the examples with duotone, this means you could allow full access to all Duotone functionality for Image blocks and only limit the Post Featured Image block like so:
+
+```json
+{
+ "version": 3,
+ "settings": {
+ "color": {
+ "custom": true,
+ "customDuotone": true
+ },
+ "blocks": {
+ "core/image": {
+ "color": {
+ "duotone": [],
+ "customDuotone": true,
+ "custom": true
+ }
+ },
+ "core/post-featured-image": {
+ "color": {
+ "duotone": [],
+ "customDuotone": false,
+ "custom": false
+ }
+ }
+ }
+ }
+}
+```
+
+You can read more about how best to [turn on/off options with theme.json here](/docs/how-to-guides/themes/global-settings-and-styles.md).
+
+### Disable inherit default layout
+
+To disable the “Inherit default layout” setting for container blocks like the Group block, remove the following section:
+
+```json
+"layout": {
+ "contentSize": null,
+ "wideSize": null
+},
+```
+
+### Limit options globally
+
+When using theme.json in a block or classic theme, these settings will stop the default color and typography controls from being enabled globally, greatly limiting what’s possible:
+
+```json
+{
+ "version": 3,
+ "settings": {
+ "layout": {
+ "contentSize": "750px"
+ },
+ "color": {
+ "background": false,
+ "custom": false,
+ "customDuotone": false,
+ "customGradient": false,
+ "defaultGradients": false,
+ "defaultPalette": false,
+ "text": false
+ },
+ "typography": {
+ "customFontSize": false,
+ "dropCap": false,
+ "fontStyle": false,
+ "fontWeight": false,
+ "letterSpacing": false,
+ "lineHeight": false,
+ "textDecoration": false,
+ "textTransform": false
+ }
+ }
+}
+```
+
+To enable something from the above, just set whatever value you want to change to `true` for more granularity.
diff --git a/gutenberg/how-to-guides/data-basics/1-data-basics-setup.md b/docs/gutenberg/how-to-guides/data-basics/1-data-basics-setup.md
similarity index 59%
rename from gutenberg/how-to-guides/data-basics/1-data-basics-setup.md
rename to docs/gutenberg/how-to-guides/data-basics/1-data-basics-setup.md
index d17c396..ad3c66b 100644
--- a/gutenberg/how-to-guides/data-basics/1-data-basics-setup.md
+++ b/docs/gutenberg/how-to-guides/data-basics/1-data-basics-setup.md
@@ -8,10 +8,10 @@ Also, this tutorial will lean heavily on Redux concepts such as state, actions,
We'll do all the development inside of a WordPress plugin. Let's start by creating a `wp-content/plugins/my-first-gutenberg-app` directory in your local WordPress environment. We will need to create four files inside that directory:
-- my-first-gutenberg-app.php – to create a new admin page
-- src/index.js – for our JavaScript application
-- src/style.css – for the minimal stylesheet
-- package.json – for the build process
+- my-first-gutenberg-app.php – to create a new admin page
+- src/index.js – for our JavaScript application
+- src/style.css – for the minimal stylesheet
+- package.json – for the build process
Go ahead and create these files using the following snippets:
@@ -22,18 +22,16 @@ import { createRoot } from 'react-dom';
import './style.css';
function MyFirstApp() {
- return Hello from JavaScript!;
+ return Hello from JavaScript!;
}
-const root = createRoot( document.getElementById( 'my-first-gutenberg-app' ) );
+const root = createRoot(document.getElementById('my-first-gutenberg-app'));
window.addEventListener(
- 'load',
- function () {
- root.render(
- ,
- );
- },
- false
+ 'load',
+ function () {
+ root.render();
+ },
+ false
);
```
@@ -41,55 +39,55 @@ window.addEventListener(
```css
.toplevel_page_my-first-gutenberg-app #wpcontent {
- background: #fff;
- height: 1000px;
+ background: #fff;
+ height: 1000px;
}
button .components-spinner {
- width: 15px;
- height: 15px;
- margin-top: 0;
- margin-bottom: 0;
- margin-left: 0;
+ width: 15px;
+ height: 15px;
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 0;
}
.form-buttons {
- display: flex;
+ display: flex;
}
.my-gutenberg-form .form-buttons {
- margin-top: 20px;
- margin-left: 1px;
+ margin-top: 20px;
+ margin-left: 1px;
}
.form-error {
- color: #cc1818;
+ color: #cc1818;
}
.form-buttons button {
- margin-right: 4px;
+ margin-right: 4px;
}
.form-buttons .components-spinner {
- margin-top: 0;
+ margin-top: 0;
}
#my-first-gutenberg-app {
- max-width: 500px;
+ max-width: 500px;
}
#my-first-gutenberg-app ul,
#my-first-gutenberg-app ul li {
- list-style-type: disc;
+ list-style-type: disc;
}
#my-first-gutenberg-app ul {
- padding-left: 20px;
+ padding-left: 20px;
}
#my-first-gutenberg-app .components-search-control__input {
- height: 36px;
- margin-left: 0;
+ height: 36px;
+ margin-left: 0;
}
#my-first-gutenberg-app .list-controls {
- display: flex;
- width: 100%;
+ display: flex;
+ width: 100%;
}
#my-first-gutenberg-app .list-controls .components-search-control {
- flex-grow: 1;
- margin-right: 8px;
+ flex-grow: 1;
+ margin-right: 8px;
}
```
@@ -103,58 +101,58 @@ button .components-spinner {
*/
function my_admin_menu() {
- // Create a new admin page for our app.
- add_menu_page(
- __( 'My first Gutenberg app', 'gutenberg' ),
- __( 'My first Gutenberg app', 'gutenberg' ),
- 'manage_options',
- 'my-first-gutenberg-app',
- function () {
- echo '
-
Pages
-
- ';
- },
- 'dashicons-schedule',
- 3
- );
+ // Create a new admin page for our app.
+ add_menu_page(
+ __( 'My first Gutenberg app', 'gutenberg' ),
+ __( 'My first Gutenberg app', 'gutenberg' ),
+ 'manage_options',
+ 'my-first-gutenberg-app',
+ function () {
+ echo '
+
Pages
+
+ ';
+ },
+ 'dashicons-schedule',
+ 3
+ );
}
add_action( 'admin_menu', 'my_admin_menu' );
function load_custom_wp_admin_scripts( $hook ) {
- // Load only on ?page=my-first-gutenberg-app.
- if ( 'toplevel_page_my-first-gutenberg-app' !== $hook ) {
- return;
- }
-
- // Load the required WordPress packages.
-
- // Automatically load imported dependencies and assets version.
- $asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php';
-
- // Enqueue CSS dependencies.
- foreach ( $asset_file['dependencies'] as $style ) {
- wp_enqueue_style( $style );
- }
-
- // Load our app.js.
- wp_register_script(
- 'my-first-gutenberg-app',
- plugins_url( 'build/index.js', __FILE__ ),
- $asset_file['dependencies'],
- $asset_file['version']
- );
- wp_enqueue_script( 'my-first-gutenberg-app' );
-
- // Load our style.css.
- wp_register_style(
- 'my-first-gutenberg-app',
- plugins_url( 'build/style-index.css', __FILE__ ),
- array(),
- $asset_file['version']
- );
- wp_enqueue_style( 'my-first-gutenberg-app' );
+ // Load only on ?page=my-first-gutenberg-app.
+ if ( 'toplevel_page_my-first-gutenberg-app' !== $hook ) {
+ return;
+ }
+
+ // Load the required WordPress packages.
+
+ // Automatically load imported dependencies and assets version.
+ $asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php';
+
+ // Enqueue CSS dependencies.
+ foreach ( $asset_file['dependencies'] as $style ) {
+ wp_enqueue_style( $style );
+ }
+
+ // Load our app.js.
+ wp_register_script(
+ 'my-first-gutenberg-app',
+ plugins_url( 'build/index.js', __FILE__ ),
+ $asset_file['dependencies'],
+ $asset_file['version']
+ );
+ wp_enqueue_script( 'my-first-gutenberg-app' );
+
+ // Load our style.css.
+ wp_register_style(
+ 'my-first-gutenberg-app',
+ plugins_url( 'build/style-index.css', __FILE__ ),
+ array(),
+ $asset_file['version']
+ );
+ wp_enqueue_style( 'my-first-gutenberg-app' );
}
add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' );
@@ -170,10 +168,7 @@ add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' );
"description": "My first Gutenberg App",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
- "keywords": [
- "WordPress",
- "block"
- ],
+ "keywords": ["WordPress", "block"],
"homepage": "https://github.com/WordPress/gutenberg-examples/",
"repository": "git+https://github.com/WordPress/gutenberg-examples.git",
"bugs": {
@@ -205,12 +200,12 @@ Once all the dependencies are in place, all that's left is to run `npm start` an
If you now go to the Plugins page, you should see a plugin called **My first Gutenberg App**. Go ahead and activate it. A new menu item labeled _My first Gutenberg app_ should show up. Once you click it, you will see a page that says _Hello from JavaScript!_:
-
+
Congratulations! You are now ready to start building the app!
## What's next?
-- Previous part: [Introduction](/docs/how-to-guides/data-basics/README.md)
-- Next part: [Building a basic list of pages](/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md)
-- (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
+- Previous part: [Introduction](/docs/how-to-guides/data-basics/README.md)
+- Next part: [Building a basic list of pages](/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md)
+- (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
diff --git a/gutenberg/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/gutenberg/how-to-guides/data-basics/2-building-a-list-of-pages.md
similarity index 66%
rename from gutenberg/how-to-guides/data-basics/2-building-a-list-of-pages.md
rename to docs/gutenberg/how-to-guides/data-basics/2-building-a-list-of-pages.md
index dbd73e0..79617e8 100644
--- a/gutenberg/how-to-guides/data-basics/2-building-a-list-of-pages.md
+++ b/docs/gutenberg/how-to-guides/data-basics/2-building-a-list-of-pages.md
@@ -12,20 +12,18 @@ Let’s start by building a minimal React component to display the list of pages
```js
function MyFirstApp() {
- const pages = [{ id: 'mock', title: 'Sample page' }]
- return ;
+ const pages = [{ id: 'mock', title: 'Sample page' }];
+ return ;
}
-function PagesList( { pages } ) {
- return (
-
+ );
}
```
@@ -48,12 +46,12 @@ Now that we have the data to work with, let’s dive into the code. We will take
To fetch the list of pages, we will use the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) selector. In broad strokes, it will issue the correct API request, cache the results, and return the list of the records we need. Here’s how to use it:
```js
-wp.data.select( 'core' ).getEntityRecords( 'postType', 'page' )
+wp.data.select('core').getEntityRecords('postType', 'page');
```
If you run that following snippet in your browser’s dev tools, you will see it returns `null`. Why? The pages are only requested by the `getEntityRecords` resolver after first running the _selector_. If you wait a moment and re-run it, it will return the list of all pages.
-*Note: To run this type of command directly make sure your browser is displaying an instance of the block editor (any page will do). Otherwise the `select( 'core' )` function won't be available, and you'll get an error.*
+_Note: To run this type of command directly make sure your browser is displaying an instance of the block editor (any page will do). Otherwise the `select( 'core' )` function won't be available, and you'll get an error._
Similarly, the `MyFirstApp` component needs to re-run the selector once the data is available. That’s exactly what the `useSelect` hook does:
@@ -62,20 +60,17 @@ import { useSelect } from '@wordpress/data';
import { store as coreDataStore } from '@wordpress/core-data';
function MyFirstApp() {
- const pages = useSelect(
- select =>
- select( coreDataStore ).getEntityRecords( 'postType', 'page' ),
- []
- );
- // ...
+ const pages = useSelect(
+ (select) => select(coreDataStore).getEntityRecords('postType', 'page'),
+ []
+ );
+ // ...
}
function PagesList({ pages }) {
- // ...
-
+ );
}
```
@@ -121,23 +113,23 @@ Refreshing the page should display a list similar to this one:
## Step 3: Turn it into a table
```js
-function PagesList( { pages } ) {
- return (
-
+ );
}
```
@@ -176,10 +165,10 @@ The field starts empty, and the contents are stored in the `searchTerm` state va
We can now request only the pages matching the `searchTerm`.
-After checking with the [WordPress API documentation](https://developer.wordpress.org/rest-api/reference/pages/), we see that the [/wp/v2/pages](https://developer.wordpress.org/rest-api/reference/pages/) endpoint accepts a `search` query parameter and uses it to _limit results to those matching a string_. But how can we use it? We can pass custom query parameters as the third argument to `getEntityRecords` as below:
+After checking with the [WordPress API documentation](https://developer.wordpress.org/rest-api/reference/pages/), we see that the [/wp/v2/pages](https://developer.wordpress.org/rest-api/reference/pages/) endpoint accepts a `search` query parameter and uses it to _limit results to those matching a string_. But how can we use it? We can pass custom query parameters as the third argument to `getEntityRecords` as below:
```js
-wp.data.select( 'core' ).getEntityRecords( 'postType', 'page', { search: 'home' } )
+wp.data.select('core').getEntityRecords('postType', 'page', { search: 'home' });
```
Running that snippet in your browser’s dev tools will trigger a request to `/wp/v2/pages?search=home` instead of just `/wp/v2/pages`.
@@ -191,18 +180,21 @@ import { useSelect } from '@wordpress/data';
import { store as coreDataStore } from '@wordpress/core-data';
function MyFirstApp() {
- // ...
- const { pages } = useSelect( select => {
- const query = {};
- if ( searchTerm ) {
- query.search = searchTerm;
- }
- return {
- pages: select( coreDataStore ).getEntityRecords( 'postType', 'page', query )
- }
- }, [searchTerm] );
-
- // ...
+ // ...
+ const { pages } = useSelect(
+ (select) => {
+ const query = {};
+ if (searchTerm) {
+ query.search = searchTerm;
+ }
+ return {
+ pages: select(coreDataStore).getEntityRecords('postType', 'page', query),
+ };
+ },
+ [searchTerm]
+ );
+
+ // ...
}
```
@@ -218,24 +210,24 @@ import { useSelect } from '@wordpress/data';
import { store as coreDataStore } from '@wordpress/core-data';
function MyFirstApp() {
- const [searchTerm, setSearchTerm] = useState( '' );
- const pages = useSelect( select => {
- const query = {};
- if ( searchTerm ) {
- query.search = searchTerm;
- }
- return select( coreDataStore ).getEntityRecords( 'postType', 'page', query );
- }, [searchTerm] );
-
- return (
-
+ );
}
```
@@ -250,26 +242,25 @@ Let’s take a pause for a moment to consider the downsides of an alternative ap
```js
import apiFetch from '@wordpress/api-fetch';
function MyFirstApp() {
- // ...
- const [pages, setPages] = useState( [] );
- useEffect( () => {
- const url = '/wp-json/wp/v2/pages?search=' + searchTerm;
- apiFetch( { url } )
- .then( setPages )
- }, [searchTerm] );
- // ...
+ // ...
+ const [pages, setPages] = useState([]);
+ useEffect(() => {
+ const url = '/wp-json/wp/v2/pages?search=' + searchTerm;
+ apiFetch({ url }).then(setPages);
+ }, [searchTerm]);
+ // ...
}
```
Working outside of core-data, we would need to solve two problems here.
-Firstly, out-of-order updates. Searching for „About” would trigger five API requests filtering for `A`, `Ab`, `Abo`, `Abou`, and `About`. These requests could finish in a different order than they started. It is possible that _search=A_ would resolve after _ search=About_ and thus we’d display the wrong data.
+Firstly, out-of-order updates. Searching for „About” would trigger five API requests filtering for `A`, `Ab`, `Abo`, `Abou`, and `About`. These requests could finish in a different order than they started. It is possible that _search=A_ would resolve after _search=About_ and thus we’d display the wrong data.
Gutenberg data helps by handling the asynchronous part behind the scenes. `useSelect` remembers the most recent call and returns only the data we expect.
Secondly, every keystroke would trigger an API request. If you typed `About`, deleted it, and retyped it, it would issue 10 requests in total even though we could reuse the data.
-Gutenberg data helps by caching the responses to API requests triggered by `getEntityRecords()` and reuses them on subsequent calls. This is especially important when other components rely on the same entity records.
+Gutenberg data helps by caching the responses to API requests triggered by `getEntityRecords()` and reuses them on subsequent calls. This is especially important when other components rely on the same entity records.
All in all, the utilities built into core-data are designed to solve the typical problems so that you can focus on your application instead.
@@ -279,35 +270,35 @@ There is one problem with our search feature. We can’t be quite sure whether i

-A few messages like _Loading…_ or _No results_ would clear it up. Let’s implement them! First, `PagesList` has to be aware of the current status:
+A few messages like _Loading…_ or _No results_ would clear it up. Let’s implement them! First, `PagesList` has to be aware of the current status:
```js
import { SearchControl, Spinner } from '@wordpress/components';
-function PagesList( { hasResolved, pages } ) {
- if ( !hasResolved ) {
- return
- }
- if ( !pages?.length ) {
- return
+ );
}
-const root = createRoot(
- document.querySelector( '#my-first-gutenberg-app' )
-);
+const root = createRoot(document.querySelector('#my-first-gutenberg-app'));
window.addEventListener(
- 'load',
- function () {
- root.render(
-
- );
- },
- false
+ 'load',
+ function () {
+ root.render();
+ },
+ false
);
```
@@ -445,6 +435,6 @@ All that’s left is to refresh the page and enjoy the brand new status indicato
## What's next?
-* **Previous part:** [Setup](/docs/how-to-guides/data-basics/1-data-basics-setup.md)
-* **Next part:** [Building an edit form](/docs/how-to-guides/data-basics/3-building-an-edit-form.md)
-* (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
+- **Previous part:** [Setup](/docs/how-to-guides/data-basics/1-data-basics-setup.md)
+- **Next part:** [Building an edit form](/docs/how-to-guides/data-basics/3-building-an-edit-form.md)
+- (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
diff --git a/docs/gutenberg/how-to-guides/data-basics/3-building-an-edit-form.md b/docs/gutenberg/how-to-guides/data-basics/3-building-an-edit-form.md
new file mode 100644
index 0000000..f86472f
--- /dev/null
+++ b/docs/gutenberg/how-to-guides/data-basics/3-building-an-edit-form.md
@@ -0,0 +1,511 @@
+# Building an edit form
+
+This part is about adding an _Edit_ feature to our app. Here's a glimpse of what we're going to build:
+
+
+
+### Step 1: Add an _Edit_ button
+
+We can't have an _Edit_ form without an _Edit_ button, so let's start by adding one to our `PagesList` component:
+
+```js
+import { Button } from '@wordpress/components';
+import { decodeEntities } from '@wordpress/html-entities';
+
+const PageEditButton = () => ;
+
+function PagesList({ hasResolved, pages }) {
+ if (!hasResolved) {
+ return ;
+ }
+ if (!pages?.length) {
+ return
No results
;
+ }
+
+ return (
+
+
+
+
Title
+
Actions
+
+
+
+ {pages?.map((page) => (
+
+
{decodeEntities(page.title.rendered)}
+
+
+
+
+ ))}
+
+
+ );
+}
+```
+
+The only change in `PagesList` is the additional column labeled _Actions_:
+
+
+
+### Step 2: Display an _Edit_ form
+
+Our button looks nice but doesn't do anything yet. To display an edit form, we need to have one first – let's create it:
+
+```js
+import { Button, TextControl } from '@wordpress/components';
+function EditPageForm({ pageId, onCancel, onSaveFinished }) {
+ return (
+
+
+
+
+
+
+
+ );
+}
+```
+
+Now let's make the button display the form we just created. As this tutorial is not focused on web design, we will wire the two together using a component that requires the least amount of code: [`Modal`](https://developer.wordpress.org/block-editor/reference-guides/components/modal/). Let's update `PageEditButton` accordingly:
+
+```js
+import { Button, Modal, TextControl } from '@wordpress/components';
+
+function PageEditButton({ pageId }) {
+ const [isOpen, setOpen] = useState(false);
+ const openModal = () => setOpen(true);
+ const closeModal = () => setOpen(false);
+ return (
+ <>
+
+ {isOpen && (
+
+
+
+ )}
+ >
+ );
+}
+```
+
+When you click the _Edit_ button now, you should see the following modal:
+
+
+
+Great! We now have a basic user interface to work with.
+
+### Step 3: Populate the form with page details
+
+We want the `EditPageForm` to display the title of the currently edited page. You may have noticed that it doesn't receive a `page` prop, only `pageId`. That's okay. Gutenberg Data allows us to easily access entity records from any component.
+
+In this case, we need to use the [`getEntityRecord`](/docs/reference-guides/data/data-core.md#getentityrecord) selector. The list of records is already available thanks to the `getEntityRecords` call in `MyFirstApp`, so there won't even be any additional HTTP requests involved – we'll get the cached record right away.
+
+Here's how you can try it in your browser's dev tools:
+
+```js
+wp.data.select('core').getEntityRecord('postType', 'page', 9); // Replace 9 with an actual page ID
+```
+
+Let's update `EditPageForm` accordingly:
+
+```js
+function EditPageForm({ pageId, onCancel, onSaveFinished }) {
+ const page = useSelect(
+ (select) => select(coreDataStore).getEntityRecord('postType', 'page', pageId),
+ [pageId]
+ );
+ return (
+
+
+ {/* ... */}
+
+ );
+}
+```
+
+Now it should look like this:
+
+
+
+### Step 4: Making the Page title field editable
+
+There's one problem with our _Page title_ field: you can't edit it. It receives a fixed `value` but doesn't update it when typing. We need an `onChange` handler.
+
+You may have seen a pattern similar to this one in other React apps. It's known as a ["controlled component"](https://reactjs.org/docs/forms.html#controlled-components):
+
+```js
+function VanillaReactForm({ initialTitle }) {
+ const [title, setTitle] = useState(initialTitle);
+ return (
+
+ );
+}
+```
+
+Updating entity records in Gutenberg Data is similar but instead of using `setTitle` to store in local (component level) state, we use the `editEntityRecord` action which stores the updates in the _Redux_ state. Here's how you can try it out in your browser's dev tools:
+
+```js
+// We need a valid page ID to call editEntityRecord, so let's get the first available one using getEntityRecords.
+const pageId = wp.data.select('core').getEntityRecords('postType', 'page')[0].id;
+
+// Update the title
+wp.data.dispatch('core').editEntityRecord('postType', 'page', pageId, { title: 'updated title' });
+```
+
+At this point, you may ask _how_ is `editEntityRecord` better than `useState`? The answer is that it offers a few features you wouldn't otherwise get.
+
+Firstly, we can save the changes as easily as we retrieve the data and ensure that all caches will be correctly updated.
+
+Secondly, the changes applied via `editEntityRecord` are easily undo-able via the `undo` and `redo` actions.
+
+Lastly, because the changes live in the _Redux_ state, they are "global" and can be accessed by other components. For example, we could make the `PagesList` display the currently edited title.
+
+To that last point, let's see what happens when we use `getEntityRecord` to access the entity record we just updated:
+
+```js
+wp.data.select('core').getEntityRecord('postType', 'page', pageId).title;
+```
+
+It doesn't reflect the edits. What's going on?
+
+Well, `` renders the data returned by `getEntityRecord()`. If `getEntityRecord()` reflected the updated title, then anything the user types in the `TextControl` would be immediately displayed inside ``, too. This is not what we want. The edits shouldn't leak outside the form until the user decides to save them.
+
+Gutenberg Data solves this problem by making a distinction between _Entity Records_ and _Edited Entity Records_. _Entity Records_ reflect the data from the API and ignore any local edits, while _Edited Entity Records_ also have all the local edits applied on top. Both co-exist in the Redux state at the same time.
+
+Let's see what happens if we call `getEditedEntityRecord`:
+
+```js
+wp.data.select('core').getEditedEntityRecord('postType', 'page', pageId).title;
+// "updated title"
+
+wp.data.select('core').getEntityRecord('postType', 'page', pageId).title;
+// { "rendered": "", "raw": "..." }
+```
+
+As you can see, the `title` of an Entity Record is an object, but the `title` of an Edited Entity record is a string.
+
+This is no accident. Fields like `title`, `excerpt`, and `content` may contain [shortcodes](https://developer.wordpress.org/apis/handbook/shortcode/) or [dynamic blocks](/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md), which means they can only be rendered on the server. For such fields, the REST API exposes both the `raw` markup _and_ the `rendered` string. For example, in the block editor, `content.rendered` could used as a visual preview, and `content.raw` could be used to populate the code editor.
+
+So why is the `content` of an Edited Entity Record a string? Since JavaScript is not be able to properly render arbitrary block markup, it stores only the `raw` markup without the `rendered` part. And since that's a string, the entire field becomes a string.
+
+We can now update `EditPageForm` accordingly. We can access the actions using the [`useDispatch`](/packages/data/README.md#usedispatch) hook similarly to how we use `useSelect` to access selectors:
+
+```js
+import { useDispatch } from '@wordpress/data';
+
+function EditPageForm({ pageId, onCancel, onSaveFinished }) {
+ const page = useSelect(
+ (select) => select(coreDataStore).getEditedEntityRecord('postType', 'page', pageId),
+ [pageId]
+ );
+ const { editEntityRecord } = useDispatch(coreDataStore);
+ const handleChange = (title) => editEntityRecord('postType', 'page', pageId, { title });
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+```
+
+We added an `onChange` handler to keep track of edits via the `editEntityRecord` action and then changed the selector to `getEditedEntityRecord` so that `page.title` always reflects the changes.
+
+This is what it looks like now:
+
+
+
+### Step 5: Saving the form data
+
+Now that we can edit the page title let's also make sure we can save it. In Gutenberg data, we save changes to the WordPress REST API using the `saveEditedEntityRecord` action. It sends the request, processes the result, and updates the cached data in the Redux state.
+
+Here's an example you may try in your browser's dev tools:
+
+```js
+// Replace 9 with an actual page ID
+wp.data.dispatch('core').editEntityRecord('postType', 'page', 9, { title: 'updated title' });
+wp.data.dispatch('core').saveEditedEntityRecord('postType', 'page', 9);
+```
+
+The above snippet saved a new title. Unlike before, `getEntityRecord` now reflects the updated title:
+
+```js
+// Replace 9 with an actual page ID
+wp.data.select('core').getEntityRecord('postType', 'page', 9).title.rendered;
+// "updated title"
+```
+
+Entity records are updated to reflect any saved changes right after the REST API request is finished.
+
+This is how the `EditPageForm` looks like with a working _Save_ button:
+
+```js
+function EditPageForm({ pageId, onCancel, onSaveFinished }) {
+ // ...
+ const { saveEditedEntityRecord } = useDispatch(coreDataStore);
+ const handleSave = () => saveEditedEntityRecord('postType', 'page', pageId);
+
+ return (
+
+ {/* ... */}
+
+
+ {/* ... */}
+
+
+ );
+}
+```
+
+It works, but there's still one thing to fix: the form modal doesn't automatically close because we never call `onSaveFinished`. Lucky for us, `saveEditedEntityRecord` returns a promise that resolves once the save operation is finished. Let's take advantage of it in `EditPageForm`:
+
+```js
+function EditPageForm({ pageId, onCancel, onSaveFinished }) {
+ // ...
+ const handleSave = async () => {
+ await saveEditedEntityRecord('postType', 'page', pageId);
+ onSaveFinished();
+ };
+ // ...
+}
+```
+
+### Step 6: Handle errors
+
+We optimistically assumed that a _save_ operation would always succeed. Unfortunately, it may fail in many ways:
+
+- The website can be down
+- The update may be invalid
+- The page could have been deleted by someone else in the meantime
+
+To tell the user when any of these happens, we have to make two adjustments. We don't want to close the form modal when the update fails. The promise returned by `saveEditedEntityRecord` is resolved with an updated record only if the update actually worked. When something goes wrong, it resolves with an empty value. Let's use it to keep the modal open:
+
+```js
+function EditPageForm({ pageId, onSaveFinished }) {
+ // ...
+ const handleSave = async () => {
+ const updatedRecord = await saveEditedEntityRecord('postType', 'page', pageId);
+ if (updatedRecord) {
+ onSaveFinished();
+ }
+ };
+ // ...
+}
+```
+
+Great! Now, let's display an error message. The failure details can be grabbed using the `getLastEntitySaveError` selector:
+
+```js
+// Replace 9 with an actual page ID
+wp.data.select('core').getLastEntitySaveError('postType', 'page', 9);
+```
+
+Here's how we can use it in `EditPageForm`:
+
+```js
+function EditPageForm({ pageId, onSaveFinished }) {
+ // ...
+ const { lastError, page } = useSelect(
+ (select) => ({
+ page: select(coreDataStore).getEditedEntityRecord('postType', 'page', pageId),
+ lastError: select(coreDataStore).getLastEntitySaveError('postType', 'page', pageId),
+ }),
+ [pageId]
+ );
+ // ...
+ return (
+
+ {/* ... */}
+ {lastError ?
Error: {lastError.message}
: false}
+ {/* ... */}
+
+ );
+}
+```
+
+Great! `EditPageForm` is now fully aware of errors.
+
+Let's see that error message in action. We'll trigger an invalid update and let it fail. The post title is hard to break, so let's set a `date` property to `-1` instead – that's a guaranteed validation error:
+
+```js
+function EditPageForm({ pageId, onCancel, onSaveFinished }) {
+ // ...
+ const handleChange = (title) => editEntityRecord('postType', 'page', pageId, { title, date: -1 });
+ // ...
+}
+```
+
+Once you refresh the page, open the form, change the title, and hit save, you should see the following error message:
+
+
+
+Fantastic! We can now **restore the previous version of `handleChange`** and move on to the next step.
+
+### Step 7: Status indicator
+
+There is one last problem with our form: no visual feedback. We can’t be quite sure whether the _Save_ button worked until either the form disappears or an error message shows.
+
+We're going to clear it up and communicate two states to the user: _Saving_ and _No changes detected_. The relevant selectors are `isSavingEntityRecord` and `hasEditsForEntityRecord`. Unlike `getEntityRecord`, they never issue any HTTP requests but only return the current entity record state.
+
+Let's use them in `EditPageForm`:
+
+```js
+function EditPageForm({ pageId, onSaveFinished }) {
+ // ...
+ const { isSaving, hasEdits /* ... */ } = useSelect(
+ (select) => ({
+ isSaving: select(coreDataStore).isSavingEntityRecord('postType', 'page', pageId),
+ hasEdits: select(coreDataStore).hasEditsForEntityRecord('postType', 'page', pageId),
+ // ...
+ }),
+ [pageId]
+ );
+}
+```
+
+We can now use `isSaving` and `hasEdits` to display a spinner when saving is in progress and grey out the save button when there are no edits:
+
+```js
+function EditPageForm({ pageId, onSaveFinished }) {
+ // ...
+ return (
+ // ...
+
+
+
+
+ // ...
+ );
+}
+```
+
+Note that we disable the _save_ button when there are no edits and when the page is currently being saved. This is to prevent the user from accidentally pressing the button twice.
+
+Also, interrupting a _save_ in progress is not supported by `@wordpress/data` so we also conditionally disabled the _cancel_ button.
+
+Here's what it looks like in action:
+
+
+
+
+### Wiring it all together
+
+All the pieces are in place, great! Here’s everything we built in this chapter in one place:
+
+```js
+import { useDispatch } from '@wordpress/data';
+import { Button, Modal, TextControl } from '@wordpress/components';
+
+function PageEditButton({ pageId }) {
+ const [isOpen, setOpen] = useState(false);
+ const openModal = () => setOpen(true);
+ const closeModal = () => setOpen(false);
+ return (
+ <>
+
+ {isOpen && (
+
+
+
+ )}
+ >
+ );
+}
+
+function EditPageForm({ pageId, onCancel, onSaveFinished }) {
+ const { page, lastError, isSaving, hasEdits } = useSelect(
+ (select) => ({
+ page: select(coreDataStore).getEditedEntityRecord('postType', 'page', pageId),
+ lastError: select(coreDataStore).getLastEntitySaveError('postType', 'page', pageId),
+ isSaving: select(coreDataStore).isSavingEntityRecord('postType', 'page', pageId),
+ hasEdits: select(coreDataStore).hasEditsForEntityRecord('postType', 'page', pageId),
+ }),
+ [pageId]
+ );
+
+ const { saveEditedEntityRecord, editEntityRecord } = useDispatch(coreDataStore);
+ const handleSave = async () => {
+ const savedRecord = await saveEditedEntityRecord('postType', 'page', pageId);
+ if (savedRecord) {
+ onSaveFinished();
+ }
+ };
+ const handleChange = (title) => editEntityRecord('postType', 'page', page.id, { title });
+
+ return (
+
+
+ {lastError ?
Error: {lastError.message}
: false}
+
+
+
+
+
+ );
+}
+```
+
+## What's next?
+
+- **Previous part:** [Building a list of pages](/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md)
+- **Next part:** [Building a Create Page form](/docs/how-to-guides/data-basics/4-building-a-create-page-form.md)
+- (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
diff --git a/docs/gutenberg/how-to-guides/data-basics/4-building-a-create-page-form.md b/docs/gutenberg/how-to-guides/data-basics/4-building-a-create-page-form.md
new file mode 100644
index 0000000..34f9c96
--- /dev/null
+++ b/docs/gutenberg/how-to-guides/data-basics/4-building-a-create-page-form.md
@@ -0,0 +1,366 @@
+# Building a Create page form
+
+In the [previous part](/docs/how-to-guides/data-basics/3-building-an-edit-form.md) we created an _Edit page_ feature, and in this part we will add a _Create page_ feature. Here's a glimpse of what we're going to build:
+
+
+
+### Step 1: Add a _Create a new page_ button
+
+Let’s start by building a button to display the _create page_ form. It’s similar to an _Edit_ button we have built in the [part 3](/docs/how-to-guides/data-basics/3-building-an-edit-form.md):
+
+```js
+import { useDispatch } from '@wordpress/data';
+import { Button, Modal, TextControl } from '@wordpress/components';
+
+function CreatePageButton() {
+ const [isOpen, setOpen] = useState(false);
+ const openModal = () => setOpen(true);
+ const closeModal = () => setOpen(false);
+ return (
+ <>
+
+ {isOpen && (
+
+
+
+ )}
+ >
+ );
+}
+
+function CreatePageForm() {
+ // Empty for now
+ return ;
+}
+```
+
+Great! Now let’s make `MyFirstApp` display our shiny new button:
+
+```js
+function MyFirstApp() {
+ // ...
+ return (
+
+
+
+
+
+
+
+ );
+}
+```
+
+The final result should look as follows:
+
+
+
+### Step 2: Extract a controlled PageForm
+
+Now that the button is in place, we can focus entirely on building the form. This tutorial is about managing data, so we will not build a complete page editor. Instead, the form will only contain one field: post title.
+
+Luckily, the `EditPageForm` we built in [part three](/docs/how-to-guides/data-basics/3-building-an-edit-form.md) already takes us 80% of the way there. The bulk of the user interface is already available, and we will reuse it in the `CreatePageForm`. Let’s start by extracting the form UI into a separate component:
+
+```js
+function EditPageForm({ pageId, onCancel, onSaveFinished }) {
+ // ...
+ return (
+
+ );
+}
+
+function PageForm({ title, onChangeTitle, hasEdits, lastError, isSaving, onCancel, onSave }) {
+ return (
+
+
+ {lastError ?
Error: {lastError.message}
: false}
+
+
+
+
+
+ );
+}
+```
+
+This code quality change should not alter anything about how the application works. Let’s try to edit a page just to be sure:
+
+
+
+Great! The edit form is still there, and now we have a building block to power the new `CreatePageForm`.
+
+### Step 3: Build a CreatePageForm
+
+The only thing that `CreatePageForm` component must do is to provide the following seven properties needed to render the `PageForm` component:
+
+- title
+- onChangeTitle
+- hasEdits
+- lastError
+- isSaving
+- onCancel
+- onSave
+
+Let’s see how we can do that:
+
+#### Title, onChangeTitle, hasEdits
+
+The `EditPageForm` updated and saved an existing entity record that lived in the Redux state. Because of that, we relied on the `editedEntityRecords` selector.
+
+In case of the `CreatePageForm` however, there is no pre-existing entity record. There is only an empty form. Anything that the user types is local to that form, which means we can keep track of it using the React’s `useState` hook:
+
+```js
+function CreatePageForm( { onCancel, onSaveFinished } ) {
+ const [title, setTitle] = useState();
+ const handleChange = ( title ) => setTitle( title );
+ return (
+
+ );
+}
+```
+
+#### onSave, onCancel
+
+In the `EditPageForm`, we dispatched the `saveEditedEntityRecord('postType', 'page', pageId )` action to save the edits that lived in the Redux state.
+
+In the `CreatePageForm` however, we do not have any edits in the Redux state, nor we do have a `pageId`. The action we need to dispatch in this case is called [`saveEntityRecord`](https://developer.wordpress.org/block-editor/reference-guides/data/data-core/#saveentityrecord) (without the word _Edited_ in the name) and it accepts an object representing the new entity record instead of a `pageId`.
+
+The data passed to `saveEntityRecord` is sent via a POST request to the appropriate REST API endpoint. For example, dispatching the following action:
+
+```js
+saveEntityRecord('postType', 'page', { title: 'Test' });
+```
+
+Triggers a POST request to the [`/wp/v2/pages` WordPress REST API](https://developer.wordpress.org/rest-api/reference/pages/) endpoint with a single field in the request body: `title=Test`.
+
+Now that we know more about `saveEntityRecord`, let's use it in `CreatePageForm`.
+
+```js
+function CreatePageForm( { onSaveFinished, onCancel } ) {
+ // ...
+ const { saveEntityRecord } = useDispatch( coreDataStore );
+ const handleSave = async () => {
+ const savedRecord = await saveEntityRecord(
+ 'postType',
+ 'page',
+ { title }
+ );
+ if ( savedRecord ) {
+ onSaveFinished();
+ }
+ };
+ return (
+
+ );
+}
+```
+
+There is one more detail to address: our newly created pages are not yet picked up by the `PagesList`. Accordingly to the REST API documentation, the `/wp/v2/pages` endpoint creates (`POST` requests) pages with `status=draft` by default, but _returns_ (`GET` requests) pages with `status=publish`. The solution is to pass the `status` parameter explicitly:
+
+```js
+function CreatePageForm( { onSaveFinished, onCancel } ) {
+ // ...
+ const { saveEntityRecord } = useDispatch( coreDataStore );
+ const handleSave = async () => {
+ const savedRecord = await saveEntityRecord(
+ 'postType',
+ 'page',
+ { title, status: 'publish' }
+ );
+ if ( savedRecord ) {
+ onSaveFinished();
+ }
+ };
+ return (
+
+ );
+}
+```
+
+Go ahead and apply that change to your local `CreatePageForm` component, and let’s tackle the remaining two props.
+
+#### lastError, isSaving
+
+The `EditPageForm` retrieved the error and progress information via the `getLastEntitySaveError` and `isSavingEntityRecord` selectors. In both cases, it passed the following three arguments: `( 'postType', 'page', pageId )`.
+
+In `CreatePageForm` however, we do not have a `pageId`. What now? We can skip the `pageId` argument to retrieve the information about the entity record without any id – this will be the newly created one. The `useSelect` call is thus very similar to the one from `EditPageForm`:
+
+```js
+function CreatePageForm( { onCancel, onSaveFinished } ) {
+ // ...
+ const { lastError, isSaving } = useSelect(
+ ( select ) => ( {
+ // Notice the missing pageId argument:
+ lastError: select( coreDataStore )
+ .getLastEntitySaveError( 'postType', 'page' ),
+ // Notice the missing pageId argument
+ isSaving: select( coreDataStore )
+ .isSavingEntityRecord( 'postType', 'page' ),
+ } ),
+ []
+ );
+ // ...
+ return (
+
+ );
+}
+```
+
+And that’s it! Here's what our new form looks like in action:
+
+
+
+
+### Wiring it all together
+
+Here’s everything we built in this chapter in one place:
+
+```js
+function CreatePageForm({ onCancel, onSaveFinished }) {
+ const [title, setTitle] = useState();
+ const { lastError, isSaving } = useSelect(
+ (select) => ({
+ lastError: select(coreDataStore).getLastEntitySaveError('postType', 'page'),
+ isSaving: select(coreDataStore).isSavingEntityRecord('postType', 'page'),
+ }),
+ []
+ );
+
+ const { saveEntityRecord } = useDispatch(coreDataStore);
+ const handleSave = async () => {
+ const savedRecord = await saveEntityRecord('postType', 'page', { title, status: 'publish' });
+ if (savedRecord) {
+ onSaveFinished();
+ }
+ };
+
+ return (
+
+ );
+}
+
+function EditPageForm({ pageId, onCancel, onSaveFinished }) {
+ const { page, lastError, isSaving, hasEdits } = useSelect(
+ (select) => ({
+ page: select(coreDataStore).getEditedEntityRecord('postType', 'page', pageId),
+ lastError: select(coreDataStore).getLastEntitySaveError('postType', 'page', pageId),
+ isSaving: select(coreDataStore).isSavingEntityRecord('postType', 'page', pageId),
+ hasEdits: select(coreDataStore).hasEditsForEntityRecord('postType', 'page', pageId),
+ }),
+ [pageId]
+ );
+
+ const { saveEditedEntityRecord, editEntityRecord } = useDispatch(coreDataStore);
+ const handleSave = async () => {
+ const savedRecord = await saveEditedEntityRecord('postType', 'page', pageId);
+ if (savedRecord) {
+ onSaveFinished();
+ }
+ };
+ const handleChange = (title) => editEntityRecord('postType', 'page', page.id, { title });
+
+ return (
+
+ );
+}
+
+function PageForm({ title, onChangeTitle, hasEdits, lastError, isSaving, onCancel, onSave }) {
+ return (
+
+
+ {lastError ?
Error: {lastError.message}
: false}
+
+
+
+
+
+ );
+}
+```
+
+All that’s left is to refresh the page and enjoy the form:
+
+
+
+## What's next?
+
+- **Next part:** [Adding a delete button](/docs/how-to-guides/data-basics/5-adding-a-delete-button.md)
+- **Previous part:** [Building an edit form](/docs/how-to-guides/data-basics/3-building-an-edit-form.md)
+- (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
diff --git a/docs/gutenberg/how-to-guides/data-basics/5-adding-a-delete-button.md b/docs/gutenberg/how-to-guides/data-basics/5-adding-a-delete-button.md
new file mode 100644
index 0000000..31af876
--- /dev/null
+++ b/docs/gutenberg/how-to-guides/data-basics/5-adding-a-delete-button.md
@@ -0,0 +1,437 @@
+# Adding a delete button
+
+In the [previous part](/docs/how-to-guides/data-basics/3-building-an-edit-form.md) we added an ability to create new pages,
+and in this part we will add a _Delete_ feature to our app.
+
+Here's a glimpse of what we're going to build:
+
+
+
+### Step 1: Add a _Delete_ button
+
+Let's start by creating the `DeletePageButton` component and updating the user interface of our `PagesList` component:
+
+```js
+import { Button } from '@wordpress/components';
+import { decodeEntities } from '@wordpress/html-entities';
+
+const DeletePageButton = () => ;
+
+function PagesList({ hasResolved, pages }) {
+ if (!hasResolved) {
+ return ;
+ }
+ if (!pages?.length) {
+ return
No results
;
+ }
+
+ return (
+
+
+
+
Title
+
Actions
+
+
+
+ {pages?.map((page) => (
+
+
{decodeEntities(page.title.rendered)}
+
+
+
+ {/* ↓ This is the only change in the PagesList component */}
+
+
+
+
+ ))}
+
+
+ );
+}
+```
+
+This is what the PagesList should look like now:
+
+
+
+### Step 2: Wire the button to a delete action
+
+In Gutenberg data, we delete entity records from the WordPress REST API using the `deleteEntityRecord` action. It sends the request, processes the result, and updates the cached data in the Redux state.
+
+Here's how you can try deleting entity records in your browser's dev tools:
+
+```js
+// We need a valid page ID to call deleteEntityRecord, so let's get the first available one using getEntityRecords.
+const pageId = wp.data.select('core').getEntityRecords('postType', 'page')[0].id;
+
+// Now let's delete that page:
+const promise = wp.data.dispatch('core').deleteEntityRecord('postType', 'page', pageId);
+
+// promise gets resolved or rejected when the API request succeeds or fails.
+```
+
+Once the REST API request is finished, you will notice one of the pages has disappeared from the list. This is because that list is populated by the `useSelect()` hook and the `select( coreDataStore ).getEntityRecords( 'postType', 'page' )` selector. Anytime the underlying data changes, the list gets re-rendered with fresh data. That's pretty convenient!
+
+Let's dispatch that action when `DeletePageButton` is clicked:
+
+```js
+const DeletePageButton = ({ pageId }) => {
+ const { deleteEntityRecord } = useDispatch(coreDataStore);
+ const handleDelete = () => deleteEntityRecord('postType', 'page', pageId);
+ return (
+
+ );
+};
+```
+
+### Step 3: Add visual feedback
+
+It may take a few moments for the REST API request to finish after clicking the _Delete_ button. Let's communicate that with a `` component similarly to what we did in the previous parts of this tutorial.
+
+We'll need the `isDeletingEntityRecord` selector for that. It is similar to the `isSavingEntityRecord` selector we've already seen in [part 3](/docs/how-to-guides/data-basics/3-building-an-edit-form.md): it returns `true` or `false` and never issues any HTTP requests:
+
+```js
+const DeletePageButton = ({ pageId }) => {
+ // ...
+ const { isDeleting } = useSelect(
+ (select) => ({
+ isDeleting: select(coreDataStore).isDeletingEntityRecord('postType', 'page', pageId),
+ }),
+ [pageId]
+ );
+ return (
+
+ );
+};
+```
+
+Here's what it looks like in action:
+
+
+
+### Step 4: Handle errors
+
+We optimistically assumed that a _delete_ operation would always succeed. Unfortunately, under the hood, it is a REST API request that can fail in many ways:
+
+- The website can be down.
+- The delete request may be invalid.
+- The page could have been deleted by someone else in the meantime.
+
+To tell the user when any of these errors happen, we need to extract the error information using the `getLastEntityDeleteError` selector:
+
+```js
+// Replace 9 with an actual page ID
+wp.data.select('core').getLastEntityDeleteError('postType', 'page', 9);
+```
+
+Here's how we can apply it in `DeletePageButton`:
+
+```js
+import { useEffect } from 'react';
+const DeletePageButton = ({ pageId }) => {
+ // ...
+ const { error /* ... */ } = useSelect(
+ (select) => ({
+ error: select(coreDataStore).getLastEntityDeleteError('postType', 'page', pageId),
+ // ...
+ }),
+ [pageId]
+ );
+ useEffect(() => {
+ if (error) {
+ // Display the error
+ }
+ }, [error]);
+
+ // ...
+};
+```
+
+The `error` object comes from the `@wordpress/api-fetch` and contains information about the error. It has the following properties:
+
+- `message` – a human-readable error message such as `Invalid post ID`.
+- `code` – a string-based error code such as `rest_post_invalid_id`. To learn about all possible error codes you'd need to refer to the [`/v2/pages` endpoint's source code](https://github.com/WordPress/wordpress-develop/blob/2648a5f984b8abf06872151898e3a61d3458a628/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php#L226-L230).
+- `data` (optional) – error details, contains the `code` property containing the HTTP response code for the failed request.
+
+There are many ways to turn that object into an error message, but in this tutorial, we will display the `error.message`.
+
+WordPress has an established pattern of displaying status information using the `Snackbar` component. Here's what it looks like **in the Widgets editor**:
+
+
+
+Let's use the same type of notifications in our plugin! There are two parts to this:
+
+1. Displaying notifications
+2. Dispatching notifications
+
+#### Displaying notifications
+
+Our application only knows how to display pages but does not know how to display notifications. Let's tell it!
+
+WordPress conveniently provides us with all the React components we need to render notifications. A [component called `Snackbar`](https://wordpress.github.io/gutenberg/?path=/story/components-snackbar--default) represents a single notification:
+
+
+
+We won't use `Snackbar` directly, though. We'll use the `SnackbarList` component, which can display multiple notices using smooth animations and automatically hide them after a few seconds. In fact, WordPress uses the same component used in the Widgets editor and other wp-admin pages!
+
+Let's create our own `Notifications` components:
+
+```js
+import { SnackbarList } from '@wordpress/components';
+import { store as noticesStore } from '@wordpress/notices';
+
+function Notifications() {
+ const notices = []; // We'll come back here in a second!
+
+ return ;
+}
+```
+
+The basic structure is in place, but the list of notifications it renders is empty. How do we populate it? We'll lean on the same package as WordPress: [`@wordpress/notices`](https://github.com/WordPress/gutenberg/blob/895ca1f6a7d7e492974ea55f693aecbeb1d5bbe3/docs/reference-guides/data/data-core-notices.md).
+
+Here's how:
+
+```js
+import { SnackbarList } from '@wordpress/components';
+import { store as noticesStore } from '@wordpress/notices';
+
+function Notifications() {
+ const notices = useSelect((select) => select(noticesStore).getNotices(), []);
+ const { removeNotice } = useDispatch(noticesStore);
+ const snackbarNotices = notices.filter(({ type }) => type === 'snackbar');
+
+ return (
+
+ );
+}
+
+function MyFirstApp() {
+ // ...
+ return (
+
+ {/* ... */}
+
+
+ );
+}
+```
+
+This tutorial is focused on managing the pages and won't discuss the above snippet in detail. If you're interested in the details of `@wordpress/notices`, the [handbook page](https://developer.wordpress.org/block-editor/reference-guides/data/data-core-notices/) is a good place to start.
+
+Now we're ready to tell the user about any errors that may have occurred.
+
+#### Dispatching notifications
+
+With the SnackbarNotices component in place, we're ready to dispatch some notifications! Here's how:
+
+```js
+import { useEffect } from 'react';
+import { store as noticesStore } from '@wordpress/notices';
+function DeletePageButton({ pageId }) {
+ const { createSuccessNotice, createErrorNotice } = useDispatch(noticesStore);
+ // useSelect returns a list of selectors if you pass the store handle
+ // instead of a callback:
+ const { getLastEntityDeleteError } = useSelect(coreDataStore);
+ const handleDelete = async () => {
+ const success = await deleteEntityRecord('postType', 'page', pageId);
+ if (success) {
+ // Tell the user the operation succeeded:
+ createSuccessNotice('The page was deleted!', {
+ type: 'snackbar',
+ });
+ } else {
+ // We use the selector directly to get the fresh error *after* the deleteEntityRecord
+ // have failed.
+ const lastError = getLastEntityDeleteError('postType', 'page', pageId);
+ const message =
+ (lastError?.message || 'There was an error.') + ' Please refresh the page and try again.';
+ // Tell the user how exactly the operation has failed:
+ createErrorNotice(message, {
+ type: 'snackbar',
+ });
+ }
+ };
+ // ...
+}
+```
+
+Great! `DeletePageButton` is now fully aware of errors. Let's see that error message in action. We'll trigger an invalid delete and let it fail. One way to do this is to multiply the `pageId` by a large number:
+
+```js
+function DeletePageButton({ pageId, onCancel, onSaveFinished }) {
+ pageId = pageId * 1000;
+ // ...
+}
+```
+
+Once you refresh the page and click any `Delete` button, you should see the following error message:
+
+
+
+Fantastic! We can now **remove the `pageId = pageId * 1000;` line.**
+
+Let's now try actually deleting a page. Here's what you should see after refreshing your browser and clicking the Delete button:
+
+
+
+And that's it!
+
+### Wiring it all together
+
+All the pieces are in place, great! Here’s all the changes we've made in this chapter:
+
+```js
+import { useState, useEffect } from 'react';
+import { useSelect, useDispatch } from '@wordpress/data';
+import { Button, Modal, TextControl } from '@wordpress/components';
+
+function MyFirstApp() {
+ const [searchTerm, setSearchTerm] = useState('');
+ const { pages, hasResolved } = useSelect(
+ (select) => {
+ const query = {};
+ if (searchTerm) {
+ query.search = searchTerm;
+ }
+ const selectorArgs = ['postType', 'page', query];
+ const pages = select(coreDataStore).getEntityRecords(...selectorArgs);
+ return {
+ pages,
+ hasResolved: select(coreDataStore).hasFinishedResolution('getEntityRecords', selectorArgs),
+ };
+ },
+ [searchTerm]
+ );
+
+ return (
+
+ );
+}
+
+function DeletePageButton({ pageId }) {
+ const { createSuccessNotice, createErrorNotice } = useDispatch(noticesStore);
+ // useSelect returns a list of selectors if you pass the store handle
+ // instead of a callback:
+ const { getLastEntityDeleteError } = useSelect(coreDataStore);
+ const handleDelete = async () => {
+ const success = await deleteEntityRecord('postType', 'page', pageId);
+ if (success) {
+ // Tell the user the operation succeeded:
+ createSuccessNotice('The page was deleted!', {
+ type: 'snackbar',
+ });
+ } else {
+ // We use the selector directly to get the error at this point in time.
+ // Imagine we fetched the error like this:
+ // const { lastError } = useSelect( function() { /* ... */ } );
+ // Then, lastError would be null inside of handleDelete.
+ // Why? Because we'd refer to the version of it that was computed
+ // before the handleDelete was even called.
+ const lastError = getLastEntityDeleteError('postType', 'page', pageId);
+ const message =
+ (lastError?.message || 'There was an error.') + ' Please refresh the page and try again.';
+ // Tell the user how exactly the operation have failed:
+ createErrorNotice(message, {
+ type: 'snackbar',
+ });
+ }
+ };
+
+ const { deleteEntityRecord } = useDispatch(coreDataStore);
+ const { isDeleting } = useSelect(
+ (select) => ({
+ isDeleting: select(coreDataStore).isDeletingEntityRecord('postType', 'page', pageId),
+ }),
+ [pageId]
+ );
+
+ return (
+
+ );
+}
+```
+
+## What's next?
+
+- **Previous part:** [Building a _Create page form_](/docs/how-to-guides/data-basics/4-building-a-create-page-form.md)
+- (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
diff --git a/gutenberg/how-to-guides/data-basics/README.md b/docs/gutenberg/how-to-guides/data-basics/README.md
similarity index 95%
rename from gutenberg/how-to-guides/data-basics/README.md
rename to docs/gutenberg/how-to-guides/data-basics/README.md
index 3e92a21..4d0c9bc 100644
--- a/gutenberg/how-to-guides/data-basics/README.md
+++ b/docs/gutenberg/how-to-guides/data-basics/README.md
@@ -2,8 +2,7 @@
This tutorial aims to get you comfortable with the Gutenberg data layer. It guides you through building a simple React application that enables the user to manage their WordPress pages. The finished app will look like this:
-
-[](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/WordPress/block-development-examples/trunk/plugins/data-basics-59c8f8/_playground/blueprint.json "Opens demo in WordPress Playground")
+[](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/WordPress/block-development-examples/trunk/plugins/data-basics-59c8f8/_playground/blueprint.json 'Opens demo in WordPress Playground')
You may review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository.
diff --git a/gutenberg/how-to-guides/data-basics/media/create-form/basic-create-form.png b/docs/gutenberg/how-to-guides/data-basics/media/create-form/basic-create-form.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/create-form/basic-create-form.png
rename to docs/gutenberg/how-to-guides/data-basics/media/create-form/basic-create-form.png
diff --git a/gutenberg/how-to-guides/data-basics/media/create-form/create-button.png b/docs/gutenberg/how-to-guides/data-basics/media/create-form/create-button.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/create-form/create-button.png
rename to docs/gutenberg/how-to-guides/data-basics/media/create-form/create-button.png
diff --git a/gutenberg/how-to-guides/data-basics/media/create-form/create-form-with-text.png b/docs/gutenberg/how-to-guides/data-basics/media/create-form/create-form-with-text.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/create-form/create-form-with-text.png
rename to docs/gutenberg/how-to-guides/data-basics/media/create-form/create-form-with-text.png
diff --git a/gutenberg/how-to-guides/data-basics/media/create-form/create-saving.png b/docs/gutenberg/how-to-guides/data-basics/media/create-form/create-saving.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/create-form/create-saving.png
rename to docs/gutenberg/how-to-guides/data-basics/media/create-form/create-saving.png
diff --git a/gutenberg/how-to-guides/data-basics/media/create-form/created-item.png b/docs/gutenberg/how-to-guides/data-basics/media/create-form/created-item.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/create-form/created-item.png
rename to docs/gutenberg/how-to-guides/data-basics/media/create-form/created-item.png
diff --git a/gutenberg/how-to-guides/data-basics/media/create-form/edit-page-form.png b/docs/gutenberg/how-to-guides/data-basics/media/create-form/edit-page-form.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/create-form/edit-page-form.png
rename to docs/gutenberg/how-to-guides/data-basics/media/create-form/edit-page-form.png
diff --git a/gutenberg/how-to-guides/data-basics/media/delete-button/delete-button.png b/docs/gutenberg/how-to-guides/data-basics/media/delete-button/delete-button.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/delete-button/delete-button.png
rename to docs/gutenberg/how-to-guides/data-basics/media/delete-button/delete-button.png
diff --git a/gutenberg/how-to-guides/data-basics/media/delete-button/deleting-in-progress.png b/docs/gutenberg/how-to-guides/data-basics/media/delete-button/deleting-in-progress.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/delete-button/deleting-in-progress.png
rename to docs/gutenberg/how-to-guides/data-basics/media/delete-button/deleting-in-progress.png
diff --git a/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-error.png b/docs/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-error.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-error.png
rename to docs/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-error.png
diff --git a/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-example.png b/docs/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-example.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-example.png
rename to docs/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-example.png
diff --git a/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-success.png b/docs/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-success.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-success.png
rename to docs/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar-success.png
diff --git a/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar.png b/docs/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/delete-button/snackbar.png
rename to docs/gutenberg/how-to-guides/data-basics/media/delete-button/snackbar.png
diff --git a/gutenberg/how-to-guides/data-basics/media/edit-form/edit-button.png b/docs/gutenberg/how-to-guides/data-basics/media/edit-form/edit-button.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/edit-form/edit-button.png
rename to docs/gutenberg/how-to-guides/data-basics/media/edit-form/edit-button.png
diff --git a/gutenberg/how-to-guides/data-basics/media/edit-form/form-editable.png b/docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-editable.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/edit-form/form-editable.png
rename to docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-editable.png
diff --git a/gutenberg/how-to-guides/data-basics/media/edit-form/form-error.png b/docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-error.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/edit-form/form-error.png
rename to docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-error.png
diff --git a/gutenberg/how-to-guides/data-basics/media/edit-form/form-finished.png b/docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-finished.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/edit-form/form-finished.png
rename to docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-finished.png
diff --git a/gutenberg/how-to-guides/data-basics/media/edit-form/form-inactive.png b/docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-inactive.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/edit-form/form-inactive.png
rename to docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-inactive.png
diff --git a/gutenberg/how-to-guides/data-basics/media/edit-form/form-populated.png b/docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-populated.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/edit-form/form-populated.png
rename to docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-populated.png
diff --git a/gutenberg/how-to-guides/data-basics/media/edit-form/form-scaffold.png b/docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-scaffold.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/edit-form/form-scaffold.png
rename to docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-scaffold.png
diff --git a/gutenberg/how-to-guides/data-basics/media/edit-form/form-spinner.png b/docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-spinner.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/edit-form/form-spinner.png
rename to docs/gutenberg/how-to-guides/data-basics/media/edit-form/form-spinner.png
diff --git a/gutenberg/how-to-guides/data-basics/media/edit-form/modal-initial.png b/docs/gutenberg/how-to-guides/data-basics/media/edit-form/modal-initial.png
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/edit-form/modal-initial.png
rename to docs/gutenberg/how-to-guides/data-basics/media/edit-form/modal-initial.png
diff --git a/gutenberg/how-to-guides/data-basics/media/finished-app.jpg b/docs/gutenberg/how-to-guides/data-basics/media/finished-app.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/finished-app.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/finished-app.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/filter-field.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/filter-field.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/filter-field.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/filter-field.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/filter.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/filter.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/filter.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/filter.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/indicator.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/indicator.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/indicator.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/indicator.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/make-a-table.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/make-a-table.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/make-a-table.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/make-a-table.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/no-results.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/no-results.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/no-results.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/no-results.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/pages-list.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/pages-list.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/pages-list.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/pages-list.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/part1-finished.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/part1-finished.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/part1-finished.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/part1-finished.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/simple-list.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/simple-list.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/simple-list.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/simple-list.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/list-of-pages/unclear-status.jpg b/docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/unclear-status.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/list-of-pages/unclear-status.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/list-of-pages/unclear-status.jpg
diff --git a/gutenberg/how-to-guides/data-basics/media/setup/hello-from-js.jpg b/docs/gutenberg/how-to-guides/data-basics/media/setup/hello-from-js.jpg
similarity index 100%
rename from gutenberg/how-to-guides/data-basics/media/setup/hello-from-js.jpg
rename to docs/gutenberg/how-to-guides/data-basics/media/setup/hello-from-js.jpg
diff --git a/gutenberg/how-to-guides/enqueueing-assets-in-the-editor.md b/docs/gutenberg/how-to-guides/enqueueing-assets-in-the-editor.md
similarity index 99%
rename from gutenberg/how-to-guides/enqueueing-assets-in-the-editor.md
rename to docs/gutenberg/how-to-guides/enqueueing-assets-in-the-editor.md
index fb0efb8..5cd82d8 100644
--- a/gutenberg/how-to-guides/enqueueing-assets-in-the-editor.md
+++ b/docs/gutenberg/how-to-guides/enqueueing-assets-in-the-editor.md
@@ -7,6 +7,7 @@ As of WordPress 6.3, the Post Editor is iframed if all registered blocks have a
For more information about why the Editor is iframed, please revisit the post [Blocks in an iframed (template) editor](https://make.wordpress.org/core/2021/06/29/blocks-in-an-iframed-template-editor/).
## The Editor versus Editor content
+
Before enqueueing assets in the Editor, you must first identify what you are trying to target.
Do you want to add styling or JavaScript to the user-generated content (blocks) in the Editor? Or do you want to modify the Editor user interface (UI) components or interact with Editor APIs? This could include everything from creating custom block controls to registering block variations.
@@ -14,6 +15,7 @@ Do you want to add styling or JavaScript to the user-generated content (blocks)
There are different hooks to use depending on the answers to these questions, and if you are building a block or a theme, there are additional approaches to consider. Refer to the designated sections below.
## Scenarios for enqueuing assets
+
### Editor scripts and styles
Whenever you need to enqueue assets for the Editor itself (i.e. not the user-generated content), you should use the [`enqueue_block_editor_assets`](https://developer.wordpress.org/reference/hooks/enqueue_block_editor_assets/) hook coupled with the standard [`wp_enqueue_script`](https://developer.wordpress.org/reference/functions/wp_enqueue_script/) and [`wp_enqueue_style`](https://developer.wordpress.org/reference/functions/wp_enqueue_style/) functions.
diff --git a/gutenberg/how-to-guides/feature-flags.md b/docs/gutenberg/how-to-guides/feature-flags.md
similarity index 81%
rename from gutenberg/how-to-guides/feature-flags.md
rename to docs/gutenberg/how-to-guides/feature-flags.md
index 04fc6c0..99bac86 100644
--- a/gutenberg/how-to-guides/feature-flags.md
+++ b/docs/gutenberg/how-to-guides/feature-flags.md
@@ -16,12 +16,10 @@ A plugin-only function or constant should be exported using the following ternar
```js
function myPluginOnlyFeature() {
- // implementation
+ // implementation
}
-export const pluginOnlyFeature = globalThis.IS_GUTENBERG_PLUGIN
- ? myPluginOnlyFeature
- : undefined;
+export const pluginOnlyFeature = globalThis.IS_GUTENBERG_PLUGIN ? myPluginOnlyFeature : undefined;
```
In the above example, the `pluginOnlyFeature` export will be `undefined` in non-plugin environments such as WordPress core.
@@ -33,8 +31,8 @@ If you're attempting to import and call a plugin-only feature, be sure to wrap t
```js
import { pluginOnlyFeature } from '@wordpress/foo';
-if ( globalThis.IS_GUTENBERG_PLUGIN ) {
- pluginOnlyFeature();
+if (globalThis.IS_GUTENBERG_PLUGIN) {
+ pluginOnlyFeature();
}
```
@@ -45,17 +43,17 @@ During the webpack build, instances of `globalThis.IS_GUTENBERG_PLUGIN` will be
For example, in the following code –
```js
-if ( globalThis.IS_GUTENBERG_PLUGIN ) {
- pluginOnlyFeature();
+if (globalThis.IS_GUTENBERG_PLUGIN) {
+ pluginOnlyFeature();
}
```
– the variable `globalThis.IS_GUTENBERG_PLUGIN` will be replaced with the boolean `true` during the plugin-only build:
```js
-if ( true ) {
- // Webpack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `true`
- pluginOnlyFeature();
+if (true) {
+ // Webpack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `true`
+ pluginOnlyFeature();
}
```
@@ -64,9 +62,9 @@ This ensures that code within the body of the `if` statement will always be exec
In WordPress core, the `globalThis.IS_GUTENBERG_PLUGIN` variable is replaced with `undefined`. The built code looks like this:
```js
-if ( undefined ) {
- // Webpack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `undefined`
- pluginOnlyFeature();
+if (undefined) {
+ // Webpack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `undefined`
+ pluginOnlyFeature();
}
```
@@ -74,13 +72,13 @@ if ( undefined ) {
### Dead code elimination
-For production builds, webpack ['minifies'](https://en.wikipedia.org/wiki/Minification_(programming)) the code, removing as much unnecessary JavaScript as it can.
+For production builds, webpack ['minifies']() the code, removing as much unnecessary JavaScript as it can.
One of the steps involves something known as 'dead code elimination'. For example, when the following code is encountered, webpack determines that the surrounding `if` statement is unnecessary:
```js
-if ( true ) {
- pluginOnlyFeature();
+if (true) {
+ pluginOnlyFeature();
}
```
@@ -93,8 +91,8 @@ pluginOnlyFeature(); // The `if` condition block has been removed. Only the body
Similarly, when building for WordPress core, the condition in the following `if` statement always resolves to false:
```js
-if ( undefined ) {
- pluginOnlyFeature();
+if (undefined) {
+ pluginOnlyFeature();
}
```
diff --git a/gutenberg/how-to-guides/format-api.md b/docs/gutenberg/how-to-guides/format-api.md
similarity index 63%
rename from gutenberg/how-to-guides/format-api.md
rename to docs/gutenberg/how-to-guides/format-api.md
index c383222..141d52e 100644
--- a/gutenberg/how-to-guides/format-api.md
+++ b/docs/gutenberg/how-to-guides/format-api.md
@@ -14,9 +14,9 @@ This guide assumes you are already familiar with WordPress plugins and loading J
You will need:
-- WordPress development environment
-- A minimal plugin activated and setup ready to edit
-- JavaScript setup for building and enqueuing
+- WordPress development environment
+- A minimal plugin activated and setup ready to edit
+- JavaScript setup for building and enqueuing
The [complete format-api example](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/format-api-f14b86) is available that you can use as a reference for your setup.
@@ -31,11 +31,11 @@ The first step is to register the new format, add `src/index.js` with the follow
```js
import { registerFormatType } from '@wordpress/rich-text';
-registerFormatType( 'my-custom-format/sample-output', {
- title: 'Sample output',
- tagName: 'samp',
- className: null,
-} );
+registerFormatType('my-custom-format/sample-output', {
+ title: 'Sample output',
+ tagName: 'samp',
+ className: null,
+});
```
The list of available format types is maintained in the `core/rich-text` store. You can query the store to check that your custom format is now available.
@@ -43,7 +43,7 @@ The list of available format types is maintained in the `core/rich-text` store.
Run this code in your browser's console to confirm:
```js
-wp.data.select( 'core/rich-text' ).getFormatTypes();
+wp.data.select('core/rich-text').getFormatTypes();
```
It'll return an array containing the format types, including your own.
@@ -58,24 +58,24 @@ Using the `RichTextToolbarButton` component, update `src/index.js`:
import { registerFormatType } from '@wordpress/rich-text';
import { RichTextToolbarButton } from '@wordpress/block-editor';
-const MyCustomButton = ( props ) => {
- return (
- {
- console.log( 'toggle format' );
- } }
- />
- );
+const MyCustomButton = (props) => {
+ return (
+ {
+ console.log('toggle format');
+ }}
+ />
+ );
};
-registerFormatType( 'my-custom-format/sample-output', {
- title: 'Sample output',
- tagName: 'samp',
- className: null,
- edit: MyCustomButton,
-} );
+registerFormatType('my-custom-format/sample-output', {
+ title: 'Sample output',
+ tagName: 'samp',
+ className: null,
+ edit: MyCustomButton,
+});
```
Let's check that everything is working as expected. Build and reload and then select any block containing text like for example the paragraph block. Confirm the new button was added to the format toolbar.
@@ -98,29 +98,29 @@ Update `src/index.js` changing the `onClick` action:
import { registerFormatType, toggleFormat } from '@wordpress/rich-text';
import { RichTextToolbarButton } from '@wordpress/block-editor';
-const MyCustomButton = ( { isActive, onChange, value } ) => {
- return (
- {
- onChange(
- toggleFormat( value, {
- type: 'my-custom-format/sample-output',
- } )
- );
- } }
- isActive={ isActive }
- />
- );
+const MyCustomButton = ({ isActive, onChange, value }) => {
+ return (
+ {
+ onChange(
+ toggleFormat(value, {
+ type: 'my-custom-format/sample-output',
+ })
+ );
+ }}
+ isActive={isActive}
+ />
+ );
};
-registerFormatType( 'my-custom-format/sample-output', {
- title: 'Sample output',
- tagName: 'samp',
- className: null,
- edit: MyCustomButton,
-} );
+registerFormatType('my-custom-format/sample-output', {
+ title: 'Sample output',
+ tagName: 'samp',
+ className: null,
+ edit: MyCustomButton,
+});
```
Confirm it is working: first build and reload, then make a text selection and click the button. Your browser will likely display that selection differently than the surrounding text.
@@ -140,37 +140,37 @@ import { registerFormatType, toggleFormat } from '@wordpress/rich-text';
import { RichTextToolbarButton } from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
-function ConditionalButton( { isActive, onChange, value } ) {
- const selectedBlock = useSelect( ( select ) => {
- return select( 'core/block-editor' ).getSelectedBlock();
- }, [] );
-
- if ( selectedBlock && selectedBlock.name !== 'core/paragraph' ) {
- return null;
- }
-
- return (
- {
- onChange(
- toggleFormat( value, {
- type: 'my-custom-format/sample-output',
- } )
- );
- } }
- isActive={ isActive }
- />
- );
+function ConditionalButton({ isActive, onChange, value }) {
+ const selectedBlock = useSelect((select) => {
+ return select('core/block-editor').getSelectedBlock();
+ }, []);
+
+ if (selectedBlock && selectedBlock.name !== 'core/paragraph') {
+ return null;
+ }
+
+ return (
+ {
+ onChange(
+ toggleFormat(value, {
+ type: 'my-custom-format/sample-output',
+ })
+ );
+ }}
+ isActive={isActive}
+ />
+ );
}
-registerFormatType( 'my-custom-format/sample-output', {
- title: 'Sample output',
- tagName: 'samp',
- className: null,
- edit: ConditionalButton,
-} );
+registerFormatType('my-custom-format/sample-output', {
+ title: 'Sample output',
+ tagName: 'samp',
+ className: null,
+ edit: ConditionalButton,
+});
```
### Step 5: Add a button outside of the dropdown (Optional)
@@ -182,53 +182,53 @@ import { registerFormatType, toggleFormat } from '@wordpress/rich-text';
import { BlockControls } from '@wordpress/block-editor';
import { ToolbarGroup, ToolbarButton } from '@wordpress/components';
-const MyCustomButton = ( { isActive, onChange, value } ) => {
- return (
-
-
- {
- onChange(
- toggleFormat( value, {
- type: 'my-custom-format/sample-output',
- } )
- );
- } }
- isActive={ isActive }
- />
-
-
- );
+const MyCustomButton = ({ isActive, onChange, value }) => {
+ return (
+
+
+ {
+ onChange(
+ toggleFormat(value, {
+ type: 'my-custom-format/sample-output',
+ })
+ );
+ }}
+ isActive={isActive}
+ />
+
+
+ );
};
-registerFormatType( 'my-custom-format/sample-output', {
- title: 'Sample output',
- tagName: 'samp',
- className: null,
- edit: MyCustomButton,
-} );
+registerFormatType('my-custom-format/sample-output', {
+ title: 'Sample output',
+ tagName: 'samp',
+ className: null,
+ edit: MyCustomButton,
+});
```
## Troubleshooting
If you run into errors:
-- Double check that you run `npm run build` first.
-- Confirm no syntax errors or issues in build process.
-- Confirm the JavaScript is loading in the editor.
-- Check for any console error messages.
+- Double check that you run `npm run build` first.
+- Confirm no syntax errors or issues in build process.
+- Confirm the JavaScript is loading in the editor.
+- Check for any console error messages.
## Additional resources
Reference documentation used in this guide:
-- RichText: [`registerFormatType`](/packages/rich-text/README.md#registerformattype)
-- Components: [`RichTextToolbarButton`](/packages/block-editor/README.md#richtexttoolbarbutton)
-- RichText: [`applyFormat`](/packages/rich-text/README.md#applyformat)
-- RichText: [`removeFormat`](/packages/rich-text/README.md#removeformat)
-- RichText: [`toggleFormat`](/packages/rich-text/README.md#toggleformat)
+- RichText: [`registerFormatType`](/packages/rich-text/README.md#registerformattype)
+- Components: [`RichTextToolbarButton`](/packages/block-editor/README.md#richtexttoolbarbutton)
+- RichText: [`applyFormat`](/packages/rich-text/README.md#applyformat)
+- RichText: [`removeFormat`](/packages/rich-text/README.md#removeformat)
+- RichText: [`toggleFormat`](/packages/rich-text/README.md#toggleformat)
## Conclusion
diff --git a/gutenberg/how-to-guides/internationalization.md b/docs/gutenberg/how-to-guides/internationalization.md
similarity index 84%
rename from gutenberg/how-to-guides/internationalization.md
rename to docs/gutenberg/how-to-guides/internationalization.md
index cd341f1..509bda8 100644
--- a/gutenberg/how-to-guides/internationalization.md
+++ b/docs/gutenberg/how-to-guides/internationalization.md
@@ -28,7 +28,7 @@ function myguten_block_init() {
);
register_block_type( 'myguten/simple', array(
- 'api_version' => 3,
+ 'api_version' => 3,
'editor_script' => 'myguten-script',
) );
}
@@ -42,32 +42,32 @@ import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
-registerBlockType( 'myguten/simple', {
- apiVersion: 3,
- title: __( 'Simple Block', 'myguten' ),
- category: 'widgets',
+registerBlockType('myguten/simple', {
+ apiVersion: 3,
+ title: __('Simple Block', 'myguten'),
+ category: 'widgets',
- edit: () => {
- const blockProps = useBlockProps( { style: { color: 'red' } } );
+ edit: () => {
+ const blockProps = useBlockProps({ style: { color: 'red' } });
- return
;
+ },
+});
```
In the above example, the function will use the first argument for the string to be translated. The second argument is the text domain which must match the text domain slug specified by your plugin.
Common functions available, these mirror their PHP counterparts are:
-- `__( 'Hello World', 'my-text-domain' )` - Translate a certain string.
-- `_n( '%s Comment', '%s Comments', numberOfComments, 'my-text-domain' )` - Translate and retrieve the singular or plural form based on the supplied number.
-- `_x( 'Default', 'block style', 'my-text-domain' )` - Translate a certain string with some additional context.
+- `__( 'Hello World', 'my-text-domain' )` - Translate a certain string.
+- `_n( '%s Comment', '%s Comments', numberOfComments, 'my-text-domain' )` - Translate and retrieve the singular or plural form based on the supplied number.
+- `_x( 'Default', 'block style', 'my-text-domain' )` - Translate a certain string with some additional context.
Note: Every string displayed to the user should be wrapped in an i18n function.
@@ -77,10 +77,10 @@ After all strings in your code is wrapped, the final step is to tell WordPress y
```php
true,
- 'single' => true,
- 'type' => 'string',
- ) );
+ register_post_meta( 'post', 'myguten_meta_block_field', array(
+ 'show_in_rest' => true,
+ 'single' => true,
+ 'type' => 'string',
+ ) );
}
add_action( 'init', 'myguten_register_post_meta' );
```
@@ -73,40 +73,37 @@ import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
import { useBlockProps } from '@wordpress/block-editor';
-registerBlockType( 'myguten/meta-block', {
- edit: ( { setAttributes, attributes } ) => {
- const blockProps = useBlockProps();
- const postType = useSelect(
- ( select ) => select( 'core/editor' ).getCurrentPostType(),
- []
- );
-
- const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
-
- const metaFieldValue = meta[ 'myguten_meta_block_field' ];
- const updateMetaValue = ( newValue ) => {
- setMeta( { ...meta, myguten_meta_block_field: newValue } );
- };
-
- return (
-
-
-
- );
- },
-
- // No information saved to the block.
- // Data is saved to post meta via the hook.
- save: () => {
- return null;
- },
-} );
+registerBlockType('myguten/meta-block', {
+ edit: ({ setAttributes, attributes }) => {
+ const blockProps = useBlockProps();
+ const postType = useSelect((select) => select('core/editor').getCurrentPostType(), []);
+
+ const [meta, setMeta] = useEntityProp('postType', postType, 'meta');
+
+ const metaFieldValue = meta['myguten_meta_block_field'];
+ const updateMetaValue = (newValue) => {
+ setMeta({ ...meta, myguten_meta_block_field: newValue });
+ };
+
+ return (
+
+
+
+ );
+ },
+
+ // No information saved to the block.
+ // Data is saved to post meta via the hook.
+ save: () => {
+ return null;
+ },
+});
```
Confirm this works by creating a post and add the Meta Block. You will see your field that you can type a value in. When you save the post, either as a draft or published, the post meta value will be saved too. You can verify by saving and reloading your draft, the form will still be filled in on reload.
@@ -125,12 +122,12 @@ The first example uses the value from the post meta field and appends it to the
```php
function myguten_content_filter( $content ) {
- $value = get_post_meta( get_the_ID(), 'myguten_meta_block_field', true );
- if ( $value ) {
- return sprintf( "%s
", $content, esc_html( $value ) );
+ } else {
+ return $content;
+ }
}
add_filter( 'the_content', 'myguten_content_filter' );
```
@@ -143,18 +140,18 @@ In PHP, use the [register_block_type](https://developer.wordpress.org/reference/
```php
function myguten_render_paragraph( $block_attributes, $content ) {
- $value = get_post_meta( get_the_ID(), 'myguten_meta_block_field', true );
- // check value is set before outputting
- if ( $value ) {
- return sprintf( "%s (%s)", $content, esc_html( $value ) );
- } else {
- return $content;
- }
+ $value = get_post_meta( get_the_ID(), 'myguten_meta_block_field', true );
+ // check value is set before outputting
+ if ( $value ) {
+ return sprintf( "%s (%s)", $content, esc_html( $value ) );
+ } else {
+ return $content;
+ }
}
register_block_type( 'core/paragraph', array(
- 'api_version' => 3,
- 'render_callback' => 'myguten_render_paragraph',
+ 'api_version' => 3,
+ 'render_callback' => 'myguten_render_paragraph',
) );
```
@@ -192,10 +189,10 @@ If a meta box _doesn't_ work with the block editor, and updating it to work corr
```php
add_meta_box( 'my-meta-box', 'My Meta Box', 'my_meta_box_callback',
- null, 'normal', 'high',
- array(
- '__block_editor_compatible_meta_box' => false,
- )
+ null, 'normal', 'high',
+ array(
+ '__block_editor_compatible_meta_box' => false,
+ )
);
```
@@ -205,10 +202,10 @@ After a meta box is converted to a block, it can be declared as existing for bac
```php
add_meta_box( 'my-meta-box', 'My Meta Box', 'my_meta_box_callback',
- null, 'normal', 'high',
- array(
- '__back_compat_meta_box' => true,
- )
+ null, 'normal', 'high',
+ array(
+ '__back_compat_meta_box' => true,
+ )
);
```
@@ -255,9 +252,9 @@ This page mimics the `post.php` post form, so when it is submitted it will fire
Most PHP meta boxes should continue to work in the block editor, but some meta boxes that include advanced functionality could break. Here are some common reasons why meta boxes might not work as expected in the block editor:
-- Plugins relying on selectors that target the post title, post content fields, and other metaboxes (of the old editor).
-- Plugins relying on TinyMCE's API because there's no longer a single TinyMCE instance to talk to in the block editor.
-- Plugins making updates to their DOM on "submit" or on "save".
+- Plugins relying on selectors that target the post title, post content fields, and other metaboxes (of the old editor).
+- Plugins relying on TinyMCE's API because there's no longer a single TinyMCE instance to talk to in the block editor.
+- Plugins making updates to their DOM on "submit" or on "save".
Please also note that if your plugin triggers a PHP warning or notice to be output on the page, this will cause the HTML document type (``) to be output incorrectly. This will cause the browser to render using "Quirks Mode", which is a compatibility layer that gets enabled when the browser doesn't know what type of document it is parsing. The block editor is not meant to work in this mode, but it can _appear_ to be working just fine. If you encounter issues such as _meta boxes overlaying the editor_ or other layout issues, please check the raw page source of your document to see that the document type definition is the first thing output on the page. There will also be a warning in the JavaScript console, noting the issue.
diff --git a/gutenberg/how-to-guides/notices/README.md b/docs/gutenberg/how-to-guides/notices/README.md
similarity index 66%
rename from gutenberg/how-to-guides/notices/README.md
rename to docs/gutenberg/how-to-guides/notices/README.md
index 479d448..f06f244 100644
--- a/gutenberg/how-to-guides/notices/README.md
+++ b/docs/gutenberg/how-to-guides/notices/README.md
@@ -18,19 +18,19 @@ Producing an equivalent "Post draft updated" notice would require code like this
* a generic HTML notice.
*/
function myguten_admin_notice() {
- $screen = get_current_screen();
- // Only render this notice in the post editor.
- if ( ! $screen || 'post' !== $screen->base ) {
- return;
- }
- // Render the notice's HTML.
- wp_admin_notice(
- sprintf( __( 'Post draft updated. Preview post' ), get_preview_post_link() ),
- array(
- 'type' => 'success',
- 'dismissible' => true,
- )
- );
+ $screen = get_current_screen();
+ // Only render this notice in the post editor.
+ if ( ! $screen || 'post' !== $screen->base ) {
+ return;
+ }
+ // Render the notice's HTML.
+ wp_admin_notice(
+ sprintf( __( 'Post draft updated. Preview post' ), get_preview_post_link() ),
+ array(
+ 'type' => 'success',
+ 'dismissible' => true,
+ )
+ );
};
add_action( 'admin_notices', 'myguten_admin_notice' );
```
@@ -46,32 +46,32 @@ In the block editor, here's an example of the "Post published" notice:
Producing an equivalent "Post published" notice would require code like this:
```js
-( function ( wp ) {
- wp.data.dispatch( 'core/notices' ).createNotice(
- 'success', // Can be one of: success, info, warning, error.
- 'Post published.', // Text string to display.
- {
- isDismissible: true, // Whether the user can dismiss the notice.
- // Any actions the user can perform.
- actions: [
- {
- url: '#',
- label: 'View post',
- },
- ],
- }
- );
-} )( window.wp );
+(function (wp) {
+ wp.data.dispatch('core/notices').createNotice(
+ 'success', // Can be one of: success, info, warning, error.
+ 'Post published.', // Text string to display.
+ {
+ isDismissible: true, // Whether the user can dismiss the notice.
+ // Any actions the user can perform.
+ actions: [
+ {
+ url: '#',
+ label: 'View post',
+ },
+ ],
+ }
+ );
+})(window.wp);
```
You'll want to use this _Notices Data API_ when producing a notice from within the JavaScript application lifecycle.
To better understand the specific code example above:
-- `wp` is WordPress global window variable.
-- `wp.data` is an object provided by the block editor for accessing the block editor data store.
-- `wp.data.dispatch('core/notices')` accesses functionality registered to the block editor data store by the Notices package.
-- `createNotice()` is a function offered by the Notices package to register a new notice. The block editor reads from the notice data store in order to know which notices to display.
+- `wp` is WordPress global window variable.
+- `wp.data` is an object provided by the block editor for accessing the block editor data store.
+- `wp.data.dispatch('core/notices')` accesses functionality registered to the block editor data store by the Notices package.
+- `createNotice()` is a function offered by the Notices package to register a new notice. The block editor reads from the notice data store in order to know which notices to display.
Check out the [_Enqueueing assets in the Editor_](/docs/how-to-guides/enqueueing-assets-in-the-editor.md) tutorial for a primer on how to load your custom JavaScript into the block editor.
diff --git a/gutenberg/how-to-guides/notices/block-editor-notice.png b/docs/gutenberg/how-to-guides/notices/block-editor-notice.png
similarity index 100%
rename from gutenberg/how-to-guides/notices/block-editor-notice.png
rename to docs/gutenberg/how-to-guides/notices/block-editor-notice.png
diff --git a/gutenberg/how-to-guides/notices/classic-editor-notice.png b/docs/gutenberg/how-to-guides/notices/classic-editor-notice.png
similarity index 100%
rename from gutenberg/how-to-guides/notices/classic-editor-notice.png
rename to docs/gutenberg/how-to-guides/notices/classic-editor-notice.png
diff --git a/gutenberg/how-to-guides/platform/README.md b/docs/gutenberg/how-to-guides/platform/README.md
similarity index 92%
rename from gutenberg/how-to-guides/platform/README.md
rename to docs/gutenberg/how-to-guides/platform/README.md
index 731ae26..cd6356c 100644
--- a/gutenberg/how-to-guides/platform/README.md
+++ b/docs/gutenberg/how-to-guides/platform/README.md
@@ -20,7 +20,7 @@ Usage in React:
import { Button } from '@wordpress/components';
function MyApp() {
- return ;
+ return ;
}
```
@@ -41,12 +41,12 @@ npm install --save-dev @wordpress/scripts
You can then add a scripts section to your package.json file, for example:
```json
- "scripts": {
- "build": "wp-scripts build",
- "format": "wp-scripts format",
- "lint:js": "wp-scripts lint-js",
- "start": "wp-scripts start"
- }
+ "scripts": {
+ "build": "wp-scripts build",
+ "format": "wp-scripts format",
+ "lint:js": "wp-scripts lint-js",
+ "start": "wp-scripts start"
+ }
```
You can then use `npm run build` to build your project with all the default webpack settings already configured, likewise for formatting and linting. The `start` command is used for development mode. See the [`@wordpress/scripts` package](/packages/scripts/README.md) for full documentation.
@@ -58,4 +58,3 @@ For more info, see the [Getting Started with JavaScript tutorial](/docs/how-to-g
The [`@wordpress/block-editor` package](https://developer.wordpress.org/block-editor/packages/packages-block-editor/) allows you to create and use standalone block editors.
You can learn more by reading the [tutorial "Building a custom block editor"](/docs/how-to-guides/platform/custom-block-editor.md).
-
diff --git a/gutenberg/how-to-guides/platform/custom-block-editor.md b/docs/gutenberg/how-to-guides/platform/custom-block-editor.md
similarity index 81%
rename from gutenberg/how-to-guides/platform/custom-block-editor.md
rename to docs/gutenberg/how-to-guides/platform/custom-block-editor.md
index b376cc3..878291a 100644
--- a/gutenberg/how-to-guides/platform/custom-block-editor.md
+++ b/docs/gutenberg/how-to-guides/platform/custom-block-editor.md
@@ -19,7 +19,7 @@ This guide will walk you through building a fully functioning, custom block edit
By the end of this article, you will have a solid understanding of the block editor's inner workings and be well on your way to creating your own block editor instances.
- The code used throughout this guide is available for download in the accompanying WordPress plugin. The demo code in this plugin as an essential resource.
+ The code used throughout this guide is available for download in the accompanying WordPress plugin. The demo code in this plugin as an essential resource.
## Code syntax
@@ -36,9 +36,9 @@ While it looks similar, this editor will not be the same _Block Editor_ you are
The editor will have the following features:
-- Ability to add and edit all Core blocks.
-- Familiar visual styles and main/sidebar layout.
-- _Basic_ block persistence between page reloads.
+- Ability to add and edit all Core blocks.
+- Familiar visual styles and main/sidebar layout.
+- _Basic_ block persistence between page reloads.
## Plugin setup and organization
@@ -50,15 +50,15 @@ The plugin file structure will look like this:
Here is a brief summary of what's going on:
-- `plugin.php` – Standard plugin "entry" file with comment meta data, which requires `init.php`.
-- `init.php` - Handles the initialization of the main plugin logic.
-- `src/` (directory) - This is where the JavaScript and CSS source files will live. These files are _not_ directly enqueued by the plugin.
-- `webpack.config.js` - A custom Webpack config extending the defaults provided by the [`@wordpress/scripts`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/) npm package to allow for custom CSS styles (via Sass).
+- `plugin.php` – Standard plugin "entry" file with comment meta data, which requires `init.php`.
+- `init.php` - Handles the initialization of the main plugin logic.
+- `src/` (directory) - This is where the JavaScript and CSS source files will live. These files are _not_ directly enqueued by the plugin.
+- `webpack.config.js` - A custom Webpack config extending the defaults provided by the [`@wordpress/scripts`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/) npm package to allow for custom CSS styles (via Sass).
The only item not shown above is the `build/` directory, which is where the _compiled_ JS and CSS files are outputted by `@wordpress/scripts`. These files are enqueued by the plugin separately.
- Throughout this guide, filename references will be placed in a comment at the top of each code snippet so you can follow along.
+ Throughout this guide, filename references will be placed in a comment at the top of each code snippet so you can follow along.
With the basic file structure in place, let's look at what packages will be needed.
@@ -76,7 +76,7 @@ Perfect, this is the main package you will use to create the custom block editor
Let's begin by creating a custom page within WordPress admin that will house the custom block editor instance.
- If you're already comfortable with the process of creating custom admin pages in WordPress, you might want to skip ahead.
+ If you're already comfortable with the process of creating custom admin pages in WordPress, you might want to skip ahead.
### Registering the page
@@ -108,14 +108,14 @@ Let's use the `getdave_sbe_render_block_editor` function referenced in the step
// File: init.php
function getdave_sbe_render_block_editor() {
- ?>
-
- It is possible to render the editor from PHP without creating an unnecessary JS global. Check out the Edit Site package in the Gutenberg plugin for an example of this.
+ It is possible to render the editor from PHP without creating an unnecessary JS global. Check out the Edit Site package in the Gutenberg plugin for an example of this.
## Reviewing the `` component
@@ -263,17 +261,17 @@ With these components available, you can define the `` component.
```jsx
// File: src/editor.js
-function Editor( { settings } ) {
- return (
-
-
+
+ );
}
```
@@ -281,10 +279,10 @@ In this process, the core of the editor's layout is being scaffolded, along with
Let's examine these in more detail:
-- `` – Enables the use of [dropzones for drag and drop functionality](https://github.com/WordPress/gutenberg/tree/e38dbe958c04d8089695eb686d4f5caff2707505/packages/components/src/drop-zone)
-- `` – Provides a "snack bar" Notice that will be rendered if any messages are dispatched to the `core/notices` store
-- `` – Renders the static title "Standalone Block Editor" at the top of the editor UI
-- `` – The custom block editor component
+- `` – Enables the use of [dropzones for drag and drop functionality](https://github.com/WordPress/gutenberg/tree/e38dbe958c04d8089695eb686d4f5caff2707505/packages/components/src/drop-zone)
+- `` – Provides a "snack bar" Notice that will be rendered if any messages are dispatched to the `core/notices` store
+- `` – Renders the static title "Standalone Block Editor" at the top of the editor UI
+- `` – The custom block editor component
### Keyboard navigation
@@ -294,7 +292,7 @@ is wrap everything in the [`navigateRegions` HOC](https://github.com/WordPress/g
```jsx
// File: src/editor.js
-export default navigateRegions( Editor );
+export default navigateRegions(Editor);
```
## The custom ``
@@ -309,19 +307,19 @@ Opening `src/components/block-editor/index.js` reveals that it's the most comple
// File: src/components/block-editor/index.js
return (
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
);
```
@@ -339,10 +337,10 @@ The children of `` comprise the UI for the block editor. Th
// File: src/components/block-editor/index.js
```
@@ -354,10 +352,10 @@ Internally it does this by subscribing to the provided `registry` (via the [`wit
For the purposes of this simple project, these features allow you to:
-- Store the array of current blocks in state as `blocks`.
-- Update the `blocks` state in memory on `onInput` by calling the hook setter
- `updateBlocks(blocks)`.
-- Handle basic persistence of blocks into `localStorage` using `onChange`. This is [fired when block updates are considered "committed"](https://github.com/WordPress/gutenberg/tree/HEAD/packages/block-editor/src/components/provider#onchange).
+- Store the array of current blocks in state as `blocks`.
+- Update the `blocks` state in memory on `onInput` by calling the hook setter
+ `updateBlocks(blocks)`.
+- Handle basic persistence of blocks into `localStorage` using `onChange`. This is [fired when block updates are considered "committed"](https://github.com/WordPress/gutenberg/tree/HEAD/packages/block-editor/src/components/provider#onchange).
It's also worth recalling that the component accepts a `settings` property. This is where you will add the editor settings inlined earlier as JSON within `init.php`. You can use these settings to configure features such as custom colors, available image sizes, and [much more](https://github.com/WordPress/gutenberg/tree/4c472c3443513d070a50ba1e96f3a476861447b3/packages/block-editor#SETTINGS_DEFAULTS).
@@ -379,25 +377,24 @@ The hierarchy of these components can be _approximated_ as follows:
// Pseudo code for example purposes only.
- /* renders a list of blocks from the rootClientId. */
-
- /* renders a single block from the BlockList. */
-
- /* renders the standard editable area of a block. */
- /* renders the block UI as defined by its `edit()` implementation.
- */
-
-
+ /* renders a list of blocks from the rootClientId. */
+
+ /* renders a single block from the BlockList. */
+
+ /* renders the standard editable area of a block. */
+ /* renders the block UI as defined by its `edit()` implementation. */
+
+
```
Here is roughly how this works together to render the list of blocks:
-- `` loops over all the block `clientIds` and
- renders each via [``](https://github.com/WordPress/gutenberg/blob/e38dbe958c04d8089695eb686d4f5caff2707505/packages/block-editor/src/components/block-list/block.js).
-- ``, in turn, renders the individual block
- using its own subcomponent [``](https://github.com/WordPress/gutenberg/blob/def076809d25e2ad680beda8b9205ab9dea45a0f/packages/block-editor/src/components/block-edit/index.js).
-- Finally, the [block itself](https://github.com/WordPress/gutenberg/blob/def076809d25e2ad680beda8b9205ab9dea45a0f/packages/block-editor/src/components/block-edit/edit.js) is rendered using the `Component` placeholder component.
+- `` loops over all the block `clientIds` and
+ renders each via [``](https://github.com/WordPress/gutenberg/blob/e38dbe958c04d8089695eb686d4f5caff2707505/packages/block-editor/src/components/block-list/block.js).
+- ``, in turn, renders the individual block
+ using its own subcomponent [``](https://github.com/WordPress/gutenberg/blob/def076809d25e2ad680beda8b9205ab9dea45a0f/packages/block-editor/src/components/block-edit/index.js).
+- Finally, the [block itself](https://github.com/WordPress/gutenberg/blob/def076809d25e2ad680beda8b9205ab9dea45a0f/packages/block-editor/src/components/block-edit/edit.js) is rendered using the `Component` placeholder component.
The `@wordpress/block-editor` package components are among the most complex and involved. Understanding them is crucial if you want to grasp how the editor functions at a fundamental level. Studying these components is strongly advised.
@@ -424,7 +421,7 @@ This is used, in part, to display advanced block settings via the `
-
+
```
@@ -474,7 +471,7 @@ Looking at the `src/components/block-editor/index.js` file, you will notice that
```jsx
// File: src/components/block-editor/index.js
-const [ blocks, updateBlocks ] = useState( [] );
+const [blocks, updateBlocks] = useState([]);
```
As mentioned earlier, `blocks` is passed to the "controlled" component `` as its `value` prop. This "hydrates" it with an initial set of blocks. Similarly, the `updateBlocks` setter is hooked up to the `onInput` callback on ``, which ensures that the block state is kept in sync with changes made to blocks within the editor.
@@ -486,9 +483,9 @@ If you now turn your attention to the `onChange` handler, you will notice it is
```js
// File: src/components/block-editor/index.js
-function persistBlocks( newBlocks ) {
- updateBlocks( newBlocks );
- window.localStorage.setItem( 'getdavesbeBlocks', serialize( newBlocks ) );
+function persistBlocks(newBlocks) {
+ updateBlocks(newBlocks);
+ window.localStorage.setItem('getdavesbeBlocks', serialize(newBlocks));
}
```
@@ -515,24 +512,24 @@ Accessing data is a side effect, so you must use the `useEffect` hook to handle
```jsx
// File: src/components/block-editor/index.js
-useEffect( () => {
- const storedBlocks = window.localStorage.getItem( 'getdavesbeBlocks' );
-
- if ( storedBlocks && storedBlocks.length ) {
- updateBlocks( () => parse( storedBlocks ) );
- createInfoNotice( 'Blocks loaded', {
- type: 'snackbar',
- isDismissible: true,
- } );
- }
-}, [] );
+useEffect(() => {
+ const storedBlocks = window.localStorage.getItem('getdavesbeBlocks');
+
+ if (storedBlocks && storedBlocks.length) {
+ updateBlocks(() => parse(storedBlocks));
+ createInfoNotice('Blocks loaded', {
+ type: 'snackbar',
+ isDismissible: true,
+ });
+ }
+}, []);
```
This handler:
-- Grabs the serialized block data from local storage.
-- Converts the serialized blocks back to JavaScript objects using the `parse()` utility.
-- Calls the state setter `updateBlocks` causing the `blocks` value to be updated in state to reflect the blocks retrieved from LocalStorage.
+- Grabs the serialized block data from local storage.
+- Converts the serialized blocks back to JavaScript objects using the `parse()` utility.
+- Calls the state setter `updateBlocks` causing the `blocks` value to be updated in state to reflect the blocks retrieved from LocalStorage.
As a result of these operations, the controlled `` component is updated with the blocks restored from LocalStorage, causing the editor to show these blocks.
@@ -540,6 +537,6 @@ Finally, you will want to generate a notice - which will display in the ` true,
- 'single' => true,
- 'type' => 'string',
+ 'show_in_rest' => true,
+ 'single' => true,
+ 'type' => 'string',
) );
```
To confirm, query the block editor store to see the field is loaded. After implementing, reload the editor page and open your browser's developer console. Use this JavaScript snippet in the console to confirm:
```js
-wp.data.select( 'core/editor' ).getCurrentPost().meta;
+wp.data.select('core/editor').getCurrentPost().meta;
```
The function will return an object containing the registered meta field you registered.
@@ -199,40 +199,36 @@ If the code returns `undefined` make sure your post type supports `custom-fields
With the field available in the editor store, it can now be surfaced to the UI. We extract the input control to a function to keep the code clean as we add functionality.
```js
-( function ( wp ) {
- var el = React.createElement;
- var registerPlugin = wp.plugins.registerPlugin;
- var PluginSidebar = wp.editor.PluginSidebar;
- var TextControl = wp.components.TextControl;
-
- var MetaBlockField = function () {
- return el( TextControl, {
- label: 'Meta Block Field',
- value: 'Initial value',
- onChange: function ( content ) {
- console.log( 'content changed to ', content );
- },
- } );
- };
-
- registerPlugin( 'my-plugin-sidebar', {
- render: function () {
- return el(
- PluginSidebar,
- {
- name: 'my-plugin-sidebar',
- icon: 'admin-post',
- title: 'My plugin sidebar',
- },
- el(
- 'div',
- { className: 'plugin-sidebar-content' },
- el( MetaBlockField )
- )
- );
- },
- } );
-} )( window.wp );
+(function (wp) {
+ var el = React.createElement;
+ var registerPlugin = wp.plugins.registerPlugin;
+ var PluginSidebar = wp.editor.PluginSidebar;
+ var TextControl = wp.components.TextControl;
+
+ var MetaBlockField = function () {
+ return el(TextControl, {
+ label: 'Meta Block Field',
+ value: 'Initial value',
+ onChange: function (content) {
+ console.log('content changed to ', content);
+ },
+ });
+ };
+
+ registerPlugin('my-plugin-sidebar', {
+ render: function () {
+ return el(
+ PluginSidebar,
+ {
+ name: 'my-plugin-sidebar',
+ icon: 'admin-post',
+ title: 'My plugin sidebar',
+ },
+ el('div', { className: 'plugin-sidebar-content' }, el(MetaBlockField))
+ );
+ },
+ });
+})(window.wp);
```
We want to initialize the value in the `MetaBlockField` component with the value of `sidebar_plugin_meta_block_field`, and keep it updated when that value changes.
@@ -240,47 +236,43 @@ We want to initialize the value in the `MetaBlockField` component with the value
The `useSelect` function is used to fetch data when the component loads and will update if the data changes. Here is the code update with `useSelect`:
```js
-( function ( wp ) {
- var el = React.createElement;
- var registerPlugin = wp.plugins.registerPlugin;
- var PluginSidebar = wp.editor.PluginSidebar;
- var Text = wp.components.TextControl;
- var useSelect = wp.data.useSelect;
-
- var MetaBlockField = function () {
- var metaFieldValue = useSelect( function ( select ) {
- return select( 'core/editor' ).getEditedPostAttribute(
- 'meta'
- )[ 'sidebar_plugin_meta_block_field' ];
- }, [] );
-
- return el( Text, {
- label: 'Meta Block Field',
- value: metaFieldValue,
- onChange: function ( content ) {
- console.log( 'content has changed to ', content );
- },
- } );
- };
-
- registerPlugin( 'my-plugin-sidebar', {
- render: function () {
- return el(
- PluginSidebar,
- {
- name: 'my-plugin-sidebar',
- icon: 'admin-post',
- title: 'My plugin sidebar',
- },
- el(
- 'div',
- { className: 'plugin-sidebar-content' },
- el( MetaBlockField )
- )
- );
- },
- } );
-} )( window.wp );
+(function (wp) {
+ var el = React.createElement;
+ var registerPlugin = wp.plugins.registerPlugin;
+ var PluginSidebar = wp.editor.PluginSidebar;
+ var Text = wp.components.TextControl;
+ var useSelect = wp.data.useSelect;
+
+ var MetaBlockField = function () {
+ var metaFieldValue = useSelect(function (select) {
+ return select('core/editor').getEditedPostAttribute('meta')[
+ 'sidebar_plugin_meta_block_field'
+ ];
+ }, []);
+
+ return el(Text, {
+ label: 'Meta Block Field',
+ value: metaFieldValue,
+ onChange: function (content) {
+ console.log('content has changed to ', content);
+ },
+ });
+ };
+
+ registerPlugin('my-plugin-sidebar', {
+ render: function () {
+ return el(
+ PluginSidebar,
+ {
+ name: 'my-plugin-sidebar',
+ icon: 'admin-post',
+ title: 'My plugin sidebar',
+ },
+ el('div', { className: 'plugin-sidebar-content' }, el(MetaBlockField))
+ );
+ },
+ });
+})(window.wp);
```
The `wp.data.useSelect` function is from the `@wordpress/data` package, so `wp-data` needs to be added as a dependency in the `wp_register_script` function in PHP.
@@ -291,8 +283,8 @@ Confirm it's working by updating the code, reloading, and opening the sidebar. T
```js
wp.data
- .dispatch( 'core/editor' )
- .editPost( { meta: { sidebar_plugin_meta_block_field: 'hello world!' } } );
+ .dispatch('core/editor')
+ .editPost({ meta: { sidebar_plugin_meta_block_field: 'hello world!' } });
```
You can observe the content changing in the input component.
@@ -303,52 +295,48 @@ The last step is to update the meta field when the input content changes.
The `useDispatch` function takes a store name as its only argument and returns methods that you can use to update the store, in this case we'll use `editPost`
```js
-( function ( wp ) {
- var el = React.createElement;
- var registerPlugin = wp.plugins.registerPlugin;
- var PluginSidebar = wp.editor.PluginSidebar;
- var TextControl = wp.components.TextControl;
- var useSelect = wp.data.useSelect;
- var useDispatch = wp.data.useDispatch;
-
- var MetaBlockField = function ( props ) {
- var metaFieldValue = useSelect( function ( select ) {
- return select( 'core/editor' ).getEditedPostAttribute(
- 'meta'
- )[ 'sidebar_plugin_meta_block_field' ];
- }, [] );
-
- var editPost = useDispatch( 'core/editor' ).editPost;
-
- return el( TextControl, {
- label: 'Meta Block Field',
- value: metaFieldValue,
- onChange: function ( content ) {
- editPost( {
- meta: { sidebar_plugin_meta_block_field: content },
- } );
- },
- } );
- };
-
- registerPlugin( 'my-plugin-sidebar', {
- render: function () {
- return el(
- PluginSidebar,
- {
- name: 'my-plugin-sidebar',
- icon: 'admin-post',
- title: 'My plugin sidebar',
- },
- el(
- 'div',
- { className: 'plugin-sidebar-content' },
- el( MetaBlockField )
- )
- );
- },
- } );
-} )( window.wp );
+(function (wp) {
+ var el = React.createElement;
+ var registerPlugin = wp.plugins.registerPlugin;
+ var PluginSidebar = wp.editor.PluginSidebar;
+ var TextControl = wp.components.TextControl;
+ var useSelect = wp.data.useSelect;
+ var useDispatch = wp.data.useDispatch;
+
+ var MetaBlockField = function (props) {
+ var metaFieldValue = useSelect(function (select) {
+ return select('core/editor').getEditedPostAttribute('meta')[
+ 'sidebar_plugin_meta_block_field'
+ ];
+ }, []);
+
+ var editPost = useDispatch('core/editor').editPost;
+
+ return el(TextControl, {
+ label: 'Meta Block Field',
+ value: metaFieldValue,
+ onChange: function (content) {
+ editPost({
+ meta: { sidebar_plugin_meta_block_field: content },
+ });
+ },
+ });
+ };
+
+ registerPlugin('my-plugin-sidebar', {
+ render: function () {
+ return el(
+ PluginSidebar,
+ {
+ name: 'my-plugin-sidebar',
+ icon: 'admin-post',
+ title: 'My plugin sidebar',
+ },
+ el('div', { className: 'plugin-sidebar-content' }, el(MetaBlockField))
+ );
+ },
+ });
+})(window.wp);
```
After the update, when the user types, the input control calls `editPost` and updates the editor store on each keystroke.
@@ -356,9 +344,7 @@ After the update, when the user types, the input control calls `editPost` and up
Update the JavaScript, load the sidebar, and type in the input field. You can confirm it is saved by typing something in the input control and executing the JavaScript snippet in your browser's development console:
```js
-wp.data.select( 'core/editor' ).getEditedPostAttribute( 'meta' )[
- 'sidebar_plugin_meta_block_field'
-];
+wp.data.select('core/editor').getEditedPostAttribute('meta')['sidebar_plugin_meta_block_field'];
```
The message displayed should be what you typed in the input.
@@ -371,9 +357,9 @@ Documentation for working with the [@wordpress/data package](/packages/data/READ
Functions used in this guide:
-- [useSelect](/packages/data/README.md#useselect).
-- [getEditedPostAttribute](/docs/reference-guides/data/data-core-editor.md#geteditedpostattribute)
-- [useDispatch](/packages/data/README.md#usedispatch)
+- [useSelect](/packages/data/README.md#useselect).
+- [getEditedPostAttribute](/docs/reference-guides/data/data-core-editor.md#geteditedpostattribute)
+- [useDispatch](/packages/data/README.md#usedispatch)
## Conclusion
@@ -393,7 +379,7 @@ This problem does not exist if Custom Fields is not enabled.
If you need to have Custom Fields enabled and also have post meta in the sidebar there are two possible solutions:
-1. Precede the name of the meta field with an underscore, so the name in the above example would be `_sidebar_plugin_meta_block_field`. This indicates that the post meta should be treated as private so it will not be visible in the Custom Fields section of a post. With this solution an error will be generated when you save the post unless you add an `auth_callback` property to the `args` array passed to `register_post_meta` with a function that ultimately returns `true`. See the `args` documentation in the [post_meta](https://developer.wordpress.org/reference/functions/register_meta/#parameters) page for more info.
+1. Precede the name of the meta field with an underscore, so the name in the above example would be `_sidebar_plugin_meta_block_field`. This indicates that the post meta should be treated as private so it will not be visible in the Custom Fields section of a post. With this solution an error will be generated when you save the post unless you add an `auth_callback` property to the `args` array passed to `register_post_meta` with a function that ultimately returns `true`. See the `args` documentation in the [post_meta](https://developer.wordpress.org/reference/functions/register_meta/#parameters) page for more info.
2. In the TextControl's `onChange` function, target the Value field textarea and set the value there to be the same as the value in the TextControl meta field. The value will then be identical in both places and so you can be assured that if the value is changed in the TextControl then it will still be saved to the database.
```js
diff --git a/gutenberg/how-to-guides/propagating-updates.md b/docs/gutenberg/how-to-guides/propagating-updates.md
similarity index 81%
rename from gutenberg/how-to-guides/propagating-updates.md
rename to docs/gutenberg/how-to-guides/propagating-updates.md
index 8079048..9f8a7e7 100644
--- a/gutenberg/how-to-guides/propagating-updates.md
+++ b/docs/gutenberg/how-to-guides/propagating-updates.md
@@ -18,7 +18,7 @@ The more that you approach design at the block level, the less need there is to
### Blocks
-How to manage block updates depends on the nature of the block itself. If the block depends on external data, then making it dynamic from start with the `render_callback` function is often a better choice as it provides more control. If the block's structure is expected to change over time, then starting with the static block that uses `save()` method defining a default output is the recommended approach. Over time, it's possible to go hybrid and include also the `render_callback` that can use the output from `save` as a fallback while processing an alternate output. Keep in mind that that flexibility and controls comes at the cost of additional processing during rendering. Another option is using static blocks that rely on managing updates with [block deprecations](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-deprecation/). This will require you to manually update exist blocks. Depending on your needs and comfortability, either approach can work. **To get started on creating blocks and save time, [you can use the Create Block tool](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/).**
+How to manage block updates depends on the nature of the block itself. If the block depends on external data, then making it dynamic from start with the `render_callback` function is often a better choice as it provides more control. If the block's structure is expected to change over time, then starting with the static block that uses `save()` method defining a default output is the recommended approach. Over time, it's possible to go hybrid and include also the `render_callback` that can use the output from `save` as a fallback while processing an alternate output. Keep in mind that that flexibility and controls comes at the cost of additional processing during rendering. Another option is using static blocks that rely on managing updates with [block deprecations](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-deprecation/). This will require you to manually update exist blocks. Depending on your needs and comfortability, either approach can work. **To get started on creating blocks and save time, [you can use the Create Block tool](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/).**
### Patterns
@@ -29,12 +29,12 @@ If needed, one potential workaround for patterns with custom styles is to add a
```
-
+
```
-It is not fool-proof because users can modify the class via the editor UI. However, because this setting is under the "Advanced" panel it is likely to stay intact in most instances. This gives theme authors some CSS control for some pattern types, allowing them to update existing uses. However, it does not prevent users from making massive alterations that cannot be updated.
+It is not fool-proof because users can modify the class via the editor UI. However, because this setting is under the "Advanced" panel it is likely to stay intact in most instances. This gives theme authors some CSS control for some pattern types, allowing them to update existing uses. However, it does not prevent users from making massive alterations that cannot be updated.
### Synced Patterns
@@ -49,14 +49,12 @@ Because block themes allow users to directly edit templates and template parts,
Generally speaking, if a user has made changes to templates then it’s recommended to leave the templates as is, unless agreed upon with the user (ie in an agency setting).
-One thing to be mindful of when updating templates is inserting references to new or different template parts. For example, the templates/page.html template could insert a parts/header.html part in version 1.0 but change that reference to parts/header-alt.html in version 2.0. Some developers may see this as a "workaround" in instances where users modified the original header.html. However, this is likely to break a user's customized design since the page.html template would no longer reference the correct part unless they also modified and saved the page template.
+One thing to be mindful of when updating templates is inserting references to new or different template parts. For example, the templates/page.html template could insert a parts/header.html part in version 1.0 but change that reference to parts/header-alt.html in version 2.0. Some developers may see this as a "workaround" in instances where users modified the original header.html. However, this is likely to break a user's customized design since the page.html template would no longer reference the correct part unless they also modified and saved the page template.
-Likewise, it is generally poor practice to delete template parts in theme updates. In this scenario, users could create custom top-level templates that include a call to the part and expect it to continue existing.
+Likewise, it is generally poor practice to delete template parts in theme updates. In this scenario, users could create custom top-level templates that include a call to the part and expect it to continue existing.
### Resources
- [Comparing Patterns, Template Parts, and Reusable Blocks](https://wordpress.org/documentation/article/comparing-patterns-template-parts-and-reusable-blocks/)
- [Block deprecation](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-deprecation/)
- [Create Block tool](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/)
-
-
diff --git a/gutenberg/how-to-guides/themes/README.md b/docs/gutenberg/how-to-guides/themes/README.md
similarity index 79%
rename from gutenberg/how-to-guides/themes/README.md
rename to docs/gutenberg/how-to-guides/themes/README.md
index 1510b20..df726f0 100644
--- a/gutenberg/how-to-guides/themes/README.md
+++ b/docs/gutenberg/how-to-guides/themes/README.md
@@ -10,7 +10,7 @@ In terms of block editor terminology this is any theme that defines its template
### Block theme
-This is any theme that has, at a minimum, an `index.html` format template in the `/block-templates` or `/templates` folders, and with templates provided in form of block content markup. While many `Block` themes will make use of a `theme.json` file to provide configuration and styling settings, a `theme.json` is not a requirement of `Block` themes. The advantage of `Block` themes is that the block editor can be used to edit all areas of the site: headers, footers, sidebars, etc.
+This is any theme that has, at a minimum, an `index.html` format template in the `/block-templates` or `/templates` folders, and with templates provided in form of block content markup. While many `Block` themes will make use of a `theme.json` file to provide configuration and styling settings, a `theme.json` is not a requirement of `Block` themes. The advantage of `Block` themes is that the block editor can be used to edit all areas of the site: headers, footers, sidebars, etc.
### Full site editing (FSE)
diff --git a/gutenberg/how-to-guides/themes/global-settings-and-styles.md b/docs/gutenberg/how-to-guides/themes/global-settings-and-styles.md
similarity index 60%
rename from gutenberg/how-to-guides/themes/global-settings-and-styles.md
rename to docs/gutenberg/how-to-guides/themes/global-settings-and-styles.md
index e0b7653..ee1b6b6 100644
--- a/gutenberg/how-to-guides/themes/global-settings-and-styles.md
+++ b/docs/gutenberg/how-to-guides/themes/global-settings-and-styles.md
@@ -12,9 +12,9 @@ This describes the current efforts to consolidate the various APIs related to st
Instead of the proliferation of theme support flags or alternative methods, the `theme.json` files provides a canonical way to define the settings of the block editor. These settings includes things like:
-- What customization options should be made available or hidden from the user.
-- What are the default colors, font sizes... available to the user.
-- Defines the default layout of the editor (widths and available alignments).
+- What customization options should be made available or hidden from the user.
+- What are the default colors, font sizes... available to the user.
+- Defines the default layout of the editor (widths and available alignments).
### Settings can be controlled per block
@@ -22,9 +22,9 @@ For more granularity, these settings also work at the block level in `theme.json
Examples of what can be achieved are:
-- Use a particular preset for a block (e.g.: table) but the common one for the rest of blocks.
-- Enable font size UI controls for all blocks but the headings block.
-- etc.
+- Use a particular preset for a block (e.g.: table) but the common one for the rest of blocks.
+- Enable font size UI controls for all blocks but the headings block.
+- etc.
### Styles are managed
@@ -48,23 +48,23 @@ To address this need, we've started to experiment with CSS Custom Properties, ak
```json
{
- "version": 3,
- "settings": {
- "color": {
- "palette": [
- {
- "name": "Black",
- "slug": "black",
- "color": "#000000"
- },
- {
- "name": "White",
- "slug": "white",
- "color": "#ffffff"
- }
- ]
- }
- }
+ "version": 3,
+ "settings": {
+ "color": {
+ "palette": [
+ {
+ "name": "Black",
+ "slug": "black",
+ "color": "#000000"
+ },
+ {
+ "name": "White",
+ "slug": "white",
+ "color": "#ffffff"
+ }
+ ]
+ }
+ }
}
```
@@ -72,29 +72,29 @@ To address this need, we've started to experiment with CSS Custom Properties, ak
```css
body {
- --wp--preset--color--black: #000000;
- --wp--preset--color--white: #ffffff;
+ --wp--preset--color--black: #000000;
+ --wp--preset--color--white: #ffffff;
}
```
{% end %}
-- **Custom properties**: there's also a mechanism to create your own CSS Custom Properties.
+- **Custom properties**: there's also a mechanism to create your own CSS Custom Properties.
{% codetabs %}
{% Input %}
```json
{
- "version": 3,
- "settings": {
- "custom": {
- "line-height": {
- "body": 1.7,
- "heading": 1.3
- }
- }
- }
+ "version": 3,
+ "settings": {
+ "custom": {
+ "line-height": {
+ "body": 1.7,
+ "heading": 1.3
+ }
+ }
+ }
}
```
@@ -102,8 +102,8 @@ body {
```css
body {
- --wp--custom--line-height--body: 1.7;
- --wp--custom--line-height--heading: 1.3;
+ --wp--custom--line-height--body: 1.7;
+ --wp--custom--line-height--heading: 1.3;
}
```
@@ -115,11 +115,11 @@ This specification is the same for the three different origins that use this for
```json
{
- "version": 3,
- "settings": {},
- "styles": {},
- "customTemplates": {},
- "templateParts": {}
+ "version": 3,
+ "settings": {},
+ "styles": {},
+ "customTemplates": {},
+ "templateParts": {}
}
```
@@ -139,6 +139,7 @@ Follow the instructions in [migrating to newer versions](https://developer.wordp
The Gutenberg plugin extends the settings available from WordPress 5.8, so they can be used with other WordPress versions and they go through a maturation process before being ported to core.
The tabs below show WordPress 5.8 supported settings and the ones supported by the Gutenberg plugin.
+
Each block declares which style properties it exposes via the [block supports mechanism](/docs/reference-guides/block-api/block-supports.md). The support declarations are used to automatically generate the UI controls for the block in the editor. Themes can use any style property via the `theme.json` for any block ― it's the theme's responsibility to verify that it works properly according to the block markup, etc.
@@ -677,171 +725,174 @@ Each block declares which style properties it exposes via the [block supports me
```json
{
- "version": 3,
- "styles": {
- "border": {
- "radius": "value",
- "color": "value",
- "style": "value",
- "width": "value"
- },
- "filter": {
- "duotone": "value"
- },
- "color": {
- "background": "value",
- "gradient": "value",
- "text": "value"
- },
- "spacing": {
- "blockGap": "value",
- "margin": {
- "top": "value",
- "right": "value",
- "bottom": "value",
- "left": "value",
- },
- "padding": {
- "top": "value",
- "right": "value",
- "bottom": "value",
- "left": "value"
- }
- },
- "typography": {
- "fontSize": "value",
- "fontStyle": "value",
- "fontWeight": "value",
- "letterSpacing": "value",
- "lineHeight": "value",
- "textDecoration": "value",
- "textTransform": "value"
- },
- "elements": {
- "link": {
- "border": {},
- "color": {},
- "spacing": {},
- "typography": {}
- },
- "h1": {},
- "h2": {},
- "h3": {},
- "h4": {},
- "h5": {},
- "h6": {}
- },
- "blocks": {
- "core/group": {
- "border": {},
- "color": {},
- "spacing": {},
- "typography": {},
- "elements": {
- "link": {},
- "h1": {},
- "h2": {},
- "h3": {},
- "h4": {},
- "h5": {},
- "h6": {}
- }
- },
- "etc": {}
- }
- }
+ "version": 3,
+ "styles": {
+ "border": {
+ "radius": "value",
+ "color": "value",
+ "style": "value",
+ "width": "value"
+ },
+ "filter": {
+ "duotone": "value"
+ },
+ "color": {
+ "background": "value",
+ "gradient": "value",
+ "text": "value"
+ },
+ "spacing": {
+ "blockGap": "value",
+ "margin": {
+ "top": "value",
+ "right": "value",
+ "bottom": "value",
+ "left": "value"
+ },
+ "padding": {
+ "top": "value",
+ "right": "value",
+ "bottom": "value",
+ "left": "value"
+ }
+ },
+ "typography": {
+ "fontSize": "value",
+ "fontStyle": "value",
+ "fontWeight": "value",
+ "letterSpacing": "value",
+ "lineHeight": "value",
+ "textDecoration": "value",
+ "textTransform": "value"
+ },
+ "elements": {
+ "link": {
+ "border": {},
+ "color": {},
+ "spacing": {},
+ "typography": {}
+ },
+ "h1": {},
+ "h2": {},
+ "h3": {},
+ "h4": {},
+ "h5": {},
+ "h6": {}
+ },
+ "blocks": {
+ "core/group": {
+ "border": {},
+ "color": {},
+ "spacing": {},
+ "typography": {},
+ "elements": {
+ "link": {},
+ "h1": {},
+ "h2": {},
+ "h3": {},
+ "h4": {},
+ "h5": {},
+ "h6": {}
+ }
+ },
+ "etc": {}
+ }
+ }
}
```
+
{% Gutenberg %}
```json
{
- "version": 3,
- "styles": {
- "border": {
- "color": "value",
- "radius": "value",
- "style": "value",
- "width": "value"
- },
- "color": {
- "background": "value",
- "gradient": "value",
- "text": "value"
- },
- "dimensions": {
- "aspectRatio": "value",
- "minHeight": "value"
- },
- "filter": {
- "duotone": "value"
- },
- "spacing": {
- "blockGap": "value",
- "margin": {
- "top": "value",
- "right": "value",
- "bottom": "value",
- "left": "value"
- },
- "padding": {
- "top": "value",
- "right": "value",
- "bottom": "value",
- "left": "value"
- }
- },
- "typography": {
- "fontFamily": "value",
- "fontSize": "value",
- "fontStyle": "value",
- "fontWeight": "value",
- "letterSpacing": "value",
- "lineHeight": "value",
- "textColumns": "value",
- "textDecoration": "value",
- "textTransform": "value"
- },
- "elements": {
- "link": {
- "border": {},
- "color": {},
- "spacing": {},
- "typography": {}
- },
- "h1": {},
- "h2": {},
- "h3": {},
- "h4": {},
- "h5": {},
- "h6": {},
- "heading": {},
- "button": {},
- "caption": {}
- },
- "blocks": {
- "core/group": {
- "border": {},
- "color": {},
- "dimensions": {},
- "spacing": {},
- "typography": {},
- "elements": {
- "link": {},
- "h1": {},
- "h2": {},
- "h3": {},
- "h4": {},
- "h5": {},
- "h6": {}
- }
- },
- "etc": {}
- }
- }
+ "version": 3,
+ "styles": {
+ "border": {
+ "color": "value",
+ "radius": "value",
+ "style": "value",
+ "width": "value"
+ },
+ "color": {
+ "background": "value",
+ "gradient": "value",
+ "text": "value"
+ },
+ "dimensions": {
+ "aspectRatio": "value",
+ "minHeight": "value"
+ },
+ "filter": {
+ "duotone": "value"
+ },
+ "spacing": {
+ "blockGap": "value",
+ "margin": {
+ "top": "value",
+ "right": "value",
+ "bottom": "value",
+ "left": "value"
+ },
+ "padding": {
+ "top": "value",
+ "right": "value",
+ "bottom": "value",
+ "left": "value"
+ }
+ },
+ "typography": {
+ "fontFamily": "value",
+ "fontSize": "value",
+ "fontStyle": "value",
+ "fontWeight": "value",
+ "letterSpacing": "value",
+ "lineHeight": "value",
+ "textColumns": "value",
+ "textDecoration": "value",
+ "textTransform": "value"
+ },
+ "elements": {
+ "link": {
+ "border": {},
+ "color": {},
+ "spacing": {},
+ "typography": {}
+ },
+ "h1": {},
+ "h2": {},
+ "h3": {},
+ "h4": {},
+ "h5": {},
+ "h6": {},
+ "heading": {},
+ "button": {},
+ "caption": {}
+ },
+ "blocks": {
+ "core/group": {
+ "border": {},
+ "color": {},
+ "dimensions": {},
+ "spacing": {},
+ "typography": {},
+ "elements": {
+ "link": {},
+ "h1": {},
+ "h2": {},
+ "h3": {},
+ "h4": {},
+ "h5": {},
+ "h6": {}
+ }
+ },
+ "etc": {}
+ }
+ }
}
```
+
{% end %}
+
### Top-level styles
Styles found at the top-level will be enqueued using the `body` selector.
@@ -851,12 +902,12 @@ Styles found at the top-level will be enqueued using the `body` selector.
```json
{
- "version": 3,
- "styles": {
- "color": {
- "text": "var(--wp--preset--color--primary)"
- }
- }
+ "version": 3,
+ "styles": {
+ "color": {
+ "text": "var(--wp--preset--color--primary)"
+ }
+ }
}
```
@@ -864,11 +915,12 @@ Styles found at the top-level will be enqueued using the `body` selector.
```css
body {
- color: var( --wp--preset--color--primary );
+ color: var(--wp--preset--color--primary);
}
```
{% end %}
+
### Block styles
Styles found within a block will be enqueued using the block selector.
@@ -880,24 +932,24 @@ By default, the block selector is generated based on its name such as `.wp-block
```json
{
- "version": 3,
- "styles": {
- "color": {
- "text": "var(--wp--preset--color--primary)"
- },
- "blocks": {
- "core/paragraph": {
- "color": {
- "text": "var(--wp--preset--color--secondary)"
- }
- },
- "core/group": {
- "color": {
- "text": "var(--wp--preset--color--tertiary)"
- }
- }
- }
- }
+ "version": 3,
+ "styles": {
+ "color": {
+ "text": "var(--wp--preset--color--primary)"
+ },
+ "blocks": {
+ "core/paragraph": {
+ "color": {
+ "text": "var(--wp--preset--color--secondary)"
+ }
+ },
+ "core/group": {
+ "color": {
+ "text": "var(--wp--preset--color--tertiary)"
+ }
+ }
+ }
+ }
}
```
@@ -905,15 +957,17 @@ By default, the block selector is generated based on its name such as `.wp-block
```css
body {
- color: var( --wp--preset--color--primary );
+ color: var(--wp--preset--color--primary);
}
-p { /* The core/paragraph opts out from the default behaviour and uses p as a selector. */
- color: var( --wp--preset--color--secondary );
+p {
+ /* The core/paragraph opts out from the default behaviour and uses p as a selector. */
+ color: var(--wp--preset--color--secondary);
}
.wp-block-group {
- color: var( --wp--preset--color--tertiary );
+ color: var(--wp--preset--color--tertiary);
}
```
+
{% end %}
#### Referencing a style
@@ -923,19 +977,19 @@ If you register a background color for the root using styles.color.background:
```JSON
"styles": {
- "color": {
- "background": "var(--wp--preset--color--primary)"
- }
- }
+ "color": {
+ "background": "var(--wp--preset--color--primary)"
+ }
+ }
```
-You can use `ref: "styles.color.background"` to re-use the style for a block:
+You can use `ref: "styles.color.background"` to re-use the style for a block:
```JSON
{
- "color": {
- "text": { "ref": "styles.color.background" }
- }
+ "color": {
+ "text": { "ref": "styles.color.background" }
+ }
}
```
@@ -961,51 +1015,50 @@ Supported by WordPress:
If they're found in the top-level the element selector will be used. If they're found within a block, the selector to be used will be the element's appended to the corresponding block.
-
{% codetabs %}
{% Input %}
```json
{
- "version": 3,
- "styles": {
- "typography": {
- "fontSize": "var(--wp--preset--font-size--normal)"
- },
- "elements": {
- "h1": {
- "typography": {
- "fontSize": "var(--wp--preset--font-size--huge)"
- }
- },
- "h2": {
- "typography": {
- "fontSize": "var(--wp--preset--font-size--big)"
- }
- },
- "h3": {
- "typography": {
- "fontSize": "var(--wp--preset--font-size--medium)"
- }
- }
- },
- "blocks": {
- "core/group": {
- "elements": {
- "h2": {
- "typography": {
- "fontSize": "var(--wp--preset--font-size--small)"
- }
- },
- "h3": {
- "typography": {
- "fontSize": "var(--wp--preset--font-size--smaller)"
- }
- }
- }
- }
- }
- }
+ "version": 3,
+ "styles": {
+ "typography": {
+ "fontSize": "var(--wp--preset--font-size--normal)"
+ },
+ "elements": {
+ "h1": {
+ "typography": {
+ "fontSize": "var(--wp--preset--font-size--huge)"
+ }
+ },
+ "h2": {
+ "typography": {
+ "fontSize": "var(--wp--preset--font-size--big)"
+ }
+ },
+ "h3": {
+ "typography": {
+ "fontSize": "var(--wp--preset--font-size--medium)"
+ }
+ }
+ },
+ "blocks": {
+ "core/group": {
+ "elements": {
+ "h2": {
+ "typography": {
+ "fontSize": "var(--wp--preset--font-size--small)"
+ }
+ },
+ "h3": {
+ "typography": {
+ "fontSize": "var(--wp--preset--font-size--smaller)"
+ }
+ }
+ }
+ }
+ }
+ }
}
```
@@ -1013,42 +1066,44 @@ If they're found in the top-level the element selector will be used. If they're
```css
body {
- font-size: var( --wp--preset--font-size--normal );
+ font-size: var(--wp--preset--font-size--normal);
}
h1 {
- font-size: var( --wp--preset--font-size--huge );
+ font-size: var(--wp--preset--font-size--huge);
}
h2 {
- font-size: var( --wp--preset--font-size--big );
+ font-size: var(--wp--preset--font-size--big);
}
h3 {
- font-size: var( --wp--preset--font-size--medium );
+ font-size: var(--wp--preset--font-size--medium);
}
.wp-block-group h2 {
- font-size: var( --wp--preset--font-size--small );
+ font-size: var(--wp--preset--font-size--small);
}
.wp-block-group h3 {
- font-size: var( --wp--preset--font-size--smaller );
+ font-size: var(--wp--preset--font-size--smaller);
}
```
+
{% end %}
+
##### Element pseudo selectors
Pseudo selectors `:hover`, `:focus`, `:focus-visible`, `:visited`, `:active`, `:link`, `:any-link` are supported by Gutenberg.
```json
"elements": {
- "link": {
- "color": {
- "text": "green"
- },
- ":hover": {
- "color": {
- "text": "hotpink"
- }
- }
- }
- }
+ "link": {
+ "color": {
+ "text": "green"
+ },
+ ":hover": {
+ "color": {
+ "text": "hotpink"
+ }
+ }
+ }
+ }
```
#### Variations
@@ -1061,20 +1116,20 @@ For example, this is how to provide styles for the existing `plain` variation fo
```json
{
- "version": 3,
- "styles": {
- "blocks": {
- "core/quote": {
- "variations": {
- "plain": {
- "color": {
- "background": "red"
- }
- }
- }
- }
- }
- }
+ "version": 3,
+ "styles": {
+ "blocks": {
+ "core/quote": {
+ "variations": {
+ "plain": {
+ "color": {
+ "background": "red"
+ }
+ }
+ }
+ }
+ }
+ }
}
```
@@ -1082,7 +1137,7 @@ The resulting CSS output is:
```css
.wp-block-quote.is-style-plain {
- background-color: red;
+ background-color: red;
}
```
@@ -1101,39 +1156,39 @@ The following is an example of a `theme.json` partial that defines styles for th
```json
{
- "$schema": "https://schemas.wp.org/trunk/theme.json",
- "version": 3,
- "title": "Variation A",
- "slug": "variation-a",
- "blockTypes": [ "core/group", "core/columns", "core/media-text" ],
- "styles": {
- "color": {
- "background": "#eed8d3",
- "text": "#201819"
- },
- "elements": {
- "heading": {
- "color": {
- "text": "#201819"
- }
- }
- },
- "blocks": {
- "core/group": {
- "color": {
- "background": "#825f58",
- "text": "#eed8d3"
- },
- "elements": {
- "heading": {
- "color": {
- "text": "#eed8d3"
- }
- }
- }
- }
- }
- }
+ "$schema": "https://schemas.wp.org/trunk/theme.json",
+ "version": 3,
+ "title": "Variation A",
+ "slug": "variation-a",
+ "blockTypes": ["core/group", "core/columns", "core/media-text"],
+ "styles": {
+ "color": {
+ "background": "#eed8d3",
+ "text": "#201819"
+ },
+ "elements": {
+ "heading": {
+ "color": {
+ "text": "#201819"
+ }
+ }
+ },
+ "blocks": {
+ "core/group": {
+ "color": {
+ "background": "#825f58",
+ "text": "#eed8d3"
+ },
+ "elements": {
+ "heading": {
+ "color": {
+ "text": "#eed8d3"
+ }
+ }
+ }
+ }
+ }
+ }
}
```
@@ -1191,18 +1246,14 @@ Within this field themes can list the custom templates present in the `templates
```json
{
- "version": 3,
- "customTemplates": [
- {
- "name": "my-custom-template",
- "title": "The template title",
- "postTypes": [
- "page",
- "post",
- "my-cpt"
- ]
- }
- ]
+ "version": 3,
+ "customTemplates": [
+ {
+ "name": "my-custom-template",
+ "title": "The template title",
+ "postTypes": ["page", "post", "my-cpt"]
+ }
+ ]
}
```
@@ -1220,14 +1271,14 @@ Currently block variations exist for "header" and "footer" values of the area te
```json
{
- "version": 3,
- "templateParts": [
- {
- "name": "my-template-part",
- "title": "Header",
- "area": "header"
- }
- ]
+ "version": 3,
+ "templateParts": [
+ {
+ "name": "my-template-part",
+ "title": "Header",
+ "area": "header"
+ }
+ ]
}
```
@@ -1239,8 +1290,8 @@ Within this field themes can list patterns to register from [Pattern Directory](
```json
{
- "version": 3,
- "patterns": [ "short-text-surrounded-by-round-images", "partner-logos" ]
+ "version": 3,
+ "patterns": ["short-text-surrounded-by-round-images", "partner-logos"]
}
```
@@ -1258,7 +1309,6 @@ Check your editor's documentation for JSON schema support. In Visual Studio Code

-
## Frequently Asked Questions
### The naming schema of CSS Custom Properties
@@ -1268,7 +1318,7 @@ One thing you may have noticed is the naming schema used for the CSS Custom Prop
**Presets** such as `--wp--preset--color--black` can be divided into the following chunks:
- `--wp`: prefix to namespace the CSS variable.
-- `preset `: indicates is a CSS variable that belongs to the presets.
+- `preset`: indicates is a CSS variable that belongs to the presets.
- `color`: indicates which preset category the variable belongs to. It can be `color`, `font-size`, `gradients`.
- `black`: the `slug` of the particular preset value.
@@ -1304,15 +1354,15 @@ For example:
```json
{
- "version": 3,
- "settings": {
- "custom": {
- "lineHeight": {
- "body": 1.7
- },
- "font-primary": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
- }
- }
+ "version": 3,
+ "settings": {
+ "custom": {
+ "lineHeight": {
+ "body": 1.7
+ },
+ "font-primary": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
+ }
+ }
}
```
@@ -1320,10 +1370,11 @@ For example:
```css
body {
- --wp--custom--line-height--body: 1.7;
- --wp--custom--font-primary: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
+ --wp--custom--line-height--body: 1.7;
+ --wp--custom--font-primary: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
}
```
+
{% end %}
A few notes about this process:
@@ -1334,14 +1385,15 @@ A few notes about this process:
```json
{
- "version": 3,
- "settings": {
- "custom": {
- "line--height": { // DO NOT DO THIS
- "body": 1.7
- }
- }
- }
+ "version": 3,
+ "settings": {
+ "custom": {
+ "line--height": {
+ // DO NOT DO THIS
+ "body": 1.7
+ }
+ }
+ }
}
```
@@ -1372,7 +1424,7 @@ For themes to override the default values they can use the `theme.json` and prov
```css
body {
- --wp--preset--font-size--large: ;
+ --wp--preset--font-size--large: ;
}
```
@@ -1381,13 +1433,17 @@ body {
In WordPress 5.8, when a user selected a link color for a specific block we attached a class to that block in the form of `.wp-element-` and then enqueued the following style:
```css
-.wp-element- a { color: !important; }
+.wp-element- a {
+ color: !important;
+}
```
While this preserved user preferences at all times, the specificity was too strong and conflicted with some blocks with legit uses of an HTML element that shouldn’t be considered links. To [address this issue](https://github.com/WordPress/gutenberg/pull/34689), in WordPress 5.9 release, the `!important` was removed and updated the corresponding blocks to style the a elements with a specificity higher than the user link color, which now is:
```css
-.wp-element- a { color: ; }
+.wp-element- a {
+ color: ;
+}
```
As a result of this change, it’s now the block author and theme author’s responsibility to make sure the user choices are respected at all times and that the link color provided by the user (specificity 011) is not overridden.
@@ -1398,17 +1454,17 @@ For blocks that contain inner blocks, such as Group, Columns, Buttons, and Socia
```json
{
- "version": 3,
- "settings": {
- "spacing": {
- "blockGap": true,
- }
- },
- "styles": {
- "spacing": {
- "blockGap": "1.5rem"
- }
- }
+ "version": 3,
+ "settings": {
+ "spacing": {
+ "blockGap": true
+ }
+ },
+ "styles": {
+ "spacing": {
+ "blockGap": "1.5rem"
+ }
+ }
}
```
diff --git a/gutenberg/how-to-guides/themes/theme-support.md b/docs/gutenberg/how-to-guides/themes/theme-support.md
similarity index 79%
rename from gutenberg/how-to-guides/themes/theme-support.md
rename to docs/gutenberg/how-to-guides/themes/theme-support.md
index e5d6c34..f63b463 100644
--- a/gutenberg/how-to-guides/themes/theme-support.md
+++ b/docs/gutenberg/how-to-guides/themes/theme-support.md
@@ -4,12 +4,12 @@ The new Blocks include baseline support in all themes, enhancements to opt-in to
There are a few new concepts to consider when building themes:
-- **Editor Color Palette** - A default set of colors is provided, but themes can register their own and optionally lock users into picking from the defined palette.
-- **Editor Text Size Palette** - A default set of sizes is provided, but themes can register their own and optionally lock users into picking from preselected sizes.
-- **Responsive Embeds** - Themes must opt-in to responsive embeds.
-- **Frontend & Editor Styles** - To get the most out of blocks, theme authors will want to make sure Core styles look good and opt-in, or write their own styles to best fit their theme.
-- **Block Tools** - Themes can opt-in to several block tools like line height, custom units.
-- **Core Block Patterns** - Themes can opt-out of the default block patterns.
+- **Editor Color Palette** - A default set of colors is provided, but themes can register their own and optionally lock users into picking from the defined palette.
+- **Editor Text Size Palette** - A default set of sizes is provided, but themes can register their own and optionally lock users into picking from preselected sizes.
+- **Responsive Embeds** - Themes must opt-in to responsive embeds.
+- **Frontend & Editor Styles** - To get the most out of blocks, theme authors will want to make sure Core styles look good and opt-in, or write their own styles to best fit their theme.
+- **Block Tools** - Themes can opt-in to several block tools like line height, custom units.
+- **Core Block Patterns** - Themes can opt-out of the default block patterns.
By default, blocks provide their styles to enable basic support for blocks in themes without any change. They also [provide opt-in opinionated styles](#default-block-styles). Themes can add/override these styles, or they can provide no styles at all, and rely fully on what the blocks provide.
@@ -19,28 +19,28 @@ To opt-in for one of these features, call `add_theme_support` in the `functions.
```php
function mytheme_setup_theme_supported_features() {
- add_theme_support( 'editor-color-palette', array(
- array(
- 'name' => esc_attr__( 'strong magenta', 'themeLangDomain' ),
- 'slug' => 'strong-magenta',
- 'color' => '#a156b4',
- ),
- array(
- 'name' => esc_attr__( 'light grayish magenta', 'themeLangDomain' ),
- 'slug' => 'light-grayish-magenta',
- 'color' => '#d0a5db',
- ),
- array(
- 'name' => esc_attr__( 'very light gray', 'themeLangDomain' ),
- 'slug' => 'very-light-gray',
- 'color' => '#eee',
- ),
- array(
- 'name' => esc_attr__( 'very dark gray', 'themeLangDomain' ),
- 'slug' => 'very-dark-gray',
- 'color' => '#444',
- ),
- ) );
+ add_theme_support( 'editor-color-palette', array(
+ array(
+ 'name' => esc_attr__( 'strong magenta', 'themeLangDomain' ),
+ 'slug' => 'strong-magenta',
+ 'color' => '#a156b4',
+ ),
+ array(
+ 'name' => esc_attr__( 'light grayish magenta', 'themeLangDomain' ),
+ 'slug' => 'light-grayish-magenta',
+ 'color' => '#d0a5db',
+ ),
+ array(
+ 'name' => esc_attr__( 'very light gray', 'themeLangDomain' ),
+ 'slug' => 'very-light-gray',
+ 'color' => '#eee',
+ ),
+ array(
+ 'name' => esc_attr__( 'very dark gray', 'themeLangDomain' ),
+ 'slug' => 'very-dark-gray',
+ 'color' => '#444',
+ ),
+ ) );
}
add_action( 'after_setup_theme', 'mytheme_setup_theme_supported_features' );
@@ -64,7 +64,7 @@ You can see the CSS that will be included in the [block library theme file](http
For block themes or themes providing a `theme.json` file, it is not recommended to use this theme support. Instead, to ensure there is no styling conflict between global styles rules and block styles, add the desired block styles to the theme's `theme.json` file.
-### Wide Alignment:
+### Wide Alignment
Some blocks such as the image block have the possibility to define a "wide" or "full" alignment by adding the corresponding classname to the block's wrapper ( `alignwide` or `alignfull` ). A theme can opt-in for this feature by calling:
@@ -84,8 +84,8 @@ Here's the markup for an `Image` with a caption:
```html
-
- Short image caption.
+
+ Short image caption.
```
@@ -93,10 +93,10 @@ Here's the markup for a left-floated image:
```html
-
-
- Short image caption.
-
+
+
+ Short image caption.
+
```
@@ -108,26 +108,26 @@ Different blocks have the possibility of customizing colors. The block editor pr
```php
add_theme_support( 'editor-color-palette', array(
- array(
- 'name' => esc_attr__( 'strong magenta', 'themeLangDomain' ),
- 'slug' => 'strong-magenta',
- 'color' => '#a156b4',
- ),
- array(
- 'name' => esc_attr__( 'light grayish magenta', 'themeLangDomain' ),
- 'slug' => 'light-grayish-magenta',
- 'color' => '#d0a5db',
- ),
- array(
- 'name' => esc_attr__( 'very light gray', 'themeLangDomain' ),
- 'slug' => 'very-light-gray',
- 'color' => '#eee',
- ),
- array(
- 'name' => esc_attr__( 'very dark gray', 'themeLangDomain' ),
- 'slug' => 'very-dark-gray',
- 'color' => '#444',
- ),
+ array(
+ 'name' => esc_attr__( 'strong magenta', 'themeLangDomain' ),
+ 'slug' => 'strong-magenta',
+ 'color' => '#a156b4',
+ ),
+ array(
+ 'name' => esc_attr__( 'light grayish magenta', 'themeLangDomain' ),
+ 'slug' => 'light-grayish-magenta',
+ 'color' => '#d0a5db',
+ ),
+ array(
+ 'name' => esc_attr__( 'very light gray', 'themeLangDomain' ),
+ 'slug' => 'very-light-gray',
+ 'color' => '#eee',
+ ),
+ array(
+ 'name' => esc_attr__( 'very dark gray', 'themeLangDomain' ),
+ 'slug' => 'very-dark-gray',
+ 'color' => '#444',
+ ),
) );
```
@@ -141,15 +141,15 @@ Themes are responsible for creating the classes that apply the colors in differe
```css
.has-strong-magenta-color {
- color: #a156b4;
+ color: #a156b4;
}
.has-strong-magenta-background-color {
- background-color: #a156b4;
+ background-color: #a156b4;
}
.has-strong-magenta-border-color {
- border-color: #a156b4;
+ border-color: #a156b4;
}
```
@@ -157,8 +157,8 @@ Starting in WordPress 5.9, to override color values defined by core, themes with
```css
:root {
- --wp--preset--color--cyan-bluish-gray: ;
- --wp--preset--color--pale-pink: ;
+ --wp--preset--color--cyan-bluish-gray: ;
+ --wp--preset--color--pale-pink: ;
}
```
@@ -168,34 +168,34 @@ Different blocks have the possibility of selecting from a list of predefined gra
```php
add_theme_support(
- 'editor-gradient-presets',
- array(
- array(
- 'name' => esc_attr__( 'Vivid cyan blue to vivid purple', 'themeLangDomain' ),
- 'gradient' => 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
- 'slug' => 'vivid-cyan-blue-to-vivid-purple'
- ),
- array(
- 'name' => esc_attr__( 'Vivid green cyan to vivid cyan blue', 'themeLangDomain' ),
- 'gradient' => 'linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)',
- 'slug' => 'vivid-green-cyan-to-vivid-cyan-blue',
- ),
- array(
- 'name' => esc_attr__( 'Light green cyan to vivid green cyan', 'themeLangDomain' ),
- 'gradient' => 'linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)',
- 'slug' => 'light-green-cyan-to-vivid-green-cyan',
- ),
- array(
- 'name' => esc_attr__( 'Luminous vivid amber to luminous vivid orange', 'themeLangDomain' ),
- 'gradient' => 'linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%)',
- 'slug' => 'luminous-vivid-amber-to-luminous-vivid-orange',
- ),
- array(
- 'name' => esc_attr__( 'Luminous vivid orange to vivid red', 'themeLangDomain' ),
- 'gradient' => 'linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%)',
- 'slug' => 'luminous-vivid-orange-to-vivid-red',
- ),
- )
+ 'editor-gradient-presets',
+ array(
+ array(
+ 'name' => esc_attr__( 'Vivid cyan blue to vivid purple', 'themeLangDomain' ),
+ 'gradient' => 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
+ 'slug' => 'vivid-cyan-blue-to-vivid-purple'
+ ),
+ array(
+ 'name' => esc_attr__( 'Vivid green cyan to vivid cyan blue', 'themeLangDomain' ),
+ 'gradient' => 'linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)',
+ 'slug' => 'vivid-green-cyan-to-vivid-cyan-blue',
+ ),
+ array(
+ 'name' => esc_attr__( 'Light green cyan to vivid green cyan', 'themeLangDomain' ),
+ 'gradient' => 'linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)',
+ 'slug' => 'light-green-cyan-to-vivid-green-cyan',
+ ),
+ array(
+ 'name' => esc_attr__( 'Luminous vivid amber to luminous vivid orange', 'themeLangDomain' ),
+ 'gradient' => 'linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%)',
+ 'slug' => 'luminous-vivid-amber-to-luminous-vivid-orange',
+ ),
+ array(
+ 'name' => esc_attr__( 'Luminous vivid orange to vivid red', 'themeLangDomain' ),
+ 'gradient' => 'linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%)',
+ 'slug' => 'luminous-vivid-orange-to-vivid-red',
+ ),
+ )
);
```
@@ -205,11 +205,7 @@ Themes are responsible for creating the classes that apply the gradients. So to
```css
.has-vivid-cyan-blue-to-vivid-purple-gradient-background {
- background: linear-gradient(
- 135deg,
- rgba( 6, 147, 227, 1 ) 0%,
- rgb( 155, 81, 224 ) 100%
- );
+ background: linear-gradient(135deg, rgba(6, 147, 227, 1) 0%, rgb(155, 81, 224) 100%);
}
```
@@ -217,8 +213,8 @@ Starting in WordPress 5.9, to override gradient values defined by core, themes w
```css
:root {
- --wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: ;
- --wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: ;
+ --wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: ;
+ --wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: ;
}
```
@@ -228,26 +224,26 @@ Blocks may allow the user to configure the font sizes they use, e.g., the paragr
```php
add_theme_support( 'editor-font-sizes', array(
- array(
- 'name' => esc_attr__( 'Small', 'themeLangDomain' ),
- 'size' => 12,
- 'slug' => 'small'
- ),
- array(
- 'name' => esc_attr__( 'Regular', 'themeLangDomain' ),
- 'size' => 16,
- 'slug' => 'regular'
- ),
- array(
- 'name' => esc_attr__( 'Large', 'themeLangDomain' ),
- 'size' => 36,
- 'slug' => 'large'
- ),
- array(
- 'name' => esc_attr__( 'Huge', 'themeLangDomain' ),
- 'size' => 50,
- 'slug' => 'huge'
- )
+ array(
+ 'name' => esc_attr__( 'Small', 'themeLangDomain' ),
+ 'size' => 12,
+ 'slug' => 'small'
+ ),
+ array(
+ 'name' => esc_attr__( 'Regular', 'themeLangDomain' ),
+ 'size' => 16,
+ 'slug' => 'regular'
+ ),
+ array(
+ 'name' => esc_attr__( 'Large', 'themeLangDomain' ),
+ 'size' => 36,
+ 'slug' => 'large'
+ ),
+ array(
+ 'name' => esc_attr__( 'Huge', 'themeLangDomain' ),
+ 'size' => 50,
+ 'slug' => 'huge'
+ )
) );
```
@@ -260,7 +256,7 @@ As an example for the regular font size, a theme may provide the following class
```css
.has-regular-font-size {
- font-size: 16px;
+ font-size: 16px;
}
```
@@ -272,8 +268,8 @@ Starting in WordPress 5.9, to override font size values defined by core, themes
```css
:root {
- --wp--preset--font-size--small: ;
- --wp--preset--font-size--large: ;
+ --wp--preset--font-size--small: ;
+ --wp--preset--font-size--large: ;
}
```
@@ -343,7 +339,7 @@ Themes can also filter the available custom units.
add_theme_support( 'custom-units', 'rem', 'em' );
```
-### Disabling the default block patterns.
+### Disabling the default block patterns
WordPress comes with a number of block patterns built-in, themes can opt-out of the bundled patterns and provide their own set using the following code:
@@ -384,8 +380,8 @@ You can style the editor like any other webpage. Here's how to change the backgr
```css
/* Add this to your `style-editor.css` file */
body {
- background-color: #d3ebf3;
- color: #00005d;
+ background-color: #d3ebf3;
+ color: #00005d;
}
```
@@ -396,17 +392,17 @@ To change the main column width of the editor, add the following CSS to `style-e
```css
/* Main column width */
.wp-block {
- max-width: 720px;
+ max-width: 720px;
}
/* Width of "wide" blocks */
.wp-block[data-align='wide'] {
- max-width: 1080px;
+ max-width: 1080px;
}
/* Width of "full-wide" blocks */
.wp-block[data-align='full'] {
- max-width: none;
+ max-width: none;
}
```
@@ -442,11 +438,11 @@ Link support has been made stable as part of WordPress 5.8. It's `false` by defa
```json
{
- "settings": {
- "color": {
- "link": true
- }
- }
+ "settings": {
+ "color": {
+ "link": true
+ }
+ }
}
```
@@ -455,8 +451,8 @@ Link support has been made stable as part of WordPress 5.8. It's `false` by defa
When the user sets the link color of a block, a new style will be added in the form of:
```css
-.wp-elements- a {
- color: !important;
+.wp-elements- a {
+ color: !important;
}
```
diff --git a/gutenberg/how-to-guides/thunks.md b/docs/gutenberg/how-to-guides/thunks.md
similarity index 56%
rename from gutenberg/how-to-guides/thunks.md
rename to docs/gutenberg/how-to-guides/thunks.md
index e403f72..1b17b8e 100644
--- a/gutenberg/how-to-guides/thunks.md
+++ b/docs/gutenberg/how-to-guides/thunks.md
@@ -4,9 +4,11 @@
```js
// actions.js
-export const myThunkAction = () => ( { select, dispatch } ) => {
- return "I'm a thunk! I can be dispatched, use selectors, and even dispatch other actions.";
-};
+export const myThunkAction =
+ () =>
+ ({ select, dispatch }) => {
+ return "I'm a thunk! I can be dispatched, use selectors, and even dispatch other actions.";
+ };
```
## Why are thunks useful?
@@ -15,30 +17,32 @@ Thunks [expand the meaning of what a Redux action is](https://jsnajdr.wordpress.
```js
export function* saveRecordAction( id ) {
- const record = yield controls.select( 'current-store', 'getRecord', id );
- yield { type: 'BEFORE_SAVE', id, record };
- const results = yield controls.fetch({ url: 'https://...', method: 'POST', data: record });
- yield { type: 'AFTER_SAVE', id, results };
- return results;
+ const record = yield controls.select( 'current-store', 'getRecord', id );
+ yield { type: 'BEFORE_SAVE', id, record };
+ const results = yield controls.fetch({ url: 'https://...', method: 'POST', data: record });
+ yield { type: 'AFTER_SAVE', id, results };
+ return results;
}
const controls = {
- select: // ...,
- fetch: // ...,
+ select: // ...,
+ fetch: // ...,
};
```
Side effects like store operations and fetch functions would be implemented outside of the action. Thunks provide an alternative to this approach. They allow you to use side effects inline, like this:
```js
-export const saveRecordAction = ( id ) => async ({ select, dispatch }) => {
- const record = select( 'current-store', 'getRecord', id );
- dispatch({ type: 'BEFORE_SAVE', id, record });
- const response = await fetch({ url: 'https://...', method: 'POST', data: record });
- const results = await response.json();
- dispatch({ type: 'AFTER_SAVE', id, results });
- return results;
-}
+export const saveRecordAction =
+ (id) =>
+ async ({ select, dispatch }) => {
+ const record = select('current-store', 'getRecord', id);
+ dispatch({ type: 'BEFORE_SAVE', id, record });
+ const response = await fetch({ url: 'https://...', method: 'POST', data: record });
+ const results = await response.json();
+ dispatch({ type: 'AFTER_SAVE', id, results });
+ return results;
+ };
```
This removes the need to implement separate controls.
@@ -48,21 +52,15 @@ This removes the need to implement separate controls.
Let's take a look at an example from Gutenberg core. Prior to thunks, the `toggleFeature` action from the `@wordpress/interface` package was implemented like this:
```js
-export function* toggleFeature( scope, featureName ) {
- const currentValue = yield controls.select(
- interfaceStoreName,
- 'isFeatureActive',
- scope,
- featureName
- );
-
- yield controls.dispatch(
- interfaceStoreName,
- 'setFeatureValue',
- scope,
- featureName,
- ! currentValue
- );
+export function* toggleFeature(scope, featureName) {
+ const currentValue = yield controls.select(
+ interfaceStoreName,
+ 'isFeatureActive',
+ scope,
+ featureName
+ );
+
+ yield controls.dispatch(interfaceStoreName, 'setFeatureValue', scope, featureName, !currentValue);
}
```
@@ -71,11 +69,11 @@ Controls were the only way to `dispatch` actions and `select` data from the stor
With thunks, there is a cleaner way. This is how `toggleFeature` is implemented now:
```js
-export function toggleFeature( scope, featureName ) {
- return function ( { select, dispatch } ) {
- const currentValue = select.isFeatureActive( scope, featureName );
- dispatch.setFeatureValue( scope, featureName, ! currentValue );
- };
+export function toggleFeature(scope, featureName) {
+ return function ({ select, dispatch }) {
+ const currentValue = select.isFeatureActive(scope, featureName);
+ dispatch.setFeatureValue(scope, featureName, !currentValue);
+ };
}
```
@@ -88,24 +86,29 @@ Imagine a simple React app that allows you to set the temperature on a thermosta
If we used controls to save the temperature, the store definition would look like below:
```js
-const store = wp.data.createReduxStore( 'my-store', {
- actions: {
- saveTemperatureToAPI: function*( temperature ) {
- const result = yield { type: 'FETCH_JSON', url: 'https://...', method: 'POST', data: { temperature } };
- return result;
- }
+const store = wp.data.createReduxStore('my-store', {
+ actions: {
+ saveTemperatureToAPI: function* (temperature) {
+ const result = yield {
+ type: 'FETCH_JSON',
+ url: 'https://...',
+ method: 'POST',
+ data: { temperature },
+ };
+ return result;
},
- controls: {
- async FETCH_JSON( action ) {
- const response = await window.fetch( action.url, {
- method: action.method,
- body: JSON.stringify( action.data ),
- } );
- return response.json();
- }
+ },
+ controls: {
+ async FETCH_JSON(action) {
+ const response = await window.fetch(action.url, {
+ method: action.method,
+ body: JSON.stringify(action.data),
+ });
+ return response.json();
},
- // reducers, selectors, ...
-} );
+ },
+ // reducers, selectors, ...
+});
```
While the code is reasonably straightforward, there is a level of indirection. The `saveTemperatureToAPI` action does not talk directly to the API, but has to go through the `FETCH_JSON` control.
@@ -113,37 +116,39 @@ While the code is reasonably straightforward, there is a level of indirection. T
Let's see how this indirection can be removed with thunks:
```js
-const store = wp.data.createReduxStore( 'my-store', {
- actions: {
- saveTemperatureToAPI: ( temperature ) => async () => {
- const response = await window.fetch( 'https://...', {
- method: 'POST',
- body: JSON.stringify( { temperature } ),
- } );
- return await response.json();
- }
+const store = wp.data.createReduxStore('my-store', {
+ actions: {
+ saveTemperatureToAPI: (temperature) => async () => {
+ const response = await window.fetch('https://...', {
+ method: 'POST',
+ body: JSON.stringify({ temperature }),
+ });
+ return await response.json();
},
- // reducers, selectors, ...
-} );
+ },
+ // reducers, selectors, ...
+});
```
That's pretty cool! What's even better is that resolvers are supported as well:
```js
-const store = wp.data.createReduxStore( 'my-store', {
- // ...
- selectors: {
- getTemperature: ( state ) => state.temperature
- },
- resolvers: {
- getTemperature: () => async ( { dispatch } ) => {
- const response = await window.fetch( 'https://...' );
- const result = await response.json();
- dispatch.receiveCurrentTemperature( result.temperature );
- }
- },
- // ...
-} );
+const store = wp.data.createReduxStore('my-store', {
+ // ...
+ selectors: {
+ getTemperature: (state) => state.temperature,
+ },
+ resolvers: {
+ getTemperature:
+ () =>
+ async ({ dispatch }) => {
+ const response = await window.fetch('https://...');
+ const result = await response.json();
+ dispatch.receiveCurrentTemperature(result.temperature);
+ },
+ },
+ // ...
+});
```
Support for thunks is included by default in every data store, just like the (now legacy) support for
@@ -157,23 +162,26 @@ A thunk receives a single object argument with the following keys:
An object containing the store’s selectors pre-bound to state, which means you don't need to provide the state, only the additional arguments. `select` triggers the related resolvers, if any, but does not wait for them to finish. It just returns the current value even if it's null.
-
If a selector is part of the public API, it's available as a method on the select object:
```js
-const thunk = () => ( { select } ) => {
+const thunk =
+ () =>
+ ({ select }) => {
// select is an object of the store’s selectors, pre-bound to current state:
const temperature = select.getTemperature();
-}
+ };
```
Since not all selectors are exposed on the store, `select` doubles as a function that supports passing a selector as an argument:
```js
-const thunk = () => ( { select } ) => {
+const thunk =
+ () =>
+ ({ select }) => {
// select supports private selectors:
- const doubleTemperature = select( ( temperature ) => temperature * 2 );
-}
+ const doubleTemperature = select((temperature) => temperature * 2);
+ };
```
### resolveSelect
@@ -202,16 +210,18 @@ const thunk = () => ( { dispatch } ) => {
Since not all actions are exposed on the store, `dispatch` doubles as a function that supports passing a Redux action as an argument:
```js
-const thunk = () => async ( { dispatch } ) => {
- // dispatch is also a function accepting inline actions:
- dispatch({ type: 'SET_TEMPERATURE', temperature: result.value });
-
- // thunks are interchangeable with actions
- dispatch( updateTemperature( 100 ) );
-
- // Thunks may be async, too. When they are, dispatch returns a promise
- await dispatch( ( ) => window.fetch( /* ... */ ) );
-}
+const thunk =
+ () =>
+ async ({ dispatch }) => {
+ // dispatch is also a function accepting inline actions:
+ dispatch({ type: 'SET_TEMPERATURE', temperature: result.value });
+
+ // thunks are interchangeable with actions
+ dispatch(updateTemperature(100));
+
+ // Thunks may be async, too. When they are, dispatch returns a promise
+ await dispatch(() => window.fetch(/* ... */));
+ };
```
### registry
@@ -220,8 +230,10 @@ A registry provides access to other stores through its `dispatch`, `select`, and
These are very similar to the ones described above, with a slight twist. Calling `registry.select( storeName )` returns a function returning an object of selectors from `storeName`. This comes handy when you need to interact with another store. For example:
```js
-const thunk = () => ( { registry } ) => {
- const error = registry.select( 'core' ).getLastEntitySaveError( 'root', 'menu', menuId );
- /* ... */
-}
+const thunk =
+ () =>
+ ({ registry }) => {
+ const error = registry.select('core').getLastEntitySaveError('root', 'menu', menuId);
+ /* ... */
+ };
```
diff --git a/gutenberg/how-to-guides/widgets/README.md b/docs/gutenberg/how-to-guides/widgets/README.md
similarity index 100%
rename from gutenberg/how-to-guides/widgets/README.md
rename to docs/gutenberg/how-to-guides/widgets/README.md
diff --git a/gutenberg/how-to-guides/widgets/legacy-widget-block.md b/docs/gutenberg/how-to-guides/widgets/legacy-widget-block.md
similarity index 68%
rename from gutenberg/how-to-guides/widgets/legacy-widget-block.md
rename to docs/gutenberg/how-to-guides/widgets/legacy-widget-block.md
index 80353f5..56c0928 100644
--- a/gutenberg/how-to-guides/widgets/legacy-widget-block.md
+++ b/docs/gutenberg/how-to-guides/widgets/legacy-widget-block.md
@@ -17,14 +17,14 @@ If the widget uses JavaScript in its form, it is important that events are added
For example, a widget might want to show a "Password" field when the "Change password" checkbox is checked.
```js
-( function ( $ ) {
- $( document ).on( 'widget-added', function ( $event, $control ) {
- $control.find( '.change-password' ).on( 'change', function () {
- var isChecked = $( this ).prop( 'checked' );
- $control.find( '.password' ).toggleClass( 'hidden', ! isChecked );
- } );
- } );
-} )( jQuery );
+(function ($) {
+ $(document).on('widget-added', function ($event, $control) {
+ $control.find('.change-password').on('change', function () {
+ var isChecked = $(this).prop('checked');
+ $control.find('.password').toggleClass('hidden', !isChecked);
+ });
+ });
+})(jQuery);
```
Note that all of the widget's event handlers are added in the `widget-added` callback.
@@ -39,18 +39,18 @@ Widgets may take advantage of this by returning early from `widget()` when a pre
```php
class ExampleWidget extends WP_Widget {
- ...
- public function widget( $instance ) {
- if ( ! isset( $instance['name'] ) ) {
- // Name is required, so display nothing if we don't have it.
- return;
- }
- ?>
-
Name:
- ...
-
+
Name:
+ ...
+ true,
- // ...other options here
- );
- parent::__construct( 'example_widget', 'ExampleWidget', $widget_ops );
- }
- ...
+ ...
+ /**
+ * Sets up the widget
+ */
+ public function __construct() {
+ $widget_ops = array(
+ // ...other options here
+ 'show_instance_in_rest' => true,
+ // ...other options here
+ );
+ parent::__construct( 'example_widget', 'ExampleWidget', $widget_ops );
+ }
+ ...
}
```
@@ -95,9 +95,9 @@ Note that [versions of WordPress prior to 5.8.0 allowed you to enable this featu
```php
class ExampleWidget extends WP_Widget {
- ...
- public $show_instance_in_rest = true;
- ...
+ ...
+ public $show_instance_in_rest = true;
+ ...
}
```
@@ -111,24 +111,24 @@ This is done by adding JavaScript code to your block's definition. In this examp
```js
transforms: {
- from: [
- {
- type: 'block',
- blocks: [ 'core/legacy-widget' ],
- isMatch: ( { idBase, instance } ) => {
- if ( ! instance?.raw ) {
- // Can't transform if raw instance is not shown in REST API.
- return false;
- }
- return idBase === 'example_widget';
- },
- transform: ( { instance } ) => {
- return createBlock( 'example/block', {
- name: instance.raw.name,
- } );
- },
- },
- ]
+ from: [
+ {
+ type: 'block',
+ blocks: [ 'core/legacy-widget' ],
+ isMatch: ( { idBase, instance } ) => {
+ if ( ! instance?.raw ) {
+ // Can't transform if raw instance is not shown in REST API.
+ return false;
+ }
+ return idBase === 'example_widget';
+ },
+ transform: ( { instance } ) => {
+ return createBlock( 'example/block', {
+ name: instance.raw.name,
+ } );
+ },
+ },
+ ]
},
```
@@ -140,8 +140,8 @@ This can be done using the `widget_types_to_hide_from_legacy_widget_block` filte
```php
function hide_example_widget( $widget_types ) {
- $widget_types[] = 'example_widget';
- return $widget_types;
+ $widget_types[] = 'example_widget';
+ return $widget_types;
}
add_filter( 'widget_types_to_hide_from_legacy_widget_block', 'hide_example_widget' );
```
@@ -158,27 +158,27 @@ screen.
```php
add_action( 'admin_print_styles', function() {
- if ( get_current_screen()->is_block_editor() ) {
- do_action( 'admin_print_styles-widgets.php' );
- }
+ if ( get_current_screen()->is_block_editor() ) {
+ do_action( 'admin_print_styles-widgets.php' );
+ }
} );
add_action( 'admin_print_scripts', function() {
- if ( get_current_screen()->is_block_editor() ) {
- do_action( 'load-widgets.php' );
- do_action( 'widgets.php' );
- do_action( 'sidebar_admin_setup' );
- do_action( 'admin_print_scripts-widgets.php' );
- }
+ if ( get_current_screen()->is_block_editor() ) {
+ do_action( 'load-widgets.php' );
+ do_action( 'widgets.php' );
+ do_action( 'sidebar_admin_setup' );
+ do_action( 'admin_print_scripts-widgets.php' );
+ }
} );
add_action( 'admin_print_footer_scripts', function() {
- if ( get_current_screen()->is_block_editor() ) {
- do_action( 'admin_print_footer_scripts-widgets.php' );
- }
+ if ( get_current_screen()->is_block_editor() ) {
+ do_action( 'admin_print_footer_scripts-widgets.php' );
+ }
} );
add_action( 'admin_footer', function() {
- if ( get_current_screen()->is_block_editor() ) {
- do_action( 'admin_footer-widgets.php' );
- }
+ if ( get_current_screen()->is_block_editor() ) {
+ do_action( 'admin_footer-widgets.php' );
+ }
} );
```
@@ -187,7 +187,7 @@ is defined in the `@wordpress/widgets` package.
```php
add_action( 'enqueue_block_editor_assets', function() {
- wp_enqueue_script( 'wp-widgets' );
- wp_add_inline_script( 'wp-widgets', 'wp.widgets.registerLegacyWidgetBlock()' );
+ wp_enqueue_script( 'wp-widgets' );
+ wp_add_inline_script( 'wp-widgets', 'wp.widgets.registerLegacyWidgetBlock()' );
} );
```
diff --git a/gutenberg/how-to-guides/widgets/opting-out.md b/docs/gutenberg/how-to-guides/widgets/opting-out.md
similarity index 90%
rename from gutenberg/how-to-guides/widgets/opting-out.md
rename to docs/gutenberg/how-to-guides/widgets/opting-out.md
index 873734b..21ed27f 100644
--- a/gutenberg/how-to-guides/widgets/opting-out.md
+++ b/docs/gutenberg/how-to-guides/widgets/opting-out.md
@@ -10,7 +10,7 @@ For example, a theme may have the following PHP code in `functions.php`.
```php
function example_theme_support() {
- remove_theme_support( 'widgets-block-editor' );
+ remove_theme_support( 'widgets-block-editor' );
}
add_action( 'after_setup_theme', 'example_theme_support' );
```
@@ -35,10 +35,10 @@ For more advanced uses, you may supply your own function. In this example, the W
```php
function example_use_widgets_block_editor( $use_widgets_block_editor ) {
- if ( 123 === get_current_user_id() ) {
- return false;
- }
- return $use_widgets_block_editor;
+ if ( 123 === get_current_user_id() ) {
+ return false;
+ }
+ return $use_widgets_block_editor;
}
add_filter( 'use_widgets_block_editor', 'example_use_widgets_block_editor' );
```
diff --git a/gutenberg/how-to-guides/widgets/overview.md b/docs/gutenberg/how-to-guides/widgets/overview.md
similarity index 100%
rename from gutenberg/how-to-guides/widgets/overview.md
rename to docs/gutenberg/how-to-guides/widgets/overview.md
diff --git a/docs/gutenberg/reference-guides/README.md b/docs/gutenberg/reference-guides/README.md
new file mode 100644
index 0000000..fc55998
--- /dev/null
+++ b/docs/gutenberg/reference-guides/README.md
@@ -0,0 +1,71 @@
+# Reference Guides
+
+## [Block API Reference](/docs/reference-guides/block-api/README.md)
+
+- [Annotations](/docs/reference-guides/block-api/block-annotations.md)
+- [API Versions](/docs/reference-guides/block-api/block-api-versions.md)
+- [Attributes](/docs/reference-guides/block-api/block-attributes.md)
+- [Context](/docs/reference-guides/block-api/block-context.md)
+- [Deprecation](/docs/reference-guides/block-api/block-deprecation.md)
+- [Edit and Save](/docs/reference-guides/block-api/block-edit-save.md)
+- [Patterns](/docs/reference-guides/block-api/block-patterns.md)
+- [Registration](/docs/reference-guides/block-api/block-registration.md)
+- [Supports](/docs/reference-guides/block-api/block-supports.md)
+- [Templates](/docs/reference-guides/block-api/block-templates.md)
+- [Transformations](/docs/reference-guides/block-api/block-transforms.md)
+- [Metadata](/docs/reference-guides/block-api/block-metadata.md)
+- [Variations](/docs/reference-guides/block-api/block-variations.md)
+
+## [Hooks Reference](/docs/reference-guides/filters/README.md)
+
+- [Block Filters](/docs/reference-guides/filters/block-filters.md)
+- [Editor Hooks](/docs/reference-guides/filters/editor-filters.md)
+- [i18n Hooks](/docs/reference-guides/filters/i18n-filters.md)
+- [Parser Hooks](/docs/reference-guides/filters/parser-filters.md)
+- [Autocomplete](/docs/reference-guides/filters/autocomplete-filters.md)
+- [Global Styles Hooks](/docs/reference-guides/filters/global-styles-filters.md)
+
+## [SlotFills Reference](/docs/reference-guides/slotfills/README.md)
+
+- [MainDashboardButton](/docs/reference-guides/slotfills/main-dashboard-button.md)
+- [PluginBlockSettingsMenuItem](/docs/reference-guides/slotfills/plugin-block-settings-menu-item.md)
+- [PluginDocumentSettingPanel](/docs/reference-guides/slotfills/plugin-document-setting-panel.md)
+- [PluginMoreMenuItem](/docs/reference-guides/slotfills/plugin-more-menu-item.md)
+- [PluginPostPublishPanel](/docs/reference-guides/slotfills/plugin-post-publish-panel.md)
+- [PluginPostStatusInfo](/docs/reference-guides/slotfills/plugin-post-status-info.md)
+- [PluginPrePublishPanel](/docs/reference-guides/slotfills/plugin-pre-publish-panel.md)
+- [PluginSidebar](/docs/reference-guides/slotfills/plugin-sidebar.md)
+- [PluginSidebarMoreMenuItem](/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md)
+
+## [Theme.json Reference](/docs/reference-guides/theme-json-reference/README.md)
+
+- [Version 3 (latest)](/docs/reference-guides/theme-json-reference/theme-json-living.md)
+- [Version 2](/docs/reference-guides/theme-json-reference/theme-json-v2.md)
+- [Version 1](/docs/reference-guides/theme-json-reference/theme-json-v1.md)
+- [Migrating to Newer Versions](/docs/reference-guides/theme-json-reference/theme-json-migrations.md)
+
+## [RichText Reference](/docs/reference-guides/richtext.md)
+
+## [Component Reference](/packages/components/README.md)
+
+## [Package Reference](/docs/reference-guides/packages.md)
+
+## [Data Module Reference](/docs/reference-guides/data/README.md)
+
+- [**core**: WordPress Core Data](/docs/reference-guides/data/data-core.md)
+ - [**core/annotations**: Annotations](/docs/reference-guides/data/data-core-annotations.md)
+ - [**core/block-directory**: Block directory](/docs/reference-guides/data/data-core-block-directory.md)
+ - [**core/block-editor**: The Block Editor’s Data](/docs/reference-guides/data/data-core-block-editor.md)
+ - [**core/blocks**: Block Types Data](/docs/reference-guides/data/data-core-blocks.md)
+ - [**core/customize-widgets**: Customize Widgets](/docs/reference-guides/data/data-core-customize-widgets.md)
+ - [**core/edit-post**: The Editor’s UI Data](/docs/reference-guides/data/data-core-edit-post.md)
+ - [**core/edit-site**: Edit Site](/docs/reference-guides/data/data-core-edit-site.md)
+ - [**core/edit-widgets**: Edit Widgets](/docs/reference-guides/data/data-core-edit-widgets.md)
+ - [**core/editor**: The Post Editor’s Data](/docs/reference-guides/data/data-core-editor.md)
+ - [**core/keyboard-shortcuts**: The Keyboard Shortcuts Data](/docs/reference-guides/data/data-core-keyboard-shortcuts.md)
+ - [**core/notices**: Notices Data](/docs/reference-guides/data/data-core-notices.md)
+ - [**core/nux**: The NUX (New User Experience) Data](/docs/reference-guides/data/data-core-nux.md)
+ - [**core/preferences**: Preferences](/docs/reference-guides/data/data-core-preferences.md)
+ - [**core/reusable-blocks**: Reusable blocks](/docs/reference-guides/data/data-core-reusable-blocks.md)
+ - [**core/rich-text**: Rich Text](/docs/reference-guides/data/data-core-rich-text.md)
+ - [**core/viewport**: The Viewport Data](/docs/reference-guides/data/data-core-viewport.md)
diff --git a/docs/gutenberg/reference-guides/block-api/README.md b/docs/gutenberg/reference-guides/block-api/README.md
new file mode 100644
index 0000000..65778d6
--- /dev/null
+++ b/docs/gutenberg/reference-guides/block-api/README.md
@@ -0,0 +1,22 @@
+# Block API Reference
+
+Blocks are the fundamental element of the editor. They are the primary way in which plugins and themes can register their own functionality and extend the capabilities of the editor.
+
+The following sections will walk you through the existing block APIs:
+
+- [Annotations](/docs/reference-guides/block-api/block-annotations.md)
+- [API Versions](/docs/reference-guides/block-api/block-api-versions.md)
+- [Attributes](/docs/reference-guides/block-api/block-attributes.md)
+- [Bindings](/docs/reference-guides/block-api/block-bindings.md)
+- [Context](/docs/reference-guides/block-api/block-context.md)
+- [Deprecation](/docs/reference-guides/block-api/block-deprecation.md)
+- [Edit and Save](/docs/reference-guides/block-api/block-edit-save.md)
+- [Metadata in block.json](/docs/reference-guides/block-api/block-metadata.md)
+- [Patterns](/docs/reference-guides/block-api/block-patterns.md)
+- [Registration](/docs/reference-guides/block-api/block-registration.md)
+- [Selectors](/docs/reference-guides/block-api/block-selectors.md)
+- [Styles](/docs/reference-guides/block-api/block-styles.md)
+- [Supports](/docs/reference-guides/block-api/block-supports.md)
+- [Transformations](/docs/reference-guides/block-api/block-transforms.md)
+- [Templates](/docs/reference-guides/block-api/block-templates.md)
+- [Variations](/docs/reference-guides/block-api/block-variations.md)
diff --git a/gutenberg/reference-guides/block-api/block-annotations.md b/docs/gutenberg/reference-guides/block-api/block-annotations.md
similarity index 85%
rename from gutenberg/reference-guides/block-api/block-annotations.md
rename to docs/gutenberg/reference-guides/block-api/block-annotations.md
index 89f64b4..2e042c9 100644
--- a/gutenberg/reference-guides/block-api/block-annotations.md
+++ b/docs/gutenberg/reference-guides/block-api/block-annotations.md
@@ -11,15 +11,15 @@ Annotations are a way to highlight a specific piece in a post created with the b
To see the API for yourself the easiest way is to have a block that is at least 200 characters long without formatting and putting the following in the console:
```js
-wp.data.dispatch( 'core/annotations' ).addAnnotation( {
- source: 'my-annotations-plugin',
- blockClientId: wp.data.select( 'core/block-editor' ).getBlockOrder()[ 0 ],
- richTextIdentifier: 'content',
- range: {
- start: 50,
- end: 100,
- },
-} );
+wp.data.dispatch('core/annotations').addAnnotation({
+ source: 'my-annotations-plugin',
+ blockClientId: wp.data.select('core/block-editor').getBlockOrder()[0],
+ richTextIdentifier: 'content',
+ range: {
+ start: 50,
+ end: 100,
+ },
+});
```
The start and the end of the range should be calculated based only on the text of the relevant `RichText`. For example, in the following HTML position 0 will refer to the position before the capital S:
@@ -41,18 +41,18 @@ For example the Paragraph block only has a single RichText instance, with the id
It is also possible to annotate a block completely. In that case just provide the `selector` property and set it to `block`. The default `selector` is `range`, which can be used for text annotation.
```js
-wp.data.dispatch( 'core/annotations' ).addAnnotation( {
- source: 'my-annotations-plugin',
- blockClientId: wp.data.select( 'core/block-editor' ).getBlockOrder()[ 0 ],
- selector: 'block',
-} );
+wp.data.dispatch('core/annotations').addAnnotation({
+ source: 'my-annotations-plugin',
+ blockClientId: wp.data.select('core/block-editor').getBlockOrder()[0],
+ selector: 'block',
+});
```
This doesn't provide any styling out of the box, so you have to provide some CSS to make sure your annotation is shown:
```css
.is-annotated-by-my-annotations-plugin {
- outline: 1px solid black;
+ outline: 1px solid black;
}
```
diff --git a/gutenberg/reference-guides/block-api/block-api-versions.md b/docs/gutenberg/reference-guides/block-api/block-api-versions.md
similarity index 63%
rename from gutenberg/reference-guides/block-api/block-api-versions.md
rename to docs/gutenberg/reference-guides/block-api/block-api-versions.md
index 07e11c7..13c03b0 100644
--- a/gutenberg/reference-guides/block-api/block-api-versions.md
+++ b/docs/gutenberg/reference-guides/block-api/block-api-versions.md
@@ -3,13 +3,14 @@
This document lists the changes made between the different API versions.
## Version 3 (>= WordPress 6.3)
+
- The post editor will be iframed if all registered blocks have a Block API version 3 or higher. Adding version 3 support means that the block should work inside an iframe, though the block may still be rendered outside the iframe if not all blocks support version 3.
- See [this article](https://make.wordpress.org/core/2021/06/29/blocks-in-an-iframed-template-editor/) for a migration guide to bump the API version to 3 and make them work in an iframe editor.
## Version 2 (>= WordPress 5.6)
-- To render the block element wrapper for the block's `edit` implementation, the block author must use the `useBlockProps()` hook.
-- The generated class names and styles are no longer added automatically to the saved markup for static blocks when `save` is processed. To include them, the block author must explicitly use `useBlockProps.save()` and add to their block wrapper.
+- To render the block element wrapper for the block's `edit` implementation, the block author must use the `useBlockProps()` hook.
+- The generated class names and styles are no longer added automatically to the saved markup for static blocks when `save` is processed. To include them, the block author must explicitly use `useBlockProps.save()` and add to their block wrapper.
## Version 1
diff --git a/gutenberg/reference-guides/block-api/block-attributes.md b/docs/gutenberg/reference-guides/block-api/block-attributes.md
similarity index 78%
rename from gutenberg/reference-guides/block-api/block-attributes.md
rename to docs/gutenberg/reference-guides/block-api/block-attributes.md
index 52f4a87..28e8c84 100644
--- a/gutenberg/reference-guides/block-api/block-attributes.md
+++ b/docs/gutenberg/reference-guides/block-api/block-attributes.md
@@ -10,22 +10,22 @@ _Example_: Attributes object defining three attributes - `url`, `title`, and `si
```js
{
- url: {
- type: 'string',
- source: 'attribute',
- selector: 'img',
- attribute: 'src',
- },
- title: {
- type: 'string',
- },
- size: {
- enum: [ 'large', 'small' ],
- },
+ url: {
+ type: 'string',
+ source: 'attribute',
+ selector: 'img',
+ attribute: 'src',
+ },
+ title: {
+ type: 'string',
+ },
+ size: {
+ enum: [ 'large', 'small' ],
+ },
}
```
-When a block is parsed this definition will be used to extract data from the block content. Anything that matches will be available to your block through the `attributes` prop.
+When a block is parsed this definition will be used to extract data from the block content. Anything that matches will be available to your block through the `attributes` prop.
This parsing process can be summarized as:
@@ -35,10 +35,12 @@ This parsing process can be summarized as:
_Example_: Attributes available in the `edit` and function, using the above attributes definition.
```js
-function YourBlockEdit( { attributes } ) {
- return (
-
URL is { attributes.url }, title is { attributes.title }, and size is { attributes.size }.
+ URL is {attributes.url}, title is {attributes.title}, and size is {attributes.size}.
+
+ );
}
```
@@ -51,10 +53,8 @@ For example, using the above attributes definition you would need to ensure that
_Example_: Example `save` function that contains the `url` attribute
```js
-function YourBlockSave( { attributes } ) {
- return (
-
- )
+function YourBlockSave({ attributes }) {
+ return ;
}
```
@@ -94,9 +94,9 @@ _Example_: Example `enum`.
```js
{
- size: {
- enum: [ 'large', 'small', 'tiny' ]
- }
+ size: {
+ enum: ['large', 'small', 'tiny'];
+ }
}
```
@@ -105,6 +105,7 @@ _Example_: Example `enum`.
Attribute sources are used to define how the attribute values are extracted from saved post content. They provide a mechanism to map from the saved markup to a JavaScript representation of a block.
The available `source` values are:
+
- `(no value)` - when no `source` is specified then data is stored in the block's [comment delimiter](/docs/explanations/architecture/key-concepts.md#data-attributes).
- `attribute` - data is stored in an HTML element attribute.
- `text` - data is stored in HTML text.
@@ -129,27 +130,30 @@ Use an `attribute` source to extract the value from an attribute in the markup.
_Example_: Extract the `src` attribute from an image found in the block's markup.
Saved content:
+
```html
- Block Content
+ Block Content
-
+
```
Attribute definition:
+
```js
{
- url: {
- type: 'string',
- source: 'attribute',
- selector: 'img',
- attribute: 'src',
- }
+ url: {
+ type: 'string',
+ source: 'attribute',
+ selector: 'img',
+ attribute: 'src',
+ }
}
```
Attribute available in the block:
+
```js
{ "url": "https://lorempixel.com/1200/800/" }
```
@@ -159,27 +163,30 @@ Most attributes from markup will be of type `string`. Numeric attributes in HTML
_Example_: Extract the `width` attribute from an image found in the block's markup.
Saved content:
+
```html
- Block Content
+ Block Content
-
+
```
Attribute definition:
+
```js
{
- width: {
- type: 'string',
- source: 'attribute',
- selector: 'img',
- attribute: 'width',
- }
+ width: {
+ type: 'string',
+ source: 'attribute',
+ selector: 'img',
+ attribute: 'width',
+ }
}
```
Attribute available in the block:
+
```js
{ "width": "50" }
```
@@ -189,27 +196,30 @@ The only exception is when checking for the existence of an attribute (for examp
_Example_: Extract the `disabled` attribute from a button found in the block's markup.
Saved content:
+
```html
- Block Content
+ Block Content
-
+
```
Attribute definition:
+
```js
{
- disabled: {
- type: 'boolean',
- source: 'attribute',
- selector: 'button',
- attribute: 'disabled',
- }
+ disabled: {
+ type: 'boolean',
+ source: 'attribute',
+ selector: 'button',
+ attribute: 'disabled',
+ }
}
```
Attribute available in the block:
+
```js
{ "disabled": true }
```
@@ -221,26 +231,29 @@ Use `text` to extract the inner text from markup. Note that HTML is returned acc
_Example_: Extract the `content` attribute from a figcaption element found in the block's markup.
Saved content:
+
```html
-
+
- The inner text of the figcaption element
+ The inner text of the figcaption element
```
Attribute definition:
+
```js
{
- content: {
- type: 'string',
- source: 'text',
- selector: 'figcaption',
- }
+ content: {
+ type: 'string',
+ source: 'text',
+ selector: 'figcaption',
+ }
}
```
Attribute available in the block:
+
```js
{ "content": "The inner text of the figcaption element" }
```
@@ -250,26 +263,29 @@ Another example, using `text` as the source, and using `.my-content` class as th
_Example_: Extract the `content` attribute from an element with `.my-content` class found in the block's markup.
Saved content:
+
```html
-
+
-
The inner text of .my-content class
+
The inner text of .my-content class
```
Attribute definition:
+
```js
{
- content: {
- type: 'string',
- source: 'text',
- selector: '.my-content',
- }
+ content: {
+ type: 'string',
+ source: 'text',
+ selector: '.my-content',
+ }
}
```
Attribute available in the block:
+
```js
{ "content": "The inner text of .my-content class" }
```
@@ -281,26 +297,29 @@ Use `html` to extract the inner HTML from markup. Note that text is returned acc
_Example_: Extract the `content` attribute from a figcaption element found in the block's markup.
Saved content:
+
```html
-
+
- The inner text of the figcaption element
+ The inner text of the figcaption element
```
Attribute definition:
+
```js
{
- content: {
- type: 'string',
- source: 'html',
- selector: 'figcaption',
- }
+ content: {
+ type: 'string',
+ source: 'html',
+ selector: 'figcaption',
+ }
}
```
Attribute available in the block:
+
```js
{ "content": "The inner text of the figcaption element" }
```
@@ -314,43 +333,46 @@ The `query` field is effectively a nested block attributes definition. It is pos
_Example_: Extract `src` and `alt` from each image element in the block's markup.
Saved content:
+
```html
-
-
+
+
```
Attribute definition:
+
```js
{
- images: {
- type: 'array',
- source: 'query',
- selector: 'img',
- query: {
- url: {
- type: 'string',
- source: 'attribute',
- attribute: 'src',
- },
- alt: {
- type: 'string',
- source: 'attribute',
- attribute: 'alt',
- },
- }
- }
+ images: {
+ type: 'array',
+ source: 'query',
+ selector: 'img',
+ query: {
+ url: {
+ type: 'string',
+ source: 'attribute',
+ attribute: 'src',
+ },
+ alt: {
+ type: 'string',
+ source: 'attribute',
+ attribute: 'alt',
+ },
+ }
+ }
}
```
Attribute available in the block:
+
```js
{
- "images": [
- { "url": "https://lorempixel.com/1200/800/", "alt": "large image" },
- { "url": "https://lorempixel.com/50/50/", "alt": "small image" }
- ]
+ "images": [
+ { "url": "https://lorempixel.com/1200/800/", "alt": "large image" },
+ { "url": "https://lorempixel.com/50/50/", "alt": "small image" }
+ ]
}
```
@@ -363,13 +385,14 @@ Although attributes may be obtained from a post's meta, meta attribute sources a
Attributes may be obtained from a post's meta rather than from the block's representation in saved post content. For this, an attribute is required to specify its corresponding meta key under the `meta` key.
Attribute definition:
+
```js
{
- author: {
- type: 'string',
- source: 'meta',
- meta: 'author'
- },
+ author: {
+ type: 'string',
+ source: 'meta',
+ meta: 'author'
+ },
},
```
@@ -377,42 +400,41 @@ From here, meta attributes can be read and written by a block using the same int
```js
edit( { attributes, setAttributes } ) {
- function onChange( event ) {
- setAttributes( { author: event.target.value } );
- }
+ function onChange( event ) {
+ setAttributes( { author: event.target.value } );
+ }
- return ;
+ return ;
},
```
-
#### Considerations
By default, a meta field will be excluded from a post object's meta. This can be circumvented by explicitly making the field visible:
```php
function gutenberg_my_block_init() {
- register_post_meta( 'post', 'author', array(
- 'show_in_rest' => true,
- ) );
+ register_post_meta( 'post', 'author', array(
+ 'show_in_rest' => true,
+ ) );
}
add_action( 'init', 'gutenberg_my_block_init' );
```
Furthermore, be aware that WordPress defaults to:
-- not treating a meta datum as being unique, instead returning an array of values;
-- treating that datum as a string.
+- not treating a meta datum as being unique, instead returning an array of values;
+- treating that datum as a string.
If either behavior is not desired, the same `register_post_meta` call can be complemented with the `single` and/or `type` parameters as follows:
```php
function gutenberg_my_block_init() {
- register_post_meta( 'post', 'author_count', array(
- 'show_in_rest' => true,
- 'single' => true,
- 'type' => 'integer',
- ) );
+ register_post_meta( 'post', 'author_count', array(
+ 'show_in_rest' => true,
+ 'single' => true,
+ 'type' => 'integer',
+ ) );
}
add_action( 'init', 'gutenberg_my_block_init' );
```
@@ -422,8 +444,8 @@ If you'd like to use an object or an array in an attribute, you can register a `
Lastly, make sure that you respect the data's type when setting attributes, as the framework does not automatically perform type casting of meta. Incorrect typing in block attributes will result in a post remaining dirty even after saving (_cf._ `isEditedPostDirty`, `hasEditedAttributes`). For instance, if `authorCount` is an integer, remember that event handlers may pass a different kind of data, thus the value should be cast explicitly:
```js
-function onChange( event ) {
- props.setAttributes( { authorCount: Number( event.target.value ) } );
+function onChange(event) {
+ props.setAttributes({ authorCount: Number(event.target.value) });
}
```
@@ -437,28 +459,28 @@ _Example_: Example `default` values.
```js
{
- type: 'string',
- default: 'hello world'
+ type: 'string',
+ default: 'hello world'
}
```
```js
{
- type: 'array',
- default: [
- { "url": "https://lorempixel.com/1200/800/", "alt": "large image" },
- { "url": "https://lorempixel.com/50/50/", "alt": "small image" }
- ]
+ type: 'array',
+ default: [
+ { "url": "https://lorempixel.com/1200/800/", "alt": "large image" },
+ { "url": "https://lorempixel.com/50/50/", "alt": "small image" }
+ ]
}
```
```js
{
- type: 'object',
- default: {
- width: 100,
- title: 'title'
- }
+ type: 'object',
+ default: {
+ width: 100,
+ title: 'title'
+ }
}
```
@@ -493,4 +515,4 @@ _Example_: `local` role used for temporary data.
}
```
-Learn more in the [WordPress 6.7 dev note](https://make.wordpress.org/core/2024/10/20/miscellaneous-block-editor-changes-in-wordpress-6-7/#stabilized-role-property-for-block-attributes).
\ No newline at end of file
+Learn more in the [WordPress 6.7 dev note](https://make.wordpress.org/core/2024/10/20/miscellaneous-block-editor-changes-in-wordpress-6-7/#stabilized-role-property-for-block-attributes).
diff --git a/gutenberg/reference-guides/block-api/block-bindings.md b/docs/gutenberg/reference-guides/block-api/block-bindings.md
similarity index 67%
rename from gutenberg/reference-guides/block-api/block-bindings.md
rename to docs/gutenberg/reference-guides/block-api/block-bindings.md
index dc4e397..96effda 100644
--- a/gutenberg/reference-guides/block-api/block-bindings.md
+++ b/docs/gutenberg/reference-guides/block-api/block-bindings.md
@@ -20,17 +20,16 @@ An example could be connecting an Image block `url` attribute to a function that
} -->
```
-
## Compatible blocks and their attributes
Right now, not all block attributes are compatible with block bindings. There is some ongoing effort to increase this compatibility, but for now, this is the list:
-| Supported Blocks | Supported Attributes |
-| ---------------- | -------------------- |
-| Paragraph | content |
-| Heading | content |
-| Image | id, url, title, alt |
-| Button | text, url, linkTarget, rel |
+| Supported Blocks | Supported Attributes |
+| ---------------- | -------------------------- |
+| Paragraph | content |
+| Heading | content |
+| Image | id, url, title, alt |
+| Button | text, url, linkTarget, rel |
## Registering a custom source
@@ -50,9 +49,9 @@ The function to register a custom source is `register_block_bindings_source($nam
- `name`: `string` that sets the unique ID for the custom source.
- `args`: `array` that contains:
- - `label`: `string` with the human-readable name of the custom source.
- - `uses_context`: `array` with the block context that is passed to the callback (optional).
- - `get_value_callback`: `function` that will run on the bound block's render function. It accepts three arguments: `source_args`, `block_instance` and `attribute_name`. This value can be overridden with the filter `block_bindings_source_value`.
+ - `label`: `string` with the human-readable name of the custom source.
+ - `uses_context`: `array` with the block context that is passed to the callback (optional).
+ - `get_value_callback`: `function` that will run on the bound block's render function. It accepts three arguments: `source_args`, `block_instance` and `attribute_name`. This value can be overridden with the filter `block_bindings_source_value`.
Note that `register_block_bindings_source()` should be called from a handler attached to the `init` hook.
@@ -60,22 +59,22 @@ Here is an example:
```php
add_action(
- 'init',
- function () {
- register_block_bindings_source(
- 'wpmovies/visualization-date',
- array(
- 'label' => __( 'Visualization Date', 'custom-bindings' ),
- 'get_value_callback' => function ( array $source_args, $block_instance ) {
- $post_id = $block_instance->context['postId'];
- if ( isset( $source_args['key'] ) ) {
- return get_post_meta( $post_id, $source_args['key'], true );
- }
- },
- 'uses_context' => array( 'postId' ),
- )
- );
- }
+ 'init',
+ function () {
+ register_block_bindings_source(
+ 'wpmovies/visualization-date',
+ array(
+ 'label' => __( 'Visualization Date', 'custom-bindings' ),
+ 'get_value_callback' => function ( array $source_args, $block_instance ) {
+ $post_id = $block_instance->context['postId'];
+ if ( isset( $source_args['key'] ) ) {
+ return get_post_meta( $post_id, $source_args['key'], true );
+ }
+ },
+ 'uses_context' => array( 'postId' ),
+ )
+ );
+ }
);
```
@@ -83,19 +82,19 @@ This example needs a `post_meta` registered, and, also, a filter can be used to
```php
add_action(
- 'init',
- function () {
- register_meta(
- 'post',
- 'wp_movies_visualization_date',
- array(
- 'show_in_rest' => true,
- 'single' => true,
- 'type' => 'string',
- 'label' => __( 'Movie visualization date', 'custom-bindings' ),
- )
- );
- }
+ 'init',
+ function () {
+ register_meta(
+ 'post',
+ 'wp_movies_visualization_date',
+ array(
+ 'show_in_rest' => true,
+ 'single' => true,
+ 'type' => 'string',
+ 'label' => __( 'Movie visualization date', 'custom-bindings' ),
+ )
+ );
+ }
);
```
@@ -120,14 +119,14 @@ Example:
```php
function wpmovies_format_visualization_date( $value, $name ) {
- // Prevent the filter to be applied to other sources.
- if ( $name !== 'wpmovies/visualization-date' ) {
- return $value;
- }
- if ( ! $value ) {
- return date( 'm/d/Y' );
- }
- return date( 'm/d/Y', strtotime( $value ) );
+ // Prevent the filter to be applied to other sources.
+ if ( $name !== 'wpmovies/visualization-date' ) {
+ return $value;
+ }
+ if ( ! $value ) {
+ return date( 'm/d/Y' );
+ }
+ return date( 'm/d/Y', strtotime( $value ) );
}
add_filter( 'block_bindings_source_value', 'wpmovies_format_visualization_date', 10, 2 );
@@ -141,7 +140,6 @@ There are a few examples in Core that can be used as reference.
- Pattern overrides. [Source code](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/block-bindings/pattern-overrides.php)
- Twenty Twenty-Five theme. [Source code](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-content/themes/twentytwentyfive/functions.php)
-
### Editor registration
_**Note:** Since WordPress 6.7._
@@ -151,63 +149,55 @@ Editor registration on the client allows defining what the bound block will do w
The function to register a custom source is `registerBlockBindingsSource( args )`:
- `args`: `object` with the following structure:
- - `name`: `string` with the unique and machine-readable name.
- - `label`: `string` with the human readable name of the custom source. In case it was defined already on the server, the server label will be overridden by this one, in that case, it is not recommended to be defined here. (optional)
- - `usesContext`: `array` with the block context that the custom source may need. In case it was defined already on the server, it should not be defined here. (optional)
- - `getValues`: `function` that retrieves the values from the source. (optional)
- - `setValues`: `function` that allows updating the values connected to the source. (optional)
- - `canUserEditValue`: `function` to determine if the user can edit the value. The user won't be able to edit by default. (optional)
-
+ - `name`: `string` with the unique and machine-readable name.
+ - `label`: `string` with the human readable name of the custom source. In case it was defined already on the server, the server label will be overridden by this one, in that case, it is not recommended to be defined here. (optional)
+ - `usesContext`: `array` with the block context that the custom source may need. In case it was defined already on the server, it should not be defined here. (optional)
+ - `getValues`: `function` that retrieves the values from the source. (optional)
+ - `setValues`: `function` that allows updating the values connected to the source. (optional)
+ - `canUserEditValue`: `function` to determine if the user can edit the value. The user won't be able to edit by default. (optional)
This example will show a custom post meta date in the editor and, if it doesn't exist, it will show today's date. The user can edit the value of the date. (Caution: This example does not format the user input as a date—it's only for educational purposes.)
```js
-import {
- registerBlockBindingsSource,
-} from '@wordpress/blocks';
+import { registerBlockBindingsSource } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { store as coreDataStore } from '@wordpress/core-data';
-registerBlockBindingsSource( {
- name: 'wpmovies/visualization-date',
- label: __( 'Visualization Date', 'custom-bindings' ), // We can skip the label, as it was already defined in the server in the previous example.
- usesContext: [ 'postType' ], // We can skip postId, as it was already defined in the server in the previous example.
- getValues( { select, context } ) {
- let wpMoviesVisualizationDate;
- const { getEditedEntityRecord } = select( coreDataStore );
- if ( context?.postType && context?.postId ) {
- wpMoviesVisualizationDate = getEditedEntityRecord(
- 'postType',
- context?.postType,
- context?.postId
- ).meta?.wp_movies_visualization_date;
- }
- if ( wpMoviesVisualizationDate ) {
- return {
- content: wpMoviesVisualizationDate,
- };
- }
-
- return {
- content: new Date().toLocaleDateString( 'en-US' ),
- };
- },
- setValues( { select, dispatch, context, bindings } ) {
- dispatch( coreDataStore ).editEntityRecord(
- 'postType',
- context?.postType,
- context?.postId,
- {
- meta: {
- wp_movies_visualization_date: bindings?.content?.newValue,
- },
- }
- );
- },
- canUserEditValue( { select, context } ) {
- return true;
- },
-} );
+registerBlockBindingsSource({
+ name: 'wpmovies/visualization-date',
+ label: __('Visualization Date', 'custom-bindings'), // We can skip the label, as it was already defined in the server in the previous example.
+ usesContext: ['postType'], // We can skip postId, as it was already defined in the server in the previous example.
+ getValues({ select, context }) {
+ let wpMoviesVisualizationDate;
+ const { getEditedEntityRecord } = select(coreDataStore);
+ if (context?.postType && context?.postId) {
+ wpMoviesVisualizationDate = getEditedEntityRecord(
+ 'postType',
+ context?.postType,
+ context?.postId
+ ).meta?.wp_movies_visualization_date;
+ }
+ if (wpMoviesVisualizationDate) {
+ return {
+ content: wpMoviesVisualizationDate,
+ };
+ }
+
+ return {
+ content: new Date().toLocaleDateString('en-US'),
+ };
+ },
+ setValues({ select, dispatch, context, bindings }) {
+ dispatch(coreDataStore).editEntityRecord('postType', context?.postType, context?.postId, {
+ meta: {
+ wp_movies_visualization_date: bindings?.content?.newValue,
+ },
+ });
+ },
+ canUserEditValue({ select, context }) {
+ return true;
+ },
+});
```
#### getValues
@@ -232,7 +222,6 @@ The `setValues` function updates all the values of the source of the block bound
- `dispatch` returns an `object` of the store's action creators. [More about dispatch](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#dispatch).
- `select` returns an `object` of a given store's selectors. [More info in their docs.](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#select).
-
#### Editor registration Core examples
There are a few examples in Core that can be used as reference.
@@ -249,7 +238,7 @@ _**Note:** Since WordPress 6.7._
```js
import { unregisterBlockBindingsSource } from '@wordpress/blocks';
-unregisterBlockBindingsSource( 'plugin/my-custom-source' );
+unregisterBlockBindingsSource('plugin/my-custom-source');
```
## Getting all sources
@@ -273,7 +262,7 @@ _**Note:** Since WordPress 6.7._
```js
import { getBlockBindingsSource } from '@wordpress/blocks';
-const blockBindingsSource = getBlockBindingsSource( 'plugin/my-custom-source' );
+const blockBindingsSource = getBlockBindingsSource('plugin/my-custom-source');
```
## Block Bindings Utils
@@ -302,17 +291,17 @@ import { useBlockBindingsUtils } from '@wordpress/block-editor';
const { updateBlockBindings } = useBlockBindingsUtils();
-function updateBlockBindingsURLSource( url ) {
- updateBlockBindings({
- url: {
- source: 'myplugin/new-source',
- }
- })
+function updateBlockBindingsURLSource(url) {
+ updateBlockBindings({
+ url: {
+ source: 'myplugin/new-source',
+ },
+ });
}
// Remove binding from url attribute.
function removeBlockBindingsURLSource() {
- updateBlockBindings( { url: undefined } );
+ updateBlockBindings({ url: undefined });
}
```
@@ -326,9 +315,6 @@ import { useBlockBindingsUtils } from '@wordpress/block-editor';
const { removeAllBlockBindings } = useBlockBindingsUtils();
function clearBlockBindings() {
- removeAllBlockBindings();
+ removeAllBlockBindings();
}
```
-
-
-
diff --git a/gutenberg/reference-guides/block-api/block-context.md b/docs/gutenberg/reference-guides/block-api/block-context.md
similarity index 73%
rename from gutenberg/reference-guides/block-api/block-context.md
rename to docs/gutenberg/reference-guides/block-api/block-context.md
index c5fcfae..f28a252 100644
--- a/gutenberg/reference-guides/block-api/block-context.md
+++ b/docs/gutenberg/reference-guides/block-api/block-context.md
@@ -15,15 +15,15 @@ Block context is defined in the registered settings of a block. A block can prov
A block can provide a context value by assigning a `providesContext` property in its registered settings. This is an object which maps a context name to one of the block's own attributes. The value corresponding to that attribute value is made available to descendent blocks and can be referenced by the same context name. Currently, block context only supports values derived from the block's own attributes. This could be enhanced in the future to support additional sources of context values.
```js
- attributes: {
- recordId: {
- type: 'number',
- },
- },
-
- providesContext: {
- 'my-plugin/recordId': 'recordId',
- },
+ attributes: {
+ recordId: {
+ type: 'number',
+ },
+ },
+
+ providesContext: {
+ 'my-plugin/recordId': 'recordId',
+ },
```
For a complete example, refer to the section below.
@@ -38,10 +38,10 @@ A block can inherit a context value from an ancestor provider by assigning a `us
```js
registerBlockType('my-plugin/record-title', {
- title: 'Record Title',
- category: 'widgets',
+ title: 'Record Title',
+ category: 'widgets',
- usesContext: ['my-plugin/recordId'],
+ usesContext: ['my-plugin/recordId'],
```
@@ -56,9 +56,9 @@ Note: Block Context is not available to `save`.
```js
registerBlockType('my-plugin/record-title', {
- edit({ context }) {
- return 'The record ID: ' + context['my-plugin/recordId'];
- },
+ edit({ context }) {
+ return 'The record ID: ' + context['my-plugin/recordId'];
+ },
```
@@ -68,9 +68,9 @@ A block's context values are available from the `context` property of the `$bloc
```php
register_block_type( 'my-plugin/record-title', array(
- 'render_callback' => function( $attributes, $content, $block ) {
- return 'The current record ID is: ' . $block->context['my-plugin/recordId'];
- },
+ 'render_callback' => function( $attributes, $content, $block ) {
+ return 'The current record ID is: ' . $block->context['my-plugin/recordId'];
+ },
) );
```
@@ -86,44 +86,44 @@ cd record
2. Edit `src/index.js`. Insert the `recordId` attribute and `providesContext` property in the `registerBlockType` function and add the registration of the `record-title` block at the bottom:
```js
-registerBlockType( 'my-plugin/record', {
- // ... cut ...
-
- attributes: {
- recordId: {
- type: 'number',
- },
- },
-
- providesContext: {
- 'my-plugin/recordId': 'recordId',
- },
-
- /**
- * @see ./edit.js
- */
- edit: Edit,
-
- /**
- * @see ./save.js
- */
- save,
-} );
-
-registerBlockType( 'my-plugin/record-title', {
- title: 'Record Title',
- category: 'widgets',
-
- usesContext: [ 'my-plugin/recordId' ],
-
- edit( { context } ) {
- return 'The record ID: ' + context[ 'my-plugin/recordId' ];
- },
-
- save() {
- return null;
- },
-} );
+registerBlockType('my-plugin/record', {
+ // ... cut ...
+
+ attributes: {
+ recordId: {
+ type: 'number',
+ },
+ },
+
+ providesContext: {
+ 'my-plugin/recordId': 'recordId',
+ },
+
+ /**
+ * @see ./edit.js
+ */
+ edit: Edit,
+
+ /**
+ * @see ./save.js
+ */
+ save,
+});
+
+registerBlockType('my-plugin/record-title', {
+ title: 'Record Title',
+ category: 'widgets',
+
+ usesContext: ['my-plugin/recordId'],
+
+ edit({ context }) {
+ return 'The record ID: ' + context['my-plugin/recordId'];
+ },
+
+ save() {
+ return null;
+ },
+});
```
3. Edit `src/edit.js` for the `record` block. Replace the `Edit` function with the following code:
@@ -132,34 +132,32 @@ registerBlockType( 'my-plugin/record-title', {
import { TextControl } from '@wordpress/components';
import { InnerBlocks } from '@wordpress/block-editor';
-export default function Edit( props ) {
- const MY_TEMPLATE = [ [ 'my-plugin/record-title', {} ] ];
- const {
- attributes: { recordId },
- setAttributes,
- } = props;
- return (
-
+ );
}
```
4. Edit `src/save.js` for the `record` block. Replace the `save` function with the following code:
```js
-export default function save( props ) {
- return
The record ID: { props.attributes.recordId }
;
+export default function save(props) {
+ return
The record ID: {props.attributes.recordId}
;
}
```
diff --git a/gutenberg/reference-guides/block-api/block-deprecation.md b/docs/gutenberg/reference-guides/block-api/block-deprecation.md
similarity index 56%
rename from gutenberg/reference-guides/block-api/block-deprecation.md
rename to docs/gutenberg/reference-guides/block-api/block-deprecation.md
index 0da85ee..9db0ab7 100644
--- a/gutenberg/reference-guides/block-api/block-deprecation.md
+++ b/docs/gutenberg/reference-guides/block-api/block-deprecation.md
@@ -4,8 +4,8 @@
When updating static blocks markup and attributes, block authors need to consider existing posts using the old versions of their block. To provide a good upgrade path, you can choose one of the following strategies:
-- Do not deprecate the block and create a new one (a different name)
-- Provide a "deprecated" version of the block allowing users opening these in the block editor to edit them using the updated block.
+- Do not deprecate the block and create a new one (a different name)
+- Provide a "deprecated" version of the block allowing users opening these in the block editor to edit them using the updated block.
A block can have several deprecated versions. A deprecation will be tried if the current state of a parsed block is invalid, or if the deprecation defines an `isEligible` function that returns true.
@@ -29,31 +29,31 @@ For blocks with multiple deprecations, it may be easier to save each deprecation
const v1 = {};
const v2 = {};
const v3 = {};
-const deprecated = [ v3, v2, v1 ];
+const deprecated = [v3, v2, v1];
```
It is also recommended to keep [fixtures](https://github.com/WordPress/gutenberg/blob/HEAD/test/integration/fixtures/blocks/README.md) which contain the different versions of the block content to allow you to easily test that new deprecations and migrations are working across all previous versions of the block.
Deprecations are defined on a block type as its `deprecated` property, an array of deprecation objects where each object takes the form:
-- `attributes` (Object): The [attributes definition](/docs/reference-guides/block-api/block-attributes.md) of the deprecated form of the block.
-- `supports` (Object): The [supports definition](/docs/reference-guides/block-api/block-registration.md) of the deprecated form of the block.
-- `save` (Function): The [save implementation](/docs/reference-guides/block-api/block-edit-save.md) of the deprecated form of the block.
-- `migrate`: (Function, Optional). A function which, given the old attributes and inner blocks is expected to return either the new attributes or a tuple array of attributes and inner blocks compatible with the block. As mentioned above, a deprecation's `migrate` will not be run if its `save` function does not return a valid block so you will need to make sure your migrations are available in all the deprecations where they are relevant.
- - _Parameters_
- - `attributes`: The block's old attributes.
- - `innerBlocks`: The block's old inner blocks.
- - _Return_
- - `Object | Array`: Either the updated block attributes or tuple array `[attributes, innerBlocks]`.
-- `isEligible`: (Function, Optional). A function which returns `true` if the deprecation can handle the block migration even if the block is valid. It is particularly useful in cases where a block is technically valid even once deprecated, but still requires updates to its attributes or inner blocks. This function is **not** called when the results of all previous deprecations' save functions were invalid.
- - _Parameters_
- - `attributes`: The raw block attributes as parsed from the serialized HTML, and before the block type code is applied.
- - `innerBlocks`: The block's current inner blocks.
- - `data`: An object containing properties representing the block node and its resulting block object.
- - `data.blockNode`: The raw form of the block as a result of parsing the serialized HTML.
- - `data.block`: The block object, which is the result of applying the block type to the `blockNode`.
- - _Return_
- - `boolean`: Whether or not this otherwise valid block is eligible to be migrated by this deprecation.
+- `attributes` (Object): The [attributes definition](/docs/reference-guides/block-api/block-attributes.md) of the deprecated form of the block.
+- `supports` (Object): The [supports definition](/docs/reference-guides/block-api/block-registration.md) of the deprecated form of the block.
+- `save` (Function): The [save implementation](/docs/reference-guides/block-api/block-edit-save.md) of the deprecated form of the block.
+- `migrate`: (Function, Optional). A function which, given the old attributes and inner blocks is expected to return either the new attributes or a tuple array of attributes and inner blocks compatible with the block. As mentioned above, a deprecation's `migrate` will not be run if its `save` function does not return a valid block so you will need to make sure your migrations are available in all the deprecations where they are relevant.
+ - _Parameters_
+ - `attributes`: The block's old attributes.
+ - `innerBlocks`: The block's old inner blocks.
+ - _Return_
+ - `Object | Array`: Either the updated block attributes or tuple array `[attributes, innerBlocks]`.
+- `isEligible`: (Function, Optional). A function which returns `true` if the deprecation can handle the block migration even if the block is valid. It is particularly useful in cases where a block is technically valid even once deprecated, but still requires updates to its attributes or inner blocks. This function is **not** called when the results of all previous deprecations' save functions were invalid.
+ - _Parameters_
+ - `attributes`: The raw block attributes as parsed from the serialized HTML, and before the block type code is applied.
+ - `innerBlocks`: The block's current inner blocks.
+ - `data`: An object containing properties representing the block node and its resulting block object.
+ - `data.blockNode`: The raw form of the block as a result of parsing the serialized HTML.
+ - `data.block`: The block object, which is the result of applying the block type to the `blockNode`.
+ - _Return_
+ - `boolean`: Whether or not this otherwise valid block is eligible to be migrated by this deprecation.
It's important to note that attributes, supports, and save are not automatically inherited from the current version, since they can impact parsing and serialization of a block, so they must be defined on the deprecated object in order to be processed during a migration.
@@ -64,38 +64,38 @@ It's important to note that attributes, supports, and
```js
const { registerBlockType } = wp.blocks;
const attributes = {
- text: {
- type: 'string',
- default: 'some random value',
- },
+ text: {
+ type: 'string',
+ default: 'some random value',
+ },
};
const supports = {
- className: false,
+ className: false,
};
-registerBlockType( 'gutenberg/block-with-deprecated-version', {
- // ... other block properties go here
+registerBlockType('gutenberg/block-with-deprecated-version', {
+ // ... other block properties go here
- attributes,
+ attributes,
- supports,
+ supports,
- save( props ) {
- return
;
+ },
+ },
+ ],
+});
```
In the example above we updated the markup of the block to use a `div` instead of `p`.
@@ -106,48 +106,46 @@ Sometimes, you need to update the attributes set to rename or modify old attribu
**Example**
-
```js
const { registerBlockType } = wp.blocks;
-registerBlockType( 'gutenberg/block-with-deprecated-version', {
- // ... other block properties go here
-
- attributes: {
- content: {
- type: 'string',
- default: 'some random value',
- },
- },
-
- save( props ) {
- return
;
+ },
+ },
+ ],
+});
```
-
In the example above we updated the markup of the block to use a `div` instead of `p` and rename the `text` attribute to `content`.
## Changing the innerBlocks
@@ -160,44 +158,44 @@ E.g: a block wants to migrate a title attribute to a paragraph innerBlock.
```js
const { registerBlockType } = wp.blocks;
-registerBlockType( 'gutenberg/block-with-deprecated-version', {
- // ... block properties go here
-
- save( props ) {
- return
;
+ },
+ },
+ ],
+});
```
In the example above we updated the block to use an inner Paragraph block with a title instead of a title attribute.
diff --git a/gutenberg/reference-guides/block-api/block-edit-save.md b/docs/gutenberg/reference-guides/block-api/block-edit-save.md
similarity index 73%
rename from gutenberg/reference-guides/block-api/block-edit-save.md
rename to docs/gutenberg/reference-guides/block-api/block-edit-save.md
index 00da32a..65bdcd4 100644
--- a/gutenberg/reference-guides/block-api/block-edit-save.md
+++ b/docs/gutenberg/reference-guides/block-api/block-edit-save.md
@@ -6,21 +6,20 @@ When registering a block with JavaScript on the client, the `edit` and `save` fu
The `edit` function describes the structure of your block in the context of the editor. This represents what the editor will render when the block is used.
-
```jsx
import { useBlockProps } from '@wordpress/block-editor';
// ...
const blockSettings = {
- apiVersion: 3,
+ apiVersion: 3,
- // ...
+ // ...
- edit: () => {
- const blockProps = useBlockProps();
+ edit: () => {
+ const blockProps = useBlockProps();
- return
Your block.
;
- },
+ return
Your block.
;
+ },
};
```
@@ -30,27 +29,25 @@ The first thing to notice here is the use of the `useBlockProps` React hook on t
If the element wrapper needs any extra custom HTML attributes, these need to be passed as an argument to the `useBlockProps` hook. For example to add a `my-random-classname` className to the wrapper, you can use the following code:
-
```jsx
import { useBlockProps } from '@wordpress/block-editor';
// ...
const blockSettings = {
- apiVersion: 3,
+ apiVersion: 3,
- // ...
+ // ...
- edit: () => {
- const blockProps = useBlockProps( {
- className: 'my-random-classname',
- } );
+ edit: () => {
+ const blockProps = useBlockProps({
+ className: 'my-random-classname',
+ });
- return
Your block.
;
- },
+ return
Your block.
;
+ },
};
```
-
### attributes
The `edit` function also receives a number of properties through an object argument. You can use these properties to adapt the behavior of your block.
@@ -59,35 +56,30 @@ The `attributes` property surfaces all the available attributes and their corres
In this case, assuming we had defined an attribute of `content` during block registration, we would receive and use that value in our edit function:
-
```js
-edit: ( { attributes } ) => {
- const blockProps = useBlockProps();
+edit: ({ attributes }) => {
+ const blockProps = useBlockProps();
- return
{ attributes.content }
;
+ return
{attributes.content}
;
};
```
-
The value of `attributes.content` will be displayed inside the `div` when inserting the block in the editor.
### isSelected
The isSelected property is a boolean that communicates whether the block is currently selected.
-
```jsx
-edit: ( { attributes, isSelected } ) => {
- const blockProps = useBlockProps();
-
- return (
-
- Your block.
- { isSelected && (
- Shows only when the block is selected.
- ) }
-
+ Your block.
+ {isSelected && Shows only when the block is selected.}
+
+ );
};
```
@@ -95,24 +87,21 @@ edit: ( { attributes, isSelected } ) => {
This function allows the block to update individual attributes based on user interactions.
-
```jsx
-edit: ( { attributes, setAttributes, isSelected } ) => {
- const blockProps = useBlockProps();
-
- // Simplify access to attributes
- const { content, mySetting } = attributes;
-
- // Toggle a setting when the user clicks the button
- const toggleSetting = () => setAttributes( { mySetting: ! mySetting } );
- return (
-
- { content }
- { isSelected && (
-
- ) }
-
- );
+edit: ({ attributes, setAttributes, isSelected }) => {
+ const blockProps = useBlockProps();
+
+ // Simplify access to attributes
+ const { content, mySetting } = attributes;
+
+ // Toggle a setting when the user clicks the button
+ const toggleSetting = () => setAttributes({ mySetting: !mySetting });
+ return (
+
+ {content}
+ {isSelected && }
+
+ );
};
```
@@ -121,18 +110,16 @@ When using attributes that are objects or arrays it's a good idea to copy or clo
```js
// Good - a new array is created from the old list attribute and a new list item:
const { list } = attributes;
-const addListItem = ( newListItem ) =>
- setAttributes( { list: [ ...list, newListItem ] } );
+const addListItem = (newListItem) => setAttributes({ list: [...list, newListItem] });
// Bad - the list from the existing attribute is modified directly to add the new list item:
const { list } = attributes;
-const addListItem = ( newListItem ) => {
- list.push( newListItem );
- setAttributes( { list } );
+const addListItem = (newListItem) => {
+ list.push(newListItem);
+ setAttributes({ list });
};
```
-
Why do this? In JavaScript, arrays and objects are passed by reference, so this practice ensures changes won't affect other code that might hold references to the same data. Furthermore, the Gutenberg project follows the philosophy of the Redux library that [state should be immutable](https://redux.js.org/faq/immutable-data#what-are-the-benefits-of-immutability)—data should not be changed directly, but instead a new version of the data created containing the changes.
The `setAttribute` also supports an updater function as an argument. It must be a pure function, which takes current attributes as its only argument and returns updated attributes. This method is helpful when you want to update an value based on a previous state or when working with objects and arrays.
@@ -142,31 +129,29 @@ _**Note:** Since WordPress 6.9._
```js
// Toggle a setting when the user clicks the button.
const toggleSetting = () =>
- setAttributes( ( currentAttr ) => ( {
- mySetting: ! currentAttr.mySetting,
- } ) );
+ setAttributes((currentAttr) => ({
+ mySetting: !currentAttr.mySetting,
+ }));
// Add item to the list.
-const addListItem = ( newListItem ) =>
- setAttributes( ( currentAttr ) => ( {
- list: [ ...currentAttr.list, newListItem ],
- } ) );
+const addListItem = (newListItem) =>
+ setAttributes((currentAttr) => ({
+ list: [...currentAttr.list, newListItem],
+ }));
```
## Save
The `save` function defines the way in which the different attributes should be combined into the final markup, which is then serialized into `post_content`.
-
```jsx
save: () => {
- const blockProps = useBlockProps.save();
+ const blockProps = useBlockProps.save();
- return
Your block.
;
+ return
Your block.
;
};
```
-
For most blocks, the return value of `save` should be an [instance of WordPress Element](/packages/element/README.md) representing how the block is to appear on the front of the site.
_Note:_ While it is possible to return a string value from `save`, it _will be escaped_. If the string includes HTML markup, the markup will be shown on the front of the site verbatim, not as the equivalent HTML node content. If you must return raw HTML from `save`, use `wp.element.RawHTML`. As the name implies, this is prone to [cross-site scripting](https://en.wikipedia.org/wiki/Cross-site_scripting) and therefore is discouraged in favor of a WordPress Element hierarchy whenever possible.
@@ -176,8 +161,8 @@ This is because if the external information changes, the block may be flagged as
If there is a need to have other information as part of the save, developers can consider one of these two alternatives:
-- Use [dynamic blocks](/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md) and dynamically retrieve the required information on the server.
-- Store the external value as an attribute which is dynamically updated in the block's `edit` function as changes occur.
+- Use [dynamic blocks](/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md) and dynamically retrieve the required information on the server.
+- Store the external value as an attribute which is dynamically updated in the block's `edit` function as changes occur.
For [dynamic blocks](/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md), the return value of `save` could represent a cached copy of the block's content to be shown only in case the plugin implementing the block is ever disabled.
@@ -191,16 +176,14 @@ Like the `edit` function, when rendering static blocks, it's important to add th
As with `edit`, the `save` function also receives an object argument including attributes which can be inserted into the markup.
-
```jsx
-save: ( { attributes } ) => {
- const blockProps = useBlockProps.save();
+save: ({ attributes }) => {
+ const blockProps = useBlockProps.save();
- return
{ attributes.content }
;
+ return
{attributes.content}
;
};
```
-
When saving your block, you want to save the attributes in the same format specified by the attribute source definition. If no attribute source is specified, the attribute will be saved to the block's comment delimiter. See the [Block Attributes documentation](/docs/reference-guides/block-api/block-attributes.md) for more details.
### innerBlocks
@@ -210,23 +193,21 @@ There is a second property in the props passed to the `save` function, `innerBlo
`innerBlocks`, when initialized, is an array containing object representations of nested blocks. In those rare cases where you might use this property,
it can help you adjust how a block is rendered. For example, you could render a block differently based on the number of nested blocks or if a specific block type is present..
-
```jsx
-save: ( { attributes, innerBlocks } ) => {
- const { className, ...rest } = useBlockProps.save();
+save: ({ attributes, innerBlocks }) => {
+ const { className, ...rest } = useBlockProps.save();
- // innerBlocks could also be an object - react element during initialization
- const numberOfInnerBlocks = innerBlocks?.length;
- if ( numberOfInnerBlocks > 1 ) {
- className = className + ( className ? ' ' : '' ) + 'more-than-one';
- };
- const blockProps = { ...rest, className };
+ // innerBlocks could also be an object - react element during initialization
+ const numberOfInnerBlocks = innerBlocks?.length;
+ if (numberOfInnerBlocks > 1) {
+ className = className + (className ? ' ' : '') + 'more-than-one';
+ }
+ const blockProps = { ...rest, className };
- return
{ attributes.content }
;
+ return
{attributes.content}
;
};
```
-
Here, an additional class is added to the block if number of inner blocks is greater than one, allowing for different styling of the block.
## Examples
@@ -235,76 +216,73 @@ Here are a couple examples of using attributes, edit, and save all together.
### Saving Attributes to Child Elements
-
```jsx
attributes: {
- content: {
- type: 'string',
- source: 'html',
- selector: 'div'
- }
+ content: {
+ type: 'string',
+ source: 'html',
+ selector: 'div'
+ }
},
edit: ( { attributes, setAttributes } ) => {
- const blockProps = useBlockProps();
- const updateFieldValue = ( val ) => {
- setAttributes( { content: val } );
- }
- return (
-
;
},
```
-
### Saving Attributes via Serialization
Ideally, the attributes saved should be included in the markup. However, there are times when this is not practical, so if no attribute source is specified the attribute is serialized and saved to the block's comment delimiter.
This example could be for a dynamic block, such as the [Latest Posts block](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/latest-posts/index.js), which renders the markup server-side. The save function is still required, however in this case it simply returns null since the block is not saving content from the editor.
-
```jsx
attributes: {
- postsToShow: {
- type: 'number',
- }
+ postsToShow: {
+ type: 'number',
+ }
},
edit: ( { attributes, setAttributes } ) => {
- const blockProps = useBlockProps();
-
- return (
-
+ );
},
save: () => {
- return null;
+ return null;
}
```
@@ -320,11 +298,11 @@ Clicking the **Attempt Block Recovery** button will attempt a recovery action as
Clicking the "3-dot" menu on the side of the block displays three options:
-- **Resolve**: Open Resolve Block dialog box with two buttons:
- - **Convert to HTML**: Protects the original markup from the saved post content and converts the block from its original type to the HTML block type, enabling the user to modify the HTML markup directly.
- - **Convert to Blocks**: Protects the original markup from the saved post content and converts the block from its original type to the validated block type.
-- **Convert to HTML**: Protects the original markup from the saved post content and converts the block from its original type to the HTML block type, enabling the user to modify the HTML markup directly.
-- **Convert to Classic Block**: Protects the original markup from the saved post content as correct. Since the block will be converted from its original type to the Classic block type, it will no longer be possible to edit the content using controls available for the original block type.
+- **Resolve**: Open Resolve Block dialog box with two buttons:
+ - **Convert to HTML**: Protects the original markup from the saved post content and converts the block from its original type to the HTML block type, enabling the user to modify the HTML markup directly.
+ - **Convert to Blocks**: Protects the original markup from the saved post content and converts the block from its original type to the validated block type.
+- **Convert to HTML**: Protects the original markup from the saved post content and converts the block from its original type to the HTML block type, enabling the user to modify the HTML markup directly.
+- **Convert to Classic Block**: Protects the original markup from the saved post content as correct. Since the block will be converted from its original type to the Classic block type, it will no longer be possible to edit the content using controls available for the original block type.
### Validation FAQ
diff --git a/gutenberg/reference-guides/block-api/block-metadata.md b/docs/gutenberg/reference-guides/block-api/block-metadata.md
similarity index 69%
rename from gutenberg/reference-guides/block-api/block-metadata.md
rename to docs/gutenberg/reference-guides/block-api/block-metadata.md
index d79f1cd..c4615b2 100644
--- a/gutenberg/reference-guides/block-api/block-metadata.md
+++ b/docs/gutenberg/reference-guides/block-api/block-metadata.md
@@ -6,59 +6,59 @@ Starting with the WordPress 5.8 release, we recommend using the `block.json` met
```json
{
- "$schema": "https://schemas.wp.org/trunk/block.json",
- "apiVersion": 3,
- "name": "my-plugin/notice",
- "title": "Notice",
- "category": "text",
- "parent": [ "core/group" ],
- "icon": "star",
- "description": "Shows warning, error or success notices...",
- "keywords": [ "alert", "message" ],
- "version": "1.0.3",
- "textdomain": "my-plugin",
- "attributes": {
- "message": {
- "type": "string",
- "source": "html",
- "selector": ".message"
- }
- },
- "providesContext": {
- "my-plugin/message": "message"
- },
- "usesContext": [ "groupId" ],
- "selectors": {
- "root": ".wp-block-my-plugin-notice"
- },
- "supports": {
- "align": true
- },
- "styles": [
- { "name": "default", "label": "Default", "isDefault": true },
- { "name": "other", "label": "Other" }
- ],
- "example": {
- "attributes": {
- "message": "This is a notice!"
- }
- },
- "variations": [
- {
- "name": "example",
- "title": "Example",
- "attributes": {
- "message": "This is an example!"
- }
- }
- ],
- "editorScript": "file:./index.js",
- "script": "file:./script.js",
- "viewScript": [ "file:./view.js", "example-shared-view-script" ],
- "editorStyle": "file:./index.css",
- "style": [ "file:./style.css", "example-shared-style" ],
- "viewStyle": [ "file:./view.css", "example-view-style" ],
- "render": "file:./render.php"
+ "$schema": "https://schemas.wp.org/trunk/block.json",
+ "apiVersion": 3,
+ "name": "my-plugin/notice",
+ "title": "Notice",
+ "category": "text",
+ "parent": ["core/group"],
+ "icon": "star",
+ "description": "Shows warning, error or success notices...",
+ "keywords": ["alert", "message"],
+ "version": "1.0.3",
+ "textdomain": "my-plugin",
+ "attributes": {
+ "message": {
+ "type": "string",
+ "source": "html",
+ "selector": ".message"
+ }
+ },
+ "providesContext": {
+ "my-plugin/message": "message"
+ },
+ "usesContext": ["groupId"],
+ "selectors": {
+ "root": ".wp-block-my-plugin-notice"
+ },
+ "supports": {
+ "align": true
+ },
+ "styles": [
+ { "name": "default", "label": "Default", "isDefault": true },
+ { "name": "other", "label": "Other" }
+ ],
+ "example": {
+ "attributes": {
+ "message": "This is a notice!"
+ }
+ },
+ "variations": [
+ {
+ "name": "example",
+ "title": "Example",
+ "attributes": {
+ "message": "This is an example!"
+ }
+ }
+ ],
+ "editorScript": "file:./index.js",
+ "script": "file:./script.js",
+ "viewScript": ["file:./view.js", "example-shared-view-script"],
+ "editorStyle": "file:./index.css",
+ "style": ["file:./style.css", "example-shared-style"],
+ "viewStyle": ["file:./view.css", "example-view-style"],
+ "render": "file:./render.php"
}
```
@@ -88,11 +88,11 @@ This section describes all the properties that can be added to the `block.json`
### API version
-- Type: `number`
-- Optional
-- Localized: No
-- Property: `apiVersion`
-- Default: `1`
+- Type: `number`
+- Optional
+- Localized: No
+- Property: `apiVersion`
+- Default: `1`
```json
{ "apiVersion": 3 }
@@ -104,10 +104,10 @@ See [the API versions documentation](/docs/reference-guides/block-api/block-api-
### Name
-- Type: `string`
-- Required
-- Localized: No
-- Property: `name`
+- Type: `string`
+- Required
+- Localized: No
+- Property: `name`
```json
{ "name": "core/heading" }
@@ -121,10 +121,10 @@ The name for a block is a unique string that identifies a block. Names have to b
### Title
-- Type: `string`
-- Required
-- Localized: Yes
-- Property: `title`
+- Type: `string`
+- Required
+- Localized: Yes
+- Property: `title`
```json
{ "title": "Heading" }
@@ -136,10 +136,10 @@ This is the display title for your block, which can be translated with our trans
### Category
-- Type: `string`
-- Optional
-- Localized: No
-- Property: `category`
+- Type: `string`
+- Optional
+- Localized: No
+- Property: `category`
```json
{ "category": "text" }
@@ -149,12 +149,12 @@ Blocks are grouped into categories to help users browse and discover them.
The core provided categories are:
-- text
-- media
-- design
-- widgets
-- theme
-- embed
+- text
+- media
+- design
+- widgets
+- theme
+- embed
Plugins and Themes can also register [custom block categories](/docs/reference-guides/filters/block-filters.md#managing-block-categories).
@@ -162,51 +162,51 @@ An implementation should expect and tolerate unknown categories, providing some
### Parent
-- Type: `string[]`
-- Optional
-- Localized: No
-- Property: `parent`
+- Type: `string[]`
+- Optional
+- Localized: No
+- Property: `parent`
```json
-{ "parent": [ "my-block/product" ] }
+{ "parent": ["my-block/product"] }
```
Setting `parent` lets a block require that it is only available when nested within the specified blocks. For example, you might want to allow an 'Add to Cart' block to only be available within a 'Product' block.
### Ancestor
-- Type: `string[]`
-- Optional
-- Localized: No
-- Property: `ancestor`
-- Since: `WordPress 6.0.0`
+- Type: `string[]`
+- Optional
+- Localized: No
+- Property: `ancestor`
+- Since: `WordPress 6.0.0`
```json
-{ "ancestor": [ "my-block/product" ] }
+{ "ancestor": ["my-block/product"] }
```
The `ancestor` property makes a block available inside the specified block types at any position of the ancestor block subtree. That allows, for example, to place a ‘Comment Content’ block inside a ‘Column’ block, as long as ‘Column’ is somewhere within a ‘Comment Template’ block. In comparison to the `parent` property blocks that specify their `ancestor` can be placed anywhere in the subtree whilst blocks with a specified `parent` need to be direct children.
### Allowed Blocks
-- Type: `string[]`
-- Optional
-- Localized: No
-- Property: `allowedBlocks`
-- Since: `WordPress 6.5.0`
+- Type: `string[]`
+- Optional
+- Localized: No
+- Property: `allowedBlocks`
+- Since: `WordPress 6.5.0`
```json
-{ "allowedBlocks": [ "my-block/product" ] }
+{ "allowedBlocks": ["my-block/product"] }
```
The `allowedBlocks` specifies which block types can be the direct children of the block. For example, a ‘List’ block can allow only ‘List Item’ blocks as children.
### Icon
-- Type: `string`
-- Optional
-- Localized: No
-- Property: `icon`
+- Type: `string`
+- Optional
+- Localized: No
+- Property: `icon`
```json
{ "icon": "smile" }
@@ -218,14 +218,14 @@ An icon property should be specified to make it easier to identify a block. Thes
### Description
-- Type: `string`
-- Optional
-- Localized: Yes
-- Property: `description`
+- Type: `string`
+- Optional
+- Localized: Yes
+- Property: `description`
```json
{
- "description": "Introduce new sections and organize content to help visitors"
+ "description": "Introduce new sections and organize content to help visitors"
}
```
@@ -233,25 +233,25 @@ This is a short description for your block, which can be translated with our tra
### Keywords
-- Type: `string[]`
-- Optional
-- Localized: Yes
-- Property: `keywords`
-- Default: `[]`
+- Type: `string[]`
+- Optional
+- Localized: Yes
+- Property: `keywords`
+- Default: `[]`
```json
-{ "keywords": [ "keyword1", "keyword2" ] }
+{ "keywords": ["keyword1", "keyword2"] }
```
Sometimes a block could have aliases that help users discover it while searching. For example, an image block could also want to be discovered by photo. You can do so by providing an array of unlimited terms (which are translated).
### Version
-- Type: `string`
-- Optional
-- Localized: No
-- Property: `version`
-- Since: `WordPress 5.8.0`
+- Type: `string`
+- Optional
+- Localized: No
+- Property: `version`
+- Since: `WordPress 5.8.0`
```json
{ "version": "1.0.3" }
@@ -261,11 +261,11 @@ The current version number of the block, such as 1.0 or 1.0.3. It's similar to h
### Text Domain
-- Type: `string`
-- Optional
-- Localized: No
-- Property: `textdomain`
-- Since: `WordPress 5.7.0`
+- Type: `string`
+- Optional
+- Localized: No
+- Property: `textdomain`
+- Since: `WordPress 5.7.0`
```json
{ "textdomain": "my-plugin" }
@@ -275,27 +275,27 @@ The [gettext](https://www.gnu.org/software/gettext/) text domain of the plugin/b
### Attributes
-- Type: `object`
-- Optional
-- Localized: No
-- Property: `attributes`
-- Default: `{}`
+- Type: `object`
+- Optional
+- Localized: No
+- Property: `attributes`
+- Default: `{}`
```json
{
- "attributes": {
- "cover": {
- "type": "string",
- "source": "attribute",
- "selector": "img",
- "attribute": "src"
- },
- "author": {
- "type": "string",
- "source": "html",
- "selector": ".book-author"
- }
- }
+ "attributes": {
+ "cover": {
+ "type": "string",
+ "source": "attribute",
+ "selector": "img",
+ "attribute": "src"
+ },
+ "author": {
+ "type": "string",
+ "source": "html",
+ "selector": ".book-author"
+ }
+ }
}
```
@@ -305,11 +305,11 @@ See [the attributes documentation](/docs/reference-guides/block-api/block-attrib
### Provides Context
-- Type: `object`
-- Optional
-- Localized: No
-- Property: `providesContext`
-- Default: `{}`
+- Type: `object`
+- Optional
+- Localized: No
+- Property: `providesContext`
+- Default: `{}`
Context provided for available access by descendants of blocks of this type, in the form of an object which maps a context name to one of the block's own attributes.
@@ -317,19 +317,19 @@ See [the block context documentation](/docs/reference-guides/block-api/block-con
```json
{
- "providesContext": {
- "my-plugin/recordId": "recordId"
- }
+ "providesContext": {
+ "my-plugin/recordId": "recordId"
+ }
}
```
### Context
-- Type: `string[]`
-- Optional
-- Localized: No
-- Property: `usesContext`
-- Default: `[]`
+- Type: `string[]`
+- Optional
+- Localized: No
+- Property: `usesContext`
+- Default: `[]`
Array of the names of context values to inherit from an ancestor provider.
@@ -337,18 +337,18 @@ See [the block context documentation](/docs/reference-guides/block-api/block-con
```json
{
- "usesContext": [ "message" ]
+ "usesContext": ["message"]
}
```
### Selectors
-- Type: `object`
-- Optional
-- Localized: No
-- Property: `selectors`
-- Default: `{}`
-- Since: `WordPress 6.3.0`
+- Type: `object`
+- Optional
+- Localized: No
+- Property: `selectors`
+- Default: `{}`
+- Since: `WordPress 6.3.0`
Any custom CSS selectors, keyed by `root`, feature, or sub-feature, to be used
when generating block styles for theme.json (global styles) stylesheets.
@@ -360,43 +360,43 @@ See [the selectors documentation](/docs/reference-guides/block-api/block-selecto
```json
{
- "selectors": {
- "root": ".my-custom-block-selector",
- "color": {
- "text": ".my-custom-block-selector p"
- },
- "typography": {
- "root": ".my-custom-block-selector > h2",
- "text-decoration": ".my-custom-block-selector > h2 span"
- }
- }
+ "selectors": {
+ "root": ".my-custom-block-selector",
+ "color": {
+ "text": ".my-custom-block-selector p"
+ },
+ "typography": {
+ "root": ".my-custom-block-selector > h2",
+ "text-decoration": ".my-custom-block-selector > h2 span"
+ }
+ }
}
```
### Supports
-- Type: `object`
-- Optional
-- Localized: No
-- Property: `supports`
-- Default: `{}`
+- Type: `object`
+- Optional
+- Localized: No
+- Property: `supports`
+- Default: `{}`
It contains a set of options to control features used in the editor. See [the supports documentation](/docs/reference-guides/block-api/block-supports.md) for more details.
### Block Styles
-- Type: `array`
-- Optional
-- Localized: Yes (`label` only)
-- Property: `styles`
-- Default: `[]`
+- Type: `array`
+- Optional
+- Localized: Yes (`label` only)
+- Property: `styles`
+- Default: `[]`
```json
{
- "styles": [
- { "name": "default", "label": "Default", "isDefault": true },
- { "name": "other", "label": "Other" }
- ]
+ "styles": [
+ { "name": "default", "label": "Default", "isDefault": true },
+ { "name": "other", "label": "Other" }
+ ]
}
```
@@ -406,18 +406,18 @@ Plugins and Themes can also register [custom block styles](/docs/reference-guide
### Example
-- Type: `object`
-- Optional
-- Localized: No
-- Property: `example`
+- Type: `object`
+- Optional
+- Localized: No
+- Property: `example`
```json
{
- "example": {
- "attributes": {
- "message": "This is a notice!"
- }
- }
+ "example": {
+ "attributes": {
+ "message": "This is a notice!"
+ }
+ }
}
```
@@ -427,26 +427,26 @@ See the [Example documentation](/docs/reference-guides/block-api/block-registrat
### Variations
-- Type: `object[]|WPDefinedPath` ([learn more](#wpdefinedpath))
-- Optional
-- Localized: Yes (`title`, `description`, and `keywords` of each variation only)
-- Property: `variations`
-- Since: `WordPress 5.9.0`
+- Type: `object[]|WPDefinedPath` ([learn more](#wpdefinedpath))
+- Optional
+- Localized: Yes (`title`, `description`, and `keywords` of each variation only)
+- Property: `variations`
+- Since: `WordPress 5.9.0`
```json
{
- "variations": [
- {
- "name": "example",
- "title": "Example",
- "attributes": {
- "level": 2,
- "message": "This is an example!"
- },
- "scope": [ "block" ],
- "isActive": [ "level" ]
- }
- ]
+ "variations": [
+ {
+ "name": "example",
+ "title": "Example",
+ "attributes": {
+ "level": 2,
+ "message": "This is an example!"
+ },
+ "scope": ["block"],
+ "isActive": ["level"]
+ }
+ ]
}
```
@@ -469,29 +469,29 @@ For example:
// Generate variations for a Social Icon kind of block.
return array(
- array(
- 'isDefault' => true,
- 'name' => 'wordpress',
- 'title' => 'WordPress',
- 'icon' => 'wordpress',
- 'attributes' => array(
- 'service' => 'wordpress',
- ),
- 'isActive' => array( 'service' )
- ),
- array(
- 'name' => 'mail',
- 'title' => __( 'Mail' ),
- 'keywords' => array(
- __( 'email' ),
- __( 'e-mail' )
- ),
- 'icon' => 'mail',
- 'attributes' => array(
- 'service' => 'mail',
- ),
- 'isActive' => array( 'mail' )
- ),
+ array(
+ 'isDefault' => true,
+ 'name' => 'wordpress',
+ 'title' => 'WordPress',
+ 'icon' => 'wordpress',
+ 'attributes' => array(
+ 'service' => 'wordpress',
+ ),
+ 'isActive' => array( 'service' )
+ ),
+ array(
+ 'name' => 'mail',
+ 'title' => __( 'Mail' ),
+ 'keywords' => array(
+ __( 'email' ),
+ __( 'e-mail' )
+ ),
+ 'icon' => 'mail',
+ 'attributes' => array(
+ 'service' => 'mail',
+ ),
+ 'isActive' => array( 'mail' )
+ ),
);
```
@@ -500,16 +500,16 @@ See [the variations documentation](/docs/reference-guides/block-api/block-variat
### Block Hooks
-- Type: `object`
-- Optional
-- Property: `blockHooks`
-- Since: `WordPress 6.4.0`
+- Type: `object`
+- Optional
+- Property: `blockHooks`
+- Since: `WordPress 6.4.0`
```json
{
- "blockHooks": {
- "my-plugin/banner": "after"
- }
+ "blockHooks": {
+ "my-plugin/banner": "after"
+ }
}
```
@@ -519,10 +519,10 @@ The key is the name of the block (`string`) to hook into, and the value is the p
### Editor script
-- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
-- Optional
-- Localized: No
-- Property: `editorScript`
+- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
+- Optional
+- Localized: No
+- Property: `editorScript`
```json
{ "editorScript": "file:./index.js" }
@@ -536,10 +536,10 @@ _Note: An option to pass also an array of editor scripts exists since WordPress
### Script
-- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
-- Optional
-- Localized: No
-- Property: `script`
+- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
+- Optional
+- Localized: No
+- Property: `script`
```json
{ "script": "file:./script.js" }
@@ -553,14 +553,14 @@ _Note: An option to pass also an array of scripts exists since WordPress `6.1.0`
### View script
-- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
-- Optional
-- Localized: No
-- Property: `viewScript`
-- Since: `WordPress 5.9.0`
+- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
+- Optional
+- Localized: No
+- Property: `viewScript`
+- Since: `WordPress 5.9.0`
```json
-{ "viewScript": [ "file:./view.js", "example-shared-view-script" ] }
+{ "viewScript": ["file:./view.js", "example-shared-view-script"] }
```
Block type frontend scripts definition. They will be enqueued only when viewing the content on the front of the site.
@@ -571,14 +571,14 @@ _Note: An option to pass also an array of view scripts exists since WordPress `6
### View script module
-- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
-- Optional
-- Localized: No
-- Property: `viewScriptModule`
-- Since: `WordPress 6.5.0`
+- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
+- Optional
+- Localized: No
+- Property: `viewScriptModule`
+- Since: `WordPress 6.5.0`
```json
-{ "viewScriptModule": [ "file:./view.js", "example-shared-script-module-id" ] }
+{ "viewScriptModule": ["file:./view.js", "example-shared-script-module-id"] }
```
Block type frontend script module definition. They will be enqueued only when viewing the content on the front of the site.
@@ -591,10 +591,10 @@ _Note: Available since WordPress `6.5.0`._
### Editor style
-- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
-- Optional
-- Localized: No
-- Property: `editorStyle`
+- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
+- Optional
+- Localized: No
+- Property: `editorStyle`
```json
{ "editorStyle": "file:./index.css" }
@@ -608,13 +608,13 @@ _Note: An option to pass also an array of editor styles exists since WordPress `
### Style
-- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
-- Optional
-- Localized: No
-- Property: `style`
+- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
+- Optional
+- Localized: No
+- Property: `style`
```json
-{ "style": [ "file:./style.css", "example-shared-style" ] }
+{ "style": ["file:./style.css", "example-shared-style"] }
```
Block type frontend and editor styles definition. They will be enqueued both in the editor and when viewing the content on the front of the site.
@@ -625,14 +625,14 @@ _Note: An option to pass also an array of styles exists since WordPress `5.9.0`.
### View Style
-- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
-- Optional
-- Localized: No
-- Property: `viewStyle`
-- Since: `WordPress 6.5.0`
+- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
+- Optional
+- Localized: No
+- Property: `viewStyle`
+- Since: `WordPress 6.5.0`
```json
-{ "viewStyle": [ "file:./view.css", "example-view-style" ] }
+{ "viewStyle": ["file:./view.css", "example-view-style"] }
```
Block type frontend styles definition. They will be enqueued only when viewing the content on the front of the site.
@@ -643,11 +643,11 @@ Frontend-only styles are especially useful for interactive blocks, to style part
### Render
-- Type: `WPDefinedPath` ([learn more](#wpdefinedpath))
-- Optional
-- Localized: No
-- Property: `render`
-- Since: `WordPress 6.1.0`
+- Type: `WPDefinedPath` ([learn more](#wpdefinedpath))
+- Optional
+- Localized: No
+- Property: `render`
+- Since: `WordPress 6.1.0`
```json
{ "render": "file:./render.php" }
@@ -655,15 +655,15 @@ Frontend-only styles are especially useful for interactive blocks, to style part
PHP file to use when rendering the block type on the server to show on the front end. The following variables are exposed to the file:
-- `$attributes` (`array`): The block attributes.
-- `$content` (`string`): The block default content.
-- `$block` (`WP_Block`): The block instance.
+- `$attributes` (`array`): The block attributes.
+- `$content` (`string`): The block default content.
+- `$block` (`WP_Block`): The block instance.
An example implementation of the `render.php` file defined with `render` could look like:
```php
>
-
+
```
@@ -681,7 +681,7 @@ In `block.json`:
```json
{
- "render": "file:./render.php"
+ "render": "file:./render.php"
}
```
@@ -695,15 +695,12 @@ In `block.json`:
```json
{
- "editorScript": "file:./index.js",
- "script": "file:./script.js",
- "viewScriptModule": [
- "file:./view.js",
- "example-registered-script-module-id"
- ],
- "editorStyle": "file:./index.css",
- "style": [ "file:./style.css", "example-shared-style" ],
- "viewStyle": [ "file:./view.css", "example-view-style" ]
+ "editorScript": "file:./index.js",
+ "script": "file:./script.js",
+ "viewScriptModule": ["file:./view.js", "example-registered-script-module-id"],
+ "editorStyle": "file:./index.css",
+ "style": ["file:./style.css", "example-shared-style"],
+ "viewStyle": ["file:./view.css", "example-view-style"]
}
```
@@ -713,9 +710,9 @@ That's why the `WPDefinedAsset` type has to offer a way to mirror the parameters
It's possible to provide an object which takes the following shape:
-- `handle` (`string`) - the name of the script. If omitted, it will be auto-generated.
-- `dependencies` (`string[]`|`{ id: string, import?: 'dynamic'|'static' }[]`) - an array of registered script handles this script depends on. Script modules may use a simple string for static dependencies or the object form to indicate a dynamic dependency. Dynamic dependencies are dependencies that may or may not be used at runtime and are typically used with the dynamic `import('module-id')` syntax. Default value: `[]`.
-- `version` (`string`|`false`|`null`) - string specifying the script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If the version is set to `false`, a version number is automatically added equal to the currently installed WordPress version. If set to `null`, no version is added. Default value: `false`.
+- `handle` (`string`) - the name of the script. If omitted, it will be auto-generated.
+- `dependencies` (`string[]`|`{ id: string, import?: 'dynamic'|'static' }[]`) - an array of registered script handles this script depends on. Script modules may use a simple string for static dependencies or the object form to indicate a dynamic dependency. Dynamic dependencies are dependencies that may or may not be used at runtime and are typically used with the dynamic `import('module-id')` syntax. Default value: `[]`.
+- `version` (`string`|`false`|`null`) - string specifying the script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If the version is set to `false`, a version number is automatically added equal to the currently installed WordPress version. If set to `null`, no version is added. Default value: `false`.
The definition is stored inside a separate PHP file which ends with `.asset.php` and is located next to the JS/CSS file listed in `block.json`. WordPress will automatically detect this file through pattern matching. This option is the preferred one as it is expected it will become an option to auto-generate those asset files with `@wordpress/scripts` package.
@@ -739,12 +736,12 @@ In `build/index.asset.php`:
```php
array(
- 'react',
- 'wp-blocks',
- 'wp-i18n',
- ),
- 'version' => '3be55b05081a63d8f9d0ecb466c42cfd',
+ 'dependencies' => array(
+ 'react',
+ 'wp-blocks',
+ 'wp-i18n',
+ ),
+ 'version' => '3be55b05081a63d8f9d0ecb466c42cfd',
);
```
@@ -752,10 +749,10 @@ return array(
Starting in the WordPress 5.8 release, it is possible to instruct WordPress to enqueue scripts and styles for a block type only when rendered on the frontend. It applies to the following asset fields in the `block.json` file:
-- `script`
-- `viewScript`
-- `style`
-- `viewStyle` (Added in WordPress 6.5.0)
+- `script`
+- `viewScript`
+- `style`
+- `viewStyle` (Added in WordPress 6.5.0)
## Internationalization
@@ -765,10 +762,10 @@ WordPress string discovery system can automatically translate fields marked in t
```json
{
- "title": "My block",
- "description": "My block is fantastic",
- "keywords": [ "fantastic" ],
- "textdomain": "my-plugin"
+ "title": "My block",
+ "description": "My block is fantastic",
+ "keywords": ["fantastic"],
+ "textdomain": "my-plugin"
}
```
@@ -781,9 +778,9 @@ The way `register_block_type` processes translatable values is roughly equivalen
```php
_x( 'My block', 'block title', 'my-plugin' ),
- 'description' => _x( 'My block is fantastic!', 'block description', 'my-plugin' ),
- 'keywords' => array( _x( 'fantastic', 'block keyword', 'my-plugin' ) ),
+ 'title' => _x( 'My block', 'block title', 'my-plugin' ),
+ 'description' => _x( 'My block is fantastic!', 'block description', 'my-plugin' ),
+ 'keywords' => array( _x( 'fantastic', 'block keyword', 'my-plugin' ) ),
);
```
@@ -800,10 +797,10 @@ import { registerBlockType } from '@wordpress/blocks';
import Edit from './edit';
import metadata from './block.json';
-registerBlockType( metadata, {
- edit: Edit,
- // ...other client-side settings
-} );
+registerBlockType(metadata, {
+ edit: Edit,
+ // ...other client-side settings
+});
```
## Backward compatibility
@@ -814,29 +811,29 @@ Once all details are ready, Core Blocks will be migrated iteratively and third-p
The following properties are going to be supported for backward compatibility reasons on the client-side only. Some of them might be replaced with alternative APIs in the future:
-- `edit` - see the [Edit and Save](/docs/reference-guides/block-api/block-edit-save.md) documentation for more details.
-- `save` - see the [Edit and Save](/docs/reference-guides/block-api/block-edit-save.md) documentation for more details.
-- `transforms` - see the [Transforms](/docs/reference-guides/block-api/block-registration.md#transforms-optional) documentation for more details.
-- `deprecated` - see the [Deprecated Blocks](/docs/reference-guides/block-api/block-deprecation.md) documentation for more details.
-- `merge` - undocumented as of today. Its role is to handle merging multiple blocks into one.
-- `getEditWrapperProps` - undocumented as well. Its role is to inject additional props to the block edit's component wrapper.
+- `edit` - see the [Edit and Save](/docs/reference-guides/block-api/block-edit-save.md) documentation for more details.
+- `save` - see the [Edit and Save](/docs/reference-guides/block-api/block-edit-save.md) documentation for more details.
+- `transforms` - see the [Transforms](/docs/reference-guides/block-api/block-registration.md#transforms-optional) documentation for more details.
+- `deprecated` - see the [Deprecated Blocks](/docs/reference-guides/block-api/block-deprecation.md) documentation for more details.
+- `merge` - undocumented as of today. Its role is to handle merging multiple blocks into one.
+- `getEditWrapperProps` - undocumented as well. Its role is to inject additional props to the block edit's component wrapper.
**Example**:
```js
import { registerBlockType } from '@wordpress/blocks';
-registerBlockType( 'my-plugin/block-name', {
- edit: function () {
- // Edit definition goes here.
- },
- save: function () {
- // Save definition goes here.
- },
- getEditWrapperProps: function () {
- // Implementation goes here.
- },
-} );
+registerBlockType('my-plugin/block-name', {
+ edit: function () {
+ // Edit definition goes here.
+ },
+ save: function () {
+ // Save definition goes here.
+ },
+ getEditWrapperProps: function () {
+ // Implementation goes here.
+ },
+});
```
In the case of [dynamic blocks](/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md) supported by WordPress, it should still be possible to register the `render_callback` property using both [`register_block_type`](https://developer.wordpress.org/reference/functions/register_block_type/) functions on the server.
diff --git a/gutenberg/reference-guides/block-api/block-patterns.md b/docs/gutenberg/reference-guides/block-api/block-patterns.md
similarity index 61%
rename from gutenberg/reference-guides/block-api/block-patterns.md
rename to docs/gutenberg/reference-guides/block-api/block-patterns.md
index b0096e2..6c8fd61 100644
--- a/gutenberg/reference-guides/block-api/block-patterns.md
+++ b/docs/gutenberg/reference-guides/block-api/block-patterns.md
@@ -9,33 +9,34 @@ Block Patterns are predefined block layouts available from the patterns tab of t
The editor comes with several core block patterns. Theme and plugin authors can register additional custom block patterns using the `register_block_pattern` helper function.
The `register_block_pattern` helper function receives two arguments.
-- `title`: A machine-readable title with a naming convention of `namespace/title`.
-- `properties`: An array describing properties of the pattern.
+
+- `title`: A machine-readable title with a naming convention of `namespace/title`.
+- `properties`: An array describing properties of the pattern.
The properties available for block patterns are:
-- `title` (required): A human-readable title for the pattern.
-- `content` (required): Block HTML Markup for the pattern.
-- `description` (optional): A visually hidden text used to describe the pattern in the inserter. A description is optional but it is strongly encouraged when the title does not fully describe what the pattern does. The description will help users discover the pattern while searching.
-- `categories` (optional): An array of registered pattern categories used to group block patterns. Block patterns can be shown on multiple categories. A category must be registered separately in order to be used here.
-- `keywords` (optional): An array of aliases or keywords that help users discover the pattern while searching.
-- `viewportWidth` (optional): An integer specifying the intended width of the pattern to allow for a scaled preview of the pattern in the inserter.
-- `blockTypes` (optional): An array of block types that the pattern is intended to be used with. Each value needs to be the declared block's `name`.
-- `postTypes` (optional): An array of post types that the pattern is restricted to be used with. The pattern will only be available when editing one of the post types passed on the array. For all the other post types, the pattern is not available at all.
-- `templateTypes` (optional): An array of template types where the pattern makes sense, for example, `404` if the pattern is for a 404 page, `single-post` if the pattern is for showing a single post.
-- `inserter` (optional): By default, all patterns will appear in the inserter. To hide a pattern so that it can only be inserted programmatically, set the `inserter` to `false`.
-- `source` (optional): A string that denotes the source of the pattern. For a plugin registering a pattern, pass the string `plugin`. For a theme, pass the string `theme`.
+- `title` (required): A human-readable title for the pattern.
+- `content` (required): Block HTML Markup for the pattern.
+- `description` (optional): A visually hidden text used to describe the pattern in the inserter. A description is optional but it is strongly encouraged when the title does not fully describe what the pattern does. The description will help users discover the pattern while searching.
+- `categories` (optional): An array of registered pattern categories used to group block patterns. Block patterns can be shown on multiple categories. A category must be registered separately in order to be used here.
+- `keywords` (optional): An array of aliases or keywords that help users discover the pattern while searching.
+- `viewportWidth` (optional): An integer specifying the intended width of the pattern to allow for a scaled preview of the pattern in the inserter.
+- `blockTypes` (optional): An array of block types that the pattern is intended to be used with. Each value needs to be the declared block's `name`.
+- `postTypes` (optional): An array of post types that the pattern is restricted to be used with. The pattern will only be available when editing one of the post types passed on the array. For all the other post types, the pattern is not available at all.
+- `templateTypes` (optional): An array of template types where the pattern makes sense, for example, `404` if the pattern is for a 404 page, `single-post` if the pattern is for showing a single post.
+- `inserter` (optional): By default, all patterns will appear in the inserter. To hide a pattern so that it can only be inserted programmatically, set the `inserter` to `false`.
+- `source` (optional): A string that denotes the source of the pattern. For a plugin registering a pattern, pass the string `plugin`. For a theme, pass the string `theme`.
The following code sample registers a block pattern named `my-plugin/my-awesome-pattern`:
```php
register_block_pattern(
- 'my-plugin/my-awesome-pattern',
- array(
- 'title' => __( 'Two buttons', 'my-plugin' ),
- 'description' => _x( 'Two horizontal buttons, the left button is filled in, and the right button is outlined.', 'Block pattern description', 'my-plugin' ),
- 'content' => "\n
\n",
+ )
);
```
@@ -55,7 +56,7 @@ add_action( 'init', 'my_plugin_register_my_patterns' );
The `unregister_block_pattern` helper function allows a previously registered block pattern to be unregistered from a theme or plugin and receives one argument.
-- `title`: The name of the block pattern to be unregistered.
+- `title`: The name of the block pattern to be unregistered.
The following code sample unregisters the block pattern named `my-plugin/my-awesome-pattern`:
@@ -83,19 +84,19 @@ Block patterns can be grouped using categories. The block editor comes with bund
The `register_block_pattern_category` helper function receives two arguments.
-- `title`: A machine-readable title for the block pattern category.
-- `properties`: An array describing properties of the pattern category.
+- `title`: A machine-readable title for the block pattern category.
+- `properties`: An array describing properties of the pattern category.
The properties of the pattern categories include:
-- `label` (required): A human-readable label for the pattern category.
+- `label` (required): A human-readable label for the pattern category.
The following code sample registers the category named `hero`:
```php
register_block_pattern_category(
- 'hero',
- array( 'label' => __( 'Hero', 'my-plugin' ) )
+ 'hero',
+ array( 'label' => __( 'Hero', 'my-plugin' ) )
);
```
@@ -117,7 +118,7 @@ add_action( 'init', 'my_plugin_register_my_pattern_categories' );
The `unregister_block_pattern_category` helper function allows for a previously registered block pattern category to be unregistered from a theme or plugin and receives one argument.
-- `title`: The name of the block pattern category to be unregistered.
+- `title`: The name of the block pattern category to be unregistered.
The following code sample unregisters the category named `hero`:
@@ -147,14 +148,14 @@ For instance:
```php
register_block_pattern(
- 'my-plugin/powered-by-wordpress',
- array(
- 'title' => __( 'Powered by WordPress', 'my-plugin' ),
- 'blockTypes' => array( 'core/paragraph' ),
- 'content' => '
-
',
+ )
);
```
@@ -194,13 +195,13 @@ Example:
```php
__( 'My Header', 'my-plugin' ),
- 'categories' => array( 'header' ),
- // Assigning the pattern the "header" area.
- 'blockTypes' => array( 'core/template-part/header' ),
- 'content' => 'Content of my block pattern',
- )
+ 'my-plugin/my-header',
+ array(
+ 'title' => __( 'My Header', 'my-plugin' ),
+ 'categories' => array( 'header' ),
+ // Assigning the pattern the "header" area.
+ 'blockTypes' => array( 'core/template-part/header' ),
+ 'content' => 'Content of my block pattern',
+ )
);
```
diff --git a/gutenberg/reference-guides/block-api/block-registration.md b/docs/gutenberg/reference-guides/block-api/block-registration.md
similarity index 76%
rename from gutenberg/reference-guides/block-api/block-registration.md
rename to docs/gutenberg/reference-guides/block-api/block-registration.md
index a04bd00..83a0fcb 100644
--- a/gutenberg/reference-guides/block-api/block-registration.md
+++ b/docs/gutenberg/reference-guides/block-api/block-registration.md
@@ -10,19 +10,19 @@ You can use the functions documented on this page to register a block with JavaS
## `registerBlockType`
-- **Type:** `Function`
+- **Type:** `Function`
Every block starts by registering a new block type definition. To register, you use the `registerBlockType` function from the [`wp-blocks` package](/packages/blocks/README.md#registerBlockType). The function takes two arguments, a block `name` and a block configuration object.
### Block Name
-- **Type:** `String`
+- **Type:** `String`
The name for a block is a unique string that identifies a block. Names have to be structured as `namespace/block-name`, where namespace is the name of your plugin or theme.
```js
// Registering my block with a unique name
-registerBlockType( 'my-plugin/book', {} );
+registerBlockType('my-plugin/book', {});
```
_Note:_ A block name can only contain lowercase alphanumeric characters and dashes, and must begin with a letter.
@@ -35,66 +35,66 @@ Block names cannot be changed later without consequences. The block name is stor
#### Namespace Best Practices
-- Use your actual plugin/theme name: `my-awesome-plugin/block-name`
-- Avoid generic names like `editorial/`, `block/`, or `create-block/`
-- Use the same namespace for all blocks in your plugin/theme
-- Make it unique to prevent conflicts with other plugins
+- Use your actual plugin/theme name: `my-awesome-plugin/block-name`
+- Avoid generic names like `editorial/`, `block/`, or `create-block/`
+- Use the same namespace for all blocks in your plugin/theme
+- Make it unique to prevent conflicts with other plugins
```js
// Good examples
-registerBlockType( 'my-company-blocks/hero', {} );
-registerBlockType( 'awesome-gallery-plugin/slideshow', {} );
+registerBlockType('my-company-blocks/hero', {});
+registerBlockType('awesome-gallery-plugin/slideshow', {});
// Avoid these
-registerBlockType( 'create-block/example', {} ); // Too generic
-registerBlockType( 'block/content', {} ); // Too generic
+registerBlockType('create-block/example', {}); // Too generic
+registerBlockType('block/content', {}); // Too generic
```
_Note:_ `registerBlockCollection()` only works with blocks from a single namespace.
### Block configuration
-- **Type:** `Object` [ `{ key: value }` ]
+- **Type:** `Object` [ `{ key: value }` ]
A block requires a few properties to be specified before it can be registered successfully. These are defined through a configuration object, which includes the following:
#### title
-- **Type:** `String`
+- **Type:** `String`
This is the display title for your block, which can be translated with our translation functions. The title will display in the Inserter and in other areas of the editor.
```js
// Our data object
-title: __( 'Book' );
+title: __('Book');
```
_Note:_ To keep your block titles readable and accessible in the UI, try to avoid very long titles.
#### description (optional)
-- **Type:** `String`
+- **Type:** `String`
This is a short description for your block, which can be translated with our translation functions. This will be shown in the Block Tab in the Settings Sidebar.
```js
-description: __( 'Block showing a Book card.' );
+description: __('Block showing a Book card.');
```
#### category
-- **Type:** `String` [ text | media | design | widgets | theme | embed ]
+- **Type:** `String` [ text | media | design | widgets | theme | embed ]
Blocks are grouped into categories to help users browse and discover them.
The core provided categories are:
-- text
-- media
-- design
-- widgets
-- theme
-- embed
+- text
+- media
+- design
+- widgets
+- theme
+- embed
```js
// Assigning to the 'widgets' category
@@ -105,7 +105,7 @@ Plugins and Themes can also register [custom block categories](/docs/reference-g
#### icon (optional)
-- **Type:** `String` | `Object`
+- **Type:** `String` | `Object`
An icon property should be specified to make it easier to identify a block. These can be any of [WordPress' Dashicons](https://developer.wordpress.org/resource/dashicons/), or a custom `svg` element.
@@ -125,18 +125,18 @@ Besides src the object can contain background and foreground colors, these color
```js
icon: {
- // Specifying a background color to appear with the icon e.g.: in the inserter.
- background: '#7e70af',
- // Specifying a color for the icon (optional: if not set, a readable color will be automatically defined)
- foreground: '#fff',
- // Specifying an icon for the block
- src: ,
+ // Specifying a background color to appear with the icon e.g.: in the inserter.
+ background: '#7e70af',
+ // Specifying a color for the icon (optional: if not set, a readable color will be automatically defined)
+ foreground: '#fff',
+ // Specifying an icon for the block
+ src: ,
} ,
```
#### keywords (optional)
-- **Type:** `Array`
+- **Type:** `Array`
Sometimes a block could have aliases that help users discover it while searching. For example, an `image` block could also want to be discovered by `photo`. You can do so by providing an array of terms (which can be translated).
@@ -148,27 +148,27 @@ keywords: [ __( 'image' ), __( 'photo' ), __( 'pics' ) ],
#### styles (optional)
-- **Type:** `Array`
+- **Type:** `Array`
Block styles can be used to provide alternative styles to block. It works by adding a class name to the block’s wrapper. Using CSS, a theme developer can target the class name for the block style if it is selected.
```js
// Register block styles.
styles: [
- // Mark style as default.
- {
- name: 'default',
- label: __( 'Rounded' ),
- isDefault: true
- },
- {
- name: 'outline',
- label: __( 'Outline' )
- },
- {
- name: 'squared',
- label: __( 'Squared' )
- },
+ // Mark style as default.
+ {
+ name: 'default',
+ label: __( 'Rounded' ),
+ isDefault: true
+ },
+ {
+ name: 'outline',
+ label: __( 'Outline' )
+ },
+ {
+ name: 'squared',
+ label: __( 'Squared' )
+ },
],
```
@@ -176,35 +176,35 @@ Plugins and Themes can also register [custom block styles](/docs/reference-guide
#### attributes (optional)
-- **Type:** `Object`
+- **Type:** `Object`
Attributes provide the structured data needs of a block. They can exist in different forms when they are serialized, but they are declared together under a common interface.
```js
// Specifying my block attributes
attributes: {
- cover: {
- type: 'string',
- source: 'attribute',
- selector: 'img',
- attribute: 'src',
- },
- author: {
- type: 'string',
- source: 'html',
- selector: '.book-author',
- },
- pages: {
- type: 'number',
- },
+ cover: {
+ type: 'string',
+ source: 'attribute',
+ selector: 'img',
+ attribute: 'src',
+ },
+ author: {
+ type: 'string',
+ source: 'html',
+ selector: '.book-author',
+ },
+ pages: {
+ type: 'number',
+ },
},
```
-- **See: [Attributes](/docs/reference-guides/block-api/block-attributes.md).**
+- **See: [Attributes](/docs/reference-guides/block-api/block-attributes.md).**
#### example (optional)
-- **Type:** `Object`
+- **Type:** `Object`
Example provides structured example data for the block. This data is used to construct a preview for the block to be shown in the Inspector Help Panel when the user mouses over the block and in the Styles panel when the block is selected.
@@ -212,11 +212,11 @@ The data provided in the example object should match the attributes defined. For
```js
example: {
- attributes: {
- cover: 'https://example.com/image.jpg',
- author: 'William Shakespeare',
- pages: 500
- },
+ attributes: {
+ cover: 'https://example.com/image.jpg',
+ author: 'William Shakespeare',
+ pages: 500
+ },
},
```
@@ -226,20 +226,20 @@ It's also possible to extend the block preview with inner blocks via `innerBlock
```js
example: {
- attributes: {
- cover: 'https://example.com/image.jpg',
- },
- innerBlocks: [
- {
- name: 'core/paragraph',
- attributes: {
- /* translators: example text. */
- content: __(
- 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent et eros eu felis.'
- ),
- },
- },
- ],
+ attributes: {
+ cover: 'https://example.com/image.jpg',
+ },
+ innerBlocks: [
+ {
+ name: 'core/paragraph',
+ attributes: {
+ /* translators: example text. */
+ content: __(
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent et eros eu felis.'
+ ),
+ },
+ },
+ ],
},
```
@@ -247,35 +247,35 @@ It's also possible to define the width of the preview container in pixels via `v
```js
example: {
- attributes: {
- cover: 'https://example.com/image.jpg',
- },
- viewportWidth: 800
+ attributes: {
+ cover: 'https://example.com/image.jpg',
+ },
+ viewportWidth: 800
},
```
#### variations (optional)
-- **Type:** `Object[]`
-- **Since**: `WordPress 5.9.0`
+- **Type:** `Object[]`
+- **Since**: `WordPress 5.9.0`
Similarly to how the block's styles can be declared, a block type can define block variations that the user can pick from. The difference is that, rather than changing only the visual appearance, this field provides a way to apply initial custom attributes and inner blocks at the time when a block is inserted. See the [Block Variations API](/docs/reference-guides/block-api/block-variations.md) for more details.
#### supports (optional)
-- **_Type:_** `Object`
+- **_Type:_** `Object`
Supports contains a set of options to control features used in the editor. See [the `supports` documentation](/docs/reference-guides/block-api/block-supports.md) for more details.
#### transforms (optional)
-- **Type:** `Object`
+- **Type:** `Object`
Transforms provide rules for what a block can be transformed from and what it can be transformed to. A block can be transformed from another block, a shortcode, a regular expression, a file, or a raw DOM node. Take a look at the [Block Transforms API](/docs/reference-guides/block-api/block-transforms.md) for more info about each available transformation.
#### parent (optional)
-- **Type:** `Array`
+- **Type:** `Array`
Blocks are able to be inserted into blocks that use [`InnerBlocks`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md) as nested content. Sometimes it is useful to restrict a block so that it is only available as a nested block. For example, you might want to allow an 'Add to Cart' block to only be available within a 'Product' block.
@@ -288,8 +288,8 @@ parent: [ 'core/columns' ],
#### ancestor (optional)
-- **Type:** `Array`
-- **Since**: `WordPress 6.0.0`
+- **Type:** `Array`
+- **Since**: `WordPress 6.0.0`
The `ancestor` property makes a block available inside the specified block types at any position of the ancestor block subtree. That allows, for example, to place a 'Comment Content' block inside a 'Column' block, as long as 'Column' is somewhere within a 'Comment Template' block. In comparison to the `parent` property, blocks that specify their `ancestor` can be placed anywhere in the subtree whilst blocks with a specified `parent` need to be direct children.
@@ -300,8 +300,8 @@ ancestor: [ 'core/columns' ],
#### allowedBlocks (optional)
-- **Type:** `Array`
-- **Since**: `WordPress 6.5.0`
+- **Type:** `Array`
+- **Since**: `WordPress 6.5.0`
Setting the `allowedBlocks` property will limit which block types can be nested as direct children of the block.
@@ -312,26 +312,26 @@ allowedBlocks: [ 'core/columns' ],
#### blockHooks (optional)
-- **Type:** `Object`
-- **Since**: `WordPress 6.4.0`
+- **Type:** `Object`
+- **Since**: `WordPress 6.4.0`
Block Hooks is an API that allows a block to automatically insert itself next to all instances of a given block type, in a relative position also specified by the "hooked" block. That is, a block can opt to be inserted before or after a given block type, or as its first or last child (i.e. to be prepended or appended to the list of its child blocks, respectively). Hooked blocks will appear both on the frontend and in the editor (to allow for customization by the user).
The key is the name of the block (`string`) to hook into, and the value is the position to hook into (`string`). Allowed target values are:
-- `before` – inject before the target block.
-- `after` - inject after the target block.
-- `firstChild` - inject before the first inner block of the target container block.
-- `lastChild` - inject after the last inner block of the target container block.
+- `before` – inject before the target block.
+- `after` - inject after the target block.
+- `firstChild` - inject before the first inner block of the target container block.
+- `lastChild` - inject after the last inner block of the target container block.
```js
{
- blockHooks: {
- 'core/verse': 'before',
- 'core/spacer': 'after',
- 'core/column': 'firstChild',
- 'core/group': 'lastChild',
- }
+ blockHooks: {
+ 'core/verse': 'before',
+ 'core/spacer': 'after',
+ 'core/column': 'firstChild',
+ 'core/group': 'lastChild',
+ }
}
```
@@ -339,7 +339,7 @@ The key is the name of the block (`string`) to hook into, and the value is the p
## `registerBlockCollection`
-- **Type:** `Function`
+- **Type:** `Function`
Blocks can be added to collections, grouping together all blocks from the same origin
@@ -347,7 +347,7 @@ Blocks can be added to collections, grouping together all blocks from the same o
### Namespace
-- **Type:** `String`
+- **Type:** `String`
This should match the namespace declared in the block name; the name of your plugin or theme.
@@ -355,17 +355,17 @@ This should match the namespace declared in the block name; the name of your plu
#### Title
-- **Type:** `String`
+- **Type:** `String`
This will display in the block inserter section, which will list all blocks in this collection.
#### Icon
-- **Type:** `Object`
+- **Type:** `Object`
(Optional) An icon to display alongside the title in the block inserter.
```js
// Registering a block collection
-registerBlockCollection( 'my-plugin', { title: 'My Plugin' } );
+registerBlockCollection('my-plugin', { title: 'My Plugin' });
```
diff --git a/gutenberg/reference-guides/block-api/block-selectors.md b/docs/gutenberg/reference-guides/block-api/block-selectors.md
similarity index 79%
rename from gutenberg/reference-guides/block-api/block-selectors.md
rename to docs/gutenberg/reference-guides/block-api/block-selectors.md
index ab810c3..9c37f94 100644
--- a/gutenberg/reference-guides/block-api/block-selectors.md
+++ b/docs/gutenberg/reference-guides/block-api/block-selectors.md
@@ -18,10 +18,10 @@ default is generated in the form of `.wp-block-`.
```json
{
- ...
- "selectors": {
- "root": ".my-custom-block-selector"
- }
+ ...
+ "selectors": {
+ "root": ".my-custom-block-selector"
+ }
}
```
@@ -38,12 +38,12 @@ but applying the typography styles to an inner heading only.
```json
{
- ...
- "selectors": {
- "root": ".my-custom-block-selector",
- "color": ".my-custom-block-selector",
- "typography": ".my-custom-block-selector > h2"
- }
+ ...
+ "selectors": {
+ "root": ".my-custom-block-selector",
+ "color": ".my-custom-block-selector",
+ "typography": ".my-custom-block-selector > h2"
+ }
}
```
@@ -65,15 +65,15 @@ elements to which it should be applied.
```json
{
- ...
- "selectors": {
- "root": ".my-custom-block-selector",
- "color": ".my-custom-block-selector",
- "typography": {
- "root": ".my-custom-block-selector > h2",
- "text-decoration": ".my-custom-block-selector > h2 span"
- }
- }
+ ...
+ "selectors": {
+ "root": ".my-custom-block-selector",
+ "color": ".my-custom-block-selector",
+ "typography": {
+ "root": ".my-custom-block-selector > h2",
+ "text-decoration": ".my-custom-block-selector > h2 span"
+ }
+ }
}
```
@@ -97,17 +97,17 @@ unique selectors for the subfeatures that differ.
```json
{
- ...
- "selectors": {
- "root": ".my-custom-block-selector",
- "color": {
- "text": ".my-custom-block-selector p"
- },
- "typography": {
- "root": ".my-custom-block-selector > h2",
- "text-decoration": ".my-custom-block-selector > h2 span"
- }
- }
+ ...
+ "selectors": {
+ "root": ".my-custom-block-selector",
+ "color": {
+ "text": ".my-custom-block-selector p"
+ },
+ "typography": {
+ "root": ".my-custom-block-selector > h2",
+ "text-decoration": ".my-custom-block-selector > h2 span"
+ }
+ }
}
```
diff --git a/gutenberg/reference-guides/block-api/block-styles.md b/docs/gutenberg/reference-guides/block-api/block-styles.md
similarity index 86%
rename from gutenberg/reference-guides/block-api/block-styles.md
rename to docs/gutenberg/reference-guides/block-api/block-styles.md
index b2e9bdc..5737d20 100644
--- a/gutenberg/reference-guides/block-api/block-styles.md
+++ b/docs/gutenberg/reference-guides/block-api/block-styles.md
@@ -5,10 +5,10 @@ Block Styles allow alternative styles to be applied to existing blocks. They wor
_Example:_
```js
-wp.blocks.registerBlockStyle( 'core/quote', {
- name: 'fancy-quote',
- label: 'Fancy Quote',
-} );
+wp.blocks.registerBlockStyle('core/quote', {
+ name: 'fancy-quote',
+ label: 'Fancy Quote',
+});
```
The example above registers a block style named `fancy-quote` to the `core/quote` block. When the user selects this block style from the styles selector, an `is-style-fancy-quote` className will be added to the block's wrapper.
@@ -20,7 +20,7 @@ To remove a block style use `wp.blocks.unregisterBlockStyle()`.
_Example:_
```js
-wp.blocks.unregisterBlockStyle( 'core/quote', 'large' );
+wp.blocks.unregisterBlockStyle('core/quote', 'large');
```
The above removes the block style named `large` from the `core/quote` block.
@@ -31,12 +31,12 @@ Enqueue your JavaScript with the following PHP code:
```php
function myguten_enqueue() {
- wp_enqueue_script(
- 'myguten-script',
- plugins_url( 'myguten.js', __FILE__ ),
- array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' ),
- filemtime( plugin_dir_path( __FILE__ ) . '/myguten.js' )
- );
+ wp_enqueue_script(
+ 'myguten-script',
+ plugins_url( 'myguten.js', __FILE__ ),
+ array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' ),
+ filemtime( plugin_dir_path( __FILE__ ) . '/myguten.js' )
+ );
}
add_action( 'enqueue_block_editor_assets', 'myguten_enqueue' );
```
@@ -44,9 +44,9 @@ add_action( 'enqueue_block_editor_assets', 'myguten_enqueue' );
The JavaScript code in `myguten.js`:
```js
-wp.domReady( function () {
- wp.blocks.unregisterBlockStyle( 'core/quote', 'large' );
-} );
+wp.domReady(function () {
+ wp.blocks.unregisterBlockStyle('core/quote', 'large');
+});
```
## Server-side registration helper
@@ -61,14 +61,14 @@ The `register_block_style` function receives the name of the block as the first
The properties of the style array must include `name` and `label`:
-- `name`: The identifier of the style used to compute a CSS class.
-- `label`: A human-readable label for the style.
+- `name`: The identifier of the style used to compute a CSS class.
+- `label`: A human-readable label for the style.
Besides the two mandatory properties, the styles properties array should also include an `inline_style` or a `style_handle` or a `style_data`property:
-- `inline_style`: Contains inline CSS code that registers the CSS class required for the style.
-- `style_handle`: Contains the handle to an already registered style that should be enqueued in places where block styles are needed.
-- `style_data`: Contains a theme.json-like notation in an array of style properties.
+- `inline_style`: Contains inline CSS code that registers the CSS class required for the style.
+- `style_handle`: Contains the handle to an already registered style that should be enqueued in places where block styles are needed.
+- `style_data`: Contains a theme.json-like notation in an array of style properties.
It is also possible to set the `is_default` property to `true` to mark one of the block styles as the default one, should one be missing.
@@ -103,6 +103,7 @@ register_block_style(
)
);
```
+
Another way is using the `style_data`property, as in below code example. It adds a block style to the image block with an orange border and slightly rounded corners.
```php
@@ -122,6 +123,7 @@ register_block_style(
)
);
```
+
Using the `style_data` property empowers the user to change it with the Global Styles UI via the **Editor > Styles**. The `style_data`property was added in WordPress 6.6.
More information via WordPress 6.6 Dev Note: [Section Styles](https://make.wordpress.org/core/2024/06/24/section-styles/).
diff --git a/gutenberg/reference-guides/block-api/block-supports.md b/docs/gutenberg/reference-guides/block-api/block-supports.md
similarity index 59%
rename from gutenberg/reference-guides/block-api/block-supports.md
rename to docs/gutenberg/reference-guides/block-api/block-supports.md
index a15191c..da5ba31 100644
--- a/gutenberg/reference-guides/block-api/block-supports.md
+++ b/docs/gutenberg/reference-guides/block-api/block-supports.md
@@ -10,9 +10,9 @@ In order for the attribute to get applied to the block the generated properties
```js
function BlockEdit() {
- const blockProps = useBlockProps();
+ const blockProps = useBlockProps();
- return
;
}
```
@@ -32,50 +32,50 @@ For dynamic blocks that get rendered via a `render_callback` in PHP you can use
```php
function render_block() {
- $wrapper_attributes = get_block_wrapper_attributes();
+ $wrapper_attributes = get_block_wrapper_attributes();
- return sprintf(
- '
',
+ $wrapper_attributes,
+ 'Hello World!'
+ );
}
```
## anchor
-- Type: `boolean`
-- Default value: `false`
+- Type: `boolean`
+- Default value: `false`
Anchors let you link directly to a specific block on a page. This property adds a field to define an id for the block and a button to copy the direct link. _Important: It doesn't work with dynamic blocks yet._
```js
// Declare support for anchor links.
supports: {
- anchor: true
+ anchor: true;
}
```
## align
-- Type: `boolean` or `array`
-- Default value: `false`
+- Type: `boolean` or `array`
+- Default value: `false`
This property adds block controls, which enable changes to a block's alignment.
```js
supports: {
- // Declare support for block's alignment.
- // This adds support for all the options:
- // left, center, right, wide, and full.
- align: true
+ // Declare support for block's alignment.
+ // This adds support for all the options:
+ // left, center, right, wide, and full.
+ align: true;
}
```
```js
supports: {
- // Declare support for specific alignment options.
- align: [ 'left', 'right', 'full' ]
+ // Declare support for specific alignment options.
+ align: ['left', 'right', 'full'];
}
```
@@ -92,29 +92,29 @@ attributes: {
## alignWide
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
This property allows to enable [wide alignment](/docs/how-to-guides/themes/theme-support.md#wide-alignment) for your theme. To disable this behavior for a single block, set this flag to `false`.
```js
supports: {
- // Remove the support for wide alignment.
- alignWide: false
+ // Remove the support for wide alignment.
+ alignWide: false;
}
```
## ariaLabel
-- Type: `boolean`
-- Default value: `false`
+- Type: `boolean`
+- Default value: `false`
ARIA-labels let you define an accessible label for elements. This property allows enabling the definition of an aria-label for the block, without exposing a UI field.
```js
supports: {
- // Add support for an aria label.
- ariaLabel: true
+ // Add support for an aria label.
+ ariaLabel: true;
}
```
@@ -122,11 +122,11 @@ supports: {
_**Note:** Since WordPress 6.5._
-- Type: `Object`
-- Default value: `null`
-- Subproperties
- - `backgroundImage`: type `boolean`, default value `false`
- - `backgroundSize`: type `boolean`, default value `false`
+- Type: `Object`
+- Default value: `null`
+- Subproperties
+ - `backgroundImage`: type `boolean`, default value `false`
+ - `backgroundSize`: type `boolean`, default value `false`
This value signals that a block supports some of the CSS style properties related to background. When it does, the block editor will show UI controls for the user to set their values if [the theme declares support](/docs/how-to-guides/themes/global-settings-and-styles.md#opt-in-into-ui-controls).
@@ -135,10 +135,10 @@ This value signals that a block supports some of the CSS style properties relate
```js
supports: {
- background: {
- backgroundImage: true // Enable background image control.
- backgroundSize: true // Enable background image + size control.
- }
+ background: {
+ backgroundImage: true; // Enable background image control.
+ backgroundSize: true; // Enable background image + size control.
+ }
}
```
@@ -148,15 +148,15 @@ When a background image is selected, the image data is stored in the `style.back
When a background images is selected and its position or size are changed, the background-position is stored in the `style.background.backgroundPosition` and its background-size in `style.background.backgroundSize` attribute.
-- `style`: an attribute of `object` type with no default assigned. This is added when `backgroundImage` or `backgroundSize` support is declared. It stores the custom values set by the user.
- - `background`: an attribute of `object` type.
- - `backgroundImage`: an attribute of `object` type, containing information about the selected image
- - `url`: type `string`, URL to the image
- - `id`: type `int`, media attachment ID
- - `source`: type `string`, at the moment the only value is `file`
- - `title`: type `string`, title of the media attachment
- - `backgroundPosition`: an attribute of `string` type, defining the background images position, selected by FocalPointPicker and used in CSS as the [`background-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-position) value.
- - `backgroundSize`: an attribute of `string` type. defining the CSS [`background-size`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-size) value.
+- `style`: an attribute of `object` type with no default assigned. This is added when `backgroundImage` or `backgroundSize` support is declared. It stores the custom values set by the user.
+ - `background`: an attribute of `object` type.
+ - `backgroundImage`: an attribute of `object` type, containing information about the selected image
+ - `url`: type `string`, URL to the image
+ - `id`: type `int`, media attachment ID
+ - `source`: type `string`, at the moment the only value is `file`
+ - `title`: type `string`, title of the media attachment
+ - `backgroundPosition`: an attribute of `string` type, defining the background images position, selected by FocalPointPicker and used in CSS as the [`background-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-position) value.
+ - `backgroundSize`: an attribute of `string` type. defining the CSS [`background-size`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-size) value.
The block can apply a default background image, position and size by specifying its own attribute with a default. For example:
@@ -165,9 +165,9 @@ attributes: {
style: {
background: {
backgroundImage: {
- "url":"IMAGE_URL"
- }
- backgroundPosition:"50% 50%",
+ "url":"IMAGE_URL"
+ }
+ backgroundPosition:"50% 50%",
backgroundSize: "cover"
}
}
@@ -176,30 +176,30 @@ attributes: {
## className
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
By default, the class `.wp-block-your-block-name` is added to the root element of your saved markup. This helps by providing a consistent mechanism for styling blocks that themes and plugins can rely on. If, for whatever reason, a class is not desired on the markup, this functionality can be disabled.
```js
supports: {
- // Remove the support for the generated className.
- className: false
+ // Remove the support for the generated className.
+ className: false;
}
```
## color
-- Type: `Object`
-- Default value: null
-- Subproperties:
- - `background`: type `boolean`, default value `true`
- - `button`: type `boolean`, default value `false`
- - `enableContrastChecker`: type `boolean`, default value `true`
- - `gradients`: type `boolean`, default value `false`
- - `heading`: type `boolean`, default value `false`
- - `link`: type `boolean`, default value `false`
- - `text`: type `boolean`, default value `true`
+- Type: `Object`
+- Default value: null
+- Subproperties:
+ - `background`: type `boolean`, default value `true`
+ - `button`: type `boolean`, default value `false`
+ - `enableContrastChecker`: type `boolean`, default value `true`
+ - `gradients`: type `boolean`, default value `false`
+ - `heading`: type `boolean`, default value `false`
+ - `link`: type `boolean`, default value `false`
+ - `text`: type `boolean`, default value `true`
This value signals that a block supports some of the properties related to color. When this value is present, the block editor will show UI controls for the user to set their values.
@@ -207,10 +207,10 @@ Note that the `background` and `text` keys have a default value of `true`, so if
```js
supports: {
- color: {
- // This also enables text and background UI controls.
- gradients: true // Enables the gradients UI control.
- }
+ color: {
+ // This also enables text and background UI controls.
+ gradients: true; // Enables the gradients UI control.
+ }
}
```
@@ -233,7 +233,7 @@ When color support is declared, this property is enabled by default (along with
```js
supports: {
- color: true // Enables background and text color support.
+ color: true; // Enables background and text color support.
}
```
@@ -241,50 +241,50 @@ To disable background support while keeping other color supports enabled, set to
```js
supports: {
- color: {
- // Disables background support. Text color support is still enabled.
- background: false
- }
+ color: {
+ // Disables background support. Text color support is still enabled.
+ background: false;
+ }
}
```
When the block declares support for `color.background`, the attributes definition is extended to include two new attributes: `backgroundColor` and `style`:
-- `backgroundColor`: an attribute of `string` type with no default assigned.
+- `backgroundColor`: an attribute of `string` type with no default assigned.
- When a user chooses from the list of preset background colors, the preset slug is stored in the `backgroundColor` attribute.
+ When a user chooses from the list of preset background colors, the preset slug is stored in the `backgroundColor` attribute.
- Background color presets are sourced from the `editor-color-palette` [theme support](/docs/how-to-guides/themes/theme-support.md#block-color-palettes).
+ Background color presets are sourced from the `editor-color-palette` [theme support](/docs/how-to-guides/themes/theme-support.md#block-color-palettes).
- The block can apply a default preset background color by specifying its own attribute with a default. For example:
+ The block can apply a default preset background color by specifying its own attribute with a default. For example:
- ```js
- attributes: {
- backgroundColor: {
- type: 'string',
- default: 'some-preset-background-slug',
- }
- }
- ```
+ ```js
+ attributes: {
+ backgroundColor: {
+ type: 'string',
+ default: 'some-preset-background-slug',
+ }
+ }
+ ```
-- `style`: attribute of `object` type with no default assigned.
+- `style`: attribute of `object` type with no default assigned.
- When a custom background color is selected (i.e. using the custom color picker), the custom color value is stored in the `style.color.background` attribute.
+ When a custom background color is selected (i.e. using the custom color picker), the custom color value is stored in the `style.color.background` attribute.
- The block can apply a default custom background color by specifying its own attribute with a default. For example:
+ The block can apply a default custom background color by specifying its own attribute with a default. For example:
- ```js
- attributes: {
- style: {
- type: 'object',
- default: {
- color: {
- background: '#aabbcc',
- }
- }
- }
- }
- ```
+ ```js
+ attributes: {
+ style: {
+ type: 'object',
+ default: {
+ color: {
+ background: '#aabbcc',
+ }
+ }
+ }
+ }
+ ```
### color.button
@@ -296,9 +296,9 @@ To enable button color support, set `color.button` to `true`.
```js
supports: {
- color: {
- button: true
- }
+ color: {
+ button: true;
+ }
}
```
@@ -306,29 +306,29 @@ Button color presets are sourced from the `editor-color-palette` [theme support]
When the block declares support for `color.button`, the attributes definition is extended to include the `style` attribute:
-- `style`: an attribute of `object` type with no default assigned.
-
- When a button color is selected, the color value is stored in the `style.elements.button.color.text` and `style.elements.button.color.background` attribute.
-
- The block can apply a default button colors by specifying its own attribute with a default. For example:
-
- ```js
- attributes: {
- style: {
- type: 'object',
- default: {
- elements: {
- button: {
- color: {
- text: 'var:preset|color|contrast',
- background: '#000000',
- }
- }
- }
- }
- }
- }
- ```
+- `style`: an attribute of `object` type with no default assigned.
+
+ When a button color is selected, the color value is stored in the `style.elements.button.color.text` and `style.elements.button.color.background` attribute.
+
+ The block can apply a default button colors by specifying its own attribute with a default. For example:
+
+ ```js
+ attributes: {
+ style: {
+ type: 'object',
+ default: {
+ elements: {
+ button: {
+ color: {
+ text: 'var:preset|color|contrast',
+ background: '#000000',
+ }
+ }
+ }
+ }
+ }
+ }
+ ```
### color.enableContrastChecker
@@ -340,9 +340,9 @@ The contrast checker appears only if the block declares support for color. It te
```js
supports: {
- color: {
- enableContrastChecker: false
- }
+ color: {
+ enableContrastChecker: false;
+ }
}
```
@@ -371,39 +371,39 @@ Gradient presets are sourced from `editor-gradient-presets` [theme support](/doc
When the block declares support for `color.gradient`, the attributes definition is extended to include two new attributes: `gradient` and `style`:
-- `gradient`: an attribute of `string` type with no default assigned.
+- `gradient`: an attribute of `string` type with no default assigned.
- When a user chooses from the list of preset gradients, the preset slug is stored in the `gradient` attribute.
+ When a user chooses from the list of preset gradients, the preset slug is stored in the `gradient` attribute.
- The block can apply a default preset gradient by specifying its own attribute with a default. For example:
+ The block can apply a default preset gradient by specifying its own attribute with a default. For example:
- ```js
- attributes: {
- gradient: {
- type: 'string',
- default: 'some-preset-gradient-slug',
- }
- }
- ```
+ ```js
+ attributes: {
+ gradient: {
+ type: 'string',
+ default: 'some-preset-gradient-slug',
+ }
+ }
+ ```
-- `style`: an attribute of `object` type with no default assigned.
+- `style`: an attribute of `object` type with no default assigned.
- When a custom gradient is selected (i.e. using the custom gradient picker), the custom gradient value is stored in the `style.color.gradient` attribute.
+ When a custom gradient is selected (i.e. using the custom gradient picker), the custom gradient value is stored in the `style.color.gradient` attribute.
- The block can apply a default custom gradient by specifying its own attribute with a default. For example:
+ The block can apply a default custom gradient by specifying its own attribute with a default. For example:
- ```js
- attributes: {
- style: {
- type: 'object',
- default: {
- color: {
- gradient: 'linear-gradient(135deg,rgb(170,187,204) 0%,rgb(17,34,51) 100%)',
- }
- }
- }
- }
- ```
+ ```js
+ attributes: {
+ style: {
+ type: 'object',
+ default: {
+ color: {
+ gradient: 'linear-gradient(135deg,rgb(170,187,204) 0%,rgb(17,34,51) 100%)',
+ }
+ }
+ }
+ }
+ ```
### color.heading
@@ -415,10 +415,10 @@ To enable heading color support, set `color.heading` to `true`.
```js
supports: {
- color: {
- // Enable heading color support.
- heading: true
- }
+ color: {
+ // Enable heading color support.
+ heading: true;
+ }
}
```
@@ -426,29 +426,29 @@ Heading color presets are sourced from the `editor-color-palette` [theme support
When the block declares support for `color.heading`, the attributes definition is extended to include the `style` attribute:
-- `style`: an attribute of `object` type with no default assigned.
-
- When a heading color is selected, the color value is stored in the `style.elements.heading.color.text` and `style.elements.heading.color.background` attribute.
-
- The block can apply default heading colors by specifying its own attribute with a default. For example:
-
- ```js
- attributes: {
- style: {
- type: 'object',
- default: {
- elements: {
- heading: {
- color: {
- text: 'var:preset|color|contrast',
- background: '#000000',
- }
- }
- }
- }
- }
- }
- ```
+- `style`: an attribute of `object` type with no default assigned.
+
+ When a heading color is selected, the color value is stored in the `style.elements.heading.color.text` and `style.elements.heading.color.background` attribute.
+
+ The block can apply default heading colors by specifying its own attribute with a default. For example:
+
+ ```js
+ attributes: {
+ style: {
+ type: 'object',
+ default: {
+ elements: {
+ heading: {
+ color: {
+ text: 'var:preset|color|contrast',
+ background: '#000000',
+ }
+ }
+ }
+ }
+ }
+ }
+ ```
### color.link
@@ -458,9 +458,9 @@ To enable link color support, set `color.link` to `true`.
```js
supports: {
- color: {
- link: true
- }
+ color: {
+ link: true;
+ }
}
```
@@ -468,33 +468,33 @@ Link color presets are sourced from the `editor-color-palette` [theme support](/
When the block declares support for `color.link`, the attributes definition is extended to include the `style` attribute:
-- `style`: an attribute of `object` type with no default assigned.
-
- When a link color is selected, the color value is stored in the `style.elements.link.color.text` and `style.elements.link.:hover.color.text` attribute.
-
- The block can apply default link colors by specifying its own attribute with a default. For example:
-
- ```js
- attributes: {
- style: {
- type: 'object',
- default: {
- elements: {
- link: {
- color: {
- text: 'var:preset|color|contrast',
- },
- ":hover": {
- color: {
- text: "#000000"
- }
- }
- }
- }
- }
- }
+- `style`: an attribute of `object` type with no default assigned.
+
+ When a link color is selected, the color value is stored in the `style.elements.link.color.text` and `style.elements.link.:hover.color.text` attribute.
+
+ The block can apply default link colors by specifying its own attribute with a default. For example:
+
+ ```js
+ attributes: {
+ style: {
+ type: 'object',
+ default: {
+ elements: {
+ link: {
+ color: {
+ text: 'var:preset|color|contrast',
+ },
+ ":hover": {
+ color: {
+ text: "#000000"
+ }
}
- ```
+ }
+ }
+ }
+ }
+ }
+ ```
### color.text
@@ -504,7 +504,7 @@ When color support is declared, this property is enabled by default (along with
```js
supports: {
- color: true // Enables background and text, but not link.
+ color: true; // Enables background and text, but not link.
}
```
@@ -512,10 +512,10 @@ To disable text color support while keeping other color supports enabled, set `c
```js
supports: {
- color: {
- // Disable text color support.
- text: false
- }
+ color: {
+ // Disable text color support.
+ text: false;
+ }
}
```
@@ -523,51 +523,51 @@ Text color presets are sourced from the `editor-color-palette` [theme support](/
When the block declares support for `color.text`, the attributes definition is extended to include two new attributes: `textColor` and `style`:
-- `textColor`: an attribute of `string` type with no default assigned.
+- `textColor`: an attribute of `string` type with no default assigned.
- When a user chooses from the list of preset text colors, the preset slug is stored in the `textColor` attribute.
+ When a user chooses from the list of preset text colors, the preset slug is stored in the `textColor` attribute.
- The block can apply a default preset text color by specifying its own attribute with a default. For example:
+ The block can apply a default preset text color by specifying its own attribute with a default. For example:
- ```js
- attributes: {
- textColor: {
- type: 'string',
- default: 'some-preset-text-color-slug',
- }
- }
- ```
+ ```js
+ attributes: {
+ textColor: {
+ type: 'string',
+ default: 'some-preset-text-color-slug',
+ }
+ }
+ ```
-- `style`: an attribute of `object` type with no default assigned.
+- `style`: an attribute of `object` type with no default assigned.
- When a custom text color is selected (i.e. using the custom color picker), the custom color value is stored in the `style.color.text` attribute.
+ When a custom text color is selected (i.e. using the custom color picker), the custom color value is stored in the `style.color.text` attribute.
- The block can apply a default custom text color by specifying its own attribute with a default. For example:
+ The block can apply a default custom text color by specifying its own attribute with a default. For example:
- ```js
- attributes: {
- style: {
- type: 'object',
- default: {
- color: {
- text: '#aabbcc',
- }
- }
- }
- }
- ```
+ ```js
+ attributes: {
+ style: {
+ type: 'object',
+ default: {
+ color: {
+ text: '#aabbcc',
+ }
+ }
+ }
+ }
+ ```
## customClassName
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
This property adds a field to define a custom className for the block's wrapper.
```js
supports: {
- // Remove the support for the custom className.
- customClassName: false
+ // Remove the support for the custom className.
+ customClassName: false;
}
```
@@ -575,25 +575,25 @@ supports: {
_**Note:** Since WordPress 6.2._
-- Type: `Object`
-- Default value: null
-- Subproperties:
- - `minHeight`: type `boolean`, default value `false`
+- Type: `Object`
+- Default value: null
+- Subproperties:
+ - `minHeight`: type `boolean`, default value `false`
This value signals that a block supports some of the CSS style properties related to dimensions. When it does, the block editor will show UI controls for the user to set their values if [the theme declares support](/docs/how-to-guides/themes/global-settings-and-styles.md#opt-in-into-ui-controls).
```js
supports: {
- dimensions: {
- aspectRatio: true // Enable aspect ratio control.
- minHeight: true // Enable min height control.
- }
+ dimensions: {
+ aspectRatio: true; // Enable aspect ratio control.
+ minHeight: true; // Enable min height control.
+ }
}
```
When a block declares support for a specific dimensions property, its attributes definition is extended to include the `style` attribute.
-- `style`: an attribute of `object` type with no default assigned. This is added when `aspectRatio` or `minHeight` support is declared. It stores the custom values set by the user. For example:
+- `style`: an attribute of `object` type with no default assigned. This is added when `aspectRatio` or `minHeight` support is declared. It stores the custom values set by the user. For example:
```js
attributes: {
@@ -608,10 +608,10 @@ attributes: {
## filter
-- Type: `Object`
-- Default value: null
-- Subproperties:
- - `duotone`: type `boolean`, default value `false`
+- Type: `Object`
+- Default value: null
+- Subproperties:
+ - `duotone`: type `boolean`, default value `false`
This value signals that a block supports some of the properties related to filters. When it does, the block editor will show UI controls for the user to set their values.
@@ -641,61 +641,61 @@ Duotone presets are sourced from `color.duotone` in [theme.json](/docs/how-to-gu
When the block declares support for `filter.duotone`, the attributes definition is extended to include the attribute `style`:
-- `style`: an attribute of `object` type with no default assigned.
-
- The block can apply a default duotone color by specifying its own attribute with a default. For example:
-
- ```js
- attributes: {
- style: {
- type: 'object',
- default: {
- color: {
- duotone: [
- '#FFF',
- '#000'
- ]
- }
- }
- }
- }
- ```
+- `style`: an attribute of `object` type with no default assigned.
+
+ The block can apply a default duotone color by specifying its own attribute with a default. For example:
+
+ ```js
+ attributes: {
+ style: {
+ type: 'object',
+ default: {
+ color: {
+ duotone: [
+ '#FFF',
+ '#000'
+ ]
+ }
+ }
+ }
+ }
+ ```
## html
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
By default, a block's markup can be edited individually. To disable this behavior, set `html` to `false`.
```js
supports: {
- // Remove support for an HTML mode.
- html: false
+ // Remove support for an HTML mode.
+ html: false;
}
```
## inserter
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
By default, all blocks will appear in the inserter, block transforms menu, Style Book, etc. To hide a block from all parts of the user interface so that it can only be inserted programmatically, set `inserter` to `false`.
```js
supports: {
- // Hide this block from the inserter.
- inserter: false
+ // Hide this block from the inserter.
+ inserter: false;
}
```
## interactivity
-- Type: `boolean` or `object`
-- Default value: `false`
-- Subproperties:
- - `clientNavigation`: type `boolean`, default value `false`
- - `interactive`: type `boolean`, default value `false`
+- Type: `boolean` or `object`
+- Default value: `false`
+- Subproperties:
+ - `clientNavigation`: type `boolean`, default value `false`
+ - `interactive`: type `boolean`, default value `false`
Indicates if the block is using Interactivity API features.
@@ -706,109 +706,109 @@ The `interactive` sub-property indicates whether the block is using the Interact
## layout
-- Type: `boolean` or `Object`
-- Default value: null
-- Subproperties:
- - `default`: type `Object`, default value null
- - `allowSwitching`: type `boolean`, default value `false`
- - `allowEditing`: type `boolean`, default value `true`
- - `allowInheriting`: type `boolean`, default value `true`
- - `allowSizingOnChildren`: type `boolean`, default value `false`
- - `allowVerticalAlignment`: type `boolean`, default value `true`
- - `allowJustification`: type `boolean`, default value `true`
- - `allowOrientation`: type `boolean`, default value `true`
- - `allowCustomContentAndWideSize`: type `boolean`, default value `true`
+- Type: `boolean` or `Object`
+- Default value: null
+- Subproperties:
+ - `default`: type `Object`, default value null
+ - `allowSwitching`: type `boolean`, default value `false`
+ - `allowEditing`: type `boolean`, default value `true`
+ - `allowInheriting`: type `boolean`, default value `true`
+ - `allowSizingOnChildren`: type `boolean`, default value `false`
+ - `allowVerticalAlignment`: type `boolean`, default value `true`
+ - `allowJustification`: type `boolean`, default value `true`
+ - `allowOrientation`: type `boolean`, default value `true`
+ - `allowCustomContentAndWideSize`: type `boolean`, default value `true`
This value only applies to blocks that are containers for inner blocks. If set to `true` the layout type will be `flow`. For other layout types it's necessary to set the `type` explicitly inside the `default` object.
### layout.default
-- Type: `Object`
-- Default value: null
+- Type: `Object`
+- Default value: null
Allows setting the `type` property to define what layout type is default for the block, and also default values for any properties inherent to that layout type. For example, for a `flex` layout, a default value can be set for `flexWrap`.
### layout.allowSwitching
-- Type: `boolean`
-- Default value: `false`
+- Type: `boolean`
+- Default value: `false`
Exposes a switcher control that allows toggling between all existing layout types.
### layout.allowEditing
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
Determines display of layout controls in the block sidebar. If set to false, layout controls will be hidden.
### layout.allowInheriting
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
For the `flow` layout type only, determines display of the "Inner blocks use content width" toggle.
### layout.allowSizingOnChildren
-- Type: `boolean`
-- Default value: `false`
+- Type: `boolean`
+- Default value: `false`
For the `flex` layout type only, determines display of sizing controls (Fit/Fill/Fixed) on all child blocks of the flex block.
### layout.allowVerticalAlignment
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
For the `flex` layout type only, determines display of the vertical alignment control in the block toolbar.
### layout.allowJustification
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
For the `flex` layout type, determines display of the justification control in the block toolbar and block sidebar. For the `constrained` layout type, determines display of justification control in the block sidebar.
### layout.allowOrientation
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
For the `flex` layout type only, determines display of the orientation control in the block toolbar.
### layout.allowCustomContentAndWideSize
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
For the `constrained` layout type only, determines display of the custom content and wide size controls in the block sidebar.
## lock
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
A block may want to disable the ability to toggle the lock state. It can be locked/unlocked by a user from the block "Options" dropdown by default. To disable this behavior, set `lock` to `false`.
```js
supports: {
- // Remove support for locking UI.
- lock: false
+ // Remove support for locking UI.
+ lock: false;
}
```
## multiple
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
A non-multiple block can be inserted into each post, one time only. For example, the built-in 'More' block cannot be inserted again if it already exists in the post being edited. A non-multiple block's icon is automatically dimmed (unclickable) to prevent multiple instances.
```js
supports: {
- // Use the block just once per post
- multiple: false
+ // Use the block just once per post
+ multiple: false;
}
```
@@ -816,10 +816,10 @@ supports: {
_**Note:** Since WordPress 6.2._
-- Type: `Object`
-- Default value: null
-- Subproperties:
- - `sticky`: type `boolean`, default value `false`
+- Type: `Object`
+- Default value: null
+- Subproperties:
+ - `sticky`: type `boolean`, default value `false`
This value signals that a block supports some of the CSS style properties related to position. When it does, the block editor will show UI controls for the user to set their values if [the theme declares support](/docs/how-to-guides/themes/global-settings-and-styles.md#opt-in-into-ui-controls).
@@ -827,15 +827,15 @@ Note that sticky position controls are currently only available for blocks set a
```js
supports: {
- position: {
- sticky: true // Enable selecting sticky position.
- }
+ position: {
+ sticky: true; // Enable selecting sticky position.
+ }
}
```
When the block declares support for a specific position property, its attributes definition is extended to include the `style` attribute.
-- `style`: an attribute of `object` type with no default assigned. This is added when `sticky` support is declared. It stores the custom values set by the user. For example:
+- `style`: an attribute of `object` type with no default assigned. This is added when `sticky` support is declared. It stores the custom values set by the user. For example:
```js
attributes: {
@@ -852,29 +852,29 @@ attributes: {
_**Note:** Since WordPress 6.5._
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
By default, a block can be renamed by a user from the block 'Options' dropdown or the 'Advanced' panel. To disable this behavior, set renaming to false.
```js
supports: {
- // Don't allow the block to be renamed in the editor.
- renaming: false,
+ // Don't allow the block to be renamed in the editor.
+ renaming: false,
}
```
## reusable
-- Type: `boolean`
-- Default value: `true`
+- Type: `boolean`
+- Default value: `true`
A block may want to disable the ability of being converted into a reusable block. By default all blocks can be converted to a reusable block. If supports reusable is set to false, the option to convert the block into a reusable block will not appear.
```js
supports: {
- // Don't allow the block to be converted into a reusable block.
- reusable: false,
+ // Don't allow the block to be converted into a reusable block.
+ reusable: false,
}
```
@@ -882,14 +882,14 @@ supports: {
_**Note:** Since WordPress 6.5._
-- Type: `boolean`
-- Default value: `false`
+- Type: `boolean`
+- Default value: `false`
This property adds block controls which allow the user to set a box shadow for a block. Shadows are disabled by default.
```js
supports: {
- shadow: true // Enable the box-shadow picker.
+ shadow: true; // Enable the box-shadow picker.
}
```
@@ -897,31 +897,31 @@ Shadow presets are sourced from the shadow presets defined in `theme.json`.
When the block declares support for `shadow`, the attributes definition is extended to include the `style` attribute:
-- `style`: an attribute of `object` type with no default assigned.
+- `style`: an attribute of `object` type with no default assigned.
- When a shadow is selected, the color value is stored in the `style.shadow`.
+ When a shadow is selected, the color value is stored in the `style.shadow`.
- The block can apply a default shadow by specifying its own attribute with a default. For example:
+ The block can apply a default shadow by specifying its own attribute with a default. For example:
- ```js
- attributes: {
- style: {
- type: 'object',
- default: {
- shadow: "var:preset|shadow|deep"
- }
- }
- }
- ```
+ ```js
+ attributes: {
+ style: {
+ type: 'object',
+ default: {
+ shadow: "var:preset|shadow|deep"
+ }
+ }
+ }
+ ```
## spacing
-- Type: `Object`
-- Default value: null
-- Subproperties:
- - `margin`: type `boolean` or `array`, default value `false`
- - `padding`: type `boolean` or `array`, default value `false`
- - `blockGap`: type `boolean` or `array`, default value `false`
+- Type: `Object`
+- Default value: null
+- Subproperties:
+ - `margin`: type `boolean` or `array`, default value `false`
+ - `padding`: type `boolean` or `array`, default value `false`
+ - `blockGap`: type `boolean` or `array`, default value `false`
This value signals that a block supports some of the CSS style properties related to spacing. When it does, the block editor will show UI controls for the user to set their values if [the theme declares support](/docs/how-to-guides/themes/theme-support.md#cover-block-padding).
@@ -937,7 +937,7 @@ supports: {
When the block declares support for a specific spacing property, its attributes definition is extended to include the `style` attribute.
-- `style`: an attribute of `object` type with no default assigned. This is added when `margin` or `padding` support is declared. It stores the custom values set by the user. For example:
+- `style`: an attribute of `object` type with no default assigned. This is added when `margin` or `padding` support is declared. It stores the custom values set by the user. For example:
```js
attributes: {
@@ -968,12 +968,12 @@ supports: {
## typography
-- Type: `Object`
-- Default value: `null`
-- Subproperties:
- - `fontSize`: type `boolean`, default value `false`
- - `lineHeight`: type `boolean`, default value `false`
- - `textAlign`: type `boolean` or `array`, default value `false`
+- Type: `Object`
+- Default value: `null`
+- Subproperties:
+ - `fontSize`: type `boolean`, default value `false`
+ - `lineHeight`: type `boolean`, default value `false`
+ - `textAlign`: type `boolean` or `array`, default value `false`
The presence of this object signals that a block supports some typography related properties. When it does, the block editor will show a typography UI allowing the user to control their values.
@@ -992,8 +992,8 @@ supports: {
### typography.fontSize
-- Type: `boolean`
-- Default value: `false`
+- Type: `boolean`
+- Default value: `false`
This value signals that a block supports the font-size CSS style property. When it does, the block editor will show an UI control for the user to set its value.
@@ -1010,7 +1010,7 @@ supports: {
When the block declares support for `fontSize`, the attributes definition is extended to include two new attributes: `fontSize` and `style`:
-- `fontSize`: an attribute of `string` type with no default assigned. It stores any preset value selected by the user. The block can apply a default fontSize by specifying its own `fontSize` attribute with a default. For example:
+- `fontSize`: an attribute of `string` type with no default assigned. It stores any preset value selected by the user. The block can apply a default fontSize by specifying its own `fontSize` attribute with a default. For example:
```js
attributes: {
@@ -1021,7 +1021,7 @@ attributes: {
}
```
-- `style`: an attribute of `object` type with no default assigned. It stores the custom values set by the user and is shared with other block supports such as color. The block can apply a default style by specifying its own `style` attribute with a default. For example:
+- `style`: an attribute of `object` type with no default assigned. It stores the custom values set by the user and is shared with other block supports such as color. The block can apply a default style by specifying its own `style` attribute with a default. For example:
```js
attributes: {
@@ -1038,8 +1038,8 @@ attributes: {
### typography.lineHeight
-- Type: `boolean`
-- Default value: `false`
+- Type: `boolean`
+- Default value: `false`
This value signals that a block supports the line-height CSS style property. When it does, the block editor will show an UI control for the user to set its value if [the theme declares support](/docs/how-to-guides/themes/theme-support.md#supporting-custom-line-heights).
@@ -1071,28 +1071,28 @@ attributes: {
_**Note:** Since WordPress 6.6._
-- Type: `boolean` or `array`
-- Default value: `false`
+- Type: `boolean` or `array`
+- Default value: `false`
This property adds block toolbar controls which allow to change block's text alignment.
```js
supports: {
- typography: {
- // Declare support for block's text alignment.
- // This adds support for all the options:
- // left, center, right.
- textAlign: true
- }
+ typography: {
+ // Declare support for block's text alignment.
+ // This adds support for all the options:
+ // left, center, right.
+ textAlign: true;
+ }
}
```
```js
supports: {
- typography: {
- // Declare support for specific text alignment options.
- textAlign: [ 'left', 'right' ]
- }
+ typography: {
+ // Declare support for specific text alignment options.
+ textAlign: ['left', 'right'];
+ }
}
```
diff --git a/gutenberg/reference-guides/block-api/block-templates.md b/docs/gutenberg/reference-guides/block-api/block-templates.md
similarity index 57%
rename from gutenberg/reference-guides/block-api/block-templates.md
rename to docs/gutenberg/reference-guides/block-api/block-templates.md
index 60af351..fd45e43 100644
--- a/gutenberg/reference-guides/block-api/block-templates.md
+++ b/docs/gutenberg/reference-guides/block-api/block-templates.md
@@ -4,14 +4,14 @@ A block template is defined as a list of block items. Such blocks can have prede
The scope of templates include:
-- Setting a default state dynamically on the client. (like `defaultBlock`)
-- Registered as a default for a given post type.
+- Setting a default state dynamically on the client. (like `defaultBlock`)
+- Registered as a default for a given post type.
Planned additions:
-- Saved and assigned to pages as "page templates".
-- Defined in a `template.php` file or pulled from a custom post type (`wp_templates`) that is site specific.
-- As the equivalent of the theme hierarchy.
+- Saved and assigned to pages as "page templates".
+- Defined in a `template.php` file or pulled from a custom post type (`wp_templates`) that is site specific.
+- As the equivalent of the theme hierarchy.
## API
@@ -40,23 +40,23 @@ const { registerBlockType } = wp.blocks;
const { InnerBlocks } = wp.blockEditor;
const BLOCKS_TEMPLATE = [
- [ 'core/image', {} ],
- [ 'core/paragraph', { placeholder: 'Image Details' } ],
+ ['core/image', {}],
+ ['core/paragraph', { placeholder: 'Image Details' }],
];
-registerBlockType( 'myplugin/template', {
- title: 'My Template Block',
- category: 'widgets',
- edit: ( props ) => {
- return el( InnerBlocks, {
- template: BLOCKS_TEMPLATE,
- templateLock: false,
- } );
- },
- save: ( props ) => {
- return el( InnerBlocks.Content, {} );
- },
-} );
+registerBlockType('myplugin/template', {
+ title: 'My Template Block',
+ category: 'widgets',
+ edit: (props) => {
+ return el(InnerBlocks, {
+ template: BLOCKS_TEMPLATE,
+ templateLock: false,
+ });
+ },
+ save: (props) => {
+ return el(InnerBlocks.Content, {});
+ },
+});
```
See the [Meta Block Tutorial](/docs/how-to-guides/metabox.md#step-4-finishing-touches) for a full example of a template in use.
@@ -75,23 +75,23 @@ A custom post type can register its own template during registration:
```php
function myplugin_register_book_post_type() {
- $args = array(
- 'public' => true,
- 'label' => 'Books',
- 'show_in_rest' => true,
- 'template' => array(
- array( 'core/image', array(
- 'align' => 'left',
- ) ),
- array( 'core/heading', array(
- 'placeholder' => 'Add Author...',
- ) ),
- array( 'core/paragraph', array(
- 'placeholder' => 'Add Description...',
- ) ),
- ),
- );
- register_post_type( 'book', $args );
+ $args = array(
+ 'public' => true,
+ 'label' => 'Books',
+ 'show_in_rest' => true,
+ 'template' => array(
+ array( 'core/image', array(
+ 'align' => 'left',
+ ) ),
+ array( 'core/heading', array(
+ 'placeholder' => 'Add Author...',
+ ) ),
+ array( 'core/paragraph', array(
+ 'placeholder' => 'Add Description...',
+ ) ),
+ ),
+ );
+ register_post_type( 'book', $args );
}
add_action( 'init', 'myplugin_register_book_post_type' );
```
@@ -102,22 +102,22 @@ Sometimes the intention might be to lock the template on the UI so that the bloc
```php
function myplugin_register_template() {
- $post_type_object = get_post_type_object( 'post' );
- $post_type_object->template = array(
- array( 'core/paragraph', array(
- 'placeholder' => 'Add Description...',
- ) ),
- );
- $post_type_object->template_lock = 'all';
+ $post_type_object = get_post_type_object( 'post' );
+ $post_type_object->template = array(
+ array( 'core/paragraph', array(
+ 'placeholder' => 'Add Description...',
+ ) ),
+ );
+ $post_type_object->template_lock = 'all';
}
add_action( 'init', 'myplugin_register_template' );
```
_Options:_
-- `contentOnly` — prevents all operations. Additionally, the block types that don't have content are hidden from the list view and can't gain focus within the block list. Unlike the other lock types, this is not overridable by children.
-- `all` — prevents all operations. It is not possible to insert new blocks, move existing blocks, or delete blocks.
-- `insert` — prevents inserting or removing blocks, but allows moving existing blocks.
+- `contentOnly` — prevents all operations. Additionally, the block types that don't have content are hidden from the list view and can't gain focus within the block list. Unlike the other lock types, this is not overridable by children.
+- `all` — prevents all operations. It is not possible to insert new blocks, move existing blocks, or delete blocks.
+- `insert` — prevents inserting or removing blocks, but allows moving existing blocks.
Lock settings can be inherited by InnerBlocks. If `templateLock` is not set in an InnerBlocks area, the locking of the parent InnerBlocks area is used. If the block is a top level block, the locking configuration of the current post type is used.
@@ -137,27 +137,27 @@ attributes: {
_Options:_
-- `remove` — Locks the ability of a block from being removed.
-- `move` — Locks the ability of a block from being moved.
+- `remove` — Locks the ability of a block from being removed.
+- `move` — Locks the ability of a block from being moved.
You can use this with `templateLock` to lock all blocks except a single block by using `false` in `remove` or `move`.
```php
$template = array(
- array( 'core/image', array(
- 'align' => 'left',
- ) ),
- array( 'core/heading', array(
- 'placeholder' => 'Add Author...',
- ) ),
- // Allow a Paragraph block to be moved or removed.
- array( 'core/paragraph', array(
- 'placeholder' => 'Add Description...',
- 'lock' => array(
- 'move' => false,
- 'remove' => false,
- ),
- ) ),
+ array( 'core/image', array(
+ 'align' => 'left',
+ ) ),
+ array( 'core/heading', array(
+ 'placeholder' => 'Add Author...',
+ ) ),
+ // Allow a Paragraph block to be moved or removed.
+ array( 'core/paragraph', array(
+ 'placeholder' => 'Add Description...',
+ 'lock' => array(
+ 'move' => false,
+ 'remove' => false,
+ ),
+ ) ),
);
```
@@ -167,18 +167,18 @@ Container blocks like the columns blocks also support templates. This is achieve
```php
$template = array(
- array( 'core/paragraph', array(
- 'placeholder' => 'Add a root-level paragraph',
- ) ),
- array( 'core/columns', array(), array(
- array( 'core/column', array(), array(
- array( 'core/image', array() ),
- ) ),
- array( 'core/column', array(), array(
- array( 'core/paragraph', array(
- 'placeholder' => 'Add an inner paragraph'
- ) ),
- ) ),
- ) )
+ array( 'core/paragraph', array(
+ 'placeholder' => 'Add a root-level paragraph',
+ ) ),
+ array( 'core/columns', array(), array(
+ array( 'core/column', array(), array(
+ array( 'core/image', array() ),
+ ) ),
+ array( 'core/column', array(), array(
+ array( 'core/paragraph', array(
+ 'placeholder' => 'Add an inner paragraph'
+ ) ),
+ ) ),
+ ) )
);
```
diff --git a/gutenberg/reference-guides/block-api/block-transforms.md b/docs/gutenberg/reference-guides/block-api/block-transforms.md
similarity index 56%
rename from gutenberg/reference-guides/block-api/block-transforms.md
rename to docs/gutenberg/reference-guides/block-api/block-transforms.md
index c78842f..799caf0 100644
--- a/gutenberg/reference-guides/block-api/block-transforms.md
+++ b/docs/gutenberg/reference-guides/block-api/block-transforms.md
@@ -8,17 +8,17 @@ A block declares which transformations it supports via the optional `transforms`
```js
export const settings = {
- title: 'My Block Title',
- description: 'My block description',
- /* ... */
- transforms: {
- from: [
- /* supported from transforms */
- ],
- to: [
- /* supported to transforms */
- ],
- },
+ title: 'My Block Title',
+ description: 'My block description',
+ /* ... */
+ transforms: {
+ from: [
+ /* supported from transforms */
+ ],
+ to: [
+ /* supported to transforms */
+ ],
+ },
};
```
@@ -26,12 +26,12 @@ export const settings = {
This section goes through the existing types of transformations blocks support:
-- block
-- enter
-- files
-- prefix
-- raw
-- shortcode
+- block
+- enter
+- files
+- prefix
+- raw
+- shortcode
### Block
@@ -39,12 +39,12 @@ This type of transformations support both _from_ and _to_ directions, allowing b
A transformation of type `block` is an object that takes the following parameters:
-- **type** _(string)_: the value `block`.
-- **blocks** _(array)_: a list of known block types. It also accepts the wildcard value (`"*"`), meaning that the transform is available to _all_ block types (eg: all blocks can transform into `core/group`).
-- **transform** _(function)_: a callback that receives the attributes and inner blocks of the block being processed. It should return a block object or an array of block objects.
-- **isMatch** _(function, optional)_: a callback that receives the block attributes as the first argument and the block object as the second argument and should return a boolean. Returning `false` from this function will prevent the transform from being available and displayed as an option to the user.
-- **isMultiBlock** _(boolean, optional)_: whether the transformation can be applied when multiple blocks are selected. If true, the `transform` function's first parameter will be an array containing each selected block's attributes, and the second an array of each selected block's inner blocks. False by default.
-- **priority** _(number, optional)_: controls the priority with which a transformation is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
+- **type** _(string)_: the value `block`.
+- **blocks** _(array)_: a list of known block types. It also accepts the wildcard value (`"*"`), meaning that the transform is available to _all_ block types (eg: all blocks can transform into `core/group`).
+- **transform** _(function)_: a callback that receives the attributes and inner blocks of the block being processed. It should return a block object or an array of block objects.
+- **isMatch** _(function, optional)_: a callback that receives the block attributes as the first argument and the block object as the second argument and should return a boolean. Returning `false` from this function will prevent the transform from being available and displayed as an option to the user.
+- **isMultiBlock** _(boolean, optional)_: whether the transformation can be applied when multiple blocks are selected. If true, the `transform` function's first parameter will be an array containing each selected block's attributes, and the second an array of each selected block's inner blocks. False by default.
+- **priority** _(number, optional)_: controls the priority with which a transformation is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
**Example: from Paragraph block to Heading block**
@@ -94,10 +94,10 @@ This type of transformations support the _from_ direction, allowing blocks to be
A transformation of type `enter` is an object that takes the following parameters:
-- **type** _(string)_: the value `enter`.
-- **regExp** _(RegExp)_: the Regular Expression to use as a matcher. If the value matches, the transformation will be applied.
-- **transform** _(function)_: a callback that receives an object with a `content` field containing the value that has been entered. It should return a block object or an array of block objects.
-- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
+- **type** _(string)_: the value `enter`.
+- **regExp** _(RegExp)_: the Regular Expression to use as a matcher. If the value matches, the transformation will be applied.
+- **transform** _(function)_: a callback that receives an object with a `content` field containing the value that has been entered. It should return a block object or an array of block objects.
+- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
**Example: from --- to Separator block**
@@ -105,13 +105,13 @@ To create a separator block when the user types the hyphen three times and then
```js
transforms = {
- from: [
- {
- type: 'enter',
- regExp: /^-{3,}$/,
- transform: () => createBlock( 'core/separator' ),
- },
- ],
+ from: [
+ {
+ type: 'enter',
+ regExp: /^-{3,}$/,
+ transform: () => createBlock('core/separator'),
+ },
+ ],
};
```
@@ -121,10 +121,10 @@ This type of transformations support the _from_ direction, allowing blocks to be
A transformation of type `files` is an object that takes the following parameters:
-- **type** _(string)_: the value `files`.
-- **transform** _(function)_: a callback that receives the array of files being processed. It should return a block object or an array of block objects.
-- **isMatch** _(function, optional)_: a callback that receives the array of files being processed and should return a boolean. Returning `false` from this function will prevent the transform from being applied.
-- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
+- **type** _(string)_: the value `files`.
+- **transform** _(function)_: a callback that receives the array of files being processed. It should return a block object or an array of block objects.
+- **isMatch** _(function, optional)_: a callback that receives the array of files being processed and should return a boolean. Returning `false` from this function will prevent the transform from being applied.
+- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
**Example: from file to File block**
@@ -132,26 +132,26 @@ To create a File block when the user drops a file into the editor we can use the
```js
transforms: {
- from: [
- {
- type: 'files',
- isMatch: ( files ) => files.length === 1,
- // By defining a lower priority than the default of 10,
- // we make that the File block to be created as a fallback,
- // if no other transform is found.
- priority: 15,
- transform: ( files ) => {
- const file = files[ 0 ];
- const blobURL = createBlobURL( file );
- // File will be uploaded in componentDidMount()
- return createBlock( 'core/file', {
- href: blobURL,
- fileName: file.name,
- textLinkHref: blobURL,
- } );
- },
- },
- ];
+ from: [
+ {
+ type: 'files',
+ isMatch: (files) => files.length === 1,
+ // By defining a lower priority than the default of 10,
+ // we make that the File block to be created as a fallback,
+ // if no other transform is found.
+ priority: 15,
+ transform: (files) => {
+ const file = files[0];
+ const blobURL = createBlobURL(file);
+ // File will be uploaded in componentDidMount()
+ return createBlock('core/file', {
+ href: blobURL,
+ fileName: file.name,
+ textLinkHref: blobURL,
+ });
+ },
+ },
+ ];
}
```
@@ -161,10 +161,10 @@ This type of transformations support the _from_ direction, allowing blocks to be
A transformation of type `prefix` is an object that takes the following parameters:
-- **type** _(string)_: the value `prefix`.
-- **prefix** _(string)_: the character or sequence of characters that match this transform.
-- **transform** _(function)_: a callback that receives the content introduced. It should return a block object or an array of block objects.
-- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
+- **type** _(string)_: the value `prefix`.
+- **prefix** _(string)_: the character or sequence of characters that match this transform.
+- **transform** _(function)_: a callback that receives the content introduced. It should return a block object or an array of block objects.
+- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
**Example: from text to custom block**
@@ -172,17 +172,17 @@ If we want to create a custom block when the user types the question mark, we co
```js
transforms: {
- from: [
- {
- type: 'prefix',
- prefix: '?',
- transform( content ) {
- return createBlock( 'my-plugin/question', {
- content,
- } );
- },
- },
- ];
+ from: [
+ {
+ type: 'prefix',
+ prefix: '?',
+ transform(content) {
+ return createBlock('my-plugin/question', {
+ content,
+ });
+ },
+ },
+ ];
}
```
@@ -192,12 +192,12 @@ This type of transformations support the _from_ direction, allowing blocks to be
A transformation of type `raw` is an object that takes the following parameters:
-- **type** _(string)_: the value `raw`.
-- **transform** _(function, optional)_: a callback that receives the node being processed. It should return a block object or an array of block objects.
-- **schema** _(object|function, optional)_: defines an [HTML content model](https://html.spec.whatwg.org/multipage/dom.html#content-models) used to detect and process pasted contents. See [below](#schemas-and-content-models).
-- **selector** _(string, optional)_: a CSS selector string to determine whether the element matches according to the [element.matches](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches) method. The transform won't be executed if the element doesn't match. This is a shorthand and alternative to using `isMatch`, which, if present, will take precedence.
-- **isMatch** _(function, optional)_: a callback that receives the node being processed and should return a boolean. Returning `false` from this function will prevent the transform from being applied.
-- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
+- **type** _(string)_: the value `raw`.
+- **transform** _(function, optional)_: a callback that receives the node being processed. It should return a block object or an array of block objects.
+- **schema** _(object|function, optional)_: defines an [HTML content model](https://html.spec.whatwg.org/multipage/dom.html#content-models) used to detect and process pasted contents. See [below](#schemas-and-content-models).
+- **selector** _(string, optional)_: a CSS selector string to determine whether the element matches according to the [element.matches](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches) method. The transform won't be executed if the element doesn't match. This is a shorthand and alternative to using `isMatch`, which, if present, will take precedence.
+- **isMatch** _(function, optional)_: a callback that receives the node being processed and should return a boolean. Returning `false` from this function will prevent the transform from being applied.
+- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
**Example: from URLs to Embed block**
@@ -237,8 +237,8 @@ Suppose we want to match the following HTML snippet and turn it into some kind o
```html
-
The Post Title
-
Some great content.
+
The Post Title
+
Some great content.
```
@@ -268,12 +268,12 @@ This type of transformations support the _from_ direction, allowing blocks to be
A transformation of type `shortcode` is an object that takes the following parameters:
-- **type** _(string)_: the value `shortcode`.
-- **tag** _(string|array)_: the shortcode tag or list of shortcode aliases this transform can work with.
-- **transform** _(function, optional)_: a callback that receives the shortcode attributes as the first argument and the [WPShortcodeMatch](/packages/shortcode/README.md#next) as the second. It should return a block object or an array of block objects. When this parameter is defined, it will take precedence over the `attributes` parameter.
-- **attributes** _(object, optional)_: object representing where the block attributes should be sourced from, according to the attributes shape defined by the [block configuration object](/docs/reference-guides/block-api/block-registration.md). If a particular attribute contains a `shortcode` key, it should be a function that receives the shortcode attributes as the first arguments and the [WPShortcodeMatch](/packages/shortcode/README.md#next) as second, and returns a value for the attribute that will be sourced in the block's comment.
-- **isMatch** _(function, optional)_: a callback that receives the shortcode attributes per the [Shortcode API](https://codex.wordpress.org/Shortcode_API) and should return a boolean. Returning `false` from this function will prevent the shortcode to be transformed into this block.
-- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
+- **type** _(string)_: the value `shortcode`.
+- **tag** _(string|array)_: the shortcode tag or list of shortcode aliases this transform can work with.
+- **transform** _(function, optional)_: a callback that receives the shortcode attributes as the first argument and the [WPShortcodeMatch](/packages/shortcode/README.md#next) as the second. It should return a block object or an array of block objects. When this parameter is defined, it will take precedence over the `attributes` parameter.
+- **attributes** _(object, optional)_: object representing where the block attributes should be sourced from, according to the attributes shape defined by the [block configuration object](/docs/reference-guides/block-api/block-registration.md). If a particular attribute contains a `shortcode` key, it should be a function that receives the shortcode attributes as the first arguments and the [WPShortcodeMatch](/packages/shortcode/README.md#next) as second, and returns a value for the attribute that will be sourced in the block's comment.
+- **isMatch** _(function, optional)_: a callback that receives the shortcode attributes per the [Shortcode API](https://codex.wordpress.org/Shortcode_API) and should return a boolean. Returning `false` from this function will prevent the shortcode to be transformed into this block.
+- **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://developer.wordpress.org/reference/#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set.
**Example: from shortcode to block using `transform`**
@@ -349,12 +349,12 @@ Example:
```js
export const settings = {
- title: 'My grouping Block Title',
- description: 'My grouping block description',
- /* ... */
- transforms: {
- ungroup: ( attributes, innerBlocks ) =>
- innerBlocks.flatMap( ( innerBlock ) => innerBlock.innerBlocks ),
- },
+ title: 'My grouping Block Title',
+ description: 'My grouping block description',
+ /* ... */
+ transforms: {
+ ungroup: (attributes, innerBlocks) =>
+ innerBlocks.flatMap((innerBlock) => innerBlock.innerBlocks),
+ },
};
```
diff --git a/gutenberg/reference-guides/block-api/block-variations.md b/docs/gutenberg/reference-guides/block-api/block-variations.md
similarity index 64%
rename from gutenberg/reference-guides/block-api/block-variations.md
rename to docs/gutenberg/reference-guides/block-api/block-variations.md
index 8c223e5..7222ee0 100644
--- a/gutenberg/reference-guides/block-api/block-variations.md
+++ b/docs/gutenberg/reference-guides/block-api/block-variations.md
@@ -8,18 +8,18 @@ To better understand this API, consider the Embed block. This block contains num
```js
variations: [
- {
- name: 'wordpress',
- title: 'WordPress',
- description: __( 'Embed a WordPress post.' ),
- attributes: { providerNameSlug: 'wordpress' },
- },
- {
- name: 'youtube',
- title: 'YouTube',
- description: __( 'Embed a YouTube video.' ),
- attributes: { providerNameSlug: 'youtube' },
- },
+ {
+ name: 'wordpress',
+ title: 'WordPress',
+ description: __( 'Embed a WordPress post.' ),
+ attributes: { providerNameSlug: 'wordpress' },
+ },
+ {
+ name: 'youtube',
+ title: 'YouTube',
+ description: __( 'Embed a YouTube video.' ),
+ attributes: { providerNameSlug: 'youtube' },
+ },
],
```
@@ -27,24 +27,24 @@ variations: [
A block variation is defined by an object that can contain the following fields:
-- `name` (type `string`) – A unique and machine-readable name.
-- `title` (optional, type `string`) – A human-readable variation title.
-- `description` (optional, type `string`) – A human-readable variation description.
-- `category` (optional, type `string`) - A category classification used in search interfaces to arrange block types by category.
-- `keywords` (optional, type `string[]`) - An array of terms (which can be translated) that help users discover the variation while searching.
-- `icon` (optional, type `string` | `Object`) – An icon helping to visualize the variation. It can have the same shape as the block type.
-- `attributes` (optional, type `Object`) – Values that override block attributes.
-- `innerBlocks` (optional, type `Array[]`) – Initial configuration of nested blocks.
-- `example` (optional, type `Object`) – Provides structured data for the block preview. Set to `undefined` to disable the preview. See the [Block Registration API](/docs/reference-guides/block-api/block-registration.md#example-optional) for more details.
-- `scope` (optional, type `WPBlockVariationScope[]`) - Defaults to `block` and `inserter`. The list of scopes where the variation is applicable. Available options include:
- - `block` - Used by blocks to filter specific block variations. `Columns` and `Query` blocks have such variations, which are passed to the [experimental BlockVariationPicker](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-variation-picker/README.md) component. This component handles displaying the variations and allows users to choose one of them.
- - `inserter` - Block variation is shown on the inserter.
- - `transform` - Block variation is shown in the component for variation transformations.
-- `isDefault` (optional, type `boolean`) – Defaults to `false`. Indicates whether the current variation is the default one (details below).
-- `isActive` (optional, type `Function|string[]`) - A function or an array of block attributes that is used to determine if the variation is active when the block is selected. The function accepts `blockAttributes` and `variationAttributes` (details below).
+- `name` (type `string`) – A unique and machine-readable name.
+- `title` (optional, type `string`) – A human-readable variation title.
+- `description` (optional, type `string`) – A human-readable variation description.
+- `category` (optional, type `string`) - A category classification used in search interfaces to arrange block types by category.
+- `keywords` (optional, type `string[]`) - An array of terms (which can be translated) that help users discover the variation while searching.
+- `icon` (optional, type `string` | `Object`) – An icon helping to visualize the variation. It can have the same shape as the block type.
+- `attributes` (optional, type `Object`) – Values that override block attributes.
+- `innerBlocks` (optional, type `Array[]`) – Initial configuration of nested blocks.
+- `example` (optional, type `Object`) – Provides structured data for the block preview. Set to `undefined` to disable the preview. See the [Block Registration API](/docs/reference-guides/block-api/block-registration.md#example-optional) for more details.
+- `scope` (optional, type `WPBlockVariationScope[]`) - Defaults to `block` and `inserter`. The list of scopes where the variation is applicable. Available options include:
+ - `block` - Used by blocks to filter specific block variations. `Columns` and `Query` blocks have such variations, which are passed to the [experimental BlockVariationPicker](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-variation-picker/README.md) component. This component handles displaying the variations and allows users to choose one of them.
+ - `inserter` - Block variation is shown on the inserter.
+ - `transform` - Block variation is shown in the component for variation transformations.
+- `isDefault` (optional, type `boolean`) – Defaults to `false`. Indicates whether the current variation is the default one (details below).
+- `isActive` (optional, type `Function|string[]`) - A function or an array of block attributes that is used to determine if the variation is active when the block is selected. The function accepts `blockAttributes` and `variationAttributes` (details below).
- You can technically create a block variation without a unique name, but this is not recommended. A unique name allows the Editor to differentiate between your variation and others that may exist. It also allows your variation to be unregistered as needed and has implications for the isDefault settings (details below).
+ You can technically create a block variation without a unique name, but this is not recommended. A unique name allows the Editor to differentiate between your variation and others that may exist. It also allows your variation to be unregistered as needed and has implications for the isDefault settings (details below).
## Creating a block variation
@@ -54,10 +54,10 @@ Block variations can be declared during a block's registration by providing the
To create a variation for an existing block, such as a Core block, use `wp.blocks.registerBlockVariation()`. This function accepts the name of the block and the object defining the variation.
```js
-wp.blocks.registerBlockVariation( 'core/embed', {
- name: 'custom-embed',
- attributes: { providerNameSlug: 'custom' },
-} );
+wp.blocks.registerBlockVariation('core/embed', {
+ name: 'custom-embed',
+ attributes: { providerNameSlug: 'custom' },
+});
```
## Registering block variations in PHP
@@ -75,14 +75,14 @@ function my_custom_image_variation( $variations, $block_type ) {
// Add a custom variation
$variations[] = array(
- 'name' => 'wide-image',
- 'title' => __( 'Wide image', 'textdomain' ),
- 'description' => __( 'A wide image', 'textdomain' ),
- 'scope' => array( 'inserter' ),
- 'isDefault' => false,
- 'attributes' => array(
- 'align' => 'wide', // Identifies the link type as custom
- ),
+ 'name' => 'wide-image',
+ 'title' => __( 'Wide image', 'textdomain' ),
+ 'description' => __( 'A wide image', 'textdomain' ),
+ 'scope' => array( 'inserter' ),
+ 'isDefault' => false,
+ 'attributes' => array(
+ 'align' => 'wide', // Identifies the link type as custom
+ ),
);
return $variations;
@@ -91,6 +91,7 @@ add_filter( 'get_block_type_variations', 'my_custom_image_variation', 10, 2 );
```
The `get_block_type_variations` filter is called when variations are requested for a block type. It receives two parameters:
+
- `$variations`: An array of currently registered variations for the block type
- `$block_type`: The full block type object
@@ -103,7 +104,7 @@ Note that variations registered through PHP will be merged with any variations r
Block variations can also be easily removed. To do so, use `wp.blocks.unregisterBlockVariation()`. This function accepts the name of the block and the `name` of the variation that should be unregistered.
```js
-wp.blocks.unregisterBlockVariation( 'core/embed', 'youtube' );
+wp.blocks.unregisterBlockVariation('core/embed', 'youtube');
```
## Block variations versus block styles
@@ -114,18 +115,18 @@ If you want to apply initial attributes or inner blocks, this falls into block v
```js
variations: [
- {
- name: 'blue',
- title: __( 'Blue Quote' ),
- isDefault: true,
- attributes: {
- color: 'blue',
- className: 'is-style-blue-quote'
- },
- icon: 'format-quote',
- isActive: ( blockAttributes, variationAttributes ) =>
- blockAttributes.color === variationAttributes.color
- },
+ {
+ name: 'blue',
+ title: __( 'Blue Quote' ),
+ isDefault: true,
+ attributes: {
+ color: 'blue',
+ className: 'is-style-blue-quote'
+ },
+ icon: 'format-quote',
+ isActive: ( blockAttributes, variationAttributes ) =>
+ blockAttributes.color === variationAttributes.color
+ },
],
```
@@ -136,14 +137,14 @@ By default, all variations will show up in the Inserter in addition to the origi
For example, if you want Media & Text block to display the image on the right by default, you could create a variation like this:
```js
-wp.blocks.registerBlockVariation( 'core/media-text', {
- name: 'media-text-media-right',
- title: __( 'Media & Text' ),
- isDefault: true,
- attributes: {
- mediaPosition: 'right',
- },
-} );
+wp.blocks.registerBlockVariation('core/media-text', {
+ name: 'media-text-media-right',
+ title: __('Media & Text'),
+ isDefault: true,
+ attributes: {
+ mediaPosition: 'right',
+ },
+});
```
### Caveats to using `isDefault`
@@ -168,35 +169,32 @@ As an example, in the core Embed block, the `providerNameSlug` attribute is used
```js
const variations = [
- {
- name: 'twitter',
- title: 'Twitter',
- icon: embedTwitterIcon,
- keywords: [ 'tweet', __( 'social' ) ],
- description: __( 'Embed a tweet.' ),
- patterns: [ /^https?:\/\/(www\.)?twitter\.com\/.+/i ],
- attributes: { providerNameSlug: 'twitter', responsive: true },
- },
- {
- name: 'youtube',
- title: 'YouTube',
- icon: embedYouTubeIcon,
- keywords: [ __( 'music' ), __( 'video' ) ],
- description: __( 'Embed a YouTube video.' ),
- patterns: [
- /^https?:\/\/((m|www)\.)?youtube\.com\/.+/i,
- /^https?:\/\/youtu\.be\/.+/i,
- ],
- attributes: { providerNameSlug: 'youtube', responsive: true },
- },
- // ...
+ {
+ name: 'twitter',
+ title: 'Twitter',
+ icon: embedTwitterIcon,
+ keywords: ['tweet', __('social')],
+ description: __('Embed a tweet.'),
+ patterns: [/^https?:\/\/(www\.)?twitter\.com\/.+/i],
+ attributes: { providerNameSlug: 'twitter', responsive: true },
+ },
+ {
+ name: 'youtube',
+ title: 'YouTube',
+ icon: embedYouTubeIcon,
+ keywords: [__('music'), __('video')],
+ description: __('Embed a YouTube video.'),
+ patterns: [/^https?:\/\/((m|www)\.)?youtube\.com\/.+/i, /^https?:\/\/youtu\.be\/.+/i],
+ attributes: { providerNameSlug: 'youtube', responsive: true },
+ },
+ // ...
];
```
The `isActive` property would then look like this:
```js
-isActive: [ 'providerNameSlug' ];
+isActive: ['providerNameSlug'];
```
This will cause the block instance value for `providerNameSlug` to be compared to the value declared in the variation's declaration (the values in the code snippet above) to determine which embed variation is active.
@@ -204,7 +202,7 @@ This will cause the block instance value for `providerNameSlug` to be compared t
Nested object paths are also supported since WordPress `6.6.0`. For example, consider a block variation that has a `query` object as an attribute. It is possible to determine if the variation is active solely based on that object's `postType` property (while ignoring all its other properties):
```js
-isActive: [ 'query.postType' ];
+isActive: ['query.postType'];
```
The function version of this property accepts a block instance's `blockAttributes` as the first argument, and the `variationAttributes` declared for a variation as the second argument. These arguments can be used to determine if a variation is active by comparing them and returning a `true` or `false` (indicating whether this variation is inactive for this block instance).
@@ -213,7 +211,7 @@ Using the same example for the embed block, the function version would look like
```js
isActive: ( blockAttributes, variationAttributes ) =>
- blockAttributes.providerNameSlug === variationAttributes.providerNameSlug,
+ blockAttributes.providerNameSlug === variationAttributes.providerNameSlug,
```
### Specificity of `isActive` matches
@@ -223,24 +221,24 @@ _Note: Improved handling since WordPress `6.6.0`._
If there are multiple variations whose `isActive` check matches a given block instance, and all of them are string arrays, then the variation with the highest _specificity_ will be chosen. Consider the following example:
```js
-wp.blocks.registerBlockVariation( 'core/paragraph', {
- name: 'paragraph-red',
- title: 'Red Paragraph',
- attributes: {
- textColor: 'vivid-red',
- },
- isActive: [ 'textColor' ],
-} );
-
-wp.blocks.registerBlockVariation( 'core/paragraph', {
- name: 'paragraph-red-grey',
- title: 'Red/Grey Paragraph',
- attributes: {
- textColor: 'vivid-red',
- backgroundColor: 'cyan-bluish-gray',
- },
- isActive: [ 'textColor', 'backgroundColor' ],
-} );
+wp.blocks.registerBlockVariation('core/paragraph', {
+ name: 'paragraph-red',
+ title: 'Red Paragraph',
+ attributes: {
+ textColor: 'vivid-red',
+ },
+ isActive: ['textColor'],
+});
+
+wp.blocks.registerBlockVariation('core/paragraph', {
+ name: 'paragraph-red-grey',
+ title: 'Red/Grey Paragraph',
+ attributes: {
+ textColor: 'vivid-red',
+ backgroundColor: 'cyan-bluish-gray',
+ },
+ isActive: ['textColor', 'backgroundColor'],
+});
```
If a block instance has attributes `textColor: vivid-red` and `backgroundColor: cyan-bluish-gray`, both variations' `isActive` criterion will match that block instance. In this case, the more _specific_ match will be determined to be the active variation, where specificity is calculated as the length of each `isActive` array. This means that the `Red/Grey Paragraph` will be shown as the active variation.
diff --git a/gutenberg/reference-guides/core-blocks.md b/docs/gutenberg/reference-guides/core-blocks.md
similarity index 60%
rename from gutenberg/reference-guides/core-blocks.md
rename to docs/gutenberg/reference-guides/core-blocks.md
index e554306..494f5e2 100644
--- a/gutenberg/reference-guides/core-blocks.md
+++ b/docs/gutenberg/reference-guides/core-blocks.md
@@ -2,9 +2,9 @@
This page lists the blocks included in the block-library package.
-- Items marked with a strikeout (~~strikeout~~) are explicitly disabled.
-- Blocks marked with **Experimental:** true are only available when Gutenberg is active.
-- Blocks marked with **Experimental:** fse are only available in the Site Editor.
+- Items marked with a strikeout (~~strikeout~~) are explicitly disabled.
+- Blocks marked with **Experimental:** true are only available when Gutenberg is active.
+- Blocks marked with **Experimental:** fse are only available in the Site Editor.
@@ -12,1006 +12,1006 @@ This page lists the blocks included in the block-library package.
Displays a group of accordion headers and associated expandable content. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/accordion))
-- **Name:** core/accordion
-- **Experimental:** true
-- **Category:** design
-- **Allowed Blocks:** core/accordion-content
-- **Supports:** align (full, wide), background (backgroundImage, backgroundSize), color (background, gradient, text), interactivity, layout, shadow, spacing (blockGap, margin, padding), ~~html~~
-- **Attributes:** allowedBlocks, autoclose, iconPosition, showIcon
+- **Name:** core/accordion
+- **Experimental:** true
+- **Category:** design
+- **Allowed Blocks:** core/accordion-content
+- **Supports:** align (full, wide), background (backgroundImage, backgroundSize), color (background, gradient, text), interactivity, layout, shadow, spacing (blockGap, margin, padding), ~~html~~
+- **Attributes:** allowedBlocks, autoclose, iconPosition, showIcon
## Accordion Content
Displays a section of content in an accordion, including a header and expandable content. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/accordion-content))
-- **Name:** core/accordion-content
-- **Experimental:** true
-- **Category:** design
-- **Parent:** core/accordion
-- **Allowed Blocks:** core/accordion-header, core/accordion-panel
-- **Supports:** align (full, wide), color (background, gradient, text), interactivity, shadow, spacing (blockGap, margin)
-- **Attributes:** openByDefault
+- **Name:** core/accordion-content
+- **Experimental:** true
+- **Category:** design
+- **Parent:** core/accordion
+- **Allowed Blocks:** core/accordion-header, core/accordion-panel
+- **Supports:** align (full, wide), color (background, gradient, text), interactivity, shadow, spacing (blockGap, margin)
+- **Attributes:** openByDefault
## Accordion Header
Displays an accordion header. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/accordion-header))
-- **Name:** core/accordion-header
-- **Experimental:** true
-- **Category:** design
-- **Parent:** core/accordion-content
-- **Supports:** anchor, border, color (background, gradient, text), interactivity, shadow, spacing (margin, padding), typography (fontSize, textAlign), ~~align~~
-- **Attributes:** iconPosition, level, levelOptions, openByDefault, showIcon, textAlignment, title
+- **Name:** core/accordion-header
+- **Experimental:** true
+- **Category:** design
+- **Parent:** core/accordion-content
+- **Supports:** anchor, border, color (background, gradient, text), interactivity, shadow, spacing (margin, padding), typography (fontSize, textAlign), ~~align~~
+- **Attributes:** iconPosition, level, levelOptions, openByDefault, showIcon, textAlignment, title
## Accordion Panel
Displays an accordion panel. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/accordion-panel))
-- **Name:** core/accordion-panel
-- **Experimental:** true
-- **Category:** design
-- **Parent:** core/accordion-content
-- **Supports:** border, color (background, gradient, text), interactivity, shadow, spacing (blockGap, margin, padding), typography (fontSize, lineHeight)
-- **Attributes:** allowedBlocks, isSelected, openByDefault, templateLock
+- **Name:** core/accordion-panel
+- **Experimental:** true
+- **Category:** design
+- **Parent:** core/accordion-content
+- **Supports:** border, color (background, gradient, text), interactivity, shadow, spacing (blockGap, margin, padding), typography (fontSize, lineHeight)
+- **Attributes:** allowedBlocks, isSelected, openByDefault, templateLock
## Archives
Display a date archive of your posts. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/archives))
-- **Name:** core/archives
-- **Category:** widgets
-- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** displayAsDropdown, showLabel, showPostCounts, type
+- **Name:** core/archives
+- **Category:** widgets
+- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** displayAsDropdown, showLabel, showPostCounts, type
## Audio
Embed a simple audio player. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/audio))
-- **Name:** core/audio
-- **Category:** media
-- **Supports:** align, anchor, interactivity (clientNavigation), spacing (margin, padding)
-- **Attributes:** autoplay, blob, caption, id, loop, preload, src
+- **Name:** core/audio
+- **Category:** media
+- **Supports:** align, anchor, interactivity (clientNavigation), spacing (margin, padding)
+- **Attributes:** autoplay, blob, caption, id, loop, preload, src
## Avatar
Add a user’s avatar. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/avatar))
-- **Name:** core/avatar
-- **Category:** theme
-- **Supports:** align, color (~~background~~, ~~text~~), filter (duotone), interactivity (clientNavigation), spacing (margin, padding), ~~alignWide~~, ~~html~~
-- **Attributes:** isLink, linkTarget, size, userId
+- **Name:** core/avatar
+- **Category:** theme
+- **Supports:** align, color (~~background~~, ~~text~~), filter (duotone), interactivity (clientNavigation), spacing (margin, padding), ~~alignWide~~, ~~html~~
+- **Attributes:** isLink, linkTarget, size, userId
## Pattern
Reuse this design across your site. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/block))
-- **Name:** core/block
-- **Category:** reusable
-- **Supports:** interactivity (clientNavigation), ~~customClassName~~, ~~html~~, ~~inserter~~, ~~renaming~~
-- **Attributes:** content, ref
+- **Name:** core/block
+- **Category:** reusable
+- **Supports:** interactivity (clientNavigation), ~~customClassName~~, ~~html~~, ~~inserter~~, ~~renaming~~
+- **Attributes:** content, ref
## Button
Prompt visitors to take action with a button-style link. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/button))
-- **Name:** core/button
-- **Category:** design
-- **Parent:** core/buttons
-- **Supports:** anchor, color (background, gradients, text), interactivity (clientNavigation), shadow (), spacing (padding), splitting, typography (fontSize, lineHeight), ~~alignWide~~, ~~align~~, ~~reusable~~
-- **Attributes:** backgroundColor, gradient, linkTarget, placeholder, rel, tagName, text, textAlign, textColor, title, type, url, width
+- **Name:** core/button
+- **Category:** design
+- **Parent:** core/buttons
+- **Supports:** anchor, color (background, gradients, text), interactivity (clientNavigation), shadow (), spacing (padding), splitting, typography (fontSize, lineHeight), ~~alignWide~~, ~~align~~, ~~reusable~~
+- **Attributes:** backgroundColor, gradient, linkTarget, placeholder, rel, tagName, text, textAlign, textColor, title, type, url, width
## Buttons
Prompt visitors to take action with a group of button-style links. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/buttons))
-- **Name:** core/buttons
-- **Category:** design
-- **Allowed Blocks:** core/button
-- **Supports:** align (full, wide), anchor, color (background, gradients, ~~text~~), interactivity (clientNavigation), layout (default, ~~allowInheriting~~, ~~allowSwitching~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Name:** core/buttons
+- **Category:** design
+- **Allowed Blocks:** core/button
+- **Supports:** align (full, wide), anchor, color (background, gradients, ~~text~~), interactivity (clientNavigation), layout (default, ~~allowInheriting~~, ~~allowSwitching~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
## Calendar
A calendar of your site’s posts. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/calendar))
-- **Name:** core/calendar
-- **Category:** widgets
-- **Supports:** align, color (background, link, text), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** month, year
+- **Name:** core/calendar
+- **Category:** widgets
+- **Supports:** align, color (background, link, text), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** month, year
## Terms List
Display a list of all terms of a given taxonomy. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/categories))
-- **Name:** core/categories
-- **Category:** widgets
-- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** displayAsDropdown, label, showEmpty, showHierarchy, showLabel, showOnlyTopLevel, showPostCounts, taxonomy
+- **Name:** core/categories
+- **Category:** widgets
+- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** displayAsDropdown, label, showEmpty, showHierarchy, showLabel, showOnlyTopLevel, showPostCounts, taxonomy
## Code
Display code snippets that respect your spacing and tabs. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/code))
-- **Name:** core/code
-- **Category:** text
-- **Supports:** align (wide), anchor, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
-- **Attributes:** content
+- **Name:** core/code
+- **Category:** text
+- **Supports:** align (wide), anchor, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
+- **Attributes:** content
## Column
A single column within a columns block. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/column))
-- **Name:** core/column
-- **Category:** design
-- **Parent:** core/columns
-- **Supports:** anchor, color (background, button, gradients, heading, link, text), interactivity (clientNavigation), layout, shadow, spacing (blockGap, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** allowedBlocks, templateLock, verticalAlignment, width
+- **Name:** core/column
+- **Category:** design
+- **Parent:** core/columns
+- **Supports:** anchor, color (background, button, gradients, heading, link, text), interactivity (clientNavigation), layout, shadow, spacing (blockGap, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** allowedBlocks, templateLock, verticalAlignment, width
## Columns
Display content in multiple columns, with blocks added to each column. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/columns))
-- **Name:** core/columns
-- **Category:** design
-- **Allowed Blocks:** core/column
-- **Supports:** align (full, wide), anchor, color (background, button, gradients, heading, link, text), interactivity (clientNavigation), layout (default, ~~allowEditing~~, ~~allowInheriting~~, ~~allowSwitching~~), shadow, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** isStackedOnMobile, templateLock, verticalAlignment
+- **Name:** core/columns
+- **Category:** design
+- **Allowed Blocks:** core/column
+- **Supports:** align (full, wide), anchor, color (background, button, gradients, heading, link, text), interactivity (clientNavigation), layout (default, ~~allowEditing~~, ~~allowInheriting~~, ~~allowSwitching~~), shadow, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** isStackedOnMobile, templateLock, verticalAlignment
## Comment Author Avatar (deprecated)
This block is deprecated. Please use the Avatar block instead. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comment-author-avatar))
-- **Name:** core/comment-author-avatar
-- **Experimental:** fse
-- **Category:** theme
-- **Ancestor:** core/comment-template
-- **Supports:** color (background, ~~text~~), interactivity (clientNavigation), spacing (margin, padding), ~~html~~, ~~inserter~~
-- **Attributes:** height, width
+- **Name:** core/comment-author-avatar
+- **Experimental:** fse
+- **Category:** theme
+- **Ancestor:** core/comment-template
+- **Supports:** color (background, ~~text~~), interactivity (clientNavigation), spacing (margin, padding), ~~html~~, ~~inserter~~
+- **Attributes:** height, width
## Comment Author Name
Displays the name of the author of the comment. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comment-author-name))
-- **Name:** core/comment-author-name
-- **Category:** theme
-- **Ancestor:** core/comment-template
-- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** isLink, linkTarget, textAlign
+- **Name:** core/comment-author-name
+- **Category:** theme
+- **Ancestor:** core/comment-template
+- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** isLink, linkTarget, textAlign
## Comment Content
Displays the contents of a comment. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comment-content))
-- **Name:** core/comment-content
-- **Category:** theme
-- **Ancestor:** core/comment-template
-- **Supports:** color (background, gradients, link, text), spacing (padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** textAlign
+- **Name:** core/comment-content
+- **Category:** theme
+- **Ancestor:** core/comment-template
+- **Supports:** color (background, gradients, link, text), spacing (padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** textAlign
## Comment Date
Displays the date on which the comment was posted. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comment-date))
-- **Name:** core/comment-date
-- **Category:** theme
-- **Ancestor:** core/comment-template
-- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** format, isLink
+- **Name:** core/comment-date
+- **Category:** theme
+- **Ancestor:** core/comment-template
+- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** format, isLink
## Comment Edit Link
Displays a link to edit the comment in the WordPress Dashboard. This link is only visible to users with the edit comment capability. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comment-edit-link))
-- **Name:** core/comment-edit-link
-- **Category:** theme
-- **Ancestor:** core/comment-template
-- **Supports:** color (background, gradients, link, ~~text~~), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** linkTarget, textAlign
+- **Name:** core/comment-edit-link
+- **Category:** theme
+- **Ancestor:** core/comment-template
+- **Supports:** color (background, gradients, link, ~~text~~), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** linkTarget, textAlign
## Comment Reply Link
Displays a link to reply to a comment. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comment-reply-link))
-- **Name:** core/comment-reply-link
-- **Category:** theme
-- **Ancestor:** core/comment-template
-- **Supports:** color (background, gradients, link, ~~text~~), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** textAlign
+- **Name:** core/comment-reply-link
+- **Category:** theme
+- **Ancestor:** core/comment-template
+- **Supports:** color (background, gradients, link, ~~text~~), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** textAlign
## Comment Template
Contains the block elements used to display a comment, like the title, date, author, avatar and more. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comment-template))
-- **Name:** core/comment-template
-- **Category:** design
-- **Parent:** core/comments
-- **Supports:** align, interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Name:** core/comment-template
+- **Category:** design
+- **Parent:** core/comments
+- **Supports:** align, interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
## Comments
An advanced block that allows displaying post comments using different visual configurations. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comments))
-- **Name:** core/comments
-- **Category:** theme
-- **Supports:** align (full, wide), color (background, gradients, heading, link, text), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** legacy, tagName
+- **Name:** core/comments
+- **Category:** theme
+- **Supports:** align (full, wide), color (background, gradients, heading, link, text), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** legacy, tagName
## Comments Pagination
Displays a paginated navigation to next/previous set of comments, when applicable. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comments-pagination))
-- **Name:** core/comments-pagination
-- **Category:** theme
-- **Parent:** core/comments
-- **Allowed Blocks:** core/comments-pagination-previous, core/comments-pagination-numbers, core/comments-pagination-next
-- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), layout (default, ~~allowInheriting~~, ~~allowSwitching~~), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** paginationArrow
+- **Name:** core/comments-pagination
+- **Category:** theme
+- **Parent:** core/comments
+- **Allowed Blocks:** core/comments-pagination-previous, core/comments-pagination-numbers, core/comments-pagination-next
+- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), layout (default, ~~allowInheriting~~, ~~allowSwitching~~), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** paginationArrow
## Comments Next Page
Displays the next comment's page link. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comments-pagination-next))
-- **Name:** core/comments-pagination-next
-- **Category:** theme
-- **Parent:** core/comments-pagination
-- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** label
+- **Name:** core/comments-pagination-next
+- **Category:** theme
+- **Parent:** core/comments-pagination
+- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** label
## Comments Page Numbers
Displays a list of page numbers for comments pagination. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comments-pagination-numbers))
-- **Name:** core/comments-pagination-numbers
-- **Category:** theme
-- **Parent:** core/comments-pagination
-- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Name:** core/comments-pagination-numbers
+- **Category:** theme
+- **Parent:** core/comments-pagination
+- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
## Comments Previous Page
Displays the previous comment's page link. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comments-pagination-previous))
-- **Name:** core/comments-pagination-previous
-- **Category:** theme
-- **Parent:** core/comments-pagination
-- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** label
+- **Name:** core/comments-pagination-previous
+- **Category:** theme
+- **Parent:** core/comments-pagination
+- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** label
## Comments Title
Displays a title with the number of comments. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/comments-title))
-- **Name:** core/comments-title
-- **Category:** theme
-- **Ancestor:** core/comments
-- **Supports:** align, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~anchor~~, ~~html~~
-- **Attributes:** level, levelOptions, showCommentsCount, showPostTitle, textAlign
+- **Name:** core/comments-title
+- **Category:** theme
+- **Ancestor:** core/comments
+- **Supports:** align, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~anchor~~, ~~html~~
+- **Attributes:** level, levelOptions, showCommentsCount, showPostTitle, textAlign
## Cover
Add an image or video with a text overlay. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/cover))
-- **Name:** core/cover
-- **Category:** media
-- **Supports:** align, anchor, color (heading, text, ~~background~~, ~~enableContrastChecker~~), dimensions (aspectRatio), filter (duotone), interactivity (clientNavigation), layout (~~allowJustification~~), shadow, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** allowedBlocks, alt, backgroundType, contentPosition, customGradient, customOverlayColor, dimRatio, focalPoint, gradient, hasParallax, id, isDark, isRepeated, isUserOverlayColor, minHeight, minHeightUnit, overlayColor, poster, sizeSlug, tagName, templateLock, url, useFeaturedImage
+- **Name:** core/cover
+- **Category:** media
+- **Supports:** align, anchor, color (heading, text, ~~background~~, ~~enableContrastChecker~~), dimensions (aspectRatio), filter (duotone), interactivity (clientNavigation), layout (~~allowJustification~~), shadow, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** allowedBlocks, alt, backgroundType, contentPosition, customGradient, customOverlayColor, dimRatio, focalPoint, gradient, hasParallax, id, isDark, isRepeated, isUserOverlayColor, minHeight, minHeightUnit, overlayColor, poster, sizeSlug, tagName, templateLock, url, useFeaturedImage
## Details
Hide and show additional content. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/details))
-- **Name:** core/details
-- **Category:** text
-- **Supports:** align (full, wide), anchor, color (background, gradients, link, text), interactivity (clientNavigation), layout (~~allowEditing~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** allowedBlocks, name, placeholder, showContent, summary
+- **Name:** core/details
+- **Category:** text
+- **Supports:** align (full, wide), anchor, color (background, gradients, link, text), interactivity (clientNavigation), layout (~~allowEditing~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** allowedBlocks, name, placeholder, showContent, summary
## Embed
Add a block that displays content pulled from other sites, like Twitter or YouTube. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/embed))
-- **Name:** core/embed
-- **Category:** embed
-- **Supports:** align, interactivity (clientNavigation), spacing (margin)
-- **Attributes:** allowResponsive, caption, previewable, providerNameSlug, responsive, type, url
+- **Name:** core/embed
+- **Category:** embed
+- **Supports:** align, interactivity (clientNavigation), spacing (margin)
+- **Attributes:** allowResponsive, caption, previewable, providerNameSlug, responsive, type, url
## File
Add a link to a downloadable file. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/file))
-- **Name:** core/file
-- **Category:** media
-- **Supports:** align, anchor, color (background, gradients, link, ~~text~~), interactivity, spacing (margin, padding)
-- **Attributes:** blob, displayPreview, downloadButtonText, fileId, fileName, href, id, previewHeight, showDownloadButton, textLinkHref, textLinkTarget
+- **Name:** core/file
+- **Category:** media
+- **Supports:** align, anchor, color (background, gradients, link, ~~text~~), interactivity, spacing (margin, padding)
+- **Attributes:** blob, displayPreview, downloadButtonText, fileId, fileName, href, id, previewHeight, showDownloadButton, textLinkHref, textLinkTarget
## Footnotes
Display footnotes added to the page. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/footnotes))
-- **Name:** core/footnotes
-- **Category:** text
-- **Supports:** color (background, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~inserter~~, ~~multiple~~, ~~reusable~~
+- **Name:** core/footnotes
+- **Category:** text
+- **Supports:** color (background, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~inserter~~, ~~multiple~~, ~~reusable~~
## Form
A form. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/form))
-- **Name:** core/form
-- **Experimental:** true
-- **Category:** common
-- **Allowed Blocks:** core/paragraph, core/heading, core/form-input, core/form-submit-button, core/form-submission-notification, core/group, core/columns
-- **Supports:** anchor, color (background, gradients, link, text), spacing (margin, padding), typography (fontSize, lineHeight)
-- **Attributes:** action, email, method, submissionMethod
+- **Name:** core/form
+- **Experimental:** true
+- **Category:** common
+- **Allowed Blocks:** core/paragraph, core/heading, core/form-input, core/form-submit-button, core/form-submission-notification, core/group, core/columns
+- **Supports:** anchor, color (background, gradients, link, text), spacing (margin, padding), typography (fontSize, lineHeight)
+- **Attributes:** action, email, method, submissionMethod
## Input Field
The basic building block for forms. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/form-input))
-- **Name:** core/form-input
-- **Experimental:** true
-- **Category:** common
-- **Ancestor:** core/form
-- **Supports:** anchor, spacing (margin), ~~reusable~~
-- **Attributes:** inlineLabel, label, name, placeholder, required, type, value, visibilityPermissions
+- **Name:** core/form-input
+- **Experimental:** true
+- **Category:** common
+- **Ancestor:** core/form
+- **Supports:** anchor, spacing (margin), ~~reusable~~
+- **Attributes:** inlineLabel, label, name, placeholder, required, type, value, visibilityPermissions
## Form Submission Notification
Provide a notification message after the form has been submitted. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/form-submission-notification))
-- **Name:** core/form-submission-notification
-- **Experimental:** true
-- **Category:** common
-- **Ancestor:** core/form
-- **Attributes:** type
+- **Name:** core/form-submission-notification
+- **Experimental:** true
+- **Category:** common
+- **Ancestor:** core/form
+- **Attributes:** type
## Form Submit Button
A submission button for forms. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/form-submit-button))
-- **Name:** core/form-submit-button
-- **Experimental:** true
-- **Category:** common
-- **Ancestor:** core/form
-- **Allowed Blocks:** core/buttons, core/button
+- **Name:** core/form-submit-button
+- **Experimental:** true
+- **Category:** common
+- **Ancestor:** core/form
+- **Allowed Blocks:** core/buttons, core/button
## Classic
Use the classic WordPress editor. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/freeform))
-- **Name:** core/freeform
-- **Category:** text
-- **Supports:** ~~className~~, ~~customClassName~~, ~~reusable~~
-- **Attributes:** content
+- **Name:** core/freeform
+- **Category:** text
+- **Supports:** ~~className~~, ~~customClassName~~, ~~reusable~~
+- **Attributes:** content
## Gallery
Display multiple images in a rich gallery. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/gallery))
-- **Name:** core/gallery
-- **Category:** media
-- **Allowed Blocks:** core/image
-- **Supports:** align, anchor, color (background, gradients, ~~text~~), interactivity (clientNavigation), layout (default, ~~allowEditing~~, ~~allowInheriting~~, ~~allowSwitching~~), spacing (blockGap, margin, padding), units (em, px, rem, vh, vw), ~~html~~
-- **Attributes:** allowResize, caption, columns, fixedHeight, ids, imageCrop, images, linkTarget, linkTo, randomOrder, shortCodeTransforms, sizeSlug
+- **Name:** core/gallery
+- **Category:** media
+- **Allowed Blocks:** core/image
+- **Supports:** align, anchor, color (background, gradients, ~~text~~), interactivity (clientNavigation), layout (default, ~~allowEditing~~, ~~allowInheriting~~, ~~allowSwitching~~), spacing (blockGap, margin, padding), units (em, px, rem, vh, vw), ~~html~~
+- **Attributes:** allowResize, caption, columns, fixedHeight, ids, imageCrop, images, linkTarget, linkTo, randomOrder, shortCodeTransforms, sizeSlug
## Group
Gather blocks in a layout container. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/group))
-- **Name:** core/group
-- **Category:** design
-- **Supports:** align (full, wide), anchor, ariaLabel, background (backgroundImage, backgroundSize), color (background, button, gradients, heading, link, text), dimensions (minHeight), interactivity (clientNavigation), layout (allowSizingOnChildren), position (sticky), shadow, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** allowedBlocks, tagName, templateLock
+- **Name:** core/group
+- **Category:** design
+- **Supports:** align (full, wide), anchor, ariaLabel, background (backgroundImage, backgroundSize), color (background, button, gradients, heading, link, text), dimensions (minHeight), interactivity (clientNavigation), layout (allowSizingOnChildren), position (sticky), shadow, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** allowedBlocks, tagName, templateLock
## Heading
Introduce new sections and organize content to help visitors (and search engines) understand the structure of your content. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/heading))
-- **Name:** core/heading
-- **Category:** text
-- **Supports:** __unstablePasteTextInline, align (full, wide), anchor, className, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), splitting, typography (fontSize, lineHeight)
-- **Attributes:** content, level, levelOptions, placeholder, textAlign
+- **Name:** core/heading
+- **Category:** text
+- **Supports:** \_\_unstablePasteTextInline, align (full, wide), anchor, className, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), splitting, typography (fontSize, lineHeight)
+- **Attributes:** content, level, levelOptions, placeholder, textAlign
## Home Link
Create a link that always points to the homepage of the site. Usually not necessary if there is already a site title link present in the header. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/home-link))
-- **Name:** core/home-link
-- **Category:** design
-- **Parent:** core/navigation
-- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** label
+- **Name:** core/home-link
+- **Category:** design
+- **Parent:** core/navigation
+- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** label
## Custom HTML
Add custom HTML code and preview it as you edit. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/html))
-- **Name:** core/html
-- **Category:** widgets
-- **Supports:** interactivity (clientNavigation), ~~className~~, ~~customClassName~~, ~~html~~
-- **Attributes:** content
+- **Name:** core/html
+- **Category:** widgets
+- **Supports:** interactivity (clientNavigation), ~~className~~, ~~customClassName~~, ~~html~~
+- **Attributes:** content
## Image
Insert an image to make a visual statement. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/image))
-- **Name:** core/image
-- **Category:** media
-- **Supports:** align (center, full, left, right, wide), anchor, color (~~background~~, ~~text~~), filter (duotone), interactivity, shadow (), spacing (margin)
-- **Attributes:** alt, aspectRatio, blob, caption, height, href, id, lightbox, linkClass, linkDestination, linkTarget, rel, scale, sizeSlug, title, url, width
+- **Name:** core/image
+- **Category:** media
+- **Supports:** align (center, full, left, right, wide), anchor, color (~~background~~, ~~text~~), filter (duotone), interactivity, shadow (), spacing (margin)
+- **Attributes:** alt, aspectRatio, blob, caption, height, href, id, lightbox, linkClass, linkDestination, linkTarget, rel, scale, sizeSlug, title, url, width
## Latest Comments
Display a list of your most recent comments. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/latest-comments))
-- **Name:** core/latest-comments
-- **Category:** widgets
-- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** commentsToShow, displayAvatar, displayDate, displayExcerpt
+- **Name:** core/latest-comments
+- **Category:** widgets
+- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** commentsToShow, displayAvatar, displayDate, displayExcerpt
## Latest Posts
Display a list of your most recent posts. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/latest-posts))
-- **Name:** core/latest-posts
-- **Category:** widgets
-- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** addLinkToFeaturedImage, categories, columns, displayAuthor, displayFeaturedImage, displayPostContent, displayPostContentRadio, displayPostDate, excerptLength, featuredImageAlign, featuredImageSizeHeight, featuredImageSizeSlug, featuredImageSizeWidth, order, orderBy, postLayout, postsToShow, selectedAuthor
+- **Name:** core/latest-posts
+- **Category:** widgets
+- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** addLinkToFeaturedImage, categories, columns, displayAuthor, displayFeaturedImage, displayPostContent, displayPostContentRadio, displayPostDate, excerptLength, featuredImageAlign, featuredImageSizeHeight, featuredImageSizeSlug, featuredImageSizeWidth, order, orderBy, postLayout, postsToShow, selectedAuthor
## List
An organized collection of items displayed in a specific order. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list))
-- **Name:** core/list
-- **Category:** text
-- **Allowed Blocks:** core/list-item
-- **Supports:** __unstablePasteTextInline, anchor, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** ordered, placeholder, reversed, start, type, values
+- **Name:** core/list
+- **Category:** text
+- **Allowed Blocks:** core/list-item
+- **Supports:** \_\_unstablePasteTextInline, anchor, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** ordered, placeholder, reversed, start, type, values
## List Item
An individual item within a list. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/list-item))
-- **Name:** core/list-item
-- **Category:** text
-- **Parent:** core/list
-- **Allowed Blocks:** core/list
-- **Supports:** anchor, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), splitting, typography (fontSize, lineHeight), ~~className~~
-- **Attributes:** content, placeholder
+- **Name:** core/list-item
+- **Category:** text
+- **Parent:** core/list
+- **Allowed Blocks:** core/list
+- **Supports:** anchor, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), splitting, typography (fontSize, lineHeight), ~~className~~
+- **Attributes:** content, placeholder
## Login/out
Show login & logout links. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/loginout))
-- **Name:** core/loginout
-- **Category:** theme
-- **Supports:** className, color (background, gradients, link, ~~text~~), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
-- **Attributes:** displayLoginAsForm, redirectToCurrent
+- **Name:** core/loginout
+- **Category:** theme
+- **Supports:** className, color (background, gradients, link, ~~text~~), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
+- **Attributes:** displayLoginAsForm, redirectToCurrent
## Media & Text
Set media and words side-by-side for a richer layout. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/media-text))
-- **Name:** core/media-text
-- **Category:** media
-- **Supports:** align (full, wide), anchor, color (background, gradients, heading, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** align, allowedBlocks, focalPoint, href, imageFill, isStackedOnMobile, linkClass, linkDestination, linkTarget, mediaAlt, mediaId, mediaLink, mediaPosition, mediaSizeSlug, mediaType, mediaUrl, mediaWidth, rel, useFeaturedImage, verticalAlignment
+- **Name:** core/media-text
+- **Category:** media
+- **Supports:** align (full, wide), anchor, color (background, gradients, heading, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** align, allowedBlocks, focalPoint, href, imageFill, isStackedOnMobile, linkClass, linkDestination, linkTarget, mediaAlt, mediaId, mediaLink, mediaPosition, mediaSizeSlug, mediaType, mediaUrl, mediaWidth, rel, useFeaturedImage, verticalAlignment
## Unsupported
Your site doesn’t include support for this block. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/missing))
-- **Name:** core/missing
-- **Category:** text
-- **Supports:** interactivity (clientNavigation), ~~className~~, ~~customClassName~~, ~~html~~, ~~inserter~~, ~~reusable~~
-- **Attributes:** originalContent, originalName, originalUndelimitedContent
+- **Name:** core/missing
+- **Category:** text
+- **Supports:** interactivity (clientNavigation), ~~className~~, ~~customClassName~~, ~~html~~, ~~inserter~~, ~~reusable~~
+- **Attributes:** originalContent, originalName, originalUndelimitedContent
## More
Content before this block will be shown in the excerpt on your archives page. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/more))
-- **Name:** core/more
-- **Category:** design
-- **Supports:** interactivity (clientNavigation), ~~className~~, ~~customClassName~~, ~~html~~, ~~multiple~~
-- **Attributes:** customText, noTeaser
+- **Name:** core/more
+- **Category:** design
+- **Supports:** interactivity (clientNavigation), ~~className~~, ~~customClassName~~, ~~html~~, ~~multiple~~
+- **Attributes:** customText, noTeaser
## Navigation
A collection of blocks that allow visitors to get around your site. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/navigation))
-- **Name:** core/navigation
-- **Category:** theme
-- **Allowed Blocks:** core/navigation-link, core/search, core/social-links, core/page-list, core/spacer, core/home-link, core/site-title, core/site-logo, core/navigation-submenu, core/loginout, core/buttons
-- **Supports:** align (full, wide), ariaLabel, inserter, interactivity, layout (allowSizingOnChildren, default, ~~allowInheriting~~, ~~allowSwitching~~, ~~allowVerticalAlignment~~), spacing (blockGap, units), typography (fontSize, lineHeight), ~~html~~, ~~renaming~~
-- **Attributes:** __unstableLocation, backgroundColor, customBackgroundColor, customOverlayBackgroundColor, customOverlayTextColor, customTextColor, hasIcon, icon, maxNestingLevel, openSubmenusOnClick, overlayBackgroundColor, overlayMenu, overlayTextColor, ref, rgbBackgroundColor, rgbTextColor, showSubmenuIcon, templateLock, textColor
+- **Name:** core/navigation
+- **Category:** theme
+- **Allowed Blocks:** core/navigation-link, core/search, core/social-links, core/page-list, core/spacer, core/home-link, core/site-title, core/site-logo, core/navigation-submenu, core/loginout, core/buttons
+- **Supports:** align (full, wide), ariaLabel, inserter, interactivity, layout (allowSizingOnChildren, default, ~~allowInheriting~~, ~~allowSwitching~~, ~~allowVerticalAlignment~~), spacing (blockGap, units), typography (fontSize, lineHeight), ~~html~~, ~~renaming~~
+- **Attributes:** \_\_unstableLocation, backgroundColor, customBackgroundColor, customOverlayBackgroundColor, customOverlayTextColor, customTextColor, hasIcon, icon, maxNestingLevel, openSubmenusOnClick, overlayBackgroundColor, overlayMenu, overlayTextColor, ref, rgbBackgroundColor, rgbTextColor, showSubmenuIcon, templateLock, textColor
## Custom Link
Add a page, link, or another item to your navigation. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/navigation-link))
-- **Name:** core/navigation-link
-- **Category:** design
-- **Parent:** core/navigation
-- **Allowed Blocks:** core/navigation-link, core/navigation-submenu, core/page-list
-- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~renaming~~, ~~reusable~~
-- **Attributes:** description, id, isTopLevelLink, kind, label, opensInNewTab, rel, title, type, url
+- **Name:** core/navigation-link
+- **Category:** design
+- **Parent:** core/navigation
+- **Allowed Blocks:** core/navigation-link, core/navigation-submenu, core/page-list
+- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~renaming~~, ~~reusable~~
+- **Attributes:** description, id, isTopLevelLink, kind, label, opensInNewTab, rel, title, type, url
## Submenu
Add a submenu to your navigation. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/navigation-submenu))
-- **Name:** core/navigation-submenu
-- **Category:** design
-- **Parent:** core/navigation
-- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** description, id, isTopLevelItem, kind, label, opensInNewTab, rel, title, type, url
+- **Name:** core/navigation-submenu
+- **Category:** design
+- **Parent:** core/navigation
+- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** description, id, isTopLevelItem, kind, label, opensInNewTab, rel, title, type, url
## Page Break
Separate your content into a multi-page experience. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/nextpage))
-- **Name:** core/nextpage
-- **Category:** design
-- **Parent:** core/post-content
-- **Supports:** interactivity (clientNavigation), ~~className~~, ~~customClassName~~, ~~html~~
+- **Name:** core/nextpage
+- **Category:** design
+- **Parent:** core/post-content
+- **Supports:** interactivity (clientNavigation), ~~className~~, ~~customClassName~~, ~~html~~
## Page List
Display a list of all pages. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/page-list))
-- **Name:** core/page-list
-- **Category:** widgets
-- **Allowed Blocks:** core/page-list-item
-- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** isNested, parentPageID
+- **Name:** core/page-list
+- **Category:** widgets
+- **Allowed Blocks:** core/page-list-item
+- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** isNested, parentPageID
## Page List Item
Displays a page inside a list of all pages. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/page-list-item))
-- **Name:** core/page-list-item
-- **Category:** widgets
-- **Parent:** core/page-list
-- **Supports:** interactivity (clientNavigation), ~~html~~, ~~inserter~~, ~~lock~~, ~~reusable~~
-- **Attributes:** hasChildren, id, label, link, title
+- **Name:** core/page-list-item
+- **Category:** widgets
+- **Parent:** core/page-list
+- **Supports:** interactivity (clientNavigation), ~~html~~, ~~inserter~~, ~~lock~~, ~~reusable~~
+- **Attributes:** hasChildren, id, label, link, title
## Paragraph
Start with the basic building block of all narrative. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/paragraph))
-- **Name:** core/paragraph
-- **Category:** text
-- **Supports:** __unstablePasteTextInline, anchor, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), splitting, typography (fontSize, lineHeight), ~~className~~
-- **Attributes:** align, content, direction, dropCap, placeholder
+- **Name:** core/paragraph
+- **Category:** text
+- **Supports:** \_\_unstablePasteTextInline, anchor, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), splitting, typography (fontSize, lineHeight), ~~className~~
+- **Attributes:** align, content, direction, dropCap, placeholder
## Pattern Placeholder
Show a block pattern. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/pattern))
-- **Name:** core/pattern
-- **Category:** theme
-- **Supports:** interactivity (clientNavigation), ~~html~~, ~~inserter~~, ~~renaming~~
-- **Attributes:** slug
+- **Name:** core/pattern
+- **Category:** theme
+- **Supports:** interactivity (clientNavigation), ~~html~~, ~~inserter~~, ~~renaming~~
+- **Attributes:** slug
## Author
Display post author details such as name, avatar, and bio. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-author))
-- **Name:** core/post-author
-- **Category:** theme
-- **Supports:** color (background, gradients, link, text), filter (duotone), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** avatarSize, byline, isLink, linkTarget, showAvatar, showBio, textAlign
+- **Name:** core/post-author
+- **Category:** theme
+- **Supports:** color (background, gradients, link, text), filter (duotone), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** avatarSize, byline, isLink, linkTarget, showAvatar, showBio, textAlign
## Author Biography
The author biography. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-author-biography))
-- **Name:** core/post-author-biography
-- **Category:** theme
-- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
-- **Attributes:** textAlign
+- **Name:** core/post-author-biography
+- **Category:** theme
+- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
+- **Attributes:** textAlign
## Author Name
The author name. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-author-name))
-- **Name:** core/post-author-name
-- **Category:** theme
-- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** isLink, linkTarget, textAlign
+- **Name:** core/post-author-name
+- **Category:** theme
+- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** isLink, linkTarget, textAlign
## Comment (deprecated)
This block is deprecated. Please use the Comments block instead. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-comment))
-- **Name:** core/post-comment
-- **Experimental:** fse
-- **Category:** theme
-- **Allowed Blocks:** core/avatar, core/comment-author-name, core/comment-content, core/comment-date, core/comment-edit-link, core/comment-reply-link
-- **Supports:** interactivity (clientNavigation), ~~html~~, ~~inserter~~
-- **Attributes:** commentId
+- **Name:** core/post-comment
+- **Experimental:** fse
+- **Category:** theme
+- **Allowed Blocks:** core/avatar, core/comment-author-name, core/comment-content, core/comment-date, core/comment-edit-link, core/comment-reply-link
+- **Supports:** interactivity (clientNavigation), ~~html~~, ~~inserter~~
+- **Attributes:** commentId
## Comments Count
Display a post's comments count. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-comments-count))
-- **Name:** core/post-comments-count
-- **Category:** theme
-- **Supports:** color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** textAlign
+- **Name:** core/post-comments-count
+- **Category:** theme
+- **Supports:** color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** textAlign
## Comments Form
Display a post's comments form. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-comments-form))
-- **Name:** core/post-comments-form
-- **Category:** theme
-- **Supports:** color (background, gradients, heading, link, text), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** textAlign
+- **Name:** core/post-comments-form
+- **Category:** theme
+- **Supports:** color (background, gradients, heading, link, text), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** textAlign
## Comments Link
Displays the link to the current post comments. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-comments-link))
-- **Name:** core/post-comments-link
-- **Category:** theme
-- **Supports:** color (background, link, ~~text~~), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** textAlign
+- **Name:** core/post-comments-link
+- **Category:** theme
+- **Supports:** color (background, link, ~~text~~), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** textAlign
## Content
Displays the contents of a post or page. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-content))
-- **Name:** core/post-content
-- **Category:** theme
-- **Supports:** align (full, wide), background (backgroundImage, backgroundSize), color (background, gradients, heading, link, text), dimensions (minHeight), layout, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** tagName
+- **Name:** core/post-content
+- **Category:** theme
+- **Supports:** align (full, wide), background (backgroundImage, backgroundSize), color (background, gradients, heading, link, text), dimensions (minHeight), layout, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** tagName
## Date
Display the publish date for an entry such as a post or page. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-date))
-- **Name:** core/post-date
-- **Category:** theme
-- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** datetime, format, isLink, textAlign
+- **Name:** core/post-date
+- **Category:** theme
+- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** datetime, format, isLink, textAlign
## Excerpt
Display the excerpt. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-excerpt))
-- **Name:** core/post-excerpt
-- **Category:** theme
-- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** excerptLength, moreText, showMoreOnNewLine, textAlign
+- **Name:** core/post-excerpt
+- **Category:** theme
+- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** excerptLength, moreText, showMoreOnNewLine, textAlign
## Featured Image
Display a post's featured image. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-featured-image))
-- **Name:** core/post-featured-image
-- **Category:** theme
-- **Supports:** align (center, full, left, right, wide), color (~~background~~, ~~text~~), filter (duotone), interactivity (clientNavigation), shadow (), spacing (margin, padding), ~~html~~
-- **Attributes:** aspectRatio, customGradient, customOverlayColor, dimRatio, gradient, height, isLink, linkTarget, overlayColor, rel, scale, sizeSlug, useFirstImageFromPost, width
+- **Name:** core/post-featured-image
+- **Category:** theme
+- **Supports:** align (center, full, left, right, wide), color (~~background~~, ~~text~~), filter (duotone), interactivity (clientNavigation), shadow (), spacing (margin, padding), ~~html~~
+- **Attributes:** aspectRatio, customGradient, customOverlayColor, dimRatio, gradient, height, isLink, linkTarget, overlayColor, rel, scale, sizeSlug, useFirstImageFromPost, width
## Post Navigation Link
Displays the next or previous post link that is adjacent to the current post. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-navigation-link))
-- **Name:** core/post-navigation-link
-- **Category:** theme
-- **Supports:** color (background, link, text), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** arrow, label, linkLabel, showTitle, taxonomy, textAlign, type
+- **Name:** core/post-navigation-link
+- **Category:** theme
+- **Supports:** color (background, link, text), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** arrow, label, linkLabel, showTitle, taxonomy, textAlign, type
## Post Template
Contains the block elements used to render a post, like the title, date, featured image, content or excerpt, and more. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-template))
-- **Name:** core/post-template
-- **Category:** theme
-- **Ancestor:** core/query
-- **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), layout, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Name:** core/post-template
+- **Category:** theme
+- **Ancestor:** core/query
+- **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), layout, spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
## Post Terms
Post terms. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-terms))
-- **Name:** core/post-terms
-- **Category:** theme
-- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** prefix, separator, suffix, term, textAlign
+- **Name:** core/post-terms
+- **Category:** theme
+- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** prefix, separator, suffix, term, textAlign
## Time to Read
Show minutes required to finish reading the post. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-time-to-read))
-- **Name:** core/post-time-to-read
-- **Experimental:** true
-- **Category:** theme
-- **Supports:** color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** textAlign
+- **Name:** core/post-time-to-read
+- **Experimental:** true
+- **Category:** theme
+- **Supports:** color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** textAlign
## Title
Displays the title of a post, page, or any other content-type. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-title))
-- **Name:** core/post-title
-- **Category:** theme
-- **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** isLink, level, levelOptions, linkTarget, rel, textAlign
+- **Name:** core/post-title
+- **Category:** theme
+- **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** isLink, level, levelOptions, linkTarget, rel, textAlign
## Preformatted
Add text that respects your spacing and tabs, and also allows styling. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/preformatted))
-- **Name:** core/preformatted
-- **Category:** text
-- **Supports:** anchor, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
-- **Attributes:** content
+- **Name:** core/preformatted
+- **Category:** text
+- **Supports:** anchor, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
+- **Attributes:** content
## Pullquote
Give special visual emphasis to a quote from your text. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/pullquote))
-- **Name:** core/pullquote
-- **Category:** text
-- **Supports:** align (full, left, right, wide), anchor, background (backgroundImage, backgroundSize), color (background, gradients, link, text), dimensions (minHeight), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
-- **Attributes:** citation, textAlign, value
+- **Name:** core/pullquote
+- **Category:** text
+- **Supports:** align (full, left, right, wide), anchor, background (backgroundImage, backgroundSize), color (background, gradients, link, text), dimensions (minHeight), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
+- **Attributes:** citation, textAlign, value
## Query Loop
An advanced block that allows displaying post types based on different query parameters and visual configurations. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/query))
-- **Name:** core/query
-- **Category:** theme
-- **Supports:** align (full, wide), interactivity, layout, ~~html~~
-- **Attributes:** enhancedPagination, namespace, query, queryId, tagName
+- **Name:** core/query
+- **Category:** theme
+- **Supports:** align (full, wide), interactivity, layout, ~~html~~
+- **Attributes:** enhancedPagination, namespace, query, queryId, tagName
## No Results
Contains the block elements used to render content when no query results are found. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/query-no-results))
-- **Name:** core/query-no-results
-- **Category:** theme
-- **Ancestor:** core/query
-- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Name:** core/query-no-results
+- **Category:** theme
+- **Ancestor:** core/query
+- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
## Pagination
Displays a paginated navigation to next/previous set of posts, when applicable. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/query-pagination))
-- **Name:** core/query-pagination
-- **Category:** theme
-- **Ancestor:** core/query
-- **Allowed Blocks:** core/query-pagination-previous, core/query-pagination-numbers, core/query-pagination-next
-- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), layout (default, ~~allowInheriting~~, ~~allowSwitching~~), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** paginationArrow, showLabel
+- **Name:** core/query-pagination
+- **Category:** theme
+- **Ancestor:** core/query
+- **Allowed Blocks:** core/query-pagination-previous, core/query-pagination-numbers, core/query-pagination-next
+- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), layout (default, ~~allowInheriting~~, ~~allowSwitching~~), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** paginationArrow, showLabel
## Next Page
Displays the next posts page link. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/query-pagination-next))
-- **Name:** core/query-pagination-next
-- **Category:** theme
-- **Parent:** core/query-pagination
-- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** label
+- **Name:** core/query-pagination-next
+- **Category:** theme
+- **Parent:** core/query-pagination
+- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** label
## Page Numbers
Displays a list of page numbers for pagination. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/query-pagination-numbers))
-- **Name:** core/query-pagination-numbers
-- **Category:** theme
-- **Parent:** core/query-pagination
-- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** midSize
+- **Name:** core/query-pagination-numbers
+- **Category:** theme
+- **Parent:** core/query-pagination
+- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** midSize
## Previous Page
Displays the previous posts page link. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/query-pagination-previous))
-- **Name:** core/query-pagination-previous
-- **Category:** theme
-- **Parent:** core/query-pagination
-- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
-- **Attributes:** label
+- **Name:** core/query-pagination-previous
+- **Category:** theme
+- **Parent:** core/query-pagination
+- **Supports:** color (background, gradients, ~~text~~), interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
+- **Attributes:** label
## Query Title
Display the query title. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/query-title))
-- **Name:** core/query-title
-- **Category:** theme
-- **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** level, levelOptions, showPrefix, showSearchTerm, textAlign, type
+- **Name:** core/query-title
+- **Category:** theme
+- **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** level, levelOptions, showPrefix, showSearchTerm, textAlign, type
## Query Total
Display the total number of results in a query. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/query-total))
-- **Name:** core/query-total
-- **Category:** theme
-- **Ancestor:** core/query
-- **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** displayType
+- **Name:** core/query-total
+- **Category:** theme
+- **Ancestor:** core/query
+- **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** displayType
## Quote
Give quoted text visual emphasis. "In quoting others, we cite ourselves." — Julio Cortázar ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/quote))
-- **Name:** core/quote
-- **Category:** text
-- **Supports:** align (full, left, right, wide), anchor, background (backgroundImage, backgroundSize), color (background, gradients, heading, link, text), dimensions (minHeight), interactivity (clientNavigation), layout (~~allowEditing~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** citation, textAlign, value
+- **Name:** core/quote
+- **Category:** text
+- **Supports:** align (full, left, right, wide), anchor, background (backgroundImage, backgroundSize), color (background, gradients, heading, link, text), dimensions (minHeight), interactivity (clientNavigation), layout (~~allowEditing~~), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** citation, textAlign, value
## Read More
Displays the link of a post, page, or any other content-type. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/read-more))
-- **Name:** core/read-more
-- **Category:** theme
-- **Supports:** color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** content, linkTarget
+- **Name:** core/read-more
+- **Category:** theme
+- **Supports:** color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** content, linkTarget
## RSS
Display entries from any RSS or Atom feed. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/rss))
-- **Name:** core/rss
-- **Category:** widgets
-- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), ~~html~~
-- **Attributes:** blockLayout, columns, displayAuthor, displayDate, displayExcerpt, excerptLength, feedURL, itemsToShow, openInNewTab, rel
+- **Name:** core/rss
+- **Category:** widgets
+- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), ~~html~~
+- **Attributes:** blockLayout, columns, displayAuthor, displayDate, displayExcerpt, excerptLength, feedURL, itemsToShow, openInNewTab, rel
## Search
Help visitors find your content. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/search))
-- **Name:** core/search
-- **Category:** widgets
-- **Supports:** align (center, left, right), color (background, gradients, text), interactivity, spacing (margin), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** buttonPosition, buttonText, buttonUseIcon, isSearchFieldHidden, label, placeholder, query, showLabel, width, widthUnit
+- **Name:** core/search
+- **Category:** widgets
+- **Supports:** align (center, left, right), color (background, gradients, text), interactivity, spacing (margin), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** buttonPosition, buttonText, buttonUseIcon, isSearchFieldHidden, label, placeholder, query, showLabel, width, widthUnit
## Separator
Create a break between ideas or sections with a horizontal separator. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/separator))
-- **Name:** core/separator
-- **Category:** design
-- **Supports:** align (center, full, wide), anchor, color (background, gradients, ~~enableContrastChecker~~, ~~text~~), interactivity (clientNavigation), spacing (margin)
-- **Attributes:** opacity, tagName
+- **Name:** core/separator
+- **Category:** design
+- **Supports:** align (center, full, wide), anchor, color (background, gradients, ~~enableContrastChecker~~, ~~text~~), interactivity (clientNavigation), spacing (margin)
+- **Attributes:** opacity, tagName
## Shortcode
Insert additional custom elements with a WordPress shortcode. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/shortcode))
-- **Name:** core/shortcode
-- **Category:** widgets
-- **Supports:** ~~className~~, ~~customClassName~~, ~~html~~
-- **Attributes:** text
+- **Name:** core/shortcode
+- **Category:** widgets
+- **Supports:** ~~className~~, ~~customClassName~~, ~~html~~
+- **Attributes:** text
## Site Logo
Display an image to represent this site. Update this block and the changes apply everywhere. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/site-logo))
-- **Name:** core/site-logo
-- **Category:** theme
-- **Supports:** align, color (~~background~~, ~~text~~), filter (duotone), interactivity (clientNavigation), spacing (margin, padding), ~~alignWide~~, ~~html~~
-- **Attributes:** isLink, linkTarget, shouldSyncIcon, width
+- **Name:** core/site-logo
+- **Category:** theme
+- **Supports:** align, color (~~background~~, ~~text~~), filter (duotone), interactivity (clientNavigation), spacing (margin, padding), ~~alignWide~~, ~~html~~
+- **Attributes:** isLink, linkTarget, shouldSyncIcon, width
## Site Tagline
Describe in a few words what this site is about. This is important for search results, sharing on social media, and gives overall clarity to visitors. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/site-tagline))
-- **Name:** core/site-tagline
-- **Category:** theme
-- **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** level, levelOptions, textAlign
+- **Name:** core/site-tagline
+- **Category:** theme
+- **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** level, levelOptions, textAlign
## Site Title
Displays the name of this site. Update the block, and the changes apply everywhere it’s used. This will also appear in the browser title bar and in search results. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/site-title))
-- **Name:** core/site-title
-- **Category:** theme
-- **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** isLink, level, levelOptions, linkTarget, textAlign
+- **Name:** core/site-title
+- **Category:** theme
+- **Supports:** align (full, wide), color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** isLink, level, levelOptions, linkTarget, textAlign
## Social Icon
Display an icon linking to a social profile or site. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/social-link))
-- **Name:** core/social-link
-- **Category:** widgets
-- **Parent:** core/social-links
-- **Supports:** interactivity (clientNavigation), ~~html~~, ~~reusable~~
-- **Attributes:** label, rel, service, url
+- **Name:** core/social-link
+- **Category:** widgets
+- **Parent:** core/social-links
+- **Supports:** interactivity (clientNavigation), ~~html~~, ~~reusable~~
+- **Attributes:** label, rel, service, url
## Social Icons
Display icons linking to your social profiles or sites. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/social-links))
-- **Name:** core/social-links
-- **Category:** widgets
-- **Allowed Blocks:** core/social-link
-- **Supports:** align (center, left, right), anchor, color (background, gradients, ~~enableContrastChecker~~, ~~text~~), interactivity (clientNavigation), layout (default, ~~allowInheriting~~, ~~allowSwitching~~, ~~allowVerticalAlignment~~), spacing (blockGap, margin, padding, units), ~~html~~
-- **Attributes:** customIconBackgroundColor, customIconColor, iconBackgroundColor, iconBackgroundColorValue, iconColor, iconColorValue, openInNewTab, showLabels, size
+- **Name:** core/social-links
+- **Category:** widgets
+- **Allowed Blocks:** core/social-link
+- **Supports:** align (center, left, right), anchor, color (background, gradients, ~~enableContrastChecker~~, ~~text~~), interactivity (clientNavigation), layout (default, ~~allowInheriting~~, ~~allowSwitching~~, ~~allowVerticalAlignment~~), spacing (blockGap, margin, padding, units), ~~html~~
+- **Attributes:** customIconBackgroundColor, customIconColor, iconBackgroundColor, iconBackgroundColorValue, iconColor, iconColorValue, openInNewTab, showLabels, size
## Spacer
Add white space between blocks and customize its height. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/spacer))
-- **Name:** core/spacer
-- **Category:** design
-- **Supports:** anchor, interactivity (clientNavigation), spacing (margin)
-- **Attributes:** height, width
+- **Name:** core/spacer
+- **Category:** design
+- **Supports:** anchor, interactivity (clientNavigation), spacing (margin)
+- **Attributes:** height, width
## Table
Create structured content in rows and columns to display information. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/table))
-- **Name:** core/table
-- **Category:** text
-- **Supports:** align, anchor, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
-- **Attributes:** body, caption, foot, hasFixedLayout, head
+- **Name:** core/table
+- **Category:** text
+- **Supports:** align, anchor, color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
+- **Attributes:** body, caption, foot, hasFixedLayout, head
## Table of Contents
Summarize your post with a list of headings. Add HTML anchors to Heading blocks to link them here. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/table-of-contents))
-- **Name:** core/table-of-contents
-- **Experimental:** true
-- **Category:** design
-- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** headings, maxLevel, onlyIncludeCurrentPage
+- **Name:** core/table-of-contents
+- **Experimental:** true
+- **Category:** design
+- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** headings, maxLevel, onlyIncludeCurrentPage
## Tag Cloud
A cloud of popular keywords, each sized by how often it appears. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/tag-cloud))
-- **Name:** core/tag-cloud
-- **Category:** widgets
-- **Supports:** align, interactivity (clientNavigation), spacing (margin, padding), typography (lineHeight), ~~html~~
-- **Attributes:** largestFontSize, numberOfTags, showTagCounts, smallestFontSize, taxonomy
+- **Name:** core/tag-cloud
+- **Category:** widgets
+- **Supports:** align, interactivity (clientNavigation), spacing (margin, padding), typography (lineHeight), ~~html~~
+- **Attributes:** largestFontSize, numberOfTags, showTagCounts, smallestFontSize, taxonomy
## Template Part
Edit the different global regions of your site, like the header, footer, sidebar, or create your own. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/template-part))
-- **Name:** core/template-part
-- **Category:** theme
-- **Supports:** align, interactivity (clientNavigation), ~~html~~, ~~renaming~~, ~~reusable~~
-- **Attributes:** area, slug, tagName, theme
+- **Name:** core/template-part
+- **Category:** theme
+- **Supports:** align, interactivity (clientNavigation), ~~html~~, ~~renaming~~, ~~reusable~~
+- **Attributes:** area, slug, tagName, theme
## Term Description
Display the description of categories, tags and custom taxonomies when viewing an archive. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/term-description))
-- **Name:** core/term-description
-- **Category:** theme
-- **Supports:** align (full, wide), color (background, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** textAlign
+- **Name:** core/term-description
+- **Category:** theme
+- **Supports:** align (full, wide), color (background, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Attributes:** textAlign
## Text Columns (deprecated)
This block is deprecated. Please use the Columns block instead. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/text-columns))
-- **Name:** core/text-columns
-- **Category:** design
-- **Supports:** interactivity (clientNavigation), ~~inserter~~
-- **Attributes:** columns, content, width
+- **Name:** core/text-columns
+- **Category:** design
+- **Supports:** interactivity (clientNavigation), ~~inserter~~
+- **Attributes:** columns, content, width
## Verse
Insert poetry. Use special spacing formats. Or quote song lyrics. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/verse))
-- **Name:** core/verse
-- **Category:** text
-- **Supports:** anchor, background (backgroundImage, backgroundSize), color (background, gradients, link, text), dimensions (minHeight), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
-- **Attributes:** content, textAlign
+- **Name:** core/verse
+- **Category:** text
+- **Supports:** anchor, background (backgroundImage, backgroundSize), color (background, gradients, link, text), dimensions (minHeight), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight)
+- **Attributes:** content, textAlign
## Video
Embed a video from your media library or upload a new one. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/video))
-- **Name:** core/video
-- **Category:** media
-- **Supports:** align, anchor, interactivity (clientNavigation), spacing (margin, padding)
-- **Attributes:** autoplay, blob, caption, controls, id, loop, muted, playsInline, poster, preload, src, tracks
+- **Name:** core/video
+- **Category:** media
+- **Supports:** align, anchor, interactivity (clientNavigation), spacing (margin, padding)
+- **Attributes:** autoplay, blob, caption, controls, id, loop, muted, playsInline, poster, preload, src, tracks
diff --git a/docs/gutenberg/reference-guides/data/README.md b/docs/gutenberg/reference-guides/data/README.md
new file mode 100644
index 0000000..974110d
--- /dev/null
+++ b/docs/gutenberg/reference-guides/data/README.md
@@ -0,0 +1,20 @@
+# Data Module Reference
+
+- [**core**: WordPress Core Data](/docs/reference-guides/data/data-core.md)
+- [**core/annotations**: Annotations](/docs/reference-guides/data/data-core-annotations.md)
+- [**core/block-directory**: Block directory](/docs/reference-guides/data/data-core-block-directory.md)
+- [**core/block-editor**: The Block Editor’s Data](/docs/reference-guides/data/data-core-block-editor.md)
+- [**core/blocks**: Block Types Data](/docs/reference-guides/data/data-core-blocks.md)
+- [**core/commands**: Command Palette](/docs/reference-guides/data/data-core-commands.md)
+- [**core/customize-widgets**: Customize Widgets](/docs/reference-guides/data/data-core-customize-widgets.md)
+- [**core/edit-post**: The Editor’s UI Data](/docs/reference-guides/data/data-core-edit-post.md)
+- [**core/edit-site**: Edit Site](/docs/reference-guides/data/data-core-edit-site.md)
+- [**core/edit-widgets**: Edit Widgets](/docs/reference-guides/data/data-core-edit-widgets.md)
+- [**core/editor**: The Post Editor’s Data](/docs/reference-guides/data/data-core-editor.md)
+- [**core/keyboard-shortcuts**: The Keyboard Shortcuts Data](/docs/reference-guides/data/data-core-keyboard-shortcuts.md)
+- [**core/notices**: Notices Data](/docs/reference-guides/data/data-core-notices.md)
+- [**core/nux**: The NUX (New User Experience) Data](/docs/reference-guides/data/data-core-nux.md)
+- [**core/preferences**: Preferences](/docs/reference-guides/data/data-core-preferences.md)
+- [**core/reusable-blocks**: Reusable blocks](/docs/reference-guides/data/data-core-reusable-blocks.md)
+- [**core/rich-text**: Rich Text](/docs/reference-guides/data/data-core-rich-text.md)
+- [**core/viewport**: The Viewport Data](/docs/reference-guides/data/data-core-viewport.md)
diff --git a/gutenberg/reference-guides/data/data-core-annotations.md b/docs/gutenberg/reference-guides/data/data-core-annotations.md
similarity index 100%
rename from gutenberg/reference-guides/data/data-core-annotations.md
rename to docs/gutenberg/reference-guides/data/data-core-annotations.md
diff --git a/gutenberg/reference-guides/data/data-core-block-directory.md b/docs/gutenberg/reference-guides/data/data-core-block-directory.md
similarity index 57%
rename from gutenberg/reference-guides/data/data-core-block-directory.md
rename to docs/gutenberg/reference-guides/data/data-core-block-directory.md
index c1fe965..a596cfb 100644
--- a/gutenberg/reference-guides/data/data-core-block-directory.md
+++ b/docs/gutenberg/reference-guides/data/data-core-block-directory.md
@@ -12,12 +12,12 @@ Returns the available uninstalled blocks.
_Parameters_
-- _state_ `Object`: Global application state.
-- _filterValue_ `string`: Search string.
+- _state_ `Object`: Global application state.
+- _filterValue_ `string`: Search string.
_Returns_
-- `Array`: Downloadable blocks.
+- `Array`: Downloadable blocks.
### getErrorNoticeForBlock
@@ -25,12 +25,12 @@ Returns the error notice for a given block.
_Parameters_
-- _state_ `Object`: Global application state.
-- _blockId_ `string`: The ID of the block plugin. eg: my-block
+- _state_ `Object`: Global application state.
+- _blockId_ `string`: The ID of the block plugin. eg: my-block
_Returns_
-- `string|boolean`: The error text, or false if no error.
+- `string|boolean`: The error text, or false if no error.
### getErrorNotices
@@ -38,11 +38,11 @@ Returns all block error notices.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: Object with error notices.
+- `Object`: Object with error notices.
### getInstalledBlockTypes
@@ -50,11 +50,11 @@ Returns the block types that have been installed on the server in this session.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Array`: Block type items
+- `Array`: Block type items
### getNewBlockTypes
@@ -62,11 +62,11 @@ Returns block types that have been installed on the server and used in the curre
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Array`: Block type items.
+- `Array`: Block type items.
### getUnusedBlockTypes
@@ -74,11 +74,11 @@ Returns the block types that have been installed on the server but are not used
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Array`: Block type items.
+- `Array`: Block type items.
### isInstalling
@@ -86,12 +86,12 @@ Returns true if a block plugin install is in progress.
_Parameters_
-- _state_ `Object`: Global application state.
-- _blockId_ `string`: Id of the block.
+- _state_ `Object`: Global application state.
+- _blockId_ `string`: Id of the block.
_Returns_
-- `boolean`: Whether this block is currently being installed.
+- `boolean`: Whether this block is currently being installed.
### isRequestingDownloadableBlocks
@@ -99,12 +99,12 @@ Returns true if application is requesting for downloadable blocks.
_Parameters_
-- _state_ `Object`: Global application state.
-- _filterValue_ `string`: Search string.
+- _state_ `Object`: Global application state.
+- _filterValue_ `string`: Search string.
_Returns_
-- `boolean`: Whether a request is in progress for the blocks list.
+- `boolean`: Whether a request is in progress for the blocks list.
@@ -118,11 +118,11 @@ Returns an action object used to add a block type to the "newly installed" track
_Parameters_
-- _item_ `Object`: The block item with the block id and name.
+- _item_ `Object`: The block item with the block id and name.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### clearErrorNotice
@@ -130,11 +130,11 @@ Sets the error notice to empty for specific block.
_Parameters_
-- _blockId_ `string`: The ID of the block plugin. eg: my-block
+- _blockId_ `string`: The ID of the block plugin. eg: my-block
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### fetchDownloadableBlocks
@@ -142,11 +142,11 @@ Returns an action object used in signalling that the downloadable blocks have be
_Parameters_
-- _filterValue_ `string`: Search string.
+- _filterValue_ `string`: Search string.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### installBlockType
@@ -154,11 +154,11 @@ Action triggered to install a block plugin.
_Parameters_
-- _block_ `Object`: The block item returned by search.
+- _block_ `Object`: The block item returned by search.
_Returns_
-- `boolean`: Whether the block was successfully installed & loaded.
+- `boolean`: Whether the block was successfully installed & loaded.
### receiveDownloadableBlocks
@@ -166,12 +166,12 @@ Returns an action object used in signalling that the downloadable blocks have be
_Parameters_
-- _downloadableBlocks_ `Array`: Downloadable blocks.
-- _filterValue_ `string`: Search string.
+- _downloadableBlocks_ `Array`: Downloadable blocks.
+- _filterValue_ `string`: Search string.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### removeInstalledBlockType
@@ -179,11 +179,11 @@ Returns an action object used to remove a block type from the "newly installed"
_Parameters_
-- _item_ `string`: The block item with the block id and name.
+- _item_ `string`: The block item with the block id and name.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setErrorNotice
@@ -191,13 +191,13 @@ Sets an error notice to be displayed to the user for a given block.
_Parameters_
-- _blockId_ `string`: The ID of the block plugin. eg: my-block
-- _message_ `string`: The message shown in the notice.
-- _isFatal_ `boolean`: Whether the user can recover from the error.
+- _blockId_ `string`: The ID of the block plugin. eg: my-block
+- _message_ `string`: The message shown in the notice.
+- _isFatal_ `boolean`: Whether the user can recover from the error.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setIsInstalling
@@ -205,12 +205,12 @@ Returns an action object used to indicate install in progress.
_Parameters_
-- _blockId_ `string`:
-- _isInstalling_ `boolean`:
+- _blockId_ `string`:
+- _isInstalling_ `boolean`:
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### uninstallBlockType
@@ -218,6 +218,6 @@ Action triggered to uninstall a block plugin.
_Parameters_
-- _block_ `Object`: The blockType object.
+- _block_ `Object`: The blockType object.
diff --git a/docs/gutenberg/reference-guides/data/data-core-block-editor.md b/docs/gutenberg/reference-guides/data/data-core-block-editor.md
new file mode 100644
index 0000000..bc5974f
--- /dev/null
+++ b/docs/gutenberg/reference-guides/data/data-core-block-editor.md
@@ -0,0 +1,1912 @@
+# The Block Editor’s Data
+
+Namespace: `core/block-editor`.
+
+## Selectors
+
+
+
+### areInnerBlocksControlled
+
+Checks if a given block has controlled inner blocks.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _clientId_ `string`: The block to check.
+
+_Returns_
+
+- `boolean`: True if the block has controlled inner blocks.
+
+### canEditBlock
+
+Determines if the given block is allowed to be edited.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: The block client Id.
+
+_Returns_
+
+- `boolean`: Whether the given block is allowed to be edited.
+
+### canInsertBlocks
+
+Determines if the given blocks are allowed to be inserted into the block list.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientIds_ `string[]`: The block client IDs to be inserted.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `boolean`: Whether the given blocks are allowed to be inserted.
+
+### canInsertBlockType
+
+Determines if the given block type is allowed to be inserted into the block list.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _blockName_ `string`: The name of the block type, e.g.' core/paragraph'.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `boolean`: Whether the given block type is allowed to be inserted.
+
+### canLockBlockType
+
+Determines if the given block type can be locked/unlocked by a user.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _nameOrType_ `(string|Object)`: Block name or type object.
+
+_Returns_
+
+- `boolean`: Whether a given block type can be locked/unlocked.
+
+### canMoveBlock
+
+Determines if the given block is allowed to be moved.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: The block client Id.
+
+_Returns_
+
+- `boolean`: Whether the given block is allowed to be moved.
+
+### canMoveBlocks
+
+Determines if the given blocks are allowed to be moved.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientIds_ `string`: The block client IDs to be moved.
+
+_Returns_
+
+- `boolean`: Whether the given blocks are allowed to be moved.
+
+### canRemoveBlock
+
+Determines if the given block is allowed to be deleted.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: The block client Id.
+
+_Returns_
+
+- `boolean`: Whether the given block is allowed to be removed.
+
+### canRemoveBlocks
+
+Determines if the given blocks are allowed to be removed.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientIds_ `string`: The block client IDs to be removed.
+
+_Returns_
+
+- `boolean`: Whether the given blocks are allowed to be removed.
+
+### didAutomaticChange
+
+Returns true if the last change was an automatic change, false otherwise.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `boolean`: Whether the last change was automatic.
+
+### getAdjacentBlockClientId
+
+Returns the client ID of the block adjacent one at the given reference startClientId and modifier directionality. Defaults start startClientId to the selected block, and direction as next block. Returns null if there is no adjacent block.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _startClientId_ `?string`: Optional client ID of block from which to search.
+- _modifier_ `?number`: Directionality multiplier (1 next, -1 previous).
+
+_Returns_
+
+- `?string`: Return the client ID of the block, or null if none exists.
+
+### getAllowedBlocks
+
+Returns the list of allowed inserter blocks for inner blocks children.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `Array?`: The list of allowed block types.
+
+### getBlock
+
+Returns a block given its client ID. This is a parsed copy of the block, containing its `blockName`, `clientId`, and current `attributes` state. This is not the block's registration settings, which must be retrieved from the blocks module registration store.
+
+getBlock recurses through its inner blocks until all its children blocks have been retrieved. Note that getBlock will not return the child inner blocks of an inner block controller. This is because an inner block controller syncs itself with its own entity, and should therefore not be included with the blocks of a different entity. For example, say you call `getBlocks( TP )` to get the blocks of a template part. If another template part is a child of TP, then the nested template part's child blocks will not be returned. This way, the template block itself is considered part of the parent, but the children are not.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `Object`: Parsed block object.
+
+### getBlockAttributes
+
+Returns a block's attributes given its client ID, or null if no block exists with the client ID.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `?Object`: Block attributes.
+
+### getBlockCount
+
+Returns the number of blocks currently present in the post.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `number`: Number of blocks in the post.
+
+### getBlockEditingMode
+
+Returns the block editing mode for a given block.
+
+The mode can be one of three options:
+
+- `'disabled'`: Prevents editing the block entirely, i.e. it cannot be selected.
+- `'contentOnly'`: Hides all non-content UI, e.g. auxiliary controls in the toolbar, the block movers, block settings.
+- `'default'`: Allows editing the block as normal.
+
+Blocks can set a mode using the `useBlockEditingMode` hook.
+
+The mode is inherited by all of the block's inner blocks, unless they have their own mode.
+
+A template lock can also set a mode. If the template lock is `'contentOnly'`, the block's mode is overridden to `'contentOnly'` if the block has a content role attribute, or `'disabled'` otherwise.
+
+_Related_
+
+- useBlockEditingMode
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _clientId_ `string`: The block client ID, or `''` for the root container.
+
+_Returns_
+
+- `BlockEditingMode`: The block editing mode. One of `'disabled'`, `'contentOnly'`, or `'default'`.
+
+### getBlockHierarchyRootClientId
+
+Given a block client ID, returns the root of the hierarchy from which the block is nested, return the block itself for root level blocks.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block from which to find root client ID.
+
+_Returns_
+
+- `string`: Root client ID
+
+### getBlockIndex
+
+Returns the index at which the block corresponding to the specified client ID occurs within the block order, or `-1` if the block does not exist.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `number`: Index at which block exists in order.
+
+### getBlockInsertionPoint
+
+Returns the location of the insertion cue. Defaults to the last index.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `Object`: Insertion point object with `rootClientId`, `index`.
+
+### getBlockListSettings
+
+Returns the Block List settings of a block, if any exist.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `?string`: Block client ID.
+
+_Returns_
+
+- `?Object`: Block settings of the block if set.
+
+### getBlockMode
+
+Returns the block's editing mode, defaulting to "visual" if not explicitly assigned.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `Object`: Block editing mode.
+
+### getBlockName
+
+Returns a block's name given its client ID, or null if no block exists with the client ID.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `string`: Block name.
+
+### getBlockNamesByClientId
+
+Given an array of block client IDs, returns the corresponding array of block names.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientIds_ `string[]`: Client IDs for which block names are to be returned.
+
+_Returns_
+
+- `string[]`: Block names.
+
+### getBlockOrder
+
+Returns an array containing all block client IDs in the editor in the order they appear. Optionally accepts a root client ID of the block list for which the order should be returned, defaulting to the top-level block order.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `Array`: Ordered client IDs of editor blocks.
+
+### getBlockParents
+
+Given a block client ID, returns the list of all its parents from top to bottom.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block from which to find root client ID.
+- _ascending_ `boolean`: Order results from bottom to top (true) or top to bottom (false).
+
+_Returns_
+
+- `Array`: ClientIDs of the parent blocks.
+
+### getBlockParentsByBlockName
+
+Given a block client ID and a block name, returns the list of all its parents from top to bottom, filtered by the given name(s). For example, if passed 'core/group' as the blockName, it will only return parents which are group blocks. If passed `[ 'core/group', 'core/cover']`, as the blockName, it will return parents which are group blocks and parents which are cover blocks.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block from which to find root client ID.
+- _blockName_ `string|string[]`: Block name(s) to filter.
+- _ascending_ `boolean`: Order results from bottom to top (true) or top to bottom (false).
+
+_Returns_
+
+- `Array`: ClientIDs of the parent blocks.
+
+### getBlockRootClientId
+
+Given a block client ID, returns the root block from which the block is nested, an empty string for top-level blocks, or null if the block does not exist.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block from which to find root client ID.
+
+_Returns_
+
+- `?string`: Root client ID, if exists
+
+### getBlocks
+
+Returns all block objects for the current post being edited as an array in the order they appear in the post. Note that this will exclude child blocks of nested inner block controllers.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `Object[]`: Post blocks.
+
+### getBlocksByClientId
+
+Given an array of block client IDs, returns the corresponding array of block objects.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientIds_ `string[]`: Client IDs for which blocks are to be returned.
+
+_Returns_
+
+- `WPBlock[]`: Block objects.
+
+### getBlocksByName
+
+Returns all blocks that match a blockName. Results include nested blocks.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _blockName_ `string[]`: Block name(s) for which clientIds are to be returned.
+
+_Returns_
+
+- `Array`: Array of clientIds of blocks with name equal to blockName.
+
+### getBlockSelectionEnd
+
+Returns the current block selection end. This value may be null, and it may represent either a singular block selection or multi-selection end. A selection is singular if its start and end match.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `?string`: Client ID of block selection end.
+
+### getBlockSelectionStart
+
+Returns the current block selection start. This value may be null, and it may represent either a singular block selection or multi-selection start. A selection is singular if its start and end match.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `?string`: Client ID of block selection start.
+
+### getBlockTransformItems
+
+Determines the items that appear in the available block transforms list.
+
+Each item object contains what's necessary to display a menu item in the transform list and handle its selection.
+
+The 'frecency' property is a heuristic () that combines block usage frequency and recency.
+
+Items are returned ordered descendingly by their 'frecency'.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _blocks_ `Object|Object[]`: Block object or array objects.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `WPEditorTransformItem[]`: Items that appear in inserter.
+
+_Type Definition_
+
+- _WPEditorTransformItem_ `Object`
+
+_Properties_
+
+- _id_ `string`: Unique identifier for the item.
+- _name_ `string`: The type of block to create.
+- _title_ `string`: Title of the item, as it appears in the inserter.
+- _icon_ `string`: Dashicon for the item, as it appears in the inserter.
+- _isDisabled_ `boolean`: Whether or not the user should be prevented from inserting this item.
+- _frecency_ `number`: Heuristic that combines frequency and recency.
+
+### getClientIdsOfDescendants
+
+Returns an array containing the clientIds of all descendants of the blocks given. Returned ids are ordered first by the order of the ids given, then by the order that they appear in the editor.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _rootIds_ `string|string[]`: Client ID(s) for which descendant blocks are to be returned.
+
+_Returns_
+
+- `Array`: Client IDs of descendants.
+
+### getClientIdsWithDescendants
+
+Returns an array containing the clientIds of the top-level blocks and their descendants of any depth (for nested blocks). Ids are returned in the same order that they appear in the editor.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `Array`: ids of top-level and descendant blocks.
+
+### getDirectInsertBlock
+
+Returns the block to be directly inserted by the block appender.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `WPDirectInsertBlock|undefined`: The block type to be directly inserted.
+
+_Type Definition_
+
+- _WPDirectInsertBlock_ `Object`
+
+_Properties_
+
+- _name_ `string`: The type of block.
+- _attributes_ `?Object`: Attributes to pass to the newly created block.
+- _attributesToCopy_ `?Array`: Attributes to be copied from adjacent blocks when inserted.
+
+### getDraggedBlockClientIds
+
+Returns the client ids of any blocks being directly dragged.
+
+This does not include children of a parent being dragged.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `string[]`: Array of dragged block client ids.
+
+### getFirstMultiSelectedBlockClientId
+
+Returns the client ID of the first block in the multi-selection set, or null if there is no multi-selection.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `?string`: First block client ID in the multi-selection set.
+
+### getGlobalBlockCount
+
+Returns the total number of blocks, or the total number of blocks with a specific name in a post. The number returned includes nested blocks.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _blockName_ `?string`: Optional block name, if specified only blocks of that type will be counted.
+
+_Returns_
+
+- `number`: Number of blocks in the post, or number of blocks with name equal to blockName.
+
+### getHoveredBlockClientId
+
+> **Deprecated**
+
+Returns the currently hovered block.
+
+### getInserterItems
+
+Determines the items that appear in the inserter. Includes both static items (e.g. a regular block type) and dynamic items (e.g. a reusable block).
+
+Each item object contains what's necessary to display a button in the inserter and handle its selection.
+
+The 'frecency' property is a heuristic () that combines block usage frequency and recency.
+
+Items are returned ordered descendingly by their 'utility' and 'frecency'.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `WPEditorInserterItem[]`: Items that appear in inserter.
+
+_Type Definition_
+
+- _WPEditorInserterItem_ `Object`
+
+_Properties_
+
+- _id_ `string`: Unique identifier for the item.
+- _name_ `string`: The type of block to create.
+- _initialAttributes_ `Object`: Attributes to pass to the newly created block.
+- _title_ `string`: Title of the item, as it appears in the inserter.
+- _icon_ `string`: Dashicon for the item, as it appears in the inserter.
+- _category_ `string`: Block category that the item is associated with.
+- _keywords_ `string[]`: Keywords that can be searched to find this item.
+- _isDisabled_ `boolean`: Whether or not the user should be prevented from inserting this item.
+- _frecency_ `number`: Heuristic that combines frequency and recency.
+
+### getLastMultiSelectedBlockClientId
+
+Returns the client ID of the last block in the multi-selection set, or null if there is no multi-selection.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `?string`: Last block client ID in the multi-selection set.
+
+### getLowestCommonAncestorWithSelectedBlock
+
+Given a block client ID, returns the lowest common ancestor with selected client ID.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block from which to find common ancestor client ID.
+
+_Returns_
+
+- `string`: Common ancestor client ID or undefined
+
+### getMultiSelectedBlockClientIds
+
+Returns the current multi-selection set of block client IDs, or an empty array if there is no multi-selection.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `Array`: Multi-selected block client IDs.
+
+### getMultiSelectedBlocks
+
+Returns the current multi-selection set of blocks, or an empty array if there is no multi-selection.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `Array`: Multi-selected block objects.
+
+### getMultiSelectedBlocksEndClientId
+
+Returns the client ID of the block which ends the multi-selection set, or null if there is no multi-selection.
+
+This is not necessarily the last client ID in the selection.
+
+_Related_
+
+- getLastMultiSelectedBlockClientId
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `?string`: Client ID of block ending multi-selection.
+
+### getMultiSelectedBlocksStartClientId
+
+Returns the client ID of the block which begins the multi-selection set, or null if there is no multi-selection.
+
+This is not necessarily the first client ID in the selection.
+
+_Related_
+
+- getFirstMultiSelectedBlockClientId
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `?string`: Client ID of block beginning multi-selection.
+
+### getNextBlockClientId
+
+Returns the next block's client ID from the given reference start ID. Defaults start to the selected block. Returns null if there is no next block.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _startClientId_ `?string`: Optional client ID of block from which to search.
+
+_Returns_
+
+- `?string`: Adjacent block's client ID, or null if none exists.
+
+### getPatternsByBlockTypes
+
+Returns the list of patterns based on their declared `blockTypes` and a block's name. Patterns can use `blockTypes` to integrate in work flows like suggesting appropriate patterns in a Placeholder state(during insertion) or blocks transformations.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _blockNames_ `string|string[]`: Block's name or array of block names to find matching patterns.
+- _rootClientId_ `?string`: Optional target root client ID.
+
+_Returns_
+
+- `Array`: The list of matched block patterns based on declared `blockTypes` and block name.
+
+### getPreviousBlockClientId
+
+Returns the previous block's client ID from the given reference start ID. Defaults start to the selected block. Returns null if there is no previous block.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _startClientId_ `?string`: Optional client ID of block from which to search.
+
+_Returns_
+
+- `?string`: Adjacent block's client ID, or null if none exists.
+
+### getSelectedBlock
+
+Returns the currently selected block, or null if there is no selected block.
+
+_Usage_
+
+```js
+import { select } from '@wordpress/data';
+import { store as blockEditorStore } from '@wordpress/block-editor';
+
+// Set initial active block client ID
+let activeBlockClientId = null;
+
+const getActiveBlockData = () => {
+ const activeBlock = select(blockEditorStore).getSelectedBlock();
+
+ if (activeBlock && activeBlock.clientId !== activeBlockClientId) {
+ activeBlockClientId = activeBlock.clientId;
+
+ // Get active block name and attributes
+ const activeBlockName = activeBlock.name;
+ const activeBlockAttributes = activeBlock.attributes;
+
+ // Log active block name and attributes
+ console.log(activeBlockName, activeBlockAttributes);
+ }
+};
+
+// Subscribe to changes in the editor
+// wp.data.subscribe(() => {
+// getActiveBlockData()
+// })
+
+// Update active block data on click
+// onclick="getActiveBlockData()"
+```
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `?Object`: Selected block.
+
+### getSelectedBlockClientId
+
+Returns the currently selected block client ID, or null if there is no selected block.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `?string`: Selected block client ID.
+
+### getSelectedBlockClientIds
+
+Returns the current selection set of block client IDs (multiselection or single selection).
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `Array`: Multi-selected block client IDs.
+
+### getSelectedBlockCount
+
+Returns the number of blocks currently selected in the post.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `number`: Number of blocks selected in the post.
+
+### getSelectedBlocksInitialCaretPosition
+
+Returns the initial caret position for the selected block. This position is to used to position the caret properly when the selected block changes. If the current block is not a RichText, having initial position set to 0 means "focus block"
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `0|-1|null`: Initial position.
+
+### getSelectionEnd
+
+Returns the current selection end block client ID, attribute key and text offset.
+
+_Parameters_
+
+- _state_ `Object`: Block editor state.
+
+_Returns_
+
+- `WPBlockSelection`: Selection end information.
+
+### getSelectionStart
+
+Returns the current selection start block client ID, attribute key and text offset.
+
+_Parameters_
+
+- _state_ `Object`: Block editor state.
+
+_Returns_
+
+- `WPBlockSelection`: Selection start information.
+
+### getSettings
+
+Returns the editor settings.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `Object`: The editor settings object.
+
+### getTemplate
+
+Returns the defined block template
+
+_Parameters_
+
+- _state_ `boolean`:
+
+_Returns_
+
+- `?Array`: Block Template.
+
+### getTemplateLock
+
+Returns the defined block template lock. Optionally accepts a root block client ID as context, otherwise defaulting to the global context.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _rootClientId_ `?string`: Optional block root client ID.
+
+_Returns_
+
+- `string|false`: Block Template Lock
+
+### hasBlockMovingClientId
+
+> **Deprecated**
+
+Returns whether block moving mode is enabled.
+
+### hasDraggedInnerBlock
+
+Returns true if one of the block's inner blocks is dragged.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+- _deep_ `boolean`: Perform a deep check.
+
+_Returns_
+
+- `boolean`: Whether the block has an inner block dragged
+
+### hasInserterItems
+
+Determines whether there are items to show in the inserter.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _rootClientId_ `?string`: Optional root client ID of block list.
+
+_Returns_
+
+- `boolean`: Items that appear in inserter.
+
+### hasMultiSelection
+
+Returns true if a multi-selection has been made, or false otherwise.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `boolean`: Whether multi-selection has been made.
+
+### hasSelectedBlock
+
+Returns true if there is a single selected block, or false otherwise.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `boolean`: Whether a single block is selected.
+
+### hasSelectedInnerBlock
+
+Returns true if one of the block's inner blocks is selected.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+- _deep_ `boolean`: Perform a deep check.
+
+_Returns_
+
+- `boolean`: Whether the block has an inner block selected
+
+### isAncestorBeingDragged
+
+Returns whether a parent/ancestor of the block is being dragged.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _clientId_ `string`: Client id for block to check.
+
+_Returns_
+
+- `boolean`: Whether the block's ancestor is being dragged.
+
+### isAncestorMultiSelected
+
+Returns true if an ancestor of the block is multi-selected, or false otherwise.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `boolean`: Whether an ancestor of the block is in multi-selection set.
+
+### isBlockBeingDragged
+
+Returns whether the block is being dragged.
+
+Only returns true if the block is being directly dragged, not if the block is a child of a parent being dragged. See `isAncestorBeingDragged` for child blocks.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _clientId_ `string`: Client id for block to check.
+
+_Returns_
+
+- `boolean`: Whether the block is being dragged.
+
+### isBlockHighlighted
+
+Returns true if the current highlighted block matches the block clientId.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _clientId_ `string`: The block to check.
+
+_Returns_
+
+- `boolean`: Whether the block is currently highlighted.
+
+### isBlockInsertionPointVisible
+
+Returns true if the block insertion point is visible.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `?boolean`: Whether the insertion point is visible or not.
+
+### isBlockMultiSelected
+
+Returns true if the client ID occurs within the block multi-selection, or false otherwise.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `boolean`: Whether block is in multi-selection set.
+
+### isBlockSelected
+
+Returns true if the block corresponding to the specified client ID is currently selected and no multi-selection exists, or false otherwise.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `boolean`: Whether block is selected and multi-selection exists.
+
+### isBlockValid
+
+Returns whether a block is valid or not.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `boolean`: Is Valid.
+
+### isBlockVisible
+
+Tells if the block is visible on the canvas or not.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _clientId_ `Object`: Client Id of the block.
+
+_Returns_
+
+- `boolean`: True if the block is visible.
+
+### isBlockWithinSelection
+
+Returns true if the block corresponding to the specified client ID is currently selected but isn't the last of the selected blocks. Here "last" refers to the block sequence in the document, _not_ the sequence of multi-selection, which is why `state.selectionEnd` isn't used.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `boolean`: Whether block is selected and not the last in the selection.
+
+### isCaretWithinFormattedText
+
+> **Deprecated**
+
+Returns true if the caret is within formatted text, or false otherwise.
+
+_Returns_
+
+- `boolean`: Whether the caret is within formatted text.
+
+### isDraggingBlocks
+
+Returns true if the user is dragging blocks, or false otherwise.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `boolean`: Whether user is dragging blocks.
+
+### isFirstMultiSelectedBlock
+
+Returns true if a multi-selection exists, and the block corresponding to the specified client ID is the first block of the multi-selection set, or false otherwise.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `boolean`: Whether block is first in multi-selection.
+
+### isGroupable
+
+Indicates if the provided blocks(by client ids) are groupable. We need to have at least one block, have a grouping block name set and be able to remove these blocks.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _clientIds_ `string[]`: Block client ids. If not passed the selected blocks client ids will be used.
+
+_Returns_
+
+- `boolean`: True if the blocks are groupable.
+
+### isLastBlockChangePersistent
+
+Returns true if the most recent block change is be considered persistent, or false otherwise. A persistent change is one committed by BlockEditorProvider via its `onChange` callback, in addition to `onInput`.
+
+_Parameters_
+
+- _state_ `Object`: Block editor state.
+
+_Returns_
+
+- `boolean`: Whether the most recent block change was persistent.
+
+### isMultiSelecting
+
+Whether in the process of multi-selecting or not. This flag is only true while the multi-selection is being selected (by mouse move), and is false once the multi-selection has been settled.
+
+_Related_
+
+- hasMultiSelection
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `boolean`: True if multi-selecting, false if not.
+
+### isNavigationMode
+
+Returns whether the navigation mode is enabled.
+
+_Parameters_
+
+- _state_ `Object`: Editor state.
+
+_Returns_
+
+- `boolean`: Is navigation mode enabled.
+
+### isSelectionEnabled
+
+Selector that returns if multi-selection is enabled or not.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `boolean`: True if it should be possible to multi-select blocks, false if multi-selection is disabled.
+
+### isTyping
+
+Returns true if the user is typing, or false otherwise.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+
+_Returns_
+
+- `boolean`: Whether user is typing.
+
+### isUngroupable
+
+Indicates if a block is ungroupable. A block is ungroupable if it is a single grouping block with inner blocks. If a block has an `ungroup` transform, it is also ungroupable, without the requirement of being the default grouping block. Additionally a block can only be ungrouped if it has inner blocks and can be removed.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _clientId_ `string`: Client Id of the block. If not passed the selected block's client id will be used.
+
+_Returns_
+
+- `boolean`: True if the block is ungroupable.
+
+### isValidTemplate
+
+Returns whether the blocks matches the template or not.
+
+_Parameters_
+
+- _state_ `boolean`:
+
+_Returns_
+
+- `?boolean`: Whether the template is valid or not.
+
+### wasBlockJustInserted
+
+Tells if the block with the passed clientId was just inserted.
+
+_Parameters_
+
+- _state_ `Object`: Global application state.
+- _clientId_ `Object`: Client Id of the block.
+- _source_ `?string`: Optional insertion source of the block.
+
+_Returns_
+
+- `boolean`: True if the block matches the last block inserted from the specified source.
+
+
+
+## Actions
+
+
+
+### clearSelectedBlock
+
+Action that clears the block selection.
+
+_Returns_
+
+- `Object`: Action object.
+
+### duplicateBlocks
+
+Action that duplicates a list of blocks.
+
+_Parameters_
+
+- _clientIds_ `string[]`:
+- _updateSelection_ `boolean`:
+
+### enterFormattedText
+
+> **Deprecated**
+
+Returns an action object used in signalling that the caret has entered formatted text.
+
+_Returns_
+
+- `Object`: Action object.
+
+### exitFormattedText
+
+> **Deprecated**
+
+Returns an action object used in signalling that the user caret has exited formatted text.
+
+_Returns_
+
+- `Object`: Action object.
+
+### flashBlock
+
+Action that "flashes" the block with a given `clientId` by rhythmically highlighting it.
+
+_Parameters_
+
+- _clientId_ `string`: Target block client ID.
+
+### hideInsertionPoint
+
+Action that hides the insertion point.
+
+### hoverBlock
+
+> **Deprecated**
+
+Returns an action object used in signalling that the block with the specified client ID has been hovered.
+
+### insertAfterBlock
+
+Action that inserts a default block after a given block.
+
+_Parameters_
+
+- _clientId_ `string`:
+
+### insertBeforeBlock
+
+Action that inserts a default block before a given block.
+
+_Parameters_
+
+- _clientId_ `string`:
+
+### insertBlock
+
+Action that inserts a single block, optionally at a specific index respective a root block list.
+
+Only allowed blocks are inserted. The action may fail silently for blocks that are not allowed or if a templateLock is active on the block list.
+
+_Parameters_
+
+- _block_ `Object`: Block object to insert.
+- _index_ `?number`: Index at which block should be inserted.
+- _rootClientId_ `?string`: Optional root client ID of block list on which to insert.
+- _updateSelection_ `?boolean`: If true block selection will be updated. If false, block selection will not change. Defaults to true.
+- _meta_ `?Object`: Optional Meta values to be passed to the action object.
+
+_Returns_
+
+- `Object`: Action object.
+
+### insertBlocks
+
+Action that inserts an array of blocks, optionally at a specific index respective a root block list.
+
+Only allowed blocks are inserted. The action may fail silently for blocks that are not allowed or if a templateLock is active on the block list.
+
+_Parameters_
+
+- _blocks_ `Object[]`: Block objects to insert.
+- _index_ `?number`: Index at which block should be inserted.
+- _rootClientId_ `?string`: Optional root client ID of block list on which to insert.
+- _updateSelection_ `?boolean`: If true block selection will be updated. If false, block selection will not change. Defaults to true.
+- _initialPosition_ `0|-1|null`: Initial focus position. Setting it to null prevent focusing the inserted block.
+- _meta_ `?Object`: Optional Meta values to be passed to the action object.
+
+_Returns_
+
+- `Object`: Action object.
+
+### insertDefaultBlock
+
+Action that adds a new block of the default type to the block list.
+
+_Parameters_
+
+- _attributes_ `?Object`: Optional attributes of the block to assign.
+- _rootClientId_ `?string`: Optional root client ID of block list on which to append.
+- _index_ `?number`: Optional index where to insert the default block.
+
+### mergeBlocks
+
+Action that merges two blocks.
+
+_Parameters_
+
+- _firstBlockClientId_ `string`: Client ID of the first block to merge.
+- _secondBlockClientId_ `string`: Client ID of the second block to merge.
+
+### moveBlocksDown
+
+Undocumented declaration.
+
+### moveBlocksToPosition
+
+Action that moves given blocks to a new position.
+
+_Parameters_
+
+- _clientIds_ `?string`: The client IDs of the blocks.
+- _fromRootClientId_ `?string`: Root client ID source.
+- _toRootClientId_ `?string`: Root client ID destination.
+- _index_ `number`: The index to move the blocks to.
+
+### moveBlocksUp
+
+Undocumented declaration.
+
+### moveBlockToPosition
+
+Action that moves given block to a new position.
+
+_Parameters_
+
+- _clientId_ `?string`: The client ID of the block.
+- _fromRootClientId_ `?string`: Root client ID source.
+- _toRootClientId_ `?string`: Root client ID destination.
+- _index_ `number`: The index to move the block to.
+
+### multiSelect
+
+Action that changes block multi-selection.
+
+_Parameters_
+
+- _start_ `string`: First block of the multi selection.
+- _end_ `string`: Last block of the multiselection.
+- _\_\_experimentalInitialPosition_ `number|null`: Optional initial position. Pass as null to skip focus within editor canvas.
+
+### receiveBlocks
+
+> **Deprecated**
+
+Returns an action object used in signalling that blocks have been received. Unlike resetBlocks, these should be appended to the existing known set, not replacing.
+
+_Parameters_
+
+- _blocks_ `Object[]`: Array of block objects.
+
+_Returns_
+
+- `Object`: Action object.
+
+### registerInserterMediaCategory
+
+Registers a new inserter media category. Once registered, the media category is available in the inserter's media tab.
+
+The following interfaces are used:
+
+_Type Definition_
+
+- _InserterMediaRequest_ `Object`: Interface for inserter media requests.
+
+_Properties_
+
+- _per_page_ `number`: How many items to fetch per page.
+- _search_ `string`: The search term to use for filtering the results.
+
+_Type Definition_
+
+- _InserterMediaItem_ `Object`: Interface for inserter media responses. Any media resource should map their response to this interface, in order to create the core WordPress media blocks (image, video, audio).
+
+_Properties_
+
+- _title_ `string`: The title of the media item.
+- _url_ \`string: The source url of the media item.
+- _previewUrl_ `[string]`: The preview source url of the media item to display in the media list.
+- _id_ `[number]`: The WordPress id of the media item.
+- _sourceId_ `[number|string]`: The id of the media item from external source.
+- _alt_ `[string]`: The alt text of the media item.
+- _caption_ `[string]`: The caption of the media item.
+
+_Usage_
+
+```js
+wp.data.dispatch('core/block-editor').registerInserterMediaCategory({
+ name: 'openverse',
+ labels: {
+ name: 'Openverse',
+ search_items: 'Search Openverse',
+ },
+ mediaType: 'image',
+ async fetch(query = {}) {
+ const defaultArgs = {
+ mature: false,
+ excluded_source: 'flickr,inaturalist,wikimedia',
+ license: 'pdm,cc0',
+ };
+ const finalQuery = { ...query, ...defaultArgs };
+ // Sometimes you might need to map the supported request params according to `InserterMediaRequest`.
+ // interface. In this example the `search` query param is named `q`.
+ const mapFromInserterMediaRequest = {
+ per_page: 'page_size',
+ search: 'q',
+ };
+ const url = new URL('https://api.openverse.org/v1/images/');
+ Object.entries(finalQuery).forEach(([key, value]) => {
+ const queryKey = mapFromInserterMediaRequest[key] || key;
+ url.searchParams.set(queryKey, value);
+ });
+ const response = await window.fetch(url, {
+ headers: {
+ 'User-Agent': 'WordPress/inserter-media-fetch',
+ },
+ });
+ const jsonResponse = await response.json();
+ const results = jsonResponse.results;
+ return results.map((result) => ({
+ ...result,
+ // If your response result includes an `id` prop that you want to access later, it should
+ // be mapped to `InserterMediaItem`'s `sourceId` prop. This can be useful if you provide
+ // a report URL getter.
+ // Additionally you should always clear the `id` value of your response results because
+ // it is used to identify WordPress media items.
+ sourceId: result.id,
+ id: undefined,
+ caption: result.caption,
+ previewUrl: result.thumbnail,
+ }));
+ },
+ getReportUrl: ({ sourceId }) => `https://wordpress.org/openverse/image/${sourceId}/report/`,
+ isExternalResource: true,
+});
+```
+
+_Parameters_
+
+- _category_ `InserterMediaCategory`: The inserter media category to register.
+
+_Type Definition_
+
+- _InserterMediaCategory_ `Object`: Interface for inserter media category.
+
+_Properties_
+
+- _name_ `string`: The name of the media category, that should be unique among all media categories.
+- _labels_ `Object`: Labels for the media category.
+- _labels.name_ `string`: General name of the media category. It's used in the inserter media items list.
+- _labels.search_items_ `[string]`: Label for searching items. Default is ‘Search Posts’ / ‘Search Pages’.
+- _mediaType_ `('image'|'audio'|'video')`: The media type of the media category.
+- _fetch_ `(InserterMediaRequest) => Promise`: The function to fetch media items for the category.
+- _getReportUrl_ `[(InserterMediaItem) => string]`: If the media category supports reporting media items, this function should return the report url for the media item. It accepts the `InserterMediaItem` as an argument.
+- _isExternalResource_ `[boolean]`: If the media category is an external resource, this should be set to true. This is used to avoid making a request to the external resource when the user
+
+### removeBlock
+
+Returns an action object used in signalling that the block with the specified client ID is to be removed.
+
+_Parameters_
+
+- _clientId_ `string`: Client ID of block to remove.
+- _selectPrevious_ `boolean`: True if the previous block should be selected when a block is removed.
+
+_Returns_
+
+- `Object`: Action object.
+
+### removeBlocks
+
+Yields action objects used in signalling that the blocks corresponding to the set of specified client IDs are to be removed.
+
+_Parameters_
+
+- _clientIds_ `string|string[]`: Client IDs of blocks to remove.
+- _selectPrevious_ `boolean`: True if the previous block or the immediate parent (if no previous block exists) should be selected when a block is removed.
+
+### replaceBlock
+
+Action that replaces a single block with one or more replacement blocks.
+
+_Parameters_
+
+- _clientId_ `(string|string[])`: Block client ID to replace.
+- _block_ `(Object|Object[])`: Replacement block(s).
+
+_Returns_
+
+- `Object`: Action object.
+
+### replaceBlocks
+
+Action that replaces given blocks with one or more replacement blocks.
+
+_Parameters_
+
+- _clientIds_ `(string|string[])`: Block client ID(s) to replace.
+- _blocks_ `(Object|Object[])`: Replacement block(s).
+- _indexToSelect_ `number`: Index of replacement block to select.
+- _initialPosition_ `0|-1|null`: Index of caret after in the selected block after the operation.
+- _meta_ `?Object`: Optional Meta values to be passed to the action object.
+
+_Returns_
+
+- `Object`: Action object.
+
+### replaceInnerBlocks
+
+Returns an action object used in signalling that the inner blocks with the specified client ID should be replaced.
+
+_Parameters_
+
+- _rootClientId_ `string`: Client ID of the block whose InnerBlocks will re replaced.
+- _blocks_ `Object[]`: Block objects to insert as new InnerBlocks
+- _updateSelection_ `?boolean`: If true block selection will be updated. If false, block selection will not change. Defaults to false.
+- _initialPosition_ `0|-1|null`: Initial block position.
+
+_Returns_
+
+- `Object`: Action object.
+
+### resetBlocks
+
+Action that resets blocks state to the specified array of blocks, taking precedence over any other content reflected as an edit in state.
+
+_Parameters_
+
+- _blocks_ `Array`: Array of blocks.
+
+### resetSelection
+
+Returns an action object used in signalling that selection state should be reset to the specified selection.
+
+_Parameters_
+
+- _selectionStart_ `WPBlockSelection`: The selection start.
+- _selectionEnd_ `WPBlockSelection`: The selection end.
+- _initialPosition_ `0|-1|null`: Initial block position.
+
+_Returns_
+
+- `Object`: Action object.
+
+### selectBlock
+
+Returns an action object used in signalling that the block with the specified client ID has been selected, optionally accepting a position value reflecting its selection directionality. An initialPosition of -1 reflects a reverse selection.
+
+_Parameters_
+
+- _clientId_ `string`: Block client ID.
+- _initialPosition_ `0|-1|null`: Optional initial position. Pass as -1 to reflect reverse selection.
+
+_Returns_
+
+- `Object`: Action object.
+
+### selectionChange
+
+Action that changes the position of the user caret.
+
+_Parameters_
+
+- _clientId_ `string|WPSelection`: The selected block client ID.
+- _attributeKey_ `string`: The selected block attribute key.
+- _startOffset_ `number`: The start offset.
+- _endOffset_ `number`: The end offset.
+
+_Returns_
+
+- `Object`: Action object.
+
+### selectNextBlock
+
+Yields action objects used in signalling that the block following the given clientId should be selected.
+
+_Parameters_
+
+- _clientId_ `string`: Block client ID.
+
+### selectPreviousBlock
+
+Yields action objects used in signalling that the block preceding the given clientId (or optionally, its first parent from bottom to top) should be selected.
+
+_Parameters_
+
+- _clientId_ `string`: Block client ID.
+- _fallbackToParent_ `boolean`: If true, select the first parent if there is no previous block.
+
+### setBlockEditingMode
+
+Sets the block editing mode for a given block.
+
+_Related_
+
+- useBlockEditingMode
+
+_Parameters_
+
+- _clientId_ `string`: The block client ID, or `''` for the root container.
+- _mode_ `BlockEditingMode`: The block editing mode. One of `'disabled'`, `'contentOnly'`, or `'default'`.
+
+_Returns_
+
+- `Object`: Action object.
+
+### setBlockMovingClientId
+
+> **Deprecated**
+
+Set the block moving client ID.
+
+_Returns_
+
+- `Object`: Action object.
+
+### setBlockVisibility
+
+Action that sets whether given blocks are visible on the canvas.
+
+_Parameters_
+
+- _updates_ `Record`: For each block's clientId, its new visibility setting.
+
+### setHasControlledInnerBlocks
+
+Action that sets whether a block has controlled inner blocks.
+
+_Parameters_
+
+- _clientId_ `string`: The block's clientId.
+- _hasControlledInnerBlocks_ `boolean`: True if the block's inner blocks are controlled.
+
+### setNavigationMode
+
+Action that enables or disables the navigation mode.
+
+_Parameters_
+
+- _isNavigationMode_ `boolean`: Enable/Disable navigation mode.
+
+### setTemplateValidity
+
+Action that resets the template validity.
+
+_Parameters_
+
+- _isValid_ `boolean`: template validity flag.
+
+_Returns_
+
+- `Object`: Action object.
+
+### showInsertionPoint
+
+Action that shows the insertion point.
+
+_Parameters_
+
+- _rootClientId_ `?string`: Optional root client ID of block list on which to insert.
+- _index_ `?number`: Index at which block should be inserted.
+- _\_\_unstableOptions_ `?Object`: Additional options.
+
+_Returns_
+
+- `Object`: Action object.
+
+_Properties_
+
+- _\_\_unstableWithInserter_ `boolean`: Whether or not to show an inserter button.
+- _operation_ `WPDropOperation`: The operation to perform when applied, either 'insert' or 'replace' for now.
+
+### startDraggingBlocks
+
+Returns an action object used in signalling that the user has begun to drag blocks.
+
+_Parameters_
+
+- _clientIds_ `string[]`: An array of client ids being dragged
+
+_Returns_
+
+- `Object`: Action object.
+
+### startMultiSelect
+
+Action that starts block multi-selection.
+
+_Returns_
+
+- `Object`: Action object.
+
+### startTyping
+
+Returns an action object used in signalling that the user has begun to type.
+
+_Returns_
+
+- `Object`: Action object.
+
+### stopDraggingBlocks
+
+Returns an action object used in signalling that the user has stopped dragging blocks.
+
+_Returns_
+
+- `Object`: Action object.
+
+### stopMultiSelect
+
+Action that stops block multi-selection.
+
+_Returns_
+
+- `Object`: Action object.
+
+### stopTyping
+
+Returns an action object used in signalling that the user has stopped typing.
+
+_Returns_
+
+- `Object`: Action object.
+
+### synchronizeTemplate
+
+Action that synchronizes the template with the list of blocks.
+
+_Returns_
+
+- `Object`: Action object.
+
+### toggleBlockHighlight
+
+Action that toggles the highlighted block state.
+
+_Parameters_
+
+- _clientId_ `string`: The block's clientId.
+- _isHighlighted_ `boolean`: The highlight state.
+
+### toggleBlockMode
+
+Returns an action object used to toggle the block editing mode between visual and HTML modes.
+
+_Parameters_
+
+- _clientId_ `string`: Block client ID.
+
+_Returns_
+
+- `Object`: Action object.
+
+### toggleSelection
+
+Action that enables or disables block selection.
+
+_Parameters_
+
+- _isSelectionEnabled_ `[boolean]`: Whether block selection should be enabled.
+
+_Returns_
+
+- `Object`: Action object.
+
+### unsetBlockEditingMode
+
+Clears the block editing mode for a given block.
+
+_Related_
+
+- useBlockEditingMode
+
+_Parameters_
+
+- _clientId_ `string`: The block client ID, or `''` for the root container.
+
+_Returns_
+
+- `Object`: Action object.
+
+### updateBlock
+
+Action that updates the block with the specified client ID.
+
+_Parameters_
+
+- _clientId_ `string`: Block client ID.
+- _updates_ `Object`: Block attributes to be merged.
+
+_Returns_
+
+- `Object`: Action object.
+
+### updateBlockAttributes
+
+Action that updates attributes of multiple blocks with the specified client IDs.
+
+_Parameters_
+
+- _clientIds_ `string|string[]`: Block client IDs.
+- _attributes_ `Object`: Block attributes to be merged. Should be keyed by clientIds if `options.uniqueByBlock` is true.
+- _options_ `Object`: Updating options.
+- _options.uniqueByBlock_ `[boolean]`: Whether each block in clientIds array has a unique set of attributes.
+
+_Returns_
+
+- `Object`: Action object.
+
+### updateBlockListSettings
+
+Action that changes the nested settings of the given block(s).
+
+_Parameters_
+
+- _clientId_ `string | SettingsByClientId`: Client ID of the block whose nested setting are being received, or object of settings by client ID.
+- _settings_ `Object`: Object with the new settings for the nested block.
+
+_Returns_
+
+- `Object`: Action object
+
+### updateSettings
+
+Action that updates the block editor settings.
+
+_Parameters_
+
+- _settings_ `Object`: Updated settings
+
+_Returns_
+
+- `Object`: Action object
+
+### validateBlocksToTemplate
+
+Block validity is a function of blocks state (at the point of a reset) and the template setting. As a compromise to its placement across distinct parts of state, it is implemented here as a side effect of the block reset action.
+
+_Parameters_
+
+- _blocks_ `Array`: Array of blocks.
+
+
diff --git a/docs/gutenberg/reference-guides/data/data-core-blocks.md b/docs/gutenberg/reference-guides/data/data-core-blocks.md
new file mode 100644
index 0000000..58d710a
--- /dev/null
+++ b/docs/gutenberg/reference-guides/data/data-core-blocks.md
@@ -0,0 +1,634 @@
+# Block Types Data
+
+Namespace: `core/blocks`.
+
+## Selectors
+
+
+
+### getActiveBlockVariation
+
+Returns the active block variation for a given block based on its attributes. Variations are determined by their `isActive` property. Which is either an array of block attribute keys or a function.
+
+In case of an array of block attribute keys, the `attributes` are compared to the variation's attributes using strict equality check.
+
+In case of function type, the function should accept a block's attributes and the variation's attributes and determines if a variation is active. A function that accepts a block's attributes and the variation's attributes and determines if a variation is active.
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { store as blocksStore } from '@wordpress/blocks';
+import { store as blockEditorStore } from '@wordpress/block-editor';
+import { useSelect } from '@wordpress/data';
+
+const ExampleComponent = () => {
+ // This example assumes that a core/embed block is the first block in the Block Editor.
+ const activeBlockVariation = useSelect((select) => {
+ // Retrieve the list of blocks.
+ const [firstBlock] = select(blockEditorStore).getBlocks();
+
+ // Return the active block variation for the first block.
+ return select(blocksStore).getActiveBlockVariation(firstBlock.name, firstBlock.attributes);
+ }, []);
+
+ return activeBlockVariation && activeBlockVariation.name === 'spotify' ? (
+
{__('Spotify variation')}
+ ) : (
+
{__('Other variation')}
+ );
+};
+```
+
+_Parameters_
+
+- _state_ `Object`: Data state.
+- _blockName_ `string`: Name of block (example: “core/columns”).
+- _attributes_ `Object`: Block attributes used to determine active variation.
+- _scope_ `[WPBlockVariationScope]`: Block variation scope name.
+
+_Returns_
+
+- `(WPBlockVariation|undefined)`: Active block variation.
+
+### getBlockStyles
+
+Returns block styles by block name.
+
+_Usage_
+
+```js
+import { store as blocksStore } from '@wordpress/blocks';
+import { useSelect } from '@wordpress/data';
+
+const ExampleComponent = () => {
+ const buttonBlockStyles = useSelect(
+ (select) => select(blocksStore).getBlockStyles('core/button'),
+ []
+ );
+
+ return (
+
;
+};
+```
+
+_Parameters_
+
+- _state_ `Object`: Data state.
+
+_Returns_
+
+- `?string`: Default block name.
+
+### getDefaultBlockVariation
+
+Returns the default block variation for the given block type. When there are multiple variations annotated as the default one, the last added item is picked. This simplifies registering overrides. When there is no default variation set, it returns the first item.
+
+_Usage_
+
+```js
+import { __, sprintf } from '@wordpress/i18n';
+import { store as blocksStore } from '@wordpress/blocks';
+import { useSelect } from '@wordpress/data';
+
+const ExampleComponent = () => {
+ const defaultEmbedBlockVariation = useSelect(
+ (select) => select(blocksStore).getDefaultBlockVariation('core/embed'),
+ []
+ );
+
+ return (
+ defaultEmbedBlockVariation && (
+
+ )
+ );
+};
+```
+
+_Parameters_
+
+- _state_ `Object`: Data state.
+
+_Returns_
+
+- `?string`: Name of the block for handling unregistered blocks.
+
+### hasBlockSupport
+
+Returns true if the block defines support for a feature, or false otherwise.
+
+_Usage_
+
+```js
+import { __, sprintf } from '@wordpress/i18n';
+import { store as blocksStore } from '@wordpress/blocks';
+import { useSelect } from '@wordpress/data';
+
+const ExampleComponent = () => {
+ const paragraphBlockSupportClassName = useSelect( ( select ) =>
+ select( blocksStore ).hasBlockSupport( 'core/paragraph', 'className' ),
+ []
+ );
+
+ return (
+
+ { sprintf(
+ __( 'core/paragraph supports custom class name?: %s' ),
+ paragraphBlockSupportClassName
+ ) }
+ /p>
+ );
+};
+```
+
+_Parameters_
+
+- _state_ `Object`: Data state.
+- _nameOrType_ `(string|Object)`: Block name or type object.
+- _feature_ `string`: Feature to test.
+- _defaultSupports_ `boolean`: Whether feature is supported by default if not explicitly defined.
+
+_Returns_
+
+- `boolean`: Whether block supports feature.
+
+### hasChildBlocks
+
+Returns a boolean indicating if a block has child blocks or not.
+
+_Usage_
+
+```js
+import { __, sprintf } from '@wordpress/i18n';
+import { store as blocksStore } from '@wordpress/blocks';
+import { useSelect } from '@wordpress/data';
+
+const ExampleComponent = () => {
+ const navigationBlockHasChildBlocks = useSelect(
+ (select) => select(blocksStore).hasChildBlocks('core/navigation'),
+ []
+ );
+
+ return (
+
{sprintf(__('core/navigation has child blocks: %s'), navigationBlockHasChildBlocks)}
+ );
+};
+```
+
+_Parameters_
+
+- _state_ `Object`: Data state.
+- _blockName_ `string`: Block type name.
+
+_Returns_
+
+- `boolean`: True if a block contains child blocks and false otherwise.
+
+### hasChildBlocksWithInserterSupport
+
+Returns a boolean indicating if a block has at least one child block with inserter support.
+
+_Usage_
+
+```js
+import { __, sprintf } from '@wordpress/i18n';
+import { store as blocksStore } from '@wordpress/blocks';
+import { useSelect } from '@wordpress/data';
+
+const ExampleComponent = () => {
+ const navigationBlockHasChildBlocksWithInserterSupport = useSelect(
+ (select) => select(blocksStore).hasChildBlocksWithInserterSupport('core/navigation'),
+ []
+ );
+
+ return (
+
+ {sprintf(
+ __('core/navigation has child blocks with inserter support: %s'),
+ navigationBlockHasChildBlocksWithInserterSupport
+ )}
+
+ );
+};
+```
+
+_Parameters_
+
+- _state_ `Object`: Data state.
+- _blockName_ `string`: Block type name.
+
+_Returns_
+
+- `boolean`: True if a block contains at least one child blocks with inserter support and false otherwise.
+
+### isMatchingSearchTerm
+
+Returns true if the block type by the given name or object value matches a search term, or false otherwise.
+
+_Usage_
+
+```js
+import { __, sprintf } from '@wordpress/i18n';
+import { store as blocksStore } from '@wordpress/blocks';
+import { useSelect } from '@wordpress/data';
+
+const ExampleComponent = () => {
+ const termFound = useSelect(
+ (select) => select(blocksStore).isMatchingSearchTerm('core/navigation', 'theme'),
+ []
+ );
+
+ return (
+
+ {sprintf(
+ __(
+ 'Search term was found in the title, keywords, category or description in block.json: %s'
+ ),
+ termFound
+ )}
+
+ );
+};
+```
+
+_Parameters_
+
+- _state_ `Object`: Blocks state.
+- _nameOrType_ `(string|Object)`: Block name or type object.
+- _searchTerm_ `string`: Search term by which to filter.
+
+_Returns_
+
+- `Object[]`: Whether block type matches search term.
+
+
+
+## Actions
+
+The actions in this package shouldn't be used directly. Instead, use the functions listed in the public API [here](/packages/blocks/README.md)
+
+
+
+### reapplyBlockTypeFilters
+
+Signals that all block types should be computed again. It uses stored unprocessed block types and all the most recent list of registered filters.
+
+It addresses the issue where third party block filters get registered after third party blocks. A sample sequence: 1. Filter A. 2. Block B. 3. Block C. 4. Filter D. 5. Filter E. 6. Block F. 7. Filter G. In this scenario some filters would not get applied for all blocks because they are registered too late.
+
+
diff --git a/gutenberg/reference-guides/data/data-core-commands.md b/docs/gutenberg/reference-guides/data/data-core-commands.md
similarity index 59%
rename from gutenberg/reference-guides/data/data-core-commands.md
rename to docs/gutenberg/reference-guides/data/data-core-commands.md
index 9621de9..c9c1748 100644
--- a/gutenberg/reference-guides/data/data-core-commands.md
+++ b/docs/gutenberg/reference-guides/data/data-core-commands.md
@@ -12,12 +12,12 @@ Returns the registered command loaders.
_Parameters_
-- _state_ `Object`: State tree.
-- _contextual_ `boolean`: Whether to return only contextual command loaders.
+- _state_ `Object`: State tree.
+- _contextual_ `boolean`: Whether to return only contextual command loaders.
_Returns_
-- `import('./actions').WPCommandLoaderConfig[]`: The list of registered command loaders.
+- `import('./actions').WPCommandLoaderConfig[]`: The list of registered command loaders.
### getCommands
@@ -25,12 +25,12 @@ Returns the registered static commands.
_Parameters_
-- _state_ `Object`: State tree.
-- _contextual_ `boolean`: Whether to return only contextual commands.
+- _state_ `Object`: State tree.
+- _contextual_ `boolean`: Whether to return only contextual commands.
_Returns_
-- `import('./actions').WPCommandConfig[]`: The list of registered commands.
+- `import('./actions').WPCommandConfig[]`: The list of registered commands.
### getContext
@@ -38,11 +38,11 @@ Returns whether the active context.
_Parameters_
-- _state_ `Object`: State tree.
+- _state_ `Object`: State tree.
_Returns_
-- `string`: Context.
+- `string`: Context.
### isOpen
@@ -50,11 +50,11 @@ Returns whether the command palette is open.
_Parameters_
-- _state_ `Object`: State tree.
+- _state_ `Object`: State tree.
_Returns_
-- `boolean`: Returns whether the command palette is open.
+- `boolean`: Returns whether the command palette is open.
@@ -68,7 +68,7 @@ Closes the command palette.
_Returns_
-- `Object`: action.
+- `Object`: action.
### open
@@ -76,7 +76,7 @@ Opens the command palette.
_Returns_
-- `Object`: action.
+- `Object`: action.
### registerCommand
@@ -84,11 +84,11 @@ Returns an action object used to register a new command.
_Parameters_
-- _config_ `WPCommandConfig`: Command config.
+- _config_ `WPCommandConfig`: Command config.
_Returns_
-- `Object`: action.
+- `Object`: action.
### registerCommandLoader
@@ -96,11 +96,11 @@ Register command loader.
_Parameters_
-- _config_ `WPCommandLoaderConfig`: Command loader config.
+- _config_ `WPCommandLoaderConfig`: Command loader config.
_Returns_
-- `Object`: action.
+- `Object`: action.
### unregisterCommand
@@ -108,11 +108,11 @@ Returns an action object used to unregister a command.
_Parameters_
-- _name_ `string`: Command name.
+- _name_ `string`: Command name.
_Returns_
-- `Object`: action.
+- `Object`: action.
### unregisterCommandLoader
@@ -120,10 +120,10 @@ Unregister command loader hook.
_Parameters_
-- _name_ `string`: Command loader name.
+- _name_ `string`: Command loader name.
_Returns_
-- `Object`: action.
+- `Object`: action.
diff --git a/gutenberg/reference-guides/data/data-core-customize-widgets.md b/docs/gutenberg/reference-guides/data/data-core-customize-widgets.md
similarity index 58%
rename from gutenberg/reference-guides/data/data-core-customize-widgets.md
rename to docs/gutenberg/reference-guides/data/data-core-customize-widgets.md
index 8796f4c..589e8e4 100644
--- a/gutenberg/reference-guides/data/data-core-customize-widgets.md
+++ b/docs/gutenberg/reference-guides/data/data-core-customize-widgets.md
@@ -18,24 +18,19 @@ import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
const ExampleComponent = () => {
- const { isInserterOpened } = useSelect(
- ( select ) => select( customizeWidgetsStore ),
- []
- );
-
- return isInserterOpened()
- ? __( 'Inserter is open' )
- : __( 'Inserter is closed.' );
+ const { isInserterOpened } = useSelect((select) => select(customizeWidgetsStore), []);
+
+ return isInserterOpened() ? __('Inserter is open') : __('Inserter is closed.');
};
```
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the inserter is opened.
+- `boolean`: Whether the inserter is opened.
@@ -57,30 +52,30 @@ import { useDispatch } from '@wordpress/data';
import { Button } from '@wordpress/components';
const ExampleComponent = () => {
- const { setIsInserterOpened } = useDispatch( customizeWidgetsStore );
- const [ isOpen, setIsOpen ] = useState( false );
-
- return (
-
- );
+ const { setIsInserterOpened } = useDispatch(customizeWidgetsStore);
+ const [isOpen, setIsOpen] = useState(false);
+
+ return (
+
+ );
};
```
_Parameters_
-- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object.
-- _value.rootClientId_ `string`: The root client ID to insert at.
-- _value.insertionIndex_ `number`: The index to insert at.
+- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object.
+- _value.rootClientId_ `string`: The root client ID to insert at.
+- _value.insertionIndex_ `number`: The index to insert at.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
diff --git a/gutenberg/reference-guides/data/data-core-edit-post.md b/docs/gutenberg/reference-guides/data/data-core-edit-post.md
similarity index 63%
rename from gutenberg/reference-guides/data/data-core-edit-post.md
rename to docs/gutenberg/reference-guides/data/data-core-edit-post.md
index c316a92..6222ad1 100644
--- a/gutenberg/reference-guides/data/data-core-edit-post.md
+++ b/docs/gutenberg/reference-guides/data/data-core-edit-post.md
@@ -12,11 +12,11 @@ Returns true if meta boxes are initialized.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether meta boxes are initialized.
+- `boolean`: Whether meta boxes are initialized.
### getActiveGeneralSidebarName
@@ -24,16 +24,16 @@ Returns the current active general sidebar name, or null if there is no general
Examples:
-- `edit-post/document`
-- `my-plugin/insert-image-sidebar`
+- `edit-post/document`
+- `my-plugin/insert-image-sidebar`
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `?string`: Active general sidebar name.
+- `?string`: Active general sidebar name.
### getActiveMetaBoxLocations
@@ -41,11 +41,11 @@ Returns an array of active meta box locations.
_Parameters_
-- _state_ `Object`: Post editor state.
+- _state_ `Object`: Post editor state.
_Returns_
-- `string[]`: Active meta box locations.
+- `string[]`: Active meta box locations.
### getAllMetaBoxes
@@ -53,11 +53,11 @@ Returns the list of all the available meta boxes.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Array`: List of meta boxes.
+- `Array`: List of meta boxes.
### getEditedPostTemplate
@@ -65,7 +65,7 @@ Retrieves the template of the currently edited post.
_Returns_
-- `?Object`: Post Template.
+- `?Object`: Post Template.
### getEditorMode
@@ -73,11 +73,11 @@ Returns the current editing mode.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `string`: Editing mode.
+- `string`: Editing mode.
### getHiddenBlockTypes
@@ -85,7 +85,7 @@ Returns an array of blocks that are hidden.
_Returns_
-- `Array`: A list of the hidden block types
+- `Array`: A list of the hidden block types
### getMetaBoxesPerLocation
@@ -93,24 +93,24 @@ Returns the list of all the available meta boxes for a given location.
_Parameters_
-- _state_ `Object`: Global application state.
-- _location_ `string`: Meta box location to test.
+- _state_ `Object`: Global application state.
+- _location_ `string`: Meta box location to test.
_Returns_
-- `?Array`: List of meta boxes.
+- `?Array`: List of meta boxes.
### getPreference
_Parameters_
-- _state_ `Object`: Global application state.
-- _preferenceKey_ `string`: Preference Key.
-- _defaultValue_ `*`: Default Value.
+- _state_ `Object`: Global application state.
+- _preferenceKey_ `string`: Preference Key.
+- _defaultValue_ `*`: Default Value.
_Returns_
-- `*`: Preference Value.
+- `*`: Preference Value.
### getPreferences
@@ -118,11 +118,11 @@ Returns the preferences (these preferences are persisted locally).
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: Preferences Object.
+- `Object`: Preferences Object.
### hasMetaBoxes
@@ -130,11 +130,11 @@ Returns true if the post is using Meta Boxes
_Parameters_
-- _state_ `Object`: Global application state
+- _state_ `Object`: Global application state
_Returns_
-- `boolean`: Whether there are metaboxes or not.
+- `boolean`: Whether there are metaboxes or not.
### isEditingTemplate
@@ -150,12 +150,12 @@ Returns true if the given panel is enabled, or false otherwise. Panels are enabl
_Parameters_
-- _state_ `Object`: Global application state.
-- _panelName_ `string`: A string that identifies the panel.
+- _state_ `Object`: Global application state.
+- _panelName_ `string`: A string that identifies the panel.
_Returns_
-- `boolean`: Whether or not the panel is enabled.
+- `boolean`: Whether or not the panel is enabled.
### isEditorPanelOpened
@@ -165,12 +165,12 @@ Returns true if the given panel is open, or false otherwise. Panels are closed b
_Parameters_
-- _state_ `Object`: Global application state.
-- _panelName_ `string`: A string that identifies the panel.
+- _state_ `Object`: Global application state.
+- _panelName_ `string`: A string that identifies the panel.
_Returns_
-- `boolean`: Whether or not the panel is open.
+- `boolean`: Whether or not the panel is open.
### isEditorPanelRemoved
@@ -180,12 +180,12 @@ Returns true if the given panel was programmatically removed, or false otherwise
_Parameters_
-- _state_ `Object`: Global application state.
-- _panelName_ `string`: A string that identifies the panel.
+- _state_ `Object`: Global application state.
+- _panelName_ `string`: A string that identifies the panel.
_Returns_
-- `boolean`: Whether or not the panel is removed.
+- `boolean`: Whether or not the panel is removed.
### isEditorSidebarOpened
@@ -193,11 +193,11 @@ Returns true if the editor sidebar is opened.
_Parameters_
-- _state_ `Object`: Global application state
+- _state_ `Object`: Global application state
_Returns_
-- `boolean`: Whether the editor sidebar is opened.
+- `boolean`: Whether the editor sidebar is opened.
### isFeatureActive
@@ -205,12 +205,12 @@ Returns whether the given feature is enabled or not.
_Parameters_
-- _state_ `Object`: Global application state.
-- _feature_ `string`: Feature slug.
+- _state_ `Object`: Global application state.
+- _feature_ `string`: Feature slug.
_Returns_
-- `boolean`: Is active.
+- `boolean`: Is active.
### isInserterOpened
@@ -220,11 +220,11 @@ Returns true if the inserter is opened.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the inserter is opened.
+- `boolean`: Whether the inserter is opened.
### isListViewOpened
@@ -232,11 +232,11 @@ Returns true if the list view is opened.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the list view is opened.
+- `boolean`: Whether the list view is opened.
### isMetaBoxLocationActive
@@ -244,12 +244,12 @@ Returns true if there is an active meta box in the given location, or false othe
_Parameters_
-- _state_ `Object`: Post editor state.
-- _location_ `string`: Meta box location to test.
+- _state_ `Object`: Post editor state.
+- _location_ `string`: Meta box location to test.
_Returns_
-- `boolean`: Whether the meta box location is active.
+- `boolean`: Whether the meta box location is active.
### isMetaBoxLocationVisible
@@ -257,12 +257,12 @@ Returns true if a metabox location is active and visible
_Parameters_
-- _state_ `Object`: Post editor state.
-- _location_ `string`: Meta box location to test.
+- _state_ `Object`: Post editor state.
+- _location_ `string`: Meta box location to test.
_Returns_
-- `boolean`: Whether the meta box location is active and visible.
+- `boolean`: Whether the meta box location is active and visible.
### isModalActive
@@ -272,12 +272,12 @@ Returns true if a modal is active, or false otherwise.
_Parameters_
-- _state_ `Object`: Global application state.
-- _modalName_ `string`: A string that uniquely identifies the modal.
+- _state_ `Object`: Global application state.
+- _modalName_ `string`: A string that uniquely identifies the modal.
_Returns_
-- `boolean`: Whether the modal is active.
+- `boolean`: Whether the modal is active.
### isPluginItemPinned
@@ -285,12 +285,12 @@ Returns true if the plugin item is pinned to the header. When the value is not s
_Parameters_
-- _state_ `Object`: Global application state.
-- _pluginName_ `string`: Plugin item name.
+- _state_ `Object`: Global application state.
+- _pluginName_ `string`: Plugin item name.
_Returns_
-- `boolean`: Whether the plugin item is pinned.
+- `boolean`: Whether the plugin item is pinned.
### isPluginSidebarOpened
@@ -298,11 +298,11 @@ Returns true if the plugin sidebar is opened.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the plugin sidebar is opened.
+- `boolean`: Whether the plugin sidebar is opened.
### isPublishSidebarOpened
@@ -312,11 +312,11 @@ Returns true if the publish sidebar is opened.
_Parameters_
-- _state_ `Object`: Global application state
+- _state_ `Object`: Global application state
_Returns_
-- `boolean`: Whether the publish sidebar is open.
+- `boolean`: Whether the publish sidebar is open.
### isSavingMetaBoxes
@@ -324,11 +324,11 @@ Returns true if the Meta Boxes are being saved.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the metaboxes are being saved.
+- `boolean`: Whether the metaboxes are being saved.
@@ -348,7 +348,7 @@ Returns an action object signalling that the user closed a modal.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### closePublishSidebar
@@ -358,7 +358,7 @@ Returns an action object used in signalling that the user closed the publish sid
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### hideBlockTypes
@@ -366,7 +366,7 @@ Update the provided block types to be hidden.
_Parameters_
-- _blockNames_ `string[]`: Names of block types to hide.
+- _blockNames_ `string[]`: Names of block types to hide.
### initializeMetaBoxes
@@ -378,7 +378,7 @@ Returns an action object used to signal a failed meta box update.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### metaBoxUpdatesSuccess
@@ -386,7 +386,7 @@ Returns an action object used to signal a successful meta box update.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### openGeneralSidebar
@@ -394,7 +394,7 @@ Returns an action object used in signalling that the user opened an editor sideb
_Parameters_
-- _name_ `?string`: Sidebar name to be opened.
+- _name_ `?string`: Sidebar name to be opened.
### openModal
@@ -404,11 +404,11 @@ Returns an action object used in signalling that the user opened a modal.
_Parameters_
-- _name_ `string`: A string that uniquely identifies the modal.
+- _name_ `string`: A string that uniquely identifies the modal.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### openPublishSidebar
@@ -418,7 +418,7 @@ Returns an action object used in signalling that the user opened the publish sid
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### removeEditorPanel
@@ -428,11 +428,11 @@ Returns an action object used to remove a panel from the editor.
_Parameters_
-- _panelName_ `string`: A string that identifies the panel to remove.
+- _panelName_ `string`: A string that identifies the panel to remove.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### requestMetaBoxUpdates
@@ -444,7 +444,7 @@ Stores info about which Meta boxes are available in which location.
_Parameters_
-- _metaBoxesPerLocation_ `Object`: Meta boxes per location.
+- _metaBoxesPerLocation_ `Object`: Meta boxes per location.
### setIsEditingTemplate
@@ -460,7 +460,7 @@ Returns an action object used to open/close the inserter.
_Parameters_
-- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false).
+- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false).
### setIsListViewOpened
@@ -470,7 +470,7 @@ Returns an action object used to open/close the list view.
_Parameters_
-- _isOpen_ `boolean`: A boolean representing whether the list view should be opened or closed.
+- _isOpen_ `boolean`: A boolean representing whether the list view should be opened or closed.
### showBlockTypes
@@ -478,7 +478,7 @@ Update the provided block types to be visible.
_Parameters_
-- _blockNames_ `string[]`: Names of block types to show.
+- _blockNames_ `string[]`: Names of block types to show.
### switchEditorMode
@@ -488,7 +488,7 @@ Triggers an action used to switch editor mode.
_Parameters_
-- _mode_ `string`: The editor mode.
+- _mode_ `string`: The editor mode.
### toggleDistractionFree
@@ -504,11 +504,11 @@ Returns an action object used to enable or disable a panel in the editor.
_Parameters_
-- _panelName_ `string`: A string that identifies the panel to enable or disable.
+- _panelName_ `string`: A string that identifies the panel to enable or disable.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### toggleEditorPanelOpened
@@ -518,7 +518,7 @@ Opens a closed panel and closes an open panel.
_Parameters_
-- _panelName_ `string`: A string that identifies the panel to open or close.
+- _panelName_ `string`: A string that identifies the panel to open or close.
### toggleFeature
@@ -526,7 +526,7 @@ Triggers an action used to toggle a feature flag.
_Parameters_
-- _feature_ `string`: Feature name.
+- _feature_ `string`: Feature name.
### toggleFullscreenMode
@@ -538,7 +538,7 @@ Triggers an action object used to toggle a plugin name flag.
_Parameters_
-- _pluginName_ `string`: Plugin name.
+- _pluginName_ `string`: Plugin name.
### togglePublishSidebar
@@ -548,7 +548,7 @@ Returns an action object used in signalling that the user toggles the publish si
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### updatePreferredStyleVariations
diff --git a/gutenberg/reference-guides/data/data-core-edit-site.md b/docs/gutenberg/reference-guides/data/data-core-edit-site.md
similarity index 62%
rename from gutenberg/reference-guides/data/data-core-edit-site.md
rename to docs/gutenberg/reference-guides/data/data-core-edit-site.md
index a16c538..bd4bea7 100644
--- a/gutenberg/reference-guides/data/data-core-edit-site.md
+++ b/docs/gutenberg/reference-guides/data/data-core-edit-site.md
@@ -12,11 +12,11 @@ Returns whether the current user can create media or not.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: Whether the current user can create media or not.
+- `Object`: Whether the current user can create media or not.
### getCurrentTemplateNavigationPanelSubMenu
@@ -30,11 +30,11 @@ Returns the template parts and their blocks for the current edited template.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Array`: Template parts and their blocks in an array.
+- `Array`: Template parts and their blocks in an array.
### getEditedPostContext
@@ -44,11 +44,11 @@ Returns the edited post's context object.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: Page.
+- `Object`: Page.
### getEditedPostId
@@ -58,11 +58,11 @@ Returns the ID of the currently edited template or template part.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `?string`: Post ID.
+- `?string`: Post ID.
### getEditedPostType
@@ -72,11 +72,11 @@ Returns the current edited post type (wp_template or wp_template_part).
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `?TemplateType`: Template type.
+- `?TemplateType`: Template type.
### getEditorMode
@@ -84,11 +84,11 @@ Returns the current editing mode.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `string`: Editing mode.
+- `string`: Editing mode.
### getHomeTemplateId
@@ -106,11 +106,11 @@ Returns the current page object.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: Page.
+- `Object`: Page.
### getReusableBlocks
@@ -118,11 +118,11 @@ Returns any available Reusable blocks.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Array`: The available reusable blocks.
+- `Array`: The available reusable blocks.
### getSettings
@@ -130,11 +130,11 @@ Returns the site editor settings.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: Settings.
+- `Object`: Settings.
### hasPageContentFocus
@@ -144,7 +144,7 @@ Whether or not the editor allows only page content to be edited.
_Returns_
-- `boolean`: Whether or not focus is on editing page content.
+- `boolean`: Whether or not focus is on editing page content.
### isFeatureActive
@@ -154,12 +154,12 @@ Returns whether the given feature is enabled or not.
_Parameters_
-- _state_ `Object`: Global application state.
-- _featureName_ `string`: Feature slug.
+- _state_ `Object`: Global application state.
+- _featureName_ `string`: Feature slug.
_Returns_
-- `boolean`: Is active.
+- `boolean`: Is active.
### isInserterOpened
@@ -169,11 +169,11 @@ Returns true if the inserter is opened.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the inserter is opened.
+- `boolean`: Whether the inserter is opened.
### isListViewOpened
@@ -181,11 +181,11 @@ Returns true if the list view is opened.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the list view is opened.
+- `boolean`: Whether the list view is opened.
### isNavigationOpened
@@ -199,15 +199,15 @@ Whether or not the editor has a page loaded into it.
_Related_
-- setPage
+- setPage
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether or not the editor has a page loaded into it.
+- `boolean`: Whether or not the editor has a page loaded into it.
### isSaveViewOpened
@@ -215,11 +215,11 @@ Returns the current opened/closed state of the save panel.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: True if the save panel should be open; false if closed.
+- `boolean`: True if the save panel should be open; false if closed.
@@ -235,11 +235,11 @@ Action that adds a new template and sets it as the current template.
_Parameters_
-- _template_ `Object`: The template.
+- _template_ `Object`: The template.
_Returns_
-- `Object`: Action object used to set the current template.
+- `Object`: Action object used to set the current template.
### closeGeneralSidebar
@@ -251,7 +251,7 @@ Action that opens an editor sidebar.
_Parameters_
-- _name_ `?string`: Sidebar name to be opened.
+- _name_ `?string`: Sidebar name to be opened.
### openNavigationPanelToMenu
@@ -265,7 +265,7 @@ Action that removes a template.
_Parameters_
-- _template_ `Object`: The template object.
+- _template_ `Object`: The template object.
### revertTemplate
@@ -273,9 +273,9 @@ Reverts a template to its original theme-provided file.
_Parameters_
-- _template_ `Object`: The template to revert.
-- _options_ `[Object]`:
-- _options.allowUndo_ `[boolean]`: Whether to allow the user to undo reverting the template. Default true.
+- _template_ `Object`: The template to revert.
+- _options_ `[Object]`:
+- _options.allowUndo_ `[boolean]`: Whether to allow the user to undo reverting the template. Default true.
### setEditedEntity
@@ -285,13 +285,13 @@ Action that sets an edited entity.
_Parameters_
-- _postType_ `string`: The entity's post type.
-- _postId_ `string`: The entity's ID.
-- _context_ `Object`: The entity's context.
+- _postType_ `string`: The entity's post type.
+- _postId_ `string`: The entity's ID.
+- _context_ `Object`: The entity's context.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setEditedPostContext
@@ -301,11 +301,11 @@ Set's the current block editor context.
_Parameters_
-- _context_ `Object`: The context object.
+- _context_ `Object`: The context object.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setHasPageContentFocus
@@ -313,7 +313,7 @@ Sets whether or not the editor allows only page content to be edited.
_Parameters_
-- _hasPageContentFocus_ `boolean`: True to allow only page content to be edited, false to allow template to be edited.
+- _hasPageContentFocus_ `boolean`: True to allow only page content to be edited, false to allow template to be edited.
### setHomeTemplateId
@@ -327,7 +327,7 @@ Returns an action object used to open/close the inserter.
_Parameters_
-- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false).
+- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false).
### setIsListViewOpened
@@ -337,7 +337,7 @@ Returns an action object used to open/close the list view.
_Parameters_
-- _isOpen_ `boolean`: A boolean representing whether the list view should be opened or closed.
+- _isOpen_ `boolean`: A boolean representing whether the list view should be opened or closed.
### setIsNavigationPanelOpened
@@ -351,7 +351,7 @@ Sets whether the save view panel should be open.
_Parameters_
-- _isOpen_ `boolean`: If true, opens the save view. If false, closes it. It does not toggle the state, but sets it directly.
+- _isOpen_ `boolean`: If true, opens the save view. If false, closes it. It does not toggle the state, but sets it directly.
### setNavigationMenu
@@ -361,11 +361,11 @@ Action that sets a navigation menu.
_Parameters_
-- _navigationMenuId_ `string`: The Navigation Menu Post ID.
+- _navigationMenuId_ `string`: The Navigation Menu Post ID.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setNavigationPanelActiveMenu
@@ -375,7 +375,7 @@ Action that sets the active navigation panel menu.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setPage
@@ -385,7 +385,7 @@ Resolves the template for a page and displays both. If no path is given, attempt
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setTemplate
@@ -393,7 +393,7 @@ Action that sets a template, optionally fetching it from REST API.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setTemplatePart
@@ -403,11 +403,11 @@ Action that sets a template part.
_Parameters_
-- _templatePartId_ `string`: The template part ID.
+- _templatePartId_ `string`: The template part ID.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### switchEditorMode
@@ -417,7 +417,7 @@ Triggers an action used to switch editor mode.
_Parameters_
-- _mode_ `string`: The editor mode.
+- _mode_ `string`: The editor mode.
### toggleDistractionFree
@@ -431,7 +431,7 @@ Dispatches an action that toggles a feature flag.
_Parameters_
-- _featureName_ `string`: Feature name.
+- _featureName_ `string`: Feature name.
### updateSettings
@@ -439,10 +439,10 @@ Returns an action object used to update the settings.
_Parameters_
-- _settings_ `Object`: New settings.
+- _settings_ `Object`: New settings.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
diff --git a/gutenberg/reference-guides/data/data-core-edit-widgets.md b/docs/gutenberg/reference-guides/data/data-core-edit-widgets.md
similarity index 54%
rename from gutenberg/reference-guides/data/data-core-edit-widgets.md
rename to docs/gutenberg/reference-guides/data/data-core-edit-widgets.md
index 94b4af5..d796f5b 100644
--- a/gutenberg/reference-guides/data/data-core-edit-widgets.md
+++ b/docs/gutenberg/reference-guides/data/data-core-edit-widgets.md
@@ -12,12 +12,12 @@ Returns true if a block can be inserted into a widget area.
_Parameters_
-- _state_ `Array`: The open state of the widget areas.
-- _blockName_ `string`: The name of the block being inserted.
+- _state_ `Array`: The open state of the widget areas.
+- _blockName_ `string`: The name of the block being inserted.
_Returns_
-- `boolean`: True if the block can be inserted in a widget area.
+- `boolean`: True if the block can be inserted in a widget area.
### getEditedWidgetAreas
@@ -25,7 +25,7 @@ Returns all edited widget area entity records.
_Returns_
-- `Object[]`: List of edited widget area entity records.
+- `Object[]`: List of edited widget area entity records.
### getIsWidgetAreaOpen
@@ -33,12 +33,12 @@ Gets whether the widget area is opened.
_Parameters_
-- _state_ `Array`: The open state of the widget areas.
-- _clientId_ `string`: The clientId of the widget area.
+- _state_ `Array`: The open state of the widget areas.
+- _clientId_ `string`: The clientId of the widget area.
_Returns_
-- `boolean`: True if the widget area is open.
+- `boolean`: True if the widget area is open.
### getParentWidgetAreaBlock
@@ -46,11 +46,11 @@ Given a child client id, returns the parent widget area block.
_Parameters_
-- _clientId_ `string`: The client id of a block in a widget area.
+- _clientId_ `string`: The client id of a block in a widget area.
_Returns_
-- `WPBlock`: The widget area block.
+- `WPBlock`: The widget area block.
### getReferenceWidgetBlocks
@@ -58,11 +58,11 @@ Returns all blocks representing reference widgets.
_Parameters_
-- _referenceWidgetName_ `string`: Optional. If given, only reference widgets with this name will be returned.
+- _referenceWidgetName_ `string`: Optional. If given, only reference widgets with this name will be returned.
_Returns_
-- `Array`: List of all blocks representing reference widgets
+- `Array`: List of all blocks representing reference widgets
### getWidget
@@ -70,11 +70,11 @@ Returns API widget data for a particular widget ID.
_Parameters_
-- _id_ `number`: Widget ID.
+- _id_ `number`: Widget ID.
_Returns_
-- `Object`: API widget data for a particular widget ID.
+- `Object`: API widget data for a particular widget ID.
### getWidgetAreaForWidgetId
@@ -82,11 +82,11 @@ Returns widgetArea containing a block identify by given widgetId
_Parameters_
-- _widgetId_ `string`: The ID of the widget.
+- _widgetId_ `string`: The ID of the widget.
_Returns_
-- `Object`: Containing widget area.
+- `Object`: Containing widget area.
### getWidgetAreas
@@ -94,7 +94,7 @@ Returns all API widget areas.
_Returns_
-- `Object[]`: API List of widget areas.
+- `Object[]`: API List of widget areas.
### getWidgets
@@ -102,7 +102,7 @@ Returns all API widgets.
_Returns_
-- `Object[]`: API List of widgets.
+- `Object[]`: API List of widgets.
### isInserterOpened
@@ -110,11 +110,11 @@ Returns true if the inserter is opened.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the inserter is opened.
+- `boolean`: Whether the inserter is opened.
### isListViewOpened
@@ -122,11 +122,11 @@ Returns true if the list view is opened.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the list view is opened.
+- `boolean`: Whether the list view is opened.
### isSavingWidgetAreas
@@ -134,7 +134,7 @@ Returns true if any widget area is currently being saved.
_Returns_
-- `boolean`: True if any widget area is currently being saved. False otherwise.
+- `boolean`: True if any widget area is currently being saved. False otherwise.
### isWidgetSavingLocked
@@ -148,26 +148,23 @@ import { store as widgetStore } from '@wordpress/edit-widgets';
import { useSelect } from '@wordpress/data';
const ExampleComponent = () => {
- const isSavingLocked = useSelect(
- ( select ) => select( widgetStore ).isWidgetSavingLocked(),
- []
- );
-
- return isSavingLocked ? (
-
+ );
};
```
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Is locked.
+- `boolean`: Is locked.
@@ -181,7 +178,7 @@ Returns an action object signalling that the user closed the sidebar.
_Returns_
-- `Object`: Action creator.
+- `Object`: Action creator.
### lockWidgetSaving
@@ -194,22 +191,18 @@ import { store as widgetStore } from '@wordpress/edit-widgets';
import { useDispatch } from '@wordpress/data';
const ExampleComponent = () => {
- const { lockWidgetSaving } = useDispatch( widgetStore );
- return (
-
- );
+ const { lockWidgetSaving } = useDispatch(widgetStore);
+ return ;
};
```
_Parameters_
-- _lockName_ `string`: The lock name.
+- _lockName_ `string`: The lock name.
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### moveBlockToWidgetArea
@@ -217,8 +210,8 @@ Action that handles moving a block between widget areas
_Parameters_
-- _clientId_ `string`: The clientId of the block to move.
-- _widgetAreaId_ `string`: The id of the widget area to move the block to.
+- _clientId_ `string`: The clientId of the block to move.
+- _widgetAreaId_ `string`: The id of the widget area to move the block to.
### persistStubPost
@@ -226,12 +219,12 @@ Persists a stub post with given ID to core data store. The post is meant to be i
_Parameters_
-- _id_ `string`: Post ID.
-- _blocks_ `Array`: Blocks the post should consist of.
+- _id_ `string`: Post ID.
+- _blocks_ `Array`: Blocks the post should consist of.
_Returns_
-- `Object`: The post object.
+- `Object`: The post object.
### saveEditedWidgetAreas
@@ -241,7 +234,7 @@ Creates a snackbar notice on either success or error.
_Returns_
-- `Function`: An action creator.
+- `Function`: An action creator.
### saveWidgetArea
@@ -249,11 +242,11 @@ Converts all the blocks from a widget area specified by ID into widgets, and sub
_Parameters_
-- _widgetAreaId_ `string`: ID of the widget area to process.
+- _widgetAreaId_ `string`: ID of the widget area to process.
_Returns_
-- `Function`: An action creator.
+- `Function`: An action creator.
### saveWidgetAreas
@@ -261,11 +254,11 @@ Converts all the blocks from specified widget areas into widgets, and submits a
_Parameters_
-- _widgetAreas_ `Object[]`: Widget areas to save.
+- _widgetAreas_ `Object[]`: Widget areas to save.
_Returns_
-- `Function`: An action creator.
+- `Function`: An action creator.
### setIsInserterOpened
@@ -273,13 +266,13 @@ Returns an action object used to open/close the inserter.
_Parameters_
-- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object.
-- _value.rootClientId_ `string`: The root client ID to insert at.
-- _value.insertionIndex_ `number`: The index to insert at.
+- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object.
+- _value.rootClientId_ `string`: The root client ID to insert at.
+- _value.insertionIndex_ `number`: The index to insert at.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setIsListViewOpened
@@ -287,11 +280,11 @@ Returns an action object used to open/close the list view.
_Parameters_
-- _isOpen_ `boolean`: A boolean representing whether the list view should be opened or closed.
+- _isOpen_ `boolean`: A boolean representing whether the list view should be opened or closed.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setIsWidgetAreaOpen
@@ -299,12 +292,12 @@ Sets the open state of the widget area.
_Parameters_
-- _clientId_ `string`: The clientId of the widget area.
-- _isOpen_ `boolean`: Whether the widget area should be opened.
+- _clientId_ `string`: The clientId of the widget area.
+- _isOpen_ `boolean`: Whether the widget area should be opened.
_Returns_
-- `Object`: Action.
+- `Object`: Action.
### setWidgetAreasOpenState
@@ -312,11 +305,11 @@ Sets the open state of all the widget areas.
_Parameters_
-- _widgetAreasOpenState_ `Object`: The open states of all the widget areas.
+- _widgetAreasOpenState_ `Object`: The open states of all the widget areas.
_Returns_
-- `Object`: Action.
+- `Object`: Action.
### setWidgetIdForClientId
@@ -324,12 +317,12 @@ Sets the clientId stored for a particular widgetId.
_Parameters_
-- _clientId_ `number`: Client id.
-- _widgetId_ `number`: Widget id.
+- _clientId_ `number`: Client id.
+- _widgetId_ `number`: Widget id.
_Returns_
-- `Object`: Action.
+- `Object`: Action.
### unlockWidgetSaving
@@ -342,21 +335,19 @@ import { store as widgetStore } from '@wordpress/edit-widgets';
import { useDispatch } from '@wordpress/data';
const ExampleComponent = () => {
- const { unlockWidgetSaving } = useDispatch( widgetStore );
- return (
-
- );
+ const { unlockWidgetSaving } = useDispatch(widgetStore);
+ return (
+
+ );
};
```
_Parameters_
-- _lockName_ `string`: The lock name.
+- _lockName_ `string`: The lock name.
_Returns_
-- `Object`: Action object
+- `Object`: Action object
diff --git a/gutenberg/reference-guides/data/data-core-editor.md b/docs/gutenberg/reference-guides/data/data-core-editor.md
similarity index 54%
rename from gutenberg/reference-guides/data/data-core-editor.md
rename to docs/gutenberg/reference-guides/data/data-core-editor.md
index 43fba21..1930a40 100644
--- a/gutenberg/reference-guides/data/data-core-editor.md
+++ b/docs/gutenberg/reference-guides/data/data-core-editor.md
@@ -10,7 +10,7 @@ Namespace: `core/editor`.
_Related_
-- canInsertBlockType in core/block-editor store.
+- canInsertBlockType in core/block-editor store.
### canUserUseUnfilteredHTML
@@ -18,11 +18,11 @@ Returns whether or not the user has the unfiltered_html capability.
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `boolean`: Whether the user can or can't post unfiltered HTML.
+- `boolean`: Whether the user can or can't post unfiltered HTML.
### didPostSaveRequestFail
@@ -30,11 +30,11 @@ Returns true if a previous post save was attempted but failed, or false otherwis
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the post save failed.
+- `boolean`: Whether the post save failed.
### didPostSaveRequestSucceed
@@ -42,11 +42,11 @@ Returns true if a previous post save was attempted successfully, or false otherw
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the post was saved successfully.
+- `boolean`: Whether the post was saved successfully.
### getActivePostLock
@@ -54,17 +54,17 @@ Returns the active post lock.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: The lock object.
+- `Object`: The lock object.
### getAdjacentBlockClientId
_Related_
-- getAdjacentBlockClientId in core/block-editor store.
+- getAdjacentBlockClientId in core/block-editor store.
### getAutosaveAttribute
@@ -74,114 +74,114 @@ Returns an attribute value of the current autosave revision for a post, or null
_Parameters_
-- _state_ `Object`: Global application state.
-- _attributeName_ `string`: Autosave attribute name.
+- _state_ `Object`: Global application state.
+- _attributeName_ `string`: Autosave attribute name.
_Returns_
-- `*`: Autosave attribute value.
+- `*`: Autosave attribute value.
### getBlock
_Related_
-- getBlock in core/block-editor store.
+- getBlock in core/block-editor store.
### getBlockAttributes
_Related_
-- getBlockAttributes in core/block-editor store.
+- getBlockAttributes in core/block-editor store.
### getBlockCount
_Related_
-- getBlockCount in core/block-editor store.
+- getBlockCount in core/block-editor store.
### getBlockHierarchyRootClientId
_Related_
-- getBlockHierarchyRootClientId in core/block-editor store.
+- getBlockHierarchyRootClientId in core/block-editor store.
### getBlockIndex
_Related_
-- getBlockIndex in core/block-editor store.
+- getBlockIndex in core/block-editor store.
### getBlockInsertionPoint
_Related_
-- getBlockInsertionPoint in core/block-editor store.
+- getBlockInsertionPoint in core/block-editor store.
### getBlockListSettings
_Related_
-- getBlockListSettings in core/block-editor store.
+- getBlockListSettings in core/block-editor store.
### getBlockMode
_Related_
-- getBlockMode in core/block-editor store.
+- getBlockMode in core/block-editor store.
### getBlockName
_Related_
-- getBlockName in core/block-editor store.
+- getBlockName in core/block-editor store.
### getBlockOrder
_Related_
-- getBlockOrder in core/block-editor store.
+- getBlockOrder in core/block-editor store.
### getBlockRootClientId
_Related_
-- getBlockRootClientId in core/block-editor store.
+- getBlockRootClientId in core/block-editor store.
### getBlocks
_Related_
-- getBlocks in core/block-editor store.
+- getBlocks in core/block-editor store.
### getBlocksByClientId
_Related_
-- getBlocksByClientId in core/block-editor store.
+- getBlocksByClientId in core/block-editor store.
### getBlockSelectionEnd
_Related_
-- getBlockSelectionEnd in core/block-editor store.
+- getBlockSelectionEnd in core/block-editor store.
### getBlockSelectionStart
_Related_
-- getBlockSelectionStart in core/block-editor store.
+- getBlockSelectionStart in core/block-editor store.
### getClientIdsOfDescendants
_Related_
-- getClientIdsOfDescendants in core/block-editor store.
+- getClientIdsOfDescendants in core/block-editor store.
### getClientIdsWithDescendants
_Related_
-- getClientIdsWithDescendants in core/block-editor store.
+- getClientIdsWithDescendants in core/block-editor store.
### getCurrentPost
@@ -189,11 +189,11 @@ Returns the post currently being edited in its last known saved state, not inclu
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: Post object.
+- `Object`: Post object.
### getCurrentPostAttribute
@@ -201,12 +201,12 @@ Returns an attribute value of the saved post.
_Parameters_
-- _state_ `Object`: Global application state.
-- _attributeName_ `string`: Post attribute name.
+- _state_ `Object`: Global application state.
+- _attributeName_ `string`: Post attribute name.
_Returns_
-- `*`: Post attribute value.
+- `*`: Post attribute value.
### getCurrentPostId
@@ -214,11 +214,11 @@ Returns the ID of the post currently being edited, or null if the post has not y
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `?number`: ID of current post.
+- `?number`: ID of current post.
### getCurrentPostLastRevisionId
@@ -226,11 +226,11 @@ Returns the last revision ID of the post currently being edited, or null if the
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `?number`: ID of the last revision.
+- `?number`: ID of the last revision.
### getCurrentPostRevisionsCount
@@ -238,11 +238,11 @@ Returns the number of revisions of the post currently being edited.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `number`: Number of revisions.
+- `number`: Number of revisions.
### getCurrentPostType
@@ -251,16 +251,16 @@ Returns the post type of the post currently being edited.
_Usage_
```js
-const currentPostType = wp.data.select( 'core/editor' ).getCurrentPostType();
+const currentPostType = wp.data.select('core/editor').getCurrentPostType();
```
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `string`: Post type.
+- `string`: Post type.
### getCurrentTemplateId
@@ -268,11 +268,11 @@ Returns the template ID currently being rendered/edited
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `?string`: Template ID.
+- `?string`: Template ID.
### getDeviceType
@@ -280,11 +280,11 @@ Returns the current editing canvas device type.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `string`: Device type.
+- `string`: Device type.
### getEditedPostAttribute
@@ -295,31 +295,22 @@ _Usage_
```js
// Get specific media size based on the featured media ID
// Note: change sizes?.large for any registered size
-const getFeaturedMediaUrl = useSelect( ( select ) => {
- const getFeaturedMediaId =
- select( 'core/editor' ).getEditedPostAttribute( 'featured_media' );
- const media = select( 'core' ).getEntityRecord(
- 'postType',
- 'attachment',
- getFeaturedMediaId
- );
-
- return (
- media?.media_details?.sizes?.large?.source_url ||
- media?.source_url ||
- ''
- );
-}, [] );
+const getFeaturedMediaUrl = useSelect((select) => {
+ const getFeaturedMediaId = select('core/editor').getEditedPostAttribute('featured_media');
+ const media = select('core').getEntityRecord('postType', 'attachment', getFeaturedMediaId);
+
+ return media?.media_details?.sizes?.large?.source_url || media?.source_url || '';
+}, []);
```
_Parameters_
-- _state_ `Object`: Global application state.
-- _attributeName_ `string`: Post attribute name.
+- _state_ `Object`: Global application state.
+- _attributeName_ `string`: Post attribute name.
_Returns_
-- `*`: Post attribute value.
+- `*`: Post attribute value.
### getEditedPostContent
@@ -327,11 +318,11 @@ Returns the content of the post being edited.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `string`: Post content.
+- `string`: Post content.
### getEditedPostPreviewLink
@@ -339,11 +330,11 @@ Returns the post preview link
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `string | undefined`: Preview Link.
+- `string | undefined`: Preview Link.
### getEditedPostSlug
@@ -351,11 +342,11 @@ Returns the slug for the post being edited, preferring a manually edited value i
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `string`: The current slug to be displayed in the editor
+- `string`: The current slug to be displayed in the editor
### getEditedPostVisibility
@@ -363,11 +354,11 @@ Returns the current visibility of the post being edited, preferring the unsaved
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `string`: Post visibility.
+- `string`: Post visibility.
### getEditorBlocks
@@ -375,11 +366,11 @@ Return the current block list.
_Parameters_
-- _state_ `Object`:
+- _state_ `Object`:
_Returns_
-- `Array`: Block list.
+- `Array`: Block list.
### getEditorMode
@@ -387,11 +378,11 @@ Returns the current editing mode.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `string`: Editing mode.
+- `string`: Editing mode.
### getEditorSelection
@@ -399,11 +390,11 @@ Returns the current selection.
_Parameters_
-- _state_ `Object`:
+- _state_ `Object`:
_Returns_
-- `WPBlockSelection`: The selection end.
+- `WPBlockSelection`: The selection end.
### getEditorSelectionEnd
@@ -413,11 +404,11 @@ Returns the current selection end.
_Parameters_
-- _state_ `Object`:
+- _state_ `Object`:
_Returns_
-- `WPBlockSelection`: The selection end.
+- `WPBlockSelection`: The selection end.
### getEditorSelectionStart
@@ -427,11 +418,11 @@ Returns the current selection start.
_Parameters_
-- _state_ `Object`:
+- _state_ `Object`:
_Returns_
-- `WPBlockSelection`: The selection start.
+- `WPBlockSelection`: The selection start.
### getEditorSettings
@@ -439,65 +430,65 @@ Returns the post editor settings.
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `Object`: The editor settings object.
+- `Object`: The editor settings object.
### getFirstMultiSelectedBlockClientId
_Related_
-- getFirstMultiSelectedBlockClientId in core/block-editor store.
+- getFirstMultiSelectedBlockClientId in core/block-editor store.
### getGlobalBlockCount
_Related_
-- getGlobalBlockCount in core/block-editor store.
+- getGlobalBlockCount in core/block-editor store.
### getInserterItems
_Related_
-- getInserterItems in core/block-editor store.
+- getInserterItems in core/block-editor store.
### getLastMultiSelectedBlockClientId
_Related_
-- getLastMultiSelectedBlockClientId in core/block-editor store.
+- getLastMultiSelectedBlockClientId in core/block-editor store.
### getMultiSelectedBlockClientIds
_Related_
-- getMultiSelectedBlockClientIds in core/block-editor store.
+- getMultiSelectedBlockClientIds in core/block-editor store.
### getMultiSelectedBlocks
_Related_
-- getMultiSelectedBlocks in core/block-editor store.
+- getMultiSelectedBlocks in core/block-editor store.
### getMultiSelectedBlocksEndClientId
_Related_
-- getMultiSelectedBlocksEndClientId in core/block-editor store.
+- getMultiSelectedBlocksEndClientId in core/block-editor store.
### getMultiSelectedBlocksStartClientId
_Related_
-- getMultiSelectedBlocksStartClientId in core/block-editor store.
+- getMultiSelectedBlocksStartClientId in core/block-editor store.
### getNextBlockClientId
_Related_
-- getNextBlockClientId in core/block-editor store.
+- getNextBlockClientId in core/block-editor store.
### getPermalink
@@ -505,11 +496,11 @@ Returns the permalink for the post.
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `?string`: The permalink, or null if the post is not viewable.
+- `?string`: The permalink, or null if the post is not viewable.
### getPermalinkParts
@@ -517,11 +508,11 @@ Returns the permalink for a post, split into its three parts: the prefix, the po
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `Object`: An object containing the prefix, postName, and suffix for the permalink, or null if the post is not viewable.
+- `Object`: An object containing the prefix, postName, and suffix for the permalink, or null if the post is not viewable.
### getPostEdits
@@ -529,11 +520,11 @@ Returns any post values which have been changed in the editor but not yet been s
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: Object of key value pairs comprising unsaved edits.
+- `Object`: Object of key value pairs comprising unsaved edits.
### getPostLockUser
@@ -541,11 +532,11 @@ Returns details about the post lock user.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `Object`: A user object.
+- `Object`: A user object.
### getPostTypeLabel
@@ -553,17 +544,17 @@ Returns a post type label depending on the current post.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `string|undefined`: The post type label if available, otherwise undefined.
+- `string|undefined`: The post type label if available, otherwise undefined.
### getPreviousBlockClientId
_Related_
-- getPreviousBlockClientId in core/block-editor store.
+- getPreviousBlockClientId in core/block-editor store.
### getRenderingMode
@@ -571,35 +562,35 @@ Returns the post editor's rendering mode.
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `string`: Rendering mode.
+- `string`: Rendering mode.
### getSelectedBlock
_Related_
-- getSelectedBlock in core/block-editor store.
+- getSelectedBlock in core/block-editor store.
### getSelectedBlockClientId
_Related_
-- getSelectedBlockClientId in core/block-editor store.
+- getSelectedBlockClientId in core/block-editor store.
### getSelectedBlockCount
_Related_
-- getSelectedBlockCount in core/block-editor store.
+- getSelectedBlockCount in core/block-editor store.
### getSelectedBlocksInitialCaretPosition
_Related_
-- getSelectedBlocksInitialCaretPosition in core/block-editor store.
+- getSelectedBlocksInitialCaretPosition in core/block-editor store.
### getStateBeforeOptimisticTransaction
@@ -613,19 +604,19 @@ Returns a suggested post format for the current post, inferred only if there is
_Returns_
-- `?string`: Suggested post format.
+- `?string`: Suggested post format.
### getTemplate
_Related_
-- getTemplate in core/block-editor store.
+- getTemplate in core/block-editor store.
### getTemplateLock
_Related_
-- getTemplateLock in core/block-editor store.
+- getTemplateLock in core/block-editor store.
### hasChangedContent
@@ -633,11 +624,11 @@ Returns true if content includes unsaved changes, or false otherwise.
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `boolean`: Whether content includes unsaved changes.
+- `boolean`: Whether content includes unsaved changes.
### hasEditorRedo
@@ -645,11 +636,11 @@ Returns true if any future editor history snapshots exist, or false otherwise.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether redo history exists.
+- `boolean`: Whether redo history exists.
### hasEditorUndo
@@ -657,23 +648,23 @@ Returns true if any past editor history snapshots exist, or false otherwise.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether undo history exists.
+- `boolean`: Whether undo history exists.
### hasInserterItems
_Related_
-- hasInserterItems in core/block-editor store.
+- hasInserterItems in core/block-editor store.
### hasMultiSelection
_Related_
-- hasMultiSelection in core/block-editor store.
+- hasMultiSelection in core/block-editor store.
### hasNonPostEntityChanges
@@ -681,23 +672,23 @@ Returns true if there are unsaved edits for entities other than the editor's pos
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether there are edits or not.
+- `boolean`: Whether there are edits or not.
### hasSelectedBlock
_Related_
-- hasSelectedBlock in core/block-editor store.
+- hasSelectedBlock in core/block-editor store.
### hasSelectedInnerBlock
_Related_
-- hasSelectedInnerBlock in core/block-editor store.
+- hasSelectedInnerBlock in core/block-editor store.
### inSomeHistory
@@ -709,7 +700,7 @@ Returns true if an optimistic transaction is pending commit, for which the befor
_Related_
-- isAncestorMultiSelected in core/block-editor store.
+- isAncestorMultiSelected in core/block-editor store.
### isAutosavingPost
@@ -717,47 +708,47 @@ Returns true if the post is autosaving, or false otherwise.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the post is autosaving.
+- `boolean`: Whether the post is autosaving.
### isBlockInsertionPointVisible
_Related_
-- isBlockInsertionPointVisible in core/block-editor store.
+- isBlockInsertionPointVisible in core/block-editor store.
### isBlockMultiSelected
_Related_
-- isBlockMultiSelected in core/block-editor store.
+- isBlockMultiSelected in core/block-editor store.
### isBlockSelected
_Related_
-- isBlockSelected in core/block-editor store.
+- isBlockSelected in core/block-editor store.
### isBlockValid
_Related_
-- isBlockValid in core/block-editor store.
+- isBlockValid in core/block-editor store.
### isBlockWithinSelection
_Related_
-- isBlockWithinSelection in core/block-editor store.
+- isBlockWithinSelection in core/block-editor store.
### isCaretWithinFormattedText
_Related_
-- isCaretWithinFormattedText in core/block-editor store.
+- isCaretWithinFormattedText in core/block-editor store.
### isCleanNewPost
@@ -765,11 +756,11 @@ Returns true if there are no unsaved values for the current edit session and if
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether new post and unsaved values exist.
+- `boolean`: Whether new post and unsaved values exist.
### isCurrentPostPending
@@ -777,11 +768,11 @@ Returns true if post is pending review.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether current post is pending review.
+- `boolean`: Whether current post is pending review.
### isCurrentPostPublished
@@ -789,12 +780,12 @@ Return true if the current post has already been published.
_Parameters_
-- _state_ `Object`: Global application state.
-- _currentPost_ `[Object]`: Explicit current post for bypassing registry selector.
+- _state_ `Object`: Global application state.
+- _currentPost_ `[Object]`: Explicit current post for bypassing registry selector.
_Returns_
-- `boolean`: Whether the post has been published.
+- `boolean`: Whether the post has been published.
### isCurrentPostScheduled
@@ -802,11 +793,11 @@ Returns true if post is already scheduled.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether current post is scheduled to be posted.
+- `boolean`: Whether current post is scheduled to be posted.
### isDeletingPost
@@ -814,11 +805,11 @@ Returns true if the post is currently being deleted, or false otherwise.
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `boolean`: Whether post is being deleted.
+- `boolean`: Whether post is being deleted.
### isEditedPostAutosaveable
@@ -826,12 +817,12 @@ Returns true if the post can be autosaved, or false otherwise.
_Parameters_
-- _state_ `Object`: Global application state.
-- _autosave_ `Object`: A raw autosave object from the REST API.
+- _state_ `Object`: Global application state.
+- _autosave_ `Object`: A raw autosave object from the REST API.
_Returns_
-- `boolean`: Whether the post can be autosaved.
+- `boolean`: Whether the post can be autosaved.
### isEditedPostBeingScheduled
@@ -839,11 +830,11 @@ Return true if the post being edited is being scheduled. Preferring the unsaved
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the post has been published.
+- `boolean`: Whether the post has been published.
### isEditedPostDateFloating
@@ -853,11 +844,11 @@ Unlike in the PHP backend, the REST API returns a full date string for posts whe
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `boolean`: Whether the edited post has a floating date value.
+- `boolean`: Whether the edited post has a floating date value.
### isEditedPostDirty
@@ -865,11 +856,11 @@ Returns true if there are unsaved values for the current edit session, or false
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether unsaved values exist.
+- `boolean`: Whether unsaved values exist.
### isEditedPostEmpty
@@ -877,11 +868,11 @@ Returns true if the edited post has content. A post has content if it has at lea
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether post has content.
+- `boolean`: Whether post has content.
### isEditedPostNew
@@ -889,11 +880,11 @@ Returns true if the currently edited post is yet to be saved, or false if the po
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the post is new.
+- `boolean`: Whether the post is new.
### isEditedPostPublishable
@@ -901,11 +892,11 @@ Return true if the post being edited can be published.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the post can been published.
+- `boolean`: Whether the post can been published.
### isEditedPostSaveable
@@ -913,11 +904,11 @@ Returns true if the post can be saved, or false otherwise. A post must contain a
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the post can be saved.
+- `boolean`: Whether the post can be saved.
### isEditorPanelEnabled
@@ -925,12 +916,12 @@ Returns true if the given panel is enabled, or false otherwise. Panels are enabl
_Parameters_
-- _state_ `Object`: Global application state.
-- _panelName_ `string`: A string that identifies the panel.
+- _state_ `Object`: Global application state.
+- _panelName_ `string`: A string that identifies the panel.
_Returns_
-- `boolean`: Whether or not the panel is enabled.
+- `boolean`: Whether or not the panel is enabled.
### isEditorPanelOpened
@@ -938,12 +929,12 @@ Returns true if the given panel is open, or false otherwise. Panels are closed b
_Parameters_
-- _state_ `Object`: Global application state.
-- _panelName_ `string`: A string that identifies the panel.
+- _state_ `Object`: Global application state.
+- _panelName_ `string`: A string that identifies the panel.
_Returns_
-- `boolean`: Whether or not the panel is open.
+- `boolean`: Whether or not the panel is open.
### isEditorPanelRemoved
@@ -951,18 +942,18 @@ Returns true if the given panel was programmatically removed, or false otherwise
_Parameters_
-- _state_ `Object`: Global application state.
-- _panelName_ `string`: A string that identifies the panel.
+- _state_ `Object`: Global application state.
+- _panelName_ `string`: A string that identifies the panel.
_Returns_
-- `boolean`: Whether or not the panel is removed.
+- `boolean`: Whether or not the panel is removed.
### isFirstMultiSelectedBlock
_Related_
-- isFirstMultiSelectedBlock in core/block-editor store.
+- isFirstMultiSelectedBlock in core/block-editor store.
### isInserterOpened
@@ -970,11 +961,11 @@ Returns true if the inserter is opened.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the inserter is opened.
+- `boolean`: Whether the inserter is opened.
### isListViewOpened
@@ -982,17 +973,17 @@ Returns true if the list view is opened.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the list view is opened.
+- `boolean`: Whether the list view is opened.
### isMultiSelecting
_Related_
-- isMultiSelecting in core/block-editor store.
+- isMultiSelecting in core/block-editor store.
### isPermalinkEditable
@@ -1000,11 +991,11 @@ Returns whether the permalink is editable or not.
_Parameters_
-- _state_ `Object`: Editor state.
+- _state_ `Object`: Editor state.
_Returns_
-- `boolean`: Whether or not the permalink is editable.
+- `boolean`: Whether or not the permalink is editable.
### isPostAutosavingLocked
@@ -1018,26 +1009,26 @@ import { store as editorStore } from '@wordpress/editor';
import { useSelect } from '@wordpress/data';
const ExampleComponent = () => {
- const isAutoSavingLocked = useSelect(
- ( select ) => select( editorStore ).isPostAutosavingLocked(),
- []
- );
-
- return isAutoSavingLocked ? (
-
+ );
};
```
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Is locked.
+- `boolean`: Is locked.
### isPreviewingPost
@@ -1102,11 +1090,11 @@ Returns true if the post is being previewed, or false otherwise.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether the post is being previewed.
+- `boolean`: Whether the post is being previewed.
### isPublishingPost
@@ -1114,11 +1102,11 @@ Returns true if the post is being published, or false otherwise.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether post is being published.
+- `boolean`: Whether post is being published.
### isPublishSidebarEnabled
@@ -1126,7 +1114,7 @@ Returns whether the pre-publish panel should be shown or skipped when the user c
_Returns_
-- `boolean`: Whether the pre-publish panel should be shown or not.
+- `boolean`: Whether the pre-publish panel should be shown or not.
### isPublishSidebarOpened
@@ -1134,11 +1122,11 @@ Returns true if the publish sidebar is opened.
_Parameters_
-- _state_ `Object`: Global application state
+- _state_ `Object`: Global application state
_Returns_
-- `boolean`: Whether the publish sidebar is open.
+- `boolean`: Whether the publish sidebar is open.
### isSavingNonPostEntityChanges
@@ -1146,11 +1134,11 @@ Returns true if non-post entities are currently being saved, or false otherwise.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether non-post entities are being saved.
+- `boolean`: Whether non-post entities are being saved.
### isSavingPost
@@ -1158,29 +1146,29 @@ Returns true if the post is currently being saved, or false otherwise.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether post is being saved.
+- `boolean`: Whether post is being saved.
### isSelectionEnabled
_Related_
-- isSelectionEnabled in core/block-editor store.
+- isSelectionEnabled in core/block-editor store.
### isTyping
_Related_
-- isTyping in core/block-editor store.
+- isTyping in core/block-editor store.
### isValidTemplate
_Related_
-- isValidTemplate in core/block-editor store.
+- isValidTemplate in core/block-editor store.
@@ -1194,14 +1182,14 @@ Action that autosaves the current post. This includes server-side autosaving (de
_Parameters_
-- _options_ `[Object]`: Extra flags to identify the autosave.
-- _options.local_ `[boolean]`: Whether to perform a local autosave.
+- _options_ `[Object]`: Extra flags to identify the autosave.
+- _options.local_ `[boolean]`: Whether to perform a local autosave.
### clearSelectedBlock
_Related_
-- clearSelectedBlock in core/block-editor store.
+- clearSelectedBlock in core/block-editor store.
### closePublishSidebar
@@ -1209,7 +1197,7 @@ Returns an action object used in signalling that the user closed the publish sid
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### createUndoLevel
@@ -1229,17 +1217,17 @@ _Usage_
```js
// Update the post title
-wp.data.dispatch( 'core/editor' ).editPost( { title: `${ newTitle }` } );
+wp.data.dispatch('core/editor').editPost({ title: `${newTitle}` });
```
_Parameters_
-- _edits_ `Object`: Post attributes to edit.
-- _options_ `[Object]`: Options for the edit.
+- _edits_ `Object`: Post attributes to edit.
+- _options_ `[Object]`: Options for the edit.
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### enablePublishSidebar
@@ -1249,37 +1237,37 @@ Enable the publish sidebar.
_Related_
-- enterFormattedText in core/block-editor store.
+- enterFormattedText in core/block-editor store.
### exitFormattedText
_Related_
-- exitFormattedText in core/block-editor store.
+- exitFormattedText in core/block-editor store.
### hideInsertionPoint
_Related_
-- hideInsertionPoint in core/block-editor store.
+- hideInsertionPoint in core/block-editor store.
### insertBlock
_Related_
-- insertBlock in core/block-editor store.
+- insertBlock in core/block-editor store.
### insertBlocks
_Related_
-- insertBlocks in core/block-editor store.
+- insertBlocks in core/block-editor store.
### insertDefaultBlock
_Related_
-- insertDefaultBlock in core/block-editor store.
+- insertDefaultBlock in core/block-editor store.
### lockPostAutosaving
@@ -1287,16 +1275,18 @@ Action that locks post autosaving.
_Usage_
- // Lock post autosaving with the lock key `mylock`:
- wp.data.dispatch( 'core/editor' ).lockPostAutosaving( 'mylock' );
+```js
+// Lock post autosaving with the lock key `mylock`:
+wp.data.dispatch('core/editor').lockPostAutosaving('mylock');
+```
_Parameters_
-- _lockName_ `string`: The lock name.
+- _lockName_ `string`: The lock name.
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### lockPostSaving
@@ -1311,69 +1301,69 @@ _Usage_
// Only allow publishing posts that are set to a future date.
if ( 'publish' !== initialPostStatus ) {
- // Track locking.
- let locked = false;
-
- // Watch for the publish event.
- let unssubscribe = subscribe( () => {
- const currentPostStatus = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'status' );
- if ( 'publish' !== currentPostStatus ) {
-
- // Compare the post date to the current date, lock the post if the date isn't in the future.
- const postDate = new Date( wp.data.select( 'core/editor' ).getEditedPostAttribute( 'date' ) );
- const currentDate = new Date();
- if ( postDate.getTime() <= currentDate.getTime() ) {
- if ( ! locked ) {
- locked = true;
- wp.data.dispatch( 'core/editor' ).lockPostSaving( 'futurelock' );
- }
- } else {
- if ( locked ) {
- locked = false;
- wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'futurelock' );
- }
- }
- }
- } );
+ // Track locking.
+ let locked = false;
+
+ // Watch for the publish event.
+ let unssubscribe = subscribe( () => {
+ const currentPostStatus = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'status' );
+ if ( 'publish' !== currentPostStatus ) {
+
+ // Compare the post date to the current date, lock the post if the date isn't in the future.
+ const postDate = new Date( wp.data.select( 'core/editor' ).getEditedPostAttribute( 'date' ) );
+ const currentDate = new Date();
+ if ( postDate.getTime() <= currentDate.getTime() ) {
+ if ( ! locked ) {
+ locked = true;
+ wp.data.dispatch( 'core/editor' ).lockPostSaving( 'futurelock' );
+ }
+ } else {
+ if ( locked ) {
+ locked = false;
+ wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'futurelock' );
+ }
+ }
+ }
+ } );
}
_Parameters_
-- _lockName_ `string`: The lock name.
+- _lockName_ `string`: The lock name.
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### mergeBlocks
_Related_
-- mergeBlocks in core/block-editor store.
+- mergeBlocks in core/block-editor store.
### moveBlocksDown
_Related_
-- moveBlocksDown in core/block-editor store.
+- moveBlocksDown in core/block-editor store.
### moveBlocksUp
_Related_
-- moveBlocksUp in core/block-editor store.
+- moveBlocksUp in core/block-editor store.
### moveBlockToPosition
_Related_
-- moveBlockToPosition in core/block-editor store.
+- moveBlockToPosition in core/block-editor store.
### multiSelect
_Related_
-- multiSelect in core/block-editor store.
+- multiSelect in core/block-editor store.
### openPublishSidebar
@@ -1381,13 +1371,13 @@ Returns an action object used in signalling that the user opened the publish sid
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### receiveBlocks
_Related_
-- receiveBlocks in core/block-editor store.
+- receiveBlocks in core/block-editor store.
### redo
@@ -1403,13 +1393,13 @@ Action for refreshing the current post.
_Related_
-- removeBlock in core/block-editor store.
+- removeBlock in core/block-editor store.
### removeBlocks
_Related_
-- removeBlocks in core/block-editor store.
+- removeBlocks in core/block-editor store.
### removeEditorPanel
@@ -1417,29 +1407,29 @@ Returns an action object used to remove a panel from the editor.
_Parameters_
-- _panelName_ `string`: A string that identifies the panel to remove.
+- _panelName_ `string`: A string that identifies the panel to remove.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### replaceBlock
_Related_
-- replaceBlock in core/block-editor store.
+- replaceBlock in core/block-editor store.
### replaceBlocks
_Related_
-- replaceBlocks in core/block-editor store.
+- replaceBlocks in core/block-editor store.
### resetBlocks
_Related_
-- resetBlocks in core/block-editor store.
+- resetBlocks in core/block-editor store.
### resetEditorBlocks
@@ -1447,8 +1437,8 @@ Returns an action object used to signal that the blocks have been updated.
_Parameters_
-- _blocks_ `Array`: Block Array.
-- _options_ `[Object]`: Optional options.
+- _blocks_ `Array`: Block Array.
+- _options_ `[Object]`: Optional options.
### resetPost
@@ -1462,13 +1452,13 @@ Action for saving the current post in the editor.
_Parameters_
-- _options_ `[Object]`:
+- _options_ `[Object]`:
### selectBlock
_Related_
-- selectBlock in core/block-editor store.
+- selectBlock in core/block-editor store.
### setDeviceType
@@ -1476,11 +1466,11 @@ Action that changes the width of the editing canvas.
_Parameters_
-- _deviceType_ `string`:
+- _deviceType_ `string`:
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setEditedPost
@@ -1488,12 +1478,12 @@ Returns an action that sets the current post Type and post ID.
_Parameters_
-- _postType_ `string`: Post Type.
-- _postId_ `string`: Post ID.
+- _postType_ `string`: Post Type.
+- _postId_ `string`: Post ID.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setIsInserterOpened
@@ -1501,17 +1491,17 @@ Returns an action object used to open/close the inserter.
_Parameters_
-- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object.
-- _value.rootClientId_ `string`: The root client ID to insert at.
-- _value.insertionIndex_ `number`: The index to insert at.
-- _value.filterValue_ `string`: A query to filter the inserter results.
-- _value.onSelect_ `Function`: A callback when an item is selected.
-- _value.tab_ `string`: The tab to open in the inserter.
-- _value.category_ `string`: The category to initialize in the inserter.
+- _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object.
+- _value.rootClientId_ `string`: The root client ID to insert at.
+- _value.insertionIndex_ `number`: The index to insert at.
+- _value.filterValue_ `string`: A query to filter the inserter results.
+- _value.onSelect_ `Function`: A callback when an item is selected.
+- _value.tab_ `string`: The tab to open in the inserter.
+- _value.category_ `string`: The category to initialize in the inserter.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setIsListViewOpened
@@ -1519,28 +1509,28 @@ Returns an action object used to open/close the list view.
_Parameters_
-- _isOpen_ `boolean`: A boolean representing whether the list view should be opened or closed.
+- _isOpen_ `boolean`: A boolean representing whether the list view should be opened or closed.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setRenderingMode
Returns an action used to set the rendering mode of the post editor. We support multiple rendering modes:
-- `post-only`: This mode extracts the post blocks from the template and renders only those. The idea is to allow the user to edit the post/page in isolation without the wrapping template.
-- `template-locked`: This mode renders both the template and the post blocks but the template blocks are locked and can't be edited. The post blocks are editable.
+- `post-only`: This mode extracts the post blocks from the template and renders only those. The idea is to allow the user to edit the post/page in isolation without the wrapping template.
+- `template-locked`: This mode renders both the template and the post blocks but the template blocks are locked and can't be edited. The post blocks are editable.
_Parameters_
-- _mode_ `string`: Mode (one of 'post-only' or 'template-locked').
+- _mode_ `string`: Mode (one of 'post-only' or 'template-locked').
### setTemplateValidity
_Related_
-- setTemplateValidity in core/block-editor store.
+- setTemplateValidity in core/block-editor store.
### setupEditor
@@ -1548,9 +1538,9 @@ Returns an action generator used in signalling that editor has initialized with
_Parameters_
-- _post_ `Object`: Post object.
-- _edits_ `Object`: Initial edited attributes object.
-- _template_ `[Array]`: Block Template.
+- _post_ `Object`: Post object.
+- _edits_ `Object`: Initial edited attributes object.
+- _template_ `[Array]`: Block Template.
### setupEditorState
@@ -1560,37 +1550,37 @@ Setup the editor state.
_Parameters_
-- _post_ `Object`: Post object.
+- _post_ `Object`: Post object.
### showInsertionPoint
_Related_
-- showInsertionPoint in core/block-editor store.
+- showInsertionPoint in core/block-editor store.
### startMultiSelect
_Related_
-- startMultiSelect in core/block-editor store.
+- startMultiSelect in core/block-editor store.
### startTyping
_Related_
-- startTyping in core/block-editor store.
+- startTyping in core/block-editor store.
### stopMultiSelect
_Related_
-- stopMultiSelect in core/block-editor store.
+- stopMultiSelect in core/block-editor store.
### stopTyping
_Related_
-- stopTyping in core/block-editor store.
+- stopTyping in core/block-editor store.
### switchEditorMode
@@ -1598,19 +1588,19 @@ Triggers an action used to switch editor mode.
_Parameters_
-- _mode_ `string`: The editor mode.
+- _mode_ `string`: The editor mode.
### synchronizeTemplate
_Related_
-- synchronizeTemplate in core/block-editor store.
+- synchronizeTemplate in core/block-editor store.
### toggleBlockMode
_Related_
-- toggleBlockMode in core/block-editor store.
+- toggleBlockMode in core/block-editor store.
### toggleDistractionFree
@@ -1618,8 +1608,8 @@ Action that toggles Distraction free mode. Distraction free mode expects there a
_Parameters_
-- _options_ `[Object]`: Optional configuration object
-- _options.createNotice_ `[boolean]`: Whether to create a notice
+- _options_ `[Object]`: Optional configuration object
+- _options.createNotice_ `[boolean]`: Whether to create a notice
### toggleEditorPanelEnabled
@@ -1627,11 +1617,11 @@ Returns an action object used to enable or disable a panel in the editor.
_Parameters_
-- _panelName_ `string`: A string that identifies the panel to enable or disable.
+- _panelName_ `string`: A string that identifies the panel to enable or disable.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### toggleEditorPanelOpened
@@ -1639,7 +1629,7 @@ Opens a closed panel and closes an open panel.
_Parameters_
-- _panelName_ `string`: A string that identifies the panel to open or close.
+- _panelName_ `string`: A string that identifies the panel to open or close.
### togglePublishSidebar
@@ -1647,13 +1637,13 @@ Returns an action object used in signalling that the user toggles the publish si
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### toggleSelection
_Related_
-- toggleSelection in core/block-editor store.
+- toggleSelection in core/block-editor store.
### toggleSpotlightMode
@@ -1682,11 +1672,11 @@ _Usage_
_Parameters_
-- _lockName_ `string`: The lock name.
+- _lockName_ `string`: The lock name.
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### unlockPostSaving
@@ -1699,29 +1689,29 @@ _Usage_
_Parameters_
-- _lockName_ `string`: The lock name.
+- _lockName_ `string`: The lock name.
_Returns_
-- `Object`: Action object
+- `Object`: Action object
### updateBlock
_Related_
-- updateBlock in core/block-editor store.
+- updateBlock in core/block-editor store.
### updateBlockAttributes
_Related_
-- updateBlockAttributes in core/block-editor store.
+- updateBlockAttributes in core/block-editor store.
### updateBlockListSettings
_Related_
-- updateBlockListSettings in core/block-editor store.
+- updateBlockListSettings in core/block-editor store.
### updateEditorSettings
@@ -1735,7 +1725,7 @@ Returns an action object used in signalling that a patch of updates for the late
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### updatePostLock
@@ -1743,10 +1733,8 @@ Action that locks the editor.
_Parameters_
-- _lock_ `Object`: Details about the post lock status, user, and nonce.
+- _lock_ `Object`: Details about the post lock status, user, and nonce.
_Returns_
-- `Object`: Action object.
-
-
+- `Object`: Action object.
diff --git a/docs/gutenberg/reference-guides/data/data-core-keyboard-shortcuts.md b/docs/gutenberg/reference-guides/data/data-core-keyboard-shortcuts.md
new file mode 100644
index 0000000..e810194
--- /dev/null
+++ b/docs/gutenberg/reference-guides/data/data-core-keyboard-shortcuts.md
@@ -0,0 +1,403 @@
+# The Keyboard Shortcuts Data
+
+Namespace: `core/keyboard-shortcuts`.
+
+## Selectors
+
+
+
+### getAllShortcutKeyCombinations
+
+Returns the shortcuts that include aliases for a given shortcut name.
+
+_Usage_
+
+```js
+import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
+import { useSelect } from '@wordpress/data';
+import { createInterpolateElement } from '@wordpress/element';
+import { sprintf } from '@wordpress/i18n';
+
+const ExampleComponent = () => {
+ const allShortcutKeyCombinations = useSelect(
+ (select) =>
+ select(keyboardShortcutsStore).getAllShortcutKeyCombinations('core/editor/next-region'),
+ []
+ );
+
+ return (
+ allShortcutKeyCombinations.length > 0 && (
+
+ );
+};
+```
+
+_Parameters_
+
+- _name_ `string`: Shortcut name.
+
+_Returns_
+
+- `Object`: action.
+
+
diff --git a/docs/gutenberg/reference-guides/data/data-core-notices.md b/docs/gutenberg/reference-guides/data/data-core-notices.md
new file mode 100644
index 0000000..a874c05
--- /dev/null
+++ b/docs/gutenberg/reference-guides/data/data-core-notices.md
@@ -0,0 +1,380 @@
+# Notices Data
+
+Namespace: `core/notices`.
+
+## Selectors
+
+
+
+### getNotices
+
+Returns all notices as an array, optionally for a given context. Defaults to the global context.
+
+_Usage_
+
+```js
+import { useSelect } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+
+const ExampleComponent = () => {
+ const notices = useSelect((select) => select(noticesStore).getNotices());
+ return (
+
+ {notices.map((notice) => (
+
{notice.content}
+ ))}
+
+ );
+};
+```
+
+_Parameters_
+
+- _state_ `Object`: Notices state.
+- _context_ `?string`: Optional grouping context.
+
+_Returns_
+
+- `WPNotice[]`: Array of notices.
+
+
+
+## Actions
+
+
+
+### createErrorNotice
+
+Returns an action object used in signalling that an error notice is to be created. Refer to `createNotice` for options documentation.
+
+_Related_
+
+- createNotice
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { useDispatch } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+import { Button } from '@wordpress/components';
+
+const ExampleComponent = () => {
+ const { createErrorNotice } = useDispatch(noticesStore);
+ return (
+
+ );
+};
+```
+
+_Parameters_
+
+- _content_ `string`: Notice message.
+- _options_ `[Object]`: Optional notice options.
+
+_Returns_
+
+- `Object`: Action object.
+
+### createInfoNotice
+
+Returns an action object used in signalling that an info notice is to be created. Refer to `createNotice` for options documentation.
+
+_Related_
+
+- createNotice
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { useDispatch } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+import { Button } from '@wordpress/components';
+
+const ExampleComponent = () => {
+ const { createInfoNotice } = useDispatch(noticesStore);
+ return (
+
+ );
+};
+```
+
+_Parameters_
+
+- _content_ `string`: Notice message.
+- _options_ `[Object]`: Optional notice options.
+
+_Returns_
+
+- `Object`: Action object.
+
+### createNotice
+
+Returns an action object used in signalling that a notice is to be created.
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { useDispatch } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+import { Button } from '@wordpress/components';
+
+const ExampleComponent = () => {
+ const { createNotice } = useDispatch(noticesStore);
+ return (
+
+ );
+};
+```
+
+_Parameters_
+
+- _status_ `string|undefined`: Notice status ("info" if undefined is passed).
+- _content_ `string`: Notice message.
+- _options_ `[Object]`: Notice options.
+- _options.context_ `[string]`: Context under which to group notice.
+- _options.id_ `[string]`: Identifier for notice. Automatically assigned if not specified.
+- _options.isDismissible_ `[boolean]`: Whether the notice can be dismissed by user.
+- _options.type_ `[string]`: Type of notice, one of `default`, or `snackbar`.
+- _options.speak_ `[boolean]`: Whether the notice content should be announced to screen readers.
+- _options.actions_ `[Array]`: User actions to be presented with notice.
+- _options.icon_ `[string]`: An icon displayed with the notice. Only used when type is set to `snackbar`.
+- _options.explicitDismiss_ `[boolean]`: Whether the notice includes an explicit dismiss button and can't be dismissed by clicking the body of the notice. Only applies when type is set to `snackbar`.
+- _options.onDismiss_ `[Function]`: Called when the notice is dismissed.
+
+_Returns_
+
+- `Object`: Action object.
+
+### createSuccessNotice
+
+Returns an action object used in signalling that a success notice is to be created. Refer to `createNotice` for options documentation.
+
+_Related_
+
+- createNotice
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { useDispatch } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+import { Button } from '@wordpress/components';
+
+const ExampleComponent = () => {
+ const { createSuccessNotice } = useDispatch(noticesStore);
+ return (
+
+ );
+};
+```
+
+_Parameters_
+
+- _content_ `string`: Notice message.
+- _options_ `[Object]`: Optional notice options.
+
+_Returns_
+
+- `Object`: Action object.
+
+### createWarningNotice
+
+Returns an action object used in signalling that a warning notice is to be created. Refer to `createNotice` for options documentation.
+
+_Related_
+
+- createNotice
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { useDispatch } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+import { Button } from '@wordpress/components';
+
+const ExampleComponent = () => {
+ const { createWarningNotice, createInfoNotice } = useDispatch(noticesStore);
+ return (
+
+ );
+};
+```
+
+_Parameters_
+
+- _content_ `string`: Notice message.
+- _options_ `[Object]`: Optional notice options.
+
+_Returns_
+
+- `Object`: Action object.
+
+### removeAllNotices
+
+Removes all notices from a given context. Defaults to the default context.
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { useDispatch, useSelect } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+import { Button } from '@wordpress/components';
+
+export const ExampleComponent = () => {
+ const notices = useSelect((select) => select(noticesStore).getNotices());
+ const { removeAllNotices } = useDispatch(noticesStore);
+ return (
+ <>
+
+ {notices.map((notice) => (
+
{notice.content}
+ ))}
+
+
+
+ >
+ );
+};
+```
+
+_Parameters_
+
+- _noticeType_ `string`: The context to remove all notices from.
+- _context_ `string`: The context to remove all notices from.
+
+_Returns_
+
+- `Object`: Action object.
+
+### removeNotice
+
+Returns an action object used in signalling that a notice is to be removed.
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { useDispatch } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+import { Button } from '@wordpress/components';
+
+const ExampleComponent = () => {
+ const notices = useSelect((select) => select(noticesStore).getNotices());
+ const { createWarningNotice, removeNotice } = useDispatch(noticesStore);
+
+ return (
+ <>
+
+ {notices.length > 0 && (
+
+ )}
+ >
+ );
+};
+```
+
+_Parameters_
+
+- _id_ `string`: Notice unique identifier.
+- _context_ `[string]`: Optional context (grouping) in which the notice is intended to appear. Defaults to default context.
+
+_Returns_
+
+- `Object`: Action object.
+
+### removeNotices
+
+Returns an action object used in signalling that several notices are to be removed.
+
+_Usage_
+
+```js
+import { __ } from '@wordpress/i18n';
+import { useDispatch, useSelect } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+import { Button } from '@wordpress/components';
+
+const ExampleComponent = () => {
+ const notices = useSelect((select) => select(noticesStore).getNotices());
+ const { removeNotices } = useDispatch(noticesStore);
+ return (
+ <>
+
+ {notices.map((notice) => (
+
{notice.content}
+ ))}
+
+
+ >
+ );
+};
+```
+
+_Parameters_
+
+- _ids_ `string[]`: List of unique notice identifiers.
+- _context_ `[string]`: Optional context (grouping) in which the notices are intended to appear. Defaults to default context.
+
+_Returns_
+
+- `Object`: Action object.
+
+
diff --git a/gutenberg/reference-guides/data/data-core-nux.md b/docs/gutenberg/reference-guides/data/data-core-nux.md
similarity index 70%
rename from gutenberg/reference-guides/data/data-core-nux.md
rename to docs/gutenberg/reference-guides/data/data-core-nux.md
index eb6a1c3..5d72395 100644
--- a/gutenberg/reference-guides/data/data-core-nux.md
+++ b/docs/gutenberg/reference-guides/data/data-core-nux.md
@@ -12,11 +12,11 @@ Returns whether or not tips are globally enabled.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Global application state.
_Returns_
-- `boolean`: Whether tips are globally enabled.
+- `boolean`: Whether tips are globally enabled.
### getAssociatedGuide
@@ -24,12 +24,12 @@ Returns an object describing the guide, if any, that the given tip is a part of.
_Parameters_
-- _state_ `Object`: Global application state.
-- _tipId_ `string`: The tip to query.
+- _state_ `Object`: Global application state.
+- _tipId_ `string`: The tip to query.
_Returns_
-- `?NUXGuideInfo`: Information about the associated guide.
+- `?NUXGuideInfo`: Information about the associated guide.
### isTipVisible
@@ -37,12 +37,12 @@ Determines whether or not the given tip is showing. Tips are hidden if they are
_Parameters_
-- _state_ `Object`: Global application state.
-- _tipId_ `string`: The tip to query.
+- _state_ `Object`: Global application state.
+- _tipId_ `string`: The tip to query.
_Returns_
-- `boolean`: Whether or not the given tip is showing.
+- `boolean`: Whether or not the given tip is showing.
@@ -56,7 +56,7 @@ Returns an action object that, when dispatched, prevents all tips from showing a
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### dismissTip
@@ -64,11 +64,11 @@ Returns an action object that, when dispatched, dismisses the given tip. A dismi
_Parameters_
-- _id_ `string`: The tip to dismiss.
+- _id_ `string`: The tip to dismiss.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### enableTips
@@ -76,7 +76,7 @@ Returns an action object that, when dispatched, makes all tips show again.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### triggerGuide
@@ -84,10 +84,10 @@ Returns an action object that, when dispatched, presents a guide that takes the
_Parameters_
-- _tipIds_ `string[]`: Which tips to show in the guide.
+- _tipIds_ `string[]`: Which tips to show in the guide.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
diff --git a/gutenberg/reference-guides/data/data-core-preferences.md b/docs/gutenberg/reference-guides/data/data-core-preferences.md
similarity index 58%
rename from gutenberg/reference-guides/data/data-core-preferences.md
rename to docs/gutenberg/reference-guides/data/data-core-preferences.md
index a07aad4..f9a24f9 100644
--- a/gutenberg/reference-guides/data/data-core-preferences.md
+++ b/docs/gutenberg/reference-guides/data/data-core-preferences.md
@@ -12,13 +12,13 @@ Returns a boolean indicating whether a prefer is active for a particular scope.
_Parameters_
-- _state_ `Object`: The store state.
-- _scope_ `string`: The scope of the feature (e.g. core/edit-post).
-- _name_ `string`: The name of the feature.
+- _state_ `Object`: The store state.
+- _scope_ `string`: The scope of the feature (e.g. core/edit-post).
+- _name_ `string`: The name of the feature.
_Returns_
-- `*`: Is the feature enabled?
+- `*`: Is the feature enabled?
@@ -32,13 +32,13 @@ Returns an action object used in signalling that a preference should be set to a
_Parameters_
-- _scope_ `string`: The preference scope (e.g. core/edit-post).
-- _name_ `string`: The preference name.
-- _value_ `*`: The value to set.
+- _scope_ `string`: The preference scope (e.g. core/edit-post).
+- _name_ `string`: The preference name.
+- _value_ `*`: The value to set.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setDefaults
@@ -46,12 +46,12 @@ Returns an action object used in signalling that preference defaults should be s
_Parameters_
-- _scope_ `string`: The preference scope (e.g. core/edit-post).
-- _defaults_ `Object`: A key/value map of preference names to values.
+- _scope_ `string`: The preference scope (e.g. core/edit-post).
+- _defaults_ `Object`: A key/value map of preference names to values.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### setPersistenceLayer
@@ -59,18 +59,18 @@ Sets the persistence layer.
When a persistence layer is set, the preferences store will:
-- call `get` immediately and update the store state to the value returned.
-- call `set` with all preferences whenever a preference changes value.
+- call `get` immediately and update the store state to the value returned.
+- call `set` with all preferences whenever a preference changes value.
`setPersistenceLayer` should ideally be dispatched at the start of an application's lifecycle, before any other actions have been dispatched to the preferences store.
_Parameters_
-- _persistenceLayer_ `WPPreferencesPersistenceLayer`: The persistence layer.
+- _persistenceLayer_ `WPPreferencesPersistenceLayer`: The persistence layer.
_Returns_
-- `Object`: Action object.
+- `Object`: Action object.
### toggle
@@ -78,7 +78,7 @@ Returns an action object used in signalling that a preference should be toggled.
_Parameters_
-- _scope_ `string`: The preference scope (e.g. core/edit-post).
-- _name_ `string`: The preference name.
+- _scope_ `string`: The preference scope (e.g. core/edit-post).
+- _name_ `string`: The preference name.
diff --git a/gutenberg/reference-guides/data/data-core-reusable-blocks.md b/docs/gutenberg/reference-guides/data/data-core-reusable-blocks.md
similarity index 99%
rename from gutenberg/reference-guides/data/data-core-reusable-blocks.md
rename to docs/gutenberg/reference-guides/data/data-core-reusable-blocks.md
index 728281d..7edcb38 100644
--- a/gutenberg/reference-guides/data/data-core-reusable-blocks.md
+++ b/docs/gutenberg/reference-guides/data/data-core-reusable-blocks.md
@@ -5,6 +5,7 @@ Namespace: `core/reusable-blocks`.
This package is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
+
## Selectors
diff --git a/gutenberg/reference-guides/data/data-core-rich-text.md b/docs/gutenberg/reference-guides/data/data-core-rich-text.md
similarity index 64%
rename from gutenberg/reference-guides/data/data-core-rich-text.md
rename to docs/gutenberg/reference-guides/data/data-core-rich-text.md
index 8c213ee..54a962e 100644
--- a/gutenberg/reference-guides/data/data-core-rich-text.md
+++ b/docs/gutenberg/reference-guides/data/data-core-rich-text.md
@@ -41,12 +41,12 @@ const ExampleComponent = () => {
_Parameters_
-- _state_ `Object`: Data state.
-- _name_ `string`: Format type name.
+- _state_ `Object`: Data state.
+- _name_ `string`: Format type name.
_Returns_
-- `?Object`: Format type.
+- `?Object`: Format type.
### getFormatTypeForBareElement
@@ -60,25 +60,22 @@ import { store as richTextStore } from '@wordpress/rich-text';
import { useSelect } from '@wordpress/data';
const ExampleComponent = () => {
- const { getFormatTypeForBareElement } = useSelect(
- ( select ) => select( richTextStore ),
- []
- );
+ const { getFormatTypeForBareElement } = useSelect((select) => select(richTextStore), []);
- const format = getFormatTypeForBareElement( 'strong' );
+ const format = getFormatTypeForBareElement('strong');
- return format &&
;
};
```
_Parameters_
-- _state_ `Object`: Data state.
-- _bareElementTagName_ `string`: The tag name of the element to find a format type for.
+- _state_ `Object`: Data state.
+- _bareElementTagName_ `string`: The tag name of the element to find a format type for.
_Returns_
-- `?Object`: Format type.
+- `?Object`: Format type.
### getFormatTypeForClassName
@@ -92,25 +89,22 @@ import { store as richTextStore } from '@wordpress/rich-text';
import { useSelect } from '@wordpress/data';
const ExampleComponent = () => {
- const { getFormatTypeForClassName } = useSelect(
- ( select ) => select( richTextStore ),
- []
- );
+ const { getFormatTypeForClassName } = useSelect((select) => select(richTextStore), []);
- const format = getFormatTypeForClassName( 'has-inline-color' );
+ const format = getFormatTypeForClassName('has-inline-color');
- return format &&
;
};
```
_Parameters_
-- _state_ `Object`: Data state.
-- _elementClassName_ `string`: The classes of the element to find a format type for.
+- _state_ `Object`: Data state.
+- _elementClassName_ `string`: The classes of the element to find a format type for.
_Returns_
-- `?Object`: Format type.
+- `?Object`: Format type.
### getFormatTypes
@@ -124,32 +118,29 @@ import { store as richTextStore } from '@wordpress/rich-text';
import { useSelect } from '@wordpress/data';
const ExampleComponent = () => {
- const { getFormatTypes } = useSelect(
- ( select ) => select( richTextStore ),
- []
- );
-
- const availableFormats = getFormatTypes();
-
- return availableFormats ? (
-
;
};
```
_Parameters_
-- _state_ `Object`: Viewport state object.
-- _query_ `string`: Query string. Includes operator and breakpoint name, space separated. Operator defaults to >=.
+- _state_ `Object`: Viewport state object.
+- _query_ `string`: Query string. Includes operator and breakpoint name, space separated. Operator defaults to >=.
_Returns_
-- `boolean`: Whether viewport matches query.
+- `boolean`: Whether viewport matches query.
diff --git a/docs/gutenberg/reference-guides/data/data-core.md b/docs/gutenberg/reference-guides/data/data-core.md
new file mode 100644
index 0000000..fa9a120
--- /dev/null
+++ b/docs/gutenberg/reference-guides/data/data-core.md
@@ -0,0 +1,920 @@
+# WordPress Core Data
+
+Namespace: `core`.
+
+## Dynamically generated selectors
+
+There are a number of user-friendly selectors that are wrappers of the more generic `getEntityRecord` and `getEntityRecords` that can be used to retrieve information for the various entities.
+
+### getPostType
+
+Returns the information for a given post type.
+
+_Usage_
+
+```js
+import { useSelect } from '@wordpress/data';
+import { store as coreDataStore } from '@wordpress/core-data';
+
+const postType = useSelect(
+ (select) => select(coreDataStore).getPostType('post')
+
+ // Equivalent to: select( coreDataStore ).getEntityRecord( 'root', 'postType', 'post' )
+);
+```
+
+_Parameters_
+
+- postType `string`
+
+_Returns_
+
+- `EntityRecord | undefined`: Record.
+
+### getPostTypes
+
+Returns the information for post types.
+
+_Usage_
+
+```js
+import { useSelect } from '@wordpress/data';
+import { store as coreDataStore } from '@wordpress/core-data';
+
+const postTypes = useSelect((select) => {
+ return select(coreDataStore).getPostTypes({ per_page: 4 });
+
+ // Equivalent to:
+ // select( coreDataStore ).getEntityRecords( 'root', 'postType', { per_page: 4 } );
+});
+```
+
+_Parameters_
+
+- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
+
+_Returns_
+
+- `EntityRecord[] | null`: Records.
+
+### getTaxonomy
+
+Returns information for a given taxonomy.
+
+_Usage_
+
+```js
+import { useSelect } from '@wordpress/data';
+import { store as coreDataStore } from '@wordpress/core-data';
+
+const taxonomy = useSelect((select) => {
+ return select(coreDataStore).getTaxonomy('category');
+
+ // Equivalent to:
+ // select( coreDataStore ).getEntityRecord( 'root', 'taxonomy', 'category' );
+});
+```
+
+_Parameters_
+
+- taxonomy `string`
+
+_Returns_
+
+- `EntityRecord | undefined`: Record.
+
+### getTaxonomies
+
+Returns information for taxonomies.
+
+_Usage_
+
+```js
+import { useSelect } from '@wordpress/data';
+import { store as coreDataStore } from '@wordpress/core-data';
+
+const taxonomies = useSelect((select) => {
+ return select(coreDataStore).getTaxonomies({ type: 'post' });
+
+ // Equivalent to:
+ // select( coreDataStore ).getEntityRecords( 'root', 'taxonomy', { type: 'post' } );
+});
+```
+
+_Parameters_
+
+- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
+
+_Returns_
+
+- `EntityRecord[] | null`: Records.
+
+## Other Selectors
+
+
+
+### canUser
+
+Returns whether the current user can perform the given action on the given REST resource.
+
+Calling this may trigger an OPTIONS request to the REST API via the `canUser()` resolver.
+
+
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _action_ `string`: Action to check. One of: 'create', 'read', 'update', 'delete'.
+- _resource_ `string | EntityResource`: Entity resource to check. Accepts entity object `{ kind: 'postType', name: 'attachment', id: 1 }` or REST base as a string - `media`.
+- _id_ `EntityRecordKey`: Optional ID of the rest resource to check.
+
+_Returns_
+
+- `boolean | undefined`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made.
+
+### canUserEditEntityRecord
+
+Returns whether the current user can edit the given entity.
+
+Calling this may trigger an OPTIONS request to the REST API via the `canUser()` resolver.
+
+
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record's id.
+
+_Returns_
+
+- `boolean | undefined`: Whether or not the user can edit, or `undefined` if the OPTIONS request is still being made.
+
+### getAuthors
+
+> **Deprecated** since 11.3. Callers should use `select( 'core' ).getUsers({ who: 'authors' })` instead.
+
+Returns all available authors.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _query_ `GetRecordsHttpQuery`: Optional object of query parameters to include with request. For valid query parameters see the [Users page](https://developer.wordpress.org/rest-api/reference/users/) in the REST API Handbook and see the arguments for [List Users](https://developer.wordpress.org/rest-api/reference/users/#list-users) and [Retrieve a User](https://developer.wordpress.org/rest-api/reference/users/#retrieve-a-user).
+
+_Returns_
+
+- `ET.User[]`: Authors list.
+
+### getAutosave
+
+Returns the autosave for the post and author.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _postType_ `string`: The type of the parent post.
+- _postId_ `EntityRecordKey`: The id of the parent post.
+- _authorId_ `EntityRecordKey`: The id of the author.
+
+_Returns_
+
+- `EntityRecord | undefined`: The autosave for the post and author.
+
+### getAutosaves
+
+Returns the latest autosaves for the post.
+
+May return multiple autosaves since the backend stores one autosave per author for each post.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _postType_ `string`: The type of the parent post.
+- _postId_ `EntityRecordKey`: The id of the parent post.
+
+_Returns_
+
+- `Array< any > | undefined`: An array of autosaves for the post, or undefined if there is none.
+
+### getBlockPatternCategories
+
+Retrieve the list of registered block pattern categories.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+
+_Returns_
+
+- `Array< any >`: Block pattern category list.
+
+### getBlockPatterns
+
+Retrieve the list of registered block patterns.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+
+_Returns_
+
+- `Array< any >`: Block pattern list.
+
+### getCurrentTheme
+
+Return the current theme.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+
+_Returns_
+
+- `any`: The current theme.
+
+### getCurrentThemeGlobalStylesRevisions
+
+> **Deprecated** since WordPress 6.5.0. Callers should use `select( 'core' ).getRevisions( 'root', 'globalStyles', ${ recordKey } )` instead, where `recordKey` is the id of the global styles parent post.
+
+Returns the revisions of the current global styles theme.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+
+_Returns_
+
+- `Array< object > | null`: The current global styles.
+
+### getCurrentUser
+
+Returns the current user.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+
+_Returns_
+
+- `ET.User< 'edit' >`: Current user object.
+
+### getDefaultTemplateId
+
+Returns the default template use to render a given query.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _query_ `TemplateQuery`: Query.
+
+_Returns_
+
+- `string`: The default template id for the given query.
+
+### getEditedEntityRecord
+
+Returns the specified entity record, merged with its edits.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record ID.
+
+_Returns_
+
+- `ET.Updatable< EntityRecord > | false`: The entity record, merged with its edits.
+
+### getEmbedPreview
+
+Returns the embed preview for the given URL.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _url_ `string`: Embedded URL.
+
+_Returns_
+
+- `any`: Undefined if the preview has not been fetched, otherwise, the preview fetched from the embed preview API.
+
+### getEntitiesByKind
+
+> **Deprecated** since WordPress 6.0. Use getEntitiesConfig instead
+
+Returns the loaded entities for the given kind.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _kind_ `string`: Entity kind.
+
+_Returns_
+
+- `Array< any >`: Array of entities with config matching kind.
+
+### getEntitiesConfig
+
+Returns the loaded entities for the given kind.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _kind_ `string`: Entity kind.
+
+_Returns_
+
+- `Array< any >`: Array of entities with config matching kind.
+
+### getEntity
+
+> **Deprecated** since WordPress 6.0. Use getEntityConfig instead
+
+Returns the entity config given its kind and name.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+
+_Returns_
+
+- `any`: Entity config
+
+### getEntityConfig
+
+Returns the entity config given its kind and name.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+
+_Returns_
+
+- `any`: Entity config
+
+### getEntityRecord
+
+Returns the Entity's record object by key. Returns `null` if the value is not yet received, undefined if the value entity is known to not exist, or the entity object if it exists and is received.
+
+_Parameters_
+
+- _state_ `State`: State tree
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _key_ `EntityRecordKey`: Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included.
+- _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]".
+
+_Returns_
+
+- `EntityRecord | undefined`: Record.
+
+### getEntityRecordEdits
+
+Returns the specified entity record's edits.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record ID.
+
+_Returns_
+
+- `Optional< any >`: The entity record's edits.
+
+### getEntityRecordNonTransientEdits
+
+Returns the specified entity record's non transient edits.
+
+Transient edits don't create an undo level, and are not considered for change detection. They are defined in the entity's config.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record ID.
+
+_Returns_
+
+- `Optional< any >`: The entity record's non transient edits.
+
+### getEntityRecords
+
+Returns the Entity's records.
+
+_Parameters_
+
+- _state_ `State`: State tree
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
+
+_Returns_
+
+- `EntityRecord[] | null`: Records.
+
+### getEntityRecordsTotalItems
+
+Returns the Entity's total available records for a given query (ignoring pagination).
+
+_Parameters_
+
+- _state_ `State`: State tree
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
+
+_Returns_
+
+- `number | null`: number | null.
+
+### getEntityRecordsTotalPages
+
+Returns the number of available pages for the given query.
+
+_Parameters_
+
+- _state_ `State`: State tree
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
+
+_Returns_
+
+- `number | null`: number | null.
+
+### getLastEntityDeleteError
+
+Returns the specified entity record's last delete error.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record ID.
+
+_Returns_
+
+- `any`: The entity record's save error.
+
+### getLastEntitySaveError
+
+Returns the specified entity record's last save error.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record ID.
+
+_Returns_
+
+- `any`: The entity record's save error.
+
+### getRawEntityRecord
+
+Returns the entity's record object by key, with its attributes mapped to their raw values.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _key_ `EntityRecordKey`: Record's key.
+
+_Returns_
+
+- `EntityRecord | undefined`: Object with the entity's raw attributes.
+
+### getRedoEdit
+
+> **Deprecated** since 6.3
+
+Returns the next edit from the current undo offset for the entity records edits history, if any.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+
+_Returns_
+
+- `Optional< any >`: The edit.
+
+### getReferenceByDistinctEdits
+
+Returns a new reference when edited values have changed. This is useful in inferring where an edit has been made between states by comparison of the return values using strict equality.
+
+_Usage_
+
+```js
+const hasEditOccurred =
+ getReferenceByDistinctEdits(beforeState) !== getReferenceByDistinctEdits(afterState);
+```
+
+_Parameters_
+
+- _state_ Editor state.
+
+_Returns_
+
+- A value whose reference will change only when an edit occurs.
+
+### getRevision
+
+Returns a single, specific revision of a parent entity.
+
+_Parameters_
+
+- _state_ `State`: State tree
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordKey_ `EntityRecordKey`: The key of the entity record whose revisions you want to fetch.
+- _revisionKey_ `EntityRecordKey`: The revision's key.
+- _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see revisions schema in [the REST API Handbook](https://developer.wordpress.org/rest-api/reference/). Then see the arguments available "Retrieve a [entity kind]".
+
+_Returns_
+
+- `RevisionRecord | Record< PropertyKey, never > | undefined`: Record.
+
+### getRevisions
+
+Returns an entity's revisions.
+
+_Parameters_
+
+- _state_ `State`: State tree
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordKey_ `EntityRecordKey`: The key of the entity record whose revisions you want to fetch.
+- _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see revisions schema in [the REST API Handbook](https://developer.wordpress.org/rest-api/reference/). Then see the arguments available "Retrieve a [Entity kind]".
+
+_Returns_
+
+- `RevisionRecord[] | null`: Record.
+
+### getThemeSupports
+
+Return theme supports data in the index.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+
+_Returns_
+
+- `any`: Index data.
+
+### getUndoEdit
+
+> **Deprecated** since 6.3
+
+Returns the previous edit from the current undo offset for the entity records edits history, if any.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+
+_Returns_
+
+- `Optional< any >`: The edit.
+
+### getUserPatternCategories
+
+Retrieve the registered user pattern categories.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+
+_Returns_
+
+- `Array< UserPatternCategory >`: User patterns category array.
+
+### getUserQueryResults
+
+Returns all the users returned by a query ID.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _queryID_ `string`: Query ID.
+
+_Returns_
+
+- `ET.User< 'edit' >[]`: Users list.
+
+### hasEditsForEntityRecord
+
+Returns true if the specified entity record has edits, and false otherwise.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record ID.
+
+_Returns_
+
+- `boolean`: Whether the entity record has edits or not.
+
+### hasEntityRecords
+
+Returns true if records have been received for the given set of parameters, or false otherwise.
+
+_Parameters_
+
+- _state_ `State`: State tree
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _query_ `GetRecordsHttpQuery`: Optional terms query. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
+
+_Returns_
+
+- `boolean`: Whether entity records have been received.
+
+### hasFetchedAutosaves
+
+Returns true if the REST request for autosaves has completed.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _postType_ `string`: The type of the parent post.
+- _postId_ `EntityRecordKey`: The id of the parent post.
+
+_Returns_
+
+- `boolean`: True if the REST request was completed. False otherwise.
+
+### hasRedo
+
+Returns true if there is a next edit from the current undo offset for the entity records edits history, and false otherwise.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+
+_Returns_
+
+- `boolean`: Whether there is a next edit or not.
+
+### hasUndo
+
+Returns true if there is a previous edit from the current undo offset for the entity records edits history, and false otherwise.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+
+_Returns_
+
+- `boolean`: Whether there is a previous edit or not.
+
+### isAutosavingEntityRecord
+
+Returns true if the specified entity record is autosaving, and false otherwise.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record ID.
+
+_Returns_
+
+- `boolean`: Whether the entity record is autosaving or not.
+
+### isDeletingEntityRecord
+
+Returns true if the specified entity record is deleting, and false otherwise.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record ID.
+
+_Returns_
+
+- `boolean`: Whether the entity record is deleting or not.
+
+### isPreviewEmbedFallback
+
+Determines if the returned preview is an oEmbed link fallback.
+
+WordPress can be configured to return a simple link to a URL if it is not embeddable. We need to be able to determine if a URL is embeddable or not, based on what we get back from the oEmbed preview API.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _url_ `string`: Embedded URL.
+
+_Returns_
+
+- `boolean`: Is the preview for the URL an oEmbed link fallback.
+
+### isRequestingEmbedPreview
+
+Returns true if a request is in progress for embed preview data, or false otherwise.
+
+_Parameters_
+
+- _state_ `State`: Data state.
+- _url_ `string`: URL the preview would be for.
+
+_Returns_
+
+- `boolean`: Whether a request is in progress for an embed preview.
+
+### isSavingEntityRecord
+
+Returns true if the specified entity record is saving, and false otherwise.
+
+_Parameters_
+
+- _state_ `State`: State tree.
+- _kind_ `string`: Entity kind.
+- _name_ `string`: Entity name.
+- _recordId_ `EntityRecordKey`: Record ID.
+
+_Returns_
+
+- `boolean`: Whether the entity record is saving or not.
+
+
+
+## Actions
+
+
+
+### addEntities
+
+Returns an action object used in adding new entities.
+
+_Parameters_
+
+- _entities_ `Array`: Entities received.
+
+_Returns_
+
+- `Object`: Action object.
+
+### deleteEntityRecord
+
+Action triggered to delete an entity record.
+
+_Parameters_
+
+- _kind_ `string`: Kind of the deleted entity.
+- _name_ `string`: Name of the deleted entity.
+- _recordId_ `number|string`: Record ID of the deleted entity.
+- _query_ `?Object`: Special query parameters for the DELETE API call.
+- _options_ `[Object]`: Delete options.
+- _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a promise.
+- _options.throwOnError_ `[boolean]`: If false, this action suppresses all the exceptions. Defaults to false.
+
+### editEntityRecord
+
+Returns an action object that triggers an edit to an entity record.
+
+_Parameters_
+
+- _kind_ `string`: Kind of the edited entity record.
+- _name_ `string`: Name of the edited entity record.
+- _recordId_ `number|string`: Record ID of the edited entity record.
+- _edits_ `Object`: The edits.
+- _options_ `Object`: Options for the edit.
+- _options.undoIgnore_ `[boolean]`: Whether to ignore the edit in undo history or not.
+
+_Returns_
+
+- `Object`: Action object.
+
+### receiveDefaultTemplateId
+
+Returns an action object used to set the template for a given query.
+
+_Parameters_
+
+- _query_ `Object`: The lookup query.
+- _templateId_ `string`: The resolved template id.
+
+_Returns_
+
+- `Object`: Action object.
+
+### receiveEntityRecords
+
+Returns an action object used in signalling that entity records have been received.
+
+_Parameters_
+
+- _kind_ `string`: Kind of the received entity record.
+- _name_ `string`: Name of the received entity record.
+- _records_ `Array|Object`: Records received.
+- _query_ `?Object`: Query Object.
+- _invalidateCache_ `?boolean`: Should invalidate query caches.
+- _edits_ `?Object`: Edits to reset.
+- _meta_ `?Object`: Meta information about pagination.
+
+_Returns_
+
+- `Object`: Action object.
+
+### receiveNavigationFallbackId
+
+Returns an action object signalling that the fallback Navigation Menu id has been received.
+
+_Parameters_
+
+- _fallbackId_ `integer`: the id of the fallback Navigation Menu
+
+_Returns_
+
+- `Object`: Action object.
+
+### receiveRevisions
+
+Action triggered to receive revision items.
+
+_Parameters_
+
+- _kind_ `string`: Kind of the received entity record revisions.
+- _name_ `string`: Name of the received entity record revisions.
+- _recordKey_ `number|string`: The key of the entity record whose revisions you want to fetch.
+- _records_ `Array|Object`: Revisions received.
+- _query_ `?Object`: Query Object.
+- _invalidateCache_ `?boolean`: Should invalidate query caches.
+- _meta_ `?Object`: Meta information about pagination.
+
+### receiveThemeSupports
+
+> **Deprecated** since WP 5.9, this is not useful anymore, use the selector directly.
+
+Returns an action object used in signalling that the index has been received.
+
+_Returns_
+
+- `Object`: Action object.
+
+### receiveUploadPermissions
+
+> **Deprecated** since WP 5.9, use receiveUserPermission instead.
+
+Returns an action object used in signalling that Upload permissions have been received.
+
+_Parameters_
+
+- _hasUploadPermissions_ `boolean`: Does the user have permission to upload files?
+
+_Returns_
+
+- `Object`: Action object.
+
+### redo
+
+Action triggered to redo the last undone edit to an entity record, if any.
+
+### saveEditedEntityRecord
+
+Action triggered to save an entity record's edits.
+
+_Parameters_
+
+- _kind_ `string`: Kind of the entity.
+- _name_ `string`: Name of the entity.
+- _recordId_ `Object`: ID of the record.
+- _options_ `Object=`: Saving options.
+
+### saveEntityRecord
+
+Action triggered to save an entity record.
+
+_Parameters_
+
+- _kind_ `string`: Kind of the received entity.
+- _name_ `string`: Name of the received entity.
+- _record_ `Object`: Record to be saved.
+- _options_ `Object`: Saving options.
+- _options.isAutosave_ `[boolean]`: Whether this is an autosave.
+- _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a promise.
+- _options.throwOnError_ `[boolean]`: If false, this action suppresses all the exceptions. Defaults to false.
+
+### undo
+
+Action triggered to undo the last edit to an entity record, if any.
+
+
diff --git a/gutenberg/reference-guides/filters/README.md b/docs/gutenberg/reference-guides/filters/README.md
similarity index 100%
rename from gutenberg/reference-guides/filters/README.md
rename to docs/gutenberg/reference-guides/filters/README.md
diff --git a/gutenberg/reference-guides/filters/autocomplete-filters.md b/docs/gutenberg/reference-guides/filters/autocomplete-filters.md
similarity index 54%
rename from gutenberg/reference-guides/filters/autocomplete-filters.md
rename to docs/gutenberg/reference-guides/filters/autocomplete-filters.md
index 85581f6..99603ce 100644
--- a/gutenberg/reference-guides/filters/autocomplete-filters.md
+++ b/docs/gutenberg/reference-guides/filters/autocomplete-filters.md
@@ -8,39 +8,37 @@ The `Autocomplete` component found in `@wordpress/block-editor` applies this fil
Here is an example of using the `editor.Autocomplete.completers` filter to add an acronym completer. You can find full documentation for the autocompleter interface with the `Autocomplete` component in the `@wordpress/components` package.
-
-
```jsx
// Our completer
const acronymCompleter = {
- name: 'acronyms',
- triggerPrefix: '::',
- options: [
- { letters: 'FYI', expansion: 'For Your Information' },
- { letters: 'AFAIK', expansion: 'As Far As I Know' },
- { letters: 'IIRC', expansion: 'If I Recall Correctly' },
- ],
- getOptionKeywords( { letters, expansion } ) {
- const expansionWords = expansion.split( /\s+/ );
- return [ letters, ...expansionWords ];
- },
- getOptionLabel: acronym => acronym.letters,
- getOptionCompletion: ( { letters, expansion } ) => (
- { letters },
- ),
+ name: 'acronyms',
+ triggerPrefix: '::',
+ options: [
+ { letters: 'FYI', expansion: 'For Your Information' },
+ { letters: 'AFAIK', expansion: 'As Far As I Know' },
+ { letters: 'IIRC', expansion: 'If I Recall Correctly' },
+ ],
+ getOptionKeywords( { letters, expansion } ) {
+ const expansionWords = expansion.split( /\s+/ );
+ return [ letters, ...expansionWords ];
+ },
+ getOptionLabel: acronym => acronym.letters,
+ getOptionCompletion: ( { letters, expansion } ) => (
+ { letters },
+ ),
};
// Our filter function
function appendAcronymCompleter( completers, blockName ) {
- return blockName === 'my-plugin/foo' ?
- [ ...completers, acronymCompleter ] :
- completers;
+ return blockName === 'my-plugin/foo' ?
+ [ ...completers, acronymCompleter ] :
+ completers;
}
// Adding the filter
wp.hooks.addFilter(
- 'editor.Autocomplete.completers',
- 'my-plugin/autocompleters/acronym',
- appendAcronymCompleter
+ 'editor.Autocomplete.completers',
+ 'my-plugin/autocompleters/acronym',
+ appendAcronymCompleter
);
```
diff --git a/gutenberg/reference-guides/filters/block-filters.md b/docs/gutenberg/reference-guides/filters/block-filters.md
similarity index 68%
rename from gutenberg/reference-guides/filters/block-filters.md
rename to docs/gutenberg/reference-guides/filters/block-filters.md
index f1952ef..ea059ef 100644
--- a/gutenberg/reference-guides/filters/block-filters.md
+++ b/docs/gutenberg/reference-guides/filters/block-filters.md
@@ -18,31 +18,31 @@ The following example sets the `apiVersion` of all blocks to `2`.
```php
function example_filter_metadata_registration( $metadata ) {
- $metadata['apiVersion'] = 2;
- return $metadata;
+ $metadata['apiVersion'] = 2;
+ return $metadata;
};
add_filter( 'block_type_metadata', 'example_filter_metadata_registration' );
```
-Here's a more robust example that disables background color and gradient support for Heading blocks. The `block_type_metadata` filter is excellent for [curating the Editor experience](https://developer.wordpress.org/block-editor/how-to-guides/curating-the-editor-experience/).
+Here's a more robust example that disables background color and gradient support for Heading blocks. The `block_type_metadata` filter is excellent for [curating the Editor experience](https://developer.wordpress.org/block-editor/how-to-guides/curating-the-editor-experience/).
```php
function example_disable_heading_background_color_and_gradients( $metadata ) {
-
- // Only apply the filter to Heading blocks.
- if ( ! isset( $metadata['name'] ) || 'core/heading' !== $metadata['name'] ) {
- return $metadata;
- }
-
- // Check if 'supports' key exists.
- if ( isset( $metadata['supports'] ) && isset( $metadata['supports']['color'] ) ) {
-
- // Remove Background color and Gradients support.
- $metadata['supports']['color']['background'] = false;
- $metadata['supports']['color']['gradients'] = false;
- }
-
- return $metadata;
+
+ // Only apply the filter to Heading blocks.
+ if ( ! isset( $metadata['name'] ) || 'core/heading' !== $metadata['name'] ) {
+ return $metadata;
+ }
+
+ // Check if 'supports' key exists.
+ if ( isset( $metadata['supports'] ) && isset( $metadata['supports']['color'] ) ) {
+
+ // Remove Background color and Gradients support.
+ $metadata['supports']['color']['background'] = false;
+ $metadata['supports']['color']['gradients'] = false;
+ }
+
+ return $metadata;
}
add_filter( 'block_type_metadata', 'example_disable_heading_background_color_and_gradients' );
```
@@ -53,15 +53,15 @@ Filters the settings determined from the processed block type metadata. It makes
The callback function for this filter receives two parameters:
-- `$settings` (`array`): Array of determined settings for registering a block type.
-- `$metadata` (`array`): Metadata loaded from the `block.json` file.
+- `$settings` (`array`): Array of determined settings for registering a block type.
+- `$metadata` (`array`): Metadata loaded from the `block.json` file.
The following example increases the `apiVersion` for all blocks by `1`.
```php
function example_filter_metadata_registration( $settings, $metadata ) {
- $settings['api_version'] = $metadata['apiVersion'] + 1;
- return $settings;
+ $settings['api_version'] = $metadata['apiVersion'] + 1;
+ return $settings;
};
add_filter( 'block_type_metadata_settings', 'example_filter_metadata_registration', 10, 2 );
```
@@ -82,25 +82,25 @@ The following code will disable the color controls for Paragraph, Heading, List,
```php
function example_disable_color_for_specific_blocks( $args, $block_type ) {
- // List of block types to modify.
- $block_types_to_modify = [
- 'core/paragraph',
- 'core/heading',
- 'core/list',
- 'core/list-item'
- ];
-
- // Check if the current block type is in the list.
- if ( in_array( $block_type, $block_types_to_modify, true ) ) {
- // Disable color controls.
- $args['supports']['color'] = array(
- 'text' => false,
- 'background' => false,
- 'link' => false,
- );
- }
-
- return $args;
+ // List of block types to modify.
+ $block_types_to_modify = [
+ 'core/paragraph',
+ 'core/heading',
+ 'core/list',
+ 'core/list-item'
+ ];
+
+ // Check if the current block type is in the list.
+ if ( in_array( $block_type, $block_types_to_modify, true ) ) {
+ // Disable color controls.
+ $args['supports']['color'] = array(
+ 'text' => false,
+ 'background' => false,
+ 'link' => false,
+ );
+ }
+
+ return $args;
}
add_filter( 'register_block_type_args', 'example_disable_color_for_specific_blocks', 10, 2 );
```
@@ -112,24 +112,24 @@ Used to filter the block settings when registering the block on the client with
The following example ensures that List blocks are saved with the canonical generated class name (`wp-block-list`):
```js
-function addListBlockClassName( settings, name ) {
- if ( name !== 'core/list' ) {
- return settings;
- }
-
- return {
- ...settings,
- supports: {
- ...settings.supports,
- className: true,
- },
- };
+function addListBlockClassName(settings, name) {
+ if (name !== 'core/list') {
+ return settings;
+ }
+
+ return {
+ ...settings,
+ supports: {
+ ...settings.supports,
+ className: true,
+ },
+ };
}
wp.hooks.addFilter(
- 'blocks.registerBlockType',
- 'my-plugin/class-names/list-block',
- addListBlockClassName
+ 'blocks.registerBlockType',
+ 'my-plugin/class-names/list-block',
+ addListBlockClassName
);
```
@@ -139,7 +139,7 @@ The following PHP filters are available to change the output of a block on the f
### `render_block`
-Filters the front-end content of any block. This filter has no impact on the behavior of blocks in the Editor.
+Filters the front-end content of any block. This filter has no impact on the behavior of blocks in the Editor.
The callback function for this filter receives three parameters:
@@ -151,21 +151,21 @@ In the following example, the class `example-class` is added to all Paragraph bl
```php
function example_add_custom_class_to_paragraph_block( $block_content, $block ) {
-
- // Check if the block is a Paragraph block.
- if ( 'core/paragraph' === $block['blockName'] ) {
-
- // Add the custom class to the block content using the HTML API.
- $processor = new WP_HTML_Tag_Processor( $block_content );
-
- if ( $processor->next_tag( 'p' ) ) {
- $processor->add_class( 'example-class' );
- }
-
- return $processor->get_updated_html();
- }
-
- return $block_content;
+
+ // Check if the block is a Paragraph block.
+ if ( 'core/paragraph' === $block['blockName'] ) {
+
+ // Add the custom class to the block content using the HTML API.
+ $processor = new WP_HTML_Tag_Processor( $block_content );
+
+ if ( $processor->next_tag( 'p' ) ) {
+ $processor->add_class( 'example-class' );
+ }
+
+ return $processor->get_updated_html();
+ }
+
+ return $block_content;
}
add_filter( 'render_block', 'example_add_custom_class_to_paragraph_block', 10, 2 );
```
@@ -184,15 +184,15 @@ In the following example, the class `example-class` is added to all Paragraph bl
```php
function example_add_custom_class_to_paragraph_block( $block_content, $block ) {
-
- // Add the custom class to the block content using the HTML API.
- $processor = new WP_HTML_Tag_Processor( $block_content );
-
- if ( $processor->next_tag( 'p' ) ) {
- $processor->add_class( 'example-class' );
- }
-
- return $processor->get_updated_html();
+
+ // Add the custom class to the block content using the HTML API.
+ $processor = new WP_HTML_Tag_Processor( $block_content );
+
+ if ( $processor->next_tag( 'p' ) ) {
+ $processor->add_class( 'example-class' );
+ }
+
+ return $processor->get_updated_html();
}
add_filter( 'render_block_core/paragraph', 'example_add_custom_class_to_paragraph_block', 10, 2 );
```
@@ -208,32 +208,31 @@ A filter that applies to the result of a block's `save` function. This filter is
The callback function for this filter receives three parameters:
- `element` (`Object`): The element to be modified and returned.
-- `blockType` (`Object`): A block-type definition object.
-- `attributes` (`Object`): The block's attributes.
+- `blockType` (`Object`): A block-type definition object.
+- `attributes` (`Object`): The block's attributes.
The following example wraps a Cover block in an outer container `div`.
```js
-function wrapCoverBlockInContainer( element, blockType, attributes ) {
-
- // Skip if element is undefined.
- if ( ! element ) {
- return;
- }
-
- // Only apply to Cover blocks.
- if ( blockType.name !== 'core/cover' ) {
- return element;
- }
-
- // Return the element wrapped in a div.
- return
{ element }
;
+function wrapCoverBlockInContainer(element, blockType, attributes) {
+ // Skip if element is undefined.
+ if (!element) {
+ return;
+ }
+
+ // Only apply to Cover blocks.
+ if (blockType.name !== 'core/cover') {
+ return element;
+ }
+
+ // Return the element wrapped in a div.
+ return
{element}
;
}
wp.hooks.addFilter(
- 'blocks.getSaveElement',
- 'my-plugin/wrap-cover-block-in-container',
- wrapCoverBlockInContainer
+ 'blocks.getSaveElement',
+ 'my-plugin/wrap-cover-block-in-container',
+ wrapCoverBlockInContainer
);
```
@@ -244,23 +243,23 @@ A filter that applies to all blocks returning a WP Element in the `save` functio
The callback function for this filter receives three parameters:
- `props` (`Object`): The current `save` element's props to be modified and returned.
-- `blockType` (`Object`): A block-type definition object.
-- `attributes` (`Object`): The block's attributes.
+- `blockType` (`Object`): A block-type definition object.
+- `attributes` (`Object`): The block's attributes.
The following example adds a red background by default to all blocks.
```js
-function addBackgroundColorStyle( props ) {
- return {
- ...props,
- style: { backgroundColor: 'red' },
- };
+function addBackgroundColorStyle(props) {
+ return {
+ ...props,
+ style: { backgroundColor: 'red' },
+ };
}
wp.hooks.addFilter(
- 'blocks.getSaveContent.extraProps',
- 'my-plugin/add-background-color-style',
- addBackgroundColorStyle
+ 'blocks.getSaveContent.extraProps',
+ 'my-plugin/add-background-color-style',
+ addBackgroundColorStyle
);
```
@@ -274,15 +273,15 @@ Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature. Thi
```js
// Our filter function.
-function setBlockCustomClassName( className, blockName ) {
- return blockName === 'core/code' ? 'my-plugin-code' : className;
+function setBlockCustomClassName(className, blockName) {
+ return blockName === 'core/code' ? 'my-plugin-code' : className;
}
// Adding the filter.
wp.hooks.addFilter(
- 'blocks.getBlockDefaultClassName',
- 'my-plugin/set-block-custom-class-name',
- setBlockCustomClassName
+ 'blocks.getBlockDefaultClassName',
+ 'my-plugin/set-block-custom-class-name',
+ setBlockCustomClassName
);
```
@@ -295,6 +294,7 @@ Used to filter an individual transform result from block transformation. All of
Called immediately after the default parsing of a block's attributes and before validation to allow a plugin to manipulate attribute values in time for validation and/or the initial values rendering of the block in the editor.
The callback function for this filter accepts 4 parameters:
+
- `blockAttributes` (`Object`): All block attributes.
- `blockType` (`Object`): The block type.
- `innerHTML` (`string`): Raw block content.
@@ -304,19 +304,15 @@ In the example below, we use the `blocks.getBlockAttributes` filter to lock the
```js
// Our filter function
-function lockParagraphs( blockAttributes, blockType, innerHTML, attributes ) {
- if('core/paragraph' === blockType.name) {
- blockAttributes['lock'] = {move: true}
- }
- return blockAttributes;
+function lockParagraphs(blockAttributes, blockType, innerHTML, attributes) {
+ if ('core/paragraph' === blockType.name) {
+ blockAttributes['lock'] = { move: true };
+ }
+ return blockAttributes;
}
// Add the filter
-wp.hooks.addFilter(
- 'blocks.getBlockAttributes',
- 'my-plugin/lock-paragraphs',
- lockParagraphs
-);
+wp.hooks.addFilter('blocks.getBlockAttributes', 'my-plugin/lock-paragraphs', lockParagraphs);
```
### `editor.BlockEdit`
@@ -330,24 +326,20 @@ const { createHigherOrderComponent } = wp.compose;
const { InspectorControls } = wp.blockEditor;
const { PanelBody } = wp.components;
-const withMyPluginControls = createHigherOrderComponent( ( BlockEdit ) => {
- return ( props ) => {
- return (
- <>
-
-
- My custom control
-
- >
- );
- };
-}, 'withMyPluginControls' );
-
-wp.hooks.addFilter(
- 'editor.BlockEdit',
- 'my-plugin/with-inspector-controls',
- withMyPluginControls
-);
+const withMyPluginControls = createHigherOrderComponent((BlockEdit) => {
+ return (props) => {
+ return (
+ <>
+
+
+ My custom control
+
+ >
+ );
+ };
+}, 'withMyPluginControls');
+
+wp.hooks.addFilter('editor.BlockEdit', 'my-plugin/with-inspector-controls', withMyPluginControls);
```
Note that as this hook is run for _all blocks_, consuming it has the potential for performance regressions, particularly around block selection metrics.
@@ -359,20 +351,20 @@ For example, suppose you are adding components that only need to render when the
The following example adds a new Inspector panel for all blocks, but only when a block is selected.
```js
-const withMyPluginControls = createHigherOrderComponent( ( BlockEdit ) => {
- return ( props ) => {
- return (
- <>
-
- { props.isSelected && (
-
- My custom control
-
- ) }
- >
- );
- };
-}, 'withMyPluginControls' );
+const withMyPluginControls = createHigherOrderComponent((BlockEdit) => {
+ return (props) => {
+ return (
+ <>
+
+ {props.isSelected && (
+
+ My custom control
+
+ )}
+ >
+ );
+ };
+}, 'withMyPluginControls');
```
### `editor.BlockListBlock`
@@ -384,24 +376,16 @@ The following example adds a unique class name to all blocks.
```js
const { createHigherOrderComponent } = wp.compose;
-const withClientIdClassName = createHigherOrderComponent(
- ( BlockListBlock ) => {
- return ( props ) => {
- return (
-
- );
- };
- },
- 'withClientIdClassName'
-);
+const withClientIdClassName = createHigherOrderComponent((BlockListBlock) => {
+ return (props) => {
+ return ;
+ };
+}, 'withClientIdClassName');
wp.hooks.addFilter(
- 'editor.BlockListBlock',
- 'my-plugin/with-client-id-class-name',
- withClientIdClassName
+ 'editor.BlockListBlock',
+ 'my-plugin/with-client-id-class-name',
+ withClientIdClassName
);
```
@@ -409,21 +393,17 @@ You can add new properties to the block's wrapper component using the `wrapperPr
```js
const { createHigherOrderComponent } = wp.compose;
-const withMyWrapperProp = createHigherOrderComponent( ( BlockListBlock ) => {
- return ( props ) => {
- const wrapperProps = {
- ...props.wrapperProps,
- 'data-my-property': 'the-value',
- };
- return ;
- };
-}, 'withMyWrapperProp' );
-
-wp.hooks.addFilter(
- 'editor.BlockListBlock',
- 'my-plugin/with-my-wrapper-prop',
- withMyWrapperProp
-);
+const withMyWrapperProp = createHigherOrderComponent((BlockListBlock) => {
+ return (props) => {
+ const wrapperProps = {
+ ...props.wrapperProps,
+ 'data-my-property': 'the-value',
+ };
+ return ;
+ };
+}, 'withMyWrapperProp');
+
+wp.hooks.addFilter('editor.BlockListBlock', 'my-plugin/with-my-wrapper-prop', withMyWrapperProp);
```
### `editor.postContentBlockTypes`
@@ -433,14 +413,14 @@ Used to modify the list of blocks that should be enabled even when used inside a
The following example enables the fictitious block `namespace/example`.
```js
-const addExampleBlockToPostContentBlockTypes = ( blockTypes ) => {
- return [ ...blockTypes, 'namespace/example' ];
+const addExampleBlockToPostContentBlockTypes = (blockTypes) => {
+ return [...blockTypes, 'namespace/example'];
};
wp.hooks.addFilter(
- 'editor.postContentBlockTypes',
- 'my-plugin/post-content-block-types',
- addExampleBlockToPostContentBlockTypes
+ 'editor.postContentBlockTypes',
+ 'my-plugin/post-content-block-types',
+ addExampleBlockToPostContentBlockTypes
);
```
@@ -457,9 +437,9 @@ Place the following code in a `my-plugin.js` file.
import { unregisterBlockType } from '@wordpress/blocks';
import domReady from '@wordpress/dom-ready';
-domReady( function () {
- unregisterBlockType( 'core/verse' );
-} );
+domReady(function () {
+ unregisterBlockType('core/verse');
+});
```
Then, load this script in the Editor using the following function.
@@ -469,17 +449,17 @@ Then, load this script in the Editor using the following function.
// my-plugin.php
function my_plugin_deny_list_blocks() {
- wp_enqueue_script(
- 'my-plugin-deny-list-blocks',
- plugins_url( 'my-plugin.js', __FILE__ ),
- array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' )
- );
+ wp_enqueue_script(
+ 'my-plugin-deny-list-blocks',
+ plugins_url( 'my-plugin.js', __FILE__ ),
+ array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' )
+ );
}
add_action( 'enqueue_block_editor_assets', 'my_plugin_deny_list_blocks' );
```
- When unregistering a block, there can be a race condition on which code runs first: registering the block or unregistering the block. You want your unregister code to run last. To do this, you must specify the component that is registering the block as a dependency, in this case, wp-edit-post. Additionally, using wp.domReady() ensures the unregister code runs once the dom is loaded.
+ When unregistering a block, there can be a race condition on which code runs first: registering the block or unregistering the block. You want your unregister code to run last. To do this, you must specify the component that is registering the block as a dependency, in this case, wp-edit-post. Additionally, using wp.domReady() ensures the unregister code runs once the dom is loaded.
### Using an allow list
@@ -489,18 +469,13 @@ If you want to disable all blocks except an allow list, you can adapt the script
```js
// my-plugin.js
-var allowedBlocks = [
- 'core/paragraph',
- 'core/image',
- 'core/html',
- 'core/freeform',
-];
-
-wp.blocks.getBlockTypes().forEach( function ( blockType ) {
- if ( allowedBlocks.indexOf( blockType.name ) === -1 ) {
- wp.blocks.unregisterBlockType( blockType.name );
- }
-} );
+var allowedBlocks = ['core/paragraph', 'core/image', 'core/html', 'core/freeform'];
+
+wp.blocks.getBlockTypes().forEach(function (blockType) {
+ if (allowedBlocks.indexOf(blockType.name) === -1) {
+ wp.blocks.unregisterBlockType(blockType.name);
+ }
+});
```
## Hiding blocks from the inserter
@@ -508,7 +483,7 @@ wp.blocks.getBlockTypes().forEach( function ( blockType ) {
### `allowed_block_types_all`
- Before WordPress 5.8, this hook was known as allowed_block_types, which is now deprecated. If you need to support older versions of WordPress, you might need a way to detect which filter should be used. You can check if allowed_block_types is safe to use by seeing if the WP_Block_Editor_Context class exists, which was introduced in 5.8.
+ Before WordPress 5.8, this hook was known as allowed_block_types, which is now deprecated. If you need to support older versions of WordPress, you might need a way to detect which filter should be used. You can check if allowed_block_types is safe to use by seeing if the WP_Block_Editor_Context class exists, which was introduced in 5.8.
On the server, you can filter the list of blocks shown in the inserter using the `allowed_block_types_all` filter. You can return either true (all block types supported), false (no block types supported), or an array of block type names to allow. You can also use the second provided parameter `$editor_context` to filter block types based on their content.
@@ -517,10 +492,10 @@ On the server, you can filter the list of blocks shown in the inserter using the
post ) ) {
- return array( 'core/paragraph', 'core/heading' );
- }
- return $allowed_block_types;
+ if ( ! empty( $editor_context->post ) ) {
+ return array( 'core/paragraph', 'core/heading' );
+ }
+ return $allowed_block_types;
}
add_filter( 'allowed_block_types_all', 'example_filter_allowed_block_types_when_post_provided', 10, 2 );
```
@@ -530,7 +505,7 @@ add_filter( 'allowed_block_types_all', 'example_filter_allowed_block_types_when_
### `block_categories_all`
- Before WordPress 5.8, this hook was known as block_categories, which is now deprecated. If you need to support older versions of WordPress, you might need a way to detect which filter should be used. You can check if block_categories is safe to use by seeing if the WP_Block_Editor_Context class exists, which was introduced in 5.8.
+ Before WordPress 5.8, this hook was known as block_categories, which is now deprecated. If you need to support older versions of WordPress, you might need a way to detect which filter should be used. You can check if block_categories is safe to use by seeing if the WP_Block_Editor_Context class exists, which was introduced in 5.8.
It is possible to filter the list of default block categories using the `block_categories_all` filter. You can do it on the server by implementing a function which returns a list of categories. It is going to be used during block registration and to group blocks in the inserter. You can also use the second provided parameter `$editor_context` to filter the based on its content.
@@ -538,17 +513,17 @@ It is possible to filter the list of default block categories using the `block_c
```php
// my-plugin.php
function example_filter_block_categories_when_post_provided( $block_categories, $editor_context ) {
- if ( ! empty( $editor_context->post ) ) {
- array_push(
- $block_categories,
- array(
- 'slug' => 'custom-category',
- 'title' => __( 'Custom Category', 'custom-plugin' ),
- 'icon' => null,
- )
- );
- }
- return $block_categories;
+ if ( ! empty( $editor_context->post ) ) {
+ array_push(
+ $block_categories,
+ array(
+ 'slug' => 'custom-category',
+ 'title' => __( 'Custom Category', 'custom-plugin' ),
+ 'icon' => null,
+ )
+ );
+ }
+ return $block_categories;
}
add_filter( 'block_categories_all', 'example_filter_block_categories_when_post_provided', 10, 2 );
```
@@ -562,22 +537,18 @@ You can also set a custom icon in SVG format. To do so, the icon should be rende
To set an SVG icon for the category shown in the previous example, add the following example JavaScript code to the Editor calling `wp.blocks.updateCategory` e.g:
```js
-( function () {
- var el = React.createElement;
- var SVG = wp.primitives.SVG;
- var circle = el( 'circle', {
- cx: 10,
- cy: 10,
- r: 10,
- fill: 'red',
- stroke: 'blue',
- strokeWidth: '10',
- } );
- var svgIcon = el(
- SVG,
- { width: 20, height: 20, viewBox: '0 0 20 20' },
- circle
- );
- wp.blocks.updateCategory( 'my-category', { icon: svgIcon } );
-} )();
+(function () {
+ var el = React.createElement;
+ var SVG = wp.primitives.SVG;
+ var circle = el('circle', {
+ cx: 10,
+ cy: 10,
+ r: 10,
+ fill: 'red',
+ stroke: 'blue',
+ strokeWidth: '10',
+ });
+ var svgIcon = el(SVG, { width: 20, height: 20, viewBox: '0 0 20 20' }, circle);
+ wp.blocks.updateCategory('my-category', { icon: svgIcon });
+})();
```
diff --git a/gutenberg/reference-guides/filters/editor-filters.md b/docs/gutenberg/reference-guides/filters/editor-filters.md
similarity index 81%
rename from gutenberg/reference-guides/filters/editor-filters.md
rename to docs/gutenberg/reference-guides/filters/editor-filters.md
index 08d1c5d..bb45a82 100644
--- a/gutenberg/reference-guides/filters/editor-filters.md
+++ b/docs/gutenberg/reference-guides/filters/editor-filters.md
@@ -7,7 +7,7 @@ WordPress exposes several APIs that allow you to modify the editor experience.
One of the most common ways to modify the Editor is through the [`block_editor_settings_all`](https://developer.wordpress.org/reference/hooks/block_editor_settings_all/) PHP filter, which is applied before settings are sent to the initialized Editor. This filter allows plugin and theme authors extensive control over how the Editor behaves.
- Before WordPress 5.8, this hook was known as block_editor_settings, which is now deprecated. If you need to support older versions of WordPress, you might need a way to detect which filter should be used. You can check if block_editor_settings is safe to use by seeing if the WP_Block_Editor_Context class exists, which was introduced in 5.8.
+ Before WordPress 5.8, this hook was known as block_editor_settings, which is now deprecated. If you need to support older versions of WordPress, you might need a way to detect which filter should be used. You can check if block_editor_settings is safe to use by seeing if the WP_Block_Editor_Context class exists, which was introduced in 5.8.
The `block_editor_settings_all` hook passes two parameters to the callback function:
@@ -21,17 +21,17 @@ The following example modifies the maximum upload file size. Add this to a plugi
add_filter( 'block_editor_settings_all', 'example_filter_block_editor_settings_when_post_provided', 10, 2 );
function example_filter_block_editor_settings_when_post_provided( $editor_settings, $editor_context ) {
- if ( ! empty( $editor_context->post ) ) {
- $editor_settings['maxUploadFileSize'] = 12345;
- }
- return $editor_settings;
+ if ( ! empty( $editor_context->post ) ) {
+ $editor_settings['maxUploadFileSize'] = 12345;
+ }
+ return $editor_settings;
}
```
There are dozens of editor settings, too many to list in this documentation article, but here are a few examples of what you can do with the `block_editor_settings_all` filter.
- To view all available settings, open the Editor and then open the console in your browser's Developer Tools. Enter the command wp.data.select( 'core/block-editor' ).getSettings() to display the current values for all Editor settings.
+ To view all available settings, open the Editor and then open the console in your browser's Developer Tools. Enter the command wp.data.select( 'core/block-editor' ).getSettings() to display the current values for all Editor settings.
### Restrict code editor access
@@ -44,14 +44,14 @@ If this setting is set to `false`, the user will not be able to switch between v
add_filter( 'block_editor_settings_all', 'example_restrict_code_editor' );
function example_restrict_code_editor( $settings ) {
- $can_active_plugins = current_user_can( 'activate_plugins' );
+ $can_active_plugins = current_user_can( 'activate_plugins' );
- // Disable the Code Editor for users that cannot activate plugins (Administrators).
- if ( ! $can_active_plugins ) {
- $settings[ 'codeEditingEnabled' ] = false;
- }
+ // Disable the Code Editor for users that cannot activate plugins (Administrators).
+ if ( ! $can_active_plugins ) {
+ $settings[ 'codeEditingEnabled' ] = false;
+ }
- return $settings;
+ return $settings;
}
```
@@ -69,8 +69,8 @@ Images are set to the `large` image size by default in the Editor. You can modif
add_filter( 'block_editor_settings_all', 'example_set_default_image_size' );
function example_set_default_image_size( $settings ) {
- $settings['imageDefaultSize'] = 'medium';
- return $settings;
+ $settings['imageDefaultSize'] = 'medium';
+ return $settings;
}
```
@@ -82,8 +82,8 @@ The [Openverse](https://openverse.org/) integration is enabled for all WordPress
add_filter( 'block_editor_settings_all', 'example_disable_openverse' );
function example_disable_openverse( $settings ) {
- $settings['enableOpenverseMediaCategory'] = false;
- return $settings;
+ $settings['enableOpenverseMediaCategory'] = false;
+ return $settings;
}
```
@@ -95,8 +95,8 @@ The Font Library allows users to install new fonts on their site, which is enabl
add_filter( 'block_editor_settings_all', 'example_disable_font_library' );
function example_disable_font_library( $settings ) {
- $settings['fontLibraryEnabled'] = false;
- return $settings;
+ $settings['fontLibraryEnabled'] = false;
+ return $settings;
}
```
@@ -108,8 +108,8 @@ Most blocks display [two tabs](https://make.wordpress.org/core/2023/03/07/introd
add_filter( 'block_editor_settings_all', 'example_disable_inspector_tabs_by_default' );
function example_disable_inspector_tabs_by_default( $settings ) {
- $settings['blockInspectorTabs'] = array( 'default' => false );
- return $settings;
+ $settings['blockInspectorTabs'] = array( 'default' => false );
+ return $settings;
}
```
@@ -119,13 +119,13 @@ You can also modify which blocks have inspector tabs. Here's an example that dis
add_filter( 'block_editor_settings_all', 'example_disable_tabs_for_my_custom_block' );
function example_disable_tabs_for_my_custom_block( $settings ) {
- $current_tab_settings = _wp_array_get( $settings, array( 'blockInspectorTabs' ), array() );
- $settings['blockInspectorTabs'] = array_merge(
- $current_tab_settings,
- array( 'my-plugin/my-custom-block' => false )
- );
+ $current_tab_settings = _wp_array_get( $settings, array( 'blockInspectorTabs' ), array() );
+ $settings['blockInspectorTabs'] = array_merge(
+ $current_tab_settings,
+ array( 'my-plugin/my-custom-block' => false )
+ );
- return $settings;
+ return $settings;
}
```
@@ -156,15 +156,11 @@ You can use this filter to modify the image size displayed in the Post Featured
```js
import { addFilter } from '@wordpress/hooks';
-const withImageSize = function ( size, mediaId, postId ) {
- return 'large';
+const withImageSize = function (size, mediaId, postId) {
+ return 'large';
};
-addFilter(
- 'editor.PostFeaturedImage.imageSize',
- 'my-plugin/with-image-size',
- withImageSize
-);
+addFilter('editor.PostFeaturedImage.imageSize', 'my-plugin/with-image-size', withImageSize);
```
### `editor.PostPreview.interstitialMarkup`
@@ -175,13 +171,13 @@ You can also filter the interstitial message shown when generating previews. Her
import { addFilter } from '@wordpress/hooks';
const customPreviewMessage = function () {
- return 'Post preview is being generated!';
+ return 'Post preview is being generated!';
};
addFilter(
- 'editor.PostPreview.interstitialMarkup',
- 'my-plugin/custom-preview-message',
- customPreviewMessage
+ 'editor.PostPreview.interstitialMarkup',
+ 'my-plugin/custom-preview-message',
+ customPreviewMessage
);
```
@@ -195,17 +191,17 @@ One example of it in action is in the Image block's transform feature to allow c
import { addFilter } from '@wordpress/hooks';
addFilter(
- 'media.crossOrigin',
- 'my-plugin/with-cors-media',
- // The callback accepts a second `mediaSrc` argument which references
- // the url to actual foreign media, useful if you want to decide
- // the value of crossOrigin based upon it.
- ( crossOrigin, mediaSrc ) => {
- if ( mediaSrc.startsWith( 'https://example.com' ) ) {
- return 'use-credentials';
- }
- return crossOrigin;
- }
+ 'media.crossOrigin',
+ 'my-plugin/with-cors-media',
+ // The callback accepts a second `mediaSrc` argument which references
+ // the url to actual foreign media, useful if you want to decide
+ // the value of crossOrigin based upon it.
+ (crossOrigin, mediaSrc) => {
+ if (mediaSrc.startsWith('https://example.com')) {
+ return 'use-credentials';
+ }
+ return crossOrigin;
+ }
);
```
@@ -217,10 +213,10 @@ You can use [`block_editor_rest_api_preload_paths`](https://developer.wordpress.
add_filter( 'block_editor_rest_api_preload_paths', 'example_filter_block_editor_rest_api_preload_paths_when_post_provided', 10, 2 );
function example_filter_block_editor_rest_api_preload_paths_when_post_provided( $preload_paths, $editor_context ) {
- if ( ! empty( $editor_context->post ) ) {
- array_push( $preload_paths, array( '/wp/v2/blocks', 'OPTIONS' ) );
- }
- return $preload_paths;
+ if ( ! empty( $editor_context->post ) ) {
+ array_push( $preload_paths, array( '/wp/v2/blocks', 'OPTIONS' ) );
+ }
+ return $preload_paths;
}
```
@@ -235,13 +231,9 @@ You can use this action to get hold of the error object handled by the boundarie
```js
import { addAction } from '@wordpress/hooks';
-addAction(
- 'editor.ErrorBoundary.errorLogged',
- 'mu-plugin/error-capture-setup',
- ( error ) => {
- // Error is the exception's error object.
- // You can console.log it or send it to an external error-tracking tool.
- console.log ( error );
- }
-);
+addAction('editor.ErrorBoundary.errorLogged', 'mu-plugin/error-capture-setup', (error) => {
+ // Error is the exception's error object.
+ // You can console.log it or send it to an external error-tracking tool.
+ console.log(error);
+});
```
diff --git a/gutenberg/reference-guides/filters/global-styles-filters.md b/docs/gutenberg/reference-guides/filters/global-styles-filters.md
similarity index 70%
rename from gutenberg/reference-guides/filters/global-styles-filters.md
rename to docs/gutenberg/reference-guides/filters/global-styles-filters.md
index 59bbbfc..8a3bfb9 100644
--- a/gutenberg/reference-guides/filters/global-styles-filters.md
+++ b/docs/gutenberg/reference-guides/filters/global-styles-filters.md
@@ -15,28 +15,28 @@ This is how to pass a new color palette for the theme and disable the text color
```php
function wpdocs_filter_theme_json_theme( $theme_json ){
- $new_data = array(
- 'version' => 2,
- 'settings' => array(
- 'color' => array(
- 'text' => false,
- 'palette' => array( /* New palette */
- array(
- 'slug' => 'foreground',
- 'color' => 'black',
- 'name' => __( 'Foreground', 'theme-domain' ),
- ),
- array(
- 'slug' => 'background',
- 'color' => 'white',
- 'name' => __( 'Background', 'theme-domain' ),
- ),
- ),
- ),
- ),
- );
+ $new_data = array(
+ 'version' => 2,
+ 'settings' => array(
+ 'color' => array(
+ 'text' => false,
+ 'palette' => array( /* New palette */
+ array(
+ 'slug' => 'foreground',
+ 'color' => 'black',
+ 'name' => __( 'Foreground', 'theme-domain' ),
+ ),
+ array(
+ 'slug' => 'background',
+ 'color' => 'white',
+ 'name' => __( 'Background', 'theme-domain' ),
+ ),
+ ),
+ ),
+ ),
+ );
- return $theme_json->update_with( $new_data );
+ return $theme_json->update_with( $new_data );
}
add_filter( 'wp_theme_json_data_theme', 'wpdocs_filter_theme_json_theme' );
```
diff --git a/gutenberg/reference-guides/filters/i18n-filters.md b/docs/gutenberg/reference-guides/filters/i18n-filters.md
similarity index 51%
rename from gutenberg/reference-guides/filters/i18n-filters.md
rename to docs/gutenberg/reference-guides/filters/i18n-filters.md
index 0f37161..59028d1 100644
--- a/gutenberg/reference-guides/filters/i18n-filters.md
+++ b/docs/gutenberg/reference-guides/filters/i18n-filters.md
@@ -2,10 +2,10 @@
The i18n functions (`__()`, `_x()`, `_n()` and `_nx()`) provide translations of strings for use in your code. The values returned by these functions are filterable if you need to override them, using the following filters:
-- `i18n.gettext`
-- `i18n.gettext_with_context`
-- `i18n.ngettext`
-- `i18n.ngettext_with_context`
+- `i18n.gettext`
+- `i18n.gettext_with_context`
+- `i18n.ngettext`
+- `i18n.ngettext_with_context`
## Filter Arguments
@@ -14,39 +14,32 @@ The filters are passed the following arguments, in line with their PHP equivalen
### i18n.gettext
```jsx
-function i18nGettextCallback( translation, text, domain ) {
- return translation;
+function i18nGettextCallback(translation, text, domain) {
+ return translation;
}
```
### i18n.gettext_with_context
```jsx
-function i18nGettextWithContextCallback( translation, text, context, domain ) {
- return translation;
+function i18nGettextWithContextCallback(translation, text, context, domain) {
+ return translation;
}
```
### i18n.ngettext
```jsx
-function i18nNgettextCallback( translation, single, plural, number, domain ) {
- return translation;
+function i18nNgettextCallback(translation, single, plural, number, domain) {
+ return translation;
}
```
### i18n.ngettext_with_context
```jsx
-function i18nNgettextWithContextCallback(
- translation,
- single,
- plural,
- number,
- context,
- domain
-) {
- return translation;
+function i18nNgettextWithContextCallback(translation, single, plural, number, context, domain) {
+ return translation;
}
```
@@ -56,18 +49,18 @@ Here is a simple example, using the `i18n.gettext` filter to override a specific
```jsx
// Define our filter callback.
-function myPluginGettextFilter( translation, text, domain ) {
- if ( text === 'Create Reusable block' ) {
- return 'Save to MyOrg block library';
- }
- return translation;
+function myPluginGettextFilter(translation, text, domain) {
+ if (text === 'Create Reusable block') {
+ return 'Save to MyOrg block library';
+ }
+ return translation;
}
// Adding the filter
wp.hooks.addFilter(
- 'i18n.gettext',
- 'my-plugin/override-add-to-reusable-blocks-label',
- myPluginGettextFilter
+ 'i18n.gettext',
+ 'my-plugin/override-add-to-reusable-blocks-label',
+ myPluginGettextFilter
);
```
@@ -77,33 +70,33 @@ Filters that are specific to the text domain you're operating on are generally p
To attach to a text domain-specific filter append an underscore and the text-domain to the standard filter name. For example, if filtering a string where the text domain is "woocommerce", you would use one of the following filters:
-- `i18n.gettext_woocommerce`
-- `i18n.gettext_with_context_woocommerce`
-- `i18n.ngettext_woocommerce`
-- `i18n.ngettext_with_context_woocommerce`
+- `i18n.gettext_woocommerce`
+- `i18n.gettext_with_context_woocommerce`
+- `i18n.ngettext_woocommerce`
+- `i18n.ngettext_with_context_woocommerce`
For example:
```jsx
// Define our filter callback.
-function myPluginGettextFilter( translation, text, domain ) {
- if ( text === 'You’ve fulfilled all your orders' ) {
- return 'All packed up and ready to go. Good job!';
- }
- return translation;
+function myPluginGettextFilter(translation, text, domain) {
+ if (text === 'You’ve fulfilled all your orders') {
+ return 'All packed up and ready to go. Good job!';
+ }
+ return translation;
}
// Adding the filter
wp.hooks.addFilter(
- 'i18n.gettext_woocommerce',
- 'my-plugin/override-fulfilled-all-orders-text',
- myPluginGettextFilter
+ 'i18n.gettext_woocommerce',
+ 'my-plugin/override-fulfilled-all-orders-text',
+ myPluginGettextFilter
);
```
_Note_: To apply a filter where the text-domain is `undefined` (for example WordPress core strings), then use the name "default" to construct the filter name.
-- `i18n.gettext_default`
-- `i18n.gettext_with_context_default`
-- `i18n.ngettext_default`
-- `i18n.ngettext_with_context_default`
+- `i18n.gettext_default`
+- `i18n.gettext_with_context_default`
+- `i18n.ngettext_default`
+- `i18n.ngettext_with_context_default`
diff --git a/gutenberg/reference-guides/filters/parser-filters.md b/docs/gutenberg/reference-guides/filters/parser-filters.md
similarity index 100%
rename from gutenberg/reference-guides/filters/parser-filters.md
rename to docs/gutenberg/reference-guides/filters/parser-filters.md
diff --git a/gutenberg/reference-guides/interactivity-api/README.md b/docs/gutenberg/reference-guides/interactivity-api/README.md
similarity index 61%
rename from gutenberg/reference-guides/interactivity-api/README.md
rename to docs/gutenberg/reference-guides/interactivity-api/README.md
index 87070d6..702948a 100644
--- a/gutenberg/reference-guides/interactivity-api/README.md
+++ b/docs/gutenberg/reference-guides/interactivity-api/README.md
@@ -16,17 +16,17 @@ For more information about the genesis of the Interactivity API, check out the [
Use the following links to locate the topic you're interested in. If you have never worked with the Interactivity API before, consider reading through the following resources in the order listed.
-- **[Requirements](#requirements-of-the-interactivity-api):** Check this section before you start creating your interactive blocks with the Interactivity API.
-- **[Quick Start Guide](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-quick-start-guide/):** Get a custom block using the Interactivity API up and running in less than one minute.
-- **[Tutorial: A first look at the Interactivity API](https://developer.wordpress.org/news/2024/04/11/a-first-look-at-the-interactivity-api/)** This article from the [WordPress Developer Blog](https://developer.wordpress.org/news/) is a great way to get introduced to the Interactivity API.
-- **[Core Concepts](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/core-concepts/)** Gain a better understanding of concepts and mental models related to Interactivity API development from this section.
-- **[API Reference](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/api-reference/):** To take a deep dive into how the API works internally, the list of Directives, and how the Store works.
-- **[Docs and Examples](#docs-examples):** Additional resources to learn/read more about the Interactivity API.
+- **[Requirements](#requirements-of-the-interactivity-api):** Check this section before you start creating your interactive blocks with the Interactivity API.
+- **[Quick Start Guide](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-quick-start-guide/):** Get a custom block using the Interactivity API up and running in less than one minute.
+- **[Tutorial: A first look at the Interactivity API](https://developer.wordpress.org/news/2024/04/11/a-first-look-at-the-interactivity-api/)** This article from the [WordPress Developer Blog](https://developer.wordpress.org/news/) is a great way to get introduced to the Interactivity API.
+- **[Core Concepts](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/core-concepts/)** Gain a better understanding of concepts and mental models related to Interactivity API development from this section.
+- **[API Reference](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/api-reference/):** To take a deep dive into how the API works internally, the list of Directives, and how the Store works.
+- **[Docs and Examples](#docs-examples):** Additional resources to learn/read more about the Interactivity API.
To get a deeper understanding of what the Interactivity API is or find answers to questions you may have about this standard, check the following resources:
-- **[About the Interactivity API](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-about/):** To learn more about the API Goals and the reasoning behind the use of a standard to add interactivity to blocks.
-- **[Frequently Asked Questions](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-faq/):** To find responses to some frequently asked questions about the technology behind and alternatives.
+- **[About the Interactivity API](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-about/):** To learn more about the API Goals and the reasoning behind the use of a standard to add interactivity to blocks.
+- **[Frequently Asked Questions](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/iapi-faq/):** To find responses to some frequently asked questions about the technology behind and alternatives.
## Requirements of the Interactivity API
@@ -34,9 +34,9 @@ Interactivity API is included in Core in WordPress 6.5. For versions below, you'
It’s also important to highlight that the block creation workflow doesn’t change, and all the [prerequisites](https://developer.wordpress.org/block-editor/getting-started/devenv/) remain the same. These include:
-- [Code Editor](https://developer.wordpress.org/block-editor/getting-started/devenv/#code-editor)
-- [Node.js development tools](https://developer.wordpress.org/block-editor/getting-started/devenv/#node-js-development-tools)
-- [Local WordPress environment (site)](https://developer.wordpress.org/block-editor/getting-started/devenv/#local-wordpress-environment)
+- [Code Editor](https://developer.wordpress.org/block-editor/getting-started/devenv/#code-editor)
+- [Node.js development tools](https://developer.wordpress.org/block-editor/getting-started/devenv/#node-js-development-tools)
+- [Local WordPress environment (site)](https://developer.wordpress.org/block-editor/getting-started/devenv/#local-wordpress-environment)
You can start creating interactions once you set up a block development environment and run WordPress 6.5+ (or Gutenberg 17.5+).
@@ -88,9 +88,9 @@ The use of `viewScriptModule` also requires the `--experimental-modules` flag fo
{
"scripts": {
...
- "build": "wp-scripts build --experimental-modules",
- "start": "wp-scripts start --experimental-modules"
- }
+ "build": "wp-scripts build --experimental-modules",
+ "start": "wp-scripts start --experimental-modules"
+ }
```
#### Add `wp-interactive` directive to a DOM element
@@ -99,7 +99,7 @@ To "activate" the Interactivity API in a DOM element (and its children), add the
```html
-
+
```
@@ -109,15 +109,15 @@ Refer to the [`wp-interactive` documentation](https://developer.wordpress.org/bl
Here you have some more resources to learn/read more about the Interactivity API:
-- [WordPress 6.5 Dev Note](https://make.wordpress.org/core/2024/03/04/interactivity-api-dev-note/)
-- [Merge announcement](https://make.wordpress.org/core/2024/02/19/merge-announcement-interactivity-api/)
-- [Proposal: The Interactivity API – A better developer experience in building interactive blocks](https://make.wordpress.org/core/2023/03/30/proposal-the-interactivity-api-a-better-developer-experience-in-building-interactive-blocks/)
-- [Interactivity API Discussions](https://github.com/WordPress/gutenberg/discussions/52882), especially the [showcase](https://github.com/WordPress/gutenberg/discussions/55642#discussioncomment-9667164) discussions.
-- [wpmovies.dev](https://wpmovies.dev/) demo and its [wp-movies-demo](https://github.com/WordPress/wp-movies-demo) repo
-- Examples using the Interactivity API at [block-development-examples](https://github.com/WordPress/block-development-examples):
- - [`my-first-interactive-block`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/my-first-interactive-block)
- - [`interactivity-api-countdown-3cd73e`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-countdown-3cd73e)
- - [`interactivity-api-quiz-1835fa`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-quiz-1835fa)
+- [WordPress 6.5 Dev Note](https://make.wordpress.org/core/2024/03/04/interactivity-api-dev-note/)
+- [Merge announcement](https://make.wordpress.org/core/2024/02/19/merge-announcement-interactivity-api/)
+- [Proposal: The Interactivity API – A better developer experience in building interactive blocks](https://make.wordpress.org/core/2023/03/30/proposal-the-interactivity-api-a-better-developer-experience-in-building-interactive-blocks/)
+- [Interactivity API Discussions](https://github.com/WordPress/gutenberg/discussions/52882), especially the [showcase](https://github.com/WordPress/gutenberg/discussions/55642#discussioncomment-9667164) discussions.
+- [wpmovies.dev](https://wpmovies.dev/) demo and its [wp-movies-demo](https://github.com/WordPress/wp-movies-demo) repo
+- Examples using the Interactivity API at [block-development-examples](https://github.com/WordPress/block-development-examples):
+ - [`my-first-interactive-block`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/my-first-interactive-block)
+ - [`interactivity-api-countdown-3cd73e`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-countdown-3cd73e)
+ - [`interactivity-api-quiz-1835fa`](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/interactivity-api-quiz-1835fa)
There's a Tracking Issue opened to ease the coordination of the work related to the Interactivity API Docs: Documentation for the Interactivity API - Tracking Issue #53296
diff --git a/gutenberg/reference-guides/interactivity-api/api-reference.md b/docs/gutenberg/reference-guides/interactivity-api/api-reference.md
similarity index 63%
rename from gutenberg/reference-guides/interactivity-api/api-reference.md
rename to docs/gutenberg/reference-guides/interactivity-api/api-reference.md
index c5ed0e8..d772a8a 100644
--- a/gutenberg/reference-guides/interactivity-api/api-reference.md
+++ b/docs/gutenberg/reference-guides/interactivity-api/api-reference.md
@@ -1,41 +1,32 @@
# API Reference
-
-Interactivity API is only available for WordPress 6.5 and above.
-
+> **Note:** Interactivity API is only available for WordPress 6.5 and above.
To add interactions to blocks using the Interactivity API, developers can use:
-- **Directives:** Added to the markup to add specific behavior to the DOM elements of the block
-- **Store:** Contains the logic and data (state, actions, side effects, etc.) needed for the behavior
+- **Directives:** Added to the markup to add specific behaviour to the DOM elements of the block
+- **Store:** Contains the logic and data (state, actions, side effects, etc.) needed for the behaviour
DOM elements are connected to data stored in the state and context through directives. If data in the state or context change directives will react to those changes, updating the DOM accordingly (see [diagram](https://excalidraw.com/#json=T4meh6lltJh6TCX51NTIu,DmIhxYSGFTL_ywZFbsmuSw)).
+DOM elements are connected to data stored in the state and context through directives. If data in the state or context change, directives will react to those changes, updating the DOM accordingly. See the [diagram](https://excalidraw.com/#json=T4meh6lltJh6TCX51NTIu,DmIhxYSGFTL_ywZFbsmuSw).
+

## What are directives?
-Directives are custom attributes that are added to the markup of your block to add behavior to its DOM elements. This can be done in the `render.php` file (for dynamic blocks) or the `save.js` file (for static blocks).
+Directives are custom attributes that are added to the markup of your block to add behaviour to its DOM elements. This can be done in the `render.php` file (for dynamic blocks) or the `save.js` file (for static blocks).
-Interactivity API directives use the `data-` prefix. Here's an example of directives used in HTML markup.
+Interactivity API directives use the `data-` prefix. Here's an example of directives used in HTML markup:
```html
-
-
-
- This element is now visible!
-
+
+
This element is now visible!
```
@@ -51,51 +42,38 @@ The `wp-interactive` directive "activates" the interactivity for the DOM element
```html
-
-
- I'm interactive now,
- and I can use directives!
-
-
-
- I'm also interactive,
- and I can also use directives!
-
-
+
+
+ I'm interactive now,
+ and I can use directives!
+
+
+
+ I'm also interactive,
+ and I can also use directives!
+
+
-
- I'm interactive now,
- and I can use directives!
-
-
-
- I'm also interactive,
- and I can also use directives!
-
-
+
+ I'm interactive now,
+ and I can use directives!
+
+
+
+ I'm also interactive,
+ and I can also use directives!
+
+
```
-
- The use of data-wp-interactive is a requirement for the Interactivity API "engine" to work. In the following examples the data-wp-interactive has not been added for the sake of simplicity. Also, the data-wp-interactive directive will be injected automatically in the future.
-
+> **Info:** The use of `data-wp-interactive` is a requirement for the Interactivity API "engine" to work. In the following examples the `data-wp-interactive` has not been added for the sake of simplicity. Also, the `data-wp-interactive` directive will be injected automatically in the future.
### `wp-context`
@@ -116,14 +94,14 @@ The `wp-context` directive accepts a stringified JSON as a value.
See store used with the directive above
```js
-store( 'myPlugin', {
- actions: {
- logId: () => {
- const { post } = getContext();
- console.log( post.id );
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ logId: () => {
+ const { post } = getContext();
+ console.log(post.id);
+ },
+ },
+});
```
@@ -132,15 +110,15 @@ Different contexts can be defined at different levels, and deeper levels will me
```html
-
+
-
-
+
+
-
-
-
-
+
+
+
+
```
@@ -150,18 +128,15 @@ This directive allows setting HTML attributes on elements based on a boolean or
```html
-
-
- Title
-
- SUBMENU ITEMS
-
-
+
+
+ Title
+
+ SUBMENU ITEMS
+
+
```
@@ -169,34 +144,34 @@ This directive allows setting HTML attributes on elements based on a boolean or
See store used with the directive above
```js
-store( 'myPlugin', {
- actions: {
- toggleMenu: () => {
- const context = getContext();
- context.isMenuOpen = ! context.isMenuOpen;
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ toggleMenu: () => {
+ const context = getContext();
+ context.isMenuOpen = !context.isMenuOpen;
+ },
+ },
+});
```
The `wp-bind` directive is executed:
-- When the element is created
-- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference)
+- When the element is created
+- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference)
When `wp-bind` directive references a callback to get its final value:
-- The `wp-bind` directive will be executed each time there's a change on any of the properties of the `state` or `context` used inside this callback.
-- The returned value in the callback function is used to change the value of the associated attribute.
+- The `wp-bind` directive will be executed each time there's a change on any of the properties of the `state` or `context` used inside this callback.
+- The returned value in the callback function is used to change the value of the associated attribute.
The `wp-bind` will do different things when the DOM element is applied, depending on its value:
-- If the value is `true`, the attribute is added: `
`
-- If the value is `false`, the attribute is removed: `
`
-- If the value is a string, the attribute is added with its value assigned: `
`
+- If the value is `true`, the attribute is added: `
`
+- If the value is `false`, the attribute is removed: `
`
+- If the value is a string, the attribute is added with its value assigned: `
`
### `wp-class`
@@ -204,20 +179,20 @@ This directive adds or removes a class to an HTML element, depending on a boolea
```html
-
- Option 1
-
-
- Option 2
-
+
+ Option 1
+
+
+ Option 2
+
```
@@ -225,22 +200,22 @@ This directive adds or removes a class to an HTML element, depending on a boolea
See store used with the directive above
```js
-store( 'myPlugin', {
- actions: {
- toggleSelection: () => {
- const context = getContext();
- context.isSelected = ! context.isSelected;
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ toggleSelection: () => {
+ const context = getContext();
+ context.isSelected = !context.isSelected;
+ },
+ },
+});
```
The `wp-class` directive is executed:
-- When the element is created
-- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference)
+- When the element is created
+- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference)
The boolean value received by the directive is used to toggle (add when `true` or remove when `false`) the associated class name from the `class` attribute.
@@ -251,24 +226,24 @@ So, for example, use the class name `is-dark` instead of `isDark` and `data-wp-c
```html
-
+
-
+
```
```css
/* Recommended */
.is-dark {
- /* ... */
+ /* ... */
}
/* Not recommended */
.isDark {
- /* ... */
+ /* ... */
}
```
@@ -278,10 +253,8 @@ This directive adds or removes inline style to an HTML element, depending on its
```html
-
-
Hello World!
+
+
Hello World!
>
```
@@ -290,27 +263,27 @@ This directive adds or removes inline style to an HTML element, depending on its
See store used with the directive above
```js
-store( 'myPlugin', {
- actions: {
- toggleContextColor: () => {
- const context = getContext();
- context.color = context.color === 'red' ? 'blue' : 'red';
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ toggleContextColor: () => {
+ const context = getContext();
+ context.color = context.color === 'red' ? 'blue' : 'red';
+ },
+ },
+});
```
The `wp-style` directive is executed:
-- When the element is created
-- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference)
+- When the element is created
+- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference)
The value received by the directive is used to add or remove the style attribute with the associated CSS property:
-- If the value is `false`, the style attribute is removed: `
`
-- If the value is a string, the attribute is added with its value assigned: `
`
+- If the value is `false`, the style attribute is removed: `
`
+- If the value is a string, the attribute is added with its value assigned: `
`
### `wp-text`
@@ -318,10 +291,8 @@ It sets the inner text of an HTML element.
```html
-
-
+
+
```
@@ -329,22 +300,22 @@ It sets the inner text of an HTML element.
See store used with the directive above
```js
-store( 'myPlugin', {
- actions: {
- toggleContextText: () => {
- const context = getContext();
- context.text = context.text === 'Text 1' ? 'Text 2' : 'Text 1';
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ toggleContextText: () => {
+ const context = getContext();
+ context.text = context.text === 'Text 1' ? 'Text 2' : 'Text 1';
+ },
+ },
+});
```
The `wp-text` directive is executed:
-- When the element is created
-- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference)
+- When the element is created
+- Each time there's a change on any of the properties of the `state` or `context` involved in getting the final value of the directive (inside the callback or the expression passed as reference)
The returned value is used to change the inner content of the element: `
value
`.
@@ -366,13 +337,13 @@ This directive runs code on dispatched DOM events like `click` or `keyup`. The s
See store used with the directive above
```js
-store( 'myPlugin', {
- actions: {
- logTime: ( event ) => {
- console.log( new Date() );
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ logTime: (event) => {
+ console.log(new Date());
+ },
+ },
+});
```
@@ -402,16 +373,16 @@ The syntax of this directive is `data-wp-on-window--[window-event]` (like `data-
```
- See store used with the directive above
+ See store used with the directive above
```js
-store( 'myPlugin', {
- callbacks: {
- logWidth() {
- console.log( 'Window width: ', window.innerWidth );
- },
- },
-} );
+store('myPlugin', {
+ callbacks: {
+ logWidth() {
+ console.log('Window width: ', window.innerWidth);
+ },
+ },
+});
```
@@ -439,16 +410,16 @@ The syntax of this directive is `data-wp-on-document--[document-event]` (like `d
```
- See store used with the directive above
+ See store used with the directive above
```js
-store( 'myPlugin', {
- callbacks: {
- logKeydown( event ) {
- console.log( 'Key pressed: ', event.key );
- },
- },
-} );
+store('myPlugin', {
+ callbacks: {
+ logKeydown(event) {
+ console.log('Key pressed: ', event.key);
+ },
+ },
+});
```
@@ -469,9 +440,9 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen
```html
-
Counter:
-
-
+
Counter:
+
+
```
@@ -479,41 +450,41 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen
See store used with the directive above
```js
-store( 'myPlugin', {
- actions: {
- increaseCounter: () => {
- const context = getContext();
- context.counter++;
- },
- decreaseCounter: () => {
- const context = getContext();
- context.counter--;
- },
- },
- callbacks: {
- logCounter: () => {
- const { counter } = getContext();
- console.log( 'Counter is ' + counter + ' at ' + new Date() );
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ increaseCounter: () => {
+ const context = getContext();
+ context.counter++;
+ },
+ decreaseCounter: () => {
+ const context = getContext();
+ context.counter--;
+ },
+ },
+ callbacks: {
+ logCounter: () => {
+ const { counter } = getContext();
+ console.log('Counter is ' + counter + ' at ' + new Date());
+ },
+ },
+});
```
The `wp-watch` directive is executed:
-- When the element is created
-- Each time that any of the properties of the `state` or `context` used inside the callback changes
+- When the element is created
+- Each time that any of the properties of the `state` or `context` used inside the callback changes
The `wp-watch` directive can return a function. If it does, the returned function is used as cleanup logic, i.e., it will run just before the callback runs again, and it will run again when the element is removed from the DOM.
As a reference, some use cases for this directive may be:
-- Logging
-- Changing the title of the page
-- Setting the focus on an element with `.focus()`.
-- Changing the state or context when certain conditions are met
+- Logging
+- Changing the title of the page
+- Setting the focus on an element with `.focus()`.
+- Changing the state or context when certain conditions are met
### `wp-init`
@@ -525,18 +496,15 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen
```html
-
Hi!
+
Hi!
```
Here's another example with several `wp-init` directives on the same DOM element.
```html
-
```
@@ -573,7 +541,7 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen
```html
-
Hi!
+
Hi!
```
@@ -581,42 +549,37 @@ The `unique-id` doesn't need to be unique globally. It just needs to be differen
See store used with the directive above
```js
-import {
- getElement,
- store,
- useState,
- useEffect,
-} from '@wordpress/interactivity';
+import { getElement, store, useState, useEffect } from '@wordpress/interactivity';
// Unlike `data-wp-init` and `data-wp-watch`, you can use any hooks inside
// `data-wp-run` callbacks.
const useInView = () => {
- const [ inView, setInView ] = useState( false );
- useEffect( () => {
- const { ref } = getElement();
- const observer = new IntersectionObserver( ( [ entry ] ) => {
- setInView( entry.isIntersecting );
- } );
- observer.observe( ref );
- return () => ref && observer.unobserve( ref );
- }, [] );
- return inView;
+ const [inView, setInView] = useState(false);
+ useEffect(() => {
+ const { ref } = getElement();
+ const observer = new IntersectionObserver(([entry]) => {
+ setInView(entry.isIntersecting);
+ });
+ observer.observe(ref);
+ return () => ref && observer.unobserve(ref);
+ }, []);
+ return inView;
};
-store( 'myPlugin', {
- callbacks: {
- logInView: () => {
- const isInView = useInView();
- useEffect( () => {
- if ( isInView ) {
- console.log( 'Inside' );
- } else {
- console.log( 'Outside' );
- }
- } );
- },
- },
-} );
+store('myPlugin', {
+ callbacks: {
+ logInView: () => {
+ const isInView = useInView();
+ useEffect(() => {
+ if (isInView) {
+ console.log('Inside');
+ } else {
+ console.log('Outside');
+ }
+ });
+ },
+ },
+});
```
@@ -631,8 +594,8 @@ The key should be a string that uniquely identifies the element among its siblin
```html
-
Item 1
-
Item 2
+
Item 1
+
Item 2
```
@@ -640,8 +603,8 @@ But it can also be used on other elements:
```html
```
@@ -657,9 +620,9 @@ For example, let's consider the following HTML.
```html
-
-
-
+
+
+
```
@@ -667,9 +630,9 @@ It would generate the following output:
```html
-
hello
-
hola
-
olá
+
hello
+
hola
+
olá
```
@@ -677,9 +640,9 @@ The prop that holds the item in the context can be changed by passing a suffix t
```html
-
-
-
+
+
+
```
@@ -689,7 +652,7 @@ For that, you must use `data-wp-each-key` in the `` tag and not `data-
```html
` tag and not `data-
]
}'
>
-
-
-
+
+
+
```
@@ -712,12 +672,12 @@ For server-side rendered lists, another directive called `data-wp-each-child` en
```html
-
-
-
-
hello
-
hola
-
olá
+
+
+
+
hello
+
hola
+
olá
```
@@ -728,21 +688,21 @@ The value assigned to a directive is a string pointing to a specific state, acti
In the following example, a getter is used to define the `state.isPlaying` derived value.
```js
-const { state } = store( 'myPlugin', {
- state: {
- currentVideo: '',
- get isPlaying() {
- return state.currentVideo !== '';
- },
- },
-} );
+const { state } = store('myPlugin', {
+ state: {
+ currentVideo: '',
+ get isPlaying() {
+ return state.currentVideo !== '';
+ },
+ },
+});
```
And then, the string value `"state.isPlaying"` is used to assign the result of this selector to `data-wp-bind--hidden`.
```html
-
+
```
@@ -754,9 +714,9 @@ The example below is getting `state.isPlaying` from `otherPlugin` instead of `my
```html
-
-
-
+
+
+
```
@@ -772,33 +732,33 @@ The store is used to create the logic (actions, side effects, etc.) linked to th
It defines data available to the HTML nodes of the page. It is important to differentiate between two ways to define the data:
-- **Global state**: It is defined using the `store()` function with the `state` property, and the data is available to all the HTML nodes of the page.
-- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children. It can be accessed using the `getContext` function inside of an action, derived state or side effect.
+- **Global state**: It is defined using the `store()` function with the `state` property, and the data is available to all the HTML nodes of the page.
+- **Context/Local State**: It is defined using the `data-wp-context` directive in an HTML node, and the data is available to that HTML node and its children. It can be accessed using the `getContext` function inside of an action, derived state or side effect.
```html
-
-
+
+
-
-
+
+
```
```js
-const { state } = store( 'myPlugin', {
- state: {
- someText: 'Hello Universe!',
- },
- actions: {
- someAction: () => {
- state.someText; // Access or modify global state - "Hello Universe!"
-
- const context = getContext();
- context.someText; // Access or modify local state (context) - "Hello World!"
- },
- },
-} );
+const { state } = store('myPlugin', {
+ state: {
+ someText: 'Hello Universe!',
+ },
+ actions: {
+ someAction: () => {
+ state.someText; // Access or modify global state - "Hello Universe!"
+
+ const context = getContext();
+ context.someText; // Access or modify local state (context) - "Hello World!"
+ },
+ },
+});
```
#### Actions
@@ -806,19 +766,19 @@ const { state } = store( 'myPlugin', {
Actions are just regular JavaScript functions. Usually triggered by the `data-wp-on` directive (using event listeners) or other actions.
```ts
-const { state, actions } = store( 'myPlugin', {
- actions: {
- selectItem: ( id ) => {
- const context = getContext();
- // `id` is optional here, so this action can be used in a directive.
- state.selected = id || context.id;
- },
- otherAction: () => {
- // but it can also be called from other actions.
- actions.selectItem( 123 ); // it works and type is correct
- },
- },
-} );
+const { state, actions } = store('myPlugin', {
+ actions: {
+ selectItem: (id) => {
+ const context = getContext();
+ // `id` is optional here, so this action can be used in a directive.
+ state.selected = id || context.id;
+ },
+ otherAction: () => {
+ // but it can also be called from other actions.
+ actions.selectItem(123); // it works and type is correct
+ },
+ },
+});
```
Async actions
@@ -831,46 +791,46 @@ Imagine a block that has two buttons. One lives inside a context that has `isOpe
```html
-
+
-
+
```
If the action is async and needs to await a long delay.
-- The user clicks the first button.
-- The scope points to the first context, where `isOpen: true`.
-- The first access to `state.isOpen` is correct because `getContext` returns the current scope.
-- The action starts awaiting a long delay.
-- Before the action resumes, the user clicks the second button.
-- The scope is changed to the second context, where `isOpen: false`.
-- The first access to `state.isOpen` is correct because `getContext` returns the current scope.
-- The second action starts awaiting a long delay.
-- The first action finishes awaiting and resumes its execution.
-- The second access to `state.isOpen` of the first action is incorrect, because `getContext` now returns the wrong scope.
+- The user clicks the first button.
+- The scope points to the first context, where `isOpen: true`.
+- The first access to `state.isOpen` is correct because `getContext` returns the current scope.
+- The action starts awaiting a long delay.
+- Before the action resumes, the user clicks the second button.
+- The scope is changed to the second context, where `isOpen: false`.
+- The first access to `state.isOpen` is correct because `getContext` returns the current scope.
+- The second action starts awaiting a long delay.
+- The first action finishes awaiting and resumes its execution.
+- The second access to `state.isOpen` of the first action is incorrect, because `getContext` now returns the wrong scope.
We need to be able to know when async actions start awaiting and resume operations, so we can restore the proper scope, and that's what generators do.
The store will work fine if it is written like this:
```js
-const { state } = store( 'myPlugin', {
- state: {
- get isOpen() {
- return getContext().isOpen;
- },
- },
- actions: {
- someAction: function* () {
- state.isOpen; // This context is correct because it's synchronous.
- yield longDelay(); // With generators, the caller controls when to resume this function.
- state.isOpen; // This context is correct because we restored the proper scope before we resumed the function.
- },
- },
-} );
+const { state } = store('myPlugin', {
+ state: {
+ get isOpen() {
+ return getContext().isOpen;
+ },
+ },
+ actions: {
+ someAction: function* () {
+ state.isOpen; // This context is correct because it's synchronous.
+ yield longDelay(); // With generators, the caller controls when to resume this function.
+ state.isOpen; // This context is correct because we restored the proper scope before we resumed the function.
+ },
+ },
+});
```
You may want to add multiple such `yield` points in your action if it is doing a lot of work.
@@ -882,20 +842,19 @@ To ensure that the action code does not contribute to a long task, you may manua
```js
import { splitTask } from '@wordpress/interactivity';
-store( 'myPlugin', {
- actions: {
- handleClick: withSyncEvent( function* ( event ) {
- event.preventDefault();
- yield splitTask();
- doTheWork();
- } ),
- },
-} );
+store('myPlugin', {
+ actions: {
+ handleClick: withSyncEvent(function* (event) {
+ event.preventDefault();
+ yield splitTask();
+ doTheWork();
+ }),
+ },
+});
```
You may notice the use of the [`withSyncEvent()`](#withsyncevent) utility function in this example. This is necessary due to an ongoing effort to handle store actions asynchronously by default, unless they require synchronous event access (which this example does due to the call to `event.preventDefault()`). Otherwise a deprecation warning will be triggered, and in a future release the behavior will change accordingly.
-
#### Side Effects
Automatically react to state changes. Usually triggered by `data-wp-watch` or `data-wp-init` directives.
@@ -906,22 +865,22 @@ They return a computed version of the state. They can access both `state` and `c
```js
// view.js
-const { state } = store( 'myPlugin', {
- state: {
- amount: 34,
- defaultCurrency: 'EUR',
- currencyExchange: {
- USD: 1.1,
- GBP: 0.85,
- },
- get amountInUSD() {
- return state.currencyExchange[ 'USD' ] * state.amount;
- },
- get amountInGBP() {
- return state.currencyExchange[ 'GBP' ] * state.amount;
- },
- },
-} );
+const { state } = store('myPlugin', {
+ state: {
+ amount: 34,
+ defaultCurrency: 'EUR',
+ currencyExchange: {
+ USD: 1.1,
+ GBP: 0.85,
+ },
+ get amountInUSD() {
+ return state.currencyExchange['USD'] * state.amount;
+ },
+ get amountInGBP() {
+ return state.currencyExchange['GBP'] * state.amount;
+ },
+ },
+});
```
### Accessing data in callbacks
@@ -929,68 +888,68 @@ const { state } = store( 'myPlugin', {
The **`store`** contains all the store properties, like `state`, `actions` or `callbacks`. They are returned by the `store()` call, so you can access them by destructuring it:
```js
-const { state, actions } = store( 'myPlugin', {
- // ...
-} );
+const { state, actions } = store('myPlugin', {
+ // ...
+});
```
The `store()` function can be called multiple times and all the store parts will be merged together:
```js
-store( 'myPlugin', {
- state: {
- someValue: 1,
- },
-} );
+store('myPlugin', {
+ state: {
+ someValue: 1,
+ },
+});
-const { state } = store( 'myPlugin', {
- actions: {
- someAction() {
- state.someValue; // = 1
- },
- },
-} );
+const { state } = store('myPlugin', {
+ actions: {
+ someAction() {
+ state.someValue; // = 1
+ },
+ },
+});
```
All store() calls with the same namespace return the same references, i.e., the same state, actions, etc., containing the result of merging all the store parts passed.
-- To access the context inside an action, derived state, or side effect, you can use the `getContext` function.
-- To access the reference, you can use the `getElement` function.
+- To access the context inside an action, derived state, or side effect, you can use the `getContext` function.
+- To access the reference, you can use the `getElement` function.
```js
-const { state } = store( 'myPlugin', {
- state: {
- get someDerivedValue() {
- const context = getContext();
- const { ref } = getElement();
- // ...
- },
- },
- actions: {
- someAction() {
- const context = getContext();
- const { ref } = getElement();
- // ...
- },
- },
- callbacks: {
- someEffect() {
- const context = getContext();
- const { ref } = getElement();
- // ...
- },
- },
-} );
+const { state } = store('myPlugin', {
+ state: {
+ get someDerivedValue() {
+ const context = getContext();
+ const { ref } = getElement();
+ // ...
+ },
+ },
+ actions: {
+ someAction() {
+ const context = getContext();
+ const { ref } = getElement();
+ // ...
+ },
+ },
+ callbacks: {
+ someEffect() {
+ const context = getContext();
+ const { ref } = getElement();
+ // ...
+ },
+ },
+});
```
This approach enables some functionalities that make directives flexible and powerful:
-- Actions and side effects can read and modify the state and the context.
-- Actions and state in blocks can be accessed by other blocks.
-- Actions and side effects can do anything a regular JavaScript function can do, like access the DOM or make API requests.
-- Side effects automatically react to state changes.
+- Actions and side effects can read and modify the state and the context.
+- Actions and state in blocks can be accessed by other blocks.
+- Actions and side effects can do anything a regular JavaScript function can do, like access the DOM or make API requests.
+- Side effects automatically react to state changes.
### Setting the store
@@ -1004,21 +963,21 @@ The `store` method used to set the store in JavaScript can be imported from `@wo
// store
import { store, getContext } from '@wordpress/interactivity';
-store( 'myPlugin', {
- actions: {
- toggle: () => {
- const context = getContext();
- context.isOpen = ! context.isOpen;
- },
- },
- callbacks: {
- logIsOpen: () => {
- const { isOpen } = getContext();
- // Log the value of `isOpen` each time it changes.
- console.log( `Is open: ${ isOpen }` );
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ toggle: () => {
+ const context = getContext();
+ context.isOpen = !context.isOpen;
+ },
+ },
+ callbacks: {
+ logIsOpen: () => {
+ const { isOpen } = getContext();
+ // Log the value of `isOpen` each time it changes.
+ console.log(`Is open: ${isOpen}`);
+ },
+ },
+});
```
#### On the server side
@@ -1034,7 +993,7 @@ _Example of store initialized from the server with a `state` = `{ someValue: 123
```php
// render.php
wp_interactivity_state( 'myPlugin', array (
- 'someValue' => get_some_value()
+ 'someValue' => get_some_value()
));
```
@@ -1056,33 +1015,33 @@ A given store namespace can be marked as private, thus preventing its content to
```js
const { state } = store(
- 'myPlugin/private',
- { state: { messages: [ 'private message' ] } },
- { lock: true }
+ 'myPlugin/private',
+ { state: { messages: ['private message'] } },
+ { lock: true }
);
// The following call throws an Error!
-store( 'myPlugin/private', {
- /* store part */
-} );
+store('myPlugin/private', {
+ /* store part */
+});
```
There is also a way to unlock private stores: instead of passing a boolean, you can use a string as the `lock` value. Such a string can then be used in subsequent `store()` calls to the same namespace to unlock its content. Only the code knowing the string lock will be able to unlock the protected store namespaced. This is useful for complex stores defined in multiple JS modules.
```js
const { state } = store(
- 'myPlugin/private',
- { state: { messages: [ 'private message' ] } },
- { lock: PRIVATE_LOCK }
+ 'myPlugin/private',
+ { state: { messages: ['private message'] } },
+ { lock: PRIVATE_LOCK }
);
// The following call works as expected.
store(
- 'myPlugin/private',
- {
- /* store part */
- },
- { lock: PRIVATE_LOCK }
+ 'myPlugin/private',
+ {
+ /* store part */
+ },
+ { lock: PRIVATE_LOCK }
);
```
@@ -1090,25 +1049,25 @@ store(
Apart from the store function, there are also some methods that allows the developer to access data on their store functions.
-- getContext()
- - getServerContext()
- - getServerState()
-- getElement()
+- getContext()
+ - getServerContext()
+ - getServerState()
+- getElement()
#### getContext()
Retrieves the context inherited by the element evaluating a function from the store. The returned value depends on the element and the namespace where the function calling `getContext()` exists. It can also take an optional namespace argument to retrieve the context of a specific interactive region.
```js
-const context = getContext( 'namespace' );
+const context = getContext('namespace');
```
-- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the context of the current interactive region.
+- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the context of the current interactive region.
```php
// render.php
-
+
```
@@ -1116,20 +1075,20 @@ const context = getContext( 'namespace' );
// store
import { store, getContext } from '@wordpress/interactivity';
-store( 'myPlugin', {
- actions: {
- log: () => {
- const context = getContext();
- // Logs "false"
- console.log( 'context => ', context.isOpen );
-
- // With namespace argument.
- const myPluginContext = getContext( 'myPlugin' );
- // Logs "false"
- console.log( 'myPlugin isOpen => ', myPluginContext.isOpen );
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ log: () => {
+ const context = getContext();
+ // Logs "false"
+ console.log('context => ', context.isOpen);
+
+ // With namespace argument.
+ const myPluginContext = getContext('myPlugin');
+ // Logs "false"
+ console.log('myPlugin isOpen => ', myPluginContext.isOpen);
+ },
+ },
+});
```
#### getServerContext()
@@ -1142,24 +1101,24 @@ This function is analogous to `getContext()`, but with 2 key differences:
The server context cannot be directly used in directives, but you can use callbacks to subscribe to its changes.
```js
-const serverContext = getServerContext( 'namespace' );
+const serverContext = getServerContext('namespace');
```
-- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the server context of the current interactive region.
+- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the server context of the current interactive region.
Example usage:
```js
-store( 'myPlugin', {
- callbacks: {
- updateServerContext() {
- const context = getContext();
- const serverContext = getServerContext();
- // Override some property with the new value that came from the server.
- context.overridableProp = serverContext.overridableProp;
- },
- },
-} );
+store('myPlugin', {
+ callbacks: {
+ updateServerContext() {
+ const context = getContext();
+ const serverContext = getServerContext();
+ // Override some property with the new value that came from the server.
+ context.overridableProp = serverContext.overridableProp;
+ },
+ },
+});
```
#### getServerState()
@@ -1171,23 +1130,23 @@ This function is serves the same purpose as `getServerContext()`, but it returns
The object returned is read-only, and includes the state defined in PHP with `wp_interactivity_state()`. When using [`actions.navigate()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/#actions) from [`@wordpress/interactivity-router`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/), the object returned by `getServerState()` is updated to reflect the changes in its properties, without affecting the state returned by `store()`. Directives can subscribe to those changes to update the state if needed.
```js
-const serverState = getServerState( 'namespace' );
+const serverState = getServerState('namespace');
```
-- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the server state of the current interactive region.
+- `namespace` (optional): A string that matches the namespace of an interactive region. If not provided, it retrieves the server state of the current interactive region.
Example usage:
```js
-const { state } = store( 'myStore', {
- callbacks: {
- updateServerState() {
- const serverState = getServerState();
- // Override some property with the new value that came from the server.
- state.overridableProp = serverState.overridableProp;
- },
- },
-} );
+const { state } = store('myStore', {
+ callbacks: {
+ updateServerState() {
+ const serverState = getServerState();
+ // Override some property with the new value that came from the server.
+ state.overridableProp = serverState.overridableProp;
+ },
+ },
+});
```
#### getElement()
@@ -1209,24 +1168,24 @@ Those attributes will contain the directives of that element. In the button exam
// store
import { store, getElement } from '@wordpress/interactivity';
-store( 'myPlugin', {
- actions: {
- log: () => {
- const element = getElement();
- // Logs attributes
- console.log( 'element attributes => ', element.attributes );
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ log: () => {
+ const element = getElement();
+ // Logs attributes
+ console.log('element attributes => ', element.attributes);
+ },
+ },
+});
```
The code will log:
```json
{
- "data-wp-on--click": 'actions.log',
- "children": ['Log'],
- "onclick": event => { evaluate(entry, event); }
+ "data-wp-on--click": 'actions.log',
+ "children": ['Log'],
+ "onclick": event => { evaluate(entry, event); }
}
```
@@ -1239,18 +1198,18 @@ When the Interactivity API runtime execute callbacks, the scope is set automatic
An example, where `actions.nextImage` would trigger an undefined error without the wrapper:
```js
-store( 'mySliderPlugin', {
- callbacks: {
- initSlideShow: () => {
- setInterval(
- withScope( () => {
- actions.nextImage();
- } ),
- 3_000
- );
- },
- },
-} );
+store('mySliderPlugin', {
+ callbacks: {
+ initSlideShow: () => {
+ setInterval(
+ withScope(() => {
+ actions.nextImage();
+ }),
+ 3_000
+ );
+ },
+ },
+});
```
### withSyncEvent()
@@ -1259,10 +1218,10 @@ Actions that require synchronous access to the `event` object need to use the `w
Only very specific event methods and properties require synchronous access, so it is advised to only use `withSyncEvent()` when necessary. The following event methods and properties require synchronous access:
-* `event.currentTarget`
-* `event.preventDefault()`
-* `event.stopImmediatePropagation()`
-* `event.stopPropagation()`
+- `event.currentTarget`
+- `event.preventDefault()`
+- `event.stopImmediatePropagation()`
+- `event.stopPropagation()`
Here is an example, where one action requires synchronous event access while the other actions do not:
@@ -1270,24 +1229,24 @@ Here is an example, where one action requires synchronous event access while the
// store
import { store, withSyncEvent } from '@wordpress/interactivity';
-store( 'myPlugin', {
- actions: {
- // `event.preventDefault()` requires synchronous event access.
- preventNavigation: withSyncEvent( ( event ) => {
- event.preventDefault();
- } ),
-
- // `event.target` does not require synchronous event access.
- logTarget: ( event ) => {
- console.log( 'event target => ', event.target );
- },
-
- // Not using `event` at all does not require synchronous event access.
- logSomething: () => {
- console.log( 'something' );
- },
- },
-} );
+store('myPlugin', {
+ actions: {
+ // `event.preventDefault()` requires synchronous event access.
+ preventNavigation: withSyncEvent((event) => {
+ event.preventDefault();
+ }),
+
+ // `event.target` does not require synchronous event access.
+ logTarget: (event) => {
+ console.log('event target => ', event.target);
+ },
+
+ // Not using `event` at all does not require synchronous event access.
+ logSomething: () => {
+ console.log('something');
+ },
+ },
+});
```
## Server functions
@@ -1304,7 +1263,7 @@ Consider it a global setting for interactions of a site, that won't be updated o
An example of setting:
```php
- wp_interactivity_config( 'myPlugin', array( 'showLikeButton' => is_user_logged_in() ) );
+ wp_interactivity_config( 'myPlugin', array( 'showLikeButton' => is_user_logged_in() ) );
```
An example of getting:
@@ -1335,36 +1294,36 @@ Here is an example of passing the WP Admin AJAX endpoint with a nonce.
// render.php
wp_interactivity_state(
- 'myPlugin',
- array(
- 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
- 'nonce' => wp_create_nonce( 'myPlugin_nonce' ),
- ),
+ 'myPlugin',
+ array(
+ 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'myPlugin_nonce' ),
+ ),
);
```
```js
// view.js
-const { state } = store( 'myPlugin', {
- actions: {
- *doSomething() {
- try {
- const formData = new FormData();
- formData.append( 'action', 'do_something' );
- formData.append( '_ajax_nonce', state.nonce );
-
- const data = yield fetch( state.ajaxUrl, {
- method: 'POST',
- body: formData,
- } ).then( ( response ) => response.json() );
- console.log( 'Server data!', data );
- } catch ( e ) {
- // Something went wrong!
- }
- },
- },
-} );
+const { state } = store('myPlugin', {
+ actions: {
+ *doSomething() {
+ try {
+ const formData = new FormData();
+ formData.append('action', 'do_something');
+ formData.append('_ajax_nonce', state.nonce);
+
+ const data = yield fetch(state.ajaxUrl, {
+ method: 'POST',
+ body: formData,
+ }).then((response) => response.json());
+ console.log('Server data!', data);
+ } catch (e) {
+ // Something went wrong!
+ }
+ },
+ },
+});
```
### wp_interactivity_process_directives
@@ -1396,8 +1355,8 @@ This function is the recommended way to print the `data-wp-context` attribute in
```php
$my_context = array(
- 'counter' => 0,
- 'isOpen' => true,
+ 'counter' => 0,
+ 'isOpen' => true,
);
?>
array( 'Apple', 'Banana', 'Cherry' )
- ));
- ```
+ }
+ ```
- If you are using local context, the initial values are defined with the `data-wp-context` directive itself, either by:
+- **2. Initialize the global state or local context**
- - Adding it directly to the HTML.
+ Then, you must initialize either the global state or the local context that will be used during the server-side rendering of the page.
- ```html
-
- ...
-
- ```
+ If you are using global state, you must use the `wp_interactivity_state` function:
- - Using the `wp_interactivity_data_wp_context` helper.
+ ```php
+ wp_interactivity_state( 'myFruitPlugin', array(
+ 'fruits' => array( 'Apple', 'Banana', 'Cherry' )
+ ));
+ ```
- ```php
- array( 'Apple', 'Banana', 'Cherry' ) );
- ?>
+ If you are using local context, the initial values are defined with the `data-wp-context` directive itself, either by:
+ - Adding it directly to the HTML.
-
>
- ...
-
- ```
+ ```html
+
+ ...
+
+ ```
-- **3. Define the interactive elements using directives**
+ - Using the `wp_interactivity_data_wp_context` helper.
- Next, you need to add the necessary directives to the HTML markup.
+ ```php
+ array( 'Apple', 'Banana', 'Cherry' ) );
+ ?>
- ```html
-
-
-
-
+
>
+ ...
```
- In this example:
+- **3. Define the interactive elements using directives**
- - The `data-wp-interactive` directive activates the interactivity for the DOM element and its children.
- - The `data-wp-each` directive is used to render a list of elements. The directive can be used in `` tags, with the value being a reference path to an array stored in the global state or the local context.
- - The `data-wp-text` directive sets the inner text of an HTML element. Here, it points to `context.item`, which is where the `data-wp-each` directive stores each item of the array.
+ Next, you need to add the necessary directives to the HTML markup.
+
+ ```html
+
+
+
+
+
+ ```
+
+ In this example:
+ - The `data-wp-interactive` directive activates the interactivity for the DOM element and its children.
+ - The `data-wp-each` directive is used to render a list of elements. The directive can be used in `` tags, with the value being a reference path to an array stored in the global state or the local context.
+ - The `data-wp-text` directive sets the inner text of an HTML element. Here, it points to `context.item`, which is where the `data-wp-each` directive stores each item of the array.
The exact same directives can also be used when using local context instead of global state. The only difference is that `data-wp-each` points to `context.fruits` instead of `state.fruits`:
```html
-
-
-
+
+
+
```
@@ -103,9 +101,9 @@ This is how the final HTML markup of the fruit list example would look like (dir
```html
-
Apple
-
Banana
-
Cherry
+
Apple
+
Banana
+
Cherry
```
@@ -124,51 +122,51 @@ Let's extend this example to include a button that the user can click to add a n
This new button has a `data-wp-on-async--click` directive that references `actions.addMango`, which is defined in our JavaScript store:
```javascript
-const { state } = store( 'myFruitPlugin', {
- actions: {
- addMango() {
- state.fruits.push( 'Mango' );
- },
- },
-} );
+const { state } = store('myFruitPlugin', {
+ actions: {
+ addMango() {
+ state.fruits.push('Mango');
+ },
+ },
+});
```
The same example would also work if you were using local context:
```javascript
-store( 'myFruitPlugin', {
- actions: {
- addMango() {
- const context = getContext();
- context.fruits.push( 'Mango' );
- },
- },
-} );
+store('myFruitPlugin', {
+ actions: {
+ addMango() {
+ const context = getContext();
+ context.fruits.push('Mango');
+ },
+ },
+});
```
Now, when the user clicks the "Add Mango" button:
-1. The `addMango` action is triggered.
-2. The `'Mango'` item is added to the `state.fruits` (or `context.fruits`) array.
-3. The Interactivity API automatically updates the DOM, adding a new `
` element for the new fruit.
+1. The `addMango` action is triggered.
+2. The `'Mango'` item is added to the `state.fruits` (or `context.fruits`) array.
+3. The Interactivity API automatically updates the DOM, adding a new `
` element for the new fruit.
```html
-
Apple
-
Banana
-
Cherry
-
Mango
+
Apple
+
Banana
+
Cherry
+
Mango
```
Remember: initializing the state on the client is not necessary when it has already been done on the server.
```javascript
-store( 'myFruitPlugin', {
- state: {
- fruits: [ 'Apple', 'Banana', 'Cherry' ], // This is not necessary!
- },
-} );
+store('myFruitPlugin', {
+ state: {
+ fruits: ['Apple', 'Banana', 'Cherry'], // This is not necessary!
+ },
+});
```
## Initializing the derived state in the server
@@ -182,72 +180,70 @@ _Please, visit the [Understanding global state, local context and derived state]
Let's imagine adding a button that can delete all fruits:
```html
-
+
```
```javascript
-const { state } = store( 'myFruitPlugin', {
- actions: {
- // ...
- deleteFruits() {
- state.fruits = [];
- },
- },
-} );
+const { state } = store('myFruitPlugin', {
+ actions: {
+ // ...
+ deleteFruits() {
+ state.fruits = [];
+ },
+ },
+});
```
Now, let's display a special message when there is no fruit. To do this, let's use a `data-wp-bind--hidden` directive that references a derived state called `state.hasFruits` to show/hide the message.
```html
-
-
-
-
-
-
No fruits, sorry!
+
+
+
+
+
+
No fruits, sorry!
```
The derived state `state.hasFruits` is defined on the client using a getter:
```javascript
-const { state } = store( 'myFruitPlugin', {
- state: {
- get hasFruits() {
- return state.fruits.length > 0;
- },
- },
- // ...
-} );
+const { state } = store('myFruitPlugin', {
+ state: {
+ get hasFruits() {
+ return state.fruits.length > 0;
+ },
+ },
+ // ...
+});
```
Up to this point, everything is fine in the client, and when we press the "Delete all fruits" button, the "No fruits, sorry!" message will be displayed. The problem is that since `state.hasFruits` is not defined on the server, the `hidden` attribute will not be part of the initial HTML, which means it will also be showing the message until JavaScript loads, causing not only confusion to the visitor, but also a layout shift when JavaScript finally loads and the message is hidden.
To fix this, you must define the initial value of the derived state in the server using `wp_interactivity_state`.
-- When the initial value is known and static, it can be defined directly:
+- When the initial value is known and static, it can be defined directly:
- ```php
- wp_interactivity_state( 'myFruitPlugin', array(
- 'fruits' => array( 'Apple', 'Banana', 'Cherry' ),
- 'hasFruits' => true
- ));
- ```
+ ```php
+ wp_interactivity_state( 'myFruitPlugin', array(
+ 'fruits' => array( 'Apple', 'Banana', 'Cherry' ),
+ 'hasFruits' => true
+ ));
+ ```
-- Or it can be defined by doing the necessary computations:
+- Or it can be defined by doing the necessary computations:
- ```php
- $fruits = array( 'Apple', 'Banana', 'Cherry' );
- $hasFruits = count( $fruits ) > 0;
+ ```php
+ $fruits = array( 'Apple', 'Banana', 'Cherry' );
+ $hasFruits = count( $fruits ) > 0;
- wp_interactivity_state( 'myFruitPlugin', array(
- 'fruits' => $fruits,
- 'hasFruits' => $hasFruits,
- ));
- ```
+ wp_interactivity_state( 'myFruitPlugin', array(
+ 'fruits' => $fruits,
+ 'hasFruits' => $hasFruits,
+ ));
+ ```
Regardless of the approach, the key point is that the initial value of `state.hasFruits` is now defined on the server. This allows the Server Directive Processing to handle the `data-wp-bind--hidden` directive and modify the HTML markup, adding the `hidden` attribute when needed.
@@ -269,27 +265,27 @@ wp_interactivity_state( 'myFruitPlugin', array(
Now, let's add a derived state on the client that checks if each fruit is on the shopping list or not and returns the emoji.
```javascript
-store( 'myFruitPlugin', {
- state: {
- get onShoppingList() {
- const context = getContext();
- return state.shoppingList.includes( context.item ) ? '🛒' : '';
- },
- },
- // ...
-} );
+store('myFruitPlugin', {
+ state: {
+ get onShoppingList() {
+ const context = getContext();
+ return state.shoppingList.includes(context.item) ? '🛒' : '';
+ },
+ },
+ // ...
+});
```
And let's use that derived state to show the appropriate emoji for each fruit.
```html
-
-
-
-
-
-
+
+
+
+
+
+
```
@@ -350,13 +346,13 @@ That's it! Since the Interactivity API works in PHP, you can add translations di
But wait, what happens with our `addMango` action? Remember, this action is defined only on JavaScript:
```javascript
-const { state } = store( 'myFruitPlugin', {
- actions: {
- addMango() {
- state.fruits.push( 'Mango' ); // Not translated!
- },
- },
-} );
+const { state } = store('myFruitPlugin', {
+ actions: {
+ addMango() {
+ state.fruits.push('Mango'); // Not translated!
+ },
+ },
+});
```
To fix this issue, you can use the `wp_interactivity_state` function to serialize the translated mango string and then access that value in your action.
@@ -369,14 +365,14 @@ wp_interactivity_state( 'myFruitPlugin', array(
```
```javascript
-const { state } = store( 'myFruitPlugin', {
- actions: {
- addMango() {
- // `state.mango` contains the 'Mango' string already translated.
- state.fruits.push( state.mango );
- },
- },
-} );
+const { state } = store('myFruitPlugin', {
+ actions: {
+ addMango() {
+ // `state.mango` contains the 'Mango' string already translated.
+ state.fruits.push(state.mango);
+ },
+ },
+});
```
Take into account that if your application is more dynamic, you could serialize an array with all the fruit translations and just work with _fruit keywords_ in your actions. For example:
@@ -416,7 +412,7 @@ const { state } = store( 'myFruitPlugin', {
```html
-
+
```
@@ -430,22 +426,22 @@ wp_interactivity_state( 'myPlugin', array(
```
```js
-const { state } = store( 'myPlugin', {
- actions: {
- *doSomething() {
- const formData = new FormData();
- formData.append( 'action', 'do_something' );
- formData.append( '_ajax_nonce', state.nonce );
-
- const data = yield fetch( state.ajaxUrl, {
- method: 'POST',
- body: formData,
- } ).then( ( response ) => response.json() );
-
- console.log( 'Server data', data );
- },
- },
-} );
+const { state } = store('myPlugin', {
+ actions: {
+ *doSomething() {
+ const formData = new FormData();
+ formData.append('action', 'do_something');
+ formData.append('_ajax_nonce', state.nonce);
+
+ const data = yield fetch(state.ajaxUrl, {
+ method: 'POST',
+ body: formData,
+ }).then((response) => response.json());
+
+ console.log('Server data', data);
+ },
+ },
+});
```
## Processing directives in classic themes
diff --git a/gutenberg/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md b/docs/gutenberg/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md
similarity index 55%
rename from gutenberg/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md
rename to docs/gutenberg/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md
index 4f167d4..decdf49 100644
--- a/gutenberg/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md
+++ b/docs/gutenberg/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md
@@ -12,68 +12,62 @@ In the early days of web development, the imperative approach was predominant. T
Take, for example, this interactive block with two buttons and a paragraph:
-- **The show/hide button**: Toggles paragraph visibility and enables/disables the "Activate" button.
-- **The activate/deactivate button**: Toggles the paragraph's text and color between "active" (green) and "inactive" (red).
+- **The show/hide button**: Toggles paragraph visibility and enables/disables the "Activate" button.
+- **The activate/deactivate button**: Toggles the paragraph's text and color between "active" (green) and "inactive" (red).
```html
-
-
-
this is inactive
+
+
+
this is inactive
```
@@ -85,69 +79,69 @@ The declarative approach simplifies the process by focusing on _what_ should hap
```html
-
-
-
- this is inactive
-
+
+
+
+ this is inactive
+
```
```js
import { store } from '@wordpress/interactivity';
-const { state } = store( 'myInteractivePlugin', {
- state: {
- isVisible: false,
- isActive: false,
- get visibilityText() {
- return state.isVisible ? 'hide' : 'show';
- },
- get activationText() {
- return state.isActive ? 'deactivate' : 'activate';
- },
- get paragraphText() {
- return state.isActive ? 'this is active' : 'this is inactive';
- },
- },
- actions: {
- toggleVisibility() {
- state.isVisible = ! state.isVisible;
- if ( ! state.isVisible ) state.isActive = false;
- },
- toggleActivation() {
- state.isActive = ! state.isActive;
- },
- },
-} );
+const { state } = store('myInteractivePlugin', {
+ state: {
+ isVisible: false,
+ isActive: false,
+ get visibilityText() {
+ return state.isVisible ? 'hide' : 'show';
+ },
+ get activationText() {
+ return state.isActive ? 'deactivate' : 'activate';
+ },
+ get paragraphText() {
+ return state.isActive ? 'this is active' : 'this is inactive';
+ },
+ },
+ actions: {
+ toggleVisibility() {
+ state.isVisible = !state.isVisible;
+ if (!state.isVisible) state.isActive = false;
+ },
+ toggleActivation() {
+ state.isActive = !state.isActive;
+ },
+ },
+});
```
In this declarative example, the UI automatically updates based on the current state. All you have to do as developers is to declare the necessary state, any derived state, the actions that modify the state, and which parts of the DOM depend on which parts of the state. The framework takes care of making all the necessary updates to the DOM so that it is always in sync with the current state. The logic remains simple and maintainable regardless of the number of elements controlled by the framework.
@@ -178,12 +172,11 @@ The Interactivity API is a declarative framework thanks to its leverage of react
The Interactivity API uses a fine-grained reactivity system. Here's how it works:
1. **Reactive State**: In the Interactivity API, both the global state and the local context are reactive. This means that when either of these data sources changes, any parts of the UI that depend on them will automatically update.
+ - **Global state**: This is global data that can be accessed throughout your interactive blocks.
+ - **Local context**: This is local data that is specific to a particular element and its children.
+ - **Derived State**: In addition to basic state properties, you can define computed properties that automatically update when their dependencies change.
- - **Global state**: This is global data that can be accessed throughout your interactive blocks.
- - **Local context**: This is local data that is specific to a particular element and its children.
- - **Derived State**: In addition to basic state properties, you can define computed properties that automatically update when their dependencies change.
-
- _Please, visit the [Understanding global state, local context and derived state](/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md) guide to learn more about how to work with the different types of reactive state in the Interactivity API._
+ _Please, visit the [Understanding global state, local context and derived state](/docs/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md) guide to learn more about how to work with the different types of reactive state in the Interactivity API._
2. **Actions**: These are functions, usually triggered by event handlers, that mutate the global state or local context.
@@ -194,39 +187,39 @@ The Interactivity API uses a fine-grained reactivity system. Here's how it works
Let's break down these concepts by reviewing the previous example:
```javascript
-const { state } = store( 'myInteractivePlugin', {
- state: {
- isVisible: false,
- isActive: false,
- get visibilityText() {
- return state.isVisible ? 'hide' : 'show';
- },
- // ... other derived state
- },
- actions: {
- toggleVisibility() {
- state.isVisible = ! state.isVisible;
- },
- // ... other actions
- },
-} );
+const { state } = store('myInteractivePlugin', {
+ state: {
+ isVisible: false,
+ isActive: false,
+ get visibilityText() {
+ return state.isVisible ? 'hide' : 'show';
+ },
+ // ... other derived state
+ },
+ actions: {
+ toggleVisibility() {
+ state.isVisible = !state.isVisible;
+ },
+ // ... other actions
+ },
+});
```
In this code:
-- `isVisible` and `isActive` are basic state properties.
-- `visibilityText` is a derived state that automatically updates when `isVisible` changes.
-- `toggleVisibility` is an action that modifies the state.
+- `isVisible` and `isActive` are basic state properties.
+- `visibilityText` is a derived state that automatically updates when `isVisible` changes.
+- `toggleVisibility` is an action that modifies the state.
The HTML bindings look like this:
```html
```
@@ -235,9 +228,9 @@ Here's how reactivity works in practice:
1. When the button is clicked, it triggers the `toggleVisibility` action.
2. This action updates `state.isVisible`.
3. The Interactivity API detects this change and automatically:
- - Updates the button's text content (because of `data-wp-text="state.visibilityText"`).
- - Changes the `aria-expanded` attribute (due to `data-wp-bind--aria-expanded="state.isVisible"`).
- - Updates any other parts of the DOM that depend on `isVisible` or `visibilityText`.
+ - Updates the button's text content (because of `data-wp-text="state.visibilityText"`).
+ - Changes the `aria-expanded` attribute (due to `data-wp-bind--aria-expanded="state.isVisible"`).
+ - Updates any other parts of the DOM that depend on `isVisible` or `visibilityText`.
### Mutability vs immutability
@@ -246,20 +239,20 @@ Unlike many other reactive frameworks, **the Interactivity API does not require
For example, you can push a new item to an array like this:
```javascript
-const { state } = store( 'myArrayPlugin', {
- state: {
- list: [ 'item 1', 'item 2' ],
- },
- actions: {
- addItem() {
- // Right:
- state.list.push( 'new item' );
-
- // Wrong:
- state.list = [ ...state.list, 'new item' ]; // Don't do this!
- },
- },
-} );
+const { state } = store('myArrayPlugin', {
+ state: {
+ list: ['item 1', 'item 2'],
+ },
+ actions: {
+ addItem() {
+ // Right:
+ state.list.push('new item');
+
+ // Wrong:
+ state.list = [...state.list, 'new item']; // Don't do this!
+ },
+ },
+});
```
There's no need to create a new array or use the spread operator as you might in other frameworks. The Interactivity API will detect this change and update any parts of the UI that depend on `state.list`.
@@ -272,30 +265,30 @@ Here's an example of how you might use `data-wp-watch`:
```html
-
Counter:
-
+
Counter:
+
```
```javascript
-store( 'myCounterPlugin', {
- actions: {
- increment() {
- const context = getContext();
- context.counter += 1;
- },
- },
- callbacks: {
- logCounter: () => {
- const context = getContext();
- console.log( `The counter is now: ${ context.counter }` );
- },
- },
-} );
+store('myCounterPlugin', {
+ actions: {
+ increment() {
+ const context = getContext();
+ context.counter += 1;
+ },
+ },
+ callbacks: {
+ logCounter: () => {
+ const context = getContext();
+ console.log(`The counter is now: ${context.counter}`);
+ },
+ },
+});
```
In this example:
@@ -307,11 +300,11 @@ In this example:
This allows you to create declarative side effects that automatically run in response to data changes. Some other use cases for `data-wp-watch` might include:
-- Saving data to `localStorage` when the data changes.
-- Sending analytics events.
-- Changing the focus for accessibility purposes.
-- Updating the page title, meta tags, or `` attributes.
-- Triggering animations.
+- Saving data to `localStorage` when the data changes.
+- Sending analytics events.
+- Changing the focus for accessibility purposes.
+- Updating the page title, meta tags, or `` attributes.
+- Triggering animations.
## Conclusion
diff --git a/docs/gutenberg/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md b/docs/gutenberg/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md
new file mode 100644
index 0000000..98ab7d1
--- /dev/null
+++ b/docs/gutenberg/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md
@@ -0,0 +1,831 @@
+# Understanding global state, local context and derived state
+
+The Interactivity API offers a powerful framework for creating interactive blocks. To make the most of its capabilities, it's crucial to understand when to use global state, local context, or derived state. This guide will clarify these concepts and provide practical examples to help you decide when to use each one.
+
+Let's start with a brief definition of global state, local context and derived state.
+
+- **Global state:** Global data that can be accessed and modified by any interactive block on the page, allowing different parts of your interactive blocks to stay in sync.
+- **Local context:** Local data defined within a specific element in the HTML structure, accessible only to that element and its children, providing independent state for individual blocks.
+- **Derived state:** Computed values based on global state or local context, dynamically calculated on-demand to ensure consistent data representation without storing redundant data.
+
+Let's now dive into each of these concepts to study them in more detail and provide some examples.
+
+## Global state
+
+**Global state** in the Interactivity API refers to global data that can be accessed and modified by any interactive block on the page. It serves as a shared information hub, allowing different parts of your blocks to communicate and stay in sync. Global state is the ideal mechanism for exchanging information between interactive blocks, regardless of their position in the DOM tree.
+
+You should use global state when:
+
+- You need to share data between multiple interactive blocks that are not directly related in the DOM hierarchy.
+- You want to maintain a single source of truth for certain data across all your interactive blocks.
+- You're dealing with data that affects multiple parts of your UI simultaneously.
+- You want to implement features that are global for the page.
+
+### Working with global state
+
+- **Initializing the global state**
+
+ Typically, the initial global state values should be defined on the server using the `wp_interactivity_state` function:
+
+ ```php
+ // Populates the initial global state values.
+ wp_interactivity_state( 'myPlugin', array(
+ 'isDarkTheme' => true,
+ 'show' => false,
+ 'helloText' => __( 'world' ),
+ ));
+ ```
+
+ These initial global state values will be used during the rendering of the page in PHP to populate the HTML markup that is sent to the browser.
+ - HTML markup written in the PHP file by the developer:
+
+ ```html
+
+
+ Hello
+
+
+
+ ```
+
+ - HTML markup after the directives have been processed and it is ready to be sent to the browser:
+
+ ```html
+
+
+ Hello world
+
+
+
+ ```
+
+ _Please, visit [the Server-side Rendering guide](/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md) to learn more about how directives are processed on the server._
+
+ In cases where the global state is not used during the rendering of the page in PHP, it can also be defined directly on the client.
+
+ ```js
+ const { state } = store('myPlugin', {
+ state: {
+ isLoading: false,
+ },
+ actions: {
+ *loadSomething() {
+ state.isLoading = true;
+ // ...
+ },
+ },
+ });
+ ```
+
+ _Please note that, although this works, in general it is a good practice to define all the global state on the server._
+
+- **Accessing the global state**
+
+ In the HTML markup, you can access the global state values directly by referencing `state` in the directive attribute values:
+
+ ```html
+
+
+
+ ```
+
+ In JavaScript, the `store` function from the package at `@wordpress/interactivity` works both as a setter and a getter, returning the store of the selected namespace.
+
+ To access the global state in your actions and callbacks, you can use the `state` property of the object returned by the `store` function:
+
+ ```js
+ const myPluginStore = store('myPlugin');
+
+ myPluginStore.state; // This is the state of the 'myPlugin' namespace.
+ ```
+
+ You can also destructure the object returned by `store`:
+
+ ```js
+ const { state } = store('myPlugin');
+ ```
+
+ And you can do the same even if you are defining the store at that moment, which is the most common scenario:
+
+ ```js
+ const { state } = store('myPlugin', {
+ state: {
+ // ...
+ },
+ actions: {
+ toggle() {
+ state.show = !state.show;
+ },
+ },
+ });
+ ```
+
+ The global state initialized on the server using the `wp_interactivity_state` function is also included in that object because it is automatically serialized from the server to the client:
+
+ ```php
+ wp_interactivity_state( 'myPlugin', array(
+ 'someValue' => 1,
+ ));
+ ```
+
+ ```js
+ const { state } = store('myPlugin', {
+ state: {
+ otherValue: 2,
+ },
+ actions: {
+ readGlobalState() {
+ state.someValue; // It exists and its initial value is 1.
+ state.otherValue; // It exists and its initial value is 2.
+ },
+ },
+ });
+ ```
+
+ Lastly, all calls to the `store` function with the same namespace are merged together:
+
+ ```js
+ store('myPlugin', { state: { someValue: 1 } });
+
+ store('myPlugin', { state: { otherValue: 2 } });
+
+ /* All calls to `store` return a stable reference to the same object, so you
+ * can get a reference to `state` from any of them. */
+ const { state } = store('myPlugin');
+
+ store('myPlugin', {
+ actions: {
+ readValues() {
+ state.someValue; // It exists and its initial value is 1.
+ state.otherValue; // It exists and its initial value is 2.
+ },
+ },
+ });
+ ```
+
+- **Updating the global state**
+
+ To update the global state, all you need to do is mutate the `state` object once you have obtained it from the `store` function:
+
+ ```js
+ const { state } = store('myPlugin', {
+ actions: {
+ updateValues() {
+ state.someValue = 3;
+ state.otherValue = 4;
+ },
+ },
+ });
+ ```
+
+ Changes to the global state will automatically trigger updates in any directives that depend on the modified values.
+
+ _Please, visit [The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._
+
+### Example: Two interactive blocks using global state to communicate
+
+In this example, there are two independent interactive blocks. One displays a counter, and the other a button to increment that counter. These blocks can be positioned anywhere on the page, regardless of the HTML structure. In other words, one does not need to be an inner block of the other.
+
+- **Counter Block**
+
+ ```php
+ 0
+ ));
+ ?>
+
+
+ >
+ Counter:
+
+ ```
+
+- **Increment Block**
+
+ ```php
+
+ >
+
+
+ ```
+
+ ```js
+ const { state } = store('myCounterPlugin', {
+ actions: {
+ increment() {
+ state.counter += 1;
+ },
+ },
+ });
+ ```
+
+In this example:
+
+1. The global state is initialized on the server using `wp_interactivity_state`, setting an initial `counter` of 0.
+2. The Counter Block displays the current counter using `data-wp-text="state.counter"`, which reads from the global state.
+3. The Increment Block contains a button that triggers the `increment` action when clicked, using `data-wp-on-async--click="actions.increment"`.
+4. In JavaScript, the `increment` action directly modifies the global state by incrementing `state.counter`.
+
+Both blocks are independent and can be placed anywhere on the page. They don't need to be nested or directly related in the DOM structure. Multiple instances of these interactive blocks can be added to the page, and they will all share and update the same global counter value.
+
+## Local context
+
+**Local context** in the Interactivity API refers to local data defined within a specific element in the HTML structure. Unlike global state, local context is only accessible to the element where it's defined and its child elements.
+
+The local context is particularly useful when you need independent state for individual interactive blocks, ensuring that each instance of a block can maintain its own unique data without interfering with others.
+
+You should use local context when:
+
+- You need to maintain separate state for multiple instances of the same interactive block.
+- You want to encapsulate data that's only relevant to a specific interactive block and its children.
+- You need to implement features that are isolated to a specific part of your UI.
+
+### Working with local context
+
+- **Initializing the local context**
+
+ The local context is initialized directly within the HTML structure using the `data-wp-context` directive. This directive accepts a JSON string that defines the initial values for that piece of context.
+
+ ```html
+
+
+
+ ```
+
+ You can also initialize the local context on the server using the `wp_interactivity_data_wp_context` PHP helper, which ensures proper escaping and formatting of the stringified values:
+
+ ```php
+ 0 );
+ ?>
+
+
>
+
+
+ ```
+
+- **Accessing the local context**
+
+ In the HTML markup, you can access the local context values directly by referencing `context` in the directive values:
+
+ ```html
+
+
+
+ ```
+
+ In JavaScript, you can access the local context values using the `getContext` function:
+
+ ```js
+ store('myPlugin', {
+ actions: {
+ sendAnalyticsEvent() {
+ const { counter } = getContext();
+ myAnalyticsLibrary.sendEvent('updated counter', counter);
+ },
+ },
+ callbacks: {
+ logCounter() {
+ const { counter } = getContext();
+ console.log(`Current counter: ${counter}`);
+ },
+ },
+ });
+ ```
+
+ The `getContext` function returns the local context of the element that triggered the action/callback execution.
+
+- **Updating the local context**
+
+ To update the local context values in JavaScript, you can modify the object returned by `getContext`:
+
+ ```js
+ store('myPlugin', {
+ actions: {
+ increment() {
+ const context = getContext();
+ context.counter += 1;
+ },
+ updateName(event) {
+ const context = getContext();
+ context.name = event.target.value;
+ },
+ },
+ });
+ ```
+
+ Changes to the local context will automatically trigger updates in any directives that depend on the modified values.
+
+ _Please, visit [The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._
+
+- **Nesting local contexts**
+
+ Local contexts can be nested, with child contexts inheriting and potentially overriding values from parent contexts:
+
+ ```html
+
+
Theme:
+
Counter:
+
+
+
Theme:
+
Counter:
+
+
+ ```
+
+ In this example, the inner `div` will have a `theme` value of `"dark"`, but will inherit the `counter` value `0` from its parent context.
+
+### Example: One interactive block using local context to have independent state
+
+In this example, there is a single interactive block that shows a counter and can increment it. By using local context, each instance of this block will have its own independent counter, even if multiple blocks are added to the page.
+
+```php
+
+ data-wp-context='{ "counter": 0 }'
+>
+
Counter:
+
+
+```
+
+```js
+store('myCounterPlugin', {
+ actions: {
+ increment() {
+ const context = getContext();
+ context.counter += 1;
+ },
+ },
+});
+```
+
+In this example:
+
+1. A local context with an initial `counter` value of `0` is defined using the `data-wp-context` directive.
+2. The counter is displayed using `data-wp-text="context.counter"`, which reads from the local context.
+3. The increment button uses `data-wp-on-async--click="actions.increment"` to trigger the increment action.
+4. In JavaScript, the `getContext` function is used to access and modify the local context for each block instance.
+
+A user will be able to add multiple instances of this block to a page, and each will maintain its own independent counter. Clicking the "Increment" button on one block will only affect that specific block's counter and not the others.
+
+## Derived state
+
+**Derived state** in the Interactivity API refers to a value that is computed from other parts of the global state or local context. It's calculated on demand rather than stored. It ensures consistency, reduces redundancies, and enhances the declarative nature of your code.
+
+Derived state is a fundamental concept in modern state management, not unique to the Interactivity API. It's also used in other popular state management systems like Redux, where it's called `selectors`, or Preact Signals, where it's known as `computed` values.
+
+Derived state offers several key benefits that make it an essential part of a well-designed application state, including:
+
+1. **Single source of truth:** Derived state encourages you to store only the essential, raw data in your state. Any values that can be calculated from this core data become derived state. This approach reduces the risk of inconsistencies in your interactive blocks.
+
+2. **Automatic updates:** When you use derived state, values are recalculated automatically whenever the underlying data changes. This ensures that all parts of your interactive blocks always have access to the most up-to-date information without manual intervention.
+
+3. **Simplified state management:** By computing values on-demand rather than storing and updating them manually, you reduce the complexity of your state management logic. This leads to cleaner, more maintainable code.
+
+4. **Improved performance:** In many cases, derived state can be optimized to recalculate only when necessary, potentially improving your interactive blocks' performance.
+
+5. **Easier debugging:** With derived state, it's clearer where data originates and how it's transformed. This can make it easier to track down issues in your interactive blocks.
+
+In essence, derived state allows you to express relationships between different pieces of data in your interactive blocks declaratively, instead of imperatively updating related values whenever something changes.
+
+_Please, visit [The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) guide to learn more about how to leverage declarative coding in the Interactivity API._
+
+You should use derived state:
+
+- When a part of your global state or local context can be computed from other state values.
+- To avoid redundant data that needs to be manually kept in sync.
+- To ensure consistency across your interactive blocks by automatically updating derived values.
+- To simplify your actions by removing the need to update multiple related state properties.
+
+### Working with derived state
+
+- **Initializing the derived state**
+
+ Typically, the derived state should be initialized on the server using the `wp_interactivity_state` function in the exact same way as the global state.
+ - When the initial value is known and static, it can be defined directly:
+
+ ```php
+ wp_interactivity_state( 'myCounterPlugin', array(
+ 'counter' => 1, // This is global state.
+ 'double' => 2, // This is derived state.
+ ));
+ ```
+
+ - Or it can be defined by doing the necessary computations:
+
+ ```php
+ $counter = 1;
+ $double = $counter * 2;
+
+ wp_interactivity_state( 'myCounterPlugin', array(
+ 'counter' => $counter, // This is global state.
+ 'double' => $double, // This is derived state.
+ ));
+ ```
+
+ Regardless of the approach, the initial derived state values will be used during the rendering of the page in PHP, and the HTML can be populated with the correct values.
+
+ _Please, visit [the Server-side Rendering guide](/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md) to learn more about how directives are processed on the server._
+
+ The same mechanism applies even when the derived state property depends on the local context.
+
+ ```php
+ $counter );
+
+ wp_interactivity_state( 'myCounterPlugin', array(
+ 'double' => $counter * 2, // This is derived state.
+ ));
+ ?>
+
+
+ >
+
+ Counter:
+
+
+ Double:
+
+
+ ```
+
+ In JavaScript, the derived state is defined using getters:
+
+ ```js
+ const { state } = store('myCounterPlugin', {
+ state: {
+ get double() {
+ return state.counter * 2;
+ },
+ },
+ });
+ ```
+
+ Derived state can depend on local context, or local context and global state at the same time.
+
+ ```js
+ const { state } = store('myCounterPlugin', {
+ state: {
+ get double() {
+ const { counter } = getContext();
+ // Depends on local context.
+ return counter * 2;
+ },
+ get product() {
+ const { counter } = getContext();
+ // Depends on local context and global state.
+ return counter * state.factor;
+ },
+ },
+ });
+ ```
+
+ In some cases, when the derived state depends on the local context and the local context can change dynamically in the server, instead of the initial derived state, you can use a function (Closure) that calculates it dynamically.
+
+ ```php
+ array( 1, 2, 3 ),
+ 'factor' => 3,
+ 'product' => function() {
+ $state = wp_interactivity_state();
+ $context = wp_interactivity_get_context();
+ return $context['item'] * $state['factor'];
+ }
+ ));
+ ?>
+
+
+
+
+ ```
+
+ This `data-wp-each` template will render this HTML (directives omitted):
+
+ ```html
+ 3
+ 6
+ 9
+ ```
+
+- **Accessing the derived state**
+
+ In the HTML markup, the syntax for the derived state is the same as the one for the global state, just by referencing `state` in the directive attribute values.
+
+ ```html
+
+ ```
+
+ The same happens in JavaScript. Both global state and derived state can be consumed through the `state` property of the store:
+
+ ```js
+ const { state } = store('myCounterPlugin', {
+ // ...
+ actions: {
+ readValues() {
+ state.counter; // Regular state, returns 1.
+ state.double; // Derived state, returns 2.
+ },
+ },
+ });
+ ```
+
+ This lack of distinction is intentional, allowing developers to consume both derived and global state uniformly, and making them interchangeable in practice.
+
+ You can also access the derived state from another derived state and, thus, create multiple levels of computed values.
+
+ ```js
+ const { state } = store('myPlugin', {
+ state: {
+ get double() {
+ return state.counter * 2;
+ },
+ get doublePlusOne() {
+ return state.double + 1;
+ },
+ },
+ });
+ ```
+
+- **Updating the derived state**
+
+ The derived state cannot be updated directly. To update its values, you need to update the global state or local context on which that derived state depends.
+
+ ```js
+ const { state } = store('myCounterPlugin', {
+ // ...
+ actions: {
+ updateValues() {
+ state.counter; // Regular state, returns 1.
+ state.double; // Derived state, returns 2.
+
+ state.counter = 2;
+
+ state.counter; // Regular state, returns 2.
+ state.double; // Derived state, returns 4.
+ },
+ },
+ });
+ ```
+
+### Example: Not using derived state vs using derived state
+
+Let's consider a scenario where there is a counter and the double value needs to be displayed, and let's compare two approaches: one without derived state and one with derived state.
+
+- **Not using derived state**
+
+ ```js
+ const { state } = store('myCounterPlugin', {
+ state: {
+ counter: 1,
+ double: 2,
+ },
+ actions: {
+ increment() {
+ state.counter += 1;
+ state.double = state.counter * 2;
+ },
+ },
+ });
+ ```
+
+ In this approach, both the `state.counter` and `state.double` values are manually updated in the `increment` action. While this works, it has several drawbacks:
+ - It's less declarative.
+ - It can lead to bugs if `state.counter` is updated from multiple places and developers forget to keep `state.double` in sync.
+ - It requires more cognitive load to remember to update related values.
+
+- **Using derived state**
+
+ ```js
+ const { state } = store('myCounterPlugin', {
+ state: {
+ counter: 1,
+ get double() {
+ return state.counter * 2;
+ },
+ },
+ actions: {
+ increment() {
+ state.counter += 1;
+ },
+ },
+ });
+ ```
+
+ In this improved version:
+ - `state.double` is defined as a getter, automatically deriving its value from `state.counter`.
+ - The `increment` action only needs to update `state.counter`.
+ - `state.double` is always guaranteed to have the correct value, regardless of how or where `state.counter` is updated.
+
+### Example: Using derived state with local context
+
+Let's now consider a scenario where there is a local context that initializes a counter.
+
+```js
+store('myCounterPlugin', {
+ state: {
+ get double() {
+ const { counter } = getContext();
+ return counter * 2;
+ },
+ },
+ actions: {
+ increment() {
+ const context = getContext();
+ context.counter += 1;
+ },
+ },
+});
+```
+
+```html
+
+
+
+ Double:
+
+
+
+
+
+
+
+ Double:
+
+
+
+
+
+```
+
+In this example, the derived state `state.double` reads from the local context present in each element and returns the correct value for each instance where it is used.
+
+### Example: Using derived state with both local context and global state
+
+Let's now consider a scenario where there is a global tax rate and local product prices and calculate the final price, including tax.
+
+```html
+
+
Product Price: $
+
Tax Rate:
+
Price (inc. tax): $
+
+```
+
+```js
+const { state } = store('myProductPlugin', {
+ state: {
+ taxRate: 0.21,
+ get taxRatePercentage() {
+ return `${state.taxRate * 100}%`;
+ },
+ get priceWithTax() {
+ const { priceWithoutTax } = getContext();
+ return price * (1 + state.taxRate);
+ },
+ },
+ actions: {
+ updateTaxRate(event) {
+ // Updates the global tax rate.
+ state.taxRate = event.target.value;
+ },
+ updatePrice(event) {
+ // Updates the local product price.
+ const context = getContext();
+ context.priceWithoutTax = event.target.value;
+ },
+ },
+});
+```
+
+In this example, `priceWithTax` is derived from both the global `taxRate` and the local `priceWithoutTax`. Every time you update the global state or local context through the `updateTaxRate` or `updatePrice` actions, the Interactivity API recomputes the derived state and updates the necessary parts of the DOM.
+
+By using derived state, you create a more maintainable and less error-prone codebase. It ensures that related state values are always in sync, reduces the complexity of your actions, and makes your code more declarative and easier to reason about.
+
+## Subscribing to Server State and Context
+
+Interactivity API offers a region-based navigation feature that dynamically replaces a part of the page without a full page reload. The [Query block](/docs/reference-guides/core-blocks.md#query-loop) natively supports this feature when the `Force page reload` toggle is disabled. Developers can use the same functionality in custom blocks by calling [`actions.navigate()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/#actions) from the [`@wordpress/interactivity-router`](https://github.com/WordPress/gutenberg/tree/trunk/packages/interactivity-router) script module.
+
+When using region-based navigation, it's crucial to ensure that your interactive blocks stay in sync with the server-provided global state and local context. By default, the Interactivity API will never overwrite the global state or local context with the server-provided values. The Interactivity API provides two functions to help manage this synchronization: [`getServerState()`](/docs/reference-guides/interactivity-api/api-reference.md#getserverstate) and [`getServerContext()`](/docs/reference-guides/interactivity-api/api-reference.md#getservercontext).
+
+### `getServerState()`
+
+`getServerState()` allows you to subscribe to changes in the **global state** that occur during client-side navigation. This function is analogous to `getServerContext()`, but it works with the global state instead of the local context.
+
+The `getServerState()` function returns a read-only reactive object. This means that any [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) you have defined that watch the returned object will only trigger when the value returned by the function changes. If the value remains the same, the callback will not re-trigger.
+
+Let's consider a quiz that has multiple questions. Each question is a separate page. When the user navigates to a new question, the server provides the new question and the time left to answer all the questions.
+
+```php
+
get_question_for_page( get_the_ID() ),
+ 'timeLeft' => 5 * 60, // Time to answer all the questions.
+) ); ?>>
+```
+
+```javascript
+import { store, getServerState } from '@wordpress/interactivity';
+
+store('myPlugin', {
+ actions: {
+ // This action would be triggered by a directive, like:
+ //
+ *nextQuestion() {
+ event.preventDefault(event);
+ const { actions } = yield import('@wordpress/interactivity-router');
+ actions.navigate('/question-2');
+ },
+ },
+ callbacks: {
+ // This callback would be triggered by a directive, like:
+ //
+ updateQuestion() {
+ const serverState = getServerState();
+
+ // Update with the new value coming from the server.
+ // We DON'T want to update `timeLeft` because it represents the time left to answer ALL the questions.
+ state.question = serverState.question;
+ },
+ },
+});
+```
+
+### `getServerContext()`
+
+`getServerContext()` allows you to subscribe to changes in the **local context** that occur during client-side navigation. This function is analogous to `getServerState()`, but it works with the local context instead of the global state.
+
+The `getServerContext()` function returns a read-only reactive object. This means that any [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) you have defined that watch the returned object will only trigger when the value returned by the function changes. If the value remains the same, the callback will not re-trigger.
+
+Consider a quiz that has multiple questions. Each question is a separate page. When the user navigates to a new question, the server provides the new question and the time left to answer all the questions.
+
+```php
+
get_question_for_page( get_the_ID() ),
+), ); ?>>
+```
+
+```javascript
+import { store, getServerContext } from '@wordpress/interactivity';
+
+store('myPlugin', {
+ actions: {
+ // This action would be triggered by a directive, like:
+ //
+ *nextQuestion() {
+ event.preventDefault(event);
+ const { actions } = yield import('@wordpress/interactivity-router');
+ actions.navigate('/question-2');
+ },
+ },
+ callbacks: {
+ // This callback would be triggered by a directive, like:
+ //
+ updateQuestion() {
+ const serverContext = getServerContext();
+ const context = getContext();
+
+ // Update with the new value coming from the server.
+ context.currentQuestion = serverContext.currentQuestion;
+ },
+ },
+});
+```
+
+### When to Use
+
+Whenever you have interactive blocks that rely on global state or local context that may change due to navigation events, ensuring consistency across different parts of your application.
+
+### Best Practices for using `getServerState()` and `getServerContext()`
+
+- **Read-Only References:** Both `getServerState()` and `getServerContext()` return read-only objects. You can use those objects to update the global state or local context.
+- **Callback Integration:** Incorporate these functions within your store [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) to react to state and context changes. Both `getServerState()` and `getServerContext()` return reactive objects. This means that their watch callbacks will only trigger when the value of a property changes. If the value remains the same, the callback will not re-trigger.
+
+## Conclusion
+
+Remember, the key to effective state management is to keep your state minimal and avoid redundancy. Use derived state to compute values dynamically, and choose between global state and local context based on the scope and requirements of your data. This will lead to a cleaner, more robust architecture that is easier to debug and maintain. Finally, if you need to synchronize the state or context with the server, you can use `getServerState()` and `getServerContext()` to achieve this.
diff --git a/gutenberg/reference-guides/interactivity-api/core-concepts/using-typescript.md b/docs/gutenberg/reference-guides/interactivity-api/core-concepts/using-typescript.md
similarity index 68%
rename from gutenberg/reference-guides/interactivity-api/core-concepts/using-typescript.md
rename to docs/gutenberg/reference-guides/interactivity-api/core-concepts/using-typescript.md
index 256f000..866e77c 100644
--- a/gutenberg/reference-guides/interactivity-api/core-concepts/using-typescript.md
+++ b/docs/gutenberg/reference-guides/interactivity-api/core-concepts/using-typescript.md
@@ -4,10 +4,10 @@ The Interactivity API provides robust support for TypeScript, enabling developer
These are the core principles of TypeScript's interaction with the Interactivity API:
-- **Inferred client types**: When you create a store using the `store` function, TypeScript automatically infers the types of the store's properties (`state`, `actions`, etc.). This means that you can often get away with just writing plain JavaScript objects, and TypeScript will figure out the types for you.
-- **Explicit server types**: When dealing with data defined on the server, like local context or the initial values of the global state, you can explicitly define its types to ensure that everything is correctly typed.
-- **Multiple store parts**: Even if your store is split into multiple parts, you can define or infer the types of each part of the store and then merge them into a single type that represents the entire store.
-- **Typed external stores**: You can import typed stores from external namespaces, allowing you to use other plugins' functionality with type safety.
+- **Inferred client types**: When you create a store using the `store` function, TypeScript automatically infers the types of the store's properties (`state`, `actions`, etc.). This means that you can often get away with just writing plain JavaScript objects, and TypeScript will figure out the types for you.
+- **Explicit server types**: When dealing with data defined on the server, like local context or the initial values of the global state, you can explicitly define its types to ensure that everything is correctly typed.
+- **Multiple store parts**: Even if your store is split into multiple parts, you can define or infer the types of each part of the store and then merge them into a single type that represents the entire store.
+- **Typed external stores**: You can import typed stores from external namespaces, allowing you to use other plugins' functionality with type safety.
## Installing `@wordpress/interactivity` locally
@@ -39,9 +39,9 @@ Finally, you can keep following the instructions in the [Getting Started Guide](
Depending on the structure of your store and your preference, there are three options you can choose from to generate your store's types:
-1. Infer the types from your client store definition.
-2. Manually type the server state, but infer the rest from your client store definition.
-3. Manually write all the types.
+1. Infer the types from your client store definition.
+2. Manually type the server state, but infer the rest from your client store definition.
+3. Manually write all the types.
### 1. Infer the types from your client store definition
@@ -51,57 +51,57 @@ Let's start with a basic example of a counter block. We will define the store in
```ts
// view.ts
-const myStore = store( 'myCounterPlugin', {
- state: {
- counter: 0,
- },
- actions: {
- increment() {
- myStore.state.counter += 1;
- },
- },
- callbacks: {
- log() {
- console.log( `counter: ${ myStore.state.counter }` );
- },
- },
-} );
+const myStore = store('myCounterPlugin', {
+ state: {
+ counter: 0,
+ },
+ actions: {
+ increment() {
+ myStore.state.counter += 1;
+ },
+ },
+ callbacks: {
+ log() {
+ console.log(`counter: ${myStore.state.counter}`);
+ },
+ },
+});
```
If you inspect the types of `myStore` using TypeScript, you will see that TypeScript has been able to infer the types correctly.
```ts
const myStore: {
- state: {
- counter: number;
- };
- actions: {
- increment(): void;
- };
- callbacks: {
- log(): void;
- };
+ state: {
+ counter: number;
+ };
+ actions: {
+ increment(): void;
+ };
+ callbacks: {
+ log(): void;
+ };
};
```
You can also destructure the `state`, `actions` and `callbacks` properties, and the types will still work correctly.
```ts
-const { state } = store( 'myCounterPlugin', {
- state: {
- counter: 0,
- },
- actions: {
- increment() {
- state.counter += 1;
- },
- },
- callbacks: {
- log() {
- console.log( `counter: ${ state.counter }` );
- },
- },
-} );
+const { state } = store('myCounterPlugin', {
+ state: {
+ counter: 0,
+ },
+ actions: {
+ increment() {
+ state.counter += 1;
+ },
+ },
+ callbacks: {
+ log() {
+ console.log(`counter: ${state.counter}`);
+ },
+ },
+});
```
In conclusion, inferring the types is useful when you have a simple store defined in a single call to the `store` function and you do not need to type any state that has been initialized on the server.
@@ -116,7 +116,7 @@ Following our previous example, let's move our `counter` state initialization to
```php
wp_interactivity_state( 'myCounterPlugin', array(
- 'counter' => 1,
+ 'counter' => 1,
));
```
@@ -125,30 +125,30 @@ Now, let's define the server state types and merge it with the types inferred fr
```ts
// Types the server state.
type ServerState = {
- state: {
- counter: number;
- };
+ state: {
+ counter: number;
+ };
};
// Defines the store in a variable to be able to extract its type later.
const storeDef = {
- actions: {
- increment() {
- state.counter += 1;
- },
- },
- callbacks: {
- log() {
- console.log( `counter: ${ state.counter }` );
- },
- },
+ actions: {
+ increment() {
+ state.counter += 1;
+ },
+ },
+ callbacks: {
+ log() {
+ console.log(`counter: ${state.counter}`);
+ },
+ },
};
// Merges the types of the server state and the client store definition.
type Store = ServerState & typeof storeDef;
// Injects the final types when calling the `store` function.
-const { state } = store< Store >( 'myCounterPlugin', storeDef );
+const { state } = store('myCounterPlugin', storeDef);
```
Alternatively, if you don't mind typing the entire state including both the values defined on the server and the values defined on the client, you can cast the `state` property and let TypeScript infer the rest of the store.
@@ -157,20 +157,20 @@ Let's imagine you have an additional property in the client global state called
```ts
type State = {
- counter: number; // The server state.
- product: number; // The client state.
+ counter: number; // The server state.
+ product: number; // The client state.
};
-const { state } = store( 'myCounterPlugin', {
- state: {
- product: 2,
- } as State, // Casts the entire state manually.
- actions: {
- increment() {
- state.counter * state.product;
- },
- },
-} );
+const { state } = store('myCounterPlugin', {
+ state: {
+ product: 2,
+ } as State, // Casts the entire state manually.
+ actions: {
+ increment() {
+ state.counter * state.product;
+ },
+ },
+});
```
That's it. Now, TypeScript will infer the types of the `actions` and `callbacks` properties from the store definition, but it will use the type `State` for the `state` property so it contains the correct types from both the client and server definitions.
@@ -184,30 +184,30 @@ If you prefer to define all the types of the store manually instead of letting T
```ts
// Defines the store types.
interface Store {
- state: {
- counter: number; // Initial server state
- };
- actions: {
- increment(): void;
- };
- callbacks: {
- log(): void;
- };
+ state: {
+ counter: number; // Initial server state
+ };
+ actions: {
+ increment(): void;
+ };
+ callbacks: {
+ log(): void;
+ };
}
// Pass the types when calling the `store` function.
-const { state } = store< Store >( 'myCounterPlugin', {
- actions: {
- increment() {
- state.counter += 1;
- },
- },
- callbacks: {
- log() {
- console.log( `counter: ${ state.counter }` );
- },
- },
-} );
+const { state } = store('myCounterPlugin', {
+ actions: {
+ increment() {
+ state.counter += 1;
+ },
+ },
+ callbacks: {
+ log() {
+ console.log(`counter: ${state.counter}`);
+ },
+ },
+});
```
That's it! In conclusion, this approach is useful when you want to control all the types of your store and you don't mind writing them by hand.
@@ -225,19 +225,19 @@ For that reason, you need to define its type manually and pass it to the `getCon
```ts
// Defines the types of your context.
type MyContext = {
- counter: number;
+ counter: number;
};
-store( 'myCounterPlugin', {
- actions: {
- increment() {
- // Passes it to the getContext function.
- const context = getContext< MyContext >();
- // Now `context` is properly typed.
- context.counter += 1;
- },
- },
-} );
+store('myCounterPlugin', {
+ actions: {
+ increment() {
+ // Passes it to the getContext function.
+ const context = getContext();
+ // Now `context` is properly typed.
+ context.counter += 1;
+ },
+ },
+});
```
To avoid having to pass the context types over and over, you can also define a typed function and use that function instead of `getContext`.
@@ -245,22 +245,22 @@ To avoid having to pass the context types over and over, you can also define a t
```ts
// Defines the types of your context.
type MyContext = {
- counter: number;
+ counter: number;
};
// Defines a typed function. You only have to do this once.
-const getMyContext = getContext< MyContext >;
+const getMyContext = getContext;
-store( 'myCounterPlugin', {
- actions: {
- increment() {
- // Use your typed function.
- const context = getMyContext();
- // Now `context` is properly typed.
- context.counter += 1;
- },
- },
-} );
+store('myCounterPlugin', {
+ actions: {
+ increment() {
+ // Use your typed function.
+ const context = getMyContext();
+ // Now `context` is properly typed.
+ context.counter += 1;
+ },
+ },
+});
```
That's it! Now you can access the context properties with the correct types.
@@ -275,34 +275,34 @@ Following our previous example, let's create a derived state that is the double
```ts
type MyContext = {
- counter: number;
+ counter: number;
};
-const myStore = store( 'myCounterPlugin', {
- state: {
- get double() {
- const { counter } = getContext< MyContext >();
- return counter * 2;
- },
- },
- actions: {
- increment() {
- state.counter += 1; // This type is number.
- },
- },
-} );
+const myStore = store('myCounterPlugin', {
+ state: {
+ get double() {
+ const { counter } = getContext();
+ return counter * 2;
+ },
+ },
+ actions: {
+ increment() {
+ state.counter += 1; // This type is number.
+ },
+ },
+});
```
Normally, when the derived state depends on the local context, TypeScript will be able to infer the correct types:
```ts
const myStore: {
- state: {
- readonly double: number;
- };
- actions: {
- increment(): void;
- };
+ state: {
+ readonly double: number;
+ };
+ actions: {
+ increment(): void;
+ };
};
```
@@ -311,20 +311,20 @@ But when the return value of the derived state depends directly on some part of
For example, in this case, TypeScript cannot infer the type of `state.double` because it depends on `state.counter`, and the type of `state` is not completed until the type of `state.double` is defined, creating a circular reference.
```ts
-const { state } = store( 'myCounterPlugin', {
- state: {
- counter: 0,
- get double() {
- // TypeScript can't infer this return type because it depends on `state`.
- return state.counter * 2;
- },
- },
- actions: {
- increment() {
- state.counter += 1; // This type is now unknown.
- },
- },
-} );
+const { state } = store('myCounterPlugin', {
+ state: {
+ counter: 0,
+ get double() {
+ // TypeScript can't infer this return type because it depends on `state`.
+ return state.counter * 2;
+ },
+ },
+ actions: {
+ increment() {
+ state.counter += 1; // This type is now unknown.
+ },
+ },
+});
```
In this case, depending on your TypeScript configuration, TypeScript will either warn you about a circular reference or simply add the `any` type to the `state` property.
@@ -332,32 +332,32 @@ In this case, depending on your TypeScript configuration, TypeScript will either
However, solving this problem is easy; we simply need to manually provide TypeScript with the return type of that getter. Once we do that, the circular reference disappears, and TypeScript can once again infer all the `state` types.
```ts
-const { state } = store( 'myCounterPlugin', {
- state: {
- counter: 1,
- get double(): number {
- return state.counter * 2;
- },
- },
- actions: {
- increment() {
- state.counter += 1; // Correctly inferred!
- },
- },
-} );
+const { state } = store('myCounterPlugin', {
+ state: {
+ counter: 1,
+ get double(): number {
+ return state.counter * 2;
+ },
+ },
+ actions: {
+ increment() {
+ state.counter += 1; // Correctly inferred!
+ },
+ },
+});
```
These are now the correct inferred types for the previous store.
```ts
const myStore: {
- state: {
- counter: number;
- readonly double: number;
- };
- actions: {
- increment(): void;
- };
+ state: {
+ counter: number;
+ readonly double: number;
+ };
+ actions: {
+ increment(): void;
+ };
};
```
@@ -365,8 +365,8 @@ When using `wp_interactivity_state` in the server, remember that you also need t
```php
wp_interactivity_state( 'myCounterPlugin', array(
- 'counter' => 1,
- 'double' => 2,
+ 'counter' => 1,
+ 'double' => 2,
));
```
@@ -375,30 +375,30 @@ But if you are inferring the types, you don't need to manually define the type o
```ts
// You don't need to type `state.double` here.
type ServerState = {
- state: {
- counter: number;
- };
+ state: {
+ counter: number;
+ };
};
// The `state.double` type is inferred from here.
const storeDef = {
- state: {
- get double(): number {
- return state.counter * 2;
- },
- },
- actions: {
- increment() {
- state.counter += 1;
- },
- },
+ state: {
+ get double(): number {
+ return state.counter * 2;
+ },
+ },
+ actions: {
+ increment() {
+ state.counter += 1;
+ },
+ },
};
// Merges the types of the server state and the client store definition.
type Store = ServerState & typeof storeDef;
// Injects the final types when calling the `store` function.
-const { state } = store< Store >( 'myCounterPlugin', storeDef );
+const { state } = store('myCounterPlugin', storeDef);
```
That's it! Now you can access the derived state properties with the correct types.
@@ -412,38 +412,38 @@ The reason for using generators in the Interactivity API's asynchronous actions
Following our previous example, let's add an asynchronous action to the store.
```ts
-const { state } = store( 'myCounterPlugin', {
- state: {
- counter: 0,
- get double(): number {
- return state.counter * 2;
- },
- },
- actions: {
- increment() {
- state.counter += 1;
- },
- *delayedIncrement() {
- yield new Promise( ( r ) => setTimeout( r, 1000 ) );
- state.counter += 1;
- },
- },
-} );
+const { state } = store('myCounterPlugin', {
+ state: {
+ counter: 0,
+ get double(): number {
+ return state.counter * 2;
+ },
+ },
+ actions: {
+ increment() {
+ state.counter += 1;
+ },
+ *delayedIncrement() {
+ yield new Promise((r) => setTimeout(r, 1000));
+ state.counter += 1;
+ },
+ },
+});
```
The inferred types for this store are:
```ts
const myStore: {
- state: {
- counter: number;
- readonly double: number;
- };
- actions: {
- increment(): void;
- // This behaves like a regular async function.
- delayedIncrement(): Promise< void >;
- };
+ state: {
+ counter: number;
+ readonly double: number;
+ };
+ actions: {
+ increment(): void;
+ // This behaves like a regular async function.
+ delayedIncrement(): Promise;
+ };
};
```
@@ -451,8 +451,8 @@ This also means that you can use your async actions in external functions, and T
```ts
const someAsyncFunction = async () => {
- // This works fine and it's correctly typed.
- await actions.delayedIncrement( 2000 );
+ // This works fine and it's correctly typed.
+ await actions.delayedIncrement(2000);
};
```
@@ -460,14 +460,14 @@ When you are not inferring types but manually writing the types for your entire
```ts
type Store = {
- state: {
- counter: number;
- readonly double: number;
- };
- actions: {
- increment(): void;
- delayedIncrement(): Promise< void >; // You can use async functions here.
- };
+ state: {
+ counter: number;
+ readonly double: number;
+ };
+ actions: {
+ increment(): void;
+ delayedIncrement(): Promise; // You can use async functions here.
+ };
};
```
@@ -475,18 +475,18 @@ There's something to keep in mind when using asynchronous actions. Just like wit
```ts
const { state, actions } = store( 'myCounterPlugin', {
- state: {
- counter: 0,
- },
- actions: {
- *delayedOperation() {
- // Example: state.counter is used as part of the yielded logic.
- yield fetchCounterData( state.counter );
-
- // And/or the final return value depends on state.
- return state.counter + 1;
- },
- },
+ state: {
+ counter: 0,
+ },
+ actions: {
+ *delayedOperation() {
+ // Example: state.counter is used as part of the yielded logic.
+ yield fetchCounterData( state.counter );
+
+ // And/or the final return value depends on state.
+ return state.counter + 1;
+ },
+ },
} );
```
@@ -496,18 +496,18 @@ In such cases, TypeScript might issue a warning about a circular reference or de
import { store, type AsyncAction } from '@wordpress/interactivity';
const { state, actions } = store( 'myCounterPlugin', {
- state: {
- counter: 0,
- },
- actions: {
- *delayedOperation(): AsyncAction< number > {
- // Now, this doesn't cause a circular reference.
- yield fetchCounterData( state.counter );
-
- // Now, this is correctly typed.
- return state.counter + 1;
- },
- },
+ state: {
+ counter: 0,
+ },
+ actions: {
+ *delayedOperation(): AsyncAction< number > {
+ // Now, this doesn't cause a circular reference.
+ yield fetchCounterData( state.counter );
+
+ // Now, this is correctly typed.
+ return state.counter + 1;
+ },
+ },
} );
```
@@ -530,21 +530,21 @@ Suppose `fetchCounterData` returns a promise that resolves to an object:
};
const { state, actions } = store( 'myCounterPlugin', {
- state: {
- counter: 0,
- },
- actions: {
- *loadCounterData(): AsyncAction< void > {
- // Use TypeYield to correctly type the resolved value of the yield.
- const data = ( yield fetchCounterData( state.counter ) ) as TypeYield< typeof fetchCounterData >;
-
- // Now, `data` is correctly typed as { current: number, next: number }.
- console.log( data.current, data.next );
-
- // Update state based on the fetched data.
- state.counter = data.next;
- },
- },
+ state: {
+ counter: 0,
+ },
+ actions: {
+ *loadCounterData(): AsyncAction< void > {
+ // Use TypeYield to correctly type the resolved value of the yield.
+ const data = ( yield fetchCounterData( state.counter ) ) as TypeYield< typeof fetchCounterData >;
+
+ // Now, `data` is correctly typed as { current: number, next: number }.
+ console.log( data.current, data.next );
+
+ // Update state based on the fetched data.
+ state.counter = data.next;
+ },
+ },
} );
```
@@ -556,8 +556,8 @@ Sometimes, stores can be divided into different files. This can happen when diff
Let's look at an example of two blocks:
-- `todo-list`: A block that displays a list of todos.
-- `add-post-to-todo`: A block that shows a button to add a new todo item to the list with the text "Read {$post_title}".
+- `todo-list`: A block that displays a list of todos.
+- `add-post-to-todo`: A block that shows a button to add a new todo item to the list with the text "Read {$post_title}".
First, let's initialize the global and derived state of the `todo-list` block on the server.
@@ -580,32 +580,32 @@ Now, let's type the server state and add the client store definition. Remember,
```ts
// todo-list-block/view.ts
type ServerState = {
- state: {
- todos: string[];
- filter: 'all' | 'completed';
- };
+ state: {
+ todos: string[];
+ filter: 'all' | 'completed';
+ };
};
const todoList = {
- state: {
- get filteredTodos(): string[] {
- return state.filter === 'completed'
- ? state.todos.filter( ( todo ) => todo.includes( '✅' ) )
- : state.todos;
- },
- },
- actions: {
- addTodo( todo: string ) {
- state.todos.push( todo );
- },
- },
+ state: {
+ get filteredTodos(): string[] {
+ return state.filter === 'completed'
+ ? state.todos.filter((todo) => todo.includes('✅'))
+ : state.todos;
+ },
+ },
+ actions: {
+ addTodo(todo: string) {
+ state.todos.push(todo);
+ },
+ },
};
// Merges the inferred types with the server state types.
export type TodoList = ServerState & typeof todoList;
// Injects the final types when calling the `store` function.
-const { state } = store< TodoList >( 'myTodoPlugin', todoList );
+const { state } = store('myTodoPlugin', todoList);
```
So far, so good. Now let's create our `add-post-to-todo` block.
@@ -628,27 +628,27 @@ Now, let's type that server state and add the client store definition.
```ts
// add-post-to-todo-block/view.ts
type ServerState = {
- state: {
- postTitle: string;
- };
+ state: {
+ postTitle: string;
+ };
};
const addPostToTodo = {
- actions: {
- addPostToTodo() {
- const todo = `Read: ${ state.postTitle }`.trim();
- if ( ! state.todos.includes( todo ) ) {
- actions.addTodo( todo );
- }
- },
- },
+ actions: {
+ addPostToTodo() {
+ const todo = `Read: ${state.postTitle}`.trim();
+ if (!state.todos.includes(todo)) {
+ actions.addTodo(todo);
+ }
+ },
+ },
};
// Merges the inferred types with the server state types.
type Store = ServerState & typeof addPostToTodo;
// Injects the final types when calling the `store` function.
-const { state, actions } = store< Store >( 'myTodoPlugin', addPostToTodo );
+const { state, actions } = store('myTodoPlugin', addPostToTodo);
```
This works fine in the browser, but TypeScript will complain that, in this block, `state` and `actions` do not include `state.todos` and `actions.addtodo`.
@@ -675,16 +675,16 @@ Finally, if you prefer to define all types manually instead of inferring them, y
```ts
// types.ts
interface Store {
- state: {
- todos: string[];
- filter: 'all' | 'completed';
- filtered: string[];
- postTitle: string;
- };
- actions: {
- addTodo( todo: string ): void;
- addPostToTodo(): void;
- };
+ state: {
+ todos: string[];
+ filter: 'all' | 'completed';
+ filtered: string[];
+ postTitle: string;
+ };
+ actions: {
+ addTodo(todo: string): void;
+ addPostToTodo(): void;
+ };
}
export default Store;
@@ -694,18 +694,18 @@ export default Store;
// todo-list-block/view.ts
import type Store from '../types';
-const { state } = store< Store >( 'myTodoPlugin', {
- // Everything is correctly typed here
-} );
+const { state } = store('myTodoPlugin', {
+ // Everything is correctly typed here
+});
```
```ts
// add-post-to-todo-block/view.ts
import type Store from '../types';
-const { state, actions } = store< Store >( 'myTodoPlugin', {
- // Everything is correctly typed here
-} );
+const { state, actions } = store('myTodoPlugin', {
+ // Everything is correctly typed here
+});
```
This approach allows you to have full control over your types and ensures consistency across all parts of your store. It's particularly useful when you have a complex store structure or when you want to enforce a specific interface across multiple blocks or components.
@@ -718,18 +718,18 @@ Let's go back to our `todo-list` block example, but this time, let's imagine tha
```ts
// Import the store of the `todo-list` block.
-const myTodoPlugin = store( 'myTodoPlugin' );
+const myTodoPlugin = store('myTodoPlugin');
-store( 'myAddPostToTodoPlugin', {
- actions: {
- addPostToTodo() {
- const todo = `Read: ${ state.postTitle }`.trim();
- if ( ! myTodoPlugin.state.todos.includes( todo ) ) {
- myTodoPlugin.actions.addTodo( todo );
- }
- },
- },
-} );
+store('myAddPostToTodoPlugin', {
+ actions: {
+ addPostToTodo() {
+ const todo = `Read: ${state.postTitle}`.trim();
+ if (!myTodoPlugin.state.todos.includes(todo)) {
+ myTodoPlugin.actions.addTodo(todo);
+ }
+ },
+ },
+});
```
This works fine in the browser, but TypeScript will complain that `myTodoPlugin.state` and `myTodoPlugin.actions` are not typed.
@@ -738,30 +738,27 @@ To fix that, the `myTodoPlugin` plugin can export the result of calling the `sto
```ts
// Export the already typed state and actions.
-export const { state, actions } = store< TodoList >( 'myTodoPlugin', {
- // ...
-} );
+export const { state, actions } = store('myTodoPlugin', {
+ // ...
+});
```
Now, the `add-post-to-todo` block can import the typed store from the `myTodoPlugin` script module, and it not only ensures that the store will be loaded, but that it also contains the correct types.
```ts
import { store } from '@wordpress/interactivity';
-import {
- state as todoState,
- actions as todoActions,
-} from 'my-todo-plugin-module';
-
-store( 'myAddPostToTodoPlugin', {
- actions: {
- addPostToTodo() {
- const todo = `Read: ${ state.postTitle }`.trim();
- if ( ! todoState.todos.includes( todo ) ) {
- todoActions.addTodo( todo );
- }
- },
- },
-} );
+import { state as todoState, actions as todoActions } from 'my-todo-plugin-module';
+
+store('myAddPostToTodoPlugin', {
+ actions: {
+ addPostToTodo() {
+ const todo = `Read: ${state.postTitle}`.trim();
+ if (!todoState.todos.includes(todo)) {
+ todoActions.addTodo(todo);
+ }
+ },
+ },
+});
```
Remember that you will need to declare the `my-todo-plugin-module` script module as a dependency.
@@ -771,17 +768,17 @@ If the other store is optional and you don't want to load it eagerly, a dynamic
```ts
import { store } from '@wordpress/interactivity';
-store( 'myAddPostToTodoPlugin', {
- actions: {
- *addPostToTodo() {
- const todoPlugin = yield import( 'my-todo-plugin-module' );
- const todo = `Read: ${ state.postTitle }`.trim();
- if ( ! todoPlugin.state.todos.includes( todo ) ) {
- todoPlugin.actions.addTodo( todo );
- }
- },
- },
-} );
+store('myAddPostToTodoPlugin', {
+ actions: {
+ *addPostToTodo() {
+ const todoPlugin = yield import('my-todo-plugin-module');
+ const todo = `Read: ${state.postTitle}`.trim();
+ if (!todoPlugin.state.todos.includes(todo)) {
+ todoPlugin.actions.addTodo(todo);
+ }
+ },
+ },
+});
```
## Conclusion
diff --git a/gutenberg/reference-guides/interactivity-api/iapi-about.md b/docs/gutenberg/reference-guides/interactivity-api/iapi-about.md
similarity index 95%
rename from gutenberg/reference-guides/interactivity-api/iapi-about.md
rename to docs/gutenberg/reference-guides/interactivity-api/iapi-about.md
index acebd37..0c25cc5 100644
--- a/gutenberg/reference-guides/interactivity-api/iapi-about.md
+++ b/docs/gutenberg/reference-guides/interactivity-api/iapi-about.md
@@ -4,7 +4,7 @@ The Interactivity API is **a [standard](#why-a-standard) system of [directives](
**Directives extend HTML with special attributes** that tell the Interactivity API to attach a specified behavior to a DOM element or even to transform it. For those familiar with [Alpine.js](https://alpinejs.dev/), it’s a similar approach but explicitly designed to work seamlessly with WordPress.
-## API Goals
+## API Goals
The main goal of the Interactivity API is to **provide a standard and simple way to handle the frontend interactivity of Gutenberg blocks**.
@@ -36,6 +36,7 @@ The API is designed for the world of blocks and takes WordPress history of being
As directives are HTML attributes, they are perfect for dynamic blocks and PHP.
_Dynamic block example_
+
```html
Toggle
-
+
This element is now visible!
@@ -63,7 +64,7 @@ As you can see, directives like [`data-wp-on--click`](https://developer.wordpres
As the Interactivity API works perfectly with server-side rendering, you can use all the WordPress APIs, including:
- **WordPress filters and actions**: You can keep using WordPress hooks to modify the HTML or even to modify directives. Additionally, existing hooks will keep working as expected.
-- **Core Translation API**: e.g. `__()` and `_e()`. You can use it to translate the text in the HTML (as you normally would) and even use those APIs on the server side of your directives.
+- **Core Translation API**: e.g. `__()` and `_e()`. You can use it to translate the text in the HTML (as you normally would) and even use those APIs on the server side of your directives.
### Optional and gradual adoption
@@ -87,18 +88,18 @@ _Imperative code_
This element is now visible!
```
@@ -108,10 +109,10 @@ This is the same use case shared above but serves as an example of declarative c
```js
// view.js file
-
-import { store, getContext } from "@wordpress/interactivity";
-
-store( 'wpmovies', {
+
+import { store, getContext } from '@wordpress/interactivity';
+
+store('wpmovies', {
actions: {
toggle: () => {
const context = getContext();
@@ -123,7 +124,7 @@ store( 'wpmovies', {
```php
-
+
@@ -168,7 +169,7 @@ The API works out of the box with standard block-building tools like [`wp-script
The Interactivity API comes with built-in primitives for adding client-side navigation to your site. This functionality is completely optional, but it opens the possibility to create these user experiences without having to opt out of the WordPress rendering system.
- Full-page client-side navigation with the Interactivity API is still a work in progress (see #60951). Still, it is expected that all the interactive blocks will have to use the Interactivity API to enable full-page client-side navigation with the Interactivity API. Only in this case, the Interactivity API won't be fully compatible with other libraries (such as jQuery).
+ Full-page client-side navigation with the Interactivity API is still a work in progress (see #60951). Still, it is expected that all the interactive blocks will have to use the Interactivity API to enable full-page client-side navigation with the Interactivity API. Only in this case, the Interactivity API won't be fully compatible with other libraries (such as jQuery).
It also pairs very well with the [View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/) allowing developers to animate page transitions easily.
@@ -188,8 +189,6 @@ _Complexities absorbed by the standard_
-
With this absorption, less knowledge is required to create interactive blocks, and developers have fewer decisions to worry about.
By adopting a standard, learning from other interactive blocks is simpler, and fosters collaboration and code reusability. As a result, the development process is leanier and friendlier to less experienced developers.
-
diff --git a/gutenberg/reference-guides/interactivity-api/iapi-faq.md b/docs/gutenberg/reference-guides/interactivity-api/iapi-faq.md
similarity index 99%
rename from gutenberg/reference-guides/interactivity-api/iapi-faq.md
rename to docs/gutenberg/reference-guides/interactivity-api/iapi-faq.md
index dea7bc1..b280a23 100644
--- a/gutenberg/reference-guides/interactivity-api/iapi-faq.md
+++ b/docs/gutenberg/reference-guides/interactivity-api/iapi-faq.md
@@ -41,10 +41,9 @@ Furthermore, with Preact operating in the background, the Interactivity API mana
Have a look at the conversation at "Why Preact instead of Alpine?" to learn more about this.
-
### Plain JavaScript
-See the answer below.
+See the answer below.
### Template DSL
@@ -52,7 +51,7 @@ The possibility of creating a [DSL](https://en.wikipedia.org/wiki/Domain-specifi
## Why should I, as a block developer, use the Interactivity API rather than React?
-Using React on the frontend doesn’t work smoothly with server rendering in PHP. Every approach that uses React to render blocks has to load content using client-side JavaScript. If you only render your blocks on the client, it typically results in a poor user experience because the user stares at empty placeholders and spinners while waiting for content to load.
+Using React on the frontend doesn’t work smoothly with server rendering in PHP. Every approach that uses React to render blocks has to load content using client-side JavaScript. If you only render your blocks on the client, it typically results in a poor user experience because the user stares at empty placeholders and spinners while waiting for content to load.
Using JS in PHP extensions (like v8js) is also possible, but unfortunately PHP extensions are not backward compatible and can only be used when there's a PHP fallback.
@@ -68,7 +67,6 @@ To summarize, using the Interactivity API rather than just using React comes wit
- The Interactivity API is PHP-friendlier. It works out of the box with WordPress hooks or other server functionalities such as internationalization. For example, with React, you can’t know which hooks are applied on the server, and their modifications would be overwritten after hydration.
- All the benefits of [using a standard](/docs/reference-guides/interactivity-api/iapi-about.md#why-a-standard).
-
## What are the benefits of Interactivity API over just using jQuery or vanilla JavaScript?
The main difference is that the Interactivity API is **declarative and reactive**, so writing and maintaining complex interactive experiences should become way easier. Additionally, it has been **specially designed to work with blocks**, providing a standard that comes with the benefits mentioned above, like inter-block communication, compatibility, or site-wide features such as client-side navigation.
@@ -133,4 +131,3 @@ Yes. The Interactivity API does not use [`eval()`](https://developer.mozilla.org
## Can you use directives to make AJAX/REST-API requests?
Sure. Actions and callbacks called by directives can do anything a JavaScript function can, including making API requests.
-
diff --git a/gutenberg/reference-guides/interactivity-api/iapi-quick-start-guide.md b/docs/gutenberg/reference-guides/interactivity-api/iapi-quick-start-guide.md
similarity index 99%
rename from gutenberg/reference-guides/interactivity-api/iapi-quick-start-guide.md
rename to docs/gutenberg/reference-guides/interactivity-api/iapi-quick-start-guide.md
index 8c8e895..1fe9ced 100644
--- a/gutenberg/reference-guides/interactivity-api/iapi-quick-start-guide.md
+++ b/docs/gutenberg/reference-guides/interactivity-api/iapi-quick-start-guide.md
@@ -48,6 +48,3 @@ You should be able to insert the "My First Interactive Block" block into any pos
-
-
-
diff --git a/gutenberg/reference-guides/packages.md b/docs/gutenberg/reference-guides/packages.md
similarity index 93%
rename from gutenberg/reference-guides/packages.md
rename to docs/gutenberg/reference-guides/packages.md
index ce9c4b7..d67ac32 100644
--- a/gutenberg/reference-guides/packages.md
+++ b/docs/gutenberg/reference-guides/packages.md
@@ -10,9 +10,9 @@ If you wanted to use the `PlainText` component from the block editor module, fir
```php
wp_enqueue_script(
- 'my-custom-block',
- plugins_url( $block_path, __FILE__ ),
- array( 'react', 'wp-blocks', 'wp-block-editor', 'wp-i18n' )
+ 'my-custom-block',
+ plugins_url( $block_path, __FILE__ ),
+ array( 'react', 'wp-blocks', 'wp-block-editor', 'wp-i18n' )
);
```
diff --git a/gutenberg/reference-guides/richtext.md b/docs/gutenberg/reference-guides/richtext.md
similarity index 62%
rename from gutenberg/reference-guides/richtext.md
rename to docs/gutenberg/reference-guides/richtext.md
index ec484ac..76fdaf4 100644
--- a/gutenberg/reference-guides/richtext.md
+++ b/docs/gutenberg/reference-guides/richtext.md
@@ -4,9 +4,9 @@ RichText is a component that allows developers to render a [`contenteditable` in
The RichText component is extremely powerful because it provides built-in functionality you won't find in other components:
-- **Consistent Styling in the Admin and Frontend:** The editable container can be set to any block-level element, such as a `div`, `h2` or `p` tag. This allows the styles you apply in style.css to more easily apply on the frontend and admin, without having to rewrite them in editor.css.
-- **Cohesive Placeholder Text:** Before the user writes their content, it's easy to include placeholder text that's already styled to match the rest of the block editor.
-- **Control Over Formatting Options:** It's possible to dictate exactly which formatting options you want to allow for the RichText field. For example, you can dictate whether to allow the user to make text bold, italics or both.
+- **Consistent Styling in the Admin and Frontend:** The editable container can be set to any block-level element, such as a `div`, `h2` or `p` tag. This allows the styles you apply in style.css to more easily apply on the frontend and admin, without having to rewrite them in editor.css.
+- **Cohesive Placeholder Text:** Before the user writes their content, it's easy to include placeholder text that's already styled to match the rest of the block editor.
+- **Control Over Formatting Options:** It's possible to dictate exactly which formatting options you want to allow for the RichText field. For example, you can dictate whether to allow the user to make text bold, italics or both.
Unlike other components that exist in the [Component Reference](/packages/components/README.md) section, RichText lives separately because it only makes sense within the block editor, and not within other areas of WordPress.
@@ -18,50 +18,48 @@ For a list of the possible properties to pass your RichText component, [check ou
There are a number of core blocks using the RichText component. The JavaScript edit function linked below for each block can be used as a best practice reference while creating your own blocks.
-- **[Button](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/button/edit.js):** RichText is used to enter the button's text.
-- **[Heading](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/heading/edit.js):** RichText is used to enter the heading's text.
-- **[Quote](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/quote/edit.js):** RichText is used in two places, for both the quotation and citation text.
-- **[Search](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/search/edit.js):** RichText is used in two places, for both the label above the search field and the submit button text.
+- **[Button](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/button/edit.js):** RichText is used to enter the button's text.
+- **[Heading](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/heading/edit.js):** RichText is used to enter the heading's text.
+- **[Quote](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/quote/edit.js):** RichText is used in two places, for both the quotation and citation text.
+- **[Search](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/search/edit.js):** RichText is used in two places, for both the label above the search field and the submit button text.
## Example
-
-
```jsx
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, RichText } from '@wordpress/block-editor';
registerBlockType( /* ... */, {
- // ...
-
- attributes: {
- content: {
- type: 'string',
- source: 'html',
- selector: 'h2',
- },
- },
-
- edit( { attributes, setAttributes } ) {
- const blockProps = useBlockProps();
-
- return (
- setAttributes( { content } ) } // Store updated content as a block attribute
- placeholder={ __( 'Heading...' ) } // Display this text before any content has been added by the user
- />
- );
- },
-
- save( { attributes } ) {
- const blockProps = useBlockProps.save();
-
- return ; // Saves
Content added in the editor...
to the database for frontend display
- }
+ // ...
+
+ attributes: {
+ content: {
+ type: 'string',
+ source: 'html',
+ selector: 'h2',
+ },
+ },
+
+ edit( { attributes, setAttributes } ) {
+ const blockProps = useBlockProps();
+
+ return (
+ setAttributes( { content } ) } // Store updated content as a block attribute
+ placeholder={ __( 'Heading...' ) } // Display this text before any content has been added by the user
+ />
+ );
+ },
+
+ save( { attributes } ) {
+ const blockProps = useBlockProps.save();
+
+ return ; // Saves
Content added in the editor...
to the database for frontend display
+ }
} );
```
diff --git a/docs/gutenberg/reference-guides/slotfills/README.md b/docs/gutenberg/reference-guides/slotfills/README.md
new file mode 100644
index 0000000..61b2bdf
--- /dev/null
+++ b/docs/gutenberg/reference-guides/slotfills/README.md
@@ -0,0 +1,351 @@
+# SlotFills Reference
+
+Slot and Fill are components that have been exposed to allow developers to inject items into some predefined places in the Gutenberg admin experience.
+Please see the [SlotFill component docs](/packages/components/src/slot-fill/README.md) for more details.
+
+In order to use them, we must leverage the [@wordpress/plugins](/packages/plugins/README.md) api to register a plugin that will inject our items.
+
+## Usage overview
+
+In order to access the SlotFills, we need to do four things:
+
+1. Import the `registerPlugin` method from the `@wordpress/plugins` package.
+2. Import the SlotFill we want from the `@wordpress/editor'` package.
+3. Define a component to render our changes. Our changes/additions will be wrapped in the SlotFill component we imported.
+4. Register the plugin.
+
+Here is an example using the `PluginPostStatusInfo` slotFill:
+
+```js
+import { registerPlugin } from '@wordpress/plugins';
+import { PluginPostStatusInfo } from '@wordpress/editor';
+
+const PluginPostStatusInfoTest = () => (
+
+
Post Status Info SlotFill
+
+);
+
+registerPlugin('post-status-info-test', { render: PluginPostStatusInfoTest });
+```
+
+## Conditionally rendering SlotFill content
+
+With the exception of [MainDashboardButton](/docs/reference-guides/slotfills/main-dashboard-button.md), every available SlotFill is exposed in both the Post Editor and Site Editor and any Fill that is registered will be rendered in both contexts. There are a number of approaches that can be implemented to conditionally render Fills.
+
+### Restricting fills to the Post Editor
+
+A fill can be restricted to the Post Editor by checking to see if the current post type object property `viewable` is set to `true`. Any post type not set to `viewable`, does not have an associated edit post screen and is a good indicator that the user is not in the Post Editor. The example below will render its content on the edit post screen for any registered post type.
+
+```js
+/**
+ * WordPress dependencies
+ */
+import { registerPlugin } from '@wordpress/plugins';
+import { PluginDocumentSettingPanel, store as editorStore } from '@wordpress/editor';
+import { store as coreStore } from '@wordpress/core-data';
+import { useSelect } from '@wordpress/data';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * The component to be rendered as part of the plugin.
+ */
+const EditPostDocumentSettingPanel = () => {
+ // Retrieve information about the current post type.
+ const isViewable = useSelect((select) => {
+ const postTypeName = select(editorStore).getCurrentPostType();
+ const postTypeObject = select(coreStore).getPostType(postTypeName);
+ return postTypeObject?.viewable;
+ }, []);
+
+ // If the post type is not viewable, then do not render my the fill.
+ if (!isViewable) {
+ return null;
+ }
+
+ return (
+
+
{__('Only appears in the Edit Post screen')}
+
+ );
+};
+
+registerPlugin('example-post-edit-only', {
+ render: EditPostDocumentSettingPanel,
+});
+```
+
+### Restricting fills to certain post types
+
+The following example expands on the example above by creating an allow list of post types where the fill should be rendered. In this case, the fill is only rendered when editing pages.
+
+```js
+/**
+ * WordPress dependencies
+ */
+import { registerPlugin } from '@wordpress/plugins';
+import { PluginDocumentSettingPanel, store as editorStore } from '@wordpress/editor';
+import { store as coreStore } from '@wordpress/core-data';
+import { useSelect } from '@wordpress/data';
+import { __, sprintf } from '@wordpress/i18n';
+
+/**
+ * The component to be rendered as part of the plugin.
+ */
+const RestrictPostTypes = () => {
+ // Retrieve information about the current post type.
+ const { isViewable, postTypeName } = useSelect((select) => {
+ const postType = select(editorStore).getCurrentPostType();
+ const postTypeObject = select(coreStore).getPostType(postType);
+ return {
+ isViewable: postTypeObject?.viewable,
+ postTypeName: postType,
+ };
+ }, []);
+
+ // The list of post types that are allowed to render the plugin.
+ const allowedPostTypes = ['page'];
+
+ // If the post type is not viewable or not in the allowed list, do not render the plugin.
+ if (!isViewable || !allowedPostTypes.includes(postTypeName)) {
+ return null;
+ }
+
+ return (
+
+
+ {sprintf(
+ __('Only appears on Post Types that are in the allowed list. %s'),
+ allowedPostTypes.join(', ')
+ )}
+
+
+ );
+};
+
+registerPlugin('example-restrict-post-types', {
+ render: RestrictPostTypes,
+});
+```
+
+### Restricting fills to the Side Editor
+
+To restrict fills to the Site Editor, the reverse logic is true. If the post type object's `viewable` property is set to `true`, then the fill should not be rendered. The example below will render its content on any Site Editor screen.
+
+```js
+/**
+ * WordPress dependencies
+ */
+import { registerPlugin } from '@wordpress/plugins';
+import { PluginDocumentSettingPanel, store as editorStore } from '@wordpress/editor';
+import { store as coreStore } from '@wordpress/core-data';
+import { useSelect } from '@wordpress/data';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * The component to be rendered as part of the plugin.
+ */
+const SiteEditorDocumentSettingPanel = () => {
+ // Retrieve information about the current post type.
+ const isViewable = useSelect((select) => {
+ const postTypeName = select(editorStore).getCurrentPostType();
+ const postTypeObject = select(coreStore).getPostType(postTypeName);
+
+ // A viewable post type is one than can be viewed in the WordPress admin. Internal ones are not set to viewable.
+ return postTypeObject?.viewable;
+ }, []);
+
+ // If the post type is viewable, do not render my fill
+ if (isViewable) {
+ return null;
+ }
+
+ return (
+
+
{__('Only appears in the Site Editor')}
+
+ );
+};
+
+registerPlugin('example-site-editor', {
+ render: SiteEditorDocumentSettingPanel,
+});
+```
+
+### Restricting fills to certain screens in the Site Editor
+
+This example builds on the example above by providing an allow list to control which screens a fill can be rendered within the Site Editor.
+
+```js
+/**
+ * WordPress dependencies
+ */
+import { registerPlugin } from '@wordpress/plugins';
+import { PluginDocumentSettingPanel, store as editorStore } from '@wordpress/editor';
+import { store as coreStore } from '@wordpress/core-data';
+import { useSelect } from '@wordpress/data';
+import { __, sprintf } from '@wordpress/i18n';
+
+/**
+ * The component to be rendered as part of the plugin.
+ */
+const SiteEditorDocumentSettingPanel = () => {
+ // Allowed areas in the Site Editor.
+ const allowedSiteEditorScreens = [
+ 'wp_template', // Templates
+ 'wp_block', // Patterns
+ 'wp_template_part', // Template Parts
+ ];
+
+ const { isViewable, postType } = useSelect((select) => {
+ const postTypeName = select(editorStore).getCurrentPostType();
+ const postTypeObject = select(coreStore).getPostType(postTypeName);
+
+ return {
+ // A viewable post type is one than can be viewed in the WordPress admin. Internal ones are not set to viewable.
+ isViewable: postTypeObject?.viewable,
+ postType: postTypeName,
+ };
+ }, []);
+
+ // If the post type is viewable, do not render my plugin.
+ if (isViewable || !allowedSiteEditorScreens.includes(postType)) {
+ return null;
+ }
+
+ return (
+
+
+ {sprintf(
+ __('Only appears on Editor Screens that are in the allowed list. %s'),
+ allowedSiteEditorScreens.join(', ')
+ )}
+
+
+ );
+};
+
+registerPlugin('example-site-editor-only', {
+ render: SiteEditorDocumentSettingPanel,
+});
+```
+
+## How do they work?
+
+SlotFills are created using `createSlotFill`. This creates two components, `Slot` and `Fill` which are then used to create a new component that is exported on the `wp.plugins` global.
+
+**Definition of the `PluginPostStatusInfo` SlotFill** ([see core code](https://github.com/WordPress/gutenberg/blob/HEAD/packages/editor/src/components/plugin-post-status-info/index.js#L55))
+
+```js
+/**
+ * Defines as extensibility slot for the Summary panel.
+ */
+
+/**
+ * WordPress dependencies
+ */
+import { createSlotFill, PanelRow } from '@wordpress/components';
+
+export const { Fill, Slot } = createSlotFill('PluginPostStatusInfo');
+
+const PluginPostStatusInfo = ({ children, className }) => (
+
+ {children}
+
+);
+
+PluginPostStatusInfo.Slot = Slot;
+
+export default PluginPostStatusInfo;
+```
+
+This new Slot is then exposed in the editor. The example below is from core and represents the Summary panel.
+
+As we can see, the `` is wrapping all of the items that will appear in the panel.
+Any items that have been added via the SlotFill ( see the example above ), will be included in the `fills` parameter and be displayed in the end of the component.
+
+See [core code](https://github.com/WordPress/gutenberg/tree/HEAD/packages/editor/src/components/sidebar/post-summary.js#L39).
+
+```js
+export default function PostSummary({ onActionPerformed }) {
+ const { isRemovedPostStatusPanel } = useSelect((select) => {
+ // We use isEditorPanelRemoved to hide the panel if it was programmatically removed. We do
+ // not use isEditorPanelEnabled since this panel should not be disabled through the UI.
+ const { isEditorPanelRemoved } = select(editorStore);
+ return {
+ isRemovedPostStatusPanel: isEditorPanelRemoved(PANEL_NAME),
+ };
+ }, []);
+
+ return (
+
+
+ {(fills) => (
+ <>
+
+
+
+
+
+
+
+
+ {!isRemovedPostStatusPanel && (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {fills}
+
+ )}
+
+ >
+ )}
+
+
+ );
+}
+```
+
+## Currently available SlotFills and examples
+
+The following SlotFills are available in the `edit-post` or `editor` packages. Please refer to the individual items below for usage and example details:
+
+- [MainDashboardButton](/docs/reference-guides/slotfills/main-dashboard-button.md)
+- [PluginBlockSettingsMenuItem](/docs/reference-guides/slotfills/plugin-block-settings-menu-item.md)
+- [PluginDocumentSettingPanel](/docs/reference-guides/slotfills/plugin-document-setting-panel.md)
+- [PluginMoreMenuItem](/docs/reference-guides/slotfills/plugin-more-menu-item.md)
+- [PluginPostPublishPanel](/docs/reference-guides/slotfills/plugin-post-publish-panel.md)
+- [PluginPostStatusInfo](/docs/reference-guides/slotfills/plugin-post-status-info.md)
+- [PluginPrePublishPanel](/docs/reference-guides/slotfills/plugin-pre-publish-panel.md)
+- [PluginSidebar](/docs/reference-guides/slotfills/plugin-sidebar.md)
+- [PluginSidebarMoreMenuItem](/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md)
diff --git a/gutenberg/reference-guides/slotfills/main-dashboard-button.md b/docs/gutenberg/reference-guides/slotfills/main-dashboard-button.md
similarity index 70%
rename from gutenberg/reference-guides/slotfills/main-dashboard-button.md
rename to docs/gutenberg/reference-guides/slotfills/main-dashboard-button.md
index 593c5c5..63d462a 100644
--- a/gutenberg/reference-guides/slotfills/main-dashboard-button.md
+++ b/docs/gutenberg/reference-guides/slotfills/main-dashboard-button.md
@@ -4,7 +4,7 @@ This slot allows replacing the default main dashboard button in the post editor.
It's used for returning back to main wp-admin dashboard when editor is in fullscreen mode.
- Please note that this SlotFill is still considered experimental and may change
+ Please note that this SlotFill is still considered experimental and may change
## Examples
@@ -19,39 +19,39 @@ import { __experimentalMainDashboardButton as MainDashboardButton } from '@wordp
import { close } from '@wordpress/icons';
const MainDashboardButtonTest = () => (
-
-
-
+
+
+
);
-registerPlugin( 'main-dashboard-button-test', {
- render: MainDashboardButtonTest,
-} );
+registerPlugin('main-dashboard-button-test', {
+ render: MainDashboardButtonTest,
+});
```

### Change the icon and link
-This example will change the icon in the header to indicate an external link that will take the user to https://wordpress.org when clicked.
+This example will change the icon in the header to indicate an external link that will take the user to when clicked.
```js
import { registerPlugin } from '@wordpress/plugins';
import {
- __experimentalFullscreenModeClose as FullscreenModeClose,
- __experimentalMainDashboardButton as MainDashboardButton,
+ __experimentalFullscreenModeClose as FullscreenModeClose,
+ __experimentalMainDashboardButton as MainDashboardButton,
} from '@wordpress/edit-post';
import { external } from '@wordpress/icons';
const MainDashboardButtonIconTest = () => (
-
-
-
+
+
+
);
-registerPlugin( 'main-dashboard-button-icon-test', {
- render: MainDashboardButtonIconTest,
-} );
+registerPlugin('main-dashboard-button-icon-test', {
+ render: MainDashboardButtonIconTest,
+});
```

diff --git a/gutenberg/reference-guides/slotfills/plugin-block-settings-menu-item.md b/docs/gutenberg/reference-guides/slotfills/plugin-block-settings-menu-item.md
similarity index 68%
rename from gutenberg/reference-guides/slotfills/plugin-block-settings-menu-item.md
rename to docs/gutenberg/reference-guides/slotfills/plugin-block-settings-menu-item.md
index aa1eecb..4af6345 100644
--- a/gutenberg/reference-guides/slotfills/plugin-block-settings-menu-item.md
+++ b/docs/gutenberg/reference-guides/slotfills/plugin-block-settings-menu-item.md
@@ -10,19 +10,19 @@ import { registerPlugin } from '@wordpress/plugins';
import { PluginBlockSettingsMenuItem } from '@wordpress/editor';
const PluginBlockSettingsMenuGroupTest = () => (
- {
- alert( 'clicked' );
- } }
- />
+ {
+ alert('clicked');
+ }}
+ />
);
-registerPlugin( 'block-settings-menu-group-test', {
- render: PluginBlockSettingsMenuGroupTest,
-} );
+registerPlugin('block-settings-menu-group-test', {
+ render: PluginBlockSettingsMenuGroupTest,
+});
```
## Location
diff --git a/docs/gutenberg/reference-guides/slotfills/plugin-document-setting-panel.md b/docs/gutenberg/reference-guides/slotfills/plugin-document-setting-panel.md
new file mode 100644
index 0000000..78aad4c
--- /dev/null
+++ b/docs/gutenberg/reference-guides/slotfills/plugin-document-setting-panel.md
@@ -0,0 +1,92 @@
+# PluginDocumentSettingPanel
+
+This SlotFill allows registering a UI to edit Document settings.
+
+## Available Props
+
+- **name** `string`: A string identifying the panel.
+- **className** `string`: An optional class name added to the sidebar body.
+- **title** `string`: Title displayed at the top of the sidebar.
+- **icon** `(string|Element)`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element.
+
+## Example
+
+```js
+import { registerPlugin } from '@wordpress/plugins';
+import { PluginDocumentSettingPanel } from '@wordpress/editor';
+
+const PluginDocumentSettingPanelDemo = () => (
+
+ Custom Panel Contents
+
+);
+
+registerPlugin('plugin-document-setting-panel-demo', {
+ render: PluginDocumentSettingPanelDemo,
+ icon: 'palmtree',
+});
+```
+
+## Accessing a panel programmatically
+
+Core and custom panels can be accessed programmatically using their panel name. The core panel names are:
+
+- Summary Panel: `post-status`
+- Categories Panel: `taxonomy-panel-category`
+- Tags Panel: `taxonomy-panel-post_tag`
+- Featured Image Panel: `featured-image`
+- Excerpt Panel: `post-excerpt`
+- DiscussionPanel: `discussion-panel`
+
+Custom panels are namespaced with the plugin name that was passed to `registerPlugin`.
+In order to access the panels using function such as `toggleEditorPanelOpened` or `toggleEditorPanelEnabled` be sure to prepend the namespace.
+
+To programmatically toggle panels, use the following:
+
+```js
+import { useDispatch } from '@wordpress/data';
+import { store as editorStore } from '@wordpress/editor';
+
+const Example = () => {
+ const { toggleEditorPanelOpened } = useDispatch(editorStore);
+ return (
+
+ );
+};
+```
+
+It is also possible to remove panels from the admin using the `removeEditorPanel` function by passing the name of the registered panel.
+
+```js
+import { useDispatch } from '@wordpress/data';
+import { store as editorStore } from '@wordpress/editor';
+
+const Example = () => {
+ const { removeEditorPanel } = useDispatch(editorStore);
+ return (
+
+ );
+};
+```
diff --git a/gutenberg/reference-guides/slotfills/plugin-more-menu-item.md b/docs/gutenberg/reference-guides/slotfills/plugin-more-menu-item.md
similarity index 66%
rename from gutenberg/reference-guides/slotfills/plugin-more-menu-item.md
rename to docs/gutenberg/reference-guides/slotfills/plugin-more-menu-item.md
index b5dd211..f4a30c6 100644
--- a/gutenberg/reference-guides/slotfills/plugin-more-menu-item.md
+++ b/docs/gutenberg/reference-guides/slotfills/plugin-more-menu-item.md
@@ -10,17 +10,17 @@ import { PluginMoreMenuItem } from '@wordpress/editor';
import { image } from '@wordpress/icons';
const MyButtonMoreMenuItemTest = () => (
- {
- alert( 'Button Clicked' );
- } }
- >
- More Menu Item
-
+ {
+ alert('Button Clicked');
+ }}
+ >
+ More Menu Item
+
);
-registerPlugin( 'more-menu-item-test', { render: MyButtonMoreMenuItemTest } );
+registerPlugin('more-menu-item-test', { render: MyButtonMoreMenuItemTest });
```
## Location
diff --git a/gutenberg/reference-guides/slotfills/plugin-post-publish-panel.md b/docs/gutenberg/reference-guides/slotfills/plugin-post-publish-panel.md
similarity index 73%
rename from gutenberg/reference-guides/slotfills/plugin-post-publish-panel.md
rename to docs/gutenberg/reference-guides/slotfills/plugin-post-publish-panel.md
index c7457c2..6329410 100644
--- a/gutenberg/reference-guides/slotfills/plugin-post-publish-panel.md
+++ b/docs/gutenberg/reference-guides/slotfills/plugin-post-publish-panel.md
@@ -9,14 +9,14 @@ import { registerPlugin } from '@wordpress/plugins';
import { PluginPostPublishPanel } from '@wordpress/editor';
const PluginPostPublishPanelTest = () => (
-
-
+
);
-registerPlugin( 'pre-publish-panel-test', {
- render: PluginPrePublishPanelTest,
-} );
+registerPlugin('pre-publish-panel-test', {
+ render: PluginPrePublishPanelTest,
+});
```
## Location
diff --git a/docs/gutenberg/reference-guides/slotfills/plugin-sidebar-more-menu-item.md b/docs/gutenberg/reference-guides/slotfills/plugin-sidebar-more-menu-item.md
new file mode 100644
index 0000000..b6d101f
--- /dev/null
+++ b/docs/gutenberg/reference-guides/slotfills/plugin-sidebar-more-menu-item.md
@@ -0,0 +1,61 @@
+# PluginSidebarMoreMenuItem
+
+This slot is used to allow the opening of a `` panel from the Options dropdown.
+When a `` is registered, a `` is automatically registered using the title prop from the `` and so it's not required to use this slot to create the menu item.
+
+## Example
+
+This example shows how customize the text for the menu item instead of using the default text provided by the `` title.
+
+```js
+import { __ } from '@wordpress/i18n';
+import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/editor';
+import { PanelBody, Button, TextControl, SelectControl } from '@wordpress/components';
+import { registerPlugin } from '@wordpress/plugins';
+import { useState } from '@wordpress/element';
+import { image } from '@wordpress/icons';
+
+const PluginSidebarMoreMenuItemTest = () => {
+ const [text, setText] = useState('');
+ const [select, setSelect] = useState('a');
+ return (
+ <>
+
+ {__('Custom Menu Item Text')}
+
+
+
+
{__('This is a heading for the PluginSidebar example.')}
+
{__('This is some example text for the PluginSidebar example.')}
+ setText(newText)}
+ />
+ setSelect(newSelect)}
+ />
+
+
+
+ >
+ );
+};
+
+registerPlugin('plugin-sidebar-more-menu-item-example', {
+ render: PluginSidebarMoreMenuItemTest,
+});
+```
+
+## Location
+
+
diff --git a/docs/gutenberg/reference-guides/slotfills/plugin-sidebar.md b/docs/gutenberg/reference-guides/slotfills/plugin-sidebar.md
new file mode 100644
index 0000000..c5237f8
--- /dev/null
+++ b/docs/gutenberg/reference-guides/slotfills/plugin-sidebar.md
@@ -0,0 +1,54 @@
+# PluginSidebar
+
+This slot allows adding items to the tool bar of either the Post or Site editor screens.
+Using this slot will add an icon to the toolbar that, when clicked, opens a panel with containing the items wrapped in the `` component.
+Additionally, it will also create a `` that will allow opening the panel from Options panel when clicked.
+
+## Example
+
+```jsx
+import { __ } from '@wordpress/i18n';
+import { PluginSidebar } from '@wordpress/editor';
+import { PanelBody, Button, TextControl, SelectControl } from '@wordpress/components';
+import { registerPlugin } from '@wordpress/plugins';
+import { useState } from '@wordpress/element';
+
+const PluginSidebarExample = () => {
+ const [text, setText] = useState('');
+ const [select, setSelect] = useState('a');
+
+ return (
+
+
+
{__('This is a heading for the PluginSidebar example.')}
+
{__('This is some example text for the PluginSidebar example.')}
+ setText(newText)}
+ />
+ setSelect(newSelect)}
+ />
+
+
+
+ );
+};
+
+// Register the plugin.
+registerPlugin('plugin-sidebar-example', { render: PluginSidebarExample });
+```
+
+## Location
+
+
diff --git a/docs/gutenberg/reference-guides/theme-json-reference/README.md b/docs/gutenberg/reference-guides/theme-json-reference/README.md
new file mode 100644
index 0000000..9bb75fd
--- /dev/null
+++ b/docs/gutenberg/reference-guides/theme-json-reference/README.md
@@ -0,0 +1,11 @@
+# Theme.json Reference
+
+This reference guide lists the settings and style properties defined in the theme.json schema. See the [theme.json how to guide](/docs/how-to-guides/themes/global-settings-and-styles.md) for examples and guide on how to use the theme.json file in your theme.
+
+- [Version 3 (latest)](/docs/reference-guides/theme-json-reference/theme-json-living.md)
+
+## Older versions
+
+- [Migrating to Newer Theme.json Versions](/docs/reference-guides/theme-json-reference/theme-json-migrations.md)
+- [Version 1](/docs/reference-guides/theme-json-reference/theme-json-v1.md)
+- [Version 2](/docs/reference-guides/theme-json-reference/theme-json-v2.md)
diff --git a/docs/gutenberg/reference-guides/theme-json-reference/styles-versions.md b/docs/gutenberg/reference-guides/theme-json-reference/styles-versions.md
new file mode 100644
index 0000000..8489342
--- /dev/null
+++ b/docs/gutenberg/reference-guides/theme-json-reference/styles-versions.md
@@ -0,0 +1,57 @@
+# Available Styles Options
+
+New styles options are integrated into theme.json on a regular basis. Knowing the style options available through theme.json or the styles editor at any given time can be challenging. To clarify, the table below indicates the WordPress version when each theme.json styles option became available and when a corresponding control was added to the user interface to allow management of the style from the Styles editor.
+
+## Styles keys
+
+| Key | theme.json Since | Style Editor Since |
+| --------------------------- | :--------------: | :----------------: |
+| `color.gradient` | 5.8 | 5.9 |
+| `color.background` | 5.8 | 5.9 |
+| `color.text` | 5.8 | 5.9 |
+| `border.color` | 5.9 | 5.9 |
+| `border.width` | 5.9 | 5.9 |
+| `border.style` | 5.9 | 5.9 |
+| `border.radius` | 5.8 | 5.9 |
+| `border.radius.topLeft` | 5.9 | 5.9 |
+| `border.radius.topRight` | 5.9 | 5.9 |
+| `border.radius.bottomLeft` | 5.9 | 5.9 |
+| `border.radius.bottomRight` | 5.9 | 5.9 |
+| `border.top.color` | 6.1 | 6.1 |
+| `border.top.width` | 6.1 | 6.1 |
+| `border.top.style` | 6.1 | 6.1 |
+| `border.right.color` | 6.1 | 6.1 |
+| `border.right.width` | 6.1 | 6.1 |
+| `border.right.style` | 6.1 | 6.1 |
+| `border.bottom.color` | 6.1 | 6.1 |
+| `border.bottom.width` | 6.1 | 6.1 |
+| `border.bottom.style` | 6.1 | 6.1 |
+| `border.left.color` | 6.1 | 6.1 |
+| `border.left.width` | 6.1 | 6.1 |
+| `border.left.style` | 6.1 | 6.1 |
+| `typography.fontFamily` | 5.9 | 5.9 |
+| `typography.fontSize` | 5.8 | 5.9 |
+| `typography.fontStyle` | 5.9 | 5.9 |
+| `typography.fontWeight` | 5.9 | 5.9 |
+| `typography.letterSpacing` | 5.9 | 5.9 |
+| `typography.lineHeight` | 5.8 | 5.9 |
+| `typography.textDecoration` | 5.9 | 6.2 |
+| `typography.textTransform` | 5.9 | 6.0 |
+| `spacing.padding` | 5.9 | 5.9 |
+| `spacing.padding.top` | 5.8 | 5.9 |
+| `spacing.padding.right` | 5.8 | 5.9 |
+| `spacing.padding.left` | 5.8 | 5.9 |
+| `spacing.padding.bottom` | 5.8 | 5.9 |
+| `spacing.margin` | 5.9 | 5.9 |
+| `spacing.margin.top` | 5.8 | 5.9 |
+| `spacing.margin.right` | 5.8 | 5.9 |
+| `spacing.margin.left` | 5.8 | 5.9 |
+| `spacing.margin.bottom` | 5.8 | 5.9 |
+| `spacing.blockGap` | 5.9 | 5.9 |
+| `dimensions.minHeight` | 6.2 | N/A |
+| `outline.color` | 6.2 | N/A |
+| `outline.offset` | 6.2 | N/A |
+| `outline.style` | 6.2 | N/A |
+| `outline.width` | 6.2 | N/A |
+| `filter.duotone` | 5.9 | N/A |
+| `shadow` | 6.1 | 6.2 |
diff --git a/docs/gutenberg/reference-guides/theme-json-reference/theme-json-living.md b/docs/gutenberg/reference-guides/theme-json-reference/theme-json-living.md
new file mode 100644
index 0000000..692ff23
--- /dev/null
+++ b/docs/gutenberg/reference-guides/theme-json-reference/theme-json-living.md
@@ -0,0 +1,364 @@
+# Theme.json Version 3 Reference (latest)
+
+> This is the living specification for **version 3** of `theme.json`. This version works with WordPress 6.6 or later, and the latest Gutenberg plugin.
+>
+> There are some related documents that you may be interested in:
+>
+> - the [theme.json v1](/docs/reference-guides/theme-json-reference/theme-json-v1.md) specification,
+> - the [theme.json v2](/docs/reference-guides/theme-json-reference/theme-json-v2.md) specification, and
+> - the [reference to migrate from older theme.json versions](/docs/reference-guides/theme-json-reference/theme-json-migrations.md).
+
+This reference guide lists the settings and style properties defined in the `theme.json` schema. See the [theme.json how to guide](/docs/how-to-guides/themes/global-settings-and-styles.md) for examples and guidance on how to use the `theme.json` file in your theme.
+
+## JSON Schema
+
+This documentation was generated from the JSON schema for theme.json.
+
+The latest schema for version 3, including all the latest changes from the Gutenberg plugin, is available at https://schemas.wp.org/trunk/theme.json.
+
+Theme.json schemas for each WordPress version are available at https://schemas.wp.org/wp/{{version}}/theme.json.
+For example, a schema for WordPress 5.8 is available at https://schemas.wp.org/wp/5.8/theme.json.
+
+See [Developing with theme.json](/docs/how-to-guides/themes/global-settings-and-styles.md#developing-with-themejson) for how to use the JSON schema in your editor.
+
+
+
+## settings
+
+Settings for the block editor and individual blocks. These include things like:
+
+- Which customization options should be available to the user.
+- The default colors, font sizes... available to the user.
+- CSS custom properties and class names used in styles.
+- And the default layout of the editor (widths and available alignments).
+
+### useRootPaddingAwareAlignments
+
+Enables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block.
+
+Please note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately.
+
+**Note:** Top-level only property. Not available in blocks.
+
+---
+
+### appearanceTools
+
+Setting that enables the following UI tools:
+
+- background: backgroundImage, backgroundSize
+- border: color, radius, style, width
+- color: link, heading, button, caption
+- dimensions: aspectRatio, minHeight
+- position: sticky
+- spacing: blockGap, margin, padding
+- typography: lineHeight
+
+---
+
+### background
+
+Settings related to background.
+
+| Property | Description | Type | Default |
+| --------------- | ------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
+| backgroundImage | Allow users to set a background image. | `boolean` | `false` |
+| backgroundSize | Allow users to set values related to the size of a background image, including size, position, and repeat controls. | `boolean` | `false` |
+
+---
+
+### border
+
+Settings related to borders.
+
+| Property | Description | Type | Default |
+| ----------- | ---------------------------------------------------------- | -------------------------- | ------- |
+| color | Allow users to set custom border colors. | `boolean` | `false` |
+| radius | Allow users to set custom border radius. | `boolean` | `false` |
+| style | Allow users to set custom border styles. | `boolean` | `false` |
+| width | Allow users to set custom border widths. | `boolean` | `false` |
+| radiusSizes | Border radius size presets for the border radius selector. | `[ { name, slug, size } ]` | |
+
+---
+
+### color
+
+Settings related to colors.
+
+| Property | Description | Type | Default |
+| ---------------- | ---------------------------------------------------------------------- | ------------------------------ | ------- |
+| background | Allow users to set background colors. | `boolean` | `true` |
+| custom | Allow users to select custom colors. | `boolean` | `true` |
+| customDuotone | Allow users to create custom duotone filters. | `boolean` | `true` |
+| customGradient | Allow users to create custom gradients. | `boolean` | `true` |
+| defaultDuotone | Allow users to choose filters from the default duotone filter presets. | `boolean` | `true` |
+| defaultGradients | Allow users to choose colors from the default gradients. | `boolean` | `true` |
+| defaultPalette | Allow users to choose colors from the default palette. | `boolean` | `true` |
+| duotone | Duotone presets for the duotone picker. | `[ { name, slug, colors } ]` | |
+| gradients | Gradient presets for the gradient picker. | `[ { name, slug, gradient } ]` | |
+| link | Allow users to set link colors in a block. | `boolean` | `false` |
+| palette | Color palette presets for the color picker. | `[ { name, slug, color } ]` | |
+| text | Allow users to set text colors in a block. | `boolean` | `true` |
+| heading | Allow users to set heading colors in a block. | `boolean` | `true` |
+| button | Allow users to set button colors in a block. | `boolean` | `true` |
+| caption | Allow users to set caption colors in a block. | `boolean` | `true` |
+
+---
+
+### dimensions
+
+Settings related to dimensions.
+
+| Property | Description | Type | Default |
+| ------------------- | -------------------------------------------------------------------------- | --------------------------- | ------- |
+| aspectRatio | Allow users to set an aspect ratio. | `boolean` | `false` |
+| defaultAspectRatios | Allow users to choose aspect ratios from the default set of aspect ratios. | `boolean` | `true` |
+| aspectRatios | Allow users to define aspect ratios for some blocks. | `[ { name, slug, ratio } ]` | |
+| minHeight | Allow users to set custom minimum height. | `boolean` | `false` |
+
+---
+
+### layout
+
+Settings related to layout.
+
+| Property | Description | Type | Default |
+| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
+| contentSize | Sets the max-width of the content. | `string` | |
+| wideSize | Sets the max-width of wide (`.alignwide`) content. Also used as the maximum viewport when calculating fluid font sizes | `string` | |
+| allowEditing | Disable the layout UI controls. | `boolean` | `true` |
+| allowCustomContentAndWideSize | Enable or disable the custom content and wide size controls. | `boolean` | `true` |
+
+---
+
+### lightbox
+
+Settings related to the lightbox.
+
+| Property | Description | Type | Default |
+| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
+| enabled | Defines whether the lightbox is enabled or not. | `boolean` | |
+| allowEditing | Defines whether to show the Lightbox UI in the block editor. If set to `false`, the user won't be able to change the lightbox settings in the block editor. | `boolean` | |
+
+---
+
+### position
+
+Settings related to position.
+
+| Property | Description | Type | Default |
+| -------- | ----------------------------------- | --------- | ------- |
+| sticky | Allow users to set sticky position. | `boolean` | `false` |
+
+---
+
+### shadow
+
+Settings related to shadows.
+
+| Property | Description | Type | Default |
+| -------------- | -------------------------------------------------------------- | ---------------------------- | ------- |
+| defaultPresets | Allow users to choose shadows from the default shadow presets. | `boolean` | `true` |
+| presets | Shadow presets for the shadow picker. | `[ { name, slug, shadow } ]` | |
+
+---
+
+### spacing
+
+Settings related to spacing.
+
+| Property | Description | Type | Default |
+| ------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------- | --------------------------------- |
+| blockGap | Enables `--wp--style--block-gap` to be generated from styles.spacing.blockGap. | `boolean`, `null` | `null` |
+| margin | Allow users to set a custom margin. | `boolean` | `false` |
+| padding | Allow users to set a custom padding. | `boolean` | `false` |
+| units | List of units the user can use for spacing values. | `[ string ]` | `["px","em","rem","vh","vw","%"]` |
+| customSpacingSize | Allow users to set custom space sizes. | `boolean` | `true` |
+| defaultSpacingSizes | Allow users to choose space sizes from the default space size presets. | `boolean` | `true` |
+| spacingSizes | Space size presets for the space size selector. | `[ { name, slug, size } ]` | |
+| spacingScale | Settings to auto-generate space size presets for the space size selector. | `{ operator, increment, steps, mediumStep, unit }` | |
+
+---
+
+### typography
+
+Settings related to typography.
+
+| Property | Description | Type | Default |
+| ---------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------- | ------- |
+| defaultFontSizes | Allow users to choose font sizes from the default font size presets. | `boolean` | `true` |
+| customFontSize | Allow users to set custom font sizes. | `boolean` | `true` |
+| fontStyle | Allow users to set custom font styles. | `boolean` | `true` |
+| fontWeight | Allow users to set custom font weights. | `boolean` | `true` |
+| fluid | Enables fluid typography and allows users to set global fluid typography parameters. | `boolean`, `{ minFontSize, maxViewportWidth, minViewportWidth }` | `false` |
+| letterSpacing | Allow users to set custom letter spacing. | `boolean` | `true` |
+| lineHeight | Allow users to set custom line height. | `boolean` | `false` |
+| textAlign | Allow users to set the text align. | `boolean` | `true` |
+| textColumns | Allow users to set the number of text columns. | `boolean` | `false` |
+| textDecoration | Allow users to set custom text decorations. | `boolean` | `true` |
+| writingMode | Allow users to set the writing mode. | `boolean` | `false` |
+| textTransform | Allow users to set custom text transforms. | `boolean` | `true` |
+| dropCap | Enable drop cap. | `boolean` | `true` |
+| fontSizes | Font size presets for the font size selector. | `[ { name, slug, size, fluid } ]` | |
+| fontFamilies | Font family presets for the font family selector. | `[ { name, slug, fontFamily, fontFace } ]` | |
+
+---
+
+### custom
+
+Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name.
+
+---
+
+## styles
+
+Organized way to set CSS properties. Styles in the top-level will be added in the `body` selector.
+
+### background
+
+Background styles.
+
+| Property | Description | Type |
+| -------------------- | ---------------------------------------------- | ------------------------------ |
+| backgroundImage | Sets the `background-image` CSS property. | `string`, `{ ref }`, `{ url }` |
+| backgroundPosition | Sets the `background-position` CSS property. | `string`, `{ ref }` |
+| backgroundRepeat | Sets the `background-repeat` CSS property. | `string`, `{ ref }` |
+| backgroundSize | Sets the `background-size` CSS property. | `string`, `{ ref }` |
+| backgroundAttachment | Sets the `background-attachment` CSS property. | `string`, `{ ref }` |
+
+---
+
+### border
+
+Border styles.
+
+| Property | Description | Type |
+| -------- | -------------------------------------- | --------------------------------------------------------------------- |
+| color | Sets the `border-color` CSS property. | `string`, `{ ref }` |
+| radius | Sets the `border-radius` CSS property. | `string`, `{ ref }`, `{ topLeft, topRight, bottomLeft, bottomRight }` |
+| style | Sets the `border-style` CSS property. | `string`, `{ ref }` |
+| width | Sets the `border-width` CSS property. | `string`, `{ ref }` |
+| top | | `{ color, style, width }` |
+| right | | `{ color, style, width }` |
+| bottom | | `{ color, style, width }` |
+| left | | `{ color, style, width }` |
+
+---
+
+### color
+
+Color styles.
+
+| Property | Description | Type |
+| ---------- | ----------------------------------------- | ------------------- |
+| background | Sets the `background-color` CSS property. | `string`, `{ ref }` |
+| gradient | Sets the `background` CSS property. | `string`, `{ ref }` |
+| text | Sets the `color` CSS property. | `string`, `{ ref }` |
+
+---
+
+### css
+
+Sets custom CSS to apply styling not covered by other theme.json properties.
+
+---
+
+### dimensions
+
+Dimensions styles.
+
+| Property | Description | Type |
+| ----------- | ------------------------------------- | ------------------- |
+| aspectRatio | Sets the `aspect-ratio` CSS property. | `string`, `{ ref }` |
+| minHeight | Sets the `min-height` CSS property. | `string`, `{ ref }` |
+
+---
+
+### filter
+
+CSS and SVG filter styles.
+
+| Property | Description | Type |
+| -------- | ------------------------ | ------------------- |
+| duotone | Sets the duotone filter. | `string`, `{ ref }` |
+
+---
+
+### outline
+
+Outline styles.
+
+| Property | Description | Type |
+| -------- | --------------------------------------- | ------------------- |
+| color | Sets the `outline-color` CSS property. | `string`, `{ ref }` |
+| offset | Sets the `outline-offset` CSS property. | `string`, `{ ref }` |
+| style | Sets the `outline-style` CSS property. | `string`, `{ ref }` |
+| width | Sets the `outline-width` CSS property. | `string`, `{ ref }` |
+
+---
+
+### shadow
+
+Box shadow styles.
+
+---
+
+### spacing
+
+Spacing styles.
+
+| Property | Description | Type |
+| -------- | --------------------------------------------------------------------------------------------- | ------------------------------ |
+| blockGap | Sets the `--wp--style--block-gap` CSS custom property when settings.spacing.blockGap is true. | `string`, `{ ref }` |
+| margin | Margin styles. | `{ top, right, bottom, left }` |
+| padding | Padding styles. | `{ top, right, bottom, left }` |
+
+---
+
+### typography
+
+Typography styles.
+
+| Property | Description | Type |
+| -------------- | ---------------------------------------- | ------------------- |
+| fontFamily | Sets the `font-family` CSS property. | `string`, `{ ref }` |
+| fontSize | Sets the `font-size` CSS property. | `string`, `{ ref }` |
+| fontStyle | Sets the `font-style` CSS property. | `string`, `{ ref }` |
+| fontWeight | Sets the `font-weight` CSS property. | `string`, `{ ref }` |
+| letterSpacing | Sets the `letter-spacing` CSS property. | `string`, `{ ref }` |
+| lineHeight | Sets the `line-height` CSS property. | `string`, `{ ref }` |
+| textAlign | Sets the `text-align` CSS property. | `string`, `{ ref }` |
+| textColumns | Sets the `column-count` CSS property. | `string`, `{ ref }` |
+| textDecoration | Sets the `text-decoration` CSS property. | `string`, `{ ref }` |
+| writingMode | Sets the `writing-mode` CSS property. | `string`, `{ ref }` |
+| textTransform | Sets the `text-transform` CSS property. | `string`, `{ ref }` |
+
+---
+
+## customTemplates
+
+Additional metadata for custom templates defined in the templates folder.
+
+| Property | Description | Type |
+| --------- | --------------------------------------------------------------------- | ------------ |
+| name | Filename, without extension, of the template in the templates folder. | `string` |
+| title | Title of the template, translatable. | `string` |
+| postTypes | List of post types that can use this custom template. | `[ string ]` |
+
+## templateParts
+
+Additional metadata for template parts defined in the parts folder.
+
+| Property | Description | Type |
+| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- |
+| name | Filename, without extension, of the template in the parts folder. | `string` |
+| title | Title of the template, translatable. | `string` |
+| area | The area the template part is used for. Block variations for `header` and `footer` values exist and will be used when the area is set to one of those. | `string` |
+
+## patterns
+
+An array of pattern slugs to be registered from the Pattern Directory.
+
+Type: `[ string ]`.
+
+
diff --git a/gutenberg/schemas/README.md b/docs/gutenberg/schemas/README.md
similarity index 73%
rename from gutenberg/schemas/README.md
rename to docs/gutenberg/schemas/README.md
index 58678e0..8ff7c11 100644
--- a/gutenberg/schemas/README.md
+++ b/docs/gutenberg/schemas/README.md
@@ -12,7 +12,7 @@ Update your `block.json` to include:
```json
{
- "$schema": "https://schemas.wp.org/trunk/block.json"
+ "$schema": "https://schemas.wp.org/trunk/block.json"
}
```
@@ -20,7 +20,7 @@ Or in your `theme.json`:
```json
{
- "$schema": "https://schemas.wp.org/trunk/theme.json"
+ "$schema": "https://schemas.wp.org/trunk/theme.json"
}
```
@@ -28,7 +28,7 @@ Or in your `font-collection.json`:
```json
{
- "$schema": "https://schemas.wp.org/trunk/font-collection.json"
+ "$schema": "https://schemas.wp.org/trunk/font-collection.json"
}
```
@@ -36,7 +36,7 @@ For a specific version of the schema, replace `trunk` with `wp/X.X`:
```json
{
- "$schema": "https://schemas.wp.org/wp/5.8/block.json"
+ "$schema": "https://schemas.wp.org/wp/5.8/block.json"
}
```
@@ -48,27 +48,27 @@ You may wish to update one of the schemas to conform to a new change in the stru
To allow this you will need to:
-- update your theme's `theme.json` to reference the _local_ version of the schema file:
+- update your theme's `theme.json` to reference the _local_ version of the schema file:
```json
{
- "$schema": "file://{{FULL_FILE_PATH}}/schemas/json/theme.json"
+ "$schema": "file://{{FULL_FILE_PATH}}/schemas/json/theme.json"
}
```
-- update your block's `block.json` to include:
+- update your block's `block.json` to include:
```json
{
- "$schema": "file://{{FULL_FILE_PATH}}/schemas/json/block.json"
+ "$schema": "file://{{FULL_FILE_PATH}}/schemas/json/block.json"
}
```
-- update your font collections's `font-collection.json` to include:
+- update your font collections's `font-collection.json` to include:
```json
{
- "$schema": "file://{{FULL_FILE_PATH}}/schemas/json/font-collection.json"
+ "$schema": "file://{{FULL_FILE_PATH}}/schemas/json/font-collection.json"
}
```
diff --git a/docs/gutenberg/schemas/json/block.json b/docs/gutenberg/schemas/json/block.json
new file mode 100644
index 0000000..c22c928
--- /dev/null
+++ b/docs/gutenberg/schemas/json/block.json
@@ -0,0 +1,931 @@
+{
+ "title": "JSON schema for WordPress blocks",
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "definitions": {
+ "//": {
+ "reference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/",
+ "attributesReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/",
+ "contextReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/",
+ "supportsReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/",
+ "registerReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#example-optional"
+ }
+ },
+ "type": "object",
+ "properties": {
+ "$schema": {
+ "type": "string"
+ },
+ "apiVersion": {
+ "description": "The version of the Block API used by the block. If the block is registered with API version 2 or lower, the post editor may work as a non-iframe editor. Since all editors are planned to work as iframes in the future, it is recommended to set the `apiVersion` field to 3 and test the block inside the iframe editor.\n\nSee the API versions documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-api-versions/ for more details.",
+ "type": "integer",
+ "const": 3
+ },
+ "name": {
+ "description": "The name for a block is a unique string that identifies a block. Names have to be structured as `namespace/block-name`, where namespace is the name of your plugin or theme.",
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$"
+ },
+ "__experimental": {
+ "description": "The name of the experiment this block is a part of, or boolean true if there is no specific experiment name.",
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "boolean"
+ }
+ ]
+ },
+ "title": {
+ "description": "This is the display title for your block, which can be translated with our translation functions. The block inserter will show this name.",
+ "type": "string"
+ },
+ "category": {
+ "description": "Blocks are grouped into categories to help users browse and discover them.\n Core provided categories are: text, media, design, widgets, theme, embed\n\nPlugins and Themes can also register custom block categories.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/#managing-block-categories",
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "string",
+ "enum": ["text", "media", "design", "widgets", "theme", "embed"]
+ }
+ ]
+ },
+ "parent": {
+ "description": "Setting parent lets a block require that it is only available when nested within the specified blocks. For example, you might want to allow an ‘Add to Cart’ block to only be available within a ‘Product’ block.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "ancestor": {
+ "description": "The `ancestor` property makes a block available inside the specified block types at any position of the ancestor block subtree. That allows, for example, to place a ‘Comment Content’ block inside a ‘Column’ block, as long as ‘Column’ is somewhere within a ‘Comment Template’ block.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allowedBlocks": {
+ "description": "The `allowedBlocks` property specifies that only the listed block types can be the children of this block. For example, a ‘List’ block allows only ‘List Item’ blocks as direct children.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "icon": {
+ "description": "An icon property should be specified to make it easier to identify a block. These can be any of WordPress’ Dashicons (slug serving also as a fallback in non-js contexts).",
+ "type": "string"
+ },
+ "description": {
+ "description": "This is a short description for your block, which can be translated with our translation functions. This will be shown in the block inspector.",
+ "type": "string"
+ },
+ "keywords": {
+ "description": "Sometimes a block could have aliases that help users discover it while searching. For example, an image block could also want to be discovered by photo. You can do so by providing an array of unlimited terms (which are translated).",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "version": {
+ "description": "The current version number of the block, such as 1.0 or 1.0.3. It’s similar to how plugins are versioned. This field might be used with block assets to control cache invalidation, and when the block author omits it, then the installed version of WordPress is used instead.",
+ "type": "string"
+ },
+ "textdomain": {
+ "description": "The gettext text domain of the plugin/block. More information can be found in the Text Domain section of the How to Internationalize your Plugin page.\n\nhttps://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/",
+ "type": "string"
+ },
+ "attributes": {
+ "description": "Attributes provide the structured data needs of a block. They can exist in different forms when they are serialized, but they are declared together under a common interface.\n\nSee the attributes documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/ for more details.",
+ "type": "object",
+ "patternProperties": {
+ "[a-zA-Z]": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "description": "The type indicates the type of data that is stored by the attribute. It does not indicate where the data is stored, which is defined by the source field.\n\nA type is required, unless an enum is provided. A type can be used with an enum.\n\nNote that the validity of an object is determined by your source. For an example, see the query details below.",
+ "oneOf": [
+ {
+ "type": "string",
+ "enum": [
+ "null",
+ "boolean",
+ "object",
+ "array",
+ "string",
+ "rich-text",
+ "integer",
+ "number"
+ ]
+ },
+ {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "enum": ["null", "boolean", "object", "array", "string", "integer", "number"]
+ }
+ }
+ ]
+ },
+ "enum": {
+ "description": "An attribute can be defined as one of a fixed set of values. This is specified by an enum, which contains an array of allowed values:",
+ "type": "array",
+ "items": {
+ "oneOf": [{ "type": "boolean" }, { "type": "number" }, { "type": "string" }]
+ }
+ },
+ "source": {
+ "description": "Attribute sources are used to define how the attribute values are extracted from saved post content. They provide a mechanism to map from the saved markup to a JavaScript representation of a block.",
+ "type": "string",
+ "enum": ["attribute", "text", "rich-text", "html", "raw", "query", "meta"]
+ },
+ "selector": {
+ "description": "The selector can be an HTML tag, or anything queryable with querySelector, such as a class or id attribute. Examples are given below.\n\nFor example, a selector of img will match an img element, and img.class will match an img element that has a class of class.",
+ "type": "string"
+ },
+ "attribute": {
+ "description": "Use an attribute source to extract the value from an attribute in the markup. The attribute is specified by the attribute field, which must be supplied.\n\nExample: Extract the src attribute from an image found in the block’s markup.",
+ "type": "string"
+ },
+ "query": {
+ "description": "Use query to extract an array of values from markup. Entries of the array are determined by the selector argument, where each matched element within the block will have an entry structured corresponding to the second argument, an object of attribute sources.",
+ "type": "object"
+ },
+ "meta": {
+ "description": "Although attributes may be obtained from a post’s meta, meta attribute sources are considered deprecated; EntityProvider and related hook APIs should be used instead, as shown in the Create Meta Block how-to here:\n\nhttps://developer.wordpress.org/block-editor/how-to-guides/metabox/#step-2-add-meta-block",
+ "type": "string"
+ },
+ "role": {
+ "description": "Designates the conceptual type of the attribute.\n\nThe `content` value marks the attribute as user-editable content, and the `local` value marks the attribute as temporary and non-persistable.",
+ "type": "string",
+ "enum": ["content", "local"]
+ },
+ "default": {
+ "description": "A block attribute can contain a default value, which will be used if the type and source do not match anything within the block content.\n\nThe value is provided by the default field, and the value should match the expected format of the attribute."
+ }
+ },
+ "anyOf": [{ "required": ["type"] }, { "required": ["enum"] }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "providesContext": {
+ "description": "Context provided for available access by descendants of blocks of this type, in the form of an object which maps a context name to one of the block’s own attribute.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.",
+ "type": "object",
+ "patternProperties": {
+ "[a-zA-Z]": {
+ "type": "string"
+ }
+ }
+ },
+ "usesContext": {
+ "description": "Array of the names of context values to inherit from an ancestor provider.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "supports": {
+ "description": "It contains as set of options to control features used in the editor. See the supports documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/ for more details.",
+ "type": "object",
+ "properties": {
+ "anchor": {
+ "description": "Anchors let you link directly to a specific block on a page. This property adds a field to define an id for the block and a button to copy the direct link.",
+ "type": "boolean",
+ "default": false
+ },
+ "align": {
+ "description": "This property adds block controls which allow to change block’s alignment.",
+ "oneOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["wide", "full", "left", "center", "right"]
+ }
+ }
+ ],
+ "default": false
+ },
+ "alignWide": {
+ "description": "This property allows to enable wide alignment for your theme. To disable this behavior for a single block, set this flag to false.",
+ "type": "boolean",
+ "default": true
+ },
+ "ariaLabel": {
+ "description": "ARIA-labels let you define an accessible label for elements. This property allows enabling the definition of an aria-label for the block, without exposing a UI field.",
+ "type": "boolean",
+ "default": false
+ },
+ "className": {
+ "description": "By default, the class .wp-block-your-block-name is added to the root element of your saved markup. This helps having a consistent mechanism for styling blocks that themes and plugins can rely on. If, for whatever reason, a class is not desired on the markup, this functionality can be disabled.",
+ "type": "boolean",
+ "default": true
+ },
+ "color": {
+ "description": "This value signals that a block supports some of the properties related to color. When it does, the block editor will show UI controls for the user to set their values.\n\nNote that the background and text keys have a default value of true, so if the color property is present they’ll also be considered enabled",
+ "type": "object",
+ "properties": {
+ "background": {
+ "description": "This property adds UI controls which allow the user to apply a solid background color to a block.\n\nWhen color support is declared, this property is enabled by default (along with text), so simply setting color will enable background color.\n\nTo disable background support while keeping other color supports enabled, set to false.\n\nWhen the block declares support for color.background, its attributes definition is extended to include two new attributes: backgroundColor and style",
+ "type": "boolean",
+ "default": true
+ },
+ "gradients": {
+ "description": "This property adds UI controls which allow the user to apply a gradient background to a block.\n\nGradient presets are sourced from editor-gradient-presets theme support.\n\nWhen the block declares support for color.gradient, its attributes definition is extended to include two new attributes: gradient and style",
+ "type": "boolean",
+ "default": false
+ },
+ "link": {
+ "description": "This property adds block controls which allow the user to set link color in a block, link color is disabled by default.\n\nLink color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.link, its attributes definition is extended to include the style attribute",
+ "type": "boolean",
+ "default": false
+ },
+ "text": {
+ "description": "This property adds block controls which allow the user to set text color in a block.\n\nWhen color support is declared, this property is enabled by default (along with background), so simply setting color will enable text color.\n\nText color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.text, its attributes definition is extended to include two new attributes: textColor and style",
+ "type": "boolean",
+ "default": true
+ },
+ "heading": {
+ "description": "This property adds block controls which allow the user to set heading colors in a block. Heading color is disabled by default.\n\nHeading color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.heading, its attributes definition is extended to include the style attribute",
+ "type": "boolean",
+ "default": false
+ },
+ "button": {
+ "description": "This property adds block controls which allow the user to set button colors in a block. Button color is disabled by default.\n\nButton color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.button, its attributes definition is extended to include the style attribute",
+ "type": "boolean",
+ "default": false
+ },
+ "enableContrastChecker": {
+ "description": "Determines whether the contrast checker widget displays in the block editor UI.\n\nThe contrast checker appears only if the block declares support for color. It tests the readability of color combinations and warns if there is a potential issue. The property is enabled by default.\n\nSet to `false` to explicitly disable.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ },
+ "customClassName": {
+ "description": "This property adds a field to define a custom className for the block’s wrapper.",
+ "type": "boolean",
+ "default": true
+ },
+ "dimensions": {
+ "description": "This value signals that a block supports some of the CSS style properties related to dimensions. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific dimensions property, its attributes definition is extended to include the style attribute.",
+ "type": "object",
+ "properties": {
+ "aspectRatio": {
+ "description": "Allow blocks to define an aspect ratio value.",
+ "type": "boolean",
+ "default": false
+ },
+ "minHeight": {
+ "description": "Allow blocks to define a minimum height value.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "filter": {
+ "description": "This value signals that a block supports some of the properties related to filters. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific filter property, its attributes definition is extended to include the style attribute.",
+ "type": "object",
+ "properties": {
+ "duotone": {
+ "description": "Allow blocks to define a duotone filter.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "background": {
+ "description": "This value signals that a block supports some of the CSS style properties related to background. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific background property, its attributes definition is extended to include the style attribute.",
+ "type": "object",
+ "properties": {
+ "backgroundImage": {
+ "description": "Allow blocks to define a background image.",
+ "type": "boolean",
+ "default": false
+ },
+ "backgroundSize": {
+ "description": "Allow blocks to define values related to the size of a background image, including size, position, and repeat controls",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "html": {
+ "description": "By default, a block’s markup can be edited individually. To disable this behavior, set html to false.",
+ "type": "boolean",
+ "default": true
+ },
+ "inserter": {
+ "description": "By default, all blocks will appear in the inserter, block transforms menu, Style Book, etc. To hide a block from all parts of the user interface so that it can only be inserted programmatically, set inserter to false.",
+ "type": "boolean",
+ "default": true
+ },
+ "renaming": {
+ "description": "By default, a block can be renamed by a user from the block 'Options' dropdown or the 'Advanced' panel. To disable this behavior, set renaming to false.",
+ "type": "boolean",
+ "default": true
+ },
+ "layout": {
+ "description": "This value only applies to blocks that are containers for inner blocks. If set to `true` the layout type will be `flow`. For other layout types it's necessary to set the `type` explicitly inside the `default` object.",
+ "oneOf": [
+ { "type": "boolean" },
+ {
+ "type": "object",
+ "properties": {
+ "default": {
+ "description": "Allows setting the `type` property to define what layout type is default for the block, and also default values for any properties inherent to that layout type, e.g., for a `flex` layout, a default value can be set for `flexWrap`.",
+ "type": "object",
+ "properties": {
+ "type": {
+ "description": "The layout type.",
+ "type": "string",
+ "enum": ["constrained", "grid", "flex"]
+ },
+ "contentSize": {
+ "description": "The content size used on all children.",
+ "type": "string"
+ },
+ "wideSize": {
+ "description": "The wide size used on alignwide children.",
+ "type": "string"
+ },
+ "justifyContent": {
+ "description": "Content justification value.",
+ "type": "string",
+ "enum": ["right", "center", "space-between", "left", "stretch"]
+ },
+ "orientation": {
+ "description": "The orientation of the layout.",
+ "type": "string",
+ "enum": ["horizontal", "vertical"]
+ },
+ "flexWrap": {
+ "description": "The flex wrap value.",
+ "type": "string",
+ "enum": ["wrap", "nowrap"]
+ },
+ "verticalAlignment": {
+ "description": "The vertical alignment value.",
+ "type": "string",
+ "enum": ["top", "center", "bottom", "space-between", "stretch"]
+ },
+ "minimumColumnWidth": {
+ "description": "The minimum column width value.",
+ "type": "string"
+ },
+ "columnCount": {
+ "description": "The column count value.",
+ "type": "number"
+ }
+ }
+ },
+ "allowSwitching": {
+ "description": "Exposes a switcher control that allows toggling between all existing layout types.",
+ "type": "boolean",
+ "default": false
+ },
+ "allowEditing": {
+ "description": "Determines display of layout controls in the block sidebar. If set to false, layout controls will be hidden.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowInheriting": {
+ "description": "For the `flow` layout type only, determines display of the `Inner blocks use content width` toggle.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowSizingOnChildren": {
+ "description": "For the `flex` layout type only, determines display of sizing controls (Fit/Fill/Fixed) on all child blocks of the flex block.",
+ "type": "boolean",
+ "default": false
+ },
+ "allowVerticalAlignment": {
+ "description": "For the `flex` layout type only, determines display of vertical alignment controls in the block toolbar.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowJustification": {
+ "description": "For the `flex` layout type, determines display of justification controls in the block toolbar and block sidebar. For the `constrained` layout type, determines display of justification control in the block sidebar.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowOrientation": {
+ "description": "For the `flex` layout type only, determines display of the orientation control in the block toolbar.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowCustomContentAndWideSize": {
+ "description": "For the `constrained` layout type only, determines display of the custom content and wide size controls in the block sidebar.",
+ "type": "boolean",
+ "default": true
+ }
+ }
+ }
+ ],
+ "default": false
+ },
+ "multiple": {
+ "description": "A non-multiple block can be inserted into each post, one time only. For example, the built-in ‘More’ block cannot be inserted again if it already exists in the post being edited. A non-multiple block’s icon is automatically dimmed (unclickable) to prevent multiple instances.",
+ "type": "boolean",
+ "default": true
+ },
+ "reusable": {
+ "description": "A block may want to disable the ability of being converted into a reusable block. By default all blocks can be converted to a reusable block. If supports reusable is set to false, the option to convert the block into a reusable block will not appear.",
+ "type": "boolean",
+ "default": true
+ },
+ "lock": {
+ "description": "A block may want to disable the ability to toggle the lock state. It can be locked/unlocked by a user from the block 'Options' dropdown by default. To disable this behavior, set lock to false.",
+ "type": "boolean",
+ "default": true
+ },
+ "position": {
+ "description": "This value signals that a block supports some of the CSS style properties related to position. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific position property, its attributes definition is extended to include the style attribute.",
+ "type": "object",
+ "properties": {
+ "sticky": {
+ "description": "Allow blocks to stick to their immediate parent when scrolling the page.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "spacing": {
+ "description": "This value signals that a block supports some of the CSS style properties related to spacing. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific spacing property, its attributes definition is extended to include the style attribute.",
+ "type": "object",
+ "properties": {
+ "margin": {
+ "oneOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["top", "right", "left", "bottom"]
+ }
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["vertical", "horizontal"]
+ }
+ }
+ ]
+ },
+ "padding": {
+ "oneOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["top", "right", "left", "bottom"]
+ }
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["vertical", "horizontal"]
+ }
+ }
+ ]
+ }
+ }
+ },
+ "shadow": {
+ "description": "Allow blocks to define a box shadow.",
+ "oneOf": [
+ {
+ "description": "Defines whether a box shadow is enabled or not.",
+ "type": "boolean"
+ },
+ {
+ "type": "object"
+ }
+ ],
+ "default": false
+ },
+ "typography": {
+ "description": "This value signals that a block supports some of the CSS style properties related to typography. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific typography property, its attributes definition is extended to include the style attribute.",
+ "type": "object",
+ "properties": {
+ "fontSize": {
+ "description": "This value signals that a block supports the font-size CSS style property. When it does, the block editor will show an UI control for the user to set its value.\n\nThe values shown in this control are the ones declared by the theme via the editor-font-sizes theme support, or the default ones if none is provided.\n\nWhen the block declares support for fontSize, its attributes definition is extended to include two new attributes: fontSize and style",
+ "type": "boolean",
+ "default": false
+ },
+ "lineHeight": {
+ "description": "This value signals that a block supports the line-height CSS style property. When it does, the block editor will show an UI control for the user to set its value if the theme declares support.\n\nWhen the block declares support for lineHeight, its attributes definition is extended to include a new attribute style of object type with no default assigned. It stores the custom value set by the user. The block can apply a default style by specifying its own style attribute with a default",
+ "type": "boolean",
+ "default": false
+ },
+ "textAlign": {
+ "description": "This property adds block toolbar controls which allow to change block's text alignment.",
+ "oneOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["left", "center", "right"]
+ }
+ }
+ ],
+ "default": false
+ }
+ }
+ },
+ "interactivity": {
+ "description": "Indicates if the block is using Interactivity API features.",
+ "oneOf": [
+ {
+ "description": "Indicates whether the block is using the Interactivity API directives.",
+ "type": "boolean",
+ "default": false
+ },
+ {
+ "type": "object",
+ "properties": {
+ "clientNavigation": {
+ "description": "Indicates whether a block is compatible with the Interactivity API client-side navigation.\n\nSet it to true only if the block is not interactive or if it is interactive using the Interactivity API. Set it to false if the block is interactive but uses vanilla JS, jQuery or another JS framework/library other than the Interactivity API.",
+ "type": "boolean",
+ "default": false
+ },
+ "interactive": {
+ "description": "Indicates whether the block is using the Interactivity API directives.",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ ]
+ },
+ "splitting": {
+ "description": "This property indicates whether the block can split when the Enter key is pressed or when blocks are pasted.",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": true
+ },
+ "selectors": {
+ "description": "Provides custom CSS selectors and mappings for the block. Selectors may be set for the block itself or per-feature e.g. typography. Custom selectors per feature or sub-feature, allow different block styles to be applied to different elements within the block.",
+ "type": "object",
+ "properties": {
+ "root": {
+ "description": "The primary CSS class to apply to the block. This replaces the `.wp-block-name` class if set.",
+ "type": "string"
+ },
+ "border": {
+ "description": "Custom CSS selector used to generate rules for the block's theme.json border styles.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "root": { "type": "string" },
+ "color": { "type": "string" },
+ "radius": { "type": "string" },
+ "style": { "type": "string" },
+ "width": { "type": "string" }
+ }
+ }
+ ]
+ },
+ "color": {
+ "description": "Custom CSS selector used to generate rules for the block's theme.json color styles.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "root": { "type": "string" },
+ "text": { "type": "string" },
+ "background": { "type": "string" }
+ }
+ }
+ ]
+ },
+ "dimensions": {
+ "description": "Custom CSS selector used to generate rules for the block's theme.json dimensions styles.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "root": { "type": "string" },
+ "aspectRatio": { "type": "string" },
+ "minHeight": { "type": "string" }
+ }
+ }
+ ]
+ },
+ "spacing": {
+ "description": "Custom CSS selector used to generate rules for the block's theme.json spacing styles.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "root": { "type": "string" },
+ "blockGap": { "type": "string" },
+ "padding": { "type": "string" },
+ "margin": { "type": "string" }
+ }
+ }
+ ]
+ },
+ "typography": {
+ "description": "Custom CSS selector used to generate rules for the block's theme.json typography styles.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "root": { "type": "string" },
+ "fontFamily": { "type": "string" },
+ "fontSize": { "type": "string" },
+ "fontStyle": { "type": "string" },
+ "fontWeight": { "type": "string" },
+ "lineHeight": { "type": "string" },
+ "letterSpacing": { "type": "string" },
+ "textDecoration": { "type": "string" },
+ "textTransform": { "type": "string" }
+ }
+ }
+ ]
+ }
+ }
+ },
+ "styles": {
+ "description": "Block styles can be used to provide alternative styles to block. It works by adding a class name to the block’s wrapper. Using CSS, a theme developer can target the class name for the block style if it is selected.\n\nPlugins and Themes can also register custom block style for existing blocks.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "label": {
+ "type": "string"
+ },
+ "isDefault": {
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "required": ["name", "label"],
+ "additionalProperties": false
+ }
+ },
+ "example": {
+ "description": "It provides structured example data for the block. This data is used to construct a preview for the block to be shown in the Inspector Help Panel when the user mouses over the block.\n\nSee the example documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#example-optional for more details.",
+ "type": "object",
+ "properties": {
+ "viewportWidth": {
+ "description": "The viewportWidth controls the width of the iFrame container in which the block preview will get rendered",
+ "type": "number",
+ "default": 1200
+ },
+ "attributes": {
+ "description": "Set the attributes for the block example",
+ "type": "object"
+ },
+ "innerBlocks": {
+ "description": "Set the inner blocks that should be used within the block example. The blocks should be defined as a nested array like this:\n\n[ { \"name\": \"core/heading\", \"attributes\": { \"content\": \"This is an Example\" } } ]\n\nWhere each block itself is an object that contains the block name, the block attributes, and the blocks inner blocks.",
+ "type": "array"
+ }
+ }
+ },
+ "blockHooks": {
+ "description": "Block Hooks allow a block to automatically insert itself next to all instances of a given block type.\n\nSee the Block Hooks documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#block-hooks-optional for more details.",
+ "type": "object",
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
+ "type": "string",
+ "enum": ["before", "after", "firstChild", "lastChild"]
+ }
+ },
+ "additionalProperties": false
+ },
+ "editorScript": {
+ "description": "Block type editor script definition. It will only be enqueued in the context of the editor.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "script": {
+ "description": "Block type frontend and editor script definition. It will be enqueued both in the editor and when viewing the content on the front of the site.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "viewScript": {
+ "description": "Block type frontend script definition. It will be enqueued only when viewing the content on the front of the site.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "viewScriptModule": {
+ "description": "Block type frontend script module definition. It will be enqueued only when viewing the content on the front of the site.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "editorStyle": {
+ "description": "Block type editor style definition. It will only be enqueued in the context of the editor.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "style": {
+ "description": "Block type frontend style definition. It will be enqueued both in the editor and when viewing the content on the front of the site.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "viewStyle": {
+ "description": "Block type frontend style definition. It will be enqueued only when viewing the content on the front of the site.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "variations": {
+ "description": "Block Variations is the API that allows a block to have similar versions of it, but all these versions share some common functionality.",
+ "oneOf": [
+ {
+ "description": "The path to a PHP file that returns an array of block variations.",
+ "type": "string"
+ },
+ {
+ "description": "An array of block variations.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "The unique and machine-readable name.",
+ "type": "string"
+ },
+ "title": {
+ "description": "A human-readable variation title.",
+ "type": "string"
+ },
+ "description": {
+ "description": "A detailed variation description.",
+ "type": "string"
+ },
+ "category": {
+ "description": "A category classification, used in search interfaces to arrange block types by category.",
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "string",
+ "enum": ["text", "media", "design", "widgets", "theme", "embed"]
+ }
+ ]
+ },
+ "icon": {
+ "description": "An icon helping to visualize the variation. It can have the same shape as the block type.",
+ "type": "string"
+ },
+ "isDefault": {
+ "description": "Indicates whether the current variation is the default one.",
+ "type": "boolean",
+ "default": false
+ },
+ "attributes": {
+ "description": "Values that override block attributes.",
+ "type": "object"
+ },
+ "innerBlocks": {
+ "description": "Initial configuration of nested blocks.",
+ "type": "array",
+ "items": {
+ "type": "array"
+ }
+ },
+ "example": {
+ "description": "Example provides structured data for the block preview. You can set to undefined to disable the preview shown for the block type.",
+ "type": "object"
+ },
+ "scope": {
+ "description": "The list of scopes where the variation is applicable.",
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": ["inserter", "block", "transform"]
+ },
+ "default": ["inserter", "block"]
+ },
+ "keywords": {
+ "description": "An array of terms (which can be translated) that help users discover the variation while searching.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "isActive": {
+ "description": "The list of attributes that should be compared. Each attributes will be matched and the variation will be active if all of them are matching.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": ["name", "title"],
+ "additionalProperties": false
+ }
+ }
+ ]
+ },
+ "render": {
+ "description": "Template file loaded on the server when rendering a block.",
+ "type": "string"
+ }
+ },
+ "required": ["apiVersion", "name", "title"],
+ "additionalProperties": false
+}
diff --git a/docs/gutenberg/schemas/json/font-collection.json b/docs/gutenberg/schemas/json/font-collection.json
new file mode 100644
index 0000000..ff91b32
--- /dev/null
+++ b/docs/gutenberg/schemas/json/font-collection.json
@@ -0,0 +1,146 @@
+{
+ "title": "JSON schema for WordPress Font Collections",
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "definitions": {
+ "fontFace": {
+ "description": "Font face settings, with added preview property.",
+ "type": "object",
+ "properties": {
+ "preview": {
+ "description": "URL to a preview image of the font.",
+ "type": "string"
+ },
+ "fontFamily": {
+ "description": "CSS font-family value.",
+ "type": "string",
+ "default": ""
+ },
+ "fontStyle": {
+ "description": "CSS font-style value.",
+ "type": "string",
+ "default": "normal"
+ },
+ "fontWeight": {
+ "description": "List of available font weights, separated by a space.",
+ "oneOf": [{ "type": "string" }, { "type": "integer" }],
+ "default": "400"
+ },
+ "fontDisplay": {
+ "description": "CSS font-display value.",
+ "type": "string",
+ "enum": ["auto", "block", "fallback", "swap", "optional"],
+ "default": "fallback"
+ },
+ "src": {
+ "description": "Paths or URLs to the font files.",
+ "oneOf": [
+ { "type": "string" },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ],
+ "default": []
+ },
+ "fontStretch": {
+ "description": "CSS font-stretch value.",
+ "type": "string"
+ },
+ "ascentOverride": {
+ "description": "CSS ascent-override value.",
+ "type": "string"
+ },
+ "descentOverride": {
+ "description": "CSS descent-override value.",
+ "type": "string"
+ },
+ "fontVariant": {
+ "description": "CSS font-variant value.",
+ "type": "string"
+ },
+ "fontFeatureSettings": {
+ "description": "CSS font-feature-settings value.",
+ "type": "string"
+ },
+ "fontVariationSettings": {
+ "description": "CSS font-variation-settings value.",
+ "type": "string"
+ },
+ "lineGapOverride": {
+ "description": "CSS line-gap-override value.",
+ "type": "string"
+ },
+ "sizeAdjust": {
+ "description": "CSS size-adjust value.",
+ "type": "string"
+ },
+ "unicodeRange": {
+ "description": "CSS unicode-range value.",
+ "type": "string"
+ }
+ },
+ "required": ["fontFamily", "src"],
+ "additionalProperties": false
+ }
+ },
+ "type": "object",
+ "properties": {
+ "$schema": {
+ "description": "JSON schema URI for font-collection.json.",
+ "type": "string"
+ },
+ "font_families": {
+ "description": "Array of font families ready to be installed.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "font_family_settings": {
+ "description": "Font family settings, with added preview property.",
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the font family preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the font family preset.",
+ "type": "string"
+ },
+ "fontFamily": {
+ "description": "CSS font-family value.",
+ "type": "string"
+ },
+ "preview": {
+ "description": "URL to a preview image of the font family.",
+ "type": "string"
+ },
+ "fontFace": {
+ "description": "Array of font-face definitions.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/fontFace"
+ }
+ }
+ },
+ "required": ["name", "fontFamily", "slug"],
+ "additionalProperties": false
+ },
+ "categories": {
+ "description": "Array of category slugs.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": ["font_family_settings"],
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false,
+ "required": ["font_families"]
+}
diff --git a/docs/gutenberg/schemas/json/theme.json b/docs/gutenberg/schemas/json/theme.json
new file mode 100644
index 0000000..f1031d1
--- /dev/null
+++ b/docs/gutenberg/schemas/json/theme.json
@@ -0,0 +1,2585 @@
+{
+ "title": "JSON schema for WordPress block theme global settings and styles",
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "definitions": {
+ "//": {
+ "explainer": "https://developer.wordpress.org/themes/global-settings-and-styles/",
+ "createTheme": "https://developer.wordpress.org/themes/",
+ "reference": "https://developer.wordpress.org/block-editor/how-to-guides/themes/global-settings-and-styles/"
+ },
+ "refComplete": {
+ "type": "object",
+ "properties": {
+ "ref": {
+ "description": "A reference to another property value. e.g. `styles.color.text`",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ },
+ "settingsAppearanceToolsProperties": {
+ "type": "object",
+ "properties": {
+ "appearanceTools": {
+ "description": "Setting that enables the following UI tools:\n\n- background: backgroundImage, backgroundSize\n- border: color, radius, style, width\n- color: link, heading, button, caption\n- dimensions: aspectRatio, minHeight\n- position: sticky\n- spacing: blockGap, margin, padding\n- typography: lineHeight",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "settingsBackgroundProperties": {
+ "type": "object",
+ "properties": {
+ "background": {
+ "description": "Settings related to background.",
+ "type": "object",
+ "properties": {
+ "backgroundImage": {
+ "description": "Allow users to set a background image.",
+ "type": "boolean",
+ "default": false
+ },
+ "backgroundSize": {
+ "description": "Allow users to set values related to the size of a background image, including size, position, and repeat controls.",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsBorderProperties": {
+ "type": "object",
+ "properties": {
+ "border": {
+ "description": "Settings related to borders.",
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Allow users to set custom border colors.",
+ "type": "boolean",
+ "default": false
+ },
+ "radius": {
+ "description": "Allow users to set custom border radius.",
+ "type": "boolean",
+ "default": false
+ },
+ "style": {
+ "description": "Allow users to set custom border styles.",
+ "type": "boolean",
+ "default": false
+ },
+ "width": {
+ "description": "Allow users to set custom border widths.",
+ "type": "boolean",
+ "default": false
+ },
+ "radiusSizes": {
+ "description": "Border radius size presets for the border radius selector.\nGenerates a custom property (`--wp--preset--border-radius--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the border radius size preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Unique identifier for the border raidus size preset.",
+ "type": "string"
+ },
+ "size": {
+ "description": "CSS border-radius value, including units.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsColorProperties": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Settings related to colors.",
+ "type": "object",
+ "properties": {
+ "background": {
+ "description": "Allow users to set background colors.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom": {
+ "description": "Allow users to select custom colors.",
+ "type": "boolean",
+ "default": true
+ },
+ "customDuotone": {
+ "description": "Allow users to create custom duotone filters.",
+ "type": "boolean",
+ "default": true
+ },
+ "customGradient": {
+ "description": "Allow users to create custom gradients.",
+ "type": "boolean",
+ "default": true
+ },
+ "defaultDuotone": {
+ "description": "Allow users to choose filters from the default duotone filter presets.",
+ "type": "boolean",
+ "default": true
+ },
+ "defaultGradients": {
+ "description": "Allow users to choose colors from the default gradients.",
+ "type": "boolean",
+ "default": true
+ },
+ "defaultPalette": {
+ "description": "Allow users to choose colors from the default palette.",
+ "type": "boolean",
+ "default": true
+ },
+ "duotone": {
+ "description": "Duotone presets for the duotone picker.\nDoesn't generate classes or properties.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the duotone preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the duotone preset.",
+ "type": "string"
+ },
+ "colors": {
+ "description": "List of colors from dark to light.",
+ "type": "array",
+ "items": {
+ "description": "CSS hex or rgb string.",
+ "type": "string"
+ }
+ }
+ },
+ "required": ["name", "slug", "colors"],
+ "additionalProperties": false
+ }
+ },
+ "gradients": {
+ "description": "Gradient presets for the gradient picker.\nGenerates a single class (`.has-{slug}-background`) and custom property (`--wp--preset--gradient--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the gradient preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the gradient preset.",
+ "type": "string"
+ },
+ "gradient": {
+ "description": "CSS gradient string.",
+ "type": "string"
+ }
+ },
+ "required": ["name", "slug", "gradient"],
+ "additionalProperties": false
+ }
+ },
+ "link": {
+ "description": "Allow users to set link colors in a block.",
+ "type": "boolean",
+ "default": false
+ },
+ "palette": {
+ "description": "Color palette presets for the color picker.\nGenerates three classes (`.has-{slug}-color`, `.has-{slug}-background-color`, and `.has-{slug}-border-color`) and a single custom property (`--wp--preset--color--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the color preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the color preset.",
+ "type": "string"
+ },
+ "color": {
+ "description": "CSS hex or rgb(a) string.",
+ "type": "string"
+ }
+ },
+ "required": ["name", "slug", "color"],
+ "additionalProperties": false
+ }
+ },
+ "text": {
+ "description": "Allow users to set text colors in a block.",
+ "type": "boolean",
+ "default": true
+ },
+ "heading": {
+ "description": "Allow users to set heading colors in a block.",
+ "type": "boolean",
+ "default": true
+ },
+ "button": {
+ "description": "Allow users to set button colors in a block.",
+ "type": "boolean",
+ "default": true
+ },
+ "caption": {
+ "description": "Allow users to set caption colors in a block.",
+ "type": "boolean",
+ "default": true
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsDimensionsProperties": {
+ "type": "object",
+ "properties": {
+ "dimensions": {
+ "description": "Settings related to dimensions.",
+ "type": "object",
+ "properties": {
+ "aspectRatio": {
+ "description": "Allow users to set an aspect ratio.",
+ "type": "boolean",
+ "default": false
+ },
+ "defaultAspectRatios": {
+ "description": "Allow users to choose aspect ratios from the default set of aspect ratios.",
+ "type": "boolean",
+ "default": true
+ },
+ "aspectRatios": {
+ "description": "Allow users to define aspect ratios for some blocks.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the aspect ratio preset.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the aspect ratio preset.",
+ "type": "string"
+ },
+ "ratio": {
+ "description": "Aspect ratio expressed as a division or decimal.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "minHeight": {
+ "description": "Allow users to set custom minimum height.",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsLayoutProperties": {
+ "type": "object",
+ "properties": {
+ "layout": {
+ "description": "Settings related to layout.",
+ "type": "object",
+ "properties": {
+ "contentSize": {
+ "description": "Sets the max-width of the content.",
+ "type": "string"
+ },
+ "wideSize": {
+ "description": "Sets the max-width of wide (`.alignwide`) content. Also used as the maximum viewport when calculating fluid font sizes",
+ "type": "string"
+ },
+ "allowEditing": {
+ "description": "Disable the layout UI controls.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowCustomContentAndWideSize": {
+ "description": "Enable or disable the custom content and wide size controls.",
+ "type": "boolean",
+ "default": true
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsLightboxProperties": {
+ "type": "object",
+ "properties": {
+ "lightbox": {
+ "description": "Settings related to the lightbox.",
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "description": "Defines whether the lightbox is enabled or not.",
+ "type": "boolean"
+ },
+ "allowEditing": {
+ "description": "Defines whether to show the Lightbox UI in the block editor. If set to `false`, the user won't be able to change the lightbox settings in the block editor.",
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsPositionProperties": {
+ "type": "object",
+ "properties": {
+ "position": {
+ "description": "Settings related to position.",
+ "type": "object",
+ "properties": {
+ "sticky": {
+ "description": "Allow users to set sticky position.",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsShadowProperties": {
+ "type": "object",
+ "properties": {
+ "shadow": {
+ "description": "Settings related to shadows.",
+ "type": "object",
+ "properties": {
+ "defaultPresets": {
+ "description": "Allow users to choose shadows from the default shadow presets.",
+ "type": "boolean",
+ "default": true
+ },
+ "presets": {
+ "description": "Shadow presets for the shadow picker.\nGenerates a single custom property (`--wp--preset--shadow--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the shadow preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the shadow preset.",
+ "type": "string"
+ },
+ "shadow": {
+ "description": "CSS box-shadow value",
+ "type": "string"
+ }
+ },
+ "required": ["name", "slug", "shadow"],
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsSpacingProperties": {
+ "type": "object",
+ "properties": {
+ "spacing": {
+ "description": "Settings related to spacing.",
+ "type": "object",
+ "properties": {
+ "blockGap": {
+ "description": "Enables `--wp--style--block-gap` to be generated from styles.spacing.blockGap.\nA value of `null` instead of `false` further disables layout styles from being generated.",
+ "oneOf": [{ "type": "boolean" }, { "type": "null" }],
+ "default": null
+ },
+ "margin": {
+ "description": "Allow users to set a custom margin.",
+ "type": "boolean",
+ "default": false
+ },
+ "padding": {
+ "description": "Allow users to set a custom padding.",
+ "type": "boolean",
+ "default": false
+ },
+ "units": {
+ "description": "List of units the user can use for spacing values.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "minItems": 1,
+ "default": ["px", "em", "rem", "vh", "vw", "%"]
+ },
+ "customSpacingSize": {
+ "description": "Allow users to set custom space sizes.",
+ "type": "boolean",
+ "default": true
+ },
+ "defaultSpacingSizes": {
+ "description": "Allow users to choose space sizes from the default space size presets.",
+ "type": "boolean",
+ "default": true
+ },
+ "spacingSizes": {
+ "description": "Space size presets for the space size selector.\nGenerates a custom property (`--wp--preset--spacing--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the space size preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Unique identifier for the space size preset. For best cross theme compatibility these should be in the form '10','20','30','40','50','60', etc. with '50' representing the 'Medium' size step. If all slugs begin with a number they will be merged with default and user slugs and sorted numerically.",
+ "type": "string"
+ },
+ "size": {
+ "description": "CSS space-size value, including units.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "spacingScale": {
+ "description": "Settings to auto-generate space size presets for the space size selector.\nGenerates a custom property (--wp--preset--spacing--{slug}`) per preset value.",
+ "type": "object",
+ "properties": {
+ "operator": {
+ "description": "With + or * depending on whether scale is generated by increment or multiplier.",
+ "type": "string",
+ "enum": ["+", "*"],
+ "default": "*"
+ },
+ "increment": {
+ "description": "The amount to increment each step by.",
+ "type": "number",
+ "exclusiveMinimum": 0,
+ "default": 1.5
+ },
+ "steps": {
+ "description": "Number of steps to generate in scale.",
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 10,
+ "default": 7
+ },
+ "mediumStep": {
+ "description": "The value to medium setting in the scale.",
+ "type": "number",
+ "exclusiveMinimum": 0,
+ "default": 1.5
+ },
+ "unit": {
+ "description": "Unit that the scale uses, eg. rem, em, px.",
+ "type": "string",
+ "enum": [
+ "px",
+ "em",
+ "rem",
+ "%",
+ "vw",
+ "svw",
+ "lvw",
+ "dvw",
+ "vh",
+ "svh",
+ "lvh",
+ "dvh",
+ "vi",
+ "svi",
+ "lvi",
+ "dvi",
+ "vb",
+ "svb",
+ "lvb",
+ "dvb",
+ "vmin",
+ "svmin",
+ "lvmin",
+ "dvmin",
+ "vmax",
+ "svmax",
+ "lvmax",
+ "dvmax"
+ ],
+ "default": "rem"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsTypographyProperties": {
+ "type": "object",
+ "properties": {
+ "typography": {
+ "description": "Settings related to typography.",
+ "type": "object",
+ "properties": {
+ "defaultFontSizes": {
+ "description": "Allow users to choose font sizes from the default font size presets.",
+ "type": "boolean",
+ "default": true
+ },
+ "customFontSize": {
+ "description": "Allow users to set custom font sizes.",
+ "type": "boolean",
+ "default": true
+ },
+ "fontStyle": {
+ "description": "Allow users to set custom font styles.",
+ "type": "boolean",
+ "default": true
+ },
+ "fontWeight": {
+ "description": "Allow users to set custom font weights.",
+ "type": "boolean",
+ "default": true
+ },
+ "fluid": {
+ "description": "Enables fluid typography and allows users to set global fluid typography parameters.",
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "minFontSize": {
+ "description": "Allow users to set a global minimum font size boundary in px, rem or em. Custom font sizes below this value will not be clamped, and all calculated minimum font sizes will be, at a minimum, this value.",
+ "type": "string"
+ },
+ "maxViewportWidth": {
+ "description": "Allow users to set custom a max viewport width in px, rem or em, used to set the maximum size boundary of a fluid font size.",
+ "type": "string"
+ },
+ "minViewportWidth": {
+ "description": "Allow users to set a custom min viewport width in px, rem or em, used to set the minimum size boundary of a fluid font size.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ },
+ {
+ "type": "boolean"
+ }
+ ],
+ "default": false
+ },
+ "letterSpacing": {
+ "description": "Allow users to set custom letter spacing.",
+ "type": "boolean",
+ "default": true
+ },
+ "lineHeight": {
+ "description": "Allow users to set custom line height.",
+ "type": "boolean",
+ "default": false
+ },
+ "textAlign": {
+ "description": "Allow users to set the text align.",
+ "type": "boolean",
+ "default": true
+ },
+ "textColumns": {
+ "description": "Allow users to set the number of text columns.",
+ "type": "boolean",
+ "default": false
+ },
+ "textDecoration": {
+ "description": "Allow users to set custom text decorations.",
+ "type": "boolean",
+ "default": true
+ },
+ "writingMode": {
+ "description": "Allow users to set the writing mode.",
+ "type": "boolean",
+ "default": false
+ },
+ "textTransform": {
+ "description": "Allow users to set custom text transforms.",
+ "type": "boolean",
+ "default": true
+ },
+ "dropCap": {
+ "description": "Enable drop cap.",
+ "type": "boolean",
+ "default": true
+ },
+ "fontSizes": {
+ "description": "Font size presets for the font size selector.\nGenerates a single class (`.has-{slug}-color`) and custom property (`--wp--preset--font-size--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the font size preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the font size preset.",
+ "type": "string"
+ },
+ "size": {
+ "description": "CSS font-size value, including units.",
+ "type": "string"
+ },
+ "fluid": {
+ "description": "Specifies the minimum and maximum font size value of a fluid font size. Set to `false` to bypass fluid calculations and use the static `size` value.",
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "min": {
+ "description": "A min font size for fluid font size calculations in px, rem or em.",
+ "type": "string"
+ },
+ "max": {
+ "description": "A max font size for fluid font size calculations in px, rem or em.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ },
+ {
+ "type": "boolean"
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "fontFamilies": {
+ "description": "Font family presets for the font family selector.\nGenerates a single custom property (`--wp--preset--font-family--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "description": "Font family preset",
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the font family preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the font family preset.",
+ "type": "string"
+ },
+ "fontFamily": {
+ "description": "CSS font-family value.",
+ "type": "string"
+ },
+ "fontFace": {
+ "description": "Array of font-face declarations.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "fontFamily": {
+ "description": "CSS font-family value.",
+ "type": "string",
+ "default": ""
+ },
+ "fontStyle": {
+ "description": "CSS font-style value.",
+ "type": "string",
+ "default": "normal"
+ },
+ "fontWeight": {
+ "description": "List of available font weights, separated by a space.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "integer"
+ }
+ ],
+ "default": "400"
+ },
+ "fontDisplay": {
+ "description": "CSS font-display value.",
+ "type": "string",
+ "enum": ["auto", "block", "fallback", "swap", "optional"],
+ "default": "fallback"
+ },
+ "src": {
+ "description": "Paths or URLs to the font files.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ],
+ "default": []
+ },
+ "fontStretch": {
+ "description": "CSS font-stretch value.",
+ "type": "string"
+ },
+ "ascentOverride": {
+ "description": "CSS ascent-override value.",
+ "type": "string"
+ },
+ "descentOverride": {
+ "description": "CSS descent-override value.",
+ "type": "string"
+ },
+ "fontVariant": {
+ "description": "CSS font-variant value.",
+ "type": "string"
+ },
+ "fontFeatureSettings": {
+ "description": "CSS font-feature-settings value.",
+ "type": "string"
+ },
+ "fontVariationSettings": {
+ "description": "CSS font-variation-settings value.",
+ "type": "string"
+ },
+ "lineGapOverride": {
+ "description": "CSS line-gap-override value.",
+ "type": "string"
+ },
+ "sizeAdjust": {
+ "description": "CSS size-adjust value.",
+ "type": "string"
+ },
+ "unicodeRange": {
+ "description": "CSS unicode-range value.",
+ "type": "string"
+ }
+ },
+ "required": ["fontFamily", "src"],
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsCustomProperties": {
+ "type": "object",
+ "properties": {
+ "custom": {
+ "$ref": "#/definitions/settingsCustomAdditionalProperties"
+ }
+ }
+ },
+ "settingsProperties": {
+ "allOf": [
+ { "$ref": "#/definitions/settingsAppearanceToolsProperties" },
+ { "$ref": "#/definitions/settingsBackgroundProperties" },
+ { "$ref": "#/definitions/settingsBorderProperties" },
+ { "$ref": "#/definitions/settingsColorProperties" },
+ { "$ref": "#/definitions/settingsDimensionsProperties" },
+ { "$ref": "#/definitions/settingsLayoutProperties" },
+ { "$ref": "#/definitions/settingsLightboxProperties" },
+ { "$ref": "#/definitions/settingsPositionProperties" },
+ { "$ref": "#/definitions/settingsShadowProperties" },
+ { "$ref": "#/definitions/settingsSpacingProperties" },
+ { "$ref": "#/definitions/settingsTypographyProperties" },
+ { "$ref": "#/definitions/settingsCustomProperties" }
+ ]
+ },
+ "settingsPropertyNames": {
+ "enum": [
+ "appearanceTools",
+ "background",
+ "border",
+ "color",
+ "dimensions",
+ "layout",
+ "lightbox",
+ "position",
+ "shadow",
+ "spacing",
+ "typography",
+ "custom"
+ ]
+ },
+ "settingsPropertiesComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/settingsProperties"
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/settingsPropertyNames"
+ }
+ }
+ ]
+ },
+ "settingsBlocksPropertiesComplete": {
+ "description": "Settings defined on a per-block basis.",
+ "type": "object",
+ "properties": {
+ "core/archives": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/audio": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/avatar": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/block": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/button": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/buttons": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/calendar": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/categories": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/code": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/column": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/columns": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-author-avatar": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-author-name": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-content": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-date": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-edit-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-reply-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-pagination": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-pagination-next": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-pagination-numbers": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-pagination-previous": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-title": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-template": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/cover": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/details": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/embed": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/file": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/footnotes": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/freeform": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/gallery": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/group": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/heading": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/home-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/html": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/image": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/latest-comments": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/latest-posts": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/list": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/list-item": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/loginout": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/media-text": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/missing": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/more": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/navigation": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/navigation-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/navigation-submenu": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/nextpage": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/page-list": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/page-list-item": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/paragraph": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-author": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-author-biography": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-author-name": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-comment": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-comments-count": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-comments-form": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-comments-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-content": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-date": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-excerpt": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-featured-image": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-navigation-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-template": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-terms": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-title": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/preformatted": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/pullquote": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-no-results": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-pagination": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-pagination-next": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-pagination-numbers": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-pagination-previous": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-title": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-total": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/quote": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/read-more": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/rss": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/search": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/separator": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/shortcode": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/site-logo": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/site-tagline": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/site-title": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/social-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/social-links": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/spacer": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/table": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/tag-cloud": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/template-part": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/term-description": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/text-columns": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/verse": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/video": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/widget-area": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/legacy-widget": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/widget-group": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ }
+ },
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ },
+ "settingsCustomAdditionalProperties": {
+ "description": "Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name.",
+ "type": "object",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ },
+ {
+ "$ref": "#/definitions/settingsCustomAdditionalProperties"
+ }
+ ]
+ }
+ },
+ "stylesProperties": {
+ "type": "object",
+ "properties": {
+ "background": {
+ "description": "Background styles.",
+ "type": "object",
+ "properties": {
+ "backgroundImage": {
+ "description": "Sets the `background-image` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ { "$ref": "#/definitions/refComplete" },
+ {
+ "type": "object",
+ "properties": {
+ "url": {
+ "description": "A URL to an image file, or a path to a file relative to the theme root directory, and prefixed with `file:`, e.g., 'file:./path/to/file.png'.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
+ },
+ "backgroundPosition": {
+ "description": "Sets the `background-position` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "backgroundRepeat": {
+ "description": "Sets the `background-repeat` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "backgroundSize": {
+ "description": "Sets the `background-size` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "backgroundAttachment": {
+ "description": "Sets the `background-attachment` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "border": {
+ "description": "Border styles.",
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "radius": {
+ "description": "Sets the `border-radius` CSS property.",
+ "anyOf": [
+ { "type": "string" },
+ { "$ref": "#/definitions/refComplete" },
+ {
+ "type": "object",
+ "properties": {
+ "topLeft": {
+ "description": "Sets the `border-top-left-radius` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ },
+ "topRight": {
+ "description": "Sets the `border-top-right-radius` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ },
+ "bottomLeft": {
+ "description": "Sets the `border-bottom-left-radius` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ },
+ "bottomRight": {
+ "description": "Sets the `border-bottom-right-radius` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ "style": {
+ "description": "Sets the `border-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "top": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-top-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `border-top-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-top-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "right": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-right-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `border-right-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-right-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "bottom": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-bottom-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `border-bottom-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-bottom-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "left": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-left-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `border-left-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-left-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ },
+ "color": {
+ "description": "Color styles.",
+ "type": "object",
+ "properties": {
+ "background": {
+ "description": "Sets the `background-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "gradient": {
+ "description": "Sets the `background` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "text": {
+ "description": "Sets the `color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "css": {
+ "description": "Sets custom CSS to apply styling not covered by other theme.json properties.",
+ "type": "string"
+ },
+ "dimensions": {
+ "description": "Dimensions styles.",
+ "type": "object",
+ "properties": {
+ "aspectRatio": {
+ "description": "Sets the `aspect-ratio` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "minHeight": {
+ "description": "Sets the `min-height` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ }
+ },
+ "filter": {
+ "description": "CSS and SVG filter styles.",
+ "type": "object",
+ "properties": {
+ "duotone": {
+ "description": "Sets the duotone filter.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "outline": {
+ "description": "Outline styles.",
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `outline-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "offset": {
+ "description": "Sets the `outline-offset` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `outline-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `outline-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "shadow": {
+ "description": "Box shadow styles.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "spacing": {
+ "description": "Spacing styles.",
+ "type": "object",
+ "properties": {
+ "blockGap": {
+ "description": "Sets the `--wp--style--block-gap` CSS custom property when settings.spacing.blockGap is true.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "margin": {
+ "description": "Margin styles.",
+ "type": "object",
+ "properties": {
+ "top": {
+ "description": "Sets the `margin-top` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "right": {
+ "description": "Sets the `margin-right` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "bottom": {
+ "description": "Sets the `margin-bottom` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "left": {
+ "description": "Sets the `margin-left` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "padding": {
+ "description": "Padding styles.",
+ "type": "object",
+ "properties": {
+ "top": {
+ "description": "Sets the `padding-top` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "right": {
+ "description": "Sets the `padding-right` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "bottom": {
+ "description": "Sets the `padding-bottom` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "left": {
+ "description": "Sets the `padding-left` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ },
+ "typography": {
+ "description": "Typography styles.",
+ "type": "object",
+ "properties": {
+ "fontFamily": {
+ "description": "Sets the `font-family` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "fontSize": {
+ "description": "Sets the `font-size` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "fontStyle": {
+ "description": "Sets the `font-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "fontWeight": {
+ "description": "Sets the `font-weight` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "letterSpacing": {
+ "description": "Sets the `letter-spacing` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "lineHeight": {
+ "description": "Sets the `line-height` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "textAlign": {
+ "description": "Sets the `text-align` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "textColumns": {
+ "description": "Sets the `column-count` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "textDecoration": {
+ "description": "Sets the `text-decoration` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "writingMode": {
+ "description": "Sets the `writing-mode` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "textTransform": {
+ "description": "Sets the `text-transform` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "stylesPropertyNames": {
+ "enum": [
+ "background",
+ "border",
+ "color",
+ "css",
+ "dimensions",
+ "filter",
+ "outline",
+ "shadow",
+ "spacing",
+ "typography"
+ ]
+ },
+ "stylesPropertiesComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/stylesPropertyNames"
+ }
+ }
+ ]
+ },
+ "stylesElementsPseudoSelectorsProperties": {
+ "type": "object",
+ "properties": {
+ ":active": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":any-link": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":focus": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":focus-visible": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":hover": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":link": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":visited": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ }
+ }
+ },
+ "stylesElementsPseudoSelectorsPropertyNames": {
+ "enum": [":active", ":any-link", ":focus", ":focus-visible", ":hover", ":link", ":visited"]
+ },
+ "stylesElementsPropertiesComplete": {
+ "description": "Styles defined on a per-element basis using the element's selector.",
+ "type": "object",
+ "properties": {
+ "button": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties"
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "link": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties"
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "heading": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h1": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h2": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h3": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h4": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h5": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h6": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "caption": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "cite": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ },
+ "stylesBlocksPropertiesComplete": {
+ "description": "Styles defined on a per-block basis using the block's selector.",
+ "type": "object",
+ "properties": {
+ "core/archives": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/audio": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/avatar": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/block": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/button": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/buttons": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/calendar": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/categories": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/code": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/column": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/columns": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-author-avatar": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-author-name": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-content": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-date": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-edit-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-reply-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-pagination": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-pagination-next": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-pagination-numbers": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-pagination-previous": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-title": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-template": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/cover": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/details": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/embed": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/file": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/footnotes": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/freeform": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/gallery": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/group": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/heading": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/home-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/html": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/image": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/latest-comments": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/latest-posts": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/list": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/list-item": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/loginout": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/media-text": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/missing": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/more": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/navigation": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/navigation-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/navigation-submenu": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/nextpage": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/page-list": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/page-list-item": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/paragraph": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-author": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-author-biography": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-author-name": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-comment": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-comments-count": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-comments-form": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-comments-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-content": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-date": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-excerpt": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-featured-image": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-navigation-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-template": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-terms": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-title": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/preformatted": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/pullquote": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-no-results": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-pagination": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-pagination-next": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-pagination-numbers": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-pagination-previous": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-title": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-total": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/quote": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/read-more": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/rss": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/search": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/separator": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/shortcode": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/site-logo": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/site-tagline": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/site-title": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/social-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/social-links": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/spacer": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/table": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/tag-cloud": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/template-part": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/term-description": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/text-columns": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/verse": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/video": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/widget-area": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/legacy-widget": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/widget-group": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ }
+ },
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ }
+ },
+ "additionalProperties": false
+ },
+ "stylesPropertiesAndElementsComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "variations": {
+ "$ref": "#/definitions/stylesVariationsPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements", "variations"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "stylesVariationsProperties": {
+ "type": "object",
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesVariationProperties"
+ }
+ }
+ },
+ "stylesVariationProperties": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "blocks": {
+ "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements", "blocks"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "stylesVariationsPropertiesComplete": {
+ "type": "object",
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesVariationPropertiesComplete"
+ }
+ }
+ },
+ "stylesVariationPropertiesComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "blocks": {
+ "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements", "blocks"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "stylesVariationBlocksPropertiesComplete": {
+ "type": "object",
+ "properties": {
+ "core/archives": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/audio": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/avatar": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/block": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/button": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/buttons": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/calendar": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/categories": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/code": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/column": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/columns": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-author-avatar": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-author-name": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-content": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-date": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-edit-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-reply-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination-next": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination-numbers": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination-previous": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-template": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/cover": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/details": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/embed": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/file": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/footnotes": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/freeform": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/gallery": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/group": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/heading": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/home-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/html": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/image": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/latest-comments": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/latest-posts": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/list": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/list-item": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/loginout": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/media-text": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/missing": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/more": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/navigation": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/navigation-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/navigation-submenu": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/nextpage": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/page-list": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/page-list-item": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/paragraph": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-author": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-author-biography": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-author-name": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comment": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comments-count": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comments-form": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comments-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-content": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-date": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-excerpt": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-featured-image": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-navigation-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-template": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-terms": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/preformatted": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/pullquote": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-no-results": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination-next": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination-numbers": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination-previous": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-total": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/quote": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/read-more": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/rss": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/search": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/separator": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/shortcode": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/site-logo": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/site-tagline": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/site-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/social-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/social-links": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/spacer": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/table": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/tag-cloud": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/template-part": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/term-description": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/text-columns": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/verse": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/video": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/widget-area": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/legacy-widget": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/widget-group": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ }
+ },
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ },
+ "stylesVariationBlockPropertiesComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements"]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "properties": {
+ "$schema": {
+ "description": "JSON schema URI for theme.json.",
+ "type": "string"
+ },
+ "version": {
+ "description": "Version of theme.json to use.",
+ "type": "integer",
+ "const": 3
+ },
+ "title": {
+ "description": "Title of the styles variation. If not defined, the file name will be used.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Slug of the styles variation. If not defined, the kebab-case title will be used.",
+ "type": "string"
+ },
+ "description": {
+ "description": "Description of the styles variation.",
+ "type": "string"
+ },
+ "blockTypes": {
+ "description": "List of block types that can use the block style variation this theme.json file represents.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "settings": {
+ "description": "Settings for the block editor and individual blocks. These include things like:\n- Which customization options should be available to the user. \n- The default colors, font sizes... available to the user. \n- CSS custom properties and class names used in styles.\n- And the default layout of the editor (widths and available alignments).",
+ "allOf": [
+ {
+ "$ref": "#/definitions/settingsProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "useRootPaddingAwareAlignments": {
+ "description": "Enables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block.\n\nPlease note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately.",
+ "type": "boolean",
+ "default": false
+ },
+ "blocks": {
+ "$ref": "#/definitions/settingsBlocksPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/settingsPropertyNames"
+ },
+ {
+ "enum": ["useRootPaddingAwareAlignments", "blocks"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "styles": {
+ "description": "Organized way to set CSS properties. Styles in the top-level will be added in the `body` selector.",
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "blocks": {
+ "$ref": "#/definitions/stylesBlocksPropertiesComplete"
+ },
+ "variations": {
+ "$ref": "#/definitions/stylesVariationsProperties"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements", "blocks", "variations"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "customTemplates": {
+ "description": "Additional metadata for custom templates defined in the templates folder.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Filename, without extension, of the template in the templates folder.",
+ "type": "string"
+ },
+ "title": {
+ "description": "Title of the template, translatable.",
+ "type": "string"
+ },
+ "postTypes": {
+ "description": "List of post types that can use this custom template.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["page"]
+ }
+ },
+ "required": ["name", "title"],
+ "additionalProperties": false
+ }
+ },
+ "templateParts": {
+ "description": "Additional metadata for template parts defined in the parts folder.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Filename, without extension, of the template in the parts folder.",
+ "type": "string"
+ },
+ "title": {
+ "description": "Title of the template, translatable.",
+ "type": "string"
+ },
+ "area": {
+ "description": "The area the template part is used for. Block variations for `header` and `footer` values exist and will be used when the area is set to one of those.",
+ "type": "string",
+ "default": "uncategorized"
+ }
+ },
+ "required": ["name"],
+ "additionalProperties": false
+ }
+ },
+ "patterns": {
+ "description": "An array of pattern slugs to be registered from the Pattern Directory.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": ["version"],
+ "additionalProperties": false
+}
diff --git a/docs/gutenberg/schemas/json/wp-env.json b/docs/gutenberg/schemas/json/wp-env.json
new file mode 100644
index 0000000..b8f3c36
--- /dev/null
+++ b/docs/gutenberg/schemas/json/wp-env.json
@@ -0,0 +1,158 @@
+{
+ "title": "JSON schema for WordPress wp-env configuration files",
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "definitions": {
+ "//": {
+ "reference": "https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/"
+ },
+ "wpEnvProperties": {
+ "type": "object",
+ "properties": {
+ "core": {
+ "description": "The WordPress installation to use. If null is specified, wp-env will use the latest production release of WordPress.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null
+ },
+ "phpVersion": {
+ "description": "The PHP version to use. If null is specified, wp-env will use the default version used with production release of WordPress.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null
+ },
+ "plugins": {
+ "description": "A list of plugins to install and activate in the environment.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "themes": {
+ "description": "A list of themes to install in the environment.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "port": {
+ "description": "The primary port number to use for the installation. You'll access the instance through the port: http://localhost:8888",
+ "type": "integer",
+ "default": 8888
+ },
+ "config": {
+ "description": "Mapping of wp-config.php constants to their desired values.",
+ "type": "object",
+ "default": {}
+ },
+ "mappings": {
+ "description": "Mapping of WordPress directories to local directories to be mounted in the WordPress instance.",
+ "type": "object",
+ "default": {}
+ },
+ "phpmyadminPort": {
+ "description": "The port number to access phpMyAdmin.",
+ "type": "integer"
+ },
+ "multisite": {
+ "description": "Whether to set up a multisite installation.",
+ "type": "boolean"
+ }
+ }
+ },
+ "wpEnvPropertyNames": {
+ "enum": [
+ "core",
+ "phpVersion",
+ "plugins",
+ "themes",
+ "port",
+ "config",
+ "mappings",
+ "phpmyadminPort",
+ "multisite"
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "$ref": "#/definitions/wpEnvProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "$schema": {
+ "type": "string"
+ },
+ "env": {
+ "description": "The key env is available to override any of the above options on an individual-environment basis.",
+ "type": "object",
+ "patternProperties": {
+ "[a-zA-Z]": {
+ "allOf": [
+ { "$ref": "#/definitions/wpEnvProperties" },
+ {
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/wpEnvPropertyNames"
+ }
+ }
+ ]
+ }
+ },
+ "default": {}
+ },
+ "testsPort": {
+ "description": "The port number for the test site. You'll access the instance through the port: http://localhost:8889",
+ "type": "integer",
+ "default": 8889
+ },
+ "lifecycleScripts": {
+ "description": "Mapping of commands that should be executed at certain points in the lifecycle.",
+ "type": "object",
+ "default": {},
+ "properties": {
+ "afterStart": {
+ "description": "Runs after wp-env start has finished setting up the environment.",
+ "type": "string"
+ },
+ "afterClean": {
+ "description": "Runs after wp-env clean has finished cleaning the environment.",
+ "type": "string"
+ },
+ "afterDestroy": {
+ "description": "Runs after wp-env destroy has destroyed the environment.",
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/wpEnvPropertyNames"
+ },
+ {
+ "enum": ["$schema", "env", "testsPort", "lifecycleScripts"]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/block-themes/README.md b/docs/wordpress/block-themes/README.md
similarity index 98%
rename from block-themes/README.md
rename to docs/wordpress/block-themes/README.md
index 074893a..4b83e86 100644
--- a/block-themes/README.md
+++ b/docs/wordpress/block-themes/README.md
@@ -5,12 +5,14 @@ This folder contains comprehensive documentation for WordPress block themes, cov
## Files
### Core Theme Development
+
- **[Theme Structure](theme-structure-epi.md)** - Guidelines for organizing block theme files and structure
- **[Templates](templates.md)** - Working with block theme templates and template parts
- **[Patterns](patterns.md)** - Creating and managing block patterns for themes
- **[Global Styles](global-styles.md)** - Implementing theme.json and global styling systems
### Design Systems & Styling
+
- **[Fluid Typography](fluid-typography.md)** - Responsive typography using clamp() and custom properties
- **[Fluid Spacing](fluid-spacing.md)** - Implementing fluid spacing systems for responsive layouts
- **[Fluid Typography & Spacing Guidelines](FluidTypography-Fluid-Spacing-Guidelines.md)** - Comprehensive guide to fluid design principles
@@ -18,17 +20,20 @@ This folder contains comprehensive documentation for WordPress block themes, cov
- **[Typesets](typesets.md)** - Typography system configuration and best practices
### Color & Visual Design
+
- **[Colour Palettes](colour-palettes.md)** - Setting up theme color systems and palettes
- **[Style Variations](style-variations.md)** - Creating theme style variations
- **[Block Styles](block-styles.md)** - Custom block styling approaches
- **[Section Styles](section-styles.md)** - Styling theme sections and layouts
### Development Best Practices
+
- **[CSS Specificity](css-specificity.md)** - Managing CSS specificity in block themes
- **[Naming Conventions](naming-conventions.md)** - Consistent naming patterns for theme development
- **[Standardising Colours, Fonts & Spacing](standardising-colours-fonts-spacing.md)** - Creating consistent design tokens
### Additional Resources
+
- **[Best Practices (Fluid Spacing & Typography)](best-practices-fluid-spacing-and%20typography.md)** - Advanced fluid design techniques
- **[theme-68.json](theme-68.json)** - Example theme.json configuration file
@@ -37,4 +42,4 @@ This folder contains comprehensive documentation for WordPress block themes, cov
- **Fluid Design**: Modern responsive design using CSS clamp() and custom properties
- **Design Tokens**: Systematic approach to colors, typography, and spacing
- **Block-First**: Designing themes around the block editor experience
-- **Progressive Enhancement**: Building accessible, performant themes that work everywhere
\ No newline at end of file
+- **Progressive Enhancement**: Building accessible, performant themes that work everywhere
diff --git a/block-themes/templates.md b/docs/wordpress/block-themes/docs.template.md
similarity index 97%
rename from block-themes/templates.md
rename to docs/wordpress/block-themes/docs.template.md
index 759b4c4..ec42ffe 100644
--- a/block-themes/templates.md
+++ b/docs/wordpress/block-themes/docs.template.md
@@ -1,24 +1,23 @@
# Templates
+
A concise overview of what templates are in this context, why they exist, and how to use them effectively.
---
## Best practices
--
---
## When to use
--
---
## Limitations
--
---
## Reference Links
+
-
-
diff --git a/block-themes/patterns.md b/docs/wordpress/block-themes/patterns/patterns.md
similarity index 93%
rename from block-themes/patterns.md
rename to docs/wordpress/block-themes/patterns/patterns.md
index cb591ec..6837982 100644
--- a/block-themes/patterns.md
+++ b/docs/wordpress/block-themes/patterns/patterns.md
@@ -3,11 +3,11 @@
---
## Best practices
--
---
## When to use
+
- Use classic (unsynced) patterns for reusable arrangements you want to start-from, where later edits to one instance should not affect others.
- Use Synced Patterns when changes should propagate to every instance across the site.
- Prefer template parts for structural theme chrome (headers, footers, sidebars) that belong in templates and should be edited in one place.
@@ -16,18 +16,19 @@
---
## Limitations
+
- Classic (unsynced) patterns do not propagate changes: once inserted, they become normal blocks. Use Synced Patterns if propagation is required.
- Updating an existing pattern does not retroactively update previously inserted instances (unless they were inserted as Synced).
- Large/complex patterns can be harder to discover without good categories and naming; keep them focused.
- Refactoring a pattern later usually requires manual content migrations for already-inserted instances.
- Patterns are static: changes to source don't auto-update inserted content
- Not dynamic; once a pattern is inserted, edits in source don’t propagate.
--
---
## Reference Links
-- WordPress Theme Handbook: Block Patterns — https://developer.wordpress.org/themes/features/block-patterns/
+
+- WordPress Theme Handbook: Block Patterns —
- [register_block_pattern()](https://developer.wordpress.org/reference/functions/register_block_pattern/)
- [register_block_pattern_category()](https://developer.wordpress.org/reference/functions/register_block_pattern_category/)
- [User docs: Patterns and Synced Patterns](https://wordpress.org/documentation/article/patterns/)
diff --git a/block-themes/block-styles.md b/docs/wordpress/block-themes/theme.json/block-styles.md
similarity index 69%
rename from block-themes/block-styles.md
rename to docs/wordpress/block-themes/theme.json/block-styles.md
index 4f06291..1d0f02d 100644
--- a/block-themes/block-styles.md
+++ b/docs/wordpress/block-themes/theme.json/block-styles.md
@@ -1,55 +1,58 @@
# Block Styles
+
Explains section styles and block style variations for WordPress container blocks, including best practices, limitations, and key updates in WordPress 6.6+.
---
## Best practices
-- Use section styles via **block style variations** in `theme.json` (e.g. `/styles/block/section-*.json`) for grouped container looks.
+
+- Use section styles via **block style variations** in `theme.json` (e.g. `/styles/block/section-*.json`) for grouped container looks.
- Ideal for reusable “mini-themes” applied to `core/group`, `core/columns`, etc.
---
## When to use
--
---
## Limitations
+
- Requires WordPress 6.6+ and correct `theme.json` structure.
- Inner block styling is limited; reuse through `blocks.*` or `elements.*` only.
---
-## Gutenberg PR #57908 — *“Block Styles: Extend block style variations as mechanism for achieving section styling”* (Merged 29 May 2024)
+## Gutenberg PR #57908 — _“Block Styles: Extend block style variations as mechanism for achieving section styling”_ (Merged 29 May 2024)
**What it is:** The foundational PR that lands “section styles” by extending block style variations so they can style **containers and their inner elements/blocks**, and crucially **nest** reliably.
**Key points**
-* New `blockTypes` in JSON partials flags a variation as a **block style variation** (section style).
-* Variations can be defined **in `/styles`** partials, or via **`styles.blocks.variations`** in `theme.json`, or **programmatically** with `gutenberg_register_block_style`.
-* Introduces **per-instance class** + **per-application partial stylesheets** so **parent > child > grandchild** cascade orders correctly (solves nesting).
-* **Specificity lowered** as far as possible to make JSON win without heavy CSS.
-* Lists **testing instructions** and examples for partial files and programmatic registration. [GitHub](https://github.com/WordPress/gutenberg/pull/57908)
+- New `blockTypes` in JSON partials flags a variation as a **block style variation** (section style).
+- Variations can be defined **in `/styles`** partials, or via **`styles.blocks.variations`** in `theme.json`, or **programmatically** with `gutenberg_register_block_style`.
+- Introduces **per-instance class** + **per-application partial stylesheets** so **parent > child > grandchild** cascade orders correctly (solves nesting).
+- **Specificity lowered** as far as possible to make JSON win without heavy CSS.
+- Lists **testing instructions** and examples for partial files and programmatic registration. [GitHub](https://github.com/WordPress/gutenberg/pull/57908)
**Why it matters for us**
-* Confirms the **/styles** directory approach for our library, the **nesting guarantee**, and the **order of application** we rely on when composing sections.
+- Confirms the **/styles** directory approach for our library, the **nesting guarantee**, and the **order of application** we rely on when composing sections.
---
-## Block Editor Handbook — *Block Styles (reference guide)*
+## Block Editor Handbook — _Block Styles (reference guide)_
**What it is:** The API reference for block style variations (the underlying mechanism).
**Key points**
-* Explains **registering block styles**, how they appear in the UI, and the distinction between **block styles vs block variations** vs **style variations**.
-* Useful for cross-checking **naming, availability, and registration** behaviour that section styles build on. ([WordPress Developer Resources][4])
+- Explains **registering block styles**, how they appear in the UI, and the distinction between **block styles vs block variations** vs **style variations**.
+- Useful for cross-checking **naming, availability, and registration** behaviour that section styles build on. ([WordPress Developer Resources][4])
**Why it matters**
-* Ground truth for **registration semantics** and how the UI picks up styles. Good for Copilot answers around **“why doesn’t my style show?”**
+- Ground truth for **registration semantics** and how the UI picks up styles. Good for Copilot answers around **“why doesn’t my style show?”**
---
## Reference links
+
- [Rich Tabor: WordPress 6.6 Section Styles](https://rich.blog/wordpress-6-6/)
diff --git a/block-themes/colour-palettes.md b/docs/wordpress/block-themes/theme.json/colour-palettes.md
similarity index 95%
rename from block-themes/colour-palettes.md
rename to docs/wordpress/block-themes/theme.json/colour-palettes.md
index ebd9fc9..5255862 100644
--- a/block-themes/colour-palettes.md
+++ b/docs/wordpress/block-themes/theme.json/colour-palettes.md
@@ -1,26 +1,26 @@
# Colour Palettes
+
Covers how to define and standardize colour palettes in theme.json for consistent theme switching, including best practices and pitfalls.
---
## Best practices
-- Standardize slugs: `base`, `contrast`, `primary` to ensure consistent theme switching and user flow.
+
+- Standardize slugs: `base`, `contrast`, `primary` to ensure consistent theme switching and user flow.
- Define in `settings.color.palette` to auto-generate CSS variables and `.has-*` classes.
- Treat slug changes as breaking. Blocks and patterns use generated classes (e.g. `.has-primary-color`, `.has-contrast-background-color`) and variables (e.g. `var(--wp--preset--color--primary)`). Renaming slugs to literal colour names like `green` will break styling when switching themes.
--
---
## Limitations
+
- Breaking slug names (like `green`) may result in broken styling when switching themes.
---
-
## Reference Links
+
- [Rich Tabor: Standardizing theme.json colors](https://rich.blog/standardizing-theme-json-colors/)
- [WordPress Dev Docs: theme.json colours and palettes](https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/#colors)
-
-
---
diff --git a/docs/wordpress/block-themes/theme.json/fluid-best-practices.md b/docs/wordpress/block-themes/theme.json/fluid-best-practices.md
new file mode 100644
index 0000000..a056e0d
--- /dev/null
+++ b/docs/wordpress/block-themes/theme.json/fluid-best-practices.md
@@ -0,0 +1,46 @@
+# **Fluid Spacing Learnings**
+
+**Context Video** \- [WordPress Fluid Spacing - 18 August 2025](https://www.loom.com/share/f56e58ff587648df97f31247bf887744?sid=003d4168-98be-47e0-8e31-8aa9ffebda95)
+
+**Fluid spacin[https://www.loom.com/share/f56e58ff587648df97f31247bf887744?sid=003d4168-98be-47e0-8e31-8aa9ffebda95](https://www.loom.com/share/f56e58ff587648df97f31247bf887744?sid=003d4168-98be-47e0-8e31-8aa9ffebda95)g** uses `clamp(min, fluid, max)` so spacing (padding, margins, gaps) scales with the viewport width, but never goes smaller than `min` or larger than `max`.
+
+- **min**: the smallest allowed spacing (protects mobile).
+- **fluid**: a viewport-based value (typically `vw`) that grows/shrinks with screen width.
+- **max**: the largest allowed spacing (protects ultra-wide screens).
+
+### **What `vw` is (and why it’s important)**
+
+- `1vw` \= 1% of the **viewport width**.
+- As the viewport changes, the `vw` portion of `clamp()` scales smoothly—no media queries needed.
+- `min` and `max` act as guardrails: clamp picks the min on tiny screens, scales fluidly in the middle, and caps at the max on large screens.
+
+## **“Visual” table: when each part of `clamp()` applies**
+
+Using `clamp(10px, 2vw, 40px)`:
+
+| Viewport width | 2vw calculation | Result (chosen by `clamp`) | Why |
+| -------------------------- | --------------- | -------------------------- | -------------------------------- |
+| 320px (small mobile) | 6.4px | **10px** | 6.4px \< min → use **min** |
+| 375px (mobile) | 7.5px | **10px** | 7.5px \< min → use **min** |
+| 768px (tablet) | 15.36px | **15.36px** | within min–max → **fluid** value |
+| 1024px (tablet/SM desktop) | 20.48px | **20.48px** | within min–max → **fluid** value |
+| 1440px (desktop) | 28.8px | **28.8px** | within min–max → **fluid** value |
+| 1920px (large desktop) | 38.4px | **38.4px** | within min–max → **fluid** value |
+| 2400px (ultra-wide) | 48px | **40px** | 48px \> max → use **max** |
+
+**Key idea:** **`vw` is not tied to a specific “device.”** It continuously scales with viewport width. `min` and `max` determine _when_ scaling starts and stops.
+
+## **Understanding the impact VW has on a Mobile device.**
+
+## **480px Mobile (min/max fixed, vw adjusted)**
+
+### **Example: `clamp(10px, Xvw, 40px)`**
+
+| `vw` value | Calculation (Xvw @ 480px) | Result at 480px | Why |
+| ---------- | ------------------------- | --------------- | ------------------------------ |
+| **1vw** | 4.8px | **10px** | 4.8 \< min → clamp uses min |
+| **2vw** | 9.6px | **10px** | 9.6 \< min → clamp uses min |
+| **2.5vw** | 12px | **12px** | Now ≥ min → clamp uses fluid |
+| **3vw** | 14.4px | **14.4px** | Within min–max → fluid applies |
+| **5vw** | 24px | **24px** | Within min–max → fluid applies |
+| **10vw** | 48px | **40px** | Above max → clamp caps at max |
diff --git a/block-themes/FluidTypography-Fluid-Spacing-Guidelines.md b/docs/wordpress/block-themes/theme.json/fluid-guidelines.md
similarity index 87%
rename from block-themes/FluidTypography-Fluid-Spacing-Guidelines.md
rename to docs/wordpress/block-themes/theme.json/fluid-guidelines.md
index 3fb1743..66d7d93 100644
--- a/block-themes/FluidTypography-Fluid-Spacing-Guidelines.md
+++ b/docs/wordpress/block-themes/theme.json/fluid-guidelines.md
@@ -4,17 +4,17 @@
Modern web design is moving beyond rigid breakpoints toward **fluid, intrinsic design** that adapts continuously to screen size[developer.wordpress.org](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/#:~:text=Following%20an%20intrinsic%20design%20method,shown%20in%20the%20following%20snippet). Instead of defining fixed styles for specific devices, fluid design embraces the web’s **ever-changing canvas**, allowing elements to scale smoothly between a minimum and maximum value. **Fluid typography** refers to text that grows or shrinks in size responsively with the viewport (or container), while **fluid spacing** means margins, paddings, and gaps that adjust proportionally as screen real estate changes[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=We%20will%20soon%20update%20Frost,of%20fluid%20spacing%20in%20Frost)[cedar.rei.com](https://cedar.rei.com/guidelines/fluid#:~:text=Fluid%20,proportional%20spacing%20across%20different). This approach avoids abrupt “jumps” at breakpoints and ensures designs look harmonious on anything from a tiny phone to an ultra-wide monitor.
-In traditional responsive design, you might use media queries to set an `h1` font-size of 48px on small screens and 64px on larger screens with a hard cutoff[developer.wordpress.org](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/#:~:text=In%20responsive%20web%20design%20based,in%20the%20following%20CSS%20snippet)[developer.wordpress.org](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/#:~:text=font). Fluid design instead asks: why not let the browser interpolate smoothly *between* those sizes? By leveraging modern CSS functions like `min()`, `max()`, and `clamp()`, we can achieve **continuous scaling** that “**flows**” with the viewport[web.dev](https://web.dev/articles/min-max-clamp#:~:text=To%20enable%20fluid%20typography%2C%20Mike,allow%20scaling%20between%20those%20sizes)[web.dev](https://web.dev/articles/min-max-clamp#:~:text=ideal%20size%20%28such%20as%20,values%2C%20using%20very%20little%20code). For example, instead of two discrete sizes for headings, one line of CSS can fluidly cover the whole range:
+In traditional responsive design, you might use media queries to set an `h1` font-size of 48px on small screens and 64px on larger screens with a hard cutoff[developer.wordpress.org](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/#:~:text=In%20responsive%20web%20design%20based,in%20the%20following%20CSS%20snippet)[developer.wordpress.org](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/#:~:text=font). Fluid design instead asks: why not let the browser interpolate smoothly _between_ those sizes? By leveraging modern CSS functions like `min()`, `max()`, and `clamp()`, we can achieve **continuous scaling** that “**flows**” with the viewport[web.dev](https://web.dev/articles/min-max-clamp#:~:text=To%20enable%20fluid%20typography%2C%20Mike,allow%20scaling%20between%20those%20sizes)[web.dev](https://web.dev/articles/min-max-clamp#:~:text=ideal%20size%20%28such%20as%20,values%2C%20using%20very%20little%20code). For example, instead of two discrete sizes for headings, one line of CSS can fluidly cover the whole range:
`h1 {`
- `font-size: clamp(2.25rem, 6vw, 3rem);`
+ `font-size: clamp(2.25rem, 6vw, 3rem);`
`}`
-In this example, the `h1` will never go below **2.25rem** or above **3rem**, but in between it scales with the viewport width at an “ideal” rate of **6vw** (6% of the viewport)[developer.wordpress.org](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/#:~:text=Following%20an%20intrinsic%20design%20method,shown%20in%20the%20following%20snippet). Effectively, `clamp()` **“clamps” a value between a minimum and maximum** — here, the font size is *at least* 2.25rem, *at most* 3rem, using 6vw as the preferred scaling factor[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=The%20,and%20a%20maximum%20allowed%20value)[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=Note%20that%20using%20,the%20use%20of%20media%20queries). The result is text that gradually resizes on each step of screen growth, rather than jumping at predefined breakpoints. This intrinsic fluidity is closer to how the web naturally behaves (think of how containers stretch/shrink), and it can drastically reduce the need for numerous media queries.
+In this example, the `h1` will never go below **2.25rem** or above **3rem**, but in between it scales with the viewport width at an “ideal” rate of **6vw** (6% of the viewport)[developer.wordpress.org](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/#:~:text=Following%20an%20intrinsic%20design%20method,shown%20in%20the%20following%20snippet). Effectively, `clamp()` **“clamps” a value between a minimum and maximum** — here, the font size is _at least_ 2.25rem, _at most_ 3rem, using 6vw as the preferred scaling factor[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=The%20,and%20a%20maximum%20allowed%20value)[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=Note%20that%20using%20,the%20use%20of%20media%20queries). The result is text that gradually resizes on each step of screen growth, rather than jumping at predefined breakpoints. This intrinsic fluidity is closer to how the web naturally behaves (think of how containers stretch/shrink), and it can drastically reduce the need for numerous media queries.
Fluid spacing applies the same concept to whitespace. Padding, margins, and block gaps can be set with a responsive function so that, for instance, a “Large” padding might be 80px on desktop, 40px on a phone, and smoothly interpolate at sizes in between[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,medium)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,large). The goal is to maintain **visual balance**: if your typography enlarges on a big screen, the space around elements should also expand proportionally to avoid looking cramped or sparse.
-**Why use fluid scales?** They provide a more **consistent, harmonious design** across devices. Designers can define a cohesive **scale or rhythm** for type and spacing that the browser then honors at any width[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=Fluid%20typography%C2%A0describes%20how%20a%20site%E2%80%99s,values%20assigned%20to%20the%20style)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=page%20sizes%2C%20Utopia%20can%20unlock,elegant%20typography%20for%20all%20devices). This avoids the “bumpiness” where something might look right at 320px and 1440px but awkward in between. Instead, fluid design results in *“buttery-smooth interpolation”* with every value in tune[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=,scales%20for%20every%20screen%20size)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=By%20defining%20a%20suitable%20type,setting%20sizes%20for%20multiple%20breakpoints). It also **reduces CSS complexity** – one declaration can replace multiple media query rules, letting browsers do the calculation work[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=Note%20that%20using%20,the%20use%20of%20media%20queries). In summary, fluid typography and spacing help embrace the fact that the web is a flexible medium, yielding designs that are both adaptive and future-proof to new screen sizes.
+**Why use fluid scales?** They provide a more **consistent, harmonious design** across devices. Designers can define a cohesive **scale or rhythm** for type and spacing that the browser then honors at any width[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=Fluid%20typography%C2%A0describes%20how%20a%20site%E2%80%99s,values%20assigned%20to%20the%20style)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=page%20sizes%2C%20Utopia%20can%20unlock,elegant%20typography%20for%20all%20devices). This avoids the “bumpiness” where something might look right at 320px and 1440px but awkward in between. Instead, fluid design results in _“buttery-smooth interpolation”_ with every value in tune[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=,scales%20for%20every%20screen%20size)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=By%20defining%20a%20suitable%20type,setting%20sizes%20for%20multiple%20breakpoints). It also **reduces CSS complexity** – one declaration can replace multiple media query rules, letting browsers do the calculation work[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=Note%20that%20using%20,the%20use%20of%20media%20queries). In summary, fluid typography and spacing help embrace the fact that the web is a flexible medium, yielding designs that are both adaptive and future-proof to new screen sizes.
## **Fluid Typography: Scalable Text Across Viewports**
@@ -25,22 +25,22 @@ Fluid spacing applies the same concept to whitespace. Padding, margins, and bloc
For example:
`p {`
- `font-size: clamp(1.0rem, 5vw, 2.0rem);`
+ `font-size: clamp(1.0rem, 5vw, 2.0rem);`
`}`
-In this case, a paragraph’s text will never be smaller than `1.0rem` (which might be \~16px, ensuring legibility on a tiny screen) and never larger than `2.0rem` (to prevent it from becoming excessively large on huge displays). Between those extremes, the `5vw` term makes the font-size scale linearly with 5% of the viewport’s width[web.dev](https://web.dev/articles/min-max-clamp#:~:text=you%20can%20let%20the%20browser,values%2C%20using%20very%20little%20code). On a narrow screen, 5vw might be smaller than 1.0rem, so the browser **clamps up** to 1.0rem; on an enormous screen, 5vw might exceed 2.0rem, so it **clamps down** to 2.0rem. In the mid-range, the 5vw rule applies, creating a smooth gradient of sizes. In effect, `clamp()` gives us a **“minimum font-size, ideal responsive formula, maximum font-size”** all in one declaration[web.dev](https://web.dev/articles/min-max-clamp#:~:text=you%20can%20let%20the%20browser,values%2C%20using%20very%20little%20code). This has the *same effect* as writing multiple media queries to progressively scale text, but it’s much simpler and more maintainable[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=Note%20that%20using%20,the%20use%20of%20media%20queries).
+In this case, a paragraph’s text will never be smaller than `1.0rem` (which might be \~16px, ensuring legibility on a tiny screen) and never larger than `2.0rem` (to prevent it from becoming excessively large on huge displays). Between those extremes, the `5vw` term makes the font-size scale linearly with 5% of the viewport’s width[web.dev](https://web.dev/articles/min-max-clamp#:~:text=you%20can%20let%20the%20browser,values%2C%20using%20very%20little%20code). On a narrow screen, 5vw might be smaller than 1.0rem, so the browser **clamps up** to 1.0rem; on an enormous screen, 5vw might exceed 2.0rem, so it **clamps down** to 2.0rem. In the mid-range, the 5vw rule applies, creating a smooth gradient of sizes. In effect, `clamp()` gives us a **“minimum font-size, ideal responsive formula, maximum font-size”** all in one declaration[web.dev](https://web.dev/articles/min-max-clamp#:~:text=you%20can%20let%20the%20browser,values%2C%20using%20very%20little%20code). This has the _same effect_ as writing multiple media queries to progressively scale text, but it’s much simpler and more maintainable[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=Note%20that%20using%20,the%20use%20of%20media%20queries).
There are many strategies for choosing the `clamp()` values:
-* **Pick design breakpoints:** One common approach is to decide that at a certain small viewport width (e.g. 320px), you want a minimum font-size, and at a certain large width (e.g. 1200px), a maximum size. You can then derive the `vw` value that interpolates between them. For instance, if 1rem at 320px and 2rem at 1200px are your targets, the slope is `(2rem - 1rem) / (1200px - 320px)` per pixel of width. This can be translated into a `calc()` or incorporated into the `clamp`. Tools like the *Utopia fluid type scale calculator* can help with this math[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=,1.592%29%2C%20%7Bfluid.max), or you can use an online *CSS clamp calculator* to plug in your desired min/max viewport and font sizes and get a formula. In practice, many designers use a bit of trial and error or existing scale presets.
+- **Pick design breakpoints:** One common approach is to decide that at a certain small viewport width (e.g. 320px), you want a minimum font-size, and at a certain large width (e.g. 1200px), a maximum size. You can then derive the `vw` value that interpolates between them. For instance, if 1rem at 320px and 2rem at 1200px are your targets, the slope is `(2rem - 1rem) / (1200px - 320px)` per pixel of width. This can be translated into a `calc()` or incorporated into the `clamp`. Tools like the _Utopia fluid type scale calculator_ can help with this math[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=,1.592%29%2C%20%7Bfluid.max), or you can use an online _CSS clamp calculator_ to plug in your desired min/max viewport and font sizes and get a formula. In practice, many designers use a bit of trial and error or existing scale presets.
-* **Use simple ratios:** Another simpler tactic is to use a fixed `vw` percentage that “feels” right for your base font. For example, `clamp(1rem, 2.5vw, 3rem)` might work if you know you want roughly 16px at minimum and 48px at maximum. The `vw` alone might not hit exactly those values at specific breakpoints, but the `clamp` ensures it never goes out of bounds. This is an **easy and quick method** – the browser will naturally apply the scaling curve.
+- **Use simple ratios:** Another simpler tactic is to use a fixed `vw` percentage that “feels” right for your base font. For example, `clamp(1rem, 2.5vw, 3rem)` might work if you know you want roughly 16px at minimum and 48px at maximum. The `vw` alone might not hit exactly those values at specific breakpoints, but the `clamp` ensures it never goes out of bounds. This is an **easy and quick method** – the browser will naturally apply the scaling curve.
-* **Combine units for fine-tuning:** Advanced usage may combine a `vw` with another unit in the middle value to fine-tune behavior. For example: `font-size: clamp(1rem, 1rem + 2vw, 2rem);`. Here at the smallest sizes, the `1rem + 2vw` will equal something slightly above 1rem, giving a gentler scale at first; on larger screens it grows more. WordPress core’s algorithm for fluid font presets uses formulas like `clamp(MIN, Xrem + ((1vw - C) * SLOPE), MAX)` to ensure a smooth curve that hits specific points[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=body%20%7B%20,2.413%29%2C%2042px%29%3B). You might see such formulas in generated theme styles – they’re essentially a calculated `vw` approach with offsets.
+- **Combine units for fine-tuning:** Advanced usage may combine a `vw` with another unit in the middle value to fine-tune behavior. For example: `font-size: clamp(1rem, 1rem + 2vw, 2rem);`. Here at the smallest sizes, the `1rem + 2vw` will equal something slightly above 1rem, giving a gentler scale at first; on larger screens it grows more. WordPress core’s algorithm for fluid font presets uses formulas like `clamp(MIN, Xrem + ((1vw - C) * SLOPE), MAX)` to ensure a smooth curve that hits specific points[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=body%20%7B%20,2.413%29%2C%2042px%29%3B). You might see such formulas in generated theme styles – they’re essentially a calculated `vw` approach with offsets.
However, for most use cases, a straightforward `clamp(min, kvw, max)` is sufficient. The key is that your **min** is the smallest comfortable size for content and **max** is the largest desired size for large screens. The middle term determines how aggressively it scales between those extremes – larger `vw` values make text grow faster as the viewport widens, while smaller `vw` (or adding a fixed base like `1rem + Xvw`) makes the growth more subtle.
-**Fluid typography vs. responsive breakpoints:** With `clamp()`, the browser handles all intermediate sizes for you. This eliminates the need for many explicit breakpoints where font-sizes jump. It’s an **intrinsic responsiveness**: the design “**knows**” how to adjust itself. As one developer noted, clamp lets us *“set a font-size that grows with the viewport, but doesn’t go below a minimum or above a maximum… the same effect as code in CSS-Tricks’ ‘Fluid Typography’ article but in one line and without media queries”*[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=Note%20that%20using%20,the%20use%20of%20media%20queries). Of course, you can still combine fluid techniques with media queries if needed (for example, perhaps switching to an entirely different layout or type scale after a certain point), but fluid sizing covers the continuous changes.
+**Fluid typography vs. responsive breakpoints:** With `clamp()`, the browser handles all intermediate sizes for you. This eliminates the need for many explicit breakpoints where font-sizes jump. It’s an **intrinsic responsiveness**: the design “**knows**” how to adjust itself. As one developer noted, clamp lets us _“set a font-size that grows with the viewport, but doesn’t go below a minimum or above a maximum… the same effect as code in CSS-Tricks’ ‘Fluid Typography’ article but in one line and without media queries”_[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=Note%20that%20using%20,the%20use%20of%20media%20queries). Of course, you can still combine fluid techniques with media queries if needed (for example, perhaps switching to an entirely different layout or type scale after a certain point), but fluid sizing covers the continuous changes.
### **Implementing Fluid Typography in CSS**
@@ -56,121 +56,121 @@ To implement fluid typography in your project:
#### **A Note on Accessibility and `clamp()`**
-Be cautious that by *locking* a maximum font-size, you aren’t inadvertently preventing users from zooming or resizing text for accessibility. For example, if you set a max that’s only 1.5× the base size, a user on a large screen might not be able to zoom text to 200% for WCAG compliance[web.dev](https://web.dev/articles/min-max-clamp#:~:text=Warning%3A%20Limiting%20maximum%20font%20sizes,test%20the%20results%20with%20zoom). Browser zoom will scale the whole page (including your `rem` calculations), so generally zoom still works fine with fluid type. However, some users (or assistive technologies) might increase text size without zooming the layout – in such cases, a `max` could constrain it. A good practice is to choose generous maximums (so text can still enlarge significantly on big displays) and always test with zoom/text-resize tools. The Web Content Accessibility Guidelines require text to be zoomable up to 200%[web.dev](https://web.dev/articles/min-max-clamp#:~:text=Warning%3A%20Limiting%20maximum%20font%20sizes,test%20the%20results%20with%20zoom), so ensure that your combination of base size and `max` in clamp doesn’t stop that. Usually, if you stick to `rem` units for min/max, a user’s browser setting increase will simply raise those rem values proportionally, and `clamp` will accommodate that new starting point.
+Be cautious that by _locking_ a maximum font-size, you aren’t inadvertently preventing users from zooming or resizing text for accessibility. For example, if you set a max that’s only 1.5× the base size, a user on a large screen might not be able to zoom text to 200% for WCAG compliance[web.dev](https://web.dev/articles/min-max-clamp#:~:text=Warning%3A%20Limiting%20maximum%20font%20sizes,test%20the%20results%20with%20zoom). Browser zoom will scale the whole page (including your `rem` calculations), so generally zoom still works fine with fluid type. However, some users (or assistive technologies) might increase text size without zooming the layout – in such cases, a `max` could constrain it. A good practice is to choose generous maximums (so text can still enlarge significantly on big displays) and always test with zoom/text-resize tools. The Web Content Accessibility Guidelines require text to be zoomable up to 200%[web.dev](https://web.dev/articles/min-max-clamp#:~:text=Warning%3A%20Limiting%20maximum%20font%20sizes,test%20the%20results%20with%20zoom), so ensure that your combination of base size and `max` in clamp doesn’t stop that. Usually, if you stick to `rem` units for min/max, a user’s browser setting increase will simply raise those rem values proportionally, and `clamp` will accommodate that new starting point.
#### **Fluid Typography in CSS Frameworks and Tools**
Fluid typography isn’t limited to writing raw CSS by hand. Many modern CSS frameworks and methodologies incorporate it:
-* **Custom Properties:** Tools like *Utopia* encourage generating a *set of CSS custom properties* for a fluid type scale[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=To%20pull%20these%20design%20foundations,drop%20it%20into%20a%20project)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=h2%20%7B%20font). For example, you might end up with `--step--1`, `--step-0`, `--step-1`, etc., each being a clamp() for a particular scale step. Then in CSS you assign `font-size: var(--step-2)` to an element. This abstracts away the magic numbers and gives a common vocabulary (“Step 2” size, “Step 3” size, etc.)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=browser%20what%20we%20want%20to,out%20how%20to%20do%20that)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=This%20also%20creates%20a%20shared%2C,infiltrating%20our%20codebases%20and%20designs). It’s a great way to ensure consistency and make it easy to update the scale in one place.
+- **Custom Properties:** Tools like _Utopia_ encourage generating a _set of CSS custom properties_ for a fluid type scale[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=To%20pull%20these%20design%20foundations,drop%20it%20into%20a%20project)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=h2%20%7B%20font). For example, you might end up with `--step--1`, `--step-0`, `--step-1`, etc., each being a clamp() for a particular scale step. Then in CSS you assign `font-size: var(--step-2)` to an element. This abstracts away the magic numbers and gives a common vocabulary (“Step 2” size, “Step 3” size, etc.)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=browser%20what%20we%20want%20to,out%20how%20to%20do%20that)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=This%20also%20creates%20a%20shared%2C,infiltrating%20our%20codebases%20and%20designs). It’s a great way to ensure consistency and make it easy to update the scale in one place.
-* **Utility Classes:** Some design systems or utility-first frameworks provide classes for fluid text. For instance, a class like `.text-fluid-lg` might apply a clamp formula for a large heading. Tailwind CSS has plugins (e.g., `tailwindcss-fluid-type`) that allow you to configure fluid type in the design system. These can simplify applying fluid styles across your codebase.
+- **Utility Classes:** Some design systems or utility-first frameworks provide classes for fluid text. For instance, a class like `.text-fluid-lg` might apply a clamp formula for a large heading. Tailwind CSS has plugins (e.g., `tailwindcss-fluid-type`) that allow you to configure fluid type in the design system. These can simplify applying fluid styles across your codebase.
-* **Calculators:** As mentioned, there are online calculators (Utopia.fyi, TypeScale, CSS-Tricks clamp calculator, etc.) where you input your desired min/max conditions and they output ready-to-use CSS. These are handy for getting the math right. For example, **Utopia’s Fluid Type Scale** tool asks for a small-screen font size, a large-screen font size, and the min/max viewport widths to consider, then generates a series of fluid values that form a harmonious scale[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=By%20defining%20a%20suitable%20type,setting%20sizes%20for%20multiple%20breakpoints)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Developing%20With%20Fluid%20Typography). Using such tools can take a lot of guesswork out of the process and ensure your scaling is mathematically consistent.
+- **Calculators:** As mentioned, there are online calculators (Utopia.fyi, TypeScale, CSS-Tricks clamp calculator, etc.) where you input your desired min/max conditions and they output ready-to-use CSS. These are handy for getting the math right. For example, **Utopia’s Fluid Type Scale** tool asks for a small-screen font size, a large-screen font size, and the min/max viewport widths to consider, then generates a series of fluid values that form a harmonious scale[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=By%20defining%20a%20suitable%20type,setting%20sizes%20for%20multiple%20breakpoints)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Developing%20With%20Fluid%20Typography). Using such tools can take a lot of guesswork out of the process and ensure your scaling is mathematically consistent.
### **Enabling Fluid Typography in WordPress (Theme JSON)**
If you are working with WordPress block themes (which use **theme.json** for configuration), there are built-in features to help implement fluid typography without writing custom CSS for each element. WordPress introduced fluid typography support in version 6.1, allowing theme authors to opt-in and define fluid font sizes in theme.json[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=While%20a%20bit%20heavy,box)[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=First%20off%2C%20a%20theme%20needs,like%20so). Here’s how it works:
-* **Global toggle:** In your theme.json, set `"settings.typography.fluid": true` to turn on fluid typography globally[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=First%20off%2C%20a%20theme%20needs,like%20so). By default, WordPress has this off (meaning font presets are static), so you need to explicitly enable it. Once enabled, WordPress will output CSS that uses `clamp()` for the font sizes you define, according to rules we’ll discuss below.
+- **Global toggle:** In your theme.json, set `"settings.typography.fluid": true` to turn on fluid typography globally[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=First%20off%2C%20a%20theme%20needs,like%20so). By default, WordPress has this off (meaning font presets are static), so you need to explicitly enable it. Once enabled, WordPress will output CSS that uses `clamp()` for the font sizes you define, according to rules we’ll discuss below.
**Defining font size presets:** Under `settings.typography.fontSizes`, you list your theme’s font size options (each with a name, slug, and size value). Normally, the `size` is a static value (e.g. "36px" or "2.25rem"). With fluid typography on, you can also provide a `fluid` object with `min` and `max` for each size[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,be%20a%20valid%20CSS%20size)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,md). For example:
+`{`
+ `"settings": {`
+ `"typography": {`
+ `"fluid": true,`
+ `"fontSizes": [`
`{`
- `"settings": {`
- `"typography": {`
- `"fluid": true,`
- `"fontSizes": [`
- `{`
- `"name": "Small",`
- `"slug": "small",`
- `"size": "1rem",`
- `"fluid": false`
- `},`
- `{`
- `"name": "Medium",`
- `"slug": "medium",`
- `"size": "1.25rem",`
- `"fluid": { "min": "1rem", "max": "1.5rem" }`
- `},`
- `{`
- `"name": "Large",`
- `"slug": "large",`
- `"size": "1.5rem",`
- `"fluid": { "min": "1.25rem", "max": "2rem" }`
- `}`
- `]`
- `}`
- `}`
+ `"name": "Small",`
+ `"slug": "small",`
+ `"size": "1rem",`
+ `"fluid": false`
+ `},`
+ `{`
+ `"name": "Medium",`
+ `"slug": "medium",`
+ `"size": "1.25rem",`
+ `"fluid": { "min": "1rem", "max": "1.5rem" }`
+ `},`
+ `{`
+ `"name": "Large",`
+ `"slug": "large",`
+ `"size": "1.5rem",`
+ `"fluid": { "min": "1.25rem", "max": "2rem" }`
+ `}`
+ `]`
+ `}`
+ `}`
`}`
In this example, we globally enable fluid type, then define three presets. “Small” is explicitly set to not fluid (perhaps we want that one constant at 1rem). “Medium” will fluidly scale between 1rem and 1.5rem, and “Large” between 1.25rem and 2rem[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,%7D%20%7D%2C)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,%7D%20%7D%20%5D). When WordPress sees this, it generates the corresponding CSS custom properties as clamps. For instance, the above might produce:
- `body {`
- `--wp--preset--font-size--sm: 1rem;`
- `--wp--preset--font-size--md: clamp(1rem, 1rem + ((1vw - 0.2rem) * 1.136), 1.5rem);`
- `--wp--preset--font-size--lg: clamp(1.25rem, 1.25rem + ((1vw - 0.2rem) * 1.705), 2rem);`
+`body {`
+ `--wp--preset--font-size--sm: 1rem;`
+ `--wp--preset--font-size--md: clamp(1rem, 1rem + ((1vw - 0.2rem) * 1.136), 1.5rem);`
+ `--wp--preset--font-size--lg: clamp(1.25rem, 1.25rem + ((1vw - 0.2rem) * 1.705), 2rem);`
`}`
-* [developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=WordPress%20will%20generate%20these%20CSS,custom%20properties)This looks a bit complex – WordPress is using a specific formula internally to calculate the middle value for clamp. You don’t necessarily need to understand or manually compute that formula; you just provide min and max. The result is that any block using the “Medium” font size will automatically get that fluid clamp value applied.
+- [developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=WordPress%20will%20generate%20these%20CSS,custom%20properties)This looks a bit complex – WordPress is using a specific formula internally to calculate the middle value for clamp. You don’t necessarily need to understand or manually compute that formula; you just provide min and max. The result is that any block using the “Medium” font size will automatically get that fluid clamp value applied.
-**Default behavior without per-size overrides:** If you set `fluid: true` globally but *don’t* specify a custom `fluid` object for each size, WordPress will still try to make your font sizes fluid. It uses an algorithm to derive min/max for each preset based on the base size. For example, the default core theme.json has presets Small=13px, Medium=20px, Large=36px, etc., and if fluid is on, WP will output something like:
+**Default behavior without per-size overrides:** If you set `fluid: true` globally but _don’t_ specify a custom `fluid` object for each size, WordPress will still try to make your font sizes fluid. It uses an algorithm to derive min/max for each preset based on the base size. For example, the default core theme.json has presets Small=13px, Medium=20px, Large=36px, etc., and if fluid is on, WP will output something like:
- `--wp--preset--font-size--medium: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.852), 20px);`
+`--wp--preset--font-size--medium: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.852), 20px);`
`--wp--preset--font-size--large: clamp(22.041px, 1.378rem + ((1vw - 3.2px) * 1.983), 36px);`
-* [developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=body%20%7B%20,2.413%29%2C%2042px%29%3B)Here WP decided on a 14px minimum for Medium (it uses 14px as a default floor for any fluid text unless told otherwise)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). The “Small” size in this case was 13px which is below that floor, so WordPress simply left Small as a static 13px[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). This reveals an important detail: **WordPress will not fluid-scale very small text by default** (to ensure readability, anything under \~14px stays fixed). Theme authors can override that by explicitly setting fluid min values, but it’s a safe default.
+- [developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=body%20%7B%20,2.413%29%2C%2042px%29%3B)Here WP decided on a 14px minimum for Medium (it uses 14px as a default floor for any fluid text unless told otherwise)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). The “Small” size in this case was 13px which is below that floor, so WordPress simply left Small as a static 13px[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). This reveals an important detail: **WordPress will not fluid-scale very small text by default** (to ensure readability, anything under \~14px stays fixed). Theme authors can override that by explicitly setting fluid min values, but it’s a safe default.
-* **Units and limitations:** Currently WordPress requires that your `size`, `fluid.min`, and `fluid.max` values be specified in **px, em, or rem** units[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=It%E2%80%99s%20worth%20noting%20that%20only%C2%A0,end%20and%20block%20editor). These are the units it knows how to handle for the calculations. You should prefer `rem` (or `em`) for those values in theme.json, as that ensures the resulting CSS is rooted in the user’s browser settings (e.g., if a user has a base font of 18px, your 1rem will be 18px for them)[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=It%E2%80%99s%20worth%20noting%20that%20only%C2%A0,end%20and%20block%20editor). Note that if you previously used a custom `clamp()` *directly* as a static size in theme.json (a trick some themes did before WP 6.1), you might need to adjust your approach to use the official fluid support. There was an early limitation that you couldn’t mix pre-clamped sizes with the new fluid system[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=In%20order%20to%20opt%20into,as%20a%20fallback) – essentially, theme.json wants a normal number for `size` if you’re enabling fluid on it. The good news is the WP fluid system covers what those manual clamps did, so you can migrate to the core feature.
+- **Units and limitations:** Currently WordPress requires that your `size`, `fluid.min`, and `fluid.max` values be specified in **px, em, or rem** units[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=It%E2%80%99s%20worth%20noting%20that%20only%C2%A0,end%20and%20block%20editor). These are the units it knows how to handle for the calculations. You should prefer `rem` (or `em`) for those values in theme.json, as that ensures the resulting CSS is rooted in the user’s browser settings (e.g., if a user has a base font of 18px, your 1rem will be 18px for them)[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=It%E2%80%99s%20worth%20noting%20that%20only%C2%A0,end%20and%20block%20editor). Note that if you previously used a custom `clamp()` _directly_ as a static size in theme.json (a trick some themes did before WP 6.1), you might need to adjust your approach to use the official fluid support. There was an early limitation that you couldn’t mix pre-clamped sizes with the new fluid system[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=In%20order%20to%20opt%20into,as%20a%20fallback) – essentially, theme.json wants a normal number for `size` if you’re enabling fluid on it. The good news is the WP fluid system covers what those manual clamps did, so you can migrate to the core feature.
-* **Using fluid fonts in blocks:** Once defined, your fluid font presets appear in the editor UI just like normal sizes. For example, the dropdown for paragraph font size will still show “Small, Medium, Large” – the difference is that choosing one will output a class (e.g. `.has-medium-font-size`) which references the `clamp()` variable instead of a fixed value. From an editor or end-user perspective, **“it just works”**, which is exactly the point – fluid typography benefits the end user’s reading experience without adding complexity for the content creator[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=As%20one%20of%20the%20bigger,I%20think%20it%20works%20great)[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=building%20with%20WordPress%20%E2%80%94%C2%A0and%20those,I%20think%20it%20works%20great).
+- **Using fluid fonts in blocks:** Once defined, your fluid font presets appear in the editor UI just like normal sizes. For example, the dropdown for paragraph font size will still show “Small, Medium, Large” – the difference is that choosing one will output a class (e.g. `.has-medium-font-size`) which references the `clamp()` variable instead of a fixed value. From an editor or end-user perspective, **“it just works”**, which is exactly the point – fluid typography benefits the end user’s reading experience without adding complexity for the content creator[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=As%20one%20of%20the%20bigger,I%20think%20it%20works%20great)[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=building%20with%20WordPress%20%E2%80%94%C2%A0and%20those,I%20think%20it%20works%20great).
**Practical tips for fluid type in WordPress:**
-* *Opt-in thoughtfully:* It’s almost always beneficial to enable fluid typography (`"fluid": true`) in block themes[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,large)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). The web is so diverse in device sizes that fixed text can feel too small on a phone or too large on a 4K screen. WordPress makes it easy to opt-in globally and refine as needed.
+- _Opt-in thoughtfully:_ It’s almost always beneficial to enable fluid typography (`"fluid": true`) in block themes[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,large)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). The web is so diverse in device sizes that fixed text can feel too small on a phone or too large on a 4K screen. WordPress makes it easy to opt-in globally and refine as needed.
-* *Override specific cases:* You might have certain text elements that should not scale fluidly – for instance, maybe a logo or menu item that should remain a consistent size. You can handle that by setting `"fluid": false` on that specific size preset (as we did for “Small” in the example)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,md), or by not using a preset and instead using a custom size for those elements. By default, if fluid is on globally, all presets above the min threshold will be fluid. So explicitly turn it off per size if needed.
+- _Override specific cases:_ You might have certain text elements that should not scale fluidly – for instance, maybe a logo or menu item that should remain a consistent size. You can handle that by setting `"fluid": false` on that specific size preset (as we did for “Small” in the example)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,md), or by not using a preset and instead using a custom size for those elements. By default, if fluid is on globally, all presets above the min threshold will be fluid. So explicitly turn it off per size if needed.
-* *Test “extremes”:* Check what your fluid text looks like on the narrowest mobile in portrait and on an ultra-wide monitor. Are headings still fitting nicely? Is any text too small to read on a tiny screen? WordPress’s default min of 14px is a good guideline – going much below that for body text can hurt readability. If you find your chosen min is too low, bump it up and regenerate. On large screens, consider usability – enormous text can be hard to scan; sometimes a slightly smaller max and a comfortable line length (max-width on content containers) yields better reading experience.
+- _Test “extremes”:_ Check what your fluid text looks like on the narrowest mobile in portrait and on an ultra-wide monitor. Are headings still fitting nicely? Is any text too small to read on a tiny screen? WordPress’s default min of 14px is a good guideline – going much below that for body text can hurt readability. If you find your chosen min is too low, bump it up and regenerate. On large screens, consider usability – enormous text can be hard to scan; sometimes a slightly smaller max and a comfortable line length (max-width on content containers) yields better reading experience.
-* *Remember line-height:* When font-size scales, you may also want to use fluid line-heights or at least generous line-heights that accommodate the largest size. WordPress’s global styles don’t yet fluid-scale line-height automatically. You can use unitless line-heights (e.g. 1.4) which naturally multiply with font-size. If you want to truly adjust line-height for different viewports, you’d need custom CSS or use container queries (beyond current core features). In most cases, a consistent line-height or a slight CSS adjustment at a certain breakpoint is fine.
+- _Remember line-height:_ When font-size scales, you may also want to use fluid line-heights or at least generous line-heights that accommodate the largest size. WordPress’s global styles don’t yet fluid-scale line-height automatically. You can use unitless line-heights (e.g. 1.4) which naturally multiply with font-size. If you want to truly adjust line-height for different viewports, you’d need custom CSS or use container queries (beyond current core features). In most cases, a consistent line-height or a slight CSS adjustment at a certain breakpoint is fine.
### **Best Practices for Fluid Typography**
Crafting fluid typography requires balancing flexibility with control. Here are some best practices to keep in mind:
-* **Use Rem Units for Base Sizes:** Define your font sizes in `rem` (or `em`) rather than `px` wherever possible[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=It%E2%80%99s%20worth%20noting%20that%20only%C2%A0,end%20and%20block%20editor). This ties your typography to the root font size, meaning if a user changes their browser’s default font setting or zoom level, your type will respect that. It also means your entire type scale can proportionally grow if the root size changes (which can be a deliberate technique for responsive design). Pixels are an absolute unit and don’t scale with user preferences – using rem makes your design more accessible.
+- **Use Rem Units for Base Sizes:** Define your font sizes in `rem` (or `em`) rather than `px` wherever possible[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=It%E2%80%99s%20worth%20noting%20that%20only%C2%A0,end%20and%20block%20editor). This ties your typography to the root font size, meaning if a user changes their browser’s default font setting or zoom level, your type will respect that. It also means your entire type scale can proportionally grow if the root size changes (which can be a deliberate technique for responsive design). Pixels are an absolute unit and don’t scale with user preferences – using rem makes your design more accessible.
-* **Set Reasonable Minimums:** Always choose a **minimum size that maintains readability**. For body text, this might be around 0.875rem–1rem (14px–16px) as an absolute floor. For smaller UI text (like captions), you might go a bit lower, but be cautious. Test on a small device held at arm’s length – can you read it comfortably? The beauty of fluid fonts is you can allow text to shrink on small screens to save space, but don’t overdo it. Remember that many mobile browsers will boost tiny fonts automatically (Chrome on Android, for instance, has text autosizing for very small text), which could interfere with your styling if your min is too low.
+- **Set Reasonable Minimums:** Always choose a **minimum size that maintains readability**. For body text, this might be around 0.875rem–1rem (14px–16px) as an absolute floor. For smaller UI text (like captions), you might go a bit lower, but be cautious. Test on a small device held at arm’s length – can you read it comfortably? The beauty of fluid fonts is you can allow text to shrink on small screens to save space, but don’t overdo it. Remember that many mobile browsers will boost tiny fonts automatically (Chrome on Android, for instance, has text autosizing for very small text), which could interfere with your styling if your min is too low.
-* **Set a Comfortable Maximum:** Conversely, pick a max that fits your design’s needs but avoids absurd scaling. Huge headings might look great in a hero section on desktop, but for paragraph text, you might not want it much larger than, say, 1.125× or 1.25× your base size even on wide screens. Too-large text can hurt readability (very long line length if not contained, or excessive scrolling). Common max for body text might be \~18px or 20px (if base 16px). For display text, max can be larger but consider the context (a marketing landing page hero can afford 80px text on desktop; a blog post title probably doesn’t need to be that large even on big monitors). It’s about *design intent* – fluid type gives flexibility, but you still impose design constraints via the max.
+- **Set a Comfortable Maximum:** Conversely, pick a max that fits your design’s needs but avoids absurd scaling. Huge headings might look great in a hero section on desktop, but for paragraph text, you might not want it much larger than, say, 1.125× or 1.25× your base size even on wide screens. Too-large text can hurt readability (very long line length if not contained, or excessive scrolling). Common max for body text might be \~18px or 20px (if base 16px). For display text, max can be larger but consider the context (a marketing landing page hero can afford 80px text on desktop; a blog post title probably doesn’t need to be that large even on big monitors). It’s about _design intent_ – fluid type gives flexibility, but you still impose design constraints via the max.
-* **Maintain Hierarchy:** Ensure that your small, medium, large text scales in harmony. Ideally, the **relative differences** (small vs medium vs large) remain somewhat consistent across sizes. If you define each size’s clamp independently, check for any crossover. For example, it would be bad if at some screen width your “Medium” text becomes larger than “Large” text. This can happen if the curves aren’t coordinated. To avoid it, you can derive all your sizes from a single scale or ratio. Many design systems choose a **modular scale** (like each step is 1.2× larger than the previous) and then apply fluid scaling to that. If using the WordPress theme.json method, the core algorithm usually prevents overlaps by basing min/max on the static size ordering, but custom values could potentially overlap if not chosen carefully. One trick is to use tools like Utopia which generate a **consistent fluid type scale** – all sizes are calculated from two endpoint scales, so they will preserve order at every viewport[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=By%20defining%20a%20suitable%20type,setting%20sizes%20for%20multiple%20breakpoints)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=This%20also%20creates%20a%20shared%2C,infiltrating%20our%20codebases%20and%20designs).
+- **Maintain Hierarchy:** Ensure that your small, medium, large text scales in harmony. Ideally, the **relative differences** (small vs medium vs large) remain somewhat consistent across sizes. If you define each size’s clamp independently, check for any crossover. For example, it would be bad if at some screen width your “Medium” text becomes larger than “Large” text. This can happen if the curves aren’t coordinated. To avoid it, you can derive all your sizes from a single scale or ratio. Many design systems choose a **modular scale** (like each step is 1.2× larger than the previous) and then apply fluid scaling to that. If using the WordPress theme.json method, the core algorithm usually prevents overlaps by basing min/max on the static size ordering, but custom values could potentially overlap if not chosen carefully. One trick is to use tools like Utopia which generate a **consistent fluid type scale** – all sizes are calculated from two endpoint scales, so they will preserve order at every viewport[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=By%20defining%20a%20suitable%20type,setting%20sizes%20for%20multiple%20breakpoints)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=This%20also%20creates%20a%20shared%2C,infiltrating%20our%20codebases%20and%20designs).
-* **Consider Container-Based Scaling:** The current fluid approach in CSS (and WordPress core) typically uses the **viewport** as the reference for scaling (via `vw`). But with the emergence of *container queries* and related units (`cqw`, `cqh` for container width/height), you can also consider fluid typography *within containers*. For instance, a sidebar widget could scale text based on its container width (which might be more relevant than the overall viewport). This is an advanced technique and not as widely supported or needed for most text. However, the principle is the same – `clamp(min, Xcqw, max)` could tie font-size to a container query if you have a component that resizes within different layouts. Keep an eye on CSS container query support if your designs require that level of responsiveness. In WordPress theme.json, fluid typography is currently only viewport-based[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=allows%20your%20font%20sizes%20to,with%20the%20viewport%20or%20container), but you could always add custom CSS for container-specific fluid rules if necessary.
+- **Consider Container-Based Scaling:** The current fluid approach in CSS (and WordPress core) typically uses the **viewport** as the reference for scaling (via `vw`). But with the emergence of _container queries_ and related units (`cqw`, `cqh` for container width/height), you can also consider fluid typography _within containers_. For instance, a sidebar widget could scale text based on its container width (which might be more relevant than the overall viewport). This is an advanced technique and not as widely supported or needed for most text. However, the principle is the same – `clamp(min, Xcqw, max)` could tie font-size to a container query if you have a component that resizes within different layouts. Keep an eye on CSS container query support if your designs require that level of responsiveness. In WordPress theme.json, fluid typography is currently only viewport-based[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=allows%20your%20font%20sizes%20to,with%20the%20viewport%20or%20container), but you could always add custom CSS for container-specific fluid rules if necessary.
-* **Link Scale to Line-Height and Spacing:** As your font-size changes, so does the space it occupies. You might want to **adjust spacing in tandem** (we’ll cover fluid spacing next). At minimum, ensure your line-heights are flexible enough. Using relative line-heights (unitless) means they automatically scale with font-size. If you set a fixed line-height in px, a fluid font could outgrow that and start overlapping. So prefer something like `line-height: 1.4;` (which is 140% of the font size, whatever that may be at a given viewport). For display text that only has one line, this is less of an issue; but for multi-line text it’s important.
+- **Link Scale to Line-Height and Spacing:** As your font-size changes, so does the space it occupies. You might want to **adjust spacing in tandem** (we’ll cover fluid spacing next). At minimum, ensure your line-heights are flexible enough. Using relative line-heights (unitless) means they automatically scale with font-size. If you set a fixed line-height in px, a fluid font could outgrow that and start overlapping. So prefer something like `line-height: 1.4;` (which is 140% of the font size, whatever that may be at a given viewport). For display text that only has one line, this is less of an issue; but for multi-line text it’s important.
-* **Test with Real Content:** Finally, always test fluid typography with actual content and on real devices if possible. Sometimes theoretical sizes behave differently when you see a full page of text. Pay attention to points where the design might still benefit from a layout change. For instance, you may realize that at extremely large screens, even though the text got bigger, the line length is too long – maybe you’d introduce a max-width or an extra column at that point. Fluid type solves *scaling* of text, but not all layout concerns. Use it in combination with other responsive techniques for best results.
+- **Test with Real Content:** Finally, always test fluid typography with actual content and on real devices if possible. Sometimes theoretical sizes behave differently when you see a full page of text. Pay attention to points where the design might still benefit from a layout change. For instance, you may realize that at extremely large screens, even though the text got bigger, the line length is too long – maybe you’d introduce a max-width or an extra column at that point. Fluid type solves _scaling_ of text, but not all layout concerns. Use it in combination with other responsive techniques for best results.
### **Troubleshooting Fluid Typography**
Even with a solid setup, you might encounter some issues when implementing fluid typography. Here are common problems and how to address them:
-* **Text Not Scaling at All:** If your font remains the same size across viewports, double-check that the CSS is applied correctly. In pure CSS, ensure you didn’t accidentally put `clamp()` in quotes or something that invalidates it. In WordPress theme.json, make sure `"fluid": true` is enabled and you’re either using core-supported units or providing min/max correctly[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=First%20off%2C%20a%20theme%20needs,like%20so)[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=%7B%20,%7D%2C). Also, verify that you’re viewing in an environment where the global styles CSS is output (in the site front-end or the editor). If using a custom framework, ensure no other CSS overrides the font-size (WordPress adds classes like `.has-x-large-font-size { font-size: var(--wp--preset--font-size--x-large) !important; }`[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=WordPress%20also%20generates%20custom%20CSS,default%20sizes%20produce%20these%20classes)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=.has), so in dev tools you should see the resolved `clamp()` value).
+- **Text Not Scaling at All:** If your font remains the same size across viewports, double-check that the CSS is applied correctly. In pure CSS, ensure you didn’t accidentally put `clamp()` in quotes or something that invalidates it. In WordPress theme.json, make sure `"fluid": true` is enabled and you’re either using core-supported units or providing min/max correctly[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=First%20off%2C%20a%20theme%20needs,like%20so)[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=%7B%20,%7D%2C). Also, verify that you’re viewing in an environment where the global styles CSS is output (in the site front-end or the editor). If using a custom framework, ensure no other CSS overrides the font-size (WordPress adds classes like `.has-x-large-font-size { font-size: var(--wp--preset--font-size--x-large) !important; }`[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=WordPress%20also%20generates%20custom%20CSS,default%20sizes%20produce%20these%20classes)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=.has), so in dev tools you should see the resolved `clamp()` value).
-* **Fluid Font Only Partially Working:** If you notice the font does change size but seems to hit a limit too early or not reach the expected size, your `vw` term might be off. For example, if the text stops growing well before the largest viewport, maybe the `vw` percentage was too small to ever reach the max. Conversely, if it hits max too quickly, the `vw` might be too large. Tweak the middle value. If using theme.json, you have less direct control over the formula WP uses unless you supply your own min/max. So consider adding a `fluid` object with custom min/max in theme.json if the automatic calculation isn’t to your liking.
+- **Fluid Font Only Partially Working:** If you notice the font does change size but seems to hit a limit too early or not reach the expected size, your `vw` term might be off. For example, if the text stops growing well before the largest viewport, maybe the `vw` percentage was too small to ever reach the max. Conversely, if it hits max too quickly, the `vw` might be too large. Tweak the middle value. If using theme.json, you have less direct control over the formula WP uses unless you supply your own min/max. So consider adding a `fluid` object with custom min/max in theme.json if the automatic calculation isn’t to your liking.
-* **Font Size Jumps or Order Inversion:** A tricky situation is if one fluid size catches up to another. Say your H2 and H3 are defined very close in size; it’s possible at a certain viewport H2’s clamp is at its low end while H3 is at its high end, momentarily making H3 appear as large as (or larger than) H2. Ideally, this shouldn’t happen if the scale differences are significant and the formulas are derived from one system. But if you do observe it, you might need to adjust the scale. Increase the contrast between sizes (so their min/max ranges don’t overlap) or use a more consistent formula for all sizes. WordPress’s built-in fluid scaling tries to maintain the preset ordering[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,13px), but custom values could lead to odd overlaps. Always verify headings maintain hierarchy across breakpoints.
+- **Font Size Jumps or Order Inversion:** A tricky situation is if one fluid size catches up to another. Say your H2 and H3 are defined very close in size; it’s possible at a certain viewport H2’s clamp is at its low end while H3 is at its high end, momentarily making H3 appear as large as (or larger than) H2. Ideally, this shouldn’t happen if the scale differences are significant and the formulas are derived from one system. But if you do observe it, you might need to adjust the scale. Increase the contrast between sizes (so their min/max ranges don’t overlap) or use a more consistent formula for all sizes. WordPress’s built-in fluid scaling tries to maintain the preset ordering[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,13px), but custom values could lead to odd overlaps. Always verify headings maintain hierarchy across breakpoints.
-* **Minimum Size Too Small to Read:** If on a very narrow screen the text becomes uncomfortably small, then your chosen `min` is likely too low. As a quick fix, bump up the `min` value in the clamp. Remember that if your design absolutely needs that small size to fit, maybe the layout or content needs rethinking (e.g., don’t try to cram a long word in a small heading – even fluid type can’t fix breaking words). As noted, WordPress by default won’t dip fonts below 14px when auto-calculating[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). Use that as a sanity check.
+- **Minimum Size Too Small to Read:** If on a very narrow screen the text becomes uncomfortably small, then your chosen `min` is likely too low. As a quick fix, bump up the `min` value in the clamp. Remember that if your design absolutely needs that small size to fit, maybe the layout or content needs rethinking (e.g., don’t try to cram a long word in a small heading – even fluid type can’t fix breaking words). As noted, WordPress by default won’t dip fonts below 14px when auto-calculating[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). Use that as a sanity check.
-* **Maximum Size Looks Odd on Huge Screens:** If someone connects an 8K display and your H1 becomes absurdly large, you might get complaints. The `max` value in clamp is your safety net. If you set it to a reasonable number, the font will stop scaling beyond that point. But what is “reasonable”? It depends on context – for body text, perhaps \~1.125rem to 1.25rem (18–20px) is plenty; for big headings you might allow 5rem (80px) or more. A useful technique is to also limit the **width of content containers** on very large screens (e.g., center text content in a max-width wrapper) so that your line lengths don’t get too long even if text is big. This way, even if someone has a wall-sized monitor, your content isn’t stretching edge to edge with gigantic text. In summary: use `max` in clamp to control extremes, and consider overall layout constraints for ultra-wide viewports.
+- **Maximum Size Looks Odd on Huge Screens:** If someone connects an 8K display and your H1 becomes absurdly large, you might get complaints. The `max` value in clamp is your safety net. If you set it to a reasonable number, the font will stop scaling beyond that point. But what is “reasonable”? It depends on context – for body text, perhaps \~1.125rem to 1.25rem (18–20px) is plenty; for big headings you might allow 5rem (80px) or more. A useful technique is to also limit the **width of content containers** on very large screens (e.g., center text content in a max-width wrapper) so that your line lengths don’t get too long even if text is big. This way, even if someone has a wall-sized monitor, your content isn’t stretching edge to edge with gigantic text. In summary: use `max` in clamp to control extremes, and consider overall layout constraints for ultra-wide viewports.
-* **Interaction with User Preferences:** If a user has “text scaling” enabled (like on some mobile browsers) or uses browser zoom, test that nothing breaks. Generally, fluid typography should play fine – zooming essentially multiplies everything, including your rem and vw. One potential gotcha: iOS Safari has a feature that will bump font-sizes up on small screens if it thinks they’re too small (to improve legibility). If you set a very low `min`, Safari might override it. There’s a CSS meta tag `viewport` setting (`maximum-scale` etc.) that can influence that, but you usually don’t want to disable it because it helps users. The best approach is simply to ensure your min is reasonable and trust the platform. If you see strange behavior on iPhones, consider slightly larger min font or test with `text-size-adjust` properties.
+- **Interaction with User Preferences:** If a user has “text scaling” enabled (like on some mobile browsers) or uses browser zoom, test that nothing breaks. Generally, fluid typography should play fine – zooming essentially multiplies everything, including your rem and vw. One potential gotcha: iOS Safari has a feature that will bump font-sizes up on small screens if it thinks they’re too small (to improve legibility). If you set a very low `min`, Safari might override it. There’s a CSS meta tag `viewport` setting (`maximum-scale` etc.) that can influence that, but you usually don’t want to disable it because it helps users. The best approach is simply to ensure your min is reasonable and trust the platform. If you see strange behavior on iPhones, consider slightly larger min font or test with `text-size-adjust` properties.
-* **Legacy Browser Support:** The `clamp()` function is widely supported in all modern browsers (Chrome/Edge 79+, Firefox 75+, Safari 13.1+)[web.dev](https://web.dev/articles/min-max-clamp#:~:text=)[web.dev](https://web.dev/articles/min-max-clamp#:~:text=Source), so you don’t need to worry about IE (which is obsolete). In the extremely rare case you need to support an older browser that lacks clamp(), you might use a CSS hack or feature query to fall back to a static size or a media-query-based approach. But for most projects in 2025, we can safely use clamp. If you suspect a user’s browser is not applying your fluid font, ensure it’s not an outdated UA.
+- **Legacy Browser Support:** The `clamp()` function is widely supported in all modern browsers (Chrome/Edge 79+, Firefox 75+, Safari 13.1+)[web.dev](https://web.dev/articles/min-max-clamp#:~:text=)[web.dev](https://web.dev/articles/min-max-clamp#:~:text=Source), so you don’t need to worry about IE (which is obsolete). In the extremely rare case you need to support an older browser that lacks clamp(), you might use a CSS hack or feature query to fall back to a static size or a media-query-based approach. But for most projects in 2025, we can safely use clamp. If you suspect a user’s browser is not applying your fluid font, ensure it’s not an outdated UA.
-* **Disabling Fluid Typography:** Occasionally, after trying it, a team might decide fluid fonts don’t suit a particular project’s look and feel. If using WordPress and you want to *remove* fluid behavior, simply set `"fluid": false` in theme.json (or omit it, since false is default)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,large)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). That will output static CSS values for presets. If you had manual clamps in custom CSS, you’d replace them with fixed values or media queries as needed. Some voices in the community requested an easy toggle because not all designs benefit from fluid type[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=August%201%2C%202024). Our recommendation is to usually keep it, but it’s good to know you can opt out or selectively apply it.
+- **Disabling Fluid Typography:** Occasionally, after trying it, a team might decide fluid fonts don’t suit a particular project’s look and feel. If using WordPress and you want to _remove_ fluid behavior, simply set `"fluid": false` in theme.json (or omit it, since false is default)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=,large)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=). That will output static CSS values for presets. If you had manual clamps in custom CSS, you’d replace them with fixed values or media queries as needed. Some voices in the community requested an easy toggle because not all designs benefit from fluid type[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=August%201%2C%202024). Our recommendation is to usually keep it, but it’s good to know you can opt out or selectively apply it.
By following these practices and troubleshooting tips, you can implement fluid typography that significantly improves adaptability without sacrificing design control. Next, we’ll apply similar concepts to spacing, ensuring the whitespace and layout gaps in your design scale as elegantly as your text does.
@@ -183,26 +183,26 @@ Just as typography can scale fluidly, so can the **spacing** in your design –
In CSS, you implement fluid spacing the same way as fluid type: using relative units and functions like `clamp()` or `min()`. For example, suppose you want a container to have padding that is at least 1rem (16px) and at most 5rem (80px), scaling with viewport width. You could write:
`.container {`
- `padding: clamp(1rem, 5vw, 5rem);`
+ `padding: clamp(1rem, 5vw, 5rem);`
`}`
This would give 16px padding on very small screens, and up to 80px on very large screens, with `5vw` (\~5% of viewport width) determining intermediate values. If the viewport is in between, say 1000px wide, 5vw \= 50px, so the padding might be around 50px – nicely in between 16 and 80\. Just like fluid type, **the smallest side wins** if the calculation would go below min (the clamp bumps it up) and **the largest side wins** if above max[web.dev](https://web.dev/articles/min-max-clamp#:~:text=you%20can%20let%20the%20browser,values%2C%20using%20very%20little%20code).
-One thing to note: spacing often needs to be consistent in multiples or steps. It’s common to define a **spacing scale** (small, medium, large, etc.) and apply those consistently to margins/padding across the site. With fluid spacing, each of those scale steps can itself be a clamp or relative formula. However, it’s important that they scale in a coordinated way; you wouldn’t want your “Medium” spacing to actually become *smaller* than “Small” spacing at some viewport width due to different scaling rates. So a good strategy is to derive all fluid spacing values from a **common formula or ratio**.
+One thing to note: spacing often needs to be consistent in multiples or steps. It’s common to define a **spacing scale** (small, medium, large, etc.) and apply those consistently to margins/padding across the site. With fluid spacing, each of those scale steps can itself be a clamp or relative formula. However, it’s important that they scale in a coordinated way; you wouldn’t want your “Medium” spacing to actually become _smaller_ than “Small” spacing at some viewport width due to different scaling rates. So a good strategy is to derive all fluid spacing values from a **common formula or ratio**.
For instance, you might decide: at a base viewport (let’s say 360px wide), my spacing sizes will be 4px, 8px, 16px, 32px (a doubling scale for extra-small, small, medium, large). At a large viewport (let’s say 1200px), maybe those become 8px, 16px, 32px, 64px. Now you can create clamp formulas for each step that interpolate between those two sets. The simplest would be:
-* X-Small: `clamp(4px, something like 1vw, 8px)`
+- X-Small: `clamp(4px, something like 1vw, 8px)`
-* Small: `clamp(8px, something like 2vw, 16px)`
+- Small: `clamp(8px, something like 2vw, 16px)`
-* Medium: `clamp(16px, something like 4vw, 32px)`
+- Medium: `clamp(16px, something like 4vw, 32px)`
-* Large: `clamp(32px, something like 8vw, 64px)`
+- Large: `clamp(32px, something like 8vw, 64px)`
This example assumes a linear relationship (as screen gets bigger, spacing doubles proportionally). The `vw` values are chosen in relation to the size: larger spacing steps use a bigger percentage so they grow faster. In fact, one approach many systems use is scaling spacing relative to font-size or base dimensions. **Utopia.fyi’s fluid space calculator** takes the base typography scale “step 0” as the fundamental unit and then multiplies it for spacing tokens[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=intentional%2C%20fluid%20gaps%20to%20be,tool%20in%20the%20Utopia%20collection)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Taking%20%E2%80%9CStep%200%E2%80%9D%20from%20the,as%20our%20base%20unit%2C%20we) – this ensures that if your body text size increases, your spacing increases in lockstep, preserving design proportions.
-In plain terms, **fluid spacing ensures that whitespace doesn’t become either too cramped on small screens or too sprawling on large screens**. It preserves the *ratio* between text and its surrounding space. Think of a call-to-action button: on mobile, you might have 8px padding and on desktop 20px padding. With fluid spacing, that padding can start at 8px and smoothly ease up as the screen widens, making the button feel consistently proportioned. Without it, the button might either look oversized on mobile (if you used desktop padding everywhere) or tiny on desktop (if you used mobile padding everywhere). Media queries could switch at some point, but fluid approach spreads the change over many widths, often yielding a nicer result.
+In plain terms, **fluid spacing ensures that whitespace doesn’t become either too cramped on small screens or too sprawling on large screens**. It preserves the _ratio_ between text and its surrounding space. Think of a call-to-action button: on mobile, you might have 8px padding and on desktop 20px padding. With fluid spacing, that padding can start at 8px and smoothly ease up as the screen widens, making the button feel consistently proportioned. Without it, the button might either look oversized on mobile (if you used desktop padding everywhere) or tiny on desktop (if you used mobile padding everywhere). Media queries could switch at some point, but fluid approach spreads the change over many widths, often yielding a nicer result.
### **Implementing Fluid Spacing in CSS**
@@ -213,12 +213,11 @@ To implement fluid spacing, you can use similar steps to fluid type:
2. **Define Min and Max Values:** Decide on a minimum and maximum spacing for each context. For example, if a section has 100px top/bottom padding on desktop comp but obviously that won’t fit on mobile, maybe plan for 30px on mobile. These become your clamp bounds. Sometimes designers provide these; other times you infer them (e.g., “I want this gap to be about 2rem on small screens and about 8rem on big screens”).
3. **Use Relative Units for the Middle:** Choose a `vw` (or `vh` or `%`) value that represents how the spacing should scale. Often `vw` works well because horizontal viewport growth often correlates with overall size. If the spacing is vertical (like vertical rhythm), using `vw` is still fine (since typically if width is small, height is small too on devices, but you could use `vh` if you specifically want to scale by height). The percent `%` unit could be used for something like padding if you want it relative to container width. For simplicity, `vw` in clamp is most popular.
-
- * You can also combine units for nuance. For example `clamp(2rem, 2rem + 5vw, 10rem)` would start at 2rem and add some viewport-based growth on top. If you want a more subtle fluidity (i.e., mostly static plus a little stretch), this pattern works.
+ - You can also combine units for nuance. For example `clamp(2rem, 2rem + 5vw, 10rem)` would start at 2rem and add some viewport-based growth on top. If you want a more subtle fluidity (i.e., mostly static plus a little stretch), this pattern works.
4. **Apply to CSS or Variables:** Set the margin/padding CSS with the clamp. For example: `.section { padding-block: clamp(2rem, 5vw, 6rem); }` would give a top/bottom padding that grows from 2rem to 6rem. If you have multiple spacing sizes, you might create CSS custom properties like `--space-small: clamp(...); --space-medium: clamp(...);` and use those throughout your CSS (similar to how typographic custom props can be used). This way, if you adjust the formula later, it updates everywhere that space token is used.
-5. **Test across breakpoints:** As always, check different viewport sizes. Ensure that at narrow widths content isn’t squished due to still-too-large padding. Conversely, on wide screens, confirm that the space doesn’t become comically large or create too much empty area. A good fluid spacing will *feel* natural – you might not even notice the change as you resize, which is the goal: it’s proportional.
+5. **Test across breakpoints:** As always, check different viewport sizes. Ensure that at narrow widths content isn’t squished due to still-too-large padding. Conversely, on wide screens, confirm that the space doesn’t become comically large or create too much empty area. A good fluid spacing will _feel_ natural – you might not even notice the change as you resize, which is the goal: it’s proportional.
One thing to mention: sometimes designers prefer **fixed spacing on one axis and fluid on another**. For instance, vertical spacing might be fluid (since vertical space is often tied to reading comfort) but horizontal padding might just stick to a max container width. This is fine – you don’t have to fluid-scale every single value. Use fluid techniques where they add value. In practice, fluid spacing shines for **larger-scale spacing** (section paddings, large gaps) more than for tiny micro-spacing (like a 4px border might just stay 4px regardless).
@@ -230,88 +229,88 @@ WordPress’s theme.json allows defining **spacing presets** (for margins, paddi
Here’s how you can set it up:
-* **Spacing Presets in theme.json:** Under `settings.spacing`, you have two main ways to define a scale. One is `"spacingScale"` (which can auto-generate a series of sizes given a formula, like a multiplier or additive sequence). The other is `"spacingSizes"` – an array where you list each preset with a name, slug, and size[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=There%20are%20two%20methods%20for,registering%20your%20spacing%20presets)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=WordPress%20generates%20a%20default%20spacing,as%20shown%20in%20this%20table). The default WP theme.json comes with a preset scale (like “Small” \= 1rem, “Medium” \= 1.5rem, etc.)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=%60,Large). You will likely override these with your theme’s design tokens.
+- **Spacing Presets in theme.json:** Under `settings.spacing`, you have two main ways to define a scale. One is `"spacingScale"` (which can auto-generate a series of sizes given a formula, like a multiplier or additive sequence). The other is `"spacingSizes"` – an array where you list each preset with a name, slug, and size[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=There%20are%20two%20methods%20for,registering%20your%20spacing%20presets)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=WordPress%20generates%20a%20default%20spacing,as%20shown%20in%20this%20table). The default WP theme.json comes with a preset scale (like “Small” \= 1rem, “Medium” \= 1.5rem, etc.)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=%60,Large). You will likely override these with your theme’s design tokens.
**Using Fluid Values:** In the `spacingSizes` array, the `size` can be any valid CSS length – including a `clamp()` expression or even a custom property reference[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=,slug). That means you can directly put fluid formulas in there. For example:
- `{`
- `"settings": {`
- `"spacing": {`
- `"spacingSizes": [`
- `{ "name": "Small", "slug": "small", "size": "clamp(0.5rem, 2vw, 1rem)" },`
- `{ "name": "Medium", "slug": "medium", "size": "clamp(1rem, 4vw, 2rem)" },`
- `{ "name": "Large", "slug": "large", "size": "clamp(2rem, 8vw, 4rem)" }`
- `]`
- `}`
- `}`
+`{`
+ `"settings": {`
+ `"spacing": {`
+ `"spacingSizes": [`
+ `{ "name": "Small", "slug": "small", "size": "clamp(0.5rem, 2vw, 1rem)" },`
+ `{ "name": "Medium", "slug": "medium", "size": "clamp(1rem, 4vw, 2rem)" },`
+ `{ "name": "Large", "slug": "large", "size": "clamp(2rem, 8vw, 4rem)" }`
+ `]`
+ `}`
+ `}`
`}`
This would create three spacing presets (small, medium, large) that are fluid. WordPress will output CSS custom properties for these, like:
- `--wp--preset--spacing--small: clamp(0.5rem, 2vw, 1rem);`
+`--wp--preset--spacing--small: clamp(0.5rem, 2vw, 1rem);`
`--wp--preset--spacing--medium: clamp(1rem, 4vw, 2rem);`
`--wp--preset--spacing--large: clamp(2rem, 8vw, 4rem);`
-* And it will generate classes or use them in styles where applicable (for instance, if a block supports a “spacing preset” control, selecting “Medium” might apply a class that uses the var). Essentially, it treats the whole clamp as a string value for the CSS variable[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=By%20defining%20these%20spacing%20presets,in%20which%20they%20are%20applied)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=Fluid%20spacing%20utilizes%20the%20clamp,Small%2C%20Medium%2C%20Large%2C%20and%20xLarge).
+- And it will generate classes or use them in styles where applicable (for instance, if a block supports a “spacing preset” control, selecting “Medium” might apply a class that uses the var). Essentially, it treats the whole clamp as a string value for the CSS variable[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=By%20defining%20these%20spacing%20presets,in%20which%20they%20are%20applied)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=Fluid%20spacing%20utilizes%20the%20clamp,Small%2C%20Medium%2C%20Large%2C%20and%20xLarge).
-* **Using Spacing Scale Generator:** Alternatively, theme.json’s `"spacingScale"` can create a series of sizes by math. For example, you can specify an operator (`*` or `+`), an increment, a number of steps, a base (medium) step, and unit[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=The%20,settings%20that%20themes%20can%20configure)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=,rem). However, the scale generator on its own doesn’t inherently produce fluid values – it gives you a static progression (unless you use `vw` as the unit, which then all sizes are relative, but that’s not clamped). In practice, most theme developers will explicitly list `spacingSizes` if they want fluid values, so they have full control over each clamp formula[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=If%20you%20want%20to%20use,for%20controlling%20the%20size%20presets).
+- **Using Spacing Scale Generator:** Alternatively, theme.json’s `"spacingScale"` can create a series of sizes by math. For example, you can specify an operator (`*` or `+`), an increment, a number of steps, a base (medium) step, and unit[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=The%20,settings%20that%20themes%20can%20configure)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=,rem). However, the scale generator on its own doesn’t inherently produce fluid values – it gives you a static progression (unless you use `vw` as the unit, which then all sizes are relative, but that’s not clamped). In practice, most theme developers will explicitly list `spacingSizes` if they want fluid values, so they have full control over each clamp formula[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=If%20you%20want%20to%20use,for%20controlling%20the%20size%20presets).
-* **Fluid Spacing in Practice (Example):** The Frost theme (a popular block theme) initially defined static spacing presets (like 20px, 40px, 60px… for x-small, small, medium, large, x-large)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=,small%22%20%7D%2C)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=,large%22). They later introduced “fluid spacing” by changing some of those values to clamp formulas[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=We%20will%20soon%20update%20Frost,of%20fluid%20spacing%20in%20Frost)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,medium). For instance, Frost’s “Small” became `clamp(20px, 4vw, 40px)`, “Medium” `clamp(30px, 6vw, 60px)`, etc.[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,medium)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,large). This means on a very narrow screen, “Small” spacing might be 20px; on a very wide screen it maxes at 40px; and it grows with 4vw in between. On the front end, this is output as part of the style so that any block using, say, a spacing preset of “Medium” will get that clamp value via the CSS var. This approach is confirmed by WP’s documentation: *“If you want to use fluid spacing, you must use the spacingSizes method… clamp(), min(), max(), and other valid CSS values are supported”*[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=If%20you%20want%20to%20use,for%20controlling%20the%20size%20presets).
+- **Fluid Spacing in Practice (Example):** The Frost theme (a popular block theme) initially defined static spacing presets (like 20px, 40px, 60px… for x-small, small, medium, large, x-large)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=,small%22%20%7D%2C)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=,large%22). They later introduced “fluid spacing” by changing some of those values to clamp formulas[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=We%20will%20soon%20update%20Frost,of%20fluid%20spacing%20in%20Frost)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,medium). For instance, Frost’s “Small” became `clamp(20px, 4vw, 40px)`, “Medium” `clamp(30px, 6vw, 60px)`, etc.[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,medium)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,large). This means on a very narrow screen, “Small” spacing might be 20px; on a very wide screen it maxes at 40px; and it grows with 4vw in between. On the front end, this is output as part of the style so that any block using, say, a spacing preset of “Medium” will get that clamp value via the CSS var. This approach is confirmed by WP’s documentation: _“If you want to use fluid spacing, you must use the spacingSizes method… clamp(), min(), max(), and other valid CSS values are supported”_[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=If%20you%20want%20to%20use,for%20controlling%20the%20size%20presets).
-* **Current Limitations:** Unlike typography, there isn’t (as of WP 6.6) a core feature that automatically generates fluid spacing for you or a toggle to turn it on globally. You define it manually. That means some themes might not implement fluid spacing at all, sticking to static preset values. If you use a theme that has static spacing presets and you want them fluid, you’d have to modify theme.json. There was discussion in the community about a “consistent fluid spacing scale” to avoid odd behavior[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20year%2C%208%20months%20ago)[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=I%20did%20also%20receive%20some,might%20provide%20some%20extra%20context). For example, early adopters found that the default scale in Twenty Twenty-Four theme led to strange values: one user noted a preset step that yielded \~7.5px on mobile, which was smaller than the step below it (16px) – an inconsistency[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=What%E2%80%99s%20weirder%20still%20is%20that%2C,the%20scale%20then%20it%20goes). This happened because the spacing scale wasn’t scaling linearly; the steps had different clamp formulas, causing a non-monotonic curve at certain points. The takeaway: **be careful to design your fluid spacing presets so they maintain order and consistency** at all screen sizes. Ideally, each larger spacing is always larger than a smaller spacing. Using proportional formulas or deriving from a single base unit can help ensure that.
+- **Current Limitations:** Unlike typography, there isn’t (as of WP 6.6) a core feature that automatically generates fluid spacing for you or a toggle to turn it on globally. You define it manually. That means some themes might not implement fluid spacing at all, sticking to static preset values. If you use a theme that has static spacing presets and you want them fluid, you’d have to modify theme.json. There was discussion in the community about a “consistent fluid spacing scale” to avoid odd behavior[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20year%2C%208%20months%20ago)[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=I%20did%20also%20receive%20some,might%20provide%20some%20extra%20context). For example, early adopters found that the default scale in Twenty Twenty-Four theme led to strange values: one user noted a preset step that yielded \~7.5px on mobile, which was smaller than the step below it (16px) – an inconsistency[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=What%E2%80%99s%20weirder%20still%20is%20that%2C,the%20scale%20then%20it%20goes). This happened because the spacing scale wasn’t scaling linearly; the steps had different clamp formulas, causing a non-monotonic curve at certain points. The takeaway: **be careful to design your fluid spacing presets so they maintain order and consistency** at all screen sizes. Ideally, each larger spacing is always larger than a smaller spacing. Using proportional formulas or deriving from a single base unit can help ensure that.
-* **Block Support:** Many blocks in WordPress support these spacing presets via UI controls. For instance, the Group block or Cover block may let you pick a padding size (“small, medium, large”) which corresponds to your theme’s values. When those are fluid, the block will automagically have fluid padding. If you have a custom block or custom CSS, you can also use the CSS variables directly (e.g., `padding: var(--wp--preset--spacing--large)` and it will inherently be fluid if that preset was defined as a clamp).
+- **Block Support:** Many blocks in WordPress support these spacing presets via UI controls. For instance, the Group block or Cover block may let you pick a padding size (“small, medium, large”) which corresponds to your theme’s values. When those are fluid, the block will automagically have fluid padding. If you have a custom block or custom CSS, you can also use the CSS variables directly (e.g., `padding: var(--wp--preset--spacing--large)` and it will inherently be fluid if that preset was defined as a clamp).
**Practical tips for WordPress fluid spacing:**
-* *Use theme.json to your advantage:* Centralize your spacing values in theme.json so everything is consistent. That also ensures the Site Editor UI shows the right options.
+- _Use theme.json to your advantage:_ Centralize your spacing values in theme.json so everything is consistent. That also ensures the Site Editor UI shows the right options.
-* *Test preset outputs:* After defining fluid spacing in theme.json, inspect the site’s CSS (in the browser or by opening the site’s `theme.css` if available) to see the actual `clamp()` values generated[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=%22name%22%3A%20%22Fluid%20Scale%20,3)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=%29%60Fluid%20Scale%20,79rem). Test at a couple of breakpoints to verify the scaling is working as expected.
+- _Test preset outputs:_ After defining fluid spacing in theme.json, inspect the site’s CSS (in the browser or by opening the site’s `theme.css` if available) to see the actual `clamp()` values generated[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=%22name%22%3A%20%22Fluid%20Scale%20,3)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=%29%60Fluid%20Scale%20,79rem). Test at a couple of breakpoints to verify the scaling is working as expected.
-* *Adjust for content:* If you find, for example, that a large section padding is still too big on a particular small device, you might lower the `min` in the clamp a bit more. Conversely, if there’s too little space on big screens, raise the `max`.
+- _Adjust for content:_ If you find, for example, that a large section padding is still too big on a particular small device, you might lower the `min` in the clamp a bit more. Conversely, if there’s too little space on big screens, raise the `max`.
-* *Combine with other tools:* WordPress fluid spacing handles the smooth scaling, but you can still enforce layout constraints via the layout settings in theme.json or custom CSS. For example, you might have fluid padding on sections, but also set a max-width on content so it doesn’t stretch too wide. These can work in tandem.
+- _Combine with other tools:_ WordPress fluid spacing handles the smooth scaling, but you can still enforce layout constraints via the layout settings in theme.json or custom CSS. For example, you might have fluid padding on sections, but also set a max-width on content so it doesn’t stretch too wide. These can work in tandem.
-* *Be mindful of interactions:* If you have **nested fluid spacing**, e.g., a fluid padding inside a container that itself has fluid margin, the combined effect should still make sense. Usually it does (since both just respond to the same viewport), but double-check that you’re not doubling up. If a section has 5rem max padding and its parent also has margin scaling, you might end up with more space than intended on large screens. You might decide to handle one or the other fluidly, but not both, depending on design.
+- _Be mindful of interactions:_ If you have **nested fluid spacing**, e.g., a fluid padding inside a container that itself has fluid margin, the combined effect should still make sense. Usually it does (since both just respond to the same viewport), but double-check that you’re not doubling up. If a section has 5rem max padding and its parent also has margin scaling, you might end up with more space than intended on large screens. You might decide to handle one or the other fluidly, but not both, depending on design.
-* *Custom spacing vs presets:* By default, WordPress allows entering custom spacing values (e.g., typing 50px in the editor). If you want to enforce using your fluid scale only (for design consistency), you can disable custom spacing by setting `"customSpacingSize": false` in theme.json[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=throughout%20your%20design)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=). That will restrict editors to your preset choices, which is great if your fluid scale is carefully designed. If custom values are allowed, users might inadvertently put a fixed value somewhere, which won’t scale.
+- _Custom spacing vs presets:_ By default, WordPress allows entering custom spacing values (e.g., typing 50px in the editor). If you want to enforce using your fluid scale only (for design consistency), you can disable custom spacing by setting `"customSpacingSize": false` in theme.json[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=throughout%20your%20design)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=). That will restrict editors to your preset choices, which is great if your fluid scale is carefully designed. If custom values are allowed, users might inadvertently put a fixed value somewhere, which won’t scale.
### **Best Practices for Fluid Spacing**
Implementing fluid spacing effectively requires a thoughtful approach. Here are key best practices:
-* **Design Spacing as a System:** Rather than assigning random padding/margins per element, define a **systematic scale** of spacing sizes (tokens) that you use throughout the project. This scale should ideally be based on meaningful increments (maybe a geometric progression or multiples of a base unit). When you make that scale fluid, all the spacing in the design will expand/contract together, preserving rhythm. This avoids one part of your design looking overly spaced out while another part looks cramped at a certain screen width. By thinking in terms of “Small, Medium, Large spacing” etc., you create a shared vocabulary for designers and developers (just like with type scale steps)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Fluid%20Space%20Palettes)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=This%20also%20creates%20a%20shared%2C,infiltrating%20our%20codebases%20and%20designs).
+- **Design Spacing as a System:** Rather than assigning random padding/margins per element, define a **systematic scale** of spacing sizes (tokens) that you use throughout the project. This scale should ideally be based on meaningful increments (maybe a geometric progression or multiples of a base unit). When you make that scale fluid, all the spacing in the design will expand/contract together, preserving rhythm. This avoids one part of your design looking overly spaced out while another part looks cramped at a certain screen width. By thinking in terms of “Small, Medium, Large spacing” etc., you create a shared vocabulary for designers and developers (just like with type scale steps)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Fluid%20Space%20Palettes)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=This%20also%20creates%20a%20shared%2C,infiltrating%20our%20codebases%20and%20designs).
-* **Link Spacing to Typography:** Often the optimal spacing is related to text size – for example, you might want a consistent number of lines or characters of padding. If your typography is fluid, one easy way to get fluid spacing is to use `em` or `rem` units for spacing. For instance, if you set a margin as `2em`, it will automatically be 2× the current font-size of that element. As the font-size (maybe an `h1`) grows, its margin in em will grow. This technique basically piggybacks on fluid type. It’s especially useful for vertical margins around text elements. For more global spacing (like page padding), tying it to `rem` (which is based on the root font-size) is good, since if the user’s default font or overall scaling changes, your spaces follow suit. Many CSS frameworks use rem for spacing for this reason. If you combine this with clamp (e.g., a clamp that itself yields rem values), you get a double benefit of viewport scaling and respecting user font settings.
+- **Link Spacing to Typography:** Often the optimal spacing is related to text size – for example, you might want a consistent number of lines or characters of padding. If your typography is fluid, one easy way to get fluid spacing is to use `em` or `rem` units for spacing. For instance, if you set a margin as `2em`, it will automatically be 2× the current font-size of that element. As the font-size (maybe an `h1`) grows, its margin in em will grow. This technique basically piggybacks on fluid type. It’s especially useful for vertical margins around text elements. For more global spacing (like page padding), tying it to `rem` (which is based on the root font-size) is good, since if the user’s default font or overall scaling changes, your spaces follow suit. Many CSS frameworks use rem for spacing for this reason. If you combine this with clamp (e.g., a clamp that itself yields rem values), you get a double benefit of viewport scaling and respecting user font settings.
-* **Ensure Monotonic Scaling:** As mentioned, keep an eye on the relative order of your spacing tokens. A “medium” space should be larger than “small” at all times. If your formulas are inconsistent (e.g., one uses `3vw` and another uses `8vw` without coordination), it’s possible that at some intermediate width the one with 8vw might overtake the other. To ensure monotonic behavior, consider using a single formula for all and just multiplying it by different factors. For example, define a base fluid unit like `--fluid-unit: clamp(4px, 1vw, 16px)` and then use `small = 2 * var(--fluid-unit)`, `medium = 4 * var(--fluid-unit)` etc. This way, no matter the viewport, the multiples remain proportional and ordered. If not using custom props, at least visually test that at critical points (small, medium, large screens) your hierarchy holds. It’s a bit embarrassing if a “larger” spacing actually looks smaller at iPad width, for instance.
+- **Ensure Monotonic Scaling:** As mentioned, keep an eye on the relative order of your spacing tokens. A “medium” space should be larger than “small” at all times. If your formulas are inconsistent (e.g., one uses `3vw` and another uses `8vw` without coordination), it’s possible that at some intermediate width the one with 8vw might overtake the other. To ensure monotonic behavior, consider using a single formula for all and just multiplying it by different factors. For example, define a base fluid unit like `--fluid-unit: clamp(4px, 1vw, 16px)` and then use `small = 2 * var(--fluid-unit)`, `medium = 4 * var(--fluid-unit)` etc. This way, no matter the viewport, the multiples remain proportional and ordered. If not using custom props, at least visually test that at critical points (small, medium, large screens) your hierarchy holds. It’s a bit embarrassing if a “larger” spacing actually looks smaller at iPad width, for instance.
-* **Don’t Overdo Minor Gaps:** Not every spacing value needs to scale. Very small gaps (like a 4px border or a 8px icon spacing) might be fine staying constant. Fluid spacing is most beneficial for **macro spacing** – the big paddings, section margins, grid gutters, etc., that really should adapt to screen real estate. Over-optimizing tiny values can complicate things for little gain. A good heuristic: if a space is less than maybe 0.5rem (8px), it can probably remain static in most cases. If it’s something like 2rem (32px) or more, that’s a candidate to fluidize. This isn’t a strict rule but helps avoid unnecessary complexity.
+- **Don’t Overdo Minor Gaps:** Not every spacing value needs to scale. Very small gaps (like a 4px border or a 8px icon spacing) might be fine staying constant. Fluid spacing is most beneficial for **macro spacing** – the big paddings, section margins, grid gutters, etc., that really should adapt to screen real estate. Over-optimizing tiny values can complicate things for little gain. A good heuristic: if a space is less than maybe 0.5rem (8px), it can probably remain static in most cases. If it’s something like 2rem (32px) or more, that’s a candidate to fluidize. This isn’t a strict rule but helps avoid unnecessary complexity.
-* **Use Clamp for Predictability:** While you could use pure `vw` or `%` for spacing (e.g., `margin-top: 10vw;` will indeed scale with width), it’s usually better to wrap them in a `clamp()` to set boundaries. Pure viewport units might shrink spacing *too much* on extremely small screens or grow too much on huge screens. By clamping you set design limits – e.g., never less than 1rem padding, never more than 10rem, etc.[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=Fluid%20spacing%20utilizes%20the%20clamp,Small%2C%20Medium%2C%20Large%2C%20and%20xLarge)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,medium). This ensures your design doesn’t break at the extremes.
+- **Use Clamp for Predictability:** While you could use pure `vw` or `%` for spacing (e.g., `margin-top: 10vw;` will indeed scale with width), it’s usually better to wrap them in a `clamp()` to set boundaries. Pure viewport units might shrink spacing _too much_ on extremely small screens or grow too much on huge screens. By clamping you set design limits – e.g., never less than 1rem padding, never more than 10rem, etc.[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=Fluid%20spacing%20utilizes%20the%20clamp,Small%2C%20Medium%2C%20Large%2C%20and%20xLarge)[wpengine.com](https://wpengine.com/builders/spacing-presets/#:~:text=%7B%20,medium). This ensures your design doesn’t break at the extremes.
-* **Consider Layout Changes at Breakpoints:** Fluid spacing will handle gradual changes, but sometimes you have a breakpoint where the layout itself changes (for example, switching from single-column to two-column at medium screens). At those points, you might want to also adjust spacing rules. Maybe your 5vw gutter in one-column layout doesn’t make sense in a multi-column layout. It’s okay to override or tweak at breakpoints – fluid design doesn’t eliminate breakpoints entirely; it reduces their necessity. Use media queries in tandem with fluid spacing for any discontinuous changes. For instance: you might have `gap: clamp(1rem, 2vw, 2rem)` on a grid by default, but at `@media(min-width: 800px) { .grid { gap: clamp(2rem, 4vw, 4rem); } }` to give a bigger range once more columns are present. This way, the spacing is fluid in both ranges, just with a different scale after the breakpoint.
+- **Consider Layout Changes at Breakpoints:** Fluid spacing will handle gradual changes, but sometimes you have a breakpoint where the layout itself changes (for example, switching from single-column to two-column at medium screens). At those points, you might want to also adjust spacing rules. Maybe your 5vw gutter in one-column layout doesn’t make sense in a multi-column layout. It’s okay to override or tweak at breakpoints – fluid design doesn’t eliminate breakpoints entirely; it reduces their necessity. Use media queries in tandem with fluid spacing for any discontinuous changes. For instance: you might have `gap: clamp(1rem, 2vw, 2rem)` on a grid by default, but at `@media(min-width: 800px) { .grid { gap: clamp(2rem, 4vw, 4rem); } }` to give a bigger range once more columns are present. This way, the spacing is fluid in both ranges, just with a different scale after the breakpoint.
-* **Document and Communicate:** If you’re working in a team, document your fluid spacing decisions just like you would the design tokens. Explain that “Spacing Small \= clamp(8px, 2vw, 16px)” etc., so everyone knows. Designers using Figma can simulate this by checking at a couple of screen sizes – the Utopia approach even suggests creating Figma variants for min and max spacing to visualize the difference[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Designing%20With%20Fluid%20Space). This helps get everyone on the same page about how much things move. It’s a bit new for some to trust the in-between to the browser, but with documentation and perhaps interactive hand-off (like a Storybook demo of fluid behavior), it becomes clearer.
+- **Document and Communicate:** If you’re working in a team, document your fluid spacing decisions just like you would the design tokens. Explain that “Spacing Small \= clamp(8px, 2vw, 16px)” etc., so everyone knows. Designers using Figma can simulate this by checking at a couple of screen sizes – the Utopia approach even suggests creating Figma variants for min and max spacing to visualize the difference[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Designing%20With%20Fluid%20Space). This helps get everyone on the same page about how much things move. It’s a bit new for some to trust the in-between to the browser, but with documentation and perhaps interactive hand-off (like a Storybook demo of fluid behavior), it becomes clearer.
### **Troubleshooting Fluid Spacing**
When implementing fluid spacing, you might run into a few issues. Here are some common ones and ways to resolve them:
-* **Unexpected Tiny or Huge Spaces:** If you see a spacing value that seems way off at a certain viewport, re-check the clamp formula. It could be that the `vw` portion is calculated differently than you assumed. For instance, remember that `vw` is 1% of the *viewport width*. So at a 320px wide screen, 1vw \= 3.2px; at a 1440px wide screen, 1vw \= 14.4px. If you did `clamp(20px, 10vw, 100px)`, on a 320px screen the ideal would be 32px (which is above the 20px min, so it might actually apply \~32px if not clamped by min), and on a 1440px screen, ideal is 144px (which would clamp down to 100px max). So between \~768px and 1440px it scales up to 100px. But below \~200px width it would actually hit the 20px min. The point is, do a quick mental check or test of what the clamp outputs at a few key widths (min width, mid, max width). If it doesn’t match expectation, adjust the values. Sometimes a weird non-linear formula can produce unintuitive results in the middle range, so simplify if needed.
+- **Unexpected Tiny or Huge Spaces:** If you see a spacing value that seems way off at a certain viewport, re-check the clamp formula. It could be that the `vw` portion is calculated differently than you assumed. For instance, remember that `vw` is 1% of the _viewport width_. So at a 320px wide screen, 1vw \= 3.2px; at a 1440px wide screen, 1vw \= 14.4px. If you did `clamp(20px, 10vw, 100px)`, on a 320px screen the ideal would be 32px (which is above the 20px min, so it might actually apply \~32px if not clamped by min), and on a 1440px screen, ideal is 144px (which would clamp down to 100px max). So between \~768px and 1440px it scales up to 100px. But below \~200px width it would actually hit the 20px min. The point is, do a quick mental check or test of what the clamp outputs at a few key widths (min width, mid, max width). If it doesn’t match expectation, adjust the values. Sometimes a weird non-linear formula can produce unintuitive results in the middle range, so simplify if needed.
-* **Overlapping/Collapsing Margins:** If you use fluid margins on elements that stack, remember that in CSS, vertical margins can collapse. This isn’t directly related to fluid, but it might confuse debugging. For example, if a section has a bottom margin that is fluid and the next section has a top margin, one of them might collapse. You might wonder “why didn’t my fluid margin give the space I expected?” It could be collapse at play. Use padding on one side or otherwise manage collapse (perhaps with a wrapper or using blockGap in container blocks which handles it internally). Just something to keep in mind, as fluid values can be any length, the concept of margin collapse still applies.
+- **Overlapping/Collapsing Margins:** If you use fluid margins on elements that stack, remember that in CSS, vertical margins can collapse. This isn’t directly related to fluid, but it might confuse debugging. For example, if a section has a bottom margin that is fluid and the next section has a top margin, one of them might collapse. You might wonder “why didn’t my fluid margin give the space I expected?” It could be collapse at play. Use padding on one side or otherwise manage collapse (perhaps with a wrapper or using blockGap in container blocks which handles it internally). Just something to keep in mind, as fluid values can be any length, the concept of margin collapse still applies.
-* **Fluid Gap in CSS Grid Not Working:** CSS Grid supports `gap` property which can use clamp. E.g., `gap: clamp(1rem, 5vw, 3rem)`. This should work normally. But if you see something odd, ensure no older browser issues. In modern browsers, it’s fine. If supporting older ones that don’t know clamp in grid, there’s no easy fallback other than defining an approximate static gap for them (perhaps via @supports if needed). But since support is good, likely not a problem now.
+- **Fluid Gap in CSS Grid Not Working:** CSS Grid supports `gap` property which can use clamp. E.g., `gap: clamp(1rem, 5vw, 3rem)`. This should work normally. But if you see something odd, ensure no older browser issues. In modern browsers, it’s fine. If supporting older ones that don’t know clamp in grid, there’s no easy fallback other than defining an approximate static gap for them (perhaps via @supports if needed). But since support is good, likely not a problem now.
-* **Editor Preview vs Front-End Difference (WP):** If you use WordPress fluid spacing in theme.json, the editor (Site Editor or post editor) should load those styles too. But occasionally, you might see slight differences in how spacing is applied in the editor canvas vs the front. This might be due to editor iframe constraints or some editor style overriding things. Make sure you have not accidentally given the editor a different spacing scale. Typically, the global styles system syncs them, but keep an eye out. If something looks off in editor, you might need to adjust the theme.json or add some editor-specific styles. Also note, as of WP 6.6, the Styles panel in the editor doesn’t yet preview custom section style variations perfectly (as per known issues), so fluid spacing within a section style might not show exactly until you view it on the front end.
+- **Editor Preview vs Front-End Difference (WP):** If you use WordPress fluid spacing in theme.json, the editor (Site Editor or post editor) should load those styles too. But occasionally, you might see slight differences in how spacing is applied in the editor canvas vs the front. This might be due to editor iframe constraints or some editor style overriding things. Make sure you have not accidentally given the editor a different spacing scale. Typically, the global styles system syncs them, but keep an eye out. If something looks off in editor, you might need to adjust the theme.json or add some editor-specific styles. Also note, as of WP 6.6, the Styles panel in the editor doesn’t yet preview custom section style variations perfectly (as per known issues), so fluid spacing within a section style might not show exactly until you view it on the front end.
-* **Fluid Spacing Inconsistencies/Bugs:** Because fluid spacing is relatively new in core, there have been a few bugs. For example, the early Twenty Twenty-Four theme’s fluid spacing scale wasn’t monotonic as we mentioned, causing a confusing UX in the slider control (a smaller value on the scale produced a larger pixel output than the next step)[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20%E2%80%94%2016px%202%20%E2%80%94,256px)[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20year%2C%208%20months%20ago). This kind of bug can “feel” like the controls are broken. The solution came from adjusting the theme’s scale values after community feedback. So if you run into an issue like that – say your spacing slider in the editor isn’t linear – you might need to refine the values in theme.json. Make sure each step’s clamp covers an appropriate range that doesn’t overlap the next. If the suggestion on GitHub was to *“add a consistent fluid spacing scale”*, you may implement that by, for instance, using a mathematical progression rather than arbitrary numbers[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20year%2C%208%20months%20ago). Keep an eye on WordPress release notes for any fluid spacing improvements; for instance, future versions might introduce an easier opt-in similar to typography.
+- **Fluid Spacing Inconsistencies/Bugs:** Because fluid spacing is relatively new in core, there have been a few bugs. For example, the early Twenty Twenty-Four theme’s fluid spacing scale wasn’t monotonic as we mentioned, causing a confusing UX in the slider control (a smaller value on the scale produced a larger pixel output than the next step)[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20%E2%80%94%2016px%202%20%E2%80%94,256px)[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20year%2C%208%20months%20ago). This kind of bug can “feel” like the controls are broken. The solution came from adjusting the theme’s scale values after community feedback. So if you run into an issue like that – say your spacing slider in the editor isn’t linear – you might need to refine the values in theme.json. Make sure each step’s clamp covers an appropriate range that doesn’t overlap the next. If the suggestion on GitHub was to _“add a consistent fluid spacing scale”_, you may implement that by, for instance, using a mathematical progression rather than arbitrary numbers[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20year%2C%208%20months%20ago). Keep an eye on WordPress release notes for any fluid spacing improvements; for instance, future versions might introduce an easier opt-in similar to typography.
-* **Interaction with Content Width:** Sometimes you may notice that on a very large screen, even though spacing increased, the content might be all aligned to one side or too spread out. This is more of a layout issue – remember to also set a max content width (via theme layouts or custom CSS) if you want to limit how far things can stretch. Fluid spacing doesn’t automatically center or contain content. Use the layout settings (like root padding, alignwide widths, etc.) to ensure your design remains balanced. Fluid spacing is one tool in the responsive design toolbox; it works best alongside a cohesive layout strategy.
+- **Interaction with Content Width:** Sometimes you may notice that on a very large screen, even though spacing increased, the content might be all aligned to one side or too spread out. This is more of a layout issue – remember to also set a max content width (via theme layouts or custom CSS) if you want to limit how far things can stretch. Fluid spacing doesn’t automatically center or contain content. Use the layout settings (like root padding, alignwide widths, etc.) to ensure your design remains balanced. Fluid spacing is one tool in the responsive design toolbox; it works best alongside a cohesive layout strategy.
-* **Nested Fluid Spacing Compounding:** If you have multiple nested elements each with fluid padding, the effect stacks. E.g., a section with padding clamp and inside it a card with padding clamp. At large screens, the section might give 100px and the card another 50px inside, totaling 150px of space around content, which might or might not be desired. If you find the spacing is too much in aggregate, consider whether both levels need fluid padding or if maybe only one level should handle the main scaling and the inner can stay more static. Often a parent section can handle the major responsive padding, and inner components can just have a consistent small padding.
+- **Nested Fluid Spacing Compounding:** If you have multiple nested elements each with fluid padding, the effect stacks. E.g., a section with padding clamp and inside it a card with padding clamp. At large screens, the section might give 100px and the card another 50px inside, totaling 150px of space around content, which might or might not be desired. If you find the spacing is too much in aggregate, consider whether both levels need fluid padding or if maybe only one level should handle the main scaling and the inner can stay more static. Often a parent section can handle the major responsive padding, and inner components can just have a consistent small padding.
-* **Older Browser Considerations:** Similar to clamp for typography, clamp for spacing has great support. If you did need a fallback, you could provide a static padding and then override with clamp in a supports query, but that’s likely overkill unless you specifically target something like an email client (which is beyond web). If targeting print CSS or some unusual user agent, they might ignore clamp, so default to the middle value maybe. But for web, assume clamp works.
+- **Older Browser Considerations:** Similar to clamp for typography, clamp for spacing has great support. If you did need a fallback, you could provide a static padding and then override with clamp in a supports query, but that’s likely overkill unless you specifically target something like an email client (which is beyond web). If targeting print CSS or some unusual user agent, they might ignore clamp, so default to the middle value maybe. But for web, assume clamp works.
By carefully implementing and testing, fluid spacing can significantly enhance the responsiveness of your layouts. Users will perceive that the design just “feels right” on any device – content isn’t too squished or too padded, and the whitespace scales elegantly as they rotate a device or resize a window.
@@ -321,23 +320,22 @@ Fluid typography and spacing are powerful techniques that bring our designs clos
For further exploration, here are some resources and tips:
-* **MDN Web Docs on CSS Functions:** Understanding `min()`, `max()`, and `clamp()` is key. The MDN documentation provides clear definitions – for instance, *“The clamp() CSS function clamps a value within a range… takes a minimum, a preferred, and a maximum value”*[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=The%20,and%20a%20maximum%20allowed%20value). It also shows examples comparing the old media query approach to the new one-liner.
+- **MDN Web Docs on CSS Functions:** Understanding `min()`, `max()`, and `clamp()` is key. The MDN documentation provides clear definitions – for instance, _“The clamp() CSS function clamps a value within a range… takes a minimum, a preferred, and a maximum value”_[developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp#:~:text=The%20,and%20a%20maximum%20allowed%20value). It also shows examples comparing the old media query approach to the new one-liner.
-* **Web.dev Guide:** Google’s web.dev has an excellent article *“CSS min(), max(), and clamp()”* by Una Kravets, which includes sections on fluid typography and fluid spacing[web.dev](https://web.dev/articles/min-max-clamp#:~:text=authors%20increased%20control,create%20flexible%20and%20fluid%20typography)[web.dev](https://web.dev/articles/min-max-clamp#:~:text=functions%2C%20now%20supported%20in%20all,create%20flexible%20and%20fluid%20typography). It even warns about the zoom issue we discussed, linking to WCAG guidelines[web.dev](https://web.dev/articles/min-max-clamp#:~:text=Warning%3A%20Limiting%20maximum%20font%20sizes,test%20the%20results%20with%20zoom). This is a great read to solidify your understanding of these functions.
+- **Web.dev Guide:** Google’s web.dev has an excellent article _“CSS min(), max(), and clamp()”_ by Una Kravets, which includes sections on fluid typography and fluid spacing[web.dev](https://web.dev/articles/min-max-clamp#:~:text=authors%20increased%20control,create%20flexible%20and%20fluid%20typography)[web.dev](https://web.dev/articles/min-max-clamp#:~:text=functions%2C%20now%20supported%20in%20all,create%20flexible%20and%20fluid%20typography). It even warns about the zoom issue we discussed, linking to WCAG guidelines[web.dev](https://web.dev/articles/min-max-clamp#:~:text=Warning%3A%20Limiting%20maximum%20font%20sizes,test%20the%20results%20with%20zoom). This is a great read to solidify your understanding of these functions.
-* **Smashing Magazine on Utopia (Fluid Type & Space):** *“Meet Utopia: Designing And Building With Fluid Type And Space Scales”*[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=page%20sizes%2C%20Utopia%20can%20unlock,elegant%20typography%20for%20all%20devices)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Developing%20With%20Fluid%20Typography) is a fantastic deep dive into creating a holistic fluid design system. The Utopia tools themselves (at utopia.fyi) allow you to input design parameters and get out CSS custom property snippets for fluid type and space. They embody a lot of best practices around maintaining harmony (using step scales, base units, etc.)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=intentional%2C%20fluid%20gaps%20to%20be,tool%20in%20the%20Utopia%20collection)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Taking%20%E2%80%9CStep%200%E2%80%9D%20from%20the,as%20our%20base%20unit%2C%20we).
+- **Smashing Magazine on Utopia (Fluid Type & Space):** _“Meet Utopia: Designing And Building With Fluid Type And Space Scales”_[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=page%20sizes%2C%20Utopia%20can%20unlock,elegant%20typography%20for%20all%20devices)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Developing%20With%20Fluid%20Typography) is a fantastic deep dive into creating a holistic fluid design system. The Utopia tools themselves (at utopia.fyi) allow you to input design parameters and get out CSS custom property snippets for fluid type and space. They embody a lot of best practices around maintaining harmony (using step scales, base units, etc.)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=intentional%2C%20fluid%20gaps%20to%20be,tool%20in%20the%20Utopia%20collection)[smashingmagazine.com](https://www.smashingmagazine.com/2021/04/designing-developing-fluid-type-space-scales/#:~:text=Taking%20%E2%80%9CStep%200%E2%80%9D%20from%20the,as%20our%20base%20unit%2C%20we).
-* **Rich Tabor’s Blog Posts:** Rich Tabor has written about fluid typography and standardizing spacing in the context of WordPress block themes. In *“Fluid Typography and Block Themes”*, he walks through opting into WP’s fluid type, adding min/max in theme.json, and shows the resulting clamp formula[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=First%20off%2C%20a%20theme%20needs,like%20so)[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=,1.592%29%2C%206rem). In *“Standardizing theme.json spacing sizes”*, he likely covers spacing presets and how to choose them (e.g., using t-shirt sizes and maybe fluid values). These can provide insight into real-world theme implementation.
+- **Rich Tabor’s Blog Posts:** Rich Tabor has written about fluid typography and standardizing spacing in the context of WordPress block themes. In _“Fluid Typography and Block Themes”_, he walks through opting into WP’s fluid type, adding min/max in theme.json, and shows the resulting clamp formula[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=First%20off%2C%20a%20theme%20needs,like%20so)[rich.blog](https://rich.blog/fluid-typography-block-themes/#:~:text=,1.592%29%2C%206rem). In _“Standardizing theme.json spacing sizes”_, he likely covers spacing presets and how to choose them (e.g., using t-shirt sizes and maybe fluid values). These can provide insight into real-world theme implementation.
-* **WordPress Developer Handbook:** The official documentation now has sections on typography and spacing. The **Typography settings** guide covers enabling fluid type and provides examples of theme.json usage[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=WordPress%20will%20now%20generate%20fluid,sizes%20for%20registered%20font%20sizes)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=You%20will%20undoubtedly%20want%20to,theme.json). The **Spacing settings** guide shows how to define spacing sizes and notes that you can use fluid expressions there[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=If%20you%20want%20to%20use,for%20controlling%20the%20size%20presets). These are useful for any WordPress theme developer to keep bookmarked.
+- **WordPress Developer Handbook:** The official documentation now has sections on typography and spacing. The **Typography settings** guide covers enabling fluid type and provides examples of theme.json usage[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=WordPress%20will%20now%20generate%20fluid,sizes%20for%20registered%20font%20sizes)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/#:~:text=You%20will%20undoubtedly%20want%20to,theme.json). The **Spacing settings** guide shows how to define spacing sizes and notes that you can use fluid expressions there[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/#:~:text=If%20you%20want%20to%20use,for%20controlling%20the%20size%20presets). These are useful for any WordPress theme developer to keep bookmarked.
-* **Community Discussions:** If you run into issues or odd behaviors, it’s worth searching the Gutenberg GitHub issues or discussions. For example, issues around fluid spacing in early themes or proposals for improving it (like issue comments about inconsistent scale) can shed light on pitfalls[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20year%2C%208%20months%20ago). The WordPress.org support forums (as we saw with Twenty Twenty-Four) also highlight how users experience these features and what might need fine-tuning[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=On%20desktop%2C%20this%20is%2064px,76px)[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=I%20did%20also%20receive%20some,might%20provide%20some%20extra%20context).
+- **Community Discussions:** If you run into issues or odd behaviors, it’s worth searching the Gutenberg GitHub issues or discussions. For example, issues around fluid spacing in early themes or proposals for improving it (like issue comments about inconsistent scale) can shed light on pitfalls[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=1%20year%2C%208%20months%20ago). The WordPress.org support forums (as we saw with Twenty Twenty-Four) also highlight how users experience these features and what might need fine-tuning[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=On%20desktop%2C%20this%20is%2064px,76px)[wordpress.org](https://wordpress.org/support/topic/inconsistent-spacing-controls/#:~:text=I%20did%20also%20receive%20some,might%20provide%20some%20extra%20context).
-* **CSS Tricks and Other Blogs:** Articles like *“Modern Fluid Typography Using CSS Clamp”* (Smashing) or *“Linearly Scale Font-Size with CSS Clamp”* (CSS-Tricks) dive into the math and various techniques for fluid type[smashingmagazine.com](https://www.smashingmagazine.com/2022/01/modern-fluid-typography-css-clamp/#:~:text=Modern%20Fluid%20Typography%20Using%20CSS,and%20how%20to%20calculate)[css-tricks.com](https://css-tricks.com/linearly-scale-font-size-with-css-clamp-based-on-the-viewport/#:~:text=Linearly%20Scale%20font,as%20the%20viewport%27s%20width%20increases). Similarly, blogs discussing fluid UI design might give creative ideas (e.g., using `calc()` inside clamp to fine-adjust, or using `vmin/vmax` units for a different approach).
+- **CSS Tricks and Other Blogs:** Articles like _“Modern Fluid Typography Using CSS Clamp”_ (Smashing) or _“Linearly Scale Font-Size with CSS Clamp”_ (CSS-Tricks) dive into the math and various techniques for fluid type[smashingmagazine.com](https://www.smashingmagazine.com/2022/01/modern-fluid-typography-css-clamp/#:~:text=Modern%20Fluid%20Typography%20Using%20CSS,and%20how%20to%20calculate)[css-tricks.com](https://css-tricks.com/linearly-scale-font-size-with-css-clamp-based-on-the-viewport/#:~:text=Linearly%20Scale%20font,as%20the%20viewport%27s%20width%20increases). Similarly, blogs discussing fluid UI design might give creative ideas (e.g., using `calc()` inside clamp to fine-adjust, or using `vmin/vmax` units for a different approach).
-* **Accessibility Checklists:** When deploying fluid designs, include zoom/text-resize in your QA checklist. Tools like browser dev tools have zoom and emulate functions; also test in high DPI settings. Ensure no important content is cut off or too small when text scales.
+- **Accessibility Checklists:** When deploying fluid designs, include zoom/text-resize in your QA checklist. Tools like browser dev tools have zoom and emulate functions; also test in high DPI settings. Ensure no important content is cut off or too small when text scales.
In conclusion, fluid typography and spacing help our designs **age gracefully** across device sizes and resolutions. By understanding the underlying CSS capabilities and following best practices from the community, you can implement a fluid design system that delivers a superior user experience. The web’s diversity of screens is no longer a liability to be managed only with breakpoints, but an opportunity to let content **intrinsically adapt** – providing readability and aesthetic integrity at every size[developer.wordpress.org](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/#:~:text=Modern,following%20CSS%20to%20handle%20that)[developer.wordpress.org](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/#:~:text=Following%20an%20intrinsic%20design%20method,shown%20in%20the%20following%20snippet). Embracing this approach will make your front-end development more future-friendly, and your designs more harmonious and professional.
With this guide and the referenced resources, the LightSpeed team (and any developers working with modern CSS or WordPress block themes) should be well-equipped to build interfaces that fluidly scale from tiny to massive screens. Now it’s time to apply these principles in your projects, perhaps starting with aligning those Figma design values to theme.json tokens and watching your site literally shape-shift perfectly at every breakpoint – or rather, every point in between. Happy coding\!
-
diff --git a/block-themes/fluid-spacing.md b/docs/wordpress/block-themes/theme.json/fluid-spacing.md
similarity index 66%
rename from block-themes/fluid-spacing.md
rename to docs/wordpress/block-themes/theme.json/fluid-spacing.md
index 9af720d..6fdc2d5 100644
--- a/block-themes/fluid-spacing.md
+++ b/docs/wordpress/block-themes/theme.json/fluid-spacing.md
@@ -1,8 +1,10 @@
# Fluid Spacing
+
Guides on creating fluid, scalable spacing systems in block themes using spacingScale and spacingSizes in theme.json, with practical examples. A systematic approach to spacing is central to clean, scalable block-theme design. This guide distils standardization principles and embeds them into actionable theme.json best practices.
## Best practices
-- Define a `spacingScale` in `settings.spacing` to auto-generate consistent spacing steps.
+
+- Define a `spacingScale` in `settings.spacing` to auto-generate consistent spacing steps.
- Optionally use `spacingSizes` for custom fluid values via `clamp()`.
- Define a consistent spacing system via `settings.spacing.spacingScale`, for example:
@@ -16,20 +18,21 @@ Guides on creating fluid, scalable spacing systems in block themes using spacing
"unit": "rem"
}
```
+
- This generates CSS custom properties like `--wp--preset--spacing--20`, `--wp--preset--spacing--30`, etc., which you can reference in CSS as `var(--wp--preset--spacing--20)`.
-* Alternatively use `spacingSizes` for granular control, including fluid values via `min()`, `clamp()`:
+- Alternatively use `spacingSizes` for granular control, including fluid values via `min()`, `clamp()`:
e.g.:
```json
- {
- "size": "min(40px, 4vw)",
- "slug": "30",
- "name": "3"
- }
+{
+ "size": "min(40px, 4vw)",
+ "slug": "30",
+ "name": "3"
+}
```
-* Enable blockGap, margin, and padding controls in the editor to leverage spacing presets visually.
+- Enable blockGap, margin, and padding controls in the editor to leverage spacing presets visually.
```json
{
@@ -44,16 +47,18 @@ Guides on creating fluid, scalable spacing systems in block themes using spacing
```
## When to use
+
- Use `spacingScale` for a consistent, predictable scale (linear or multiplicative) with a slider UI across the site.
- Use `spacingSizes` when you need bespoke tokens (e.g. semantic names like `s`, `m`, `l`) or fluid values via `clamp()` that don’t fit a uniform scale.
- Prefer one approach globally to keep the editor UI coherent; mixing can be reserved for specific blocks with a clear rationale.
+
---
## Limitations
-* Mixing `spacingScale` and `spacingSizes` can confuse UI patterns—choose one for clarity.
-* More than seven custom sizes create a dropdown UI instead of a slider.
-* Custom spacing control per block is not supported natively.
+- Mixing `spacingScale` and `spacingSizes` can confuse UI patterns—choose one for clarity.
+- More than seven custom sizes create a dropdown UI instead of a slider.
+- Custom spacing control per block is not supported natively.
---
@@ -65,42 +70,38 @@ Spacing—encompassing margin, padding, and column/child gaps—provides the "br
Using clamp(10px, 2vw, 40px):
-| **Viewport width** | **2vw calculation** | **Result (chosen by ****clamp****)** | **Why** |
-| --- | --- | --- | --- |
-| 320px (small mobile) | 6.4px | **10px** | 6.4px < min → use **min** |
-| 375px (mobile) | 7.5px | **10px** | 7.5px < min → use **min** |
-| 768px (tablet) | 15.36px | **15.36px** | within min–max → **fluid** value |
-| 1024px (tablet/SM desktop) | 20.48px | **20.48px** | within min–max → **fluid** value |
-| 1440px (desktop) | 28.8px | **28.8px** | within min–max → **fluid** value |
-| 1920px (large desktop) | 38.4px | **38.4px** | within min–max → **fluid** value |
-| 2400px (ultra-wide) | 48px | **40px** | 48px > max → use **max** |
-
-
+| **Viewport width** | **2vw calculation** | **Result (chosen by \*\***clamp\***\*)** | **Why** |
+| -------------------------- | ------------------- | ---------------------------------------- | -------------------------------- |
+| 320px (small mobile) | 6.4px | **10px** | 6.4px < min → use **min** |
+| 375px (mobile) | 7.5px | **10px** | 7.5px < min → use **min** |
+| 768px (tablet) | 15.36px | **15.36px** | within min–max → **fluid** value |
+| 1024px (tablet/SM desktop) | 20.48px | **20.48px** | within min–max → **fluid** value |
+| 1440px (desktop) | 28.8px | **28.8px** | within min–max → **fluid** value |
+| 1920px (large desktop) | 38.4px | **38.4px** | within min–max → **fluid** value |
+| 2400px (ultra-wide) | 48px | **40px** | 48px > max → use **max** |
### Key idea
-**vw**** is not tied to a specific “device.”** It continuously scales with viewport width. min and max determine *when* scaling starts and stops.
+**vw\*\***is not tied to a specific “device.”\**It continuously scales with viewport width. min and max determine*when\* scaling starts and stops.
-## Understanding the impact VW has on a Mobile device.
+## Understanding the impact VW has on a Mobile device
## 480px Mobile (min/max fixed, vw adjusted)
### Example: clamp(10px, Xvw, 40px)
-| **vw**** value** | **Calculation (Xvw @ 480px)** | **Result at 480px** | **Why** |
-| --- | --- | --- | --- |
-| **1vw** | 4.8px | **10px** | 4.8 < min → clamp uses min |
-| **2vw** | 9.6px | **10px** | 9.6 < min → clamp uses min |
-| **2.5vw** | 12px | **12px** | Now ≥ min → clamp uses fluid |
-| **3vw** | 14.4px | **14.4px** | Within min–max → fluid applies |
-| **5vw** | 24px | **24px** | Within min–max → fluid applies |
-| **10vw** | 48px | **40px** | Above max → clamp caps at max |
-
-
+| **vw\*\***value\*\* | **Calculation (Xvw @ 480px)** | **Result at 480px** | **Why** |
+| ------------------- | ----------------------------- | ------------------- | ------------------------------ |
+| **1vw** | 4.8px | **10px** | 4.8 < min → clamp uses min |
+| **2vw** | 9.6px | **10px** | 9.6 < min → clamp uses min |
+| **2.5vw** | 12px | **12px** | Now ≥ min → clamp uses fluid |
+| **3vw** | 14.4px | **14.4px** | Within min–max → fluid applies |
+| **5vw** | 24px | **24px** | Within min–max → fluid applies |
+| **10vw** | 48px | **40px** | Above max → clamp caps at max |
---
-### Option 1: `spacingScale`
+### Option 1: `spacingScale`
Use when you want a **scalable, incremental set of spacing values** generated by the system:
@@ -116,7 +117,7 @@ Use when you want a **scalable, incremental set of spacing values** generated by
}
}
}
-````
+```
This auto-generates CSS custom properties:
@@ -186,10 +187,10 @@ This outputs `--wp--style--block-gap` and controls gap spacing between child blo
## Expert Recommendations
-* **Use `spacingScale`** for quick, system-generated spacing hierarchy.
-* **Use `spacingSizes`** when you need fine control or fluid units.
-* **Always define slugs consistently** (20, 30…70), not arbitrary labels—editor UI order depends on this order.
-* Avoid mixing both without controlling `defaultSpacingSizes` in theme.json v3.
+- **Use `spacingScale`** for quick, system-generated spacing hierarchy.
+- **Use `spacingSizes`** when you need fine control or fluid units.
+- **Always define slugs consistently** (20, 30…70), not arbitrary labels—editor UI order depends on this order.
+- Avoid mixing both without controlling `defaultSpacingSizes` in theme.json v3.
---
@@ -228,6 +229,7 @@ Here, editors get consistent margin controls via presets, while the scale can be
---
## Reference Links
+
- [WordPress Developer Resources: Everything you need to know about spacing in block themes](https://developer.wordpress.org/news/2023/03/everything-you-need-to-know-about-spacing-in-block-themes)
- [WordPress Developer Resources: Theme Handbook - Global Settings & Styles (theme.json) - Spacing](https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/)
- [Rich Tabor on Standardizing theme.json spacing sizes](https://rich.blog/standardizing-theme-json-spacing/)
diff --git a/block-themes/fluid-typography.md b/docs/wordpress/block-themes/theme.json/fluid-typography.md
similarity index 95%
rename from block-themes/fluid-typography.md
rename to docs/wordpress/block-themes/theme.json/fluid-typography.md
index 9ca70f7..b2066f9 100644
--- a/block-themes/fluid-typography.md
+++ b/docs/wordpress/block-themes/theme.json/fluid-typography.md
@@ -1,10 +1,12 @@
# Fluid Typography
+
Introduces fluid typography techniques for responsive type scaling in block themes, using clamp() and custom properties in theme.json.
---
## Best practices
-- Combine **typographic scale** with `clamp()` in `theme.json` for scalable, responsive typography.
+
+- Combine **typographic scale** with `clamp()` in `theme.json` for scalable, responsive typography.
- Define CSS custom properties in `settings.custom.typography.scale`.
- Generate a dual `scale` and font-size system using `settings.custom.typography.scale`, e.g.:
@@ -22,12 +24,13 @@ Introduces fluid typography techniques for responsive type scaling in block them
```
Apply clamp() in settings.typography.fontSizes for responsive scaling:
+
```json
- {
+{
"name": "Large",
"size": "clamp(var(--wp--custom--typography--small), calc(var(--wp--custom--typography--normal) + 3vw), var(--wp--custom--typography--large))",
"slug": "large"
- }
+}
```
Or use WordPress's built-in fluid support:
@@ -36,15 +39,17 @@ Or use WordPress's built-in fluid support:
"settings": { "typography": { "fluid": true } }
```
- …and define min/max ranges in fontSizes entries.
+…and define min/max ranges in fontSizes entries.
## When to use
+
- You want type to scale smoothly between breakpoints without multiple media queries.
- Your design system defines a base size with proportional steps (e.g. minor third 1.2–1.25).
- You need consistent, predictable min/max sizes across blocks and patterns.
- You are targeting modern browsers where clamp() is supported.
## When to use
+
- You want type to scale smoothly between breakpoints without multiple media queries.
- Your design system defines a base size with proportional steps (e.g. minor third 1.2–1.25).
- You need consistent, predictable min/max sizes across blocks and patterns.
@@ -53,12 +58,14 @@ Or use WordPress's built-in fluid support:
---
## Limitations
+
- Requires well-defined scale; overcomplex logic could hinder maintainability.
- Only px, em, and rem units are supported in fluid typography.
---
## Reference Links
+
- [Rich Tabor: Fluid Type Scale in Block Themes](https://rich.blog/fluid-type-scale-theme-json/)
- [Rich Tabor: Fluid Typography and Block Themes](https://rich.blog/fluid-typography-block-themes/)
diff --git a/block-themes/global-styles.md b/docs/wordpress/block-themes/theme.json/global-styles.md
similarity index 97%
rename from block-themes/global-styles.md
rename to docs/wordpress/block-themes/theme.json/global-styles.md
index 64f88ec..40ac97a 100644
--- a/block-themes/global-styles.md
+++ b/docs/wordpress/block-themes/theme.json/global-styles.md
@@ -1,9 +1,11 @@
# Global Styles and theme.json
+
Describes how to use theme.json for global styles, design tokens, and editor/front-end parity in block themes.
---
## Best Practices
+
- Use `theme.json` as the single source of truth for **site-wide styles** and editor/front-end consistency.
- Treat it as a **design system definition file** (colours, typography, spacing, layout, etc.).
- Define **design tokens** in `settings` (e.g., font sizes, spacing presets, custom line-heights).
@@ -20,6 +22,7 @@ Describes how to use theme.json for global styles, design tokens, and editor/fro
```
## When to use
+
- You want editor/front-end parity without bespoke CSS.
- You’re defining design tokens (colour, spacing, typography scales, line-height presets) for reuse across blocks.
- You need variables available to both theme CSS and block styles.
@@ -27,6 +30,7 @@ Describes how to use theme.json for global styles, design tokens, and editor/fro
- You’re migrating from classic themes and want to reduce reliance on the Customizer and ad-hoc CSS.
## When to use
+
- To establish **editor/front-end parity** without bespoke CSS.
- When defining **global variables** (colour, spacing, typography scales, line-height presets) for use across blocks.
- When migrating from **classic themes** and aiming to reduce reliance on the Customizer or ad-hoc CSS.
@@ -36,6 +40,7 @@ Describes how to use theme.json for global styles, design tokens, and editor/fro
---
## Limitations
+
- Deep customization may still require block-level overrides or PHP-based fallbacks.
- You’ll still need to use CSS (via `.has‑slug‑font‑size`) to apply some conditional logic like matching line height with font size. Class helpers like `.has-slug-font-size` may still be required (e.g. coupling font size and line height).
- Define `custom` variables for use in CSS, such as:
@@ -53,21 +58,21 @@ Describes how to use theme.json for global styles, design tokens, and editor/fro
- Per-breakpoint control is limited; prefer **fluid typography/spacing** over rigid breakpoints.
- Features vary by WP/Gutenberg version; confirm the **minimum supported version** for your theme.
-
---
## Tips for Full Site Editing
-- ***Shift from Templates to Tokens**: Instead of hardcoding layouts, block themes lean on `theme.json` + patterns.
+
+- **\*Shift from Templates to Tokens**: Instead of hardcoding layouts, block themes lean on `theme.json` + patterns.
- **Global Styles as the Backbone**: They serve as the connective tissue between tokens (colours, spacing, typography) and blocks/patterns.
- **Theme.json + Patterns = The Theme**: Rich emphasises that the modern WordPress theme is a combination of `theme.json` (rules/tokens) and block patterns (structure/layout).
- **Style Variations = Skins**: Entirely different looks can be shipped in one theme using variations defined in `theme.json`.
- **Lean, Composable Themes**: Avoid bloated CSS. Define reusable rules in JSON, use patterns to compose layouts, and let site owners customise via Global Styles UI.
- **Future-facing**: Themes are less about delivering static designs and more about providing a **system** users can adapt.
-
---
## Reference Links
+
- [WordPress Developer Resources](https://developer.wordpress.org/block-editor/how-to-guides/themes/global-settings-and-styles/)
- [Rich Tabor: Full Site Editing](https://rich.blog/full-site-editing/)
- [WordPress Developer Resources — Global Settings & Styles](https://developer.wordpress.org/block-editor/how-to-guides/themes/global-settings-and-styles/)
diff --git a/block-themes/naming-conventions.md b/docs/wordpress/block-themes/theme.json/naming-conventions.md
similarity index 91%
rename from block-themes/naming-conventions.md
rename to docs/wordpress/block-themes/theme.json/naming-conventions.md
index 3d1bb06..a791a95 100644
--- a/block-themes/naming-conventions.md
+++ b/docs/wordpress/block-themes/theme.json/naming-conventions.md
@@ -1,18 +1,21 @@
# Naming Conventions
+
Outlines naming conventions block themes to ensure portability and prevent layout issues.
---
## Best practices
-- **Colour slugs**: Standardise colour slugs to generic names like `base`, `contrast`, `primary` to ensure portability between themes.
+
+- **Colour slugs**: Standardise colour slugs to generic names like `base`, `contrast`, `primary` to ensure portability between themes.
- **Font size slugs**: Define consistent font-size slugs such as `small`, `medium`, `large`, `x-large`. Enable fluid typography via `settings.typography.fluid`.
-- **Spacing slugs**: Use numeric spacing slugs (e.g., `20`, `30`, `40`), particularly when using scales or custom sizes.
+- **Spacing slugs**: Use numeric spacing slugs (e.g., `20`, `30`, `40`), particularly when using scales or custom sizes.
---
## Examples
- Inconsistent naming across themes can break layouts and content formatting when switching themes.
+
```json
{
"$schema": "https://schemas.wp.org/wp/6.8/theme.json",
@@ -28,7 +31,7 @@ Outlines naming conventions block themes to ensure portability and prevent layou
},
{
"slug": "contrast",
- "color": "#000000",
+ "color": "#000000",
"name": "Contrast"
},
{
@@ -47,13 +50,13 @@ Outlines naming conventions block themes to ensure portability and prevent layou
"name": "Small"
},
{
- "slug": "medium",
+ "slug": "medium",
"size": "1rem",
"name": "Medium"
},
{
"slug": "large",
- "size": "1.25rem",
+ "size": "1.25rem",
"name": "Large"
},
{
@@ -72,13 +75,13 @@ Outlines naming conventions block themes to ensure portability and prevent layou
},
"spacingSizes": [
{
- "slug": "20",
+ "slug": "20",
"size": "1rem",
"name": "Small"
},
{
"slug": "30",
- "size": "1.5rem",
+ "size": "1.5rem",
"name": "Medium"
},
{
@@ -95,18 +98,21 @@ Outlines naming conventions block themes to ensure portability and prevent layou
---
## When to use
+
- Use colour palettes via `settings.color.palette` to auto-generate CSS variables and `.has-*` classes.
- Use font size presets via `settings.custom.typography.scale`.
- Use spacing presets via `settings.spacing.spacingScale`.
## Limitations
+
- Inconsistent naming leads to layout brokenness when switching themes.
-- Inconsistent naming across themes breaks content formatting when switching themes.
-- Order of `spacingSizes` matters—UI reflects the insertion order.
+- Inconsistent naming across themes breaks content formatting when switching themes.
+- Order of `spacingSizes` matters—UI reflects the insertion order.
---
## Reference Links
+
- [Rich Tabor: Standardizing theme.json spacing sizes](https://rich.blog/standardizing-theme-json-colors/)
---
diff --git a/block-themes/best-practices-best-practices-.md b/docs/wordpress/block-themes/theme.json/section-styles-best-practices.md
similarity index 72%
rename from block-themes/best-practices-best-practices-.md
rename to docs/wordpress/block-themes/theme.json/section-styles-best-practices.md
index cbcb14d..146339c 100644
--- a/block-themes/best-practices-best-practices-.md
+++ b/docs/wordpress/block-themes/theme.json/section-styles-best-practices.md
@@ -2,7 +2,7 @@
## **Introduction to Section Styles**
-**Section Styles** are an extension of WordPress **block style variations** that let you apply a single, reusable design to an entire section of content. In practice, these are custom style variations (e.g. “Hero”, “CTA”, “Card Grid”) registered for container blocks like **Group**, **Columns**, or **Cover**. By toggling a Section Style in the editor, you instantly apply a curated set of colors, typography, spacing, etc., to that container *and its inner blocks*, rather than manually styling each block. This provides a one-click way to restyle a whole section and ensures consistency across repeated layouts[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=Section%20Styles).
+**Section Styles** are an extension of WordPress **block style variations** that let you apply a single, reusable design to an entire section of content. In practice, these are custom style variations (e.g. “Hero”, “CTA”, “Card Grid”) registered for container blocks like **Group**, **Columns**, or **Cover**. By toggling a Section Style in the editor, you instantly apply a curated set of colors, typography, spacing, etc., to that container _and its inner blocks_, rather than manually styling each block. This provides a one-click way to restyle a whole section and ensures consistency across repeated layouts[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=Section%20Styles).
Under the hood, Section Styles are powered by the **theme.json** system introduced in Full Site Editing. WordPress 6.6 massively expanded this system to support nested styling of inner elements and child blocks within a block style variation[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=discovery%20into%20a%20single%20consistent,6). Theme authors can now move many design rules from ad-hoc CSS into a unified JSON schema. In fact, developers have reported cutting “hundreds of lines” of custom CSS by migrating to theme.json for section designs[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=I%20have%20already%20cut%20100s,standardized%20system%20cannot%20be%20understated). Section Styles are most beneficial for **reusable “bands” of content** that appear throughout a site – for example, a hero banner, a features/info row, a card grid of posts, or a call-to-action strip. Defining these as Section Styles means editors can apply a tested, accessible design in one step, and any global updates to that style (in code) will propagate everywhere it’s used.
@@ -10,11 +10,11 @@ Under the hood, Section Styles are powered by the **theme.json** system introduc
Section Styles are defined as **theme.json partial files** in your theme, usually placed under a `/styles` directory. In WordPress 6.6, you can organize this folder by variation type. For example[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=In%20the%20past%2C%20you%20could,typography%20variations%20to%20this%20folder):
-`/styles/`
- `├── block/ ← Section or block-specific style variations`
- `├── color/ ← Color palette variations (new in 6.6)`
- `├── global/ ← Whole-theme style variations`
- `└── typography/ ← Font or typeset variations`
+`/styles/`
+`├── block/ ← Section or block-specific style variations`
+`├── color/ ← Color palette variations (new in 6.6)`
+`├── global/ ← Whole-theme style variations`
+`└── typography/ ← Font or typeset variations`
Section Style files reside in the `block/` (or `section/`) subfolder. Each file defines one variation using a JSON structure. A **recommended naming convention** is to use a clear, purposeful slug for the filename and variation slug. For example, a hero banner style might live in `styles/block/section-hero.json` with slug `"section-hero"`. Use lowercase kebab-case for slugs, and include a concise descriptor of the section’s purpose or context (e.g. `section-hero-dark`, `section-cards-grid`). This makes it easy to identify what each style is for. The JSON file also supports a human-friendly **title** (shown in the editor’s style picker) – by convention, include a word like “Section” or an icon for clarity (e.g. title `"Section · Cards"`).
@@ -22,38 +22,38 @@ Inside the variation JSON, you must specify a `blockTypes` array to declare whic
**File structure tips:** Keep each Section Style in its own JSON file for modularity. Ensure each file includes the required top-level fields:
-* **`$schema`** – points to the WP theme.json schema (matching the WP version, see below).
+- **`$schema`** – points to the WP theme.json schema (matching the WP version, see below).
-* **`version`** – theme.json format version (e.g. `3` for WP 6.6+).
+- **`version`** – theme.json format version (e.g. `3` for WP 6.6+).
-* **`slug`** – unique slug for this style (no spaces, used in class name).
+- **`slug`** – unique slug for this style (no spaces, used in class name).
-* **`title`** – readable title for UI.
+- **`title`** – readable title for UI.
-* **`blockTypes`** – array of block names that can use this style.
+- **`blockTypes`** – array of block names that can use this style.
-* **`styles`** – the actual style rules (same structure as in theme.json).
+- **`styles`** – the actual style rules (same structure as in theme.json).
-Section Style JSON files are automatically loaded by WordPress at theme init – you do *not* need to manually `register_block_style()` for JSON files placed in `/styles/block/` (WP will auto-register any unregistered style variations found in these partials)[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=The%20block%20style%20variations%20that,it%20will%20be%20stripped%20out). However, you can still register styles via PHP if needed – WP 6.6 updated the API so that `register_block_style()` can accept an **array of block types** and a `style_data` array parallel to the JSON structure[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=The%20third%20option%20for%20registering,function%20that%20make%20this%20possible)[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=register_block_style%28%20,%27var%3Apreset%7Ccolor%7Cbase). In general, using JSON files is preferable for clarity and ease of maintenance, keeping all style definitions in theme config.
+Section Style JSON files are automatically loaded by WordPress at theme init – you do _not_ need to manually `register_block_style()` for JSON files placed in `/styles/block/` (WP will auto-register any unregistered style variations found in these partials)[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=The%20block%20style%20variations%20that,it%20will%20be%20stripped%20out). However, you can still register styles via PHP if needed – WP 6.6 updated the API so that `register_block_style()` can accept an **array of block types** and a `style_data` array parallel to the JSON structure[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=The%20third%20option%20for%20registering,function%20that%20make%20this%20possible)[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=register_block_style%28%20,%27var%3Apreset%7Ccolor%7Cbase). In general, using JSON files is preferable for clarity and ease of maintenance, keeping all style definitions in theme config.
## **Schema and Tokens in Theme.JSON**
When creating Section Styles, use the **theme.json Version 3 schema** (introduced in WP 6.6). At the top of each file, set the `$schema` URL to the latest schema – for example:
`{`
- `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
- `"version": 3,`
- `…`
+ `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
+ `"version": 3,`
+ `…`
`}`
This ensures your editor or validator knows about the new properties available. Version 3 supports nested styling of elements and blocks, which is critical for Section Styles. Under the `"styles"` object, you can include keys like `"elements"` or `"blocks"` to target inner content. For instance, you might style all links inside the section, or tweak specific blocks (headings, buttons, etc.) when they appear within the styled container. We’ll see examples of this in the next section.
-It’s best practice to rely on **Global Style tokens** (presets) for all values instead of hard-coding colors, font sizes, etc. Theme.json provides a special syntax to reference preset values: **`var:preset|category|slug`](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/#:~:text=To%20reference%20presets%20in%20,base)**[[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/#:~:text=To%20reference%20presets%20in%20,base). For example, to apply the theme’s primary color you’d use `"color": "var:preset|color|primary"` in JSON, or for a spacing size token `"padding": "var:preset|spacing|60"`[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=,right). These tokens resolve to the CSS custom properties (`--wp--preset----`) output by WordPress[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/#:~:text=For%20example%2C%20when%20you%20learned,size%E2%80%93%7B%24slug)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/#:~:text=body%20%7B%20,primary%3A%20%2389cff0%3B). By using `var:preset|*` references, your Section Styles will automatically reflect any changes to the preset palettes and will match what users see in design tools. In short, *avoid raw hex codes or pixel values* in theme.json – use your theme’s design tokens instead. The only time you might use a raw value is if a very unique design element isn’t covered by a token, but even then consider adding a custom preset.
+It’s best practice to rely on **Global Style tokens** (presets) for all values instead of hard-coding colors, font sizes, etc. Theme.json provides a special syntax to reference preset values: **`var:preset|category|slug`](](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/#:~:text=To%20reference%20presets%20in%20,base). For example, to apply the theme’s primary color you’d use `"color": "var:preset|color|primary"` in JSON, or for a spacing size token `"padding": "var:preset|spacing|60"`[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=,right). These tokens resolve to the CSS custom properties (`--wp--preset----`) output by WordPress[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/#:~:text=For%20example%2C%20when%20you%20learned,size%E2%80%93%7B%24slug)[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/#:~:text=body%20%7B%20,primary%3A%20%2389cff0%3B). By using `var:preset|*` references, your Section Styles will automatically reflect any changes to the preset palettes and will match what users see in design tools. In short, _avoid raw hex codes or pixel values_ in theme.json – use your theme’s design tokens instead. The only time you might use a raw value is if a very unique design element isn’t covered by a token, but even then consider adding a custom preset.
The theme.json v3 schema supports nested targets like pseudo-classes on links. For example, you can define styles for `elements.link:hover` or `elements.link:focus` within your variation[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=,%7D). These let you customise link hover/focus states purely in JSON. (Currently only links have pseudo-class support in theme.json; for other hover effects, see limitations below.) You can also target specific inner blocks by name under `styles.blocks`. For example, you could adjust the heading block:
`"blocks": {`
- `"core/heading": { "...": "..." }`
+ `"core/heading": { "...": "..." }`
`}`
inside your Section Style to fine-tune headings when used in that section[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=%22blocks%22%3A%20%7B%20%22core%2Fpost,%7D%20%7D). This nested schema approach is powerful – it means your JSON can mimic CSS selectors like `.is-style-mysection h2 { ... }` without writing actual CSS. The theme.json processor will merge these styles into the generated stylesheet with proper specificity.
@@ -64,21 +64,21 @@ inside your Section Style to fine-tune headings when used in that section[develo
While Section Styles greatly expand what’s possible in theme.json, there are some **known limitations in WordPress 6.6** to be aware of[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=The%20following%20limitations%20for%20block,6%20should%20be%20noted):
-* **Global Styles UI:** Only *root-level* style properties of a variation can be tweaked through the Site Editor’s Styles panel[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=1,previewed%20within%20the%20Style%20Book). If your Section Style sets an inner block rule (e.g. a heading color), that inner style won’t appear as an adjustable option in Global Styles – those controls only reflect the global defaults. In short, Section Styles can be *applied* by editors, but not finely edited via UI in 6.6. The entire variation is treated as a predefined package of styles.
+- **Global Styles UI:** Only _root-level_ style properties of a variation can be tweaked through the Site Editor’s Styles panel[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=1,previewed%20within%20the%20Style%20Book). If your Section Style sets an inner block rule (e.g. a heading color), that inner style won’t appear as an adjustable option in Global Styles – those controls only reflect the global defaults. In short, Section Styles can be _applied_ by editors, but not finely edited via UI in 6.6. The entire variation is treated as a predefined package of styles.
-* **Style Book Preview:** Currently, custom block style variations do **not show in the Style Book**[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=%28yet%29,previewed%20within%20the%20Style%20Book). The Style Book (which previews blocks with global styles) doesn’t render your Section Styles for inspection. Users must apply the style on a real page/post to see its effect. This is planned to improve in future releases[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=What%E2%80%99s%20Next%3F)[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=The%20Global%20Styles%20UI%20UI,to%20support%20block%20style%20variations).
+- **Style Book Preview:** Currently, custom block style variations do **not show in the Style Book**[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=%28yet%29,previewed%20within%20the%20Style%20Book). The Style Book (which previews blocks with global styles) doesn’t render your Section Styles for inspection. Users must apply the style on a real page/post to see its effect. This is planned to improve in future releases[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=What%E2%80%99s%20Next%3F)[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=The%20Global%20Styles%20UI%20UI,to%20support%20block%20style%20variations).
-* **No Variation-Specific Settings:** Section Styles cannot define their own `settings` (e.g. custom presets unique to that style) – only `styles`. The theme.json `settings` are global for the theme or per-block, not per style variation[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=2,values%20%28yet). For example, you can’t have a variation that introduces a new color palette just for that style.
+- **No Variation-Specific Settings:** Section Styles cannot define their own `settings` (e.g. custom presets unique to that style) – only `styles`. The theme.json `settings` are global for the theme or per-block, not per style variation[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=2,values%20%28yet). For example, you can’t have a variation that introduces a new color palette just for that style.
-* **No Inheritance of Inner Variations:** A Section Style can style inner blocks, but it **cannot activate a style variation on a child block**. For instance, you could not make a Section Style that automatically applies a Button block’s “outline” style to inner buttons – style variations don’t nest within each other. You also can’t create a Section Style that *conditionally* applies different styles to different inner blocks beyond what you declare in JSON. Each variation is a fixed JSON bundle.
+- **No Inheritance of Inner Variations:** A Section Style can style inner blocks, but it **cannot activate a style variation on a child block**. For instance, you could not make a Section Style that automatically applies a Button block’s “outline” style to inner buttons – style variations don’t nest within each other. You also can’t create a Section Style that _conditionally_ applies different styles to different inner blocks beyond what you declare in JSON. Each variation is a fixed JSON bundle.
-* **CSS Specificity and Overrides:** WordPress 6.6 introduced a **uniform specificity** for global styles (selectors now typically carry a specificity of 0-1-0)[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=discovery%20into%20a%20single%20consistent,6). This means a Section Style and a regular block style rule often have the same weight, so the cascade order or last-in stylesheet order determines which wins when nested. Notably, if an editor manually customizes a block’s style (through block settings), those inline styles or additional classes will override the Section Style in most cases – this is by design[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=This%20is%20the%20intended%20behaviour). For example, if a user sets a heading to have a blue color via the editor, and your Section Style makes headings green, the user’s choice will prevail because it’s a more specific or later-loaded rule. Section Styles are meant to provide smart defaults, but **user adjustments override them** (just as Global Styles do).
+- **CSS Specificity and Overrides:** WordPress 6.6 introduced a **uniform specificity** for global styles (selectors now typically carry a specificity of 0-1-0)[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=discovery%20into%20a%20single%20consistent,6). This means a Section Style and a regular block style rule often have the same weight, so the cascade order or last-in stylesheet order determines which wins when nested. Notably, if an editor manually customizes a block’s style (through block settings), those inline styles or additional classes will override the Section Style in most cases – this is by design[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=This%20is%20the%20intended%20behaviour). For example, if a user sets a heading to have a blue color via the editor, and your Section Style makes headings green, the user’s choice will prevail because it’s a more specific or later-loaded rule. Section Styles are meant to provide smart defaults, but **user adjustments override them** (just as Global Styles do).
-* **No Media Queries or Conditional Logic:** Theme.json (and thus Section Styles) cannot handle responsive breakpoints or stateful logic. You can use CSS tricks like fluid units (and WP’s fluid presets for font/spacing) for responsiveness, but you can’t, for instance, change a layout at a specific breakpoint via theme.json alone. Likewise, you can’t target states like `:first-child` or parent selectors – the JSON schema doesn’t allow those. Any such needs require custom CSS (possibly inserted via the `styles.css` hook in theme.json – see next section – or a stylesheet).
+- **No Media Queries or Conditional Logic:** Theme.json (and thus Section Styles) cannot handle responsive breakpoints or stateful logic. You can use CSS tricks like fluid units (and WP’s fluid presets for font/spacing) for responsiveness, but you can’t, for instance, change a layout at a specific breakpoint via theme.json alone. Likewise, you can’t target states like `:first-child` or parent selectors – the JSON schema doesn’t allow those. Any such needs require custom CSS (possibly inserted via the `styles.css` hook in theme.json – see next section – or a stylesheet).
-* **Limited Hover and Interactivity:** Aside from link hover/focus styling, theme.json currently doesn’t support most pseudo-classes. For example, you can’t define how a button’s background should change on hover using theme.json alone. Similarly, any design that relies on dynamic behavior (e.g. toggling classes with JS) is outside theme.json’s static scope. This means some interactive styling (menus on hover, etc.) still needs CSS in your theme. WordPress is working on exposing more in JSON, but for now these are constraints.
+- **Limited Hover and Interactivity:** Aside from link hover/focus styling, theme.json currently doesn’t support most pseudo-classes. For example, you can’t define how a button’s background should change on hover using theme.json alone. Similarly, any design that relies on dynamic behavior (e.g. toggling classes with JS) is outside theme.json’s static scope. This means some interactive styling (menus on hover, etc.) still needs CSS in your theme. WordPress is working on exposing more in JSON, but for now these are constraints.
-* **Block Support Gaps:** Not all blocks expose all their styling via Global Styles yet. A notable example discussed is the **Pagination** block – it had limited support for styling its elements in 6.6. If your Section Style involves a block that isn’t fully supported (e.g. styling the appearance of the page number links or hover state in Pagination), you may need to supplement with custom CSS. Always test your Section Styles with the blocks in question to see if any part of the design isn’t applied, and check Gutenberg release notes for ongoing improvements.
+- **Block Support Gaps:** Not all blocks expose all their styling via Global Styles yet. A notable example discussed is the **Pagination** block – it had limited support for styling its elements in 6.6. If your Section Style involves a block that isn’t fully supported (e.g. styling the appearance of the page number links or hover state in Pagination), you may need to supplement with custom CSS. Always test your Section Styles with the blocks in question to see if any part of the design isn’t applied, and check Gutenberg release notes for ongoing improvements.
Keep these limitations in mind when designing Section Styles, so you don’t get caught off guard. Most are expected to be addressed in upcoming WordPress versions[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=What%E2%80%99s%20Next%3F). For now, design within these boundaries to ensure consistent results.
@@ -86,15 +86,15 @@ Keep these limitations in mind when designing Section Styles, so you don’t get
With multiple Section Styles and global styles at play, you may occasionally hit conflicts or specificity issues. Here’s how to manage and avoid them:
-* **Understand Cascade Priority:** As noted, a user’s direct block style settings override Section Styles, and Section Styles override global defaults. This is the intended hierarchy[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=This%20is%20the%20intended%20behaviour). So if a Section Style isn’t “working,” first check if an inline style or class from the editor is taking precedence. For example, if the user set a different font size on a heading block, that will override your variation’s typography for that heading.
+- **Understand Cascade Priority:** As noted, a user’s direct block style settings override Section Styles, and Section Styles override global defaults. This is the intended hierarchy[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=This%20is%20the%20intended%20behaviour). So if a Section Style isn’t “working,” first check if an inline style or class from the editor is taking precedence. For example, if the user set a different font size on a heading block, that will override your variation’s typography for that heading.
-* **Avoid Nesting Section Styles if Possible:** Technically you can nest a styled Group within another styled Group (each with different Section Styles). Thanks to the reduced specificity in 6.6, this *can* work, but if both variations target some of the same inner elements, you might see cascade conflicts (whichever style is applied to the inner block last in the stylesheet will win). If you must nest, ensure your inner variation redefines any crucial styles. For instance, if a parent section makes all headings blue, and an inner section style wants them red, you should explicitly set the inner heading color in the inner variation’s JSON (under `styles.blocks.core/heading`) to override the inherited blue. In general, **don’t stack section variations on the same block** – use them on distinct containers.
+- **Avoid Nesting Section Styles if Possible:** Technically you can nest a styled Group within another styled Group (each with different Section Styles). Thanks to the reduced specificity in 6.6, this _can_ work, but if both variations target some of the same inner elements, you might see cascade conflicts (whichever style is applied to the inner block last in the stylesheet will win). If you must nest, ensure your inner variation redefines any crucial styles. For instance, if a parent section makes all headings blue, and an inner section style wants them red, you should explicitly set the inner heading color in the inner variation’s JSON (under `styles.blocks.core/heading`) to override the inherited blue. In general, **don’t stack section variations on the same block** – use them on distinct containers.
-* **Scope Styles to Specific Elements:** A good practice is to keep broad styles (background, overall text color) at the root of the Section Style, but move more granular typography or spacing rules into targeted inner selectors. For example, instead of making *all* text in a section 18px, perhaps target just headings or paragraphs specifically. This way, if another section is nested, you have more control. It also prevents unintended inheritance. In other words, **target what you mean to style** as deeply as needed, rather than applying one size/color to all elements globally and then fighting to override it in sub-sections.
+- **Scope Styles to Specific Elements:** A good practice is to keep broad styles (background, overall text color) at the root of the Section Style, but move more granular typography or spacing rules into targeted inner selectors. For example, instead of making _all_ text in a section 18px, perhaps target just headings or paragraphs specifically. This way, if another section is nested, you have more control. It also prevents unintended inheritance. In other words, **target what you mean to style** as deeply as needed, rather than applying one size/color to all elements globally and then fighting to override it in sub-sections.
-* **Use the CSS Escape Hatch Sparingly:** WordPress allows adding custom CSS in theme.json via a `"css"` property (per block or per section)[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=You%20add%20custom%20styles%20by,generate%20that%20for%20the%20block)[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=%7B%20,spacing%3A%201px%3B%22%20%7D). In a Section Style JSON, you can include `"css": "& .your-selector { ... }"` to append extra rules. This is useful for edge cases (e.g. targeting a particular child element or using a pseudo-class not supported by schema). The `&` will be replaced by the section’s class (e.g. `.wp-block-group.is-style-section-hero`) when generated[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=Using%20the%20%26%20selector%20and,brackets)[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=block,a%20custom%20block%20style%20variation). If you use this, keep it minimal – *don’t* overload it with large chunks of CSS. And remember such CSS won’t be editable via Global Styles. Use it only when the JSON format truly cannot achieve the needed effect.
+- **Use the CSS Escape Hatch Sparingly:** WordPress allows adding custom CSS in theme.json via a `"css"` property (per block or per section)[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=You%20add%20custom%20styles%20by,generate%20that%20for%20the%20block)[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=%7B%20,spacing%3A%201px%3B%22%20%7D). In a Section Style JSON, you can include `"css": "& .your-selector { ... }"` to append extra rules. This is useful for edge cases (e.g. targeting a particular child element or using a pseudo-class not supported by schema). The `&` will be replaced by the section’s class (e.g. `.wp-block-group.is-style-section-hero`) when generated[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=Using%20the%20%26%20selector%20and,brackets)[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=block,a%20custom%20block%20style%20variation). If you use this, keep it minimal – _don’t_ overload it with large chunks of CSS. And remember such CSS won’t be editable via Global Styles. Use it only when the JSON format truly cannot achieve the needed effect.
-* **Prefer JSON Solutions:** As a rule, if something *can* be done within the theme.json schema, do it that way rather than writing custom CSS. This ensures consistency and that the styles show up in the editor UI. For example, setting padding via JSON means it’s reflected in the editor canvas and can be tweaked by design tools, whereas a manual CSS rule might not. Justin Tadlock, a core developer, noted: *“If it can be done via JSON, it usually should be… things like border, color, shadow, spacing, and typography are all easily portable to JSON… only use block stylesheets for things not part of the standard design tools.”*[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=Absolutely,to%20JSON%20from%20block%20stylesheets) In practice, this means leveraging presets, `elements`, and `blocks` keys in JSON to resolve conflicts (by increasing specificity in JSON) before reaching for `!important` or additional CSS.
+- **Prefer JSON Solutions:** As a rule, if something _can_ be done within the theme.json schema, do it that way rather than writing custom CSS. This ensures consistency and that the styles show up in the editor UI. For example, setting padding via JSON means it’s reflected in the editor canvas and can be tweaked by design tools, whereas a manual CSS rule might not. Justin Tadlock, a core developer, noted: _“If it can be done via JSON, it usually should be… things like border, color, shadow, spacing, and typography are all easily portable to JSON… only use block stylesheets for things not part of the standard design tools.”_[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=Absolutely,to%20JSON%20from%20block%20stylesheets) In practice, this means leveraging presets, `elements`, and `blocks` keys in JSON to resolve conflicts (by increasing specificity in JSON) before reaching for `!important` or additional CSS.
**Debugging tip:** To troubleshoot a Section Style, use your browser’s inspector to see which CSS rules are affecting the element in question. Because WP outputs styles in a certain order (global styles, then global user customizations, then section style CSS, then block-specific user customizations, etc.), checking the order will show what’s winning. If your section JSON rule is getting overridden by a later rule, you might need to adjust by targeting a more specific element (as above) or accept that the user’s own style is intended to override it.
@@ -105,223 +105,223 @@ Let’s look at some concrete examples of Section Styles in JSON. Below are four
**1\. Hero Section (Dark Hero)** – A full-width hero banner with a dark background and prominent text. Typically used for the top section of a page.
`{`
- `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
- `"version": 3,`
- `"slug": "section-hero",`
- `"title": "Section · Hero",`
- `"blockTypes": [ "core/group", "core/cover" ],`
- `"styles": {`
- `"color": {`
- `"background": "var:preset|color|contrast", /* dark background (e.g. black) */`
- `"text": "var:preset|color|base" /* light text (e.g. white) */`
- `},`
- `"typography": {`
- `"fontSize": "var:preset|font-size|x-large", /* base font size for section */`
- `"lineHeight": "1.3"`
- `},`
- `"spacing": {`
- `"padding": {`
- `"top": "var:preset|spacing|70",`
- `"bottom": "var:preset|spacing|70",`
- `"left": "var:preset|spacing|30",`
- `"right": "var:preset|spacing|30"`
- `}`
- `},`
- `"elements": {`
- `"link": {`
- `"color": {`
- `"text": "var:preset|color|base"`
- `},`
- `"typography": {`
- `"textDecoration": "underline"`
- `},`
- `":hover": {`
- `"typography": {`
- `"textDecoration": "none"`
- `}`
- `}`
- `}`
- `},`
- `"blocks": {`
- `"core/heading": {`
- `"typography": {`
- `"fontSize": "var:preset|font-size|xx-large",`
- `"fontWeight": "700"`
- `},`
- `"color": {`
- `"text": "var:preset|color|base"`
- `},`
- `"spacing": {`
- `"margin": {`
- `"bottom": "var:preset|spacing|20"`
- `}`
- `}`
- `}`
- `}`
- `}`
+ `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
+ `"version": 3,`
+ `"slug": "section-hero",`
+ `"title": "Section · Hero",`
+ `"blockTypes": [ "core/group", "core/cover" ],`
+ `"styles": {`
+ `"color": {`
+ `"background": "var:preset|color|contrast", /* dark background (e.g. black) */`
+ `"text": "var:preset|color|base" /* light text (e.g. white) */`
+ `},`
+ `"typography": {`
+ `"fontSize": "var:preset|font-size|x-large", /* base font size for section */`
+ `"lineHeight": "1.3"`
+ `},`
+ `"spacing": {`
+ `"padding": {`
+ `"top": "var:preset|spacing|70",`
+ `"bottom": "var:preset|spacing|70",`
+ `"left": "var:preset|spacing|30",`
+ `"right": "var:preset|spacing|30"`
+ `}`
+ `},`
+ `"elements": {`
+ `"link": {`
+ `"color": {`
+ `"text": "var:preset|color|base"`
+ `},`
+ `"typography": {`
+ `"textDecoration": "underline"`
+ `},`
+ `":hover": {`
+ `"typography": {`
+ `"textDecoration": "none"`
+ `}`
+ `}`
+ `}`
+ `},`
+ `"blocks": {`
+ `"core/heading": {`
+ `"typography": {`
+ `"fontSize": "var:preset|font-size|xx-large",`
+ `"fontWeight": "700"`
+ `},`
+ `"color": {`
+ `"text": "var:preset|color|base"`
+ `},`
+ `"spacing": {`
+ `"margin": {`
+ `"bottom": "var:preset|spacing|20"`
+ `}`
+ `}`
+ `}`
+ `}`
+ `}`
`}`
-*About this style:* The Hero section uses the theme’s **“contrast” color** for a dark background and **“base” color** for text (assuming those presets are something like black and white)[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=,%7D%20%7D). It adds generous padding (`spacing.padding` presets) to top and bottom for a spacious feel. All headings (`core/heading`) inside are made extra large, bold, and also colored base (ensuring they appear in light text on the dark background). We also used `elements.link` to style links in the hero: here we make links the same light color and underline them by default, removing the underline on hover (to highlight that interactivity). If the hero is implemented with a Cover block, this style will still apply (we included core/cover in blockTypes). Note no custom `css` was needed – everything is handled via theme.json keys.
+_About this style:_ The Hero section uses the theme’s **“contrast” color** for a dark background and **“base” color** for text (assuming those presets are something like black and white)[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=,%7D%20%7D). It adds generous padding (`spacing.padding` presets) to top and bottom for a spacious feel. All headings (`core/heading`) inside are made extra large, bold, and also colored base (ensuring they appear in light text on the dark background). We also used `elements.link` to style links in the hero: here we make links the same light color and underline them by default, removing the underline on hover (to highlight that interactivity). If the hero is implemented with a Cover block, this style will still apply (we included core/cover in blockTypes). Note no custom `css` was needed – everything is handled via theme.json keys.
**2\. Card Grid Section** – A section for a grid of “card” items, e.g. a posts grid or features grid. Typically implemented with a Columns block containing multiple Column blocks, each acting as a card.
`{`
- `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
- `"version": 3,`
- `"slug": "section-cards",`
- `"title": "Section · Cards",`
- `"blockTypes": [ "core/group", "core/columns" ],`
- `"styles": {`
- `"color": {`
- `"background": "var:preset|color|surface", /* neutral light background for cards section */`
- `"text": "var:preset|color|contrast" /* use default text color (e.g. dark) */`
- `},`
- `"elements": {`
- `"link": {`
- `"color": {`
- `"text": "var:preset|color|primary" /* links in cards use primary brand color */`
- `},`
- `"typography": {`
- `"textDecoration": "none"`
- `}`
- `}`
- `},`
- `"blocks": {`
- `"core/heading": {`
- `"typography": {`
- `"fontSize": "var:preset|font-size|large",`
- `"fontWeight": "600"`
- `},`
- `"spacing": {`
- `"margin": {`
- `"top": "0",`
- `"bottom": "var:preset|spacing|20"`
- `}`
- `}`
- `},`
- `"core/paragraph": {`
- `"typography": {`
- `"fontSize": "var:preset|font-size|medium"`
- `},`
- `"spacing": {`
- `"margin": {`
- `"bottom": "var:preset|spacing|20"`
- `}`
- `}`
- `}`
- `},`
- `"css": "& .wp-block-post-terms__separator { display: none; }"`
- `}`
+ `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
+ `"version": 3,`
+ `"slug": "section-cards",`
+ `"title": "Section · Cards",`
+ `"blockTypes": [ "core/group", "core/columns" ],`
+ `"styles": {`
+ `"color": {`
+ `"background": "var:preset|color|surface", /* neutral light background for cards section */`
+ `"text": "var:preset|color|contrast" /* use default text color (e.g. dark) */`
+ `},`
+ `"elements": {`
+ `"link": {`
+ `"color": {`
+ `"text": "var:preset|color|primary" /* links in cards use primary brand color */`
+ `},`
+ `"typography": {`
+ `"textDecoration": "none"`
+ `}`
+ `}`
+ `},`
+ `"blocks": {`
+ `"core/heading": {`
+ `"typography": {`
+ `"fontSize": "var:preset|font-size|large",`
+ `"fontWeight": "600"`
+ `},`
+ `"spacing": {`
+ `"margin": {`
+ `"top": "0",`
+ `"bottom": "var:preset|spacing|20"`
+ `}`
+ `}`
+ `},`
+ `"core/paragraph": {`
+ `"typography": {`
+ `"fontSize": "var:preset|font-size|medium"`
+ `},`
+ `"spacing": {`
+ `"margin": {`
+ `"bottom": "var:preset|spacing|20"`
+ `}`
+ `}`
+ `}`
+ `},`
+ `"css": "& .wp-block-post-terms__separator { display: none; }"`
+ `}`
`}`
-*About this style:* The Cards section is scoped to Groups or Columns that serve as a container for a grid of items. It sets a **“surface” color** for the background (presumably a light gray or off-white) to distinguish the section from a plain white page background. Text remains the default contrast (dark) color for readability. We styled links within this section to use the theme’s **primary color** and removed underlines (since links might be buttons or titles of cards). We targeted headings and paragraphs inside the cards to adjust their size and spacing – headings get a larger font and a bottom margin, paragraphs get a medium font size. These ensure consistent typography in each card. Lastly, we demonstrate a `css` override: this example hides the separator character in a Post Terms block (which might be used to list categories on a post card). We used the `& .wp-block-post-terms__separator` selector to target that element inside this section. This is a niche tweak (removing the decorative separator), included to show how to handle something not available via standard JSON properties. In most cases, you might not need custom CSS in a cards section, but it’s there if needed.
+_About this style:_ The Cards section is scoped to Groups or Columns that serve as a container for a grid of items. It sets a **“surface” color** for the background (presumably a light gray or off-white) to distinguish the section from a plain white page background. Text remains the default contrast (dark) color for readability. We styled links within this section to use the theme’s **primary color** and removed underlines (since links might be buttons or titles of cards). We targeted headings and paragraphs inside the cards to adjust their size and spacing – headings get a larger font and a bottom margin, paragraphs get a medium font size. These ensure consistent typography in each card. Lastly, we demonstrate a `css` override: this example hides the separator character in a Post Terms block (which might be used to list categories on a post card). We used the `& .wp-block-post-terms__separator` selector to target that element inside this section. This is a niche tweak (removing the decorative separator), included to show how to handle something not available via standard JSON properties. In most cases, you might not need custom CSS in a cards section, but it’s there if needed.
**3\. Info Row Section** – A horizontal info bar or feature list, often used to highlight key points (e.g. stats, USPs). Could be a single Group with inner paragraphs or a Columns block with each column containing an icon and text.
`{`
- `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
- `"version": 3,`
- `"slug": "section-info-row",`
- `"title": "Section · Info Row",`
- `"blockTypes": [ "core/group", "core/columns" ],`
- `"styles": {`
- `"color": {`
- `"background": "var:preset|color|accent-2", /* a subtle accent background */`
- `"text": "var:preset|color|contrast" /* standard text color */`
- `},`
- `"spacing": {`
- `"padding": {`
- `"top": "var:preset|spacing|40",`
- `"bottom": "var:preset|spacing|40",`
- `"left": "var:preset|spacing|20",`
- `"right": "var:preset|spacing|20"`
- `}`
- `},`
- `"blocks": {`
- `"core/heading": {`
- `"typography": {`
- `"fontSize": "var:preset|font-size|medium",`
- `"fontWeight": "600"`
- `},`
- `"spacing": {`
- `"margin": {`
- `"bottom": "var:preset|spacing|10"`
- `}`
- `}`
- `},`
- `"core/paragraph": {`
- `"typography": {`
- `"fontSize": "var:preset|font-size|small"`
- `}`
- `}`
- `}`
- `}`
+ `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
+ `"version": 3,`
+ `"slug": "section-info-row",`
+ `"title": "Section · Info Row",`
+ `"blockTypes": [ "core/group", "core/columns" ],`
+ `"styles": {`
+ `"color": {`
+ `"background": "var:preset|color|accent-2", /* a subtle accent background */`
+ `"text": "var:preset|color|contrast" /* standard text color */`
+ `},`
+ `"spacing": {`
+ `"padding": {`
+ `"top": "var:preset|spacing|40",`
+ `"bottom": "var:preset|spacing|40",`
+ `"left": "var:preset|spacing|20",`
+ `"right": "var:preset|spacing|20"`
+ `}`
+ `},`
+ `"blocks": {`
+ `"core/heading": {`
+ `"typography": {`
+ `"fontSize": "var:preset|font-size|medium",`
+ `"fontWeight": "600"`
+ `},`
+ `"spacing": {`
+ `"margin": {`
+ `"bottom": "var:preset|spacing|10"`
+ `}`
+ `}`
+ `},`
+ `"core/paragraph": {`
+ `"typography": {`
+ `"fontSize": "var:preset|font-size|small"`
+ `}`
+ `}`
+ `}`
+ `}`
`}`
-*About this style:* The Info Row section uses an **accent color** (perhaps a light tinted background) to set it apart from plain content. We’ve added moderate padding so it has some vertical separation. Inside, we assume an info item might have a heading (for a stat or feature title) and a paragraph (for a description). The heading is styled to be slightly bolder and larger than normal text, but smaller than a typical heading (since info stats are often a bit more subtle). The paragraph is set to a small font size. These help multiple info items in a row appear uniform. If the info row uses Icons or other blocks, additional styling could be added (e.g. targeting `core/image` for icon images to set a max-width), but for brevity we haven’t included that here. There is no custom CSS needed in this example – it’s purely using tokens and basic properties.
+_About this style:_ The Info Row section uses an **accent color** (perhaps a light tinted background) to set it apart from plain content. We’ve added moderate padding so it has some vertical separation. Inside, we assume an info item might have a heading (for a stat or feature title) and a paragraph (for a description). The heading is styled to be slightly bolder and larger than normal text, but smaller than a typical heading (since info stats are often a bit more subtle). The paragraph is set to a small font size. These help multiple info items in a row appear uniform. If the info row uses Icons or other blocks, additional styling could be added (e.g. targeting `core/image` for icon images to set a max-width), but for brevity we haven’t included that here. There is no custom CSS needed in this example – it’s purely using tokens and basic properties.
**4\. Call-To-Action Section** – A banner or strip intended to draw user attention and prompt an action (like signing up or contacting sales). Often has a short line of text and a button.
`{`
- `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
- `"version": 3,`
- `"slug": "section-cta",`
- `"title": "Section · Call To Action",`
- `"blockTypes": [ "core/group", "core/cover" ],`
- `"styles": {`
- `"color": {`
- `"background": "var:preset|color|primary", /* brand primary color background */`
- `"text": "var:preset|color|base" /* light text for contrast */`
- `},`
- `"spacing": {`
- `"padding": {`
- `"top": "var:preset|spacing|50",`
- `"bottom": "var:preset|spacing|50",`
- `"left": "var:preset|spacing|30",`
- `"right": "var:preset|spacing|30"`
- `}`
- `},`
- `"elements": {`
- `"link": {`
- `"color": {`
- `"text": "var:preset|color|base"`
- `},`
- `"typography": {`
- `"textDecoration": "underline"`
- `},`
- `":hover": {`
- `"typography": {`
- `"textDecoration": "none"`
- `}`
- `}`
- `}`
- `},`
- `"blocks": {`
- `"core/heading": {`
- `"typography": {`
- `"fontSize": "var:preset|font-size|large",`
- `"fontStyle": "italic"`
- `}`
- `},`
- `"core/button": {`
- `"color": {`
- `"background": "var:preset|color|base", /* white button */`
- `"text": "var:preset|color|primary" /* text in button matches section bg */`
- `},`
- `"border": {`
- `"radius": "4px"`
- `},`
- `"spacing": {`
- `"padding": {`
- `"top": "0.5em", "bottom": "0.5em", "left": "1.5em", "right": "1.5em"`
- `}`
- `}`
- `}`
- `}`
- `}`
+ `"$schema": "https://schemas.wp.org/wp/6.6/theme.json",`
+ `"version": 3,`
+ `"slug": "section-cta",`
+ `"title": "Section · Call To Action",`
+ `"blockTypes": [ "core/group", "core/cover" ],`
+ `"styles": {`
+ `"color": {`
+ `"background": "var:preset|color|primary", /* brand primary color background */`
+ `"text": "var:preset|color|base" /* light text for contrast */`
+ `},`
+ `"spacing": {`
+ `"padding": {`
+ `"top": "var:preset|spacing|50",`
+ `"bottom": "var:preset|spacing|50",`
+ `"left": "var:preset|spacing|30",`
+ `"right": "var:preset|spacing|30"`
+ `}`
+ `},`
+ `"elements": {`
+ `"link": {`
+ `"color": {`
+ `"text": "var:preset|color|base"`
+ `},`
+ `"typography": {`
+ `"textDecoration": "underline"`
+ `},`
+ `":hover": {`
+ `"typography": {`
+ `"textDecoration": "none"`
+ `}`
+ `}`
+ `}`
+ `},`
+ `"blocks": {`
+ `"core/heading": {`
+ `"typography": {`
+ `"fontSize": "var:preset|font-size|large",`
+ `"fontStyle": "italic"`
+ `}`
+ `},`
+ `"core/button": {`
+ `"color": {`
+ `"background": "var:preset|color|base", /* white button */`
+ `"text": "var:preset|color|primary" /* text in button matches section bg */`
+ `},`
+ `"border": {`
+ `"radius": "4px"`
+ `},`
+ `"spacing": {`
+ `"padding": {`
+ `"top": "0.5em", "bottom": "0.5em", "left": "1.5em", "right": "1.5em"`
+ `}`
+ `}`
+ `}`
+ `}`
+ `}`
`}`
-*About this style:* The CTA section uses the theme’s **primary brand color** as a bold background, with white (base) text for maximum contrast. We gave it generous padding so it stands out as a separate band. For any links in the text, we styled them to appear as standard underlined links in white (and removing underline on hover) – for instance, if the CTA text says *“Learn more about our services”* and “Learn more” is a link, it will be underlined. The assumption, though, is a CTA will have a Button block for the main action. We included a rule for `core/button` to style the button with a white background and primary-colored text (an “inverted” style that complements the section). We also added a small border radius and some padding to give the button a custom look. All of this is done in JSON. Note: the Button block’s default style might differ, but by specifying these under the Section Style, we ensure that whenever a Button is placed inside a Group/Cover with `section-cta` style, it adopts this inverted color scheme. (If the user applies a different button style or color manually, that will override our settings – which is fine.) No extra CSS was needed; hover states for the button background aren’t covered here due to theme.json limitations, but the button will at least match the section style.
+_About this style:_ The CTA section uses the theme’s **primary brand color** as a bold background, with white (base) text for maximum contrast. We gave it generous padding so it stands out as a separate band. For any links in the text, we styled them to appear as standard underlined links in white (and removing underline on hover) – for instance, if the CTA text says _“Learn more about our services”_ and “Learn more” is a link, it will be underlined. The assumption, though, is a CTA will have a Button block for the main action. We included a rule for `core/button` to style the button with a white background and primary-colored text (an “inverted” style that complements the section). We also added a small border radius and some padding to give the button a custom look. All of this is done in JSON. Note: the Button block’s default style might differ, but by specifying these under the Section Style, we ensure that whenever a Button is placed inside a Group/Cover with `section-cta` style, it adopts this inverted color scheme. (If the user applies a different button style or color manually, that will override our settings – which is fine.) No extra CSS was needed; hover states for the button background aren’t covered here due to theme.json limitations, but the button will at least match the section style.
Each of these JSON examples can be saved as a file in your theme’s `styles/block/` folder. In a real theme, you would replace the preset names with ones defined in your theme, and adjust values to match your design system. The above are illustrative, showing how to combine **color**, **spacing**, **typography**, **elements.link**, **blocks.core/**\*, and even **css** in your section style definitions.
@@ -329,23 +329,23 @@ Each of these JSON examples can be saved as a file in your theme’s `styles/blo
If you’re using GitHub Copilot (or another code assistant), here are some reusable prompt templates to help generate and troubleshoot Section Styles. These prompts assume Copilot has access to your theme context (design tokens, etc.) and can significantly speed up your workflow:
-* **Generate a New Section Style:**
+- **Generate a New Section Style:**
`"Create a /styles/block/section-{slug}.json for core/group and core/columns using these tokens: [list tokens]. Include nested styles for core/heading, core/paragraph, and elements.link. Avoid unsupported CSS (pseudo-elements, selectors) and keep to schema v3. Provide a short description and an A/B test name."`
-*Use this prompt to have the AI draft a new section style JSON.* The instruction guides Copilot to use the correct file location, apply tokens you specify (e.g. colors or spacing values you want), include some inner element styling, and avoid things we know theme.json can’t do. It even asks for a short description/A/B name if you are doing testing. You would replace `[list tokens]` with actual token names from your design (for example: “accent-1 background, base text, large font size, 40px padding”). Copilot should then produce a JSON snippet following these guidelines.
+_Use this prompt to have the AI draft a new section style JSON._ The instruction guides Copilot to use the correct file location, apply tokens you specify (e.g. colors or spacing values you want), include some inner element styling, and avoid things we know theme.json can’t do. It even asks for a short description/A/B name if you are doing testing. You would replace `[list tokens]` with actual token names from your design (for example: “accent-1 background, base text, large font size, 40px padding”). Copilot should then produce a JSON snippet following these guidelines.
-* **Resolve a Style Conflict:**
+- **Resolve a Style Conflict:**
`"Given section styles A (dark) and B (card), a Group inside a Group shows wrong heading colour. Propose which rules to move to inner block-scoped styles (styles.blocks.core/heading) in section B, and which remain at root, so the inner card’s heading wins. Confirm selectors/specificity assumptions for WP 6.6."`
-*Use this prompt when two section styles are clashing (for example, nested as parent and child).* This asks the AI to analyze which CSS rules should be adjusted so that the inner section’s styles take precedence for a particular element (here, headings). It explicitly mentions moving rules to `styles.blocks.core/heading` in the inner style – which is the JSON way of increasing specificity – and asks for confirmation of how specificity works in WP 6.6. The AI’s answer can help you pinpoint what to change in your theme.json files to fix the conflict.
+_Use this prompt when two section styles are clashing (for example, nested as parent and child)._ This asks the AI to analyze which CSS rules should be adjusted so that the inner section’s styles take precedence for a particular element (here, headings). It explicitly mentions moving rules to `styles.blocks.core/heading` in the inner style – which is the JSON way of increasing specificity – and asks for confirmation of how specificity works in WP 6.6. The AI’s answer can help you pinpoint what to change in your theme.json files to fix the conflict.
-* **Scaffold a GitHub Issue for a New Style:**
+- **Scaffold a GitHub Issue for a New Style:**
`"Draft a GitHub issue for 'Section Style: Blog Sidebar'. Include: objective, affected blocks, design tokens used, constraints (WP 6.6 limits), a test plan (including Style Book note), and a rollback plan."`
-*Use this prompt to generate a well-structured issue description* when you’re adding a new Section Style to your project. It reminds the AI to include key sections: what the goal of the new style is, which blocks it targets, which tokens or presets will be involved, any known constraints (perhaps “no hover state for links” etc.), how to test it (e.g. apply it in the editor, check front-end, check Style Book – noting that Style Book doesn’t show it), and how to roll it back if something goes wrong. This ensures your issue covers all bases for your team and QA.
+_Use this prompt to generate a well-structured issue description_ when you’re adding a new Section Style to your project. It reminds the AI to include key sections: what the goal of the new style is, which blocks it targets, which tokens or presets will be involved, any known constraints (perhaps “no hover state for links” etc.), how to test it (e.g. apply it in the editor, check front-end, check Style Book – noting that Style Book doesn’t show it), and how to roll it back if something goes wrong. This ensures your issue covers all bases for your team and QA.
Feel free to adapt these prompts to your team’s naming conventions or the particular problem you’re trying to solve. The idea is to leverage AI to follow the **“schema-first” approach** – enforcing the use of theme.json structure and known best practices from this guide, rather than blindly suggesting CSS that might not fit.
@@ -356,64 +356,64 @@ When translating a design system from Figma into theme.json presets, it’s impo
**Color Tokens → theme.json Palette**
Designers often define colors with names like “Primary”, “Secondary”, “Neutral 100”, etc. In theme.json, these become entries in the **color palette** (under `settings.color.palette`). For example:
-| Figma Color Token | Example Value | theme.json Mapping |
-| ----- | ----- | ----- |
-| Primary (Brand Blue) | `#0055EE` | Palette color with `"slug": "primary"` – use \`var:preset |
-| Secondary (Accent Orange) | `#FF7733` | Palette color with `"slug": "secondary"` – use \`var:preset |
-| Neutral 100 (Light Gray) | `#F3F3F3` | Palette color with `"slug": "surface"` (or “neutral-100”) – use \`var:preset |
-| Neutral 900 (Dark Gray) | `#111111` | Palette color with `"slug": "contrast"` – use \`var:preset |
-| Base (White) | `#FFFFFF` | Palette color `"slug": "base"` – use \`var:preset |
+| Figma Color Token | Example Value | theme.json Mapping |
+| ------------------------- | ------------- | ---------------------------------------------------------------------------- |
+| Primary (Brand Blue) | `#0055EE` | Palette color with `"slug": "primary"` – use \`var:preset |
+| Secondary (Accent Orange) | `#FF7733` | Palette color with `"slug": "secondary"` – use \`var:preset |
+| Neutral 100 (Light Gray) | `#F3F3F3` | Palette color with `"slug": "surface"` (or “neutral-100”) – use \`var:preset |
+| Neutral 900 (Dark Gray) | `#111111` | Palette color with `"slug": "contrast"` – use \`var:preset |
+| Base (White) | `#FFFFFF` | Palette color `"slug": "base"` – use \`var:preset |
-*Guidance:* Use clear, semantic slugs for colors (e.g. *primary, secondary, contrast, base, surface*). Ensure contrast pairs (text vs background) are considered – e.g. in the table above, “base” (white) is meant for backgrounds when “contrast” (black/dark) is used for text, and vice versa. Figma’s names might be numeric (Neutral 900\) – you can rename these to more semantic slugs in theme.json if desired (e.g. neutral-900 → contrast).
+_Guidance:_ Use clear, semantic slugs for colors (e.g. _primary, secondary, contrast, base, surface_). Ensure contrast pairs (text vs background) are considered – e.g. in the table above, “base” (white) is meant for backgrounds when “contrast” (black/dark) is used for text, and vice versa. Figma’s names might be numeric (Neutral 900\) – you can rename these to more semantic slugs in theme.json if desired (e.g. neutral-900 → contrast).
**Spacing Tokens → theme.json Spacing Scale**
If your design defines a spacing scale (e.g. increments like 4px, 8px, 16px labeled XS, S, M, L, etc.), map these to theme.json **`spacing.spacingSizes`** presets:
-| Figma Spacing Token | Pixel Value | theme.json Mapping |
-| ----- | ----- | ----- |
-| XS (Extra Small) | 4px | Add to `spacingSizes`: `{ "slug": "xs", "size": "4px" }` – use \`var:preset |
-| S (Small) | 8px | `spacingSizes`: `{ "slug": "s", "size": "8px" }` – use \`var:preset |
-| M (Medium) | 16px | `spacingSizes`: `{ "slug": "m", "size": "16px" }` – use \`var:preset |
-| L (Large) | 32px | `spacingSizes`: `{ "slug": "l", "size": "32px" }` – use \`var:preset |
-| XL (Extra Large) | 64px | `spacingSizes`: `{ "slug": "xl", "size": "64px" }` – use \`var:preset |
+| Figma Spacing Token | Pixel Value | theme.json Mapping |
+| ------------------- | ----------- | --------------------------------------------------------------------------- |
+| XS (Extra Small) | 4px | Add to `spacingSizes`: `{ "slug": "xs", "size": "4px" }` – use \`var:preset |
+| S (Small) | 8px | `spacingSizes`: `{ "slug": "s", "size": "8px" }` – use \`var:preset |
+| M (Medium) | 16px | `spacingSizes`: `{ "slug": "m", "size": "16px" }` – use \`var:preset |
+| L (Large) | 32px | `spacingSizes`: `{ "slug": "l", "size": "32px" }` – use \`var:preset |
+| XL (Extra Large) | 64px | `spacingSizes`: `{ "slug": "xl", "size": "64px" }` – use \`var:preset |
-*Guidance:* Keep the unit (px, em, etc.) in the value. Use slugs that make sense (avoid just numbers if possible; “m” is fine if scale is well-known, or use numbers like “spacing-4” but be consistent). Once defined, use these for margins, padding, gaps in your Section Styles. This way, if the design team updates spacing (or switches to fluid values), you update it in one place.
+_Guidance:_ Keep the unit (px, em, etc.) in the value. Use slugs that make sense (avoid just numbers if possible; “m” is fine if scale is well-known, or use numbers like “spacing-4” but be consistent). Once defined, use these for margins, padding, gaps in your Section Styles. This way, if the design team updates spacing (or switches to fluid values), you update it in one place.
**Typography Tokens → theme.json Font Presets**
For typography, Figma might have font size names (H1, H2, Body, Small, etc.). Map these to **`fontSizes`** in theme.json, and font families to `fontFamilies` if you have custom fonts:
-| Figma Text Style | Size/Style | theme.json Mapping |
-| ----- | ----- | ----- |
-| H1 (Hero Heading) | 48px, Bold | `fontSizes`: `{ "slug": "xx-large", "size": "3rem" }` (approx 48px). Use \`var:preset |
-| H2 (Section Heading) | 36px, Bold | `fontSizes`: `{ "slug": "x-large", "size": "2.25rem" }`. Use \`var:preset |
-| Body (Paragraph) | 16px, Regular | `fontSizes`: `{ "slug": "medium", "size": "1rem" }`. Use \`var:preset |
-| Small Text | 14px, Regular | `fontSizes`: `{ "slug": "small", "size": "0.875rem" }`. Use \`var:preset |
+| Figma Text Style | Size/Style | theme.json Mapping |
+| -------------------- | ---------------------- | ------------------------------------------------------------------------------------------------- |
+| H1 (Hero Heading) | 48px, Bold | `fontSizes`: `{ "slug": "xx-large", "size": "3rem" }` (approx 48px). Use \`var:preset |
+| H2 (Section Heading) | 36px, Bold | `fontSizes`: `{ "slug": "x-large", "size": "2.25rem" }`. Use \`var:preset |
+| Body (Paragraph) | 16px, Regular | `fontSizes`: `{ "slug": "medium", "size": "1rem" }`. Use \`var:preset |
+| Small Text | 14px, Regular | `fontSizes`: `{ "slug": "small", "size": "0.875rem" }`. Use \`var:preset |
| Brand Font (Display) | Font Family "AcmeCorp" | `fontFamilies`: `{ "slug": "brand", "fontFamily": "\"AcmeCorp\", sans-serif" }`. Use \`var:preset |
-*Guidance:* Establish a consistent set of font size slugs that cover your use cases (WP themes often use names like small, normal, medium, large, x-large, etc.). Match Figma styles to these. For font families, if you have custom fonts (like a brand display font), register them in `settings.typography.fontFamilies`. That provides a token you can use in styles (e.g. setting `typography.fontFamily`: `"var:preset|font-family|brand"` for a heading). Make sure to enqueue the font files or include them via Google Fonts as needed; theme.json can declare font face sources as well.
+_Guidance:_ Establish a consistent set of font size slugs that cover your use cases (WP themes often use names like small, normal, medium, large, x-large, etc.). Match Figma styles to these. For font families, if you have custom fonts (like a brand display font), register them in `settings.typography.fontFamilies`. That provides a token you can use in styles (e.g. setting `typography.fontFamily`: `"var:preset|font-family|brand"` for a heading). Make sure to enqueue the font files or include them via Google Fonts as needed; theme.json can declare font face sources as well.
**Effect Tokens (Shadows, Radii) → theme.json Presets**
Figma may have standardized shadows or corner radii. WP 6.6 allows defining **shadow presets** and **border radius presets** similarly:
-* *Example:* Figma shadow called "Card Shadow" \-\> add to `settings.shadow.presets` with a slug (e.g. `"card"`) and the CSS shadow value. Then use `var:preset|shadow|card` in Section Styles (`styles.shadow` property).
+- _Example:_ Figma shadow called "Card Shadow" \-\> add to `settings.shadow.presets` with a slug (e.g. `"card"`) and the CSS shadow value. Then use `var:preset|shadow|card` in Section Styles (`styles.shadow` property).
-* *Example:* Figma border radius tokens (Small \= 4px, Round \= 999px) \-\> map to `settings.border.radiusSizes` with slugs (`"small"` \= 4px, `"round"` \= 999px). Then use in styles like `"border": { "radius": "var:preset|border-radius|small" }`. (Note: border radius presets usage in theme.json v3 uses a different key, but conceptually similar.)
+- _Example:_ Figma border radius tokens (Small \= 4px, Round \= 999px) \-\> map to `settings.border.radiusSizes` with slugs (`"small"` \= 4px, `"round"` \= 999px). Then use in styles like `"border": { "radius": "var:preset|border-radius|small" }`. (Note: border radius presets usage in theme.json v3 uses a different key, but conceptually similar.)
By mapping design tokens to theme.json presets, you create a “source of truth” that both designers and developers share. When handing off, it’s useful to include in documentation a table like above so everyone knows that e.g. “Primary” in Figma equals `--wp--preset--color--primary` in code[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/#:~:text=For%20example%2C%20when%20you%20learned,size%E2%80%93%7B%24slug).
**Generation Guardrails:** When generating JSON from design specs (manually or via AI tools), keep these tips in mind:
-* *Double-check units:* Figma might use pixels, but theme.json can handle units like em, rem for scalability. Decide on a consistent unit (rem is common for font sizes to allow user scaling). Update token values accordingly during mapping.
+- _Double-check units:_ Figma might use pixels, but theme.json can handle units like em, rem for scalability. Decide on a consistent unit (rem is common for font sizes to allow user scaling). Update token values accordingly during mapping.
-* *Ensure schema validity:* Use the `$schema` link in your JSON and consider using a JSON linter/validator. A tiny syntax error can break your theme.json. The schema will catch unknown properties.
+- _Ensure schema validity:_ Use the `$schema` link in your JSON and consider using a JSON linter/validator. A tiny syntax error can break your theme.json. The schema will catch unknown properties.
-* *Name slugs predictably:* Slugs should be lowercase, alphanumeric (and hyphens). They become part of class names and variables, so keep them short and indicative (avoid spaces or special chars).
+- _Name slugs predictably:_ Slugs should be lowercase, alphanumeric (and hyphens). They become part of class names and variables, so keep them short and indicative (avoid spaces or special chars).
-* *Keep design tokens **global***: Don’t create one-off presets hidden inside a Section Style. If a color is only used in one section, it’s still better to put it in the global palette so it’s documented and perhaps reusable later. It also lets editors use that color elsewhere if desired.
+- \*Keep design tokens **global\***: Don’t create one-off presets hidden inside a Section Style. If a color is only used in one section, it’s still better to put it in the global palette so it’s documented and perhaps reusable later. It also lets editors use that color elsewhere if desired.
-* *Document any deviations:* If a token couldn’t be mapped (e.g. a Figma gradient or complex effect), note that and decide if it will be handled via custom CSS. Theme.json doesn’t support gradients as presets in the same way as solid colors (though you can define gradient presets, they have specific format). Likewise, advanced filters or blend modes might be out of scope.
+- _Document any deviations:_ If a token couldn’t be mapped (e.g. a Figma gradient or complex effect), note that and decide if it will be handled via custom CSS. Theme.json doesn’t support gradients as presets in the same way as solid colors (though you can define gradient presets, they have specific format). Likewise, advanced filters or blend modes might be out of scope.
-* *Leverage **fluid presets***: WordPress now supports fluid typography and spacing. If your Figma uses responsive sizing (say it specifies different values for mobile), consider using WP’s fluid preset features (e.g. font size presets can have fluid values). This might not directly map from Figma tokens, but it’s worth exploring for better responsiveness without media queries.
+- \*Leverage **fluid presets\***: WordPress now supports fluid typography and spacing. If your Figma uses responsive sizing (say it specifies different values for mobile), consider using WP’s fluid preset features (e.g. font size presets can have fluid values). This might not directly map from Figma tokens, but it’s worth exploring for better responsiveness without media queries.
In summary, maintain a clear mapping of Figma design tokens to theme.json presets so that your Section Styles can directly use `var:preset` references. This ensures design fidelity and makes it easier to update values in one place.
@@ -421,41 +421,41 @@ In summary, maintain a clear mapping of Figma design tokens to theme.json preset
When adding a new Section Style to your project, it’s helpful to standardize how you document and review it. Using an issue template can ensure all relevant details are captured. Below is a template outline you might use for GitHub issues (or pull requests) when proposing/implementing a new Section Style:
-`**Title:** Section Style – [Name of Section]`
+`**Title:** Section Style – [Name of Section]`
-`**Labels:** enhancement, section-style, design-system 🎨`
+`**Labels:** enhancement, section-style, design-system 🎨`
-`**Overview:**`
-`- **Goal/Purpose:** Describe what this section style is for (e.g. “A promotional hero section for landing pages with background image and large title”).`
-`- **Design Reference:** Link to Figma frames or design docs for this section. Include screenshot if possible.`
-`- **Block Types:** Which blocks will this style apply to (Group, Columns, Cover, etc.).`
+`**Overview:**`
+`- **Goal/Purpose:** Describe what this section style is for (e.g. “A promotional hero section for landing pages with background image and large title”).`
+`- **Design Reference:** Link to Figma frames or design docs for this section. Include screenshot if possible.`
+`- **Block Types:** Which blocks will this style apply to (Group, Columns, Cover, etc.).`
`- **Style Summary:** High-level summary of the stylistic choices (colors, typography, spacing, any special element tweaks).`
-`**Implementation Plan:**`
-``- Add JSON file `/styles/block/section-[slug].json` with defined presets.``
-`- Use existing design tokens: [list key tokens like colors, font sizes, etc.].`
-`- Include any needed nested styles (e.g. “style headings H3 and buttons inside the section”).`
+`**Implementation Plan:**`
+``- Add JSON file `/styles/block/section-[slug].json` with defined presets.``
+`- Use existing design tokens: [list key tokens like colors, font sizes, etc.].`
+`- Include any needed nested styles (e.g. “style headings H3 and buttons inside the section”).`
`- (If needed) Include minimal custom CSS in the JSON for anything not supported (explain why).`
-`**Constraints/Considerations:**`
-`- Note any WP 6.6 limitations (e.g. “will not show in Style Book preview”, “button hover state not possible via theme.json – will accept default hover”).`
-`- Accessibility check: e.g. color contrast meets guidelines (provide contrast ratios for text on background).`
+`**Constraints/Considerations:**`
+`- Note any WP 6.6 limitations (e.g. “will not show in Style Book preview”, “button hover state not possible via theme.json – will accept default hover”).`
+`- Accessibility check: e.g. color contrast meets guidelines (provide contrast ratios for text on background).`
`- Responsive: if using fluid typography or spacing, mention how it’s tested.`
-`**Test Plan:**`
-`1. **Editor:** Apply the Section Style in the Site Editor or post editor. Verify the styles (colors, fonts, etc.) appear as expected in editor.`
-`2. **Front-end:** Publish and view on front-end. Verify it matches design and is responsive.`
-`3. **Style Book:** (If applicable) Check Style Book – note that custom section styles might not preview (expected in 6.6).`
-`4. **Nested Scenario:** Test a section of this style inside another section (if applicable) to confirm no weird inheritance issues.`
+`**Test Plan:**`
+`1. **Editor:** Apply the Section Style in the Site Editor or post editor. Verify the styles (colors, fonts, etc.) appear as expected in editor.`
+`2. **Front-end:** Publish and view on front-end. Verify it matches design and is responsive.`
+`3. **Style Book:** (If applicable) Check Style Book – note that custom section styles might not preview (expected in 6.6).`
+`4. **Nested Scenario:** Test a section of this style inside another section (if applicable) to confirm no weird inheritance issues.`
`5. **Cross-Browser:** Basic check on Chrome, Firefox, Safari for any rendering differences.`
-`**Rollback Plan:**`
-`- This feature is self-contained. To disable, we can remove or comment out the JSON file and unregister the style if needed.`
-`- No migration for content needed (sections will just lose the style option if rolled back).`
-`- We will keep a backup of the JSON in case of reintroducing.`
+`**Rollback Plan:**`
+`- This feature is self-contained. To disable, we can remove or comment out the JSON file and unregister the style if needed.`
+`- No migration for content needed (sections will just lose the style option if rolled back).`
+`- We will keep a backup of the JSON in case of reintroducing.`
-`**Additional Notes:**`
-`- [Include any other info, e.g. if this is behind a feature flag or toggle in the theme.]`
+`**Additional Notes:**`
+`- [Include any other info, e.g. if this is behind a feature flag or toggle in the theme.]`
This template ensures everyone involved considers the important aspects: design fidelity, technical constraints, testing, and fallback. You can further integrate this into GitHub by creating an **Issue Form** (YAML file in `.github/ISSUE_TEMPLATE`). For example, a simplified excerpt of such a form might look like:
@@ -463,14 +463,14 @@ This template ensures everyone involved considers the important aspects: design
`labels: [ "section-style", "theme.json" ]`
`description: "Propose a new Section Style (block style variation) including design and implementation details."`
`body:`
- `- type: markdown`
- `attributes:`
- `value: "## Goal\nBriefly describe the section's purpose..."`
- `- type: textarea`
- `id: design_tokens`
- `attributes:`
- `label: "Design Tokens Used"`
- `description: "List key color, typography, spacing tokens for this style."`
+ `- type: markdown`
+ `attributes:`
+ `value: "## Goal\nBriefly describe the section's purpose..."`
+ `- type: textarea`
+ `id: design_tokens`
+ `attributes:`
+ `label: "Design Tokens Used"`
+ `description: "List key color, typography, spacing tokens for this style."`
…and so on for each section (Test Plan, Rollback). This would present a structured form for contributors when opening a new issue. Whether using a freeform template or an Issue Form, the key is to cover **labels** (to categorize it, e.g. `section-style` label), a clear **test plan**, and a **rollback plan** in case the style needs to be removed or adjusted. Including those shows forethought and makes QA and project managers happy.
@@ -480,39 +480,39 @@ Even with best practices, you may encounter some common issues when working with
**A. Section Style not applying (or part of it not working):**
-* **Style registration:** Confirm the JSON file is in the correct folder (`/styles/block/`) and named properly (`section-*.json`). If the style isn’t appearing in the editor at all, it might not be loading – check your theme’s minimum WP version (must be ≥6.6 for version 3 theme.json) and that the file has a unique slug.
+- **Style registration:** Confirm the JSON file is in the correct folder (`/styles/block/`) and named properly (`section-*.json`). If the style isn’t appearing in the editor at all, it might not be loading – check your theme’s minimum WP version (must be ≥6.6 for version 3 theme.json) and that the file has a unique slug.
-* **Block selection:** Make sure you applied the style to the intended block. The style will only show for the block types listed in `blockTypes`. E.g. if your style is for core/group but you applied it to a Cover block, nothing happens (unless you included core/cover in blockTypes).
+- **Block selection:** Make sure you applied the style to the intended block. The style will only show for the block types listed in `blockTypes`. E.g. if your style is for core/group but you applied it to a Cover block, nothing happens (unless you included core/cover in blockTypes).
-* **Cascading override:** If a specific CSS property isn’t taking effect, inspect the page with developer tools. Look at the element’s classes and computed styles. Is another rule overriding yours (maybe an inline style or a more specific selector)? For example, if a paragraph inside has an inline color set, theme.json styles won’t override that[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=This%20is%20the%20intended%20behaviour). The solution might be to remove the manual formatting or ensure your style targets a more specific element.
+- **Cascading override:** If a specific CSS property isn’t taking effect, inspect the page with developer tools. Look at the element’s classes and computed styles. Is another rule overriding yours (maybe an inline style or a more specific selector)? For example, if a paragraph inside has an inline color set, theme.json styles won’t override that[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=This%20is%20the%20intended%20behaviour). The solution might be to remove the manual formatting or ensure your style targets a more specific element.
-* **Specificity issues:** Remember that global styles and section styles often have the same specificity. WordPress tries to output section styles later so they win, but in nested cases the order can be tricky[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=discovery%20into%20a%20single%20consistent,6). If your parent section’s styles are overriding a child, consider moving the child-specific rules into the child’s section style (as discussed in Conflict Management).
+- **Specificity issues:** Remember that global styles and section styles often have the same specificity. WordPress tries to output section styles later so they win, but in nested cases the order can be tricky[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=discovery%20into%20a%20single%20consistent,6). If your parent section’s styles are overriding a child, consider moving the child-specific rules into the child’s section style (as discussed in Conflict Management).
-* **Schema errors:** If nothing is applying, your JSON might have a syntax error and WP ignored it. Check browser console or WP site health for JSON errors. Validate the JSON against the schema URL. Common mistakes include trailing commas, incorrect property names, or using an unsupported value (e.g. a wrong preset reference).
+- **Schema errors:** If nothing is applying, your JSON might have a syntax error and WP ignored it. Check browser console or WP site health for JSON errors. Validate the JSON against the schema URL. Common mistakes include trailing commas, incorrect property names, or using an unsupported value (e.g. a wrong preset reference).
**B. Spacing or layout looks “off” (spacing drift between editor and front):**
-* **Check theme layout settings:** If your theme uses `layout` (content size, etc.) or if the section is full-width vs constrained, differences can appear. The Site Editor might show padding differently if not in a full-width template. Test with the front-end in mind (often front is correct).
+- **Check theme layout settings:** If your theme uses `layout` (content size, etc.) or if the section is full-width vs constrained, differences can appear. The Site Editor might show padding differently if not in a full-width template. Test with the front-end in mind (often front is correct).
-* **Fluid spacing/typography differences:** If you’re using fluid values (clamp, etc.), minor discrepancies can occur due to rounding or viewport differences. Ensure that the editor canvas is wide enough or zoom set to 100% to reflect fluid values. Also double-check the computed value on different screen sizes to ensure it stays within expected range (not too small on mobile, etc.). Adjust your clamp() min/max if needed.
+- **Fluid spacing/typography differences:** If you’re using fluid values (clamp, etc.), minor discrepancies can occur due to rounding or viewport differences. Ensure that the editor canvas is wide enough or zoom set to 100% to reflect fluid values. Also double-check the computed value on different screen sizes to ensure it stays within expected range (not too small on mobile, etc.). Adjust your clamp() min/max if needed.
-* **Nested margins collapsing:** If you see unexpected extra or less space, remember that vertical margins can collapse in CSS. E.g. a heading with margin-bottom inside a group with margin-top might overlap. In such cases, consider using padding on the container rather than margins on the first/last element, or use the `:first-child/:last-child` selectors in custom CSS if absolutely needed (not available in theme.json). A quick fix can be giving the container a tiny padding (like 1px) to prevent margin collapse – or just be conscious of using only padding for section spacing.
+- **Nested margins collapsing:** If you see unexpected extra or less space, remember that vertical margins can collapse in CSS. E.g. a heading with margin-bottom inside a group with margin-top might overlap. In such cases, consider using padding on the container rather than margins on the first/last element, or use the `:first-child/:last-child` selectors in custom CSS if absolutely needed (not available in theme.json). A quick fix can be giving the container a tiny padding (like 1px) to prevent margin collapse – or just be conscious of using only padding for section spacing.
-* **Consistent units:** Ensure you didn’t mix units inadvertently – e.g. using `em` in one place and `px` in another could cause scaling issues. It’s usually fine, but if something looks off, try using the same unit for related measurements or rely on preset values.
+- **Consistent units:** Ensure you didn’t mix units inadvertently – e.g. using `em` in one place and `px` in another could cause scaling issues. It’s usually fine, but if something looks off, try using the same unit for related measurements or rely on preset values.
**C. Missing styles for interactive states or elements (e.g. no hover effect, pagination unstyled):**
-* **Hover/Focus styles:** As noted, theme.json supports link hover via `elements.link: hover/focus`, but not for other blocks. If your design calls for a hover change on a button or column, you’ll need to add custom CSS. For example, you might add in your theme’s stylesheet a rule targeting `.is-style-section-cta .wp-block-button__link:hover { background: ... }` for a CTA button hover. Keep these in a dedicated CSS file or inject via `styles.css` in theme.json for that block style[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=At%20the%20moment%2C%20WordPress%20only,ticket%20to%20add%20element%20support).
+- **Hover/Focus styles:** As noted, theme.json supports link hover via `elements.link: hover/focus`, but not for other blocks. If your design calls for a hover change on a button or column, you’ll need to add custom CSS. For example, you might add in your theme’s stylesheet a rule targeting `.is-style-section-cta .wp-block-button__link:hover { background: ... }` for a CTA button hover. Keep these in a dedicated CSS file or inject via `styles.css` in theme.json for that block style[developer.wordpress.org](https://developer.wordpress.org/news/2023/04/per-block-css-with-theme-json/#:~:text=At%20the%20moment%2C%20WordPress%20only,ticket%20to%20add%20element%20support).
-* **Pagination or complex block parts:** Some blocks (Navigation, Query Pagination, etc.) have sub-components that aren’t yet stylable via theme.json. Check the block’s documentation – if there are no Global Style options for that piece, you likely must write CSS. For instance, to style the current page number in Pagination, you might target `.wp-block-pagination__page.is-current` in CSS. Include these styles in your theme’s stylesheet or as a temporary fix in Additional CSS. Monitor WordPress dev notes – future versions may add support for these, and you can then migrate your CSS into theme.json presets.
+- **Pagination or complex block parts:** Some blocks (Navigation, Query Pagination, etc.) have sub-components that aren’t yet stylable via theme.json. Check the block’s documentation – if there are no Global Style options for that piece, you likely must write CSS. For instance, to style the current page number in Pagination, you might target `.wp-block-pagination__page.is-current` in CSS. Include these styles in your theme’s stylesheet or as a temporary fix in Additional CSS. Monitor WordPress dev notes – future versions may add support for these, and you can then migrate your CSS into theme.json presets.
-* **Icons or pseudo-elements:** If an icon (say a SVG icon in a button) isn’t taking color from your Section Style, it might be an inline SVG that requires a CSS fill rule. Again, use custom CSS: e.g. `.is-style-section-info-row .wp-block-button__link svg { fill: white; }` if needed. Pseudo-elements (`::before/::after`) also can’t be styled via JSON; any needed (for decorative flourish, etc.) must be handled by adding custom CSS or perhaps using an extra HTML block.
+- **Icons or pseudo-elements:** If an icon (say a SVG icon in a button) isn’t taking color from your Section Style, it might be an inline SVG that requires a CSS fill rule. Again, use custom CSS: e.g. `.is-style-section-info-row .wp-block-button__link svg { fill: white; }` if needed. Pseudo-elements (`::before/::after`) also can’t be styled via JSON; any needed (for decorative flourish, etc.) must be handled by adding custom CSS or perhaps using an extra HTML block.
-* **Consider contributions to Core:** If you find yourself adding a lot of the same custom CSS for things that feel like they *should* be in theme.json (like a particular block part), consider checking Gutenberg GitHub issues. There may already be an open issue or PR to add support. For example, WordPress 6.7+ might introduce more pseudo-class or block-part options. If not, you might even contribute a suggestion. In the meantime, document these exceptions in your code comments so future maintainers know why that CSS exists.
+- **Consider contributions to Core:** If you find yourself adding a lot of the same custom CSS for things that feel like they _should_ be in theme.json (like a particular block part), consider checking Gutenberg GitHub issues. There may already be an open issue or PR to add support. For example, WordPress 6.7+ might introduce more pseudo-class or block-part options. If not, you might even contribute a suggestion. In the meantime, document these exceptions in your code comments so future maintainers know why that CSS exists.
Using the above playbooks, you can systematically address issues. The key theme is: **verify the source of truth (JSON), then verify how it’s output (CSS), then adjust either the JSON or add a bit of CSS as needed** – always favouring JSON where possible. With WordPress 6.6’s improvements and those on the horizon, Section Styles are becoming a robust tool for theme developers to create flexible, design-system-driven themes with less code and more consistency. Happy theming\!
**Sources:** Official WordPress Developer Blog and Make/Core announcements were referenced for accuracy on new features and limitations[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=discovery%20into%20a%20single%20consistent,6)[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=1,previewed%20within%20the%20Style%20Book)[make.wordpress.org](https://make.wordpress.org/core/2024/06/24/section-styles/#:~:text=This%20is%20the%20intended%20behaviour)[developer.wordpress.org](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/#:~:text=Absolutely,to%20JSON%20from%20block%20stylesheets), alongside WordPress Handbook documentation on using presets[developer.wordpress.org](https://developer.wordpress.org/themes/global-settings-and-styles/styles/using-presets/#:~:text=To%20reference%20presets%20in%20,base) and theme.json structure. These provide further reading and context for the concepts covered in this guide.
Sources
-Extended thinking
+Extended thinking
diff --git a/block-themes/section-styles.md b/docs/wordpress/block-themes/theme.json/section-styles.md
similarity index 79%
rename from block-themes/section-styles.md
rename to docs/wordpress/block-themes/theme.json/section-styles.md
index cd5bac9..dc0e629 100644
--- a/block-themes/section-styles.md
+++ b/docs/wordpress/block-themes/theme.json/section-styles.md
@@ -1,4 +1,5 @@
# Section styles
+
Guidance on defining, naming, and applying section-level styles to create consistent, reusable layout and visual patterns across your theme. When building reusable section styles, focus on container-level design tokens and nested block element rules. These keep layouts consistent and reduce ad-hoc overrides.
---
@@ -6,20 +7,22 @@ Guidance on defining, naming, and applying section-level styles to create consis
## What they are (and when to use)
Section styles are **block style variations** you register for container blocks (commonly `core/group`, `core/columns`, `core/cover`).
-They are defined in `theme.json` and can cascade styles to **nested elements** (links, buttons, headings) and **child blocks**.
+They are defined in `theme.json` and can cascade styles to **nested elements** (links, buttons, headings) and **child blocks**.
### Key points
-- Applied at the container level for consistent section design.
-- Cascading rules let headings, links, and other inner blocks inherit styles automatically.
-- Keeps design tokens in `theme.json` instead of ad-hoc CSS.
-- Best used for **reusable “bands”** that repeat across a theme.
+
+- Applied at the container level for consistent section design.
+- Cascading rules let headings, links, and other inner blocks inherit styles automatically.
+- Keeps design tokens in `theme.json` instead of ad-hoc CSS.
+- Best used for **reusable “bands”** that repeat across a theme.
### When to use
-- **Hero sections** (dark/light backgrounds, strong typography).
-- **Card grids** (consistent padding, border radius, shadows).
-- **Feature or infobox rows** (controlled spacing, link colors, heading scale).
-- **Call-to-action strips** (buttons + background presets).
-- **Archive/blog sections** (uniform card or list layouts).
+
+- **Hero sections** (dark/light backgrounds, strong typography).
+- **Card grids** (consistent padding, border radius, shadows).
+- **Feature or infobox rows** (controlled spacing, link colors, heading scale).
+- **Call-to-action strips** (buttons + background presets).
+- **Archive/blog sections** (uniform card or list layouts).
---
@@ -27,49 +30,50 @@ They are defined in `theme.json` and can cascade styles to **nested elements** (
- **Scope to containers first**
Register styles for `core/group`, `core/columns`, `core/cover`.
- Apply child tweaks with `blocks.core/*` and `elements.*` inside the variation.
+ Apply child tweaks with `blocks.core/*` and `elements.*` inside the variation.
- **Use presets, not hard-coded values**
- Always prefer tokens like `var:preset|color|*`, `var:preset|spacing|*`, `var:preset|font-size|*` to stay aligned with Global Styles.
+ Always prefer tokens like `var:preset|color|*`, `var:preset|spacing|*`, `var:preset|font-size|*` to stay aligned with Global Styles.
- **One purpose per slug**
Follow the format `section-{context}-{purpose}` (e.g. `section-archive-cards`).
- Keep styles focused; don’t mix utilities into a section style.
+ Keep styles focused; don’t mix utilities into a section style.
- **Style nested blocks/elements, not roots**
Target inner headings, links, and paragraphs within the section.
- Avoid broad root color rules that can clash inside nested sections.
+ Avoid broad root color rules that can clash inside nested sections.
- **Stay within schema**
No pseudo-elements, arbitrary selectors, or JS.
- If needed, keep `css` string overrides minimal.
+ If needed, keep `css` string overrides minimal.
- **Respect WP 6.6 specificity changes**
Core selectors are now lower-specificity.
- Let `theme.json` handle overrides first instead of using `!important`.
+ Let `theme.json` handle overrides first instead of using `!important`.
---
## Limitations
- **Restricted to theme.json**
- Only properties supported by `theme.json` can be used. No custom selectors, pseudo-elements (`::before`, `::after`), or JavaScript behaviors.
+ Only properties supported by `theme.json` can be used. No custom selectors, pseudo-elements (`::before`, `::after`), or JavaScript behaviors.
- **Static logic only**
- Section styles are static. They cannot apply conditionally by template, post type, or device size. Use patterns, block visibility, or templates for conditional behavior.
+ Section styles are static. They cannot apply conditionally by template, post type, or device size. Use patterns, block visibility, or templates for conditional behavior.
- **No deep targeting**
- You cannot style structural positions (e.g. “first child only”). Styling cascades only to defined blocks (`blocks.core/*`) or elements (`elements.link`).
+ You cannot style structural positions (e.g. “first child only”). Styling cascades only to defined blocks (`blocks.core/*`) or elements (`elements.link`).
- **Manual application**
- Variations must be applied manually in the Block Editor or pre-applied in block patterns. There is no automatic inheritance across all blocks.
+ Variations must be applied manually in the Block Editor or pre-applied in block patterns. There is no automatic inheritance across all blocks.
- **Code-only workflow**
- Section styles must be defined in JSON partials or via `register_block_style()`. They cannot be created or edited visually in the Site Editor.
-- **Global Styles limitations (WP 6.6)**
- - Only **root block styles** are configurable in Global Styles; inner-block rules are not.
- - Variations cannot override inner block variations.
- - Variations do not have their own `settings` store.
- - Custom variations cannot be previewed in the **Style Book**.
+ Section styles must be defined in JSON partials or via `register_block_style()`. They cannot be created or edited visually in the Site Editor.
+- **Global Styles limitations (WP 6.6)**
+ - Only **root block styles** are configurable in Global Styles; inner-block rules are not.
+ - Variations cannot override inner block variations.
+ - Variations do not have their own `settings` store.
+ - Custom variations cannot be previewed in the **Style Book**.
- **Maintenance & accessibility**
Too many variations increase bundle size and maintenance overhead.
Background and contrast choices must always meet accessibility guidelines.
- Some blocks still lack full block supports to benefit from section styles — check [tracking issues](https://github.com/WordPress/gutenberg/issues/57537) before assuming support.
+ Some blocks still lack full block supports to benefit from section styles — check [tracking issues](https://github.com/WordPress/gutenberg/issues/57537) before assuming support.
---
## Naming conventions
+
- Filenames: `/styles/block/section-{slug}.json`
- Slugs: lowercase kebab-case; stable per “look”, e.g. `section-dark-hero`, `section-cards`.
- Titles: human, screen-reader friendly (e.g. `Section · Cards`).
@@ -92,6 +96,7 @@ They are defined in `theme.json` and can cascade styles to **nested elements** (
---
## What blocks benefit most
+
- Start with container blocks: `core/group`, `core/columns`, `core/cover`. Add nested rules for `core/heading`, `core/paragraph`, `core/buttons`, and specific components used repeatedly (e.g. `core/post-terms` example).
---
@@ -112,7 +117,7 @@ They are defined in `theme.json` and can cascade styles to **nested elements** (
"version": 3,
"slug": "section-1",
"title": "Section 1",
- "blockTypes": ["core/group","core/columns"],
+ "blockTypes": ["core/group", "core/columns"],
"styles": {
"color": { "background": "var:preset|color|contrast", "text": "var:preset|color|base" }
}
@@ -129,7 +134,7 @@ They are defined in `theme.json` and can cascade styles to **nested elements** (
"version": 3,
"slug": "section-2",
"title": "Section 2",
- "blockTypes": ["core/group","core/columns"],
+ "blockTypes": ["core/group", "core/columns"],
"styles": {
"color": { "background": "#cbd5e1", "text": "var:preset|color|contrast" }
}
@@ -150,7 +155,7 @@ You can scope **inner elements** (e.g. `elements.link`) and **inner blocks** (e.
"version": 3,
"slug": "section-cards",
"title": "Section · Cards",
- "blockTypes": ["core/group","core/columns"],
+ "blockTypes": ["core/group", "core/columns"],
"styles": {
"color": { "background": "var:preset|color|surface", "text": "var:preset|color|contrast" },
"elements": {
@@ -170,7 +175,7 @@ You can scope **inner elements** (e.g. `elements.link`) and **inner blocks** (e.
}
```
-The exact capabilities and `css` usage are demonstrated in the Dev Blog’s 6.6 tutorial.
+The exact capabilities and `css` usage are demonstrated in the Dev Blog’s 6.6 tutorial.
---
@@ -192,11 +197,11 @@ add_action( 'init', function () {
)
)
);
-}
+}
);
```
-`style_data` is new in 6.6 and maps to the theme.json-like notation. The first arg now accepts an **array of block types**.
+`style_data` is new in 6.6 and maps to the theme.json-like notation. The first arg now accepts an **array of block types**.
---
@@ -204,15 +209,15 @@ add_action( 'init', function () {
### Why conflicts happen
-* Two variations applied **nested** (Group inside Group) share specificity; rules can cascade unpredictably.
-* Local user controls (inline classes/inline styles) can override your variation.
- The 6.6 work reduced specificity to make the cascade saner, but nested edge cases remain.
+- Two variations applied **nested** (Group inside Group) share specificity; rules can cascade unpredictably.
+- Local user controls (inline classes/inline styles) can override your variation.
+ The 6.6 work reduced specificity to make the cascade saner, but nested edge cases remain.
### Avoidance rules
-* Keep **section-wide colour/background** at the variation root; move typography/spacing for specific components into `blocks.core/*` so inner sections can override locally.
-* Don’t stack variations on non-container blocks.
-* Prefer **patterns** to combine multiple looks in a predictable structure. ([WordPress Developer Resources][1])
+- Keep **section-wide colour/background** at the variation root; move typography/spacing for specific components into `blocks.core/*` so inner sections can override locally.
+- Don’t stack variations on non-container blocks.
+- Prefer **patterns** to combine multiple looks in a predictable structure. ([WordPress Developer Resources][1])
### Debug checklist
@@ -220,16 +225,18 @@ add_action( 'init', function () {
2. Is a **local control** (e.g. link colour) applied on the child block?
3. Are you missing an **inner block** rule where you expected inheritance?
4. If nested sections clash, shift the contested rule into the inner variation’s `blocks.core/*`.
-5. Only drop down to the `css` string if schema can’t express the tweak.
+5. Only drop down to the `css` string if schema can’t express the tweak.
---
## Benefits
-- Saving time ?? Why
+
+- Saving time ?? Why
---
## When to use
+
- You need to visually group content into distinct sections (hero, feature grid, testimonials) with consistent spacing and backgrounds.
- Multiple pages reuse the same section look-and-feel and should change uniformly via a single update.
- You want to offer non-technical authors a curated set of section presets instead of custom CSS per page.
@@ -251,77 +258,79 @@ test('section-cards applies nested heading + link styles', async ({ page }) => {
});
```
-Use selectors by **block wrapper class** plus the auto `is-style-{slug}` class, mirroring Block Styles API behaviour.
+Use selectors by **block wrapper class** plus the auto `is-style-{slug}` class, mirroring Block Styles API behaviour.
---
## Linting rules (CI)
-* Validate against **theme.json v3** schema via `$schema` and a JSON schema check.
-* Enforce: has `slug`, `title`, `blockTypes`, **no disallowed CSS** (pseudo-elements), at least one `elements.link` or inner `blocks.*` rule.
-* Check tokens: only `var:preset|…` or theme variables for colours/spacing/typography. Dev Blog & API pages confirm v3 and `style_data` conventions.
-
+- Validate against **theme.json v3** schema via `$schema` and a JSON schema check.
+- Enforce: has `slug`, `title`, `blockTypes`, **no disallowed CSS** (pseudo-elements), at least one `elements.link` or inner `blocks.*` rule.
+- Check tokens: only `var:preset|…` or theme variables for colours/spacing/typography. Dev Blog & API pages confirm v3 and `style_data` conventions.
---
-## Make/Core (24 Jun 2024) — *“Section Styles”*
+## Make/Core (24 Jun 2024) — _“Section Styles”_
**What it is:** Official feature announcement + quick how-to.
**Key points**
+
- Section styles are **block style variations** defined in **theme.json partials** under **`/styles/`**, scoped by `blockTypes` (e.g., Group/Columns/Cover).
-- How to **apply** in the editor, and **limitations** for 6.6 (root styles in Global Styles, no per-variation settings, etc.).
+- How to **apply** in the editor, and **limitations** for 6.6 (root styles in Global Styles, no per-variation settings, etc.).
**Why it matters**
+
- Provides the **canonical folder structure**, editor UX, and **current limits** we’ll document in the Copilot.
---
-## WP Dev Blog (21 Jun 2024) — *“Styling sections, nested elements, and more with Block Style Variations in WordPress 6.6”*
+## WP Dev Blog (21 Jun 2024) — _“Styling sections, nested elements, and more with Block Style Variations in WordPress 6.6”_
**What it is:** Hands-on tutorial from Core team on using section styles.
**Key points**
-* Shows **JSON structure**: `blockTypes`, `styles.color/spacing`, **`elements.link`**, and **`blocks.core/*`** for inner targeting.
-* Demonstrates **nested application** and managing **cascades** via JSON (not CSS).
-* Notes practical **limitations** and **tips** for predictable outcomes.
+- Shows **JSON structure**: `blockTypes`, `styles.color/spacing`, **`elements.link`**, and **`blocks.core/*`** for inner targeting.
+- Demonstrates **nested application** and managing **cascades** via JSON (not CSS).
+- Notes practical **limitations** and **tips** for predictable outcomes.
**Why it matters**
-* This is the **best practice cookbook** we’ll codify into the Copilot’s generators and debug playbooks.
+- This is the **best practice cookbook** we’ll codify into the Copilot’s generators and debug playbooks.
---
-## WP Dev Blog (Feb 2023) — *“Intrinsic design, theming, and rethinking how to design with WordPress”*
+## WP Dev Blog (Feb 2023) — _“Intrinsic design, theming, and rethinking how to design with WordPress”_
**What it is:** Design philosophy that informed the section-style direction.
**Key points**
-* Advocates **intrinsic design**: fluid, token-driven, systemised scales for spacing/typography/colour.
-* Encourages **theme.json as the source of truth**, avoiding ad-hoc CSS.
+- Advocates **intrinsic design**: fluid, token-driven, systemised scales for spacing/typography/colour.
+- Encourages **theme.json as the source of truth**, avoiding ad-hoc CSS.
**Why it matters**
-* Backs our **token mapping** (Figma → presets) and **fluid spacing** approach in Copilot guidance.
+- Backs our **token mapping** (Figma → presets) and **fluid spacing** approach in Copilot guidance.
---
-## 7) Gutenberg Issue #57537 — *“Section Styling, Colorways, and Typesets for WP 6.6”* (tracking/design)
+## 7) Gutenberg Issue #57537 — _“Section Styling, Colorways, and Typesets for WP 6.6”_ (tracking/design)
**What it is:** The **planning/tracking issue** for the feature.
**Key points**
-* Documents the plan: **reduce specificity**, refine block style variations, push section styling into **6.6**.
-* Introduces **`gutenberg_register_block_style`**, integration with **`theme.json`**, and support for **inner elements/blocks** (but not arbitrarily deep/over-specific variants).
-* Mentions referencing shared definitions via `styles.blocks.variations`.
+- Documents the plan: **reduce specificity**, refine block style variations, push section styling into **6.6**.
+- Introduces **`gutenberg_register_block_style`**, integration with **`theme.json`**, and support for **inner elements/blocks** (but not arbitrarily deep/over-specific variants).
+- Mentions referencing shared definitions via `styles.blocks.variations`.
**Why it matters**
-* Explains the **rationale & constraints** we must uphold in our lint rules and Copilot “dos/don’ts”.
+- Explains the **rationale & constraints** we must uphold in our lint rules and Copilot “dos/don’ts”.
---
## Reference Links
+
- [Section Styles – Make WordPress Core](https://make.wordpress.org/core/2024/06/24/section-styles/)
- [WordPress Developer Resources: Intrinsic design, theming, and rethinking how to design with WordPress](https://developer.wordpress.org/news/2023/02/intrinsic-design-theming-and-rethinking-how-to-design-with-wordpress/)
- [Styling sections, nested elements, and more with Block Style Variations in WordPress 6.6 – WordPress Developer Blog](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/)
diff --git a/block-themes/spacing-presets.md b/docs/wordpress/block-themes/theme.json/spacing-presets.md
similarity index 72%
rename from block-themes/spacing-presets.md
rename to docs/wordpress/block-themes/theme.json/spacing-presets.md
index 97bacf7..d229c8a 100644
--- a/block-themes/spacing-presets.md
+++ b/docs/wordpress/block-themes/theme.json/spacing-presets.md
@@ -1,4 +1,5 @@
# Spacing Presets
+
Spacing presets are reusable design tokens for margins, paddings, and gaps. They are defined in `theme.json` and exposed to the block editor, allowing designers and developers to apply consistent, scalable spacing across blocks and patterns.
---
@@ -38,7 +39,7 @@ Spacing presets are created using the `spacingSizes` property:
]
}
}
-````
+```
### Output CSS Variables
@@ -82,19 +83,19 @@ Apply within block patterns:
## Best Practices
-* **Slug naming**: use numeric slugs (`20`, `30`, `40`) for predictable ordering in the editor.
-* **Editor clarity**: provide clear `name` labels ("Small", "Medium", "Large").
-* **Token-first**: reference presets (`var:preset|spacing|30`) instead of hardcoding values.
-* **Consistency**: define the **full range** of values, even if not all are used immediately.
-* **Scalability**: align preset sizes with typography and layout scales.
+- **Slug naming**: use numeric slugs (`20`, `30`, `40`) for predictable ordering in the editor.
+- **Editor clarity**: provide clear `name` labels ("Small", "Medium", "Large").
+- **Token-first**: reference presets (`var:preset|spacing|30`) instead of hardcoding values.
+- **Consistency**: define the **full range** of values, even if not all are used immediately.
+- **Scalability**: align preset sizes with typography and layout scales.
---
## Limitations
-* Presets must be **fully declared**; missing steps hide defaults unintentionally.
-* `spacingSizes` and `spacingScale` can conflict if both are defined — control with `defaultSpacingSizes`.
-* Not all core blocks support spacing presets yet; some still rely on hardcoded margins.
+- Presets must be **fully declared**; missing steps hide defaults unintentionally.
+- `spacingSizes` and `spacingScale` can conflict if both are defined — control with `defaultSpacingSizes`.
+- Not all core blocks support spacing presets yet; some still rely on hardcoded margins.
---
@@ -126,17 +127,19 @@ This generates a system scale, with an additional “Auto” option for specific
## Key Takeaways
-* **Presets = design tokens** for spacing.
-* Use **numeric slugs** for consistent editor ordering.
-* Apply spacing via **variables**, not hardcoded units.
-* Pair with `blockGap` for section styles and layout consistency.
+- **Presets = design tokens** for spacing.
+- Use **numeric slugs** for consistent editor ordering.
+- Apply spacing via **variables**, not hardcoded units.
+- Pair with `blockGap` for section styles and layout consistency.
---
## References
-* [Rich Tabor — Standardizing Spacing in theme.json](https://rich.blog/standardizing-theme-json-spacing/)
-* [WordPress Developer Docs — Block Spacing](https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/#spacing)
-* [Make Core: Theme.json v3](https://make.wordpress.org/core/2024/06/19/theme-json-version-3/)
+- [Rich Tabor — Standardizing Spacing in theme.json](https://rich.blog/standardizing-theme-json-spacing/)
+- [WordPress Developer Docs — Block Spacing](https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/#spacing)
+- [Make Core: Theme.json v3](https://make.wordpress.org/core/2024/06/19/theme-json-version-3/)
+
+```
```
diff --git a/block-themes/standardising-colours-fonts-spacing.md b/docs/wordpress/block-themes/theme.json/standardising-colours-fonts-spacing.md
similarity index 66%
rename from block-themes/standardising-colours-fonts-spacing.md
rename to docs/wordpress/block-themes/theme.json/standardising-colours-fonts-spacing.md
index 3ce573c..c2f8d9f 100644
--- a/block-themes/standardising-colours-fonts-spacing.md
+++ b/docs/wordpress/block-themes/theme.json/standardising-colours-fonts-spacing.md
@@ -6,21 +6,21 @@ A predictable, token-based system for **colours, spacing, and typography** helps
### Core Semantic
-* `base` → background
-* `contrast` → text
-* `primary` → brand/CTA
+- `base` → background
+- `contrast` → text
+- `primary` → brand/CTA
### Neutral Scale
-* `neutral-0` → white
-* `neutral-100` → lightest grey
-* `neutral-200 … neutral-900` → progressively darker greys
-* `neutral-900` → pure black
+- `neutral-0` → white
+- `neutral-100` → lightest grey
+- `neutral-200 … neutral-900` → progressively darker greys
+- `neutral-900` → pure black
### Accent Scale
-* `accent-100 … accent-900` to up to however many brand/utility accents you need.
-* These can represent different **hues** or **tones** of your brand colour system.
+- `accent-100 … accent-900` to up to however many brand/utility accents you need.
+- These can represent different **hues** or **tones** of your brand colour system.
---
@@ -34,20 +34,20 @@ A predictable, token-based system for **colours, spacing, and typography** helps
"color": {
"defaultPalette": false,
"palette": [
- { "slug": "base", "name": "Base", "color": "#FFFFFF" },
+ { "slug": "base", "name": "Base", "color": "#FFFFFF" },
{ "slug": "contrast", "name": "Contrast", "color": "#111111" },
- { "slug": "primary", "name": "Primary", "color": "#0A84FF" },
-
- { "slug": "neutral-0", "name": "Neutral 0", "color": "#FFFFFF" },
- { "slug": "neutral-100", "name": "Neutral 100", "color": "#F9FAFB" },
- { "slug": "neutral-200", "name": "Neutral 200", "color": "#F3F4F6" },
- { "slug": "neutral-300", "name": "Neutral 300", "color": "#E5E7EB" },
- { "slug": "neutral-400", "name": "Neutral 400", "color": "#D1D5DB" },
- { "slug": "neutral-500", "name": "Neutral 500", "color": "#9CA3AF" },
- { "slug": "neutral-600", "name": "Neutral 600", "color": "#6B7280" },
- { "slug": "neutral-700", "name": "Neutral 700", "color": "#4B5563" },
- { "slug": "neutral-800", "name": "Neutral 800", "color": "#1F2937" },
- { "slug": "neutral-900", "name": "Neutral 900", "color": "#111111" },
+ { "slug": "primary", "name": "Primary", "color": "#0A84FF" },
+
+ { "slug": "neutral-0", "name": "Neutral 0", "color": "#FFFFFF" },
+ { "slug": "neutral-100", "name": "Neutral 100", "color": "#F9FAFB" },
+ { "slug": "neutral-200", "name": "Neutral 200", "color": "#F3F4F6" },
+ { "slug": "neutral-300", "name": "Neutral 300", "color": "#E5E7EB" },
+ { "slug": "neutral-400", "name": "Neutral 400", "color": "#D1D5DB" },
+ { "slug": "neutral-500", "name": "Neutral 500", "color": "#9CA3AF" },
+ { "slug": "neutral-600", "name": "Neutral 600", "color": "#6B7280" },
+ { "slug": "neutral-700", "name": "Neutral 700", "color": "#4B5563" },
+ { "slug": "neutral-800", "name": "Neutral 800", "color": "#1F2937" },
+ { "slug": "neutral-900", "name": "Neutral 900", "color": "#111111" },
{ "slug": "accent-100", "name": "Accent 100", "color": "#0A84FF" },
{ "slug": "accent-200", "name": "Accent 200", "color": "#3399FF" },
@@ -68,16 +68,17 @@ A predictable, token-based system for **colours, spacing, and typography** helps
## Best Practices
-* **Extend in 100-steps** for predictable scaling.
-* **Group hues into bands** (e.g., `accent-100` → `accent-500` for blues, `accent-600` → `accent-900` for warm tones).
-* **Don’t rename slugs** once published — just change values to update brand colours.
-* **Use neutrals for UI foundations**, **accents for highlights/brand identity**.
-
+- **Extend in 100-steps** for predictable scaling.
+- **Group hues into bands** (e.g., `accent-100` → `accent-500` for blues, `accent-600` → `accent-900` for warm tones).
+- **Don’t rename slugs** once published — just change values to update brand colours.
+- **Use neutrals for UI foundations**, **accents for highlights/brand identity**.
---
+
## Font Sizes & Slugs
### WordPress Default Font Size Slugs
+
WordPress ships with four core font sizes:
- `small`
@@ -91,10 +92,10 @@ Perfect — let’s extend the **WordPress default font sizes** into a numeric s
### Default WP Font Sizes (approx)
-* `small` → 13px
-* `medium` → 20px (default body size = 16px)
-* `large` → 36px
-* `x-large` → 42px
+- `small` → 13px
+- `medium` → 20px (default body size = 16px)
+- `large` → 36px
+- `x-large` → 42px
(These are defaults, but the slugs can vary across themes.)
@@ -105,8 +106,8 @@ Perfect — let’s extend the **WordPress default font sizes** into a numeric s
| Slug | Label | px size | rem (base 16px) |
| --------------- | -------- | ------- | --------------- |
| `font-size-100` | Tiny | 12px | 0.75rem |
-| `font-size-200` | Base | 16px | 1rem |
-| `font-size-300` | Small | 20px | 1.25rem |
+| `font-size-200` | Base | 16px | 1rem |
+| `font-size-300` | Small | 20px | 1.25rem |
| `font-size-400` | Medium | 24px | 1.5rem |
| `font-size-500` | Large | 32px | 2rem |
| `font-size-600` | X-Large | 40px | 2.5rem |
@@ -128,14 +129,14 @@ Perfect — let’s extend the **WordPress default font sizes** into a numeric s
"typography": {
"fontSizes": [
{ "slug": "font-size-100", "size": "0.75rem", "name": "Tiny" },
- { "slug": "font-size-200", "size": "1rem", "name": "Base" },
+ { "slug": "font-size-200", "size": "1rem", "name": "Base" },
{ "slug": "font-size-300", "size": "1.25rem", "name": "Small" },
- { "slug": "font-size-400", "size": "1.5rem", "name": "Medium" },
- { "slug": "font-size-500", "size": "2rem", "name": "Large" },
- { "slug": "font-size-600", "size": "2.5rem", "name": "X-Large" },
- { "slug": "font-size-700", "size": "3rem", "name": "Huge" },
- { "slug": "font-size-800", "size": "4rem", "name": "Gigantic" },
- { "slug": "font-size-900", "size": "5rem", "name": "Colossal" }
+ { "slug": "font-size-400", "size": "1.5rem", "name": "Medium" },
+ { "slug": "font-size-500", "size": "2rem", "name": "Large" },
+ { "slug": "font-size-600", "size": "2.5rem", "name": "X-Large" },
+ { "slug": "font-size-700", "size": "3rem", "name": "Huge" },
+ { "slug": "font-size-800", "size": "4rem", "name": "Gigantic" },
+ { "slug": "font-size-900", "size": "5rem", "name": "Colossal" }
]
}
}
@@ -146,17 +147,18 @@ Perfect — let’s extend the **WordPress default font sizes** into a numeric s
### Best Practices for Font Size Values
-* **Numeric slugs** keep naming scalable and consistent (`font-size-100 … 900`).
-* **Multiples of 8px** ensure harmony with spacing scales.
-* Always **keep slugs stable** → you can change size values without breaking references.
-* Use **semantic naming** in addition to numeric (helps editors know what’s “Huge” vs “Tiny”).
-* Pair with **fluid typography** in WP 6.6+ so these sizes scale across devices.
+- **Numeric slugs** keep naming scalable and consistent (`font-size-100 … 900`).
+- **Multiples of 8px** ensure harmony with spacing scales.
+- Always **keep slugs stable** → you can change size values without breaking references.
+- Use **semantic naming** in addition to numeric (helps editors know what’s “Huge” vs “Tiny”).
+- Pair with **fluid typography** in WP 6.6+ so these sizes scale across devices.
---
## Spacing Sizes & Slugs
### WordPress Default Spacing Slugs
+
The default spacing scale is numeric and increments by 10:
- `spacing-10`
@@ -172,19 +174,19 @@ The default spacing scale is numeric and increments by 10:
We extend this with additional slugs to cover larger gaps, while **keeping naming consistent**:
-- `spacing-70` → `3.5rem` (56px)
-- `spacing-80` → `4rem` (64px)
-- `spacing-90` → `4.5rem` (72px)
-- `spacing-100` → `5rem` (80px)
+- `spacing-70` → `3.5rem` (56px)
+- `spacing-80` → `4rem` (64px)
+- `spacing-90` → `4.5rem` (72px)
+- `spacing-100` → `5rem` (80px)
## Extended Spacing Scale
We extend this with additional slugs to cover larger gaps, while **keeping naming consistent**:
-- `spacing-70` → `3.5rem` (56px)
-- `spacing-80` → `4rem` (64px)
-- `spacing-90` → `4.5rem` (72px)
-- `spacing-100` → `5rem` (80px)
+- `spacing-70` → `3.5rem` (56px)
+- `spacing-80` → `4rem` (64px)
+- `spacing-90` → `4.5rem` (72px)
+- `spacing-100` → `5rem` (80px)
---
@@ -214,10 +216,11 @@ We extend this with additional slugs to cover larger gaps, while **keeping namin
## Best Practices for Naming Conventions
### 1. **Spacing**
+
- Use either:
- - `spacingScale`: system-generated (`20`, `30`, `40`…)
- - `spacingSizes`: manual with fluid units (`s`, `m`, `l`)
-- Always keep **numeric slugs in sequence** (`20`, `30`, `40`…), since the editor orders presets by slug.
+ - `spacingScale`: system-generated (`20`, `30`, `40`…)
+ - `spacingSizes`: manual with fluid units (`s`, `m`, `l`)
+- Always keep **numeric slugs in sequence** (`20`, `30`, `40`…), since the editor orders presets by slug.
- If semantic slugs are preferred (`s`, `m`, `l`), use them consistently across all blocks.
✅ Recommendation: Stick with numeric scales (`20–80`) for compatibility with WordPress defaults, but allow semantic naming at the design system layer (e.g. mapping `space.m → spacing-40`).
@@ -225,8 +228,9 @@ We extend this with additional slugs to cover larger gaps, while **keeping namin
---
### 2. **Typography**
-- WordPress default slugs: `small`, `medium`, `large`, `x-large`.
-- Rich Tabor recommends a **numbered scale** (`xs`, `s`, `m`, `l`, `xl`, `xxl`) to create predictable progression.
+
+- WordPress default slugs: `small`, `medium`, `large`, `x-large`.
+- Rich Tabor recommends a **numbered scale** (`xs`, `s`, `m`, `l`, `xl`, `xxl`) to create predictable progression.
- FullSiteEditing.com supports both, but stresses aligning naming with design tokens in Figma.
✅ Recommendation: Retain WP defaults for editor familiarity, but override values with your scale (e.g. keep slug `large` but define it as `clamp(1.5rem, 2vw, 2rem)`).
@@ -234,9 +238,10 @@ We extend this with additional slugs to cover larger gaps, while **keeping namin
---
### 3. **Colours**
-- WordPress defaults (`black`, `white`, `primary`, `secondary`) may not align with brand palettes.
-- Use **semantic naming** (`brand-primary`, `brand-accent`, `neutral-100`) instead of hardcoded names (`blue`, `red`).
-- This ensures **future-proofing** if brand colours shift.
+
+- WordPress defaults (`black`, `white`, `primary`, `secondary`) may not align with brand palettes.
+- Use **semantic naming** (`brand-primary`, `brand-accent`, `neutral-100`) instead of hardcoded names (`blue`, `red`).
+- This ensures **future-proofing** if brand colours shift.
- Rich Tabor emphasises using **systematic palettes**: base colours + tints/shades.
✅ Recommendation: Keep `base` colours minimal (3–5), then extend with `neutral` and `accent` palettes. Always prefer semantic over literal names.
@@ -254,30 +259,29 @@ The **hybrid approach** is currently best practice:
- Keep `primary`, but remap it to `brand-primary` (#0047AB).
3. **Document the mapping** between Figma tokens and WordPress slugs so developers/designers stay aligned.
-
-
---
## General Advice
-- **Consistency over creativity**: don’t reinvent slugs across projects.
-- **Keep editor UX predictable**: preserve WP defaults where possible so editors recognise controls.
-- **Token-first thinking**: Figma variables → theme.json presets → CSS variables.
-- **Avoid mixing too many systems**: pick `spacingScale` OR `spacingSizes` globally, not both.
-- **Future-proof**: semantic naming ensures flexibility for rebrands.
+- **Consistency over creativity**: don’t reinvent slugs across projects.
+- **Keep editor UX predictable**: preserve WP defaults where possible so editors recognise controls.
+- **Token-first thinking**: Figma variables → theme.json presets → CSS variables.
+- **Avoid mixing too many systems**: pick `spacingScale` OR `spacingSizes` globally, not both.
+- **Future-proof**: semantic naming ensures flexibility for rebrands.
---
## References
+
- Rich Tabor: [Standardizing theme.json spacing](https://rich.blog/standardizing-theme-json-spacing/)
- Rich Tabor: [Standardizing theme.json colours](https://rich.blog/standardizing-theme-json-colors/)
- Rich Tabor: [Standardizing theme.json fonts sizes](https://rich.blog/standardizing-theme-json-font-sizes/)
-- Rich Tabor: [Fluid type scale in theme.json](https://rich.blog/fluid-type-scale-theme-json/)
-- Rich Tabor: [Standardizing theme.json colours](https://rich.blog/standardizing-theme-json-colors/)
-- FullSiteEditing.com: [Global Styles & theme.json](https://fullsiteediting.com/)
+- Rich Tabor: [Fluid type scale in theme.json](https://rich.blog/fluid-type-scale-theme-json/)
+- Rich Tabor: [Standardizing theme.json colours](https://rich.blog/standardizing-theme-json-colors/)
+- FullSiteEditing.com: [Global Styles & theme.json](https://fullsiteediting.com/)
- WordPress Developer Docs: [theme.json reference](https://developer.wordpress.org/themes/global-settings-and-styles/)
-- https://developer.wordpress.org/themes/global-settings-and-styles/settings/spacing/
-- https://developer.wordpress.org/themes/global-settings-and-styles/settings/typography/
-- https://developer.wordpress.org/themes/global-settings-and-styles/settings/color/
+-
+-
+-
---
diff --git a/block-themes/style-variations.md b/docs/wordpress/block-themes/theme.json/style-variations.md
similarity index 99%
rename from block-themes/style-variations.md
rename to docs/wordpress/block-themes/theme.json/style-variations.md
index 6b7d83d..26de32f 100644
--- a/block-themes/style-variations.md
+++ b/docs/wordpress/block-themes/theme.json/style-variations.md
@@ -3,22 +3,26 @@
---
## Best practices
+
- **Style variations**: Visual alternatives for a block via `theme.json`.
- **Block variations**: Structural variations shown at insert time, registered via JS (`wp.blocks.registerBlockVariation`). ([Rich Tabor](https://rich.blog/block-variations/?utm_source=chatgpt.com))
---
## Use when
+
- Use style variations for styling; block variations for altering block structure/configuration.
---
## Limitations
+
- Do not confuse them; they are distinct APIs with different use cases.
---
## Reference links
+
- [Rich Tabor: Block Variations](https://rich.blog/block-variations/)
---
diff --git a/docs/wordpress/block-themes/theme.json/theme-68.json b/docs/wordpress/block-themes/theme.json/theme-68.json
new file mode 100644
index 0000000..d28b3a2
--- /dev/null
+++ b/docs/wordpress/block-themes/theme.json/theme-68.json
@@ -0,0 +1,2563 @@
+{
+ "title": "JSON schema for WordPress block theme global settings and styles",
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "definitions": {
+ "//": {
+ "explainer": "https://developer.wordpress.org/themes/advanced-topics/theme-json/",
+ "createTheme": "https://developer.wordpress.org/themes/",
+ "reference": "https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/"
+ },
+ "refComplete": {
+ "type": "object",
+ "properties": {
+ "ref": {
+ "description": "A reference to another property value. e.g. `styles.color.text`",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ },
+ "settingsAppearanceToolsProperties": {
+ "type": "object",
+ "properties": {
+ "appearanceTools": {
+ "description": "Setting that enables the following UI tools:\n\n- background: backgroundImage, backgroundSize\n- border: color, radius, style, width\n- color: link, heading, button, caption\n- dimensions: aspectRatio, minHeight\n- position: sticky\n- spacing: blockGap, margin, padding\n- typography: lineHeight",
+ "type": "boolean",
+ "default": false
+ }
+ }
+ },
+ "settingsBackgroundProperties": {
+ "type": "object",
+ "properties": {
+ "background": {
+ "description": "Settings related to background.",
+ "type": "object",
+ "properties": {
+ "backgroundImage": {
+ "description": "Allow users to set a background image.",
+ "type": "boolean",
+ "default": false
+ },
+ "backgroundSize": {
+ "description": "Allow users to set values related to the size of a background image, including size, position, and repeat controls.",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsBorderProperties": {
+ "type": "object",
+ "properties": {
+ "border": {
+ "description": "Settings related to borders.",
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Allow users to set custom border colors.",
+ "type": "boolean",
+ "default": false
+ },
+ "radius": {
+ "description": "Allow users to set custom border radius.",
+ "type": "boolean",
+ "default": false
+ },
+ "style": {
+ "description": "Allow users to set custom border styles.",
+ "type": "boolean",
+ "default": false
+ },
+ "width": {
+ "description": "Allow users to set custom border widths.",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsColorProperties": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Settings related to colors.",
+ "type": "object",
+ "properties": {
+ "background": {
+ "description": "Allow users to set background colors.",
+ "type": "boolean",
+ "default": true
+ },
+ "custom": {
+ "description": "Allow users to select custom colors.",
+ "type": "boolean",
+ "default": true
+ },
+ "customDuotone": {
+ "description": "Allow users to create custom duotone filters.",
+ "type": "boolean",
+ "default": true
+ },
+ "customGradient": {
+ "description": "Allow users to create custom gradients.",
+ "type": "boolean",
+ "default": true
+ },
+ "defaultDuotone": {
+ "description": "Allow users to choose filters from the default duotone filter presets.",
+ "type": "boolean",
+ "default": true
+ },
+ "defaultGradients": {
+ "description": "Allow users to choose colors from the default gradients.",
+ "type": "boolean",
+ "default": true
+ },
+ "defaultPalette": {
+ "description": "Allow users to choose colors from the default palette.",
+ "type": "boolean",
+ "default": true
+ },
+ "duotone": {
+ "description": "Duotone presets for the duotone picker.\nDoesn't generate classes or properties.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the duotone preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the duotone preset.",
+ "type": "string"
+ },
+ "colors": {
+ "description": "List of colors from dark to light.",
+ "type": "array",
+ "items": {
+ "description": "CSS hex or rgb string.",
+ "type": "string"
+ }
+ }
+ },
+ "required": ["name", "slug", "colors"],
+ "additionalProperties": false
+ }
+ },
+ "gradients": {
+ "description": "Gradient presets for the gradient picker.\nGenerates a single class (`.has-{slug}-background`) and custom property (`--wp--preset--gradient--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the gradient preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the gradient preset.",
+ "type": "string"
+ },
+ "gradient": {
+ "description": "CSS gradient string.",
+ "type": "string"
+ }
+ },
+ "required": ["name", "slug", "gradient"],
+ "additionalProperties": false
+ }
+ },
+ "link": {
+ "description": "Allow users to set link colors in a block.",
+ "type": "boolean",
+ "default": false
+ },
+ "palette": {
+ "description": "Color palette presets for the color picker.\nGenerates three classes (`.has-{slug}-color`, `.has-{slug}-background-color`, and `.has-{slug}-border-color`) and a single custom property (`--wp--preset--color--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the color preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the color preset.",
+ "type": "string"
+ },
+ "color": {
+ "description": "CSS hex or rgb(a) string.",
+ "type": "string"
+ }
+ },
+ "required": ["name", "slug", "color"],
+ "additionalProperties": false
+ }
+ },
+ "text": {
+ "description": "Allow users to set text colors in a block.",
+ "type": "boolean",
+ "default": true
+ },
+ "heading": {
+ "description": "Allow users to set heading colors in a block.",
+ "type": "boolean",
+ "default": true
+ },
+ "button": {
+ "description": "Allow users to set button colors in a block.",
+ "type": "boolean",
+ "default": true
+ },
+ "caption": {
+ "description": "Allow users to set caption colors in a block.",
+ "type": "boolean",
+ "default": true
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsDimensionsProperties": {
+ "type": "object",
+ "properties": {
+ "dimensions": {
+ "description": "Settings related to dimensions.",
+ "type": "object",
+ "properties": {
+ "aspectRatio": {
+ "description": "Allow users to set an aspect ratio.",
+ "type": "boolean",
+ "default": false
+ },
+ "defaultAspectRatios": {
+ "description": "Allow users to choose aspect ratios from the default set of aspect ratios.",
+ "type": "boolean",
+ "default": true
+ },
+ "aspectRatios": {
+ "description": "Allow users to define aspect ratios for some blocks.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the aspect ratio preset.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the aspect ratio preset.",
+ "type": "string"
+ },
+ "ratio": {
+ "description": "Aspect ratio expressed as a division or decimal.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "minHeight": {
+ "description": "Allow users to set custom minimum height.",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsLayoutProperties": {
+ "type": "object",
+ "properties": {
+ "layout": {
+ "description": "Settings related to layout.",
+ "type": "object",
+ "properties": {
+ "contentSize": {
+ "description": "Sets the max-width of the content.",
+ "type": "string"
+ },
+ "wideSize": {
+ "description": "Sets the max-width of wide (`.alignwide`) content. Also used as the maximum viewport when calculating fluid font sizes",
+ "type": "string"
+ },
+ "allowEditing": {
+ "description": "Disable the layout UI controls.",
+ "type": "boolean",
+ "default": true
+ },
+ "allowCustomContentAndWideSize": {
+ "description": "Enable or disable the custom content and wide size controls.",
+ "type": "boolean",
+ "default": true
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsLightboxProperties": {
+ "type": "object",
+ "properties": {
+ "lightbox": {
+ "description": "Settings related to the lightbox.",
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "description": "Defines whether the lightbox is enabled or not.",
+ "type": "boolean"
+ },
+ "allowEditing": {
+ "description": "Defines whether to show the Lightbox UI in the block editor. If set to `false`, the user won't be able to change the lightbox settings in the block editor.",
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsPositionProperties": {
+ "type": "object",
+ "properties": {
+ "position": {
+ "description": "Settings related to position.",
+ "type": "object",
+ "properties": {
+ "sticky": {
+ "description": "Allow users to set sticky position.",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsShadowProperties": {
+ "type": "object",
+ "properties": {
+ "shadow": {
+ "description": "Settings related to shadows.",
+ "type": "object",
+ "properties": {
+ "defaultPresets": {
+ "description": "Allow users to choose shadows from the default shadow presets.",
+ "type": "boolean",
+ "default": true
+ },
+ "presets": {
+ "description": "Shadow presets for the shadow picker.\nGenerates a single custom property (`--wp--preset--shadow--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the shadow preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the shadow preset.",
+ "type": "string"
+ },
+ "shadow": {
+ "description": "CSS box-shadow value",
+ "type": "string"
+ }
+ },
+ "required": ["name", "slug", "shadow"],
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsSpacingProperties": {
+ "type": "object",
+ "properties": {
+ "spacing": {
+ "description": "Settings related to spacing.",
+ "type": "object",
+ "properties": {
+ "blockGap": {
+ "description": "Enables `--wp--style--block-gap` to be generated from styles.spacing.blockGap.\nA value of `null` instead of `false` further disables layout styles from being generated.",
+ "oneOf": [{ "type": "boolean" }, { "type": "null" }],
+ "default": null
+ },
+ "margin": {
+ "description": "Allow users to set a custom margin.",
+ "type": "boolean",
+ "default": false
+ },
+ "padding": {
+ "description": "Allow users to set a custom padding.",
+ "type": "boolean",
+ "default": false
+ },
+ "units": {
+ "description": "List of units the user can use for spacing values.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "minItems": 1,
+ "default": ["px", "em", "rem", "vh", "vw", "%"]
+ },
+ "customSpacingSize": {
+ "description": "Allow users to set custom space sizes.",
+ "type": "boolean",
+ "default": true
+ },
+ "defaultSpacingSizes": {
+ "description": "Allow users to choose space sizes from the default space size presets.",
+ "type": "boolean",
+ "default": true
+ },
+ "spacingSizes": {
+ "description": "Space size presets for the space size selector.\nGenerates a custom property (`--wp--preset--spacing--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the space size preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Unique identifier for the space size preset. For best cross theme compatibility these should be in the form '10','20','30','40','50','60', etc. with '50' representing the 'Medium' size step. If all slugs begin with a number they will be merged with default and user slugs and sorted numerically.",
+ "type": "string"
+ },
+ "size": {
+ "description": "CSS space-size value, including units.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "spacingScale": {
+ "description": "Settings to auto-generate space size presets for the space size selector.\nGenerates a custom property (--wp--preset--spacing--{slug}`) per preset value.",
+ "type": "object",
+ "properties": {
+ "operator": {
+ "description": "With + or * depending on whether scale is generated by increment or multiplier.",
+ "type": "string",
+ "enum": ["+", "*"],
+ "default": "*"
+ },
+ "increment": {
+ "description": "The amount to increment each step by.",
+ "type": "number",
+ "exclusiveMinimum": 0,
+ "default": 1.5
+ },
+ "steps": {
+ "description": "Number of steps to generate in scale.",
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 10,
+ "default": 7
+ },
+ "mediumStep": {
+ "description": "The value to medium setting in the scale.",
+ "type": "number",
+ "exclusiveMinimum": 0,
+ "default": 1.5
+ },
+ "unit": {
+ "description": "Unit that the scale uses, eg. rem, em, px.",
+ "type": "string",
+ "enum": [
+ "px",
+ "em",
+ "rem",
+ "%",
+ "vw",
+ "svw",
+ "lvw",
+ "dvw",
+ "vh",
+ "svh",
+ "lvh",
+ "dvh",
+ "vi",
+ "svi",
+ "lvi",
+ "dvi",
+ "vb",
+ "svb",
+ "lvb",
+ "dvb",
+ "vmin",
+ "svmin",
+ "lvmin",
+ "dvmin",
+ "vmax",
+ "svmax",
+ "lvmax",
+ "dvmax"
+ ],
+ "default": "rem"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsTypographyProperties": {
+ "type": "object",
+ "properties": {
+ "typography": {
+ "description": "Settings related to typography.",
+ "type": "object",
+ "properties": {
+ "defaultFontSizes": {
+ "description": "Allow users to choose font sizes from the default font size presets.",
+ "type": "boolean",
+ "default": true
+ },
+ "customFontSize": {
+ "description": "Allow users to set custom font sizes.",
+ "type": "boolean",
+ "default": true
+ },
+ "fontStyle": {
+ "description": "Allow users to set custom font styles.",
+ "type": "boolean",
+ "default": true
+ },
+ "fontWeight": {
+ "description": "Allow users to set custom font weights.",
+ "type": "boolean",
+ "default": true
+ },
+ "fluid": {
+ "description": "Enables fluid typography and allows users to set global fluid typography parameters.",
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "minFontSize": {
+ "description": "Allow users to set a global minimum font size boundary in px, rem or em. Custom font sizes below this value will not be clamped, and all calculated minimum font sizes will be, at a minimum, this value.",
+ "type": "string"
+ },
+ "maxViewportWidth": {
+ "description": "Allow users to set custom a max viewport width in px, rem or em, used to set the maximum size boundary of a fluid font size.",
+ "type": "string"
+ },
+ "minViewportWidth": {
+ "description": "Allow users to set a custom min viewport width in px, rem or em, used to set the minimum size boundary of a fluid font size.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ },
+ {
+ "type": "boolean"
+ }
+ ],
+ "default": false
+ },
+ "letterSpacing": {
+ "description": "Allow users to set custom letter spacing.",
+ "type": "boolean",
+ "default": true
+ },
+ "lineHeight": {
+ "description": "Allow users to set custom line height.",
+ "type": "boolean",
+ "default": false
+ },
+ "textAlign": {
+ "description": "Allow users to set the text align.",
+ "type": "boolean",
+ "default": true
+ },
+ "textColumns": {
+ "description": "Allow users to set the number of text columns.",
+ "type": "boolean",
+ "default": false
+ },
+ "textDecoration": {
+ "description": "Allow users to set custom text decorations.",
+ "type": "boolean",
+ "default": true
+ },
+ "writingMode": {
+ "description": "Allow users to set the writing mode.",
+ "type": "boolean",
+ "default": false
+ },
+ "textTransform": {
+ "description": "Allow users to set custom text transforms.",
+ "type": "boolean",
+ "default": true
+ },
+ "dropCap": {
+ "description": "Enable drop cap.",
+ "type": "boolean",
+ "default": true
+ },
+ "fontSizes": {
+ "description": "Font size presets for the font size selector.\nGenerates a single class (`.has-{slug}-color`) and custom property (`--wp--preset--font-size--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the font size preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the font size preset.",
+ "type": "string"
+ },
+ "size": {
+ "description": "CSS font-size value, including units.",
+ "type": "string"
+ },
+ "fluid": {
+ "description": "Specifies the minimum and maximum font size value of a fluid font size. Set to `false` to bypass fluid calculations and use the static `size` value.",
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "min": {
+ "description": "A min font size for fluid font size calculations in px, rem or em.",
+ "type": "string"
+ },
+ "max": {
+ "description": "A max font size for fluid font size calculations in px, rem or em.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ },
+ {
+ "type": "boolean"
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "fontFamilies": {
+ "description": "Font family presets for the font family selector.\nGenerates a single custom property (`--wp--preset--font-family--{slug}`) per preset value.",
+ "type": "array",
+ "items": {
+ "description": "Font family preset",
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Name of the font family preset, translatable.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Kebab-case unique identifier for the font family preset.",
+ "type": "string"
+ },
+ "fontFamily": {
+ "description": "CSS font-family value.",
+ "type": "string"
+ },
+ "fontFace": {
+ "description": "Array of font-face declarations.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "fontFamily": {
+ "description": "CSS font-family value.",
+ "type": "string",
+ "default": ""
+ },
+ "fontStyle": {
+ "description": "CSS font-style value.",
+ "type": "string",
+ "default": "normal"
+ },
+ "fontWeight": {
+ "description": "List of available font weights, separated by a space.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "integer"
+ }
+ ],
+ "default": "400"
+ },
+ "fontDisplay": {
+ "description": "CSS font-display value.",
+ "type": "string",
+ "enum": ["auto", "block", "fallback", "swap", "optional"],
+ "default": "fallback"
+ },
+ "src": {
+ "description": "Paths or URLs to the font files.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ],
+ "default": []
+ },
+ "fontStretch": {
+ "description": "CSS font-stretch value.",
+ "type": "string"
+ },
+ "ascentOverride": {
+ "description": "CSS ascent-override value.",
+ "type": "string"
+ },
+ "descentOverride": {
+ "description": "CSS descent-override value.",
+ "type": "string"
+ },
+ "fontVariant": {
+ "description": "CSS font-variant value.",
+ "type": "string"
+ },
+ "fontFeatureSettings": {
+ "description": "CSS font-feature-settings value.",
+ "type": "string"
+ },
+ "fontVariationSettings": {
+ "description": "CSS font-variation-settings value.",
+ "type": "string"
+ },
+ "lineGapOverride": {
+ "description": "CSS line-gap-override value.",
+ "type": "string"
+ },
+ "sizeAdjust": {
+ "description": "CSS size-adjust value.",
+ "type": "string"
+ },
+ "unicodeRange": {
+ "description": "CSS unicode-range value.",
+ "type": "string"
+ }
+ },
+ "required": ["fontFamily", "src"],
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "settingsCustomProperties": {
+ "type": "object",
+ "properties": {
+ "custom": {
+ "$ref": "#/definitions/settingsCustomAdditionalProperties"
+ }
+ }
+ },
+ "settingsProperties": {
+ "allOf": [
+ { "$ref": "#/definitions/settingsAppearanceToolsProperties" },
+ { "$ref": "#/definitions/settingsBackgroundProperties" },
+ { "$ref": "#/definitions/settingsBorderProperties" },
+ { "$ref": "#/definitions/settingsColorProperties" },
+ { "$ref": "#/definitions/settingsDimensionsProperties" },
+ { "$ref": "#/definitions/settingsLayoutProperties" },
+ { "$ref": "#/definitions/settingsLightboxProperties" },
+ { "$ref": "#/definitions/settingsPositionProperties" },
+ { "$ref": "#/definitions/settingsShadowProperties" },
+ { "$ref": "#/definitions/settingsSpacingProperties" },
+ { "$ref": "#/definitions/settingsTypographyProperties" },
+ { "$ref": "#/definitions/settingsCustomProperties" }
+ ]
+ },
+ "settingsPropertyNames": {
+ "enum": [
+ "appearanceTools",
+ "background",
+ "border",
+ "color",
+ "dimensions",
+ "layout",
+ "lightbox",
+ "position",
+ "shadow",
+ "spacing",
+ "typography",
+ "custom"
+ ]
+ },
+ "settingsPropertiesComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/settingsProperties"
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/settingsPropertyNames"
+ }
+ }
+ ]
+ },
+ "settingsBlocksPropertiesComplete": {
+ "description": "Settings defined on a per-block basis.",
+ "type": "object",
+ "properties": {
+ "core/archives": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/audio": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/avatar": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/block": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/button": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/buttons": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/calendar": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/categories": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/code": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/column": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/columns": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-author-avatar": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-author-name": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-content": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-date": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-edit-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-reply-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-pagination": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-pagination-next": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-pagination-numbers": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-pagination-previous": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comments-title": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/comment-template": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/cover": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/details": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/embed": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/file": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/footnotes": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/freeform": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/gallery": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/group": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/heading": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/home-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/html": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/image": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/latest-comments": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/latest-posts": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/list": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/list-item": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/loginout": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/media-text": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/missing": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/more": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/navigation": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/navigation-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/navigation-submenu": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/nextpage": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/page-list": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/page-list-item": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/paragraph": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-author": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-author-biography": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-author-name": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-comment": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-comments-count": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-comments-form": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-comments-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-content": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-date": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-excerpt": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-featured-image": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-navigation-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-template": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-terms": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/post-title": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/preformatted": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/pullquote": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-no-results": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-pagination": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-pagination-next": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-pagination-numbers": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-pagination-previous": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-title": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/query-total": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/quote": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/read-more": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/rss": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/search": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/separator": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/shortcode": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/site-logo": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/site-tagline": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/site-title": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/social-link": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/social-links": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/spacer": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/table": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/tag-cloud": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/template-part": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/term-description": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/text-columns": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/verse": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/video": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/widget-area": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/legacy-widget": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ },
+ "core/widget-group": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ }
+ },
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/settingsPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ },
+ "settingsCustomAdditionalProperties": {
+ "description": "Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name.",
+ "type": "object",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "number"
+ },
+ {
+ "$ref": "#/definitions/settingsCustomAdditionalProperties"
+ }
+ ]
+ }
+ },
+ "stylesProperties": {
+ "type": "object",
+ "properties": {
+ "background": {
+ "description": "Background styles.",
+ "type": "object",
+ "properties": {
+ "backgroundImage": {
+ "description": "Sets the `background-image` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ { "$ref": "#/definitions/refComplete" },
+ {
+ "type": "object",
+ "properties": {
+ "url": {
+ "description": "A URL to an image file, or a path to a file relative to the theme root directory, and prefixed with `file:`, e.g., 'file:./path/to/file.png'.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
+ },
+ "backgroundPosition": {
+ "description": "Sets the `background-position` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "backgroundRepeat": {
+ "description": "Sets the `background-repeat` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "backgroundSize": {
+ "description": "Sets the `background-size` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "backgroundAttachment": {
+ "description": "Sets the `background-attachment` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "border": {
+ "description": "Border styles.",
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "radius": {
+ "description": "Sets the `border-radius` CSS property.",
+ "anyOf": [
+ { "type": "string" },
+ { "$ref": "#/definitions/refComplete" },
+ {
+ "type": "object",
+ "properties": {
+ "topLeft": {
+ "description": "Sets the `border-top-left-radius` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ },
+ "topRight": {
+ "description": "Sets the `border-top-right-radius` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ },
+ "bottomLeft": {
+ "description": "Sets the `border-bottom-left-radius` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ },
+ "bottomRight": {
+ "description": "Sets the `border-bottom-right-radius` CSS property.",
+ "oneOf": [
+ { "type": "string" },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ "style": {
+ "description": "Sets the `border-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "top": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-top-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `border-top-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-top-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "right": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-right-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `border-right-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-right-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "bottom": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-bottom-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `border-bottom-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-bottom-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "left": {
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `border-left-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `border-left-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `border-left-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ },
+ "color": {
+ "description": "Color styles.",
+ "type": "object",
+ "properties": {
+ "background": {
+ "description": "Sets the `background-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "gradient": {
+ "description": "Sets the `background` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "text": {
+ "description": "Sets the `color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "css": {
+ "description": "Sets custom CSS to apply styling not covered by other theme.json properties.",
+ "type": "string"
+ },
+ "dimensions": {
+ "description": "Dimensions styles.",
+ "type": "object",
+ "properties": {
+ "aspectRatio": {
+ "description": "Sets the `aspect-ratio` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "minHeight": {
+ "description": "Sets the `min-height` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ }
+ },
+ "filter": {
+ "description": "CSS and SVG filter styles.",
+ "type": "object",
+ "properties": {
+ "duotone": {
+ "description": "Sets the duotone filter.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "outline": {
+ "description": "Outline styles.",
+ "type": "object",
+ "properties": {
+ "color": {
+ "description": "Sets the `outline-color` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "offset": {
+ "description": "Sets the `outline-offset` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "style": {
+ "description": "Sets the `outline-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "width": {
+ "description": "Sets the `outline-width` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "shadow": {
+ "description": "Box shadow styles.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "spacing": {
+ "description": "Spacing styles.",
+ "type": "object",
+ "properties": {
+ "blockGap": {
+ "description": "Sets the `--wp--style--block-gap` CSS custom property when settings.spacing.blockGap is true.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "margin": {
+ "description": "Margin styles.",
+ "type": "object",
+ "properties": {
+ "top": {
+ "description": "Sets the `margin-top` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "right": {
+ "description": "Sets the `margin-right` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "bottom": {
+ "description": "Sets the `margin-bottom` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "left": {
+ "description": "Sets the `margin-left` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ },
+ "padding": {
+ "description": "Padding styles.",
+ "type": "object",
+ "properties": {
+ "top": {
+ "description": "Sets the `padding-top` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "right": {
+ "description": "Sets the `padding-right` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "bottom": {
+ "description": "Sets the `padding-bottom` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "left": {
+ "description": "Sets the `padding-left` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ },
+ "typography": {
+ "description": "Typography styles.",
+ "type": "object",
+ "properties": {
+ "fontFamily": {
+ "description": "Sets the `font-family` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "fontSize": {
+ "description": "Sets the `font-size` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "fontStyle": {
+ "description": "Sets the `font-style` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "fontWeight": {
+ "description": "Sets the `font-weight` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "letterSpacing": {
+ "description": "Sets the `letter-spacing` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "lineHeight": {
+ "description": "Sets the `line-height` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "textAlign": {
+ "description": "Sets the `text-align` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "textColumns": {
+ "description": "Sets the `column-count` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "textDecoration": {
+ "description": "Sets the `text-decoration` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "writingMode": {
+ "description": "Sets the `writing-mode` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ },
+ "textTransform": {
+ "description": "Sets the `text-transform` CSS property.",
+ "oneOf": [{ "type": "string" }, { "$ref": "#/definitions/refComplete" }]
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "stylesPropertyNames": {
+ "enum": [
+ "background",
+ "border",
+ "color",
+ "css",
+ "dimensions",
+ "filter",
+ "outline",
+ "shadow",
+ "spacing",
+ "typography"
+ ]
+ },
+ "stylesPropertiesComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "$ref": "#/definitions/stylesPropertyNames"
+ }
+ }
+ ]
+ },
+ "stylesElementsPseudoSelectorsProperties": {
+ "type": "object",
+ "properties": {
+ ":active": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":any-link": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":focus": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":focus-visible": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":hover": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":link": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ ":visited": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ }
+ }
+ },
+ "stylesElementsPseudoSelectorsPropertyNames": {
+ "enum": [":active", ":any-link", ":focus", ":focus-visible", ":hover", ":link", ":visited"]
+ },
+ "stylesElementsPropertiesComplete": {
+ "description": "Styles defined on a per-element basis using the element's selector.",
+ "type": "object",
+ "properties": {
+ "button": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties"
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "link": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties"
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "heading": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h1": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h2": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h3": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h4": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h5": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "h6": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "caption": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ },
+ "cite": {
+ "$ref": "#/definitions/stylesPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ },
+ "stylesBlocksPropertiesComplete": {
+ "description": "Styles defined on a per-block basis using the block's selector.",
+ "type": "object",
+ "properties": {
+ "core/archives": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/audio": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/avatar": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/block": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/button": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/buttons": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/calendar": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/categories": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/code": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/column": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/columns": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-author-avatar": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-author-name": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-content": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-date": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-edit-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-reply-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-pagination": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-pagination-next": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-pagination-numbers": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-pagination-previous": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comments-title": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/comment-template": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/cover": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/details": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/embed": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/file": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/footnotes": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/freeform": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/gallery": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/group": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/heading": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/home-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/html": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/image": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/latest-comments": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/latest-posts": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/list": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/list-item": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/loginout": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/media-text": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/missing": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/more": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/navigation": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/navigation-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/navigation-submenu": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/nextpage": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/page-list": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/page-list-item": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/paragraph": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-author": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-author-biography": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-author-name": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-comment": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-comments-count": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-comments-form": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-comments-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-content": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-date": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-excerpt": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-featured-image": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-navigation-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-template": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-terms": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/post-title": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/preformatted": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/pullquote": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-no-results": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-pagination": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-pagination-next": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-pagination-numbers": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-pagination-previous": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-title": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/query-total": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/quote": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/read-more": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/rss": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/search": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/separator": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/shortcode": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/site-logo": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/site-tagline": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/site-title": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/social-link": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/social-links": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/spacer": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/table": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/tag-cloud": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/template-part": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/term-description": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/text-columns": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/verse": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/video": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/widget-area": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/legacy-widget": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/widget-group": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ }
+ },
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ }
+ },
+ "additionalProperties": false
+ },
+ "stylesPropertiesAndElementsComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "variations": {
+ "$ref": "#/definitions/stylesVariationsPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements", "variations"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "stylesVariationsProperties": {
+ "type": "object",
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesVariationProperties"
+ }
+ }
+ },
+ "stylesVariationProperties": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "blocks": {
+ "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements", "blocks"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "stylesVariationsPropertiesComplete": {
+ "type": "object",
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesVariationPropertiesComplete"
+ }
+ }
+ },
+ "stylesVariationPropertiesComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "blocks": {
+ "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements", "blocks"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "stylesVariationBlocksPropertiesComplete": {
+ "type": "object",
+ "properties": {
+ "core/archives": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/audio": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/avatar": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/block": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/button": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/buttons": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/calendar": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/categories": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/code": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/column": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/columns": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-author-avatar": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-author-name": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-content": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-date": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-edit-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-reply-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination-next": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination-numbers": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination-previous": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-template": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/cover": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/details": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/embed": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/file": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/footnotes": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/freeform": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/gallery": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/group": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/heading": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/home-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/html": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/image": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/latest-comments": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/latest-posts": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/list": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/list-item": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/loginout": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/media-text": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/missing": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/more": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/navigation": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/navigation-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/navigation-submenu": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/nextpage": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/page-list": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/page-list-item": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/paragraph": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-author": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-author-biography": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-author-name": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comment": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comments-count": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comments-form": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comments-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-content": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-date": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-excerpt": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-featured-image": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-navigation-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-template": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-terms": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/preformatted": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/pullquote": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-no-results": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination-next": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination-numbers": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination-previous": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-total": {
+ "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
+ },
+ "core/quote": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/read-more": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/rss": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/search": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/separator": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/shortcode": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/site-logo": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/site-tagline": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/site-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/social-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/social-links": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/spacer": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/table": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/tag-cloud": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/template-part": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/term-description": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/text-columns": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/verse": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/video": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/widget-area": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/legacy-widget": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/widget-group": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ }
+ },
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ },
+ "stylesVariationBlockPropertiesComplete": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements"]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "type": "object",
+ "properties": {
+ "$schema": {
+ "description": "JSON schema URI for theme.json.",
+ "type": "string"
+ },
+ "version": {
+ "description": "Version of theme.json to use.",
+ "type": "integer",
+ "const": 3
+ },
+ "title": {
+ "description": "Title of the global styles variation. If not defined, the file name will be used.",
+ "type": "string"
+ },
+ "slug": {
+ "description": "Slug of the global styles variation. If not defined, the kebab-case title will be used.",
+ "type": "string"
+ },
+ "description": {
+ "description": "Description of the global styles variation.",
+ "type": "string"
+ },
+ "blockTypes": {
+ "description": "List of block types that can use the block style variation this theme.json file represents.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "settings": {
+ "description": "Settings for the block editor and individual blocks. These include things like:\n- Which customization options should be available to the user. \n- The default colors, font sizes... available to the user. \n- CSS custom properties and class names used in styles.\n- And the default layout of the editor (widths and available alignments).",
+ "allOf": [
+ {
+ "$ref": "#/definitions/settingsProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "useRootPaddingAwareAlignments": {
+ "description": "Enables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block.\n\nPlease note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately.",
+ "type": "boolean",
+ "default": false
+ },
+ "blocks": {
+ "$ref": "#/definitions/settingsBlocksPropertiesComplete"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/settingsPropertyNames"
+ },
+ {
+ "enum": ["useRootPaddingAwareAlignments", "blocks"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "styles": {
+ "description": "Organized way to set CSS properties. Styles in the top-level will be added in the `body` selector.",
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "blocks": {
+ "$ref": "#/definitions/stylesBlocksPropertiesComplete"
+ },
+ "variations": {
+ "$ref": "#/definitions/stylesVariationsProperties"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "propertyNames": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/stylesPropertyNames"
+ },
+ {
+ "enum": ["elements", "blocks", "variations"]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "customTemplates": {
+ "description": "Additional metadata for custom templates defined in the templates folder.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Filename, without extension, of the template in the templates folder.",
+ "type": "string"
+ },
+ "title": {
+ "description": "Title of the template, translatable.",
+ "type": "string"
+ },
+ "postTypes": {
+ "description": "List of post types that can use this custom template.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": ["page"]
+ }
+ },
+ "required": ["name", "title"],
+ "additionalProperties": false
+ }
+ },
+ "templateParts": {
+ "description": "Additional metadata for template parts defined in the parts folder.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Filename, without extension, of the template in the parts folder.",
+ "type": "string"
+ },
+ "title": {
+ "description": "Title of the template, translatable.",
+ "type": "string"
+ },
+ "area": {
+ "description": "The area the template part is used for. Block variations for `header` and `footer` values exist and will be used when the area is set to one of those.",
+ "type": "string",
+ "default": "uncategorized"
+ }
+ },
+ "required": ["name"],
+ "additionalProperties": false
+ }
+ },
+ "patterns": {
+ "description": "An array of pattern slugs to be registered from the Pattern Directory.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": ["version"],
+ "additionalProperties": false
+}
diff --git a/docs/wordpress/block-themes/theme.json/typesets.md b/docs/wordpress/block-themes/theme.json/typesets.md
new file mode 100644
index 0000000..20fcaf7
--- /dev/null
+++ b/docs/wordpress/block-themes/theme.json/typesets.md
@@ -0,0 +1,13 @@
+# Typesets (Font Size Presets)
+
+## The file style-variations.md provides a concise guide to the differences between style variations and block variations in WordPress block development. It explains that style variations are visual alternatives for blocks defined via theme.json, while block variations are structural alternatives registered with JavaScript. The document outlines best practices, use cases, and limitations, emphasizing not to confuse the two APIs. It also includes a reference link for further reading
+
+**Best practices**
+
+- Leverage new **typeset support** in WordPress 6.6 for consistent font-size presets. ([Rich Tabor](https://rich.blog/wordpress-6-6/?utm_source=chatgpt.com))
+
+---
+
+## When to use
+
+---
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..c0382ca
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,17 @@
+// ESLint v9 Flat Config (optional). Remove .eslintrc.* if using this.
+import js from '@eslint/js';
+import ts from 'typescript-eslint';
+import prettier from 'eslint-plugin-prettier';
+
+export default [
+ js.configs.recommended,
+ ...ts.configs.recommended,
+ {
+ files: ['**/*.{js,ts,tsx,jsx}'],
+ ignores: ['node_modules/**', 'build/**', 'dist/**'],
+ plugins: { prettier },
+ rules: {
+ 'prettier/prettier': 'warn',
+ },
+ },
+];
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 0000000..07ae4e3
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,20 @@
+// ESLint v9+ Flat Config (optional). If you use this, remove .eslintrc.*
+import js from "@eslint/js";
+import tseslint from "typescript-eslint";
+import eslintPluginPrettier from "eslint-plugin-prettier";
+
+export default [
+ js.configs.recommended,
+ ...tseslint.configs.recommended,
+ {
+ files: ["**/*.{js,cjs,mjs,ts,tsx}"],
+ languageOptions: {
+ ecmaVersion: 2022,
+ sourceType: "module"
+ },
+ plugins: { prettier: eslintPluginPrettier },
+ rules: {
+ "prettier/prettier": "warn"
+ }
+ }
+];
diff --git a/extensions.json b/extensions.json
new file mode 100644
index 0000000..668d23f
--- /dev/null
+++ b/extensions.json
@@ -0,0 +1,56 @@
+{
+ "recommendations": [
+ // AI Related Extensions - Advanced AI assistance for development
+ "anthropic.claude-code",
+ "google.gemini-cli-vscode-ide-companion",
+ "google.geminicodeassist",
+ "coderabbit.coderabbit-vscode",
+ "openai.chatgpt",
+
+ // GitHub Extensions - Essential GitHub workflow tools
+ "github.codespaces",
+ "github.copilot",
+ "github.copilot-chat",
+ "github.remotehub",
+ "github.vscode-github-actions",
+ "github.vscode-pull-request-github",
+ "eamodio.gitlens",
+ "mhutchie.git-graph",
+
+ // Microsoft Extensions - Official Microsoft development tools
+ "ms-vscode-remote.remote-containers",
+ "ms-vscode-remote.remote-ssh",
+ "ms-vscode-remote.remote-ssh-edit",
+ "ms-vscode-remote.remote-wsl",
+ "ms-vscode-remote.vscode-remote-extensionpack",
+ "ms-vscode.live-server",
+ "ms-vscode.remote-explorer",
+ "ms-vscode.remote-repositories",
+ "ms-vscode.vscode-github-issue-notebooks",
+ "ms-vscode.vscode-speech",
+ "ms-vscode.wordcount",
+
+ // Dev Container Extensions - Docker and container development
+ "ms-vscode-remote.vscode-remote-extensionpack",
+
+ // Unit Testing Extensions - Automated testing tools
+ "ms-playwright.playwright",
+
+ // Linting Extensions - Code quality and formatting
+ "esbenp.prettier-vscode",
+ "davidanson.vscode-markdownlint",
+ "michelemelluso.code-beautifier",
+ "dbaeumer.vscode-eslint",
+
+ // JavaScript Testing - Jest and testing tools
+ "orta.vscode-jest",
+ "christian-kohler.npm-intellisense",
+
+ // JSON and Configuration - Enhanced JSON support
+ "zainchen.json",
+ "quicktype.quicktype",
+
+ // Core development tools
+ "editorconfig.editorconfig"
+ ]
+}
diff --git a/frontmatter/YAML Frontmatter Cheat Sheet.md b/frontmatter/YAML Frontmatter Cheat Sheet.md
deleted file mode 100644
index 0b13ec8..0000000
--- a/frontmatter/YAML Frontmatter Cheat Sheet.md
+++ /dev/null
@@ -1,525 +0,0 @@
-# **YAML Frontmatter Cheat Sheet for GitHub Templates and AI Agent Configurations**
-
-## **GitHub Issue Template Frontmatter (Issue Forms)**
-
-GitHub **issue templates** can use a YAML frontmatter (especially for the new **Issue Forms**) to define metadata and form fields. All issue form files **must** begin with at least three keys: `name`, `description` (often called “about” in legacy templates), and `body`[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=All%20issue%20form%20configuration%20files,value%20pairs). Additional optional keys let you preassign labels, assignees, etc. Here are the top-level frontmatter fields for an issue form template[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,repository%2C%20it%20will%20not%20be)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,using%20this%20template%20to%20have):
-
-* **`name`** – Unique name for the template (appears in template picker UI) **(required)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,Required%20String).
-
-* **`description`** – Short explanation of the template’s purpose (shown in picker UI) **(required)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=templates%2C%20including%20Markdown%20templates,Required%20String).
-
-* **`body`** – An array defining the form fields and content blocks for the issue form **(required)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,assigned%20to%20issues%20created%20with).
-
-* **`title`** – Default title that will pre-fill in the new issue title input **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=template,Optional%20String).
-
-* **`labels`** – Labels to auto-apply on issue creation (array or comma-separated) **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,delimited%20string).
-
-* **`assignees`** – GitHub usernames to auto-assign the issue to (array or comma-separated) **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,repository%2C%20it%20will%20not%20be).
-
-* **`projects`** – GitHub Projects to auto-add the issue to (format `"OWNER/PROJECT-NUMBER"`) **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=to%20create%20a%20shared%20syntax,delimited%20string).
-
-* **`type`** – Issue type to assign (if your organization uses custom issue types) **(optional)**[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,created%20with%20this%20template%20will).
-
-Below is an **example** of a comprehensive issue form YAML frontmatter, including a variety of field types in the `body`. Comments (`# ...`) are added to explain each parameter and best practices:
-
-`---`
-`name: "Bug Report" # Template name (must be unique in repo)`
-`description: "Report a bug in the project." # Shown in the new issue template chooser`
-`title: "[Bug]: " # Default issue title prefix`
-`labels: ["bug", "needs-triage"] # Labels to apply automatically`
-`assignees: ["octocat"] # Users to assign by default`
-`projects: ["my-org/42"] # Add issue to project board (org/project-number)`
-`type: bug # Issue type (if using typed issues in org)`
-
-`body:`
- `- type: markdown`
- `attributes:`
- `value: "## Thank you for reporting a bug!\nPlease fill out the sections below."`
- `# ^ A static guidance section (Markdown instructions for the user).`
- `# Note: Use quotes for text containing '#' or special YAML chars:contentReference[oaicite:11]{index=11},`
- `# and use '|' for multi-line content as shown above.`
-
- `- type: input`
- `id: "contact"`
- `attributes:`
- `label: "Contact Details"`
- `description: "How can the team reach you for more info?"`
- `placeholder: "e.g. email@example.com"`
- `value: "" # default can be left blank`
- `validations:`
- `required: false # mark field optional (true would prevent submission if empty)`
-
- `- type: textarea`
- `id: "steps"`
- `attributes:`
- `label: "Steps to Reproduce"`
- `description: "Provide step-by-step instructions to reproduce the issue."`
- `placeholder: |`
- `1. Step one...`
- `2. Step two...`
- `3. *Feel free to add more steps as needed...*`
- `value: "" # you can pre-fill common steps or leave empty`
- `render: markdown # if provided, the submitted text will be formatted as a code block of this type (e.g. markdown, bash)`
- `validations:`
- `required: true # this textarea must be filled in`
-
- `- type: dropdown`
- `id: "browser"`
- `attributes:`
- `label: "Affected Browser(s)"`
- `description: "Which web browsers show the issue?"`
- `options:`
- `- "Firefox"`
- `- "Chrome"`
- `- "Safari"`
- `- "Edge"`
- `multiple: true # allow multiple selections`
- `validations:`
- `required: true # at least one option must be selected`
-
- `- type: checkboxes`
- `id: "agree"`
- `attributes:`
- `label: "Code of Conduct Agreement"`
- `description: "Please confirm:"`
- `options:`
- `- label: "I have searched for duplicate issues"`
- `required: true # this box must be checked to submit (ensures reporter did a search)`
- `- label: "I agree to follow the project’s Code of Conduct"`
- `required: true`
-`---`
-
-In the **`body`** array above, we demonstrated each supported input type:
-
-* **Markdown (`type: markdown`)** – Just static text guidance (not included in final issue content). Use this for instructions or banners. *Tip:* If using `#` in the text (for headings), wrap the value in quotes to prevent YAML treating it as a comment[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,if%20we%20need%20more%20info).
-
-* **Text Input (`type: input`)** – Single-line text field. Supports `label`, `description`, `placeholder`, `value` (default text), and validations like `required`[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=%23%23%23%20Current%20Behavior%3A%20%3C%21,)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=1.%20See%20error...%20).
-
-* **Textarea (`type: textarea`)** – Multi-line text field for longer input. Supports the same attributes as input, plus `render` (to automatically format user text as a code block of a given language)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=attributes%3A%20label%3A%20Relevant%20log%20output,attributes%3A%20label%3A%20Code%20of%20Conduct)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=description%3A%20Please%20copy%20and%20paste,Code%20of%20Conduct%5D%28https%3A%2F%2Fexample.com).
-
-* **Dropdown (`type: dropdown`)** – Single or multi-select from a list of options. Requires an `options` list. You can set `multiple: true` for multi-select. If you include a `default:` index (0-based) in attributes, that option will be pre-selected[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=id%3A%20version%20attributes%3A%20label%3A%20Version,3%20%28Edge%29%20default%3A%200%20validations). Validation `required: true` means the user must select at least one[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,type%3A%20dropdown).
-
-* **Checkboxes (`type: checkboxes`)** – A group of one or more checkbox items. Each option has a `label` (supports basic Markdown) and optionally `required: true` if that particular box must be checked[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=id%3A%20terms%20attributes%3A%20label%3A%20Code,Code%20of%20Conduct%20required%3A%20true). If any checkbox option is marked required, the form won’t submit until it’s checked (useful for “I agree” confirmations).
-
-**Best Practices:**
-
-* **Formatting:** Enclose the frontmatter between `---` lines at the top of the template file. Indentation is significant in YAML – use consistent two-space indents for nested fields.
-
-* **Quoting:** Quote strings that contain special characters (like `:` or `#`) or begin with square brackets. For instance, the `title` value `[Bug]:` is quoted in YAML[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=name%3A%20%20Bug%20description%3A%20File,already%20exists%20for%20the%20bug) to avoid parsing issues.
-
-* **Multiline Text:** Use the pipe `|` in YAML to input multiline default text or placeholders (as shown for the steps placeholder above) so that line breaks are preserved[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,if%20we%20need%20more%20info).
-
-* **Required Fields:** Use `validations: required: true` judiciously – only when the issue cannot be submitted without that info. Otherwise, leave as optional to not frustrate contributors.
-
-* **Unique IDs:** The `id` fields in inputs aren’t mandatory, but assigning them (alphanumeric, `-` or `_` only) can help reference responses programmatically (or for future automation).
-
-* **Keep it Short:** While you can include many fields, try not to overwhelm the contributor. Only ask for information that is necessary to triage the issue.
-
-## **GitHub Pull Request Template Frontmatter**
-
-Pull request templates are simpler – GitHub **does not currently support form-style PR templates with YAML-defined inputs** (issue forms are for issues only)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=Issue%20forms%20are%20not%20supported,request%20template%20for%20your%20repository)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=When%20a%20contributor%20fills%20out,issue%20created%20through%20other%20methods). However, you *can* include a YAML frontmatter at the top of a PR template file to pre-specify metadata like title, labels, etc., but as of now, **GitHub ignores these frontmatter fields for PRs** – any frontmatter will simply remain in the text of the PR body (not parsed out)[stackoverflow.com](https://stackoverflow.com/questions/66392676/github-pull-request-template-detect-yaml-front-matter-using-config-yml-and-apply#:~:text=5). In practice, this means the YAML block would just be visible to users opening the PR, which is usually undesirable. (There is no PR template picker UI, unlike issues.)
-
-For completeness, here are the **frontmatter keys** that parallel issue templates (even though they won’t be auto-applied by GitHub for PRs as of 2025):
-
-* **`name`** – Name of the PR template (if multiple templates via query parameter).
-
-* **`about`** – Description of the template’s use.
-
-* **`title`** – Default title for pull requests using this template.
-
-* **`labels`** – Labels to add to the PR.
-
-* **`assignees`** – Users to assign to the PR.
-
-These keys mirror the issue template keys (note: here it’s `about` instead of `description`). For example, a PR template might start like:
-
-`---`
-`name: "Feature PR Template"`
-`about: "Use this template for pull requests adding a new feature"`
-`title: "feat: "`
-`labels: enhancement, needs-review`
-`assignees: octocat`
-`---`
-
-*Even though you can include such a frontmatter in a PR template file, GitHub will currently just display it as text in the PR body[stackoverflow.com](https://stackoverflow.com/questions/66392676/github-pull-request-template-detect-yaml-front-matter-using-config-yml-and-apply#:~:text=5).* Therefore, many repositories omit YAML frontmatter in PR templates altogether, and instead just provide a structured markdown checklist or guidance for the contributor. A good pull request template includes sections like “Linked Issue”, “Summary of Changes”, “Testing Instructions”, etc., written as comments or headings in Markdown (since those will guide the PR author).
-
-**Best Practices:**
-
-* If you include a YAML header in a PR template, be aware it won’t be processed by GitHub (it might confuse contributors seeing raw `---` lines). It’s often better to stick to plain Markdown for PR templates.
-
-* Use HTML comments (``) in the template to provide guidance that won’t appear in the final PR description. For example, ``.
-
-* Encourage linking issues in the PR body (e.g., “Closes \#123”) and including screenshots or test output if applicable. These aren’t frontmatter parameters, but important content for PR quality.
-
-*(Note: GitHub might add support for parsing PR template frontmatter in the future, but at the time of writing it’s not implemented[stackoverflow.com](https://stackoverflow.com/questions/66392676/github-pull-request-template-detect-yaml-front-matter-using-config-yml-and-apply#:~:text=5).)*
-
-## **GitHub Saved Replies**
-
-GitHub **saved replies** are canned responses for commenting on issues and PRs. They **do not use file-based YAML frontmatter** at all – instead, they are created and managed via the GitHub web UI (under your profile’s **Saved replies** settings)[docs.github.com](https://docs.github.com/en/get-started/writing-on-github/working-with-saved-replies#:~:text=Creating%20a%20saved%20reply). Each saved reply simply has two pieces of metadata:
-
-* **Title** – a short name you give the saved reply (for your own reference in the UI).
-
-* **Body content** – the actual text (which can include Markdown formatting) that will be inserted when you use the saved reply.
-
-For example, you might have a saved reply titled “Duplicate Issue Response” with a body like:
-
-“Thank you for reporting this. We’re tracking this issue in \#XYZ, so I’ll close this as a duplicate. Please follow the other thread for updates.”
-
-When you insert that saved reply, GitHub will populate the comment box with that message.
-
-**Key points:**
-
-* **No frontmatter file:** Saved replies are not stored in a repository file. They’re tied to your GitHub account. (There is no native way to define them in code or config files, thus no YAML format to document here.)
-
-* **Usage:** You create/edit them via **Settings \> Saved replies**. Each reply’s title is just for your menu; it isn’t inserted into the comment. Only the body content gets inserted[docs.github.com](https://docs.github.com/en/get-started/writing-on-github/working-with-saved-replies#:~:text=Using%20saved%20replies).
-
-* **Markdown Support:** The body supports normal comment formatting (Markdown links, lists, etc.), so you can include checklists or bold text as part of the saved reply.
-
-* **Best Practices:** Keep saved replies concise and general. You can always customize the inserted text after picking it, so they serve best as starting templates. For instance, it’s fine to include a placeholder like “\[issue link\]” in the saved reply text that you replace with a real link after insertion.
-
-*(Since saved replies don’t utilize YAML, there are no frontmatter parameters to list here.)*
-
-## **GitHub Copilot – Repository & Path-Specific Custom Instructions**
-
-GitHub Copilot allows you to provide **custom instructions** to guide code suggestions. These can be set at different levels:
-
-* **Personal instructions** (via your GitHub Copilot settings in your account) – not a file, just text you save in your profile.
-
-* **Repository-wide instructions** – a special file in the repository.
-
-* **Path-specific instructions** – files that apply only to certain files/paths in a repo.
-
-For **repository-wide instructions**, create a Markdown file named **`.github/copilot-instructions.md`** at the root of your repo[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=Creating%20repository). This file contains plain Markdown text with whatever guidance you want Copilot to always consider for this repository. For example, you might describe coding style, architectural guidelines, or context about the project. There is *no YAML frontmatter needed or used* in this file – it’s just a Markdown document of instructions (whitespace and newlines don’t matter to Copilot; it treats it as one block of text)[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=2,the%20file%2C%20in%20Markdown%20format).
-
-For **path-specific instructions**, create a folder `.github/instructions/`, and inside it one or more files with names like `XYZ.instructions.md` (the name can indicate the context). These files **do use YAML frontmatter** to specify where they apply. At the very top, include an `applyTo` key with a glob pattern (or multiple patterns) matching file paths[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=3,directories%20the%20instructions%20apply%20to)[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=). For example:
-
-`---`
-`applyTo: "app/models/**/*.rb,app/controllers/**/*.rb" # apply to all Ruby files in app/models or app/controllers`
-`---`
-`# Rails Model/Controller Conventions`
-
-`- Follow Ruby on Rails idioms for models and controllers.`
-`- Ensure to include necessary unit tests for any new model methods.`
-
-**Frontmatter fields for `*.instructions.md`:**
-
-* **`applyTo`** – Glob pattern of files that this instructions file should apply to[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=3,directories%20the%20instructions%20apply%20to). Use Unix shell style globs (e.g. `"**/*.ts"` for all TypeScript files, or `"docs/**/*"` for anything under docs). You can specify multiple patterns by separating with commas[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=You%20can%20specify%20multiple%20patterns,use%20the%20following%20frontmatter%20block). For a file that should apply to all files in the repo, use `applyTo: "**"`[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=).
-
-* **`description`** – *(Optional)* A short description of these instructions. In VS Code’s Copilot Chat UI, this description will show on hover or in the list of available instruction files[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-instructions#:~:text=Instructions%20files%20use%20the%20,extension%20and%20have%20this%20structure). This is mainly for your own organization; Copilot itself doesn’t use the description content for suggestions.
-
-After the frontmatter, the rest of the file is just Markdown text describing the instructions (similar to the repo-wide file). **Whitespace or blank lines are ignored** by Copilot, so you can format the instructions for readability[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=2,the%20file%2C%20in%20Markdown%20format). You can even use Markdown links to reference other files or documentation within your instructions.
-
-**Example path-specific instructions file:**
-
-`---`
-`applyTo: "**/*.py" # apply to all Python files`
-`description: "Python code style guidelines for this repo"`
-`---`
-`# Python Coding Guidelines`
-
-``- Follow PEP 8 style guide for Python code (use `black` for formatting).``
-`- Use type hints for all functions and methods.`
-`- Prefer list comprehensions and generator expressions for simple loops.`
-``- Avoid using wildcard `import` statements; import only what is needed.``
-
-In the above, whenever Copilot is generating suggestions **while editing a `.py` file**, it will factor in these Python Coding Guidelines in addition to any repo-wide instructions. If multiple instruction files apply (say you had one for all backend code and one for Python specifically), all relevant instructions are combined.
-
-**Best Practices:**
-
-* Keep instruction statements **concise and in natural language** (Copilot works best with clear, high-level guidance). For example, “Use 4 spaces for indentation” or “All API calls must include error handling.”
-
-* Use **separate files for distinct domains** – e.g., language-specific guidelines, or testing guidelines vs. deployment guidelines. This modular approach makes it easier to maintain. You can have many instruction files as needed.
-
-* Name the files logically (the name before `.instructions.md` doesn’t affect function, but helps you identify it). For example, `python.instructions.md`, `frontend.instructions.md`, `security.instructions.md`, etc.
-
-* Leverage the `applyTo` glob to target precisely. Be careful that your pattern isn’t too broad or too narrow. (Multiple patterns can be combined in one file if the instructions are identical.)
-
-* **Tip:** In VS Code, you can manually attach an instructions file to a chat even if its pattern doesn’t auto-apply, via the *Add Context \> Instructions* option. This is useful if you want to use an instruction file in a one-off manner outside its auto scope.
-
-## **GitHub Copilot – Custom Prompt Files (`.prompt.md`)**
-
-Copilot also supports **reusable prompt files** (especially in VS Code’s Copilot Chat context). A prompt file is a Markdown file (with extension `.prompt.md`) that defines a specific prompt or task for the AI, which you can invoke easily. The file can include a YAML frontmatter header to configure how it runs[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=Prompt%20files%20are%20Markdown%20files,extension%20and%20have%20this%20structure). Here are the frontmatter fields for prompt files[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=):
-
-* **`description`** – A short description of what the prompt does. This is used as tooltip or help text in the UI.
-
-* **`mode`** – Which Copilot chat mode to execute the prompt in. Options: `"ask"`, `"edit"`, or `"agent"`.
-
- * **ask** \= default Q\&A chat mode,
-
- * **edit** \= the mode for modifying code,
-
- * **agent** \= the “agent” mode which can use tools.
- If not specified, it defaults to the normal (currently selected) mode, which is typically “agent” for prompt files[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=,If%20not%20specified).
-
-* **`model`** – The AI model to use for this prompt. If omitted, it uses whatever model is currently selected by the user. You can specify something like `"gpt-4"`, `"GPT-4 Code Assist"`, `"Claude 2"`, etc., depending on what models are available in your environment[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=,in%20model%20picker%20is%20used).
-
-* **`tools`** – A list of tools or tool-set names that this prompt is allowed to use (only applicable if running in agent mode and if tools are available). For example, you might list `['terminal', 'browser', 'search']` to allow those tools during the prompt execution[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=,If). If a listed tool isn’t actually available, it will be ignored. (If not running in agent mode, tools list is ignored.)
-
-After the frontmatter, the **body of the `.prompt.md` file** is where you write the actual prompt instructions, in Markdown. This can be multiple paragraphs, include code blocks, etc. You can also reference other files or other prompt/instruction files by relative Markdown links to avoid duplication[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=Reference%20other%20workspace%20files%2C%20prompt,location%20of%20the%20prompt%20file).
-
-**Example prompt file with frontmatter:**
-
-`---`
-`description: "Convert a code snippet into a well-documented function"`
-`mode: "edit" # use edit mode (applies changes to code)`
-`model: "GPT-4" # ensure a powerful model for better docs`
-`tools: [] # (no external tools needed for this prompt)`
-`---`
-`# Convert to Documented Function`
-
-`Take the selected code and refactor it into a self-contained function with a clear name.`
-
-`- The new function should have a concise docstring explaining its purpose, inputs, and output.`
-`- Add comments inside the function to explain complex logic, if any.`
-`- **Do not** change the external behavior of the code.`
-
-`If the selected code is not a complete snippet (e.g., part of a larger expression), make an assumption to create a valid function.`
-
-In this example, the prompt file (say we named it `refactor.prompt.md`) can be invoked in VS Code by typing `/refactor` in the Copilot chat, or by running a command. It tells Copilot (in edit mode) to transform the selected code into a documented function. The YAML header ensures it uses the edit mode and GPT-4 model.
-
-**Notes and Best Practices:**
-
-* When writing the prompt (body), clearly state the task and any format you expect in the answer. The AI will follow these instructions when you run the prompt.
-
-* You can include **placeholders or variables** in prompt files. For instance, VS Code supports placeholders like `${selection}` (the currently selected text), `${file}` (current filename), or custom inputs like `${input:variableName}` where the user can supply additional data[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=Within%20a%20prompt%20file%2C%20you,can%20reference%20the%20following%20variables). In our example, we implicitly rely on the selected code (since it’s an edit mode prompt).
-
-* **Link to instructions or other prompts:** You can compose prompt files by linking to other instruction files or prompt files. For example, you might have a general style guide in an instructions file and within your prompt say “Follow our Python style guide” to automatically bring in those rules[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=Reference%20other%20workspace%20files%2C%20prompt,location%20of%20the%20prompt%20file).
-
-* Keep the `description` concise – think of it as tooltip text. It should summarize the prompt’s action (e.g., “Generate a release notes summary from commit messages”).
-
-* The `mode` field is important: use *ask* for things that don’t involve editing code (just Q\&A or explanation), *edit* for code transformations, and *agent* if the prompt might require using tools (like browsing documentation, running tests, etc.)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=,If%20not%20specified).
-
-* Only list necessary `tools`. For instance, if your prompt needs to search the codebase or run a shell command, include those; otherwise leaving it empty (or omitting the field) is fine. Unnecessary tools can introduce side effects or extra context that might confuse the AI.
-
-## **GitHub Copilot – Custom Chat Modes (`.chatmode.md`)**
-
-**Custom chat modes** allow you to define an entirely new mode for Copilot Chat, with specialized behavior or purpose. Each mode is defined in a file with extension `.chatmode.md`. The structure is similar to prompt files: an optional YAML frontmatter header, followed by Markdown instructions in the body[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=Chat%20mode%20files%20are%20Markdown,extension%20and%20have%20this%20structure)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=).
-
-**YAML frontmatter fields for chat modes**[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=,in%20model%20picker%20is%20used):
-
-* **`description`** – A brief description of the chat mode’s purpose. This is displayed as placeholder text in the chat input when the mode is active and as a tooltip when hovering over the mode in the mode selector[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=,in%20model%20picker%20is%20used).
-
-* **`tools`** – A list of tool names or predefined tool sets that are available in this mode[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=displayed%20as%20placeholder%20text%20in,and%20instructions%20in%20Markdown%20format). You might include built-in tools like `'terminal'`, `'browser'`, `'search'`, or any extension-contributed tools. (This works just like the `tools` field in prompt files, but here it defines tools for any prompt in this mode.)
-
-* **`model`** – The AI model to use when this mode is active. If not specified, it will use whichever model the user has currently selected by default[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=contributed%20by%20extensions,in%20model%20picker%20is%20used). You can set this if the mode is best suited to a particular model (e.g., a lightweight model for quick responses, or a specific one like `"Claude Instant 1"` or `"GPT-4"` if available).
-
-The body of the file contains the **detailed instructions or persona for that mode**. These instructions will be *prepended* or considered alongside the user’s inputs whenever this mode is used in chat. Essentially, this is where you set the behavior. For example, a “SQL Assistant” mode might have instructions like “You are an expert SQL assistant. Answer all questions with SQL examples when possible,” etc. You can include whatever guidance needed, including sections, lists, or Markdown formatting.
-
-You may also **reference other instruction or prompt files** in the mode’s body via Markdown links if you want to pull in shared rules (the content of those files will be included when the mode runs)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=This%20is%20where%20you%20provide,when%20in%20this%20chat%20mode).
-
-**Example of a custom chat mode file:**
-
-`---`
-`description: "Plan new features without writing any code (outputs an implementation plan)"`
-`tools: ['search', 'codebase'] # allow searching the repository and codebase introspection`
-`model: "GPT-4" # use a powerful model for thorough analysis`
-`---`
-`# Planning Mode`
-
-`You are in **Planning Mode**. Your job is to help plan out implementations for new feature requests or major refactors, without writing actual code.`
-
-`When the user asks a question or provides a feature description in this mode:`
- `- Do **not** produce any source code.`
- `- Instead, break the problem down into a series of steps, considerations, or tasks.`
- `- Provide the output as a Markdown document with sections for "Overview", "Requirements", "Implementation Plan", and "Testing Strategy".`
-
-`Always ask for clarification if requirements are ambiguous. This mode is about high-level planning and clarification.`
-
-In this example, we set up a mode that helps with planning. We gave it a description (which would show up as placeholder text like “Plan new features without writing code…” in the chat input when selected). We limited tools to just `'search'` and `'codebase'` (so it can search the project, but not run terminal commands or web fetches, for instance). We also specified the model as GPT-4 for better quality. The body instructions clearly state the role and what the assistant should and shouldn’t do in this mode.
-
-**Using and creating chat modes:**
-
-* Chat mode files for a **workspace** are typically stored in `.github/chatmodes/` (you may need to create this folder). You can also keep personal modes in your user profile (outside of any repo)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=2,mode%20file%20should%20be%20created).
-
-* Once a mode is created and the file is present, it will appear in the Copilot Chat interface as a selectable mode (alongside default modes like “Ask”, “Edit”, etc.). The `description` will show as ghost text in the input box, guiding the user on what that mode is for[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=).
-
-* Provide a clear **name** for the mode by the file name itself. For example, `planning.chatmode.md` will create a mode named “planning” (VS Code will use the file name as the mode name).
-
-* The YAML frontmatter is optional; if you omit, the mode will just use the current model and no special tool restrictions (which might be fine in some cases). However, providing at least a description is recommended for clarity.
-
-* **Tool configuration:** Only list tools that are needed for the mode’s purpose. For instance, a “Web Research” mode might enable a browser or web search tool, whereas a “Code Cleanup” mode might only need access to the codebase and perhaps a terminal to run linters.
-
-* **Testing:** After writing a mode’s instructions, test it by switching to that mode and prompting the assistant. Tweak the instructions as needed if the output isn’t as expected. For complex modes, sometimes breaking the instructions into bullet points (as in the example) helps the AI follow them systematically.
-
-## **Unified Multi-Agent Instructions – `AGENTS.md`**
-
-There is an emerging convention (sometimes called the “Agent Rules standard”) to use a file named **`AGENTS.md`** at the root of a project to provide guidelines that apply to *all* AI assistants/agents working on the repository[github.com](https://github.com/continuedev/continue/issues/6716#:~:text=The%20Agent%20Rules%20initiative%20proposes,continue%2Frules%2F%20system)[github.com](https://github.com/continuedev/continue/issues/6716#:~:text=,as%20natural%20language%20if%20none). Think of it as a central place to define coding conventions, architectural overviews, or any rules that any AI (whether GitHub Copilot, Claude, Gemini, or others) should follow when generating content for this repo.
-
-In the context of **GitHub Copilot in VS Code**, an `AGENTS.md` file (if enabled in settings) will automatically be pulled into context for **all Copilot chat requests**, regardless of mode[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-instructions#:~:text=If%20you%20work%20with%20multiple,chat%20requests%20within%20this%20workspace). This is useful if you work with multiple AI backends (GitHub’s model, OpenAI’s, Anthropic’s, etc.) so they all get the same project-specific instructions.
-
-**Format:** The `AGENTS.md` file is simply a Markdown file. Typically, it does **not require any YAML frontmatter** – you can just start with normal text or Markdown headings. For example, your `AGENTS.md` might contain:
-
-`# Project AI Guidelines`
-
-`- All code must follow the style guide in [CONTRIBUTING.md](CONTRIBUTING.md).`
-`- Assume the user is familiar with the project’s domain; avoid explaining basic concepts.`
-`- Prioritize security and privacy: do not output secrets or credentials, and mention security implications of code changes.`
-`- Every generated function *must* have a docstring.`
-
-This would act as a set of universal instructions. Whenever Copilot (or other integrated agents) generate code or responses for this repository, they would ideally consider these guidelines. The **scope** of `AGENTS.md` is broad – by design it should hold rules that are generally applicable to any AI actions in the repo (akin to an `.editorconfig` but for AI).
-
-**Do’s and Don’ts:**
-
-* **Do include high-level or project-wide concerns**: e.g., “We use tabs, not spaces”, “No external library imports without approval”, “Follow OWASP security best practices”, etc.
-
-* **Don’t include extremely granular instructions** that might only apply in certain contexts – those might be better in the specific prompt or handled by an `.instructions.md` for that context. `AGENTS.md` should be relatively static and universal.
-
-* Typically, you don’t need `applyTo` patterns here, because it’s meant to always apply to everything (the tools or editors that support `AGENTS.md` treat it as global). Some tools or proposals allow YAML frontmatter in `AGENTS.md` to fine-tune applicability[github.com](https://github.com/continuedev/continue/issues/6716#:~:text=,as%20natural%20language%20if%20none), but generally you can omit it. The file is implicitly applied to all files/agents.
-
-* Keep it maintainable: since many AI tools now look for `AGENTS.md`, it’s a single source of truth. Update it as your practices evolve. If it gets too long, consider splitting certain parts into more targeted instruction files (and you can reference them from `AGENTS.md` if needed).
-
-**Note:** This concept is gaining traction to unify AI assistant behavior across different platforms. GitHub’s documentation notes that instead of multiple `.instructions.md` files, you can also use a single `AGENTS.md` (or model-specific files like `CLAUDE.md`, `GEMINI.md` as noted below) and the “nearest” such file up the directory tree will be used[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=,by%20AI%20agents). The goal is to avoid duplicating rules for each AI vendor.
-
-In summary, if you have a **mixed AI environment** or just want a one-stop config, `AGENTS.md` is the way to go. If you’re only using GitHub Copilot, `.github/copilot-instructions.md` plus selective instruction files might suffice, but there’s no harm in also having an `AGENTS.md` as a fallback for other tools (many third-party AI dev tools now check for this file).
-
-## **Anthropic Claude – Custom Instructions (`CLAUDE.md`)**
-
-Anthropic’s Claude (especially **Claude Code**, their coding assistant) allows project-specific customization via a file commonly named **`CLAUDE.md`**. This file serves a purpose similar to `AGENTS.md` but specifically for Claude. According to Anthropic, Claude will automatically look for a file named `CLAUDE.md` in your repository and load it as part of its system prompt (what Anthropic calls a “memory file”) every time you start a Claude session in that project[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=System%20prompt%20availability).
-
-**Format:** `CLAUDE.md` is a plain Markdown file. There is no required YAML frontmatter schema for it – you just fill it with any instructions or context you want Claude to always have. This could include things like coding style guidelines, a high-level overview of the project, important conventions, etc. Essentially, it’s a way to give Claude persistent knowledge or rules without having to repeat them in each prompt.
-
-For example, `CLAUDE.md` might contain:
-
-`# Claude Instructions for MyProject`
-
-`**Project Overview:** This is a web application for online book reviews. It uses a Python Flask backend and a React frontend.`
-
-`**Coding Style:** Follow PEP8 for Python code (use 4 spaces indentation, snake_case for functions). For JavaScript/React, follow Airbnb style guide.`
-
-`**Testing:** Whenever you write new code, include unit tests (PyTest for backend, Jest for frontend).`
-
-`**Do’s:**`
-`- Be concise in explanations.`
-`- Use docstrings in all public functions.`
-
-`**Don’ts:**`
-`- Don’t disclose any API keys or secrets that might be in the code.`
-`- Don’t make assumptions about user data; validate everything.`
-
-When you open Claude in the context of this repo, it will read that file and incorporate these points into its responses. This mechanism is powerful for shaping Claude’s behavior.
-
-**Tips:**
-
-* Think of `CLAUDE.md` as “setting the stage” for Claude. It’s loaded as part of Claude’s initial prompt. So it can contain a mix of factual info (project summary) and normative guidelines (style rules, etc.).
-
-* You can use Markdown formatting, but remember that it’s primarily for you – the formatting (bold, headings) might slightly influence Claude (it might assume bold means important), but mostly it’s to keep the file organized.
-
-* Keep it reasonably sized. Claude has context limits; a very large CLAUDE.md could consume a lot of tokens. Focus on the most important guidance.
-
-* If you have multiple Claude-specific files (though typically one is enough), Claude will by default load the one in the root. Anthropic’s tooling might also recognize `docs/claude.md` or similar, but **the standard is root-level `CLAUDE.md`**.
-
-**Note:** Claude also supports an **API for “sub-agents”** (discussed next) which use YAML frontmatter. But the top-level CLAUDE.md itself is straightforward Markdown. It’s essentially a special case of the more general `AGENTS.md` idea, dedicated just to Claude. GitHub’s Copilot integration notes that you can use a `CLAUDE.md` in combination with Copilot’s agent, presumably for when Copilot is backed by Claude or working alongside Claude[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=You%20can%20create%20one%20or,directory%20tree%20will%20take%20precedence).
-
-## **Anthropic Claude – Custom Sub-Agents (YAML Configuration)**
-
-Claude’s advanced **subagent** feature allows you to create multiple specialized AI “agents” under the main Claude agent. Each sub-agent is defined by a Markdown file with a YAML frontmatter header that Claude reads to configure that agent’s identity and permissions[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=Subagent%20configuration)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=Subagents%20are%20defined%20as%20Markdown,or%20from%20your%20user%20scope). These are usually stored in a `.claude/agents/` directory (for project-specific agents) or `~/.claude/agents/` (for user-wide agents)[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=Claude%20Code%20supports%20custom%20AI,Markdown%20files%20with%20YAML%20frontmatter).
-
-A subagent file’s **YAML frontmatter** typically includes:
-
-* **`name`** – The name of the subagent. This is how you will invoke it (Claude can be prompted to delegate tasks to an agent by name)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=,plus%20the%20system%20prompt).
-
-* **`description`** – A short description of what the subagent’s role or specialty is[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=,plus%20the%20system%20prompt). Claude may use this to decide when to auto-delegate tasks. It’s also useful documentation for you and your team.
-
-* **`tools`** – *(Optional)* A list of tools that this subagent is allowed to use[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=). Claude operates with a set of tools (like reading files, writing files, running shell commands, web search, etc.). By specifying `tools` here, you **whitelist** which ones the subagent can access. If you omit `tools`, the subagent inherits all the tools available to the main Claude session (which might be too permissive in some cases)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=%60Use%20the%20implementer,presets). For tighter control, list only what it needs (e.g., maybe a “DatabaseAgent” only gets read/write database access, nothing else).
-
-After the frontmatter, the rest of the file is the **subagent’s prompt/instructions** – essentially a dedicated system prompt for that subagent. This is where you describe in detail how the subagent should behave, its step-by-step approach, or any domain knowledge it should have.
-
-**Example subagent file (`architect-review.md`):**
-
-`---`
-`name: "architect-review"`
-`description: "Architect Agent – validates designs against constraints and produces an architecture decision record."`
-`tools: ["Read", "Search"] # e.g., can read files and search documentation, but not write code`
-`---`
-`You are the **Architect** sub-agent. Your goal is to review proposed software designs or feature specifications and ensure they meet the system's constraints and best practices.`
-
-`When activated, you will:`
-``- Read the feature specification from the repository (`specs/` directory).``
-`- Analyze it for compliance with our scalability and security requirements.`
-`- Output an **Architecture Decision Record (ADR)** with sections for Context, Decision, Rationale, and Consequences.`
-
-`You should not write any code. Focus only on architectural guidance. If the spec is unclear, list assumptions or ask for clarification.`
-
-In this file, the YAML header gives the subagent a name (“architect-review”), a description, and limits its tools. The body instructs it on exactly what to do when called. Claude’s main agent can be asked, *“Use the architect-review subagent on the new feature spec,”* and it will spin up this specialized agent with these instructions to perform that task[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=%2A%20Usage%3A%20Claude%20can%20auto,presets).
-
-**Key Points for Claude Subagents:**
-
-* Store project subagents in the repository under `.claude/agents/`. This makes them shareable with the team (and version controlled). User-level (global) agents go in `~/.claude/agents/` on your machine[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=Claude%20Code%20supports%20custom%20AI,Markdown%20files%20with%20YAML%20frontmatter).
-
-* The **filename** isn’t directly used as the name; it’s the `name:` in YAML that counts. However, by convention, you might name the file the same as the agent name for clarity.
-
-* The `description` should be action-oriented, because Claude can auto-select subagents based on descriptions. For instance, if the description says “writes unit tests”, Claude might automatically use that agent when a task is about testing.
-
-* If `tools` is not specified, the subagent can use any tool the main agent has, which might be fine for general-purpose agents. If you want to sandbox an agent, list only specific tools. For example, a “QA” agent might only need read access (to verify code) and perhaps run tests, but not write access.
-
-* You can define multiple subagents to form a pipeline. For example, one subagent could be “planner”, another “coder”, another “tester”, each with its own YAML config and instructions, and you orchestrate them (often using Claude’s **hooks** or by manual prompts)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=%2A%20Reproducibility%3A%20Stop%20re,and%20hooks%20codify%20repeatable%20steps)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=We%20started%20with%20a%20three,that%E2%80%99s%20generic%20to%20any%20stack).
-
-* **Best practices:** Give each subagent one clear responsibility (single responsibility principle)[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=1%29%20Single). Keep their instructions focused on that role. This makes the overall AI workflow more reliable and easier to troubleshoot.
-
-* **Security:** Use the `tools` limitation to prevent a subagent from doing things it shouldn’t. For instance, a planning agent probably doesn’t need the `Execute` (shell command) tool. And as noted in Anthropic’s docs, if you want to exclude access to certain files entirely, you’d configure that in Claude’s permissions (which is outside the scope of the YAML, done in `.claude/settings.json`)[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=,working%20directories%20that%20Claude%20has)[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=,to%20prevent%20%60bypassPermissions).
-
-In summary, Claude’s subagents use YAML frontmatter for **metadata and permissions** and Markdown body for the **agent’s persona/instructions**. It’s a powerful system to split tasks among “expert” agents.
-
-## **Google Gemini – Custom Instructions (`GEMINI.md`)**
-
-Google’s **Gemini** (an AI model from Google) is still relatively new on the scene for code assistance, and detailed public documentation on project-specific config is sparse. However, we can draw parallels from patterns established by others and hints from tools:
-
-GitHub’s Copilot documentation and community standards suggest that you can use a **`GEMINI.md`** file at the root of your repository to provide custom instructions when using a Gemini-based AI assistant[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=You%20can%20create%20one%20or,directory%20tree%20will%20take%20precedence). This is analogous to `CLAUDE.md` for Claude. For example, if an AI extension or tool uses Google’s Gemini model to assist with your code, it could check for `GEMINI.md` to preload instructions.
-
-Since specifics aren’t officially published, we’ll assume **`GEMINI.md` is treated like a free-form instructions file**, just like `CLAUDE.md`. That means likely no required YAML keys, just Markdown content (unless a specific tool layer adds its own frontmatter options).
-
-What might you put in a `GEMINI.md`? Probably similar content to CLAUDE.md or AGENTS.md: high-level guidelines, project overview, dos/don’ts for the AI. For example:
-
-`# Gemini Instructions for MyProject`
-
-`This project is a machine learning pipeline for image classification.`
-
-`- The codebase is primarily TensorFlow (Python) and some C++ for performance-critical components.`
-`- **Style Guidelines:** Follow Google Python style guide. In C++ code, follow Google C++ style.`
-`- **Important:** Do not use external packages that are not already in the requirements.txt.`
-`- Focus on clarity and maintainability over cleverness.`
-
-`If asked to produce a solution, prefer simple implementations and add comments explaining any non-obvious steps.`
-
-If a Gemini-powered tool is being used, it would incorporate those notes.
-
-**Parameters for custom agents:** If in the future tools allow more structured config for Gemini, it would likely mirror the structure of subagents (name, description, etc.) if Gemini supports multiple specialized agents. There’s also mention that some CLI tools (Codex CLI, Aider, etc.) and potentially a “Gemini CLI” support the same **Agent Rules** standard (i.e., `AGENTS.md`)[github.com](https://github.com/continuedev/continue/issues/6716#:~:text=The%20Agent%20Rules%20initiative%20proposes,continue%2Frules%2F%20system). This means Gemini might already respect a unified format with YAML frontmatter if present. For now, though, a single `GEMINI.md` with plain text instructions is the safe bet.
-
-**Best Practices:**
-
-* Treat `GEMINI.md` much like `CLAUDE.md`: keep it concise and focused on things unique to your project or preferences.
-
-* Since Gemini is from Google and likely tuned with different data, be explicit about things like privacy or licensing constraints in your instructions (e.g., “Don’t suggest any solution that would violate our license terms” if relevant).
-
-* Update the file as the project evolves – if certain frameworks are deprecated or new conventions adopted, reflect that in the instructions.
-
-**Note:** If you’re not actively using any Gemini-based coding assistant, you don’t need a GEMINI.md yet. But some teams include it preemptively as part of adopting the `AGENTS.md` convention, in case collaborators use different AI tools. It doesn’t harm anything to have it there. In the future, we expect more concrete schemas or tools for Gemini; until then, stick to the general guidance approach.
-
----
-
-**Summary:** The table below recaps the **YAML frontmatter fields** discussed for each file type:
-
-* **Issue Template (YAML form)** – `name`, `description` (or `about`), `title`, `labels`, `assignees`, `projects`, `type`, and a structured `body` with `type`, `id`, `attributes`, and `validations` for each input[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,repository%2C%20it%20will%20not%20be)[docs.github.com](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#:~:text=,using%20this%20template%20to%20have).
-
-* **PR Template** – *(same fields as issue template, but not currently parsed by GitHub)*[stackoverflow.com](https://stackoverflow.com/questions/66392676/github-pull-request-template-detect-yaml-front-matter-using-config-yml-and-apply#:~:text=,request%20assignees%3A%20self).
-
-* **Saved Reply** – *no YAML (title & body managed via UI)*.
-
-* **Copilot Repo Instructions** – *no YAML needed (just markdown content in* `.github/copilot-instructions.md`*)*.
-
-* **Copilot Path Instructions** – `applyTo` (pattern) and optional `description` in frontmatter[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=3,directories%20the%20instructions%20apply%20to)[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-instructions#:~:text=,Body%3A%20Instructions%20in%20Markdown%20format); body is markdown instructions.
-
-* **Copilot Prompt File** – `description`, `mode` (`ask|edit|agent`), `model`, `tools` in frontmatter[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/prompt-files#:~:text=); body is the prompt text.
-
-* **Copilot Chat Mode** – `description`, `tools`, `model` in frontmatter[code.visualstudio.com](https://code.visualstudio.com/docs/copilot/customization/custom-chat-modes#:~:text=,in%20model%20picker%20is%20used); body is mode-specific instructions.
-
-* **AGENTS.md** – *generally no fixed fields; global instructions for all AIs (some tools may parse frontmatter if included, but typically just markdown content)*.
-
-* **Claude CLAUDE.md** – *no fixed fields; markdown instructions for Claude*[docs.claude.com](https://docs.claude.com/en/docs/claude-code/settings#:~:text=System%20prompt%20availability).
-
-* **Claude Subagent** – `name`, `description`, `tools` (optional) in frontmatter[pubnub.com](https://www.pubnub.com/blog/best-practices-for-claude-code-sub-agents/#:~:text=,plus%20the%20system%20prompt); body is that agent’s system prompt.
-
-* **Gemini GEMINI.md** – *no known fixed schema; markdown instructions (analogous to CLAUDE.md)*[docs.github.com](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions#:~:text=You%20can%20create%20one%20or,directory%20tree%20will%20take%20precedence).
-
-By using the above configurations, you can customize issue and PR workflows on GitHub, as well as tailor AI assistants (like Copilot, Claude, and eventually Gemini) to better suit your project’s needs. Each file has a specific role – from guiding human contributors (templates) to guiding AI behavior (instructions and prompts). Use them in combination for the best effect (for instance, an issue template can gather structured data from a user, and your Copilot instructions can remind the AI to utilize that data when generating code or responses).
-
diff --git a/frontmatter/YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files1.md b/frontmatter/YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files1.md
deleted file mode 100644
index d732a97..0000000
--- a/frontmatter/YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files1.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# **YAML Frontmatter Schemas for GitHub, Copilot, Claude, and Gemini Files**
-
-comprehensive breakdown of YAML frontmatter schemas for the following file types:
-
-* GitHub issue and PR templates
-
-* GitHub saved replies
-
-* GitHub Copilot: custom instructions, prompt files, `AGENTS.md`, and `.chatmode.md`
-
-* Claude agents (Anthropic YAML-based config)
-
-* Gemini agents (Google)
-
-For each, I’ll include:
-
-* Maximum parameter set and required vs optional fields
-
-* Example YAML frontmatter blocks
-
-* Best practices and caveats
-
-* Placeholder documentation next to each field
-
-* Recommended folder/filename conventions
-
-* YAML schema examples where available or inferred
-
-I’ll also reference the two zips you provided (`awesome-copilot-main` and the awesome-chat examples) and cross-check with the official docs.
-
diff --git a/frontmatter/YAML-Frontmatter Schema-Guidelines.md b/frontmatter/YAML-Frontmatter Schema-Guidelines.md
deleted file mode 100644
index 55569ad..0000000
--- a/frontmatter/YAML-Frontmatter Schema-Guidelines.md
+++ /dev/null
@@ -1,906 +0,0 @@
-# **YAML Frontmatter Files Types with Schema**
-
-`A minimal, **WordPress-friendly** Copilot Space that teaches and enforces correct use of YAML frontmatter`
-`across GitHub templates and AI files. Includes docs, schemas, reusable prompts, custom chat modes,`
-`and example Claude subagents. Built to standardise WP plugin/theme workflows.`
-
-Always show details
-`# Create a WordPress-focused Copilot Space with frontmatter docs, prompts, chat modes, and agents, then zip it`
-`import os, zipfile, json, textwrap, pathlib`
-
-`root = "/mnt/data/copilot-space-wp"`
-`os.makedirs(root, exist_ok=True)`
-
-`# Folders`
-`dirs = [`
- `".github",`
- `".github/instructions",`
- `".github/prompts",`
- `".github/chatmodes",`
- `".github/agents",`
- `".github/ISSUE_TEMPLATE",`
- `".github/PULL_REQUEST_TEMPLATE",`
- `"docs/copilot-space",`
- `"docs/copilot-space/schemas",`
- `"docs/wp-guides",`
- `".vscode"`
-`]`
-`for d in dirs:`
- `os.makedirs(os.path.join(root, d), exist_ok=True)`
-
-`# ---------- Root docs ----------`
-`readme = """# Copilot Space (WordPress Edition)`
-
-`A minimal, **WordPress-friendly** Copilot Space that teaches and enforces correct use of YAML frontmatter`
-`across GitHub templates and AI files. Includes docs, schemas, reusable prompts, custom chat modes,`
-`and example Claude subagents. Built to standardise WP plugin/theme workflows.`
-
-`` Start here: `docs/copilot-space/INDEX.md` ``
-`"""`
-
-`agents_md = """# AGENTS.md — Universal AI Rules (WordPress)`
-
-``- Follow **WordPress Coding Standards** (PHPCS: `WordPress`, `WordPress-Docs`, `WordPress-Extra`).``
-`- PHP versions: prefer compatibility with current WP supported PHP (adjust per project).`
-`- Escape, sanitise, and validate all inputs; use nonces for forms; respect capabilities/roles.`
-`- I18n: wrap user-facing text in translation functions; provide text domain.`
-`- Keep changes minimal and reversible; propose diffs and tests.`
-`- Never output secrets; redact credentials and keys.`
-`"""`
-
-`claude_md = """# CLAUDE.md — Project Instructions (WordPress)`
-
-`Claude should:`
-`- Prefer WordPress core APIs (Options, Settings API, REST API, Transients, WP_Filesystem).`
-`- Use hooks/filters where appropriate; avoid monkey-patching core.`
-`- Generate **PHPCS-compliant** PHP and add PHPDoc for public APIs.`
-`- For JS (blocks), use @wordpress/* packages; register blocks via block.json where sensible.`
-`"""`
-
-`gemini_md = """# GEMINI.md — Project Instructions (WordPress)`
-
-`Gemini should follow: WordPress coding standards, security best practices (escaping/sanitising),`
-`and internationalisation. Prefer minimal dependencies and progressive enhancement.`
-`"""`
-
-`editorconfig = """root = true`
-
-`[*]`
-`end_of_line = lf`
-`insert_final_newline = true`
-`charset = utf-8`
-`trim_trailing_whitespace = true`
-
-`[*.php]`
-`indent_style = tab`
-`indent_size = 4`
-
-`[*.{js,jsx,ts,tsx,json}]`
-`indent_style = space`
-`indent_size = 2`
-
-`[*.{css,scss,sass}]`
-`indent_style = space`
-`indent_size = 2`
-
-`[*.md]`
-`trim_trailing_whitespace = false`
-`"""`
-
-`gitignore = """# OS`
-`.DS_Store`
-`Thumbs.db`
-
-`# Node/Yarn`
-`node_modules/`
-`npm-debug.log*`
-`yarn-error.log*`
-`dist/`
-`build/`
-`coverage/`
-
-`# Composer`
-`vendor/`
-`composer.lock`
-
-`# IDE`
-`.vscode/`
-`.idea/`
-
-`# PHP unit caches`
-`.phpunit.result.cache`
-`"""`
-
-`gitattributes = """* text=auto eol=lf`
-`docs/* linguist-documentation`
-`"""`
-
-`# ---------- Docs (Copilot Space Guides) ----------`
-`index_md = """# Copilot Space Index — WordPress Frontmatter Playbook`
-
-`This space blends **GitHub templates** and **AI instruction files** with a WordPress focus.`
-
-`## GitHub Templates`
-`- [Issue Templates (Issue Forms)](issue-templates.md)`
-`- [Pull Request Templates](pr-templates.md)`
-`- [Saved Replies (overview)](saved-replies.md)`
-
-`## Copilot Customisation`
-`- [Repo & Path Instructions](copilot-instructions.md)`
-`- [Reusable Prompt Files](prompt-files.md)`
-`- [Custom Chat Modes](chatmodes.md)`
-`- [AGENTS.md (universal rules)](agents-md.md)`
-
-`## Claude & Gemini`
-`- [Claude: CLAUDE.md & Subagents](claude-agents.md)`
-`- [Gemini: GEMINI.md (convention)](gemini-md.md)`
-
-`## Schemas`
-`- [Issue Form schema](schemas/issue-form-schema.md)`
-`- [Prompt frontmatter schema](schemas/prompt-frontmatter-schema.md)`
-`- [Chat Mode frontmatter schema](schemas/chatmode-frontmatter-schema.md)`
-`- [Claude Subagent schema](schemas/claude-subagent-schema.md)`
-`- [Prompt Collection schema (experimental)](schemas/prompt-collection-schema.md)`
-
-`## WordPress Guides`
-`- [WordPress Coding Standards quickstart](../wp-guides/wp-coding-standards.md)`
-`- [Security checklist for WP](../wp-guides/wp-security-checklist.md)`
-`- [Block development checklist](../wp-guides/block-dev-checklist.md)`
-`"""`
-
-`issue_templates_md = """# Issue Templates (Issue Forms) — YAML Frontmatter (WordPress)`
-
-`` **Location:** `.github/ISSUE_TEMPLATE/*.yml` ``
-
-``Required: `name`, `description`, `body`.``
-``Optional: `title`, `labels`, `assignees`, `projects`, `type`.``
-
-`The examples below include common WordPress fields (WP version, PHP version, theme/plugin). See live templates in this repo.`
-`"""`
-
-`pr_templates_md = """# Pull Request Templates (WordPress)`
-
-`` **Location:** `.github/PULL_REQUEST_TEMPLATE/*.md` ``
-
-`PR templates are plain Markdown (no form YAML). Use sections/checklists to enforce **WP coding standards**,`
-`testing steps, PHPCS, and i18n checks. A minimal example is provided in this repo.`
-`"""`
-
-`saved_replies_md = """# Saved Replies`
-
-`Managed via GitHub UI (Profile → Saved replies). No frontmatter available. Keep replies short; customise after insertion.`
-`"""`
-
-`copilot_instructions_doc = """# Copilot Custom Instructions (WordPress)`
-
-`## Repository-wide`
-``**File:** `.github/copilot-instructions.md` (Markdown only)``
-
-`- Follow WordPress Coding Standards (PHPCS).`
-`- Use esc_html/esc_attr/sanitize_* appropriately; nonces for forms; capability checks.`
-`- All user-facing strings must be translatable with text domain.`
-`- Prefer core APIs over custom implementations.`
-
-``## Path-specific (`*.instructions.md`)``
-``**Folder:** `.github/instructions/` (with YAML frontmatter)``
-
-```` ```markdown ````
-`---`
-`applyTo: "**/*.php"`
-`description: "PHP (WordPress) rules"`
-`---`
-`- Use WP functions (get_option, update_option, wp_safe_redirect).`
-`- Enqueue assets via wp_enqueue_scripts/admin_enqueue_scripts.`
-`- Avoid direct DB queries; use $wpdb safely only when needed.`
-
-"""
-
-prompt\_files\_doc \= """\# Reusable Prompt Files (`*.prompt.md`)
-
-**Folder:** `.github/prompts/`
-
-Frontmatter:
-
-* `description` — tooltip/summary
-
-* `mode` — ask | edit | agent
-
-* `model` — optional; uses current if omitted
-
-* `tools` — optional list of tools (agent mode)
-
-Body: the instructions. Reference shared guides with Markdown links.
- """
-
-chatmodes\_doc \= """\# Custom Chat Modes (`*.chatmode.md`)
-
-**Folder:** `.github/chatmodes/`
-
-Frontmatter:
-
-* `description` — shown as placeholder & tooltip
-
-* `tools` — allowed tools
-
-* `model` — pinned model (optional)
-
-Body: persona & guardrails for that mode.
- """
-
-agents\_md\_doc \= """\# AGENTS.md — Universal Rules
-
-Use this as a vendor-neutral rulebook for Copilot/Claude/Gemini. Keep it concise; assistants may include it on every run.
- """
-
-claude\_agents\_doc \= """\# Claude — CLAUDE.md & Subagents
-
-**CLAUDE.md**: Markdown file at repo root; high-level rules for Claude.
-
-**Subagents**: `.github/agents/*.md` with YAML frontmatter (`name`, `description`, `tools`), body as the subagent's persona/instructions.
- """
-
-gemini\_doc \= """\# Gemini — GEMINI.md
-
-Conventionally place a Markdown file at repo root with persistent guidance for Gemini-based tools.
- """
-
-# **\---------- Schemas \----------**
-
-issue\_schema \= """\# Issue Form — Frontmatter Keys (Reference)
-
-Always show details
-`name: string # required`
-`description: string # required`
-`title: string # optional`
-`labels: [string] | string # optional`
-`assignees: [string] | string # optional`
-`projects: [string] # optional`
-`type: string # optional`
-`body: # required`
- `- type: markdown|input|textarea|dropdown|checkboxes`
- `id: string # optional`
- `attributes:`
- `label: string # required (except markdown)`
- `description: string # optional`
- `placeholder: string # optional`
- `value: string # optional`
- `options: [string] # dropdown/checkboxes`
- `multiple: boolean # dropdown only`
- `render: string # textarea only (e.g., bash, markdown)`
- `validations:`
- `required: boolean`
-
-"""
-
-prompt\_schema \= """\# Prompt File — Frontmatter Keys
-
-Always show details
-`description: string`
-`mode: ask|edit|agent`
-`model: string # optional`
-`tools: [string] # optional`
-
-"""
-
-chatmode\_schema \= """\# Chat Mode — Frontmatter Keys
-
-Always show details
-`description: string`
-`tools: [string] # optional`
-`model: string # optional`
-
-"""
-
-claude\_subagent\_schema \= """\# Claude Subagent — Frontmatter Keys
-
-Always show details
-`name: string`
-`description: string`
-`tools: [string] # optional`
-
-"""
-
-prompt\_collection\_schema \= """\# Prompt Collection — Schema (Experimental)
-
-A lightweight collection format to group prompts for discovery.
-
-Always show details
-`{`
- `"$schema": "https://example.com/schemas/prompt-collection.schema.json",`
- `"name": "WordPress Starters",`
- `"description": "Reusable Copilot prompts for WP",`
- `"prompts": [`
- `{`
- `"id": "wp-register-block",`
- `"path": ".github/prompts/wp-register-block.prompt.md",`
- `"tags": ["blocks","gutenberg"]`
- `}`
- `]`
-`}`
-
-"""
-
-# **\---------- WP Guides \----------**
-
-wp\_coding \= """\# WordPress Coding Standards Quickstart
-
-* Install PHPCS and WPCS rulesets.
-
-* Use tabs for PHP indentation; wrap user strings for i18n; docblock public APIs.
-
-* Escape late, sanitise early; always validate and authorise.
- """
-
-wp\_security \= """\# WordPress Security Checklist
-
-* Nonces for any state-changing actions.
-
-* Escape output: `esc_html()`, `esc_attr()`, `wp_kses_post()`.
-
-* Sanitise input: `sanitize_text_field()`, `sanitize_email()`.
-
-* Cap checks with `current_user_can()`; never trust user input.
- """
-
-block\_dev \= """\# Block Development Checklist
-
-* Use `@wordpress/scripts`; define `block.json` (name, title, category, attributes).
-
-* Register via `register_block_type_from_metadata()`.
-
-* Enqueue editor/front assets properly; namespace styles.
-
-* Provide `supports` (align, color, typography) as needed.
- """
-
-# **\---------- .github root \----------**
-
-copilot\_repo\_instructions \= """\# Copilot Repository Instructions (WordPress)
-
-* Use core WP APIs; follow WPCS; propose small diffs.
-
-* For plugins: prefix functions, classes, and filters with project slug.
-
-* For themes: follow Template Hierarchy; enqueue assets, no direct script tags.
-
-* I18n: load text domain; add translators' comments for placeholders.
- """
-
-codeowners \= """\# CODEOWNERS
-
-* @your-team
- """
-
-# **\---------- Issue Templates (WP-focused) \----------**
-
-bug\_report\_yml \= """name: "🐛 Bug report (WordPress)"
- description: "Report a reproducible issue with the plugin/theme"
- title: "\[Bug\]: "
- labels: \["bug","needs-triage"\]
-
-body:
-
-* type: markdown
- attributes:
- value: |
- Thanks\! Please fill out the details below to help us reproduce the issue.
-
-* type: input
- id: wp\_version
- attributes:
- label: "WordPress version"
- placeholder: "e.g. 6.6.2"
- validations:
- required: true
-
-* type: input
- id: php\_version
- attributes:
- label: "PHP version"
- placeholder: "e.g. 8.2"
- validations:
- required: true
-
-* type: input
- id: plugin\_theme
- attributes:
- label: "Affected component"
- description: "Which plugin/theme/module?"
- placeholder: "Plugin XYZ / Theme ABC"
- validations:
- required: true
-
-* type: textarea
- id: repro
- attributes:
- label: "Steps to reproduce"
- value: |
- 1\. Go to …
- 2\. Click …
- 3\. Observe …
- validations:
- required: true
-
-* type: textarea
- id: expected
- attributes:
- label: "Expected behaviour"
- validations:
- required: true
-
-* type: textarea
- id: actual
- attributes:
- label: "Actual behaviour (include error messages/logs)"
- validations:
- required: true
-
-* type: dropdown
- id: environment
- attributes:
- label: "Environment"
- options:
- \- "Local (wp-env/Local/Valet)"
- \- "Staging"
- \- "Production"
- multiple: false
- validations:
- required: true
-
-* type: checkboxes
- id: checks
- attributes:
- label: "Checks"
- options:
- \- label: "I searched for duplicate issues"
- required: true
- \- label: "I can reproduce with all other plugins disabled and a default theme"
- """
-
-feature\_request\_yml \= """name: "✨ Feature request (WordPress)"
- description: "Suggest an improvement or new feature"
- title: "\[Feature\]: "
- labels: \["enhancement"\]
-
-body:
-
-* type: textarea
- id: problem
- attributes:
- label: "Problem to solve"
- description: "What user/customer problem does this feature address?"
- validations:
- required: true
-
-* type: textarea
- id: proposal
- attributes:
- label: "Proposed solution"
- description: "Describe how it should work (include examples or prior art)"
- validations:
- required: true
-
-* type: textarea
- id: impact
- attributes:
- label: "Impact / Risks"
- description: "Performance, backwards-compatibility, security, etc."
- validations:
- required: false
- """
-
-# **\---------- PR Template (WP-focused) \----------**
-
-pr\_template \= """\#\# Summary
-
-\<\!-- Concise description of the change and why it's needed. \--\>
-
-## **Related Issues**
-
-Closes \#\_\_\_
-
-## **Changes**
-
-* PHP follows WPCS & PHPCS passes locally
-
-* Escaping/sanitisation/nonces/capability checks added where needed
-
-* I18n added (text domain, translators' comments)
-
-* Blocks registered correctly (block.json / register\_block\_type\_from\_metadata)
-
-* Tests/docs updated (if applicable)
-
-## **Manual QA**
-
-1. …
-
-2. …
-
-3. …
-
-## **Screenshots / GIF**
-
-\<\!-- If UI changes, include before/after \--\>
-
-"""
-
-# **\---------- Instructions (applyTo) \----------**
-
-## **php\_instructions \= """---**
-
-## **applyTo: "\*\*/\*.php"**
-
-## **description: "PHP (WordPress) rules"**
-
-# **PHP (WordPress) Guidelines**
-
-* Follow WPCS; write PHPDoc for public APIs.
-
-* Escape output with `esc_*` and sanitise input with `sanitize_*`.
-
-* Use nonces for forms and actions; check capabilities with `current_user_can()`.
-
-* Use core APIs (Options, Settings API, REST API, Transients) before custom.
- """
-
-## **js\_instructions \= """---**
-
-## **applyTo: "assets/\*\*/\*.{js,jsx,ts,tsx}"**
-
-## **description: "JS/Blocks rules"**
-
-# **JavaScript / Blocks Guidelines**
-
-* Use @wordpress/scripts and @wordpress/\* packages.
-
-* Prefer functional components and hooks; keep components small.
-
-* Register blocks with block.json \+ `register_block_type_from_metadata()`.
- """
-
-## **css\_instructions \= """---**
-
-## **applyTo: "assets/\*\*/\*.{css,scss,sass}"**
-
-## **description: "Styles guidelines"**
-
-# **CSS/Styles Guidelines**
-
-* Namespaces/prefixes to avoid collisions.
-
-* Prefer CSS custom properties; avoid \!important unless necessary.
-
-* Provide editor styles for blocks where needed.
- """
-
-# **\---------- Prompts (WP) \----------**
-
-## **prompt\_register\_block \= """---**
-
-## **description: "Register a Gutenberg block from block.json and scaffold files"**
-
-## **mode: "ask"**
-
-## **model: ""**
-
-## **tools: \[\]**
-
-# **Register a Gutenberg Block**
-
-Given a short block idea, scaffold:
-
-* `block.json` (name, title, category, attributes, supports)
-
-* `index.js` using @wordpress/scripts, functional component
-
-* Register via `register_block_type_from_metadata()` in PHP
-
-Ensure i18n, namespace prefixes, and enqueue correct editor/front assets.
- """
-
-## **prompt\_enqueue\_assets \= """---**
-
-## **description: "Enqueue scripts/styles the WordPress way"**
-
-## **mode: "ask"**
-
-## **model: ""**
-
-## **tools: \[\]**
-
-# **Enqueue Assets**
-
-Enqueue assets using `wp_enqueue_scripts` (front) and `admin_enqueue_scripts` (admin):
-
-* Use `wp_register_script/style` and dependency arrays.
-
-* Version assets with file modification time or build hash.
-
-* Localise data via `wp_localize_script` (no secrets).
-
-Return code snippets for functions.php or plugin main file.
- """
-
-## **prompt\_settings\_page \= """---**
-
-## **description: "Create an admin Settings page using WordPress Settings API"**
-
-## **mode: "ask"**
-
-## **model: ""**
-
-## **tools: \[\]**
-
-# **WP Settings Page**
-
-Create a Settings page with:
-
-* Admin menu entry (capability check)
-
-* Settings API: register\_setting, add\_settings\_section, add\_settings\_field
-
-* Sanitisation callbacks; nonces
-
-* Translatable labels using a specified text domain (placeholder: `your-text-domain`)
- """
-
-## **prompt\_phpdoc \= """---**
-
-## **description: "Generate PHPDoc for public functions/classes (WPCS)"**
-
-## **mode: "edit"**
-
-## **model: ""**
-
-## **tools: \[\]**
-
-# **Generate PHPDoc**
-
-Add concise PHPDoc blocks for public functions/classes:
-
-* Summary one-liner; `@since` (placeholder), `@param` with types, `@return`
-
-* Reference hooks/filters where relevant
-
-* Do not alter behaviour
- """
-
-# **\---------- Chat Modes \----------**
-
-## **chatmode\_wp \= """---**
-
-## **description: "WordPress Mode: secure, PHPCS-compliant answers with core APIs"**
-
-## **tools: \["codebase"\]**
-
-## **model: ""**
-
-# **WordPress Mode**
-
-Answer as a seasoned WordPress engineer. Prioritise:
-
-* Security (escaping/sanitising, nonces, caps)
-
-* I18n (text domain)
-
-* WPCS compliance
-
-* Core APIs over custom re-implementation
- """
-
-# **\---------- Claude Subagents \----------**
-
-## **agent\_security \= """---**
-
-## **name: "wp-security-review"**
-
-## **description: "Audits code for escaping/sanitisation/nonces/cap checks"**
-
-## **tools: \["Read"\]**
-
-# **WP Security Review Agent**
-
-* Scan changed PHP files for unescaped output and unsanitised input.
-
-* Verify nonces and capability checks for actions.
-
-* Report concrete fixes with code examples.
- """
-
-## **agent\_performance \= """---**
-
-## **name: "wp-performance-audit"**
-
-## **description: "Finds obvious performance pitfalls (queries, transients, caching)"**
-
-## **tools: \["Read"\]**
-
-# **WP Performance Audit Agent**
-
-* Flag N+1 DB queries, missing caching/transients, or unbounded loops.
-
-* Suggest use of `WP_Query` args, transients, and object caching patterns.
- """
-
-# **\---------- Prompt Collection (experimental) \----------**
-
-prompt\_collection \= {
- "$schema": "https://example.com/schemas/prompt-collection.schema.json",
- "name": "WordPress Starters",
- "description": "Reusable Copilot prompts for common WP tasks",
- "prompts": \[
- {"id": "wp-register-block", "path": ".github/prompts/wp-register-block.prompt.md", "tags": \["blocks","gutenberg"\]},
- {"id": "wp-enqueue-assets", "path": ".github/prompts/wp-enqueue-assets.prompt.md", "tags": \["assets","enqueue"\]},
- {"id": "wp-settings-page", "path": ".github/prompts/wp-settings-page.prompt.md", "tags": \["admin","settings"\]},
- {"id": "wp-phpdoc", "path": ".github/prompts/wp-phpdoc.prompt.md", "tags": \["phpdoc","wpcs"\]}
- \]
- }
-
-# **\---------- PR Template \----------**
-
-pr\_template \= """\#\# Summary
-
-\<\!-- Why is this change needed? \--\>
-
-## **Related Issues**
-
-Closes \#\_\_\_
-
-## **Changes**
-
-* PHPCS passes (WPCS)
-
-* Escaping/sanitisation/nonces/cap checks verified
-
-* I18n (text domain, translators' comments)
-
-* Blocks registered properly (block.json & PHP)
-
-* Back-compat verified (PHP/WP)
-
-* Tests/docs updated
-
-## **QA Steps**
-
-1. …
-
-2. …
-
-3. …
-
-## **Screenshots**
-
-"""
-
-# **\---------- Copilot repo instructions \----------**
-
-copilot\_repo \= """\# Copilot Instructions (WordPress)
-
-* Generate WPCS-compliant PHP and i18n-ready strings.
-
-* Always propose escaping/sanitising and capability checks.
-
-* Use core WP APIs first; blocks via block.json.
-
-* Keep diffs minimal; include PHPDoc.
- """
-
-# **\---------- Write files \----------**
-
-files \= {
- "README.md": readme,
- "AGENTS.md": agents\_md,
- "CLAUDE.md": claude\_md,
- "GEMINI.md": gemini\_md,
- ".editorconfig": editorconfig,
- ".gitignore": gitignore,
- ".gitattributes": gitattributes,
- "docs/copilot-space/INDEX.md": index\_md,
- "docs/copilot-space/issue-templates.md": issue\_templates\_md,
- "docs/copilot-space/pr-templates.md": pr\_templates\_md,
- "docs/copilot-space/saved-replies.md": saved\_replies\_md,
- "docs/copilot-space/copilot-instructions.md": copilot\_instructions\_doc,
- "docs/copilot-space/prompt-files.md": prompt\_files\_doc,
- "docs/copilot-space/chatmodes.md": chatmodes\_doc,
- "docs/copilot-space/agents-md.md": agents\_md\_doc,
- "docs/copilot-space/claude-agents.md": claude\_agents\_doc,
- "docs/copilot-space/gemini-md.md": gemini\_doc,
- "docs/copilot-space/schemas/issue-form-schema.md": issue\_schema,
- "docs/copilot-space/schemas/prompt-frontmatter-schema.md": prompt\_schema,
- "docs/copilot-space/schemas/chatmode-frontmatter-schema.md": chatmode\_schema,
- "docs/copilot-space/schemas/claude-subagent-schema.md": claude\_subagent\_schema,
- "docs/copilot-space/schemas/prompt-collection-schema.md": prompt\_collection\_schema,
- "docs/wp-guides/wp-coding-standards.md": wp\_coding,
- "docs/wp-guides/wp-security-checklist.md": wp\_security,
- "docs/wp-guides/block-dev-checklist.md": block\_dev,
- ".github/copilot-instructions.md": copilot\_repo\_instructions,
- ".github/CODEOWNERS": codeowners,
- ".github/ISSUE\_TEMPLATE/bug\_report.yml": bug\_report\_yml,
- ".github/ISSUE\_TEMPLATE/feature\_request.yml": feature\_request\_yml,
- ".github/PULL\_REQUEST\_TEMPLATE/pull\_request\_template.md": pr\_template,
- ".github/instructions/php.instructions.md": php\_instructions,
- ".github/instructions/js.instructions.md": js\_instructions,
- ".github/instructions/css.instructions.md": css\_instructions,
- ".github/prompts/wp-register-block.prompt.md": prompt\_register\_block,
- ".github/prompts/wp-enqueue-assets.prompt.md": prompt\_enqueue\_assets,
- ".github/prompts/wp-settings-page.prompt.md": prompt\_settings\_page,
- ".github/prompts/wp-phpdoc.prompt.md": prompt\_phpdoc,
- ".github/chatmodes/wordpress.chatmode.md": chatmode\_wp,
- ".github/agents/wp-security-review.md": agent\_security,
- ".github/agents/wp-performance-audit.md": agent\_performance,
- ".github/prompts/collection.wp.json": json.dumps(prompt\_collection, indent=2),
- }
-
-for rel, content in files.items():
- p \= os.path.join(root, rel)
- os.makedirs(os.path.dirname(p), exist\_ok=True)
- mode \= "w"
- encoding \= "utf-8"
- with open(p, mode, encoding=encoding, newline="\\n") as f:
- f.write(content)
-
-# **VSCode settings**
-
-vscode\_settings \= {
- "editor.wordWrap": "on",
- "editor.defaultFormatter": "esbenp.prettier-vscode",
- "\[markdown\]": {"editor.wordWrap": "on"}
- }
- with open(os.path.join(root, ".vscode/settings.json"), "w", encoding="utf-8") as f:
- json.dump(vscode\_settings, f, indent=2)
-
-# **Zip it**
-
-zip\_path \= "/mnt/data/copilot-space-wordpress.zip"
- with zipfile.ZipFile(zip\_path, "w", zipfile.ZIP\_DEFLATED) as z:
- for base, \_, files\_in in os.walk(root):
- for name in files\_in:
- full \= os.path.join(base, name)
- rel \= os.path.relpath(full, root)
- z.write(full, arcname=os.path.join("copilot-space-wp", rel))
-
-zip\_path
-
-Always show details
-Result
-'/mnt/data/copilot-space-wordpress.zip'
-
-Done, Ash — I built a **WordPress-focused Copilot Space** with correct, compliant front matter across templates and AI files, plus clear docs and a lightweight prompt-collection schema.
-
-Download the Copilot Space (WordPress)
-
-## **Highlights**
-
-* **WordPress-ready**: repo/path Copilot instructions, prompts for blocks/enqueues/settings pages/PHPDoc, WP chat mode, and Claude subagents for security & performance.
-
-* **Issue/PR templates**: proper Issue Forms YAML (WP \+ PHP env fields) and a PR checklist aligned to WPCS, i18n, and security.
-
-* **Docs & schemas**: tutorial pages for each file type \+ schema references, including an **experimental prompt collection** (`.github/prompts/collection.wp.json`).
-
-## **Structure (key parts)**
-
-* `.github/`
-
- * `copilot-instructions.md` (repo-wide WP rules)
-
- * `instructions/*.instructions.md` (PHP/JS/CSS rules via `applyTo`)
-
- * `prompts/*.prompt.md` (WP block, enqueue, settings page, PHPDoc)
-
- * `prompts/collection.wp.json` (prompt bundle)
-
- * `chatmodes/wordpress.chatmode.md` (secure, PHPCS-compliant persona)
-
- * `agents/wp-security-review.md`, `wp-performance-audit.md`
-
- * `ISSUE_TEMPLATE/*.yml`, `PULL_REQUEST_TEMPLATE/pull_request_template.md`
-
-* `docs/copilot-space/*` (how-to guides \+ schemas)
-
-* `docs/wp-guides/*` (WPCS quickstart, security checklist, block dev checklist)
-
-* Root: `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `.editorconfig` tuned for WP (tabs for PHP)
-
-If you want this merged into your template repo (with workflows, Composer/Node scaffolding, or PHPCS config out the box), I can package that next.
-
diff --git a/gutenberg/how-to-guides/curating-the-editor-experience/theme-json.md b/gutenberg/how-to-guides/curating-the-editor-experience/theme-json.md
deleted file mode 100644
index d14f29e..0000000
--- a/gutenberg/how-to-guides/curating-the-editor-experience/theme-json.md
+++ /dev/null
@@ -1,206 +0,0 @@
-# theme.json
-
-A theme's theme.json file is one of the best ways to curate the Editor experience and will likely be the first tool you use before reaching for more sophisticated solutions.
-
-## Providing default controls/options
-
-Since theme.json acts as a configuration tool, there are numerous ways to define at a granular level what options are available. This section will use duotone as an example since it showcases a feature that cuts across a few blocks and allows for varying levels of access.
-
-*Duotone with Core options and customization available for each image related block:*
-
-```json
-{
- "version": 3,
- "settings": {
- "color": {
- "customDuotone": true,
- "duotone": [
- ]
- }
- }
-}
-```
-
-*Duotone with theme defined color options, Core options, and customization available for each image related block:*
-
-```json
-{
- "version": 3,
- "settings": {
- "color": {
- "duotone": [
- {
- "colors": [ "#000000", "#ffffff" ],
- "slug": "foreground-and-background",
- "name": "Foreground and background"
- },
- {
- "colors": [ "#000000", "#ff0200" ],
- "slug": "foreground-and-secondary",
- "name": "Foreground and secondary"
- },
- {
- "colors": [ "#000000", "#7f5dee" ],
- "slug": "foreground-and-tertiary",
- "name": "Foreground and tertiary"
- },
- ]
- }
- }
-}
-```
-
-*Duotone with defined default options and all customization available for the Post Featured Image block:*
-
-```json
-{
- "version": 3,
- "settings": {
- "color": {
- "custom": true,
- "customDuotone": true
- },
- "blocks": {
- "core/post-featured-image": {
- "color": {
- "duotone": [
- {
- "colors": [ "#282828", "#ff5837" ],
- "slug": "black-and-orange",
- "name": "Black and Orange"
- },
- {
- "colors": [ "#282828", "#0288d1" ],
- "slug": "black-and-blue",
- "name": "Black and Blue"
- }
- ],
- "customDuotone": true,
- "custom": true
- }
- }
- }
- }
-}
-```
-
-*Duotone with only defined default options and core options available for the Post Featured Image block (no customization):*
-
-```json
-{
- "version": 3,
- "settings": {
- "color": {
- "custom": true,
- "customDuotone": true
- },
- "blocks": {
- "core/post-featured-image": {
- "color": {
- "duotone": [
- {
- "colors": [ "#282828", "#ff5837" ],
- "slug": "black-and-orange",
- "name": "Black and Orange"
- },
- {
- "colors": [ "#282828", "#0288d1" ],
- "slug": "black-and-blue",
- "name": "Black and Blue"
- }
- ],
- "customDuotone": false,
- "custom": false
- }
- }
- }
- }
-}
-```
-
-## Limiting interface options with theme.json
-
-### Limit options on a per-block basis
-
-Beyond defining default values, using theme.json allows you to also remove options entirely and instead rely on what the theme has set in place. Below is a visual showing two extremes with the same paragraph block:
-
-
-
-Continuing the examples with duotone, this means you could allow full access to all Duotone functionality for Image blocks and only limit the Post Featured Image block like so:
-
-```json
-{
- "version": 3,
- "settings": {
- "color": {
- "custom": true,
- "customDuotone": true
- },
- "blocks": {
- "core/image": {
- "color": {
- "duotone": [],
- "customDuotone": true,
- "custom": true
- }
- },
- "core/post-featured-image": {
- "color": {
- "duotone": [],
- "customDuotone": false,
- "custom": false
- }
- }
- }
- }
-}
-```
-
-You can read more about how best to [turn on/off options with theme.json here](/docs/how-to-guides/themes/global-settings-and-styles.md).
-
-### Disable inherit default layout
-
-To disable the “Inherit default layout” setting for container blocks like the Group block, remove the following section:
-
-```json
-"layout": {
- "contentSize": null,
- "wideSize": null
-},
-```
-
-### Limit options globally
-
-When using theme.json in a block or classic theme, these settings will stop the default color and typography controls from being enabled globally, greatly limiting what’s possible:
-
-```json
-{
- "version": 3,
- "settings": {
- "layout": {
- "contentSize": "750px"
- },
- "color": {
- "background": false,
- "custom": false,
- "customDuotone": false,
- "customGradient": false,
- "defaultGradients": false,
- "defaultPalette": false,
- "text": false
- },
- "typography": {
- "customFontSize": false,
- "dropCap": false,
- "fontStyle": false,
- "fontWeight": false,
- "letterSpacing": false,
- "lineHeight": false,
- "textDecoration": false,
- "textTransform": false
- }
- }
-}
-```
-
-To enable something from the above, just set whatever value you want to change to `true` for more granularity.
\ No newline at end of file
diff --git a/gutenberg/how-to-guides/data-basics/3-building-an-edit-form.md b/gutenberg/how-to-guides/data-basics/3-building-an-edit-form.md
deleted file mode 100644
index 1e2b445..0000000
--- a/gutenberg/how-to-guides/data-basics/3-building-an-edit-form.md
+++ /dev/null
@@ -1,553 +0,0 @@
-# Building an edit form
-
-This part is about adding an *Edit* feature to our app. Here's a glimpse of what we're going to build:
-
-
-
-### Step 1: Add an _Edit_ button
-
-We can't have an *Edit* form without an *Edit* button, so let's start by adding one to our `PagesList` component:
-
-```js
-import { Button } from '@wordpress/components';
-import { decodeEntities } from '@wordpress/html-entities';
-
-const PageEditButton = () => (
-
-)
-
-function PagesList( { hasResolved, pages } ) {
- if ( ! hasResolved ) {
- return ;
- }
- if ( ! pages?.length ) {
- return
No results
;
- }
-
- return (
-
-
-
-
Title
-
Actions
-
-
-
- { pages?.map( ( page ) => (
-
-
{ decodeEntities( page.title.rendered ) }
-
-
-
-
- ) ) }
-
-
- );
-}
-```
-
-The only change in `PagesList` is the additional column labeled _Actions_:
-
-
-
-### Step 2: Display an _Edit_ form
-
-Our button looks nice but doesn't do anything yet. To display an edit form, we need to have one first – let's create it:
-
-```js
-import { Button, TextControl } from '@wordpress/components';
-function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
- return (
-
-
-
-
-
-
-
- );
-}
-```
-
-Now let's make the button display the form we just created. As this tutorial is not focused on web design, we will wire the two together using a component that requires the least amount of code: [`Modal`](https://developer.wordpress.org/block-editor/reference-guides/components/modal/). Let's update `PageEditButton` accordingly:
-
-```js
-import { Button, Modal, TextControl } from '@wordpress/components';
-
-function PageEditButton({ pageId }) {
- const [ isOpen, setOpen ] = useState( false );
- const openModal = () => setOpen( true );
- const closeModal = () => setOpen( false );
- return (
- <>
-
- { isOpen && (
-
-
-
- ) }
- >
- )
-}
-```
-
-When you click the *Edit* button now, you should see the following modal:
-
-
-
-Great! We now have a basic user interface to work with.
-
-### Step 3: Populate the form with page details
-
-We want the `EditPageForm` to display the title of the currently edited page. You may have noticed that it doesn't receive a `page` prop, only `pageId`. That's okay. Gutenberg Data allows us to easily access entity records from any component.
-
-In this case, we need to use the [`getEntityRecord`](/docs/reference-guides/data/data-core.md#getentityrecord) selector. The list of records is already available thanks to the `getEntityRecords` call in `MyFirstApp`, so there won't even be any additional HTTP requests involved – we'll get the cached record right away.
-
-Here's how you can try it in your browser's dev tools:
-
-```js
-wp.data.select( 'core' ).getEntityRecord( 'postType', 'page', 9 ); // Replace 9 with an actual page ID
-```
-
-Let's update `EditPageForm` accordingly:
-
-```js
-function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
- const page = useSelect(
- select => select( coreDataStore ).getEntityRecord( 'postType', 'page', pageId ),
- [pageId]
- );
- return (
-
-
- { /* ... */ }
-
- );
-}
-```
-
-Now it should look like this:
-
-
-
-### Step 4: Making the Page title field editable
-
-There's one problem with our _Page title_ field: you can't edit it. It receives a fixed `value` but doesn't update it when typing. We need an `onChange` handler.
-
-
-You may have seen a pattern similar to this one in other React apps. It's known as a ["controlled component"](https://reactjs.org/docs/forms.html#controlled-components):
-
-```js
-function VanillaReactForm({ initialTitle }) {
- const [title, setTitle] = useState( initialTitle );
- return (
-
- );
-}
-```
-
-Updating entity records in Gutenberg Data is similar but instead of using `setTitle` to store in local (component level) state, we use the `editEntityRecord` action which stores the updates in the _Redux_ state. Here's how you can try it out in your browser's dev tools:
-
-```js
-// We need a valid page ID to call editEntityRecord, so let's get the first available one using getEntityRecords.
-const pageId = wp.data.select( 'core' ).getEntityRecords( 'postType', 'page' )[0].id;
-
-// Update the title
-wp.data.dispatch( 'core' ).editEntityRecord( 'postType', 'page', pageId, { title: 'updated title' } );
-```
-
-At this point, you may ask _how_ is `editEntityRecord` better than `useState`? The answer is that it offers a few features you wouldn't otherwise get.
-
-Firstly, we can save the changes as easily as we retrieve the data and ensure that all caches will be correctly updated.
-
-Secondly, the changes applied via `editEntityRecord` are easily undo-able via the `undo` and `redo` actions.
-
-Lastly, because the changes live in the _Redux_ state, they are "global" and can be accessed by other components. For example, we could make the `PagesList` display the currently edited title.
-
-To that last point, let's see what happens when we use `getEntityRecord` to access the entity record we just updated:
-
-```js
-wp.data.select( 'core' ).getEntityRecord( 'postType', 'page', pageId ).title
-```
-
-It doesn't reflect the edits. What's going on?
-
-Well, `` renders the data returned by `getEntityRecord()`. If `getEntityRecord()` reflected the updated title, then anything the user types in the `TextControl` would be immediately displayed inside ``, too. This is not what we want. The edits shouldn't leak outside the form until the user decides to save them.
-
-Gutenberg Data solves this problem by making a distinction between *Entity Records* and *Edited Entity Records*. *Entity Records* reflect the data from the API and ignore any local edits, while *Edited Entity Records* also have all the local edits applied on top. Both co-exist in the Redux state at the same time.
-
-Let's see what happens if we call `getEditedEntityRecord`:
-
-```js
-wp.data.select( 'core' ).getEditedEntityRecord( 'postType', 'page', pageId ).title
-// "updated title"
-
-wp.data.select( 'core' ).getEntityRecord( 'postType', 'page', pageId ).title
-// { "rendered": "", "raw": "..." }
-```
-
-As you can see, the `title` of an Entity Record is an object, but the `title` of an Edited Entity record is a string.
-
-This is no accident. Fields like `title`, `excerpt`, and `content` may contain [shortcodes](https://developer.wordpress.org/apis/handbook/shortcode/) or [dynamic blocks](/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md), which means they can only be rendered on the server. For such fields, the REST API exposes both the `raw` markup _and_ the `rendered` string. For example, in the block editor, `content.rendered` could used as a visual preview, and `content.raw` could be used to populate the code editor.
-
-So why is the `content` of an Edited Entity Record a string? Since JavaScript is not be able to properly render arbitrary block markup, it stores only the `raw` markup without the `rendered` part. And since that's a string, the entire field becomes a string.
-
-We can now update `EditPageForm` accordingly. We can access the actions using the [`useDispatch`](/packages/data/README.md#usedispatch) hook similarly to how we use `useSelect` to access selectors:
-
-```js
-import { useDispatch } from '@wordpress/data';
-
-function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
- const page = useSelect(
- select => select( coreDataStore ).getEditedEntityRecord( 'postType', 'page', pageId ),
- [ pageId ]
- );
- const { editEntityRecord } = useDispatch( coreDataStore );
- const handleChange = ( title ) => editEntityRecord( 'postType', 'page', pageId, { title } );
-
- return (
-
-
-
-
-
-
-
- );
-}
-```
-
-We added an `onChange` handler to keep track of edits via the `editEntityRecord` action and then changed the selector to `getEditedEntityRecord` so that `page.title` always reflects the changes.
-
-This is what it looks like now:
-
-
-
-### Step 5: Saving the form data
-
-Now that we can edit the page title let's also make sure we can save it. In Gutenberg data, we save changes to the WordPress REST API using the `saveEditedEntityRecord` action. It sends the request, processes the result, and updates the cached data in the Redux state.
-
-Here's an example you may try in your browser's dev tools:
-
-```js
-// Replace 9 with an actual page ID
-wp.data.dispatch( 'core' ).editEntityRecord( 'postType', 'page', 9, { title: 'updated title' } );
-wp.data.dispatch( 'core' ).saveEditedEntityRecord( 'postType', 'page', 9 );
-```
-
-The above snippet saved a new title. Unlike before, `getEntityRecord` now reflects the updated title:
-
-```js
-// Replace 9 with an actual page ID
-wp.data.select( 'core' ).getEntityRecord( 'postType', 'page', 9 ).title.rendered
-// "updated title"
-```
-
-Entity records are updated to reflect any saved changes right after the REST API request is finished.
-
-This is how the `EditPageForm` looks like with a working *Save* button:
-
-```js
-function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
- // ...
- const { saveEditedEntityRecord } = useDispatch( coreDataStore );
- const handleSave = () => saveEditedEntityRecord( 'postType', 'page', pageId );
-
- return (
-
- {/* ... */}
-
-
- {/* ... */}
-
-
- );
-}
-```
-
-It works, but there's still one thing to fix: the form modal doesn't automatically close because we never call `onSaveFinished`. Lucky for us, `saveEditedEntityRecord` returns a promise that resolves once the save operation is finished. Let's take advantage of it in `EditPageForm`:
-
-```js
-function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
- // ...
- const handleSave = async () => {
- await saveEditedEntityRecord( 'postType', 'page', pageId );
- onSaveFinished();
- };
- // ...
-}
-```
-
-### Step 6: Handle errors
-
-We optimistically assumed that a *save* operation would always succeed. Unfortunately, it may fail in many ways:
-
-* The website can be down
-* The update may be invalid
-* The page could have been deleted by someone else in the meantime
-
-To tell the user when any of these happens, we have to make two adjustments. We don't want to close the form modal when the update fails. The promise returned by `saveEditedEntityRecord` is resolved with an updated record only if the update actually worked. When something goes wrong, it resolves with an empty value. Let's use it to keep the modal open:
-
-```js
-function EditPageForm( { pageId, onSaveFinished } ) {
- // ...
- const handleSave = async () => {
- const updatedRecord = await saveEditedEntityRecord( 'postType', 'page', pageId );
- if ( updatedRecord ) {
- onSaveFinished();
- }
- };
- // ...
-}
-```
-
-Great! Now, let's display an error message. The failure details can be grabbed using the `getLastEntitySaveError` selector:
-
-```js
-// Replace 9 with an actual page ID
-wp.data.select( 'core' ).getLastEntitySaveError( 'postType', 'page', 9 )
-```
-
-Here's how we can use it in `EditPageForm`:
-
-```js
-function EditPageForm( { pageId, onSaveFinished } ) {
- // ...
- const { lastError, page } = useSelect(
- select => ({
- page: select( coreDataStore ).getEditedEntityRecord( 'postType', 'page', pageId ),
- lastError: select( coreDataStore ).getLastEntitySaveError( 'postType', 'page', pageId )
- }),
- [ pageId ]
- )
- // ...
- return (
-
- {/* ... */}
- { lastError ? (
-
- Error: { lastError.message }
-
- ) : false }
- {/* ... */}
-
- );
-}
-```
-
-Great! `EditPageForm` is now fully aware of errors.
-
-Let's see that error message in action. We'll trigger an invalid update and let it fail. The post title is hard to break, so let's set a `date` property to `-1` instead – that's a guaranteed validation error:
-
-```js
-function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
- // ...
- const handleChange = ( title ) => editEntityRecord( 'postType', 'page', pageId, { title, date: -1 } );
- // ...
-}
-```
-
-Once you refresh the page, open the form, change the title, and hit save, you should see the following error message:
-
-
-
-Fantastic! We can now **restore the previous version of `handleChange`** and move on to the next step.
-
-### Step 7: Status indicator
-
-There is one last problem with our form: no visual feedback. We can’t be quite sure whether the *Save* button worked until either the form disappears or an error message shows.
-
-We're going to clear it up and communicate two states to the user: _Saving_ and _No changes detected_. The relevant selectors are `isSavingEntityRecord` and `hasEditsForEntityRecord`. Unlike `getEntityRecord`, they never issue any HTTP requests but only return the current entity record state.
-
-Let's use them in `EditPageForm`:
-
-```js
-function EditPageForm( { pageId, onSaveFinished } ) {
- // ...
- const { isSaving, hasEdits, /* ... */ } = useSelect(
- select => ({
- isSaving: select( coreDataStore ).isSavingEntityRecord( 'postType', 'page', pageId ),
- hasEdits: select( coreDataStore ).hasEditsForEntityRecord( 'postType', 'page', pageId ),
- // ...
- }),
- [ pageId ]
- )
-}
-```
-
-We can now use `isSaving` and `hasEdits` to display a spinner when saving is in progress and grey out the save button when there are no edits:
-
-```js
-function EditPageForm( { pageId, onSaveFinished } ) {
- // ...
- return (
- // ...
-
-
-
-
- // ...
- );
-}
-```
-
-Note that we disable the _save_ button when there are no edits and when the page is currently being saved. This is to prevent the user from accidentally pressing the button twice.
-
-Also, interrupting a *save* in progress is not supported by `@wordpress/data` so we also conditionally disabled the _cancel_ button.
-
-Here's what it looks like in action:
-
-
-
-
-### Wiring it all together
-
-All the pieces are in place, great! Here’s everything we built in this chapter in one place:
-
-```js
-import { useDispatch } from '@wordpress/data';
-import { Button, Modal, TextControl } from '@wordpress/components';
-
-function PageEditButton( { pageId } ) {
- const [ isOpen, setOpen ] = useState( false );
- const openModal = () => setOpen( true );
- const closeModal = () => setOpen( false );
- return (
- <>
-
- { isOpen && (
-
-
-
- ) }
- >
- );
-}
-
-function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
- const { page, lastError, isSaving, hasEdits } = useSelect(
- ( select ) => ( {
- page: select( coreDataStore ).getEditedEntityRecord( 'postType', 'page', pageId ),
- lastError: select( coreDataStore ).getLastEntitySaveError( 'postType', 'page', pageId ),
- isSaving: select( coreDataStore ).isSavingEntityRecord( 'postType', 'page', pageId ),
- hasEdits: select( coreDataStore ).hasEditsForEntityRecord( 'postType', 'page', pageId ),
- } ),
- [ pageId ]
- );
-
- const { saveEditedEntityRecord, editEntityRecord } = useDispatch( coreDataStore );
- const handleSave = async () => {
- const savedRecord = await saveEditedEntityRecord( 'postType', 'page', pageId );
- if ( savedRecord ) {
- onSaveFinished();
- }
- };
- const handleChange = ( title ) => editEntityRecord( 'postType', 'page', page.id, { title } );
-
- return (
-
-
- { lastError ? (
-
Error: { lastError.message }
- ) : (
- false
- ) }
-
-
-
-
-
- );
-}
-```
-
-## What's next?
-
-* **Previous part:** [Building a list of pages](/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md)
-* **Next part:** [Building a Create Page form](/docs/how-to-guides/data-basics/4-building-a-create-page-form.md)
-* (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
diff --git a/gutenberg/how-to-guides/data-basics/4-building-a-create-page-form.md b/gutenberg/how-to-guides/data-basics/4-building-a-create-page-form.md
deleted file mode 100644
index c880a1a..0000000
--- a/gutenberg/how-to-guides/data-basics/4-building-a-create-page-form.md
+++ /dev/null
@@ -1,396 +0,0 @@
-# Building a Create page form
-
-In the [previous part](/docs/how-to-guides/data-basics/3-building-an-edit-form.md) we created an *Edit page* feature, and in this part we will add a *Create page* feature. Here's a glimpse of what we're going to build:
-
-
-
-### Step 1: Add a _Create a new page_ button
-
-Let’s start by building a button to display the _create page_ form. It’s similar to an _Edit_ button we have built in the [part 3](/docs/how-to-guides/data-basics/3-building-an-edit-form.md):
-
-```js
-import { useDispatch } from '@wordpress/data';
-import { Button, Modal, TextControl } from '@wordpress/components';
-
-function CreatePageButton() {
- const [isOpen, setOpen] = useState( false );
- const openModal = () => setOpen( true );
- const closeModal = () => setOpen( false );
- return (
- <>
-
- { isOpen && (
-
-
-
- ) }
- >
- );
-}
-
-function CreatePageForm() {
- // Empty for now
- return ;
-}
-
-```
-
-Great! Now let’s make `MyFirstApp` display our shiny new button:
-
-```js
-function MyFirstApp() {
- // ...
- return (
-
-
-
-
-
-
-
- );
-}
-```
-
-The final result should look as follows:
-
-
-
-### Step 2: Extract a controlled PageForm
-
-Now that the button is in place, we can focus entirely on building the form. This tutorial is about managing data, so we will not build a complete page editor. Instead, the form will only contain one field: post title.
-
-Luckily, the `EditPageForm` we built in [part three](/docs/how-to-guides/data-basics/3-building-an-edit-form.md) already takes us 80% of the way there. The bulk of the user interface is already available, and we will reuse it in the `CreatePageForm`. Let’s start by extracting the form UI into a separate component:
-
-```js
-function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
- // ...
- return (
-
- );
-}
-
-function PageForm( { title, onChangeTitle, hasEdits, lastError, isSaving, onCancel, onSave } ) {
- return (
-
-
- { lastError ? (
-
Error: { lastError.message }
- ) : (
- false
- ) }
-
-
-
-
-
- );
-}
-```
-
-This code quality change should not alter anything about how the application works. Let’s try to edit a page just to be sure:
-
-
-
-Great! The edit form is still there, and now we have a building block to power the new `CreatePageForm`.
-
-### Step 3: Build a CreatePageForm
-
-The only thing that `CreatePageForm` component must do is to provide the following seven properties needed to render the `PageForm` component:
-
-* title
-* onChangeTitle
-* hasEdits
-* lastError
-* isSaving
-* onCancel
-* onSave
-
-Let’s see how we can do that:
-
-#### Title, onChangeTitle, hasEdits
-
-The `EditPageForm` updated and saved an existing entity record that lived in the Redux state. Because of that, we relied on the `editedEntityRecords` selector.
-
-In case of the `CreatePageForm` however, there is no pre-existing entity record. There is only an empty form. Anything that the user types is local to that form, which means we can keep track of it using the React’s `useState` hook:
-
-```js
-function CreatePageForm( { onCancel, onSaveFinished } ) {
- const [title, setTitle] = useState();
- const handleChange = ( title ) => setTitle( title );
- return (
-
- );
-}
-```
-
-#### onSave, onCancel
-
-In the `EditPageForm`, we dispatched the `saveEditedEntityRecord('postType', 'page', pageId )` action to save the edits that lived in the Redux state.
-
-In the `CreatePageForm` however, we do not have any edits in the Redux state, nor we do have a `pageId`. The action we need to dispatch in this case is called [`saveEntityRecord`](https://developer.wordpress.org/block-editor/reference-guides/data/data-core/#saveentityrecord) (without the word _Edited_ in the name) and it accepts an object representing the new entity record instead of a `pageId`.
-
-The data passed to `saveEntityRecord` is sent via a POST request to the appropriate REST API endpoint. For example, dispatching the following action:
-
-```js
-saveEntityRecord( 'postType', 'page', { title: "Test" } );
-```
-
-Triggers a POST request to the [`/wp/v2/pages` WordPress REST API](https://developer.wordpress.org/rest-api/reference/pages/) endpoint with a single field in the request body: `title=Test`.
-
-Now that we know more about `saveEntityRecord`, let's use it in `CreatePageForm`.
-
-```js
-function CreatePageForm( { onSaveFinished, onCancel } ) {
- // ...
- const { saveEntityRecord } = useDispatch( coreDataStore );
- const handleSave = async () => {
- const savedRecord = await saveEntityRecord(
- 'postType',
- 'page',
- { title }
- );
- if ( savedRecord ) {
- onSaveFinished();
- }
- };
- return (
-
- );
-}
-```
-
-There is one more detail to address: our newly created pages are not yet picked up by the `PagesList`. Accordingly to the REST API documentation, the `/wp/v2/pages` endpoint creates (`POST` requests) pages with `status=draft` by default, but _returns_ (`GET` requests) pages with `status=publish`. The solution is to pass the `status` parameter explicitly:
-
-```js
-function CreatePageForm( { onSaveFinished, onCancel } ) {
- // ...
- const { saveEntityRecord } = useDispatch( coreDataStore );
- const handleSave = async () => {
- const savedRecord = await saveEntityRecord(
- 'postType',
- 'page',
- { title, status: 'publish' }
- );
- if ( savedRecord ) {
- onSaveFinished();
- }
- };
- return (
-
- );
-}
-```
-
-Go ahead and apply that change to your local `CreatePageForm` component, and let’s tackle the remaining two props.
-
-#### lastError, isSaving
-
-The `EditPageForm` retrieved the error and progress information via the `getLastEntitySaveError` and `isSavingEntityRecord` selectors. In both cases, it passed the following three arguments: `( 'postType', 'page', pageId )`.
-
-In `CreatePageForm` however, we do not have a `pageId`. What now? We can skip the `pageId` argument to retrieve the information about the entity record without any id – this will be the newly created one. The `useSelect` call is thus very similar to the one from `EditPageForm`:
-
-```js
-function CreatePageForm( { onCancel, onSaveFinished } ) {
- // ...
- const { lastError, isSaving } = useSelect(
- ( select ) => ( {
- // Notice the missing pageId argument:
- lastError: select( coreDataStore )
- .getLastEntitySaveError( 'postType', 'page' ),
- // Notice the missing pageId argument
- isSaving: select( coreDataStore )
- .isSavingEntityRecord( 'postType', 'page' ),
- } ),
- []
- );
- // ...
- return (
-
- );
-}
-```
-
-And that’s it! Here's what our new form looks like in action:
-
-
-
-
-### Wiring it all together
-
-Here’s everything we built in this chapter in one place:
-
-```js
-function CreatePageForm( { onCancel, onSaveFinished } ) {
- const [title, setTitle] = useState();
- const { lastError, isSaving } = useSelect(
- ( select ) => ( {
- lastError: select( coreDataStore )
- .getLastEntitySaveError( 'postType', 'page' ),
- isSaving: select( coreDataStore )
- .isSavingEntityRecord( 'postType', 'page' ),
- } ),
- []
- );
-
- const { saveEntityRecord } = useDispatch( coreDataStore );
- const handleSave = async () => {
- const savedRecord = await saveEntityRecord(
- 'postType',
- 'page',
- { title, status: 'publish' }
- );
- if ( savedRecord ) {
- onSaveFinished();
- }
- };
-
- return (
-
- );
-}
-
-function EditPageForm( { pageId, onCancel, onSaveFinished } ) {
- const { page, lastError, isSaving, hasEdits } = useSelect(
- ( select ) => ( {
- page: select( coreDataStore ).getEditedEntityRecord( 'postType', 'page', pageId ),
- lastError: select( coreDataStore ).getLastEntitySaveError( 'postType', 'page', pageId ),
- isSaving: select( coreDataStore ).isSavingEntityRecord( 'postType', 'page', pageId ),
- hasEdits: select( coreDataStore ).hasEditsForEntityRecord( 'postType', 'page', pageId ),
- } ),
- [pageId]
- );
-
- const { saveEditedEntityRecord, editEntityRecord } = useDispatch( coreDataStore );
- const handleSave = async () => {
- const savedRecord = await saveEditedEntityRecord( 'postType', 'page', pageId );
- if ( savedRecord ) {
- onSaveFinished();
- }
- };
- const handleChange = ( title ) => editEntityRecord( 'postType', 'page', page.id, { title } );
-
- return (
-
- );
-}
-
-function PageForm( { title, onChangeTitle, hasEdits, lastError, isSaving, onCancel, onSave } ) {
- return (
-
-
- { lastError ? (
-
Error: { lastError.message }
- ) : (
- false
- ) }
-
-
-
-
-
- );
-}
-```
-
-All that’s left is to refresh the page and enjoy the form:
-
-
-
-## What's next?
-
-* **Next part:** [Adding a delete button](/docs/how-to-guides/data-basics/5-adding-a-delete-button.md)
-* **Previous part:** [Building an edit form](/docs/how-to-guides/data-basics/3-building-an-edit-form.md)
-* (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
diff --git a/gutenberg/how-to-guides/data-basics/5-adding-a-delete-button.md b/gutenberg/how-to-guides/data-basics/5-adding-a-delete-button.md
deleted file mode 100644
index e0a0b0d..0000000
--- a/gutenberg/how-to-guides/data-basics/5-adding-a-delete-button.md
+++ /dev/null
@@ -1,449 +0,0 @@
-# Adding a delete button
-
-In the [previous part](/docs/how-to-guides/data-basics/3-building-an-edit-form.md) we added an ability to create new pages,
-and in this part we will add a *Delete* feature to our app.
-
-Here's a glimpse of what we're going to build:
-
-
-
-### Step 1: Add a _Delete_ button
-
-Let's start by creating the `DeletePageButton` component and updating the user interface of our `PagesList` component:
-
-```js
-import { Button } from '@wordpress/components';
-import { decodeEntities } from '@wordpress/html-entities';
-
-const DeletePageButton = () => (
-
-)
-
-function PagesList( { hasResolved, pages } ) {
- if ( ! hasResolved ) {
- return ;
- }
- if ( ! pages?.length ) {
- return
No results
;
- }
-
- return (
-
-
-
-
Title
-
Actions
-
-
-
- { pages?.map( ( page ) => (
-
-
{ decodeEntities( page.title.rendered ) }
-
-
-
- {/* ↓ This is the only change in the PagesList component */}
-
-
-
-
- ) ) }
-
-
- );
-}
-```
-
-This is what the PagesList should look like now:
-
-
-
-### Step 2: Wire the button to a delete action
-
-In Gutenberg data, we delete entity records from the WordPress REST API using the `deleteEntityRecord` action. It sends the request, processes the result, and updates the cached data in the Redux state.
-
-Here's how you can try deleting entity records in your browser's dev tools:
-
-```js
-// We need a valid page ID to call deleteEntityRecord, so let's get the first available one using getEntityRecords.
-const pageId = wp.data.select( 'core' ).getEntityRecords( 'postType', 'page' )[0].id;
-
-// Now let's delete that page:
-const promise = wp.data.dispatch( 'core' ).deleteEntityRecord( 'postType', 'page', pageId );
-
-// promise gets resolved or rejected when the API request succeeds or fails.
-```
-
-Once the REST API request is finished, you will notice one of the pages has disappeared from the list. This is because that list is populated by the `useSelect()` hook and the `select( coreDataStore ).getEntityRecords( 'postType', 'page' )` selector. Anytime the underlying data changes, the list gets re-rendered with fresh data. That's pretty convenient!
-
-Let's dispatch that action when `DeletePageButton` is clicked:
-
-```js
-const DeletePageButton = ({ pageId }) => {
- const { deleteEntityRecord } = useDispatch( coreDataStore );
- const handleDelete = () => deleteEntityRecord( 'postType', 'page', pageId );
- return (
-
- );
-}
-```
-
-### Step 3: Add visual feedback
-
-It may take a few moments for the REST API request to finish after clicking the _Delete_ button. Let's communicate that with a `` component similarly to what we did in the previous parts of this tutorial.
-
-We'll need the `isDeletingEntityRecord` selector for that. It is similar to the `isSavingEntityRecord` selector we've already seen in [part 3](/docs/how-to-guides/data-basics/3-building-an-edit-form.md): it returns `true` or `false` and never issues any HTTP requests:
-
-```js
-const DeletePageButton = ({ pageId }) => {
- // ...
- const { isDeleting } = useSelect(
- select => ({
- isDeleting: select( coreDataStore ).isDeletingEntityRecord( 'postType', 'page', pageId ),
- }),
- [ pageId ]
- )
- return (
-
- );
-}
-```
-
-Here's what it looks like in action:
-
-
-
-### Step 4: Handle errors
-
-We optimistically assumed that a *delete* operation would always succeed. Unfortunately, under the hood, it is a REST API request that can fail in many ways:
-
-* The website can be down.
-* The delete request may be invalid.
-* The page could have been deleted by someone else in the meantime.
-
-To tell the user when any of these errors happen, we need to extract the error information using the `getLastEntityDeleteError` selector:
-
-```js
-// Replace 9 with an actual page ID
-wp.data.select( 'core' ).getLastEntityDeleteError( 'postType', 'page', 9 )
-```
-
-Here's how we can apply it in `DeletePageButton`:
-
-```js
-import { useEffect } from 'react';
-const DeletePageButton = ({ pageId }) => {
- // ...
- const { error, /* ... */ } = useSelect(
- select => ( {
- error: select( coreDataStore ).getLastEntityDeleteError( 'postType', 'page', pageId ),
- // ...
- } ),
- [pageId]
- );
- useEffect( () => {
- if ( error ) {
- // Display the error
- }
- }, [error] )
-
- // ...
-}
-```
-
-The `error` object comes from the `@wordpress/api-fetch` and contains information about the error. It has the following properties:
-
-* `message` – a human-readable error message such as `Invalid post ID`.
-* `code` – a string-based error code such as `rest_post_invalid_id`. To learn about all possible error codes you'd need to refer to the [`/v2/pages` endpoint's source code](https://github.com/WordPress/wordpress-develop/blob/2648a5f984b8abf06872151898e3a61d3458a628/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php#L226-L230).
-* `data` (optional) – error details, contains the `code` property containing the HTTP response code for the failed request.
-
-There are many ways to turn that object into an error message, but in this tutorial, we will display the `error.message`.
-
-WordPress has an established pattern of displaying status information using the `Snackbar` component. Here's what it looks like **in the Widgets editor**:
-
-
-
-Let's use the same type of notifications in our plugin! There are two parts to this:
-
-1. Displaying notifications
-2. Dispatching notifications
-
-#### Displaying notifications
-
-Our application only knows how to display pages but does not know how to display notifications. Let's tell it!
-
-WordPress conveniently provides us with all the React components we need to render notifications. A [component called `Snackbar`](https://wordpress.github.io/gutenberg/?path=/story/components-snackbar--default) represents a single notification:
-
-
-
-We won't use `Snackbar` directly, though. We'll use the `SnackbarList` component, which can display multiple notices using smooth animations and automatically hide them after a few seconds. In fact, WordPress uses the same component used in the Widgets editor and other wp-admin pages!
-
-Let's create our own `Notifications` components:
-
-```js
-import { SnackbarList } from '@wordpress/components';
-import { store as noticesStore } from '@wordpress/notices';
-
-function Notifications() {
- const notices = []; // We'll come back here in a second!
-
- return (
-
- );
-}
-```
-
-The basic structure is in place, but the list of notifications it renders is empty. How do we populate it? We'll lean on the same package as WordPress: [`@wordpress/notices`](https://github.com/WordPress/gutenberg/blob/895ca1f6a7d7e492974ea55f693aecbeb1d5bbe3/docs/reference-guides/data/data-core-notices.md).
-
-Here's how:
-
-```js
-import { SnackbarList } from '@wordpress/components';
-import { store as noticesStore } from '@wordpress/notices';
-
-function Notifications() {
- const notices = useSelect(
- ( select ) => select( noticesStore ).getNotices(),
- []
- );
- const { removeNotice } = useDispatch( noticesStore );
- const snackbarNotices = notices.filter( ({ type }) => type === 'snackbar' );
-
- return (
-
- );
-}
-
-function MyFirstApp() {
- // ...
- return (
-
- {/* ... */}
-
-
- );
-}
-```
-
-This tutorial is focused on managing the pages and won't discuss the above snippet in detail. If you're interested in the details of `@wordpress/notices`, the [handbook page](https://developer.wordpress.org/block-editor/reference-guides/data/data-core-notices/) is a good place to start.
-
-Now we're ready to tell the user about any errors that may have occurred.
-
-#### Dispatching notifications
-
-With the SnackbarNotices component in place, we're ready to dispatch some notifications! Here's how:
-
-```js
-import { useEffect } from 'react';
-import { store as noticesStore } from '@wordpress/notices';
-function DeletePageButton( { pageId } ) {
- const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore );
- // useSelect returns a list of selectors if you pass the store handle
- // instead of a callback:
- const { getLastEntityDeleteError } = useSelect( coreDataStore )
- const handleDelete = async () => {
- const success = await deleteEntityRecord( 'postType', 'page', pageId);
- if ( success ) {
- // Tell the user the operation succeeded:
- createSuccessNotice( "The page was deleted!", {
- type: 'snackbar',
- } );
- } else {
- // We use the selector directly to get the fresh error *after* the deleteEntityRecord
- // have failed.
- const lastError = getLastEntityDeleteError( 'postType', 'page', pageId );
- const message = ( lastError?.message || 'There was an error.' ) + ' Please refresh the page and try again.'
- // Tell the user how exactly the operation has failed:
- createErrorNotice( message, {
- type: 'snackbar',
- } );
- }
- }
- // ...
-}
-```
-
-Great! `DeletePageButton` is now fully aware of errors. Let's see that error message in action. We'll trigger an invalid delete and let it fail. One way to do this is to multiply the `pageId` by a large number:
-
-```js
-function DeletePageButton( { pageId, onCancel, onSaveFinished } ) {
- pageId = pageId * 1000;
- // ...
-}
-```
-
-Once you refresh the page and click any `Delete` button, you should see the following error message:
-
-
-
-Fantastic! We can now **remove the `pageId = pageId * 1000;` line.**
-
-Let's now try actually deleting a page. Here's what you should see after refreshing your browser and clicking the Delete button:
-
-
-
-And that's it!
-
-### Wiring it all together
-
-All the pieces are in place, great! Here’s all the changes we've made in this chapter:
-
-```js
-import { useState, useEffect } from 'react';
-import { useSelect, useDispatch } from '@wordpress/data';
-import { Button, Modal, TextControl } from '@wordpress/components';
-
-function MyFirstApp() {
- const [searchTerm, setSearchTerm] = useState( '' );
- const { pages, hasResolved } = useSelect(
- ( select ) => {
- const query = {};
- if ( searchTerm ) {
- query.search = searchTerm;
- }
- const selectorArgs = ['postType', 'page', query];
- const pages = select( coreDataStore ).getEntityRecords( ...selectorArgs );
- return {
- pages,
- hasResolved: select( coreDataStore ).hasFinishedResolution(
- 'getEntityRecords',
- selectorArgs,
- ),
- };
- },
- [searchTerm],
- );
-
- return (
-
- );
-}
-
-function DeletePageButton( { pageId } ) {
- const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore );
- // useSelect returns a list of selectors if you pass the store handle
- // instead of a callback:
- const { getLastEntityDeleteError } = useSelect( coreDataStore )
- const handleDelete = async () => {
- const success = await deleteEntityRecord( 'postType', 'page', pageId);
- if ( success ) {
- // Tell the user the operation succeeded:
- createSuccessNotice( "The page was deleted!", {
- type: 'snackbar',
- } );
- } else {
- // We use the selector directly to get the error at this point in time.
- // Imagine we fetched the error like this:
- // const { lastError } = useSelect( function() { /* ... */ } );
- // Then, lastError would be null inside of handleDelete.
- // Why? Because we'd refer to the version of it that was computed
- // before the handleDelete was even called.
- const lastError = getLastEntityDeleteError( 'postType', 'page', pageId );
- const message = ( lastError?.message || 'There was an error.' ) + ' Please refresh the page and try again.'
- // Tell the user how exactly the operation have failed:
- createErrorNotice( message, {
- type: 'snackbar',
- } );
- }
- }
-
- const { deleteEntityRecord } = useDispatch( coreDataStore );
- const { isDeleting } = useSelect(
- select => ( {
- isDeleting: select( coreDataStore ).isDeletingEntityRecord( 'postType', 'page', pageId ),
- } ),
- [ pageId ]
- );
-
- return (
-
- );
-}
-```
-
-## What's next?
-
-* **Previous part:** [Building a *Create page form*](/docs/how-to-guides/data-basics/4-building-a-create-page-form.md)
-* (optional) Review the [finished app](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) in the block-development-examples repository
diff --git a/gutenberg/reference-guides/README.md b/gutenberg/reference-guides/README.md
deleted file mode 100644
index cc30aa8..0000000
--- a/gutenberg/reference-guides/README.md
+++ /dev/null
@@ -1,71 +0,0 @@
-# Reference Guides
-
-## [Block API Reference](/docs/reference-guides/block-api/README.md)
-
-- [Annotations](/docs/reference-guides/block-api/block-annotations.md)
-- [API Versions](/docs/reference-guides/block-api/block-api-versions.md)
-- [Attributes](/docs/reference-guides/block-api/block-attributes.md)
-- [Context](/docs/reference-guides/block-api/block-context.md)
-- [Deprecation](/docs/reference-guides/block-api/block-deprecation.md)
-- [Edit and Save](/docs/reference-guides/block-api/block-edit-save.md)
-- [Patterns](/docs/reference-guides/block-api/block-patterns.md)
-- [Registration](/docs/reference-guides/block-api/block-registration.md)
-- [Supports](/docs/reference-guides/block-api/block-supports.md)
-- [Templates](/docs/reference-guides/block-api/block-templates.md)
-- [Transformations](/docs/reference-guides/block-api/block-transforms.md)
-- [Metadata](/docs/reference-guides/block-api/block-metadata.md)
-- [Variations](/docs/reference-guides/block-api/block-variations.md)
-
-## [Hooks Reference](/docs/reference-guides/filters/README.md)
-
-- [Block Filters](/docs/reference-guides/filters/block-filters.md)
-- [Editor Hooks](/docs/reference-guides/filters/editor-filters.md)
-- [i18n Hooks](/docs/reference-guides/filters/i18n-filters.md)
-- [Parser Hooks](/docs/reference-guides/filters/parser-filters.md)
-- [Autocomplete](/docs/reference-guides/filters/autocomplete-filters.md)
-- [Global Styles Hooks](/docs/reference-guides/filters/global-styles-filters.md)
-
-## [SlotFills Reference](/docs/reference-guides/slotfills/README.md)
-
-- [MainDashboardButton](/docs/reference-guides/slotfills/main-dashboard-button.md)
-- [PluginBlockSettingsMenuItem](/docs/reference-guides/slotfills/plugin-block-settings-menu-item.md)
-- [PluginDocumentSettingPanel](/docs/reference-guides/slotfills/plugin-document-setting-panel.md)
-- [PluginMoreMenuItem](/docs/reference-guides/slotfills/plugin-more-menu-item.md)
-- [PluginPostPublishPanel](/docs/reference-guides/slotfills/plugin-post-publish-panel.md)
-- [PluginPostStatusInfo](/docs/reference-guides/slotfills/plugin-post-status-info.md)
-- [PluginPrePublishPanel](/docs/reference-guides/slotfills/plugin-pre-publish-panel.md)
-- [PluginSidebar](/docs/reference-guides/slotfills/plugin-sidebar.md)
-- [PluginSidebarMoreMenuItem](/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md)
-
-## [Theme.json Reference](/docs/reference-guides/theme-json-reference/README.md)
-
-- [Version 3 (latest)](/docs/reference-guides/theme-json-reference/theme-json-living.md)
-- [Version 2](/docs/reference-guides/theme-json-reference/theme-json-v2.md)
-- [Version 1](/docs/reference-guides/theme-json-reference/theme-json-v1.md)
-- [Migrating to Newer Versions](/docs/reference-guides/theme-json-reference/theme-json-migrations.md)
-
-## [RichText Reference](/docs/reference-guides/richtext.md)
-
-## [Component Reference](/packages/components/README.md)
-
-## [Package Reference](/docs/reference-guides/packages.md)
-
-## [Data Module Reference](/docs/reference-guides/data/README.md)
-
-- [**core**: WordPress Core Data](/docs/reference-guides/data/data-core.md)
- - [**core/annotations**: Annotations](/docs/reference-guides/data/data-core-annotations.md)
- - [**core/block-directory**: Block directory](/docs/reference-guides/data/data-core-block-directory.md)
- - [**core/block-editor**: The Block Editor’s Data](/docs/reference-guides/data/data-core-block-editor.md)
- - [**core/blocks**: Block Types Data](/docs/reference-guides/data/data-core-blocks.md)
- - [**core/customize-widgets**: Customize Widgets](/docs/reference-guides/data/data-core-customize-widgets.md)
- - [**core/edit-post**: The Editor’s UI Data](/docs/reference-guides/data/data-core-edit-post.md)
- - [**core/edit-site**: Edit Site](/docs/reference-guides/data/data-core-edit-site.md)
- - [**core/edit-widgets**: Edit Widgets](/docs/reference-guides/data/data-core-edit-widgets.md)
- - [**core/editor**: The Post Editor’s Data](/docs/reference-guides/data/data-core-editor.md)
- - [**core/keyboard-shortcuts**: The Keyboard Shortcuts Data](/docs/reference-guides/data/data-core-keyboard-shortcuts.md)
- - [**core/notices**: Notices Data](/docs/reference-guides/data/data-core-notices.md)
- - [**core/nux**: The NUX (New User Experience) Data](/docs/reference-guides/data/data-core-nux.md)
- - [**core/preferences**: Preferences](/docs/reference-guides/data/data-core-preferences.md)
- - [**core/reusable-blocks**: Reusable blocks](/docs/reference-guides/data/data-core-reusable-blocks.md)
- - [**core/rich-text**: Rich Text](/docs/reference-guides/data/data-core-rich-text.md)
- - [**core/viewport**: The Viewport Data](/docs/reference-guides/data/data-core-viewport.md)
diff --git a/gutenberg/reference-guides/block-api/README.md b/gutenberg/reference-guides/block-api/README.md
deleted file mode 100644
index 1b89b92..0000000
--- a/gutenberg/reference-guides/block-api/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Block API Reference
-
-Blocks are the fundamental element of the editor. They are the primary way in which plugins and themes can register their own functionality and extend the capabilities of the editor.
-
-The following sections will walk you through the existing block APIs:
-
-- [Annotations](/docs/reference-guides/block-api/block-annotations.md)
-- [API Versions](/docs/reference-guides/block-api/block-api-versions.md)
-- [Attributes](/docs/reference-guides/block-api/block-attributes.md)
-- [Bindings](/docs/reference-guides/block-api/block-bindings.md)
-- [Context](/docs/reference-guides/block-api/block-context.md)
-- [Deprecation](/docs/reference-guides/block-api/block-deprecation.md)
-- [Edit and Save](/docs/reference-guides/block-api/block-edit-save.md)
-- [Metadata in block.json](/docs/reference-guides/block-api/block-metadata.md)
-- [Patterns](/docs/reference-guides/block-api/block-patterns.md)
-- [Registration](/docs/reference-guides/block-api/block-registration.md)
-- [Selectors](/docs/reference-guides/block-api/block-selectors.md)
-- [Styles](/docs/reference-guides/block-api/block-styles.md)
-- [Supports](/docs/reference-guides/block-api/block-supports.md)
-- [Transformations](/docs/reference-guides/block-api/block-transforms.md)
-- [Templates](/docs/reference-guides/block-api/block-templates.md)
-- [Variations](/docs/reference-guides/block-api/block-variations.md)
diff --git a/gutenberg/reference-guides/data/README.md b/gutenberg/reference-guides/data/README.md
deleted file mode 100644
index 8500cc3..0000000
--- a/gutenberg/reference-guides/data/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Data Module Reference
-
-- [**core**: WordPress Core Data](/docs/reference-guides/data/data-core.md)
-- [**core/annotations**: Annotations](/docs/reference-guides/data/data-core-annotations.md)
-- [**core/block-directory**: Block directory](/docs/reference-guides/data/data-core-block-directory.md)
-- [**core/block-editor**: The Block Editor’s Data](/docs/reference-guides/data/data-core-block-editor.md)
-- [**core/blocks**: Block Types Data](/docs/reference-guides/data/data-core-blocks.md)
-- [**core/commands**: Command Palette](/docs/reference-guides/data/data-core-commands.md)
-- [**core/customize-widgets**: Customize Widgets](/docs/reference-guides/data/data-core-customize-widgets.md)
-- [**core/edit-post**: The Editor’s UI Data](/docs/reference-guides/data/data-core-edit-post.md)
-- [**core/edit-site**: Edit Site](/docs/reference-guides/data/data-core-edit-site.md)
-- [**core/edit-widgets**: Edit Widgets](/docs/reference-guides/data/data-core-edit-widgets.md)
-- [**core/editor**: The Post Editor’s Data](/docs/reference-guides/data/data-core-editor.md)
-- [**core/keyboard-shortcuts**: The Keyboard Shortcuts Data](/docs/reference-guides/data/data-core-keyboard-shortcuts.md)
-- [**core/notices**: Notices Data](/docs/reference-guides/data/data-core-notices.md)
-- [**core/nux**: The NUX (New User Experience) Data](/docs/reference-guides/data/data-core-nux.md)
-- [**core/preferences**: Preferences](/docs/reference-guides/data/data-core-preferences.md)
-- [**core/reusable-blocks**: Reusable blocks](/docs/reference-guides/data/data-core-reusable-blocks.md)
-- [**core/rich-text**: Rich Text](/docs/reference-guides/data/data-core-rich-text.md)
-- [**core/viewport**: The Viewport Data](/docs/reference-guides/data/data-core-viewport.md)
diff --git a/gutenberg/reference-guides/data/data-core-block-editor.md b/gutenberg/reference-guides/data/data-core-block-editor.md
deleted file mode 100644
index 6820b4d..0000000
--- a/gutenberg/reference-guides/data/data-core-block-editor.md
+++ /dev/null
@@ -1,1913 +0,0 @@
-# The Block Editor’s Data
-
-Namespace: `core/block-editor`.
-
-## Selectors
-
-
-
-### areInnerBlocksControlled
-
-Checks if a given block has controlled inner blocks.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _clientId_ `string`: The block to check.
-
-_Returns_
-
-- `boolean`: True if the block has controlled inner blocks.
-
-### canEditBlock
-
-Determines if the given block is allowed to be edited.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: The block client Id.
-
-_Returns_
-
-- `boolean`: Whether the given block is allowed to be edited.
-
-### canInsertBlocks
-
-Determines if the given blocks are allowed to be inserted into the block list.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientIds_ `string[]`: The block client IDs to be inserted.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `boolean`: Whether the given blocks are allowed to be inserted.
-
-### canInsertBlockType
-
-Determines if the given block type is allowed to be inserted into the block list.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _blockName_ `string`: The name of the block type, e.g.' core/paragraph'.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `boolean`: Whether the given block type is allowed to be inserted.
-
-### canLockBlockType
-
-Determines if the given block type can be locked/unlocked by a user.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _nameOrType_ `(string|Object)`: Block name or type object.
-
-_Returns_
-
-- `boolean`: Whether a given block type can be locked/unlocked.
-
-### canMoveBlock
-
-Determines if the given block is allowed to be moved.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: The block client Id.
-
-_Returns_
-
-- `boolean`: Whether the given block is allowed to be moved.
-
-### canMoveBlocks
-
-Determines if the given blocks are allowed to be moved.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientIds_ `string`: The block client IDs to be moved.
-
-_Returns_
-
-- `boolean`: Whether the given blocks are allowed to be moved.
-
-### canRemoveBlock
-
-Determines if the given block is allowed to be deleted.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: The block client Id.
-
-_Returns_
-
-- `boolean`: Whether the given block is allowed to be removed.
-
-### canRemoveBlocks
-
-Determines if the given blocks are allowed to be removed.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientIds_ `string`: The block client IDs to be removed.
-
-_Returns_
-
-- `boolean`: Whether the given blocks are allowed to be removed.
-
-### didAutomaticChange
-
-Returns true if the last change was an automatic change, false otherwise.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `boolean`: Whether the last change was automatic.
-
-### getAdjacentBlockClientId
-
-Returns the client ID of the block adjacent one at the given reference startClientId and modifier directionality. Defaults start startClientId to the selected block, and direction as next block. Returns null if there is no adjacent block.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _startClientId_ `?string`: Optional client ID of block from which to search.
-- _modifier_ `?number`: Directionality multiplier (1 next, -1 previous).
-
-_Returns_
-
-- `?string`: Return the client ID of the block, or null if none exists.
-
-### getAllowedBlocks
-
-Returns the list of allowed inserter blocks for inner blocks children.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `Array?`: The list of allowed block types.
-
-### getBlock
-
-Returns a block given its client ID. This is a parsed copy of the block, containing its `blockName`, `clientId`, and current `attributes` state. This is not the block's registration settings, which must be retrieved from the blocks module registration store.
-
-getBlock recurses through its inner blocks until all its children blocks have been retrieved. Note that getBlock will not return the child inner blocks of an inner block controller. This is because an inner block controller syncs itself with its own entity, and should therefore not be included with the blocks of a different entity. For example, say you call `getBlocks( TP )` to get the blocks of a template part. If another template part is a child of TP, then the nested template part's child blocks will not be returned. This way, the template block itself is considered part of the parent, but the children are not.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `Object`: Parsed block object.
-
-### getBlockAttributes
-
-Returns a block's attributes given its client ID, or null if no block exists with the client ID.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `?Object`: Block attributes.
-
-### getBlockCount
-
-Returns the number of blocks currently present in the post.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `number`: Number of blocks in the post.
-
-### getBlockEditingMode
-
-Returns the block editing mode for a given block.
-
-The mode can be one of three options:
-
-- `'disabled'`: Prevents editing the block entirely, i.e. it cannot be selected.
-- `'contentOnly'`: Hides all non-content UI, e.g. auxiliary controls in the toolbar, the block movers, block settings.
-- `'default'`: Allows editing the block as normal.
-
-Blocks can set a mode using the `useBlockEditingMode` hook.
-
-The mode is inherited by all of the block's inner blocks, unless they have their own mode.
-
-A template lock can also set a mode. If the template lock is `'contentOnly'`, the block's mode is overridden to `'contentOnly'` if the block has a content role attribute, or `'disabled'` otherwise.
-
-_Related_
-
-- useBlockEditingMode
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _clientId_ `string`: The block client ID, or `''` for the root container.
-
-_Returns_
-
-- `BlockEditingMode`: The block editing mode. One of `'disabled'`, `'contentOnly'`, or `'default'`.
-
-### getBlockHierarchyRootClientId
-
-Given a block client ID, returns the root of the hierarchy from which the block is nested, return the block itself for root level blocks.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block from which to find root client ID.
-
-_Returns_
-
-- `string`: Root client ID
-
-### getBlockIndex
-
-Returns the index at which the block corresponding to the specified client ID occurs within the block order, or `-1` if the block does not exist.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `number`: Index at which block exists in order.
-
-### getBlockInsertionPoint
-
-Returns the location of the insertion cue. Defaults to the last index.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `Object`: Insertion point object with `rootClientId`, `index`.
-
-### getBlockListSettings
-
-Returns the Block List settings of a block, if any exist.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `?string`: Block client ID.
-
-_Returns_
-
-- `?Object`: Block settings of the block if set.
-
-### getBlockMode
-
-Returns the block's editing mode, defaulting to "visual" if not explicitly assigned.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `Object`: Block editing mode.
-
-### getBlockName
-
-Returns a block's name given its client ID, or null if no block exists with the client ID.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `string`: Block name.
-
-### getBlockNamesByClientId
-
-Given an array of block client IDs, returns the corresponding array of block names.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientIds_ `string[]`: Client IDs for which block names are to be returned.
-
-_Returns_
-
-- `string[]`: Block names.
-
-### getBlockOrder
-
-Returns an array containing all block client IDs in the editor in the order they appear. Optionally accepts a root client ID of the block list for which the order should be returned, defaulting to the top-level block order.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `Array`: Ordered client IDs of editor blocks.
-
-### getBlockParents
-
-Given a block client ID, returns the list of all its parents from top to bottom.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block from which to find root client ID.
-- _ascending_ `boolean`: Order results from bottom to top (true) or top to bottom (false).
-
-_Returns_
-
-- `Array`: ClientIDs of the parent blocks.
-
-### getBlockParentsByBlockName
-
-Given a block client ID and a block name, returns the list of all its parents from top to bottom, filtered by the given name(s). For example, if passed 'core/group' as the blockName, it will only return parents which are group blocks. If passed `[ 'core/group', 'core/cover']`, as the blockName, it will return parents which are group blocks and parents which are cover blocks.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block from which to find root client ID.
-- _blockName_ `string|string[]`: Block name(s) to filter.
-- _ascending_ `boolean`: Order results from bottom to top (true) or top to bottom (false).
-
-_Returns_
-
-- `Array`: ClientIDs of the parent blocks.
-
-### getBlockRootClientId
-
-Given a block client ID, returns the root block from which the block is nested, an empty string for top-level blocks, or null if the block does not exist.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block from which to find root client ID.
-
-_Returns_
-
-- `?string`: Root client ID, if exists
-
-### getBlocks
-
-Returns all block objects for the current post being edited as an array in the order they appear in the post. Note that this will exclude child blocks of nested inner block controllers.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `Object[]`: Post blocks.
-
-### getBlocksByClientId
-
-Given an array of block client IDs, returns the corresponding array of block objects.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientIds_ `string[]`: Client IDs for which blocks are to be returned.
-
-_Returns_
-
-- `WPBlock[]`: Block objects.
-
-### getBlocksByName
-
-Returns all blocks that match a blockName. Results include nested blocks.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _blockName_ `string[]`: Block name(s) for which clientIds are to be returned.
-
-_Returns_
-
-- `Array`: Array of clientIds of blocks with name equal to blockName.
-
-### getBlockSelectionEnd
-
-Returns the current block selection end. This value may be null, and it may represent either a singular block selection or multi-selection end. A selection is singular if its start and end match.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `?string`: Client ID of block selection end.
-
-### getBlockSelectionStart
-
-Returns the current block selection start. This value may be null, and it may represent either a singular block selection or multi-selection start. A selection is singular if its start and end match.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `?string`: Client ID of block selection start.
-
-### getBlockTransformItems
-
-Determines the items that appear in the available block transforms list.
-
-Each item object contains what's necessary to display a menu item in the transform list and handle its selection.
-
-The 'frecency' property is a heuristic () that combines block usage frequency and recency.
-
-Items are returned ordered descendingly by their 'frecency'.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _blocks_ `Object|Object[]`: Block object or array objects.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `WPEditorTransformItem[]`: Items that appear in inserter.
-
-_Type Definition_
-
-- _WPEditorTransformItem_ `Object`
-
-_Properties_
-
-- _id_ `string`: Unique identifier for the item.
-- _name_ `string`: The type of block to create.
-- _title_ `string`: Title of the item, as it appears in the inserter.
-- _icon_ `string`: Dashicon for the item, as it appears in the inserter.
-- _isDisabled_ `boolean`: Whether or not the user should be prevented from inserting this item.
-- _frecency_ `number`: Heuristic that combines frequency and recency.
-
-### getClientIdsOfDescendants
-
-Returns an array containing the clientIds of all descendants of the blocks given. Returned ids are ordered first by the order of the ids given, then by the order that they appear in the editor.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _rootIds_ `string|string[]`: Client ID(s) for which descendant blocks are to be returned.
-
-_Returns_
-
-- `Array`: Client IDs of descendants.
-
-### getClientIdsWithDescendants
-
-Returns an array containing the clientIds of the top-level blocks and their descendants of any depth (for nested blocks). Ids are returned in the same order that they appear in the editor.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `Array`: ids of top-level and descendant blocks.
-
-### getDirectInsertBlock
-
-Returns the block to be directly inserted by the block appender.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `WPDirectInsertBlock|undefined`: The block type to be directly inserted.
-
-_Type Definition_
-
-- _WPDirectInsertBlock_ `Object`
-
-_Properties_
-
-- _name_ `string`: The type of block.
-- _attributes_ `?Object`: Attributes to pass to the newly created block.
-- _attributesToCopy_ `?Array`: Attributes to be copied from adjacent blocks when inserted.
-
-### getDraggedBlockClientIds
-
-Returns the client ids of any blocks being directly dragged.
-
-This does not include children of a parent being dragged.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `string[]`: Array of dragged block client ids.
-
-### getFirstMultiSelectedBlockClientId
-
-Returns the client ID of the first block in the multi-selection set, or null if there is no multi-selection.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `?string`: First block client ID in the multi-selection set.
-
-### getGlobalBlockCount
-
-Returns the total number of blocks, or the total number of blocks with a specific name in a post. The number returned includes nested blocks.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _blockName_ `?string`: Optional block name, if specified only blocks of that type will be counted.
-
-_Returns_
-
-- `number`: Number of blocks in the post, or number of blocks with name equal to blockName.
-
-### getHoveredBlockClientId
-
-> **Deprecated**
-
-Returns the currently hovered block.
-
-### getInserterItems
-
-Determines the items that appear in the inserter. Includes both static items (e.g. a regular block type) and dynamic items (e.g. a reusable block).
-
-Each item object contains what's necessary to display a button in the inserter and handle its selection.
-
-The 'frecency' property is a heuristic () that combines block usage frequency and recency.
-
-Items are returned ordered descendingly by their 'utility' and 'frecency'.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `WPEditorInserterItem[]`: Items that appear in inserter.
-
-_Type Definition_
-
-- _WPEditorInserterItem_ `Object`
-
-_Properties_
-
-- _id_ `string`: Unique identifier for the item.
-- _name_ `string`: The type of block to create.
-- _initialAttributes_ `Object`: Attributes to pass to the newly created block.
-- _title_ `string`: Title of the item, as it appears in the inserter.
-- _icon_ `string`: Dashicon for the item, as it appears in the inserter.
-- _category_ `string`: Block category that the item is associated with.
-- _keywords_ `string[]`: Keywords that can be searched to find this item.
-- _isDisabled_ `boolean`: Whether or not the user should be prevented from inserting this item.
-- _frecency_ `number`: Heuristic that combines frequency and recency.
-
-### getLastMultiSelectedBlockClientId
-
-Returns the client ID of the last block in the multi-selection set, or null if there is no multi-selection.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `?string`: Last block client ID in the multi-selection set.
-
-### getLowestCommonAncestorWithSelectedBlock
-
-Given a block client ID, returns the lowest common ancestor with selected client ID.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block from which to find common ancestor client ID.
-
-_Returns_
-
-- `string`: Common ancestor client ID or undefined
-
-### getMultiSelectedBlockClientIds
-
-Returns the current multi-selection set of block client IDs, or an empty array if there is no multi-selection.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `Array`: Multi-selected block client IDs.
-
-### getMultiSelectedBlocks
-
-Returns the current multi-selection set of blocks, or an empty array if there is no multi-selection.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `Array`: Multi-selected block objects.
-
-### getMultiSelectedBlocksEndClientId
-
-Returns the client ID of the block which ends the multi-selection set, or null if there is no multi-selection.
-
-This is not necessarily the last client ID in the selection.
-
-_Related_
-
-- getLastMultiSelectedBlockClientId
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `?string`: Client ID of block ending multi-selection.
-
-### getMultiSelectedBlocksStartClientId
-
-Returns the client ID of the block which begins the multi-selection set, or null if there is no multi-selection.
-
-This is not necessarily the first client ID in the selection.
-
-_Related_
-
-- getFirstMultiSelectedBlockClientId
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `?string`: Client ID of block beginning multi-selection.
-
-### getNextBlockClientId
-
-Returns the next block's client ID from the given reference start ID. Defaults start to the selected block. Returns null if there is no next block.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _startClientId_ `?string`: Optional client ID of block from which to search.
-
-_Returns_
-
-- `?string`: Adjacent block's client ID, or null if none exists.
-
-### getPatternsByBlockTypes
-
-Returns the list of patterns based on their declared `blockTypes` and a block's name. Patterns can use `blockTypes` to integrate in work flows like suggesting appropriate patterns in a Placeholder state(during insertion) or blocks transformations.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _blockNames_ `string|string[]`: Block's name or array of block names to find matching patterns.
-- _rootClientId_ `?string`: Optional target root client ID.
-
-_Returns_
-
-- `Array`: The list of matched block patterns based on declared `blockTypes` and block name.
-
-### getPreviousBlockClientId
-
-Returns the previous block's client ID from the given reference start ID. Defaults start to the selected block. Returns null if there is no previous block.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _startClientId_ `?string`: Optional client ID of block from which to search.
-
-_Returns_
-
-- `?string`: Adjacent block's client ID, or null if none exists.
-
-### getSelectedBlock
-
-Returns the currently selected block, or null if there is no selected block.
-
-_Usage_
-
-```js
-import { select } from '@wordpress/data';
-import { store as blockEditorStore } from '@wordpress/block-editor';
-
-// Set initial active block client ID
-let activeBlockClientId = null;
-
-const getActiveBlockData = () => {
- const activeBlock = select( blockEditorStore ).getSelectedBlock();
-
- if ( activeBlock && activeBlock.clientId !== activeBlockClientId ) {
- activeBlockClientId = activeBlock.clientId;
-
- // Get active block name and attributes
- const activeBlockName = activeBlock.name;
- const activeBlockAttributes = activeBlock.attributes;
-
- // Log active block name and attributes
- console.log( activeBlockName, activeBlockAttributes );
- }
-};
-
-// Subscribe to changes in the editor
-// wp.data.subscribe(() => {
-// getActiveBlockData()
-// })
-
-// Update active block data on click
-// onclick="getActiveBlockData()"
-```
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `?Object`: Selected block.
-
-### getSelectedBlockClientId
-
-Returns the currently selected block client ID, or null if there is no selected block.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `?string`: Selected block client ID.
-
-### getSelectedBlockClientIds
-
-Returns the current selection set of block client IDs (multiselection or single selection).
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `Array`: Multi-selected block client IDs.
-
-### getSelectedBlockCount
-
-Returns the number of blocks currently selected in the post.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `number`: Number of blocks selected in the post.
-
-### getSelectedBlocksInitialCaretPosition
-
-Returns the initial caret position for the selected block. This position is to used to position the caret properly when the selected block changes. If the current block is not a RichText, having initial position set to 0 means "focus block"
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `0|-1|null`: Initial position.
-
-### getSelectionEnd
-
-Returns the current selection end block client ID, attribute key and text offset.
-
-_Parameters_
-
-- _state_ `Object`: Block editor state.
-
-_Returns_
-
-- `WPBlockSelection`: Selection end information.
-
-### getSelectionStart
-
-Returns the current selection start block client ID, attribute key and text offset.
-
-_Parameters_
-
-- _state_ `Object`: Block editor state.
-
-_Returns_
-
-- `WPBlockSelection`: Selection start information.
-
-### getSettings
-
-Returns the editor settings.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `Object`: The editor settings object.
-
-### getTemplate
-
-Returns the defined block template
-
-_Parameters_
-
-- _state_ `boolean`:
-
-_Returns_
-
-- `?Array`: Block Template.
-
-### getTemplateLock
-
-Returns the defined block template lock. Optionally accepts a root block client ID as context, otherwise defaulting to the global context.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _rootClientId_ `?string`: Optional block root client ID.
-
-_Returns_
-
-- `string|false`: Block Template Lock
-
-### hasBlockMovingClientId
-
-> **Deprecated**
-
-Returns whether block moving mode is enabled.
-
-### hasDraggedInnerBlock
-
-Returns true if one of the block's inner blocks is dragged.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-- _deep_ `boolean`: Perform a deep check.
-
-_Returns_
-
-- `boolean`: Whether the block has an inner block dragged
-
-### hasInserterItems
-
-Determines whether there are items to show in the inserter.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _rootClientId_ `?string`: Optional root client ID of block list.
-
-_Returns_
-
-- `boolean`: Items that appear in inserter.
-
-### hasMultiSelection
-
-Returns true if a multi-selection has been made, or false otherwise.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `boolean`: Whether multi-selection has been made.
-
-### hasSelectedBlock
-
-Returns true if there is a single selected block, or false otherwise.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `boolean`: Whether a single block is selected.
-
-### hasSelectedInnerBlock
-
-Returns true if one of the block's inner blocks is selected.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-- _deep_ `boolean`: Perform a deep check.
-
-_Returns_
-
-- `boolean`: Whether the block has an inner block selected
-
-### isAncestorBeingDragged
-
-Returns whether a parent/ancestor of the block is being dragged.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _clientId_ `string`: Client id for block to check.
-
-_Returns_
-
-- `boolean`: Whether the block's ancestor is being dragged.
-
-### isAncestorMultiSelected
-
-Returns true if an ancestor of the block is multi-selected, or false otherwise.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `boolean`: Whether an ancestor of the block is in multi-selection set.
-
-### isBlockBeingDragged
-
-Returns whether the block is being dragged.
-
-Only returns true if the block is being directly dragged, not if the block is a child of a parent being dragged. See `isAncestorBeingDragged` for child blocks.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _clientId_ `string`: Client id for block to check.
-
-_Returns_
-
-- `boolean`: Whether the block is being dragged.
-
-### isBlockHighlighted
-
-Returns true if the current highlighted block matches the block clientId.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _clientId_ `string`: The block to check.
-
-_Returns_
-
-- `boolean`: Whether the block is currently highlighted.
-
-### isBlockInsertionPointVisible
-
-Returns true if the block insertion point is visible.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `?boolean`: Whether the insertion point is visible or not.
-
-### isBlockMultiSelected
-
-Returns true if the client ID occurs within the block multi-selection, or false otherwise.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `boolean`: Whether block is in multi-selection set.
-
-### isBlockSelected
-
-Returns true if the block corresponding to the specified client ID is currently selected and no multi-selection exists, or false otherwise.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `boolean`: Whether block is selected and multi-selection exists.
-
-### isBlockValid
-
-Returns whether a block is valid or not.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `boolean`: Is Valid.
-
-### isBlockVisible
-
-Tells if the block is visible on the canvas or not.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _clientId_ `Object`: Client Id of the block.
-
-_Returns_
-
-- `boolean`: True if the block is visible.
-
-### isBlockWithinSelection
-
-Returns true if the block corresponding to the specified client ID is currently selected but isn't the last of the selected blocks. Here "last" refers to the block sequence in the document, _not_ the sequence of multi-selection, which is why `state.selectionEnd` isn't used.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `boolean`: Whether block is selected and not the last in the selection.
-
-### isCaretWithinFormattedText
-
-> **Deprecated**
-
-Returns true if the caret is within formatted text, or false otherwise.
-
-_Returns_
-
-- `boolean`: Whether the caret is within formatted text.
-
-### isDraggingBlocks
-
-Returns true if the user is dragging blocks, or false otherwise.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `boolean`: Whether user is dragging blocks.
-
-### isFirstMultiSelectedBlock
-
-Returns true if a multi-selection exists, and the block corresponding to the specified client ID is the first block of the multi-selection set, or false otherwise.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `boolean`: Whether block is first in multi-selection.
-
-### isGroupable
-
-Indicates if the provided blocks(by client ids) are groupable. We need to have at least one block, have a grouping block name set and be able to remove these blocks.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _clientIds_ `string[]`: Block client ids. If not passed the selected blocks client ids will be used.
-
-_Returns_
-
-- `boolean`: True if the blocks are groupable.
-
-### isLastBlockChangePersistent
-
-Returns true if the most recent block change is be considered persistent, or false otherwise. A persistent change is one committed by BlockEditorProvider via its `onChange` callback, in addition to `onInput`.
-
-_Parameters_
-
-- _state_ `Object`: Block editor state.
-
-_Returns_
-
-- `boolean`: Whether the most recent block change was persistent.
-
-### isMultiSelecting
-
-Whether in the process of multi-selecting or not. This flag is only true while the multi-selection is being selected (by mouse move), and is false once the multi-selection has been settled.
-
-_Related_
-
-- hasMultiSelection
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `boolean`: True if multi-selecting, false if not.
-
-### isNavigationMode
-
-Returns whether the navigation mode is enabled.
-
-_Parameters_
-
-- _state_ `Object`: Editor state.
-
-_Returns_
-
-- `boolean`: Is navigation mode enabled.
-
-### isSelectionEnabled
-
-Selector that returns if multi-selection is enabled or not.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `boolean`: True if it should be possible to multi-select blocks, false if multi-selection is disabled.
-
-### isTyping
-
-Returns true if the user is typing, or false otherwise.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-
-_Returns_
-
-- `boolean`: Whether user is typing.
-
-### isUngroupable
-
-Indicates if a block is ungroupable. A block is ungroupable if it is a single grouping block with inner blocks. If a block has an `ungroup` transform, it is also ungroupable, without the requirement of being the default grouping block. Additionally a block can only be ungrouped if it has inner blocks and can be removed.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _clientId_ `string`: Client Id of the block. If not passed the selected block's client id will be used.
-
-_Returns_
-
-- `boolean`: True if the block is ungroupable.
-
-### isValidTemplate
-
-Returns whether the blocks matches the template or not.
-
-_Parameters_
-
-- _state_ `boolean`:
-
-_Returns_
-
-- `?boolean`: Whether the template is valid or not.
-
-### wasBlockJustInserted
-
-Tells if the block with the passed clientId was just inserted.
-
-_Parameters_
-
-- _state_ `Object`: Global application state.
-- _clientId_ `Object`: Client Id of the block.
-- _source_ `?string`: Optional insertion source of the block.
-
-_Returns_
-
-- `boolean`: True if the block matches the last block inserted from the specified source.
-
-
-
-## Actions
-
-
-
-### clearSelectedBlock
-
-Action that clears the block selection.
-
-_Returns_
-
-- `Object`: Action object.
-
-### duplicateBlocks
-
-Action that duplicates a list of blocks.
-
-_Parameters_
-
-- _clientIds_ `string[]`:
-- _updateSelection_ `boolean`:
-
-### enterFormattedText
-
-> **Deprecated**
-
-Returns an action object used in signalling that the caret has entered formatted text.
-
-_Returns_
-
-- `Object`: Action object.
-
-### exitFormattedText
-
-> **Deprecated**
-
-Returns an action object used in signalling that the user caret has exited formatted text.
-
-_Returns_
-
-- `Object`: Action object.
-
-### flashBlock
-
-Action that "flashes" the block with a given `clientId` by rhythmically highlighting it.
-
-_Parameters_
-
-- _clientId_ `string`: Target block client ID.
-
-### hideInsertionPoint
-
-Action that hides the insertion point.
-
-### hoverBlock
-
-> **Deprecated**
-
-Returns an action object used in signalling that the block with the specified client ID has been hovered.
-
-### insertAfterBlock
-
-Action that inserts a default block after a given block.
-
-_Parameters_
-
-- _clientId_ `string`:
-
-### insertBeforeBlock
-
-Action that inserts a default block before a given block.
-
-_Parameters_
-
-- _clientId_ `string`:
-
-### insertBlock
-
-Action that inserts a single block, optionally at a specific index respective a root block list.
-
-Only allowed blocks are inserted. The action may fail silently for blocks that are not allowed or if a templateLock is active on the block list.
-
-_Parameters_
-
-- _block_ `Object`: Block object to insert.
-- _index_ `?number`: Index at which block should be inserted.
-- _rootClientId_ `?string`: Optional root client ID of block list on which to insert.
-- _updateSelection_ `?boolean`: If true block selection will be updated. If false, block selection will not change. Defaults to true.
-- _meta_ `?Object`: Optional Meta values to be passed to the action object.
-
-_Returns_
-
-- `Object`: Action object.
-
-### insertBlocks
-
-Action that inserts an array of blocks, optionally at a specific index respective a root block list.
-
-Only allowed blocks are inserted. The action may fail silently for blocks that are not allowed or if a templateLock is active on the block list.
-
-_Parameters_
-
-- _blocks_ `Object[]`: Block objects to insert.
-- _index_ `?number`: Index at which block should be inserted.
-- _rootClientId_ `?string`: Optional root client ID of block list on which to insert.
-- _updateSelection_ `?boolean`: If true block selection will be updated. If false, block selection will not change. Defaults to true.
-- _initialPosition_ `0|-1|null`: Initial focus position. Setting it to null prevent focusing the inserted block.
-- _meta_ `?Object`: Optional Meta values to be passed to the action object.
-
-_Returns_
-
-- `Object`: Action object.
-
-### insertDefaultBlock
-
-Action that adds a new block of the default type to the block list.
-
-_Parameters_
-
-- _attributes_ `?Object`: Optional attributes of the block to assign.
-- _rootClientId_ `?string`: Optional root client ID of block list on which to append.
-- _index_ `?number`: Optional index where to insert the default block.
-
-### mergeBlocks
-
-Action that merges two blocks.
-
-_Parameters_
-
-- _firstBlockClientId_ `string`: Client ID of the first block to merge.
-- _secondBlockClientId_ `string`: Client ID of the second block to merge.
-
-### moveBlocksDown
-
-Undocumented declaration.
-
-### moveBlocksToPosition
-
-Action that moves given blocks to a new position.
-
-_Parameters_
-
-- _clientIds_ `?string`: The client IDs of the blocks.
-- _fromRootClientId_ `?string`: Root client ID source.
-- _toRootClientId_ `?string`: Root client ID destination.
-- _index_ `number`: The index to move the blocks to.
-
-### moveBlocksUp
-
-Undocumented declaration.
-
-### moveBlockToPosition
-
-Action that moves given block to a new position.
-
-_Parameters_
-
-- _clientId_ `?string`: The client ID of the block.
-- _fromRootClientId_ `?string`: Root client ID source.
-- _toRootClientId_ `?string`: Root client ID destination.
-- _index_ `number`: The index to move the block to.
-
-### multiSelect
-
-Action that changes block multi-selection.
-
-_Parameters_
-
-- _start_ `string`: First block of the multi selection.
-- _end_ `string`: Last block of the multiselection.
-- _\_\_experimentalInitialPosition_ `number|null`: Optional initial position. Pass as null to skip focus within editor canvas.
-
-### receiveBlocks
-
-> **Deprecated**
-
-Returns an action object used in signalling that blocks have been received. Unlike resetBlocks, these should be appended to the existing known set, not replacing.
-
-_Parameters_
-
-- _blocks_ `Object[]`: Array of block objects.
-
-_Returns_
-
-- `Object`: Action object.
-
-### registerInserterMediaCategory
-
-Registers a new inserter media category. Once registered, the media category is available in the inserter's media tab.
-
-The following interfaces are used:
-
-_Type Definition_
-
-- _InserterMediaRequest_ `Object`: Interface for inserter media requests.
-
-_Properties_
-
-- _per_page_ `number`: How many items to fetch per page.
-- _search_ `string`: The search term to use for filtering the results.
-
-_Type Definition_
-
-- _InserterMediaItem_ `Object`: Interface for inserter media responses. Any media resource should map their response to this interface, in order to create the core WordPress media blocks (image, video, audio).
-
-_Properties_
-
-- _title_ `string`: The title of the media item.
-- _url_ \`string: The source url of the media item.
-- _previewUrl_ `[string]`: The preview source url of the media item to display in the media list.
-- _id_ `[number]`: The WordPress id of the media item.
-- _sourceId_ `[number|string]`: The id of the media item from external source.
-- _alt_ `[string]`: The alt text of the media item.
-- _caption_ `[string]`: The caption of the media item.
-
-_Usage_
-
-```js
-wp.data.dispatch( 'core/block-editor' ).registerInserterMediaCategory( {
- name: 'openverse',
- labels: {
- name: 'Openverse',
- search_items: 'Search Openverse',
- },
- mediaType: 'image',
- async fetch( query = {} ) {
- const defaultArgs = {
- mature: false,
- excluded_source: 'flickr,inaturalist,wikimedia',
- license: 'pdm,cc0',
- };
- const finalQuery = { ...query, ...defaultArgs };
- // Sometimes you might need to map the supported request params according to `InserterMediaRequest`.
- // interface. In this example the `search` query param is named `q`.
- const mapFromInserterMediaRequest = {
- per_page: 'page_size',
- search: 'q',
- };
- const url = new URL( 'https://api.openverse.org/v1/images/' );
- Object.entries( finalQuery ).forEach( ( [ key, value ] ) => {
- const queryKey = mapFromInserterMediaRequest[ key ] || key;
- url.searchParams.set( queryKey, value );
- } );
- const response = await window.fetch( url, {
- headers: {
- 'User-Agent': 'WordPress/inserter-media-fetch',
- },
- } );
- const jsonResponse = await response.json();
- const results = jsonResponse.results;
- return results.map( ( result ) => ( {
- ...result,
- // If your response result includes an `id` prop that you want to access later, it should
- // be mapped to `InserterMediaItem`'s `sourceId` prop. This can be useful if you provide
- // a report URL getter.
- // Additionally you should always clear the `id` value of your response results because
- // it is used to identify WordPress media items.
- sourceId: result.id,
- id: undefined,
- caption: result.caption,
- previewUrl: result.thumbnail,
- } ) );
- },
- getReportUrl: ( { sourceId } ) =>
- `https://wordpress.org/openverse/image/${ sourceId }/report/`,
- isExternalResource: true,
-} );
-```
-
-_Parameters_
-
-- _category_ `InserterMediaCategory`: The inserter media category to register.
-
-_Type Definition_
-
-- _InserterMediaCategory_ `Object`: Interface for inserter media category.
-
-_Properties_
-
-- _name_ `string`: The name of the media category, that should be unique among all media categories.
-- _labels_ `Object`: Labels for the media category.
-- _labels.name_ `string`: General name of the media category. It's used in the inserter media items list.
-- _labels.search_items_ `[string]`: Label for searching items. Default is ‘Search Posts’ / ‘Search Pages’.
-- _mediaType_ `('image'|'audio'|'video')`: The media type of the media category.
-- _fetch_ `(InserterMediaRequest) => Promise`: The function to fetch media items for the category.
-- _getReportUrl_ `[(InserterMediaItem) => string]`: If the media category supports reporting media items, this function should return the report url for the media item. It accepts the `InserterMediaItem` as an argument.
-- _isExternalResource_ `[boolean]`: If the media category is an external resource, this should be set to true. This is used to avoid making a request to the external resource when the user
-
-### removeBlock
-
-Returns an action object used in signalling that the block with the specified client ID is to be removed.
-
-_Parameters_
-
-- _clientId_ `string`: Client ID of block to remove.
-- _selectPrevious_ `boolean`: True if the previous block should be selected when a block is removed.
-
-_Returns_
-
-- `Object`: Action object.
-
-### removeBlocks
-
-Yields action objects used in signalling that the blocks corresponding to the set of specified client IDs are to be removed.
-
-_Parameters_
-
-- _clientIds_ `string|string[]`: Client IDs of blocks to remove.
-- _selectPrevious_ `boolean`: True if the previous block or the immediate parent (if no previous block exists) should be selected when a block is removed.
-
-### replaceBlock
-
-Action that replaces a single block with one or more replacement blocks.
-
-_Parameters_
-
-- _clientId_ `(string|string[])`: Block client ID to replace.
-- _block_ `(Object|Object[])`: Replacement block(s).
-
-_Returns_
-
-- `Object`: Action object.
-
-### replaceBlocks
-
-Action that replaces given blocks with one or more replacement blocks.
-
-_Parameters_
-
-- _clientIds_ `(string|string[])`: Block client ID(s) to replace.
-- _blocks_ `(Object|Object[])`: Replacement block(s).
-- _indexToSelect_ `number`: Index of replacement block to select.
-- _initialPosition_ `0|-1|null`: Index of caret after in the selected block after the operation.
-- _meta_ `?Object`: Optional Meta values to be passed to the action object.
-
-_Returns_
-
-- `Object`: Action object.
-
-### replaceInnerBlocks
-
-Returns an action object used in signalling that the inner blocks with the specified client ID should be replaced.
-
-_Parameters_
-
-- _rootClientId_ `string`: Client ID of the block whose InnerBlocks will re replaced.
-- _blocks_ `Object[]`: Block objects to insert as new InnerBlocks
-- _updateSelection_ `?boolean`: If true block selection will be updated. If false, block selection will not change. Defaults to false.
-- _initialPosition_ `0|-1|null`: Initial block position.
-
-_Returns_
-
-- `Object`: Action object.
-
-### resetBlocks
-
-Action that resets blocks state to the specified array of blocks, taking precedence over any other content reflected as an edit in state.
-
-_Parameters_
-
-- _blocks_ `Array`: Array of blocks.
-
-### resetSelection
-
-Returns an action object used in signalling that selection state should be reset to the specified selection.
-
-_Parameters_
-
-- _selectionStart_ `WPBlockSelection`: The selection start.
-- _selectionEnd_ `WPBlockSelection`: The selection end.
-- _initialPosition_ `0|-1|null`: Initial block position.
-
-_Returns_
-
-- `Object`: Action object.
-
-### selectBlock
-
-Returns an action object used in signalling that the block with the specified client ID has been selected, optionally accepting a position value reflecting its selection directionality. An initialPosition of -1 reflects a reverse selection.
-
-_Parameters_
-
-- _clientId_ `string`: Block client ID.
-- _initialPosition_ `0|-1|null`: Optional initial position. Pass as -1 to reflect reverse selection.
-
-_Returns_
-
-- `Object`: Action object.
-
-### selectionChange
-
-Action that changes the position of the user caret.
-
-_Parameters_
-
-- _clientId_ `string|WPSelection`: The selected block client ID.
-- _attributeKey_ `string`: The selected block attribute key.
-- _startOffset_ `number`: The start offset.
-- _endOffset_ `number`: The end offset.
-
-_Returns_
-
-- `Object`: Action object.
-
-### selectNextBlock
-
-Yields action objects used in signalling that the block following the given clientId should be selected.
-
-_Parameters_
-
-- _clientId_ `string`: Block client ID.
-
-### selectPreviousBlock
-
-Yields action objects used in signalling that the block preceding the given clientId (or optionally, its first parent from bottom to top) should be selected.
-
-_Parameters_
-
-- _clientId_ `string`: Block client ID.
-- _fallbackToParent_ `boolean`: If true, select the first parent if there is no previous block.
-
-### setBlockEditingMode
-
-Sets the block editing mode for a given block.
-
-_Related_
-
-- useBlockEditingMode
-
-_Parameters_
-
-- _clientId_ `string`: The block client ID, or `''` for the root container.
-- _mode_ `BlockEditingMode`: The block editing mode. One of `'disabled'`, `'contentOnly'`, or `'default'`.
-
-_Returns_
-
-- `Object`: Action object.
-
-### setBlockMovingClientId
-
-> **Deprecated**
-
-Set the block moving client ID.
-
-_Returns_
-
-- `Object`: Action object.
-
-### setBlockVisibility
-
-Action that sets whether given blocks are visible on the canvas.
-
-_Parameters_
-
-- _updates_ `Record`: For each block's clientId, its new visibility setting.
-
-### setHasControlledInnerBlocks
-
-Action that sets whether a block has controlled inner blocks.
-
-_Parameters_
-
-- _clientId_ `string`: The block's clientId.
-- _hasControlledInnerBlocks_ `boolean`: True if the block's inner blocks are controlled.
-
-### setNavigationMode
-
-Action that enables or disables the navigation mode.
-
-_Parameters_
-
-- _isNavigationMode_ `boolean`: Enable/Disable navigation mode.
-
-### setTemplateValidity
-
-Action that resets the template validity.
-
-_Parameters_
-
-- _isValid_ `boolean`: template validity flag.
-
-_Returns_
-
-- `Object`: Action object.
-
-### showInsertionPoint
-
-Action that shows the insertion point.
-
-_Parameters_
-
-- _rootClientId_ `?string`: Optional root client ID of block list on which to insert.
-- _index_ `?number`: Index at which block should be inserted.
-- _\_\_unstableOptions_ `?Object`: Additional options.
-
-_Returns_
-
-- `Object`: Action object.
-
-_Properties_
-
-- _\_\_unstableWithInserter_ `boolean`: Whether or not to show an inserter button.
-- _operation_ `WPDropOperation`: The operation to perform when applied, either 'insert' or 'replace' for now.
-
-### startDraggingBlocks
-
-Returns an action object used in signalling that the user has begun to drag blocks.
-
-_Parameters_
-
-- _clientIds_ `string[]`: An array of client ids being dragged
-
-_Returns_
-
-- `Object`: Action object.
-
-### startMultiSelect
-
-Action that starts block multi-selection.
-
-_Returns_
-
-- `Object`: Action object.
-
-### startTyping
-
-Returns an action object used in signalling that the user has begun to type.
-
-_Returns_
-
-- `Object`: Action object.
-
-### stopDraggingBlocks
-
-Returns an action object used in signalling that the user has stopped dragging blocks.
-
-_Returns_
-
-- `Object`: Action object.
-
-### stopMultiSelect
-
-Action that stops block multi-selection.
-
-_Returns_
-
-- `Object`: Action object.
-
-### stopTyping
-
-Returns an action object used in signalling that the user has stopped typing.
-
-_Returns_
-
-- `Object`: Action object.
-
-### synchronizeTemplate
-
-Action that synchronizes the template with the list of blocks.
-
-_Returns_
-
-- `Object`: Action object.
-
-### toggleBlockHighlight
-
-Action that toggles the highlighted block state.
-
-_Parameters_
-
-- _clientId_ `string`: The block's clientId.
-- _isHighlighted_ `boolean`: The highlight state.
-
-### toggleBlockMode
-
-Returns an action object used to toggle the block editing mode between visual and HTML modes.
-
-_Parameters_
-
-- _clientId_ `string`: Block client ID.
-
-_Returns_
-
-- `Object`: Action object.
-
-### toggleSelection
-
-Action that enables or disables block selection.
-
-_Parameters_
-
-- _isSelectionEnabled_ `[boolean]`: Whether block selection should be enabled.
-
-_Returns_
-
-- `Object`: Action object.
-
-### unsetBlockEditingMode
-
-Clears the block editing mode for a given block.
-
-_Related_
-
-- useBlockEditingMode
-
-_Parameters_
-
-- _clientId_ `string`: The block client ID, or `''` for the root container.
-
-_Returns_
-
-- `Object`: Action object.
-
-### updateBlock
-
-Action that updates the block with the specified client ID.
-
-_Parameters_
-
-- _clientId_ `string`: Block client ID.
-- _updates_ `Object`: Block attributes to be merged.
-
-_Returns_
-
-- `Object`: Action object.
-
-### updateBlockAttributes
-
-Action that updates attributes of multiple blocks with the specified client IDs.
-
-_Parameters_
-
-- _clientIds_ `string|string[]`: Block client IDs.
-- _attributes_ `Object`: Block attributes to be merged. Should be keyed by clientIds if `options.uniqueByBlock` is true.
-- _options_ `Object`: Updating options.
-- _options.uniqueByBlock_ `[boolean]`: Whether each block in clientIds array has a unique set of attributes.
-
-_Returns_
-
-- `Object`: Action object.
-
-### updateBlockListSettings
-
-Action that changes the nested settings of the given block(s).
-
-_Parameters_
-
-- _clientId_ `string | SettingsByClientId`: Client ID of the block whose nested setting are being received, or object of settings by client ID.
-- _settings_ `Object`: Object with the new settings for the nested block.
-
-_Returns_
-
-- `Object`: Action object
-
-### updateSettings
-
-Action that updates the block editor settings.
-
-_Parameters_
-
-- _settings_ `Object`: Updated settings
-
-_Returns_
-
-- `Object`: Action object
-
-### validateBlocksToTemplate
-
-Block validity is a function of blocks state (at the point of a reset) and the template setting. As a compromise to its placement across distinct parts of state, it is implemented here as a side effect of the block reset action.
-
-_Parameters_
-
-- _blocks_ `Array`: Array of blocks.
-
-
diff --git a/gutenberg/reference-guides/data/data-core-blocks.md b/gutenberg/reference-guides/data/data-core-blocks.md
deleted file mode 100644
index 0429213..0000000
--- a/gutenberg/reference-guides/data/data-core-blocks.md
+++ /dev/null
@@ -1,721 +0,0 @@
-# Block Types Data
-
-Namespace: `core/blocks`.
-
-## Selectors
-
-
-
-### getActiveBlockVariation
-
-Returns the active block variation for a given block based on its attributes. Variations are determined by their `isActive` property. Which is either an array of block attribute keys or a function.
-
-In case of an array of block attribute keys, the `attributes` are compared to the variation's attributes using strict equality check.
-
-In case of function type, the function should accept a block's attributes and the variation's attributes and determines if a variation is active. A function that accepts a block's attributes and the variation's attributes and determines if a variation is active.
-
-_Usage_
-
-```js
-import { __ } from '@wordpress/i18n';
-import { store as blocksStore } from '@wordpress/blocks';
-import { store as blockEditorStore } from '@wordpress/block-editor';
-import { useSelect } from '@wordpress/data';
-
-const ExampleComponent = () => {
- // This example assumes that a core/embed block is the first block in the Block Editor.
- const activeBlockVariation = useSelect( ( select ) => {
- // Retrieve the list of blocks.
- const [ firstBlock ] = select( blockEditorStore ).getBlocks();
-
- // Return the active block variation for the first block.
- return select( blocksStore ).getActiveBlockVariation(
- firstBlock.name,
- firstBlock.attributes
- );
- }, [] );
-
- return activeBlockVariation && activeBlockVariation.name === 'spotify' ? (
-
{ __( 'Spotify variation' ) }
- ) : (
-
{ __( 'Other variation' ) }
- );
-};
-```
-
-_Parameters_
-
-- _state_ `Object`: Data state.
-- _blockName_ `string`: Name of block (example: “core/columns”).
-- _attributes_ `Object`: Block attributes used to determine active variation.
-- _scope_ `[WPBlockVariationScope]`: Block variation scope name.
-
-_Returns_
-
-- `(WPBlockVariation|undefined)`: Active block variation.
-
-### getBlockStyles
-
-Returns block styles by block name.
-
-_Usage_
-
-```js
-import { store as blocksStore } from '@wordpress/blocks';
-import { useSelect } from '@wordpress/data';
-
-const ExampleComponent = () => {
- const buttonBlockStyles = useSelect(
- ( select ) => select( blocksStore ).getBlockStyles( 'core/button' ),
- []
- );
-
- return (
-
- )
- );
-};
-```
-
-_Parameters_
-
-- _state_ `Object`: Data state.
-
-_Returns_
-
-- `?string`: Default block name.
-
-### getDefaultBlockVariation
-
-Returns the default block variation for the given block type. When there are multiple variations annotated as the default one, the last added item is picked. This simplifies registering overrides. When there is no default variation set, it returns the first item.
-
-_Usage_
-
-```js
-import { __, sprintf } from '@wordpress/i18n';
-import { store as blocksStore } from '@wordpress/blocks';
-import { useSelect } from '@wordpress/data';
-
-const ExampleComponent = () => {
- const defaultEmbedBlockVariation = useSelect(
- ( select ) =>
- select( blocksStore ).getDefaultBlockVariation( 'core/embed' ),
- []
- );
-
- return (
- defaultEmbedBlockVariation && (
-
- );
-};
-```
-
-_Parameters_
-
-- _state_ `Object`: Data state.
-- _blockName_ `string`: Block type name.
-
-_Returns_
-
-- `boolean`: True if a block contains at least one child blocks with inserter support and false otherwise.
-
-### isMatchingSearchTerm
-
-Returns true if the block type by the given name or object value matches a search term, or false otherwise.
-
-_Usage_
-
-```js
-import { __, sprintf } from '@wordpress/i18n';
-import { store as blocksStore } from '@wordpress/blocks';
-import { useSelect } from '@wordpress/data';
-
-const ExampleComponent = () => {
- const termFound = useSelect(
- ( select ) =>
- select( blocksStore ).isMatchingSearchTerm(
- 'core/navigation',
- 'theme'
- ),
- []
- );
-
- return (
-
- { sprintf(
- __(
- 'Search term was found in the title, keywords, category or description in block.json: %s'
- ),
- termFound
- ) }
-
- );
-};
-```
-
-_Parameters_
-
-- _state_ `Object`: Blocks state.
-- _nameOrType_ `(string|Object)`: Block name or type object.
-- _searchTerm_ `string`: Search term by which to filter.
-
-_Returns_
-
-- `Object[]`: Whether block type matches search term.
-
-
-
-## Actions
-
-The actions in this package shouldn't be used directly. Instead, use the functions listed in the public API [here](/packages/blocks/README.md)
-
-
-
-### reapplyBlockTypeFilters
-
-Signals that all block types should be computed again. It uses stored unprocessed block types and all the most recent list of registered filters.
-
-It addresses the issue where third party block filters get registered after third party blocks. A sample sequence: 1. Filter A. 2. Block B. 3. Block C. 4. Filter D. 5. Filter E. 6. Block F. 7. Filter G. In this scenario some filters would not get applied for all blocks because they are registered too late.
-
-
diff --git a/gutenberg/reference-guides/data/data-core-keyboard-shortcuts.md b/gutenberg/reference-guides/data/data-core-keyboard-shortcuts.md
deleted file mode 100644
index 426fb31..0000000
--- a/gutenberg/reference-guides/data/data-core-keyboard-shortcuts.md
+++ /dev/null
@@ -1,440 +0,0 @@
-# The Keyboard Shortcuts Data
-
-Namespace: `core/keyboard-shortcuts`.
-
-## Selectors
-
-
-
-### getAllShortcutKeyCombinations
-
-Returns the shortcuts that include aliases for a given shortcut name.
-
-_Usage_
-
-```js
-import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
-import { useSelect } from '@wordpress/data';
-import { createInterpolateElement } from '@wordpress/element';
-import { sprintf } from '@wordpress/i18n';
-
-const ExampleComponent = () => {
- const allShortcutKeyCombinations = useSelect(
- ( select ) =>
- select( keyboardShortcutsStore ).getAllShortcutKeyCombinations(
- 'core/editor/next-region'
- ),
- []
- );
-
- return (
- allShortcutKeyCombinations.length > 0 && (
-
- );
-};
-```
-
-_Parameters_
-
-- _name_ `string`: Shortcut name.
-
-_Returns_
-
-- `Object`: action.
-
-
diff --git a/gutenberg/reference-guides/data/data-core-notices.md b/gutenberg/reference-guides/data/data-core-notices.md
deleted file mode 100644
index ca71b84..0000000
--- a/gutenberg/reference-guides/data/data-core-notices.md
+++ /dev/null
@@ -1,404 +0,0 @@
-# Notices Data
-
-Namespace: `core/notices`.
-
-## Selectors
-
-
-
-### getNotices
-
-Returns all notices as an array, optionally for a given context. Defaults to the global context.
-
-_Usage_
-
-```js
-import { useSelect } from '@wordpress/data';
-import { store as noticesStore } from '@wordpress/notices';
-
-const ExampleComponent = () => {
- const notices = useSelect( ( select ) =>
- select( noticesStore ).getNotices()
- );
- return (
-
- { notices.map( ( notice ) => (
-
{ notice.content }
- ) ) }
-
- );
-};
-```
-
-_Parameters_
-
-- _state_ `Object`: Notices state.
-- _context_ `?string`: Optional grouping context.
-
-_Returns_
-
-- `WPNotice[]`: Array of notices.
-
-
-
-## Actions
-
-
-
-### createErrorNotice
-
-Returns an action object used in signalling that an error notice is to be created. Refer to `createNotice` for options documentation.
-
-_Related_
-
-- createNotice
-
-_Usage_
-
-```js
-import { __ } from '@wordpress/i18n';
-import { useDispatch } from '@wordpress/data';
-import { store as noticesStore } from '@wordpress/notices';
-import { Button } from '@wordpress/components';
-
-const ExampleComponent = () => {
- const { createErrorNotice } = useDispatch( noticesStore );
- return (
-
- );
-};
-```
-
-_Parameters_
-
-- _content_ `string`: Notice message.
-- _options_ `[Object]`: Optional notice options.
-
-_Returns_
-
-- `Object`: Action object.
-
-### createInfoNotice
-
-Returns an action object used in signalling that an info notice is to be created. Refer to `createNotice` for options documentation.
-
-_Related_
-
-- createNotice
-
-_Usage_
-
-```js
-import { __ } from '@wordpress/i18n';
-import { useDispatch } from '@wordpress/data';
-import { store as noticesStore } from '@wordpress/notices';
-import { Button } from '@wordpress/components';
-
-const ExampleComponent = () => {
- const { createInfoNotice } = useDispatch( noticesStore );
- return (
-
- );
-};
-```
-
-_Parameters_
-
-- _content_ `string`: Notice message.
-- _options_ `[Object]`: Optional notice options.
-
-_Returns_
-
-- `Object`: Action object.
-
-### createNotice
-
-Returns an action object used in signalling that a notice is to be created.
-
-_Usage_
-
-```js
-import { __ } from '@wordpress/i18n';
-import { useDispatch } from '@wordpress/data';
-import { store as noticesStore } from '@wordpress/notices';
-import { Button } from '@wordpress/components';
-
-const ExampleComponent = () => {
- const { createNotice } = useDispatch( noticesStore );
- return (
-
- );
-};
-```
-
-_Parameters_
-
-- _status_ `string|undefined`: Notice status ("info" if undefined is passed).
-- _content_ `string`: Notice message.
-- _options_ `[Object]`: Notice options.
-- _options.context_ `[string]`: Context under which to group notice.
-- _options.id_ `[string]`: Identifier for notice. Automatically assigned if not specified.
-- _options.isDismissible_ `[boolean]`: Whether the notice can be dismissed by user.
-- _options.type_ `[string]`: Type of notice, one of `default`, or `snackbar`.
-- _options.speak_ `[boolean]`: Whether the notice content should be announced to screen readers.
-- _options.actions_ `[Array]`: User actions to be presented with notice.
-- _options.icon_ `[string]`: An icon displayed with the notice. Only used when type is set to `snackbar`.
-- _options.explicitDismiss_ `[boolean]`: Whether the notice includes an explicit dismiss button and can't be dismissed by clicking the body of the notice. Only applies when type is set to `snackbar`.
-- _options.onDismiss_ `[Function]`: Called when the notice is dismissed.
-
-_Returns_
-
-- `Object`: Action object.
-
-### createSuccessNotice
-
-Returns an action object used in signalling that a success notice is to be created. Refer to `createNotice` for options documentation.
-
-_Related_
-
-- createNotice
-
-_Usage_
-
-```js
-import { __ } from '@wordpress/i18n';
-import { useDispatch } from '@wordpress/data';
-import { store as noticesStore } from '@wordpress/notices';
-import { Button } from '@wordpress/components';
-
-const ExampleComponent = () => {
- const { createSuccessNotice } = useDispatch( noticesStore );
- return (
-
- );
-};
-```
-
-_Parameters_
-
-- _content_ `string`: Notice message.
-- _options_ `[Object]`: Optional notice options.
-
-_Returns_
-
-- `Object`: Action object.
-
-### createWarningNotice
-
-Returns an action object used in signalling that a warning notice is to be created. Refer to `createNotice` for options documentation.
-
-_Related_
-
-- createNotice
-
-_Usage_
-
-```js
-import { __ } from '@wordpress/i18n';
-import { useDispatch } from '@wordpress/data';
-import { store as noticesStore } from '@wordpress/notices';
-import { Button } from '@wordpress/components';
-
-const ExampleComponent = () => {
- const { createWarningNotice, createInfoNotice } =
- useDispatch( noticesStore );
- return (
-
- );
-};
-```
-
-_Parameters_
-
-- _content_ `string`: Notice message.
-- _options_ `[Object]`: Optional notice options.
-
-_Returns_
-
-- `Object`: Action object.
-
-### removeAllNotices
-
-Removes all notices from a given context. Defaults to the default context.
-
-_Usage_
-
-```js
-import { __ } from '@wordpress/i18n';
-import { useDispatch, useSelect } from '@wordpress/data';
-import { store as noticesStore } from '@wordpress/notices';
-import { Button } from '@wordpress/components';
-
-export const ExampleComponent = () => {
- const notices = useSelect( ( select ) =>
- select( noticesStore ).getNotices()
- );
- const { removeAllNotices } = useDispatch( noticesStore );
- return (
- <>
-
- { notices.map( ( notice ) => (
-
{ notice.content }
- ) ) }
-
-
-
- >
- );
-};
-```
-
-_Parameters_
-
-- _noticeType_ `string`: The context to remove all notices from.
-- _context_ `string`: The context to remove all notices from.
-
-_Returns_
-
-- `Object`: Action object.
-
-### removeNotice
-
-Returns an action object used in signalling that a notice is to be removed.
-
-_Usage_
-
-```js
-import { __ } from '@wordpress/i18n';
-import { useDispatch } from '@wordpress/data';
-import { store as noticesStore } from '@wordpress/notices';
-import { Button } from '@wordpress/components';
-
-const ExampleComponent = () => {
- const notices = useSelect( ( select ) =>
- select( noticesStore ).getNotices()
- );
- const { createWarningNotice, removeNotice } = useDispatch( noticesStore );
-
- return (
- <>
-
- { notices.length > 0 && (
-
- ) }
- >
- );
-};
-```
-
-_Parameters_
-
-- _id_ `string`: Notice unique identifier.
-- _context_ `[string]`: Optional context (grouping) in which the notice is intended to appear. Defaults to default context.
-
-_Returns_
-
-- `Object`: Action object.
-
-### removeNotices
-
-Returns an action object used in signalling that several notices are to be removed.
-
-_Usage_
-
-```js
-import { __ } from '@wordpress/i18n';
-import { useDispatch, useSelect } from '@wordpress/data';
-import { store as noticesStore } from '@wordpress/notices';
-import { Button } from '@wordpress/components';
-
-const ExampleComponent = () => {
- const notices = useSelect( ( select ) =>
- select( noticesStore ).getNotices()
- );
- const { removeNotices } = useDispatch( noticesStore );
- return (
- <>
-
- { notices.map( ( notice ) => (
-
{ notice.content }
- ) ) }
-
-
- >
- );
-};
-```
-
-_Parameters_
-
-- _ids_ `string[]`: List of unique notice identifiers.
-- _context_ `[string]`: Optional context (grouping) in which the notices are intended to appear. Defaults to default context.
-
-_Returns_
-
-- `Object`: Action object.
-
-
diff --git a/gutenberg/reference-guides/data/data-core.md b/gutenberg/reference-guides/data/data-core.md
deleted file mode 100644
index 757a92f..0000000
--- a/gutenberg/reference-guides/data/data-core.md
+++ /dev/null
@@ -1,912 +0,0 @@
-# WordPress Core Data
-
-Namespace: `core`.
-
-## Dynamically generated selectors
-
-There are a number of user-friendly selectors that are wrappers of the more generic `getEntityRecord` and `getEntityRecords` that can be used to retrieve information for the various entities.
-
-### getPostType
-
-Returns the information for a given post type.
-
-_Usage_
-
- import { useSelect } from '@wordpress/data';
- import { store as coreDataStore } from '@wordpress/core-data';
-
- const postType = useSelect(
- ( select ) => select( coreDataStore ).getPostType( 'post' )
-
- // Equivalent to: select( coreDataStore ).getEntityRecord( 'root', 'postType', 'post' )
- );
-
-_Parameters_
-
-- postType `string`
-
-_Returns_
-
-- `EntityRecord | undefined`: Record.
-
-### getPostTypes
-
-Returns the information for post types.
-
-_Usage_
-
- import { useSelect } from '@wordpress/data';
- import { store as coreDataStore } from '@wordpress/core-data';
-
- const postTypes = useSelect( ( select ) => {
- return select( coreDataStore ).getPostTypes( { per_page: 4 } );
-
- // Equivalent to:
- // select( coreDataStore ).getEntityRecords( 'root', 'postType', { per_page: 4 } );
- } );
-
-_Parameters_
-
-- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
-
-_Returns_
-
-- `EntityRecord[] | null`: Records.
-
-### getTaxonomy
-
-Returns information for a given taxonomy.
-
-_Usage_
-
- import { useSelect } from '@wordpress/data';
- import { store as coreDataStore } from '@wordpress/core-data';
-
- const taxonomy = useSelect( ( select ) => {
- return select( coreDataStore ).getTaxonomy( 'category' );
-
- // Equivalent to:
- // select( coreDataStore ).getEntityRecord( 'root', 'taxonomy', 'category' );
- } );
-
-_Parameters_
-
-- taxonomy `string`
-
-_Returns_
-
-- `EntityRecord | undefined`: Record.
-
-### getTaxonomies
-
-Returns information for taxonomies.
-
-_Usage_
-
- import { useSelect } from '@wordpress/data';
- import { store as coreDataStore } from '@wordpress/core-data';
-
- const taxonomies = useSelect( ( select ) => {
- return select( coreDataStore ).getTaxonomies( { type: 'post' } );
-
- // Equivalent to:
- // select( coreDataStore ).getEntityRecords( 'root', 'taxonomy', { type: 'post' } );
- } );
-
-_Parameters_
-
-- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
-
-_Returns_
-
-- `EntityRecord[] | null`: Records.
-
-## Other Selectors
-
-
-
-### canUser
-
-Returns whether the current user can perform the given action on the given REST resource.
-
-Calling this may trigger an OPTIONS request to the REST API via the `canUser()` resolver.
-
-
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _action_ `string`: Action to check. One of: 'create', 'read', 'update', 'delete'.
-- _resource_ `string | EntityResource`: Entity resource to check. Accepts entity object `{ kind: 'postType', name: 'attachment', id: 1 }` or REST base as a string - `media`.
-- _id_ `EntityRecordKey`: Optional ID of the rest resource to check.
-
-_Returns_
-
-- `boolean | undefined`: Whether or not the user can perform the action, or `undefined` if the OPTIONS request is still being made.
-
-### canUserEditEntityRecord
-
-Returns whether the current user can edit the given entity.
-
-Calling this may trigger an OPTIONS request to the REST API via the `canUser()` resolver.
-
-
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record's id.
-
-_Returns_
-
-- `boolean | undefined`: Whether or not the user can edit, or `undefined` if the OPTIONS request is still being made.
-
-### getAuthors
-
-> **Deprecated** since 11.3. Callers should use `select( 'core' ).getUsers({ who: 'authors' })` instead.
-
-Returns all available authors.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _query_ `GetRecordsHttpQuery`: Optional object of query parameters to include with request. For valid query parameters see the [Users page](https://developer.wordpress.org/rest-api/reference/users/) in the REST API Handbook and see the arguments for [List Users](https://developer.wordpress.org/rest-api/reference/users/#list-users) and [Retrieve a User](https://developer.wordpress.org/rest-api/reference/users/#retrieve-a-user).
-
-_Returns_
-
-- `ET.User[]`: Authors list.
-
-### getAutosave
-
-Returns the autosave for the post and author.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _postType_ `string`: The type of the parent post.
-- _postId_ `EntityRecordKey`: The id of the parent post.
-- _authorId_ `EntityRecordKey`: The id of the author.
-
-_Returns_
-
-- `EntityRecord | undefined`: The autosave for the post and author.
-
-### getAutosaves
-
-Returns the latest autosaves for the post.
-
-May return multiple autosaves since the backend stores one autosave per author for each post.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _postType_ `string`: The type of the parent post.
-- _postId_ `EntityRecordKey`: The id of the parent post.
-
-_Returns_
-
-- `Array< any > | undefined`: An array of autosaves for the post, or undefined if there is none.
-
-### getBlockPatternCategories
-
-Retrieve the list of registered block pattern categories.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-
-_Returns_
-
-- `Array< any >`: Block pattern category list.
-
-### getBlockPatterns
-
-Retrieve the list of registered block patterns.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-
-_Returns_
-
-- `Array< any >`: Block pattern list.
-
-### getCurrentTheme
-
-Return the current theme.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-
-_Returns_
-
-- `any`: The current theme.
-
-### getCurrentThemeGlobalStylesRevisions
-
-> **Deprecated** since WordPress 6.5.0. Callers should use `select( 'core' ).getRevisions( 'root', 'globalStyles', ${ recordKey } )` instead, where `recordKey` is the id of the global styles parent post.
-
-Returns the revisions of the current global styles theme.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-
-_Returns_
-
-- `Array< object > | null`: The current global styles.
-
-### getCurrentUser
-
-Returns the current user.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-
-_Returns_
-
-- `ET.User< 'edit' >`: Current user object.
-
-### getDefaultTemplateId
-
-Returns the default template use to render a given query.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _query_ `TemplateQuery`: Query.
-
-_Returns_
-
-- `string`: The default template id for the given query.
-
-### getEditedEntityRecord
-
-Returns the specified entity record, merged with its edits.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record ID.
-
-_Returns_
-
-- `ET.Updatable< EntityRecord > | false`: The entity record, merged with its edits.
-
-### getEmbedPreview
-
-Returns the embed preview for the given URL.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _url_ `string`: Embedded URL.
-
-_Returns_
-
-- `any`: Undefined if the preview has not been fetched, otherwise, the preview fetched from the embed preview API.
-
-### getEntitiesByKind
-
-> **Deprecated** since WordPress 6.0. Use getEntitiesConfig instead
-
-Returns the loaded entities for the given kind.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _kind_ `string`: Entity kind.
-
-_Returns_
-
-- `Array< any >`: Array of entities with config matching kind.
-
-### getEntitiesConfig
-
-Returns the loaded entities for the given kind.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _kind_ `string`: Entity kind.
-
-_Returns_
-
-- `Array< any >`: Array of entities with config matching kind.
-
-### getEntity
-
-> **Deprecated** since WordPress 6.0. Use getEntityConfig instead
-
-Returns the entity config given its kind and name.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-
-_Returns_
-
-- `any`: Entity config
-
-### getEntityConfig
-
-Returns the entity config given its kind and name.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-
-_Returns_
-
-- `any`: Entity config
-
-### getEntityRecord
-
-Returns the Entity's record object by key. Returns `null` if the value is not yet received, undefined if the value entity is known to not exist, or the entity object if it exists and is received.
-
-_Parameters_
-
-- _state_ `State`: State tree
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _key_ `EntityRecordKey`: Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included.
-- _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]".
-
-_Returns_
-
-- `EntityRecord | undefined`: Record.
-
-### getEntityRecordEdits
-
-Returns the specified entity record's edits.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record ID.
-
-_Returns_
-
-- `Optional< any >`: The entity record's edits.
-
-### getEntityRecordNonTransientEdits
-
-Returns the specified entity record's non transient edits.
-
-Transient edits don't create an undo level, and are not considered for change detection. They are defined in the entity's config.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record ID.
-
-_Returns_
-
-- `Optional< any >`: The entity record's non transient edits.
-
-### getEntityRecords
-
-Returns the Entity's records.
-
-_Parameters_
-
-- _state_ `State`: State tree
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
-
-_Returns_
-
-- `EntityRecord[] | null`: Records.
-
-### getEntityRecordsTotalItems
-
-Returns the Entity's total available records for a given query (ignoring pagination).
-
-_Parameters_
-
-- _state_ `State`: State tree
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
-
-_Returns_
-
-- `number | null`: number | null.
-
-### getEntityRecordsTotalPages
-
-Returns the number of available pages for the given query.
-
-_Parameters_
-
-- _state_ `State`: State tree
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
-
-_Returns_
-
-- `number | null`: number | null.
-
-### getLastEntityDeleteError
-
-Returns the specified entity record's last delete error.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record ID.
-
-_Returns_
-
-- `any`: The entity record's save error.
-
-### getLastEntitySaveError
-
-Returns the specified entity record's last save error.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record ID.
-
-_Returns_
-
-- `any`: The entity record's save error.
-
-### getRawEntityRecord
-
-Returns the entity's record object by key, with its attributes mapped to their raw values.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _key_ `EntityRecordKey`: Record's key.
-
-_Returns_
-
-- `EntityRecord | undefined`: Object with the entity's raw attributes.
-
-### getRedoEdit
-
-> **Deprecated** since 6.3
-
-Returns the next edit from the current undo offset for the entity records edits history, if any.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-
-_Returns_
-
-- `Optional< any >`: The edit.
-
-### getReferenceByDistinctEdits
-
-Returns a new reference when edited values have changed. This is useful in inferring where an edit has been made between states by comparison of the return values using strict equality.
-
-_Usage_
-
- const hasEditOccurred = (
- getReferenceByDistinctEdits( beforeState ) !==
- getReferenceByDistinctEdits( afterState )
- );
-
-_Parameters_
-
-- _state_ Editor state.
-
-_Returns_
-
-- A value whose reference will change only when an edit occurs.
-
-### getRevision
-
-Returns a single, specific revision of a parent entity.
-
-_Parameters_
-
-- _state_ `State`: State tree
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordKey_ `EntityRecordKey`: The key of the entity record whose revisions you want to fetch.
-- _revisionKey_ `EntityRecordKey`: The revision's key.
-- _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see revisions schema in [the REST API Handbook](https://developer.wordpress.org/rest-api/reference/). Then see the arguments available "Retrieve a [entity kind]".
-
-_Returns_
-
-- `RevisionRecord | Record< PropertyKey, never > | undefined`: Record.
-
-### getRevisions
-
-Returns an entity's revisions.
-
-_Parameters_
-
-- _state_ `State`: State tree
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordKey_ `EntityRecordKey`: The key of the entity record whose revisions you want to fetch.
-- _query_ `GetRecordsHttpQuery`: Optional query. If requesting specific fields, fields must always include the ID. For valid query parameters see revisions schema in [the REST API Handbook](https://developer.wordpress.org/rest-api/reference/). Then see the arguments available "Retrieve a [Entity kind]".
-
-_Returns_
-
-- `RevisionRecord[] | null`: Record.
-
-### getThemeSupports
-
-Return theme supports data in the index.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-
-_Returns_
-
-- `any`: Index data.
-
-### getUndoEdit
-
-> **Deprecated** since 6.3
-
-Returns the previous edit from the current undo offset for the entity records edits history, if any.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-
-_Returns_
-
-- `Optional< any >`: The edit.
-
-### getUserPatternCategories
-
-Retrieve the registered user pattern categories.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-
-_Returns_
-
-- `Array< UserPatternCategory >`: User patterns category array.
-
-### getUserQueryResults
-
-Returns all the users returned by a query ID.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _queryID_ `string`: Query ID.
-
-_Returns_
-
-- `ET.User< 'edit' >[]`: Users list.
-
-### hasEditsForEntityRecord
-
-Returns true if the specified entity record has edits, and false otherwise.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record ID.
-
-_Returns_
-
-- `boolean`: Whether the entity record has edits or not.
-
-### hasEntityRecords
-
-Returns true if records have been received for the given set of parameters, or false otherwise.
-
-_Parameters_
-
-- _state_ `State`: State tree
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _query_ `GetRecordsHttpQuery`: Optional terms query. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
-
-_Returns_
-
-- `boolean`: Whether entity records have been received.
-
-### hasFetchedAutosaves
-
-Returns true if the REST request for autosaves has completed.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _postType_ `string`: The type of the parent post.
-- _postId_ `EntityRecordKey`: The id of the parent post.
-
-_Returns_
-
-- `boolean`: True if the REST request was completed. False otherwise.
-
-### hasRedo
-
-Returns true if there is a next edit from the current undo offset for the entity records edits history, and false otherwise.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-
-_Returns_
-
-- `boolean`: Whether there is a next edit or not.
-
-### hasUndo
-
-Returns true if there is a previous edit from the current undo offset for the entity records edits history, and false otherwise.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-
-_Returns_
-
-- `boolean`: Whether there is a previous edit or not.
-
-### isAutosavingEntityRecord
-
-Returns true if the specified entity record is autosaving, and false otherwise.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record ID.
-
-_Returns_
-
-- `boolean`: Whether the entity record is autosaving or not.
-
-### isDeletingEntityRecord
-
-Returns true if the specified entity record is deleting, and false otherwise.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record ID.
-
-_Returns_
-
-- `boolean`: Whether the entity record is deleting or not.
-
-### isPreviewEmbedFallback
-
-Determines if the returned preview is an oEmbed link fallback.
-
-WordPress can be configured to return a simple link to a URL if it is not embeddable. We need to be able to determine if a URL is embeddable or not, based on what we get back from the oEmbed preview API.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _url_ `string`: Embedded URL.
-
-_Returns_
-
-- `boolean`: Is the preview for the URL an oEmbed link fallback.
-
-### isRequestingEmbedPreview
-
-Returns true if a request is in progress for embed preview data, or false otherwise.
-
-_Parameters_
-
-- _state_ `State`: Data state.
-- _url_ `string`: URL the preview would be for.
-
-_Returns_
-
-- `boolean`: Whether a request is in progress for an embed preview.
-
-### isSavingEntityRecord
-
-Returns true if the specified entity record is saving, and false otherwise.
-
-_Parameters_
-
-- _state_ `State`: State tree.
-- _kind_ `string`: Entity kind.
-- _name_ `string`: Entity name.
-- _recordId_ `EntityRecordKey`: Record ID.
-
-_Returns_
-
-- `boolean`: Whether the entity record is saving or not.
-
-
-
-## Actions
-
-
-
-### addEntities
-
-Returns an action object used in adding new entities.
-
-_Parameters_
-
-- _entities_ `Array`: Entities received.
-
-_Returns_
-
-- `Object`: Action object.
-
-### deleteEntityRecord
-
-Action triggered to delete an entity record.
-
-_Parameters_
-
-- _kind_ `string`: Kind of the deleted entity.
-- _name_ `string`: Name of the deleted entity.
-- _recordId_ `number|string`: Record ID of the deleted entity.
-- _query_ `?Object`: Special query parameters for the DELETE API call.
-- _options_ `[Object]`: Delete options.
-- _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a promise.
-- _options.throwOnError_ `[boolean]`: If false, this action suppresses all the exceptions. Defaults to false.
-
-### editEntityRecord
-
-Returns an action object that triggers an edit to an entity record.
-
-_Parameters_
-
-- _kind_ `string`: Kind of the edited entity record.
-- _name_ `string`: Name of the edited entity record.
-- _recordId_ `number|string`: Record ID of the edited entity record.
-- _edits_ `Object`: The edits.
-- _options_ `Object`: Options for the edit.
-- _options.undoIgnore_ `[boolean]`: Whether to ignore the edit in undo history or not.
-
-_Returns_
-
-- `Object`: Action object.
-
-### receiveDefaultTemplateId
-
-Returns an action object used to set the template for a given query.
-
-_Parameters_
-
-- _query_ `Object`: The lookup query.
-- _templateId_ `string`: The resolved template id.
-
-_Returns_
-
-- `Object`: Action object.
-
-### receiveEntityRecords
-
-Returns an action object used in signalling that entity records have been received.
-
-_Parameters_
-
-- _kind_ `string`: Kind of the received entity record.
-- _name_ `string`: Name of the received entity record.
-- _records_ `Array|Object`: Records received.
-- _query_ `?Object`: Query Object.
-- _invalidateCache_ `?boolean`: Should invalidate query caches.
-- _edits_ `?Object`: Edits to reset.
-- _meta_ `?Object`: Meta information about pagination.
-
-_Returns_
-
-- `Object`: Action object.
-
-### receiveNavigationFallbackId
-
-Returns an action object signalling that the fallback Navigation Menu id has been received.
-
-_Parameters_
-
-- _fallbackId_ `integer`: the id of the fallback Navigation Menu
-
-_Returns_
-
-- `Object`: Action object.
-
-### receiveRevisions
-
-Action triggered to receive revision items.
-
-_Parameters_
-
-- _kind_ `string`: Kind of the received entity record revisions.
-- _name_ `string`: Name of the received entity record revisions.
-- _recordKey_ `number|string`: The key of the entity record whose revisions you want to fetch.
-- _records_ `Array|Object`: Revisions received.
-- _query_ `?Object`: Query Object.
-- _invalidateCache_ `?boolean`: Should invalidate query caches.
-- _meta_ `?Object`: Meta information about pagination.
-
-### receiveThemeSupports
-
-> **Deprecated** since WP 5.9, this is not useful anymore, use the selector directly.
-
-Returns an action object used in signalling that the index has been received.
-
-_Returns_
-
-- `Object`: Action object.
-
-### receiveUploadPermissions
-
-> **Deprecated** since WP 5.9, use receiveUserPermission instead.
-
-Returns an action object used in signalling that Upload permissions have been received.
-
-_Parameters_
-
-- _hasUploadPermissions_ `boolean`: Does the user have permission to upload files?
-
-_Returns_
-
-- `Object`: Action object.
-
-### redo
-
-Action triggered to redo the last undone edit to an entity record, if any.
-
-### saveEditedEntityRecord
-
-Action triggered to save an entity record's edits.
-
-_Parameters_
-
-- _kind_ `string`: Kind of the entity.
-- _name_ `string`: Name of the entity.
-- _recordId_ `Object`: ID of the record.
-- _options_ `Object=`: Saving options.
-
-### saveEntityRecord
-
-Action triggered to save an entity record.
-
-_Parameters_
-
-- _kind_ `string`: Kind of the received entity.
-- _name_ `string`: Name of the received entity.
-- _record_ `Object`: Record to be saved.
-- _options_ `Object`: Saving options.
-- _options.isAutosave_ `[boolean]`: Whether this is an autosave.
-- _options.\_\_unstableFetch_ `[Function]`: Internal use only. Function to call instead of `apiFetch()`. Must return a promise.
-- _options.throwOnError_ `[boolean]`: If false, this action suppresses all the exceptions. Defaults to false.
-
-### undo
-
-Action triggered to undo the last edit to an entity record, if any.
-
-
diff --git a/gutenberg/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md b/gutenberg/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md
deleted file mode 100644
index f614574..0000000
--- a/gutenberg/reference-guides/interactivity-api/core-concepts/undestanding-global-state-local-context-and-derived-state.md
+++ /dev/null
@@ -1,842 +0,0 @@
-# Understanding global state, local context and derived state
-
-The Interactivity API offers a powerful framework for creating interactive blocks. To make the most of its capabilities, it's crucial to understand when to use global state, local context, or derived state. This guide will clarify these concepts and provide practical examples to help you decide when to use each one.
-
-Let's start with a brief definition of global state, local context and derived state.
-
-- **Global state:** Global data that can be accessed and modified by any interactive block on the page, allowing different parts of your interactive blocks to stay in sync.
-- **Local context:** Local data defined within a specific element in the HTML structure, accessible only to that element and its children, providing independent state for individual blocks.
-- **Derived state:** Computed values based on global state or local context, dynamically calculated on-demand to ensure consistent data representation without storing redundant data.
-
-Let's now dive into each of these concepts to study them in more detail and provide some examples.
-
-## Global state
-
-**Global state** in the Interactivity API refers to global data that can be accessed and modified by any interactive block on the page. It serves as a shared information hub, allowing different parts of your blocks to communicate and stay in sync. Global state is the ideal mechanism for exchanging information between interactive blocks, regardless of their position in the DOM tree.
-
-You should use global state when:
-
-- You need to share data between multiple interactive blocks that are not directly related in the DOM hierarchy.
-- You want to maintain a single source of truth for certain data across all your interactive blocks.
-- You're dealing with data that affects multiple parts of your UI simultaneously.
-- You want to implement features that are global for the page.
-
-### Working with global state
-
-- **Initializing the global state**
-
- Typically, the initial global state values should be defined on the server using the `wp_interactivity_state` function:
-
- ```php
- // Populates the initial global state values.
- wp_interactivity_state( 'myPlugin', array(
- 'isDarkTheme' => true,
- 'show' => false,
- 'helloText' => __( 'world' ),
- ));
- ```
-
- These initial global state values will be used during the rendering of the page in PHP to populate the HTML markup that is sent to the browser.
-
- - HTML markup written in the PHP file by the developer:
-
- ```html
-
-
- Hello
-
-
-
- ```
-
- - HTML markup after the directives have been processed and it is ready to be sent to the browser:
-
- ```html
-
-
- Hello world
-
-
-
- ```
-
- _Please, visit [the Server-side Rendering guide](/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md) to learn more about how directives are processed on the server._
-
- In cases where the global state is not used during the rendering of the page in PHP, it can also be defined directly on the client.
-
- ```js
- const { state } = store( 'myPlugin', {
- state: {
- isLoading: false,
- },
- actions: {
- *loadSomething() {
- state.isLoading = true;
- // ...
- },
- },
- } );
- ```
-
- _Please note that, although this works, in general it is a good practice to define all the global state on the server._
-
-- **Accessing the global state**
-
- In the HTML markup, you can access the global state values directly by referencing `state` in the directive attribute values:
-
- ```html
-
-
-
- ```
-
- In JavaScript, the `store` function from the package at `@wordpress/interactivity` works both as a setter and a getter, returning the store of the selected namespace.
-
- To access the global state in your actions and callbacks, you can use the `state` property of the object returned by the `store` function:
-
- ```js
- const myPluginStore = store( 'myPlugin' );
-
- myPluginStore.state; // This is the state of the 'myPlugin' namespace.
- ```
-
- You can also destructure the object returned by `store`:
-
- ```js
- const { state } = store( 'myPlugin' );
- ```
-
- And you can do the same even if you are defining the store at that moment, which is the most common scenario:
-
- ```js
- const { state } = store( 'myPlugin', {
- state: {
- // ...
- },
- actions: {
- toggle() {
- state.show = ! state.show;
- },
- },
- } );
- ```
-
- The global state initialized on the server using the `wp_interactivity_state` function is also included in that object because it is automatically serialized from the server to the client:
-
- ```php
- wp_interactivity_state( 'myPlugin', array(
- 'someValue' => 1,
- ));
- ```
-
- ```js
- const { state } = store( 'myPlugin', {
- state: {
- otherValue: 2,
- },
- actions: {
- readGlobalState() {
- state.someValue; // It exists and its initial value is 1.
- state.otherValue; // It exists and its initial value is 2.
- },
- },
- } );
- ```
-
- Lastly, all calls to the `store` function with the same namespace are merged together:
-
- ```js
- store( 'myPlugin', { state: { someValue: 1 } } );
-
- store( 'myPlugin', { state: { otherValue: 2 } } );
-
- /* All calls to `store` return a stable reference to the same object, so you
- * can get a reference to `state` from any of them. */
- const { state } = store( 'myPlugin' );
-
- store( 'myPlugin', {
- actions: {
- readValues() {
- state.someValue; // It exists and its initial value is 1.
- state.otherValue; // It exists and its initial value is 2.
- },
- },
- } );
- ```
-
-- **Updating the global state**
-
- To update the global state, all you need to do is mutate the `state` object once you have obtained it from the `store` function:
-
- ```js
- const { state } = store( 'myPlugin', {
- actions: {
- updateValues() {
- state.someValue = 3;
- state.otherValue = 4;
- },
- },
- } );
- ```
-
- Changes to the global state will automatically trigger updates in any directives that depend on the modified values.
-
- _Please, visit [The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._
-
-### Example: Two interactive blocks using global state to communicate
-
-In this example, there are two independent interactive blocks. One displays a counter, and the other a button to increment that counter. These blocks can be positioned anywhere on the page, regardless of the HTML structure. In other words, one does not need to be an inner block of the other.
-
-- **Counter Block**
-
- ```php
- 0
- ));
- ?>
-
-
- >
- Counter:
-
- ```
-
-- **Increment Block**
-
- ```php
-
- >
-
-
- ```
-
- ```js
- const { state } = store( 'myCounterPlugin', {
- actions: {
- increment() {
- state.counter += 1;
- },
- },
- } );
- ```
-
-In this example:
-
-1. The global state is initialized on the server using `wp_interactivity_state`, setting an initial `counter` of 0.
-2. The Counter Block displays the current counter using `data-wp-text="state.counter"`, which reads from the global state.
-3. The Increment Block contains a button that triggers the `increment` action when clicked, using `data-wp-on-async--click="actions.increment"`.
-4. In JavaScript, the `increment` action directly modifies the global state by incrementing `state.counter`.
-
-Both blocks are independent and can be placed anywhere on the page. They don't need to be nested or directly related in the DOM structure. Multiple instances of these interactive blocks can be added to the page, and they will all share and update the same global counter value.
-
-## Local context
-
-**Local context** in the Interactivity API refers to local data defined within a specific element in the HTML structure. Unlike global state, local context is only accessible to the element where it's defined and its child elements.
-
-The local context is particularly useful when you need independent state for individual interactive blocks, ensuring that each instance of a block can maintain its own unique data without interfering with others.
-
-You should use local context when:
-
-- You need to maintain separate state for multiple instances of the same interactive block.
-- You want to encapsulate data that's only relevant to a specific interactive block and its children.
-- You need to implement features that are isolated to a specific part of your UI.
-
-### Working with local context
-
-- **Initializing the local context**
-
- The local context is initialized directly within the HTML structure using the `data-wp-context` directive. This directive accepts a JSON string that defines the initial values for that piece of context.
-
- ```html
-
-
-
- ```
-
- You can also initialize the local context on the server using the `wp_interactivity_data_wp_context` PHP helper, which ensures proper escaping and formatting of the stringified values:
-
- ```php
- 0 );
- ?>
-
-
>
-
-
- ```
-
-- **Accessing the local context**
-
- In the HTML markup, you can access the local context values directly by referencing `context` in the directive values:
-
- ```html
-
-
-
- ```
-
- In JavaScript, you can access the local context values using the `getContext` function:
-
- ```js
- store( 'myPlugin', {
- actions: {
- sendAnalyticsEvent() {
- const { counter } = getContext();
- myAnalyticsLibrary.sendEvent( 'updated counter', counter );
- },
- },
- callbacks: {
- logCounter() {
- const { counter } = getContext();
- console.log( `Current counter: ${ counter }` );
- },
- },
- } );
- ```
-
- The `getContext` function returns the local context of the element that triggered the action/callback execution.
-
-- **Updating the local context**
-
- To update the local context values in JavaScript, you can modify the object returned by `getContext`:
-
- ```js
- store( 'myPlugin', {
- actions: {
- increment() {
- const context = getContext();
- context.counter += 1;
- },
- updateName( event ) {
- const context = getContext();
- context.name = event.target.value;
- },
- },
- } );
- ```
-
- Changes to the local context will automatically trigger updates in any directives that depend on the modified values.
-
- _Please, visit [The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) guide to learn more about how reactivity works in the Interactivity API._
-
-- **Nesting local contexts**
-
- Local contexts can be nested, with child contexts inheriting and potentially overriding values from parent contexts:
-
- ```html
-
-
Theme:
-
Counter:
-
-
-
Theme:
-
Counter:
-
-
- ```
-
- In this example, the inner `div` will have a `theme` value of `"dark"`, but will inherit the `counter` value `0` from its parent context.
-
-### Example: One interactive block using local context to have independent state
-
-In this example, there is a single interactive block that shows a counter and can increment it. By using local context, each instance of this block will have its own independent counter, even if multiple blocks are added to the page.
-
-```php
-
- data-wp-context='{ "counter": 0 }'
->
-
Counter:
-
-
-```
-
-```js
-store( 'myCounterPlugin', {
- actions: {
- increment() {
- const context = getContext();
- context.counter += 1;
- },
- },
-} );
-```
-
-In this example:
-
-1. A local context with an initial `counter` value of `0` is defined using the `data-wp-context` directive.
-2. The counter is displayed using `data-wp-text="context.counter"`, which reads from the local context.
-3. The increment button uses `data-wp-on-async--click="actions.increment"` to trigger the increment action.
-4. In JavaScript, the `getContext` function is used to access and modify the local context for each block instance.
-
-A user will be able to add multiple instances of this block to a page, and each will maintain its own independent counter. Clicking the "Increment" button on one block will only affect that specific block's counter and not the others.
-
-## Derived state
-
-**Derived state** in the Interactivity API refers to a value that is computed from other parts of the global state or local context. It's calculated on demand rather than stored. It ensures consistency, reduces redundancies, and enhances the declarative nature of your code.
-
-Derived state is a fundamental concept in modern state management, not unique to the Interactivity API. It's also used in other popular state management systems like Redux, where it's called `selectors`, or Preact Signals, where it's known as `computed` values.
-
-Derived state offers several key benefits that make it an essential part of a well-designed application state, including:
-
-1. **Single source of truth:** Derived state encourages you to store only the essential, raw data in your state. Any values that can be calculated from this core data become derived state. This approach reduces the risk of inconsistencies in your interactive blocks.
-
-2. **Automatic updates:** When you use derived state, values are recalculated automatically whenever the underlying data changes. This ensures that all parts of your interactive blocks always have access to the most up-to-date information without manual intervention.
-
-3. **Simplified state management:** By computing values on-demand rather than storing and updating them manually, you reduce the complexity of your state management logic. This leads to cleaner, more maintainable code.
-
-4. **Improved performance:** In many cases, derived state can be optimized to recalculate only when necessary, potentially improving your interactive blocks' performance.
-
-5. **Easier debugging:** With derived state, it's clearer where data originates and how it's transformed. This can make it easier to track down issues in your interactive blocks.
-
-In essence, derived state allows you to express relationships between different pieces of data in your interactive blocks declaratively, instead of imperatively updating related values whenever something changes.
-
-_Please, visit [The Reactive and Declarative mindset](/docs/reference-guides/interactivity-api/core-concepts/the-reactive-and-declarative-mindset.md) guide to learn more about how to leverage declarative coding in the Interactivity API._
-
-You should use derived state:
-
-- When a part of your global state or local context can be computed from other state values.
-- To avoid redundant data that needs to be manually kept in sync.
-- To ensure consistency across your interactive blocks by automatically updating derived values.
-- To simplify your actions by removing the need to update multiple related state properties.
-
-### Working with derived state
-
-- **Initializing the derived state**
-
- Typically, the derived state should be initialized on the server using the `wp_interactivity_state` function in the exact same way as the global state.
-
- - When the initial value is known and static, it can be defined directly:
-
- ```php
- wp_interactivity_state( 'myCounterPlugin', array(
- 'counter' => 1, // This is global state.
- 'double' => 2, // This is derived state.
- ));
- ```
-
- - Or it can be defined by doing the necessary computations:
-
- ```php
- $counter = 1;
- $double = $counter * 2;
-
- wp_interactivity_state( 'myCounterPlugin', array(
- 'counter' => $counter, // This is global state.
- 'double' => $double, // This is derived state.
- ));
- ```
-
- Regardless of the approach, the initial derived state values will be used during the rendering of the page in PHP, and the HTML can be populated with the correct values.
-
- _Please, visit [the Server-side Rendering guide](/docs/reference-guides/interactivity-api/core-concepts/server-side-rendering.md) to learn more about how directives are processed on the server._
-
- The same mechanism applies even when the derived state property depends on the local context.
-
- ```php
- $counter );
-
- wp_interactivity_state( 'myCounterPlugin', array(
- 'double' => $counter * 2, // This is derived state.
- ));
- ?>
-
-
- >
-
- Counter:
-
-
- Double:
-
-
- ```
-
- In JavaScript, the derived state is defined using getters:
-
- ```js
- const { state } = store( 'myCounterPlugin', {
- state: {
- get double() {
- return state.counter * 2;
- },
- },
- } );
- ```
-
- Derived state can depend on local context, or local context and global state at the same time.
-
- ```js
- const { state } = store( 'myCounterPlugin', {
- state: {
- get double() {
- const { counter } = getContext();
- // Depends on local context.
- return counter * 2;
- },
- get product() {
- const { counter } = getContext();
- // Depends on local context and global state.
- return counter * state.factor;
- },
- },
- } );
- ```
-
- In some cases, when the derived state depends on the local context and the local context can change dynamically in the server, instead of the initial derived state, you can use a function (Closure) that calculates it dynamically.
-
- ```php
- array( 1, 2, 3 ),
- 'factor' => 3,
- 'product' => function() {
- $state = wp_interactivity_state();
- $context = wp_interactivity_get_context();
- return $context['item'] * $state['factor'];
- }
- ));
- ?>
-
-
-
-
- ```
-
- This `data-wp-each` template will render this HTML (directives omitted):
-
- ```html
- 3
- 6
- 9
- ```
-
-- **Accessing the derived state**
-
- In the HTML markup, the syntax for the derived state is the same as the one for the global state, just by referencing `state` in the directive attribute values.
-
- ```html
-
- ```
-
- The same happens in JavaScript. Both global state and derived state can be consumed through the `state` property of the store:
-
- ```js
- const { state } = store( 'myCounterPlugin', {
- // ...
- actions: {
- readValues() {
- state.counter; // Regular state, returns 1.
- state.double; // Derived state, returns 2.
- },
- },
- } );
- ```
-
- This lack of distinction is intentional, allowing developers to consume both derived and global state uniformly, and making them interchangeable in practice.
-
- You can also access the derived state from another derived state and, thus, create multiple levels of computed values.
-
- ```js
- const { state } = store( 'myPlugin', {
- state: {
- get double() {
- return state.counter * 2;
- },
- get doublePlusOne() {
- return state.double + 1;
- },
- },
- } );
- ```
-
-- **Updating the derived state**
-
- The derived state cannot be updated directly. To update its values, you need to update the global state or local context on which that derived state depends.
-
- ```js
- const { state } = store( 'myCounterPlugin', {
- // ...
- actions: {
- updateValues() {
- state.counter; // Regular state, returns 1.
- state.double; // Derived state, returns 2.
-
- state.counter = 2;
-
- state.counter; // Regular state, returns 2.
- state.double; // Derived state, returns 4.
- },
- },
- } );
- ```
-
-### Example: Not using derived state vs using derived state
-
-Let's consider a scenario where there is a counter and the double value needs to be displayed, and let's compare two approaches: one without derived state and one with derived state.
-
-- **Not using derived state**
-
- ```js
- const { state } = store( 'myCounterPlugin', {
- state: {
- counter: 1,
- double: 2,
- },
- actions: {
- increment() {
- state.counter += 1;
- state.double = state.counter * 2;
- },
- },
- } );
- ```
-
- In this approach, both the `state.counter` and `state.double` values are manually updated in the `increment` action. While this works, it has several drawbacks:
-
- - It's less declarative.
- - It can lead to bugs if `state.counter` is updated from multiple places and developers forget to keep `state.double` in sync.
- - It requires more cognitive load to remember to update related values.
-
-- **Using derived state**
-
- ```js
- const { state } = store( 'myCounterPlugin', {
- state: {
- counter: 1,
- get double() {
- return state.counter * 2;
- },
- },
- actions: {
- increment() {
- state.counter += 1;
- },
- },
- } );
- ```
-
- In this improved version:
-
- - `state.double` is defined as a getter, automatically deriving its value from `state.counter`.
- - The `increment` action only needs to update `state.counter`.
- - `state.double` is always guaranteed to have the correct value, regardless of how or where `state.counter` is updated.
-
-### Example: Using derived state with local context
-
-Let's now consider a scenario where there is a local context that initializes a counter.
-
-```js
-store( 'myCounterPlugin', {
- state: {
- get double() {
- const { counter } = getContext();
- return counter * 2;
- },
- },
- actions: {
- increment() {
- const context = getContext();
- context.counter += 1;
- },
- },
-} );
-```
-
-```html
-
-
-
- Double:
-
-
-
-
-
-
-
- Double:
-
-
-
-
-
-```
-
-In this example, the derived state `state.double` reads from the local context present in each element and returns the correct value for each instance where it is used.
-
-### Example: Using derived state with both local context and global state
-
-Let's now consider a scenario where there is a global tax rate and local product prices and calculate the final price, including tax.
-
-```html
-
-
Product Price: $
-
Tax Rate:
-
Price (inc. tax): $
-
-```
-
-```js
-const { state } = store( 'myProductPlugin', {
- state: {
- taxRate: 0.21,
- get taxRatePercentage() {
- return `${ state.taxRate * 100 }%`;
- },
- get priceWithTax() {
- const { priceWithoutTax } = getContext();
- return price * ( 1 + state.taxRate );
- },
- },
- actions: {
- updateTaxRate( event ) {
- // Updates the global tax rate.
- state.taxRate = event.target.value;
- },
- updatePrice( event ) {
- // Updates the local product price.
- const context = getContext();
- context.priceWithoutTax = event.target.value;
- },
- },
-} );
-```
-
-In this example, `priceWithTax` is derived from both the global `taxRate` and the local `priceWithoutTax`. Every time you update the global state or local context through the `updateTaxRate` or `updatePrice` actions, the Interactivity API recomputes the derived state and updates the necessary parts of the DOM.
-
-By using derived state, you create a more maintainable and less error-prone codebase. It ensures that related state values are always in sync, reduces the complexity of your actions, and makes your code more declarative and easier to reason about.
-
-## Subscribing to Server State and Context
-
-Interactivity API offers a region-based navigation feature that dynamically replaces a part of the page without a full page reload. The [Query block](/docs/reference-guides/core-blocks.md#query-loop) natively supports this feature when the `Force page reload` toggle is disabled. Developers can use the same functionality in custom blocks by calling [`actions.navigate()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/#actions) from the [`@wordpress/interactivity-router`](https://github.com/WordPress/gutenberg/tree/trunk/packages/interactivity-router) script module.
-
-When using region-based navigation, it's crucial to ensure that your interactive blocks stay in sync with the server-provided global state and local context. By default, the Interactivity API will never overwrite the global state or local context with the server-provided values. The Interactivity API provides two functions to help manage this synchronization: [`getServerState()`](/docs/reference-guides/interactivity-api/api-reference.md#getserverstate) and [`getServerContext()`](/docs/reference-guides/interactivity-api/api-reference.md#getservercontext).
-
-### `getServerState()`
-
-`getServerState()` allows you to subscribe to changes in the **global state** that occur during client-side navigation. This function is analogous to `getServerContext()`, but it works with the global state instead of the local context.
-
-The `getServerState()` function returns a read-only reactive object. This means that any [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) you have defined that watch the returned object will only trigger when the value returned by the function changes. If the value remains the same, the callback will not re-trigger.
-
-Let's consider a quiz that has multiple questions. Each question is a separate page. When the user navigates to a new question, the server provides the new question and the time left to answer all the questions.
-
-```php
-
get_question_for_page( get_the_ID() ),
- 'timeLeft' => 5 * 60, // Time to answer all the questions.
-) ); ?>>
-```
-
-```javascript
-import { store, getServerState } from '@wordpress/interactivity';
-
-store( 'myPlugin', {
- actions: {
- // This action would be triggered by a directive, like:
- //
- *nextQuestion() {
- event.preventDefault( event );
- const { actions } = yield import(
- '@wordpress/interactivity-router'
- );
- actions.navigate( '/question-2' );
- },
- },
- callbacks: {
- // This callback would be triggered by a directive, like:
- //
- updateQuestion() {
- const serverState = getServerState();
-
- // Update with the new value coming from the server.
- // We DON'T want to update `timeLeft` because it represents the time left to answer ALL the questions.
- state.question = serverState.question;
- },
- },
-} );
-```
-
-### `getServerContext()`
-
-`getServerContext()` allows you to subscribe to changes in the **local context** that occur during client-side navigation. This function is analogous to `getServerState()`, but it works with the local context instead of the global state.
-
-The `getServerContext()` function returns a read-only reactive object. This means that any [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) you have defined that watch the returned object will only trigger when the value returned by the function changes. If the value remains the same, the callback will not re-trigger.
-
-Consider a quiz that has multiple questions. Each question is a separate page. When the user navigates to a new question, the server provides the new question and the time left to answer all the questions.
-
-```php
-
get_question_for_page( get_the_ID() ),
-), ); ?>>
-```
-
-```javascript
-import { store, getServerContext } from '@wordpress/interactivity';
-
-store( 'myPlugin', {
- actions: {
- // This action would be triggered by a directive, like:
- //
- *nextQuestion() {
- event.preventDefault( event );
- const { actions } = yield import(
- '@wordpress/interactivity-router'
- );
- actions.navigate( '/question-2' );
- },
- },
- callbacks: {
- // This callback would be triggered by a directive, like:
- //
- updateQuestion() {
- const serverContext = getServerContext();
- const context = getContext();
-
- // Update with the new value coming from the server.
- context.currentQuestion = serverContext.currentQuestion;
- },
- },
-} );
-```
-
-### When to Use
-
-Whenever you have interactive blocks that rely on global state or local context that may change due to navigation events, ensuring consistency across different parts of your application.
-
-### Best Practices for using `getServerState()` and `getServerContext()`
-
-- **Read-Only References:** Both `getServerState()` and `getServerContext()` return read-only objects. You can use those objects to update the global state or local context.
-- **Callback Integration:** Incorporate these functions within your store [callbacks](/docs/reference-guides/interactivity-api/api-reference.md#accessing-data-in-callbacks) to react to state and context changes. Both `getServerState()` and `getServerContext()` return reactive objects. This means that their watch callbacks will only trigger when the value of a property changes. If the value remains the same, the callback will not re-trigger.
-
-## Conclusion
-
-Remember, the key to effective state management is to keep your state minimal and avoid redundancy. Use derived state to compute values dynamically, and choose between global state and local context based on the scope and requirements of your data. This will lead to a cleaner, more robust architecture that is easier to debug and maintain. Finally, if you need to synchronize the state or context with the server, you can use `getServerState()` and `getServerContext()` to achieve this.
diff --git a/gutenberg/reference-guides/slotfills/README.md b/gutenberg/reference-guides/slotfills/README.md
deleted file mode 100644
index 874a3a6..0000000
--- a/gutenberg/reference-guides/slotfills/README.md
+++ /dev/null
@@ -1,369 +0,0 @@
-# SlotFills Reference
-
-Slot and Fill are components that have been exposed to allow developers to inject items into some predefined places in the Gutenberg admin experience.
-Please see the [SlotFill component docs](/packages/components/src/slot-fill/README.md) for more details.
-
-In order to use them, we must leverage the [@wordpress/plugins](/packages/plugins/README.md) api to register a plugin that will inject our items.
-
-## Usage overview
-
-In order to access the SlotFills, we need to do four things:
-
-1. Import the `registerPlugin` method from the `@wordpress/plugins` package.
-2. Import the SlotFill we want from the `@wordpress/editor'` package.
-3. Define a component to render our changes. Our changes/additions will be wrapped in the SlotFill component we imported.
-4. Register the plugin.
-
-Here is an example using the `PluginPostStatusInfo` slotFill:
-
-```js
-import { registerPlugin } from '@wordpress/plugins';
-import { PluginPostStatusInfo } from '@wordpress/editor';
-
-const PluginPostStatusInfoTest = () => (
-
-
Post Status Info SlotFill
-
-);
-
-registerPlugin( 'post-status-info-test', { render: PluginPostStatusInfoTest } );
-```
-
-## Conditionally rendering SlotFill content
-
-With the exception of [MainDashboardButton](/docs/reference-guides/slotfills/main-dashboard-button.md), every available SlotFill is exposed in both the Post Editor and Site Editor and any Fill that is registered will be rendered in both contexts. There are a number of approaches that can be implemented to conditionally render Fills.
-
-### Restricting fills to the Post Editor
-
-A fill can be restricted to the Post Editor by checking to see if the current post type object property `viewable` is set to `true`. Any post type not set to `viewable`, does not have an associated edit post screen and is a good indicator that the user is not in the Post Editor. The example below will render its content on the edit post screen for any registered post type.
-
-```js
-/**
- * WordPress dependencies
- */
-import { registerPlugin } from '@wordpress/plugins';
-import {
- PluginDocumentSettingPanel,
- store as editorStore,
-} from '@wordpress/editor';
-import { store as coreStore } from '@wordpress/core-data';
-import { useSelect } from '@wordpress/data';
-import { __ } from '@wordpress/i18n';
-
-/**
- * The component to be rendered as part of the plugin.
- */
-const EditPostDocumentSettingPanel = () => {
- // Retrieve information about the current post type.
- const isViewable = useSelect( ( select ) => {
- const postTypeName = select( editorStore ).getCurrentPostType();
- const postTypeObject = select( coreStore ).getPostType( postTypeName );
- return postTypeObject?.viewable;
- }, [] );
-
- // If the post type is not viewable, then do not render my the fill.
- if ( ! isViewable ) {
- return null;
- }
-
- return (
-
-
{ __( 'Only appears in the Edit Post screen' ) }
-
- );
-};
-
-registerPlugin( 'example-post-edit-only', {
- render: EditPostDocumentSettingPanel,
-} );
-```
-
-### Restricting fills to certain post types.
-
-The following example expands on the example above by creating an allow list of post types where the fill should be rendered. In this case, the fill is only rendered when editing pages.
-
-```js
-/**
- * WordPress dependencies
- */
-import { registerPlugin } from '@wordpress/plugins';
-import {
- PluginDocumentSettingPanel,
- store as editorStore,
-} from '@wordpress/editor';
-import { store as coreStore } from '@wordpress/core-data';
-import { useSelect } from '@wordpress/data';
-import { __, sprintf } from '@wordpress/i18n';
-
-/**
- * The component to be rendered as part of the plugin.
- */
-const RestrictPostTypes = () => {
- // Retrieve information about the current post type.
- const { isViewable, postTypeName } = useSelect( ( select ) => {
- const postType = select( editorStore ).getCurrentPostType();
- const postTypeObject = select( coreStore ).getPostType( postType );
- return {
- isViewable: postTypeObject?.viewable,
- postTypeName: postType,
- };
- }, [] );
-
- // The list of post types that are allowed to render the plugin.
- const allowedPostTypes = [ 'page' ];
-
- // If the post type is not viewable or not in the allowed list, do not render the plugin.
- if ( ! isViewable || ! allowedPostTypes.includes( postTypeName ) ) {
- return null;
- }
-
- return (
-
-
- { sprintf(
- __(
- 'Only appears on Post Types that are in the allowed list. %s'
- ),
- allowedPostTypes.join( ', ' )
- ) }
-
-
- );
-};
-
-registerPlugin( 'example-restrict-post-types', {
- render: RestrictPostTypes,
-} );
-```
-
-### Restricting fills to the Side Editor
-
-To restrict fills to the Site Editor, the reverse logic is true. If the post type object's `viewable` property is set to `true`, then the fill should not be rendered. The example below will render its content on any Site Editor screen.
-
-```js
-/**
- * WordPress dependencies
- */
-import { registerPlugin } from '@wordpress/plugins';
-import {
- PluginDocumentSettingPanel,
- store as editorStore,
-} from '@wordpress/editor';
-import { store as coreStore } from '@wordpress/core-data';
-import { useSelect } from '@wordpress/data';
-import { __ } from '@wordpress/i18n';
-
-/**
- * The component to be rendered as part of the plugin.
- */
-const SiteEditorDocumentSettingPanel = () => {
- // Retrieve information about the current post type.
- const isViewable = useSelect( ( select ) => {
- const postTypeName = select( editorStore ).getCurrentPostType();
- const postTypeObject = select( coreStore ).getPostType( postTypeName );
-
- // A viewable post type is one than can be viewed in the WordPress admin. Internal ones are not set to viewable.
- return postTypeObject?.viewable;
- }, [] );
-
- // If the post type is viewable, do not render my fill
- if ( isViewable ) {
- return null;
- }
-
- return (
-
-
{ __( 'Only appears in the Site Editor' ) }
-
- );
-};
-
-registerPlugin( 'example-site-editor', {
- render: SiteEditorDocumentSettingPanel,
-} );
-```
-
-### Restricting fills to certain screens in the Site Editor.
-
-This example builds on the example above by providing an allow list to control which screens a fill can be rendered within the Site Editor.
-
-```js
-/**
- * WordPress dependencies
- */
-import { registerPlugin } from '@wordpress/plugins';
-import {
- PluginDocumentSettingPanel,
- store as editorStore,
-} from '@wordpress/editor';
-import { store as coreStore } from '@wordpress/core-data';
-import { useSelect } from '@wordpress/data';
-import { __, sprintf } from '@wordpress/i18n';
-
-/**
- * The component to be rendered as part of the plugin.
- */
-const SiteEditorDocumentSettingPanel = () => {
- // Allowed areas in the Site Editor.
- const allowedSiteEditorScreens = [
- 'wp_template', // Templates
- 'wp_block', // Patterns
- 'wp_template_part', // Template Parts
- ];
-
- const { isViewable, postType } = useSelect( ( select ) => {
- const postTypeName = select( editorStore ).getCurrentPostType();
- const postTypeObject = select( coreStore ).getPostType( postTypeName );
-
- return {
- // A viewable post type is one than can be viewed in the WordPress admin. Internal ones are not set to viewable.
- isViewable: postTypeObject?.viewable,
- postType: postTypeName,
- };
- }, [] );
-
- // If the post type is viewable, do not render my plugin.
- if ( isViewable || ! allowedSiteEditorScreens.includes( postType ) ) {
- return null;
- }
-
- return (
-
-
- { sprintf(
- __(
- 'Only appears on Editor Screens that are in the allowed list. %s'
- ),
- allowedSiteEditorScreens.join( ', ' )
- ) }
-
-
- );
-};
-
-registerPlugin( 'example-site-editor-only', {
- render: SiteEditorDocumentSettingPanel,
-} );
-```
-
-## How do they work?
-
-SlotFills are created using `createSlotFill`. This creates two components, `Slot` and `Fill` which are then used to create a new component that is exported on the `wp.plugins` global.
-
-**Definition of the `PluginPostStatusInfo` SlotFill** ([see core code](https://github.com/WordPress/gutenberg/blob/HEAD/packages/editor/src/components/plugin-post-status-info/index.js#L55))
-
-```js
-/**
- * Defines as extensibility slot for the Summary panel.
- */
-
-/**
- * WordPress dependencies
- */
-import { createSlotFill, PanelRow } from '@wordpress/components';
-
-export const { Fill, Slot } = createSlotFill( 'PluginPostStatusInfo' );
-
-const PluginPostStatusInfo = ( { children, className } ) => (
-
- { children }
-
-);
-
-PluginPostStatusInfo.Slot = Slot;
-
-export default PluginPostStatusInfo;
-```
-
-This new Slot is then exposed in the editor. The example below is from core and represents the Summary panel.
-
-As we can see, the `` is wrapping all of the items that will appear in the panel.
-Any items that have been added via the SlotFill ( see the example above ), will be included in the `fills` parameter and be displayed in the end of the component.
-
-See [core code](https://github.com/WordPress/gutenberg/tree/HEAD/packages/editor/src/components/sidebar/post-summary.js#L39).
-
-```js
-export default function PostSummary( { onActionPerformed } ) {
- const { isRemovedPostStatusPanel } = useSelect( ( select ) => {
- // We use isEditorPanelRemoved to hide the panel if it was programmatically removed. We do
- // not use isEditorPanelEnabled since this panel should not be disabled through the UI.
- const { isEditorPanelRemoved } = select( editorStore );
- return {
- isRemovedPostStatusPanel: isEditorPanelRemoved( PANEL_NAME ),
- };
- }, [] );
-
- return (
-
-
- { ( fills ) => (
- <>
-
-
-
-
-
-
-
-
- { ! isRemovedPostStatusPanel && (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- { fills }
-
- ) }
-
- >
- ) }
-
-
- );
-}
-```
-
-## Currently available SlotFills and examples
-
-The following SlotFills are available in the `edit-post` or `editor` packages. Please refer to the individual items below for usage and example details:
-
-- [MainDashboardButton](/docs/reference-guides/slotfills/main-dashboard-button.md)
-- [PluginBlockSettingsMenuItem](/docs/reference-guides/slotfills/plugin-block-settings-menu-item.md)
-- [PluginDocumentSettingPanel](/docs/reference-guides/slotfills/plugin-document-setting-panel.md)
-- [PluginMoreMenuItem](/docs/reference-guides/slotfills/plugin-more-menu-item.md)
-- [PluginPostPublishPanel](/docs/reference-guides/slotfills/plugin-post-publish-panel.md)
-- [PluginPostStatusInfo](/docs/reference-guides/slotfills/plugin-post-status-info.md)
-- [PluginPrePublishPanel](/docs/reference-guides/slotfills/plugin-pre-publish-panel.md)
-- [PluginSidebar](/docs/reference-guides/slotfills/plugin-sidebar.md)
-- [PluginSidebarMoreMenuItem](/docs/reference-guides/slotfills/plugin-sidebar-more-menu-item.md)
diff --git a/gutenberg/reference-guides/slotfills/plugin-document-setting-panel.md b/gutenberg/reference-guides/slotfills/plugin-document-setting-panel.md
deleted file mode 100644
index aa3e55a..0000000
--- a/gutenberg/reference-guides/slotfills/plugin-document-setting-panel.md
+++ /dev/null
@@ -1,100 +0,0 @@
-# PluginDocumentSettingPanel
-
-This SlotFill allows registering a UI to edit Document settings.
-
-## Available Props
-
-- **name** `string`: A string identifying the panel.
-- **className** `string`: An optional class name added to the sidebar body.
-- **title** `string`: Title displayed at the top of the sidebar.
-- **icon** `(string|Element)`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element.
-
-## Example
-
-```js
-import { registerPlugin } from '@wordpress/plugins';
-import { PluginDocumentSettingPanel } from '@wordpress/editor';
-
-const PluginDocumentSettingPanelDemo = () => (
-
- Custom Panel Contents
-
-);
-
-registerPlugin( 'plugin-document-setting-panel-demo', {
- render: PluginDocumentSettingPanelDemo,
- icon: 'palmtree',
-} );
-```
-
-## Accessing a panel programmatically
-
-Core and custom panels can be accessed programmatically using their panel name. The core panel names are:
-
-- Summary Panel: `post-status`
-- Categories Panel: `taxonomy-panel-category`
-- Tags Panel: `taxonomy-panel-post_tag`
-- Featured Image Panel: `featured-image`
-- Excerpt Panel: `post-excerpt`
-- DiscussionPanel: `discussion-panel`
-
-Custom panels are namespaced with the plugin name that was passed to `registerPlugin`.
-In order to access the panels using function such as `toggleEditorPanelOpened` or `toggleEditorPanelEnabled` be sure to prepend the namespace.
-
-To programmatically toggle panels, use the following:
-
-```js
-import { useDispatch } from '@wordpress/data';
-import { store as editorStore } from '@wordpress/editor';
-
-const Example = () => {
- const { toggleEditorPanelOpened } = useDispatch( editorStore );
- return (
-
- );
-};
-```
-
-It is also possible to remove panels from the admin using the `removeEditorPanel` function by passing the name of the registered panel.
-
-```js
-import { useDispatch } from '@wordpress/data';
-import { store as editorStore } from '@wordpress/editor';
-
-const Example = () => {
- const { removeEditorPanel } = useDispatch( editorStore );
- return (
-
- );
-};
-```
diff --git a/gutenberg/reference-guides/slotfills/plugin-sidebar-more-menu-item.md b/gutenberg/reference-guides/slotfills/plugin-sidebar-more-menu-item.md
deleted file mode 100644
index 1a1b254..0000000
--- a/gutenberg/reference-guides/slotfills/plugin-sidebar-more-menu-item.md
+++ /dev/null
@@ -1,80 +0,0 @@
-# PluginSidebarMoreMenuItem
-
-This slot is used to allow the opening of a `` panel from the Options dropdown.
-When a `` is registered, a `` is automatically registered using the title prop from the `` and so it's not required to use this slot to create the menu item.
-
-## Example
-
-This example shows how customize the text for the menu item instead of using the default text provided by the `` title.
-
-```js
-import { __ } from '@wordpress/i18n';
-import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/editor';
-import {
- PanelBody,
- Button,
- TextControl,
- SelectControl,
-} from '@wordpress/components';
-import { registerPlugin } from '@wordpress/plugins';
-import { useState } from '@wordpress/element';
-import { image } from '@wordpress/icons';
-
-const PluginSidebarMoreMenuItemTest = () => {
- const [ text, setText ] = useState( '' );
- const [ select, setSelect ] = useState( 'a' );
- return (
- <>
-
- { __( 'Custom Menu Item Text' ) }
-
-
-
-
- { __(
- 'This is a heading for the PluginSidebar example.'
- ) }
-
-
- { __(
- 'This is some example text for the PluginSidebar example.'
- ) }
-
- setText( newText ) }
- />
- setSelect( newSelect ) }
- />
-
-
-
- >
- );
-};
-
-registerPlugin( 'plugin-sidebar-more-menu-item-example', {
- render: PluginSidebarMoreMenuItemTest,
-} );
-```
-
-## Location
-
-
diff --git a/gutenberg/reference-guides/slotfills/plugin-sidebar.md b/gutenberg/reference-guides/slotfills/plugin-sidebar.md
deleted file mode 100644
index 7191b80..0000000
--- a/gutenberg/reference-guides/slotfills/plugin-sidebar.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# PluginSidebar
-
-This slot allows adding items to the tool bar of either the Post or Site editor screens.
-Using this slot will add an icon to the toolbar that, when clicked, opens a panel with containing the items wrapped in the `` component.
-Additionally, it will also create a `` that will allow opening the panel from Options panel when clicked.
-
-## Example
-
-```jsx
-import { __ } from '@wordpress/i18n';
-import { PluginSidebar } from '@wordpress/editor';
-import {
- PanelBody,
- Button,
- TextControl,
- SelectControl,
-} from '@wordpress/components';
-import { registerPlugin } from '@wordpress/plugins';
-import { useState } from '@wordpress/element';
-
-const PluginSidebarExample = () => {
- const [ text, setText ] = useState( '' );
- const [ select, setSelect ] = useState( 'a' );
-
- return (
-
-
-
- { __( 'This is a heading for the PluginSidebar example.' ) }
-
-
- { __(
- 'This is some example text for the PluginSidebar example.'
- ) }
-
- setText( newText ) }
- />
- setSelect( newSelect ) }
- />
-
-
-
- );
-};
-
-// Register the plugin.
-registerPlugin( 'plugin-sidebar-example', { render: PluginSidebarExample } );
-```
-
-## Location
-
-
diff --git a/gutenberg/reference-guides/theme-json-reference/README.md b/gutenberg/reference-guides/theme-json-reference/README.md
deleted file mode 100644
index 9f53a09..0000000
--- a/gutenberg/reference-guides/theme-json-reference/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Theme.json Reference
-
-This reference guide lists the settings and style properties defined in the theme.json schema. See the [theme.json how to guide](/docs/how-to-guides/themes/global-settings-and-styles.md) for examples and guide on how to use the theme.json file in your theme.
-
-- [Version 3 (latest)](/docs/reference-guides/theme-json-reference/theme-json-living.md)
-
-## Older versions
-
-- [Migrating to Newer Theme.json Versions](/docs/reference-guides/theme-json-reference/theme-json-migrations.md)
-- [Version 1](/docs/reference-guides/theme-json-reference/theme-json-v1.md)
-- [Version 2](/docs/reference-guides/theme-json-reference/theme-json-v2.md)
diff --git a/gutenberg/reference-guides/theme-json-reference/styles-versions.md b/gutenberg/reference-guides/theme-json-reference/styles-versions.md
deleted file mode 100644
index 0cbffdc..0000000
--- a/gutenberg/reference-guides/theme-json-reference/styles-versions.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Available Styles Options
-
-New styles options are integrated into theme.json on a regular basis. Knowing the style options available through theme.json or the styles editor at any given time can be challenging. To clarify, the table below indicates the WordPress version when each theme.json styles option became available and when a corresponding control was added to the user interface to allow management of the style from the Styles editor.
-
-## Styles keys
-
-| Key | theme.json Since| Style Editor Since |
-| --- | :---: | :---: |
-| `color.gradient` | 5.8 | 5.9 |
-| `color.background` | 5.8 | 5.9 |
-| `color.text` | 5.8 | 5.9 |
-| `border.color` | 5.9 | 5.9 |
-| `border.width` | 5.9 | 5.9 |
-| `border.style` | 5.9 | 5.9 |
-| `border.radius` | 5.8 | 5.9 |
-| `border.radius.topLeft` | 5.9 | 5.9 |
-| `border.radius.topRight` | 5.9 | 5.9 |
-| `border.radius.bottomLeft` | 5.9 | 5.9 |
-| `border.radius.bottomRight` | 5.9 | 5.9 |
-| `border.top.color` | 6.1 | 6.1 |
-| `border.top.width` | 6.1 | 6.1 |
-| `border.top.style` | 6.1 | 6.1 |
-| `border.right.color` | 6.1 | 6.1 |
-| `border.right.width` | 6.1 | 6.1 |
-| `border.right.style` | 6.1 | 6.1 |
-| `border.bottom.color` | 6.1 | 6.1 |
-| `border.bottom.width` | 6.1 | 6.1 |
-| `border.bottom.style` | 6.1 | 6.1 |
-| `border.left.color` | 6.1 | 6.1 |
-| `border.left.width` | 6.1 | 6.1 |
-| `border.left.style` | 6.1 | 6.1 |
-| `typography.fontFamily` | 5.9 | 5.9 |
-| `typography.fontSize` | 5.8 | 5.9 |
-| `typography.fontStyle` | 5.9 | 5.9 |
-| `typography.fontWeight` | 5.9 | 5.9 |
-| `typography.letterSpacing` | 5.9 | 5.9 |
-| `typography.lineHeight` | 5.8 | 5.9 |
-| `typography.textDecoration` | 5.9 | 6.2 |
-| `typography.textTransform` | 5.9 | 6.0 |
-| `spacing.padding` | 5.9 | 5.9 |
-| `spacing.padding.top` | 5.8 | 5.9 |
-| `spacing.padding.right` | 5.8 | 5.9 |
-| `spacing.padding.left` | 5.8 | 5.9 |
-| `spacing.padding.bottom` | 5.8 | 5.9 |
-| `spacing.margin` | 5.9 | 5.9 |
-| `spacing.margin.top` | 5.8 | 5.9 |
-| `spacing.margin.right` | 5.8 | 5.9 |
-| `spacing.margin.left` | 5.8 | 5.9 |
-| `spacing.margin.bottom` | 5.8 | 5.9 |
-| `spacing.blockGap` | 5.9 | 5.9 |
-| `dimensions.minHeight` | 6.2 | N/A |
-| `outline.color` | 6.2 | N/A |
-| `outline.offset` | 6.2 | N/A |
-| `outline.style` | 6.2 | N/A |
-| `outline.width` | 6.2 | N/A |
-| `filter.duotone` | 5.9 | N/A |
-| `shadow` | 6.1 | 6.2 |
diff --git a/gutenberg/reference-guides/theme-json-reference/theme-json-living.md b/gutenberg/reference-guides/theme-json-reference/theme-json-living.md
deleted file mode 100644
index 138e32f..0000000
--- a/gutenberg/reference-guides/theme-json-reference/theme-json-living.md
+++ /dev/null
@@ -1,361 +0,0 @@
-# Theme.json Version 3 Reference (latest)
-
-> This is the living specification for **version 3** of `theme.json`. This version works with WordPress 6.6 or later, and the latest Gutenberg plugin.
->
-> There are some related documents that you may be interested in:
-> - the [theme.json v1](/docs/reference-guides/theme-json-reference/theme-json-v1.md) specification,
-> - the [theme.json v2](/docs/reference-guides/theme-json-reference/theme-json-v2.md) specification, and
-> - the [reference to migrate from older theme.json versions](/docs/reference-guides/theme-json-reference/theme-json-migrations.md).
-
-This reference guide lists the settings and style properties defined in the `theme.json` schema. See the [theme.json how to guide](/docs/how-to-guides/themes/global-settings-and-styles.md) for examples and guidance on how to use the `theme.json` file in your theme.
-
-## JSON Schema
-
-This documentation was generated from the JSON schema for theme.json.
-
-The latest schema for version 3, including all the latest changes from the Gutenberg plugin, is available at https://schemas.wp.org/trunk/theme.json.
-
-Theme.json schemas for each WordPress version are available at https://schemas.wp.org/wp/{{version}}/theme.json.
-For example, a schema for WordPress 5.8 is available at https://schemas.wp.org/wp/5.8/theme.json.
-
-See [Developing with theme.json](/docs/how-to-guides/themes/global-settings-and-styles.md#developing-with-themejson) for how to use the JSON schema in your editor.
-
-
-## settings
-
-Settings for the block editor and individual blocks. These include things like:
-- Which customization options should be available to the user.
-- The default colors, font sizes... available to the user.
-- CSS custom properties and class names used in styles.
-- And the default layout of the editor (widths and available alignments).
-
-### useRootPaddingAwareAlignments
-
-Enables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block.
-
-Please note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately.
-
-**Note:** Top-level only property. Not available in blocks.
-
----
-
-### appearanceTools
-
-Setting that enables the following UI tools:
-
-- background: backgroundImage, backgroundSize
-- border: color, radius, style, width
-- color: link, heading, button, caption
-- dimensions: aspectRatio, minHeight
-- position: sticky
-- spacing: blockGap, margin, padding
-- typography: lineHeight
-
----
-
-### background
-
-Settings related to background.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| backgroundImage | Allow users to set a background image. | `boolean` | `false` |
-| backgroundSize | Allow users to set values related to the size of a background image, including size, position, and repeat controls. | `boolean` | `false` |
-
----
-
-### border
-
-Settings related to borders.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| color | Allow users to set custom border colors. | `boolean` | `false` |
-| radius | Allow users to set custom border radius. | `boolean` | `false` |
-| style | Allow users to set custom border styles. | `boolean` | `false` |
-| width | Allow users to set custom border widths. | `boolean` | `false` |
-| radiusSizes | Border radius size presets for the border radius selector. | `[ { name, slug, size } ]` | |
-
----
-
-### color
-
-Settings related to colors.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| background | Allow users to set background colors. | `boolean` | `true` |
-| custom | Allow users to select custom colors. | `boolean` | `true` |
-| customDuotone | Allow users to create custom duotone filters. | `boolean` | `true` |
-| customGradient | Allow users to create custom gradients. | `boolean` | `true` |
-| defaultDuotone | Allow users to choose filters from the default duotone filter presets. | `boolean` | `true` |
-| defaultGradients | Allow users to choose colors from the default gradients. | `boolean` | `true` |
-| defaultPalette | Allow users to choose colors from the default palette. | `boolean` | `true` |
-| duotone | Duotone presets for the duotone picker. | `[ { name, slug, colors } ]` | |
-| gradients | Gradient presets for the gradient picker. | `[ { name, slug, gradient } ]` | |
-| link | Allow users to set link colors in a block. | `boolean` | `false` |
-| palette | Color palette presets for the color picker. | `[ { name, slug, color } ]` | |
-| text | Allow users to set text colors in a block. | `boolean` | `true` |
-| heading | Allow users to set heading colors in a block. | `boolean` | `true` |
-| button | Allow users to set button colors in a block. | `boolean` | `true` |
-| caption | Allow users to set caption colors in a block. | `boolean` | `true` |
-
----
-
-### dimensions
-
-Settings related to dimensions.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| aspectRatio | Allow users to set an aspect ratio. | `boolean` | `false` |
-| defaultAspectRatios | Allow users to choose aspect ratios from the default set of aspect ratios. | `boolean` | `true` |
-| aspectRatios | Allow users to define aspect ratios for some blocks. | `[ { name, slug, ratio } ]` | |
-| minHeight | Allow users to set custom minimum height. | `boolean` | `false` |
-
----
-
-### layout
-
-Settings related to layout.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| contentSize | Sets the max-width of the content. | `string` | |
-| wideSize | Sets the max-width of wide (`.alignwide`) content. Also used as the maximum viewport when calculating fluid font sizes | `string` | |
-| allowEditing | Disable the layout UI controls. | `boolean` | `true` |
-| allowCustomContentAndWideSize | Enable or disable the custom content and wide size controls. | `boolean` | `true` |
-
----
-
-### lightbox
-
-Settings related to the lightbox.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| enabled | Defines whether the lightbox is enabled or not. | `boolean` | |
-| allowEditing | Defines whether to show the Lightbox UI in the block editor. If set to `false`, the user won't be able to change the lightbox settings in the block editor. | `boolean` | |
-
----
-
-### position
-
-Settings related to position.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| sticky | Allow users to set sticky position. | `boolean` | `false` |
-
----
-
-### shadow
-
-Settings related to shadows.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| defaultPresets | Allow users to choose shadows from the default shadow presets. | `boolean` | `true` |
-| presets | Shadow presets for the shadow picker. | `[ { name, slug, shadow } ]` | |
-
----
-
-### spacing
-
-Settings related to spacing.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| blockGap | Enables `--wp--style--block-gap` to be generated from styles.spacing.blockGap. | `boolean`, `null` | `null` |
-| margin | Allow users to set a custom margin. | `boolean` | `false` |
-| padding | Allow users to set a custom padding. | `boolean` | `false` |
-| units | List of units the user can use for spacing values. | `[ string ]` | `["px","em","rem","vh","vw","%"]` |
-| customSpacingSize | Allow users to set custom space sizes. | `boolean` | `true` |
-| defaultSpacingSizes | Allow users to choose space sizes from the default space size presets. | `boolean` | `true` |
-| spacingSizes | Space size presets for the space size selector. | `[ { name, slug, size } ]` | |
-| spacingScale | Settings to auto-generate space size presets for the space size selector. | `{ operator, increment, steps, mediumStep, unit }` | |
-
----
-
-### typography
-
-Settings related to typography.
-
-| Property | Description | Type | Default |
-| -------- | ----------- | ---- | ------- |
-| defaultFontSizes | Allow users to choose font sizes from the default font size presets. | `boolean` | `true` |
-| customFontSize | Allow users to set custom font sizes. | `boolean` | `true` |
-| fontStyle | Allow users to set custom font styles. | `boolean` | `true` |
-| fontWeight | Allow users to set custom font weights. | `boolean` | `true` |
-| fluid | Enables fluid typography and allows users to set global fluid typography parameters. | `boolean`, `{ minFontSize, maxViewportWidth, minViewportWidth }` | `false` |
-| letterSpacing | Allow users to set custom letter spacing. | `boolean` | `true` |
-| lineHeight | Allow users to set custom line height. | `boolean` | `false` |
-| textAlign | Allow users to set the text align. | `boolean` | `true` |
-| textColumns | Allow users to set the number of text columns. | `boolean` | `false` |
-| textDecoration | Allow users to set custom text decorations. | `boolean` | `true` |
-| writingMode | Allow users to set the writing mode. | `boolean` | `false` |
-| textTransform | Allow users to set custom text transforms. | `boolean` | `true` |
-| dropCap | Enable drop cap. | `boolean` | `true` |
-| fontSizes | Font size presets for the font size selector. | `[ { name, slug, size, fluid } ]` | |
-| fontFamilies | Font family presets for the font family selector. | `[ { name, slug, fontFamily, fontFace } ]` | |
-
----
-
-### custom
-
-Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name.
-
----
-
-## styles
-
-Organized way to set CSS properties. Styles in the top-level will be added in the `body` selector.
-
-### background
-
-Background styles.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| backgroundImage | Sets the `background-image` CSS property. | `string`, `{ ref }`, `{ url }` |
-| backgroundPosition | Sets the `background-position` CSS property. | `string`, `{ ref }` |
-| backgroundRepeat | Sets the `background-repeat` CSS property. | `string`, `{ ref }` |
-| backgroundSize | Sets the `background-size` CSS property. | `string`, `{ ref }` |
-| backgroundAttachment | Sets the `background-attachment` CSS property. | `string`, `{ ref }` |
-
----
-
-### border
-
-Border styles.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| color | Sets the `border-color` CSS property. | `string`, `{ ref }` |
-| radius | Sets the `border-radius` CSS property. | `string`, `{ ref }`, `{ topLeft, topRight, bottomLeft, bottomRight }` |
-| style | Sets the `border-style` CSS property. | `string`, `{ ref }` |
-| width | Sets the `border-width` CSS property. | `string`, `{ ref }` |
-| top | | `{ color, style, width }` |
-| right | | `{ color, style, width }` |
-| bottom | | `{ color, style, width }` |
-| left | | `{ color, style, width }` |
-
----
-
-### color
-
-Color styles.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| background | Sets the `background-color` CSS property. | `string`, `{ ref }` |
-| gradient | Sets the `background` CSS property. | `string`, `{ ref }` |
-| text | Sets the `color` CSS property. | `string`, `{ ref }` |
-
----
-
-### css
-
-Sets custom CSS to apply styling not covered by other theme.json properties.
-
----
-
-### dimensions
-
-Dimensions styles.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| aspectRatio | Sets the `aspect-ratio` CSS property. | `string`, `{ ref }` |
-| minHeight | Sets the `min-height` CSS property. | `string`, `{ ref }` |
-
----
-
-### filter
-
-CSS and SVG filter styles.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| duotone | Sets the duotone filter. | `string`, `{ ref }` |
-
----
-
-### outline
-
-Outline styles.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| color | Sets the `outline-color` CSS property. | `string`, `{ ref }` |
-| offset | Sets the `outline-offset` CSS property. | `string`, `{ ref }` |
-| style | Sets the `outline-style` CSS property. | `string`, `{ ref }` |
-| width | Sets the `outline-width` CSS property. | `string`, `{ ref }` |
-
----
-
-### shadow
-
-Box shadow styles.
-
----
-
-### spacing
-
-Spacing styles.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| blockGap | Sets the `--wp--style--block-gap` CSS custom property when settings.spacing.blockGap is true. | `string`, `{ ref }` |
-| margin | Margin styles. | `{ top, right, bottom, left }` |
-| padding | Padding styles. | `{ top, right, bottom, left }` |
-
----
-
-### typography
-
-Typography styles.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| fontFamily | Sets the `font-family` CSS property. | `string`, `{ ref }` |
-| fontSize | Sets the `font-size` CSS property. | `string`, `{ ref }` |
-| fontStyle | Sets the `font-style` CSS property. | `string`, `{ ref }` |
-| fontWeight | Sets the `font-weight` CSS property. | `string`, `{ ref }` |
-| letterSpacing | Sets the `letter-spacing` CSS property. | `string`, `{ ref }` |
-| lineHeight | Sets the `line-height` CSS property. | `string`, `{ ref }` |
-| textAlign | Sets the `text-align` CSS property. | `string`, `{ ref }` |
-| textColumns | Sets the `column-count` CSS property. | `string`, `{ ref }` |
-| textDecoration | Sets the `text-decoration` CSS property. | `string`, `{ ref }` |
-| writingMode | Sets the `writing-mode` CSS property. | `string`, `{ ref }` |
-| textTransform | Sets the `text-transform` CSS property. | `string`, `{ ref }` |
-
----
-
-## customTemplates
-
-Additional metadata for custom templates defined in the templates folder.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| name | Filename, without extension, of the template in the templates folder. | `string` |
-| title | Title of the template, translatable. | `string` |
-| postTypes | List of post types that can use this custom template. | `[ string ]` |
-
-## templateParts
-
-Additional metadata for template parts defined in the parts folder.
-
-| Property | Description | Type |
-| -------- | ----------- | ---- |
-| name | Filename, without extension, of the template in the parts folder. | `string` |
-| title | Title of the template, translatable. | `string` |
-| area | The area the template part is used for. Block variations for `header` and `footer` values exist and will be used when the area is set to one of those. | `string` |
-
-## patterns
-
-An array of pattern slugs to be registered from the Pattern Directory.
-
-Type: `[ string ]`.
-
-
diff --git a/gutenberg/schemas/json/block.json b/gutenberg/schemas/json/block.json
deleted file mode 100644
index 0c40d08..0000000
--- a/gutenberg/schemas/json/block.json
+++ /dev/null
@@ -1,1000 +0,0 @@
-{
- "title": "JSON schema for WordPress blocks",
- "$schema": "http://json-schema.org/draft-07/schema#",
- "definitions": {
- "//": {
- "reference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/",
- "attributesReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/",
- "contextReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/",
- "supportsReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/",
- "registerReference": "https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#example-optional"
- }
- },
- "type": "object",
- "properties": {
- "$schema": {
- "type": "string"
- },
- "apiVersion": {
- "description": "The version of the Block API used by the block. If the block is registered with API version 2 or lower, the post editor may work as a non-iframe editor. Since all editors are planned to work as iframes in the future, it is recommended to set the `apiVersion` field to 3 and test the block inside the iframe editor.\n\nSee the API versions documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-api-versions/ for more details.",
- "type": "integer",
- "const": 3
- },
- "name": {
- "description": "The name for a block is a unique string that identifies a block. Names have to be structured as `namespace/block-name`, where namespace is the name of your plugin or theme.",
- "type": "string",
- "pattern": "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$"
- },
- "__experimental": {
- "description": "The name of the experiment this block is a part of, or boolean true if there is no specific experiment name.",
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "boolean"
- }
- ]
- },
- "title": {
- "description": "This is the display title for your block, which can be translated with our translation functions. The block inserter will show this name.",
- "type": "string"
- },
- "category": {
- "description": "Blocks are grouped into categories to help users browse and discover them.\n Core provided categories are: text, media, design, widgets, theme, embed\n\nPlugins and Themes can also register custom block categories.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/#managing-block-categories",
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "string",
- "enum": [
- "text",
- "media",
- "design",
- "widgets",
- "theme",
- "embed"
- ]
- }
- ]
- },
- "parent": {
- "description": "Setting parent lets a block require that it is only available when nested within the specified blocks. For example, you might want to allow an ‘Add to Cart’ block to only be available within a ‘Product’ block.",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "ancestor": {
- "description": "The `ancestor` property makes a block available inside the specified block types at any position of the ancestor block subtree. That allows, for example, to place a ‘Comment Content’ block inside a ‘Column’ block, as long as ‘Column’ is somewhere within a ‘Comment Template’ block.",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "allowedBlocks": {
- "description": "The `allowedBlocks` property specifies that only the listed block types can be the children of this block. For example, a ‘List’ block allows only ‘List Item’ blocks as direct children.",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "icon": {
- "description": "An icon property should be specified to make it easier to identify a block. These can be any of WordPress’ Dashicons (slug serving also as a fallback in non-js contexts).",
- "type": "string"
- },
- "description": {
- "description": "This is a short description for your block, which can be translated with our translation functions. This will be shown in the block inspector.",
- "type": "string"
- },
- "keywords": {
- "description": "Sometimes a block could have aliases that help users discover it while searching. For example, an image block could also want to be discovered by photo. You can do so by providing an array of unlimited terms (which are translated).",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "version": {
- "description": "The current version number of the block, such as 1.0 or 1.0.3. It’s similar to how plugins are versioned. This field might be used with block assets to control cache invalidation, and when the block author omits it, then the installed version of WordPress is used instead.",
- "type": "string"
- },
- "textdomain": {
- "description": "The gettext text domain of the plugin/block. More information can be found in the Text Domain section of the How to Internationalize your Plugin page.\n\nhttps://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/",
- "type": "string"
- },
- "attributes": {
- "description": "Attributes provide the structured data needs of a block. They can exist in different forms when they are serialized, but they are declared together under a common interface.\n\nSee the attributes documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/ for more details.",
- "type": "object",
- "patternProperties": {
- "[a-zA-Z]": {
- "type": "object",
- "properties": {
- "type": {
- "description": "The type indicates the type of data that is stored by the attribute. It does not indicate where the data is stored, which is defined by the source field.\n\nA type is required, unless an enum is provided. A type can be used with an enum.\n\nNote that the validity of an object is determined by your source. For an example, see the query details below.",
- "oneOf": [
- {
- "type": "string",
- "enum": [
- "null",
- "boolean",
- "object",
- "array",
- "string",
- "rich-text",
- "integer",
- "number"
- ]
- },
- {
- "type": "array",
- "uniqueItems": true,
- "items": {
- "type": "string",
- "enum": [
- "null",
- "boolean",
- "object",
- "array",
- "string",
- "integer",
- "number"
- ]
- }
- }
- ]
- },
- "enum": {
- "description": "An attribute can be defined as one of a fixed set of values. This is specified by an enum, which contains an array of allowed values:",
- "type": "array",
- "items": {
- "oneOf": [
- { "type": "boolean" },
- { "type": "number" },
- { "type": "string" }
- ]
- }
- },
- "source": {
- "description": "Attribute sources are used to define how the attribute values are extracted from saved post content. They provide a mechanism to map from the saved markup to a JavaScript representation of a block.",
- "type": "string",
- "enum": [
- "attribute",
- "text",
- "rich-text",
- "html",
- "raw",
- "query",
- "meta"
- ]
- },
- "selector": {
- "description": "The selector can be an HTML tag, or anything queryable with querySelector, such as a class or id attribute. Examples are given below.\n\nFor example, a selector of img will match an img element, and img.class will match an img element that has a class of class.",
- "type": "string"
- },
- "attribute": {
- "description": "Use an attribute source to extract the value from an attribute in the markup. The attribute is specified by the attribute field, which must be supplied.\n\nExample: Extract the src attribute from an image found in the block’s markup.",
- "type": "string"
- },
- "query": {
- "description": "Use query to extract an array of values from markup. Entries of the array are determined by the selector argument, where each matched element within the block will have an entry structured corresponding to the second argument, an object of attribute sources.",
- "type": "object"
- },
- "meta": {
- "description": "Although attributes may be obtained from a post’s meta, meta attribute sources are considered deprecated; EntityProvider and related hook APIs should be used instead, as shown in the Create Meta Block how-to here:\n\nhttps://developer.wordpress.org/block-editor/how-to-guides/metabox/#step-2-add-meta-block",
- "type": "string"
- },
- "role": {
- "description": "Designates the conceptual type of the attribute.\n\nThe `content` value marks the attribute as user-editable content, and the `local` value marks the attribute as temporary and non-persistable.",
- "type": "string",
- "enum": [ "content", "local" ]
- },
- "default": {
- "description": "A block attribute can contain a default value, which will be used if the type and source do not match anything within the block content.\n\nThe value is provided by the default field, and the value should match the expected format of the attribute."
- }
- },
- "anyOf": [
- { "required": [ "type" ] },
- { "required": [ "enum" ] }
- ]
- }
- },
- "additionalProperties": false
- },
- "providesContext": {
- "description": "Context provided for available access by descendants of blocks of this type, in the form of an object which maps a context name to one of the block’s own attribute.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.",
- "type": "object",
- "patternProperties": {
- "[a-zA-Z]": {
- "type": "string"
- }
- }
- },
- "usesContext": {
- "description": "Array of the names of context values to inherit from an ancestor provider.\n\nSee the block context documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/ for more details.",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "supports": {
- "description": "It contains as set of options to control features used in the editor. See the supports documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/ for more details.",
- "type": "object",
- "properties": {
- "anchor": {
- "description": "Anchors let you link directly to a specific block on a page. This property adds a field to define an id for the block and a button to copy the direct link.",
- "type": "boolean",
- "default": false
- },
- "align": {
- "description": "This property adds block controls which allow to change block’s alignment.",
- "oneOf": [
- {
- "type": "boolean"
- },
- {
- "type": "array",
- "items": {
- "type": "string",
- "enum": [
- "wide",
- "full",
- "left",
- "center",
- "right"
- ]
- }
- }
- ],
- "default": false
- },
- "alignWide": {
- "description": "This property allows to enable wide alignment for your theme. To disable this behavior for a single block, set this flag to false.",
- "type": "boolean",
- "default": true
- },
- "ariaLabel": {
- "description": "ARIA-labels let you define an accessible label for elements. This property allows enabling the definition of an aria-label for the block, without exposing a UI field.",
- "type": "boolean",
- "default": false
- },
- "className": {
- "description": "By default, the class .wp-block-your-block-name is added to the root element of your saved markup. This helps having a consistent mechanism for styling blocks that themes and plugins can rely on. If, for whatever reason, a class is not desired on the markup, this functionality can be disabled.",
- "type": "boolean",
- "default": true
- },
- "color": {
- "description": "This value signals that a block supports some of the properties related to color. When it does, the block editor will show UI controls for the user to set their values.\n\nNote that the background and text keys have a default value of true, so if the color property is present they’ll also be considered enabled",
- "type": "object",
- "properties": {
- "background": {
- "description": "This property adds UI controls which allow the user to apply a solid background color to a block.\n\nWhen color support is declared, this property is enabled by default (along with text), so simply setting color will enable background color.\n\nTo disable background support while keeping other color supports enabled, set to false.\n\nWhen the block declares support for color.background, its attributes definition is extended to include two new attributes: backgroundColor and style",
- "type": "boolean",
- "default": true
- },
- "gradients": {
- "description": "This property adds UI controls which allow the user to apply a gradient background to a block.\n\nGradient presets are sourced from editor-gradient-presets theme support.\n\nWhen the block declares support for color.gradient, its attributes definition is extended to include two new attributes: gradient and style",
- "type": "boolean",
- "default": false
- },
- "link": {
- "description": "This property adds block controls which allow the user to set link color in a block, link color is disabled by default.\n\nLink color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.link, its attributes definition is extended to include the style attribute",
- "type": "boolean",
- "default": false
- },
- "text": {
- "description": "This property adds block controls which allow the user to set text color in a block.\n\nWhen color support is declared, this property is enabled by default (along with background), so simply setting color will enable text color.\n\nText color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.text, its attributes definition is extended to include two new attributes: textColor and style",
- "type": "boolean",
- "default": true
- },
- "heading": {
- "description": "This property adds block controls which allow the user to set heading colors in a block. Heading color is disabled by default.\n\nHeading color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.heading, its attributes definition is extended to include the style attribute",
- "type": "boolean",
- "default": false
- },
- "button": {
- "description": "This property adds block controls which allow the user to set button colors in a block. Button color is disabled by default.\n\nButton color presets are sourced from the editor-color-palette theme support.\n\nWhen the block declares support for color.button, its attributes definition is extended to include the style attribute",
- "type": "boolean",
- "default": false
- },
- "enableContrastChecker": {
- "description": "Determines whether the contrast checker widget displays in the block editor UI.\n\nThe contrast checker appears only if the block declares support for color. It tests the readability of color combinations and warns if there is a potential issue. The property is enabled by default.\n\nSet to `false` to explicitly disable.",
- "type": "boolean",
- "default": true
- }
- }
- },
- "customClassName": {
- "description": "This property adds a field to define a custom className for the block’s wrapper.",
- "type": "boolean",
- "default": true
- },
- "dimensions": {
- "description": "This value signals that a block supports some of the CSS style properties related to dimensions. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific dimensions property, its attributes definition is extended to include the style attribute.",
- "type": "object",
- "properties": {
- "aspectRatio": {
- "description": "Allow blocks to define an aspect ratio value.",
- "type": "boolean",
- "default": false
- },
- "minHeight": {
- "description": "Allow blocks to define a minimum height value.",
- "type": "boolean",
- "default": false
- }
- }
- },
- "filter": {
- "description": "This value signals that a block supports some of the properties related to filters. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific filter property, its attributes definition is extended to include the style attribute.",
- "type": "object",
- "properties": {
- "duotone": {
- "description": "Allow blocks to define a duotone filter.",
- "type": "boolean",
- "default": false
- }
- }
- },
- "background": {
- "description": "This value signals that a block supports some of the CSS style properties related to background. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific background property, its attributes definition is extended to include the style attribute.",
- "type": "object",
- "properties": {
- "backgroundImage": {
- "description": "Allow blocks to define a background image.",
- "type": "boolean",
- "default": false
- },
- "backgroundSize": {
- "description": "Allow blocks to define values related to the size of a background image, including size, position, and repeat controls",
- "type": "boolean",
- "default": false
- }
- }
- },
- "html": {
- "description": "By default, a block’s markup can be edited individually. To disable this behavior, set html to false.",
- "type": "boolean",
- "default": true
- },
- "inserter": {
- "description": "By default, all blocks will appear in the inserter, block transforms menu, Style Book, etc. To hide a block from all parts of the user interface so that it can only be inserted programmatically, set inserter to false.",
- "type": "boolean",
- "default": true
- },
- "renaming": {
- "description": "By default, a block can be renamed by a user from the block 'Options' dropdown or the 'Advanced' panel. To disable this behavior, set renaming to false.",
- "type": "boolean",
- "default": true
- },
- "layout": {
- "description": "This value only applies to blocks that are containers for inner blocks. If set to `true` the layout type will be `flow`. For other layout types it's necessary to set the `type` explicitly inside the `default` object.",
- "oneOf": [
- { "type": "boolean" },
- {
- "type": "object",
- "properties": {
- "default": {
- "description": "Allows setting the `type` property to define what layout type is default for the block, and also default values for any properties inherent to that layout type, e.g., for a `flex` layout, a default value can be set for `flexWrap`.",
- "type": "object",
- "properties": {
- "type": {
- "description": "The layout type.",
- "type": "string",
- "enum": [
- "constrained",
- "grid",
- "flex"
- ]
- },
- "contentSize": {
- "description": "The content size used on all children.",
- "type": "string"
- },
- "wideSize": {
- "description": "The wide size used on alignwide children.",
- "type": "string"
- },
- "justifyContent": {
- "description": "Content justification value.",
- "type": "string",
- "enum": [
- "right",
- "center",
- "space-between",
- "left",
- "stretch"
- ]
- },
- "orientation": {
- "description": "The orientation of the layout.",
- "type": "string",
- "enum": [ "horizontal", "vertical" ]
- },
- "flexWrap": {
- "description": "The flex wrap value.",
- "type": "string",
- "enum": [ "wrap", "nowrap" ]
- },
- "verticalAlignment": {
- "description": "The vertical alignment value.",
- "type": "string",
- "enum": [
- "top",
- "center",
- "bottom",
- "space-between",
- "stretch"
- ]
- },
- "minimumColumnWidth": {
- "description": "The minimum column width value.",
- "type": "string"
- },
- "columnCount": {
- "description": "The column count value.",
- "type": "number"
- }
- }
- },
- "allowSwitching": {
- "description": "Exposes a switcher control that allows toggling between all existing layout types.",
- "type": "boolean",
- "default": false
- },
- "allowEditing": {
- "description": "Determines display of layout controls in the block sidebar. If set to false, layout controls will be hidden.",
- "type": "boolean",
- "default": true
- },
- "allowInheriting": {
- "description": "For the `flow` layout type only, determines display of the `Inner blocks use content width` toggle.",
- "type": "boolean",
- "default": true
- },
- "allowSizingOnChildren": {
- "description": "For the `flex` layout type only, determines display of sizing controls (Fit/Fill/Fixed) on all child blocks of the flex block.",
- "type": "boolean",
- "default": false
- },
- "allowVerticalAlignment": {
- "description": "For the `flex` layout type only, determines display of vertical alignment controls in the block toolbar.",
- "type": "boolean",
- "default": true
- },
- "allowJustification": {
- "description": "For the `flex` layout type, determines display of justification controls in the block toolbar and block sidebar. For the `constrained` layout type, determines display of justification control in the block sidebar.",
- "type": "boolean",
- "default": true
- },
- "allowOrientation": {
- "description": "For the `flex` layout type only, determines display of the orientation control in the block toolbar.",
- "type": "boolean",
- "default": true
- },
- "allowCustomContentAndWideSize": {
- "description": "For the `constrained` layout type only, determines display of the custom content and wide size controls in the block sidebar.",
- "type": "boolean",
- "default": true
- }
- }
- }
- ],
- "default": false
- },
- "multiple": {
- "description": "A non-multiple block can be inserted into each post, one time only. For example, the built-in ‘More’ block cannot be inserted again if it already exists in the post being edited. A non-multiple block’s icon is automatically dimmed (unclickable) to prevent multiple instances.",
- "type": "boolean",
- "default": true
- },
- "reusable": {
- "description": "A block may want to disable the ability of being converted into a reusable block. By default all blocks can be converted to a reusable block. If supports reusable is set to false, the option to convert the block into a reusable block will not appear.",
- "type": "boolean",
- "default": true
- },
- "lock": {
- "description": "A block may want to disable the ability to toggle the lock state. It can be locked/unlocked by a user from the block 'Options' dropdown by default. To disable this behavior, set lock to false.",
- "type": "boolean",
- "default": true
- },
- "position": {
- "description": "This value signals that a block supports some of the CSS style properties related to position. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific position property, its attributes definition is extended to include the style attribute.",
- "type": "object",
- "properties": {
- "sticky": {
- "description": "Allow blocks to stick to their immediate parent when scrolling the page.",
- "type": "boolean",
- "default": false
- }
- }
- },
- "spacing": {
- "description": "This value signals that a block supports some of the CSS style properties related to spacing. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific spacing property, its attributes definition is extended to include the style attribute.",
- "type": "object",
- "properties": {
- "margin": {
- "oneOf": [
- {
- "type": "boolean"
- },
- {
- "type": "array",
- "items": {
- "type": "string",
- "enum": [
- "top",
- "right",
- "left",
- "bottom"
- ]
- }
- },
- {
- "type": "array",
- "items": {
- "type": "string",
- "enum": [ "vertical", "horizontal" ]
- }
- }
- ]
- },
- "padding": {
- "oneOf": [
- {
- "type": "boolean"
- },
- {
- "type": "array",
- "items": {
- "type": "string",
- "enum": [
- "top",
- "right",
- "left",
- "bottom"
- ]
- }
- },
- {
- "type": "array",
- "items": {
- "type": "string",
- "enum": [ "vertical", "horizontal" ]
- }
- }
- ]
- }
- }
- },
- "shadow": {
- "description": "Allow blocks to define a box shadow.",
- "oneOf": [
- {
- "description": "Defines whether a box shadow is enabled or not.",
- "type": "boolean"
- },
- {
- "type": "object"
- }
- ],
- "default": false
- },
- "typography": {
- "description": "This value signals that a block supports some of the CSS style properties related to typography. When it does, the block editor will show UI controls for the user to set their values if the theme declares support.\n\nWhen the block declares support for a specific typography property, its attributes definition is extended to include the style attribute.",
- "type": "object",
- "properties": {
- "fontSize": {
- "description": "This value signals that a block supports the font-size CSS style property. When it does, the block editor will show an UI control for the user to set its value.\n\nThe values shown in this control are the ones declared by the theme via the editor-font-sizes theme support, or the default ones if none is provided.\n\nWhen the block declares support for fontSize, its attributes definition is extended to include two new attributes: fontSize and style",
- "type": "boolean",
- "default": false
- },
- "lineHeight": {
- "description": "This value signals that a block supports the line-height CSS style property. When it does, the block editor will show an UI control for the user to set its value if the theme declares support.\n\nWhen the block declares support for lineHeight, its attributes definition is extended to include a new attribute style of object type with no default assigned. It stores the custom value set by the user. The block can apply a default style by specifying its own style attribute with a default",
- "type": "boolean",
- "default": false
- },
- "textAlign": {
- "description": "This property adds block toolbar controls which allow to change block's text alignment.",
- "oneOf": [
- {
- "type": "boolean"
- },
- {
- "type": "array",
- "items": {
- "type": "string",
- "enum": [ "left", "center", "right" ]
- }
- }
- ],
- "default": false
- }
- }
- },
- "interactivity": {
- "description": "Indicates if the block is using Interactivity API features.",
- "oneOf": [
- {
- "description": "Indicates whether the block is using the Interactivity API directives.",
- "type": "boolean",
- "default": false
- },
- {
- "type": "object",
- "properties": {
- "clientNavigation": {
- "description": "Indicates whether a block is compatible with the Interactivity API client-side navigation.\n\nSet it to true only if the block is not interactive or if it is interactive using the Interactivity API. Set it to false if the block is interactive but uses vanilla JS, jQuery or another JS framework/library other than the Interactivity API.",
- "type": "boolean",
- "default": false
- },
- "interactive": {
- "description": "Indicates whether the block is using the Interactivity API directives.",
- "type": "boolean",
- "default": false
- }
- }
- }
- ]
- },
- "splitting": {
- "description": "This property indicates whether the block can split when the Enter key is pressed or when blocks are pasted.",
- "type": "boolean",
- "default": false
- }
- },
- "additionalProperties": true
- },
- "selectors": {
- "description": "Provides custom CSS selectors and mappings for the block. Selectors may be set for the block itself or per-feature e.g. typography. Custom selectors per feature or sub-feature, allow different block styles to be applied to different elements within the block.",
- "type": "object",
- "properties": {
- "root": {
- "description": "The primary CSS class to apply to the block. This replaces the `.wp-block-name` class if set.",
- "type": "string"
- },
- "border": {
- "description": "Custom CSS selector used to generate rules for the block's theme.json border styles.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "object",
- "properties": {
- "root": { "type": "string" },
- "color": { "type": "string" },
- "radius": { "type": "string" },
- "style": { "type": "string" },
- "width": { "type": "string" }
- }
- }
- ]
- },
- "color": {
- "description": "Custom CSS selector used to generate rules for the block's theme.json color styles.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "object",
- "properties": {
- "root": { "type": "string" },
- "text": { "type": "string" },
- "background": { "type": "string" }
- }
- }
- ]
- },
- "dimensions": {
- "description": "Custom CSS selector used to generate rules for the block's theme.json dimensions styles.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "object",
- "properties": {
- "root": { "type": "string" },
- "aspectRatio": { "type": "string" },
- "minHeight": { "type": "string" }
- }
- }
- ]
- },
- "spacing": {
- "description": "Custom CSS selector used to generate rules for the block's theme.json spacing styles.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "object",
- "properties": {
- "root": { "type": "string" },
- "blockGap": { "type": "string" },
- "padding": { "type": "string" },
- "margin": { "type": "string" }
- }
- }
- ]
- },
- "typography": {
- "description": "Custom CSS selector used to generate rules for the block's theme.json typography styles.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "object",
- "properties": {
- "root": { "type": "string" },
- "fontFamily": { "type": "string" },
- "fontSize": { "type": "string" },
- "fontStyle": { "type": "string" },
- "fontWeight": { "type": "string" },
- "lineHeight": { "type": "string" },
- "letterSpacing": { "type": "string" },
- "textDecoration": { "type": "string" },
- "textTransform": { "type": "string" }
- }
- }
- ]
- }
- }
- },
- "styles": {
- "description": "Block styles can be used to provide alternative styles to block. It works by adding a class name to the block’s wrapper. Using CSS, a theme developer can target the class name for the block style if it is selected.\n\nPlugins and Themes can also register custom block style for existing blocks.\n\nhttps://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
- },
- "label": {
- "type": "string"
- },
- "isDefault": {
- "type": "boolean",
- "default": false
- }
- },
- "required": [ "name", "label" ],
- "additionalProperties": false
- }
- },
- "example": {
- "description": "It provides structured example data for the block. This data is used to construct a preview for the block to be shown in the Inspector Help Panel when the user mouses over the block.\n\nSee the example documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#example-optional for more details.",
- "type": "object",
- "properties": {
- "viewportWidth": {
- "description": "The viewportWidth controls the width of the iFrame container in which the block preview will get rendered",
- "type": "number",
- "default": 1200
- },
- "attributes": {
- "description": "Set the attributes for the block example",
- "type": "object"
- },
- "innerBlocks": {
- "description": "Set the inner blocks that should be used within the block example. The blocks should be defined as a nested array like this:\n\n[ { \"name\": \"core/heading\", \"attributes\": { \"content\": \"This is an Example\" } } ]\n\nWhere each block itself is an object that contains the block name, the block attributes, and the blocks inner blocks.",
- "type": "array"
- }
- }
- },
- "blockHooks": {
- "description": "Block Hooks allow a block to automatically insert itself next to all instances of a given block type.\n\nSee the Block Hooks documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#block-hooks-optional for more details.",
- "type": "object",
- "patternProperties": {
- "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
- "type": "string",
- "enum": [ "before", "after", "firstChild", "lastChild" ]
- }
- },
- "additionalProperties": false
- },
- "editorScript": {
- "description": "Block type editor script definition. It will only be enqueued in the context of the editor.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ]
- },
- "script": {
- "description": "Block type frontend and editor script definition. It will be enqueued both in the editor and when viewing the content on the front of the site.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ]
- },
- "viewScript": {
- "description": "Block type frontend script definition. It will be enqueued only when viewing the content on the front of the site.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ]
- },
- "viewScriptModule": {
- "description": "Block type frontend script module definition. It will be enqueued only when viewing the content on the front of the site.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ]
- },
- "editorStyle": {
- "description": "Block type editor style definition. It will only be enqueued in the context of the editor.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ]
- },
- "style": {
- "description": "Block type frontend style definition. It will be enqueued both in the editor and when viewing the content on the front of the site.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ]
- },
- "viewStyle": {
- "description": "Block type frontend style definition. It will be enqueued only when viewing the content on the front of the site.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ]
- },
- "variations": {
- "description": "Block Variations is the API that allows a block to have similar versions of it, but all these versions share some common functionality.",
- "oneOf": [
- {
- "description": "The path to a PHP file that returns an array of block variations.",
- "type": "string"
- },
- {
- "description": "An array of block variations.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "The unique and machine-readable name.",
- "type": "string"
- },
- "title": {
- "description": "A human-readable variation title.",
- "type": "string"
- },
- "description": {
- "description": "A detailed variation description.",
- "type": "string"
- },
- "category": {
- "description": "A category classification, used in search interfaces to arrange block types by category.",
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "string",
- "enum": [
- "text",
- "media",
- "design",
- "widgets",
- "theme",
- "embed"
- ]
- }
- ]
- },
- "icon": {
- "description": "An icon helping to visualize the variation. It can have the same shape as the block type.",
- "type": "string"
- },
- "isDefault": {
- "description": "Indicates whether the current variation is the default one.",
- "type": "boolean",
- "default": false
- },
- "attributes": {
- "description": "Values that override block attributes.",
- "type": "object"
- },
- "innerBlocks": {
- "description": "Initial configuration of nested blocks.",
- "type": "array",
- "items": {
- "type": "array"
- }
- },
- "example": {
- "description": "Example provides structured data for the block preview. You can set to undefined to disable the preview shown for the block type.",
- "type": "object"
- },
- "scope": {
- "description": "The list of scopes where the variation is applicable.",
- "type": "array",
- "items": {
- "type": "string",
- "enum": [ "inserter", "block", "transform" ]
- },
- "default": [ "inserter", "block" ]
- },
- "keywords": {
- "description": "An array of terms (which can be translated) that help users discover the variation while searching.",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "isActive": {
- "description": "The list of attributes that should be compared. Each attributes will be matched and the variation will be active if all of them are matching.",
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- },
- "required": [ "name", "title" ],
- "additionalProperties": false
- }
- }
- ]
- },
- "render": {
- "description": "Template file loaded on the server when rendering a block.",
- "type": "string"
- }
- },
- "required": [ "apiVersion", "name", "title" ],
- "additionalProperties": false
-}
diff --git a/gutenberg/schemas/json/font-collection.json b/gutenberg/schemas/json/font-collection.json
deleted file mode 100644
index 7b5bd8f..0000000
--- a/gutenberg/schemas/json/font-collection.json
+++ /dev/null
@@ -1,146 +0,0 @@
-{
- "title": "JSON schema for WordPress Font Collections",
- "$schema": "http://json-schema.org/draft-07/schema#",
- "definitions": {
- "fontFace": {
- "description": "Font face settings, with added preview property.",
- "type": "object",
- "properties": {
- "preview": {
- "description": "URL to a preview image of the font.",
- "type": "string"
- },
- "fontFamily": {
- "description": "CSS font-family value.",
- "type": "string",
- "default": ""
- },
- "fontStyle": {
- "description": "CSS font-style value.",
- "type": "string",
- "default": "normal"
- },
- "fontWeight": {
- "description": "List of available font weights, separated by a space.",
- "oneOf": [ { "type": "string" }, { "type": "integer" } ],
- "default": "400"
- },
- "fontDisplay": {
- "description": "CSS font-display value.",
- "type": "string",
- "enum": [ "auto", "block", "fallback", "swap", "optional" ],
- "default": "fallback"
- },
- "src": {
- "description": "Paths or URLs to the font files.",
- "oneOf": [
- { "type": "string" },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ],
- "default": []
- },
- "fontStretch": {
- "description": "CSS font-stretch value.",
- "type": "string"
- },
- "ascentOverride": {
- "description": "CSS ascent-override value.",
- "type": "string"
- },
- "descentOverride": {
- "description": "CSS descent-override value.",
- "type": "string"
- },
- "fontVariant": {
- "description": "CSS font-variant value.",
- "type": "string"
- },
- "fontFeatureSettings": {
- "description": "CSS font-feature-settings value.",
- "type": "string"
- },
- "fontVariationSettings": {
- "description": "CSS font-variation-settings value.",
- "type": "string"
- },
- "lineGapOverride": {
- "description": "CSS line-gap-override value.",
- "type": "string"
- },
- "sizeAdjust": {
- "description": "CSS size-adjust value.",
- "type": "string"
- },
- "unicodeRange": {
- "description": "CSS unicode-range value.",
- "type": "string"
- }
- },
- "required": [ "fontFamily", "src" ],
- "additionalProperties": false
- }
- },
- "type": "object",
- "properties": {
- "$schema": {
- "description": "JSON schema URI for font-collection.json.",
- "type": "string"
- },
- "font_families": {
- "description": "Array of font families ready to be installed.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "font_family_settings": {
- "description": "Font family settings, with added preview property.",
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the font family preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the font family preset.",
- "type": "string"
- },
- "fontFamily": {
- "description": "CSS font-family value.",
- "type": "string"
- },
- "preview": {
- "description": "URL to a preview image of the font family.",
- "type": "string"
- },
- "fontFace": {
- "description": "Array of font-face definitions.",
- "type": "array",
- "items": {
- "$ref": "#/definitions/fontFace"
- }
- }
- },
- "required": [ "name", "fontFamily", "slug" ],
- "additionalProperties": false
- },
- "categories": {
- "description": "Array of category slugs.",
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- },
- "required": [ "font_family_settings" ],
- "additionalProperties": false
- }
- }
- },
- "additionalProperties": false,
- "required": [ "font_families" ]
-}
diff --git a/gutenberg/schemas/json/theme.json b/gutenberg/schemas/json/theme.json
deleted file mode 100644
index 6a4a259..0000000
--- a/gutenberg/schemas/json/theme.json
+++ /dev/null
@@ -1,2755 +0,0 @@
-{
- "title": "JSON schema for WordPress block theme global settings and styles",
- "$schema": "http://json-schema.org/draft-07/schema#",
- "definitions": {
- "//": {
- "explainer": "https://developer.wordpress.org/themes/global-settings-and-styles/",
- "createTheme": "https://developer.wordpress.org/themes/",
- "reference": "https://developer.wordpress.org/block-editor/how-to-guides/themes/global-settings-and-styles/"
- },
- "refComplete": {
- "type": "object",
- "properties": {
- "ref": {
- "description": "A reference to another property value. e.g. `styles.color.text`",
- "type": "string"
- }
- },
- "additionalProperties": false
- },
- "settingsAppearanceToolsProperties": {
- "type": "object",
- "properties": {
- "appearanceTools": {
- "description": "Setting that enables the following UI tools:\n\n- background: backgroundImage, backgroundSize\n- border: color, radius, style, width\n- color: link, heading, button, caption\n- dimensions: aspectRatio, minHeight\n- position: sticky\n- spacing: blockGap, margin, padding\n- typography: lineHeight",
- "type": "boolean",
- "default": false
- }
- }
- },
- "settingsBackgroundProperties": {
- "type": "object",
- "properties": {
- "background": {
- "description": "Settings related to background.",
- "type": "object",
- "properties": {
- "backgroundImage": {
- "description": "Allow users to set a background image.",
- "type": "boolean",
- "default": false
- },
- "backgroundSize": {
- "description": "Allow users to set values related to the size of a background image, including size, position, and repeat controls.",
- "type": "boolean",
- "default": false
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsBorderProperties": {
- "type": "object",
- "properties": {
- "border": {
- "description": "Settings related to borders.",
- "type": "object",
- "properties": {
- "color": {
- "description": "Allow users to set custom border colors.",
- "type": "boolean",
- "default": false
- },
- "radius": {
- "description": "Allow users to set custom border radius.",
- "type": "boolean",
- "default": false
- },
- "style": {
- "description": "Allow users to set custom border styles.",
- "type": "boolean",
- "default": false
- },
- "width": {
- "description": "Allow users to set custom border widths.",
- "type": "boolean",
- "default": false
- },
- "radiusSizes": {
- "description": "Border radius size presets for the border radius selector.\nGenerates a custom property (`--wp--preset--border-radius--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the border radius size preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Unique identifier for the border raidus size preset.",
- "type": "string"
- },
- "size": {
- "description": "CSS border-radius value, including units.",
- "type": "string"
- }
- },
- "additionalProperties": false
- }
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsColorProperties": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Settings related to colors.",
- "type": "object",
- "properties": {
- "background": {
- "description": "Allow users to set background colors.",
- "type": "boolean",
- "default": true
- },
- "custom": {
- "description": "Allow users to select custom colors.",
- "type": "boolean",
- "default": true
- },
- "customDuotone": {
- "description": "Allow users to create custom duotone filters.",
- "type": "boolean",
- "default": true
- },
- "customGradient": {
- "description": "Allow users to create custom gradients.",
- "type": "boolean",
- "default": true
- },
- "defaultDuotone": {
- "description": "Allow users to choose filters from the default duotone filter presets.",
- "type": "boolean",
- "default": true
- },
- "defaultGradients": {
- "description": "Allow users to choose colors from the default gradients.",
- "type": "boolean",
- "default": true
- },
- "defaultPalette": {
- "description": "Allow users to choose colors from the default palette.",
- "type": "boolean",
- "default": true
- },
- "duotone": {
- "description": "Duotone presets for the duotone picker.\nDoesn't generate classes or properties.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the duotone preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the duotone preset.",
- "type": "string"
- },
- "colors": {
- "description": "List of colors from dark to light.",
- "type": "array",
- "items": {
- "description": "CSS hex or rgb string.",
- "type": "string"
- }
- }
- },
- "required": [ "name", "slug", "colors" ],
- "additionalProperties": false
- }
- },
- "gradients": {
- "description": "Gradient presets for the gradient picker.\nGenerates a single class (`.has-{slug}-background`) and custom property (`--wp--preset--gradient--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the gradient preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the gradient preset.",
- "type": "string"
- },
- "gradient": {
- "description": "CSS gradient string.",
- "type": "string"
- }
- },
- "required": [ "name", "slug", "gradient" ],
- "additionalProperties": false
- }
- },
- "link": {
- "description": "Allow users to set link colors in a block.",
- "type": "boolean",
- "default": false
- },
- "palette": {
- "description": "Color palette presets for the color picker.\nGenerates three classes (`.has-{slug}-color`, `.has-{slug}-background-color`, and `.has-{slug}-border-color`) and a single custom property (`--wp--preset--color--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the color preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the color preset.",
- "type": "string"
- },
- "color": {
- "description": "CSS hex or rgb(a) string.",
- "type": "string"
- }
- },
- "required": [ "name", "slug", "color" ],
- "additionalProperties": false
- }
- },
- "text": {
- "description": "Allow users to set text colors in a block.",
- "type": "boolean",
- "default": true
- },
- "heading": {
- "description": "Allow users to set heading colors in a block.",
- "type": "boolean",
- "default": true
- },
- "button": {
- "description": "Allow users to set button colors in a block.",
- "type": "boolean",
- "default": true
- },
- "caption": {
- "description": "Allow users to set caption colors in a block.",
- "type": "boolean",
- "default": true
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsDimensionsProperties": {
- "type": "object",
- "properties": {
- "dimensions": {
- "description": "Settings related to dimensions.",
- "type": "object",
- "properties": {
- "aspectRatio": {
- "description": "Allow users to set an aspect ratio.",
- "type": "boolean",
- "default": false
- },
- "defaultAspectRatios": {
- "description": "Allow users to choose aspect ratios from the default set of aspect ratios.",
- "type": "boolean",
- "default": true
- },
- "aspectRatios": {
- "description": "Allow users to define aspect ratios for some blocks.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the aspect ratio preset.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the aspect ratio preset.",
- "type": "string"
- },
- "ratio": {
- "description": "Aspect ratio expressed as a division or decimal.",
- "type": "string"
- }
- }
- }
- },
- "minHeight": {
- "description": "Allow users to set custom minimum height.",
- "type": "boolean",
- "default": false
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsLayoutProperties": {
- "type": "object",
- "properties": {
- "layout": {
- "description": "Settings related to layout.",
- "type": "object",
- "properties": {
- "contentSize": {
- "description": "Sets the max-width of the content.",
- "type": "string"
- },
- "wideSize": {
- "description": "Sets the max-width of wide (`.alignwide`) content. Also used as the maximum viewport when calculating fluid font sizes",
- "type": "string"
- },
- "allowEditing": {
- "description": "Disable the layout UI controls.",
- "type": "boolean",
- "default": true
- },
- "allowCustomContentAndWideSize": {
- "description": "Enable or disable the custom content and wide size controls.",
- "type": "boolean",
- "default": true
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsLightboxProperties": {
- "type": "object",
- "properties": {
- "lightbox": {
- "description": "Settings related to the lightbox.",
- "type": "object",
- "properties": {
- "enabled": {
- "description": "Defines whether the lightbox is enabled or not.",
- "type": "boolean"
- },
- "allowEditing": {
- "description": "Defines whether to show the Lightbox UI in the block editor. If set to `false`, the user won't be able to change the lightbox settings in the block editor.",
- "type": "boolean"
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsPositionProperties": {
- "type": "object",
- "properties": {
- "position": {
- "description": "Settings related to position.",
- "type": "object",
- "properties": {
- "sticky": {
- "description": "Allow users to set sticky position.",
- "type": "boolean",
- "default": false
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsShadowProperties": {
- "type": "object",
- "properties": {
- "shadow": {
- "description": "Settings related to shadows.",
- "type": "object",
- "properties": {
- "defaultPresets": {
- "description": "Allow users to choose shadows from the default shadow presets.",
- "type": "boolean",
- "default": true
- },
- "presets": {
- "description": "Shadow presets for the shadow picker.\nGenerates a single custom property (`--wp--preset--shadow--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the shadow preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the shadow preset.",
- "type": "string"
- },
- "shadow": {
- "description": "CSS box-shadow value",
- "type": "string"
- }
- },
- "required": [ "name", "slug", "shadow" ],
- "additionalProperties": false
- }
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsSpacingProperties": {
- "type": "object",
- "properties": {
- "spacing": {
- "description": "Settings related to spacing.",
- "type": "object",
- "properties": {
- "blockGap": {
- "description": "Enables `--wp--style--block-gap` to be generated from styles.spacing.blockGap.\nA value of `null` instead of `false` further disables layout styles from being generated.",
- "oneOf": [
- { "type": "boolean" },
- { "type": "null" }
- ],
- "default": null
- },
- "margin": {
- "description": "Allow users to set a custom margin.",
- "type": "boolean",
- "default": false
- },
- "padding": {
- "description": "Allow users to set a custom padding.",
- "type": "boolean",
- "default": false
- },
- "units": {
- "description": "List of units the user can use for spacing values.",
- "type": "array",
- "items": {
- "type": "string"
- },
- "minItems": 1,
- "default": [ "px", "em", "rem", "vh", "vw", "%" ]
- },
- "customSpacingSize": {
- "description": "Allow users to set custom space sizes.",
- "type": "boolean",
- "default": true
- },
- "defaultSpacingSizes": {
- "description": "Allow users to choose space sizes from the default space size presets.",
- "type": "boolean",
- "default": true
- },
- "spacingSizes": {
- "description": "Space size presets for the space size selector.\nGenerates a custom property (`--wp--preset--spacing--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the space size preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Unique identifier for the space size preset. For best cross theme compatibility these should be in the form '10','20','30','40','50','60', etc. with '50' representing the 'Medium' size step. If all slugs begin with a number they will be merged with default and user slugs and sorted numerically.",
- "type": "string"
- },
- "size": {
- "description": "CSS space-size value, including units.",
- "type": "string"
- }
- },
- "additionalProperties": false
- }
- },
- "spacingScale": {
- "description": "Settings to auto-generate space size presets for the space size selector.\nGenerates a custom property (--wp--preset--spacing--{slug}`) per preset value.",
- "type": "object",
- "properties": {
- "operator": {
- "description": "With + or * depending on whether scale is generated by increment or multiplier.",
- "type": "string",
- "enum": [ "+", "*" ],
- "default": "*"
- },
- "increment": {
- "description": "The amount to increment each step by.",
- "type": "number",
- "exclusiveMinimum": 0,
- "default": 1.5
- },
- "steps": {
- "description": "Number of steps to generate in scale.",
- "type": "integer",
- "minimum": 1,
- "maximum": 10,
- "default": 7
- },
- "mediumStep": {
- "description": "The value to medium setting in the scale.",
- "type": "number",
- "exclusiveMinimum": 0,
- "default": 1.5
- },
- "unit": {
- "description": "Unit that the scale uses, eg. rem, em, px.",
- "type": "string",
- "enum": [
- "px",
- "em",
- "rem",
- "%",
- "vw",
- "svw",
- "lvw",
- "dvw",
- "vh",
- "svh",
- "lvh",
- "dvh",
- "vi",
- "svi",
- "lvi",
- "dvi",
- "vb",
- "svb",
- "lvb",
- "dvb",
- "vmin",
- "svmin",
- "lvmin",
- "dvmin",
- "vmax",
- "svmax",
- "lvmax",
- "dvmax"
- ],
- "default": "rem"
- }
- },
- "additionalProperties": false
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsTypographyProperties": {
- "type": "object",
- "properties": {
- "typography": {
- "description": "Settings related to typography.",
- "type": "object",
- "properties": {
- "defaultFontSizes": {
- "description": "Allow users to choose font sizes from the default font size presets.",
- "type": "boolean",
- "default": true
- },
- "customFontSize": {
- "description": "Allow users to set custom font sizes.",
- "type": "boolean",
- "default": true
- },
- "fontStyle": {
- "description": "Allow users to set custom font styles.",
- "type": "boolean",
- "default": true
- },
- "fontWeight": {
- "description": "Allow users to set custom font weights.",
- "type": "boolean",
- "default": true
- },
- "fluid": {
- "description": "Enables fluid typography and allows users to set global fluid typography parameters.",
- "oneOf": [
- {
- "type": "object",
- "properties": {
- "minFontSize": {
- "description": "Allow users to set a global minimum font size boundary in px, rem or em. Custom font sizes below this value will not be clamped, and all calculated minimum font sizes will be, at a minimum, this value.",
- "type": "string"
- },
- "maxViewportWidth": {
- "description": "Allow users to set custom a max viewport width in px, rem or em, used to set the maximum size boundary of a fluid font size.",
- "type": "string"
- },
- "minViewportWidth": {
- "description": "Allow users to set a custom min viewport width in px, rem or em, used to set the minimum size boundary of a fluid font size.",
- "type": "string"
- }
- },
- "additionalProperties": false
- },
- {
- "type": "boolean"
- }
- ],
- "default": false
- },
- "letterSpacing": {
- "description": "Allow users to set custom letter spacing.",
- "type": "boolean",
- "default": true
- },
- "lineHeight": {
- "description": "Allow users to set custom line height.",
- "type": "boolean",
- "default": false
- },
- "textAlign": {
- "description": "Allow users to set the text align.",
- "type": "boolean",
- "default": true
- },
- "textColumns": {
- "description": "Allow users to set the number of text columns.",
- "type": "boolean",
- "default": false
- },
- "textDecoration": {
- "description": "Allow users to set custom text decorations.",
- "type": "boolean",
- "default": true
- },
- "writingMode": {
- "description": "Allow users to set the writing mode.",
- "type": "boolean",
- "default": false
- },
- "textTransform": {
- "description": "Allow users to set custom text transforms.",
- "type": "boolean",
- "default": true
- },
- "dropCap": {
- "description": "Enable drop cap.",
- "type": "boolean",
- "default": true
- },
- "fontSizes": {
- "description": "Font size presets for the font size selector.\nGenerates a single class (`.has-{slug}-color`) and custom property (`--wp--preset--font-size--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the font size preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the font size preset.",
- "type": "string"
- },
- "size": {
- "description": "CSS font-size value, including units.",
- "type": "string"
- },
- "fluid": {
- "description": "Specifies the minimum and maximum font size value of a fluid font size. Set to `false` to bypass fluid calculations and use the static `size` value.",
- "oneOf": [
- {
- "type": "object",
- "properties": {
- "min": {
- "description": "A min font size for fluid font size calculations in px, rem or em.",
- "type": "string"
- },
- "max": {
- "description": "A max font size for fluid font size calculations in px, rem or em.",
- "type": "string"
- }
- },
- "additionalProperties": false
- },
- {
- "type": "boolean"
- }
- ]
- }
- },
- "additionalProperties": false
- }
- },
- "fontFamilies": {
- "description": "Font family presets for the font family selector.\nGenerates a single custom property (`--wp--preset--font-family--{slug}`) per preset value.",
- "type": "array",
- "items": {
- "description": "Font family preset",
- "type": "object",
- "properties": {
- "name": {
- "description": "Name of the font family preset, translatable.",
- "type": "string"
- },
- "slug": {
- "description": "Kebab-case unique identifier for the font family preset.",
- "type": "string"
- },
- "fontFamily": {
- "description": "CSS font-family value.",
- "type": "string"
- },
- "fontFace": {
- "description": "Array of font-face declarations.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "fontFamily": {
- "description": "CSS font-family value.",
- "type": "string",
- "default": ""
- },
- "fontStyle": {
- "description": "CSS font-style value.",
- "type": "string",
- "default": "normal"
- },
- "fontWeight": {
- "description": "List of available font weights, separated by a space.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "integer"
- }
- ],
- "default": "400"
- },
- "fontDisplay": {
- "description": "CSS font-display value.",
- "type": "string",
- "enum": [
- "auto",
- "block",
- "fallback",
- "swap",
- "optional"
- ],
- "default": "fallback"
- },
- "src": {
- "description": "Paths or URLs to the font files.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- ],
- "default": []
- },
- "fontStretch": {
- "description": "CSS font-stretch value.",
- "type": "string"
- },
- "ascentOverride": {
- "description": "CSS ascent-override value.",
- "type": "string"
- },
- "descentOverride": {
- "description": "CSS descent-override value.",
- "type": "string"
- },
- "fontVariant": {
- "description": "CSS font-variant value.",
- "type": "string"
- },
- "fontFeatureSettings": {
- "description": "CSS font-feature-settings value.",
- "type": "string"
- },
- "fontVariationSettings": {
- "description": "CSS font-variation-settings value.",
- "type": "string"
- },
- "lineGapOverride": {
- "description": "CSS line-gap-override value.",
- "type": "string"
- },
- "sizeAdjust": {
- "description": "CSS size-adjust value.",
- "type": "string"
- },
- "unicodeRange": {
- "description": "CSS unicode-range value.",
- "type": "string"
- }
- },
- "required": [ "fontFamily", "src" ],
- "additionalProperties": false
- }
- }
- },
- "additionalProperties": false
- }
- }
- },
- "additionalProperties": false
- }
- }
- },
- "settingsCustomProperties": {
- "type": "object",
- "properties": {
- "custom": {
- "$ref": "#/definitions/settingsCustomAdditionalProperties"
- }
- }
- },
- "settingsProperties": {
- "allOf": [
- { "$ref": "#/definitions/settingsAppearanceToolsProperties" },
- { "$ref": "#/definitions/settingsBackgroundProperties" },
- { "$ref": "#/definitions/settingsBorderProperties" },
- { "$ref": "#/definitions/settingsColorProperties" },
- { "$ref": "#/definitions/settingsDimensionsProperties" },
- { "$ref": "#/definitions/settingsLayoutProperties" },
- { "$ref": "#/definitions/settingsLightboxProperties" },
- { "$ref": "#/definitions/settingsPositionProperties" },
- { "$ref": "#/definitions/settingsShadowProperties" },
- { "$ref": "#/definitions/settingsSpacingProperties" },
- { "$ref": "#/definitions/settingsTypographyProperties" },
- { "$ref": "#/definitions/settingsCustomProperties" }
- ]
- },
- "settingsPropertyNames": {
- "enum": [
- "appearanceTools",
- "background",
- "border",
- "color",
- "dimensions",
- "layout",
- "lightbox",
- "position",
- "shadow",
- "spacing",
- "typography",
- "custom"
- ]
- },
- "settingsPropertiesComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/settingsProperties"
- },
- {
- "type": "object",
- "propertyNames": {
- "$ref": "#/definitions/settingsPropertyNames"
- }
- }
- ]
- },
- "settingsBlocksPropertiesComplete": {
- "description": "Settings defined on a per-block basis.",
- "type": "object",
- "properties": {
- "core/archives": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/audio": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/avatar": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/block": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/button": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/buttons": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/calendar": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/categories": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/code": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/column": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/columns": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-author-avatar": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-author-name": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-content": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-date": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-edit-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-reply-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-pagination": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-pagination-next": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-pagination-numbers": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-pagination-previous": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comments-title": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/comment-template": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/cover": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/details": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/embed": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/file": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/footnotes": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/freeform": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/gallery": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/group": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/heading": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/home-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/html": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/image": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/latest-comments": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/latest-posts": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/list": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/list-item": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/loginout": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/media-text": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/missing": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/more": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/navigation": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/navigation-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/navigation-submenu": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/nextpage": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/page-list": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/page-list-item": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/paragraph": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-author": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-author-biography": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-author-name": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-comment": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-comments-count": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-comments-form": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-comments-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-content": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-date": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-excerpt": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-featured-image": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-navigation-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-template": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-terms": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/post-title": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/preformatted": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/pullquote": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-no-results": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-pagination": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-pagination-next": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-pagination-numbers": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-pagination-previous": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-title": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/query-total": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/quote": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/read-more": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/rss": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/search": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/separator": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/shortcode": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/site-logo": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/site-tagline": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/site-title": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/social-link": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/social-links": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/spacer": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/table": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/tag-cloud": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/template-part": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/term-description": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/text-columns": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/verse": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/video": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/widget-area": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/legacy-widget": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- },
- "core/widget-group": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- }
- },
- "patternProperties": {
- "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/settingsPropertiesComplete"
- }
- },
- "additionalProperties": false
- },
- "settingsCustomAdditionalProperties": {
- "description": "Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name.",
- "type": "object",
- "additionalProperties": {
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "number"
- },
- {
- "$ref": "#/definitions/settingsCustomAdditionalProperties"
- }
- ]
- }
- },
- "stylesProperties": {
- "type": "object",
- "properties": {
- "background": {
- "description": "Background styles.",
- "type": "object",
- "properties": {
- "backgroundImage": {
- "description": "Sets the `background-image` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" },
- {
- "type": "object",
- "properties": {
- "url": {
- "description": "A URL to an image file, or a path to a file relative to the theme root directory, and prefixed with `file:`, e.g., 'file:./path/to/file.png'.",
- "type": "string"
- }
- },
- "additionalProperties": false
- }
- ]
- },
- "backgroundPosition": {
- "description": "Sets the `background-position` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "backgroundRepeat": {
- "description": "Sets the `background-repeat` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "backgroundSize": {
- "description": "Sets the `background-size` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "backgroundAttachment": {
- "description": "Sets the `background-attachment` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "border": {
- "description": "Border styles.",
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "radius": {
- "description": "Sets the `border-radius` CSS property.",
- "anyOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" },
- {
- "type": "object",
- "properties": {
- "topLeft": {
- "description": "Sets the `border-top-left-radius` CSS property.",
- "oneOf": [
- { "type": "string" },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- },
- "topRight": {
- "description": "Sets the `border-top-right-radius` CSS property.",
- "oneOf": [
- { "type": "string" },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- },
- "bottomLeft": {
- "description": "Sets the `border-bottom-left-radius` CSS property.",
- "oneOf": [
- { "type": "string" },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- },
- "bottomRight": {
- "description": "Sets the `border-bottom-right-radius` CSS property.",
- "oneOf": [
- { "type": "string" },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- }
- }
- }
- ]
- },
- "style": {
- "description": "Sets the `border-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "top": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-top-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `border-top-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-top-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "right": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-right-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `border-right-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-right-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "bottom": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-bottom-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `border-bottom-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-bottom-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "left": {
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `border-left-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `border-left-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `border-left-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- }
- },
- "additionalProperties": false
- },
- "color": {
- "description": "Color styles.",
- "type": "object",
- "properties": {
- "background": {
- "description": "Sets the `background-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "gradient": {
- "description": "Sets the `background` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "text": {
- "description": "Sets the `color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "css": {
- "description": "Sets custom CSS to apply styling not covered by other theme.json properties.",
- "type": "string"
- },
- "dimensions": {
- "description": "Dimensions styles.",
- "type": "object",
- "properties": {
- "aspectRatio": {
- "description": "Sets the `aspect-ratio` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "minHeight": {
- "description": "Sets the `min-height` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- }
- },
- "filter": {
- "description": "CSS and SVG filter styles.",
- "type": "object",
- "properties": {
- "duotone": {
- "description": "Sets the duotone filter.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "outline": {
- "description": "Outline styles.",
- "type": "object",
- "properties": {
- "color": {
- "description": "Sets the `outline-color` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "offset": {
- "description": "Sets the `outline-offset` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "style": {
- "description": "Sets the `outline-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "width": {
- "description": "Sets the `outline-width` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "shadow": {
- "description": "Box shadow styles.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "spacing": {
- "description": "Spacing styles.",
- "type": "object",
- "properties": {
- "blockGap": {
- "description": "Sets the `--wp--style--block-gap` CSS custom property when settings.spacing.blockGap is true.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "margin": {
- "description": "Margin styles.",
- "type": "object",
- "properties": {
- "top": {
- "description": "Sets the `margin-top` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "right": {
- "description": "Sets the `margin-right` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "bottom": {
- "description": "Sets the `margin-bottom` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "left": {
- "description": "Sets the `margin-left` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- },
- "padding": {
- "description": "Padding styles.",
- "type": "object",
- "properties": {
- "top": {
- "description": "Sets the `padding-top` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "right": {
- "description": "Sets the `padding-right` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "bottom": {
- "description": "Sets the `padding-bottom` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "left": {
- "description": "Sets the `padding-left` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- }
- },
- "additionalProperties": false
- },
- "typography": {
- "description": "Typography styles.",
- "type": "object",
- "properties": {
- "fontFamily": {
- "description": "Sets the `font-family` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "fontSize": {
- "description": "Sets the `font-size` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "fontStyle": {
- "description": "Sets the `font-style` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "fontWeight": {
- "description": "Sets the `font-weight` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "letterSpacing": {
- "description": "Sets the `letter-spacing` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "lineHeight": {
- "description": "Sets the `line-height` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "textAlign": {
- "description": "Sets the `text-align` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "textColumns": {
- "description": "Sets the `column-count` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "textDecoration": {
- "description": "Sets the `text-decoration` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "writingMode": {
- "description": "Sets the `writing-mode` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- },
- "textTransform": {
- "description": "Sets the `text-transform` CSS property.",
- "oneOf": [
- { "type": "string" },
- { "$ref": "#/definitions/refComplete" }
- ]
- }
- },
- "additionalProperties": false
- }
- }
- },
- "stylesPropertyNames": {
- "enum": [
- "background",
- "border",
- "color",
- "css",
- "dimensions",
- "filter",
- "outline",
- "shadow",
- "spacing",
- "typography"
- ]
- },
- "stylesPropertiesComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "propertyNames": {
- "$ref": "#/definitions/stylesPropertyNames"
- }
- }
- ]
- },
- "stylesElementsPseudoSelectorsProperties": {
- "type": "object",
- "properties": {
- ":active": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":any-link": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":focus": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":focus-visible": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":hover": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":link": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- ":visited": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- }
- }
- },
- "stylesElementsPseudoSelectorsPropertyNames": {
- "enum": [
- ":active",
- ":any-link",
- ":focus",
- ":focus-visible",
- ":hover",
- ":link",
- ":visited"
- ]
- },
- "stylesElementsPropertiesComplete": {
- "description": "Styles defined on a per-element basis using the element's selector.",
- "type": "object",
- "properties": {
- "button": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties"
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames"
- }
- ]
- }
- }
- ]
- },
- "link": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "$ref": "#/definitions/stylesElementsPseudoSelectorsProperties"
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "$ref": "#/definitions/stylesElementsPseudoSelectorsPropertyNames"
- }
- ]
- }
- }
- ]
- },
- "heading": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h1": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h2": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h3": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h4": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h5": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "h6": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "caption": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- },
- "cite": {
- "$ref": "#/definitions/stylesPropertiesComplete"
- }
- },
- "additionalProperties": false
- },
- "stylesBlocksPropertiesComplete": {
- "description": "Styles defined on a per-block basis using the block's selector.",
- "type": "object",
- "properties": {
- "core/archives": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/audio": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/avatar": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/block": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/button": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/buttons": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/calendar": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/categories": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/code": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/column": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/columns": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-author-avatar": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-author-name": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-content": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-date": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-edit-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-reply-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-pagination": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-pagination-next": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-pagination-numbers": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-pagination-previous": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comments-title": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/comment-template": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/cover": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/details": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/embed": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/file": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/footnotes": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/freeform": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/gallery": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/group": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/heading": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/home-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/html": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/image": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/latest-comments": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/latest-posts": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/list": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/list-item": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/loginout": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/media-text": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/missing": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/more": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/navigation": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/navigation-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/navigation-submenu": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/nextpage": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/page-list": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/page-list-item": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/paragraph": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-author": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-author-biography": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-author-name": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-comment": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-comments-count": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-comments-form": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-comments-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-content": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-date": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-excerpt": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-featured-image": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-navigation-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-template": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-terms": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/post-title": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/preformatted": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/pullquote": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-no-results": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-pagination": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-pagination-next": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-pagination-numbers": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-pagination-previous": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-title": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/query-total": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/quote": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/read-more": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/rss": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/search": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/separator": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/shortcode": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/site-logo": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/site-tagline": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/site-title": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/social-link": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/social-links": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/spacer": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/table": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/tag-cloud": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/template-part": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/term-description": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/text-columns": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/verse": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/video": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/widget-area": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/legacy-widget": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/widget-group": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- }
- },
- "patternProperties": {
- "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- }
- },
- "additionalProperties": false
- },
- "stylesPropertiesAndElementsComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- },
- "variations": {
- "$ref": "#/definitions/stylesVariationsPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements", "variations" ]
- }
- ]
- }
- }
- ]
- },
- "stylesVariationsProperties": {
- "type": "object",
- "patternProperties": {
- "^[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/stylesVariationProperties"
- }
- }
- },
- "stylesVariationProperties": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- },
- "blocks": {
- "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements", "blocks" ]
- }
- ]
- }
- }
- ]
- },
- "stylesVariationsPropertiesComplete": {
- "type": "object",
- "patternProperties": {
- "^[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/stylesVariationPropertiesComplete"
- }
- }
- },
- "stylesVariationPropertiesComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- },
- "blocks": {
- "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements", "blocks" ]
- }
- ]
- }
- }
- ]
- },
- "stylesVariationBlocksPropertiesComplete": {
- "type": "object",
- "properties": {
- "core/archives": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/audio": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/avatar": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/block": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/button": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/buttons": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/calendar": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/categories": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/code": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/column": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/columns": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-author-avatar": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-author-name": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-content": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-date": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-edit-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-reply-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-pagination": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-pagination-next": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-pagination-numbers": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-pagination-previous": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comments-title": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/comment-template": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/cover": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/details": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/embed": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/file": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/footnotes": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/freeform": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/gallery": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/group": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/heading": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/home-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/html": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/image": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/latest-comments": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/latest-posts": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/list": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/list-item": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/loginout": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/media-text": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/missing": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/more": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/navigation": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/navigation-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/navigation-submenu": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/nextpage": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/page-list": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/page-list-item": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/paragraph": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-author": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-author-biography": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-author-name": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-comment": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-comments-count": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-comments-form": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-comments-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-content": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-date": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-excerpt": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-featured-image": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-navigation-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-template": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-terms": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/post-title": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/preformatted": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/pullquote": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-no-results": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-pagination": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-pagination-next": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-pagination-numbers": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-pagination-previous": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-title": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/query-total": {
- "$ref": "#/definitions/stylesPropertiesAndElementsComplete"
- },
- "core/quote": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/read-more": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/rss": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/search": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/separator": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/shortcode": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/site-logo": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/site-tagline": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/site-title": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/social-link": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/social-links": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/spacer": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/table": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/tag-cloud": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/template-part": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/term-description": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/text-columns": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/verse": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/video": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/widget-area": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/legacy-widget": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- },
- "core/widget-group": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- }
- },
- "patternProperties": {
- "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
- }
- },
- "additionalProperties": false
- },
- "stylesVariationBlockPropertiesComplete": {
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements" ]
- }
- ]
- }
- }
- ]
- }
- },
- "type": "object",
- "properties": {
- "$schema": {
- "description": "JSON schema URI for theme.json.",
- "type": "string"
- },
- "version": {
- "description": "Version of theme.json to use.",
- "type": "integer",
- "const": 3
- },
- "title": {
- "description": "Title of the styles variation. If not defined, the file name will be used.",
- "type": "string"
- },
- "slug": {
- "description": "Slug of the styles variation. If not defined, the kebab-case title will be used.",
- "type": "string"
- },
- "description": {
- "description": "Description of the styles variation.",
- "type": "string"
- },
- "blockTypes": {
- "description": "List of block types that can use the block style variation this theme.json file represents.",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "settings": {
- "description": "Settings for the block editor and individual blocks. These include things like:\n- Which customization options should be available to the user. \n- The default colors, font sizes... available to the user. \n- CSS custom properties and class names used in styles.\n- And the default layout of the editor (widths and available alignments).",
- "allOf": [
- {
- "$ref": "#/definitions/settingsProperties"
- },
- {
- "type": "object",
- "properties": {
- "useRootPaddingAwareAlignments": {
- "description": "Enables root padding (the values from `styles.spacing.padding`) to be applied to the contents of full-width blocks instead of the root block.\n\nPlease note that when using this setting, `styles.spacing.padding` should always be set as an object with `top`, `right`, `bottom`, `left` values declared separately.",
- "type": "boolean",
- "default": false
- },
- "blocks": {
- "$ref": "#/definitions/settingsBlocksPropertiesComplete"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/settingsPropertyNames"
- },
- {
- "enum": [
- "useRootPaddingAwareAlignments",
- "blocks"
- ]
- }
- ]
- }
- }
- ]
- },
- "styles": {
- "description": "Organized way to set CSS properties. Styles in the top-level will be added in the `body` selector.",
- "allOf": [
- {
- "$ref": "#/definitions/stylesProperties"
- },
- {
- "type": "object",
- "properties": {
- "elements": {
- "$ref": "#/definitions/stylesElementsPropertiesComplete"
- },
- "blocks": {
- "$ref": "#/definitions/stylesBlocksPropertiesComplete"
- },
- "variations": {
- "$ref": "#/definitions/stylesVariationsProperties"
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/stylesPropertyNames"
- },
- {
- "enum": [ "elements", "blocks", "variations" ]
- }
- ]
- }
- }
- ]
- },
- "customTemplates": {
- "description": "Additional metadata for custom templates defined in the templates folder.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Filename, without extension, of the template in the templates folder.",
- "type": "string"
- },
- "title": {
- "description": "Title of the template, translatable.",
- "type": "string"
- },
- "postTypes": {
- "description": "List of post types that can use this custom template.",
- "type": "array",
- "items": {
- "type": "string"
- },
- "default": [ "page" ]
- }
- },
- "required": [ "name", "title" ],
- "additionalProperties": false
- }
- },
- "templateParts": {
- "description": "Additional metadata for template parts defined in the parts folder.",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "name": {
- "description": "Filename, without extension, of the template in the parts folder.",
- "type": "string"
- },
- "title": {
- "description": "Title of the template, translatable.",
- "type": "string"
- },
- "area": {
- "description": "The area the template part is used for. Block variations for `header` and `footer` values exist and will be used when the area is set to one of those.",
- "type": "string",
- "default": "uncategorized"
- }
- },
- "required": [ "name" ],
- "additionalProperties": false
- }
- },
- "patterns": {
- "description": "An array of pattern slugs to be registered from the Pattern Directory.",
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- },
- "required": [ "version" ],
- "additionalProperties": false
-}
diff --git a/gutenberg/schemas/json/wp-env.json b/gutenberg/schemas/json/wp-env.json
deleted file mode 100644
index bc54c6e..0000000
--- a/gutenberg/schemas/json/wp-env.json
+++ /dev/null
@@ -1,163 +0,0 @@
-{
- "title": "JSON schema for WordPress wp-env configuration files",
- "$schema": "http://json-schema.org/draft-07/schema#",
- "definitions": {
- "//": {
- "reference": "https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/"
- },
- "wpEnvProperties": {
- "type": "object",
- "properties": {
- "core": {
- "description": "The WordPress installation to use. If null is specified, wp-env will use the latest production release of WordPress.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "default": null
- },
- "phpVersion": {
- "description": "The PHP version to use. If null is specified, wp-env will use the default version used with production release of WordPress.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "default": null
- },
- "plugins": {
- "description": "A list of plugins to install and activate in the environment.",
- "type": "array",
- "items": {
- "type": "string"
- },
- "default": []
- },
- "themes": {
- "description": "A list of themes to install in the environment.",
- "type": "array",
- "items": {
- "type": "string"
- },
- "default": []
- },
- "port": {
- "description": "The primary port number to use for the installation. You'll access the instance through the port: http://localhost:8888",
- "type": "integer",
- "default": 8888
- },
- "config": {
- "description": "Mapping of wp-config.php constants to their desired values.",
- "type": "object",
- "default": {}
- },
- "mappings": {
- "description": "Mapping of WordPress directories to local directories to be mounted in the WordPress instance.",
- "type": "object",
- "default": {}
- },
- "phpmyadminPort": {
- "description": "The port number to access phpMyAdmin.",
- "type": "integer"
- },
- "multisite": {
- "description": "Whether to set up a multisite installation.",
- "type": "boolean"
- }
- }
- },
- "wpEnvPropertyNames": {
- "enum": [
- "core",
- "phpVersion",
- "plugins",
- "themes",
- "port",
- "config",
- "mappings",
- "phpmyadminPort",
- "multisite"
- ]
- }
- },
- "allOf": [
- {
- "$ref": "#/definitions/wpEnvProperties"
- },
- {
- "type": "object",
- "properties": {
- "$schema": {
- "type": "string"
- },
- "env": {
- "description": "The key env is available to override any of the above options on an individual-environment basis.",
- "type": "object",
- "patternProperties": {
- "[a-zA-Z]": {
- "allOf": [
- { "$ref": "#/definitions/wpEnvProperties" },
- {
- "type": "object",
- "propertyNames": {
- "$ref": "#/definitions/wpEnvPropertyNames"
- }
- }
- ]
- }
- },
- "default": {}
- },
- "testsPort": {
- "description": "The port number for the test site. You'll access the instance through the port: http://localhost:8889",
- "type": "integer",
- "default": 8889
- },
- "lifecycleScripts": {
- "description": "Mapping of commands that should be executed at certain points in the lifecycle.",
- "type": "object",
- "default": {},
- "properties": {
- "afterStart": {
- "description": "Runs after wp-env start has finished setting up the environment.",
- "type": "string"
- },
- "afterClean": {
- "description": "Runs after wp-env clean has finished cleaning the environment.",
- "type": "string"
- },
- "afterDestroy": {
- "description": "Runs after wp-env destroy has destroyed the environment.",
- "type": "string"
- }
- }
- }
- }
- },
- {
- "type": "object",
- "propertyNames": {
- "anyOf": [
- {
- "$ref": "#/definitions/wpEnvPropertyNames"
- },
- {
- "enum": [
- "$schema",
- "env",
- "testsPort",
- "lifecycleScripts"
- ]
- }
- ]
- }
- }
- ]
-}
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 0000000..2c1ff59
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,17 @@
+// Jest configuration for TypeScript testing
+// eslint-disable-next-line @typescript-eslint/no-require-imports
+const { defaults: tsjPreset } = require('ts-jest/presets'); // TypeScript Jest presets
+
+module.exports = {
+ testEnvironment: 'node',
+ testMatch: ['**/tests/**/*.test.js', '**/tests/**/*.test.ts'],
+ verbose: true,
+ transform: {
+ '^.+\\.[jt]sx?$': 'babel-jest',
+ },
+ moduleFileExtensions: ['js', 'ts', 'jsx', 'tsx', 'json'],
+ coverageDirectory: './coverage',
+ collectCoverage: true,
+ collectCoverageFrom: ['src/**/*.{js,ts}', 'tests/**/*.{js,ts}'],
+ testPathIgnorePatterns: ['/node_modules/'],
+};
diff --git a/jest.config.json.bak b/jest.config.json.bak
new file mode 100644
index 0000000..7236ca3
--- /dev/null
+++ b/jest.config.json.bak
@@ -0,0 +1,9 @@
+{
+ "testEnvironment": "node",
+ "collectCoverageFrom": ["scripts/**/*.js", "!scripts/**/node_modules/**", "!**/coverage/**"],
+ "coverageDirectory": "coverage",
+ "coverageReporters": ["text", "lcov", "html"],
+ "testMatch": ["**/__tests__/**/*.js", "**/?(*.)+(spec|test).js"],
+ "verbose": true,
+ "clearMocks": true
+}
diff --git a/launch.json b/launch.json
new file mode 100644
index 0000000..55cb646
--- /dev/null
+++ b/launch.json
@@ -0,0 +1,50 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Debug Node.js Script",
+ "type": "node",
+ "request": "launch",
+ "program": "${workspaceFolder}/scripts/${input:scriptName}.js",
+ "console": "integratedTerminal",
+ "internalConsoleOptions": "neverOpen"
+ },
+ {
+ "name": "Debug Current File",
+ "type": "node",
+ "request": "launch",
+ "program": "${file}",
+ "console": "integratedTerminal",
+ "internalConsoleOptions": "neverOpen",
+ "skipFiles": ["/**"]
+ },
+ {
+ "name": "Jest Tests",
+ "type": "node",
+ "request": "launch",
+ "program": "${workspaceFolder}/node_modules/.bin/jest",
+ "args": ["--runInBand"],
+ "console": "integratedTerminal",
+ "internalConsoleOptions": "neverOpen",
+ "disableOptimisticBPs": true
+ },
+ {
+ "name": "Jest Current File",
+ "type": "node",
+ "request": "launch",
+ "program": "${workspaceFolder}/node_modules/.bin/jest",
+ "args": ["${fileBasenameNoExtension}", "--runInBand"],
+ "console": "integratedTerminal",
+ "internalConsoleOptions": "neverOpen",
+ "disableOptimisticBPs": true
+ }
+ ],
+ "inputs": [
+ {
+ "id": "scriptName",
+ "description": "Script name (without .js extension)",
+ "default": "validate-frontmatter",
+ "type": "promptString"
+ }
+ ]
+}
diff --git a/mcp.json b/mcp.json
new file mode 100644
index 0000000..06402e0
--- /dev/null
+++ b/mcp.json
@@ -0,0 +1,17 @@
+{
+ "mcpServers": {
+ // GitHub MCP Server with full support (repos, issues, PRs, Copilot Spaces)
+ "github": {
+ "command": "npx",
+ "args": ["@modelcontextprotocol/server-github"],
+ "env": {
+ "GITHUB_AUTH_TYPE": "oauth"
+ }
+ },
+ // Filesystem MCP Server for local documentation access
+ "filesystem": {
+ "command": "npx",
+ "args": ["@modelcontextprotocol/server-filesystem", "/Users/ash/Studio/non-wordpress/wp-docs"]
+ }
+ }
+}
diff --git a/wp-docs.code-workspace b/wp-docs.code-workspace
index d181aa1..e1547a6 100644
--- a/wp-docs.code-workspace
+++ b/wp-docs.code-workspace
@@ -7,7 +7,8 @@
],
"settings": {
"editor.formatOnSave": true,
- "files.insertFinalNewline": true
+ "files.insertFinalNewline": true,
+ "git.ignoreLimitWarning": true
},
"extensions": {
"recommendations": [
From 7f899b2484a036b3608945e4c0ce4564ab867a70 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 23 Oct 2025 05:02:06 +0000
Subject: [PATCH 4/4] Initial plan