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

Blocks: Add formula typesetting block. #58912

Draft
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Draft
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
9 changes: 9 additions & 0 deletions docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,15 @@ A submission button for forms. ([Source](https://github.com/WordPress/gutenberg/
- **Supports:**
- **Attributes:**

## Formula

Render mathematical formulæ. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/formula))

- **Name:** core/formula
- **Category:** text
- **Supports:** align, anchor, spacing (blockGap, margin, padding), ~~html~~
- **Attributes:** alt, formulaSource

## Classic

Use the classic WordPress editor. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/freeform))
Expand Down
1 change: 1 addition & 0 deletions lib/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function gutenberg_reregister_core_block_types() {
'column',
'columns',
'details',
'formula',
'form-input',
'form-submit-button',
'group',
Expand Down
39 changes: 39 additions & 0 deletions packages/block-library/src/formula/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "core/formula",
"title": "Formula",
"category": "text",
"description": "Render mathematical formulæ.",
"textdomain": "default",
"attributes": {
"formulaSource": {
"type": "string",
"selector": "img",
"source": "attribute",
"attribute": "data-formula"
},
"alt": {
"type": "string",
"selector": "img",
"source": "attribute",
"attribute": "alt"
}
},
"supports": {
"anchor": true,
"align": true,
"html": false,
"spacing": {
"padding": true,
"margin": [ "top", "bottom" ],
"blockGap": true,
"__experimentalDefaultControls": {
"padding": true,
"blockGap": true
}
}
},
"editorStyle": "wp-block-formula",
"style": "wp-block-formula"
}
97 changes: 97 additions & 0 deletions packages/block-library/src/formula/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* WordPress dependencies
*/
import { useBlockProps, PlainText } from '@wordpress/block-editor';

let loading = false;

const requireMathJaxScript = () => {
if ( loading ) {
return;
}

loading = true;
const script = document.createElement( 'script' );
script.id = 'MathJax-script';
script.setAttribute( 'async', '' );
script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';
document.head.appendChild( script );
};

document.addEventListener( 'readystatechange', () => {
if ( document.readyState === 'complete' ) {
requireMathJaxScript();
}
} );

/**
* Generate an SVG data URI for embedding in an IMG element src.
*
* @param {Element} svg The input SVG
* @return {string} Data URI for safely embedding SVG as a string.
*/
const svgElementToDataURI = ( svg ) => {
return `data:image/svg+xml,${ encodeURIComponent(
svg.childNodes[ 0 ].outerHTML
) }`;
};

export const Edit = ( { attributes, isSelected, setAttributes } ) => {
const blockProps = useBlockProps();

return (
<div { ...blockProps }>
<figure>
{ isSelected && (
<>
<PlainText
value={ attributes.formulaSource }
onChange={ ( value ) =>
window.MathJax.tex2svgPromise( value ).then(
( svg ) => {
const errors =
svg.childNodes[ 1 ].querySelectorAll(
'merror'
);

if ( ! errors.length ) {
setAttributes( {
src: svgElementToDataURI( svg ),
formulaSource: value,
errors: null,
} );
} else {
setAttributes( {
formulaSource: value,
errors: [ ...errors ].map(
( error ) =>
error.textContent
),
} );
}
}
)
}
placeholder="a^2 = b^2 + c^2"
/>
<PlainText
value={ attributes.alt }
onChange={ ( alt ) => setAttributes( { alt } ) }
placeholder="How would you describe your formula if your reader cannot read the symbols?"
/>
</>
) }
<img src={ attributes.src } alt={ attributes.alt } />
{ attributes.errors?.length && (
<ul>
{ attributes.errors.map( ( error ) => (
<li key={ error }>{ error }</li>
) ) }
</ul>
) }
</figure>
</div>
);
};

export default Edit;
31 changes: 31 additions & 0 deletions packages/block-library/src/formula/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* WordPress dependencies
*/

/**
* Internal dependencies
*/
import metadata from './block.json';
import Edit from './edit';
import Save from './save';
import initBlock from '../utils/init-block';

const { name } = metadata;

export { metadata, name };

export const settings = {
apiVersion: 3,
icon: 'edit-page',
example: {
attributes: {
formulaSource:
'\\Delta T_{\\text{heatsink}} = 100W\n\\cdot 0.15 \\frac{K}{W} = 15^\\circ C',
alt: "At 100W, the heatsink's temperature will rise by 15 degrees Celsius.",
},
},
save: Save,
edit: Edit,
};

export const init = () => initBlock( { name, metadata, settings } );
31 changes: 31 additions & 0 deletions packages/block-library/src/formula/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* Server-side rendering of the `core/formula` block.
*
* @package WordPress
*/

/**
* Renders the `core/formula` block on server.
*
* @param array $attributes The block attributes.
* @param string $content The block rendered content.
*
* @return string Returns the formula block markup.
*/
function render_block_core_formula( $attributes, $content ) {

Check warning on line 16 in packages/block-library/src/formula/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Unused function parameter $attributes.

Check warning on line 16 in packages/block-library/src/formula/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Unused function parameter $content.
return '<p>Formula!</p>';
}

/**
* Registers the `core/cover` block renderer on server.
*/
function register_block_core_formula() {
register_block_type_from_metadata(
__DIR__ . '/formula',
array(
'render_callback' => 'formula',
)
);
}
add_action( 'init', 'register_block_core_formula' );
20 changes: 20 additions & 0 deletions packages/block-library/src/formula/save.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* WordPress dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';

export const Save = ( { attributes } ) => {
const blockProps = useBlockProps.save();

return (
<figure className="wp-block-formula" { ...blockProps }>
<img
src={ attributes.src }
data-formula-source={ attributes.formulaSource }
alt={ attributes.alt }
/>
</figure>
);
};

export default Save;
2 changes: 2 additions & 0 deletions packages/block-library/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import * as details from './details';
import * as embed from './embed';
import * as file from './file';
import * as form from './form';
import * as formula from './formula';
import * as formInput from './form-input';
import * as formSubmitButton from './form-submit-button';
import * as formSubmissionNotification from './form-submission-notification';
Expand Down Expand Up @@ -154,6 +155,7 @@ const getAllBlocks = () => {
details,
embed,
file,
formula,
group,
html,
latestComments,
Expand Down
Loading