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

Release Nov 25 #298

Merged
merged 6 commits into from
Nov 25, 2024
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# [1.14.0-alpha.1](https://github.com/Automattic/newspack-block-theme/compare/v1.13.0...v1.14.0-alpha.1) (2024-11-15)


### Features

* add post subtitle support ([#290](https://github.com/Automattic/newspack-block-theme/issues/290)) ([593ffca](https://github.com/Automattic/newspack-block-theme/commit/593ffca3787ebffd665433d82dadea450bb9b7b9))

# [1.13.0](https://github.com/Automattic/newspack-block-theme/compare/v1.12.0...v1.13.0) (2024-10-08)


Expand Down
7 changes: 4 additions & 3 deletions functions.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<?php
/**
* Newspack Block Theme functions and definitions
* Version: 1.13.0
* Version: 1.14.0-alpha.1
*
* @link https://developer.wordpress.org/themes/basics/theme-functions/
*
* @package Newspack Block Theme
* @since Newspack Block Theme 1.0
*/

defined( 'ABSPATH' ) || exit;
Expand All @@ -16,10 +15,12 @@
define( 'NEWSPACK_BLOCK_THEME_FILE', __FILE__ );
define( 'NEWSPACK_BLOCK_THEME_FILE_PATH', plugin_dir_path( NEWSPACK_BLOCK_THEME_FILE ) );
define( 'NEWSPACK_BLOCK_THEME_URL', plugin_dir_url( NEWSPACK_BLOCK_THEME_FILE ) );
define( 'NEWSPACK_BLOCK_THEME_VERSION', '1.13.0' );
define( 'NEWSPACK_BLOCK_THEME_VERSION', '1.14.0-alpha.1' );
}


// Include theme resources.
require_once NEWSPACK_BLOCK_THEME_FILE_PATH . '/includes/class-core.php';
require_once NEWSPACK_BLOCK_THEME_FILE_PATH . '/includes/blocks/index.php';
require_once NEWSPACK_BLOCK_THEME_FILE_PATH . '/includes/class-patterns.php';
require_once NEWSPACK_BLOCK_THEME_FILE_PATH . '/includes/class-jetpack.php';
12 changes: 12 additions & 0 deletions includes/blocks/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
/**
* Newspack Block Theme Blocks.
*
* @package Newspack_Block_Theme
*/

namespace Newspack_Block_Theme;

defined( 'ABSPATH' ) || exit;

require_once NEWSPACK_BLOCK_THEME_FILE_PATH . '/includes/blocks/subtitle-block/class-subtitle-block.php';
25 changes: 25 additions & 0 deletions includes/blocks/subtitle-block/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "newspack-block-theme/article-subtitle",
"title": "Article Subtitle",
"category": "newspack",
"attributes": {},
"supports": {
"html": false,
"color": {
"gradients": true,
"__experimentalDefaultControls": {
"background": true,
"text": true,
"link": true
}
},
"spacing": {
"margin": true,
"padding": true
},
"typography": {
"fontSize": true,
"lineHeight": true
}
}
}
82 changes: 82 additions & 0 deletions includes/blocks/subtitle-block/class-subtitle-block.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
/**
* Subtitle Block.
*
* @package Newspack_Block_Theme
*/

namespace Newspack_Block_Theme;

defined( 'ABSPATH' ) || exit;


