ファイル構造
/patterns
/public
/resources
/js
editor.js
meta.js
query.js
variations.js
/templates
functions.php
package.json
style.css
webpack.config.js
メインのスタイルシートと関数ファイル
/*!
* Theme Name: TT4 Book Reviews
* Description: A child theme for a book review site.
* Version: 1.0.0
* Template: twentytwentyfour
* Tags: full-site-editing
* Text Domain: themeslug
* Tested up to: 6.5
* Requires at least: 6.5
* Requires PHP: 7.4
* License: GNU General Public License v2.0 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/
functions.php
<?php
// Add your custom code below here.
TT4 Book Reviewsテーマを見つけて有効
ビルドスクリプト
package.json
{
"name": "your-project-name",
"scripts": {
"start": "wp-scripts start --webpack-src-dir=resources --output-path=public",
"build": "wp-scripts build --webpack-src-dir=resources --output-path=public"
}
}
wp-content/themes/tt4-book-reviews
npm install @wordpress/scripts @wordpress/icons path webpack-remove-empty-scripts --save-dev
package.json
{
"name": "your-project-name",
"scripts": {
"start": "wp-scripts start --webpack-src-dir=resources --output-path=public",
"build": "wp-scripts build --webpack-src-dir=resources --output-path=public"
},
"devDependencies": {
"@wordpress/icons": "^9.46.0",
"@wordpress/scripts": "^27.6.0",
"path": "^0.12.7",
"webpack-remove-empty-scripts": "^1.0.4"
}
}
webpack.config.js
const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
const RemoveEmptyScriptsPlugin = require( 'webpack-remove-empty-scripts' );
const path = require( 'path' );
module.exports = {
...defaultConfig,
...{
entry: {
'js/editor': path.resolve( process.cwd(), 'resources/js', 'editor.js' )
},
plugins: [
// Include WP's plugin config.
...defaultConfig.plugins,
// Removes the empty `.js` files generated by webpack but
// sets it after WP has generated its `*.asset.php` file.
new RemoveEmptyScriptsPlugin( {
stage: RemoveEmptyScriptsPlugin.STAGE_AFTER_PROCESS_PLUGINS
} )
]
}
};
カスタム フィールドを登録し、ブロック属性にバインド
themeslug_book_author
:本の著者名。themeslug_book_rating
:ユーザーがその本に付けた星評価。themeslug_book_length
:本のページ数。themeslug_book_goodreads_url
: Goodreads.com 上の本のページの URL。
functions.php
add_action( 'init', 'themeslug_register_meta' );
function themeslug_register_meta() {
register_meta( 'post', 'themeslug_book_author', [
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'sanitize_callback' => 'wp_filter_nohtml_kses'
] );
register_meta( 'post', 'themeslug_book_rating', [
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'sanitize_callback' => 'wp_filter_nohtml_kses'
] );
register_meta( 'post', 'themeslug_book_length', [
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'sanitize_callback' => 'wp_filter_nohtml_kses'
] );
register_meta( 'post', 'themeslug_book_goodreads_url', [
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'sanitize_callback' => 'esc_url_raw'
] );
}
カスタムフィールドをブロックに接続
<!-- wp:paragraph {
"metadata":{
"bindings":{
"content":{
"source":"core/post-meta",
"args":{
"key":"themeslug_book_author"
}
}
}
}
} -->
<p></p>
<!-- /wp:paragraph -->
ブロックバリエーションを使用してバインドされたブロックを挿入する
npm run start
functions.php
add_action( 'enqueue_block_editor_assets', 'themeslug_editor_assets' );
function themeslug_editor_assets() {
$script_asset = include get_theme_file_path( 'public/js/editor.asset.php' );
wp_enqueue_script(
'themeslug-editor',
get_theme_file_uri( 'public/js/editor.js' ),
$script_asset['dependencies'],
$script_asset['version'],
true
);
}
/resources/js/editor.js
import './variations';
variations.js
import { registerBlockVariation } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { page, pencil, starFilled } from '@wordpress/icons';
const goodreadsIcon = (
<svg width="24" height="24" viewBox="0 0 24 24" version="1.1">
<path d="M17.3,17.5c-0.2,0.8-0.5,1.4-1,1.9c-0.4,0.5-1,0.9-1.7,1.2C13.9,20.9,13.1,21,12,21c-0.6,0-1.3-0.1-1.9-0.2 c-0.6-0.1-1.1-0.4-1.6-0.7c-0.5-0.3-0.9-0.7-1.2-1.2c-0.3-0.5-0.5-1.1-0.5-1.7h1.5c0.1,0.5,0.2,0.9,0.5,1.2 c0.2,0.3,0.5,0.6,0.9,0.8c0.3,0.2,0.7,0.3,1.1,0.4c0.4,0.1,0.8,0.1,1.2,0.1c1.4,0,2.5-0.4,3.1-1.2c0.6-0.8,1-2,1-3.5v-1.7h0 c-0.4,0.8-0.9,1.4-1.6,1.9c-0.7,0.5-1.5,0.7-2.4,0.7c-1,0-1.9-0.2-2.6-0.5C8.7,15,8.1,14.5,7.7,14c-0.5-0.6-0.8-1.3-1-2.1 c-0.2-0.8-0.3-1.6-0.3-2.5c0-0.9,0.1-1.7,0.4-2.5c0.3-0.8,0.6-1.5,1.1-2c0.5-0.6,1.1-1,1.8-1.4C10.3,3.2,11.1,3,12,3 c0.5,0,0.9,0.1,1.3,0.2c0.4,0.1,0.8,0.3,1.1,0.5c0.3,0.2,0.6,0.5,0.9,0.8c0.3,0.3,0.5,0.6,0.6,1h0V3.4h1.5V15 C17.6,15.9,17.5,16.7,17.3,17.5z M13.8,14.1c0.5-0.3,0.9-0.7,1.3-1.1c0.3-0.5,0.6-1,0.8-1.6c0.2-0.6,0.3-1.2,0.3-1.9 c0-0.6-0.1-1.2-0.2-1.9c-0.1-0.6-0.4-1.2-0.7-1.7c-0.3-0.5-0.7-0.9-1.3-1.2c-0.5-0.3-1.1-0.5-1.9-0.5s-1.4,0.2-1.9,0.5 c-0.5,0.3-1,0.7-1.3,1.2C8.5,6.4,8.3,7,8.1,7.6C8,8.2,7.9,8.9,7.9,9.5c0,0.6,0.1,1.3,0.2,1.9C8.3,12,8.6,12.5,8.9,13 c0.3,0.5,0.8,0.8,1.3,1.1c0.5,0.3,1.1,0.4,1.9,0.4C12.7,14.5,13.3,14.4,13.8,14.1z" />
</svg>
);
registerBlockVariation( 'core/paragraph', {
name: 'themeslug/book-author',
title: __( 'Book Author', 'themeslug' ),
description: __( 'Displays the book author.', 'themeslug' ),
category: 'widgets',
keywords: [ 'book', 'author' ],
icon: pencil,
scope: [ 'inserter' ],
attributes: {
metadata: {
bindings: {
content: {
source: 'core/post-meta',
args: {
key: 'themeslug_book_author'
}
}
}
},
placeholder: __( 'Book Author', 'themeslug' )
},
example: {},
isActive: (blockAttributes) =>
'themeslug_book_author' === blockAttributes?.metadata?.bindings?.content?.args?.key
});
registerBlockVariation( 'core/paragraph', {
name: 'themeslug/book-length',
title: __( 'Book Length', 'themeslug' ),
description: __( 'Displays the book length in pages.', 'themeslug' ),
category: 'widgets',
keywords: [ 'book', 'pages', 'length' ],
icon: page,
scope: [ 'inserter' ],
attributes: {
metadata: {
bindings: {
content: {
source: 'core/post-meta',
args: {
key: 'themeslug_book_length'
}
}
}
},
placeholder: __( 'Book Length', 'themeslug' )
},
example: {},
isActive: (blockAttributes) =>
'themeslug_book_length' === blockAttributes?.metadata?.bindings?.content?.args?.key
});
registerBlockVariation( 'core/paragraph', {
name: 'themeslug/book-rating',
title: __( 'Book Rating', 'themeslug' ),
description: __( 'Displays the book rating.', 'themeslug' ),
category: 'widgets',
keywords: [ 'book', 'rating', 'review' ],
icon: starFilled,
scope: [ 'inserter' ],
attributes: {
metadata: {
bindings: {
content: {
source: 'core/post-meta',
args: {
key: 'themeslug_book_rating'
}
}
}
},
placeholder: __( 'Book Rating', 'themeslug' )
},
example: {},
isActive: (blockAttributes) =>
'themeslug_book_rating' === blockAttributes?.metadata?.bindings?.content?.args?.key
});
registerBlockVariation( 'core/button', {
name: 'themeslug/book-goodreads-button',
title: __( 'Book Goodreads Button', 'themeslug' ),
description: __( 'Displays a button with the link to the Goodreads book URL.', 'themeslug' ),
category: 'widgets',
keywords: [ 'book', 'author' ],
icon: goodreadsIcon,
scope: [ 'inserter' ],
attributes: {
text: __( 'View on Goodreads →', 'themeslug' ),
metadata: {
bindings: {
url: {
source: 'core/post-meta',
args: {
key: 'themeslug_book_goodreads_url'
}
}
}
}
},
example: {},
isActive: (blockAttributes) =>
'themeslug_book_goodreads_url' === blockAttributes?.metadata?.bindings?.url?.args?.key
});
メタ入力コントロールの追加
/resources/js/editor.js
meta.js
import { useEntityProp } from "@wordpress/core-data";
import { useSelect } from "@wordpress/data";
import { PluginDocumentSettingPanel } from "@wordpress/edit-post";
import { __ } from "@wordpress/i18n";
import { starFilled } from "@wordpress/icons";
import { registerPlugin } from "@wordpress/plugins";
import { RangeControl, __experimentalInputControl as InputControl, __experimentalNumberControl as NumberControl, __experimentalVStack as VStack } from "@wordpress/components";
registerPlugin("tt4-book-reviews", {
render: () => {
// Add your custom code here.
const postType = useSelect((select) => select("core/editor").getCurrentPostType(), []);
const [meta, setMeta] = useEntityProp("postType", postType, "meta");
if ("post" !== postType) {
return null;
}
return (
<PluginDocumentSettingPanel title={__("Book Review", "themeslug")}>
<VStack>
<RangeControl
label={__("Rating", "themeslug")}
beforeIcon={starFilled}
currentInput={0}
initialPosition={0}
min={0}
max={5}
step={1}
value={parseInt(meta?.themeslug_book_rating, 10)}
onChange={(value) =>
setMeta({
...meta,
themeslug_book_rating: `${value}` || null,
})
}
/>
<InputControl
label={__("Author", "themeslug")}
value={meta?.themeslug_book_author}
onChange={(value) =>
setMeta({
...meta,
themeslug_book_author: value || null,
})
}
/>
<NumberControl
label={__("Total Pages", "themeslug")}
min={0}
value={parseInt(meta?.themeslug_book_length, 10)}
onChange={(value) =>
setMeta({
...meta,
themeslug_book_length: `${value}` || null,
})
}
/>
<InputControl
label={__("Goodreads URL", "themeslug")}
value={meta?.themeslug_book_goodreads_url}
onChange={(value) =>
setMeta({
...meta,
themeslug_book_goodreads_url: value || null,
})
}
/>
</VStack>
</PluginDocumentSettingPanel>
);
},
});