questmark 0.0.35 → 0.0.36
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/bin/package.json +2 -2
- package/bin/questmark +3 -3
- package/bin/questmark.mjs +3 -3
- package/dist/browser/QuestVM.d.ts +13 -13
- package/dist/browser/QuestVM.js +88 -88
- package/dist/browser/cli.d.ts +2 -2
- package/dist/browser/cli.js +79 -79
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/index.js +14 -14
- package/dist/browser/parseMarkdown.d.ts +25 -25
- package/dist/browser/parseMarkdown.js +412 -349
- package/dist/browser/parseMarkdown.js.map +1 -1
- package/dist/node/QuestVM.d.ts +13 -13
- package/dist/node/QuestVM.js +88 -88
- package/dist/node/cli.d.ts +2 -2
- package/dist/node/cli.js +79 -79
- package/dist/node/index.d.ts +2 -2
- package/dist/node/index.js +14 -14
- package/dist/node/parseMarkdown.d.ts +25 -25
- package/dist/node/parseMarkdown.js +412 -349
- package/dist/node/parseMarkdown.js.map +1 -1
- package/package.json +54 -54
- package/readme.md +102 -102
- package/tsconfig-browser.json +8 -8
- package/tsconfig.json +27 -27
|
@@ -1,350 +1,413 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.parseMarkdown = exports.NoLinkBehaviour = void 0;
|
|
7
|
-
const mdast_util_from_markdown_1 = __importDefault(require("mdast-util-from-markdown"));
|
|
8
|
-
const unist_util_find_after_1 = __importDefault(require("unist-util-find-after"));
|
|
9
|
-
const unist_util_remove_position_1 = __importDefault(require("unist-util-remove-position"));
|
|
10
|
-
const unist_util_find_all_after_1 = __importDefault(require("unist-util-find-all-after"));
|
|
11
|
-
const unist_util_find_all_between_1 = __importDefault(require("unist-util-find-all-between"));
|
|
12
|
-
const unist_util_visit_parents_1 = __importDefault(require("unist-util-visit-parents"));
|
|
13
|
-
const unist_util_visit_1 = __importDefault(require("unist-util-visit"));
|
|
14
|
-
const unist_builder_1 = __importDefault(require("unist-builder"));
|
|
15
|
-
require("array-flat-polyfill");
|
|
16
|
-
const tzo_1 = require("tzo");
|
|
17
|
-
var NoLinkBehaviour;
|
|
18
|
-
(function (NoLinkBehaviour) {
|
|
19
|
-
NoLinkBehaviour[NoLinkBehaviour["EXIT"] = 0] = "EXIT";
|
|
20
|
-
NoLinkBehaviour[NoLinkBehaviour["LOOPBACK_TO_OPTIONS"] = 1] = "LOOPBACK_TO_OPTIONS"; // DEFAULT: Loopback to the options section if no link is found for an option and an option does not explicitly call an `exit` or `goto` effect.
|
|
21
|
-
})(NoLinkBehaviour = exports.NoLinkBehaviour || (exports.NoLinkBehaviour = {}));
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
remainingChildren = remainingChildren.map(child => {
|
|
85
|
-
if (child.type === '
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (n.type
|
|
113
|
-
if (n.value && n.value.trim().length
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
q(tzo_1.invokeFunction("
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
q(tzo_1.pushString(once_directive_name));
|
|
281
|
-
q(tzo_1.invokeFunction("
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
if (option.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
q(tzo_1.pushString(
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
q(tzo_1.invokeFunction("
|
|
316
|
-
}
|
|
317
|
-
if (
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseMarkdown = exports.NoLinkBehaviour = void 0;
|
|
7
|
+
const mdast_util_from_markdown_1 = __importDefault(require("mdast-util-from-markdown"));
|
|
8
|
+
const unist_util_find_after_1 = __importDefault(require("unist-util-find-after"));
|
|
9
|
+
const unist_util_remove_position_1 = __importDefault(require("unist-util-remove-position"));
|
|
10
|
+
const unist_util_find_all_after_1 = __importDefault(require("unist-util-find-all-after"));
|
|
11
|
+
const unist_util_find_all_between_1 = __importDefault(require("unist-util-find-all-between"));
|
|
12
|
+
const unist_util_visit_parents_1 = __importDefault(require("unist-util-visit-parents"));
|
|
13
|
+
const unist_util_visit_1 = __importDefault(require("unist-util-visit"));
|
|
14
|
+
const unist_builder_1 = __importDefault(require("unist-builder"));
|
|
15
|
+
require("array-flat-polyfill");
|
|
16
|
+
const tzo_1 = require("tzo");
|
|
17
|
+
var NoLinkBehaviour;
|
|
18
|
+
(function (NoLinkBehaviour) {
|
|
19
|
+
NoLinkBehaviour[NoLinkBehaviour["EXIT"] = 0] = "EXIT";
|
|
20
|
+
NoLinkBehaviour[NoLinkBehaviour["LOOPBACK_TO_OPTIONS"] = 1] = "LOOPBACK_TO_OPTIONS"; // DEFAULT: Loopback to the options section if no link is found for an option and an option does not explicitly call an `exit` or `goto` effect.
|
|
21
|
+
})(NoLinkBehaviour = exports.NoLinkBehaviour || (exports.NoLinkBehaviour = {}));
|
|
22
|
+
var EmitOn;
|
|
23
|
+
(function (EmitOn) {
|
|
24
|
+
EmitOn[EmitOn["CLASSIC"] = 0] = "CLASSIC";
|
|
25
|
+
EmitOn[EmitOn["END_OF_LINE"] = 1] = "END_OF_LINE";
|
|
26
|
+
})(EmitOn || (EmitOn = {}));
|
|
27
|
+
function parseMarkdown(file_contents) {
|
|
28
|
+
const tree = mdast_util_from_markdown_1.default(file_contents);
|
|
29
|
+
const tokenizer = new tzo_1.Tokenizer();
|
|
30
|
+
const root = unist_builder_1.default('questmarkDocument', { options: {} }, []);
|
|
31
|
+
let last_once_directive_nr = 0;
|
|
32
|
+
let noLinkBehaviour = NoLinkBehaviour.LOOPBACK_TO_OPTIONS;
|
|
33
|
+
let retainWhitespace = false;
|
|
34
|
+
let emitOn = EmitOn.CLASSIC;
|
|
35
|
+
let missed_emits = 0;
|
|
36
|
+
let strip_leading_newlines = false;
|
|
37
|
+
unist_util_visit_parents_1.default(tree, 'heading', (x, ancestors) => {
|
|
38
|
+
if (ancestors.length > 1) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// capture name
|
|
42
|
+
let name = "";
|
|
43
|
+
unist_util_visit_parents_1.default(x, 'text', t => {
|
|
44
|
+
name = `${name} ${t.value}`;
|
|
45
|
+
});
|
|
46
|
+
name = name.trim();
|
|
47
|
+
// capture children belonging to this heading group
|
|
48
|
+
const nextHeading = unist_util_find_after_1.default(tree, x, 'heading');
|
|
49
|
+
const children = nextHeading !== null ? unist_util_find_all_between_1.default(tree, x, nextHeading) : unist_util_find_all_after_1.default(tree, x);
|
|
50
|
+
if (name === "QUESTMARK-OPTIONS-HEADER") {
|
|
51
|
+
root.options = getQuestmarkOptions(children);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
root.children.push(createStateNode(name, children));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
function getQuestmarkOptions(children) {
|
|
58
|
+
let code = '';
|
|
59
|
+
unist_util_visit_1.default(unist_builder_1.default('bla', children), 'code', n => {
|
|
60
|
+
code = `${code} ${n.value}`;
|
|
61
|
+
});
|
|
62
|
+
return JSON.parse(code.trim());
|
|
63
|
+
}
|
|
64
|
+
function createStateNode(name, children) {
|
|
65
|
+
// create new state node
|
|
66
|
+
const stateNode = unist_builder_1.default('state', { name, options: [] }, []);
|
|
67
|
+
let found = false;
|
|
68
|
+
let stateChildren = [];
|
|
69
|
+
let remainingChildren = [];
|
|
70
|
+
// phase 0: split children into stateChildren and remaining children.
|
|
71
|
+
children.forEach(child => {
|
|
72
|
+
if (child.type === 'list' && child.ordered === false) {
|
|
73
|
+
found = true;
|
|
74
|
+
}
|
|
75
|
+
if (found) {
|
|
76
|
+
remainingChildren.push(child);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
stateChildren.push(child);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
stateNode.children = stateChildren;
|
|
83
|
+
// phase 1: replace list nodes with their children, then flatten the list
|
|
84
|
+
remainingChildren = remainingChildren.map(child => {
|
|
85
|
+
if (child.type === 'list' && child.ordered === false) {
|
|
86
|
+
return child.children;
|
|
87
|
+
}
|
|
88
|
+
return child;
|
|
89
|
+
}).flat(1);
|
|
90
|
+
// phase 2: reparent non-listItem nodes to the last-seen listItem.
|
|
91
|
+
let lastSeenListItem = null;
|
|
92
|
+
remainingChildren = remainingChildren.map(child => {
|
|
93
|
+
if (child.type === 'listItem') {
|
|
94
|
+
lastSeenListItem = child;
|
|
95
|
+
return child;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
lastSeenListItem.children.push(child);
|
|
99
|
+
}
|
|
100
|
+
}).filter(x => x !== undefined);
|
|
101
|
+
// phase 3: build the options from the remainingChildren (now all listItems)
|
|
102
|
+
const options = remainingChildren.map((li) => {
|
|
103
|
+
// li's `link` / `text` children are the main links / options, but only the first item is considered (the others are effect nodes)
|
|
104
|
+
// li's `inlineCode` children are either precondition or effect code blocks
|
|
105
|
+
const optionNode = unist_builder_1.default("option", { preconditionChildren: null, effectChildren: null, text: null, link: null, directives: null });
|
|
106
|
+
let effectNodes = [];
|
|
107
|
+
let preconditionNodes = [];
|
|
108
|
+
let text = [];
|
|
109
|
+
let link = [];
|
|
110
|
+
let directives = [];
|
|
111
|
+
unist_util_visit_1.default(li, n => {
|
|
112
|
+
if (text.length > 0 && n.type !== "paragraph") {
|
|
113
|
+
if (n.type === "text" && n.value && n.value.trim().length === 0) {
|
|
114
|
+
// whitespace only node!
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
effectNodes.push(n);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (n.type === "text") {
|
|
121
|
+
if (n.value && n.value.trim().length > 0 && text.length === 0) {
|
|
122
|
+
text.push(n.value);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (n.type === "link") {
|
|
126
|
+
if (n.url && link.length === 0) {
|
|
127
|
+
link.push(n.url);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (text.length === 0 && n.type === "inlineCode") {
|
|
131
|
+
if (n.value.startsWith("@")) {
|
|
132
|
+
// this contains directives!
|
|
133
|
+
n.value.split(/\s+/).forEach(directive => directives.push(directive));
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
// this contains precondition nodes..
|
|
137
|
+
preconditionNodes.push(n);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
optionNode.preconditionChildren = preconditionNodes;
|
|
142
|
+
optionNode.effectChildren = effectNodes;
|
|
143
|
+
optionNode.directives = directives;
|
|
144
|
+
optionNode.text = text.join(" ").trim();
|
|
145
|
+
optionNode.link = link.join(" ");
|
|
146
|
+
if (optionNode.link.length === 0) {
|
|
147
|
+
optionNode.link = null;
|
|
148
|
+
}
|
|
149
|
+
if (optionNode.text.length === 0) {
|
|
150
|
+
optionNode.text = null;
|
|
151
|
+
}
|
|
152
|
+
if (optionNode.directives.length === 0) {
|
|
153
|
+
optionNode.directives = null;
|
|
154
|
+
}
|
|
155
|
+
if (optionNode.preconditionChildren.length === 0) {
|
|
156
|
+
optionNode.preconditionChildren = null;
|
|
157
|
+
}
|
|
158
|
+
if (optionNode.effectChildren.length === 0) {
|
|
159
|
+
optionNode.effectChildren = null;
|
|
160
|
+
}
|
|
161
|
+
return optionNode;
|
|
162
|
+
});
|
|
163
|
+
stateNode.options = options;
|
|
164
|
+
return stateNode;
|
|
165
|
+
}
|
|
166
|
+
const qvmState = unist_builder_1.default("questmarkVMState", {
|
|
167
|
+
stack: [],
|
|
168
|
+
context: {},
|
|
169
|
+
programList: [],
|
|
170
|
+
labelMap: {},
|
|
171
|
+
programCounter: 0,
|
|
172
|
+
exit: false,
|
|
173
|
+
pause: false
|
|
174
|
+
}, []);
|
|
175
|
+
const q = (a) => {
|
|
176
|
+
qvmState.programList.push(a);
|
|
177
|
+
};
|
|
178
|
+
const visitorFunc = (node, index, parent) => {
|
|
179
|
+
let getText = (n) => {
|
|
180
|
+
let text = "";
|
|
181
|
+
if (retainWhitespace) {
|
|
182
|
+
text = file_contents.substring(n.position.start.offset, n.position.end.offset);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
text = n.value;
|
|
186
|
+
}
|
|
187
|
+
return text;
|
|
188
|
+
};
|
|
189
|
+
let fixText = (n) => {
|
|
190
|
+
let text = getText(n);
|
|
191
|
+
if (parent.type === "paragraph" && parent.children.indexOf(n) === parent.children.length - 1) {
|
|
192
|
+
text = text + '\n\n';
|
|
193
|
+
}
|
|
194
|
+
text = text.replaceAll('\\*', '*').replaceAll('\\[', '[').replaceAll('\\]', ']').replaceAll('\\#', '#').replaceAll('\\`', '`').replaceAll('\\(', '(').replaceAll('\\)', ')');
|
|
195
|
+
if (parent.type === "emphasis" || parent.type === "strong") {
|
|
196
|
+
text = `*${text}*`;
|
|
197
|
+
}
|
|
198
|
+
if (strip_leading_newlines) {
|
|
199
|
+
text = text.replace(/^[\r\n]+/, "");
|
|
200
|
+
}
|
|
201
|
+
return text;
|
|
202
|
+
};
|
|
203
|
+
if (parent === undefined && node.type !== "questmarkDocument") {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
switch (node.type) {
|
|
207
|
+
case "questmarkDocument":
|
|
208
|
+
if (node.options) {
|
|
209
|
+
if (node.options["initial-context"]) {
|
|
210
|
+
Object.entries(node.options["initial-context"]).forEach(entry => {
|
|
211
|
+
if (typeof entry[1] === "string") {
|
|
212
|
+
q(tzo_1.pushString(entry[1]));
|
|
213
|
+
}
|
|
214
|
+
else if (typeof entry[1] === "number") {
|
|
215
|
+
q(tzo_1.pushNumber(entry[1]));
|
|
216
|
+
}
|
|
217
|
+
q(tzo_1.pushString(entry[0]));
|
|
218
|
+
q(tzo_1.invokeFunction("setContext"));
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
if (node.options["initial-state"]) {
|
|
222
|
+
q(tzo_1.pushString(node.options["initial-state"]));
|
|
223
|
+
q(tzo_1.invokeFunction("goto"));
|
|
224
|
+
}
|
|
225
|
+
if (node.options["options"]) {
|
|
226
|
+
if (node.options["options"]["no_link_behaviour"]) {
|
|
227
|
+
if (node.options["options"]["no_link_behaviour"] === "exit") {
|
|
228
|
+
noLinkBehaviour = NoLinkBehaviour.EXIT;
|
|
229
|
+
}
|
|
230
|
+
else if (node.options["options"]["no_link_behaviour"] === "loopback_to_options") {
|
|
231
|
+
noLinkBehaviour = NoLinkBehaviour.LOOPBACK_TO_OPTIONS;
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
throw new Error(`Unknown 'options.no_link_behaviour': ${node.options["options"]["no_link_behaviour"]}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (node.options["options"]["whitespace"]) {
|
|
238
|
+
if (node.options["options"]["whitespace"] === "retain") {
|
|
239
|
+
retainWhitespace = true;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (node.options["options"]["emit_on"]) {
|
|
243
|
+
if (node.options["options"]["emit_on"] === "end_of_line") {
|
|
244
|
+
emitOn = EmitOn.END_OF_LINE;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (node.options["options"]["strip_leading_newlines"]) {
|
|
248
|
+
if (node.options["options"]["strip_leading_newlines"] === true) {
|
|
249
|
+
strip_leading_newlines = true;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break;
|
|
255
|
+
case "state":
|
|
256
|
+
const nodeLabel = node.name;
|
|
257
|
+
const nodeOptionsLabel = node.name + "__options";
|
|
258
|
+
qvmState.labelMap[nodeLabel] = qvmState.programList.length;
|
|
259
|
+
unist_util_visit_1.default(node, visitorFunc); // parse children immediately, before we parse the node's options
|
|
260
|
+
// if there are any missing emits, perform them now
|
|
261
|
+
if (missed_emits > 0) {
|
|
262
|
+
while (missed_emits > 1) {
|
|
263
|
+
q(tzo_1.invokeFunction("rconcat"));
|
|
264
|
+
missed_emits -= 1;
|
|
265
|
+
}
|
|
266
|
+
missed_emits = 0;
|
|
267
|
+
q(tzo_1.invokeFunction("emit")); // need to still emit!
|
|
268
|
+
}
|
|
269
|
+
qvmState.labelMap[nodeOptionsLabel] = qvmState.programList.length; // add a label immediately after the node's options to be able to shortcut jump to in certain cases
|
|
270
|
+
node.options.forEach(option => {
|
|
271
|
+
let has_precondition = false;
|
|
272
|
+
let has_once_directive = false;
|
|
273
|
+
let once_directive_name = null;
|
|
274
|
+
if (option.directives !== null && option.directives.includes('@once')) {
|
|
275
|
+
has_once_directive = true;
|
|
276
|
+
once_directive_name = `__once__${last_once_directive_nr}`;
|
|
277
|
+
last_once_directive_nr += 1;
|
|
278
|
+
}
|
|
279
|
+
if (has_once_directive) {
|
|
280
|
+
q(tzo_1.pushString(once_directive_name));
|
|
281
|
+
q(tzo_1.invokeFunction("hasContext"));
|
|
282
|
+
q(tzo_1.invokeFunction("jz"));
|
|
283
|
+
q(tzo_1.invokeFunction("{")); // once directive block start
|
|
284
|
+
}
|
|
285
|
+
if (option.preconditionChildren !== null) {
|
|
286
|
+
has_precondition = true;
|
|
287
|
+
option.preconditionChildren.forEach(child => {
|
|
288
|
+
if (child.type === "inlineCode") {
|
|
289
|
+
tokenizer.parse(child.value).forEach(i => q(i));
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
throw new Error("preconditionChildren contain non-inlineCode elements. Aborting!");
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
if (has_precondition) {
|
|
297
|
+
q(tzo_1.invokeFunction("jgz"));
|
|
298
|
+
q(tzo_1.invokeFunction("{")); // precondition block start
|
|
299
|
+
}
|
|
300
|
+
if (option.text !== null) {
|
|
301
|
+
if (option.text.includes("`")) {
|
|
302
|
+
// TODO: support inlineCode in options. Can do via `concat`.
|
|
303
|
+
console.warn("WARN: Option text contains a backtick. Inline code elements in option blocks is currently not supported!");
|
|
304
|
+
}
|
|
305
|
+
q(tzo_1.pushString(option.text));
|
|
306
|
+
}
|
|
307
|
+
q(tzo_1.invokeFunction("ppc")); // push address of effect body to stack
|
|
308
|
+
q(tzo_1.pushNumber(4));
|
|
309
|
+
q(tzo_1.invokeFunction("+"));
|
|
310
|
+
q(tzo_1.invokeFunction("{")); // effect body start
|
|
311
|
+
if (has_once_directive) {
|
|
312
|
+
// set the once directive context variable immediatley
|
|
313
|
+
q(tzo_1.pushNumber(1));
|
|
314
|
+
q(tzo_1.pushString(once_directive_name));
|
|
315
|
+
q(tzo_1.invokeFunction("setContext"));
|
|
316
|
+
}
|
|
317
|
+
if (option.effectChildren !== null) {
|
|
318
|
+
option.effectChildren.forEach(child => {
|
|
319
|
+
if (child.type === "inlineCode") {
|
|
320
|
+
tokenizer.parse(child.value).forEach(i => q(i));
|
|
321
|
+
}
|
|
322
|
+
else if (child.type === "code") {
|
|
323
|
+
if (child.lang === "comment") {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
tokenizer.parse(child.value).forEach(i => q(i));
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
let t = getText(child);
|
|
330
|
+
q(tzo_1.pushString(fixText(child), t));
|
|
331
|
+
if (emitOn === EmitOn.CLASSIC || (emitOn === EmitOn.END_OF_LINE && t.replace(/[\t\f\v ]+$/, "").endsWith('\n'))) {
|
|
332
|
+
while (missed_emits > 0) {
|
|
333
|
+
q(tzo_1.invokeFunction("rconcat"));
|
|
334
|
+
missed_emits -= 1;
|
|
335
|
+
}
|
|
336
|
+
q(tzo_1.invokeFunction("emit"));
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
missed_emits += 1;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
// if there are any missing emits, perform them now before we close off this option effect body
|
|
345
|
+
if (missed_emits > 0) {
|
|
346
|
+
while (missed_emits > 1) {
|
|
347
|
+
q(tzo_1.invokeFunction("rconcat"));
|
|
348
|
+
missed_emits -= 1;
|
|
349
|
+
}
|
|
350
|
+
missed_emits = 0;
|
|
351
|
+
q(tzo_1.invokeFunction("emit")); // need to still emit!
|
|
352
|
+
}
|
|
353
|
+
if (option.link !== null) {
|
|
354
|
+
q(tzo_1.pushString(option.link.substr(1)));
|
|
355
|
+
q(tzo_1.invokeFunction("goto"));
|
|
356
|
+
}
|
|
357
|
+
if (noLinkBehaviour === NoLinkBehaviour.LOOPBACK_TO_OPTIONS) {
|
|
358
|
+
q(tzo_1.pushString(nodeOptionsLabel)); // ensure that options with no link or "goto" effect loop back to the options
|
|
359
|
+
q(tzo_1.invokeFunction("goto"));
|
|
360
|
+
}
|
|
361
|
+
else if (noLinkBehaviour === NoLinkBehaviour.EXIT) {
|
|
362
|
+
q(tzo_1.invokeFunction("exit")); // ensure that options with no effect or link cause the VM to exit
|
|
363
|
+
}
|
|
364
|
+
q(tzo_1.invokeFunction("}")); // effect body end
|
|
365
|
+
q(tzo_1.invokeFunction("response"));
|
|
366
|
+
if (has_once_directive) {
|
|
367
|
+
// when there was a once directive, ensure we close its block
|
|
368
|
+
q(tzo_1.invokeFunction("}")); // once directive block end
|
|
369
|
+
}
|
|
370
|
+
if (has_precondition) {
|
|
371
|
+
// when there was a precondition, ensure we close the precondition block
|
|
372
|
+
q(tzo_1.invokeFunction("}")); // precondition block end
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
q(tzo_1.invokeFunction("getResponse")); // getResponse is expected to pause the VM and push the relevant programlist index onto the stack
|
|
376
|
+
q(tzo_1.invokeFunction("goto")); // goto whatever was pushed onto the stack by getResponse
|
|
377
|
+
return "skip";
|
|
378
|
+
// children have been parsed earlier
|
|
379
|
+
break;
|
|
380
|
+
case "inlineCode":
|
|
381
|
+
case "code":
|
|
382
|
+
if (node.lang === "comment") {
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
tokenizer.parse(node.value).forEach(i => q(i));
|
|
386
|
+
break;
|
|
387
|
+
case "text":
|
|
388
|
+
let t = getText(node);
|
|
389
|
+
q(tzo_1.pushString(fixText(node), t));
|
|
390
|
+
if (emitOn === EmitOn.CLASSIC || (emitOn === EmitOn.END_OF_LINE && t.replace(/[\t\f\v ]+$/, "").endsWith('\n'))) {
|
|
391
|
+
while (missed_emits > 0) {
|
|
392
|
+
q(tzo_1.invokeFunction("rconcat"));
|
|
393
|
+
missed_emits -= 1;
|
|
394
|
+
}
|
|
395
|
+
q(tzo_1.invokeFunction("emit"));
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
missed_emits += 1;
|
|
399
|
+
}
|
|
400
|
+
break;
|
|
401
|
+
default:
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
unist_util_visit_1.default(root, visitorFunc);
|
|
406
|
+
q(tzo_1.invokeFunction("exit")); // ensure we always exit at the end
|
|
407
|
+
return {
|
|
408
|
+
parsedMDFile: unist_util_remove_position_1.default(root, true),
|
|
409
|
+
qvmState
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
exports.parseMarkdown = parseMarkdown;
|
|
350
413
|
//# sourceMappingURL=parseMarkdown.js.map
|