はじめに

Gutenbergエディターでブロック全体をリンク化するには、「カスタムHTML」ブロックを使用して <a>タグでブロックを囲む必要があります(図1参照)。
Cocoonには、プラグイン「VK Blocks」のようにグループ全体をリンクで囲む機能はありません。
そこで、ブロック全体をリンク化するブロックを作成します。
この記事では、この方法について説明します。
完成イメージ

実装手順
以下のコードをfunctions.phpに追加します。
// ブロックを登録
add_action('init', function () {
ob_start();
?>
.wp-block-custom-link-wrapper,
.wp-block-custom-link-wrapper:hover {
color: unset;
text-decoration: none;
}
<?php
wp_register_style($handle, false);
wp_add_inline_style($handle, ob_get_clean());
ob_start();
?>
(function (wp) {
const { registerBlockType } = wp.blocks;
const { __ } = wp.i18n;
const { InspectorControls, useBlockProps, InnerBlocks } = wp.blockEditor;
const { PanelBody, TextControl, ToggleControl } = wp.components;
const { createElement: el, Fragment } = wp.element;
registerBlockType('custom/link-wrapper', {
title: __('リンクラッパー', 'link-wrapper'),
icon: 'admin-links',
category: 'cocoon-block',
attributes: {
url: { type: 'string', default: '' },
openInNewTab: { type: 'boolean', default: false }
},
/**
* エディター描画コンポーネント
*
* @param {Object} props ブロックのProps
* @return {import('react').ReactElement} Reactエレメント
*/
edit: function (props) {
const { attributes, setAttributes } = props;
const { url, openInNewTab } = attributes;
const blockProps = useBlockProps({
style: {
border: '1px dashed #ccc',
padding: '10px'
}
});
return el(Fragment, null,
el(InspectorControls, null,
el(PanelBody, {
title: __('リンク設定', 'link-wrapper'),
initialOpen: true
},
el(TextControl, {
label: __('リンク先URL', 'link-wrapper'),
value: url,
onChange: (value) => setAttributes({ url: value })
}),
el(ToggleControl, {
label: __('新しいタブで開く', 'link-wrapper'),
checked: openInNewTab,
onChange: (value) => setAttributes({ openInNewTab: value })
})
)
),
el('div', blockProps,
el(InnerBlocks)
)
);
},
/**
* 保存用コンポーネント
*
* @param {Object} props ブロックのProps
* @return {import('react').ReactElement} Reactエレメント
*/
save: function (props) {
const { attributes } = props;
const { url, openInNewTab } = attributes;
const target = openInNewTab ? '_blank' : '_self';
const blockProps = useBlockProps.save({
href: url,
target: target
});
return el('a', blockProps,
el('div', null,
el(InnerBlocks.Content)
)
);
}
});
})(window.wp);
<?php
$handle = 'link-wrapper-block';
wp_register_script($handle, false, ['wp-blocks', 'wp-element', 'wp-i18n', 'wp-components', 'wp-block-editor'], false, true);
wp_add_inline_script($handle, ob_get_clean());
register_block_type('custom/link-wrapper', [
'editor_script' => $handle,
'style' => $handle,
]);
});
参考:「グループ」ブロックにリンクメニューを追加する方法
「グループ」ブロックのツールバーにリンクメニューを追加します。
完成イメージ

