Skip to content
Merged
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
1 change: 0 additions & 1 deletion .phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPrivate" />
</rule>
<file>.</file>
<exclude-pattern>\.stubs/</exclude-pattern>
<exclude-pattern>hack/</exclude-pattern>
<exclude-pattern>tests/</exclude-pattern>
<arg name="extensions" value="php"/>
Expand Down
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# AGENTS.md

Run `make checks` before committing. `test` runs plain PHP scripts
(`php tests/*.php`), not PHPUnit. `phpcs` needs `composer install`, which
`make` does automatically.

`hack/demo/demo.sh` / `make screenshots [demo]` render a demo through a
local Docker MediaWiki and regenerate `docs/screenshots/*.png`. Only run
this when asked to, or when a change affects rendering (`resources/`,
`hack/demo/demos.yaml`) — not for routine changes.
23 changes: 18 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
.PHONY: checks test phpcs mathjax
.PHONY: checks test phpcs local-mathjax screenshots

MATHJAX_VERSION_LOCAL ?= 4.1.3
MATHJAX_VERSION_CDN ?= 4
LOCAL_MATHJAX_VERSION ?= 4.1.3

checks: test phpcs ## Everything CI runs before merging (needs `composer install`, PHP >= 8.2)

test: ## Run the pure-PHP test suites
php tests/QuotesTest.php
php tests/RevisionOverridesTest.php

phpcs: vendor/autoload.php ## parallel-lint + minus-x + phpcs against the MediaWiki coding standard
composer test

local-mathjax: ## Pin the bundled local MathJax submodule, e.g. `make local-mathjax LOCAL_MATHJAX_VERSION=4.1.3`
hack/local-mathjax.sh $(LOCAL_MATHJAX_VERSION)

vendor/autoload.php: composer.json
composer install --no-progress

mathjax: ## Pin the local MathJax submodule + CDN major version, e.g. `make mathjax MATHJAX_VERSION_LOCAL=4.1.3 MATHJAX_VERSION_CDN=4`
hack/mathjax.sh $(MATHJAX_VERSION_LOCAL) $(MATHJAX_VERSION_CDN)
screenshots: ## Screenshot a demo page, e.g. `make screenshots custom01` (no demo = every demo in hack/demo/demos.yaml)
hack/demo/demo.sh screenshot $(filter-out $@,$(MAKECMDGOALS))

