UNPKG

3.63 kBJavaScriptView Raw
1// @flow
2import {_htmlGroupBuilders, _mathmlGroupBuilders} from "./defineFunction";
3
4import type Parser from "./Parser";
5import type {AnyParseNode} from "./parseNode";
6import type {ArgType, Mode} from "./types";
7import type {NodeType} from "./parseNode";
8import type {HtmlBuilder, MathMLBuilder} from "./defineFunction";
9
10/**
11 * The context contains the following properties:
12 * - mode: current parsing mode.
13 * - envName: the name of the environment, one of the listed names.
14 * - parser: the parser object.
15 */
16type EnvContext = {|
17 mode: Mode,
18 envName: string,
19 parser: Parser,
20|};
21
22/**
23 * - context: information and references provided by the parser
24 * - args: an array of arguments passed to \begin{name}
25 * - optArgs: an array of optional arguments passed to \begin{name}
26 */
27type EnvHandler = (
28 context: EnvContext,
29 args: AnyParseNode[],
30 optArgs: (?AnyParseNode)[],
31) => AnyParseNode;
32
33/**
34 * - numArgs: (default 0) The number of arguments after the \begin{name} function.
35 * - argTypes: (optional) Just like for a function
36 * - allowedInText: (default false) Whether or not the environment is allowed
37 * inside text mode (not enforced yet).
38 * - numOptionalArgs: (default 0) Just like for a function
39 */
40type EnvProps = {
41 numArgs: number,
42};
43
44/**
45 * Final enviornment spec for use at parse time.
46 * This is almost identical to `EnvDefSpec`, except it
47 * 1. includes the function handler
48 * 2. requires all arguments except argType
49 * It is generated by `defineEnvironment()` below.
50 */
51export type EnvSpec<NODETYPE: NodeType> = {|
52 type: NODETYPE, // Need to use the type to avoid error. See NOTES below.
53 numArgs: number,
54 argTypes?: ArgType[],
55 greediness: number,
56 allowedInText: boolean,
57 numOptionalArgs: number,
58 handler: EnvHandler,
59|};
60
61/**
62 * All registered environments.
63 * `environments.js` exports this same dictionary again and makes it public.
64 * `Parser.js` requires this dictionary via `environments.js`.
65 */
66export const _environments: {[string]: EnvSpec<*>} = {};
67
68type EnvDefSpec<NODETYPE: NodeType> = {|
69 // Unique string to differentiate parse nodes.
70 type: NODETYPE,
71
72 // List of functions which use the give handler, htmlBuilder,
73 // and mathmlBuilder.
74 names: Array<string>,
75
76 // Properties that control how the environments are parsed.
77 props: EnvProps,
78
79 handler: EnvHandler,
80
81 // This function returns an object representing the DOM structure to be
82 // created when rendering the defined LaTeX function.
83 htmlBuilder: HtmlBuilder<NODETYPE>,
84
85 // This function returns an object representing the MathML structure to be
86 // created when rendering the defined LaTeX function.
87 mathmlBuilder: MathMLBuilder<NODETYPE>,
88|};
89
90export default function defineEnvironment<NODETYPE: NodeType>({
91 type,
92 names,
93 props,
94 handler,
95 htmlBuilder,
96 mathmlBuilder,
97}: EnvDefSpec<NODETYPE>) {
98 // Set default values of environments.
99 const data = {
100 type,
101 numArgs: props.numArgs || 0,
102 greediness: 1,
103 allowedInText: false,
104 numOptionalArgs: 0,
105 handler,
106 };
107 for (let i = 0; i < names.length; ++i) {
108 // TODO: The value type of _environments should be a type union of all
109 // possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is
110 // an existential type.
111 // $FlowFixMe
112 _environments[names[i]] = data;
113 }
114 if (htmlBuilder) {
115 _htmlGroupBuilders[type] = htmlBuilder;
116 }
117 if (mathmlBuilder) {
118 _mathmlGroupBuilders[type] = mathmlBuilder;
119 }
120}