Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new block development "Quick Start Guide" and update the create-block-tutorial-template #56056

Merged
merged 9 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions docs/getting-started/create-block/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,6 @@ The tutorial includes setting up your development environment, tools, and gettin

The first thing you need is a development environment and tools. This includes setting up your WordPress environment, Node, NPM, and your code editor. If you need help, see the [setting up your development environment documentation](/docs/getting-started/devenv/README.md).

## Quick Start

The `@wordpress/create-block` package exists to create the necessary block scaffolding to get you started. See [create-block package documentation](https://www.npmjs.com/package/@wordpress/create-block) for additional features. This quick start assumes you have a development environment with node installed, and a WordPress site.

From your plugins directory, to create your block run:

```sh
npx @wordpress/create-block gutenpride --template @wordpress/create-block-tutorial-template
```

> Remember that you should use Node.js v14. Other versions may result in an error in the terminal. See [Node Development Tools](https://developer.wordpress.org/block-editor/getting-started/devenv/#node-development-tools) for more info.

The [npx command](https://docs.npmjs.com/cli/v8/commands/npx) runs a command from a remote package, in this case our create-block package that will create a new directory called `gutenpride`, installs the necessary files, and builds the block plugin. If you want an interactive mode that prompts you for details, run the command without the `gutenpride` name.

You now need to activate the plugin from inside wp-admin plugins page.

After activation, go to the block editor and use the inserter to search and add your new block.

## Table of Contents

The create a block tutorials breaks down to the following sections.
Expand Down
44 changes: 44 additions & 0 deletions docs/getting-started/quick-start-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
## Quick Start Guide

This guide is designed to demonstrate the basic principles of block development in WordPress using a hands-on approach. Following the steps below, you will create a custom block plugin that uses modern JavaScript (ESNext and JSX) in a matter of minutes. The example block displays the copyright symbol (©) and the current year, the perfect addition to any website's footer.

## Scaffold the block plugin

Start by ensuring you have Node.js and `npm` installed on your computer. Review the [Node.js development environment](https://developer.wordpress.org/block-editor/getting-started/devenv/nodejs-development-environment/) guide if not.

Next, use the [`@wordpress/create-block`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/) package and the [`@wordpress/create-block-tutorial-template`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block-tutorial-template/) template to scaffold the complete “Copyright Date Block” plugin.

<div class="callout callout-info">
<p>You can use <code>create-block</code> to scaffold a block just about anywhere and then use <a href="https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-env/"><code>wp-env</code></a> inside the generated plugin folder. This will create a local WordPress development environment with your new block plugin installed and activated.</p>
<p>If you already have your own <a href="https://developer.wordpress.org/block-editor/getting-started/devenv/#local-wordpress-environment">local WordPress development environment</a>, navigate to the <code>plugins/</code> folder using the terminal.</p>
</div>

Choose the folder where you want to create the plugin, and then execute the following command in the terminal from within that folder:

```sh
npx @wordpress/create-block copyright-date-block --template create-block-tutorial-template
```

The `slug` provided (`copyright-date-block`) defines the folder name for the scaffolded plugin and the internal block name.

Navigate to the Plugins page of your local WordPress installation and activate the “Copyright Date Block” plugin. The example block will then be available in the Editor.

## Basic usage

With the plugin activated, you can explore how the block works. Use the following command to move into the newly created plugin folder and start the development process.

```sh
cd copyright-date-block && npm start
```

When `create-block` scaffolds the block, it installs `wp-scripts` and adds the most common scripts to the block’s `package.json` file. Refer to the [Get started with wp-scripts](https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-scripts/) article for an introduction to this package.

The `npm start` command will start a development server and watch for changes in the block’s code, rebuilding the block whenever modifications are made.

When you are finished making changes, run the `npm run build` command. This optimizes the block code and makes it production-ready.

## Additional resources

- [Get started with create-block](https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-create-block/)
- [Get started with wp-scripts](https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-scripts/)
- [Get started with wp-env](https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-env/)
6 changes: 6 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
"markdown_source": "../docs/getting-started/devenv/get-started-with-wp-scripts.md",
"parent": "devenv"
},
{
"title": "QuickStartGuide",
"slug": "quick-start-guide",
"markdown_source": "../docs/getting-started/quick-start-guide.md",
"parent": "getting-started"
},
{
"title": "Create a Block Tutorial",
"slug": "create-block",
Expand Down
1 change: 1 addition & 0 deletions docs/toc.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
}
]
},
{ "docs/getting-started/quick-start-guide.md": [] },
{
"docs/getting-started/create-block/README.md": [
{
Expand Down
4 changes: 4 additions & 0 deletions packages/create-block-tutorial-template/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Change

- Update the block example scaffolded by the template.

## 2.33.0 (2023-11-02)

## 2.32.0 (2023-10-18)
Expand Down
4 changes: 3 additions & 1 deletion packages/create-block-tutorial-template/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Create Block Tutorial Template

This is a template for [`@wordpress/create-block`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/create-block/README.md) that is the finished version of the block in the official [WordPress Tutorial](https://github.com/WordPress/gutenberg/tree/HEAD/docs/getting-started/create-block/README.md) for the block editor.
This is a template for [`@wordpress/create-block`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/create-block/README.md) that creates an example "Copyright Date" block. This block is used in the official WordPress block development [Quick Start Guide](https://developer.wordpress.org/block-editor/getting-started/quick-start-guide).

## Usage

Expand All @@ -10,6 +10,8 @@ This block template can be used by running the following command:
npx @wordpress/create-block --template @wordpress/create-block-tutorial-template
```

Use the default options when prompted in the terminal.

## Contributing to this package

This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects.
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
/**
* WordPress components that create the necessary UI elements for the block
* Retrieves the translation of text.
*
* @see https://developer.wordpress.org/block-editor/packages/packages-components/
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
*/
import { TextControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* React hook that is used to mark the block wrapper element.
* It provides all the necessary props like the class name.
* Imports the InspectorControls component, which is used to wrap
* the block's custom controls that will appear in in the Settings
* Sidebar when the block is selected.
*
* Also imports the React hook that is used to mark the block wrapper
* element. It provides all the necessary props like the class name.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#inspectorcontrols
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
*/
import { useBlockProps } from '@wordpress/block-editor';
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';

/**
* Imports the necessary components that will be used to create
* the user interface for the block's settings.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/components/panel/#panelbody
* @see https://developer.wordpress.org/block-editor/reference-guides/components/text-control/
* @see https://developer.wordpress.org/block-editor/reference-guides/components/toggle-control/
*/
import { PanelBody, TextControl, ToggleControl } from '@wordpress/components';

/**
* Imports the useEffect React Hook. This is used to set an attribute when the
* block is loaded in the Editor.
*
* @see https://react.dev/reference/react/useEffect
*/
import { useEffect } from 'react';

/**
* The edit function describes the structure of your block in the context of the
Expand All @@ -26,13 +49,59 @@ import { useBlockProps } from '@wordpress/block-editor';
* @return {Element} Element to render.
*/
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const { fallbackCurrentYear, showStartingYear, startingYear } = attributes;

// Get the current year and make sure it's a string.
const currentYear = new Date().getFullYear().toString();

// When the block loads, set the fallbackCurrentYear attribute to the
// current year if it's not already set.
useEffect( () => {
if ( currentYear !== fallbackCurrentYear ) {
setAttributes( { fallbackCurrentYear: currentYear } );
}
}, [ currentYear, fallbackCurrentYear, setAttributes ] );

let displayDate;

// Display the starting year as well if supplied by the user.
if ( showStartingYear && startingYear ) {
displayDate = startingYear + '–' + currentYear;
} else {
displayDate = currentYear;
}

return (
<div { ...blockProps }>
<TextControl
value={ attributes.message }
onChange={ ( val ) => setAttributes( { message: val } ) }
/>
</div>
<>
<InspectorControls>
<PanelBody title={ __( 'Settings', '{{textdomain}}' ) }>
<ToggleControl
checked={ showStartingYear }
label={ __(
'Show starting year',
'{{textdomain}}'
) }
onChange={ () =>
setAttributes( {
showStartingYear: ! showStartingYear,
} )
}
/>
{ showStartingYear && (
<TextControl
label={ __(
'Starting year',
'{{textdomain}}'
) }
value={ startingYear }
onChange={ ( value ) =>
setAttributes( { startingYear: value } )
}
/>
) }
</PanelBody>
</InspectorControls>
<p { ...useBlockProps() }>© { displayDate }</p>
</>
);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,27 @@
import { registerBlockType } from '@wordpress/blocks';

/**
* Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
* All files containing `style` keyword are bundled together. The code used
* gets applied both to the front of your site and to the editor. All other files
* get applied to the editor only.
* Imports the calendar icon, which will be used for the block icon.
*
* @see https://www.npmjs.com/package/@wordpress/scripts#using-css
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-icons/
*/
import './style.scss';
import './editor.scss';
import { calendar } from '@wordpress/icons';

/**
* Internal dependencies
*/
import Edit from './edit';
{{#isStaticVariant}}
import save from './save';
{{/isStaticVariant}}
import metadata from './block.json';

/**
ndiego marked this conversation as resolved.
Show resolved Hide resolved
* Every block starts by registering a new block type definition.
*
* @see https://developer.wordpress.org/block-editor/developers/block-api/#registering-a-block
*/
registerBlockType( metadata.name, {
/**
* Used to construct a preview for the block to be shown in the block inserter.
*/
example: {
attributes: {
message: '{{title}}',
},
},
icon: calendar,
/**
* @see ./edit.js
*/
edit: Edit,
{{#isStaticVariant}}

/**
* @see ./save.js
*/
save,
{{/isStaticVariant}}
} );
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
{{#isDynamicVariant}}
<?php
/**
* PHP file to use when rendering the block type on the server to show on the front end.
*
* The following variables are exposed to the file:
* $attributes (array): The block attributes.
* $content (string): The block default content.
* $block (WP_Block): The block instance.
*
* @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render
*/
?>
<p <?php echo get_block_wrapper_attributes(); ?>>
<?php echo esc_html( $attributes['message'] ); ?>
</p>
{{/isDynamicVariant}}

// Get the current year.
$current_year = date( "Y" );

// Determine which content to display.
if ( isset( $attributes['fallbackCurrentYear'] ) && $attributes['fallbackCurrentYear'] === $current_year ) {

// The current year is the same as the fallback, so use the block content saved in the database (by the save.js function).
$block_content = $content;
} else {

// The current year is different from the fallback, so render the updated block content.
if ( ! empty( $attributes['startingYear'] ) && ! empty( $attributes['showStartingYear'] ) ) {
$display_date = $attributes['startingYear'] . '–' . $current_year;
} else {
$display_date = $current_year;
}

$block_content = '<p ' . get_block_wrapper_attributes() . '>© ' . esc_html( $display_date ) . '</p>';
}

echo wp_kses_post( $block_content );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the same wp_kses_post is used with many core blocks in certain scenarios. What's the reasoning behind using it at this level? I'm asking because in the case where we render the content as saved to the database then it doesn't differ much from not having the render at all. In effect, I expect that the similar processing would happen somewhere else.

I'm mostly trying to understand how it all really works in WordPress core today so it's clear for me when to use kses.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's always been a best practice to late escape anything that is being output to the browser that could be modified by a hook, filter, etc - https://developer.wordpress.org/apis/security/escaping/#toc_3

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that would be an issue, then all core blocks would call wp_kses_post. However, it isn't the case. If this function is used, it's used to escape the content that comes from the user input when it is expected it might contain HTML. In the case of this block, it should be enough to cast the startingYear to the number and the rest should be safe.

Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{{#isStaticVariant}}
/**
* React hook that is used to mark the block wrapper element.
* It provides all the necessary props like the class name.
Expand All @@ -16,10 +15,27 @@ import { useBlockProps } from '@wordpress/block-editor';
*
* @param {Object} props Properties passed to the function.
* @param {Object} props.attributes Available block attributes.
*
* @return {Element} Element to render.
*/
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return <div { ...blockProps }>{ attributes.message }</div>;
const { fallbackCurrentYear, showStartingYear, startingYear } = attributes;

// If there is no fallbackCurrentYear, which could happen if the block
// is loaded from a template/pattern, return null. In this case, block
// rendering will be handled by the render.php file.
if ( ! fallbackCurrentYear ) {
return null;
}

let displayDate;

// Display the starting year as well if supplied by the user.
if ( showStartingYear && startingYear ) {
displayDate = startingYear + '–' + fallbackCurrentYear;
} else {
displayDate = fallbackCurrentYear;
}

return <p { ...useBlockProps.save() }>© { displayDate }</p>;
}
{{/isStaticVariant}}

This file was deleted.

Loading