/**
* Subtitle Block class.
*/
final class Subtitle_Block {
const POST_META_NAME = 'newspack_post_subtitle';

/**
* Initializer.
*/
public static function init() {
\add_action( 'init', [ __CLASS__, 'register_block_and_post_meta' ] );
\add_action( 'enqueue_block_editor_assets', [ __CLASS__, 'enqueue_block_editor_assets' ] );
}

/**
* Register the block.
*/
public static function register_block_and_post_meta() {
register_block_type_from_metadata(
__DIR__ . '/block.json',
[
'render_callback' => [ __CLASS__, 'render_block' ],
]
);

register_post_meta(
'post',
self::POST_META_NAME,
[
'show_in_rest' => true,
'single' => true,
'type' => 'string',
]
);
}

/**
* Block render callback.
*/
public static function render_block() {
$post_subtitle = get_post_meta( get_the_ID(), self::POST_META_NAME, true );
$wrapper_attributes = get_block_wrapper_attributes();
return sprintf( '<p %1$s>%2$s</p>', $wrapper_attributes, $post_subtitle );
}

/**
* Enqueue block editor ad suppression assets for any post type considered
* "viewable".
*/
public static function enqueue_block_editor_assets() {
$script_data = [
'post_meta_name' => self::POST_META_NAME,
];

global $pagenow;
if ( $pagenow === 'site-editor.php' ) {
$handle = 'newspack-block-theme-subtitle-block-site-editor';
\wp_enqueue_script( $handle, \get_theme_file_uri( 'dist/subtitle-block-site-editor.js' ), [], NEWSPACK_BLOCK_THEME_VERSION, true );
\wp_localize_script( $handle, 'newspack_block_theme_subtitle_block', $script_data );
}

$post_type = \get_current_screen()->post_type;
if ( $post_type === 'post' ) {
$handle = 'newspack-block-theme-subtitle-block-post-editor';
\wp_enqueue_script( $handle, \get_theme_file_uri( 'dist/subtitle-block-post-editor.js' ), [], NEWSPACK_BLOCK_THEME_VERSION, true );
\wp_localize_script( $handle, 'newspack_block_theme_subtitle_block', $script_data );
}
}
}
Subtitle_Block::init();
77 changes: 77 additions & 0 deletions includes/blocks/subtitle-block/post-editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* globals newspack_block_theme_subtitle_block */
'use strict';

/**
* WordPress dependencies
*/
import { registerPlugin } from '@wordpress/plugins';
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect } from '@wordpress/element';

const META_FIELD_NAME = newspack_block_theme_subtitle_block.post_meta_name;

const SUBTITLE_ID = 'newspack-post-subtitle-element';
const SUBTITLE_STYLE_ID = 'newspack-post-subtitle-element-style';

const appendSubtitleToTitleDOMElement = ( subtitle, callback ) => {
const titleWrapperEl = document.querySelector( '.edit-post-visual-editor__post-title-wrapper' );

if ( titleWrapperEl && typeof subtitle === 'string' ) {
let subtitleEl = document.getElementById( SUBTITLE_ID );
const titleParent = titleWrapperEl.parentNode;

if ( ! document.getElementById( SUBTITLE_STYLE_ID ) ) {
const style = document.createElement( 'style' );
style.innerHTML = `
#${ SUBTITLE_ID } {
font-style: italic;
max-width: calc(632px + var(--wp--preset--spacing--30)* 2);
margin-left: auto;
margin-right: auto;
margin-bottom: 2em;
padding-left: var(--wp--preset--spacing--30);
padding-right: var(--wp--preset--spacing--30);
}
`;
document.head.appendChild( style );
}

if ( ! subtitleEl ) {
subtitleEl = document.createElement( 'div' );
subtitleEl.setAttribute( 'contenteditable', 'plaintext-only' );
subtitleEl.addEventListener( 'input', () => {
callback( subtitleEl.innerHTML );
} );
subtitleEl.id = SUBTITLE_ID;
titleParent.insertBefore( subtitleEl, titleWrapperEl.nextSibling );
}
subtitleEl.innerHTML = subtitle;
}
};

/**
* This functionality is handled via DOM interaction, which is risky, but in the name of WYSIWYG.
* The post subtitle is edited directly beneath the post title, and no block is
* registered in the post editor – this block will only be registered in the site editor.
*/
const NewspackSubtitlePanel = () => {
const subtitle = useSelect(
select => select( 'core/editor' ).getEditedPostAttribute( 'meta' )[ META_FIELD_NAME ]
);
const dispatch = useDispatch();
const saveSubtitle = updatedSubtitle => {
dispatch( 'core/editor' ).editPost( {
meta: {
[ META_FIELD_NAME ]: updatedSubtitle,
},
} );
};
useEffect( () => {
appendSubtitleToTitleDOMElement( subtitle, saveSubtitle );
}, [] );
};

