Skip to content

Commit 574122d

Browse files
Support MathJax backend (#12)
Co-authored-by: Saswat Padhi <padhi@cs.ucla.edu>
1 parent 5272ece commit 574122d

File tree

9 files changed

+533
-88
lines changed

9 files changed

+533
-88
lines changed

LICENSE.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2015 Tate Tian (tatetian@gmail.com)
3+
Copyright (c) 2020 Saswat Padhi (saswat.sourav@gmail.com)
4+
Copyright (c) 2015-2019 Tate Tian (tatetian@gmail.com)
45

56
Permission is hereby granted, free of charge, to any person obtaining a copy
67
of this software and associated documentation files (the "Software"), to deal

Makefile

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.PHONY: default setup lint build release clean
22

3-
VERSION=1.1
3+
VERSION=2.0
44

55
# Building tools
66
BROWSERIFY = $(realpath ./node_modules/.bin/browserify)
@@ -12,6 +12,8 @@ UGLIFYJS = $(realpath ./node_modules/.bin/uglifyjs) \
1212
CLEANCSS = $(realpath ./node_modules/.bin/cleancss)
1313
ESLINT = $(realpath ./node_modules/.bin/eslint)
1414

15+
SAMPLES = build/katex-samples.html build/mathjax-v2-samples.html build/mathjax-v3-samples.html
16+
1517
default: build
1618

1719

@@ -21,12 +23,12 @@ setup: static/katex/
2123

2224
static/katex/:
2325
@rm -rf static/katex
24-
cd static && wget https://github.com/Khan/KaTeX/releases/download/v0.8.0/katex.zip && unzip katex.zip
26+
cd static && wget https://github.com/Khan/KaTeX/releases/download/v0.11.1/katex.zip && unzip katex.zip
2527
@rm -rf static/katex.zip
2628
@echo "> Katex downloaded"
2729

2830

29-
build: build/pseudocode.js build/pseudocode.css build/samples.html
31+
build: build/pseudocode.js build/pseudocode.css $(SAMPLES)
3032
@echo "> Building succeeded"
3133

3234
build/pseudocode.js: pseudocode.js $(wildcard src/*.js)
@@ -43,7 +45,7 @@ watch-js: pseudocode.js $(wildcard src/*.js)
4345
build/pseudocode.css: static/pseudocode.css
4446
cp static/pseudocode.css build/pseudocode.css
4547

46-
build/samples.html: static/samples.html.template
48+
build/%-samples.html: static/%-samples.html.template
4749
cp $< $@
4850

4951

@@ -57,7 +59,7 @@ build/pseudocode-js.tar.gz: build/$(RELEASE_DIR)
5759
build/pseudocode-js.zip: build/$(RELEASE_DIR)
5860
cd build && zip -rq pseudocode-js.zip $(RELEASE_DIR)
5961

60-
build/$(RELEASE_DIR): build/pseudocode.js build/pseudocode.min.js build/pseudocode.css build/pseudocode.min.css build/samples.html README.md
62+
build/$(RELEASE_DIR): build/pseudocode.js build/pseudocode.min.js build/pseudocode.css build/pseudocode.min.css $(SAMPLES) README.md
6163
mkdir -p build/$(RELEASE_DIR)
6264
cp -r $^ build/$(RELEASE_DIR)
6365

README.md

Lines changed: 99 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,57 +16,78 @@ It supports all modern browsers, including Chrome, Safari, Firefox, Edge, and
1616
IE 9 - IE 11.
1717

1818
## Demo
19-
Visit the [project website](http://www.tatetian.io/pseudocode.js) for demo.
19+
Visit the [project website](https://saswatpadhi.github.io/pseudocode.js) for demo.
2020

2121
## Usage
2222

2323
### Quick Start
24-
Download [pseudocode.js](https://github.com/tatetian/pseudocode.js/releases),
25-
and host the files on your server. And then include the `js` and `css` files in
26-
your HTML files:
24+
25+
Pseudocode.js can render math formulas using either
26+
[KaTeX](https://github.com/Khan/KaTeX), or [MathJax](https://www.mathjax.org/).
27+
28+
#### Step 1A &middot; For KaTeX users
29+
Include the following in the `<head>` of your page:
2730

2831
```html
29-
<link rel="stylesheet" href="//path/to/pseudocode/pseudocode.min.css">
30-
<script src="//path/to/pseudocode/pseudocode.min.js"></script>
32+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min.css"
33+
integrity="sha256-V8SV2MO1FUb63Bwht5Wx9x6PVHNa02gv8BgH/uH3ung=" crossorigin="anonymous" />
34+
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min.js"
35+
integrity="sha256-F/Xda58SPdcUCr+xhSGz9MA2zQBPb0ASEYKohl8UCHc=" crossorigin="anonymous">
36+
</script>
3137
```
3238

33-
Pseudocode.js depends on [KaTeX](https://github.com/Khan/KaTeX) to render math
34-
formulas and uses KaTeX's fonts to render texts. So make sure that [KaTeX is
35-
setup](https://github.com/Khan/KaTeX#usage) properly.
39+
#### Step 1B &middot; For MathJax 2.x users
40+
Include the following in the `<head>` of your page:
3641

37-
Assume the pseudocode to be rendered is in a `<pre>` DOM element:
3842
```html
39-
<pre id="hello-world-code" style="display:hidden;">
40-
\begin{algorithmc}
41-
\PRINT \texttt{'hello world'}
42-
\end{algorithmc}
43-
</pre>
43+
<script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_CHTML'>
44+
</script>
45+
<script type="text/x-mathjax-config">
46+
MathJax.Hub.Config({
47+
tex2jax: {
48+
inlineMath: [['$','$'], ['\\(','\\)']],
49+
displayMath: [['$$','$$'], ['\[','\]']],
50+
processEscapes: true,
51+
processEnvironments: true,
52+
}
53+
});
54+
</script>
4455
```
4556

46-
To render the above code as a HTML element and append to a parent DOM element,
47-
call `pseudocode.render`:
48-
```js
49-
var code = document.getElementById("hello-world-code").textContent;
50-
var parentEl = document.body;
51-
var options = {
52-
lineNumber: true
53-
};
54-
pseudocode.render(code, parentEl, options);
57+
#### Step 1C &middot; For MathJax 3.x users
58+
Include the following in the `<head>` of your page:
59+
60+
```html
61+
<script>
62+
MathJax = {
63+
tex: {
64+
inlineMath: [['$','$'], ['\\(','\\)']],
65+
displayMath: [['$$','$$'], ['\[','\]']],
66+
processEscapes: true,
67+
processEnvironments: true,
68+
}
69+
}
70+
</script>
71+
<script src="https://cdn.jsdelivr.net/npm/mathjax@3.0.0/es5/tex-chtml.js"
72+
integrity="sha256-3Fdoa5wQb+JYfEmTpQHx9sc/GuwpfC/0R9EpBki+mf8=" crossorigin>
73+
</script>
5574
```
5675

57-
To generate a string of rendered HTML, call `pseudocode.renderToString`:
58-
```js
59-
var code = document.getElementById("hello-world-code").textContent;
60-
var options = {
61-
lineNumber: true
62-
};
63-
var htmlStr = pseudocode.renderToString(code, options);
64-
console.log(htmlStr);
76+
#### Step 2 &middot; Grab pseudocode.js
77+
Download a stable release of [pseudocode.js](https://github.com/SaswatPadhi/pseudocode.js/releases),
78+
and host the files on your server.
79+
Then include the following in the `<head>` of your page:
80+
81+
```html
82+
<link rel="stylesheet" href="//path/to/pseudocode/pseudocode.min.css">
83+
<script src="//path/to/pseudocode/pseudocode.min.js"></script>
6584
```
6685

67-
### Example
68-
To give you a sense of the grammar for pseudocode, here is an example that
69-
illustrates a quicksort algorithm:
86+
87+
#### Step 3 &middot; Write your pseudocode inside a `<pre>`
88+
We assume the pseudocode to be rendered is in a `<pre>` DOM element.
89+
Here is an example that illustrates a quicksort algorithm:
90+
7091
```tex
7192
% This quicksort algorithm is extracted from Chapter 7, Introduction to Algorithms (3rd edition)
7293
\begin{algorithm}
@@ -95,6 +116,38 @@ illustrates a quicksort algorithm:
95116
\end{algorithm}</textarea>
96117
```
97118

119+
### API
120+
Assume the pseudocode to be rendered is in a `<pre>` DOM element:
121+
```html
122+
<pre id="hello-world-code" style="display:hidden;">
123+
\begin{algorithmc}
124+
\PRINT \texttt{'hello world'}
125+
\end{algorithmc}
126+
</pre>
127+
```
128+
129+
To render the above code as a HTML element and append to a parent DOM element,
130+
call `pseudocode.render`:
131+
```js
132+
var code = document.getElementById("hello-world-code").textContent;
133+
var parentEl = document.body;
134+
var options = {
135+
lineNumber: true
136+
};
137+
pseudocode.render(code, parentEl, options);
138+
```
139+
140+
To generate a string of rendered HTML, call `pseudocode.renderToString`:
141+
```js
142+
var code = document.getElementById("hello-world-code").textContent;
143+
var options = {
144+
lineNumber: true
145+
};
146+
var htmlStr = pseudocode.renderToString(code, options);
147+
console.log(htmlStr);
148+
```
149+
150+
98151
### Grammar
99152
There are several packages for typesetting algorithms in LaTeX, among which
100153
[`algorithmic`](http://mirror.ctan.org/tex-archive/macros/latex/contrib/algorithms/algorithms.pdf)
@@ -237,17 +290,21 @@ make setup
237290
make
238291
```
239292

240-
Then, open `static/test-suite.html` in your favourite browser to see whether
241-
algorithms are typeset correctly.
293+
Then, open one of the sample documents:
294+
- `build/katex-samples.html`, or
295+
- `build/mathjax-v2-samples.html`, or
296+
- `build/mathjax-v3-samples.html`
297+
in your favourite browser to check if the algorithms are typeset correctly.
242298

243299

244300
## Author
245-
Tate Tian ([@tatetian](https://github.com/tatetian)) creates pseudocode.js. Any
246-
suggestions and bug reports are welcome.
301+
pseudocode.js was originally written by Tate Tian ([@tatetian](https://github.com/tatetian)).
302+
Together with [@ZJUGuoShuai](https://github.com/ZJUGuoShuai),
303+
I ([@SaswatPadhi](https://github.com/SaswatPadhi)) added the MathJax support,
304+
and I am the current maintainer of this project.
305+
Suggestions, bug reports and pull requests are most welcome.
247306

248307
## Acknowledgement
249-
Pseudocode.js is partially inspired by [KaTeX](http://khan.github.io/KaTeX/) and
250-
relies on it to render math formulas.
308+
Pseudocode.js is partially inspired by [KaTeX](http://khan.github.io/KaTeX/).
251309
Thanks Emily Eisenberg([@xymostech](https://github.com/xymostech))
252310
and other contributers for building such a wonderful project.
253-

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
{
22
"name": "pseudocode",
3-
"version": "1.1.1",
3+
"version": "2.0",
44
"author": {
5-
"name": "Tate Tian",
6-
"email": "tatetian@gmail.com",
7-
"url": "http://www.tatetian.me"
5+
"name": "Saswat Padhi",
6+
"email": "saswat.sourav@gmail.com",
7+
"url": "https://saswatpadhi.github.io/"
88
},
99
"description": "Beautiful pseudocode for the Web",
1010
"main": "pseudocode.js",
1111
"repository": {
1212
"type": "git",
13-
"url": "git://github.com/tatetian/pseudocode.js"
13+
"url": "git://github.com/SaswatPadhi/pseudocode.js"
1414
},
1515
"files": [
16-
"PseudoCode.js",
16+
"pseudoCode.js",
1717
"src/"
1818
],
1919
"devDependencies": {

src/Renderer.js

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
var utils = require('./utils');
44

55
/*
6-
* TextStyle - used by TextEnvironment class to handles LaTeX text-style
6+
* TextStyle - used by TextEnvironment class to handle LaTeX text-style
77
* commands or declarations.
88
*
99
* The font declarations are:
@@ -141,7 +141,7 @@ TextEnvironment.prototype._renderCloseText = function(node) {
141141
var newTextStyle = new TextStyle(this._textStyle.fontSize());
142142
var closeTextEnv = new TextEnvironment(node.children, newTextStyle);
143143
if (node.whitespace) this._html.putText(' ');
144-
this._html.putSpan(closeTextEnv.renderToHTML());
144+
this._html.putHTML(closeTextEnv.renderToHTML());
145145
};
146146

147147
TextEnvironment.prototype.renderToHTML = function() {
@@ -160,12 +160,24 @@ TextEnvironment.prototype.renderToHTML = function() {
160160
this._html.putText(text);
161161
break;
162162
case 'math':
163-
if (!katex) {
163+
useKatex = true;
164+
if (typeof katex === 'undefined') {
164165
try { katex = require('katex'); }
165-
catch (e) { throw 'katex is required to render math'; }
166+
catch (e) {
167+
if (typeof MathJax === 'undefined') {
168+
throw 'KaTeX or MathJax is required to render math';
169+
}
170+
var useKatex = false;
171+
}
166172
}
167-
var mathHTML = katex.renderToString(text);
168-
this._html.putSpan(mathHTML);
173+
174+
if (useKatex) { // KaTeX
175+
this._html.putHTML(katex.renderToString(text));
176+
}
177+
else { // MathJax
178+
this._html.putText("$" + text + "$");
179+
}
180+
169181
break;
170182
case 'cond-symbol':
171183
this._html
@@ -244,7 +256,7 @@ TextEnvironment.prototype.renderToHTML = function() {
244256
this._html.beginSpan(null, this._textStyle.toCSS());
245257
var textEnvForDclr = new TextEnvironment(this._nodes,
246258
this._textStyle);
247-
this._html.putSpan(textEnvForDclr.renderToHTML());
259+
this._html.putHTML(textEnvForDclr.renderToHTML());
248260
this._html.endSpan();
249261
break;
250262
case 'font-cmd':
@@ -256,7 +268,7 @@ TextEnvironment.prototype.renderToHTML = function() {
256268
this._html.beginSpan(null, innerTextStyle.toCSS());
257269
var textEnvForCmd = new TextEnvironment(textNode.children,
258270
innerTextStyle);
259-
this._html.putSpan(textEnvForCmd.renderToHTML());
271+
this._html.putHTML(textEnvForCmd.renderToHTML());
260272
this._html.endSpan();
261273
break;
262274
default:
@@ -308,8 +320,7 @@ HTMLBuilder.prototype.endSpan = function() {
308320
return this._endTag('span');
309321
};
310322

311-
HTMLBuilder.prototype.putHTML =
312-
HTMLBuilder.prototype.putSpan = function(html) {
323+
HTMLBuilder.prototype.putHTML = function(html) {
313324
this._flushText();
314325
this._body.push(html);
315326
return this;
@@ -799,13 +810,13 @@ Renderer.prototype._buildTree = function(node) {
799810
case 'open-text':
800811
var openTextEnv = new TextEnvironment(node.children,
801812
this._globalTextStyle);
802-
this._html.putSpan(openTextEnv.renderToHTML());
813+
this._html.putHTML(openTextEnv.renderToHTML());
803814
break;
804815
case 'close-text':
805816
var outerFontSize = this._globalTextStyle.fontSize();
806817
var newTextStyle = new TextStyle(outerFontSize);
807818
var closeTextEnv = new TextEnvironment(node.children, newTextStyle);
808-
this._html.putSpan(closeTextEnv.renderToHTML());
819+
this._html.putHTML(closeTextEnv.renderToHTML());
809820
break;
810821
default:
811822
throw new ParseError('Unexpected ParseNode of type ' + node.type);

0 commit comments

Comments
 (0)