Changeset 3423300
- Timestamp:
- 12/19/2025 02:42:32 AM (7 days ago)
- Location:
- post-formats-for-block-themes
- Files:
-
- 2 added
- 4 deleted
- 34 edited
- 1 copied
-
tags/1.1.3 (copied) (copied from post-formats-for-block-themes/trunk)
-
tags/1.1.3/CHANGELOG.md (deleted)
-
tags/1.1.3/blocks/post-format-block/index.js (modified) (2 diffs)
-
tags/1.1.3/blocks/post-format-block/index.min.asset.php (added)
-
tags/1.1.3/blocks/post-format-block/index.min.js (modified) (1 diff)
-
tags/1.1.3/build/index.asset.php (modified) (1 diff)
-
tags/1.1.3/build/index.js (modified) (1 diff)
-
tags/1.1.3/img (deleted)
-
tags/1.1.3/includes/class-admin-columns.php (modified) (1 diff)
-
tags/1.1.3/includes/class-pattern-manager.php (modified) (5 diffs)
-
tags/1.1.3/patterns/aside.php (modified) (1 diff)
-
tags/1.1.3/patterns/audio.php (modified) (2 diffs)
-
tags/1.1.3/patterns/chat.php (modified) (2 diffs)
-
tags/1.1.3/patterns/gallery.php (modified) (2 diffs)
-
tags/1.1.3/patterns/image.php (modified) (2 diffs)
-
tags/1.1.3/patterns/link.php (modified) (2 diffs)
-
tags/1.1.3/patterns/quote.php (modified) (2 diffs)
-
tags/1.1.3/patterns/status.php (modified) (1 diff)
-
tags/1.1.3/patterns/video.php (modified) (2 diffs)
-
tags/1.1.3/post-formats-for-block-themes.php (modified) (3 diffs)
-
tags/1.1.3/readme.txt (modified) (3 diffs)
-
trunk/CHANGELOG.md (deleted)
-
trunk/blocks/post-format-block/index.js (modified) (2 diffs)
-
trunk/blocks/post-format-block/index.min.asset.php (added)
-
trunk/blocks/post-format-block/index.min.js (modified) (1 diff)
-
trunk/build/index.asset.php (modified) (1 diff)
-
trunk/build/index.js (modified) (1 diff)
-
trunk/img (deleted)
-
trunk/includes/class-admin-columns.php (modified) (1 diff)
-
trunk/includes/class-pattern-manager.php (modified) (5 diffs)
-
trunk/patterns/aside.php (modified) (1 diff)
-
trunk/patterns/audio.php (modified) (2 diffs)
-
trunk/patterns/chat.php (modified) (2 diffs)
-
trunk/patterns/gallery.php (modified) (2 diffs)
-
trunk/patterns/image.php (modified) (2 diffs)
-
trunk/patterns/link.php (modified) (2 diffs)
-
trunk/patterns/quote.php (modified) (2 diffs)
-
trunk/patterns/status.php (modified) (1 diff)
-
trunk/patterns/video.php (modified) (2 diffs)
-
trunk/post-formats-for-block-themes.php (modified) (3 diffs)
-
trunk/readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
post-formats-for-block-themes/tags/1.1.3/blocks/post-format-block/index.js
r3413728 r3423300 18 18 import { __ } from '@wordpress/i18n'; 19 19 20 // Icon 20 // DOM Ready 21 import domReady from '@wordpress/dom-ready'; 22 23 // Icon - use optional chaining to prevent errors if icons not loaded yet 21 24 import { postCategories as icon } from '@wordpress/icons'; 22 25 … … 29 32 * @see https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/post-terms/variations.js 30 33 */ 31 const variation = { 32 name: 'post_format', 33 title: __( 'Post Format', 'post-formats-for-block-themes' ), 34 description: __( "Display a post's format", 'post-formats-for-block-themes' ), 35 icon, 36 isDefault: false, 37 attributes: { term: 'post_format' }, 38 isActive: ( blockAttributes ) => blockAttributes.term === 'post_format', 39 scope: [ 'inserter', 'transform' ], 40 }; 34 domReady( () => { 35 // Fallback icon if postCategories isn't available 36 const variationIcon = icon || 'tag'; 41 37 42 registerBlockVariation( 'core/post-terms', variation ); 38 const variation = { 39 name: 'post_format', 40 title: __( 'Post Format', 'post-formats-for-block-themes' ), 41 description: __( "Display a post's format", 'post-formats-for-block-themes' ), 42 icon: variationIcon, 43 isDefault: false, 44 attributes: { term: 'post_format' }, 45 isActive: ( blockAttributes ) => blockAttributes.term === 'post_format', 46 scope: [ 'inserter', 'transform' ], 47 }; 48 49 registerBlockVariation( 'core/post-terms', variation ); 50 } ); -
post-formats-for-block-themes/tags/1.1.3/blocks/post-format-block/index.min.js
r3413728 r3423300 3 3 * @package PostFormatsBlockThemes 4 4 */ 5 (function(){var e=window.wp.blocks,t=window.wp.i18n,n=window.wp.icons ;const r={name:"post_format",title:(0,t.__)("Post Format","post-formats-for-block-themes"),description:(0,t.__)("Display a post's format","post-formats-for-block-themes"),icon:n.postCategories,isDefault:false,attributes:{term:"post_format"},isActive:function(e){return e.term==="post_format"},scope:["inserter","transform"]};(0,e.registerBlockVariation)("core/post-terms",r)})();5 (function(){var e=window.wp.blocks,t=window.wp.i18n,n=window.wp.icons,d=window.wp.domReady;d(function(){var i=(n&&n.postCategories)?n.postCategories:"tag";var r={name:"post_format",title:(0,t.__)("Post Format","post-formats-for-block-themes"),description:(0,t.__)("Display a post's format","post-formats-for-block-themes"),icon:i,isDefault:false,attributes:{term:"post_format"},isActive:function(e){return e.term==="post_format"},scope:["inserter","transform"]};(0,e.registerBlockVariation)("core/post-terms",r)})})(); -
post-formats-for-block-themes/tags/1.1.3/build/index.asset.php
r3416925 r3423300 1 <?php return array('dependencies' => array('react', 'wp-a11y', 'wp-blocks', 'wp-components', 'wp- data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => 'aee0db3c8e30a508c90e');1 <?php return array('dependencies' => array('react', 'wp-a11y', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => '5add7157ad1a69c9a4cc'); -
post-formats-for-block-themes/tags/1.1.3/build/index.js
r3416925 r3423300 1 (()=>{"use strict";const t=window.React,e=window.wp.plugins,a=window.wp.components,n=window.wp.data,r=window.wp.element,o=window.wp.i18n,s=window.wp.a11y,i=window.wp.hooks,p=window.wp.blocks,l=()=>{const[e,i]=(0,r.useState)(!1),[l,m]=(0,r.useState)(!1),{isNewPost:c,currentFormat:d,postType:u}=(0,n.useSelect)(t=>{const e=t("core/editor"),a=e.getCurrentPost();return{isNewPost:!a.id||"auto-draft"===a.status,currentFormat:e.getEditedPostAttribute("format")||"standard",postType:a.type}},[]),{editPost:f}=(0,n.useDispatch)("core/editor"),{insertBlocks:b}=(0,n.useDispatch)("core/block-editor");(0,r.useEffect)(()=>{c&&"post"===u&&!l&&window.pfbtData&&setTimeout(()=>{i(!0),m(!0)},500)},[c,u,l]);if(!e||!window.pfbtData)return null;const h=window.pfbtData.formats,g=Object.entries(h).map(([t,e])=>"standard"===t?[t,{...e,name:(0,o.__)("Standard (Single Template)","post-formats-for-block-themes"),description:(0,o.__)("Default post format using the Single template","post-formats-for-block-themes")}]:[t,e]).sort((t,e)=>"standard"===t[0]?-1:"standard"===e[0]?1:t[1].name.localeCompare(e[1].name));return(0,t.createElement)(a.Modal,{title:(0,o.__)("Choose Post Format","post-formats-for-block-themes"),onRequestClose:()=>i(!1),className:"pfpu-format-modal"},(0,t.createElement)("div",{className:"pfpu-format-grid"},g.map(([e,n])=>(0,t.createElement)(a.Card,{key:e,className:"pfpu-format-card"},(0,t.createElement)(a.CardBody,null,(0,t.createElement)(a.Button,{onClick:()=>(t=>{if(f({format:t,template:"standard"===t?"":`single-format-${t}`}),"standard"!==t&&window.pfbtData.formats[t]){const e=window.pfbtData.formats[t];((t,e)=>{if(!window.pfbtData.patterns||!window.pfbtData.patterns[t])return;const a=window.pfbtData.patterns[t],n=(0,p.parse)(a);n.length>0&&e(n,0,void 0,!1)})(t,b),(0,s.speak)(sprintf(/* translators: %s: Format name */ /* translators: %s: Format name */ 2 (0,o.__)("Selected %s format. Pattern inserted.","post-formats-for-block-themes"),e.name),"polite")}i(!1)})(e),className:"pfpu-format-button",variant:"standard"===e?"primary":"secondary"},(0,t.createElement)("span",{className:`dashicons dashicons-${n.icon}`,"aria-hidden":"true"}),(0,t.createElement)("span",{className:"pfpu-format-name"},n.name)),(0,t.createElement)("p",{className:"pfpu-format-description"},n.description))))))},m=()=>{const{createNotice:t,removeNotice:e}=(0,n.useDispatch)("core/notices"),{currentFormat:a,blocks:s}=(0,n.useSelect)(t=>{const e=t("core/editor"),a=t("core/block-editor");return{currentFormat:e.getEditedPostAttribute("format")||"standard",blocks:a.getBlocks()}},[]);return(0,r.useEffect)(()=>{if("status"!==a)return void e("pfbt-status-char-count");const n=s.find(t=>"core/paragraph"===t.name&&t.attributes.className?.includes("status-paragraph"));if(!n)return void e("pfbt-status-char-count");const r=(n.attributes.content||"").replace(/<[^>]*>/g,"").length;r>280?t("error",sprintf(/* translators: %d: Current character count */ /* translators: %d: Current character count */ 3 (0,o.__)("%d / 280 characters - Status updates should be 280 characters or less","post-formats-for-block-themes"),r),{id:"pfbt-status-char-count",isDismissible:!1}):r>=260?t("warning",sprintf(/* translators: %d: Current character count */ /* translators: %d: Current character count */ 4 (0,o.__)("%d / 280 characters - Approaching limit","post-formats-for-block-themes"),r),{id:"pfbt-status-char-count",isDismissible:!1}):e("pfbt-status-char-count")},[a,s,t,e]),null};if((0,e.registerPlugin)("post-formats-for-block-themes",{render:()=>(0,t.createElement)(t.Fragment,null,(0,t.createElement)(l,null),(0,t.createElement)(m,null))}),(0,i.addFilter)("editor.BlockEdit","pfpu/status-paragraph-counter",e=>a=>{const{name:n,attributes:r,setAttributes:s}=a;if("core/paragraph"!==n||!r.className?.includes("status-paragraph"))return(0,t.createElement)(e,{...a});const i=280-(r.content||"").replace(/<[^>]*>/g,"").length,p=i<0;return(0,t.createElement)("div",{className:"pfpu-status-paragraph-wrapper"},(0,t.createElement)(e,{...a}),(0,t.createElement)("div",{className:`pfpu-char-counter ${p?"is-over-limit":""} ${i<=20?"is-warning":""}`,"aria-live":"polite","aria-atomic":"true"},(0,t.createElement)("span",null,sprintf(/* translators: %d: Remaining characters */ /* translators: %d: Remaining characters */ 5 (0,o.__)("%d characters remaining","post-formats-for-block-themes"),i))))}),"undefined"!=typeof document){const t=document.createElement("style");t.textContent='\n\t.pfpu-format-modal {\n\t\tmax-width: 800px;\n\t}\n\n\t.pfpu-format-grid {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n\t\tgap: 1rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-format-card {\n\t\ttext-align: center;\n\t}\n\n\t.pfpu-format-button {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\tpadding: 1rem;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tgap: 0.5rem;\n\t}\n\n\t.pfpu-format-button .dashicons {\n\t\tfont-size: 2rem;\n\t\twidth: 2rem;\n\t\theight: 2rem;\n\t}\n\n\t.pfpu-format-name {\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-format-description {\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t\tmargin-top: 0.5rem;\n\t}\n\n\t.pfpu-format-change-actions {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.5rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-validator {\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-paragraph-wrapper {\n\t\tposition: relative;\n\t}\n\n\t.pfpu-char-counter {\n\t\tposition: absolute;\n\t\tbottom: -30px;\n\t\tright: 0;\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t}\n\n\t.pfpu-char-counter.is-warning {\n\t\tcolor: #f0b849;\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-char-counter.is-over-limit {\n\t\tcolor: #d63638;\n\t\tfont-weight: 600;\n\t}\n\n\t/* Template Modal - Visual Separation for Format Templates */\n\n\t/* Target template items in the template selection modal */\n\t/* Format templates have "Format" in their title (e.g., "Gallery Format", "Aside Format") */\n\n\t/* Template card styling - targets the button/card elements */\n\t.edit-post-template__panel .components-panel__body button[aria-label*="Format"],\n\t.edit-site-template-card button[aria-label*="Format"],\n\t.block-editor-block-card button[aria-label*="Format"] {\n\t\tborder-left: 4px solid var(--wp-admin-theme-color, #2271b1) !important;\n\t\tpadding-left: 12px !important;\n\t\tbackground: rgba(34, 113, 177, 0.05) !important;\n\t\tposition: relative;\n\t}\n\n\t/* Add emoji badge to format templates */\n\t.edit-post-template__panel .components-panel__body button[aria-label*="Format"]::before,\n\t.edit-site-template-card button[aria-label*="Format"]::before,\n\t.block-editor-block-card button[aria-label*="Format"]::before {\n\t\tcontent: "🎨 ";\n\t\tmargin-right: 4px;\n\t\tfont-size: 14px;\n\t}\n\n\t/* Template dropdown/modal items */\n\t.edit-post-template-dropdown__content button[aria-label*="Format"],\n\t.components-dropdown-menu__menu button[aria-label*="Format"] {\n\t\tborder-left: 4px solid var(--wp-admin-theme-color, #2271b1);\n\t\tpadding-left: 12px;\n\t\tbackground: rgba(34, 113, 177, 0.05);\n\t}\n\n\t/* Add visual indicator to currently selected format template */\n\t.edit-post-template__panel .components-panel__body .is-selected[aria-label*="Format"],\n\tbutton[aria-checked="true"][aria-label*="Format"] {\n\t\tbackground: rgba(34, 113, 177, 0.1) !important;\n\t\tfont-weight: 600;\n\t}\n\n\t/* Template name in sidebar - show when auto-applied */\n\t.edit-post-template__panel .components-panel__body .components-base-control__help {\n\t\tfont-style: italic;\n\t\tcolor: #757575;\n\t}\n',document.head.appendChild(t)}})(); 1 (()=>{"use strict";const t=window.React,e=window.wp.plugins,n=window.wp.components,r=window.wp.data,a=window.wp.element,o=window.wp.i18n,s=window.wp.a11y,i=window.wp.hooks,p=window.wp.blocks,c=window.wp.compose,m={},l=(t,e,n=null,r=!1)=>{if(m[t])return!1;if(!window.pfbtData?.patterns?.[t])return!1;const a=window.pfbtData.patterns[t],o=(0,p.parse)(a);return o.length>0&&(r&&n?n(o):e(o,0,void 0,!1),m[t]=!0,!0)},d=()=>{const t=(0,a.useRef)(null),{currentFormat:e,postType:n,blocks:i}=(0,r.useSelect)(t=>{const e=t("core/editor"),n=t("core/block-editor");return{currentFormat:e.getEditedPostAttribute("format")||"standard",postType:e.getCurrentPostType(),blocks:n.getBlocks()}},[]),{insertBlocks:p,resetBlocks:c}=(0,r.useDispatch)("core/block-editor");return(0,a.useEffect)(()=>{if("post"!==n)return;if(t.current===e)return;const r=null===t.current;if(t.current=e,r)return;if("standard"===e)return;const a=0===i.length||1===i.length&&"core/paragraph"===i[0].name&&!i[0].attributes.content;if(window.pfbtData?.patterns?.[e]&&l(e,p,c,a)){const t=window.pfbtData.formats?.[e]?.name||e;(0,s.speak)(sprintf((0,o.__)("Switched to %s format. Pattern inserted.","post-formats-for-block-themes"),t),"polite")}},[e,n,i,p,c]),null},u=()=>{const[e,i]=(0,a.useState)(!1),[p,c]=(0,a.useState)(!1),{isNewPost:m,currentFormat:d,postType:u}=(0,r.useSelect)(t=>{const e=t("core/editor"),n=e.getCurrentPost();return{isNewPost:!n.id||"auto-draft"===n.status,currentFormat:e.getEditedPostAttribute("format")||"standard",postType:n.type}},[]),{editPost:f}=(0,r.useDispatch)("core/editor"),{insertBlocks:w,resetBlocks:g}=(0,r.useDispatch)("core/block-editor");if((0,a.useEffect)(()=>{m&&"post"===u&&!p&&window.pfbtData&&setTimeout(()=>{i(!0),c(!0)},500)},[m,u,p]),!e||!window.pfbtData)return null;const h=window.pfbtData.formats,b=Object.entries(h).map(([t,e])=>"standard"===t?[t,{...e,name:(0,o.__)("Standard (Single Template)","post-formats-for-block-themes"),description:(0,o.__)("Default post format using the Single template","post-formats-for-block-themes")}]:[t,e]).sort((t,e)=>"standard"===t[0]?-1:"standard"===e[0]?1:t[1].name.localeCompare(e[1].name));return(0,t.createElement)(n.Modal,{title:(0,o.__)("Choose Post Format","post-formats-for-block-themes"),onRequestClose:()=>i(!1),className:"pfpu-format-modal"},(0,t.createElement)("div",{className:"pfpu-format-grid"},b.map(([e,r])=>(0,t.createElement)(n.Card,{key:e,className:"pfpu-format-card"},(0,t.createElement)(n.CardBody,null,(0,t.createElement)(n.Button,{onClick:()=>(t=>{if(f({format:t}),"standard"!==t&&window.pfbtData?.formats?.[t]){const e=window.pfbtData.formats[t];l(t,w,g,!0),(0,s.speak)(sprintf(/* translators: %s: Format name */ /* translators: %s: Format name */ 2 (0,o.__)("Selected %s format. Pattern inserted.","post-formats-for-block-themes"),e.name),"polite")}i(!1)})(e),className:"pfpu-format-button",variant:"standard"===e?"primary":"secondary"},(0,t.createElement)("span",{className:`dashicons dashicons-${r.icon}`,"aria-hidden":"true"}),(0,t.createElement)("span",{className:"pfpu-format-name"},r.name)),(0,t.createElement)("p",{className:"pfpu-format-description"},r.description))))))};(0,e.registerPlugin)("post-formats-for-block-themes",{render:()=>(0,t.createElement)(t.Fragment,null,(0,t.createElement)(u,null),(0,t.createElement)(d,null))});const f=(0,c.createHigherOrderComponent)(e=>n=>{const{name:a,attributes:s}=n,i=((0,r.useSelect)(t=>{const e=t("core/editor");return e?e.getEditedPostAttribute("format"):null},[]),s.className?.includes("status-paragraph"));if("core/paragraph"!==a||!i)return(0,t.createElement)(e,{...n});const p=280-(s.content||"").replace(/<[^>]*>/g,"").length,c=p<0;return(0,t.createElement)("div",{className:"pfpu-status-paragraph-wrapper"},(0,t.createElement)(e,{...n}),(0,t.createElement)("div",{className:`pfpu-char-counter ${c?"is-over-limit":""} ${p<=20?"is-warning":""}`,"aria-live":"polite","aria-atomic":"true"},(0,t.createElement)("span",null,sprintf(/* translators: %d: Remaining characters */ /* translators: %d: Remaining characters */ 3 (0,o.__)("%d characters remaining","post-formats-for-block-themes"),p))))},"withStatusCharacterCounter");if((0,i.addFilter)("editor.BlockEdit","pfpu/status-paragraph-counter",f),"undefined"!=typeof document){const t=document.createElement("style");t.textContent="\n\t.pfpu-format-modal {\n\t\tmax-width: 800px;\n\t}\n\n\t.pfpu-format-grid {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n\t\tgap: 1rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-format-card {\n\t\ttext-align: center;\n\t}\n\n\t.pfpu-format-button {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\tpadding: 1rem;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tgap: 0.5rem;\n\t}\n\n\t.pfpu-format-button .dashicons {\n\t\tfont-size: 2rem;\n\t\twidth: 2rem;\n\t\theight: 2rem;\n\t}\n\n\t.pfpu-format-name {\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-format-description {\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t\tmargin-top: 0.5rem;\n\t}\n\n\t.pfpu-format-change-actions {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.5rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-validator {\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-paragraph-wrapper {\n\t\tposition: relative;\n\t\tmargin-bottom: 30px;\n\t}\n\n\t.pfpu-char-counter {\n\t\tposition: absolute;\n\t\tbottom: -25px;\n\t\tright: 0;\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t\tbackground: #fff;\n\t\tpadding: 2px 8px;\n\t\tborder-radius: 3px;\n\t\tbox-shadow: 0 1px 3px rgba(0,0,0,0.1);\n\t}\n\n\t.pfpu-char-counter.is-warning {\n\t\tcolor: #f0b849;\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-char-counter.is-over-limit {\n\t\tcolor: #d63638;\n\t\tfont-weight: 600;\n\t\tbackground: #fcf0f1;\n\t}\n",document.head.appendChild(t)}})(); -
post-formats-for-block-themes/tags/1.1.3/includes/class-admin-columns.php
r3413728 r3423300 170 170 $icons = array( 171 171 'standard' => 'dashicons-admin-post', 172 'aside' => 'dashicons- aside',172 'aside' => 'dashicons-format-aside', 173 173 'gallery' => 'dashicons-format-gallery', 174 174 'link' => 'dashicons-admin-links', -
post-formats-for-block-themes/tags/1.1.3/includes/class-pattern-manager.php
r3413728 r3423300 89 89 * Only synced blocks are created to avoid duplicates. 90 90 * 91 * PERFORMANCE FIX: Only runs on plugin activation or when patterns 92 * are missing. Uses a transient to avoid checking on every page load. 93 * 91 94 * @since 1.0.0 92 95 */ 93 96 public static function register_all_patterns() { 97 // PERFORMANCE: Skip on front-end entirely. 98 if ( ! is_admin() && ! wp_doing_ajax() && ! ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { 99 return; 100 } 101 102 // PERFORMANCE: Use transient to avoid running on every admin page load. 103 // Patterns only need to be created once, then they persist in the database. 104 $patterns_version = PFBT_VERSION; 105 $cached_version = get_transient( 'pfbt_patterns_registered' ); 106 107 // Skip if patterns were already registered for this plugin version. 108 if ( $cached_version === $patterns_version ) { 109 return; 110 } 111 94 112 $instance = self::instance(); 95 113 $formats = PFBT_Format_Registry::get_all_formats(); … … 99 117 $instance->create_synced_pattern( $slug, $format ); 100 118 } 119 120 // Mark patterns as registered for 1 week (they persist in database anyway). 121 set_transient( 'pfbt_patterns_registered', $patterns_version, WEEK_IN_SECONDS ); 122 } 123 124 /** 125 * Force re-registration of patterns 126 * 127 * Called on plugin activation to ensure patterns are up to date. 128 * 129 * @since 1.1.3 130 */ 131 public static function force_register_patterns() { 132 delete_transient( 'pfbt_patterns_registered' ); 133 self::register_all_patterns(); 101 134 } 102 135 … … 157 190 * all instances update automatically. 158 191 * 192 * PERFORMANCE FIX: Only updates existing blocks when content has 193 * actually changed to avoid creating unnecessary revisions. 194 * 159 195 * @since 1.0.0 160 196 * … … 188 224 ); 189 225 190 $block_data = array(191 'post_title' => $block_title,192 'post_content' => $pattern_content,193 'post_status' => 'publish',194 'post_type' => 'wp_block',195 'post_name' => $block_slug,196 );197 198 226 if ( $existing_block ) { 199 // Update existing reusable block. 200 $block_data['ID'] = $existing_block->ID; 201 $block_id = wp_update_post( $block_data ); 227 // PERFORMANCE: Only update if content has actually changed. 228 // This prevents creating revisions on every admin page load. 229 $content_changed = ( trim( $existing_block->post_content ) !== trim( $pattern_content ) ); 230 $title_changed = ( $existing_block->post_title !== $block_title ); 231 232 if ( ! $content_changed && ! $title_changed ) { 233 // Content unchanged - skip update to avoid revision creation. 234 $block_id = $existing_block->ID; 235 } else { 236 // Content changed - update the block. 237 $block_data = array( 238 'ID' => $existing_block->ID, 239 'post_title' => $block_title, 240 'post_content' => $pattern_content, 241 'post_status' => 'publish', 242 'post_type' => 'wp_block', 243 'post_name' => $block_slug, 244 ); 245 $block_id = wp_update_post( $block_data ); 246 } 202 247 } else { 203 248 // Create new reusable block. 204 $block_id = wp_insert_post( $block_data ); 249 $block_data = array( 250 'post_title' => $block_title, 251 'post_content' => $pattern_content, 252 'post_status' => 'publish', 253 'post_type' => 'wp_block', 254 'post_name' => $block_slug, 255 ); 256 $block_id = wp_insert_post( $block_data ); 205 257 206 258 // Add metadata to identify this as a post format pattern. … … 210 262 } 211 263 212 // Assign to Post formats category .264 // Assign to Post formats category (only for new blocks or if category missing). 213 265 if ( $block_id && ! is_wp_error( $block_id ) ) { 214 // Get or create the category term. 215 $category_term = get_term_by( 'slug', 'post-formats', 'wp_pattern_category' ); 216 217 if ( ! $category_term ) { 218 $category_term = wp_insert_term( 219 __( 'Post formats', 'post-formats-for-block-themes' ), 220 'wp_pattern_category', 221 array( 'slug' => 'post-formats' ) 222 ); 223 } 224 225 // Assign the category to the block. 226 if ( $category_term && ! is_wp_error( $category_term ) ) { 227 $term_id = is_array( $category_term ) ? $category_term['term_id'] : $category_term->term_id; 228 wp_set_object_terms( $block_id, $term_id, 'wp_pattern_category' ); 266 // PERFORMANCE: Check if block already has the correct category. 267 $existing_terms = wp_get_object_terms( $block_id, 'wp_pattern_category', array( 'fields' => 'slugs' ) ); 268 $has_category = ! is_wp_error( $existing_terms ) && in_array( 'post-formats', $existing_terms, true ); 269 270 if ( ! $has_category ) { 271 // Get or create the category term. 272 $category_term = get_term_by( 'slug', 'post-formats', 'wp_pattern_category' ); 273 274 if ( ! $category_term ) { 275 $category_term = wp_insert_term( 276 __( 'Post formats', 'post-formats-for-block-themes' ), 277 'wp_pattern_category', 278 array( 'slug' => 'post-formats' ) 279 ); 280 } 281 282 // Assign the category to the block. 283 if ( $category_term && ! is_wp_error( $category_term ) ) { 284 $term_id = is_array( $category_term ) ? $category_term['term_id'] : $category_term->term_id; 285 wp_set_object_terms( $block_id, $term_id, 'wp_pattern_category' ); 286 } 229 287 } 230 288 } -
post-formats-for-block-themes/tags/1.1.3/patterns/aside.php
r3413728 r3423300 14 14 */ 15 15 ?> 16 <!-- wp:group {"layout":{"type":"constrained"}} --> 17 <div class="wp-block-group"> 18 <!-- wp:paragraph --> 19 <p></p> 20 <!-- /wp:paragraph --> 21 </div> 22 <!-- /wp:group --> 16 <!-- wp:paragraph --> 17 <p></p> 18 <!-- /wp:paragraph --> -
post-formats-for-block-themes/tags/1.1.3/patterns/audio.php
r3413728 r3423300 7 7 * Audio Post Format Pattern 8 8 * 9 * Audio file or embed. Starts with a core audio block .9 * Audio file or embed. Starts with a core audio block followed by a paragraph. 10 10 * Can be swapped with Podlove Podcast Publisher or Able Player blocks. 11 11 * … … 14 14 */ 15 15 ?> 16 <!-- wp:group {"layout":{"type":"constrained"}} --> 17 <div class="wp-block-group"> 18 <!-- wp:audio --> 19 <figure class="wp-block-audio"><audio controls></audio></figure> 20 <!-- /wp:audio --> 21 </div> 22 <!-- /wp:group --> 16 <!-- wp:audio --> 17 <figure class="wp-block-audio"><audio controls></audio></figure> 18 <!-- /wp:audio --> 23 19 20 <!-- wp:paragraph --> 21 <p></p> 22 <!-- /wp:paragraph --> -
post-formats-for-block-themes/tags/1.1.3/patterns/chat.php
r3413728 r3423300 7 7 * Chat Post Format Pattern 8 8 * 9 * Chat transcript or conversation log. Uses the Chat Log block .9 * Chat transcript or conversation log. Uses the Chat Log block followed by a paragraph. 10 10 * 11 11 * Note: Requires the Chat Log plugin to be active. … … 16 16 */ 17 17 ?> 18 <!-- wp:group {"layout":{"type":"constrained"}} --> 19 <div class="wp-block-group"> 20 <!-- wp:chatlog/conversation /--> 21 </div> 22 <!-- /wp:group --> 18 <!-- wp:chatlog/conversation /--> 23 19 20 <!-- wp:paragraph --> 21 <p></p> 22 <!-- /wp:paragraph --> -
post-formats-for-block-themes/tags/1.1.3/patterns/gallery.php
r3413728 r3423300 7 7 * Gallery Post Format Pattern 8 8 * 9 * Image gallery post. Starts with a gallery block .9 * Image gallery post. Starts with a gallery block followed by a paragraph. 10 10 * 11 11 * @package PostFormatsBlockThemes … … 13 13 */ 14 14 ?> 15 <!-- wp:group {"layout":{"type":"constrained"}} --> 16 <div class="wp-block-group"> 17 <!-- wp:gallery {"linkTo":"none"} --> 18 <figure class="wp-block-gallery has-nested-images columns-default is-cropped"> 19 <!-- wp:image --> 20 <figure class="wp-block-image"><img alt=""/></figure> 21 <!-- /wp:image --> 22 </figure> 23 <!-- /wp:gallery --> 24 </div> 25 <!-- /wp:group --> 15 <!-- wp:gallery {"linkTo":"none"} --> 16 <figure class="wp-block-gallery has-nested-images columns-default is-cropped"></figure> 17 <!-- /wp:gallery --> 26 18 19 <!-- wp:paragraph --> 20 <p></p> 21 <!-- /wp:paragraph --> -
post-formats-for-block-themes/tags/1.1.3/patterns/image.php
r3413728 r3423300 7 7 * Image Post Format Pattern 8 8 * 9 * Single image post. Starts with an image block .9 * Single image post. Starts with an image block followed by a paragraph. 10 10 * 11 11 * @package PostFormatsBlockThemes … … 13 13 */ 14 14 ?> 15 <!-- wp:group {"layout":{"type":"constrained"}} --> 16 <div class="wp-block-group"> 17 <!-- wp:image {"sizeSlug":"large"} --> 18 <figure class="wp-block-image size-large"><img alt=""/></figure> 19 <!-- /wp:image --> 20 </div> 21 <!-- /wp:group --> 15 <!-- wp:image {"sizeSlug":"large"} --> 16 <figure class="wp-block-image size-large"><img alt=""/></figure> 17 <!-- /wp:image --> 22 18 19 <!-- wp:paragraph --> 20 <p></p> 21 <!-- /wp:paragraph --> -
post-formats-for-block-themes/tags/1.1.3/patterns/link.php
r3413728 r3423300 9 9 * Link to external content. Uses Bookmark Card plugin if available, 10 10 * otherwise falls back to paragraph with link styling. 11 * Followed by a paragraph for additional commentary. 11 12 * 12 13 * @package PostFormatsBlockThemes … … 16 17 // Check if Bookmark Card plugin is available. 17 18 $pfbt_has_bookmark_card = function_exists( 'bookmark_card_register_block' ) || has_block( 'bookmark-card/bookmark-card' ); 18 ?> 19 <!-- wp:group {"layout":{"type":"constrained"}} --> 20 <div class="wp-block-group"> 21 <?php 19 22 20 if ( $pfbt_has_bookmark_card ) { 23 21 // Use Bookmark Card block. 24 22 ?> 25 <!-- wp:bookmark-card/bookmark-card /--> 23 <!-- wp:bookmark-card/bookmark-card /--> 24 25 <!-- wp:paragraph --> 26 <p></p> 27 <!-- /wp:paragraph --> 26 28 <?php 27 29 } else { 28 30 // Fallback to paragraph with link placeholder. 29 31 ?> 30 <!-- wp:paragraph {"className":"link-format-fallback","fontSize":"large"} --> 31 <p class="link-format-fallback has-large-font-size"><a href="#"></a></p> 32 <!-- /wp:paragraph --> 32 <!-- wp:paragraph {"className":"link-format-fallback","fontSize":"large"} --> 33 <p class="link-format-fallback has-large-font-size"><a href="#"></a></p> 34 <!-- /wp:paragraph --> 35 36 <!-- wp:paragraph --> 37 <p></p> 38 <!-- /wp:paragraph --> 33 39 <?php 34 40 } 35 41 ?> 36 </div>37 <!-- /wp:group -->38 -
post-formats-for-block-themes/tags/1.1.3/patterns/quote.php
r3413728 r3423300 7 7 * Quote Post Format Pattern 8 8 * 9 * Quotation or citation. Starts with a quote block .9 * Quotation or citation. Starts with a quote block followed by a paragraph. 10 10 * 11 11 * @package PostFormatsBlockThemes … … 13 13 */ 14 14 ?> 15 <!-- wp:group {"layout":{"type":"constrained"}} --> 16 <div class="wp-block-group"> 17 <!-- wp:quote --> 18 <blockquote class="wp-block-quote"> 19 <!-- wp:paragraph --> 20 <p></p> 21 <!-- /wp:paragraph --> 22 </blockquote> 23 <!-- /wp:quote --> 24 </div> 25 <!-- /wp:group --> 15 <!-- wp:quote --> 16 <blockquote class="wp-block-quote"> 17 <!-- wp:paragraph --> 18 <p></p> 19 <!-- /wp:paragraph --> 20 </blockquote> 21 <!-- /wp:quote --> 26 22 23 <!-- wp:paragraph --> 24 <p></p> 25 <!-- /wp:paragraph --> -
post-formats-for-block-themes/tags/1.1.3/patterns/status.php
r3413728 r3423300 14 14 */ 15 15 16 // Paragraph with status-paragraph class for validation.16 // Single paragraph with status-paragraph class for character counter. 17 17 ?> 18 <!-- wp:group {"layout":{"type":"constrained"}} --> 19 <div class="wp-block-group"> 20 <!-- wp:paragraph {"className":"status-paragraph","fontSize":"large"} --> 21 <p class="status-paragraph has-large-font-size"></p> 22 <!-- /wp:paragraph --> 23 </div> 24 <!-- /wp:group --> 18 <!-- wp:paragraph {"className":"status-paragraph","fontSize":"large"} --> 19 <p class="status-paragraph has-large-font-size"></p> 20 <!-- /wp:paragraph --> 25 21 -
post-formats-for-block-themes/tags/1.1.3/patterns/video.php
r3413728 r3423300 7 7 * Video Post Format Pattern 8 8 * 9 * Video file or embed. Starts with a video block .9 * Video file or embed. Starts with a video block followed by a paragraph. 10 10 * 11 11 * @package PostFormatsBlockThemes … … 13 13 */ 14 14 ?> 15 <!-- wp:group {"layout":{"type":"constrained"}} --> 16 <div class="wp-block-group"> 17 <!-- wp:video --> 18 <figure class="wp-block-video"><video controls></video></figure> 19 <!-- /wp:video --> 20 </div> 21 <!-- /wp:group --> 15 <!-- wp:video --> 16 <figure class="wp-block-video"><video controls></video></figure> 17 <!-- /wp:video --> 22 18 19 <!-- wp:paragraph --> 20 <p></p> 21 <!-- /wp:paragraph --> -
post-formats-for-block-themes/tags/1.1.3/post-formats-for-block-themes.php
r3416925 r3423300 4 4 * Plugin URI: https://wordpress.org/plugins/post-formats-for-block-themes/ 5 5 * Description: Modernizes WordPress post formats for block themes with format-specific patterns, auto-detection, and enhanced editor experience. 6 * Version: 1.1. 26 * Version: 1.1.3 7 7 * Requires at least: 6.8 8 8 * Tested up to: 6.9 … … 39 39 * Plugin constants 40 40 */ 41 define( 'PFBT_VERSION', '1.1. 2' );41 define( 'PFBT_VERSION', '1.1.3' ); 42 42 define( 'PFBT_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 43 43 define( 'PFBT_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); … … 378 378 delete_transient( 'pfbt_bookmark_card_available' ); 379 379 delete_transient( 'pfbt_chatlog_block_available' ); 380 delete_transient( 'pfbt_patterns_registered' ); 380 381 } 381 382 register_deactivation_hook( __FILE__, 'pfbt_deactivate' ); 383 384 /** 385 * Add plugin action links 386 * 387 * Adds a "Settings" link to the plugin's row on the Plugins page 388 * that links to the Post Format Repair tool. 389 * 390 * @since 1.1.3 391 * 392 * @param array $links Existing plugin action links. 393 * @return array Modified plugin action links. 394 */ 395 function pfbt_plugin_action_links( $links ) { 396 $settings_link = sprintf( 397 '<a href="%s">%s</a>', 398 esc_url( admin_url( 'tools.php?page=pfbt-repair-tool' ) ), 399 esc_html__( 'Settings', 'post-formats-for-block-themes' ) 400 ); 401 array_unshift( $links, $settings_link ); 402 return $links; 403 } 404 add_filter( 'plugin_action_links_' . PFBT_PLUGIN_BASENAME, 'pfbt_plugin_action_links' ); 405 406 /** 407 * Limit revisions for wp_block post type 408 * 409 * Synced patterns are stored as wp_block posts. Limit revisions 410 * to prevent database bloat from pattern updates. 411 * 412 * @since 1.1.3 413 * 414 * @param int $num Number of revisions to keep. 415 * @param WP_Post $post The post object. 416 * @return int Modified number of revisions. 417 */ 418 function pfbt_limit_wp_block_revisions( $num, $post ) { 419 if ( 'wp_block' === $post->post_type ) { 420 return 3; 421 } 422 return $num; 423 } 424 add_filter( 'wp_revisions_to_keep', 'pfbt_limit_wp_block_revisions', 10, 2 ); -
post-formats-for-block-themes/tags/1.1.3/readme.txt
r3416925 r3423300 6 6 Tested up to: 6.9 7 7 Requires PHP: 7.4 8 Stable tag: 1.1. 28 Stable tag: 1.1.3 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 347 347 348 348 == Changelog == 349 350 = 1.1.3 - 2025-12-18 = 351 352 **Performance** 353 354 * **Fixed:** Critical performance issue with revision queries on sites with many synced patterns 355 * **Added:** Transient-based caching for pattern registration to avoid unnecessary database operations 356 * **Added:** Pattern registration now skipped entirely on front-end for better performance 357 * **Added:** Pattern updates only occur when content has actually changed 358 * **Added:** Revision limiter for wp_block post type (limits to 3 revisions to prevent database bloat) 359 360 **New Features** 361 362 * **Added:** "Settings" link on Plugins page that links to Post Format Repair tool for easy access 363 364 **Bug Fixes** 365 366 * **Fixed:** Duplicate pattern insertion when selecting format from modal (patterns were being inserted twice) 367 * **Fixed:** Status format character counter appearing twice in editor 368 * **Fixed:** Aside format icon not displaying in Posts admin list (changed from `dashicons-aside` to `dashicons-format-aside`) 369 * **Fixed:** JavaScript error "Cannot read properties of undefined (reading 'postCategories')" in block editor 370 * **Fixed:** Pattern transient now cleared on plugin deactivation to ensure fresh patterns on reactivation 371 372 **Improvements** 373 374 * **Changed:** Simplified all format patterns by removing unnecessary wrapper Group blocks 375 * **Changed:** Status pattern now uses single paragraph with `status-paragraph` class 376 * **Changed:** Aside pattern now uses single paragraph (no wrapper) 377 * **Changed:** All other format patterns now use primary block + paragraph structure for cleaner editing 378 379 **Security** 380 381 * **Added:** `domReady` wrapper for Post Format Block to prevent race conditions 382 * **Added:** Null check with fallback icon for safer script initialization 383 * **Added:** Asset file for Post Format Block script dependencies 349 384 350 385 = 1.1.2 - 2025-12-11 = … … 460 495 == Upgrade Notice == 461 496 497 = 1.1.3 = 498 Critical performance fix: Resolves database performance issue with revision queries. Also fixes duplicate pattern insertion, character counter appearing twice, and JavaScript errors. Simplified patterns for cleaner editing. All users should upgrade. 499 500 = 1.1.2 = 501 Editor UI improvements: Simplified format selection, better template chooser, fixed standard posts incorrectly showing format templates. 502 503 = 1.1.1 = 504 Critical fix: Format templates no longer appear in Template dropdown, fixing template selection issues. 505 462 506 = 1.1.0 = 463 507 Major update: Adds Post Format Block for frontend display, post format admin column with filtering, template improvements with category/tag/format display, and critical bug fixes for template assignment. All users should upgrade. -
post-formats-for-block-themes/trunk/blocks/post-format-block/index.js
r3413728 r3423300 18 18 import { __ } from '@wordpress/i18n'; 19 19 20 // Icon 20 // DOM Ready 21 import domReady from '@wordpress/dom-ready'; 22 23 // Icon - use optional chaining to prevent errors if icons not loaded yet 21 24 import { postCategories as icon } from '@wordpress/icons'; 22 25 … … 29 32 * @see https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/post-terms/variations.js 30 33 */ 31 const variation = { 32 name: 'post_format', 33 title: __( 'Post Format', 'post-formats-for-block-themes' ), 34 description: __( "Display a post's format", 'post-formats-for-block-themes' ), 35 icon, 36 isDefault: false, 37 attributes: { term: 'post_format' }, 38 isActive: ( blockAttributes ) => blockAttributes.term === 'post_format', 39 scope: [ 'inserter', 'transform' ], 40 }; 34 domReady( () => { 35 // Fallback icon if postCategories isn't available 36 const variationIcon = icon || 'tag'; 41 37 42 registerBlockVariation( 'core/post-terms', variation ); 38 const variation = { 39 name: 'post_format', 40 title: __( 'Post Format', 'post-formats-for-block-themes' ), 41 description: __( "Display a post's format", 'post-formats-for-block-themes' ), 42 icon: variationIcon, 43 isDefault: false, 44 attributes: { term: 'post_format' }, 45 isActive: ( blockAttributes ) => blockAttributes.term === 'post_format', 46 scope: [ 'inserter', 'transform' ], 47 }; 48 49 registerBlockVariation( 'core/post-terms', variation ); 50 } ); -
post-formats-for-block-themes/trunk/blocks/post-format-block/index.min.js
r3413728 r3423300 3 3 * @package PostFormatsBlockThemes 4 4 */ 5 (function(){var e=window.wp.blocks,t=window.wp.i18n,n=window.wp.icons ;const r={name:"post_format",title:(0,t.__)("Post Format","post-formats-for-block-themes"),description:(0,t.__)("Display a post's format","post-formats-for-block-themes"),icon:n.postCategories,isDefault:false,attributes:{term:"post_format"},isActive:function(e){return e.term==="post_format"},scope:["inserter","transform"]};(0,e.registerBlockVariation)("core/post-terms",r)})();5 (function(){var e=window.wp.blocks,t=window.wp.i18n,n=window.wp.icons,d=window.wp.domReady;d(function(){var i=(n&&n.postCategories)?n.postCategories:"tag";var r={name:"post_format",title:(0,t.__)("Post Format","post-formats-for-block-themes"),description:(0,t.__)("Display a post's format","post-formats-for-block-themes"),icon:i,isDefault:false,attributes:{term:"post_format"},isActive:function(e){return e.term==="post_format"},scope:["inserter","transform"]};(0,e.registerBlockVariation)("core/post-terms",r)})})(); -
post-formats-for-block-themes/trunk/build/index.asset.php
r3416925 r3423300 1 <?php return array('dependencies' => array('react', 'wp-a11y', 'wp-blocks', 'wp-components', 'wp- data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => 'aee0db3c8e30a508c90e');1 <?php return array('dependencies' => array('react', 'wp-a11y', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => '5add7157ad1a69c9a4cc'); -
post-formats-for-block-themes/trunk/build/index.js
r3416925 r3423300 1 (()=>{"use strict";const t=window.React,e=window.wp.plugins,a=window.wp.components,n=window.wp.data,r=window.wp.element,o=window.wp.i18n,s=window.wp.a11y,i=window.wp.hooks,p=window.wp.blocks,l=()=>{const[e,i]=(0,r.useState)(!1),[l,m]=(0,r.useState)(!1),{isNewPost:c,currentFormat:d,postType:u}=(0,n.useSelect)(t=>{const e=t("core/editor"),a=e.getCurrentPost();return{isNewPost:!a.id||"auto-draft"===a.status,currentFormat:e.getEditedPostAttribute("format")||"standard",postType:a.type}},[]),{editPost:f}=(0,n.useDispatch)("core/editor"),{insertBlocks:b}=(0,n.useDispatch)("core/block-editor");(0,r.useEffect)(()=>{c&&"post"===u&&!l&&window.pfbtData&&setTimeout(()=>{i(!0),m(!0)},500)},[c,u,l]);if(!e||!window.pfbtData)return null;const h=window.pfbtData.formats,g=Object.entries(h).map(([t,e])=>"standard"===t?[t,{...e,name:(0,o.__)("Standard (Single Template)","post-formats-for-block-themes"),description:(0,o.__)("Default post format using the Single template","post-formats-for-block-themes")}]:[t,e]).sort((t,e)=>"standard"===t[0]?-1:"standard"===e[0]?1:t[1].name.localeCompare(e[1].name));return(0,t.createElement)(a.Modal,{title:(0,o.__)("Choose Post Format","post-formats-for-block-themes"),onRequestClose:()=>i(!1),className:"pfpu-format-modal"},(0,t.createElement)("div",{className:"pfpu-format-grid"},g.map(([e,n])=>(0,t.createElement)(a.Card,{key:e,className:"pfpu-format-card"},(0,t.createElement)(a.CardBody,null,(0,t.createElement)(a.Button,{onClick:()=>(t=>{if(f({format:t,template:"standard"===t?"":`single-format-${t}`}),"standard"!==t&&window.pfbtData.formats[t]){const e=window.pfbtData.formats[t];((t,e)=>{if(!window.pfbtData.patterns||!window.pfbtData.patterns[t])return;const a=window.pfbtData.patterns[t],n=(0,p.parse)(a);n.length>0&&e(n,0,void 0,!1)})(t,b),(0,s.speak)(sprintf(/* translators: %s: Format name */ /* translators: %s: Format name */ 2 (0,o.__)("Selected %s format. Pattern inserted.","post-formats-for-block-themes"),e.name),"polite")}i(!1)})(e),className:"pfpu-format-button",variant:"standard"===e?"primary":"secondary"},(0,t.createElement)("span",{className:`dashicons dashicons-${n.icon}`,"aria-hidden":"true"}),(0,t.createElement)("span",{className:"pfpu-format-name"},n.name)),(0,t.createElement)("p",{className:"pfpu-format-description"},n.description))))))},m=()=>{const{createNotice:t,removeNotice:e}=(0,n.useDispatch)("core/notices"),{currentFormat:a,blocks:s}=(0,n.useSelect)(t=>{const e=t("core/editor"),a=t("core/block-editor");return{currentFormat:e.getEditedPostAttribute("format")||"standard",blocks:a.getBlocks()}},[]);return(0,r.useEffect)(()=>{if("status"!==a)return void e("pfbt-status-char-count");const n=s.find(t=>"core/paragraph"===t.name&&t.attributes.className?.includes("status-paragraph"));if(!n)return void e("pfbt-status-char-count");const r=(n.attributes.content||"").replace(/<[^>]*>/g,"").length;r>280?t("error",sprintf(/* translators: %d: Current character count */ /* translators: %d: Current character count */ 3 (0,o.__)("%d / 280 characters - Status updates should be 280 characters or less","post-formats-for-block-themes"),r),{id:"pfbt-status-char-count",isDismissible:!1}):r>=260?t("warning",sprintf(/* translators: %d: Current character count */ /* translators: %d: Current character count */ 4 (0,o.__)("%d / 280 characters - Approaching limit","post-formats-for-block-themes"),r),{id:"pfbt-status-char-count",isDismissible:!1}):e("pfbt-status-char-count")},[a,s,t,e]),null};if((0,e.registerPlugin)("post-formats-for-block-themes",{render:()=>(0,t.createElement)(t.Fragment,null,(0,t.createElement)(l,null),(0,t.createElement)(m,null))}),(0,i.addFilter)("editor.BlockEdit","pfpu/status-paragraph-counter",e=>a=>{const{name:n,attributes:r,setAttributes:s}=a;if("core/paragraph"!==n||!r.className?.includes("status-paragraph"))return(0,t.createElement)(e,{...a});const i=280-(r.content||"").replace(/<[^>]*>/g,"").length,p=i<0;return(0,t.createElement)("div",{className:"pfpu-status-paragraph-wrapper"},(0,t.createElement)(e,{...a}),(0,t.createElement)("div",{className:`pfpu-char-counter ${p?"is-over-limit":""} ${i<=20?"is-warning":""}`,"aria-live":"polite","aria-atomic":"true"},(0,t.createElement)("span",null,sprintf(/* translators: %d: Remaining characters */ /* translators: %d: Remaining characters */ 5 (0,o.__)("%d characters remaining","post-formats-for-block-themes"),i))))}),"undefined"!=typeof document){const t=document.createElement("style");t.textContent='\n\t.pfpu-format-modal {\n\t\tmax-width: 800px;\n\t}\n\n\t.pfpu-format-grid {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n\t\tgap: 1rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-format-card {\n\t\ttext-align: center;\n\t}\n\n\t.pfpu-format-button {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\tpadding: 1rem;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tgap: 0.5rem;\n\t}\n\n\t.pfpu-format-button .dashicons {\n\t\tfont-size: 2rem;\n\t\twidth: 2rem;\n\t\theight: 2rem;\n\t}\n\n\t.pfpu-format-name {\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-format-description {\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t\tmargin-top: 0.5rem;\n\t}\n\n\t.pfpu-format-change-actions {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.5rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-validator {\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-paragraph-wrapper {\n\t\tposition: relative;\n\t}\n\n\t.pfpu-char-counter {\n\t\tposition: absolute;\n\t\tbottom: -30px;\n\t\tright: 0;\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t}\n\n\t.pfpu-char-counter.is-warning {\n\t\tcolor: #f0b849;\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-char-counter.is-over-limit {\n\t\tcolor: #d63638;\n\t\tfont-weight: 600;\n\t}\n\n\t/* Template Modal - Visual Separation for Format Templates */\n\n\t/* Target template items in the template selection modal */\n\t/* Format templates have "Format" in their title (e.g., "Gallery Format", "Aside Format") */\n\n\t/* Template card styling - targets the button/card elements */\n\t.edit-post-template__panel .components-panel__body button[aria-label*="Format"],\n\t.edit-site-template-card button[aria-label*="Format"],\n\t.block-editor-block-card button[aria-label*="Format"] {\n\t\tborder-left: 4px solid var(--wp-admin-theme-color, #2271b1) !important;\n\t\tpadding-left: 12px !important;\n\t\tbackground: rgba(34, 113, 177, 0.05) !important;\n\t\tposition: relative;\n\t}\n\n\t/* Add emoji badge to format templates */\n\t.edit-post-template__panel .components-panel__body button[aria-label*="Format"]::before,\n\t.edit-site-template-card button[aria-label*="Format"]::before,\n\t.block-editor-block-card button[aria-label*="Format"]::before {\n\t\tcontent: "🎨 ";\n\t\tmargin-right: 4px;\n\t\tfont-size: 14px;\n\t}\n\n\t/* Template dropdown/modal items */\n\t.edit-post-template-dropdown__content button[aria-label*="Format"],\n\t.components-dropdown-menu__menu button[aria-label*="Format"] {\n\t\tborder-left: 4px solid var(--wp-admin-theme-color, #2271b1);\n\t\tpadding-left: 12px;\n\t\tbackground: rgba(34, 113, 177, 0.05);\n\t}\n\n\t/* Add visual indicator to currently selected format template */\n\t.edit-post-template__panel .components-panel__body .is-selected[aria-label*="Format"],\n\tbutton[aria-checked="true"][aria-label*="Format"] {\n\t\tbackground: rgba(34, 113, 177, 0.1) !important;\n\t\tfont-weight: 600;\n\t}\n\n\t/* Template name in sidebar - show when auto-applied */\n\t.edit-post-template__panel .components-panel__body .components-base-control__help {\n\t\tfont-style: italic;\n\t\tcolor: #757575;\n\t}\n',document.head.appendChild(t)}})(); 1 (()=>{"use strict";const t=window.React,e=window.wp.plugins,n=window.wp.components,r=window.wp.data,a=window.wp.element,o=window.wp.i18n,s=window.wp.a11y,i=window.wp.hooks,p=window.wp.blocks,c=window.wp.compose,m={},l=(t,e,n=null,r=!1)=>{if(m[t])return!1;if(!window.pfbtData?.patterns?.[t])return!1;const a=window.pfbtData.patterns[t],o=(0,p.parse)(a);return o.length>0&&(r&&n?n(o):e(o,0,void 0,!1),m[t]=!0,!0)},d=()=>{const t=(0,a.useRef)(null),{currentFormat:e,postType:n,blocks:i}=(0,r.useSelect)(t=>{const e=t("core/editor"),n=t("core/block-editor");return{currentFormat:e.getEditedPostAttribute("format")||"standard",postType:e.getCurrentPostType(),blocks:n.getBlocks()}},[]),{insertBlocks:p,resetBlocks:c}=(0,r.useDispatch)("core/block-editor");return(0,a.useEffect)(()=>{if("post"!==n)return;if(t.current===e)return;const r=null===t.current;if(t.current=e,r)return;if("standard"===e)return;const a=0===i.length||1===i.length&&"core/paragraph"===i[0].name&&!i[0].attributes.content;if(window.pfbtData?.patterns?.[e]&&l(e,p,c,a)){const t=window.pfbtData.formats?.[e]?.name||e;(0,s.speak)(sprintf((0,o.__)("Switched to %s format. Pattern inserted.","post-formats-for-block-themes"),t),"polite")}},[e,n,i,p,c]),null},u=()=>{const[e,i]=(0,a.useState)(!1),[p,c]=(0,a.useState)(!1),{isNewPost:m,currentFormat:d,postType:u}=(0,r.useSelect)(t=>{const e=t("core/editor"),n=e.getCurrentPost();return{isNewPost:!n.id||"auto-draft"===n.status,currentFormat:e.getEditedPostAttribute("format")||"standard",postType:n.type}},[]),{editPost:f}=(0,r.useDispatch)("core/editor"),{insertBlocks:w,resetBlocks:g}=(0,r.useDispatch)("core/block-editor");if((0,a.useEffect)(()=>{m&&"post"===u&&!p&&window.pfbtData&&setTimeout(()=>{i(!0),c(!0)},500)},[m,u,p]),!e||!window.pfbtData)return null;const h=window.pfbtData.formats,b=Object.entries(h).map(([t,e])=>"standard"===t?[t,{...e,name:(0,o.__)("Standard (Single Template)","post-formats-for-block-themes"),description:(0,o.__)("Default post format using the Single template","post-formats-for-block-themes")}]:[t,e]).sort((t,e)=>"standard"===t[0]?-1:"standard"===e[0]?1:t[1].name.localeCompare(e[1].name));return(0,t.createElement)(n.Modal,{title:(0,o.__)("Choose Post Format","post-formats-for-block-themes"),onRequestClose:()=>i(!1),className:"pfpu-format-modal"},(0,t.createElement)("div",{className:"pfpu-format-grid"},b.map(([e,r])=>(0,t.createElement)(n.Card,{key:e,className:"pfpu-format-card"},(0,t.createElement)(n.CardBody,null,(0,t.createElement)(n.Button,{onClick:()=>(t=>{if(f({format:t}),"standard"!==t&&window.pfbtData?.formats?.[t]){const e=window.pfbtData.formats[t];l(t,w,g,!0),(0,s.speak)(sprintf(/* translators: %s: Format name */ /* translators: %s: Format name */ 2 (0,o.__)("Selected %s format. Pattern inserted.","post-formats-for-block-themes"),e.name),"polite")}i(!1)})(e),className:"pfpu-format-button",variant:"standard"===e?"primary":"secondary"},(0,t.createElement)("span",{className:`dashicons dashicons-${r.icon}`,"aria-hidden":"true"}),(0,t.createElement)("span",{className:"pfpu-format-name"},r.name)),(0,t.createElement)("p",{className:"pfpu-format-description"},r.description))))))};(0,e.registerPlugin)("post-formats-for-block-themes",{render:()=>(0,t.createElement)(t.Fragment,null,(0,t.createElement)(u,null),(0,t.createElement)(d,null))});const f=(0,c.createHigherOrderComponent)(e=>n=>{const{name:a,attributes:s}=n,i=((0,r.useSelect)(t=>{const e=t("core/editor");return e?e.getEditedPostAttribute("format"):null},[]),s.className?.includes("status-paragraph"));if("core/paragraph"!==a||!i)return(0,t.createElement)(e,{...n});const p=280-(s.content||"").replace(/<[^>]*>/g,"").length,c=p<0;return(0,t.createElement)("div",{className:"pfpu-status-paragraph-wrapper"},(0,t.createElement)(e,{...n}),(0,t.createElement)("div",{className:`pfpu-char-counter ${c?"is-over-limit":""} ${p<=20?"is-warning":""}`,"aria-live":"polite","aria-atomic":"true"},(0,t.createElement)("span",null,sprintf(/* translators: %d: Remaining characters */ /* translators: %d: Remaining characters */ 3 (0,o.__)("%d characters remaining","post-formats-for-block-themes"),p))))},"withStatusCharacterCounter");if((0,i.addFilter)("editor.BlockEdit","pfpu/status-paragraph-counter",f),"undefined"!=typeof document){const t=document.createElement("style");t.textContent="\n\t.pfpu-format-modal {\n\t\tmax-width: 800px;\n\t}\n\n\t.pfpu-format-grid {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n\t\tgap: 1rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-format-card {\n\t\ttext-align: center;\n\t}\n\n\t.pfpu-format-button {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\tpadding: 1rem;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tgap: 0.5rem;\n\t}\n\n\t.pfpu-format-button .dashicons {\n\t\tfont-size: 2rem;\n\t\twidth: 2rem;\n\t\theight: 2rem;\n\t}\n\n\t.pfpu-format-name {\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-format-description {\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t\tmargin-top: 0.5rem;\n\t}\n\n\t.pfpu-format-change-actions {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 0.5rem;\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-validator {\n\t\tmargin-top: 1rem;\n\t}\n\n\t.pfpu-status-paragraph-wrapper {\n\t\tposition: relative;\n\t\tmargin-bottom: 30px;\n\t}\n\n\t.pfpu-char-counter {\n\t\tposition: absolute;\n\t\tbottom: -25px;\n\t\tright: 0;\n\t\tfont-size: 0.875rem;\n\t\tcolor: #757575;\n\t\tbackground: #fff;\n\t\tpadding: 2px 8px;\n\t\tborder-radius: 3px;\n\t\tbox-shadow: 0 1px 3px rgba(0,0,0,0.1);\n\t}\n\n\t.pfpu-char-counter.is-warning {\n\t\tcolor: #f0b849;\n\t\tfont-weight: 600;\n\t}\n\n\t.pfpu-char-counter.is-over-limit {\n\t\tcolor: #d63638;\n\t\tfont-weight: 600;\n\t\tbackground: #fcf0f1;\n\t}\n",document.head.appendChild(t)}})(); -
post-formats-for-block-themes/trunk/includes/class-admin-columns.php
r3413728 r3423300 170 170 $icons = array( 171 171 'standard' => 'dashicons-admin-post', 172 'aside' => 'dashicons- aside',172 'aside' => 'dashicons-format-aside', 173 173 'gallery' => 'dashicons-format-gallery', 174 174 'link' => 'dashicons-admin-links', -
post-formats-for-block-themes/trunk/includes/class-pattern-manager.php
r3413728 r3423300 89 89 * Only synced blocks are created to avoid duplicates. 90 90 * 91 * PERFORMANCE FIX: Only runs on plugin activation or when patterns 92 * are missing. Uses a transient to avoid checking on every page load. 93 * 91 94 * @since 1.0.0 92 95 */ 93 96 public static function register_all_patterns() { 97 // PERFORMANCE: Skip on front-end entirely. 98 if ( ! is_admin() && ! wp_doing_ajax() && ! ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { 99 return; 100 } 101 102 // PERFORMANCE: Use transient to avoid running on every admin page load. 103 // Patterns only need to be created once, then they persist in the database. 104 $patterns_version = PFBT_VERSION; 105 $cached_version = get_transient( 'pfbt_patterns_registered' ); 106 107 // Skip if patterns were already registered for this plugin version. 108 if ( $cached_version === $patterns_version ) { 109 return; 110 } 111 94 112 $instance = self::instance(); 95 113 $formats = PFBT_Format_Registry::get_all_formats(); … … 99 117 $instance->create_synced_pattern( $slug, $format ); 100 118 } 119 120 // Mark patterns as registered for 1 week (they persist in database anyway). 121 set_transient( 'pfbt_patterns_registered', $patterns_version, WEEK_IN_SECONDS ); 122 } 123 124 /** 125 * Force re-registration of patterns 126 * 127 * Called on plugin activation to ensure patterns are up to date. 128 * 129 * @since 1.1.3 130 */ 131 public static function force_register_patterns() { 132 delete_transient( 'pfbt_patterns_registered' ); 133 self::register_all_patterns(); 101 134 } 102 135 … … 157 190 * all instances update automatically. 158 191 * 192 * PERFORMANCE FIX: Only updates existing blocks when content has 193 * actually changed to avoid creating unnecessary revisions. 194 * 159 195 * @since 1.0.0 160 196 * … … 188 224 ); 189 225 190 $block_data = array(191 'post_title' => $block_title,192 'post_content' => $pattern_content,193 'post_status' => 'publish',194 'post_type' => 'wp_block',195 'post_name' => $block_slug,196 );197 198 226 if ( $existing_block ) { 199 // Update existing reusable block. 200 $block_data['ID'] = $existing_block->ID; 201 $block_id = wp_update_post( $block_data ); 227 // PERFORMANCE: Only update if content has actually changed. 228 // This prevents creating revisions on every admin page load. 229 $content_changed = ( trim( $existing_block->post_content ) !== trim( $pattern_content ) ); 230 $title_changed = ( $existing_block->post_title !== $block_title ); 231 232 if ( ! $content_changed && ! $title_changed ) { 233 // Content unchanged - skip update to avoid revision creation. 234 $block_id = $existing_block->ID; 235 } else { 236 // Content changed - update the block. 237 $block_data = array( 238 'ID' => $existing_block->ID, 239 'post_title' => $block_title, 240 'post_content' => $pattern_content, 241 'post_status' => 'publish', 242 'post_type' => 'wp_block', 243 'post_name' => $block_slug, 244 ); 245 $block_id = wp_update_post( $block_data ); 246 } 202 247 } else { 203 248 // Create new reusable block. 204 $block_id = wp_insert_post( $block_data ); 249 $block_data = array( 250 'post_title' => $block_title, 251 'post_content' => $pattern_content, 252 'post_status' => 'publish', 253 'post_type' => 'wp_block', 254 'post_name' => $block_slug, 255 ); 256 $block_id = wp_insert_post( $block_data ); 205 257 206 258 // Add metadata to identify this as a post format pattern. … … 210 262 } 211 263 212 // Assign to Post formats category .264 // Assign to Post formats category (only for new blocks or if category missing). 213 265 if ( $block_id && ! is_wp_error( $block_id ) ) { 214 // Get or create the category term. 215 $category_term = get_term_by( 'slug', 'post-formats', 'wp_pattern_category' ); 216 217 if ( ! $category_term ) { 218 $category_term = wp_insert_term( 219 __( 'Post formats', 'post-formats-for-block-themes' ), 220 'wp_pattern_category', 221 array( 'slug' => 'post-formats' ) 222 ); 223 } 224 225 // Assign the category to the block. 226 if ( $category_term && ! is_wp_error( $category_term ) ) { 227 $term_id = is_array( $category_term ) ? $category_term['term_id'] : $category_term->term_id; 228 wp_set_object_terms( $block_id, $term_id, 'wp_pattern_category' ); 266 // PERFORMANCE: Check if block already has the correct category. 267 $existing_terms = wp_get_object_terms( $block_id, 'wp_pattern_category', array( 'fields' => 'slugs' ) ); 268 $has_category = ! is_wp_error( $existing_terms ) && in_array( 'post-formats', $existing_terms, true ); 269 270 if ( ! $has_category ) { 271 // Get or create the category term. 272 $category_term = get_term_by( 'slug', 'post-formats', 'wp_pattern_category' ); 273 274 if ( ! $category_term ) { 275 $category_term = wp_insert_term( 276 __( 'Post formats', 'post-formats-for-block-themes' ), 277 'wp_pattern_category', 278 array( 'slug' => 'post-formats' ) 279 ); 280 } 281 282 // Assign the category to the block. 283 if ( $category_term && ! is_wp_error( $category_term ) ) { 284 $term_id = is_array( $category_term ) ? $category_term['term_id'] : $category_term->term_id; 285 wp_set_object_terms( $block_id, $term_id, 'wp_pattern_category' ); 286 } 229 287 } 230 288 } -
post-formats-for-block-themes/trunk/patterns/aside.php
r3413728 r3423300 14 14 */ 15 15 ?> 16 <!-- wp:group {"layout":{"type":"constrained"}} --> 17 <div class="wp-block-group"> 18 <!-- wp:paragraph --> 19 <p></p> 20 <!-- /wp:paragraph --> 21 </div> 22 <!-- /wp:group --> 16 <!-- wp:paragraph --> 17 <p></p> 18 <!-- /wp:paragraph --> -
post-formats-for-block-themes/trunk/patterns/audio.php
r3413728 r3423300 7 7 * Audio Post Format Pattern 8 8 * 9 * Audio file or embed. Starts with a core audio block .9 * Audio file or embed. Starts with a core audio block followed by a paragraph. 10 10 * Can be swapped with Podlove Podcast Publisher or Able Player blocks. 11 11 * … … 14 14 */ 15 15 ?> 16 <!-- wp:group {"layout":{"type":"constrained"}} --> 17 <div class="wp-block-group"> 18 <!-- wp:audio --> 19 <figure class="wp-block-audio"><audio controls></audio></figure> 20 <!-- /wp:audio --> 21 </div> 22 <!-- /wp:group --> 16 <!-- wp:audio --> 17 <figure class="wp-block-audio"><audio controls></audio></figure> 18 <!-- /wp:audio --> 23 19 20 <!-- wp:paragraph --> 21 <p></p> 22 <!-- /wp:paragraph --> -
post-formats-for-block-themes/trunk/patterns/chat.php
r3413728 r3423300 7 7 * Chat Post Format Pattern 8 8 * 9 * Chat transcript or conversation log. Uses the Chat Log block .9 * Chat transcript or conversation log. Uses the Chat Log block followed by a paragraph. 10 10 * 11 11 * Note: Requires the Chat Log plugin to be active. … … 16 16 */ 17 17 ?> 18 <!-- wp:group {"layout":{"type":"constrained"}} --> 19 <div class="wp-block-group"> 20 <!-- wp:chatlog/conversation /--> 21 </div> 22 <!-- /wp:group --> 18 <!-- wp:chatlog/conversation /--> 23 19 20 <!-- wp:paragraph --> 21 <p></p> 22 <!-- /wp:paragraph --> -
post-formats-for-block-themes/trunk/patterns/gallery.php
r3413728 r3423300 7 7 * Gallery Post Format Pattern 8 8 * 9 * Image gallery post. Starts with a gallery block .9 * Image gallery post. Starts with a gallery block followed by a paragraph. 10 10 * 11 11 * @package PostFormatsBlockThemes … … 13 13 */ 14 14 ?> 15 <!-- wp:group {"layout":{"type":"constrained"}} --> 16 <div class="wp-block-group"> 17 <!-- wp:gallery {"linkTo":"none"} --> 18 <figure class="wp-block-gallery has-nested-images columns-default is-cropped"> 19 <!-- wp:image --> 20 <figure class="wp-block-image"><img alt=""/></figure> 21 <!-- /wp:image --> 22 </figure> 23 <!-- /wp:gallery --> 24 </div> 25 <!-- /wp:group --> 15 <!-- wp:gallery {"linkTo":"none"} --> 16 <figure class="wp-block-gallery has-nested-images columns-default is-cropped"></figure> 17 <!-- /wp:gallery --> 26 18 19 <!-- wp:paragraph --> 20 <p></p> 21 <!-- /wp:paragraph --> -
post-formats-for-block-themes/trunk/patterns/image.php
r3413728 r3423300 7 7 * Image Post Format Pattern 8 8 * 9 * Single image post. Starts with an image block .9 * Single image post. Starts with an image block followed by a paragraph. 10 10 * 11 11 * @package PostFormatsBlockThemes … … 13 13 */ 14 14 ?> 15 <!-- wp:group {"layout":{"type":"constrained"}} --> 16 <div class="wp-block-group"> 17 <!-- wp:image {"sizeSlug":"large"} --> 18 <figure class="wp-block-image size-large"><img alt=""/></figure> 19 <!-- /wp:image --> 20 </div> 21 <!-- /wp:group --> 15 <!-- wp:image {"sizeSlug":"large"} --> 16 <figure class="wp-block-image size-large"><img alt=""/></figure> 17 <!-- /wp:image --> 22 18 19 <!-- wp:paragraph --> 20 <p></p> 21 <!-- /wp:paragraph --> -
post-formats-for-block-themes/trunk/patterns/link.php
r3413728 r3423300 9 9 * Link to external content. Uses Bookmark Card plugin if available, 10 10 * otherwise falls back to paragraph with link styling. 11 * Followed by a paragraph for additional commentary. 11 12 * 12 13 * @package PostFormatsBlockThemes … … 16 17 // Check if Bookmark Card plugin is available. 17 18 $pfbt_has_bookmark_card = function_exists( 'bookmark_card_register_block' ) || has_block( 'bookmark-card/bookmark-card' ); 18 ?> 19 <!-- wp:group {"layout":{"type":"constrained"}} --> 20 <div class="wp-block-group"> 21 <?php 19 22 20 if ( $pfbt_has_bookmark_card ) { 23 21 // Use Bookmark Card block. 24 22 ?> 25 <!-- wp:bookmark-card/bookmark-card /--> 23 <!-- wp:bookmark-card/bookmark-card /--> 24 25 <!-- wp:paragraph --> 26 <p></p> 27 <!-- /wp:paragraph --> 26 28 <?php 27 29 } else { 28 30 // Fallback to paragraph with link placeholder. 29 31 ?> 30 <!-- wp:paragraph {"className":"link-format-fallback","fontSize":"large"} --> 31 <p class="link-format-fallback has-large-font-size"><a href="#"></a></p> 32 <!-- /wp:paragraph --> 32 <!-- wp:paragraph {"className":"link-format-fallback","fontSize":"large"} --> 33 <p class="link-format-fallback has-large-font-size"><a href="#"></a></p> 34 <!-- /wp:paragraph --> 35 36 <!-- wp:paragraph --> 37 <p></p> 38 <!-- /wp:paragraph --> 33 39 <?php 34 40 } 35 41 ?> 36 </div>37 <!-- /wp:group -->38 -
post-formats-for-block-themes/trunk/patterns/quote.php
r3413728 r3423300 7 7 * Quote Post Format Pattern 8 8 * 9 * Quotation or citation. Starts with a quote block .9 * Quotation or citation. Starts with a quote block followed by a paragraph. 10 10 * 11 11 * @package PostFormatsBlockThemes … … 13 13 */ 14 14 ?> 15 <!-- wp:group {"layout":{"type":"constrained"}} --> 16 <div class="wp-block-group"> 17 <!-- wp:quote --> 18 <blockquote class="wp-block-quote"> 19 <!-- wp:paragraph --> 20 <p></p> 21 <!-- /wp:paragraph --> 22 </blockquote> 23 <!-- /wp:quote --> 24 </div> 25 <!-- /wp:group --> 15 <!-- wp:quote --> 16 <blockquote class="wp-block-quote"> 17 <!-- wp:paragraph --> 18 <p></p> 19 <!-- /wp:paragraph --> 20 </blockquote> 21 <!-- /wp:quote --> 26 22 23 <!-- wp:paragraph --> 24 <p></p> 25 <!-- /wp:paragraph --> -
post-formats-for-block-themes/trunk/patterns/status.php
r3413728 r3423300 14 14 */ 15 15 16 // Paragraph with status-paragraph class for validation.16 // Single paragraph with status-paragraph class for character counter. 17 17 ?> 18 <!-- wp:group {"layout":{"type":"constrained"}} --> 19 <div class="wp-block-group"> 20 <!-- wp:paragraph {"className":"status-paragraph","fontSize":"large"} --> 21 <p class="status-paragraph has-large-font-size"></p> 22 <!-- /wp:paragraph --> 23 </div> 24 <!-- /wp:group --> 18 <!-- wp:paragraph {"className":"status-paragraph","fontSize":"large"} --> 19 <p class="status-paragraph has-large-font-size"></p> 20 <!-- /wp:paragraph --> 25 21 -
post-formats-for-block-themes/trunk/patterns/video.php
r3413728 r3423300 7 7 * Video Post Format Pattern 8 8 * 9 * Video file or embed. Starts with a video block .9 * Video file or embed. Starts with a video block followed by a paragraph. 10 10 * 11 11 * @package PostFormatsBlockThemes … … 13 13 */ 14 14 ?> 15 <!-- wp:group {"layout":{"type":"constrained"}} --> 16 <div class="wp-block-group"> 17 <!-- wp:video --> 18 <figure class="wp-block-video"><video controls></video></figure> 19 <!-- /wp:video --> 20 </div> 21 <!-- /wp:group --> 15 <!-- wp:video --> 16 <figure class="wp-block-video"><video controls></video></figure> 17 <!-- /wp:video --> 22 18 19 <!-- wp:paragraph --> 20 <p></p> 21 <!-- /wp:paragraph --> -
post-formats-for-block-themes/trunk/post-formats-for-block-themes.php
r3416925 r3423300 4 4 * Plugin URI: https://wordpress.org/plugins/post-formats-for-block-themes/ 5 5 * Description: Modernizes WordPress post formats for block themes with format-specific patterns, auto-detection, and enhanced editor experience. 6 * Version: 1.1. 26 * Version: 1.1.3 7 7 * Requires at least: 6.8 8 8 * Tested up to: 6.9 … … 39 39 * Plugin constants 40 40 */ 41 define( 'PFBT_VERSION', '1.1. 2' );41 define( 'PFBT_VERSION', '1.1.3' ); 42 42 define( 'PFBT_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 43 43 define( 'PFBT_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); … … 378 378 delete_transient( 'pfbt_bookmark_card_available' ); 379 379 delete_transient( 'pfbt_chatlog_block_available' ); 380 delete_transient( 'pfbt_patterns_registered' ); 380 381 } 381 382 register_deactivation_hook( __FILE__, 'pfbt_deactivate' ); 383 384 /** 385 * Add plugin action links 386 * 387 * Adds a "Settings" link to the plugin's row on the Plugins page 388 * that links to the Post Format Repair tool. 389 * 390 * @since 1.1.3 391 * 392 * @param array $links Existing plugin action links. 393 * @return array Modified plugin action links. 394 */ 395 function pfbt_plugin_action_links( $links ) { 396 $settings_link = sprintf( 397 '<a href="%s">%s</a>', 398 esc_url( admin_url( 'tools.php?page=pfbt-repair-tool' ) ), 399 esc_html__( 'Settings', 'post-formats-for-block-themes' ) 400 ); 401 array_unshift( $links, $settings_link ); 402 return $links; 403 } 404 add_filter( 'plugin_action_links_' . PFBT_PLUGIN_BASENAME, 'pfbt_plugin_action_links' ); 405 406 /** 407 * Limit revisions for wp_block post type 408 * 409 * Synced patterns are stored as wp_block posts. Limit revisions 410 * to prevent database bloat from pattern updates. 411 * 412 * @since 1.1.3 413 * 414 * @param int $num Number of revisions to keep. 415 * @param WP_Post $post The post object. 416 * @return int Modified number of revisions. 417 */ 418 function pfbt_limit_wp_block_revisions( $num, $post ) { 419 if ( 'wp_block' === $post->post_type ) { 420 return 3; 421 } 422 return $num; 423 } 424 add_filter( 'wp_revisions_to_keep', 'pfbt_limit_wp_block_revisions', 10, 2 ); -
post-formats-for-block-themes/trunk/readme.txt
r3416925 r3423300 6 6 Tested up to: 6.9 7 7 Requires PHP: 7.4 8 Stable tag: 1.1. 28 Stable tag: 1.1.3 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 347 347 348 348 == Changelog == 349 350 = 1.1.3 - 2025-12-18 = 351 352 **Performance** 353 354 * **Fixed:** Critical performance issue with revision queries on sites with many synced patterns 355 * **Added:** Transient-based caching for pattern registration to avoid unnecessary database operations 356 * **Added:** Pattern registration now skipped entirely on front-end for better performance 357 * **Added:** Pattern updates only occur when content has actually changed 358 * **Added:** Revision limiter for wp_block post type (limits to 3 revisions to prevent database bloat) 359 360 **New Features** 361 362 * **Added:** "Settings" link on Plugins page that links to Post Format Repair tool for easy access 363 364 **Bug Fixes** 365 366 * **Fixed:** Duplicate pattern insertion when selecting format from modal (patterns were being inserted twice) 367 * **Fixed:** Status format character counter appearing twice in editor 368 * **Fixed:** Aside format icon not displaying in Posts admin list (changed from `dashicons-aside` to `dashicons-format-aside`) 369 * **Fixed:** JavaScript error "Cannot read properties of undefined (reading 'postCategories')" in block editor 370 * **Fixed:** Pattern transient now cleared on plugin deactivation to ensure fresh patterns on reactivation 371 372 **Improvements** 373 374 * **Changed:** Simplified all format patterns by removing unnecessary wrapper Group blocks 375 * **Changed:** Status pattern now uses single paragraph with `status-paragraph` class 376 * **Changed:** Aside pattern now uses single paragraph (no wrapper) 377 * **Changed:** All other format patterns now use primary block + paragraph structure for cleaner editing 378 379 **Security** 380 381 * **Added:** `domReady` wrapper for Post Format Block to prevent race conditions 382 * **Added:** Null check with fallback icon for safer script initialization 383 * **Added:** Asset file for Post Format Block script dependencies 349 384 350 385 = 1.1.2 - 2025-12-11 = … … 460 495 == Upgrade Notice == 461 496 497 = 1.1.3 = 498 Critical performance fix: Resolves database performance issue with revision queries. Also fixes duplicate pattern insertion, character counter appearing twice, and JavaScript errors. Simplified patterns for cleaner editing. All users should upgrade. 499 500 = 1.1.2 = 501 Editor UI improvements: Simplified format selection, better template chooser, fixed standard posts incorrectly showing format templates. 502 503 = 1.1.1 = 504 Critical fix: Format templates no longer appear in Template dropdown, fixing template selection issues. 505 462 506 = 1.1.0 = 463 507 Major update: Adds Post Format Block for frontend display, post format admin column with filtering, template improvements with category/tag/format display, and critical bug fixes for template assignment. All users should upgrade.
Note: See TracChangeset
for help on using the changeset viewer.