-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfunction.js
91 lines (78 loc) · 2.58 KB
/
function.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
85
86
87
88
89
90
91
setup.functions_macro ??= { prefix: 'tw' };
Macro.add('function', {
tags : null,
handler() {
if (this.args.length === 0) {
return this.error('no function name specified');
}
const functionName = this.args[0];
const MacroContext = this;
const prefix = setup?.functions_macro?.prefix ?? "tw";
if (prefix && typeof window[prefix] == "undefined") { window[prefix] = { } }
const target = prefix ? window[prefix] : window;
if (target[functionName]) {
return this.error(`cannot clobber existing function "${functionName}"`);
}
try {
target[functionName] = (function (functionCode) {
return function() {
const shadowStore = {};
// Cache the existing value of the `_args` variable, if necessary.
if (State.temporary.hasOwnProperty('args')) {
shadowStore._args = State.temporary.args;
}
// Cache the existing value of the `_return` variable, if necessary.
if (State.temporary.hasOwnProperty('return')) {
shadowStore._return = State.temporary.return;
}
// Set up the function `_args` variable and add a shadow.
State.temporary.args = [...arguments];
MacroContext.addShadow('_args');
MacroContext.addShadow('_return');
try {
// Set up the error trapping variables.
const resFrag = document.createDocumentFragment();
const errList = [];
// Wikify the function's code.
new Wikifier(resFrag, functionCode);
// Carry over the output, unless there were errors.
Array.from(resFrag.querySelectorAll('.error')).forEach(errEl => {
errList.push(errEl.textContent);
});
if (errList.length === 0) {
return State.temporary.return;
}
else {
return MacroContext.error(`error${errList.length > 1 ? 's' : ''} within function code (${errList.join('; ')})`);
}
}
catch (ex) {
return MacroContext.error(`cannot execute function: ${ex.message}`);
}
finally {
// Revert the `_args` variable shadowing.
if (shadowStore.hasOwnProperty('_args')) {
State.temporary.args = shadowStore._args;
}
else {
delete State.temporary.args;
}
// Revert the `_return` variable shadowing.
if (shadowStore.hasOwnProperty('_return')) {
State.temporary.return = shadowStore._return;
}
else {
delete State.temporary.return;
}
}
}
})(this.payload[0].contents);
}
catch (ex) {
return this.error(`cannot create function "${functionName}": ${ex.message}`);
}
}
});
Story.lookup("tags", "function").forEach(p => {
$.wiki(p.text);
});