",
7 | "license-name": "GPL-2.0+",
8 | "type": "parserhook",
9 | "AutoloadClasses": {
10 | "SimpleMathJaxHooks": "SimpleMathJaxHooks.php"
11 | },
12 | "config": {
13 | "SmjUseCdn": {"value":true, "description":"true to load mathjax from CDN"},
14 | "SmjUseChem": {"value":true, "description":"true to enabled chem tag"},
15 | "SmjDisplayMath": {"value":[], "description":"MathJax.tex.displayMath"},
16 | "SmjExtraInlineMath": {"value":[], "description":"MathJax.tex.inlineMath"},
17 | "SmjIgnoreHtmlClass": {"value":"mathjax_ignore|comment|diff-(context|addedline|deletedline)", "description":"MathJax.options.ignoreHtmlClass"},
18 | "SmjScale": {"value":1, "description":"MathJax.chtml.scale"},
19 | "SmjEnableMenu": {"value":true, "description":"MathJax.options.enableMenu"},
20 | "SmjDisplayAlign": {"value":"left", "description":"MathJax.chtml.displayAlign"},
21 | "SmjWrapDisplaystyle": {"value":true, "description":"true to wrap with displaystyle"},
22 | "SmjEnableHtmlAttributes": {"value":false, "description":"true to process attributes of math tag"}
23 | },
24 | "Hooks": {
25 | "ParserFirstCallInit": "SimpleMathJaxHooks::onParserFirstCallInit"
26 | },
27 | "ResourceModules": {
28 | "ext.SimpleMathJax": {
29 | "scripts": ["resources/ext.SimpleMathJax.js"],
30 | "targets": ["desktop", "mobile"]
31 | }
32 | },
33 | "ResourceFileModulePaths": {
34 | "localBasePath": "",
35 | "remoteExtPath": "SimpleMathJax"
36 | },
37 | "manifest_version": 2
38 | }
39 |
--------------------------------------------------------------------------------
/SimpleMathJaxHooks.php:
--------------------------------------------------------------------------------
1 | addJsConfigVars( 'wgSmjUseCdn', $wgSmjUseCdn );
11 | $wgOut->addJsConfigVars( 'wgSmjUseChem', $wgSmjUseChem );
12 | $wgOut->addJsConfigVars( 'wgSmjDisplayMath', $wgSmjDisplayMath );
13 | $wgOut->addJsConfigVars( 'wgSmjExtraInlineMath', $wgSmjExtraInlineMath );
14 | $wgOut->addJsConfigVars( 'wgSmjIgnoreHtmlClass', $wgSmjIgnoreHtmlClass );
15 | $wgOut->addJsConfigVars( 'wgSmjScale', $wgSmjScale );
16 | $wgOut->addJsConfigVars( 'wgSmjEnableMenu', $wgSmjEnableMenu );
17 | $wgOut->addJsConfigVars( 'wgSmjDisplayAlign', $wgSmjDisplayAlign );
18 | $wgOut->addJsConfigVars( 'wgSmjEnableHtmlAttributes', $wgSmjEnableHtmlAttributes );
19 | $wgOut->addModules( [ 'ext.SimpleMathJax' ] );
20 | $wgOut->addModules( [ 'ext.SimpleMathJax.mobile' ] ); // For MobileFrontend
21 |
22 | $parser->setHook( 'math', __CLASS__ . '::renderMath' );
23 | if( $wgSmjUseChem ) $parser->setHook( 'chem', __CLASS__ . '::renderChem' ); }
24 |
25 | public static function renderMath($tex, array $args, Parser $parser, PPFrame $frame ) {
26 | global $wgSmjWrapDisplaystyle, $wgSmjEnableHtmlAttributes;
27 |
28 | if( !$wgSmjEnableHtmlAttributes ) $args = [];
29 | if( !isset($args["chem"]) ) {
30 | $tex = str_replace('\>', '\;', $tex);
31 | $tex = str_replace('<', '\lt ', $tex);
32 | $tex = str_replace('>', '\gt ', $tex);
33 | }
34 | if( !isset($args["display"]) ) {
35 | if( $wgSmjWrapDisplaystyle ) $tex = "\\displaystyle{ $tex }";
36 | } else switch ($args["display"]) {
37 | case "":
38 | break;
39 | case "inline":
40 | $tex = "\\textstyle{ $tex }";
41 | break;
42 | case "block":
43 | $tex = "\\displaystyle{ $tex }";
44 | break;
45 | default:
46 | return self::renderError('SimpleMathJax: Invalid attribute value: display="' . $args["display"] . '"');
47 | }
48 | return self::renderTex($tex, $parser, $args);
49 | }
50 |
51 | public static function renderChem($tex, array $args, Parser $parser, PPFrame $frame ) {
52 | global $wgSmjEnableHtmlAttributes;
53 |
54 | if( !$wgSmjEnableHtmlAttributes ) $args = [];
55 | return self::renderTex("\\ce{ $tex }", $parser, $args);
56 | }
57 |
58 | private static function renderTex($tex, $parser, $args) {
59 | global $wgSmjEnableHtmlAttributes;
60 |
61 | $hookContainer = MediaWiki\MediaWikiServices::getInstance()->getHookContainer();
62 | $attributes = [ "style" => "opacity:.5" ];
63 | $attributes["class"] = ($args["class"] ?? '');
64 | if( !$wgSmjEnableHtmlAttributes ) {
65 | $attributes["class"] .= " smj-container";
66 | }
67 | $inherit_tags = [ "id", "title", "lang", "dir" ];
68 | foreach( $inherit_tags as $tag ) {
69 | if( isset($args[$tag]) ) $attributes[$tag] = $args[$tag];
70 | }
71 | $hookContainer->run( "SimpleMathJaxAttributes", [ &$attributes, $tex ] );
72 | if( $wgSmjEnableHtmlAttributes && !isset($args["debug"]) ) {
73 | $attributes["class"] .= " smj-container";
74 | }
75 |
76 | if( isset($args["display"]) && $args["display"] == "block" ) {
77 | $element = Html::Element( "span", $attributes, "\\begin{displaymjx}{$tex}\\end{displaymjx}" );
78 | } else {
79 | $element = Html::Element( "span", $attributes, "[math]{$tex}[/math]" );
80 | }
81 | return [$element, 'markerType'=>'nowiki'];
82 | }
83 |
84 | private static function renderError($str) {
85 | $attributes = [ "class" => "error texerror" ];
86 | $element = Html::Element( "strong", $attributes, $str );
87 | return [$element, 'markerType'=>'nowiki'];
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/resources/ext.SimpleMathJax.js:
--------------------------------------------------------------------------------
1 | mw.hook( 'wikipage.content' ).add( function ( $content ) {
2 | window.MathJax = {
3 | tex: {
4 | inlineMath: mw.config.get('wgSmjExtraInlineMath').concat([['[math]','[/math]']]),
5 | displayMath: mw.config.get('wgSmjDisplayMath'),
6 | packages: mw.config.get('wgSmjUseChem') ? {'[+]': ['mhchem']} : {},
7 | macros: {
8 | AA: "{\u00c5}",
9 | alef: "{\\aleph}",
10 | alefsym: "{\\aleph}",
11 | Alpha: "{\\mathrm{A}}",
12 | and: "{\\land}",
13 | ang: "{\\angle}",
14 | Bbb: "{\\mathbb}",
15 | Beta: "{\\mathrm{B}}",
16 | bold: "{\\mathbf}",
17 | bull: "{\\bullet}",
18 | C: "{\\mathbb{C}}",
19 | Chi: "{\\mathrm{X}}",
20 | clubs: "{\\clubsuit}",
21 | cnums: "{\\mathbb{C}}",
22 | Complex: "{\\mathbb{C}}",
23 | coppa: "{\u03D9}",
24 | Coppa: "{\u03D8}",
25 | Dagger: "{\\ddagger}",
26 | Digamma: "{\u03DC}",
27 | darr: "{\\downarrow}",
28 | dArr: "{\\Downarrow}",
29 | Darr: "{\\Downarrow}",
30 | dashint: "{\\unicodeInt{x2A0D}}",
31 | ddashint: "{\\unicodeInt{x2A0E}}",
32 | diamonds: "{\\diamondsuit}",
33 | empty: "{\\emptyset}",
34 | Epsilon: "{\\mathrm{E}}",
35 | Eta: "{\\mathrm{H}}",
36 | euro: "{\u20AC}",
37 | exist: "{\\exists}",
38 | geneuro: "{\u20AC}",
39 | geneuronarrow: "{\u20AC}",
40 | geneurowide: "{\u20AC}",
41 | H: "{\\mathbb{H}}",
42 | hAar: "{\\Leftrightarrow}",
43 | harr: "{\\leftrightarrow}",
44 | Harr: "{\\Leftrightarrow}",
45 | hearts: "{\\heartsuit}",
46 | image: "{\\Im}",
47 | infin: "{\\infty}",
48 | Iota: "{\\mathrm{I}}",
49 | isin: "{\\in}",
50 | Kappa: "{\\mathrm{K}}",
51 | koppa: "{\u03DF}",
52 | Koppa: "{\u03DE}",
53 | lang: "{\\langle}",
54 | larr: "{\\leftarrow}",
55 | Larr: "{\\Leftarrow}",
56 | lArr: "{\\Leftarrow}",
57 | lrarr: "{\\leftrightarrow}",
58 | Lrarr: "{\\Leftrightarrow}",
59 | lrArr: "{\\Leftrightarrow}",
60 | Mu: "{\\mathrm{M}}",
61 | N: "{\\mathbb{N}}",
62 | natnums: "{\\mathbb{N}}",
63 | Nu: "{\\mathrm{N}}",
64 | O: "{\\emptyset}",
65 | oiint: "{\\unicodeInt{x222F}}",
66 | oiiint: "{\\unicodeInt{x2230}}",
67 | ointctrclockwise: "{\\unicodeInt{x2233}}",
68 | officialeuro: "{\u20AC}",
69 | Omicron: "{\\mathrm{O}}",
70 | or: "{\\lor}",
71 | P: "{\u00B6}",
72 | pagecolor: ["",1],
73 | part: "{\\partial}",
74 | plusmn: "{\\pm}",
75 | Q: "{\\mathbb{Q}}",
76 | R: "{\\mathbb{R}}",
77 | rang: "{\\rangle}",
78 | rarr: "{\\rightarrow}",
79 | Rarr: "{\\Rightarrow}",
80 | rArr: "{\\Rightarrow}",
81 | real: "{\\Re}",
82 | reals: "{\\mathbb{R}}",
83 | Reals: "{\\mathbb{R}}",
84 | Rho: "{\\mathrm{P}}",
85 | sdot: "{\\cdot}",
86 | sampi: "{\u03E1}",
87 | Sampi: "{\u03E0}",
88 | sect: "{\\S}",
89 | spades: "{\\spadesuit}",
90 | stigma: "{\u03DB}",
91 | Stigma: "{\u03DA}",
92 | sub: "{\\subset}",
93 | sube: "{\\subseteq}",
94 | supe: "{\\supseteq}",
95 | Tau: "{\\mathrm{T}}",
96 | textvisiblespace: "{\u2423}",
97 | thetasym: "{\\vartheta}",
98 | uarr: "{\\uparrow}",
99 | uArr: "{\\Uparrow}",
100 | Uarr: "{\\Uparrow}",
101 | unicodeInt: ["{\\mathop{\\vcenter{\\mathchoice{\\huge\\unicode{#1}\\,}{\\unicode{#1}}{\\unicode{#1}}{\\unicode{#1}}}\\,}\\nolimits}", 1],
102 | varcoppa: "{\u03D9}",
103 | varstigma: "{\u03DB}",
104 | varointclockwise: "{\\unicodeInt{x2232}}",
105 | vline: ["{\\smash{\\large\\lvert #1}", 0],
106 | weierp: "{\\wp}",
107 | Z: "{\\mathbb{Z}}",
108 | Zeta: "{\\mathrm{Z}}"
109 | },
110 | environments: {
111 | displaymjx: ["", ""]
112 | }
113 | },
114 | options: {
115 | ignoreHtmlClass: mw.config.get('wgSmjIgnoreHtmlClass'),
116 | processHtmlClass: mw.config.get('wgSmjEnableHtmlAttributes') ? "mathjax_process|smj-container" : "mathjax_process"
117 | },
118 | chtml: {
119 | scale: mw.config.get('wgSmjScale'),
120 | displayAlign: mw.config.get('wgSmjDisplayAlign')
121 | },
122 | loader: {
123 | load: mw.config.get('wgSmjUseChem') ? ['[tex]/mhchem'] : []
124 | },
125 | startup: {
126 | pageReady: () => {
127 | return MathJax.startup.defaultPageReady().then(() => {
128 | $(mw.config.get('wgSmjEnableHtmlAttributes') ? "span.smj-container > .MathJax" : ".MathJax").parent().css('opacity',1);
129 | });
130 | }
131 | }
132 | };
133 | (function () {
134 | var script = document.createElement('script');
135 | script.src = mw.config.get('wgSmjUseCdn')
136 | ? 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js'
137 | : mw.config.get('wgExtensionAssetsPath') + '/SimpleMathJax/resources/MathJax/es5/tex-chtml.js';
138 | script.async = true;
139 | document.head.appendChild(script);
140 | })();
141 | });
142 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | The SimpleMathJax extension enables MathJax, a Javascript library, for typesetting TeX formula in MediaWiki inside math environments.
2 |
3 | https://www.mediawiki.org/wiki/Extension:SimpleMathJax
4 |
5 |
6 | # Installation
7 | * git clone in extensions directory
8 | * Using CDN is recommended. Because it's much faster than using local resources in most cases. ("the benefits of using a CDN")
9 | ```Bash
10 | $ git clone https://github.com/jmnote/SimpleMathJax.git
11 | ```
12 |
13 | * (Optional) If you want to use not CDN but local mathjax scripts, you can use git clone recursive.
14 | ```Bash
15 | $ git clone --recursive https://github.com/jmnote/SimpleMathJax.git
16 | ```
17 |
18 | * LocalSettings.php
19 | ```PHP
20 | wfLoadExtension( 'SimpleMathJax' );
21 | ```
22 |
23 | # Optional Settings
24 | | Setting name | Description | default value | custom value example |
25 | | ------------------------ | -------------------------------- | ------------------------- | --------------------------- |
26 | | `$wgSmjUseCdn` | use CDN or local scripts | true | false |
27 | | `$wgSmjUseChem` | enable chem tag | true | false |
28 | | `$wgSmjEnableMenu` | MathJax.options.enableMenu | true | false |
29 | | `$wgSmjDisplayMath` | MathJax.tex.displayMath | [] | [['$$','$$'],['\\[','\\]']] |
30 | | `$wgSmjExtraInlineMath` | MathJax.tex.inlineMath | [] | [['\\(', '\\)']] |
31 | | `$wgSmjIgnoreHtmlClass` | MathJax.options.ignoreHtmlClass | "mathjax_ignore\|comment\|