実装手順
以下のコードをfunctions.phpに追加します。
// エディター用JS・CSSを追加
add_action('enqueue_block_editor_assets', function () {
ob_start();
?>
(function (wp) {
// Gutenberg APIから必要なコンポーネントを抽出
const { addFilter } = wp.hooks;
const { createHigherOrderComponent } = wp.compose;
const { Fragment, useState, createElement: el } = wp.element;
const { BlockControls, __experimentalLinkControl: LinkControl } = wp.blockEditor;
const { ToolbarButton, Popover } = wp.components;
// ブロックエディタの既存コンポーネントを拡張する高階コンポーネントを作成
const withToolbar = createHigherOrderComponent((BlockEdit) => {
return (props) => {
// 「グループ」ブロック以外はそのまま描画
if (props.name !== 'core/group') {
return el(BlockEdit, props);
}
// 属性と状態の管理
const { attributes, setAttributes } = props;
const { dataLink, dataTarget } = attributes;
const [open, setOpen] = useState(false);
return el(Fragment, null,
// ツールバーにリンク追加ボタンを配置
el(BlockControls, { group: 'block' },
el(ToolbarButton, {
icon: 'admin-links',
label: 'リンク',
isPressed: !!dataLink,
onClick: () => setOpen(!open)
})
),
// ボタン押下時に表示されるリンク設定用UI
open && el(Popover, { position: 'bottom center', onClose: () => setOpen(false) },
el(LinkControl, {
value: { url: dataLink, opensInNewTab: dataTarget },
onChange: (val) => setAttributes({ dataLink: val.url, dataTarget: val.opensInNewTab }),
onRemove: () => setAttributes({ dataLink: '', dataTarget: false })
})
),
// ブロックを囲み、リンク設定済みであることを示すラッパーを追加
el('div', { className: dataLink ? 'group-has-link' : '' },
el(BlockEdit, props)
)
);
};
}, 'withToolbar');
// エディタの編集機能に上記ツールバー処理をフック
addFilter('editor.BlockEdit', 'custom/group-link-toolbar', withToolbar);
})(window.wp);
<?php
$handle = 'my-group-link';
wp_register_script($handle, false, ['wp-blocks', 'wp-element', 'wp-components', 'wp-compose', 'wp-hooks', 'wp-block-editor'], false, true);
wp_add_inline_script($handle, ob_get_clean());
wp_enqueue_script($handle);
});
// ブロックに属性追加
add_filter('block_type_metadata_settings', function ($settings, $metadata) {
if ($metadata['name'] !== 'core/group') {
return $settings;
}
// リンク先URLを保持
$settings['attributes']['dataLink'] = [
'type' => 'string',
'default' => ''
];
// 別タブで開くフラグを保持
$settings['attributes']['dataTarget'] = [
'type' => 'boolean',
'default' => false
];
return $settings;
}, 10, 2);
// ブロックに反映
add_filter('render_block', function ($content, $block) {
if ($block['blockName'] !== 'core/group' || empty($block['attrs']['dataLink'])) {
return $content;
}
$url = esc_url($block['attrs']['dataLink']);
$target = !empty($block['attrs']['dataTarget']) ? '_blank' : '';
// data属性を追加
$processor = new WP_HTML_Tag_Processor($content);
if ($processor->next_tag()) {
$processor->set_attribute('data-link', $url);
if ($target) {
$processor->set_attribute('data-target', $target);
}
}
return $processor->get_updated_html();
}, 10, 2);
// フロント・エディタ共通のCSSを追加
add_action('enqueue_block_assets', function () {
$handle = 'my-group-link';
wp_register_style($handle, false);
wp_enqueue_style($handle);
ob_start();
?>
.group-has-link {
border: 2px dashed #2271b1;
}
[data-link] {
cursor: pointer;
}
[data-link] a {
pointer-events: none;
}
<?php
$css = ob_get_clean();
wp_add_inline_style($handle, $css);
});
// フロント用JS・CSSを追加
add_action('wp_enqueue_scripts', function () {
ob_start();
?>
document.addEventListener('click', function (e) {
const card = e.target.closest('[data-link]');
if (!card) return;
const { link, target } = card.dataset;
if (!link) {
return;
}
// target指定に応じて遷移方法を切り替え
target === '_blank' ? window.open(link, '_blank') : location.href = link;
});
<?php
wp_add_inline_script('jquery', ob_get_clean());
});
さいごに
今回紹介した方法を使えば、Gutenbergエディターで任意のブロックをリンク全体で囲む「リンクラッパー」ブロックを簡単に追加できます。
これまでのようにカスタムHTMLで <a>タグを手動で書いてブロックを囲む必要がなく、エディター上から直感的にリンク化できるのが大きなメリットです。


