这是indexloc提供的服务,不要输入任何密码
Skip to content

Add Interactivity API support #451

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

Merged
merged 14 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .wp-env.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"core": null,
"phpVersion": "8.2",
"themes": ["."],
"themes": [ "." ],
"port": 5890,
"env": {
"tests": {
Expand Down
37 changes: 37 additions & 0 deletions assets/src/js/modules/media-text.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Custom module script required for the media text interactive pattern.
*/

/**
* WordPress dependencies
*/
import { store, getContext, getElement } from '@wordpress/interactivity';

store( 'elementary/media-text', {
actions: {
/**
* Update the video play state.
*
* @return {void}
*/
play() {
const context = getContext();
context.isPlaying = true;
},
},
callbacks: {
/**
* Play the video.
*
* @return {void}
*/
playVideo() {
const context = getContext();
const { ref } = getElement();
if ( context.isPlaying ) {
ref.querySelector( 'video' )?.play();
context.isPlaying = false;
}
},
},
} );
113 changes: 113 additions & 0 deletions docs/asset-building-process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Asset Building Process

This document outlines the process of building and managing assets (CSS, JS, and modules) within the theme. It also explains how to add new scripts or modules into the build process.

## Overview

Our asset pipeline is managed by **Webpack**, using the configuration provided by WordPress and some additional optimizations. The build process involves the following steps:

1. **JS and CSS Files** are processed, concatenated, and minified for production.
2. **Modules** are handled separately to ensure they're loaded correctly.
3. **CSS/SCSS files** are extracted and moved to a dedicated `css` directory.

### Key Configuration Files

- **webpack.config.js**: This is the main configuration file for building assets.
- **package.json**: Contains the scripts and dependencies necessary for the build process.

### Directory Structure

- **assets/src/js**: Contains JavaScript files.
- **assets/src/css**: Contains CSS/SCSS files.
- **assets/src/js/modules**: Contains modular JavaScript files that are handled separately.
- **assets/build/js**: Where built JavaScript files are output.
- **assets/build/css**: Where built CSS files are output.

---

## How the Asset Building Works

### JS and CSS Build Process

1. **CSS Files**: All `.css` or `.scss` files in the `assets/src/css` directory are collected into the build process. They are extracted into a separate CSS file in the `assets/build/css` folder.

- The main `webpack.config.js` file uses the `MiniCssExtractPlugin` to extract the CSS.
- The extracted CSS files are minified using `CssMinimizerPlugin` in production builds.

2. **JS Files**: The JavaScript files are bundled into a single file or multiple files (for split chunks). The `assets/src/js` folder contains files like `core-navigation.js`, which are part of the main entry point.

- JavaScript files are processed using Babel to ensure compatibility with different browsers.
- We use `webpack-remove-empty-scripts` to remove any empty JavaScript files that do not have content.

3. **Modules**: Files located in `assets/src/js/modules` are treated as separate entry points. These are compiled into separate files and stored in the `assets/build/js/modules` directory.

- The configuration for modules is handled through the `moduleScripts` entry in the `webpack.config.js`.

---

## Adding New Scripts or Modules

To add a new script or module to the build process, follow these steps:

### Adding a New Script

1. Place your JavaScript file in the `assets/src/js` directory or a subdirectory.

Example: `assets/src/js/my-script.js`

2. Edit the `webpack.config.js` file and add your script to the `scripts` entry object.

Example:
```js
entry: {
'my-new-script': path.resolve( process.cwd(), 'assets', 'src', 'js', 'my-script.js' ),
},
```

3. If necessary, add any required dependencies or libraries to `assets/src/js` and import them in your new script.

4. Run the build script:

```bash
npm run build:dev # For development
npm run build:prod # For production
```

---

### Adding a New Module

1. Place your module JavaScript file in the `assets/src/js/modules` directory.

Example: `assets/src/js/modules/my-module.js`

2. The modules will automatically be included in the Webpack build process, but if you want to make sure it is included in the final output, ensure it’s referenced correctly in the entry object for modules:

```js
entry: () => readAllFileEntries( './assets/src/js/modules' ),
```

3. Add any necessary logic in your module’s JavaScript code to ensure it functions correctly within the theme. Modules are usually self-contained and independent, so make sure to export and import dependencies as needed.

4. Run the build script:

```bash
npm run build:dev # For development
npm run build:prod # For production
```

## Avoid Bundling Specific Files

For example, if you have a file like `_my-excluded-script.js` or `_my-excluded-styles.css`, Webpack will **ignore** it when bundling and it won't be included in the final output.

### How to Exclude Files

- **CSS/SCSS**: If you want to add a CSS file without bundling it, name it starting with an underscore.

Example: `_my-excluded-styles.scss`

- **JavaScript**: Similarly, prefix JS files with an underscore to prevent bundling.

Example: `_my-excluded-script.js`

By naming files with the underscore, we make sure they are excluded from the Webpack build process but can still be used elsewhere in the project.
111 changes: 111 additions & 0 deletions inc/classes/block-extension/class-media-text-interactive.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php
/**
* Media Text Interactive.
*
* @package Elementary-Theme
*/

namespace Elementary_Theme\Block_Extensions;

use WP_HTML_Tag_Processor;
use Elementary_Theme\Traits\Singleton;

/**
* Class Media_Text_Interactive
*/
class Media_Text_Interactive {

use Singleton;

/**
* Constructor.
*/
protected function __construct() {
$this->setup_hooks();
}

/**
* Setup hooks.
*
* @return void
*/
public function setup_hooks() {

add_filter( 'render_block_core/button', array( $this, 'render_block_core_button' ), 10, 2 );
add_filter( 'render_block_core/columns', array( $this, 'render_block_core_columns' ), 10, 2 );
add_filter( 'render_block_core/video', array( $this, 'render_block_core_video' ), 10, 2 );

}

/**
* Render block core/button.
*
* @param string $block_content Block content.
* @param array $block Block.
* @return string
*/
public function render_block_core_button( $block_content, $block ) {
if ( ! isset( $block['attrs']['className'] ) || ! str_contains( $block['attrs']['className'], 'elementary-media-text-interactive' ) ) {
return $block_content;
}

$p = new WP_HTML_Tag_Processor( $block_content );

$p->next_tag();
$p->set_attribute( 'data-wp-on--click', 'actions.play' );

return $p->get_updated_html();
}

/**
* Render block core/columns.
*
* @param string $block_content Block content.
* @param array $block Block.
* @return string
*/
public function render_block_core_columns( $block_content, $block ) {
if ( ! isset( $block['attrs']['className'] ) || ! str_contains( $block['attrs']['className'], 'elementary-media-text-interactive' ) ) {
return $block_content;
}

/**
* Enqueue the module script, The prefix `@` is used to indicate that the script is a module.
* This handle with the prefix `@` will be used in other scripts to import this module.
*/
wp_enqueue_script_module(
'@elementary/media-text',
sprintf( '%s/js/modules/media-text.js', ELEMENTARY_THEME_BUILD_URI ),
[
'@wordpress/interactivity',
]
);

$p = new WP_HTML_Tag_Processor( $block_content );

$p->next_tag();
$p->set_attribute( 'data-wp-interactive', '{ "namespace": "elementary/media-text" }' );
$p->set_attribute( 'data-wp-context', '{ "isPlaying": false }' );

return $p->get_updated_html();
}

/**
* Render block core/video.
*
* @param string $block_content Block content.
* @param array $block Block.
* @return string
*/
public function render_block_core_video( $block_content, $block ) {
if ( ! isset( $block['attrs']['className'] ) || ! str_contains( $block['attrs']['className'], 'elementary-media-text-interactive' ) ) {
return $block_content;
}
$p = new WP_HTML_Tag_Processor( $block_content );

$p->next_tag();
$p->set_attribute( 'data-wp-watch', 'callbacks.playVideo' );

return $p->get_updated_html();
}
}
11 changes: 11 additions & 0 deletions inc/classes/class-elementary-theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Elementary_Theme;

use Elementary_Theme\Block_Extensions\Media_Text_Interactive;
use Elementary_Theme\Traits\Singleton;
use Elementary_Theme\Assets;

Expand All @@ -28,6 +29,7 @@ protected function __construct() {

// Setup hooks.
$this->setup_hooks();
$this->block_extensions();
}

/**
Expand All @@ -48,4 +50,13 @@ public function elementary_theme_support() {
// Add support for core block styles.
add_theme_support( 'wp-block-styles' );
}

/**
* Block extensions
*
* @since 1.0.0
*/
public function block_extensions() {
Media_Text_Interactive::get_instance();
}
}
Loading
Loading