Plugin Directory

Changeset 3465978


Ignore:
Timestamp:
02/20/2026 06:05:53 PM (5 weeks ago)
Author:
happyprime
Message:

Update to version 1.1.1 from GitHub

Location:
theme-image-block
Files:
28 added
18 edited
1 copied

Legend:

Unmodified
Added
Removed
  • theme-image-block/tags/1.1.1/LICENSE

    r3421447 r3465978  
    11Theme Image Block - a plugin for WordPress
    22
    3 Copyright 2025 by Happy Prime
     3Copyright 2025-2026 by Happy Prime
    44
    55This program is free software; you can redistribute it and/or modify
  • theme-image-block/tags/1.1.1/blocks/build/theme-image/index.asset.php

    r3421447 r3465978  
    1 <?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'a084c1de89a76e2f384a');
     1<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '38acce586dd7a3df84e2');
  • theme-image-block/tags/1.1.1/blocks/build/theme-image/index.js

    r3421447 r3465978  
    1 (()=>{"use strict";const e=window.wp.blockEditor,t=window.wp.blocks,l=window.wp.components,a=window.wp.i18n,n=window.wp.element,o=window.wp.primitives,i=window.ReactJSXRuntime;var c=(0,i.jsx)(o.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,i.jsx)(o.Path,{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5 4.5h14c.3 0 .5.2.5.5v8.4l-3-2.9c-.3-.3-.8-.3-1 0L11.9 14 9 12c-.3-.2-.6-.2-.8 0l-3.6 2.6V5c-.1-.3.1-.5.4-.5zm14 15H5c-.3 0-.5-.2-.5-.5v-2.4l4.1-3 3 1.9c.3.2.7.2.9-.1L16 12l3.5 3.4V19c0 .3-.2.5-.5.5z"})}),m=(0,i.jsx)(o.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,i.jsx)(o.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M6 5.5h12a.5.5 0 0 1 .5.5v12a.5.5 0 0 1-.5.5H6a.5.5 0 0 1-.5-.5V6a.5.5 0 0 1 .5-.5ZM4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6Zm4 10h2v-1.5H8V16Zm5 0h-2v-1.5h2V16Zm1 0h2v-1.5h-2V16Z"})});const r=JSON.parse('{"UU":"happyprime/theme-image"}');(0,t.registerBlockType)(r.UU,{edit:function({attributes:t,setAttributes:o}){const{themeImage:i,imageSize:r,imageStyle:s,inlineSVG:h,linkUrl:g,linkTarget:p,linkRel:b,caption:k,showCaption:u,altText:_,omitAltText:d}=t,[v,w]=(0,n.useState)(null),[R,f]=(0,n.useState)(!1),S=happyprime_themeimageblock_data?.images||[],y=happyprime_themeimageblock_data?.styles||[],T=[{value:"",label:(0,a.__)("Select an image","theme-image-block")},...S.map(e=>({value:e.slug,label:e.label}))],C=S.find(e=>e.slug===i),E=[{value:"original",label:(0,a.__)("Original","theme-image-block")}];C&&C.variations&&Object.keys(C.variations).forEach(e=>{const t=C.variations[e];E.push({value:e,label:t.name||e})});let x=C?.value||"";C&&"original"!==r&&C.variations&&C.variations[r]&&(x=C.variations[r].path),(0,n.useEffect)(()=>{if(h&&x&&x.toLowerCase().endsWith(".svg")){const e=`${happyprimeData.themeUrl}/${x}`;fetch(e).then(e=>e.text()).then(e=>{w(e)}).catch(e=>{console.error("Failed to fetch SVG:",e),w(null)})}else w(null)},[h,x]);const V=(0,e.useBlockProps)({className:h?"has-inline-svg":""}),I=x&&happyprimeData?.themeUrl?`${happyprimeData.themeUrl}/${x}`:"",U=x&&x.toLowerCase().endsWith(".svg"),B=y.find(e=>e.slug===s),$=B?.width||"",j=B?.height||"";let A,L=null;if(h&&v){const e=[];$?e.push(`width: ${$}`):$||e.push("width: 100%"),j&&e.push(`height: ${j}`);const t=e.join("; "),l=v.match(/<svg([^>]*)>/);if(l){const e=l[1].match(/style="([^"]*)"/);if(e){const l=e[1];L=v.replace(/<svg([^>]*)>/,e=>e.replace(/style="[^"]*"/,`style="${l}; ${t}"`))}else L=v.replace(/<svg([^>]*)>/,`<svg$1 style="${t}">`)}}if(I)if(h&&L)A=g?React.createElement("a",{href:g,target:p,rel:b,dangerouslySetInnerHTML:{__html:L}}):null;else{const e={};$&&(e.width=$),j&&(e.height=j);const t=React.createElement("img",{src:I,alt:C?.alt||(0,a.__)("Theme image preview","theme-image-block"),style:Object.keys(e).length>0?e:void 0});A=g?React.createElement("a",{href:g,target:p,rel:b},t):t}else A=React.createElement(l.Placeholder,{icon:React.createElement(e.BlockIcon,{icon:c}),label:(0,a.__)("Theme Image","theme-image-block"),instructions:(0,a.__)("Select an image from the block settings","theme-image-block")});const O=h&&L&&!g?{...V,dangerouslySetInnerHTML:{__html:L}}:V;return React.createElement(React.Fragment,null,I&&React.createElement(e.BlockControls,{group:"block"},React.createElement(l.ToolbarButton,{icon:"admin-links",label:(0,a.__)("Link","theme-image-block"),onClick:()=>f(!0),isActive:!!g}),g&&React.createElement(l.ToolbarButton,{icon:"editor-unlink",label:(0,a.__)("Unlink","theme-image-block"),onClick:()=>{o({linkUrl:"",linkTarget:"",linkRel:""})}}),React.createElement(l.ToolbarButton,{icon:m,label:(0,a.__)("Add caption","theme-image-block"),onClick:()=>o({showCaption:!u}),isActive:u})),R&&React.createElement(l.Popover,{position:"bottom center",onClose:()=>f(!1),anchor:document.querySelector(".wp-block-happyprime-theme-image")},React.createElement(e.__experimentalLinkControl,{value:{url:g,opensInNewTab:"_blank"===p,nofollow:b?.includes("nofollow")},onChange:e=>{const t=[];e?.opensInNewTab&&t.push("noopener","noreferrer"),e?.nofollow&&t.push("nofollow"),o({linkUrl:e?.url||"",linkTarget:e?.opensInNewTab?"_blank":"",linkRel:t.join(" ")})},onRemove:()=>{o({linkUrl:"",linkTarget:"",linkRel:""}),f(!1)},settings:[{id:"opensInNewTab",title:(0,a.__)("Open in new tab","theme-image-block")},{id:"nofollow",title:(0,a.__)("Mark as nofollow","theme-image-block")}]})),React.createElement(e.InspectorControls,null,React.createElement(l.PanelBody,{title:(0,a.__)("Settings","theme-image-block"),initialOpen:!0},React.createElement(l.SelectControl,{label:(0,a.__)("Theme Image","theme-image-block"),value:i,options:T,onChange:e=>{o({themeImage:e,imageSize:"original"})},help:(0,a.__)("Select a registered theme image.","theme-image-block")}),C&&C.variations&&Object.keys(C.variations).length>0&&React.createElement(l.SelectControl,{label:(0,a.__)("Variation","theme-image-block"),value:r,options:E,onChange:e=>o({imageSize:e}),help:(0,a.__)("Select the image variation.","theme-image-block")}),React.createElement(l.SelectControl,{label:(0,a.__)("Style","theme-image-block"),value:s,options:[{value:"",label:(0,a.__)("Default","theme-image-block")},...y.map(e=>({value:e.slug,label:e.name}))],onChange:e=>o({imageStyle:e}),help:(0,a.__)("Select a registered style to apply.","theme-image-block")}),U&&React.createElement(l.ToggleControl,{label:(0,a.__)("Inline SVG","theme-image-block"),checked:h,onChange:e=>o({inlineSVG:e}),help:(0,a.__)("Render SVG code inline.","theme-image-block")}),!d&&React.createElement(l.TextControl,{label:(0,a.__)("Alt Text","theme-image-block"),value:_,onChange:e=>o({altText:e}),placeholder:C?.alt||"",help:(0,a.__)("Alternative text for the image. Leave empty to use the registered default.","theme-image-block")}),React.createElement(l.ToggleControl,{label:(0,a.__)("Omit alt text","theme-image-block"),checked:d,onChange:e=>o({omitAltText:e}),help:(0,a.__)("Output empty alt text, even if a registered value exists.","theme-image-block")}))),React.createElement("figure",O,A,I&&u&&React.createElement(e.RichText,{tagName:"figcaption",placeholder:C?.caption||(0,a.__)("Add caption…","theme-image-block"),value:k,onChange:e=>o({caption:e}),allowedFormats:["core/bold","core/italic","core/link"]})))}})})();
     1(()=>{"use strict";const e=window.wp.blockEditor,t=window.wp.blocks,l=window.wp.components,a=window.wp.i18n,n=window.wp.element,o=window.wp.primitives,i=window.ReactJSXRuntime;var c=(0,i.jsx)(o.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(o.Path,{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5 4.5h14c.3 0 .5.2.5.5v8.4l-3-2.9c-.3-.3-.8-.3-1 0L11.9 14 9 12c-.3-.2-.6-.2-.8 0l-3.6 2.6V5c-.1-.3.1-.5.4-.5zm14 15H5c-.3 0-.5-.2-.5-.5v-2.4l4.1-3 3 1.9c.3.2.7.2.9-.1L16 12l3.5 3.4V19c0 .3-.2.5-.5.5z"})}),m=(0,i.jsx)(o.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(o.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M6 5.5h12a.5.5 0 0 1 .5.5v12a.5.5 0 0 1-.5.5H6a.5.5 0 0 1-.5-.5V6a.5.5 0 0 1 .5-.5ZM4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6Zm4 10h2v-1.5H8V16Zm5 0h-2v-1.5h2V16Zm1 0h2v-1.5h-2V16Z"})});const r=JSON.parse('{"UU":"happyprime/theme-image"}');(0,t.registerBlockType)(r.UU,{edit:function({attributes:t,setAttributes:o}){const{themeImage:i,imageSize:r,imageStyle:s,inlineSVG:h,linkUrl:g,linkTarget:p,linkRel:b,caption:k,showCaption:_,altText:u,omitAltText:d}=t,[v,w]=(0,n.useState)(null),[R,f]=(0,n.useState)(!1),y=(0,n.useRef)(),S=happyprime_themeimageblock_data?.images||[],E=happyprime_themeimageblock_data?.styles||[],C=[{value:"",label:(0,a.__)("Select an image","theme-image-block")},...S.map(e=>({value:e.slug,label:e.label}))],T=S.find(e=>e.slug===i),x=[{value:"original",label:(0,a.__)("Original","theme-image-block")}];T&&T.variations&&Object.keys(T.variations).forEach(e=>{const t=T.variations[e];x.push({value:e,label:t.name||e})});let V=T?.value||"";T&&"original"!==r&&T.variations&&T.variations[r]&&(V=T.variations[r].path),(0,n.useEffect)(()=>{if(h&&V&&V.toLowerCase().endsWith(".svg")){const e=`${happyprime_themeimageblock_data.themeUrl}/${V}`;fetch(e).then(e=>e.text()).then(e=>{w(e)}).catch(e=>{console.error("Failed to fetch SVG:",e),w(null)})}else w(null)},[h,V]);const I=(0,e.useBlockProps)({ref:y,className:h?"has-inline-svg":""}),U=V&&happyprime_themeimageblock_data?.themeUrl?`${happyprime_themeimageblock_data.themeUrl}/${V}`:"",B=V&&V.toLowerCase().endsWith(".svg"),$=E.find(e=>e.slug===s),j=$?.width||"",A=$?.height||"";let O,L=null;if(h&&v){const e=[];j&&e.push(`width: ${j}`),A&&e.push(`height: ${A}`);const t=e.join("; "),l=v.match(/<svg([^>]*)>/);if(l){const e=l[1].match(/style="([^"]*)"/);if(e){const l=e[1];L=v.replace(/<svg([^>]*)>/,e=>e.replace(/style="[^"]*"/,`style="${l}; ${t}"`))}else L=v.replace(/<svg([^>]*)>/,`<svg$1 style="${t}">`)}}if(U)if(h&&L){const e=React.createElement("span",{dangerouslySetInnerHTML:{__html:L},style:{display:"contents"}});O=g?React.createElement("a",{href:g,target:p,rel:b},e):e}else{const e={};j&&(e.width=j),A&&(e.height=A);const t=d?"":u||T?.alt||"",l=React.createElement("img",{src:U,alt:t,style:Object.keys(e).length>0?e:void 0});O=g?React.createElement("a",{href:g,target:p,rel:b},l):l}else O=React.createElement(l.Placeholder,{icon:React.createElement(e.BlockIcon,{icon:c}),label:(0,a.__)("Theme Image","theme-image-block"),instructions:(0,a.__)("Select an image from the block settings","theme-image-block")});const G=I;return React.createElement(React.Fragment,null,U&&React.createElement(e.BlockControls,{group:"block"},React.createElement(l.ToolbarButton,{icon:"admin-links",label:(0,a.__)("Link","theme-image-block"),onClick:()=>f(!0),isActive:!!g}),g&&React.createElement(l.ToolbarButton,{icon:"editor-unlink",label:(0,a.__)("Unlink","theme-image-block"),onClick:()=>{o({linkUrl:"",linkTarget:"",linkRel:""})}}),React.createElement(l.ToolbarButton,{icon:m,label:(0,a.__)("Add caption","theme-image-block"),onClick:()=>o({showCaption:!_}),isActive:_})),R&&React.createElement(l.Popover,{position:"bottom center",onClose:()=>f(!1),anchor:y.current},React.createElement(e.__experimentalLinkControl,{value:{url:g,opensInNewTab:"_blank"===p,nofollow:b?.includes("nofollow")},onChange:e=>{const t=[];e?.opensInNewTab&&t.push("noopener","noreferrer"),e?.nofollow&&t.push("nofollow"),o({linkUrl:e?.url||"",linkTarget:e?.opensInNewTab?"_blank":"",linkRel:t.join(" ")})},onRemove:()=>{o({linkUrl:"",linkTarget:"",linkRel:""}),f(!1)},settings:[{id:"opensInNewTab",title:(0,a.__)("Open in new tab","theme-image-block")},{id:"nofollow",title:(0,a.__)("Mark as nofollow","theme-image-block")}]})),React.createElement(e.InspectorControls,null,React.createElement(l.PanelBody,{title:(0,a.__)("Settings","theme-image-block"),initialOpen:!0},React.createElement(l.SelectControl,{label:(0,a.__)("Theme Image","theme-image-block"),value:i,options:C,onChange:e=>{o({themeImage:e,imageSize:"original"})},help:(0,a.__)("Select a registered theme image.","theme-image-block")}),T&&T.variations&&Object.keys(T.variations).length>0&&React.createElement(l.SelectControl,{label:(0,a.__)("Variation","theme-image-block"),value:r,options:x,onChange:e=>o({imageSize:e}),help:(0,a.__)("Select the image variation.","theme-image-block")}),React.createElement(l.SelectControl,{label:(0,a.__)("Style","theme-image-block"),value:s,options:[{value:"",label:(0,a.__)("Default","theme-image-block")},...E.map(e=>({value:e.slug,label:e.name}))],onChange:e=>o({imageStyle:e}),help:(0,a.__)("Select a registered style to apply.","theme-image-block")}),B&&React.createElement(l.ToggleControl,{label:(0,a.__)("Inline SVG","theme-image-block"),checked:h,onChange:e=>o({inlineSVG:e}),help:(0,a.__)("Render SVG code inline.","theme-image-block")}),!d&&React.createElement(l.TextControl,{label:(0,a.__)("Alt Text","theme-image-block"),value:u,onChange:e=>o({altText:e}),placeholder:T?.alt||"",help:(0,a.__)("Alternative text for the image. Leave empty to use the registered default.","theme-image-block")}),React.createElement(l.ToggleControl,{label:(0,a.__)("Omit alt text","theme-image-block"),checked:d,onChange:e=>o({omitAltText:e}),help:(0,a.__)("Output empty alt text, even if a registered value exists.","theme-image-block")}))),React.createElement("figure",G,O,U&&_&&React.createElement(e.RichText,{tagName:"figcaption",placeholder:T?.caption||(0,a.__)("Add caption…","theme-image-block"),value:k,onChange:e=>o({caption:e}),allowedFormats:["core/bold","core/italic","core/link"]})))}})})();
  • theme-image-block/tags/1.1.1/blocks/src/theme-image/block.json

    r3421447 r3465978  
    6666        }
    6767    },
    68     "textdomain": "happyprime",
     68    "textdomain": "theme-image-block",
    6969    "editorScript": "file:../../build/theme-image/index.js",
    7070    "style": "file:./style.css"
  • theme-image-block/tags/1.1.1/blocks/src/theme-image/index.js

    r3421447 r3465978  
    2121} from '@wordpress/components';
    2222import { __ } from '@wordpress/i18n';
    23 import { useState, useEffect } from '@wordpress/element';
     23import { useState, useEffect, useRef } from '@wordpress/element';
    2424import { image, caption as captionIcon } from '@wordpress/icons';
    2525
     
    5353    const [svgContent, setSvgContent] = useState(null);
    5454    const [isEditingLink, setIsEditingLink] = useState(false);
     55    const blockRef = useRef();
    5556
    5657    // Get registered theme images and styles from localized data.
     
    105106            imagePath.toLowerCase().endsWith('.svg')
    106107        ) {
    107             const svgUrl = `${happyprimeData.themeUrl}/${imagePath}`;
     108            const svgUrl = `${happyprime_themeimageblock_data.themeUrl}/${imagePath}`;
    108109            fetch(svgUrl)
    109110                .then((response) => response.text())
     
    121122
    122123    const blockProps = useBlockProps({
     124        ref: blockRef,
    123125        className: inlineSVG ? 'has-inline-svg' : '',
    124126    });
    125127
    126128    const imageUrl =
    127         imagePath && happyprimeData?.themeUrl
    128             ? `${happyprimeData.themeUrl}/${imagePath}`
     129        imagePath && happyprime_themeimageblock_data?.themeUrl
     130            ? `${happyprime_themeimageblock_data.themeUrl}/${imagePath}`
    129131            : '';
    130132    const isSVG = imagePath && imagePath.toLowerCase().endsWith('.svg');
     
    144146        if (width) {
    145147            styles.push(`width: ${width}`);
    146         } else if (!width) {
    147             // Default width for editor preview when not specified.
    148             styles.push('width: 100%');
    149148        }
    150149        if (height) {
     
    194193        // For inline SVG, apply dangerouslySetInnerHTML to link or wrapper
    195194        // to match server-side structure without extra figure wrapper.
     195        const svgElement = (
     196            <span
     197                dangerouslySetInnerHTML={{ __html: processedSvg }}
     198                style={{ display: 'contents' }}
     199            />
     200        );
    196201        if (linkUrl) {
    197202            content = (
    198                 <a
    199                     href={linkUrl}
    200                     target={linkTarget}
    201                     rel={linkRel}
    202                     dangerouslySetInnerHTML={{ __html: processedSvg }}
    203                 />
     203                <a href={linkUrl} target={linkTarget} rel={linkRel}>
     204                    {svgElement}
     205                </a>
    204206            );
    205207        } else {
    206             // Will be applied to wrapper figure via blockProps below.
    207             content = null;
     208            content = svgElement;
    208209        }
    209210    } else {
     
    217218        }
    218219
     220        const editorAlt = omitAltText ? '' : altText || currentImage?.alt || '';
     221
    219222        const img = (
    220223            <img
    221224                src={imageUrl}
    222                 alt={
    223                     currentImage?.alt ||
    224                     __('Theme image preview', 'theme-image-block')
    225                 }
     225                alt={editorAlt}
    226226                style={
    227227                    Object.keys(imgStyles).length > 0 ? imgStyles : undefined
     
    238238    }
    239239
    240     // For inline SVG without link, apply HTML directly to wrapper.
    241     const wrapperProps =
    242         inlineSVG && processedSvg && !linkUrl
    243             ? {
    244                     ...blockProps,
    245                     dangerouslySetInnerHTML: { __html: processedSvg },
    246                 }
    247             : blockProps;
     240    const wrapperProps = blockProps;
    248241
    249242    return (
     
    273266                        icon={captionIcon}
    274267                        label={__('Add caption', 'theme-image-block')}
    275                         onClick={() => setAttributes({ showCaption: !showCaption })}
     268                        onClick={() =>
     269                            setAttributes({ showCaption: !showCaption })
     270                        }
    276271                        isActive={showCaption}
    277272                    />
     
    283278                    position="bottom center"
    284279                    onClose={() => setIsEditingLink(false)}
    285                     anchor={document.querySelector(
    286                         '.wp-block-happyprime-theme-image'
    287                     )}
     280                    anchor={blockRef.current}
    288281                >
    289282                    <LinkControl
  • theme-image-block/tags/1.1.1/composer.json

    r3421447 r3465978  
    1414        }
    1515    },
     16    "repositories": [
     17        {
     18            "type": "package",
     19            "package": {
     20                "name": "phpcompatibility/php-compatibility",
     21                "type": "phpcodesniffer-standard",
     22                "version": "9.99.9",
     23                "source": {
     24                    "url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
     25                    "type": "git",
     26                    "reference": "9f7142356b5674164a6f6dbe12a7a1bcc632db21"
     27                }
     28            }
     29        }
     30    ],
    1631    "autoload": {
    1732        "psr-4": {
     
    2136    "require-dev": {
    2237        "happyprime/coding-standards": "*",
    23         "phpcompatibility/php-compatibility": "dev-develop as 9.99.99"
     38        "phpcompatibility/php-compatibility": "9.99.9"
    2439    },
    2540    "scripts": {
  • theme-image-block/tags/1.1.1/readme.txt

    r3423224 r3465978  
    44Requires at least: 6.8
    55Tested up to: 6.9
    6 Stable tag: 1.1.0
     6Stable tag: 1.1.1
    77License: GPLv2 or later
    88Requires PHP: 7.4
     
    7676## Changelog
    7777
     78### 1.1.1
     79
     80* Prevent fatal error on activation.
     81* Improve HTML processing when rendering output.
     82* Fix reference to renamed global JavaScript variable.
     83* Fix textdomain mismatch.
     84* Improve support for multiple theme image blocks in one editor view.
     85
    7886### 1.1.0
    7987
  • theme-image-block/tags/1.1.1/src/Block.php

    r3421447 r3465978  
    181181        if ( $link_url ) {
    182182            $content = '<a>' . $content . '</a>';
     183
     184            $html = new \WP_HTML_Tag_Processor( $content );
     185            if ( $html->next_tag( array( 'tag_name' => 'a' ) ) ) {
     186                $html->set_attribute( 'href', $link_url );
     187                if ( $link_target ) {
     188                    $html->set_attribute( 'target', $link_target );
     189                }
     190                if ( $link_rel ) {
     191                    $html->set_attribute( 'rel', $link_rel );
     192                }
     193            }
     194
     195            $content = $html->get_updated_html();
    183196        }
    184197
    185198        $html = new \WP_HTML_Tag_Processor( $content );
    186         if ( $html->next_tag( array( 'tag_name' => 'a' ) ) ) {
    187             $html->set_attribute( 'href', $link_url );
    188             if ( $link_target ) {
    189                 $html->set_attribute( 'target', $link_target );
    190             }
    191             if ( $link_rel ) {
    192                 $html->set_attribute( 'rel', $link_rel );
    193             }
    194         }
    195 
    196         // This seems to be the best way to rewind and seek again? Seems strange.
    197         $html = new \WP_HTML_Tag_Processor( $html->get_updated_html() );
    198199
    199200        if ( $html->next_tag( array( 'tag_name' => 'img' ) ) ) {
     
    218219        }
    219220
    220         $wrapper_attrs = array( 'class' => implode( ' ', $wrapper_classes ) );
     221        $wrapper_attrs = ! empty( $wrapper_classes )
     222            ? array( 'class' => implode( ' ', $wrapper_classes ) )
     223            : array();
    221224
    222225        return sprintf(
  • theme-image-block/tags/1.1.1/theme-image-block.php

    r3421447 r3465978  
    33 * Plugin Name:  Theme Image Block
    44 * Description:  Use images from your theme as blocks in content.
    5  * Version:      1.1.0
     5 * Version:      1.1.1
    66 * Author:       Happy Prime
    77 * Author URI:   https://happyprime.co
  • theme-image-block/trunk/LICENSE

    r3421447 r3465978  
    11Theme Image Block - a plugin for WordPress
    22
    3 Copyright 2025 by Happy Prime
     3Copyright 2025-2026 by Happy Prime
    44
    55This program is free software; you can redistribute it and/or modify
  • theme-image-block/trunk/blocks/build/theme-image/index.asset.php

    r3421447 r3465978  
    1 <?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'a084c1de89a76e2f384a');
     1<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '38acce586dd7a3df84e2');
  • theme-image-block/trunk/blocks/build/theme-image/index.js

    r3421447 r3465978  
    1 (()=>{"use strict";const e=window.wp.blockEditor,t=window.wp.blocks,l=window.wp.components,a=window.wp.i18n,n=window.wp.element,o=window.wp.primitives,i=window.ReactJSXRuntime;var c=(0,i.jsx)(o.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,i.jsx)(o.Path,{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5 4.5h14c.3 0 .5.2.5.5v8.4l-3-2.9c-.3-.3-.8-.3-1 0L11.9 14 9 12c-.3-.2-.6-.2-.8 0l-3.6 2.6V5c-.1-.3.1-.5.4-.5zm14 15H5c-.3 0-.5-.2-.5-.5v-2.4l4.1-3 3 1.9c.3.2.7.2.9-.1L16 12l3.5 3.4V19c0 .3-.2.5-.5.5z"})}),m=(0,i.jsx)(o.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,i.jsx)(o.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M6 5.5h12a.5.5 0 0 1 .5.5v12a.5.5 0 0 1-.5.5H6a.5.5 0 0 1-.5-.5V6a.5.5 0 0 1 .5-.5ZM4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6Zm4 10h2v-1.5H8V16Zm5 0h-2v-1.5h2V16Zm1 0h2v-1.5h-2V16Z"})});const r=JSON.parse('{"UU":"happyprime/theme-image"}');(0,t.registerBlockType)(r.UU,{edit:function({attributes:t,setAttributes:o}){const{themeImage:i,imageSize:r,imageStyle:s,inlineSVG:h,linkUrl:g,linkTarget:p,linkRel:b,caption:k,showCaption:u,altText:_,omitAltText:d}=t,[v,w]=(0,n.useState)(null),[R,f]=(0,n.useState)(!1),S=happyprime_themeimageblock_data?.images||[],y=happyprime_themeimageblock_data?.styles||[],T=[{value:"",label:(0,a.__)("Select an image","theme-image-block")},...S.map(e=>({value:e.slug,label:e.label}))],C=S.find(e=>e.slug===i),E=[{value:"original",label:(0,a.__)("Original","theme-image-block")}];C&&C.variations&&Object.keys(C.variations).forEach(e=>{const t=C.variations[e];E.push({value:e,label:t.name||e})});let x=C?.value||"";C&&"original"!==r&&C.variations&&C.variations[r]&&(x=C.variations[r].path),(0,n.useEffect)(()=>{if(h&&x&&x.toLowerCase().endsWith(".svg")){const e=`${happyprimeData.themeUrl}/${x}`;fetch(e).then(e=>e.text()).then(e=>{w(e)}).catch(e=>{console.error("Failed to fetch SVG:",e),w(null)})}else w(null)},[h,x]);const V=(0,e.useBlockProps)({className:h?"has-inline-svg":""}),I=x&&happyprimeData?.themeUrl?`${happyprimeData.themeUrl}/${x}`:"",U=x&&x.toLowerCase().endsWith(".svg"),B=y.find(e=>e.slug===s),$=B?.width||"",j=B?.height||"";let A,L=null;if(h&&v){const e=[];$?e.push(`width: ${$}`):$||e.push("width: 100%"),j&&e.push(`height: ${j}`);const t=e.join("; "),l=v.match(/<svg([^>]*)>/);if(l){const e=l[1].match(/style="([^"]*)"/);if(e){const l=e[1];L=v.replace(/<svg([^>]*)>/,e=>e.replace(/style="[^"]*"/,`style="${l}; ${t}"`))}else L=v.replace(/<svg([^>]*)>/,`<svg$1 style="${t}">`)}}if(I)if(h&&L)A=g?React.createElement("a",{href:g,target:p,rel:b,dangerouslySetInnerHTML:{__html:L}}):null;else{const e={};$&&(e.width=$),j&&(e.height=j);const t=React.createElement("img",{src:I,alt:C?.alt||(0,a.__)("Theme image preview","theme-image-block"),style:Object.keys(e).length>0?e:void 0});A=g?React.createElement("a",{href:g,target:p,rel:b},t):t}else A=React.createElement(l.Placeholder,{icon:React.createElement(e.BlockIcon,{icon:c}),label:(0,a.__)("Theme Image","theme-image-block"),instructions:(0,a.__)("Select an image from the block settings","theme-image-block")});const O=h&&L&&!g?{...V,dangerouslySetInnerHTML:{__html:L}}:V;return React.createElement(React.Fragment,null,I&&React.createElement(e.BlockControls,{group:"block"},React.createElement(l.ToolbarButton,{icon:"admin-links",label:(0,a.__)("Link","theme-image-block"),onClick:()=>f(!0),isActive:!!g}),g&&React.createElement(l.ToolbarButton,{icon:"editor-unlink",label:(0,a.__)("Unlink","theme-image-block"),onClick:()=>{o({linkUrl:"",linkTarget:"",linkRel:""})}}),React.createElement(l.ToolbarButton,{icon:m,label:(0,a.__)("Add caption","theme-image-block"),onClick:()=>o({showCaption:!u}),isActive:u})),R&&React.createElement(l.Popover,{position:"bottom center",onClose:()=>f(!1),anchor:document.querySelector(".wp-block-happyprime-theme-image")},React.createElement(e.__experimentalLinkControl,{value:{url:g,opensInNewTab:"_blank"===p,nofollow:b?.includes("nofollow")},onChange:e=>{const t=[];e?.opensInNewTab&&t.push("noopener","noreferrer"),e?.nofollow&&t.push("nofollow"),o({linkUrl:e?.url||"",linkTarget:e?.opensInNewTab?"_blank":"",linkRel:t.join(" ")})},onRemove:()=>{o({linkUrl:"",linkTarget:"",linkRel:""}),f(!1)},settings:[{id:"opensInNewTab",title:(0,a.__)("Open in new tab","theme-image-block")},{id:"nofollow",title:(0,a.__)("Mark as nofollow","theme-image-block")}]})),React.createElement(e.InspectorControls,null,React.createElement(l.PanelBody,{title:(0,a.__)("Settings","theme-image-block"),initialOpen:!0},React.createElement(l.SelectControl,{label:(0,a.__)("Theme Image","theme-image-block"),value:i,options:T,onChange:e=>{o({themeImage:e,imageSize:"original"})},help:(0,a.__)("Select a registered theme image.","theme-image-block")}),C&&C.variations&&Object.keys(C.variations).length>0&&React.createElement(l.SelectControl,{label:(0,a.__)("Variation","theme-image-block"),value:r,options:E,onChange:e=>o({imageSize:e}),help:(0,a.__)("Select the image variation.","theme-image-block")}),React.createElement(l.SelectControl,{label:(0,a.__)("Style","theme-image-block"),value:s,options:[{value:"",label:(0,a.__)("Default","theme-image-block")},...y.map(e=>({value:e.slug,label:e.name}))],onChange:e=>o({imageStyle:e}),help:(0,a.__)("Select a registered style to apply.","theme-image-block")}),U&&React.createElement(l.ToggleControl,{label:(0,a.__)("Inline SVG","theme-image-block"),checked:h,onChange:e=>o({inlineSVG:e}),help:(0,a.__)("Render SVG code inline.","theme-image-block")}),!d&&React.createElement(l.TextControl,{label:(0,a.__)("Alt Text","theme-image-block"),value:_,onChange:e=>o({altText:e}),placeholder:C?.alt||"",help:(0,a.__)("Alternative text for the image. Leave empty to use the registered default.","theme-image-block")}),React.createElement(l.ToggleControl,{label:(0,a.__)("Omit alt text","theme-image-block"),checked:d,onChange:e=>o({omitAltText:e}),help:(0,a.__)("Output empty alt text, even if a registered value exists.","theme-image-block")}))),React.createElement("figure",O,A,I&&u&&React.createElement(e.RichText,{tagName:"figcaption",placeholder:C?.caption||(0,a.__)("Add caption…","theme-image-block"),value:k,onChange:e=>o({caption:e}),allowedFormats:["core/bold","core/italic","core/link"]})))}})})();
     1(()=>{"use strict";const e=window.wp.blockEditor,t=window.wp.blocks,l=window.wp.components,a=window.wp.i18n,n=window.wp.element,o=window.wp.primitives,i=window.ReactJSXRuntime;var c=(0,i.jsx)(o.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(o.Path,{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5 4.5h14c.3 0 .5.2.5.5v8.4l-3-2.9c-.3-.3-.8-.3-1 0L11.9 14 9 12c-.3-.2-.6-.2-.8 0l-3.6 2.6V5c-.1-.3.1-.5.4-.5zm14 15H5c-.3 0-.5-.2-.5-.5v-2.4l4.1-3 3 1.9c.3.2.7.2.9-.1L16 12l3.5 3.4V19c0 .3-.2.5-.5.5z"})}),m=(0,i.jsx)(o.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(o.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M6 5.5h12a.5.5 0 0 1 .5.5v12a.5.5 0 0 1-.5.5H6a.5.5 0 0 1-.5-.5V6a.5.5 0 0 1 .5-.5ZM4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6Zm4 10h2v-1.5H8V16Zm5 0h-2v-1.5h2V16Zm1 0h2v-1.5h-2V16Z"})});const r=JSON.parse('{"UU":"happyprime/theme-image"}');(0,t.registerBlockType)(r.UU,{edit:function({attributes:t,setAttributes:o}){const{themeImage:i,imageSize:r,imageStyle:s,inlineSVG:h,linkUrl:g,linkTarget:p,linkRel:b,caption:k,showCaption:_,altText:u,omitAltText:d}=t,[v,w]=(0,n.useState)(null),[R,f]=(0,n.useState)(!1),y=(0,n.useRef)(),S=happyprime_themeimageblock_data?.images||[],E=happyprime_themeimageblock_data?.styles||[],C=[{value:"",label:(0,a.__)("Select an image","theme-image-block")},...S.map(e=>({value:e.slug,label:e.label}))],T=S.find(e=>e.slug===i),x=[{value:"original",label:(0,a.__)("Original","theme-image-block")}];T&&T.variations&&Object.keys(T.variations).forEach(e=>{const t=T.variations[e];x.push({value:e,label:t.name||e})});let V=T?.value||"";T&&"original"!==r&&T.variations&&T.variations[r]&&(V=T.variations[r].path),(0,n.useEffect)(()=>{if(h&&V&&V.toLowerCase().endsWith(".svg")){const e=`${happyprime_themeimageblock_data.themeUrl}/${V}`;fetch(e).then(e=>e.text()).then(e=>{w(e)}).catch(e=>{console.error("Failed to fetch SVG:",e),w(null)})}else w(null)},[h,V]);const I=(0,e.useBlockProps)({ref:y,className:h?"has-inline-svg":""}),U=V&&happyprime_themeimageblock_data?.themeUrl?`${happyprime_themeimageblock_data.themeUrl}/${V}`:"",B=V&&V.toLowerCase().endsWith(".svg"),$=E.find(e=>e.slug===s),j=$?.width||"",A=$?.height||"";let O,L=null;if(h&&v){const e=[];j&&e.push(`width: ${j}`),A&&e.push(`height: ${A}`);const t=e.join("; "),l=v.match(/<svg([^>]*)>/);if(l){const e=l[1].match(/style="([^"]*)"/);if(e){const l=e[1];L=v.replace(/<svg([^>]*)>/,e=>e.replace(/style="[^"]*"/,`style="${l}; ${t}"`))}else L=v.replace(/<svg([^>]*)>/,`<svg$1 style="${t}">`)}}if(U)if(h&&L){const e=React.createElement("span",{dangerouslySetInnerHTML:{__html:L},style:{display:"contents"}});O=g?React.createElement("a",{href:g,target:p,rel:b},e):e}else{const e={};j&&(e.width=j),A&&(e.height=A);const t=d?"":u||T?.alt||"",l=React.createElement("img",{src:U,alt:t,style:Object.keys(e).length>0?e:void 0});O=g?React.createElement("a",{href:g,target:p,rel:b},l):l}else O=React.createElement(l.Placeholder,{icon:React.createElement(e.BlockIcon,{icon:c}),label:(0,a.__)("Theme Image","theme-image-block"),instructions:(0,a.__)("Select an image from the block settings","theme-image-block")});const G=I;return React.createElement(React.Fragment,null,U&&React.createElement(e.BlockControls,{group:"block"},React.createElement(l.ToolbarButton,{icon:"admin-links",label:(0,a.__)("Link","theme-image-block"),onClick:()=>f(!0),isActive:!!g}),g&&React.createElement(l.ToolbarButton,{icon:"editor-unlink",label:(0,a.__)("Unlink","theme-image-block"),onClick:()=>{o({linkUrl:"",linkTarget:"",linkRel:""})}}),React.createElement(l.ToolbarButton,{icon:m,label:(0,a.__)("Add caption","theme-image-block"),onClick:()=>o({showCaption:!_}),isActive:_})),R&&React.createElement(l.Popover,{position:"bottom center",onClose:()=>f(!1),anchor:y.current},React.createElement(e.__experimentalLinkControl,{value:{url:g,opensInNewTab:"_blank"===p,nofollow:b?.includes("nofollow")},onChange:e=>{const t=[];e?.opensInNewTab&&t.push("noopener","noreferrer"),e?.nofollow&&t.push("nofollow"),o({linkUrl:e?.url||"",linkTarget:e?.opensInNewTab?"_blank":"",linkRel:t.join(" ")})},onRemove:()=>{o({linkUrl:"",linkTarget:"",linkRel:""}),f(!1)},settings:[{id:"opensInNewTab",title:(0,a.__)("Open in new tab","theme-image-block")},{id:"nofollow",title:(0,a.__)("Mark as nofollow","theme-image-block")}]})),React.createElement(e.InspectorControls,null,React.createElement(l.PanelBody,{title:(0,a.__)("Settings","theme-image-block"),initialOpen:!0},React.createElement(l.SelectControl,{label:(0,a.__)("Theme Image","theme-image-block"),value:i,options:C,onChange:e=>{o({themeImage:e,imageSize:"original"})},help:(0,a.__)("Select a registered theme image.","theme-image-block")}),T&&T.variations&&Object.keys(T.variations).length>0&&React.createElement(l.SelectControl,{label:(0,a.__)("Variation","theme-image-block"),value:r,options:x,onChange:e=>o({imageSize:e}),help:(0,a.__)("Select the image variation.","theme-image-block")}),React.createElement(l.SelectControl,{label:(0,a.__)("Style","theme-image-block"),value:s,options:[{value:"",label:(0,a.__)("Default","theme-image-block")},...E.map(e=>({value:e.slug,label:e.name}))],onChange:e=>o({imageStyle:e}),help:(0,a.__)("Select a registered style to apply.","theme-image-block")}),B&&React.createElement(l.ToggleControl,{label:(0,a.__)("Inline SVG","theme-image-block"),checked:h,onChange:e=>o({inlineSVG:e}),help:(0,a.__)("Render SVG code inline.","theme-image-block")}),!d&&React.createElement(l.TextControl,{label:(0,a.__)("Alt Text","theme-image-block"),value:u,onChange:e=>o({altText:e}),placeholder:T?.alt||"",help:(0,a.__)("Alternative text for the image. Leave empty to use the registered default.","theme-image-block")}),React.createElement(l.ToggleControl,{label:(0,a.__)("Omit alt text","theme-image-block"),checked:d,onChange:e=>o({omitAltText:e}),help:(0,a.__)("Output empty alt text, even if a registered value exists.","theme-image-block")}))),React.createElement("figure",G,O,U&&_&&React.createElement(e.RichText,{tagName:"figcaption",placeholder:T?.caption||(0,a.__)("Add caption…","theme-image-block"),value:k,onChange:e=>o({caption:e}),allowedFormats:["core/bold","core/italic","core/link"]})))}})})();
  • theme-image-block/trunk/blocks/src/theme-image/block.json

    r3421447 r3465978  
    6666        }
    6767    },
    68     "textdomain": "happyprime",
     68    "textdomain": "theme-image-block",
    6969    "editorScript": "file:../../build/theme-image/index.js",
    7070    "style": "file:./style.css"
  • theme-image-block/trunk/blocks/src/theme-image/index.js

    r3421447 r3465978  
    2121} from '@wordpress/components';
    2222import { __ } from '@wordpress/i18n';
    23 import { useState, useEffect } from '@wordpress/element';
     23import { useState, useEffect, useRef } from '@wordpress/element';
    2424import { image, caption as captionIcon } from '@wordpress/icons';
    2525
     
    5353    const [svgContent, setSvgContent] = useState(null);
    5454    const [isEditingLink, setIsEditingLink] = useState(false);
     55    const blockRef = useRef();
    5556
    5657    // Get registered theme images and styles from localized data.
     
    105106            imagePath.toLowerCase().endsWith('.svg')
    106107        ) {
    107             const svgUrl = `${happyprimeData.themeUrl}/${imagePath}`;
     108            const svgUrl = `${happyprime_themeimageblock_data.themeUrl}/${imagePath}`;
    108109            fetch(svgUrl)
    109110                .then((response) => response.text())
     
    121122
    122123    const blockProps = useBlockProps({
     124        ref: blockRef,
    123125        className: inlineSVG ? 'has-inline-svg' : '',
    124126    });
    125127
    126128    const imageUrl =
    127         imagePath && happyprimeData?.themeUrl
    128             ? `${happyprimeData.themeUrl}/${imagePath}`
     129        imagePath && happyprime_themeimageblock_data?.themeUrl
     130            ? `${happyprime_themeimageblock_data.themeUrl}/${imagePath}`
    129131            : '';
    130132    const isSVG = imagePath && imagePath.toLowerCase().endsWith('.svg');
     
    144146        if (width) {
    145147            styles.push(`width: ${width}`);
    146         } else if (!width) {
    147             // Default width for editor preview when not specified.
    148             styles.push('width: 100%');
    149148        }
    150149        if (height) {
     
    194193        // For inline SVG, apply dangerouslySetInnerHTML to link or wrapper
    195194        // to match server-side structure without extra figure wrapper.
     195        const svgElement = (
     196            <span
     197                dangerouslySetInnerHTML={{ __html: processedSvg }}
     198                style={{ display: 'contents' }}
     199            />
     200        );
    196201        if (linkUrl) {
    197202            content = (
    198                 <a
    199                     href={linkUrl}
    200                     target={linkTarget}
    201                     rel={linkRel}
    202                     dangerouslySetInnerHTML={{ __html: processedSvg }}
    203                 />
     203                <a href={linkUrl} target={linkTarget} rel={linkRel}>
     204                    {svgElement}
     205                </a>
    204206            );
    205207        } else {
    206             // Will be applied to wrapper figure via blockProps below.
    207             content = null;
     208            content = svgElement;
    208209        }
    209210    } else {
     
    217218        }
    218219
     220        const editorAlt = omitAltText ? '' : altText || currentImage?.alt || '';
     221
    219222        const img = (
    220223            <img
    221224                src={imageUrl}
    222                 alt={
    223                     currentImage?.alt ||
    224                     __('Theme image preview', 'theme-image-block')
    225                 }
     225                alt={editorAlt}
    226226                style={
    227227                    Object.keys(imgStyles).length > 0 ? imgStyles : undefined
     
    238238    }
    239239
    240     // For inline SVG without link, apply HTML directly to wrapper.
    241     const wrapperProps =
    242         inlineSVG && processedSvg && !linkUrl
    243             ? {
    244                     ...blockProps,
    245                     dangerouslySetInnerHTML: { __html: processedSvg },
    246                 }
    247             : blockProps;
     240    const wrapperProps = blockProps;
    248241
    249242    return (
     
    273266                        icon={captionIcon}
    274267                        label={__('Add caption', 'theme-image-block')}
    275                         onClick={() => setAttributes({ showCaption: !showCaption })}
     268                        onClick={() =>
     269                            setAttributes({ showCaption: !showCaption })
     270                        }
    276271                        isActive={showCaption}
    277272                    />
     
    283278                    position="bottom center"
    284279                    onClose={() => setIsEditingLink(false)}
    285                     anchor={document.querySelector(
    286                         '.wp-block-happyprime-theme-image'
    287                     )}
     280                    anchor={blockRef.current}
    288281                >
    289282                    <LinkControl
  • theme-image-block/trunk/composer.json

    r3421447 r3465978  
    1414        }
    1515    },
     16    "repositories": [
     17        {
     18            "type": "package",
     19            "package": {
     20                "name": "phpcompatibility/php-compatibility",
     21                "type": "phpcodesniffer-standard",
     22                "version": "9.99.9",
     23                "source": {
     24                    "url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
     25                    "type": "git",
     26                    "reference": "9f7142356b5674164a6f6dbe12a7a1bcc632db21"
     27                }
     28            }
     29        }
     30    ],
    1631    "autoload": {
    1732        "psr-4": {
     
    2136    "require-dev": {
    2237        "happyprime/coding-standards": "*",
    23         "phpcompatibility/php-compatibility": "dev-develop as 9.99.99"
     38        "phpcompatibility/php-compatibility": "9.99.9"
    2439    },
    2540    "scripts": {
  • theme-image-block/trunk/readme.txt

    r3423224 r3465978  
    44Requires at least: 6.8
    55Tested up to: 6.9
    6 Stable tag: 1.1.0
     6Stable tag: 1.1.1
    77License: GPLv2 or later
    88Requires PHP: 7.4
     
    7676## Changelog
    7777
     78### 1.1.1
     79
     80* Prevent fatal error on activation.
     81* Improve HTML processing when rendering output.
     82* Fix reference to renamed global JavaScript variable.
     83* Fix textdomain mismatch.
     84* Improve support for multiple theme image blocks in one editor view.
     85
    7886### 1.1.0
    7987
  • theme-image-block/trunk/src/Block.php

    r3421447 r3465978  
    181181        if ( $link_url ) {
    182182            $content = '<a>' . $content . '</a>';
     183
     184            $html = new \WP_HTML_Tag_Processor( $content );
     185            if ( $html->next_tag( array( 'tag_name' => 'a' ) ) ) {
     186                $html->set_attribute( 'href', $link_url );
     187                if ( $link_target ) {
     188                    $html->set_attribute( 'target', $link_target );
     189                }
     190                if ( $link_rel ) {
     191                    $html->set_attribute( 'rel', $link_rel );
     192                }
     193            }
     194
     195            $content = $html->get_updated_html();
    183196        }
    184197
    185198        $html = new \WP_HTML_Tag_Processor( $content );
    186         if ( $html->next_tag( array( 'tag_name' => 'a' ) ) ) {
    187             $html->set_attribute( 'href', $link_url );
    188             if ( $link_target ) {
    189                 $html->set_attribute( 'target', $link_target );
    190             }
    191             if ( $link_rel ) {
    192                 $html->set_attribute( 'rel', $link_rel );
    193             }
    194         }
    195 
    196         // This seems to be the best way to rewind and seek again? Seems strange.
    197         $html = new \WP_HTML_Tag_Processor( $html->get_updated_html() );
    198199
    199200        if ( $html->next_tag( array( 'tag_name' => 'img' ) ) ) {
     
    218219        }
    219220
    220         $wrapper_attrs = array( 'class' => implode( ' ', $wrapper_classes ) );
     221        $wrapper_attrs = ! empty( $wrapper_classes )
     222            ? array( 'class' => implode( ' ', $wrapper_classes ) )
     223            : array();
    221224
    222225        return sprintf(
  • theme-image-block/trunk/theme-image-block.php

    r3421447 r3465978  
    33 * Plugin Name:  Theme Image Block
    44 * Description:  Use images from your theme as blocks in content.
    5  * Version:      1.1.0
     5 * Version:      1.1.1
    66 * Author:       Happy Prime
    77 * Author URI:   https://happyprime.co
Note: See TracChangeset for help on using the changeset viewer.