FEATURE FIX Changing icons injection behaviour and opting for and php exposed url to fix svg injection problem with non admin editors

This commit is contained in:
Nonimart 2025-12-04 10:22:29 +01:00
parent 42bc69f0af
commit 04bc117f64
12 changed files with 1122 additions and 903 deletions

View File

@ -20,7 +20,7 @@
"source": "html", "source": "html",
"selector": "h3" "selector": "h3"
}, },
"iconName": { "iconUrl": {
"type": "string", "type": "string",
"default": "key" "default": "key"
}, },

View File

@ -1 +1 @@
<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '5e5d7d1fc3323c17a47b'); <?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '8cdbe6d5e08fd9883c1a');

View File

@ -1,6 +1,6 @@
/*!**********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ /*!****************************************************************************************************************************************************************************************************************************************************!*\
!*** css ./node_modules/.pnpm/css-loader@6.11.0_webpack@5.99.9/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/.pnpm/postcss-loader@6.2.1_postcss@8.5.3_webpack@5.99.9/node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/.pnpm/sass-loader@12.6.0_sass@1.89.0_webpack@5.99.9/node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/editor.scss ***! !*** css ../../node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!../../node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!../../node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/editor.scss ***!
\**********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ \****************************************************************************************************************************************************************************************************************************************************/
/** /**
* The following styles get applied inside the editor only. * The following styles get applied inside the editor only.
* *

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ /*!***************************************************************************************************************************************************************************************************************************************************!*\
!*** css ./node_modules/.pnpm/css-loader@6.11.0_webpack@5.99.9/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/.pnpm/postcss-loader@6.2.1_postcss@8.5.3_webpack@5.99.9/node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/.pnpm/sass-loader@12.6.0_sass@1.89.0_webpack@5.99.9/node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/style.scss ***! !*** css ../../node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!../../node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!../../node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/style.scss ***!
\*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ \***************************************************************************************************************************************************************************************************************************************************/
/** /**
* The following styles get applied both on the front of your site * The following styles get applied both on the front of your site
* and in the editor. * and in the editor.

View File

@ -0,0 +1,9 @@
<?php
add_action('enqueue_block_editor_assets', function () {
wp_localize_script(
'homegrade-content-blocks-highlight-editor-script',
'HOMEGRADE_HIGHLIGHT',
['iconsBaseUrl' => plugin_dir_url(__FILE__) . 'src/img/']
);
});

View File

@ -20,7 +20,7 @@
"source": "html", "source": "html",
"selector": "h3" "selector": "h3"
}, },
"iconName": { "iconUrl": {
"type": "string", "type": "string",
"default": "key" "default": "key"
}, },

View File

@ -1,111 +1,288 @@
import { createBlock } from "@wordpress/blocks"; import { createBlock } from '@wordpress/blocks';
import { useBlockProps, RichText, InnerBlocks } from "@wordpress/block-editor"; import { useBlockProps, RichText, InnerBlocks } from '@wordpress/block-editor';
import { useSelect } from "@wordpress/data"; import { useSelect } from '@wordpress/data';
import keyIcon from "./img/icon_key.svg"; import keyIcon from './img/icon_key.svg';
import chainIcon from "./img/icon_chain.svg"; import chainIcon from './img/icon_chain.svg';
import houseIcon from "./img/icon_house.svg"; import houseIcon from './img/icon_house.svg';
import bulbIcon from "./img/icon_bulb.svg"; import bulbIcon from './img/icon_bulb.svg';
import warningIcon from "./img/icon_warning.svg"; import warningIcon from './img/icon_warning.svg';
import acousticIcon from "./img/icon_acoustic.svg"; import acousticIcon from './img/icon_acoustic.svg';
import documentationIcon from "./img/icon_documentation.svg"; import documentationIcon from './img/icon_documentation.svg';
import notificationIcon from "./img/icon_notification.svg"; import notificationIcon from './img/icon_notification.svg';
import searchIcon from "./img/icon_search.svg"; import searchIcon from './img/icon_search.svg';
import infoIcon from "./img/icon_info.svg"; import infoIcon from './img/icon_info.svg';
import tipIcon from "./img/icon_tip.svg"; import tipIcon from './img/icon_tip.svg';
import euroIcon from "./img/icon_euro.svg"; import euroIcon from './img/icon_euro.svg';
const v1 = { // v2 — prior version (icons imported in JS, no persistent iconUrl attribute)
const v2 = {
attributes: { attributes: {
title: { title: {
type: "string", type: 'string',
source: "html", source: 'html',
selector: "h3", selector: 'h3',
}, },
iconName: { iconName: {
type: "string", type: 'string',
default: "key", default: 'key',
}, },
hasTitle: { hasTitle: {
type: "boolean", type: 'boolean',
default: true, default: true,
}, },
hasTitleIcon: { hasIcon: {
type: "boolean", type: 'boolean',
default: true, default: true,
}, },
hasLogo: { hasLogo: {
type: "boolean", type: 'boolean',
default: false, default: false,
}, },
logoId: { logoId: {
type: "number", type: 'number',
}, },
logoAlt: { logoAlt: {
type: "string", type: 'string',
}, },
logoUrl: { logoUrl: {
type: "string", type: 'string',
}, },
variant: { variant: {
type: "string", type: 'string',
default: "classic", default: 'classic',
},
iconPosition: {
type: 'string',
default: 'top',
},
// Read historical <img src> to ensure the deprecated save matches exactly
iconUrl: {
type: 'string',
source: 'attribute',
selector: '.icon .icon__image',
attribute: 'src',
}, },
}, },
save({ attributes }) { save({ attributes }) {
const { const {
title, title,
iconName, iconName,
hasTitle, hasTitle,
hasTitleIcon, hasIcon,
hasLogo, hasLogo,
logoId,
logoAlt, logoAlt,
logoUrl, logoUrl,
variant, variant,
iconPosition,
iconUrl,
} = attributes; } = attributes;
function getIconPicture() { function getIconPicture() {
switch (iconName) { switch (iconName) {
case "key": case 'key':
return keyIcon;
case 'chain':
return chainIcon;
case 'house':
return houseIcon;
case 'bulb':
return bulbIcon;
case 'warning':
return warningIcon;
case 'acoustic':
return acousticIcon;
case 'documentation':
return documentationIcon;
case 'notification':
return notificationIcon;
case 'search':
return searchIcon;
case 'info':
return infoIcon;
case 'tip':
return tipIcon;
case 'euro':
return euroIcon;
default:
return '';
}
}
// Use exact stored src when present for perfect match
const iconPicture = iconUrl || getIconPicture();
return (
<section
{...useBlockProps.save({
className: `homegrade-blocks-highlight ${
variant ? `homegrade-blocks-highlight--${variant}` : ''
}`,
})}
>
{hasTitle && (
<div
className={`homegrade-blocks-highlight__titling ${
!hasIcon ? 'homegrade-blocks-highlight__titling--has-no-icon' : ''
}`}
>
{hasIcon && iconPosition === 'top' && (
<div className="icon">
<img className="icon__image" src={iconPicture} alt="" />
</div>
)}
<RichText.Content
tagName="h3"
value={title}
className="homegrade-blocks-highlight__block-title"
/>
</div>
)}
<div className="homegrade-blocks-highlight__content">
{hasIcon && iconPosition === 'side' && !hasTitle && (
<div className="icon">
<img src={iconPicture} alt="" />
</div>
)}
<div className="homegrade-blocks-highlight__content__innerblocks">
<InnerBlocks.Content />
</div>
{hasLogo && logoUrl && (
<div className="homegrade-blocks-highlight__logo">
<img src={logoUrl} alt={logoAlt} />
</div>
)}
</div>
</section>
);
},
migrate(attributes) {
// Compute iconUrl from iconName for the new version (stored attribute),
// using file URL mapping so next save writes http(s) src instead of data URI.
const ICON_FILES = {
key: 'icon_key.svg',
chain: 'icon_chain.svg',
house: 'icon_house.svg',
bulb: 'icon_bulb.svg',
warning: 'icon_warning.svg',
acoustic: 'icon_acoustic.svg',
documentation: 'icon_documentation.svg',
notification: 'icon_notification.svg',
search: 'icon_search.svg',
info: 'icon_info.svg',
tip: 'icon_tip.svg',
euro: 'icon_euro.svg',
};
let iconUrl = '';
const filename = ICON_FILES[attributes.iconName];
if (filename) {
// Prefer PHP-exposed public base URL when available (robust in all environments)
const baseUrl =
typeof HOMEGRADE_HIGHLIGHT !== 'undefined' && HOMEGRADE_HIGHLIGHT?.iconsBaseUrl
? HOMEGRADE_HIGHLIGHT.iconsBaseUrl
: '';
if (baseUrl) {
iconUrl = baseUrl + filename;
} else {
// Fallback: rely on bundler URL resolution
try {
iconUrl = new URL(`./img/${filename}`, import.meta.url).toString();
} catch (e) {
iconUrl = '';
}
}
}
return {
...attributes,
iconUrl,
};
},
};
const v1 = {
attributes: {
title: {
type: 'string',
source: 'html',
selector: 'h3',
},
iconName: {
type: 'string',
default: 'key',
},
hasTitle: {
type: 'boolean',
default: true,
},
hasTitleIcon: {
type: 'boolean',
default: true,
},
hasLogo: {
type: 'boolean',
default: false,
},
logoId: {
type: 'number',
},
logoAlt: {
type: 'string',
},
logoUrl: {
type: 'string',
},
variant: {
type: 'string',
default: 'classic',
},
},
save({ attributes }) {
const { title, iconName, hasTitle, hasTitleIcon, hasLogo, logoId, logoAlt, logoUrl, variant } =
attributes;
function getIconPicture() {
switch (iconName) {
case 'key':
return keyIcon; return keyIcon;
case "chain": case 'chain':
return chainIcon; return chainIcon;
case "house": case 'house':
return houseIcon; return houseIcon;
case "bulb": case 'bulb':
return bulbIcon; return bulbIcon;
case "warning": case 'warning':
return warningIcon; return warningIcon;
case "acoustic": case 'acoustic':
return acousticIcon; return acousticIcon;
case "documentation": case 'documentation':
return documentationIcon; return documentationIcon;
case "notification": case 'notification':
return notificationIcon; return notificationIcon;
case "search": case 'search':
return searchIcon; return searchIcon;
case "info": case 'info':
return infoIcon; return infoIcon;
case "tip": case 'tip':
return tipIcon; return tipIcon;
case "euro": case 'euro':
return euroIcon; return euroIcon;
default: default:
return ""; return '';
} }
} }
const iconPicture = getIconPicture(); const iconPicture = getIconPicture();
@ -114,16 +291,14 @@ const v1 = {
<section <section
{...useBlockProps.save({ {...useBlockProps.save({
className: `homegrade-blocks-highlight ${ className: `homegrade-blocks-highlight ${
variant ? `homegrade-blocks-highlight--${variant}` : "" variant ? `homegrade-blocks-highlight--${variant}` : ''
}`, }`,
})} })}
> >
{hasTitle && ( {hasTitle && (
<div <div
className={`homegrade-blocks-highlight__titling ${ className={`homegrade-blocks-highlight__titling ${
!hasTitleIcon !hasTitleIcon ? 'homegrade-blocks-highlight__titling--has-no-icon' : ''
? "homegrade-blocks-highlight__titling--has-no-icon"
: ""
}`} }`}
> >
{hasTitleIcon && ( {hasTitleIcon && (
@ -159,4 +334,4 @@ const v1 = {
}, },
}; };
export default [v1]; export default [v2KSES, v2, v1];

View File

@ -1,17 +1,5 @@
import { __ } from "@wordpress/i18n"; import { __ } from '@wordpress/i18n';
import "./editor.scss"; import './editor.scss';
import keyIcon from "./img/icon_key.svg";
import chainIcon from "./img/icon_chain.svg";
import houseIcon from "./img/icon_house.svg";
import bulbIcon from "./img/icon_bulb.svg";
import warningIcon from "./img/icon_warning.svg";
import acousticIcon from "./img/icon_acoustic.svg";
import documentationIcon from "./img/icon_documentation.svg";
import notificationIcon from "./img/icon_notification.svg";
import searchIcon from "./img/icon_search.svg";
import infoIcon from "./img/icon_info.svg";
import tipIcon from "./img/icon_tip.svg";
import euroIcon from "./img/icon_euro.svg";
import { import {
RichText, RichText,
@ -20,9 +8,9 @@ import {
InnerBlocks, InnerBlocks,
InspectorControls, InspectorControls,
MediaReplaceFlow, MediaReplaceFlow,
} from "@wordpress/block-editor"; } from '@wordpress/block-editor';
import { trash } from "@wordpress/icons"; import { trash } from '@wordpress/icons';
import { import {
Button, Button,
ToolbarButton, ToolbarButton,
@ -31,12 +19,13 @@ import {
__experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOption as ToggleGroupControlOption, __experimentalToggleGroupControlOption as ToggleGroupControlOption,
RadioControl, RadioControl,
} from "@wordpress/components"; } from '@wordpress/components';
export default function Edit({ attributes, setAttributes }) { export default function Edit({ attributes, setAttributes }) {
const { const {
title, title,
iconName, iconName,
iconUrl,
hasTitle, hasTitle,
hasIcon, hasIcon,
hasLogo, hasLogo,
@ -47,51 +36,28 @@ export default function Edit({ attributes, setAttributes }) {
iconPosition, iconPosition,
} = attributes; } = attributes;
function getIconPicture() { const ICON_FILES = {
switch (iconName) { key: 'icon_key.svg',
case "key": chain: 'icon_chain.svg',
return keyIcon; house: 'icon_house.svg',
bulb: 'icon_bulb.svg',
case "chain": warning: 'icon_warning.svg',
return chainIcon; acoustic: 'icon_acoustic.svg',
documentation: 'icon_documentation.svg',
case "house": notification: 'icon_notification.svg',
return houseIcon; search: 'icon_search.svg',
info: 'icon_info.svg',
case "bulb": tip: 'icon_tip.svg',
return bulbIcon; euro: 'icon_euro.svg',
};
case "warning": const getIconUrl = (iconName) => {
return warningIcon; if (!iconName) return '';
return HOMEGRADE_HIGHLIGHT.iconsBaseUrl + ICON_FILES[iconName];
case "acoustic": };
return acousticIcon;
case "documentation":
return documentationIcon;
case "notification":
return notificationIcon;
case "search":
return searchIcon;
case "info":
return infoIcon;
case "tip":
return tipIcon;
case "euro":
return euroIcon;
default:
return "";
}
}
function onIconChange(newIconName) { function onIconChange(newIconName) {
setAttributes({ iconName: newIconName }); const newIconUrl = getIconUrl(newIconName);
setAttributes({ iconName: newIconName, iconUrl: newIconUrl });
} }
function onTitleChange(title) { function onTitleChange(title) {
setAttributes({ title }); setAttributes({ title });
@ -133,8 +99,6 @@ export default function Edit({ attributes, setAttributes }) {
}); });
} }
let iconPicture = getIconPicture();
function handleIconPositionChange(newPosition) { function handleIconPositionChange(newPosition) {
setAttributes({ iconPosition: newPosition }); setAttributes({ iconPosition: newPosition });
} }
@ -143,7 +107,7 @@ export default function Edit({ attributes, setAttributes }) {
<> <>
<InspectorControls> <InspectorControls>
<PanelBody <PanelBody
title={__("Variantes", "homegrade-blocks__texte-fonctionnel")} title={__('Variantes', 'homegrade-blocks__texte-fonctionnel')}
initialOpen={true} initialOpen={true}
> >
<ToggleGroupControl <ToggleGroupControl
@ -156,16 +120,8 @@ export default function Edit({ attributes, setAttributes }) {
<ToggleGroupControlOption label="Warning" value="warning" /> <ToggleGroupControlOption label="Warning" value="warning" />
<ToggleGroupControlOption label="Gris" value="gray" /> <ToggleGroupControlOption label="Gris" value="gray" />
</ToggleGroupControl> </ToggleGroupControl>
<ToggleControl <ToggleControl label="Afficher le titre" checked={hasTitle} onChange={onHasTitleChange} />
label="Afficher le titre" <ToggleControl label="Afficher une Icone" checked={hasIcon} onChange={onhasIconChange} />
checked={hasTitle}
onChange={onHasTitleChange}
/>
<ToggleControl
label="Afficher une Icone"
checked={hasIcon}
onChange={onhasIconChange}
/>
{hasIcon && ( {hasIcon && (
<RadioControl <RadioControl
@ -174,30 +130,26 @@ export default function Edit({ attributes, setAttributes }) {
onChange={handleIconPositionChange} onChange={handleIconPositionChange}
options={[ options={[
{ {
label: "Avant le titre", label: 'Avant le titre',
value: "top", value: 'top',
description: "Seulement lorsque le titre est ACTIVÉ", description: 'Seulement lorsque le titre est ACTIVÉ',
}, },
{ {
label: "Coté", label: 'Coté',
value: "side", value: 'side',
disabled: hasTitle, disabled: hasTitle,
description: "Seulement lorsque le titre est DÉSACTIVÉ", description: 'Seulement lorsque le titre est DÉSACTIVÉ',
}, },
]} ]}
selected={iconPosition} selected={iconPosition}
/> />
)} )}
<ToggleControl <ToggleControl label="Attacher un logo" checked={hasLogo} onChange={onHasLogoChange} />
label="Attacher un logo"
checked={hasLogo}
onChange={onHasLogoChange}
/>
</PanelBody> </PanelBody>
{hasLogo && ( {hasLogo && (
<PanelBody <PanelBody
className="homegrade-blocks-highlight__panel-body" className="homegrade-blocks-highlight__panel-body"
title={__("Logo", "homegrade-blocks")} title={__('Logo', 'homegrade-blocks')}
> >
{logoUrl && <img src={logoUrl} alt={logoAlt} />} {logoUrl && <img src={logoUrl} alt={logoAlt} />}
@ -205,13 +157,13 @@ export default function Edit({ attributes, setAttributes }) {
<MediaReplaceFlow <MediaReplaceFlow
mediaId={logoId} mediaId={logoId}
mediaUrl={logoUrl} mediaUrl={logoUrl}
allowedTypes={["image"]} allowedTypes={['image']}
accept="image/*" accept="image/*"
onSelect={setLogoAttributes} onSelect={setLogoAttributes}
name={ name={
!logoUrl !logoUrl
? __("Ajouter un Logo", "homegrade-blocks") ? __('Ajouter un Logo', 'homegrade-blocks')
: __("Remplacer", "homegrade-blocks") : __('Remplacer', 'homegrade-blocks')
} }
/> />
{logoUrl && ( {logoUrl && (
@ -231,130 +183,127 @@ export default function Edit({ attributes, setAttributes }) {
</InspectorControls> </InspectorControls>
<BlockControls> <BlockControls>
<ToolbarButton <ToolbarButton
title={"Clé"} title={'Clé'}
icon={"admin-network"} icon={'admin-network'}
isActive={iconName === "key"} isActive={iconName === 'key'}
onClick={() => onIconChange("key")} onClick={() => onIconChange('key')}
/> />
<ToolbarButton <ToolbarButton
title={"Lien"} title={'Lien'}
icon={"admin-links"} icon={'admin-links'}
isActive={iconName === "chain"} isActive={iconName === 'chain'}
onClick={() => onIconChange("chain")} onClick={() => onIconChange('chain')}
/> />
<ToolbarButton <ToolbarButton
title={"Homegrade"} title={'Homegrade'}
icon={"admin-home"} icon={'admin-home'}
isActive={iconName === "house"} isActive={iconName === 'house'}
onClick={() => onIconChange("house")} onClick={() => onIconChange('house')}
/> />
<ToolbarButton <ToolbarButton
title={"Inspiration"} title={'Inspiration'}
icon={"lightbulb"} icon={'lightbulb'}
isActive={iconName === "bulb"} isActive={iconName === 'bulb'}
onClick={() => onIconChange("bulb")} onClick={() => onIconChange('bulb')}
/> />
<ToolbarButton <ToolbarButton
title={"Attention"} title={'Attention'}
icon={"warning"} icon={'warning'}
isActive={iconName === "warning"} isActive={iconName === 'warning'}
onClick={() => onIconChange("warning")} onClick={() => onIconChange('warning')}
/> />
<ToolbarButton <ToolbarButton
title={"Acoustique"} title={'Acoustique'}
icon={"controls-volumeon"} icon={'controls-volumeon'}
isActive={iconName === "acoustic"} isActive={iconName === 'acoustic'}
onClick={() => onIconChange("acoustic")} onClick={() => onIconChange('acoustic')}
/> />
<ToolbarButton <ToolbarButton
title={"Documentation"} title={'Documentation'}
icon={"book-alt"} icon={'book-alt'}
isActive={iconName === "documentation"} isActive={iconName === 'documentation'}
onClick={() => onIconChange("documentation")} onClick={() => onIconChange('documentation')}
/> />
<ToolbarButton <ToolbarButton
title={"Recherche"} title={'Recherche'}
icon={"search"} icon={'search'}
isActive={iconName === "search"} isActive={iconName === 'search'}
onClick={() => onIconChange("search")} onClick={() => onIconChange('search')}
/> />
<ToolbarButton <ToolbarButton
title={"Notification"} title={'Notification'}
icon={"bell"} icon={'bell'}
isActive={iconName === "notification"} isActive={iconName === 'notification'}
onClick={() => onIconChange("notification")} onClick={() => onIconChange('notification')}
/> />
<ToolbarButton <ToolbarButton
title={"Info"} title={'Info'}
icon={"info"} icon={'info'}
isActive={iconName === "info"} isActive={iconName === 'info'}
onClick={() => onIconChange("info")} onClick={() => onIconChange('info')}
/> />
<ToolbarButton <ToolbarButton
title={"Euro"} title={'Euro'}
icon={"money-alt"} icon={'money-alt'}
isActive={iconName === "euro"} isActive={iconName === 'euro'}
onClick={() => onIconChange("euro")} onClick={() => onIconChange('euro')}
/> />
<ToolbarButton <ToolbarButton
title={"Astuce"} title={'Astuce'}
icon={"thumbs-up"} icon={'thumbs-up'}
isActive={iconName === "tip"} isActive={iconName === 'tip'}
onClick={() => onIconChange("tip")} onClick={() => onIconChange('tip')}
/> />
</BlockControls> </BlockControls>
<section <section
{...useBlockProps({ {...useBlockProps({
className: `homegrade-blocks-highlight ${ className: `homegrade-blocks-highlight ${
variant ? `homegrade-blocks-highlight--${variant}` : "" variant ? `homegrade-blocks-highlight--${variant}` : ''
}`, }`,
})} })}
> >
{hasTitle && ( {hasTitle && (
<div <div
className={`homegrade-blocks-highlight__titling ${ className={`homegrade-blocks-highlight__titling ${
!hasIcon ? "homegrade-blocks-highlight__titling--has-no-icon" : "" !hasIcon ? 'homegrade-blocks-highlight__titling--has-no-icon' : ''
}`} }`}
> >
{hasIcon && iconPosition === "top" && ( {hasIcon && iconPosition === 'top' && (
<div className="icon"> <div className="icon">
<img src={iconPicture} alt="" /> <img className="icon__image" src={iconUrl} alt="" />
</div> </div>
)} )}
<RichText <RichText
className="homegrade-blocks-highlight__block-title" className="homegrade-blocks-highlight__block-title"
onChange={onTitleChange} onChange={onTitleChange}
value={title} value={title}
placeholder={__( placeholder={__('Insérez un titre', 'homegrade-blocks__texte-fonctionnel')}
"Insérez un titre",
"homegrade-blocks__texte-fonctionnel"
)}
tagName="h3" tagName="h3"
allowedFormats={[]} allowedFormats={[]}
/> />
</div> </div>
)} )}
<div className="homegrade-blocks-highlight__content"> <div className="homegrade-blocks-highlight__content">
{hasIcon && iconPosition === "side" && !hasTitle && ( {hasIcon && iconPosition === 'side' && !hasTitle && (
<div className="icon"> <div className="icon">
<img src={iconPicture} alt="" /> <img className="icon__image" src={iconUrl} alt="" />
</div> </div>
)} )}
<div className="homegrade-blocks-highlight__content__innerblocks"> <div className="homegrade-blocks-highlight__content__innerblocks">
<InnerBlocks <InnerBlocks
allowedBlocks={[ allowedBlocks={[
"core/paragraph", 'core/paragraph',
"core/list", 'core/list',
"core/buttons", 'core/buttons',
"core/button", 'core/button',
"core/colums", 'core/colums',
"core/colum", 'core/colum',
"homegrade-content-blocks/text-image", 'homegrade-content-blocks/text-image',
"homegrade-content-blocks/content-heading", 'homegrade-content-blocks/content-heading',
"homegrade-content-blocks/staff-member", 'homegrade-content-blocks/staff-member',
]} ]}
template={[["core/paragraph"]]} template={[['core/paragraph']]}
/> />
</div> </div>
@ -364,13 +313,13 @@ export default function Edit({ attributes, setAttributes }) {
<MediaReplaceFlow <MediaReplaceFlow
mediaId={logoId} mediaId={logoId}
mediaUrl={logoUrl} mediaUrl={logoUrl}
allowedTypes={["image"]} allowedTypes={['image']}
accept="image/*" accept="image/*"
onSelect={setLogoAttributes} onSelect={setLogoAttributes}
name={ name={
!logoUrl !logoUrl
? __("Ajouter Logo", "homegrade-blocks") ? __('Ajouter Logo', 'homegrade-blocks')
: __("Remplacer", "homegrade-blocks") : __('Remplacer', 'homegrade-blocks')
} }
/> />
)} )}

View File

@ -1,22 +1,11 @@
import { useBlockProps, RichText, InnerBlocks } from "@wordpress/block-editor"; import { useBlockProps, RichText, InnerBlocks } from '@wordpress/block-editor';
import { __ } from "@wordpress/i18n"; import { __ } from '@wordpress/i18n';
import { useSelect, useDispatch } from "@wordpress/data"; // pour les querry import { useSelect, useDispatch } from '@wordpress/data'; // pour les querry
import keyIcon from "./img/icon_key.svg";
import chainIcon from "./img/icon_chain.svg";
import houseIcon from "./img/icon_house.svg";
import bulbIcon from "./img/icon_bulb.svg";
import warningIcon from "./img/icon_warning.svg";
import acousticIcon from "./img/icon_acoustic.svg";
import documentationIcon from "./img/icon_documentation.svg";
import notificationIcon from "./img/icon_notification.svg";
import searchIcon from "./img/icon_search.svg";
import infoIcon from "./img/icon_info.svg";
import tipIcon from "./img/icon_tip.svg";
import euroIcon from "./img/icon_euro.svg";
export default function save({ attributes }) { export default function save({ attributes }) {
const { const {
title, title,
iconUrl,
iconName, iconName,
hasTitle, hasTitle,
hasIcon, hasIcon,
@ -26,67 +15,51 @@ export default function save({ attributes }) {
logoUrl, logoUrl,
iconPosition, iconPosition,
} = attributes; } = attributes;
function getIconPicture() {
switch (iconName) {
case "key":
return keyIcon;
case "chain": const ICON_FILES = {
return chainIcon; key: 'icon_key.svg',
chain: 'icon_chain.svg',
case "house": house: 'icon_house.svg',
return houseIcon; bulb: 'icon_bulb.svg',
warning: 'icon_warning.svg',
case "bulb": acoustic: 'icon_acoustic.svg',
return bulbIcon; documentation: 'icon_documentation.svg',
notification: 'icon_notification.svg',
case "warning": search: 'icon_search.svg',
return warningIcon; info: 'icon_info.svg',
tip: 'icon_tip.svg',
case "acoustic": euro: 'icon_euro.svg',
return acousticIcon; };
const buildIconUrlFromName = () => {
case "documentation": const filename = ICON_FILES[iconName];
return documentationIcon; if (!filename) return '';
try {
case "notification": return new URL(`./img/${filename}`, import.meta.url).toString();
return notificationIcon; } catch (e) {
return '';
case "search":
return searchIcon;
case "info":
return infoIcon;
case "tip":
return tipIcon;
case "euro":
return euroIcon;
default:
return "";
} }
} };
let iconPicture = getIconPicture(); const isLikelyIconName = (value) =>
typeof value === 'string' && Object.keys(ICON_FILES).includes(value);
const resolvedIconUrl = !iconUrl || isLikelyIconName(iconUrl) ? buildIconUrlFromName() : iconUrl;
return ( return (
<section <section
{...useBlockProps.save({ {...useBlockProps.save({
className: `homegrade-blocks-highlight ${ className: `homegrade-blocks-highlight ${
variant ? `homegrade-blocks-highlight--${variant}` : "" variant ? `homegrade-blocks-highlight--${variant}` : ''
}`, }`,
})} })}
> >
{hasTitle && ( {hasTitle && (
<div <div
className={`homegrade-blocks-highlight__titling ${ className={`homegrade-blocks-highlight__titling ${
!hasIcon ? "homegrade-blocks-highlight__titling--has-no-icon" : "" !hasIcon ? 'homegrade-blocks-highlight__titling--has-no-icon' : ''
}`} }`}
> >
{hasIcon && iconPosition === "top" && ( {hasIcon && iconPosition === 'top' && (
<div className="icon"> <div className="icon">
<img className="icon__image" src={iconPicture} alt="" /> <img className="icon__image" src={resolvedIconUrl} alt="" />
</div> </div>
)} )}
@ -98,9 +71,9 @@ export default function save({ attributes }) {
</div> </div>
)} )}
<div className="homegrade-blocks-highlight__content"> <div className="homegrade-blocks-highlight__content">
{hasIcon && iconPosition === "side" && !hasTitle && ( {hasIcon && iconPosition === 'side' && !hasTitle && (
<div className="icon"> <div className="icon">
<img src={iconPicture} alt="" /> <img className="icon__image" src={resolvedIconUrl} alt="" />
</div> </div>
)} )}

View File

@ -312,5 +312,5 @@ function wpdocs_load_textdomain()
} }
require_once(__DIR__ . '/blocks/highlight/highlight.php');
require_once(__DIR__ . '/acf-blocks/google-map/map-api-key.php'); require_once(__DIR__ . '/acf-blocks/google-map/map-api-key.php');