kni 4.0.2 → 5.0.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/story.js CHANGED
@@ -1,178 +1,187 @@
1
- 'use strict';
1
+ import * as Path from './path.js';
2
2
 
3
- var Path = require('./path');
4
-
5
- var constructors = {};
6
-
7
- module.exports = Story;
8
-
9
- function Story() {
3
+ export default class Story {
4
+ constructor() {
10
5
  this.states = {};
11
6
  this.errors = [];
12
7
  Object.seal(this);
13
- }
14
-
15
- Story.constructors = constructors;
8
+ }
16
9
 
17
- Story.prototype.create = function create(path, type, arg, position) {
18
- var name = Path.toName(path);
19
- var Node = constructors[type];
20
- // istanbul ignore if
10
+ create(path, type, arg, position) {
11
+ const name = Path.toName(path);
12
+ const Node = this.constructors[type];
21
13
  if (!Node) {
22
- throw new Error('No node constructor for type: ' + type);
14
+ throw new Error(`No node constructor for type: ${type}`);
23
15
  }
24
- var node = new Node(arg);
16
+ const node = new Node(arg);
25
17
  node.position = position;
26
18
  this.states[name] = node;
27
19
  return node;
28
- };
20
+ }
29
21
 
30
- // istanbul ignore next
31
- Story.prototype.error = function _error(error) {
22
+ error(error) {
32
23
  this.errors.push(error);
33
- };
34
-
35
- constructors.text = Text;
36
- function Text(text) {
37
- this.type = 'text';
38
- this.text = text;
39
- this.lift = ' ';
40
- this.drop = ' ';
41
- this.next = 'RET';
42
- this.position = null;
43
- Object.seal(this);
44
- }
45
-
46
- constructors.echo = Echo;
47
- function Echo(expression) {
48
- this.type = 'echo';
49
- this.expression = expression;
50
- this.lift = '';
51
- this.drop = '';
52
- this.next = 'RET';
53
- this.position = null;
54
- Object.seal(this);
55
- }
56
-
57
- constructors.option = Option;
58
- function Option(label) {
59
- this.type = 'opt';
60
- this.question = [];
61
- this.answer = [];
62
- this.keywords = null;
63
- this.next = 'RET';
64
- this.position = null;
65
- Object.seal(this);
66
- }
67
-
68
- constructors.goto = Goto;
69
- function Goto(next) {
70
- this.type = 'goto';
71
- this.next = next;
72
- this.position = null;
73
- Object.seal(this);
74
- }
75
-
76
- constructors.call = Call;
77
- function Call(label) {
78
- this.type = 'call';
79
- this.label = label;
80
- this.args = null;
81
- this.next = 'RET';
82
- this.branch = 'RET';
83
- this.position = null;
84
- Object.seal(this);
85
- }
86
-
87
- constructors.cue = Cue;
88
- function Cue(cue) {
89
- this.type = 'cue';
90
- this.cue = cue;
91
- this.next = 'RET';
92
- this.position = null;
93
- Object.seal(this);
94
- }
95
-
96
- constructors.def = Def;
97
- function Def(locals) {
98
- this.type = 'def';
99
- this.locals = locals;
100
- this.next = 'RET';
101
- this.position = null;
102
- Object.seal(this);
103
- }
104
-
105
- constructors.jump = Jump;
106
- function Jump(condition) {
107
- this.type = 'jump';
108
- this.condition = condition;
109
- this.branch = 'RET';
110
- this.next = 'RET';
111
- this.position = null;
112
- Object.seal(this);
113
- }
114
-
115
- constructors.switch = Switch;
116
- function Switch(expression) {
117
- this.type = 'switch';
118
- this.expression = expression;
119
- this.variable = null;
120
- this.value = 0;
121
- this.mode = null;
122
- this.branches = [];
123
- this.weights = [];
124
- this.next = 'RET';
125
- this.position = null;
126
- Object.seal(this);
127
- }
128
-
129
- constructors.move = Move;
130
- function Move() {
131
- this.type = 'move';
132
- this.source = null;
133
- this.target = null;
134
- this.next = 'RET';
135
- this.position = null;
136
- Object.seal(this);
137
- }
138
-
139
- constructors.break = Break;
140
- function Break() {
141
- this.type = 'br';
142
- this.next = 'RET';
143
- this.position = null;
144
- Object.seal(this);
145
- }
146
-
147
- constructors.paragraph = Paragraph;
148
- function Paragraph() {
149
- this.type = 'par';
150
- this.next = 'RET';
151
- this.position = null;
152
- Object.seal(this);
153
- }
154
-
155
- constructors.rule = Rule;
156
- function Rule() {
157
- this.type = 'rule';
158
- this.next = 'RET';
159
- this.position = null;
160
- Object.seal(this);
161
- }
162
-
163
- constructors.ask = Ask;
164
- function Ask() {
165
- this.type = 'ask';
166
- this.position = null;
167
- Object.seal(this);
168
- }
169
-
170
- constructors.read = Read;
171
- function Read(variable) {
172
- this.type = 'read';
173
- this.next = 'RET';
174
- this.variable = variable;
175
- this.cue = null;
176
- this.position = null;
177
- Object.seal(this);
24
+ }
25
+
26
+ constructors = {
27
+ text: class Text {
28
+ constructor(text) {
29
+ this.type = 'text';
30
+ this.text = text;
31
+ this.lift = ' ';
32
+ this.drop = ' ';
33
+ this.next = 'RET';
34
+ this.position = null;
35
+ Object.seal(this);
36
+ }
37
+ },
38
+
39
+ echo: class Echo {
40
+ constructor(expression) {
41
+ this.type = 'echo';
42
+ this.expression = expression;
43
+ this.lift = '';
44
+ this.drop = '';
45
+ this.next = 'RET';
46
+ this.position = null;
47
+ Object.seal(this);
48
+ }
49
+ },
50
+
51
+ option: class Option {
52
+ constructor(_label) {
53
+ this.type = 'opt';
54
+ this.question = [];
55
+ this.answer = [];
56
+ this.keywords = null;
57
+ this.next = 'RET';
58
+ this.position = null;
59
+ Object.seal(this);
60
+ }
61
+ },
62
+
63
+ goto: class Goto {
64
+ constructor(next) {
65
+ this.type = 'goto';
66
+ this.next = next;
67
+ this.position = null;
68
+ Object.seal(this);
69
+ }
70
+ },
71
+
72
+ call: class Call {
73
+ constructor(label) {
74
+ this.type = 'call';
75
+ this.label = label;
76
+ this.args = null;
77
+ this.next = 'RET';
78
+ this.branch = 'RET';
79
+ this.position = null;
80
+ Object.seal(this);
81
+ }
82
+ },
83
+
84
+ cue: class Cue {
85
+ constructor(cue) {
86
+ this.type = 'cue';
87
+ this.cue = cue;
88
+ this.next = 'RET';
89
+ this.position = null;
90
+ Object.seal(this);
91
+ }
92
+ },
93
+
94
+ def: class Def {
95
+ constructor(locals) {
96
+ this.type = 'def';
97
+ this.locals = locals;
98
+ this.next = 'RET';
99
+ this.position = null;
100
+ Object.seal(this);
101
+ }
102
+ },
103
+
104
+ jump: class Jump {
105
+ constructor(condition) {
106
+ this.type = 'jump';
107
+ this.condition = condition;
108
+ this.branch = 'RET';
109
+ this.next = 'RET';
110
+ this.position = null;
111
+ Object.seal(this);
112
+ }
113
+ },
114
+
115
+ switch: class Switch {
116
+ constructor(expression) {
117
+ this.type = 'switch';
118
+ this.expression = expression;
119
+ this.variable = null;
120
+ this.value = 0;
121
+ this.mode = null;
122
+ this.branches = [];
123
+ this.weights = [];
124
+ this.next = 'RET';
125
+ this.position = null;
126
+ Object.seal(this);
127
+ }
128
+ },
129
+
130
+ move: class Move {
131
+ constructor() {
132
+ this.type = 'move';
133
+ this.source = null;
134
+ this.target = null;
135
+ this.next = 'RET';
136
+ this.position = null;
137
+ Object.seal(this);
138
+ }
139
+ },
140
+
141
+ break: class Break {
142
+ constructor() {
143
+ this.type = 'br';
144
+ this.next = 'RET';
145
+ this.position = null;
146
+ Object.seal(this);
147
+ }
148
+ },
149
+
150
+ paragraph: class Paragraph {
151
+ constructor() {
152
+ this.type = 'par';
153
+ this.next = 'RET';
154
+ this.position = null;
155
+ Object.seal(this);
156
+ }
157
+ },
158
+
159
+ rule: class Rule {
160
+ constructor() {
161
+ this.type = 'rule';
162
+ this.next = 'RET';
163
+ this.position = null;
164
+ Object.seal(this);
165
+ }
166
+ },
167
+
168
+ ask: class Ask {
169
+ constructor() {
170
+ this.type = 'ask';
171
+ this.position = null;
172
+ Object.seal(this);
173
+ }
174
+ },
175
+
176
+ read: class Read {
177
+ constructor(variable) {
178
+ this.type = 'read';
179
+ this.next = 'RET';
180
+ this.variable = variable;
181
+ this.cue = null;
182
+ this.position = null;
183
+ Object.seal(this);
184
+ }
185
+ },
186
+ };
178
187
  }
package/test.js ADDED
@@ -0,0 +1,6 @@
1
+ Error.stackTraceLimit = 1024;
2
+
3
+ import './outline-lexer-test.js';
4
+ import './inline-lexer-test.js';
5
+ import './engine-test.js';
6
+ import './kni-test.js';
package/translate-json.js CHANGED
@@ -1,5 +1,3 @@
1
- 'use strict';
2
- module.exports = translate;
3
- function translate(module) {
4
- module.text = 'module.exports = ' + module.text;
5
- }
1
+ export default module => {
2
+ module.text = `export default ${module.text}`;
3
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "noEmit": true,
5
+
6
+ "module": "CommonJS",
7
+ "target": "es2020",
8
+
9
+ "strict": true
10
+ }
11
+ }
package/verify.js CHANGED
@@ -1,143 +1,147 @@
1
- 'use strict';
2
-
3
- var xorshift = require('xorshift');
4
- var Engine = require('./engine');
5
- var Console = require('./console');
6
- var Scanner = require('./scanner');
7
- var OutlineLexer = require('./outline-lexer');
8
- var InlineLexer = require('./inline-lexer');
9
- var Parser = require('./parser');
10
- var Story = require('./story');
11
- var Path = require('./path');
12
- var grammar = require('./grammar');
13
- var link = require('./link');
14
-
15
- module.exports = verify;
16
-
17
- function verify(kni, trans, handler, kniscript) {
18
- var lines = trans.split('\n');
19
-
20
- // filter the transcript for given answers
21
- var answers = [];
22
- for (var i = 0; i < lines.length; i++) {
23
- var line = lines[i];
24
- if (line.lastIndexOf('>', 0) === 0) {
25
- answers.push(line.slice(1).trim());
26
- }
1
+ import xorshift from 'xorshift';
2
+ import Engine from './engine.js';
3
+ import Console from './console.js';
4
+ import Scanner from './scanner.js';
5
+ import OutlineLexer from './outline-lexer.js';
6
+ import InlineLexer from './inline-lexer.js';
7
+ import Parser from './parser.js';
8
+ import Story from './story.js';
9
+ import * as Path from './path.js';
10
+ import start from './grammar.js';
11
+ import link from './link.js';
12
+
13
+ const verify = (kni, trans, handler, kniscript) => {
14
+ const lines = trans.split('\n');
15
+
16
+ // filter the transcript for given answers
17
+ const answers = [];
18
+ for (const line of lines) {
19
+ if (line.lastIndexOf('>', 0) === 0) {
20
+ answers.push(line.slice(1).trim());
27
21
  }
22
+ }
28
23
 
29
- var path = Path.start();
30
- var base = [];
31
-
32
- // build a story from the kni
33
- var story = new Story();
34
- var p = new Parser(grammar.start(story, path, base));
35
- var il = new InlineLexer(p);
36
- var ol = new OutlineLexer(il);
37
- var s = new Scanner(ol, kniscript);
38
-
39
- s.next(kni);
40
- s.return();
41
-
42
- link(story);
43
-
44
- // istanbul ignore if
45
- if (story.errors.length) {
46
- var errors = '';
47
- for (var i = 0; i < story.errors.length; i++) {
48
- errors += story.errors[i] + '\n';
49
- }
50
-
51
- if (errors === trans) {
52
- return {
53
- pass: true,
54
- expected: 'errors',
55
- actual: 'errors',
56
- };
57
- }
58
-
59
- for (var i = 0; i < story.errors.length; i++) {
60
- console.error(story.errors[i]);
61
- }
62
- return {
63
- pass: false,
64
- expected: trans,
65
- actual: errors,
66
- };
24
+ const path = Path.start();
25
+ const base = [];
26
+
27
+ // build a story from the kni
28
+ const story = new Story();
29
+ const p = new Parser(start(story, path, base));
30
+ const il = new InlineLexer(p);
31
+ const ol = new OutlineLexer(il);
32
+ const s = new Scanner(ol, kniscript);
33
+
34
+ s.next(kni);
35
+ s.return();
36
+
37
+ link(story);
38
+
39
+ if (story.errors.length) {
40
+ let errors = '';
41
+ for (const err of story.errors) {
42
+ errors += `${err}\n`;
67
43
  }
68
44
 
69
- var states = story.states;
70
-
71
- // TODO support alternate seeds
72
- var seed = 0;
73
- // I rolled 4d64k this morning, for kni.js
74
- var randomer = new xorshift.constructor([
75
- 37615 ^ seed,
76
- 54552 ^ seed,
77
- 59156 ^ seed,
78
- 24695 ^ seed
79
- ]);
80
-
81
- var writer = new StringWriter();
82
- var render = new Console(writer);
83
- var readline = new FakeReadline(writer, answers);
84
- var engine = new Engine({
85
- story: states,
86
- start: 'start',
87
- handler: handler,
88
- render: render,
89
- dialog: readline,
90
- randomer: randomer
91
- });
92
- readline.engine = engine;
93
- engine.reset();
94
-
95
- var expected = trans.trim();
96
- var actual = writer.string.trim();
45
+ if (errors === trans) {
46
+ return {
47
+ pass: true,
48
+ expected: 'errors',
49
+ actual: 'errors',
50
+ };
51
+ }
52
+
53
+ for (const err of story.errors) {
54
+ console.error(err);
55
+ }
97
56
  return {
98
- pass: expected === actual,
99
- expected: expected,
100
- actual: actual
57
+ pass: false,
58
+ expected: trans,
59
+ actual: errors,
101
60
  };
102
- }
61
+ }
62
+
63
+ const states = story.states;
64
+
65
+ // TODO support alternate seeds
66
+ const seed = 0;
67
+ // I rolled 4d64k this morning, for kni.js
68
+ const randomer = new xorshift.constructor([
69
+ 37615 ^ seed,
70
+ 54552 ^ seed,
71
+ 59156 ^ seed,
72
+ 24695 ^ seed,
73
+ ]);
74
+
75
+ const writer = new StringWriter();
76
+ const render = new Console(writer);
77
+ const readline = new FakeReadline(writer, answers, kniscript);
78
+ const engine = new Engine({
79
+ story: states,
80
+ start: 'start',
81
+ handler: handler,
82
+ render: render,
83
+ dialog: readline,
84
+ randomer: randomer,
85
+ });
86
+ readline.engine = engine;
87
+ engine.reset();
88
+
89
+ const expected = trans.trim();
90
+ const actual = writer.string.trim();
91
+ return {
92
+ pass: expected === actual,
93
+ expected: expected,
94
+ actual: actual,
95
+ };
96
+ };
103
97
 
104
- function FakeReadline(writer, answers) {
98
+ export default verify;
99
+
100
+ class FakeReadline {
101
+ constructor(writer, answers, kniscript) {
105
102
  this.writer = writer;
106
103
  this.answers = answers;
104
+ this.kniscript = kniscript;
107
105
  this.engine = null;
108
106
  this.history = [];
109
107
  Object.seal(this);
110
- }
108
+ }
111
109
 
112
- FakeReadline.prototype.ask = function ask(question) {
113
- var answer = this.answers.shift();
114
- // istanbul ignore if
110
+ ask(_question) {
111
+ const answer = this.answers.shift();
115
112
  if (answer == null) {
116
- return;
113
+ return;
117
114
  }
118
- this.writer.write(('> ' + answer).trim() + '\n');
115
+ this.writer.write(`${`> ${answer}`.trim()}\n`);
119
116
 
120
117
  if (answer === 'quit') {
118
+ // noop
121
119
  } else if (answer === 'replay') {
122
- this.writer.write('\n');
123
- this.engine.resume(this.engine.waypoint);
120
+ this.writer.write('\n');
121
+ this.engine.resume(this.engine.waypoint);
124
122
  } else if (answer === 'back') {
125
- this.writer.write('\n');
126
- this.engine.waypoint = this.history.pop();
127
- this.engine.resume(this.engine.waypoint);
123
+ this.writer.write('\n');
124
+ this.engine.waypoint = this.history.pop();
125
+ this.engine.resume(this.engine.waypoint);
128
126
  } else {
129
- this.history.push(this.engine.waypoint);
130
- this.engine.answer(answer);
127
+ this.history.push(this.engine.waypoint);
128
+ this.engine.answer(answer);
131
129
  }
132
- };
130
+ }
133
131
 
134
- FakeReadline.prototype.close = function close() {
135
- };
132
+ close() {}
136
133
 
137
- function StringWriter() {
138
- this.string = '';
134
+ meterFault() {
135
+ throw new Error(`meter fault in ${this.kniscript}`);
136
+ }
139
137
  }
140
138
 
141
- StringWriter.prototype.write = function write(string) {
139
+ class StringWriter {
140
+ constructor() {
141
+ this.string = '';
142
+ }
143
+
144
+ write(string) {
142
145
  this.string += string;
143
- };
146
+ }
147
+ }