Skip to content

Commit eac2cb6

Browse files
✨ NEW: Add math directive (#13)
Co-authored-by: Chris Sewell <[email protected]>
1 parent e7f8490 commit eac2cb6

File tree

9 files changed

+83
-17
lines changed

9 files changed

+83
-17
lines changed

README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,11 @@ All directives have a fallback renderer, but the the following are specifically
9797
- Tables:
9898
- `list-table`
9999
- HTML:
100-
- `sub`: Subscript
101-
- `sup`: Superscript
102-
- `abbr`: Abbreviation
100+
- `sub`: Subscript
101+
- `sup`: Superscript
102+
- `abbr`: Abbreviation
103+
- Other:
104+
- `math`
103105

104106
## CSS Styling
105107

docs/index.html

+7
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ <h1>markdown-it-docutils</h1>
9898
* H{sub}`2`O
9999
* 4{sup}`th` of July
100100
* {abbr}`CSS (Cascading Style Sheets)`
101+
102+
Math:
103+
104+
```{math}
105+
:label: math_label
106+
w_{t+1} = (1 + r_{t+1}) s(w_t) + y_{t+1}
107+
```
101108
</textarea
102109
>
103110
<div id="renderer" class="rendered"></div>

src/directives/admonitions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class BaseAdmonition extends Directive {
1818
name: unchanged
1919
}
2020
public title = ""
21-
run(data: IDirectiveData): Token[] {
21+
run(data: IDirectiveData<keyof BaseAdmonition["option_spec"]>): Token[] {
2222
const newTokens: Token[] = []
2323

2424
// we create an overall container, then individual containers for the title and body

src/directives/code.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class Code extends Directive {
2929
name: unchanged,
3030
class: class_option
3131
}
32-
run(data: IDirectiveData): Token[] {
32+
run(data: IDirectiveData<keyof Code["option_spec"]>): Token[] {
3333
// TODO handle options
3434
this.assert_has_content(data)
3535
const token = this.createToken("fence", "code", 0, {
@@ -68,7 +68,7 @@ export class CodeBlock extends Directive {
6868
name: unchanged,
6969
class: class_option
7070
}
71-
run(data: IDirectiveData): Token[] {
71+
run(data: IDirectiveData<keyof CodeBlock["option_spec"]>): Token[] {
7272
// TODO handle options
7373
this.assert_has_content(data)
7474
const token = this.createToken("fence", "code", 0, {
@@ -89,7 +89,7 @@ export class CodeCell extends Directive {
8989
public has_content = true
9090
public rawOptions = true
9191

92-
run(data: IDirectiveData): Token[] {
92+
run(data: IDirectiveData<keyof CodeCell["option_spec"]>): Token[] {
9393
// TODO store options and the fact that this is a code cell rather than a fence?
9494
const token = this.createToken("fence", "code", 0, {
9595
info: data.args ? data.args[0] : "",

src/directives/images.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class Image extends Directive {
3838
...shared_option_spec,
3939
align: create_choice(["left", "center", "right", "top", "middle", "bottom"])
4040
}
41-
create_image(data: IDirectiveData): Token {
41+
create_image(data: IDirectiveData<keyof Image["option_spec"]>): Token {
4242
// get URI
4343
const src = uri(data.args[0] || "")
4444

@@ -89,7 +89,7 @@ export class Figure extends Image {
8989
figclass: class_option
9090
}
9191
public has_content = true
92-
run(data: IDirectiveData): Token[] {
92+
run(data: IDirectiveData<keyof Figure["option_spec"]>): Token[] {
9393
const openToken = this.createToken("figure_open", "figure", 1, { map: data.map })
9494
if (data.options.figclass) {
9595
openToken.attrJoin("class", data.options.figclass.join(" "))

src/directives/main.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,7 @@ export interface IDirectiveSpec {
6565
/** if body content is allowed */
6666
has_content?: boolean
6767
/** mapping known option names to conversion functions */
68-
option_spec?: {
69-
[key: string]: OptionSpecConverter
70-
}
68+
option_spec?: Record<string, OptionSpecConverter>
7169
/** If true, do not attempt to validate/convert options. */
7270
rawOptions?: boolean
7371
}
@@ -153,10 +151,10 @@ export class Directive implements IDirectiveSpec {
153151
}
154152

155153
/** Data structure of a directive */
156-
export interface IDirectiveData {
154+
export interface IDirectiveData<T extends string = string> {
157155
map: [number, number]
158156
args: string[]
159-
options: { [key: string]: any }
157+
options: Record<T, any>
160158
body: string
161159
bodyMap: [number, number]
162160
}

src/directives/math.ts

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/** Admonitions to visualise programming codes */
2+
import type Token from "markdown-it/lib/token"
3+
import { Directive, IDirectiveData } from "./main"
4+
import { unchanged } from "./options"
5+
6+
/** Math directive with a label
7+
*/
8+
export class Math extends Directive {
9+
public required_arguments = 0
10+
public optional_arguments = 0
11+
public final_argument_whitespace = false
12+
public has_content = true
13+
public option_spec = {
14+
label: unchanged
15+
}
16+
run(data: IDirectiveData<keyof Math["option_spec"]>): Token[] {
17+
// TODO handle options
18+
this.assert_has_content(data)
19+
const token = this.createToken("math_block", "div", 0, {
20+
content: data.body,
21+
map: data.bodyMap,
22+
block: true
23+
})
24+
token.attrSet("class", "math block")
25+
if (data.options.label) {
26+
token.info = data.options.label
27+
token.meta = { label: data.options.label, numbered: true }
28+
}
29+
return [token]
30+
}
31+
}
32+
33+
export const math = {
34+
math: Math
35+
}

src/index.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import { roles } from "./roles/main"
99
import { html } from "./roles/html"
1010
import rolePlugin from "./roles/plugin"
1111
import type { IOptions as IRoleOptions } from "./roles/types"
12-
import { math } from "./roles/math"
12+
import { math as mathRole } from "./roles/math"
13+
import { math as mathDirective } from "./directives/math"
1314

1415
/** Allowed options for docutils plugin */
1516
export interface IOptions extends IDirectiveOptions, IRoleOptions {
@@ -22,8 +23,8 @@ const OptionDefaults: IOptions = {
2223
replaceFences: true,
2324
rolesAfter: "inline",
2425
directivesAfter: "block",
25-
directives: { ...admonitions, ...images, ...code, ...tables },
26-
roles: { ...roles, ...html, ...math }
26+
directives: { ...admonitions, ...images, ...code, ...tables, ...mathDirective },
27+
roles: { ...roles, ...html, ...mathRole }
2728
}
2829

2930
/**

tests/fixtures/directives.math.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
math directive
2+
.
3+
```{math}
4+
w_{t+1} = (1 + r_{t+1}) s(w_t) + y_{t+1}
5+
```
6+
.
7+
<div class="math block">
8+
w_{t+1} = (1 + r_{t+1}) s(w_t) + y_{t+1}
9+
</div>
10+
.
11+
12+
math directive with label
13+
.
14+
```{math}
15+
:label: my_label
16+
w_{t+1} = (1 + r_{t+1}) s(w_t) + y_{t+1}
17+
```
18+
.
19+
<div class="math block">
20+
w_{t+1} = (1 + r_{t+1}) s(w_t) + y_{t+1}
21+
</div>
22+
.
23+

0 commit comments

Comments
 (0)