Skip to content

Commit

Permalink
Add MathML support (ampproject#12836)
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Silverstein authored and gzgogo committed Jan 26, 2018
1 parent 92e33da commit ee61d94
Show file tree
Hide file tree
Showing 11 changed files with 327 additions and 1 deletion.
3 changes: 2 additions & 1 deletion 3p/ampcontext-integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ export class IntegrationAmpContext extends AbstractAmpContext {
// available.
return (this.embedType_ === 'facebook'
|| this.embedType_ === 'twitter'
|| this.embedType_ == 'github');
|| this.embedType_ === 'github'
|| this.embedType_ === 'mathml');
}

/** @return {!Window} */
Expand Down
2 changes: 2 additions & 0 deletions 3p/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import {MessageType} from '../src/3p-frame-messaging';
// 3P - please keep in alphabetic order
import {facebook} from './facebook';
import {github} from './github';
import {mathml} from './mathml';
import {reddit} from './reddit';
import {twitter} from './twitter';

Expand Down Expand Up @@ -330,6 +331,7 @@ register('loka', loka);
register('mads', mads);
register('mantis-display', mantisDisplay);
register('mantis-recommend', mantisRecommend);
register('mathml', mathml);
register('mediaimpact', mediaimpact);
register('medianet', medianet);
register('mediavine', mediavine);
Expand Down
70 changes: 70 additions & 0 deletions 3p/mathml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copyright 2018 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {writeScript} from './3p';
import {user} from '../src/log';

/**
* Get the correct script for the mathml formula.
*
* Use writeScript: Failed to execute 'write' on 'Document': It isn't possible
* to write into a document from an asynchronously-loaded external script unless
* it is explicitly opened.
*
* @param {!Window} global
* @param {string} scriptSource The source of the script, different for post and comment embeds.
*/
function getMathmlJs(global, scriptSource, cb) {
writeScript(global, scriptSource, function() {
cb(global.MathJax);
});
}

/**
* @param {!Window} global
* @param {!Object} data
*/
export function mathml(global, data) {
user().assert(
data.formula,
'The formula attribute is required for <amp-mathml> %s',
data.element);

getMathmlJs(
global,
'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML',
mathjax => {
// Dimensions are given by the parent frame.
delete data.width;
delete data.height;
const div = document.createElement('div');
div.setAttribute('id','mathmlformula');
div.textContent = data.formula;
global.document.body.appendChild(div);
mathjax.Hub.Queue(function() {
const rendered = document.getElementById('MathJax-Element-1-Frame');
// Remove built in mathjax margins.
const display = document.getElementsByClassName('MJXc-display');
if (display[0]) {
display[0].setAttribute('style','margin-top:0;margin-bottom:0');
context.requestResize(
rendered./*OK*/offsetWidth,
rendered./*OK*/offsetHeight
);
}
});
}
);
}
7 changes: 7 additions & 0 deletions ads/ads.extern.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ data.src;
//twitter.js
data.tweetid

//mathml.js
data.formula
var mathjax
mathjax.Hub
mathjax.Hub.Queue
window.MathJax

// Under ads/google folder

// adsense.js
Expand Down
31 changes: 31 additions & 0 deletions examples/amp-mathml.amp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<html >
<head>
<meta charset="utf-8">
<title>amp-mathml example</title>
<link rel="canonical" href="amps.html">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async custom-element="amp-mathml" src="https://cdn.ampproject.org/v0/amp-mathml-0.1.js"></script>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>
<h2>The Quadratic Formula</h2>
<amp-mathml
layout="container"
data-formula="\[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]">
</amp-mathml>
<h2>Cauchy's Integral Formula</h2>
<amp-mathml
layout="container"
data-formula="\[f(a) = \frac{1}{2\pi i} \oint\frac{f(z)}{z-a}dz\]">
</amp-mathml>
<h2>Double angle formula for Cosines</h2>
<amp-mathml
layout="container"
data-formula="\[ \cos(θ+φ)=\cos(θ)\cos(φ)−\sin(θ)\sin(φ) \]">
</amp-mathml>
<h2>Inline formula.</h2>
This is an example of a formula placed inline in the middle of a block of text. <amp-mathml layout="container" inline data-formula="\[ \cos(θ+φ) \]"></amp-mathml> This shows how the formula will fit inside a block of text and can be styled with CSS.
</body>
</html>
27 changes: 27 additions & 0 deletions extensions/amp-mathml/0.1/amp-mathml.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Copyright 2018 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software'
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

amp-mathml[inline] {
display: inline-block;
}

amp-mathml {
height: 1px;
}

amp-mathml[inline] {
width: 1px;
}
71 changes: 71 additions & 0 deletions extensions/amp-mathml/0.1/amp-mathml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Copyright 2018 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Layout} from '../../../src/layout';
import {getIframe} from '../../../src/3p-frame';
import {removeElement} from '../../../src/dom';
import {listenFor} from '../../../src/iframe-helper';
import {CSS} from '../../../build/amp-mathml-0.1.css';

