Home
Softono
a

automattic

Professional software vendor delivering innovative solutions on the Softono platform. Specialized in both open-source and proprietary software development.

Total Products
23

Software by automattic

harper
Open Source

harper

<div id="header" align="center"> <img src="logo.svg" width="400px" /> <h1>Harper</h1> </div> [![Harper Binaries](https://github.com/automattic/harper/actions/workflows/binaries.yml/badge.svg)](https://github.com/automattic/harper/actions/workflows/binaries.yml) [![Website](https://github.com/automattic/harper/actions/workflows/build_web.yml/badge.svg)](https://github.com/automattic/harper/actions/workflows/build_web.yml) [![Checks](https://github.com/automattic/harper/actions/workflows/just_checks.yml/badge.svg)](https://github.com/automattic/harper/actions/workflows/just_checks.yml) [![Crates.io](https://img.shields.io/crates/v/harper-ls)](https://crates.io/crates/harper-ls) ![NPM Version](https://img.shields.io/npm/v/harper.js) ![Downloads](https://img.shields.io/github/downloads/automattic/harper/total?label=Binary+Downloads) ![Obsidian Plugin Downloads](https://img.shields.io/github/downloads/automattic/harper-obsidian-plugin/total?label=Obsidian+Plugin+Downloads) Harper is an English grammar checker designed to be _just right._ I created it after years of dealing with the shortcomings of the competition. Grammarly was too expensive and too overbearing. Its suggestions lacked context, and were often just plain _wrong_. Not to mention: it's a privacy nightmare. Everything you write with Grammarly is sent to their servers. Their privacy policy claims they don't sell the data, but that doesn't mean they don't use it to train large language models and god knows what else. Not only that, but the round-trip-time of the network request makes revising your work all the more tedious. LanguageTool is great, if you have gigabytes of RAM to spare and are willing to download the ~16GB n-gram dataset. Besides the memory requirements, I found LanguageTool too slow: it would take several seconds to lint even a moderate-size document. That's why I created Harper: it is the grammar checker that fits my needs. Not only does it take milliseconds to lint a document, take less than 1/50th of LanguageTool's memory footprint, but it is also completely private. Harper is even small enough to load via [WebAssembly.](https://writewithharper.com) ## Language Support Harper currently only supports English, but the core is extensible to support other languages, so we welcome contributions that allow for other language support. ## Performance Issues We consider long lint times bugs. If you encounter any significant performance issues, please create an issue on the topic. If you find a fix to any performance issue, we would appreciate the contribution. Just please make sure to read [our contribution guidelines first.](https://writewithharper.com/docs/contributors/introduction) ## Links - [Frequently Asked Questions](https://writewithharper.com/#faqs) - [Obsidian Documentation](https://writewithharper.com/docs/integrations/obsidian) - [`harper-ls` Documentation](https://writewithharper.com/docs/integrations/language-server) - Supported Editors' Documentation - [Visual Studio Code](https://writewithharper.com/docs/integrations/visual-studio-code) - [Neovim](https://writewithharper.com/docs/integrations/neovim) - [Helix](https://writewithharper.com/docs/integrations/helix) - [Emacs](https://writewithharper.com/docs/integrations/emacs) - [Zed](https://writewithharper.com/docs/integrations/zed) - [`harper.js` Documentation](https://writewithharper.com/docs/harperjs/introduction) - [Official Discord Server](https://discord.com/invite/JBqcAaKrzQ) ## Huge Thanks This project would not be possible without the hard work from those who [contribute](https://writewithharper.com/docs/contributors/introduction). <a href="https://github.com/automattic/harper/graphs/contributors"> <img src="https://contrib.rocks/image?repo=automattic/harper" /> </a> Harper's logo was designed by [Lukas Werner](https://lukaswerner.com/).

Code Quality & Linting Web Browsers
10.8K Github Stars
jetpack
Open Source

jetpack

# Jetpack Monorepo [![License](https://poser.pugx.org/automattic/jetpack/license.svg)](https://www.gnu.org/licenses/gpl-2.0.html) This is the Jetpack Monorepo. It contains source code for the different Jetpack plugins, Composer and JavaScript packages used by the plugins, and other things. ## How to install Jetpack plugin on your site **If you are not planning on developing with Jetpack, you should install Jetpack from pre-built sources.** Details on that may be found [on this page](https://github.com/Automattic/jetpack-production#jetpack). ## Developing from the Monorepo If you're interested in developing with the Jetpack monorepo, you can check out the [Quick Start Guide here](./docs/quick-start.md). ### Installation From Git Monorepo To run the Jetpack plugin from the monorepo, you'll first need to build it. To do so, [follow the instructions here](./docs/development-environment.md). If you're using the [Docker development environment](./docs/development-environment.md#docker-supported-recommended), you should then be all set. If not, you'll need to create a link to the Jetpack plugin from your WordPress `wp-content/plugins` folder (you cannot clone the monorepo into your WordPress plugins directory - you will see a warning on your plugins page if so saying that the Jetpack Monorepo is not a plugin and shouldn't be installed as one). You'll need to know the filesystem path to the monorepo checkout and to your WordPress installation. Then, on Linux or Mac OS X, open a terminal and use `ln -s` to create the link, something like ``` ln -s /path/to/jetpack-monorepo/projects/plugins/jetpack /path/to/wordpress/wp-content/plugins/jetpack ``` On Windows (Vista and later), open an Administrator Command Prompt window and use `mklink /D` similarly. ## Contribute Thank you for thinking about contributing to Jetpack! If you're unsure of anything, feel free to submit an issue or pull request on any topic. The worst that can happen is that you'll be politely directed to the best location to ask your question or to change something in your pull request. There are a variety of options for how you can help: - [Write and submit patches](./docs/CONTRIBUTING.md#write-and-submit-a-patch). - If you found a bug, [file a report here](https://github.com/Automattic/jetpack/issues/new?assignees=&labels=%5BType%5D+Bug&template=bug-report.yml). You can [check our recommendations to create great bug reports here](./docs/guides/report-bugs.md). - [Join our Jetpack Beta program](./docs/testing/beta-testing.md) and help us test new releases. - [Translate Jetpack in your language](./docs/translations.md). To clarify these expectations, Jetpack has adopted the code of conduct defined by the Contributor Covenant. It can be read in full [here](CODE-OF-CONDUCT.md). ## Security Need to report a security vulnerability? Go to [https://automattic.com/security/](https://automattic.com/security/) or directly to our security bug bounty site [https://hackerone.com/automattic](https://hackerone.com/automattic). ## License Jetpack is licensed under [GNU General Public License v2 (or later)](./LICENSE.txt). <!-- end sync section --> ## Join us! Interested in working on awesome open-source code all day? [Join us](https://automattic.com/work-with-us/)!

WordPress Themes & Plugins
1.8K Github Stars
sensei
Open Source

sensei

# Sensei LMS - Online Courses, Quizzes, & Learning [![Trunk Workflow](https://github.com/Automattic/sensei/actions/workflows/trunk.yml/badge.svg)](https://github.com/Automattic/sensei/actions/workflows/trunk.yml) Welcome to the repository of the Sensei LMS project, an open-source Learning Management System (LMS) built specifically for WordPress. Sensei LMS provides a robust and intuitive platform for creating, managing, and delivering online courses, quizzes, and learning experiences. Whether you're an educator or simply passionate about sharing knowledge online, our platform is designed with you in mind. With seamless integration into the WordPress ecosystem, including compatibility with any WordPress theme, you'll have everything you need to create engaging and effective online content. Our aim is to empower you with an efficient and user-friendly toolset that helps you create a top-notch e-learning experience. We're committed to the open-source community and we welcome contributions from developers. To learn more about contributing, please check out our [Contributing Guide](CONTRIBUTING.md). ## Key Features ### For Educators - **Guest Access Support**: Allow unregistered users to explore course content, providing a sneak peek of what your courses have to offer. - **Preview as Student support**: Enable teachers to preview courses as if they were students, allowing for comprehensive quality control and review. - **Course Management**: Easily manage courses, enrollments, and student progress with Sensei LMS's intuitive interface. - **Analytics and Reporting**: Keep track of student progress and course performance with detailed reports and analytics. - **Block Editor Support**: Easily build and design course content with WordPress's block editor, which provides a seamless content creation experience. - **Learning Mode**: Create a distraction-free learning environment with Sensei LMS's custom Learning Mode. It appears only for Sensei lessons and is fully customizable via the site editor, providing endless flexibility for editing the header and sidebar of the theme visually. - **Mailpoet Integration**: Streamline email communications and marketing campaigns with seamless integration of the popular Mailpoet plugin. ### For Developers - **Open Source**: Sensei LMS is licensed under GPLv2, the same as used by WordPress, ensuring that you have the freedom to use, modify, and distribute it to suit your needs. - **Flexible Iitegration with third-party code**: Sensei LMS's source code is widely documented and provides several hooks for seamless integration with other WordPress plugins and themes. This flexibility allows for easy customization and provides endless possibilities for creating new and exciting features. - **Complete Testing Suite**: Ensure the reliability and stability of the Sensei LMS project with a comprehensive suite of unit tests. ## Get More Features with Sensei Pro - **Sell Courses**: Sell online courses using WooCommerce integration. - **Content Drip** - Schedule student access to lessons based on a specific date or a number of days/weeks after starting a course. - **Advanced Groups** - Add students to customizable groups to manage course access, show/hide content, and run reports. - **Quiz Timer** - Set a time limit for quizzes and display a countdown timer to students. - **Updates and Support**: Get 1 year of updates and support included, ensuring a seamless experience and continued improvements. - **Collaboration**: Collaborate with co-teachers to create and manage course content, providing a comprehensive learning experience. - **Interactive Blocks**: Create interesting lessons using flashcards, image hotspots and interactive videos for the best learning experience. - And [much more](https://senseilms.com/sensei-pro/#features). ## Managed Hosting with Sensei Bundle - **Powered by WordPress.com**: Get the most out of Sensei Pro by running it on the managed WordPress.com infrastructure with the Sensei Bundle. **Video Upload**: Have 200GB of space for uploading videos for VideoPress that integrate seamlessly with Sensei courses - **Real Time Backups**: Every part of your website is backed up in real-time. Need to restore something? It's just a single click. - **1 year Free domain**: Choose an annual plan, and register a new domain name at no extra cost for the first year - And [much more](https://wordpress.com/create-a-course/). ## Test the Platform If you're interested in trying out the Sensei LMS and Sensei Pro features, you can test it out for free with our demo available at [https://senseilms.com/demo](https://senseilms.com/demo). Get a feel for the platform's capabilities and see if it's the right fit for your needs. ## Installation To get started with Sensei LMS, follow either of these steps: ### Automatic installation Automatic installation is the easiest option as WordPress handles the file transfers itself and you don't even need to leave your web browser. To do an automatic install: 1. Log in to your WordPress admin panel 2. Navigate to the Plugins menu and click Add New. 3. In the search field type "**Sensei LMS**" and click Search Plugins. 4. Once you've found the plugin you can view details about it such as the point release, rating and description. Most importantly of course, you can install it by clicking _Install Now_. 4. Activate the plugin by clicking the _Activate_ button. 5. Create your first course and start sharing knowledge! ### Manual installation The manual installation method involves downloading the plugin and uploading it to your web server via your favorite file transfer application. 1. [Download the plugin file from the WordPress.org repository](https://downloads.wordpress.org/plugin/sensei-lms.latest-stable.zip) to your computer and unzip it 2. Using an FTP program, or your hosting control panel, upload the unzipped plugin folder to your WordPress installation's `wp-content/plugins/` directory. 3. Activate the plugin from the Plugins menu within the WordPress admin. 4. Create your first course and start sharing knowledge! ## Documentation To learn more about the Sensei LMS project and how to use it effectively, check out our comprehensive [Documentation](https://senseilms.com/documentation/). Automattician? Read more at: PCYsg-15ed-p2 ## Community and Support Join the growing community of Sensei LMS users and developers! Share your ideas, ask questions, and provide feedback through our [community forums](https://educatorsp2.wordpress.com/), or contact us at our [Free Support Forum](https://wordpress.org/support/plugin/sensei-lms/). For support for our paid products, please contact us through our [Support Portal](https://wordpress.org/support/plugin/sensei-lms/). ## Contributing to Sensei LMS See our [guidelines for Contributing to Sensei LMS](https://github.com/Automattic/sensei/blob/trunk/CONTRIBUTING.md) ## Stay Up-to-Date with Sensei Don't miss out on the latest Sensei LMS news, updates, and tips! [Follow our blog](https://senseilms.com/blog) to stay up-to-date with everything related to Sensei. Our team of experts regularly publishes new articles, tutorials, and resources to help you get the most out of Sensei and stay on top of the latest trends in online education. Whether you're an educator or developer, our blog has something for everyone. [Subscribe to our newsletter](https://senseilms.com/mailing-list/) to get the latest updates delivered right to your inbox, and never miss a beat with Sensei LMS.

WordPress Themes & Plugins
586 Github Stars
wordpress-activitypub
Open Source

wordpress-activitypub

# ActivityPub This is the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/) repo. Enter the fediverse with **ActivityPub**, broadcasting your blog to a wider audience! Attract followers, deliver updates, and receive comments from a diverse user base of **ActivityPub**-compliant platforms. ## Demo You can test out the plugin (settings) with [WordPress Playground](https://wordpress.org/plugins/activitypub/?preview=1). > [!NOTE] > [WordPress Playground](https://wordpress.org/playground/) is the platform that lets you run WordPress instantly on any device without a host. It’s your place to build, experiment, test, and grow. ## Documentation - [Developer Documentation](docs/developer-docs.md) - Guide for developers working with the plugin. - [Development Environment](docs/development-environment.md) - Setting up your development environment. - [Pull Request Guidelines](docs/pull-request.md) - How to submit pull requests. - [Release Process](docs/release-process.md) - Guide for releasing new versions. - [Translations](docs/translations.md) - Information about translating the plugin. - [Snippets](snippets/) - Community-contributed snippets to extend or customize the plugin. ## Federation ActivityPub is a protocol for federated social networks, enabling communication between different platforms. For details on what the plugin supports, refer to the [FEDERATION.md](FEDERATION.md) file. ## Support If you need help, [check out the support forums on WordPress.org](https://wordpress.org/support/plugin/activitypub/). ## Contribute Thank you for thinking about contributing to the ActivityPub plugin! We welcome contributions of all kinds, but to keep things productive for everyone, please follow these guidelines: * **Keep issues clear and focused.** If you're reporting a bug, please use the [bug report form](https://github.com/Automattic/wordpress-activitypub/issues/new?q=sort%3Aupdated-desc+is%3Aissue+is%3Aopen&template=bug_report.yml). For feature ideas, please share them in [Discussions](https://github.com/Automattic/wordpress-activitypub/discussions) so we can consider them together. * **Stay relevant to the plugin's scope.** Issues and comments should relate directly to improving this plugin. Tangential ideas or unrelated feature requests will be closed. * **Be concise.** Short, actionable descriptions are much easier for maintainers to respond to. * **Respectful collaboration.** We follow the [Contributor Covenant Code of Conduct](./CODE_OF_CONDUCT.md). Please keep your contributions constructive and professional. Other ways to help include: * Writing and submitting patches. * Translating the ActivityPub plugin into your language ([translate here](https://translate.wordpress.org/projects/wp-plugins/activitypub/)). ## Security Need to report a security vulnerability? Go to https://automattic.com/security/ or directly to our security bug bounty site https://hackerone.com/automattic. You can find more information on reporting security vulnerabilities in our [SECURITY.md](./SECURITY.md) file. ## License The ActivityPub plugin is licensed under the [MIT license](./LICENSE). ## Join us! Interested in working on awesome open-source code all day? [Join us](https://automattic.com/work-with-us/)!

WordPress Themes & Plugins
570 Github Stars
edit-flow
Open Source

edit-flow

# Edit Flow Contributors: batmoo, danielbachhuber, sbressler, automattic, garyj Donate link: http://editflow.org/contribute/ Tags: workflow, editorial, editorial calendar, custom status, newsroom Requires at least: 6.4 Requires PHP: 7.4 Tested up to: 6.9 Stable tag: 0.10.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Redefining your editorial workflow. ## Description Edit Flow empowers you to collaborate with your editorial team inside WordPress. We've made it modular so you can customize it to your needs: * [Calendar](http://editflow.org/features/calendar/) - A convenient month-by-month look at your content. * [Custom Statuses](http://editflow.org/features/custom-statuses/) - Define the key stages to your workflow. * [Editorial Comments](http://editflow.org/features/editorial-comments/) - Threaded commenting in the admin for private discussion between writers and editors. * [Editorial Metadata](http://editflow.org/features/editorial-metadata/) - Keep track of the important details. * [Notifications](http://editflow.org/features/notifications/) - Receive timely updates on the content you're following. * [Story Budget](http://editflow.org/features/story-budget/) - View your upcoming content budget. * [User Groups](http://editflow.org/features/user-groups/) - Keep your users organized by department or function. More details for each feature, screenshots and documentation can be found on [our website](http://editflow.org/). We'd love to hear from you! For support questions, feedback and ideas, please use the [WordPress.org forums](https://wordpress.org/support/plugin/edit-flow/), which we look at often. If you'd like to contribute code, [we'd love to have you involved](http://editflow.org/contribute/). ## Installation The easiest way to install this plugin is to go to Add New in the Plugins section of your blog admin and search for "Edit Flow." On the far right side of the search results, click "Install." If the automatic process above fails, follow these simple steps to do a manual install: 1. Extract the contents of the zip file into your `/wp-content/plugins/` directory 2. Activate the plugin through the 'Plugins' menu in WordPress 3. Write and enjoy the merits of a structured editorial workflow! ## Frequently Asked Questions ### Does Edit Flow work with multisite? Yep, in the sense that you can activate Edit Flow on each subsite. Edit Flow doesn't yet offer the ability to manage content across a network of sites. ### Edit Flow doesn't do X, Y, and Z. That makes me sad. All development happens on [GitHub](https://github.com/Automattic/Edit-Flow). For support questions, feedback and ideas, please use the [WordPress.org forums](https://wordpress.org/support/plugin/edit-flow/), which we look at often. For everything else, say [[email protected]](mailto:[email protected]). ## Screenshots 1. The calendar is a convenient month-by-month look at your content. Filter to specific statuses or categories to drill down. 2. Custom statuses allow you to define the key stages of your workflow. 3. Editorial comments allow for private discussion between writers and editors on a post-by-post basis. 4. Keep track of the important details with editorial metadata. 5. View all of your upcoming posts with the more traditional story budget view, and hit the print button to take it to your planning meeting. ## Changelog See [CHANGELOG.md](https://github.com/Automattic/edit-flow/blob/develop/CHANGELOG.md) for the full changelog.

Project Management WordPress Themes & Plugins
364 Github Stars
co-authors-plus
Open Source

co-authors-plus

# Co-Authors Plus Stable tag: 4.0.2 Requires at least: 6.4 Tested up to: 7.0 Requires PHP: 7.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: authors, users, multiple authors, co-authors, multi-author Contributors: batmoo, danielbachhuber, automattic, GaryJ Assign multiple bylines to posts, pages, and custom post types with a search-as-you-type input box. ## Description Assign multiple bylines to posts, pages, and custom post types via a search-as-you-type input box. Co-authored posts appear on a co-author's archive page and in their feed. Co-authors may edit the posts they are associated with, and co-authors who are contributors may only edit posts if they have not been published (as is core behavior). Add writers as bylines without creating WordPress user accounts. Simply [create a guest author profile](https://github.com/Automattic/Co-Authors-Plus/wiki/Creating-and-editing-guest-authors) for the writer and assign the byline as you normally would. On the frontend, use the [Co-Authors Plus template tags](https://github.com/Automattic/Co-Authors-Plus/wiki/Template-tags) or the [block editor blocks](https://github.com/Automattic/Co-Authors-Plus/wiki/Blocks) to list co-authors anywhere you'd normally list the author. ## Documentation - **Usage** — themer and site-owner guides live on the [GitHub Wiki](https://github.com/Automattic/Co-Authors-Plus/wiki): template tags, blocks, guest author management, and multisite. - **Developer reference** — lives in-repo under [`docs/`](./docs/) (not bundled in the distribution ZIP): - [Filters and actions](./docs/filters.md) - [REST API](./docs/rest-api.md) - [Upgrading to 4.0](./docs/upgrading-to-4.0.md) Co-Authors Plus is an almost complete rewrite of the [Co-Authors](https://wordpress.org/plugins/co-authors/) plugin originally developed by Weston Ruter (2007). The original plugin was inspired by the '[Multiple Authors](https://txfx.net/2005/08/16/new-plugin-multiple-authors/)' plugin by Mark Jaquith (2005). ## Installation 1. IMPORTANT: If you are using the original Co-Authors plugin, disable it before installing Co-Authors Plus. 2. Extract the co-authors-plus.zip file and upload its contents to the `/wp-content/plugins/` directory. Alternately, you can install directly from the Plugin directory within your WordPress Install. 3. Activate the plugin through the "Plugins" menu in WordPress. 4. Place [co-authors template tags](https://github.com/Automattic/Co-Authors-Plus/wiki/Template-tags) in your template. 5. Add co-authors to your posts and pages. ## Screenshots 1. Multiple authors can be added to a Post, Page, or Custom Post Type using an auto-complete interface. 2. Guest authors allow you to assign bylines without creating WordPress user accounts. You can also override existing WordPress account meta by mapping a guest author to a WordPress user. ## Frequently Asked Questions ### How do I add Co-Authors Plus support to my theme? If you've just installed Co-Authors Plus, you might notice that the bylines are being added in the backend but aren't appearing on the front end. You'll need to [add the template tags to your theme](https://github.com/Automattic/Co-Authors-Plus/wiki/Template-tags) before the bylines will appear. ### What happens to posts and pages when I delete a user assigned to a post or page as a co-author? When a user is deleted from WordPress, they will be removed from all posts for which they are co-authors. If you reassign their posts to another user, that user will be the co-author instead. ### Can I use Co-Authors Plus with WordPress multisite? Yes! You can [use Co-Authors Plus on WordPress multisite](https://github.com/Automattic/Co-Authors-Plus/wiki#wordpress-multisites). Co-Authors Plus can be activated on a site-by-site basis or network-activated. If you create guest authors, however, those guest authors will exist on a site-by-site basis. ### Who needs permission to do what? A WordPress user will need the `edit_others_posts` capability to assign co-authors to posts. This is typically granted to the Editor role but can be altered with the `coauthors_plus_edit_authors` filter. A WordPress user will need the `list_users` capability to create new guest author profiles. This is typically granted to the Administrator role but can be altered with the `coauthors_guest_author_manage_cap` filter. ### Can I easily create a list of all co-authors? Yes! You can [create a list of all co-authors with a template tag](https://github.com/Automattic/Co-Authors-Plus/wiki/Template-tags#create-a-list-of-all-co-authors) `coauthors_wp_list_authors()` template tag. This template tag accepts many of the same arguments as `wp_list_authors()`. Look in `template-tags.php` for more details. ### Can I disable Guest Authors? Yes! You can disable guest authors entirely through a filter. Having the following line load on `init` will do the trick: `add_filter( 'coauthors_guest_authors_enabled', '__return_false' )` ## Change Log [View the change log](https://github.com/Automattic/co-authors-plus/blob/develop/CHANGELOG.md).

WordPress Themes & Plugins HR & Payroll
317 Github Stars
liveblog
Open Source

liveblog

# Liveblog Contributors: automattic, garyj, nbachiyski, batmoo, johnjamesjacoby, philipjohn Tags: liveblog, live blog, real-time, news, sports Requires at least: 6.4 Requires PHP: 7.4 Tested up to: 6.9 Stable tag: 1.12.1 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Empowers website owners to provide rich and engaging live event coverage to a large, distributed audience. ## Description Your readers want your updates as quickly as possible, and we think we provide the easiest and most flexible publishing environment to make that happen. Sometimes though, that's just not enough. When you're covering a fast-paced event — the latest Apple unveiling, an F1 Grand Prix or the Super Bowl — a full blog post for each individual update is a poor experience for your authors and your audience. The [WordPress.com VIP Liveblog Add-On](https://wpvip.com/) was purpose-built to address these issues. Here's what makes it special: * Post updates right from the front end of your site (no need to use the `/wp-admin` dashboard). * Viewers of your liveblog get new entries served to them instantly and automatically, without needing to refresh. * Authors can drag and drop photos straight into the liveblog area, without separate browser tabs or windows. * No need for a separate site dedicated to liveblogging — every post can be a liveblog, even existing ones. If you'd like to check out the code and contribute, [join us on GitHub](https://github.com/Automattic/liveblog) — pull requests are more than welcome. ## Installation 1. Upload the `liveblog` folder to your plugins directory (e.g. `/wp-content/plugins/`). 2. Activate the plugin through the 'Plugins' menu in WordPress. 3. Enable the liveblog on any post's edit page. ## Screenshots 1. The entry form is the simplest possible. 2. Writers can preview before posting. 3. New posts are highlighted. 4. Adding images is a matter of just drag and drop. 5. Dragged photos are automatically inserted. 6. Typical liveblog view. ## Documentation Developer and end-user documentation lives in the [`docs/`](https://github.com/Automattic/liveblog/tree/develop/docs) directory: * [End user guide](https://github.com/Automattic/liveblog/blob/develop/docs/end-user-guide.md) — for editors and site administrators. * [Customization](https://github.com/Automattic/liveblog/blob/develop/docs/customization.md) — entry features, key events, hashtags, commands, emoji, shortcodes, template overrides. * [Extending the admin meta box](https://github.com/Automattic/liveblog/blob/develop/docs/admin-meta-box.md) * [Hooking into entries](https://github.com/Automattic/liveblog/blob/develop/docs/entry-hooks.md) * [Auto-archiving](https://github.com/Automattic/liveblog/blob/develop/docs/auto-archive.md) * [WebSocket support](https://github.com/Automattic/liveblog/blob/develop/docs/websockets.md) ## Contributing See [CONTRIBUTING.md](https://github.com/Automattic/liveblog/blob/develop/CONTRIBUTING.md) for how to set up the development environment and submit changes. ## Changelog See the [full changelog on GitHub](https://github.com/Automattic/liveblog/blob/develop/CHANGELOG.md).

WordPress Themes & Plugins Screen Recording & Cast
313 Github Stars
syntaxhighlighter
Open Source

syntaxhighlighter

# SyntaxHighlighter Evolved [![WordPress Plugin Version](https://img.shields.io/wordpress/plugin/v/syntaxhighlighter.svg?style=flat-square)](https://wordpress.org/plugins/syntaxhighlighter/) [![WordPress Tested](https://img.shields.io/wordpress/v/syntaxhighlighter.svg?style=flat-square)](https://wordpress.org/plugins/syntaxhighlighter/) [![WordPress Plugin Downloads](https://img.shields.io/wordpress/plugin/dt/syntaxhighlighter.svg?style=flat-square)](https://wordpress.org/plugins/syntaxhighlighter/advanced/) [![WordPress Plugin Rating](https://img.shields.io/wordpress/plugin/r/syntaxhighlighter.svg?style=flat-square)](https://wordpress.org/support/plugin/syntaxhighlighter/reviews/) Easily post syntax-highlighted code to your WordPress site without having to modify the code at all. As seen on WordPress.com. Supports the new Gutenberg editor! ## Block Development Workflow Source code is located in the `src` folder. Run `npm install` to install all of the required modules. When making changes to the block: * Run `npm start` to build a development version with file watching. * Run `npm run build` to build a minified production file.

WordPress Themes & Plugins Documentation
250 Github Stars
babble
Open Source

babble

# Babble * Tags: translations, translation, multilingual, i18n, l10n, localisation * Requires at least: 3.5.1 * Tested up to: 4.1.1 * Stable tag: 1.5.1 * License: GPLv2 or later * License URI: http://www.gnu.org/licenses/gpl-2.0.html Multilingual WordPress done right. ## Description This plugin is at a beta stage for translating: * Posts * Pages * Custom post types * Categories * Tags * Custom taxonomies. It is powering a live site at http://freespeechdebate.com/. The plugin was built with an aversion to both additional database tables, additional columns or column changes and a desire to keep additional queries to a minimum. The plugin is (in theory) compatible with WordPress.com VIP and was built with this platform in mind. There are a **lot** of `@FIXME` comments, expressing doubts, fears, uncertainties and unknowns; feel free to weigh in on any of them. Please add bugs and contribute patches and pull requests to https://github.com/cftp/babble/issues **Pull requests on the *develop* branch, please, not the master branch.** Contributors: Simon Wheatley, John Blackbourn, Scott Evans, Simon Dickson, Marko Heijnen, Tom Nowell, Gary Jones, Emyr Thomas ## Installation Installation is fairly standard: 1. Upload the `babble` directory to the `/wp-content/plugins/` directory 2. Ensure pretty permalinks are activated in Settings -> Permalinks, not sure how it will cope without these! 3. Activate the plugin through the 'Plugins' menu in WordPress 4. You'll now be prompted to set the languages you want, you can pick from any of the language packs you've got installed 5. You'll notice the language switcher menu in the admin bar, use this to switch languages and (depending on context) to create new versions of the content you are looking at (from the front end) or editing (from the admin area) ## Screenshots ![Trigger a translation from the post edit screen](screenshot-1.png "Trigger a translation from the post edit screen") _Trigger a translation from the post edit screen_ ![View the jobs in the translation queue](screenshot-2.png "View the jobs in the translation queue") _View the jobs in the translation queue_ ![Add the translation on the translation editor](screenshot-3.png "Add the translation on the translation editor") _Add the translation on the translation editor_ ## Changelog ### 1.5.1 * Fix for not syncing when updating post meta (#261) ### 1.5 * New functionality for translating post meta data. * New option to immediately create blank translations when a translation job is open. * Use the default language text direction for translations which have empty content. * Visual tweaks to the translation editing screen. ### 1.4.4 * Load the interface textdomain when loading and displaying the admin toolbar on the front end. * Correctly set the interface language and content language separately from each other. * The WPLANG constant is deprecated since WP 4.0. We now give preference to the WPLANG option when setting the defaults. * Fix registration of 'term_translation' taxonomy. * Fix breaking rewrite rules starting with ^. * Various corrections to templates and body classes. * Various smaller bug fixes. ### 1.4.3 * Fix the single post template names * Update the bundled External Update API library ### 1.4.2 * Fix the language switcher widget so it correctly displays language names ### 1.4.1 * Add the External Update API library to serve updates to Babble from GitHub ### 1.4 * ENHANCEMENT: Translation job UI and workflow * ENHANCEMENT: Separation of admin language setting from the content language * Various fixes and enhancements *gap of time while we add various things* ### alpha 1.1 * Taxonomy terms. ### alpha 1 * Proof of concept concentrating on the translation of posts. Taxonomies and menus are not handled yet. Widgets are out of scope completely for this phase of work.

CMS & Blogging WordPress Themes & Plugins
250 Github Stars
custom-metadata
Open Source

custom-metadata

# Custom Metadata Manager for WordPress This code-only developer WordPress plugin allows you to add custom fields to your object types (post, pages, custom post types, users) This is a WordPress Plugin. We sync changes between github and the [WordPress.org plugin repository](http://wordpress.org/extend/plugins/custom-metadata/). Why? Because collaboration is made much easier on github :) **NOTE**: The plugin requires WordPress 3.5+ # Installation 1. Install through the WordPress admin or upload the plugin folder to your `/wp-content/plugins/` directory 2. Activate the plugin through the 'Plugins' menu in WordPress 3. Add the necessary code to register your custom groups and fields to your functions.php or plugin. 4. Enjoy! # Frequently Asked Questions ## Why a code-based approach instead of a UI? Because the UI thing has [been](http://wordpress.org/extend/plugins/verve-meta-boxes/) [done](http://wordpress.org/extend/plugins/fresh-page/) [before](http://wordpress.org/extend/plugins/pods/). And this more closely aligns with the existing WordPress approach of registering new types of content (post types, taxonomies, etc.) This is also a developer feature, aimed towards site builders. And real developers don't need UIs ;) (But really, though, the main benefit of this fact comes into play when you're working with multiple environments, i.e. development/local, qa/staging, production. This approach makes it easy to replicate UIs and features without having to worry about database synchronization and other crazy things.) For another really well-done, really powerful code-based plugin for managing custom fields, check out [Easy Custom Fields](http://wordpress.org/extend/plugins/easy-custom-fields/) and the [Custom Metaboxes and Fields For WordPress Class](https://github.com/jaredatch/Custom-Metaboxes-and-Fields-for-WordPress). ## Why isn't the function just `add_metadata_field`? Do you really need the stupid `x_`? We're being good and ["namespacing" our public functions](http://andrewnacin.com/2010/05/11/in-wordpress-prefix-everything/). You should too. ## How do I use this plugin? There are usage instructions below # Changelog ## 0.8 (currently under development) * added ability to group several fields as a `multifield`; see `x_add_metadata_multifield()`, props @greatislander, @rinatkhaziev and @PhilippSchreiber for their contributions there * allow field types that save as multiples but don't display as cloneable or multiples * added the `taxonomy_checkbox` and `taxonomy_multi_select` field types, props @greatislander * made use of the `selected()` and `checked()` functions in WordPress instead of clumsy if statements * limit or exclude groups and fields using a custom callback * adjusted the copyright to include 2013 and to list "The Contributors" instead of specific individuals * adjusted the list of contributors in the plugin * adjusted the plugin URL and removed the donate URL * adjusted files for code standards * fixed PHP warning with empty values for date fields * moved filtering of instance vars to `init` instead of on `construct` which runs too early * added new field types: `number`, `email`, `telephone`, `datetimepicker`, `timepicker` and `link` (which uses the WP link manager) * added ability to add default value for certain field types * added ability to set placeholder for certain fields * updated the examples file * rewrote the `upload` field to use the media manager from WordPress 3.5+. Note the `upload` field is now `readonly` by default (but can be set to `false` when you setup the field) * updated JavaScript to be up to standard with coding standards and be fully compatible with jQuery 1.9+ * replaced chosen.js with select2.js * reformat and clean up css file * added ability for groups to display a description * added ability to limit capabilities for entire groups using `required_cap` * convert plugin class to singleton ## 0.7 * added the ability to have readonly fields with the new `readonly` paramater ## 0.6 * note: the plugin now requires WordPress 3.3+ (chiefly for the wysiwyg & datepicker fields) * update/clean-up the examples file * properly enqueue admin css for WP 3.3+ * added a filter for the `CUSTOM_METADATA_MANAGER_URL` constant * fix fields not appearing when editing users in WP 3.3+ (props @FolioVision) * now passing the `$value` for a `display_callback` (props @FolioVision) * use the new `wp_editor()` function (since WP 3.3+) instead of `the_editor()` (now deprecated) * wysiwyg fields are no longer cloneable (may be revisited in a future version) * note: metaboxes that have a wysiwyg field will break when moved, this is not a bug per-se (may be revisited in a future version) * password fields are now cloneable * added filters for most of the plugin's internal variables * now using WordPress' built-in jQuery UI for the datepicker field * updated the screenshots * updated the instructions in readme.txt ## 0.5.7 * pass additional params for `display_callback` ## 0.5.6 * fix bugs with datepicker ## 0.5.5 * remove all whitespace * fix some bugs with the tinymce field ## 0.5.4 * fix display_callback for fields ## 0.5.3 * removed php opening shorttags `<?` in favor of regular `<?php` tags, which caused parse errors on some servers ## 0.5.2 * better tiny mce implementation and added html/visual switch * small css fixes and added inline documentation * moved `DEFINE`s in to `admin_init` so that they can be filtered more easily ## 0.5.1 * Bug fix with group context on add meta box * Remove few lines of old code left-over from 0.4 ## 0.5 * Making the changes from 0.4 public * Removed ability to generate option pages; after further consideration this is out of scope for this project * Removed attachment_list field, useless * Dates now save as unix timestamp * Taxonomy fields now save as both a custom field and as their proper taxonomy (will consider adding the ability to enable/disable this in a future version) * Multiplied fields no longer save as a serialized array, instead they save as multiple metadata with the same key (metadata api supports multiples!) - remember to set the last param to false to get multiple values. * NOTE: currently multiplied fields will display out of order after saving, however this should not affect anything else other than the admin, should be fixed soon * Other small improvements ## 0.4 * Enhanced the code which generates the different field types * Added new types: `password`, `upload`, `wysiwyg`, `datepicker`, `taxonomy_select`, `taxonomy_radio`, `attachment_list` * Added field multiplication ability * Metadata is now deleted if a value is empty * Can now also generate option pages which use a metabox interface ## 0.3 * Can now limit or exclude fields or groups from specific ids * Added updated screenshots and new code samples! * Bug fix: the custom display examples weren't working well * Bug fix: fields not showing on "Add New" page. Thanks Jan Fabry! * Bug fix: fields not showing on "My Profile" page. Thanks Mike Tew! ## 0.2 * Added a textarea field type * Added support for comments (you can now specify comments as an object type) * Added basic styling for fields so that they look nice ## 0.1 * Initial release # Usage ### Object Types The main idea behind this plugin is to have a single API to work with regardless of the object type. Currently, Custom Metadata Manager works with `user`, `comment` and any built-in or custom post types, e.g. `post`, `page`, etc. ### Registering your fields For the sake of performance (and to avoid potential race conditions), always register your custom fields in the `custom_metadata_manager_admin_init` hook. This way your front-end doesn't get bogged down with unnecessary processing and you can be sure that your fields will be registered safely. Here's a code sample: ```php add_action( 'custom_metadata_manager_init_metadata', 'my_theme_init_custom_fields' ); function my_theme_init_custom_fields() { x_add_metadata_field( 'my_field', array( 'user', 'post' ) ); } ``` ### Getting the data You can get the data as you normally would using the `get_metadata` function. Custom Metadata manager stores all data using the WordPress metadata APIs using the slug name you provide. That way, even if you decide to deactivate this wonderful plugin, your data is safe and accessible. For options, you can use `get_option`. Example: ```php $value = get_metadata( 'post', get_the_ID(), 'featured', true ); // Returns post metadata value for the field 'featured' ``` ### Adding Metadata Groups A group is essentially a metabox that groups together multiple fields. Register the group before any fields ```php x_add_metadata_group( $slug, $object_types, $args ); ``` #### Parameters * `$slug` (string) The key under which the metadata will be stored. * `$object_types` (string|array) The object types to which this field should be added. Supported: post, page, any custom post type, user, comment. #### Options and Overrides ```php $args = array( 'label' => $group_slug, // Label for the group 'context' => 'normal', // (post only) 'priority' => 'default', // (post only) 'autosave' => false, // (post only) Should the group be saved in autosave? NOT IMPLEMENTED YET! 'exclude' => '', // see below for details 'include' => '', // see below for details ); ``` ### Adding Metadata Fields `x_add_metadata_field( $slug, $object_types, $args );` #### Parameters * `$slug` (string) The key under which the metadata will be stored. For post_types, prefix the slug with an underscore (e.g. `_hidden`) to hide it from the the Custom Fields box. * `$object_types` (string|array) The object types to which this field should be added. Supported: post, page, any custom post type, user, comment. #### Options and Overrides ```php $args = array( 'group' => '', // The slug of group the field should be added to. This needs to be registered with x_add_metadata_group first. 'field_type' => 'text', // The type of field; 'text', 'textarea', 'password', 'checkbox', 'radio', 'select', 'upload', 'wysiwyg', 'datepicker', 'taxonomy_select', 'taxonomy_radio' 'label' => '', // Label for the field 'description' => '', // Description of the field, displayed below the input 'values' => array(), // Values for select and radio buttons. Associative array 'display_callback' => '', // Callback to custom render the field 'sanitize_callback' => '', // Callback to sanitize data before it's saved 'display_column' => false, // Add the field to the columns when viewing all posts 'display_column_callback' => '', // Callback to render output for the custom column 'required_cap' => '', // The cap required to view and edit the field 'exclude' => '', // see below for details 'include' => '', // see below for details 'multiple' => false, // true or false, can the field be duplicated with a click of a button? 'readonly' => false, // makes the field be readonly (works with text, textarea, password, upload and datepicker fields) ); ``` #### Include / Exclude You can exclude fields and groups from specific object. For example, with the following, field-1 will show up for all posts except post #123: ```php $args = array( 'exclude' => 123 ); x_add_metadata_field( 'field-1', 'post', $args ); ``` Alternatively, you can limit ("include") fields and groups to specific objects. The following will ''only'' show group-1 to post #456: ```php $args = array( 'include' => 123 ); x_add_metadata_group( 'group-1', 'post', $args ); ``` You can pass in an array of IDs: ```php $args = array( 'include' => array( 123, 456, 789 ); ); ``` With multiple object types, you can pass in an associative array: ```php $args = array( 'exclude' => array( 'post' => 123, 'user' => array( 123, 456, 789 ) ) ); ``` You can also pass in a callback to programattically include or exclude posts: ```php $args = array( 'exclude' => function( $thing_slug, $thing, $object_type, $object_id, $object_slug ) { // exclude from all posts that are in the aside category. return in_category( 'aside', $object_id ); } ); ``` ```php $args = array( 'include' => function( $thing_slug, $thing, $object_type, $object_id, $object_slug ) { // include for posts that are not published. $post = get_post( $object_id ); return 'publish' != $post->post_status; } ); ``` # Examples For examples, please see the [custom_metadata_examples.php](https://github.com/jkudish/custom-metadata/blob/master/custom_metadata_examples.php) file included with the plugin. Add a constant to your wp-config.php called `CUSTOM_METADATA_MANAGER_DEBUG` with a value of `true` to see it in action: `define( 'CUSTOM_METADATA_MANAGER_DEBUG', true );` # License 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 2 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, write to: Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

WordPress Themes & Plugins Web Components & Widgets
192 Github Stars
regenerate-thumbnails
Open Source

regenerate-thumbnails

# Regenerate Thumbnails [![Travis CI Build Status](https://img.shields.io/travis/Viper007Bond/regenerate-thumbnails/master.svg?style=flat-square)](https://travis-ci.org/Viper007Bond/regenerate-thumbnails) [![WordPress Plugin Version](https://img.shields.io/wordpress/plugin/v/regenerate-thumbnails.svg?style=flat-square)](https://wordpress.org/plugins/regenerate-thumbnails/) [![WordPress Tested](https://img.shields.io/wordpress/v/regenerate-thumbnails.svg?style=flat-square)](https://wordpress.org/plugins/regenerate-thumbnails/) [![WordPress Plugin Downloads](https://img.shields.io/wordpress/plugin/dt/regenerate-thumbnails.svg?style=flat-square)](https://wordpress.org/plugins/regenerate-thumbnails/advanced/) [![WordPress Plugin Rating](https://img.shields.io/wordpress/plugin/r/regenerate-thumbnails.svg?style=flat-square)](https://wordpress.org/support/plugin/regenerate-thumbnails/reviews/) Regenerate Thumbnails is a WordPress plugin that will regenerate all thumbnail sizes for one or more images that have been uploaded to your WordPress Media Library. This is useful for situations such as: * A new thumbnail size has been added and you want past uploads to have a thumbnail in that size. * You've changed the dimensions of an existing thumbnail size, for example via Settings → Media. * You've switched to a new WordPress theme that uses featured images of a different size. It also offers the ability to delete old, unused thumbnails as well as update the content of posts to use the new thumbnail sizes. ## Alternatives ### WP-CLI If you have command line access to your server, I highly recommend using [WP-CLI](https://wp-cli.org/) instead of this plugin as it's faster (no HTTP requests overhead) and can be run inside of a `screen` for those with many thumbnails. For details, see the documentation of its [`media regenerate` command](https://developer.wordpress.org/cli/commands/media/regenerate/). ### Jetpack's Site Accelerator Module [Jetpack](https://jetpack.com/) is a plugin by Automattic, makers of WordPress.com. It gives your self-hosted WordPress site some of the functionality that is available to WordPress.com-hosted sites. [The Site Accelerator Module](https://jetpack.com/support/site-accelerator/) makes the images on your site be served from WordPress.com's global content delivery network (CDN) which should speed up the loading of images. Importantly though it can create thumbnails on the fly which means you'll never need to use this plugin. ## Building The Plugin The latest release can be [downloaded from WordPress.org](https://wordpress.org/plugins/regenerate-thumbnails/), but if you wish to build your own copy, here's how: 1. Make sure you have [Node.js](https://nodejs.org/) installed. 2. Clone this repository inside your `plugins` directory: ``` $ git clone https://github.com/automattic/regenerate-thumbnails.git $ cd regenerate-thumbnails ``` 3. Install [yarn](https://yarnpkg.com/) package manager. It's like npm but better. 4. Install the other dependencies: ``` yarn ``` 5. Build the plugin's JavaScript file in production mode: ``` yarn build-production ``` 6. Activate the plugin and visit Tools → Regenerate Thumbnails. ### Development Mode If you're looking to make modifications to this plugin's Vue.js code, run the following command: ``` yarn watch ``` This will do the following things: * Automatically rebuild the `build.js` file whenever any of the source files change. * Put Vue.js in development mode which will allow you to use [a browser extension](https://github.com/vuejs/vue-devtools#vue-devtools) to help with debugging. * Spawn a [Browsersync](https://www.browsersync.io/) server at [http://localhost:3030/](http://localhost:3030/) that will load a proxied version of your development WordPress install that automatically refresh the page in your browser when changes are made to files. Also if you open the site in multiple browsers, it will sync your navigation and scrolling between them. By default, this assumes that your WordPress install lives at `localhost`. If this is not the case (for example you're using [Varying Vagrant Vagrants](https://varyingvagrantvagrants.org/)), then edit `browsersync-config.json`. Alternatively if you just want to manually build a development copy of the Javascript, then run this command: ``` yarn build ``` ## Unit Tests To run the [PHPUnit](https://phpunit.de/) unit tests, first run the `install-wp-tests.sh` script from the `bin` directory. Then simply run `phpunit` from the plugin's root directory.

WordPress Themes & Plugins Image Editing
139 Github Stars
Rewrite-Rules-Inspector
Open Source

Rewrite-Rules-Inspector

# Rewrite Rules Inspector Stable tag: 1.6.0 Requires at least: 6.4 Tested up to: 6.9 Requires PHP: 7.4 License: GPLv2 or later Tags: rewrite rules, tools Contributors: danielbachhuber, automattic, tmoorewp, garyj A simple admin tool for inspecting rewrite rules. ## Description A simple WordPress admin tool for inspecting rewrite rules. View a listing of all your rewrite rules, see which rewrite rules match a given URL (and the priorities they match in), or filter by different sources of rewrite rules. Perform a soft flush of your rewrite rules to regenerate them. [Developed on GitHub](https://github.com/Automattic/Rewrite-Rules-Inspector/) — pull requests are always welcome. Please leave feedback, questions, bug reports, and feature requests in the GitHub issues. ### Where to find it Go to `Tools → Rewrite Rules` in the WordPress admin. ### URL Tester Quickly test any URL (or path) against your site's rewrite rules: - See whether the URL would be a **404** or which rule would match first (the one WordPress uses). - View the list of **all matching rules**, in match priority order. - Inspect the **query variables** extracted from the match and the resulting **final query** WordPress would run. Works with full URLs or paths and automatically handles sites installed in a subdirectory. ### Permastructs Browse a table of all **permastructs** that WordPress is aware of, including: - **Name** — the permastruct key (e.g. for posts, taxonomies, authors). - **Structure** — the permalink structure pattern used to generate rules. - **Description** — a human-friendly summary of what the permastruct controls. ### Flush Rules The "Flush Rules" button allows you to regenerate your site's rewrite rules. Here's exactly what happens when you click it: #### What the Flush Rules Button Does When you click the "Flush Rules" button, the following sequence occurs: 1. **Security Check**: The system verifies you have the proper permissions (`manage_options` capability) and validates the security nonce to prevent unauthorized access. 2. **Cache Clearing**: WordPress deletes the cached rewrite rules from the options cache using `wp_cache_delete('rewrite_rules', 'options')`. 3. **Rule Regeneration**: WordPress calls `flush_rewrite_rules(false)` to regenerate all rewrite rules based on: - Current permalink structure settings - Custom post types and taxonomies - Any custom rewrite rules added by themes or plugins 4. **Hook Execution**: The `rri_flush_rules` action hook is fired, allowing other plugins to perform additional cleanup or actions after the flush. 5. **Success Feedback**: You're redirected back to the Rewrite Rules Inspector page with a success message confirming the rules have been flushed. #### When to Use Flush Rules Use the "Flush Rules" button when: - **Missing Rules**: You see rules marked as "missing" (red background) in the inspector - **Custom URLs Not Working**: Your custom permalinks or post type URLs aren't working properly - **After Plugin Changes**: You've activated/deactivated plugins that register custom rewrite rules - **Permalink Structure Changes**: You've modified your site's permalink structure - **Custom Post Type Issues**: New custom post types or taxonomies aren't generating proper URLs #### Important Notes - **Soft Flush**: This performs a "soft" flush (using `flush_rewrite_rules(false)`), which is safer than a hard flush as it doesn't force regeneration of all rules unnecessarily. - **Permissions Required**: Only users with `manage_options` capability can flush rules. - **No Data Loss**: Flushing rules doesn't delete any content or settings, it only regenerates the URL routing rules. - **Immediate Effect**: Changes take effect immediately after flushing. ## Installation ### Install the plugin from within WordPress 1. Visit the Plugins page from your WordPress dashboard and click "Add New" at the top of the page. 1. Search for "rewrite-rules-inspector" using the search bar on the right side. 1. Click "Install Now" to install the plugin. 1. After it's installed, click "Activate" to activate the plugin on your site. ### Install the plugin manually 1. Download the plugin from WordPress.org or get the latest release from our [GitHub Releases page](https://github.com/automattic/Rewrite-Rules-Inspector/releases). 1. Unzip the downloaded archive. 1. Upload the entire `rewrite-rules-inspector` folder to your `/wp-content/plugins` directory. 1. Visit the Plugins page from your WordPress dashboard and look for the newly installed plugin. 1. Click "Activate" to activate the plugin on your site. ## Screenshots 1. See all of the rewrite rules and flush them or download them. ![The main screen showing the rewrite rules](.wordpress-org/screenshot-1.png) 2. Test a URL against the rules to see which one(s) would match, and the priority they would match in. ![Showing the URL test results](.wordpress-org/screenshot-2.png) 3. Limit rules and URL testing results down to specificrule sources. ![Showing the URL test results when no rules from that source match](.wordpress-org/screenshot-3.png) 4. See which permastructs WordPress knows about. ![Showing the permastructs table](.wordpress-org/screenshot-4.png) ## Changelog See the [change log](https://github.com/automattic/Rewrite-Rules-Inspector/blob/master/CHANGELOG.md).

DevOps & Infrastructure WordPress Themes & Plugins
135 Github Stars
Cron-Control
Open Source

Cron-Control

# Cron Control # **Contributors:** [automattic](https://profiles.wordpress.org/automattic/), [ethitter](https://profiles.wordpress.org/ethitter/) **Tags:** cron, cron control, concurrency, parallel, async **Requires at least:** 5.1 **Tested up to:** 5.8 **Requires PHP:** 7.4 **Stable tag:** 3.1 **License:** GPLv2 or later **License URI:** http://www.gnu.org/licenses/gpl-2.0.html Execute WordPress cron events in parallel, with custom event storage for high-volume cron. ## Description ## This plugin sets up a custom cron table for better events storage. Using WP hooks, it then intercepts cron registration/retrieval/deletions. There are two additional interaction layers exposed by the plugin - WP-CLI and the REST API. By default the plugin disables default WP cron processing. It is recommended to use the cron control runner to process cron: https://github.com/Automattic/cron-control-runner. This is how we are able to process cron events in parallel, allowing for high-volume and reliable cron. ## Installation ## 1. Define `WP_CRON_CONTROL_SECRET` in `wp-config.php`, set to `false` to disable the REST API interface. 1. Upload the `cron-control` directory to the `/wp-content/mu-plugins/` directory 1. Create a file at `/wp-content/mu-plugins/cron-control.php` to load `/wp-content/mu-plugins/cron-control/cron-control.php` 1. (optional) Set up the the cron control runner for event processing. ## Frequently Asked Questions ## ### Deviations from WordPress Core ### * Cron jobs are stored in a custom table and not in the `cron` option in wp_options. As long relevant code uses WP core functions for retrieving events and not direct SQL, all will stay compatible. * Duplicate recurring events with the same action/args/schedule are prevented. If multiple of the same action is needed on the same schedule, can add an arbitrary number to the args array. * When the cron control runner is running events, it does so via WP-CLI. So the environment can be slightly different than that of a normal web request. * The cron control runner can process multiple events in parallel, whereas core cron only did 1 at a time. By default, events with the same action will not run in parallel unless specifically granted permission to do so. ### Adding Internal Events ### **This should be done sparingly as "Internal Events" bypass certain locks and limits built into the plugin.** Overuse will lead to unexpected resource usage, and likely resource exhaustion. In `wp-config.php` or a similarly-early and appropriate place, define `CRON_CONTROL_ADDITIONAL_INTERNAL_EVENTS` as an array of arrays like: ``` define( 'CRON_CONTROL_ADDITIONAL_INTERNAL_EVENTS', array( array( 'schedule' => 'hourly', 'action' => 'do_a_thing', 'callback' => '__return_true', ), ) ); ``` Due to the early loading (to limit additions), the `action` and `callback` generally can't directly reference any Core, plugin, or theme code. Since WordPress uses actions to trigger cron, class methods can be referenced, so long as the class name is not dynamically referenced. For example: ``` define( 'CRON_CONTROL_ADDITIONAL_INTERNAL_EVENTS', array( array( 'schedule' => 'hourly', 'action' => 'do_a_thing', 'callback' => array( 'Some_Class', 'some_method' ), ), ) ); ``` Take care to reference the full namespace when appropriate. ### Increasing Event Concurrency ### In some circumstances, multiple events with the same action can safely run in parallel. This is usually not the case, largely due to Core's alloptions, but sometimes an event is written in a way that we can support concurrent executions. To allow concurrency for your event, and to specify the level of concurrency, please hook the `a8c_cron_control_concurrent_event_whitelist` filter as in the following example: ``` add_filter( 'a8c_cron_control_concurrent_event_whitelist', function( $wh ) { $wh['my_custom_event'] = 2; return $wh; } ); ``` ## Development & Testing ## ### Quick and easy testing ### If you have docker installed, can just run `./__tests__/bin/test.sh`. ### Manual testing setup ### First, you'll need svn and composer. Example of installing them on a docker container if needed: ``` apk add subversion wget -q https://getcomposer.org/installer -O - | php -- --install-dir=/usr/bin/ --filename=composer ``` Next change directories to the plugin and set up the test environment: ``` cd wp-content/mu-plugins/cron-control composer install # Note that the values below can be different, it is: <db-name> <db-user> <db-pass> [db-host] [wp-version] ./__tests__/bin/install-wp-tests.sh test wordpress wordpress database latest ``` Lastly, kick things off with one command: `phpunit` ### Readme & language file updates ### Will need `npm`. Example of installing on a docker container: `apk add --update npm` Run `npm install` then `npm run build` to create/update language files and to convert `readme.txt` to `readme.md` if needed. ## Changelog ## ### 3.1 ### * Update installation process, always ensuring the custom table is installed. * Swap out deprecated `wpmu_new_blog` hook. * Ignore archived/deleted/spam subsites during the runner's `list sites` cli command. * Migrate legacy events from the `cron` option to the new table before deleting the option. * Delete duplicate recurring events. Runs daily. ### 3.0 ### * Implement WP cron filters that were added in WP 5.1. * Cleanup the event's store & introduce new Event() object. * Switch to a more efficient caching strategy. ### 2.0 ### * Support additional Internal Events * Break large cron queues into several caches * Introduce Golang runner to execute cron * Support concurrency for whitelisted events ### 1.5 ### * Convert from custom post type to custom table with proper indices ### 1.0 ### * Initial release

WordPress Themes & Plugins
133 Github Stars
vip-block-data-api
Open Source

vip-block-data-api

# VIP Block Data API <picture> <source srcset="https://github.com/Automattic/vip-block-data-api/blob/media/vip-block-data-api-animation-1660.gif" media="(-webkit-min-device-pixel-ratio: 2.0)" /> <source srcset="https://github.com/Automattic/vip-block-data-api/blob/media/vip-block-data-api-animation-830.gif" media="(-webkit-min-device-pixel-ratio: 1.0)" /> <img src="https://github.com/Automattic/vip-block-data-api/blob/media/vip-block-data-api-animation-830.gif" alt="VIP Block Data API attribute sourcing animation" /> </picture> The Block Data API is an API for retrieving block editor posts structured as JSON data, with integrations for both the official WordPress REST API and WPGraphQL. While primarily designed for use in decoupled WordPress, the Block Data API can be used anywhere you want to represent block markup as structured data. This plugin is currently developed for use on WordPress sites hosted on the VIP Platform. ## Table of contents - [Installation](#installation) - [Install on WordPress VIP](#install-on-wordpress-vip) - [Install via ZIP file](#install-via-zip-file) - [Plugin activation](#plugin-activation) - [APIs](#apis) - [REST](#rest) - [Usage](#usage) - [Versioning](#versioning) - [Examples](#examples) - [Example: Basic text blocks: `core/heading` and `core/paragraph`](#example-basic-text-blocks-coreheading-and-coreparagraph) - [Example: Text attributes in `core/pullquote`](#example-text-attributes-in-corepullquote) - [Example: Nested blocks in `core/media-text`](#example-nested-blocks-in-coremedia-text) - [GraphQL](#graphql) - [Setup](#setup) - [Usage](#usage-1) - [Block Attributes](#block-attributes) - [Complex attributes](#complex-attributes) - [Example: Simple nested blocks: `core/list` and `core/quote`](#example-simple-nested-blocks-corelist-and-corequote) - [API Consumption](#api-consumption) - [Preact](#preact) - [Block hierarchy reconstruction](#block-hierarchy-reconstruction) - [Limitations](#limitations) - [Client-side blocks](#client-side-blocks) - [Client-side example](#client-side-example) - [Registering client-side blocks](#registering-client-side-blocks) - [Rich text support](#rich-text-support) - [Deprecated blocks](#deprecated-blocks) - [Rest API Query Parameters](#rest-api-query-parameters) - [Example Post](#example-post) - [`include`](#include) - [`exclude`](#exclude) - [Filters and actions](#filters-and-actions) - [GraphQL](#graphql-1) - [REST](#rest-1) - [`vip_block_data_api__rest_validate_post_id`](#vip_block_data_api__rest_validate_post_id) - [`vip_block_data_api__rest_permission_callback`](#vip_block_data_api__rest_permission_callback) - [`vip_block_data_api__allow_block`](#vip_block_data_api__allow_block) - [`vip_block_data_api__sourced_block_result`](#vip_block_data_api__sourced_block_result) - [`vip_block_data_api__before_parse_post_content`](#vip_block_data_api__before_parse_post_content) - [`vip_block_data_api__after_parse_blocks`](#vip_block_data_api__after_parse_blocks) - [Analytics](#analytics) - [Caching on WPVIP](#caching-on-wpvip) - [Errors and Warnings](#errors-and-warnings) - [Error: `vip-block-data-api-no-blocks`](#error-vip-block-data-api-no-blocks) - [Error: `vip-block-data-api-parser-error`](#error-vip-block-data-api-parser-error) - [Warning: Unregistered block type](#warning-unregistered-block-type) - [Development](#development) - [Tests](#tests) ## Installation ### Install on WordPress VIP The Block Data API plugin is authored and maintained by [WordPress VIP][wpvip], and made available to all WordPress sites by the [VIP Integrations Center][vip-ic]. Customers who host on WordPress VIP or use [`vip dev-env`](https://docs.wpvip.com/how-tos/local-development/use-the-vip-local-development-environment/) to develop locally have access to the Block Data API automatically. We recommend this activation method for WordPress VIP customers. Enable the Integration by [adding it to your organization][vip-ic-org]. Once that is complete, you can [activate the integration on your application][vip-ic-app]. Activation is for the current environment only, so you may need to activate the Integration on multiple environments. We plan to utilize API versioning to make automatic updates safe for consumer code. See [Versioning](#versioning) for more information. To use the Block Data API after activation, skip to [Usage](#usage). ### Install via ZIP file The latest version of the plugin can be downloaded from the [repository's Releases page][repo-releases]. Unzip the downloaded plugin and add it to the `plugins/` directory of your site's GitHub repository. #### Plugin activation Usually VIP recommends [activating plugins with code][wpvip-plugin-activate]. In this case, we are recommending activating the plugin in the WordPress Admin dashboard. This will allow the plugin to be more easily enabled and disabled during testing. To activate the installed plugin: 1. Navigate to the WordPress Admin dashboard as a logged-in user. 2. Select **Plugins** from the lefthand navigation menu. 3. Locate the "VIP Block Data API" plugin in the list and select the "Activate" link located below it. ![Plugin activation][media-plugin-activate] ## APIs The VIP Block Data API plugin provides two types of APIs to use - REST and GraphQL. The Block Data API [uses server-side registered blocks][wordpress-block-metadata-php-registration] to determine block attributes. Refer to the **[Client-side blocks](#client-side-blocks)** section for more information about client-side block support limitations. ### REST There is no extra setup necessary for the REST API. It is ready to use out of the box. #### Usage The REST URL is located at: ```js /wp-json/vip-block-data-api/v1/posts/<post_id>/blocks // e.g. https://my-site.com/wp-json/vip-block-data-api/v1/posts/139/blocks ``` This public endpoint will return editor block metadata as structured JSON for any published post, page, or published `WP_Post` object. Review these [**Filters**](#filters) to learn more about limiting access to the REST endpoint: - [`vip_block_data_api__rest_validate_post_id`](#vip_block_data_api__rest_validate_post_id) - [`vip_block_data_api__rest_permission_callback`](#vip_block_data_api__rest_permission_callback) #### Versioning The current REST endpoint uses a `v1` prefix: ``` /wp-json/vip-block-data-api/v1/... ``` We plan to utilize API versioning to avoid unexpected changes to the plugin. In the event that we make breaking changes to API output, we will add a new endpoint (e.g. `/wp-json/vip-block-data-api/v2/`) with access to new data. Previous versions will remain accessible for backward compatibility. #### Examples Examples of WordPress block markup and the associated data structure returned by the Block Data API. ##### Example: Basic text blocks: `core/heading` and `core/paragraph` ![Heading and paragraph block in editor][media-example-heading-paragraph] <table> <tr> <td>Block Markup</td> <td>Block Data API</td> </tr> <tr> <td> ```html <!-- wp:heading {"level":3} --> <h3 class="wp-block-heading">Block Data API</h3> <!-- /wp:heading --> <!-- wp:paragraph --> <p>Blocks as JSON.</p> <!-- /wp:paragraph --> ``` </td> <td> ```json [{ "name": "core/heading", "attributes": { "level": 3, "content": "Block Data API" } }, { "name": "core/paragraph", "attributes": { "content": "Blocks as JSON." } }] ``` </td> </tr> </table> --- ##### Example: Text attributes in `core/pullquote` ![Pullquote block in editor][media-example-pullquote] <table> <tr> <td>Block Markup</td> <td>Block Data API</td> </tr> <tr> <td> ```html <!-- wp:pullquote --> <figure class="wp-block-pullquote"> <blockquote> <p>From markup -> props</p> <cite>~ WPVIP</cite> </blockquote> </figure> <!-- /wp:pullquote --> ``` </td> <td> ```json [{ "name": "core/pullquote", "attributes": { "value": "From markup -> props", "citation": "~ WPVIP" } }] ``` </td> </tr> </table> --- ##### Example: Nested blocks in `core/media-text` ![Media-text block containing heading in editor][media-example-media-text] <table> <tr> <td>Block Markup</td> <td>Block Data API</td> </tr> <tr> <td> ```html <!-- wp:media-text {"mediaId":256, "mediaType":"image"} --> <div class="wp-block-media-text"> <figure class="wp-block-media-text__media"> <img src="http://my.site/api.jpg" class="wp-image-256 size-full" /> </figure> <div class="wp-block-media-text__content"> <!-- wp:heading --> <h2 class="wp-block-heading"> REST API </h2> <!-- /wp:heading --> </div> </div> <!-- /wp:media-text --> ``` </td> <td> ```json [{ "name": "core/media-text", "attributes": { "mediaId": 256, "mediaType": "image", "mediaPosition": "left", "mediaUrl": "http://my.site/api.jpg", "mediaWidth": 50 }, "innerBlocks": [ { "name": "core/heading", "attributes": { "content": "REST API", "level": 2 } } ] }] ``` </td> </tr> </table> ### GraphQL The GraphQL API requires some setup before it can be it can be used. #### Setup The Block Data API integrates with **WPGraphQL** to provide a GraphQL API. It is necessary to have [WPGraphQL installed and activated][wpgraphql-install]. Once WPGraphQL has been installed and setup, a new field called `blocksDataV2` will be available for post types that provide content, like posts, pages, etc. For information on the legacy `blocksData` (v1) field, see [the README from plugin version `1.2.4`][repo-readme-1.2.4]. #### Usage The `blocksDataV2` field provides block data for post types that support it. Here is an example query: ```graphQL query NewQuery { post(id: 1, idType: DATABASE_ID) { blocksDataV2 { blocks { name id parentId attributes { name value } } } } } ``` The `id` and `parentId` fields are dynamically generated unique IDs that help to identify parent-child relationships between blocks. The resulting set of blocks is a flattened list that can be untangled using the combination of `id` and `parentId` fields. This allows a flat query to return a complex nested block structure. For more information on recreating `innerBlocks` from IDs, see the example code in [Block Hierarchy Reconstruction](#block-hierarchy-reconstruction). #### Block Attributes The attributes of a block in GraphQL are available in a list of `name` / `value` string pairs, e.g. ```js "attributes": [ { "name": "content", "value": "This is item 1 in the list", }, { "name": "fontSize", "value": "small" } ] ``` This is used instead of a key-value structure. This is a trade-off that makes it easy to retrieve block attributes without specifying the the block type ahead of time, but attribute type information is lost. #### Complex attributes Some block attributes contain arrays or complex nested values. Demonstrated below, [the `core/table` block uses an array of objects][gutenberg-code-table-body] to represent head, body, and footer cell contents. The GraphQL Block Data API implementation represents these attributes as JSON-encoded strings along with the `isValueJsonEncoded` boolean field. When `isValueJsonEncoded` is `true`, an attribute's value must be JSON decoded to get the original complex value. For example, using this table: ![Example core/table block with a two header cells and two body cells][media-example-table] We can query for attributes along with the `isValueJsonEncoded` field in a GraphQL query: ```graphql query PostQuery { post(id: 1, idType: DATABASE_ID) { blocksDataV2 { blocks { name id parentId attributes { name value isValueJsonEncoded } } } } } ``` The result will contain JSON-encoded attributes designated by the `isValueJsonEncoded` field: ```json { "data": { "post": { "blocksDataV2": { "blocks": [ { "name": "core/table", "attributes": [ { "name": "hasFixedLayout", "value": "false", "isValueJsonEncoded": true }, { "name": "head", "value": "[{\"cells\":[{\"content\":\"Header A\",\"tag\":\"th\"},{\"content\":\"Header B\",\"tag\":\"th\"}]}]", "isValueJsonEncoded": true }, { "name": "body", "value": "[{\"cells\":[{\"content\":\"Value 1\",\"tag\":\"td\"},{\"content\":\"Value 2\",\"tag\":\"td\"}]}]", "isValueJsonEncoded": true }, { "name": "foot", "value": "[]", "isValueJsonEncoded": true } ] } ] } } } } ``` --- #### Example: Simple nested blocks: `core/list` and `core/quote` ![List and Quote block in editor][media-example-list-quote] *Block Markup* ```html <!-- wp:list --> <ul><!-- wp:list-item --> <li>This is item 1 in the list</li> <!-- /wp:list-item --> <!-- wp:list-item --> <li>This is item 2 in the list</li> <!-- /wp:list-item --> </ul> <!-- /wp:list --> <!-- wp:quote --> <blockquote class="wp-block-quote"> <!-- wp:paragraph --> <p>This is a paragraph within a quote</p> <!-- /wp:paragraph --> </blockquote> <!-- /wp:quote --> ``` <table> <tr> <td>Query</td> <td>Block Data API</td> </tr> <tr> <td> ```graphQL query NewQuery { post(id: "1", idType: DATABASE_ID) { blocksDataV2 { blocks { name id parentId attributes { name value } } } } } ``` </td> <td> ```json { "data": { "post": { "blocksDataV2": { "blocks": [ { "name": "core/list", "id": "1", "parentId": null, "attributes": [ { "name": "ordered", "value": "false" }, { "name": "values", "value": "" } ] }, { "name": "core/list-item", "id": "2", "parentId": "1", "attributes": [ { "name": "content", "value": "This is item 1 in the list" } ] }, { "name": "core/list-item", "id": "3", "parentId": "1", "attributes": [ { "name": "content", "value": "This is item 2 in the list" } ] }, { "name": "core/quote", "id": "4", "parentId": null, "attributes": [ { "name": "value", "value": "" } ] }, { "name": "core/paragraph", "id": "QmxvY2tEYXRhVjI6NDY6NQ==", "parentId": "4", "attributes": [ { "name": "content", "value": "This is a paragraph within a quote" }, { "name": "dropCap", "value": "false" } ] } ] } } } } ``` </td> </tr> </table> Note that `id` values returned from GraphQL will be alpha-numeric strings, e.g. `"id": "SUQ6MQ=="` and not integers. ## API Consumption ### Preact An example [Preact app][preact] app that queries for block data and maps it into customized components. The example post being queried contains a `core/media-text` element with an image on the left and `core/heading` and `core/paragraph` blocks on the right side: ![Screenshot of example media-text post content][media-preact-media-text] The following code uses the REST API to retrieve post and block metadata and map each block onto a custom component. ```html <!DOCTYPE html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>VIP Block Data API Preact example</title> </head> <body></body> <script type="module"> import { h, render } from 'https://esm.sh/preact'; renderPost('https://gutenberg-content-api-test.go-vip.net/wp-json', 55); async function renderPost(restUrl, postId) { const postResponse = await fetch(`${restUrl}/wp/v2/posts/${postId}`); const postTitle = (await postResponse.json())?.title?.rendered; const blocksResponse = await fetch(`${restUrl}/vip-block-data-api/v1/posts/${postId}/blocks`); const blocks = (await blocksResponse.json())?.blocks; const App = Post(postTitle, blocks); render(App, document.body); } function mapBlockToComponent(block) { if (block.name === 'core/heading') { return Heading(block); } else if (block.name === 'core/paragraph') { return Paragraph(block); } else if (block.name === 'core/media-text') { return MediaText(block); } else { return null; } } /* Components */ function Post(title, blocks) { return h('div', { className: 'post' }, h('h1', null, title), blocks.map(mapBlockToComponent), ); } function Heading(props) { // Use dangerouslySetInnerHTML for rich text formatting return h('h2', { dangerouslySetInnerHTML: { __html: props.attributes.content } }); } function Paragraph(props) { // Use dangerouslySetInnerHTML for rich text formatting return h('p', { dangerouslySetInnerHTML: { __html: props.attributes.content } }); } function MediaText(props) { return h('div', { className: 'media-text' }, h('div', { className: 'media' }, h('img', { src: props.attributes.mediaUrl }) ), h('div', { className: 'text' }, props.innerBlocks ? props.innerBlocks.map(mapBlockToComponent) : null, ), ) } </script> </html> ``` The code above produces this HTML from post data: ```html <div class="post"> <h1>Post with a media-text</h1> <div class="media-text"> <div class="media"> <img src="https://gutenberg-content-api-test.go-vip.net/.../api.webp?w=1024"> </div> <div class="text"> <h2>Heading content</h2> <p>Paragraph content</p> </div> </div> </div> ``` ### Block hierarchy reconstruction The purpose of this function is to take the flattened set of GraphQL blocks, and reconstruct the block hierarchy. The logic is as follows: 1. Partition blocks by `parentId` into `blocksByParentId`. 2. Loop through root-level blocks. 3. For each block, determine inner blocks by using `blocksByParentId` as a look-up table. 4. Apply the same step (3) recursively for that block's `innerBlocks`, if present. Given `payload` contains a GraphQL response with `blocksDataV2` data, `blockHierarchy` will contain the nested result. ```js const blocks = payload.data?.post?.blocksDataV2?.blocks ?? []; // Partition blocks by parentId, using 'root' for blocks without a parentId. const blocksByParentId = blocks.reduce( ( acc, block ) => { const parentId = block.parentId || 'root'; // Create or append to the array of other blocks sharing this parentId acc[ parentId ] = ( acc[ parentId ] || [] ).concat( block ); return acc; }, {} ); function addInnerBlocks( block, blocksByParentId ) { // If this block has children: if ( block.id in blocksByParentId ) { // Recurse into child blocks and setup their innerBlocks let innerBlocks = blocksByParentId[ block.id ].map( innerBlock => { return addInnerBlocks( innerBlock, blocksByParentId ); } ); // Set the completed innerBlocks on this block block.innerBlocks = innerBlocks; } return block; } // Recursively add innerBlocks to root blocks. const blockHierarchy = blocksByParentId[ 'root' ].map( block => addInnerBlocks( block, blocksByParentId ) ); ``` #### Example This is a post containing two columns, each with an inner `core/paragraph`: ![Post containing two columns, each with a paragraph][media-example-nested-columns] This post is queried with GraphQL: ```graphql query PostQuery { post(id: 123, idType: DATABASE_ID) { blocksDataV2 { blocks { name id parentId attributes { name value } } } } } ``` GraphQL returns this payload: ```json { "data": { "post": { "blocksDataV2": { "blocks": [ { "name": "core/columns", "id": "1", "parentId": null, }, { "name": "core/column", "id": "2", "parentId": "1", }, { "name": "core/paragraph", "id": "3", "parentId": "2", "attributes": [ { "name": "content", "value": "Left column" } ] }, { "name": "core/column", "id": "4", "parentId": "1", }, { "name": "core/paragraph", "id": "5", "parentId": "4", "attributes": [ { "name": "content", "value": "Right column" } ] } ] } } } } ``` Next, we run the block hierarchy reconstruction code above on the payload data: ```js const blocks = payload.data?.post?.blocksDataV2?.blocks ?? []; // ... const blockHierarchy = blocksByParentId[ 'root' ].map( block => addInnerBlocks( block, blocksByParentId ) ); ``` `blockHierarchy` now holds: ```json [ { "name": "core/columns", "id": "1", "parentId": null, "innerBlocks": [ { "name": "core/column", "id": "2", "parentId": "1", "innerBlocks": [ { "name": "core/paragraph", "id": "3", "parentId": "2", "attributes": [ { "name": "content", "value": "Left column" } ] } ] }, { "name": "core/column", "id": "4", "parentId": "1", "innerBlocks": [ { "name": "core/paragraph", "id": "5", "parentId": "4", "attributes": [ { "name": "content", "value": "Right column" } ] } ] } ] } ] ``` ## Limitations ### Client-side blocks The Block Data API relies on [server-side registered blocks][wordpress-block-metadata-php-registration] to source attributes from HTML. Custom blocks that register via [`register_block_type()`][wordpress-register-block-type-php] and `block.json` will automatically be available in the Block Data API. All Gutenberg core blocks are registered server-side. Modern blocks are likely to be registered server-side and work immediately with the Block Data API. However, some custom blocks may only use [`registerBlockType()`][wordpress-register-block-type-js] in JavaScript and will not provide server-side registration. For these blocks, some attribute data may be missing. To address this issue, we recommend: - Creating a `block.json` file for each of your site's custom blocks. - Using [`register_block_type()`][wordpress-register-block-type-php] with the `block.json` file to expose the block information to the server. For more information on using `block.json` to enhance block capabilities, [read this WordPress core post][wordpress-block-json-recommendation]. #### Client-side example For legacy block content or third-party blocks that are not registered server-side, some attributes may still be available through the Block Data API. For example, this is a hero block that is registered *only* in JavaScript: ```js blocks.registerBlockType('wpvip/hero-block', { title: __('Hero Block', 'wpvip'), icon: 'index-card', category: 'text', attributes: { title: { type: 'string', source: 'html', selector: 'h2', }, mediaURL: { type: 'string', source: 'attribute', selector: 'img', attribute: 'src', }, content: { type: 'string', source: 'html', selector: '.hero-text', }, mediaID: { type: 'number', } } }); ``` The block's output markup will render like this: ```html <!-- wp:wpvip/hero-block {"mediaID":9} --> <div class="wp-block-wpvip-hero-block"> <h2>Hero title</h2> <div class="hero-image"> <img src="http://my.site/uploads/hero-image.png" /> </div> <p class="hero-text">Hero summary</p> </div> <!-- /wp:wpvip/hero-block --> ``` Because the block is not registered server-side, the server is unaware of the block's sourced attributes like `title` and `mediaURL`. The Block Data API can only return a subset of the block's attributes: ```js [{ "name": "wpvip/hero-block", "attributes": { "mediaID": 9 } }] ``` `mediaID` is stored directly in the block's delimiter (`<!-- wp:wpvip/hero-block {"mediaID":9} -->`), and will be available in the Block Data API. Any other sourced attributes will be missing. #### Registering client-side blocks The example above shows block attributes missing on a client-side block. To fix this problem, the block can be changed to register with a `block.json` via [`register_block_type()`][wordpress-register-block-type-php]: *block.json* ```json { "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 2, "name": "wpvip/hero-block", "title": "Hero block", "icon": "index-card", "category": "text", "attributes": { "title": { "type": "string", "source": "html", "selector": "h2" }, "mediaURL": { "type": "string", "source": "attribute", "selector": "img", "attribute": "src" }, "content": { "type": "string", "source": "html", "selector": ".hero-text" }, "mediaID": { "type": "number" } } } ``` The `block.json` file is used to register the block both server-side and client-side: *In PHP plugin code*: ```php register_block_type( __DIR__ . '/block.json' ); ``` *In JavaScript*: ```js import metadata from './block.json'; registerBlockType( metadata, { edit: Edit, // ...other client-side settings } ); ``` After server-side registration, the block's full structure is available via the Block Data API: ```js [{ "name": "wpvip/hero-block", "attributes": { "mediaID": 9, "title": "Hero title", "mediaURL": "http://my.site/uploads/hero-image.png", "content": "Hero summary" } }] ``` ### Rich text support Blocks with [`html`-sourced attributes][wordpress-block-attributes-html] can contain HTML rich-text formatting, but that may not always be apparent. For example, this is an image with a basic plain-text caption: ![Image with plain-text caption][media-example-caption-plain] The image is saved in WordPress with this markup: ```html <!-- wp:image {"id":17,"sizeSlug":"large","linkDestination":"media"} --> <figure class="wp-block-image size-large"> <a href="https://my.site/wp-content/wpvip.jpg"> <img src="https://my.site/wp-content/wpvip.jpg" alt="" class="wp-image-17"/> </a> <figcaption class="wp-element-caption">This is a center-aligned image with a caption</figcaption> </figure> <!-- /wp:image --> ``` The Block Data API uses the `caption` property definition from [`core/image`'s `block.json` file][gutenberg-code-image-caption]: ```js "attributes": { "caption": { "type": "string", "source": "html", "selector": "figcaption", /* ... */ }, } ``` The sourced caption is returned in the Block Data API: ```js { "name": "core/image", "attributes": { /* ... */ "caption": "This is a center-aligned image with a caption", } } ``` Because the `caption` property in this example is plaintext, it seems possible to print the caption to the page safely (e.g. without using `innerHTML` or React's `dangerouslySetInnerHTML`). However, this is not the case and may result in incorrect rendering. Attributes with the `html` source like the image block caption attribute above can contain plain-text as well as markup. ![Image with rich-text caption][media-example-caption-rich-text] Retrieving the `caption` through the Block Data API yields this result: ```js { "name": "core/image", "attributes": { /* ... */ "caption": "This is a caption with <strong>bold text</strong> <a href=\"https://wpvip.com/\">and a link</a>.", } } ``` `caption` now contains inline HTML. In order to view rich-text formatting in a decoupled component, direct HTML usage with `innerHTML` or `dangerouslySetInnerHTML` is necessary. You could also use the [`vip_block_data_api__sourced_block_result`](#vip_block_data_api__sourced_block_result) filter to remove HTML from attributes. Formatting would be removed as well, but the resulting data may be more flexible. In the future we are considering providing a rich-text data format so that no direct HTML is required to render blocks correctly. This would improve the flexibility of the Block Data API in non-browser locations such as in native mobile applications. For now, however, some direct HTML is still required to render blocks with rich formatting. ### Deprecated blocks When core or custom editor blocks are updated to a new version, block attributes can change. This can result in the Block Data API returning a different block structure for the same block type depending on when the post containing a block was authored. For example, the `core/list` block [was updated in 2022][gutenberg-pr-core-list-innerblocks] from storing list items in the `values` attribute to use `innerBlocks` instead. Before this change, a list with two items was structured like this: ```html <!-- wp:list --> <ul> <li>List item 1</li> <li>List item 2</li> </ul> <!-- /wp:list --> ``` The resulting attributes for a `core/list` block pulled from the Block Data API would be structured like this: ```json { "name": "core/list", "attributes": { "ordered": false, "values": "<li>List item 1</li><li>List item 2</li>" } } ``` List items are stored as HTML in the `values` attribute, which is not an ideal structure for mapping to custom components. After the [`core/list` block was updated][gutenberg-pr-core-list-innerblocks] in WordPress, the same two-item list block is represented this way in HTML: ```html <!-- wp:list --> <ul> <!-- wp:list-item --> <li>List item 1</li> <!-- /wp:list-item --> <!-- wp:list-item --> <li>List item 2</li> <!-- /wp:list-item --> </ul> <!-- /wp:list --> ``` The resulting `core/list` item from the Block Data API parses the list items as `core/list-item` children in `innerBlocks`: ```json { "name": "core/list", "attributes": { "ordered": false, "values": "" }, "innerBlocks": [ { "name": "core/list-item", "attributes": { "content": "List item 1" } }, { "name": "core/list-item", "attributes": { "content": "List item 2" } } ] } ``` Deprecated blocks can be a tricky problem when using the Block Data API to render multiple versions of the same block. A `core/list` block from a post in 2021 has a different data shape than a `core/list` block created in 2023. Consumers of the API need to be aware of legacy block structures in order to implement custom frontend components. This issue applies to custom blocks as well; if a block has legacy markup saved in the database, this can result in legacy block representation in the Block Data API. We are considering ways to mitigate this problem for consumers of the API, such as [implementing server-side block deprecation rules][wordpress-block-deprecation] or providing type structures to represent legacy block data shapes. For now, ensure that Block Data API consumers test against older content to ensure that legacy block versions used in content are covered by code. ## Rest API Query Parameters These query parameters can be passed in the REST API to filter the results of the Block Data API. The example post below will be used to demonstrate the filters: ### Example Post ```html <!-- wp:heading --> <h2>Heading 1</h2> <!-- /wp:heading --> <!-- wp:quote --> <blockquote class="wp-block-quote"> <!-- wp:paragraph --> <p>Text in quote</p> <!-- /wp:paragraph --> <cite>~ Citation, 2023</cite> </blockquote> <!-- /wp:quote --> ``` ### `include` Limit the types of blocks that will be returned by the Block Data API. This can be useful for providing an allowed list of supported blocks, and skipping the contents of all other blocks. Multiple block types can be specified using commas, e.g. `?include=core/heading,core/paragraph`. Example: using the [post data above](#example-post) with `?include=core/heading`, only return `core/heading` blocks in the output: ```js GET /wp-json/vip-block-data-api/v1/posts/<post_id>/blocks?include=core/heading ``` ```json { "blocks": [ { "name": "core/heading", "attributes": { "content": "Heading 1", "level": 2 } } ] } ``` This query parameter cannot be used at the same time as [the `exclude` query parameter](#exclude). Note that custom block filter rules can also be created in code via [the `vip_block_data_api__allow_block` filter](#vip_block_data_api__allow_block). --- ### `exclude` Exclude some block types from the Block Data API. This can be useful for providing a block list of unsupported blocks and skipping those in REST API output. Multiple block types can be specified using commas, e.g. `?exclude=core/heading,core/paragraph`. Example: using the [post data above](#example-post) with `?exclude=core/heading`, skip `core/heading` blocks in the output: ```js GET /wp-json/vip-block-data-api/v1/posts/<post_id>/blocks?exclude=core/heading ``` ```json { "blocks": [ { "name": "core/quote", "attributes": { "value": "", "citation": "Citation, 2023" }, "innerBlocks": [ { "name": "core/paragraph", "attributes": { "content": "Text in quote", "dropCap": false } } ] } ] } ``` This query parameter cannot be used at the same time as [the `include` query parameter](#include). Note that custom block filter rules can also be created in code via [the `vip_block_data_api__allow_block` filter](#vip_block_data_api__allow_block). ## Filters and actions ### GraphQL By default, the VIP Block Data API enables GraphQL integration automatically if WPGraphQL is activated. To disable this behavior, use the `vip_block_data_api__is_graphql_enabled` filter: ```php // Disable GraphQL integration add_filter( 'vip_block_data_api__is_graphql_enabled', '__return_false', 10, 1 ); ``` ### REST These filters and actions can be applied to limit access to the REST API and modify the output of parsed blocks. ### `vip_block_data_api__rest_validate_post_id` Limit which post IDs are valid in the REST API. By default, posts that are available via the [WordPress `/posts` REST API][wordpress-rest-api-posts] are queryable. ```php /** * Validates that a post can be queried via the Block Data API REST endpoint. * Return false to disable access to a post. * * @param boolean $is_valid Whether the post ID is valid for querying. Defaults to true * when a post is available via the WordPress REST API. * @param int $post_id The queried post ID. */ return apply_filters( 'vip_block_data_api__rest_validate_post_id', $is_valid, $post_id ); ``` For example, this filter can be used to allow only pages that are published to be available: ```php add_filter( 'vip_block_data_api__rest_validate_post_id', function( $is_valid, $post_id ) { // Only allow published pages return 'page' === get_post_type( $post_id ) && 'publish' === get_post_status( $post_id ); }, 10, 2); ``` --- ### `vip_block_data_api__rest_permission_callback` Limit Block Data API access to specific users or roles. ```php /** * Validates that a request can access the Block Data API. This filter can be used to * limit access to authenticated users. * Return false to disable access. * * @param boolean $is_permitted Whether the request is permitted. Defaults to true. */ return apply_filters( 'vip_block_data_api__rest_permission_callback', true ); ``` **Warning**: Authenticated requests to the Block Data API will bypass WPVIP's built-in REST API caching. Review [**Caching on WPVIP**](#caching-on-wpvip) for more information. By default no authentication is required, as posts must be published to be available on the Block Data API. If limited access is desired (e.g. [via Application Password credentials][wordpress-application-passwords]) this filter can be used to check user permissions: ```php add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) { // Require authenticated user access with 'publish_posts' permission return current_user_can( 'publish_posts' ); }); ``` --- ### `vip_block_data_api__allow_block` Filter out blocks from the output of the Block Data API. This is a server-side alternative to the [`include`](#include) and [`exclude`](#exclude) query parameters. ```php /** * Filter out blocks from the blocks output * * @param bool $is_block_included True if the block should be included, or false to filter it out. * @param string $block_name The name of the parsed block, e.g. 'core/paragraph'. * @param string $block The result of parse_blocks() for this block. * Contains 'blockName', 'attrs', 'innerHTML', and 'innerBlocks' keys. */ apply_filters( 'vip_block_data_api__allow_block', $is_block_included, $block_name, $block ); ``` This is useful for restricting types of blocks returned from the Block Data API. Blocks that are disallowed by this filter will be removed from `innerBlocks` of other blocks as well. This filter can be used to create a server-side deny list. In the example below, `core/quote` blocks are fully removed from the Block Data API output: ```php add_filter( 'vip_block_data_api__allow_block', 'custom_allow_block', 10, 3 ); function custom_allow_block( $is_block_included, $block_name, $block ) { if ( 'core/quote' === $block_name ) { return false; } // Use $is_block_included result to allow additional filtering by query parameters return $is_block_included; }; ``` This filter can also be used to create a server-side allowlist. In the example below, we only want to return `core/heading` and `core/paragraphs` blocks from the Block Data API: ```php add_filter( 'vip_block_data_api__allow_block', 'add_allowlist', 10, 3 ); function add_allowlist( $is_block_included, $block_name, $block ) { if ( 'core/paragraph' === $block_name || 'core/heading' === $block_name ) { // Use $is_block_included result to allow additional filtering by query parameters return $is_block_included; } return false; }; ``` Note that this filter is evaluated after the [`include`](#include) and [`exclude`](#exclude) query parameters, which means that the filter's result takes precedence. If a block type is disallowed by this filter, query parameters will not be able to override the behavior. --- ### `vip_block_data_api__sourced_block_inner_blocks` Modify a block's inner blocks before they are recursively added to the result tree. ```php /** * Filters a block's inner blocks before recursive iteration. * * @param array $inner_blocks An array of inner block (WP_Block) instances. * @param string $block_name Name of the parsed block, e.g. 'core/paragraph'. * @param int $post_id Post ID associated with the parsed block. * @param array $block Result of parse_blocks() for this block. */ $inner_blocks = apply_filters( 'vip_block_data_api__sourced_block_inner_blocks', $inner_blocks, $block_name, $this->post_id, $block->parsed_block ); ``` This is useful if you want to add or remove inner blocks from the tree based on the parent block. Note that the inner blocks are WP_Block instances, not the associative arrays returned by `parse_blocks`. ```php add_filter( 'vip_block_data_api__sourced_block_inner_blocks', 'remove_gallery_inner_blocks', 10, 4 ); function remove_gallery_inner_blocks( $inner_blocks, $block_name, $post_id, $block ) { if ( 'core/gallery' === $block_name ) { return []; } return $inner_blocks; } ``` --- ### `vip_block_data_api__sourced_block_result` Modify or add attributes to a block's output in the Block Data API. ```php /** * Filters a block when parsing is complete. * * @param array $sourced_block An associative array of parsed block data with keys 'name' and 'attributes'. * @param string $block_name The name of the parsed block, e.g. 'core/paragraph'. * @param int $post_id The post ID associated with the parsed block. * @param array $block The result of parse_blocks() for this block. * Contains 'blockName', 'attrs', 'innerHTML', and 'innerBlocks' keys. */ $sourced_block = apply_filters( 'vip_block_data_api__sourced_block_result', $sourced_block, $block_name, $post_id, $block->parsed_block); ``` This is useful when block rendering requires attributes stored in post metadata or outside of a block's markup. This filter can be used to add attributes to any core or custom block. For example: ```php add_filter( 'vip_block_data_api__sourced_block_result', 'add_custom_block_metadata', 10, 4 ); function add_custom_block_metadata( $sourced_block, $block_name, $post_id, $block ) { if ( 'wpvip/my-custom-block' !== $block_name ) { return $sourced_block; } // Add custom attribute to REST API result $sourced_block['attributes']['custom-attribute-name'] = 'custom-attribute-value'; return $sourced_block; } ``` Direct block HTML can be accessed through `$block['innerHTML']`. This may be useful if manual HTML parsing is necessary to gather data from a block. For another example of how this filter can be used to extend block data, we have implemented a default image block filter in [`src/parser/block-additions/core-image.php`][repo-core-image-block-addition]. This filter is automatically called on `core/image` blocks to add `width` and `height` to image attributes. --- ### `vip_block_data_api__before_parse_post_content` Modify raw post content before it's parsed by the Block Data API. The `$post_content` provided by this filter is directly what is stored in the post database before any processing occurs. ```php /** * Filters content before parsing blocks in a post. * * @param string $post_content The content of the post being parsed. * @param int $post_id Post ID associated with the content. */ $post_content = apply_filters( 'vip_block_data_api__before_parse_post_content', $post_content, $post_id ); ``` For example, this could be used to modify a block's type before parsing. The code below replaces instances of `test/invalid-block` blocks with `core/paragraph`: ```php add_filter( 'vip_block_data_api__before_parse_post_content', 'replace_invalid_blocks' ); function replace_invalid_blocks( $post_content, $post_id ) { return str_replace( 'wp:test/invalid-block', 'wp:paragraph', $post_content ); } $html = ' <!-- wp:test/invalid-block --> <p>Block content!</p> <!-- /wp:test/invalid-block --> '; $content_parser = new ContentParser(); $result = $content_parser->parse( $html ); // Evaluates to true assertEquals( [ [ 'name' => 'core/paragraph', 'attributes' => [ 'content' => 'Block content!', ], ], ], $result['blocks'] ); ``` **Warning** Be careful with content modification before parsing. In the example above, if a block contained the text "wp:test/invalid-block" outside of a block header, this would also be changed to "wp:paragraph". This is likely not the intent of the code. All block markup is sensitive to changes, even changes in whitespace. We've added this filter to make the plugin flexible, but any transforms to `post_content` should be done with extreme care. Strongly consider adding tests to any usage of this filter. --- ### `vip_block_data_api__after_parse_blocks` Modify the Block Data API REST endpoint response. ```php /** * Filters the API result before returning parsed blocks in a post. * * @param string $result The successful API result, contains 'blocks' key with an array * of block data, and optionally 'warnings' and 'debug' keys. * @param int $post_id Post ID associated with the content. */ $result = apply_filters( 'vip_block_data_api__after_parse_blocks', $result, $post_id ); ``` This filter is called directly before returning a result in the REST API. Use this filter to add additional metadata or debug information to the API output. ```php add_filter( 'vip_block_data_api__after_parse_blocks', 'add_block_data_debug_info', 10, 2 ); function add_block_data_debug_info( $result, $post_id ) { $result['debug']['my-value'] = 123; return $result; } ``` This would add `debug.my-value` to all Block Data API REST results: ```bash > curl https://my.site/wp-json/vip-block-data-api/v1/posts/1/blocks { "debug": { "my-value": 123 }, "blocks": [ /* ... */ ] } ``` --- ### `vip_block_data_api__before_block_render` ### `vip_block_data_api__after_block_render` Perform actions before or after blocks are rendered by the `ContentParser`, such as hooking into core block rendering functions. ```php add_action( 'vip_block_data_api__before_block_render', 'add_block_context_filter', 10, 2 ); add_action( 'vip_block_data_api__after_block_render', 'remove_block_context_filter', 10, 2 ); function block_context_filter( $block_context, $parsed_block ) { // Modify block context before rendering $block_context['custom/injected-context'] = 'example'; return $block_context; } function add_block_context_filter( $blocks, $post_id ) { add_filter( 'render_block_context', 'block_context_filter', 10, 2 ); } function remove_block_context_filter( $blocks, $post_id ) { remove_filter( 'render_block_context', 'block_context_filter', 10 ); } ``` ## Analytics **Please note that, this is for VIP sites only. Analytics are disabled if this plugin is not being run on VIP sites.** The plugin records two data points for analytics, on VIP sites: 1. A usage metric when the `/wp-json/vip-block-data-api` REST API is used to retrive block data. This analytic data simply is a counter, and includes no information about the post's content or metadata. It will only include the customer site ID to associate the usage. 2. When an error occurs from within the plugin on the [WordPress VIP][wpvip] platform. This is used to identify issues with customers for private follow-up. Both of these data points are a counter that is incremented, and do not contain any other telemetry or sensitive data. You can see what's being [collected in code here][repo-analytics], and WPVIP's privacy policy [here](https://wpvip.com/privacy/). In addition, the analytics are sent every 10 seconds only. ## Caching on WPVIP All requests to the Block Data API on WPVIP will automatically be cached for 1 minute. Be aware that authenticated requests will bypass this cache, so be very cautious when using the [REST permissions filter](#vip_block_data_api__rest_permission_callback). More information about WPVIP's caching [can be found here][wpvip-page-cache]. ## Errors and Warnings ### Error: `vip-block-data-api-no-blocks` The VIP Block Data API is designed to parse structured block data, and can not read content from WordPress before the release of Gutenberg in [WordPress 5.0][wordpress-release-5-0] or created using the [classic editor plugin][wordpress-plugin-classic-editor]. If the parser encounters post content that does not contain block data, this error will be returned with an HTTP `400` response code: ```js { "code": "vip-block-data-api-no-blocks", "message": "Error parsing post ID ...: This post does not appear to contain block content. The VIP Block Data API is designed to parse Gutenberg blocks and can not read classic editor content." } ``` ### Error: `vip-block-data-api-parser-error` If any unexpected errors are encountered during block parsing, the block API will return error data with an HTTP `500` response code: ```js { "code": "vip-block-data-api-parser-error", "message": "..." } ``` The full stack trace for the error will be available in the site's logs: ``` [29-Mar-2023 07:42:58 UTC] PHP Warning: vip-block-data-api (<version>): Exception: ... Stack trace: #0 ... ``` If you encounter an error, we would really appreciate it if you could [create a bug report][repo-issue-create] so that we can understand and fix the issue. ### Warning: Unregistered block type The Block Data API requires blocks to be [server-side registered][wordpress-block-metadata-php-registration] in order to return full block attributes. When the plugin encounters post content containing a block that is not registered, a warning will be returned with block data: ```js { "blocks": [{ "name": "wpvip/client-side-block", "attributes": { /* ... */ } }], "warnings": [ "Block type 'wpvip/client-side-block' is not server-side registered. Sourced block attributes will not be available." ] } ``` These warnings indicate blocks that are missing from the server-side registry. Review the **[Client-side blocks](#client-side-blocks)** section for information about this limitation, which attributes will be accessible in client-side blocks, and recommendations for registering custom blocks server-side. ## Development In order to ensure no dev dependencies go in, the following can be done while installing the packages: ``` composer install --no-dev ``` ### Tests Run tests locally with [`wp-env`][wp-env] and Docker: ``` wp-env start composer install composer run test ``` <!-- Links --> [gutenberg-code-image-caption]: https://github.com/WordPress/gutenberg/blob/3d2a6d7eaa4509c4d89bde674e9b73743868db2c/packages/block-library/src/image/block.json#L30-L35 [gutenberg-code-table-body]: https://github.com/WordPress/gutenberg/blob/74a06c73613d9f90d66905c14d36eda19101999e/packages/block-library/src/table/block.json#L64-L108 [gutenberg-pr-core-list-innerblocks]: https://href.li/?https://github.com/WordPress/gutenberg/pull/39487 [media-example-caption-plain]: https://github.com/Automattic/vip-block-data-api/blob/media/example-caption-plain.png [media-example-caption-rich-text]: https://github.com/Automattic/vip-block-data-api/blob/media/example-caption-rich-text.png [media-example-heading-paragraph]: https://github.com/Automattic/vip-block-data-api/blob/media/example-header-paragraph.png [media-example-list-quote]: https://github.com/Automattic/vip-block-data-api/blob/media/example-utility-quote-list.png [media-example-media-text]: https://github.com/Automattic/vip-block-data-api/blob/media/example-media-text.png [media-example-nested-columns]: https://github.com/Automattic/vip-block-data-api/blob/media/example-nested-columns.png [media-example-pullquote]: https://github.com/Automattic/vip-block-data-api/blob/media/example-pullquote.png [media-example-table]: https://github.com/Automattic/vip-block-data-api/blob/media/example-table.png [media-example-utility-quote-list]: https://github.com/Automattic/vip-block-data-api/blob/media/example-list-quote.png [media-plugin-activate]: https://github.com/Automattic/vip-block-data-api/blob/media/plugin-activate.png [media-preact-media-text]: https://github.com/Automattic/vip-block-data-api/blob/media/preact-media-text.png [preact]: https://preactjs.com [repo-analytics]: src/analytics/analytics.php [repo-core-image-block-addition]: src/parser/block-additions/core-image.php [repo-issue-create]: https://github.com/Automattic/vip-block-data-api/issues/new/choose [repo-readme-1.2.4]: https://github.com/Automattic/vip-block-data-api/blob/1.2.4/README.md#graphql [repo-releases]: https://github.com/Automattic/vip-block-data-api/releases [vip-go-mu-plugins]: https://github.com/Automattic/vip-go-mu-plugins/ [vip-go-skeleton-plugin-loader-example]: https://github.com/Automattic/vip-go-skeleton/blob/ce21ab0/client-mu-plugins/plugin-loader.php [wordpress-application-passwords]: https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/ [wordpress-block-attributes-html]: https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#html-source [wordpress-block-deprecation]: https://developer.wordpress.org/block-editor/reference-guides/block-api/block-deprecation/ [wordpress-block-json-recommendation]: https://make.wordpress.org/core/2021/06/23/block-api-enhancements-in-wordpress-5-8/ [wordpress-block-metadata-php-registration]: https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#php-server-side [wordpress-plugin-classic-editor]: https://wordpress.org/plugins/classic-editor/ [wordpress-register-block-type-js]: https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#registerblocktype [wordpress-register-block-type-php]: https://developer.wordpress.org/reference/functions/register_block_type/ [wordpress-release-5-0]: https://wordpress.org/documentation/wordpress-version/version-5-0/ [wordpress-rest-api-posts]: https://developer.wordpress.org/rest-api/reference/posts/ [wp-env]: https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/ [wpgraphql-install]: https://www.wpgraphql.com/docs/quick-start#install [wpvip-mu-plugins-block-data-api]: https://docs.wpvip.com/technical-references/vip-go-mu-plugins/block-data-api-plugin/ [wpvip-page-cache]: https://docs.wpvip.com/technical-references/caching/page-cache/ [wpvip-plugin-activate]: https://docs.wpvip.com/how-tos/activate-plugins-through-code/ [wpvip-plugin-submodules]: https://docs.wpvip.com/technical-references/plugins/installing-plugins-best-practices/#h-submodules [wpvip-plugin-subtrees]: https://docs.wpvip.com/technical-references/plugins/installing-plugins-best-practices/#h-subtrees [wpvip]: https://wpvip.com/ [vip-ic]:https://docs.wpvip.com/integrations/center/ [vip-ic-org]:https://docs.wpvip.com/integrations/org-integrations/ [vip-ic-app]:https://docs.wpvip.com/integrations/app-integrations/

WordPress Themes & Plugins
123 Github Stars
media-explorer
Open Source

media-explorer

Media Explorer ============== Media Explorer gives you the ability to insert content from social media services in your posts. Setup ----- In order to get this working in your WordPress installation, you have to follow the next steps: * Clone this repo in the plugins folder of your WordPress install with `git clone https://github.com/Automattic/media-explorer.git`. * Get your credentials: * [Twitter](https://dev.twitter.com) * [Instagram](https://instagram.com/developer). * [YouTube](https://developers.google.com/youtube/v3/). * For YouTube, you'll have to create or use an existing project in your [Google Developers Console](https://cloud.google.com/console/project) * Ensure that this project has the "YouTube Data API v3" API enabled. * Create and use a public access API Key for your project. * Write your credentials in [mexp-creds.php](https://github.com/Automattic/media-explorer/blob/master/mexp-creds.php) * Activate the "MEXP oAuth Creditials" plugin to enable the configured API keys. * Enjoy!

Media WordPress Themes & Plugins
123 Github Stars
ad-code-manager
Open Source

ad-code-manager

# Ad Code Manager Stable tag: 0.8.0 Requires at least: 6.4 Tested up to: 6.9 Requires PHP: 7.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: advertising, ad codes, ads, adsense, dfp, doubleclick for publishers Contributors: rinatkhaziev, jeremyfelt, danielbachhuber, carldanley, zztimur, automattic, doejo, garyj Manage your ad codes through the WordPress admin safely and easily. ## Description Ad Code Manager gives non-developers an interface in the WordPress admin for configuring your complex set of ad codes. Some code-level configuration may be necessary to set up Ad Code Manager. Ad tags must be added (via `do_action()`) to your theme's template files where you'd like ads to appear. Alternatively, you can incorporate ad tags into your website with our widget and shortcode. Check out the configuration guide below for the full details. A common set of parameters must also be defined for your ad provider. This includes the tag IDs used by your template, the default URL for your ad provider, and the default HTML surrounding that URL. Ad Code Manager supports Google DoubleClick For Publishers (and Async), and Google AdSense. All the logic is abstracted, however, so configuring a different provider is relatively easy. Check `providers/doubleclick-for-publishers.php` for an idea of how to extend ACM to suit your needs. Once this configuration is in place, the Ad Code Manager admin interface will allow you to add new ad codes, modify the parameters for your script URL, and define conditionals to determine when the ad code appears. Conditionals are core WordPress functions like is_page(), is_category(), or your own custom functions that evaluate certain expressions and then return true or false. [Fork the plugin on Github](https://github.com/Automattic/Ad-Code-Manager) and [follow our development blog](http://adcodemanager.wordpress.com/). ## Installation The plugin requires PHP 7.4 or later. It is also tested WordPress 6.4 and later, though it may run on older versions. Since the plugin is in its early stages, there are a couple additional configuration steps: 1. Upload `ad-code-manager` to the `/wp-content/plugins/` directory. 2. Activate the plugin through the 'Plugins' menu in WordPress. 3. Incorporate ad tags in your theme template with `do_action( 'acm_tag', 'slot' );`. Also, you can use `[acm-tag id="slot"]` shortcode or ACM Widget. 4. Implement filters to make the plugin work with your provider. 5. Configure your ad codes in the WordPress admin (Tools -> Ad Code Manager). ## Screenshots 1. Adding an ad code with a site name, zone, and multiple conditionals. ![Adding an ad code with a site name, zone, and multiple conditionals.](.wordpress-org/screenshot-1.png) 2. Edit existing ad codes inline through the admin interface. ![Edit existing ad codes inline through the admin interface.](.wordpress-org/screenshot-2.png) 3. Access the Help menu in the upper right for configuration assistance. ![Access the Help menu in the upper right for configuration assistance.](.wordpress-org/screenshot-3.png) 4. Example of ad tag in use in a theme header template. ![Example of ad tag in use in a theme header template.](.wordpress-org/screenshot-4.jpg) ## Configure Ad Code Manager to manage the advertisements on your site Ad Code Manager is a VIP-sponsored plugin designed to make managing the ad codes used to display advertisements on your site easier. There's a little bit of work you'll need to do upfront to integrate Ad Code Manager with your theme. The high-level idea behind Ad Code Manager is that it gives non-developers an admin interface to manage ad codes. It then permits users to (optionally) target specific ad codes using conditionals like `is_home()` and `is_single()`. Ad codes are associated with positions in the theme through the use of ad tags. Currently, Ad Code Manager easily integrates with Google DoubleClick For Publishers Async and Google AdSense. Other ad providers are supported with additional configuration. ### Google AdSense and DoubleClick For Publishers Async Let's use AdSense as our first example. You'll want to incorporate some of the default ad tags into your theme by use of `do_action()`. Here's an example you might put in your header.php file: ~~~php do_action( 'acm_tag', '728x90_leaderboard' ); ~~~ Once done, you can select the "Google AdSense" provider in the admin. Ad codes can be registered against ad tags (positions) by choosing the ad tag from the drop-down, entering the tag ID and publisher ID, and hitting "Add New Ad Code". And like that, your 728x90 leaderboard will appear on your site. The Google AdSense configuration comes with many of Google's suggested sizes. Additional ad tags can be registered by way of filtering: ~~~php add_filter( 'acm_ad_tag_ids', 'acmx_filter_ad_tag_ids' ); function acmx_filter_ad_tag_ids( $ids ) { $ids[] = array( 'enable_ui_mapping' => true, 'tag' => '100x100_smallsquare', 'url_vars' => array( 'tag' => '100x100_smallsquare', 'height' => '100', 'width' => '100', ), ); return $ids; } ~~~ Keep in mind that you'll still need to incorporate a `do_action( 'acm_tag', '100x100_smallsquare' );` in your theme to display the ad tag. If you choose Google DFP Async as your provider, you'll likely need to register additional ad tags, as we only package two default ad tags. ### Custom Ad Provider Implementations As mentioned previously, other ad code providers are supported with additional configuration. Here's an example of the different filters you would use to configure the older version of Google DoubleClick For Publishers: ~~~php /** * Define the default URL to be used when rendering ad codes */ add_filter( 'acm_default_url', 'acmx_filter_default_url' ) ; function acmx_filter_default_url( $url ) { if ( 0 === strlen( $url ) ) { return "http://ad.doubleclick.net/adj/%site_name%/%zone1%;s1=%zone1%;s2=;pid=%permalink%;fold=%fold%;kw=;test=%test%;ltv=ad;pos=%pos%;dcopt=%dcopt%;tile=%tile%;sz=%sz%;"; } } /** * Whitelist the DFP URL to be used in ad tags. The whitelist * helps prevent execution of arbitrary scripts */ add_filter( 'acm_whitelisted_script_urls', 'acmx_filter_whitelisted_script_urls'); function acmx_filter_whitelisted_script_urls( $whitelisted_urls ) { $whitelisted_urls = array( 'ad.doubleclick.net' ); return $whitelisted_urls; } /** * Define the different ad tags (locations) you'd like to use in your theme */ add_filter( 'acm_ad_tag_ids', 'acmx_ad_tags_ids' ); function acmx_ad_tags_ids( $ad_tag_ids ) { return array( array( 'tag' => '728x90-atf', 'url_vars' => array( 'sz' => '728x90', 'fold' => 'atf', 'width' => '728', 'height' => '90', ), ), array( 'tag' => '728x90-btf', 'url_vars' => array( 'sz' => '728x90', 'fold' => 'btf', 'width' => '728', 'height' => '90', ), ), array( 'tag' => '300x250-atf', 'url_vars' => array( 'sz' => '300x250', 'fold' => 'atf', 'width' => '300', 'height' => '250', ), ), array( 'tag' => '300x250-btf', 'url_vars' => array( 'sz' => '300x250', 'fold' => 'btf', 'width' => '300', 'height' => '250', ), ), array( 'tag' => '160x600-atf', 'url_vars' => array( 'sz' => '160x600', 'fold' => 'atf', 'width' => '160', 'height' => '600', ), ), array( 'tag' => '1x1', 'url_vars' => array( 'sz' => '1x1', 'fold' => 'int', 'pos' => 'top', ), ) ); } add_filter( 'acm_output_html','acmx_filter_output_html', 5, 2 ); /** * Register the full script output to use with each ad tag. */ function acmx_filter_output_html( $output_html, $tag_id ) { $output_html = '<!-- DFP %pos% %sz% ad tag --> <script> if ( typeof ord=='undefined' ) { ord=Math.random()*10000000000000000; } if ( typeof( dfp_tile ) == 'undefined' ) { dfp_tile=%tile% }; document.write('<script src="%url%ord=' + ord + '?"></script>'); </script><noscript><a href="%url%ord=%random%?" target="_blank"><img src="%url%ord=%random%?" width="%width%" height="%height%" border="0" alt="></a></noscript> <!-- //DFP %pos% %sz% tag -->'; return $output_html; } add_filter('acm_output_tokens', 'acmx_filter_output_tokens', 5, 3 ); /** * Fine tune our output tokens. * * This is the real example of how easily you can modify output * depending on your ad network specs. */ function acmx_filter_output_tokens( $output_tokens, $tag_id, $code_to_display ) { global $dfp_tile; global $dfp_ord; global $dfp_pos; global $dfp_dcopt; global $wp_query; // We can't really rely on get_permalink() so use $_SERVER['REQUEST_URI] as bulletproof solution for generating unique pids $link = strlen( $_SERVER['REQUEST_URI'] ) > 1 ? sanitize_key( $_SERVER['REQUEST_URI'] ) : home_url(); $output_tokens['%permalink%'] = str_replace( array( '/',':', '.' ), '', $link ); $output_tokens['%random%'] = $dfp_ord; $output_tokens['%tile%'] = ++$dfp_tile; if ( false === $dfp_pos[ $code_to_display['url_vars']['sz'] ] ) { $output_tokens['%pos%'] = 'top'; $dfp_pos[ $code_to_display['url_vars']['sz'] ] = true; } else { $output_tokens['%pos%'] = 'bottom'; } if ( ! $dfp_dcopt ) { $output_tokens['%dcopt%'] = 'ist'; $dfp_dcopt = true; } else { $output_tokens['%dcopt%'] = ''; } $output_tokens['%test%'] = isset( $_GET['test'] ) && $_GET['test'] == 'on' ? 'on' : ''; return $output_tokens; } ~~~ ## Configuration Filters There are some filters which allow you to easily customize the output of the plugin. You should place these filters in your theme's functions.php file or in another appropriate place. [Check out this gist](https://gist.github.com/1631131) to see all of the filters in action. ### `acm_ad_tag_ids` Ad tag IDs are used as a parameter when adding tags to your theme (e.g. `do_action( 'acm_tag', 'my_top_leaderboard' )`). The `url_vars` defined as part of each tag here will also be used to replace tokens in your default URL. Arguments: * array $tag_ids array of default tag IDs Example usage: Add a new ad tag called 'my_top_leaderboard' ~~~php add_filter( 'acm_ad_tag_ids', 'my_acm_ad_tag_ids' ); function my_acm_ad_tag_ids( $tag_ids ) { $tag_ids[] = array( 'tag' => 'my_top_leaderboard', // tag_id 'url_vars' => array( 'sz' => '728x90', // %sz% token 'fold' => 'atf', // %fold% token 'my_custom_token' => 'something' // %my_custom_token% will be replaced with 'something' ), ); return $tag_ids; } ~~~ ### `acm_default_url` Set the default tokenized URL used when displaying your ad tags. This filter is required. Arguments: * string $url The tokenized URL of Ad Code Example usage: Set your default ad code URL ~~~php add_filter( 'acm_default_url', 'my_acm_default_url' ); function my_acm_default_url( $url ) { if ( 0 === strlen( $url ) ) { return "http://ad.doubleclick.net/adj/%site_name%/%zone1%;s1=%zone1%;s2=;pid=%permalink%;fold=%fold%;kw=;test=%test%;ltv=ad;pos=%pos%;dcopt=%dcopt%;tile=%tile%;sz=%sz%;"; } } ~~~ ### `acm_output_html` The HTML outputted by the `do_action( 'acm_tag', 'ad_tag_id' );` call in your theme. Support multiple ad formats (e.g. JavaScript or simple HTML tags) by adjusting the HTML rendered for a given ad tag. The `%url%` token used in this HTML will be filled in with the URL defined with `acm_default_url`. Arguments: * string $output_html The original output HTML * string $tag_id Ad tag currently being accessed Example usage: ~~~php add_filter( 'acm_output_html', 'my_acm_output_html', 10, 2 ); function my_acm_output_html( $output_html, $tag_id ) { switch ( $tag_id ) { case 'my_leaderboard': $output_html = '<a href="%url%"><img src="%image_url%" /></a>'; break; case 'rich_media_leaderboard': $output_html = '<script> // omitted </script>'; break; default: break; } return $output_html; } ~~~ ### `acm_register_provider_slug` Ad Code Manager has a built-in list of providers that it gathers by scanning the 'providers' directory used by the plugin. Additional providers can be added by placing the appropriate files in that directory or using the `acm_register_provider_slug` filter to register those that may be included as part of your theme or another plugin. When using this plugin, you are defining the provider slug as part of the existing object as well as an array of classes associated with that provider slug. Arguments: * object $providers An object containing the current registered providers. Example usage: ~~~php add_filter( 'acm_register_provider_slug', 'my_acm_register_provider_slug' ); function my_acm_register_provider_slug( $providers ) { $providers->new_provider_slug = array( 'provider' => 'My_New_Ad_Company_ACM_Provider', 'table' => 'My_New_Ad_Company_ACM_WP_List_Table' ); return $providers; } ~~~ ### `acm_whitelisted_script_urls` A security filter to define a safelist for which ad code script URLs can be added in the admin. Arguments: * array $whitelisted_urls Existing whitelisted ad code URLs Example usage: Allow DoubleClick for Publishers ad codes to be used ~~~php add_filter( 'acm_whitelisted_script_urls', 'my_acm_safelisted_script_urls' ); function my_acm_safelisted_script_urls( $safelisted_urls ) { $safelisted_urls = array( 'ad.doubleclick.net' ); return $safelisted_urls; } ~~~ ### `acm_output_tokens` Output tokens can be registered depending on the needs of your setup. Tokens defined here will be replaced in the ad tag's tokenized URL in addition to the tokens already registered with your tag ID. Arguments: * array $output_tokens Any existing output tokens * string $tag_id Unique tag ID * array $code_to_display Ad Code that matched conditionals Example usage: Test to determine whether you're in test or production by passing ?test=on query argument ~~~php add_filter( 'acm_output_tokens', 'my_acm_output_tokens', 10, 3 ); function my_acm_output_tokens( $output_tokens, $tag_id, $code_to_display ) { $output_tokens['%test%'] = isset( $_GET['test'] ) && $_GET['test'] == 'on' ? 'on' : ''; return $output_tokens; } ~~~ ### `acm_whitelisted_conditionals` Extend the list of usable conditional functions with your own awesome ones. We safelist these so users can't execute random PHP functions. Arguments: * array $conditionals Default conditionals Example usage: Register a few custom conditional callbacks ~~~php add_filter( 'acm_whitelisted_conditionals', 'my_acm_safelisted_conditionals' ); function my_acm_safelisted_conditionals( $conditionals ) { $conditionals[] = 'my_is_post_type'; $conditionals[] = 'is_post_type_archive'; $conditionals[] = 'my_page_is_child_of'; return $conditionals; } ~~~ ### `acm_conditional_args` For certain conditionals (`has_tag()`, `has_category()`), you might need to pass additional arguments. Arguments: * array $cond_args Existing conditional arguments * string $cond_func Conditional function (`is_category()`, `is_page()`, etc.) Example usage: `has_category()` and `has_tag()` use `has_term()`, which requires the object ID to function properly. ~~~php add_filter( 'acm_conditional_args', 'my_acm_conditional_args', 10, 2 ); function my_acm_conditional_args( $cond_args, $cond_func ) { global $wp_query; // The `has_category()` and `has_tag()` functions call the `has_term()` function. // We should pass queried object id for it to produce correct result. if ( in_array( $cond_func, array( 'has_category', 'has_tag' ) ) && $wp_query->is_single == true ) { $cond_args[] = $wp_query->queried_object->ID; } // my_page_is_child_of is our custom WP conditional tag and we have to pass queried object ID to it. if ( in_array( $cond_func, array( 'my_page_is_child_of' ) ) && $wp_query->is_page ) { $cond_args[] = $cond_args[] = $wp_query->queried_object->ID; } return $cond_args; } ~~~ ### `acm_display_ad_codes_without_conditionals` Change the behavior of Ad Code Manager so that ad codes without conditionals display on the front end. The default behavior is that each ad code requires a conditional to be included in the presentation logic. Arguments: * bool $behavior Whether or not to display the ad codes that don't have conditionals Example usage: ~~~php add_filter( 'acm_display_ad_codes_without_conditionals', '__return_true' ); ~~~ ### `acm_provider_slug` By default, we use our bundled doubleclick_for_publishers config (check it in `/providers/doubleclick-for-publishers.php`). If you want to add your own flavor of DFP or even implement configuration for another ad network, you'd have to apply a filter to correct the slug. Example usage: ~~~php add_filter( 'acm_provider_slug', function() { return 'my-ad-network-slug'; } ); ~~~ ### `acm_logical_operator` By default, the logical operator is set to "OR", that is, ad code will be displayed if at least one conditional returns true. You can change it to "AND", so that the ad code will be displayed only if ALL the conditionals match. Example usage: ~~~php add_filter( 'acm_logical_operator', function() { return 'AND'; } ); ~~~ ### `acm_manage_ads_cap` By default, the user has to have `manage_options` cap. This filter comes in handy if you want to relax the requirements. Example usage: ~~~php add_filter( 'acm_manage_ads_cap', function( $cap ) { return 'edit_others_posts'; } ); ~~~ ### `acm_allowed_get_posts_args` This filter is only for edge cases. Most likely, you won't have to touch it. Allows to include additional query args for `Ad_Code_Manager->get_ad_codes()` method. Example usage: ~~~php add_filter( 'acm_allowed_get_posts_args', function( $args_array ) { return array( 'offset', 'exclude' ); } ); ~~~ ### `acm_ad_code_count` By default, the total number of ad codes to get is 50, which is reasonable for any small to mid-sized site. However, in certain cases, you would want to increase the limit. This will affect `Ad_Code_Manager->get_ad_codes()` `numberposts` query argument. Example usage: ~~~php add_filter( 'acm_ad_code_count', function( $total ) { return 100; } ); ~~~ ### `acm_list_table_columns` This filter can alter table columns that are displayed in ACM UI. Example usage: ~~~php add_filter( 'acm_list_table_columns', 'my_acm_list_table_columns' ); function my_acm_list_table_columns( $columns ) { $columns = array( 'id' => __( 'ID', 'ad-code-manager' ), 'name' => __( 'Name', 'ad-code-manager' ), 'priority' => __( 'Priority', 'ad-code-manager' ), 'conditionals' => __( 'Conditionals', 'ad-code-manager' ), ); return $columns; } ~~~ ### `acm_ad_code_args` This filter comes in pair with the previous one. It should return an array of ad network-specific parameters. E.g. in `acm_list_table_columns` example, we have 'id', 'name', 'priority', and 'conditionals'. All of them except 'name' are generic for Ad Code Manager. Hence, `acm_provider_columns` should return only "name". "editable" and "required" indicate whether this field should be editable and required. Example usage: ~~~php add_filter( 'acm_ad_code_args', 'my_acm_ad_code_args' ); function my_acm_ad_code_args( $args ) { $args = array( array( 'key' => 'name', 'label' => __( 'Name', 'ad-code-manager' ), 'editable' => true, 'required' => true, ), ); return $args; } ~~~ ### Change Log [View the change log](https://github.com/Automattic/ad-code-manager/blob/master/CHANGELOG.md).

Marketing & SEO WordPress Themes & Plugins
118 Github Stars
syndication
Open Source

syndication

# Syndication Stable tag: 2.2.0 Requires at least: 6.4 Tested up to: 6.9 Requires PHP: 7.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: syndication, xmlrpc, rest-api, content-distribution, multisite Contributors: automattic, garyj, nprasath002, batmoo, betzster, nickdaugherty Syndicate content to and from your WordPress sites. Push posts to multiple destinations or pull content from external feeds with a single click. ## Description Syndication helps users manage posts across multiple sites. It's useful when managing posts on different platforms. With a single click you can push a post to more than 100 sites. ### Features * **Push syndication** - Publish content to multiple WordPress sites simultaneously * **Pull syndication** - Import content from RSS/XML feeds automatically * **Multiple transport methods** - WordPress.com REST API, XML-RPC, and RSS/XML feeds * **Site groups** - Organise destination sites into groups for easier management * **Scheduled syndication** - Content syncs automatically when posts are published * **WP-CLI support** - Manage syndication from the command line ## Installation 1. Upload the `syndication` folder to `/wp-content/plugins/` or install via the WordPress admin. 2. Activate the plugin through the 'Plugins' menu in WordPress. 3. Visit **Settings > Push Syndication** to configure the plugin. 4. When editing a post, use the "Syndication" metabox to select destination sites/groups. ## Usage Here's how it works: 1. Configure which post types are "pushable", as well as whether you'd like syndicated posts to be deleted when the master post is deleted. 2. Register and group your sites into "Sitegroups" in settings. 3. In the WordPress posting interface, you'll see a new "Syndication" metabox, with all of your sitegroups listed. Select the sitegroups you want to push to and the post will be automatically syndicated to your other sites when it's published and updated. ### WordPress.com REST API To push content using the WordPress.com REST API you need to create an [application](https://developer.wordpress.com/apps/new/) from the [WordPress.com Developer Resources](https://developer.wordpress.com/) site - and you can also generate API tokens directly from the plugin's settings page. Fill in the client ID and client secret as displayed on the app page, and click the authorize button to get directed to the authorization page on WordPress.com. Select which site you'd like to push to and click "Authorize", at which point you'll be redirected back to your settings page-which will now display the API token, Blog ID, and Blog URL. You can now use this information to register your WordPress.com site. ### Using WordPress XML-RPC To push content using XML-RPC, you'll need to enable XML-RPC on the destination site and provide the site URL, username, and password. Note that if you have two-factor authentication enabled on the destination site, you will need to create an application password to use when adding a new site. Using your regular password will not work. ### Pulling from RSS Feeds Push Syndication can ingest RSS feeds into your site. It's as simple as adding a site, setting the transport type to "RSS (pull)" and entering an RSS URL and title. To add a site, go to the WordPress admin and find the "Sites" menu item, below Settings and choose "Add New". In the settings, you'll be able to customise the post's type, status, comment settings, pingback settings and category. ### Secure Credential Storage To store passwords securely, define an encryption key in your `wp-config.php`: ```php define( 'PUSH_SYNDICATE_KEY', 'your-random-encryption-key-here' ); ``` This key is used to encrypt credentials when saved to the database. ## Frequently Asked Questions ### What transport methods are supported? * **WordPress.com REST API** - For sites hosted on WordPress.com or using Jetpack * **XML-RPC** - For self-hosted WordPress sites with XML-RPC enabled * **RSS/XML feeds** - For pulling content from any feed source ### Can I syndicate to non-WordPress sites? The push functionality requires WordPress on the destination site. However, pull syndication can import content from any valid RSS or XML feed. ### Does it work with multisite? Yes, Syndication works with WordPress multisite installations. You can syndicate content between subsites or to external sites. ## Changelog See [CHANGELOG.md](CHANGELOG.md) for the full changelog. ## Contributing Pull requests are welcome on [GitHub](https://github.com/Automattic/syndication).

CMS Plugins & Extensions Object Storage
107 Github Stars
zoninator
Open Source

zoninator

# Zone Manager (Zoninator) Stable tag: 0.11.0 Requires at least: 6.4 Tested up to: 6.9 Requires PHP: 7.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: zones, post order, post list, posts, order, zonination, content curation, curation, content management Contributors: batmoo, automattic, wpcomvip, pkevan, matthumphreys, potatomaster, jblz, nickdaugherty, betzster, garyj Content curation made easy! Create "zones" then add and order your content! ## Description This plugin is designed to help you curate your content. It lets you assign and order stories within zones that you create, edit, and delete, and display those groupings of related stories on your site. This plugin was originally built by [Mohammad Jangda](http://digitalize.ca) in conjunction with [William Davis](http://wpdavis.com/) and the [Bangor Daily News](http://www.bangordailynews.com/). ### Features * Add, edit, and delete zones. * Add and remove posts (or any custom post type) to or from zones. * Order posts in any given zone. * Limit capabilities on who can add, edit, and delete zones vs add content to zones. * Locking mechanism, so only one user can edit a zone at a time (to avoid conflicts). * Idle control, so people can't keep the zone locked. ## Installation 1. Unzip contents and upload to the `/wp-content/plugins/` directory 2. Activate the plugin through the 'Plugins' menu in WordPress 3. Go to Dashboard > Zones to create and manage your zones, and easily search for and add existing posts. 4. Use the plugin's handy API functions to add zones to your theme that retrieve and display your content. Or, for those who are a bit code-averse, go to Appearance-Widgets and add Zone Posts widgets to display your zone posts in your sidebar or footer. The widget will pull the posts from the chosen zone. ### Usage examples You can work with a zone's posts either as a `WP_Query` object or as a plain array. **WP_Query** ~~~php $zone_query = z_get_zone_query( 'homepage' ); if ( $zone_query->have_posts() ) : while ( $zone_query->have_posts() ) : $zone_query->the_post(); echo '<li>' . esc_html( get_the_title() ) . '</li>'; endwhile; wp_reset_postdata(); endif; ~~~ **Posts Array** ~~~php $zone_posts = z_get_posts_in_zone( 'homepage' ); foreach ( $zone_posts as $zone_post ) : echo '<li>' . esc_html( get_the_title( $zone_post->ID ) ) . '</li>'; endforeach; ~~~ For the full template-tag reference, see the [theme developer guide](https://github.com/Automattic/zoninator/blob/main/docs/theme-developers.md). ## Documentation Audience-targeted documentation lives in the GitHub repository: * [Theme developer guide](https://github.com/Automattic/zoninator/blob/main/docs/theme-developers.md) — using zones in your theme. * [Hooks reference](https://github.com/Automattic/zoninator/blob/main/docs/hooks.md) — every filter and action the plugin exposes. * [REST API](https://github.com/Automattic/zoninator/blob/main/docs/rest-api.md) — endpoints under the `zoninator/v1` namespace, for headless integrations. * [Contributing](https://github.com/Automattic/zoninator/blob/main/CONTRIBUTING.md) — local setup, tests, and PR conventions. * [Security](https://github.com/Automattic/zoninator/blob/main/SECURITY.md) — responsible disclosure. ## Frequently Asked Questions ### How do I disable the locking feature? You can use a filter: ~~~php add_filter( 'zoninator_zone_max_lock_period', 'z_disable_zoninator_locks' ); ~~~ ### How do I change the locking feature settings? Filter the following and change according to your needs: * Number of seconds a lock is valid for, default `30`: `zoninator_zone_lock_period` * Max idle time in seconds: `zoninator_zone_max_lock_period` ### Can anonymous users still read zones over the REST API? Not by default since version 0.11.0. The `GET /wp-json/zoninator/v1/zones` endpoint now requires an authenticated user. If your integration relied on anonymous access, you can restore the previous behaviour with the `zoninator_rest_get_zones_permissions_check` filter: ~~~php add_filter( 'zoninator_rest_get_zones_permissions_check', '__return_true' ); ~~~ See the [REST API documentation](https://github.com/Automattic/zoninator/blob/main/docs/rest-api.md) for the full endpoint reference. ### Can I use Zoninator with custom post types? Yes. Call `Zoninator()->register_zone_post_type( 'your_post_type' )` after `init` to add zone support to a custom post type. ## Upgrade Notice ### 0.11.0 The `GET /wp-json/zoninator/v1/zones` REST endpoint now requires an authenticated user. If your site depends on anonymous access, opt back in with the `zoninator_rest_get_zones_permissions_check` filter. Three security fixes are included — review the changelog before upgrading. ## Changelog Please visit the [changelog](https://github.com/Automattic/zoninator/blob/main/CHANGELOG.md). ## Screenshots 1. Create and manage your zones and content through a fairly intuitive and familiar interface. ![Overview of a homepage slideshow zone showing the name and description, and two posts assigned to that zone](.wordpress-org/screenshot-1.png) 2. Zone editing ![Editing a food zone in Zoninator](.wordpress-org/screenshot-2.png) 3. Use the Zone Posts widget in the widgets area. ![A sidebar widget area with a couple of Zone Posts widgets](.wordpress-org/screenshot-3.png) 4. Output of the zone posts widgets. ![Sidebar front end with the links to posts showing](.wordpress-org/screenshot-4.png)

WordPress Themes & Plugins
86 Github Stars
msm-sitemap
Open Source

msm-sitemap

# Metro Sitemap Stable tag: 1.5.6 Requires at least: 6.4 Tested up to: 6.9 Requires PHP: 7.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: sitemap, xml, seo, performance, multisite Contributors: metro, automattic, alleyinteractive, makermedia, 10up, garyj High-performance XML sitemaps for large-scale WordPress sites. Built for speed, extensibility, and reliability. Metro Sitemap generates robust, scalable XML sitemaps for WordPress sites of any size. Designed for high-traffic and enterprise environments, it ensures your content is discoverable by search engines without slowing down your site. ## At a Glance * **Fast, reliable XML sitemaps** for large and small sites * **Asynchronous generation** avoids timeouts and memory issues * **Supports custom post types** (see FAQ) * **Multisite compatible** * **WP-CLI support** for advanced management * **Extensible** via hooks and filters ([see developer docs](./DEVELOPERS.md)) * **Admin UI** for stats, manual actions, and cron management * **Browser-friendly XSL styling** with independent stylesheet endpoints ## Installation 1. Upload the plugin folder to `/wp-content/plugins/` or install via the WordPress admin. 2. Activate the plugin through the 'Plugins' menu in WordPress. 3. (Optional) Visit **Tools > Sitemap** in the admin for stats and manual actions. 4. Sitemaps will be generated automatically in the background. ## Usage * Your sitemap index will be available at `/sitemap.xml` (e.g., `https://example.com/sitemap.xml`). * Sitemaps are generated in the background and updated as you publish new content. * The admin UI (Tools > Sitemap) provides stats and lets you manually trigger generation if needed. ### Automatic Updates By default, automatic sitemap updates are **disabled** to prevent resource issues on large sites. To enable automatic updates: **Via Admin UI:** 1. Go to **Tools > Sitemap** in your WordPress admin 2. In the "Cron Management" section, click "Enable Automatic Updates" 3. Once enabled, you can use the "Generate" section to manually trigger sitemap generation **Via WP-CLI:** ```shell wp msm-sitemap cron enable ``` **Important:** Automatic updates can use significant resources on sites with many posts. For large sites, consider using date-targeted WP-CLI commands instead (see below). ## Frequently Asked Questions ### Why isn’t my custom post type included in the sitemap? By default, only the `post` post type is included. To add custom post types (like `page`, `news`, or others), see the [Developer Guide](./DEVELOPERS.md). ### How do I include posts with a custom status? By default, only published posts are included. You can change this via a filter. See the [Developer Guide](./DEVELOPERS.md). ### How do I regenerate the sitemap? Sitemaps are generated automatically, but you can: * Use the admin UI (**Tools > Sitemap**) to trigger a manual rebuild * Use WP-CLI commands (see below) ### Does it work on multisite? Yes! Each site in your network will have its own sitemaps. The plugin can be network-activated. ### How do I exclude specific posts or dates? You can filter which posts or dates appear in the sitemap using hooks—see the [Developer Guide](./DEVELOPERS.md). ### Where is the sitemap stored? Sitemap XML is stored in a custom post type (`msm_sitemap`) and served on-demand for fast performance. ### Can I customize the number of posts per sitemap? Yes, this is filterable. See the [Developer Guide](./DEVELOPERS.md). ### How do I disable the XSL styling for sitemaps? If you want to serve plain XML without browser styling, you can disable the XSL stylesheet references: ```php add_filter( 'msm_sitemap_include_xsl_reference', '__return_false' ); ``` For more XSL customization options, see the [Developer Guide](./DEVELOPERS.md). ## WP-CLI Commands Metro Sitemap supports advanced management via WP-CLI. Here are the most common commands: ### Core Commands - **generate**: Generate sitemaps for all or specific dates. ```shell wp msm-sitemap generate --all ``` - **delete**: Delete sitemaps for all or specific dates. ```shell wp msm-sitemap delete --date=2024-07 ``` - **list**: List sitemaps. ```shell wp msm-sitemap list --format=json ``` - **get**: Get details for a sitemap by ID or date. ```shell wp msm-sitemap get 579 ``` - **validate**: Validate sitemaps for all or specific dates. ```shell wp msm-sitemap validate --all ``` - **export**: Export sitemaps to a directory. ```shell wp msm-sitemap export --all --output=/tmp ``` - **recount**: Recalculate and update the indexed URL count for all sitemap posts. ```shell wp msm-sitemap recount ``` - **stats**: Show sitemap statistics (total, most recent, etc). ```shell wp msm-sitemap stats --format=table ``` ### Cron Management Commands - **cron enable**: Enable automatic sitemap updates. ```shell wp msm-sitemap cron enable ``` - **cron disable**: Disable automatic sitemap updates. ```shell wp msm-sitemap cron disable ``` - **cron status**: Check the status of automatic updates. ```shell wp msm-sitemap cron status ``` - **cron reset**: Reset cron to clean state (for testing). ```shell wp msm-sitemap cron reset ``` For the full list of commands, options, and legacy command mapping, see [DEVELOPERS.md](./DEVELOPERS.md). ## Support * [GitHub Issues](https://github.com/Automattic/msm-sitemap/issues) (for bug reports and feature requests) * [WordPress VIP Support](https://wpvip.com/wordpress-vip-enterprise-support/) (for WPVIP customers) ## Credits Metro Sitemap is a joint collaboration between Metro.co.uk, WordPress VIP, Alley Interactive, Maker Media, 10up, and others. Special thanks to all contributors. ## Changelog See [CHANGELOG.md](./CHANGELOG.md) for a full history of changes. ## License GPLv2 or later. See [LICENSE](./LICENSE) for details. ## Developer Documentation For advanced customization, see [DEVELOPERS.md](./DEVELOPERS.md).

WordPress Themes & Plugins SEO Tools
86 Github Stars
maintenance-mode-wp
Open Source

maintenance-mode-wp

# Maintenance Mode Stable tag: 0.3.2 Requires at least: 6.4 Tested up to: 6.9 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: maintenance-mode, maintenance Contributors: wpcomvip, automattic, benoitchantre, emrikol, philipjohn, GaryJ Shut down your site for a little while and do some maintenance on it! ## Description Easily provide a holding maintenance page, including with a custom template, to site visitors. ### Custom Template To add a custom template and messaging: - Create a template in your theme's root folder named `template-maintenance-mode.php`. - This should be a simple HTML page that includes the message you want to show your visitors. - Note: the template should include `wp_head()` and `wp_footer()` calls. You can also use the `vip_maintenance_mode_template_args` filter to adjust the file name and location of the custom template within your theme. For instance, if you want it to live at `wp-content/themes/my-theme/plugin-templates/maintenance-mode-alt.php`, then add code like: ~~~php add_filter( 'vip_maintenance_mode_template_args', function( $args ) { $args['slug'] = 'plugin-templates/maintenance-mode'; $args['name'] = 'alt'; return $args; } ); ~~~ This also allows the third array key to be used to pass in custom arguments to the template. ### Additional Configurations Using filters and conditionals, you can customize the behavior of the Maintenance Mode plugin based on your needs. These options rely on the plugin being installed as described above. #### Selectively Load Maintenance Mode Configure Maintenance Mode to only display for a specific network site. Code similar to this example must be added to the `vip-config/vip-config.php` file: ~~~php $site_name = $_SERVER['SERVER_NAME']; $lockdown = false; if ( false !== strpos( $site_name, 'url-to-enable-maintentance-mode' ) ) { // Set lockdown $lockdown = true; } // Set maintenance plugin define( 'VIP_MAINTENANCE_MODE', $lockdown ); ~~~ #### Enable WordPress REST API Configure Maintenance Mode to keep the WordPress REST API enabled even though the rest of the site is not accessible. Note that this code should be added to a file located within the `client-mu-plugins` directory: ~~~php // Generally allow API access add_filter( 'vip_maintenance_mode_restrict_rest_api', '__return_false' ); ~~~ You can also choose to enable the REST API only in more narrow use-cases: ~~~php add_filter( 'vip_maintenance_mode_restrict_rest_api', 'x_mm_allow_api' ); function x_mm_allow_api( $default ) { if ( my_check() ) { return false; } return true; } ~~~ ## Installation 1. Add the plugin to the `/plugins` directory of an application's GitHub repository. 2. Define the `VIP_MAINTENANCE_MODE` constant as true in `vip-config/vip-config.php`. 3. Activate the plugin in the WordPress Admin dashboard Plugins screen. ## Screenshots On Twenty Twenty-Five: ![Screenshot of active Maintenance mode on Twenty Twenty-Five](.wordpress-org/screenshot-8.png) On Twenty Twenty-Four: ![Screenshot of active Maintenance mode on Twenty Twenty-Four](.wordpress-org/screenshot-7.png) On Twenty Twenty-Three: ![Screenshot of active Maintenance mode on Twenty Twenty-Three](.wordpress-org/screenshot-6.png) On Twenty Twenty-Two: ![Screenshot of active Maintenance mode on Twenty Twenty-Two](.wordpress-org/screenshot-5.png) On Twenty Twenty-One: ![Screenshot of active Maintenance mode on Twenty Twenty-One](.wordpress-org/screenshot-4.png) On Twenty Twenty: ![Screenshot of active Maintenance mode on Twenty Twenty](.wordpress-org/screenshot-3.png) On Twenty Nineteen: ![Screenshot of active Maintenance mode on Twenty Nineteen](.wordpress-org/screenshot-2.png) On Twenty Seventeen: ![Screenshot of active Maintenance mode on Twenty Seventeen](.wordpress-org/screenshot-1.png) ## Changelog See [the changelog](CHANGELOG.md).

WordPress Themes & Plugins Load Balancers & Proxy
50 Github Stars
Post-Meta-Inspector
Open Source

Post-Meta-Inspector

=== Post Meta Inspector === Contributors: danielbachhuber, automattic Tags: post meta, tools Tested up to: 5.0 Requires at least: 3.1 Stable tag: 1.1.2 License: GPLv2 or later Peer inside your post meta == Description == A quick and easy way to see post meta associated with any given post. When activated, this plugin prints your post meta keys and values inside of a post meta box. Originally developed for [WordPress.com VIP](http://vip.wordpress.com/)-hosted clients, we thought it would be useful for development environments, etc. too. Feel free to [fork the plugin in Github](https://github.com/Automattic/Post-Meta-Inspector) and pull requests are always welcome. Hit us with feedback, questions, bug reports, and feature requests in the forums. == Screenshots == 1. See the metadata associated with any post using the post meta box == Changelog == = 1.1.1 (Feb. 5, 2014) = * Bug fix: Properly declare static methods. = 1.1 (Nov. 6, 2012) = * New filter 'pmi_toggle_long_value_length' let's you optionally convert long post meta values to a "Click to view" UX. Thanks [cfg](https://github.com/cfg) for the pull request * Bug fix: Add CSS rules to prevent long code blocks from flowing outside of the meta box. Thanks [cfg](https://github.com/cfg) for the pull request * Change to singleton pattern = 1.0 (Oct. 5, 2012) = * Initial release * View the post meta associated with a given post through a post meta box

WordPress Themes & Plugins CRM
48 Github Stars
chatrix
Open Source

chatrix

# Chatrix - Contributors: wordpressdotorg, akirk, ashfame, psrpinto - Tags: matrix, chat - Requires at least: 6.0 - Tested up to: 6.8 - Requires PHP: 7.4 - License: [GPLv2](http://www.gnu.org/licenses/gpl-2.0.html) - Stable tag: 0.9.2 - GitHub Plugin URI: https://github.com/Automattic/chatrix Matrix client for WordPress. ## Description Easily add a [Matrix](https://matrix.org) client to WordPress pages, either through the Block Editor, or as a _popup_. ### Feedback welcome If you have any feedback or questions about Chatrix, please do talk to plugin maintainers at [#chatrix:matrix.org](https://matrix.to/#/#chatrix:matrix.org). ## Screenshots ![Block - Login](.wporg/screenshot-1.png) ![Block - Room List](.wporg/screenshot-2.png) ![Block - Timeline](.wporg/screenshot-3.png) ![Popup - Settings](.wporg/screenshot-4.png) ![Popup - Timeline](.wporg/screenshot-5.png) ## Frequently Asked Questions ### How can I install this plugin on my site? This plugin can be used in two distinct ways: 1. By adding a block to a page through the block editor 2. By selecting pages in which a _popup_ will be displayed. You configure this through `Settings -> Chatrix`. ### Is there a more flexible way to configure the popup? Yes. Instead of configuring the _popup_ through `Settings -> Chatrix`, you can configure it through code, by using the `chatrix_instances` filter: ~~~php // functions.php add_filter( 'chatrix_instances', function ( array $default_instances ) { // The key is an instance_id, the value array is the config for that instance. // Set 'pages' to an array of the ids of the pages which should show chatrix. // You can also set 'pages' to 'all' which results in that instance always being used. // Only one instance can be shown on a given page. return array( 'foo' => array( 'homeserver' => 'https://foo.com', 'room_id' => '!id:foo.com', 'pages' => 'all', ), 'bar' => array( 'homeserver' => 'https://bar.com', 'room_id' => '!id:bar.com', 'pages' => array(1, 2, 3), ), ); } ); ~~~ ### How can I configure WordPress user accounts to register and login on Matrix homeserver? The plugin will respect the login methods configured on the Matrix homeserver. For example, if the homeserver has both password and SSO login enabled, both options will be available to the user. In light of the [plan for Matrix to replace their user management with Open ID Connect (OIDC)](https://areweoidcyet.com/), we recommend to use a Single-Sign On (SSO) flow by configuring [Open ID Connect login on Synapse](https://matrix-org.github.io/synapse/latest/openid.html) and use the [OpenID Connect Server WordPress plugin](https://wordpress.org/plugins/openid-connect-server/). The flow will then be as follows: When logging into your homeserver, it will redirect you to your own WordPress login page and ask you to authorize the login by the click of a button, and then relay your information to the homeserver. You'll be redirected back to your WordPress page and Chatrix will receive the login information and you can start chatting. Later, when Matrix makes the switch to OIDC, you are already prepared and can continue to use this setup. ## Changelog ### 0.9.2 - Fix Chatrix iframe not loading in Gutenberg editor [#256](https://github.com/Automattic/chatrix/pull/256) ### 0.9.1 - We now don't enqueue scripts in embeds [#249](https://github.com/Automattic/chatrix/pull/249) - It is now possible to disable service worker at runtime [#243](https://github.com/Automattic/chatrix/pull/243) ### 0.9.0 - Chatrix is now a single-session client. The session picker is no longer displayed [[#239](https://github.com/Automattic/chatrix/pull/239)]. This fixes [#236](https://github.com/Automattic/chatrix/issues/236) [#224](https://github.com/Automattic/chatrix/issues/224) [#200](https://github.com/Automattic/chatrix/issues/200). ### 0.8.3 - Improve the view for rooms that are you not a member of (Upgraded our Hydrogen's fork to [latest](https://github.com/Automattic/hydrogen-web/compare/chatrix-0.8.0...Automattic:hydrogen-web:chatrix-0.8.3)) ### 0.8.2 - Fix issues with single-room mode and guest login [[#222](https://github.com/Automattic/chatrix/pull/222)] ### 0.8.1 - Correctly remember last url when multiple blocks are on the same page [[#217](https://github.com/Automattic/chatrix/pull/217)] ### 0.8.0 - Fix issue when chatrix plugin is not installed in the default location [[#205](https://github.com/Automattic/chatrix/pull/205)] - Fix issue with z-index of the popup [[#207](https://github.com/Automattic/chatrix/pull/207)] - Fix issue that prevented navigating away from the *unknown room* screen [[#213](https://github.com/Automattic/chatrix/pull/213)] - Allow multiple blocks on the same page or on different browser tabs (behind feature flag, still unstable) [[#214](https://github.com/Automattic/chatrix/pull/214)] ### 0.7.1 - Fix button text from 'Login' to 'Log In' - Meta changes for WP.org plugins repo ### 0.7.0 - Implement Room Previews (Peeking) functionality [[#199](https://github.com/Automattic/chatrix/pull/199)] - Disable restoration to last screen when in Single room mode [[#196](https://github.com/Automattic/chatrix/pull/196)] - Switch to our Hydrogen's fork (ahead of v0.3.8) as dependency which includes un-merged upstream contributions - Fix query params in SSO - Allow create room screen to be closed on smaller width screens - Ensure Service worker is started before anything else - Fix bug in normalization of homeserver - Room Previews (Peeking) support - Fix loading of messages & timelines in some cases ### 0.6.0 - Support for multiple blocks on the same page [[#175](https://github.com/Automattic/chatrix/pull/175)] - Support room alias in configuration [[#179](https://github.com/Automattic/chatrix/pull/179)] - Fixed a bug where port wasn't allowed in homeserver in configuration [[#184](https://github.com/Automattic/chatrix/pull/184)] - Provide a filter to choose to not load the logout script if required [[#165](https://github.com/Automattic/chatrix/pull/165)] ### 0.5.1 - Fix issue that caused popup configuration to be ignored [[#173](https://github.com/Automattic/chatrix/pull/173)] ### 0.5.0 - Logout and delete data when user logs out of WordPress [[#150](https://github.com/Automattic/chatrix/pull/150), [#153](https://github.com/Automattic/chatrix/pull/153)] - Improvements to single room mode [[#151](https://github.com/Automattic/chatrix/pull/151)] - Add a Settings entry to the options menu of the room - Closing the Settings screen navigates to configured `roomId` - Closing the Room (timeline) screen navigates to session picker - Hide the left panel completely - Fix issue that caused Chatrix to not load in certain conditions [[#160](https://github.com/Automattic/chatrix/pull/160)] - Allow setting a unit for certain styling options (previously was always `px`) [[#154](https://github.com/Automattic/chatrix/pull/154)] ### 0.4.0 - Prevent data corruption when more than one Chatrix instance (block or Popup) is active, either in multiple browser tabs or windows, or in the same page [[#75](https://github.com/Automattic/chatrix/pull/75)] - Allow setting the height of the block from the block editor [[#135](https://github.com/Automattic/chatrix/pull/135)] - Allow styling the block's border from the block editor [[#139](https://github.com/Automattic/chatrix/pull/139)] - Styling and layout improvements and fixes in pre-session screens (session selection, login, logout) [[#134](https://github.com/Automattic/chatrix/pull/134)] - Reduce plugin size by 50%, from 12MB to 6MB [[#143](https://github.com/Automattic/chatrix/pull/143)] - Update to Hydrogen [0.3.5](https://github.com/vector-im/hydrogen-web/releases/tag/v0.3.5) - Fix issue that prevented opening rooms with slashes in the room ID [[#451](https://github.com/vector-im/hydrogen-web/issues/451)] - Improve date headers in room timeline [[#938](https://github.com/vector-im/hydrogen-web/pull/938)] - Provide basic UI to join room [[#870](https://github.com/vector-im/hydrogen-web/pull/870)] - Fix an error that can stop sync [[#885](https://github.com/vector-im/hydrogen-web/pull/885)] - Fetch missing e2ee devices when verifying message sender [[#913](https://github.com/vector-im/hydrogen-web/pull/913)] - Fix message verification not working in rooms where we haven't sent a message yet [[#920](https://github.com/vector-im/hydrogen-web/pull/920)] - Various maintenance fixes ### 0.3.9 - Initial public release

WordPress Themes & Plugins Team Chat
45 Github Stars
table-of-contents
Open Source

table-of-contents

[![Run PHPUnit and PHPCS](https://github.com/Automattic/table-of-contents/actions/workflows/integrate.yml/badge.svg)](https://github.com/Automattic/table-of-contents/actions/workflows/integrate.yml) # Table of Contents Adds a table of contents to your pages based on h3 and h4 tags. Useful for documention-centric sites. ## Installation 1. Upload "/table-of-contents/" to the "/wp-content/plugins/" directory. 1. Activate the plugin through the "Plugins" menu in WordPress. ## Changelog ### 0.5.1 * Testing for 5.0 * Testing for Gutenberg ### 0.5.0 * Initial release.

Web Development WordPress Themes & Plugins
45 Github Stars