-
Notifications
You must be signed in to change notification settings - Fork 7
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 AMP compatibility and implement rendering on archive/home pages #32
Changes from all commits
79a7337
5f767ca
cbe8787
32be062
02c0bd2
1f27736
a72edfa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,12 +14,64 @@ | |
* | ||
* @package mathml-block | ||
*/ | ||
|
||
namespace MathMLBlock; | ||
|
||
/** | ||
* Enqueue the admin JavaScript assets. | ||
*/ | ||
use WP_Block_Type_Registry; | ||
use WP_Scripts; | ||
|
||
const BLOCK_NAME = 'mathml/mathmlblock'; | ||
|
||
const MATHJAX_SCRIPT_HANDLE = 'mathjax'; | ||
|
||
const MATHJAX_SCRIPT_URL = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js'; | ||
|
||
/** | ||
* Determine whether the response will be an AMP page. | ||
* | ||
* @return bool | ||
*/ | ||
function is_amp() { | ||
return ( | ||
( function_exists( 'amp_is_request' ) && \amp_is_request() ) | ||
|| | ||
( function_exists( 'is_amp_endpoint' ) && \is_amp_endpoint() ) | ||
); | ||
} | ||
|
||
/** | ||
* Register MathJax script. | ||
* | ||
* @param WP_Scripts $scripts Scripts. | ||
*/ | ||
function register_mathjax_script( WP_Scripts $scripts ) { | ||
|
||
/** | ||
* Filters the MathJax config string. | ||
* | ||
* @param string $config MathHax config. | ||
*/ | ||
$config_string = apply_filters( 'mathml_block_mathjax_config', 'TeX-MML-AM_CHTML' ); | ||
|
||
$src = add_query_arg( | ||
array( | ||
'config' => rawurlencode( $config_string ) | ||
), | ||
MATHJAX_SCRIPT_URL | ||
); | ||
|
||
$scripts->add( MATHJAX_SCRIPT_HANDLE, $src, array(), null, false ); | ||
|
||
// Make JavaScript translatable. | ||
$scripts->set_translations( MATHJAX_SCRIPT_HANDLE, 'mathml-block' ); | ||
} | ||
add_action( 'wp_default_scripts', __NAMESPACE__ . '\register_mathjax_script' ); | ||
|
||
/** | ||
* Enqueue the admin JavaScript assets. | ||
*/ | ||
function mathml_block_enqueue_scripts() { | ||
wp_enqueue_script( MATHJAX_SCRIPT_HANDLE ); | ||
|
||
wp_enqueue_script( | ||
'mathml-block', | ||
|
@@ -28,45 +80,127 @@ function mathml_block_enqueue_scripts() { | |
'', | ||
true | ||
); | ||
} | ||
add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\mathml_block_enqueue_scripts' ); | ||
|
||
// Maka JavaScript translatable. | ||
wp_set_script_translations( 'mathml-block', 'mathml-block' ); | ||
/** | ||
* Register block. | ||
*/ | ||
function register_block() { | ||
if ( ! function_exists( 'register_block_type' ) ) { | ||
return; | ||
} | ||
|
||
// Filter the MathJax config string. | ||
$config_string = apply_filters( 'mathml_block_mathjax_config', 'TeX-MML-AM_CHTML' ); | ||
$registry = WP_Block_Type_Registry::get_instance(); | ||
|
||
wp_enqueue_script( | ||
'mathjax', | ||
'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=' . $config_string | ||
// @todo This can probably be de-duplicated in the JS code with registerBlockType. | ||
$attributes = array( | ||
'formula' => array( | ||
'source' => 'html', | ||
'selector' => 'div', | ||
'type' => 'string', | ||
), | ||
); | ||
|
||
if ( $registry->is_registered( BLOCK_NAME ) ) { | ||
$block = $registry->get_registered( BLOCK_NAME ); | ||
$block->render_callback = __NAMESPACE__ . '\render_block'; | ||
$block->attributes = array_merge( $block->attributes, $attributes ); | ||
} else { | ||
register_block_type( | ||
BLOCK_NAME, | ||
[ | ||
'render_callback' => __NAMESPACE__ . '\render_block', | ||
'attributes' => $attributes, | ||
] | ||
); | ||
} | ||
} | ||
add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\mathml_block_enqueue_scripts' ); | ||
add_action( 'init', __NAMESPACE__ . '\register_block' ); | ||
|
||
/** | ||
* Potentially enqueue the front end mathjax script, if any mathml blocks are detected in the content. | ||
* Add async attribute to MathJax script tag. | ||
* | ||
* @param string $tag Script tag. | ||
* @param string $handle Script handle. | ||
* | ||
* @return string Script tag. | ||
*/ | ||
function potentially_add_front_end_mathjax_script() { | ||
global $post; | ||
|
||
// Only apply on singular pages. | ||
if ( ! is_singular() ) { | ||
return; | ||
function add_async_to_mathjax_script_loader_tag( $tag, $handle ) { | ||
if ( MATHJAX_SCRIPT_HANDLE === $handle ) { | ||
$tag = preg_replace( '/(?<=<script\s)/', ' async ', $tag ); | ||
} | ||
return $tag; | ||
} | ||
|
||
// Check the content for mathml blocks. | ||
$has_mathml_block = strpos( $post->post_content, 'wp:mathml/mathmlblock' ); | ||
$has_mathml_inline = strpos( $post->post_content, '<mathml>' ); | ||
if ( false === $has_mathml_block && false === $has_mathml_inline ) { | ||
return; | ||
/** | ||
* Render block. | ||
* | ||
* Creates an <amp-mathml> element on AMP responses. | ||
* | ||
* @param array $attributes Attributes. | ||
* @param string $content Content. | ||
* | ||
* @return string Rendered block. | ||
*/ | ||
function render_block( $attributes, $content = '' ) { | ||
if ( is_admin() || ! preg_match( '#^(?P<start_div>\s*<div.*?>)(?P<formula>.+)(?P<end_div></div>\s*)$#s', $content, $matches ) ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this regex do? The goal is to only enqueue the mathjax script on the front end when there are (inline) tags or mathml blocks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The regex is for parsing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently the regex needs to be adapted to support inline |
||
return $content; | ||
} | ||
|
||
// Filter the MathJax config string. | ||
$config_string = apply_filters( 'mathml_block_mathjax_config', 'TeX-MML-AM_CHTML' ); | ||
if ( is_amp() ) { | ||
static $printed_style = false; | ||
if ( ! $printed_style ) { | ||
// Add same margins as .MJXc-display. | ||
?> | ||
<style class="amp-mathml"> | ||
.wp-block-mathml-mathmlblock amp-mathml { margin: 1em 0; } | ||
</style> | ||
<?php | ||
Comment on lines
+154
to
+159
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was wrong. It caused a bug in legacy Reader mode. See #38. |
||
$printed_style = true; | ||
} | ||
|
||
// Enqueue the MathJax script for front end formula display. | ||
wp_register_script( 'mathjax', 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=' . $config_string ); | ||
wp_enqueue_script( 'mathjax' ); | ||
return sprintf( | ||
'%s<amp-mathml layout="container" data-formula="%s"><span placeholder>%s</span></amp-mathml>%s', | ||
$matches['start_div'], | ||
esc_attr( $matches['formula'] ), | ||
esc_html( $matches['formula'] ), | ||
$matches['end_div'] | ||
); | ||
} elseif ( ! wp_script_is( MATHJAX_SCRIPT_HANDLE, 'done' ) ) { | ||
ob_start(); | ||
add_filter( 'script_loader_tag', __NAMESPACE__ . '\add_async_to_mathjax_script_loader_tag', 10, 2 ); | ||
wp_scripts()->do_items( MATHJAX_SCRIPT_HANDLE ); | ||
remove_filter( 'script_loader_tag', __NAMESPACE__ . '\add_async_to_mathjax_script_loader_tag' ); | ||
$scripts = ob_get_clean(); | ||
|
||
$content = $matches['start_div'] . $matches['formula'] . $scripts . $matches['end_div']; | ||
} | ||
return $content; | ||
} | ||
|
||
/** | ||
* Filter content to transform inline math. | ||
* | ||
* @param string $content Content. | ||
* @return string Replaced content. | ||
*/ | ||
function filter_content( $content ) { | ||
return preg_replace_callback( | ||
'#(?P<start_tag><mathml>)(?P<formula>.+)(?P<end_tag></mathml>)#s', | ||
static function ( $matches ) { | ||
if ( is_amp() ) { | ||
return sprintf( | ||
'<amp-mathml layout="container" data-formula="%s" inline><span placeholder>%s</span></amp-mathml>', | ||
esc_attr( $matches['formula'] ), | ||
esc_html( $matches['formula'] ) | ||
); | ||
} else { | ||
wp_enqueue_script( MATHJAX_SCRIPT_HANDLE ); | ||
return $matches['start_tag'] . $matches['formula'] . $matches['end_tag']; | ||
} | ||
}, | ||
$content | ||
); | ||
} | ||
add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\potentially_add_front_end_mathjax_script' ); | ||
add_filter( 'the_content', __NAMESPACE__ . '\filter_content', 20 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@westonruter is this the newer 2.0+ preferred way to detect is_amp?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In reality it is identical. We just renamed
is_amp_endpoint()
toamp_is_request()
and then added a soft-deprecatedis_amp_endpoint()
which callsamp_is_request()
. This was done just to start using prefixed functions everywhere. We're not going to hard-deprecate it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 ah, ok so purely a naming convention based change. thanks for clarifying.