export class AmpMathml extends AMP.BaseElement {

/** @param {!AmpElement} element */
constructor(element) {
super(element);

/** @private {?HTMLIFrameElement} */
this.iframe_ = null;
}

preconnectCallback() {
this.preconnect.url('https://cdnjs.cloudflare.com');
}

layoutCallback() {
const iframe = getIframe(this.win, this.element, 'mathml');
this.applyFillContent(iframe);
// Triggered by context.updateDimensions() inside the iframe.
listenFor(iframe, 'embed-size', data => {
if (!this.element.hasAttribute('inline')) {
// Don't change the width if not inlined.
data['width'] = undefined;
}
this.element.getResources()./*OK*/changeSize(
this.element, data['height'], data['width']);
}, /* opt_is3P */true);
this.element.appendChild(iframe);
this.iframe_ = iframe;
return this.loadPromise(iframe);
}

unlayoutCallback() {
if (this.iframe_) {
removeElement(this.iframe_);
this.iframe_ = null;
}
return true;
}

/** @override */
isLayoutSupported(layout) {
return layout == Layout.CONTAINER;
}

}


AMP.extension('amp-mathml', '0.1', AMP => {
AMP.registerElement('amp-mathml', AmpMathml, CSS);
});
1 change: 1 addition & 0 deletions extensions/amp-mathml/OWNERS.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- adamsilverstein
72 changes: 72 additions & 0 deletions extensions/amp-mathml/amp-mathml.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!--
Copyright 2018 The AMP HTML Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS-IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

# <a name="`amp-mathml`"></a> `amp-mathml`

<table>
<tr>
<td width="40%"><strong>Description</strong></td>
<td>Displays a <a href="https://www.w3.org/Math/">MathML formula</a>.</td>
</tr>
<tr>
<td width="40%"><strong>Required Script</strong></td>
<td><code>&lt;script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-mathml-0.1.js">&lt;/script></code></td>
</tr>
<tr>
<td class="col-fourty"><strong><a href="https://www.ampproject.org/docs/guides/responsive/control_layout.html">Supported Layouts</a></strong></td>
<td>container</td>
</tr>
<tr>
<td width="40%"><strong>Examples</strong></td>
<td><a href="https://ampbyexample.com/components/amp-mathml/">Annotated code example for amp-mathml</a></td>
</tr>
</table>

## Behavior

This extension creates an iframe and renders a MathML formula.

#### Example: The Quadratic Formula

```html
<amp-mathml layout="container" data-formula="\[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]">
</amp-mathml>
```

#### Example: Cauchy's Integral Formula

```html
<amp-mathml layout="container" data-formula="\[f(a) = \frac{1}{2\pi i} \oint\frac{f(z)}{z-a}dz\]">
</amp-mathml>
```
#### Example: Double angle formula for Cosines

```html
<amp-mathml layout="container" data-formula="\[ \cos(θ+φ)=\cos(θ)\cos(φ)−\sin(θ)\sin(φ) \]">
</amp-mathml>
```
#### Example: Inline formula.

This is an example of a formula placed inline in the middle of a block of text. `<amp-mathml layout="container" inline data-formula="\[ \cos(θ+φ) \]"></amp-mathml>` This shows how the formula will fit inside a block of text and can be styled with CSS.

## Attributes

##### data-formula (required)

The formula to render.

## Validation
See [amp-mathml rules](https://github.com/ampproject/amphtml/blob/master/extensions/amp-mathml/validator-amp-mathml.protoascii) in the AMP validator specification.
43 changes: 43 additions & 0 deletions extensions/amp-mathml/validator-amp-mathml.protoascii
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#
# Copyright 2018 The AMP HTML Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the license.
#

tags: { # amp-mathml
html_format: AMP
tag_name: "SCRIPT"
extension_spec: {
name: "amp-html"
allowed_versions: "0.1"
allowed_versions: "latest"
}
attr_lists: "common-extension-attrs"
}

tags: { # <amp-mathml>
html_format: AMP
tag_name: "AMP-MATHML"
requires_extension: "amp-mathml"
attrs: {
name: "formula"
mandatory: true
}
attrs: {
name: "inline"
}
attr_lists: "extended-amp-global"
amp_layout: {
supported_layouts: CONTAINER
}
}
1 change: 1 addition & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ declareExtension('amp-lightbox', '0.1', true);
declareExtension('amp-lightbox-viewer', '0.1', true);
declareExtension('amp-list', '0.1', false);
declareExtension('amp-live-list', '0.1', true);
declareExtension('amp-mathml', '0.1', true);
declareExtension('amp-mustache', '0.1', false);
declareExtension('amp-nexxtv-player', '0.1', false);
declareExtension('amp-o2-player', '0.1', false);
Expand Down

0 comments on commit ee61d94

Please sign in to comment.