registerPlugin( 'plugin-document-setting-panel-newspack-subtitle', {
render: NewspackSubtitlePanel,
icon: null,
} );
32 changes: 32 additions & 0 deletions includes/blocks/subtitle-block/site-editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* globals newspack_block_theme_subtitle_block */

/**
* WordPress dependencies
*/
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { Icon, listView } from '@wordpress/icons';
import { useEntityProp } from '@wordpress/core-data';

import blockData from './block.json';

const EditComponent = ( { context: { postType, postId } } ) => {
const [ postMeta = {} ] = useEntityProp( 'postType', postType, 'meta', postId );
return (
postMeta[ newspack_block_theme_subtitle_block.post_meta_name ] ||
__( 'Article subtitle', 'newspack-block-theme' )
);
};

blockData = {
title: __( 'Article Subtitle', 'newspack-block-theme' ),
icon: {
src: <Icon icon={ listView } />,
foreground: '#36f',
},
edit: EditComponent,
usesContext: [ 'postId', 'postType' ],
...blockData,
};

registerBlockType( blockData.name, blockData );
3 changes: 3 additions & 0 deletions includes/blocks/subtitle-block/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.wp-block-newspack-block-theme-subtitle {
font-style: italic;
}
3 changes: 2 additions & 1 deletion includes/class-core.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public static function theme_support() {

// Make theme available for translation.
\load_theme_textdomain( 'newspack-block-theme' );

\add_theme_support( 'post-subtitle' );
}

/**
Expand All @@ -50,7 +52,6 @@ public static function theme_support() {
* @return void
*/
public static function theme_styles() {

// Register theme stylesheet.
\wp_register_style(
'newspack_block_theme-style',
Expand Down
97 changes: 97 additions & 0 deletions includes/class-patterns.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php
/**
* Newspack Block Theme patterns handling.
*
* @package Newspack_Block_Theme
*/

namespace Newspack_Block_Theme;

defined( 'ABSPATH' ) || exit;

/**
* Main Patterns class.
*/
final class Patterns {
/**
* Initializer.
*/
public static function init() {
\add_action( 'init', [ __CLASS__, 'register_nested_patterns' ] );
}

/**
* Find nested PHP files.
*
* @param string $directory The base directory to search in.
*/
public static function find_nested_php_files( $directory ) {
$php_files = [];
$items = glob( $directory . '/*' );

foreach ( $items as $item ) {
if ( is_dir( $item ) ) {
$php_files = array_merge( $php_files, self::find_nested_php_files( $item ) );
} elseif ( is_file( $item ) && pathinfo( $item, PATHINFO_EXTENSION ) === 'php' ) {
$php_files[] = $item;
}
}

return $php_files;
}

/**
* Registers patterns nested in the /patterns directory. WP will only
* register automatically the patterns which are top-level files in this directory.
*
* @see get_block_patterns
*/
public static function register_nested_patterns() {
$directory = get_stylesheet_directory() . '/patterns';
$files = self::find_nested_php_files( $directory );

foreach ( $files as $file ) {
$relative_path = str_replace( $directory, '', $file );
// Check if the path is nested. Non-nested patterns will be automatically registered by WP.
if ( substr_count( $relative_path, '/' ) === 1 ) {
continue;
}
$default_headers = [
'title' => 'Title',
'slug' => 'Slug',
'description' => 'Description',
'viewportWidth' => 'Viewport Width',
'inserter' => 'Inserter',
'categories' => 'Categories',
'keywords' => 'Keywords',
'blockTypes' => 'Block Types',
'postTypes' => 'Post Types',
'templateTypes' => 'Template Types',
];
$pattern = get_file_data( $file, $default_headers );

if ( isset( $pattern['slug'] ) ) {
$properties_to_parse = [
'categories',
'keywords',
'blockTypes',
'postTypes',
'templateTypes',
];
// For properties of type array, parse data as comma-separated.
foreach ( $properties_to_parse as $property ) {
if ( ! empty( $pattern[ $property ] ) ) {
$pattern[ $property ] = array_filter( wp_parse_list( (string) $pattern[ $property ] ) );
} else {
unset( $pattern[ $property ] );
}
}

$pattern['filePath'] = $file;
register_block_pattern( $pattern['slug'], $pattern );
}
}
}
}

Patterns::init();
Loading