desmost 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/compiler/compile.d.ts +1 -7
- package/dist/compiler/compile.d.ts.map +1 -1
- package/dist/compiler/compile.js +3 -94
- package/dist/compiler/compile.js.map +1 -1
- package/dist/compiler/compiler.d.ts +56 -0
- package/dist/compiler/compiler.d.ts.map +1 -0
- package/dist/compiler/compiler.js +209 -0
- package/dist/compiler/compiler.js.map +1 -0
- package/dist/compiler/format.d.ts +2 -2
- package/dist/compiler/format.d.ts.map +1 -1
- package/dist/compiler/format.js +18 -9
- package/dist/compiler/format.js.map +1 -1
- package/dist/decompiler/decompile.d.ts +1 -1
- package/dist/decompiler/decompile.d.ts.map +1 -1
- package/dist/decompiler/extract.d.ts.map +1 -1
- package/dist/decompiler/extract.js +7 -3
- package/dist/decompiler/extract.js.map +1 -1
- package/dist/errors.d.ts +35 -27
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +46 -48
- package/dist/errors.js.map +1 -1
- package/dist/index.internal.d.ts +1 -1
- package/dist/index.internal.d.ts.map +1 -1
- package/dist/magic/global/desmos.d.ts +2 -2
- package/dist/magic/global/desmos.d.ts.map +1 -1
- package/dist/magic/global/desmos.js +3 -2
- package/dist/magic/global/desmos.js.map +1 -1
- package/dist/magic/global/viewport.d.ts +2 -2
- package/dist/magic/global/viewport.d.ts.map +1 -1
- package/dist/magic/global/viewport.js +5 -5
- package/dist/magic/global/viewport.js.map +1 -1
- package/dist/magic/incantation.d.ts +4 -4
- package/dist/magic/incantation.d.ts.map +1 -1
- package/dist/magic/incantation.js +15 -8
- package/dist/magic/incantation.js.map +1 -1
- package/dist/magic/local/colour.d.ts +3 -1
- package/dist/magic/local/colour.d.ts.map +1 -1
- package/dist/magic/local/colour.js +15 -11
- package/dist/magic/local/colour.js.map +1 -1
- package/dist/magic/local/label.d.ts.map +1 -1
- package/dist/magic/local/label.js +7 -7
- package/dist/magic/local/label.js.map +1 -1
- package/dist/magic/local/line.d.ts +2 -2
- package/dist/magic/local/line.d.ts.map +1 -1
- package/dist/magic/local/line.js +0 -1
- package/dist/magic/local/line.js.map +1 -1
- package/dist/options.d.ts +57 -23
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +2 -1
- package/dist/options.js.map +1 -1
- package/dist/parser/ast.d.ts +3 -17
- package/dist/parser/ast.d.ts.map +1 -1
- package/dist/parser/ast.js +0 -2
- package/dist/parser/ast.js.map +1 -1
- package/dist/parser/desmost-parser.d.ts +33 -22
- package/dist/parser/desmost-parser.d.ts.map +1 -1
- package/dist/parser/desmost-parser.js +106 -92
- package/dist/parser/desmost-parser.js.map +1 -1
- package/dist/parser/generic-parser.d.ts +19 -10
- package/dist/parser/generic-parser.d.ts.map +1 -1
- package/dist/parser/generic-parser.js +56 -16
- package/dist/parser/generic-parser.js.map +1 -1
- package/dist/utils.d.ts +9 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +13 -2
- package/dist/utils.js.map +1 -1
- package/package.json +5 -2
- package/src/compiler/compile.ts +7 -120
- package/src/compiler/compiler.ts +275 -0
- package/src/compiler/format.ts +19 -7
- package/src/decompiler/decompile.ts +1 -1
- package/src/decompiler/extract.ts +3 -1
- package/src/errors.ts +40 -24
- package/src/index.internal.ts +1 -1
- package/src/magic/.template.ts +2 -2
- package/src/magic/global/desmos.ts +7 -9
- package/src/magic/global/viewport.ts +11 -17
- package/src/magic/incantation.ts +21 -22
- package/src/magic/local/colour.ts +23 -13
- package/src/magic/local/label.ts +11 -17
- package/src/magic/local/line.ts +2 -2
- package/src/options.ts +81 -47
- package/src/parser/ast.ts +1 -21
- package/src/parser/desmost-parser.ts +131 -135
- package/src/parser/generic-parser.ts +71 -29
- package/src/utils.ts +25 -3
- package/dist/compiler/evaluate.d.ts +0 -18
- package/dist/compiler/evaluate.d.ts.map +0 -1
- package/dist/compiler/evaluate.js +0 -93
- package/dist/compiler/evaluate.js.map +0 -1
- package/dist/desmos.d.ts +0 -16
- package/dist/desmos.d.ts.map +0 -1
- package/dist/desmos.js +0 -19
- package/dist/desmos.js.map +0 -1
- package/src/compiler/evaluate.ts +0 -128
- package/src/desmos.ts +0 -22
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type GLOBAL } from "../incantation";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { DesmostError, type Fallible } from "../../errors";
|
|
4
4
|
import type { DesmostOptions } from "../../options";
|
|
5
5
|
|
|
6
6
|
|
|
@@ -26,19 +26,17 @@ export class DesmosIncantation extends ArgIncantation<GLOBAL>
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
override evaluate_arg(raw: string, options: DesmostOptions):
|
|
29
|
+
override evaluate_arg(raw: string, options: DesmostOptions): Fallible<DesmosSettings>
|
|
30
30
|
{
|
|
31
31
|
let out = super.evaluate_arg(raw, options) as DesmosSettings;
|
|
32
32
|
|
|
33
33
|
if (options.check_args) {
|
|
34
34
|
if (Object.keys(out).length === 0) {
|
|
35
|
-
throw new
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
);
|
|
35
|
+
throw new DesmostError.MissingInput({
|
|
36
|
+
msg: `/desmos received empty settings`,
|
|
37
|
+
hint: `Provide settings like \`/desmos{expressionsCollapsed: true}\``,
|
|
38
|
+
note: `Use just /desmos (without \`{}\`) if you want it as an indicator`,
|
|
39
|
+
});
|
|
42
40
|
}
|
|
43
41
|
}
|
|
44
42
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type GLOBAL } from "../incantation";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { DesmostError, type Fallible } from "../../errors";
|
|
4
4
|
import type { DesmostOptions } from "../../options";
|
|
5
5
|
|
|
6
6
|
|
|
@@ -36,20 +36,17 @@ export class ViewportIncantation extends ArgIncantation<GLOBAL>
|
|
|
36
36
|
target.setMathBounds({ left, right, bottom, top });
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
override evaluate_arg(raw: string, options: DesmostOptions):
|
|
39
|
+
override evaluate_arg(raw: string, options: DesmostOptions): Fallible<ViewportBounds>
|
|
40
40
|
{
|
|
41
41
|
let out = super.evaluate_arg(raw, options) as ViewportBounds;
|
|
42
42
|
|
|
43
43
|
if (options.check_args) {
|
|
44
44
|
if (Object.keys(out).length === 0) {
|
|
45
|
-
throw new
|
|
46
|
-
`/${this.identifier} received empty viewport bounds`,
|
|
47
|
-
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
flagged_by: "check_args",
|
|
51
|
-
}
|
|
52
|
-
);
|
|
45
|
+
throw new DesmostError.InvalidArgument({
|
|
46
|
+
msg: `/${this.identifier} received empty viewport bounds`,
|
|
47
|
+
hint: `Provide bounds like \`/viewport{left: -8, right: 8}\``,
|
|
48
|
+
note: `Missing bounds are kept as their defaults`,
|
|
49
|
+
});
|
|
53
50
|
}
|
|
54
51
|
|
|
55
52
|
let invalid_keys = Object.keys(out).filter(key => !VALID_KEYS.includes(key));
|
|
@@ -57,13 +54,10 @@ export class ViewportIncantation extends ArgIncantation<GLOBAL>
|
|
|
57
54
|
if (invalid_keys.length > 0) {
|
|
58
55
|
let plural = invalid_keys.length > 1 ? "fields" : "field";
|
|
59
56
|
|
|
60
|
-
throw new
|
|
61
|
-
`/${this.identifier} received invalid ${plural}: [${invalid_keys.join(", ")}]`,
|
|
62
|
-
{
|
|
63
|
-
|
|
64
|
-
flagged_by: "check_args",
|
|
65
|
-
}
|
|
66
|
-
);
|
|
57
|
+
throw new DesmostError.InvalidArgument({
|
|
58
|
+
msg: `/${this.identifier} received invalid ${plural}: [${invalid_keys.join(", ")}]`,
|
|
59
|
+
hint: `Valid fields are: [${VALID_KEYS.join(", ")}]`,
|
|
60
|
+
});
|
|
67
61
|
}
|
|
68
62
|
}
|
|
69
63
|
|
package/src/magic/incantation.ts
CHANGED
|
@@ -2,7 +2,7 @@ import Json5 from "json5";
|
|
|
2
2
|
import dedent from "dedent";
|
|
3
3
|
|
|
4
4
|
import type { DesmostOptions } from "../options";
|
|
5
|
-
import {
|
|
5
|
+
import { DesmostError, type Fallible } from "../errors";
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -46,9 +46,11 @@ export abstract class Incantation<
|
|
|
46
46
|
{
|
|
47
47
|
if ((actual ?? "expression") !== required)
|
|
48
48
|
{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
let req = required === "expression" ? "latex" : required;
|
|
50
|
+
|
|
51
|
+
throw new DesmostError.IllegalIncantation({
|
|
52
|
+
msg: `/${this.identifier} can only applied to ${req} blocks, but target block has type: ${actual}`,
|
|
53
|
+
});
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
}
|
|
@@ -80,7 +82,7 @@ export abstract class ArgIncantation<
|
|
|
80
82
|
*
|
|
81
83
|
* Validity checks for missing or invalid values, incorrect types, and unknown fields should be performed here, so that `.apply()` can assume the data it receives is guaranteed to be valid.
|
|
82
84
|
*/
|
|
83
|
-
evaluate_arg(raw: string, options: DesmostOptions):
|
|
85
|
+
evaluate_arg(raw: string, options: DesmostOptions): Fallible<unknown>
|
|
84
86
|
{
|
|
85
87
|
switch (this.arg_type) {
|
|
86
88
|
case Incantation.ArgType.LATEX: return raw;
|
|
@@ -95,7 +97,7 @@ export abstract class ArgIncantation<
|
|
|
95
97
|
}
|
|
96
98
|
catch (e) {
|
|
97
99
|
// @ts-expect-error: fine
|
|
98
|
-
throw new
|
|
100
|
+
throw new DesmostError.InvalidArgument({ msg: e.message });
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
103
|
}
|
|
@@ -103,34 +105,31 @@ export abstract class ArgIncantation<
|
|
|
103
105
|
|
|
104
106
|
protected require_nonempty(
|
|
105
107
|
arg: object,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
): Unrecoverable<void>
|
|
108
|
+
error_data?: DesmostError.Data,
|
|
109
|
+
): Fallible<void>
|
|
109
110
|
{
|
|
110
111
|
if (Object.entries(arg).length === 0) {
|
|
111
|
-
throw new
|
|
112
|
-
msg
|
|
113
|
-
|
|
114
|
-
);
|
|
112
|
+
throw new DesmostError.MissingInput({
|
|
113
|
+
msg: `/${this.identifier} received an empty argument {}`,
|
|
114
|
+
...error_data
|
|
115
|
+
});
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
protected require_known(
|
|
119
120
|
arg: object,
|
|
120
121
|
valid_fields: string[],
|
|
121
|
-
|
|
122
|
-
):
|
|
122
|
+
error_data?: DesmostError.Data,
|
|
123
|
+
): Fallible<void>
|
|
123
124
|
{
|
|
124
125
|
// TODO accumulate
|
|
125
126
|
for (let field of Object.keys(arg)) {
|
|
126
127
|
if (!valid_fields.includes(field)) {
|
|
127
|
-
throw new
|
|
128
|
-
`/${this.identifier} received invalid field: ${field}`,
|
|
129
|
-
{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
);
|
|
128
|
+
throw new DesmostError.InvalidArgument({
|
|
129
|
+
msg: `/${this.identifier} received invalid field: ${field}`,
|
|
130
|
+
hint: `Valid fields are [${valid_fields.join(", ")}]`,
|
|
131
|
+
...error_data,
|
|
132
|
+
});
|
|
134
133
|
}
|
|
135
134
|
}
|
|
136
135
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { UnrecoverableError } from "../../errors";
|
|
3
|
+
import { DesmostError } from "../../errors";
|
|
5
4
|
import type { DesmostOptions } from "../../options";
|
|
6
5
|
|
|
7
6
|
|
|
7
|
+
type DesmosColourName = keyof typeof Desmos.Colors;
|
|
8
|
+
type DesmosColour = (typeof Desmos.Colors)[DesmosColourName];
|
|
9
|
+
|
|
10
|
+
const VALID_COLOURS = ["RED", "BLUE", "GREEN", "PURPLE", "ORANGE", "BLACK"];
|
|
11
|
+
|
|
12
|
+
|
|
8
13
|
export class ColourIncantation extends ArgIncantation<LOCAL>
|
|
9
14
|
{
|
|
10
15
|
override readonly description
|
|
@@ -23,17 +28,22 @@ export class ColourIncantation extends ArgIncantation<LOCAL>
|
|
|
23
28
|
|
|
24
29
|
override evaluate_arg(data: string, options: DesmostOptions): DesmosColour
|
|
25
30
|
{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
let colour = data.trim().toUpperCase();
|
|
32
|
+
|
|
33
|
+
if (VALID_COLOURS.includes(colour)) {
|
|
34
|
+
return Desmos.Colors[colour as DesmosColourName];
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
let internal = Desmos.Colors[colour as DesmosColourName];
|
|
38
|
+
|
|
39
|
+
if (options.check_args && internal == undefined) {
|
|
40
|
+
throw new DesmostError.InvalidArgument({
|
|
41
|
+
msg: `/colour received invalid colour: \`${data}\``,
|
|
42
|
+
hint: `Valid colours are ${VALID_COLOURS.join(", ")}`,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return internal;
|
|
37
47
|
}
|
|
38
48
|
}
|
|
39
49
|
}
|
package/src/magic/local/label.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { DesmostError } from "../../errors";
|
|
4
4
|
import type { DesmostOptions } from "../../options";
|
|
5
5
|
|
|
6
6
|
|
|
@@ -45,19 +45,16 @@ export class LabelIncantation extends ArgIncantation<LOCAL>
|
|
|
45
45
|
let out = super.evaluate_arg(raw, options) as LabelOptions;
|
|
46
46
|
|
|
47
47
|
if (options.check_args) {
|
|
48
|
-
super.require_nonempty(out,
|
|
48
|
+
super.require_nonempty(out, {
|
|
49
|
+
msg: `/label received empty argument`,
|
|
49
50
|
hint: `You can provide [${VALID_FIELDS.join(", ")}]`,
|
|
50
|
-
flagged_by: "check_args",
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
if (!("text" in out)) {
|
|
54
|
-
throw new
|
|
55
|
-
`/label is missing label text`,
|
|
56
|
-
{
|
|
57
|
-
|
|
58
|
-
flagged_by: "check_args",
|
|
59
|
-
}
|
|
60
|
-
);
|
|
54
|
+
throw new DesmostError.MissingInput({
|
|
55
|
+
msg: `/label is missing label text`,
|
|
56
|
+
hint: `Provide text for the label: \`/label{text: "sup world!"}\``,
|
|
57
|
+
});
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
super.require_known(out, VALID_FIELDS);
|
|
@@ -75,13 +72,10 @@ export class LabelIncantation extends ArgIncantation<LOCAL>
|
|
|
75
72
|
let orientation = Desmos.LabelOrientations[pos];
|
|
76
73
|
|
|
77
74
|
if (options.check_args && orientation == undefined) {
|
|
78
|
-
throw new
|
|
79
|
-
`/label received invalid label position: ${pos}`,
|
|
80
|
-
{
|
|
81
|
-
|
|
82
|
-
flagged_by: "check_args"
|
|
83
|
-
}
|
|
84
|
-
);
|
|
75
|
+
throw new DesmostError.InvalidArgument({
|
|
76
|
+
msg: `/label received invalid label position: ${pos}`,
|
|
77
|
+
hint: `Valid label positions are ${VALID_POSITIONS.join(", ")}`,
|
|
78
|
+
});
|
|
85
79
|
}
|
|
86
80
|
|
|
87
81
|
out.pos = orientation;
|
package/src/magic/local/line.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
3
|
import type { DesmostOptions } from "../../options";
|
|
4
|
-
import {
|
|
4
|
+
import type { Fallible } from "../../errors";
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
interface LineOptions
|
|
@@ -32,7 +32,7 @@ export class LineIncantation extends ArgIncantation<LOCAL>
|
|
|
32
32
|
if (data.opacity != undefined) target.lineOpacity = data.opacity;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
override evaluate_arg(raw: string, options: DesmostOptions):
|
|
35
|
+
override evaluate_arg(raw: string, options: DesmostOptions): Fallible<LineOptions>
|
|
36
36
|
{
|
|
37
37
|
let out = super.evaluate_arg(raw, options) as LineOptions;
|
|
38
38
|
|
package/src/options.ts
CHANGED
|
@@ -2,6 +2,36 @@ import { LINE } from "./utils";
|
|
|
2
2
|
import { compile } from "./compiler/compile";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
/** Default options that Desmost uses for `compile()` and `decompile()`. */
|
|
6
|
+
export const DEFAULT_OPTIONS: DesmostOptions =
|
|
7
|
+
{
|
|
8
|
+
errors: "surface",
|
|
9
|
+
place_errors: "inline",
|
|
10
|
+
error_prefix: `[DESMOST ERROR]\n${LINE}\n`,
|
|
11
|
+
expand_errors: true,
|
|
12
|
+
check_args: true,
|
|
13
|
+
prettify: true,
|
|
14
|
+
dedent_text: true,
|
|
15
|
+
ignore_comments: false,
|
|
16
|
+
ignore_all_blanks: false,
|
|
17
|
+
keep_leading_blanks: false,
|
|
18
|
+
keep_trailing_blanks: false,
|
|
19
|
+
debug: false,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Fill in `options` with Desmost's defaults to produce a complete `DesmostOptions` config.
|
|
25
|
+
*/
|
|
26
|
+
export function fill_defaults(options: Partial<DesmostOptions> | undefined): DesmostOptions
|
|
27
|
+
{
|
|
28
|
+
return {
|
|
29
|
+
...DEFAULT_OPTIONS,
|
|
30
|
+
...options,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
5
35
|
/**
|
|
6
36
|
* Options to customise Desmost compilation.
|
|
7
37
|
*
|
|
@@ -29,14 +59,15 @@ import { compile } from "./compiler/compile";
|
|
|
29
59
|
export interface DesmostOptions
|
|
30
60
|
{
|
|
31
61
|
/**
|
|
32
|
-
* How should errors be
|
|
62
|
+
* How should errors be displayed?
|
|
33
63
|
*
|
|
34
|
-
* - `surface` (default): Blocks that result in errors will become Desmos text
|
|
64
|
+
* - `surface` (default): Blocks that result in errors will become Desmos text blocks containing the error message, leaving other expressions unaffected.
|
|
35
65
|
*
|
|
36
|
-
* - `crash`: The entire compilation to Desmos will terminate with a single error message
|
|
37
|
-
*
|
|
66
|
+
* - `crash`: The entire compilation to Desmos will terminate with a single error message in a text block.
|
|
67
|
+
* - This means you don't get any Desmos rendering at all, but errors are also immediately obvious.
|
|
68
|
+
* - Note that this will *clear all expressions* in the calculator instance. If you pass in a non-blank `Desmos.Calculator` to `compile()`, it could get cleared.
|
|
38
69
|
*
|
|
39
|
-
* - `suppress`: Silently fail on the frontend (if you wish to give the illusion that everything is fine).
|
|
70
|
+
* - `suppress`: Silently fail on the frontend (if you wish to give the illusion that everything is fine!).
|
|
40
71
|
*/
|
|
41
72
|
errors: "surface" | "crash" | "suppress"
|
|
42
73
|
|
|
@@ -52,7 +83,7 @@ export interface DesmostOptions
|
|
|
52
83
|
/**
|
|
53
84
|
* The prefix to prepend to error blocks.
|
|
54
85
|
*
|
|
55
|
-
* Defaults to `[DESMOST ERROR]
|
|
86
|
+
* Defaults to `"[DESMOST ERROR]"`.
|
|
56
87
|
*
|
|
57
88
|
* Provide a `""` blank string if you wish for no prefix to be added.
|
|
58
89
|
*/
|
|
@@ -61,7 +92,7 @@ export interface DesmostOptions
|
|
|
61
92
|
/**
|
|
62
93
|
* Show all the available diagnostics for errors, including hints and debug information?
|
|
63
94
|
*
|
|
64
|
-
* Defaults to `true
|
|
95
|
+
* Defaults to `true` – all output is shown.
|
|
65
96
|
*/
|
|
66
97
|
expand_errors: boolean
|
|
67
98
|
|
|
@@ -72,87 +103,90 @@ export interface DesmostOptions
|
|
|
72
103
|
*
|
|
73
104
|
* Desmost doesn’t remove unknown fields, it just passes them directly to the Desmos API. If you know what you’re doing and a field you know exists isn’t supported by Desmos, you can disable this to avoid erroring.
|
|
74
105
|
*
|
|
75
|
-
* Defaults to `true
|
|
106
|
+
* Defaults to `true` – arguments are checked. The Desmos API happily accepts and ignores invalid fields, so Desmost provides a safety net for you ;)
|
|
76
107
|
*/
|
|
77
108
|
check_args: boolean
|
|
78
109
|
|
|
79
110
|
/**
|
|
80
111
|
* Prettify LaTeX output so it renders nicely in the Desmos editor?
|
|
81
112
|
*
|
|
82
|
-
*
|
|
113
|
+
* This means you can keep your source code much neater. It handles stuff like converting `()` –> `\left(\right)`, `x, y` –> `x,\ y`, `min(x, y)` –> `\operatorname{min}\left(x,\ y\right)`, and more!
|
|
114
|
+
*
|
|
115
|
+
* Defaults to `true` – LaTeX is prettified.
|
|
83
116
|
*/
|
|
84
117
|
prettify: boolean
|
|
85
118
|
|
|
86
119
|
/**
|
|
87
120
|
* Strip common indentation from `/text{}` blocks?
|
|
88
121
|
*
|
|
89
|
-
*
|
|
122
|
+
* This allows you to indent content for readability:
|
|
123
|
+
*
|
|
124
|
+
* ```hs
|
|
125
|
+
* /text{
|
|
126
|
+
* Now I have
|
|
127
|
+
* a lovely indent
|
|
128
|
+
* }
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* Defaults to `true` – text is dedented.
|
|
90
132
|
*/
|
|
91
133
|
dedent_text: boolean
|
|
92
134
|
|
|
93
135
|
/**
|
|
94
|
-
* Should `%` LaTeX comments be ignored, instead of turned into text
|
|
136
|
+
* Should `%` LaTeX comments be ignored, instead of turned into text blocks (notes)?
|
|
95
137
|
*
|
|
96
|
-
*
|
|
138
|
+
* ```hs
|
|
139
|
+
* % Do I become a text expression?
|
|
140
|
+
* y = x
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* Defaults to `false` – comments are kept.
|
|
97
144
|
*/
|
|
98
145
|
ignore_comments: boolean
|
|
99
146
|
|
|
100
147
|
/**
|
|
101
148
|
* Should all line breaks be ignored, instead of kept as blank expressions?
|
|
102
149
|
*
|
|
103
|
-
*
|
|
150
|
+
* ```hs
|
|
151
|
+
* % Should there be a blank block after this?
|
|
152
|
+
*
|
|
153
|
+
* % Should there be a blank block before this?
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* This takes precedence over `keep_leading_blanks` and `keep_trailing_blanks`.
|
|
157
|
+
*
|
|
158
|
+
* Defaults to `false` – blank lines are recognised.
|
|
104
159
|
*/
|
|
105
160
|
ignore_all_blanks: boolean
|
|
106
161
|
|
|
107
162
|
/**
|
|
108
163
|
* Should trailing blank lines at the start of the source be kept as blank expressions?
|
|
109
164
|
*
|
|
110
|
-
*
|
|
165
|
+
* This is disabled by default so line breaks after global incantations don’t mess things up:
|
|
166
|
+
*
|
|
167
|
+
* ```hs
|
|
168
|
+
* /viewport{left: -8, right: 8}
|
|
169
|
+
*
|
|
170
|
+
* % I don’t have a blank block above me, yay
|
|
171
|
+
* ```
|
|
172
|
+
*
|
|
173
|
+
* Defaults to `false` – leading blank lines are ignored.
|
|
111
174
|
*/
|
|
112
175
|
keep_leading_blanks: boolean
|
|
113
176
|
|
|
114
177
|
/**
|
|
115
178
|
* Should trailing blank lines at the end of the source be kept as blank expressions?
|
|
116
179
|
*
|
|
117
|
-
* Defaults to `false
|
|
180
|
+
* Defaults to `false` – trailing blank lines are ignored.
|
|
118
181
|
*/
|
|
119
182
|
keep_trailing_blanks: boolean
|
|
120
183
|
|
|
121
184
|
/**
|
|
122
|
-
* Return debug diagnostics
|
|
185
|
+
* Return debug diagnostics from `compile()`?
|
|
123
186
|
*
|
|
124
|
-
* This includes the unevaluated AST and performance diagnostics.
|
|
187
|
+
* This includes the unevaluated AST and performance diagnostics. Relevant types are exposed from `desmost/internal`, but beware that these are implementation details and unstable.
|
|
125
188
|
*
|
|
126
|
-
* Defaults to `false
|
|
189
|
+
* Defaults to `false` – `compile()` returns `void`.
|
|
127
190
|
*/
|
|
128
191
|
debug: boolean
|
|
129
192
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
export const DEFAULT_OPTIONS: DesmostOptions =
|
|
133
|
-
{
|
|
134
|
-
errors: "surface",
|
|
135
|
-
place_errors: "inline",
|
|
136
|
-
error_prefix: `[DESMOST ERROR]\n${LINE}\n`,
|
|
137
|
-
expand_errors: true,
|
|
138
|
-
prettify: true,
|
|
139
|
-
dedent_text: true,
|
|
140
|
-
check_args: false,
|
|
141
|
-
ignore_comments: false,
|
|
142
|
-
ignore_all_blanks: false,
|
|
143
|
-
keep_leading_blanks: false,
|
|
144
|
-
keep_trailing_blanks: false,
|
|
145
|
-
debug: false,
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Fill in `options` with Desmost's defaults to produce a complete `DesmostOptions` config.
|
|
151
|
-
*/
|
|
152
|
-
export function fill_defaults(options: Partial<DesmostOptions> | undefined): DesmostOptions
|
|
153
|
-
{
|
|
154
|
-
return {
|
|
155
|
-
...DEFAULT_OPTIONS,
|
|
156
|
-
...options,
|
|
157
|
-
};
|
|
158
|
-
}
|
package/src/parser/ast.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { UnrecoverableError } from "../errors";
|
|
2
1
|
import { Incantation, ArgIncantation } from "../magic";
|
|
3
2
|
|
|
4
3
|
|
|
@@ -9,7 +8,6 @@ export namespace Ast
|
|
|
9
8
|
{
|
|
10
9
|
EXPRESSION = "Expression",
|
|
11
10
|
INCANTATION_INVOCATION = "Incantation-Invocation",
|
|
12
|
-
INVALID_INCANTATION = "Invalid-Incantation",
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
|
|
@@ -18,10 +16,7 @@ export namespace Ast
|
|
|
18
16
|
{
|
|
19
17
|
kind: Kind.EXPRESSION
|
|
20
18
|
data: Desmos.ExpressionState
|
|
21
|
-
incantations:
|
|
22
|
-
| IncantationInvocation<Incantation.Effect.LOCAL>
|
|
23
|
-
| InvalidInvocation
|
|
24
|
-
>
|
|
19
|
+
incantations: IncantationInvocation<Incantation.Effect.LOCAL>[]
|
|
25
20
|
}
|
|
26
21
|
|
|
27
22
|
|
|
@@ -30,31 +25,16 @@ export namespace Ast
|
|
|
30
25
|
| {
|
|
31
26
|
kind: Kind.INCANTATION_INVOCATION
|
|
32
27
|
incantation: Incantation<Effect>
|
|
33
|
-
arg_raw: undefined
|
|
34
28
|
}
|
|
35
29
|
| {
|
|
36
30
|
kind: Kind.INCANTATION_INVOCATION
|
|
37
31
|
incantation: ArgIncantation<Effect>
|
|
38
32
|
arg_raw: string | undefined
|
|
39
33
|
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* An invalid invantation invocation that raised an error when parsed.
|
|
43
|
-
*
|
|
44
|
-
* This will be propogated to the user as an extra Desmos text expression (unless they have `errors: "suppress"` configured).
|
|
45
|
-
*/
|
|
46
|
-
export interface InvalidInvocation
|
|
47
|
-
{
|
|
48
|
-
kind: Kind.INVALID_INCANTATION
|
|
49
|
-
incantation: Incantation
|
|
50
|
-
arg_raw?: string
|
|
51
|
-
error: UnrecoverableError
|
|
52
|
-
}
|
|
53
34
|
}
|
|
54
35
|
|
|
55
36
|
/** An abstract object produced by the parser. */
|
|
56
37
|
export type Ast =
|
|
57
38
|
| Ast.Expression
|
|
58
39
|
| Ast.IncantationInvocation
|
|
59
|
-
| Ast.InvalidInvocation
|
|
60
40
|
;
|