-
Notifications
You must be signed in to change notification settings - Fork 6
/
mathjax.php
274 lines (238 loc) · 8.67 KB
/
mathjax.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
<?php
/**
* MathJax v1.6.0
*
* This plugin allows you to include math formulas in your web pages,
* either using TeX and LaTeX notation, and/or as MathML.
*
* Dual licensed under the MIT or GPL Version 3 licenses, see LICENSE.
* http://benjamin-regler.de/license/
*
* @package MathJax
* @version 1.6.0
* @link <https://github.com/sommerregen/grav-plugin-mathjax>
* @author Benjamin Regler <[email protected]>
* @copyright 2017+, Benjamin Regler
* @license <http://opensource.org/licenses/MIT> MIT
* @license <http://opensource.org/licenses/GPL-3.0> GPLv3
*/
namespace Grav\Plugin;
use Grav\Common\Plugin;
use Grav\Common\Data\Blueprints;
use Grav\Plugin\Shortcodes\BlockShortcode;
use RocketTheme\Toolbox\Event\Event;
/**
* MathJaxPlugin
* @package Grav\Plugin
*/
class MathJaxPlugin extends Plugin
{
/**
* Instance of MathJax class
*
* @var Grav\Plugin\MathJax
*/
protected $mathjax;
/**
* Return a list of subscribed events.
*
* @return array The list of events of the plugin of the form
* 'name' => ['method_name', priority].
*/
public static function getSubscribedEvents()
{
return [
'onPluginsInitialized' => ['onPluginsInitialized', 0]
];
}
/**
* Initialize configuration
*/
public function onPluginsInitialized()
{
// Set admin specific events
if ($this->isAdmin()) {
$this->active = false;
$this->enable([
'onBlueprintCreated' => ['onBlueprintCreated', 0]
]);
return;
}
// Initialize MathJax class
require_once(__DIR__ . '/classes/MathJax.php');
$this->mathjax = new MathJax();
// Process contents order according to weight option
// (default: -5): to process page content right after SmartyPants
$weight = $this->config->get('plugins.mathjax.weight', -5);
// Register events
$this->enable([
'onShortcodesInitialized' => ['onShortcodesInitialized', 0],
'onMarkdownInitialized' => ['onMarkdownInitialized', 0],
'onPageContentRaw' => ['onPageContentRaw', 0],
'onPageContentProcessed' => ['onPageContentProcessed', $weight],
'onTwigInitialized' => ['onTwigInitialized', 0],
'onTwigSiteVariables' => ['onTwigSiteVariables', 0]
]);
}
/**
* Extend page blueprints with MathJax configuration options.
*
* @param Event $event
*/
public function onBlueprintCreated(Event $event)
{
/** @var Blueprints $blueprint */
$blueprint = $event['blueprint'];
if ($blueprint->get('form/fields/tabs')) {
$blueprints = new Blueprints(__DIR__ . '/blueprints');
$extends = $blueprints->get($this->name);
$blueprint->extend($extends, true);
}
}
/**
* Handle the markdown initialized event.
*
* @param Event $event The event containing the markdown parser
*/
public function onMarkdownInitialized(Event $event)
{
/** @var Grav\Common\Markdown\Parsedownextra $markdown */
$markdown = $event['markdown'];
$this->mathjax->setupMarkdown($markdown);
}
/**
* Add content after page content was read into the system.
*
* @param Event $event An event object, when `onPageContentRaw` is
* fired.
*/
public function onPageContentRaw(Event $event)
{
/** @var Page $page */
$page = $event['page'];
$config = $this->mergeConfig($page);
$enabled = ($config->get('enabled') && $config->get('active')) ? true : false;
// Reset MathJax instance
$this->mathjax->reset();
$this->mathjax->enabled($enabled);
if ($enabled) {
// Set X-UA-Compatible meta tag for Internet Explorer
$metadata = $page->metadata();
$metadata['X-UA-Compatible'] = array(
'http_equiv' => 'X-UA-Compatible',
'content' => 'IE=edge'
);
$page->metadata($metadata);
}
}
/**
* Add content after page was processed.
*
* @param Event $event An event object, when `onPageContentProcessed`
* is fired.
*/
public function onPageContentProcessed(Event $event)
{
// Get the page header
$page = $event['page'];
$config = $this->mergeConfig($page);
$enabled = ($config->get('enabled') && $config->get('active')) ? true : false;
// Get modified content, replace all tokens with their
// respective formula and write content back to page
$type = $enabled ? 'html' : 'raw';
$content = $page->getRawContent();
$page->setRawContent($this->mathjax->normalize($content, $type));
}
/**
* Initialize Twig configuration and filters.
*/
public function onTwigInitialized()
{
// Expose function
$this->grav['twig']->twig()->addFilter(
new \Twig_SimpleFilter('mathjax', [$this, 'mathjaxFilter'], ['is_safe' => ['html']])
);
}
/**
* Set needed variables to display MathJax LaTeX formulas.
*/
public function onTwigSiteVariables()
{
/** @var \Grav\Common\Assets $assets */
$assets = $this->grav['assets'];
/** @var Page $page */
$page = $this->grav['page'];
// Skip if active is set to false
$config = $this->mergeConfig($page);
if (!($config->get('enabled') && $config->get('active'))) {
return;
}
// Reset MathJax instance and enable parser
$this->mathjax->reset();
$this->mathjax->enabled(true);
// Add MathJax stylesheet to page
if ($this->config->get('plugins.mathjax.built_in_css')) {
$assets->add('plugins://mathjax/assets/css/mathjax.css');
}
// Add MathJax configuration file to page
if ($this->config->get('plugins.mathjax.built_in_js')) {
$assets->add('plugins://mathjax/assets/js/mathjax.js');
}
// Resolve user data path
$data_path = $this->grav['locator']->findResource('user://data');
// Check if MathJax library was properly installed locally
$installed = file_exists($data_path . DS .'mathjax' . DS . 'MathJax.js');
// Load MathJax library
if ($this->config->get('plugins.mathjax.CDN.enabled') || !$installed) {
// Load MathJax library via CDN
$assets->add($this->config->get('plugins.mathjax.CDN.url'));
} elseif ($installed) {
// Load MathJax library from user data path
$assets->add('user://data/mathjax/MathJax.js');
}
}
/**
* Filter to parse MathJax formula.
*
* @param string $content The content to be filtered.
* @param array $options Array of options for the MathJax formula filter.
*
* @return string The filtered content.
*/
public function mathjaxFilter($content, $params = [])
{
// Get custom user configuration
$page = func_num_args() > 2 ? func_get_arg(2) : $this->grav['page'];
$config = $this->mergeConfig($page, true, $params);
// Enable parser
$this->mathjax->enabled(true);
// Render content
$content = $this->mathjax->render($content, $config, $page);
$content = $this->mathjax->normalize($content);
// Reset MathJax instance
$this->mathjax->reset();
return $content;
}
/**
* Register {{% mathjax %}} shortcode.
*
* @param Event $event An event object.
*/
public function onShortcodesInitialized(Event $event)
{
// Register {{% mathjax %}} shortcode
$event['shortcodes']->register(
new BlockShortcode('mathjax', function($event) {
$weight = $this->config->get('plugins.mathjax.weight', -5);
$this->enable([
'onPageContentProcessed' => ['onPageContentProcessed', $weight]
]);
// Update header variable to bypass evaluation
if (isset($event['page']->header()->mathjax->process)){
$event['page']->header()->mathjax->process = true;
}
return $this->mathjax->mathjaxShortcode($event);
})
);
}
}