# Swallows the extra word in `make screenshots custom01` so make doesn't
# treat "custom01" as a target of its own and fail with "No rule to make
# target". Scoped to only fire when `screenshots` is actually one of the
# invoked goals, so an unrelated typo like `make cheks` still fails loudly
# instead of silently no-op'ing.
ifneq ($(filter screenshots,$(MAKECMDGOALS)),)
%:
@:
endif
112 changes: 28 additions & 84 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,98 +6,42 @@ https://www.mediawiki.org/wiki/Extension:SimpleMathJax
# Installation
* git clone in extensions directory
* Using CDN is recommended. Because it's much faster than using local resources in most cases. ("the benefits of using a CDN")
```Bash
```bash
$ git clone https://github.com/jmnote/SimpleMathJax.git
```

* (Optional) If you want to use not CDN but local mathjax scripts, you can use git clone recursive.
```Bash
* (Optional) If you want to use not CDN but local mathjax scripts, you can use git clone recursive, then set `$wgSmjCdnEnabled = false` (see [`$wgSmjCdnEnabled`](docs/configuration.md#wgsmjcdnenabled)).
```bash
$ git clone --recursive https://github.com/jmnote/SimpleMathJax.git
```

* LocalSettings.php
```PHP
```php
wfLoadExtension( 'SimpleMathJax' );
```

# Optional Settings
| Setting name | Description | default value | custom value example |
| ------------------------ | -------------------------------- | ------------------------- | --------------------------- |
| `$wgSmjUseCdn` | use CDN or local scripts | true | false |
| `$wgSmjUseChem` | enable chem tag | true | false |
| `$wgSmjDirectMathJax` | which ones can be written directly | "full" | "none" |
| `$wgSmjEnableMenu` | MathJax.options.enableMenu | true | false |
| `$wgSmjDisplayMath` | MathJax.tex.displayMath | [] | [['$$','$$'],['\\[','\\]']] |
| `$wgSmjExtraInlineMath` | MathJax.tex.inlineMath | [] | [['\\(', '\\)']] |
| `$wgSmjIgnoreHtmlClass` | MathJax.options.ignoreHtmlClass | "mathjax_ignore\|comment\|<br>diff-(context\|<br>addedline\|deletedline)" | "mathjax_ignore" |
| `$wgSmjScale` | MathJax.chtml.scale | 1 | 1.5 |
| `$wgSmjDisplayAlign` | MathJax.chtml.displayAlign | "left" | "center" |
| `$wgSmjWrapDisplaystyle` | wrap with displaystyle on `<math>` | true | false |
| `$wgSmjEnableHtmlAttributes` | process attributes of math tag | false | true |
| `$wgSmjConfigByRevision` | switch the configuration according to the article's revision | [] | [['upto'=>1048576,<br>'wgSmjDisplayAlign'<br>=>'left']] |

If you want to change font size, set `$wgSmjScale`.
```PHP
wfLoadExtension( 'SimpleMathJax' );
$wgSmjScale = 1.5;
```

If you want to use local module, set `$wgSmjUseCdn`.
```PHP
wfLoadExtension( 'SimpleMathJax' );
$wgSmjUseCdn = false;
```

If you want to enable some extra inlineMath symbol pairs, set `$wgSmjExtraInlineMath`. Pairs of `[math][/math]` are always in-line math delimiters. (And independently of this setting, you can use `$ ... $` to switch to math mode within text (`\text{}` etc.) or chemical formulas (`\ce{}`).)
```PHP
wfLoadExtension( 'SimpleMathJax' );
$wgSmjExtraInlineMath = [["$","$"],["\\(","\\)"]];
```

Since version 0.8.7, inlineMath and blockMath and environments are ignored in edit summaries and diffs. To restore the previous behavior (especially if you are using maths in edit summaries), set `$wgSmjIgnoreHtmlClass`.
```PHP
wfLoadExtension( 'SimpleMathJax' );
$wgSmjIgnoreHtmlClass = "mathjax_ignore";
```

If you want to disable MathJax context menu, set `$wgSmjEnableMenu`.
```PHP
wfLoadExtension( 'SimpleMathJax' );
$wgSmjEnableMenu = false;
```

By enabling `$wgSmjEnableHtmlAttributes`, the `display` attribute of the `<math>` tag will work, and the `class`, `id`, `title` and `data-*` attributes of the `<math>` tag will be carried over to the `<span>` tag.
```PHP
wfLoadExtension( 'SimpleMathJax' );
$wgSmjEnableHtmlAttributes = true;
```

In version 0.8.9, an option was added to make it completely dedicated to `<math>` and `<chem>`. Setting `$wgSmjDirectMathJax` to `env` disables `\ref{}` and escaping of `$`, while setting it to `none` disables all delimiters, including `[math]`, making it mandatory to enclose all TeX expressions in `<math>` or `<chem>` (and `$wgSmjDisplayMath`, `$wgSmjExtraInlineMath`, and `$wgSmjIgnoreHtmlClass` will become meaningless).
```PHP
wfLoadExtension( 'SimpleMathJax' );
$wgSmjDirectMathJax = "none";
```

By using $wgSmjConfigByRevision, you can apply different settings to an article's revisions up to a certain point and to revisions after that. This allows past revisions to be displayed with the settings that were in place at the time. Only the keys written inside the [] are overwritten. Preview, History and SpecialPages are treated as base cases that do not apply this setting.
```PHP
wfLoadExtension( 'SimpleMathJax' );
$wgSmjDirectMathJax = "none"; #To match the preview with the actual rendering, write the latest settings in the base case
$wgSmjConfigByRevision = [
["upto"=>50000, "wgSmjDirectMathJax"=>"full"],
["since"=>50001, "upto"=>60000, "wgSmjDirectMathJax"=>"env"]
];
```

# Hooks
The hook `SimpleMathJaxAttributes` is available to add attributes to the span around the math. (Note that this process is performed only for `<math>` and `<chem>` elements, and other delimiters are handled directly by MathJax.) This hook provides you with the opportunity to ensure that your own code does not interfere with MathJax's rendering of math.

For instance, if Lingo's JS functions are called before MathJax is invoked, then it is possible that Lingo will change the text so that MathJax could no longer render the math.

Lingo understands that [it should not touch anything inside an element with the class `noglossary`](https://www.mediawiki.org/wiki/Extension:Lingo#Excluding_text_from_markup) so the following code can be used to keep Lingo from ruining math:
```PHP
$wgHooks['SimpleMathJaxAttributes'][]
= function ( array &$attributes, string $tex, array $args = [] ) {
$attributes['class'] .= ' noglossary';
};
```

| Setting name | Default value | Description | Custom value example |
| ------------------------ | --------------------------- | -------------------------------- | --------------------------- |
| `$wgSmjCdnEnabled` | `true` | Whether to load MathJax from a CDN | `false` |
| `$wgSmjCdnVersion` | `'4'` | MathJax version to load from the CDN | `'4.1.3'` |
| `$wgSmjScale` | `1` | `MathJax.chtml.scale` | `1.5` |
| `$wgSmjEnableMenu` | `true` | `MathJax.options.enableMenu` | `false` |
| `$wgSmjDelimitersEnabled` | `false` | Whether to also scan for bare delimiters (e.g. `$...$`) outside `<math>`/`<chem>` | `true` |
| `$wgSmjDelimitersInlineMath` | `[]` | Inline math delimiter pairs | `[['$','$']]` |
| `$wgSmjDelimitersDisplayMath` | `[]` | Display math delimiter pairs | `[['$$','$$']]` |
| `$wgSmjAllowedAttributes` | `[]` | List of generic HTML attributes to carry over to the output `<span>` | `['class', 'title']` |
| `$wgSmjIgnoreHtmlClass` | `'mathjax_ignore\|comment\|`<br>`diff-(context\|`<br>`addedline\|deletedline)'` | `MathJax.options.ignoreHtmlClass` | `'mathjax_ignore\|comment\|`<br>`diff-(context\|`<br>`addedline\|deletedline)\|my_custom_class'` |
| `$wgSmjRevisionOverrides` | `[]` | Switch the configuration according to the article's revision | `[['max'=>1048576,`<br>`'wgSmjScale'=>1.5]]` |

See [docs/configuration.md](docs/configuration.md) for a detailed walkthrough of each
setting, with usage examples. Upgrading from before 1.0.0? See the
[migration guide](docs/mig-1.0.md) for what to change in your
`LocalSettings.php`.

See [docs/displaystyle.md](docs/displaystyle.md) for the `<math display>`
rendering modes and examples.

Need to keep another extension (e.g. Lingo) from interfering with MathJax's
rendering? See [Hooks](docs/configuration.md#hooks) in the configuration
guide for the `SimpleMathJaxAttributes` hook.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"license": "MIT",
"require-dev": {
"mediawiki/mediawiki-codesniffer": "52.0.0",
"mediawiki/mediawiki-phan-config": "0.20.0",
Expand Down
185 changes: 185 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Configuration

Full reference for every `$wgSmj*` setting, plus the `SimpleMathJaxAttributes`
hook for extending it in code. The quick-reference table in the
[README](../README.md#optional-settings) links here for full explanations
and examples. Upgrading from before 1.0.0? See the
[migration guide](mig-1.0.md) instead.

## Settings reference

| Setting name | Default value | Description |
| ------------------------ | ------------- | ----------- |
| `$wgSmjCdnEnabled` | `true` | Whether to load MathJax from a CDN instead of the bundled local copy |
| `$wgSmjCdnVersion` | `'4'` | MathJax version to load from the CDN |
| `$wgSmjScale` | `1` | `MathJax.chtml.scale` |
| `$wgSmjEnableMenu` | `true` | `MathJax.options.enableMenu` |
| `$wgSmjDelimitersEnabled` | `false` | Whether to also scan for bare delimiters (e.g. `$...$`) outside `<math>`/`<chem>` |
| `$wgSmjDelimitersInlineMath` | `[]` | Inline math delimiter pairs, e.g. `[['$','$']]` |
| `$wgSmjDelimitersDisplayMath` | `[]` | Display math delimiter pairs, e.g. `[['$$','$$']]` |
| `$wgSmjAllowedAttributes` | `[]` | List of generic HTML attributes to carry over to the output `<span>` |
| `$wgSmjIgnoreHtmlClass` | `'mathjax_ignore\|comment\|`<br>`diff-(context\|`<br>`addedline\|deletedline)'` | `MathJax.options.ignoreHtmlClass` |
| `$wgSmjRevisionOverrides` | `[]` | Switch the configuration according to the article's revision |

### `$wgSmjCdnEnabled`

The default follows the latest 4.x release. To pin the CDN to an exact
version, set it explicitly:

```php
wfLoadExtension( 'SimpleMathJax' );
$wgSmjCdnVersion = '4.1.3';
```

To use the local MathJax module, disable the CDN.

```php
wfLoadExtension( 'SimpleMathJax' );
$wgSmjCdnEnabled = false;
```

When working from the Git repository, initialize or update the bundled
MathJax submodule with `make local-mathjax` — see
[Updating MathJax](development.md#updating-mathjax) for version
selection. Normal extension packages already include the bundled MathJax
resources and do not require Git commands.
Comment on lines +44 to +45

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not promise MathJax files in source packages

The repository stores resources/MathJax only as a gitlink, while the release workflow merely invokes gh release create and uploads no archive containing initialized submodule contents. Consequently, users of the generated GitHub source packages who follow this paragraph and set $wgSmjCdnEnabled = false will not have resources/MathJax/tex-chtml.js and local rendering will fail; either package the submodule contents or instruct package users to obtain them.

Useful? React with 👍 / 👎.


### `$wgSmjScale`

`$wgSmjScale` is passed straight through as MathJax's own `chtml.scale`
option — a multiplier on the default font size, where `1` is 100% (the
default) and, say, `1.5` is 150%. Any positive number works; there's no
built-in minimum or maximum.

```php
wfLoadExtension( 'SimpleMathJax' );
$wgSmjScale = 1.5;
```

### `$wgSmjEnableMenu`

If you want to disable MathJax context menu, set `$wgSmjEnableMenu`.

```php
wfLoadExtension( 'SimpleMathJax' );
$wgSmjEnableMenu = false;
```

### `$wgSmjDelimitersEnabled`

By default, `$wgSmjDelimitersEnabled` is `false`, so only TeX wrapped in
`<math>` or `<chem>` is recognized — bare `$...$`/`$$...$$` delimiters are
left as plain text, and `$wgSmjDelimitersInlineMath`/`DisplayMath` go
unused (as does [`$wgSmjIgnoreHtmlClass`](#wgsmjignorehtmlclass)'s
diff/comment protection, since there's nothing for it to protect against).
Set `Enabled` to `true` and list the delimiter pairs yourself to also
recognize bare delimiters:

```php
wfLoadExtension( 'SimpleMathJax' );
$wgSmjDelimitersEnabled = true;
$wgSmjDelimitersInlineMath = [ [ '$', '$' ] ];
$wgSmjDelimitersDisplayMath = [ [ '$$', '$$' ] ];
```

### `$wgSmjAllowedAttributes`

`$wgSmjAllowedAttributes` is the administrator-defined allow-list of generic
HTML attributes to copy from `<math>`/`<chem>` to the output `<span>`. No
attributes are copied by default; add the attribute names you want. Values
are still passed through MediaWiki's attribute sanitizer. A common case is
wanting a CSS styling hook plus a hover tooltip, without carrying over `id`
(which must be unique on the page, so an editor-supplied one can collide with
an anchor link (`#section`) or another element/JS gadget):

```php
wfLoadExtension( 'SimpleMathJax' );
$wgSmjAllowedAttributes = [ 'class', 'title' ];
```

`display` and `chem` are unrelated to this list and always work regardless —
see [Display styles](displaystyle.md).

### `$wgSmjIgnoreHtmlClass`

You probably don't need to change this — the default already covers what it
needs to:

```
mathjax_ignore|comment|diff-(context|addedline|deletedline)
```

`mathjax_ignore` lets an editor skip one `<math>`/`<chem>` by adding that
class, if `class` is allowed via
[`$wgSmjAllowedAttributes`](#wgsmjallowedattributes) (empty by default).
`comment` and `diff-(context|addedline|deletedline)` match what MediaWiki
puts on edit-summary and diff-table elements, protecting them — though only
if [`$wgSmjDelimitersEnabled`](#wgsmjdelimitersenabled) is on (see
[Rendering internals](development.md#rendering-internals) for why).

**Don't** replace the whole pattern with just your own class when extra
delimiters are on — the default's diff/comment protection goes with it:

```php
wfLoadExtension( 'SimpleMathJax' );
$wgSmjDelimitersEnabled = true;
// Don't: replaces the whole pattern, so it loses diff/comment protection.
$wgSmjIgnoreHtmlClass = 'my_custom_class';
```

**Do**, only if you really need your own class, extend the default with `|`
instead — and add `class` to `$wgSmjAllowedAttributes` so it survives on
individual `<math class="my_custom_class">` elements:

```php
wfLoadExtension( 'SimpleMathJax' );
$wgSmjDelimitersEnabled = true;
// Do, if you really need it: extends the default pattern instead of replacing it.
$wgSmjIgnoreHtmlClass = 'mathjax_ignore|comment|diff-(context|addedline|deletedline)|my_custom_class';
$wgSmjAllowedAttributes = [ 'class' ];
```

### `$wgSmjRevisionOverrides`

`$wgSmjRevisionOverrides` applies different settings to different ranges of
an article's revisions. This doesn't happen on its own — a past revision only
keeps rendering with the settings that were in effect when it was current if
you map that revision range to those settings yourself, as below. Each entry
is an array whose other keys are the overrides to apply, plus:

- A `min` and/or a `max` (the revision id bounds it applies to; either end
is open if omitted). Both bounds are inclusive. Revision ids increase
across the whole wiki, not per page — check the page's history for the
actual numbers rather than guessing from its edit count.
- Only the keys written inside `[]` are overwritten — the rest of your
`$wgSmj*` settings stay as they are.
- When more than one entry matches the same revision, later entries in the
list win — each one overwrites whatever the ones before it set for the
same key.
- Preview, History and Special pages are treated as revision `0`, a base
case where no entry ever applies, so they always render with the plain
`$wgSmj*` settings instead.

```php
wfLoadExtension( 'SimpleMathJax' );
$wgSmjDelimitersEnabled = false; // To match the preview with the actual rendering, write the latest settings in the base case
$wgSmjRevisionOverrides = [
[ 'max' => 50000, 'wgSmjDelimitersEnabled' => true ],
[ 'min' => 50001, 'max' => 60000, 'wgSmjDelimitersEnabled' => false ],
];
```

## Hooks

The hook `SimpleMathJaxAttributes` is available to add attributes to the span around the math. (Note that this process is performed only for `<math>` and `<chem>` elements, and other delimiters are handled directly by MathJax.) This hook provides you with the opportunity to ensure that your own code does not interfere with MathJax's rendering of math.

For instance, if Lingo's JS functions are called before MathJax is invoked, then it is possible that Lingo will change the text so that MathJax could no longer render the math.

Lingo understands that [it should not touch anything inside an element with the class `noglossary`](https://www.mediawiki.org/wiki/Extension:Lingo#Excluding_text_from_markup) so the following code can be used to keep Lingo from ruining math:

```php
$wgHooks['SimpleMathJaxAttributes'][]
= function ( array &$attributes, string $tex, array $args = [] ) {
$attributes['class'] .= ' noglossary';
};
```
Loading
Loading