n3.js-messages 0.1.2 → 0.2.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 +73 -8
- package/browser/THIRD-PARTY-LICENSES.txt +172 -0
- package/browser/index.global.js +27 -0
- package/browser/index.global.js.LEGAL.txt +15 -0
- package/browser/index.global.js.map +7 -0
- package/browser/index.js +27 -0
- package/browser/index.js.LEGAL.txt +15 -0
- package/browser/index.js.map +7 -0
- package/browser.d.ts +26 -0
- package/common.d.ts +89 -0
- package/index.d.ts +2 -76
- package/lib/MessageParser.js +38 -4
- package/lib/MessageParser.js.map +1 -0
- package/lib/MessageParserCore.js +42 -6
- package/lib/MessageParserCore.js.map +1 -0
- package/lib/MessageStreamParser.js +12 -1
- package/lib/MessageStreamParser.js.map +1 -0
- package/lib/MessageStreamWriter.js +13 -3
- package/lib/MessageStreamWriter.js.map +1 -0
- package/lib/MessageWriter.js +141 -18
- package/lib/MessageWriter.js.map +1 -0
- package/lib/formats.js +7 -2
- package/lib/formats.js.map +1 -0
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -0
- package/package.json +42 -14
- package/src/MessageParser.js +35 -3
- package/src/MessageParserCore.js +34 -5
- package/src/MessageStreamParser.js +8 -0
- package/src/MessageStreamWriter.js +10 -2
- package/src/MessageWriter.js +138 -20
- package/src/browser.js +61 -0
- package/src/formats.js +5 -1
- package/src/internal.d.ts +15 -0
- package/lib/MessageScanner.js +0 -395
package/lib/MessageWriter.js
CHANGED
|
@@ -16,6 +16,7 @@ var _formats = require("./formats.js");
|
|
|
16
16
|
// (current graph, subject, predicate) leaks from one message into the next, and trailing
|
|
17
17
|
// empty messages survive a round trip (a delimiter before the end of the input does not create a message).
|
|
18
18
|
|
|
19
|
+
/** @extends {Writer<import('@rdfjs/types').BaseQuad>} */
|
|
19
20
|
class LogWriter extends _n.Writer {
|
|
20
21
|
// ### `addDelimiter` ends the current message
|
|
21
22
|
addDelimiter() {
|
|
@@ -23,55 +24,125 @@ class LogWriter extends _n.Writer {
|
|
|
23
24
|
this._write(this._lineMode ? 'MESSAGE\n' : '@message .\n');
|
|
24
25
|
}
|
|
25
26
|
}
|
|
27
|
+
|
|
28
|
+
/** @typedef {import('./internal.js').Done} Done */
|
|
29
|
+
/** @typedef {import('./internal.js').End} End */
|
|
30
|
+
/** @typedef {import('../common.js').MessageWriterOptions} Options */
|
|
31
|
+
/** @typedef {Pick<import('./internal.js').Output, 'write'> & Partial<Pick<import('./internal.js').Output, 'end'>>} Output */
|
|
26
32
|
class MessageWriter {
|
|
27
33
|
// `outputStream` is optional: without it, `end` returns the output as a string
|
|
34
|
+
/** @overload
|
|
35
|
+
* @param {Options} [options] */
|
|
36
|
+
/** @overload
|
|
37
|
+
* @param {Output | null} outputStream
|
|
38
|
+
* @param {Options} [options] */
|
|
39
|
+
/** @param {Output | Options | null} [outputStream]
|
|
40
|
+
* @param {Options} [options] */
|
|
28
41
|
constructor(outputStream, options) {
|
|
29
|
-
if (outputStream && typeof outputStream.write !== 'function') options = outputStream, outputStream = null;
|
|
42
|
+
if (outputStream && typeof /** @type {Output} */outputStream.write !== 'function') options = /** @type {Options} */outputStream, outputStream = null;
|
|
30
43
|
options = options || {};
|
|
31
44
|
this._format = (0, _formats.resolveFormat)(options.format);
|
|
32
45
|
this._options = options;
|
|
33
46
|
this._version = options.version === undefined ? '1.2-messages' : options.version;
|
|
34
47
|
if (!(0, _formats.isMessagesVersion)(this._version) || !(0, _formats.isSupportedVersion)((0, _formats.baseVersion)(this._version))) throw new TypeError(`Unsupported RDF Messages version: "${this._version}"`);
|
|
35
48
|
this._output = '';
|
|
36
|
-
this._stream = outputStream;
|
|
49
|
+
this._stream = /** @type {Output | null | undefined} */outputStream;
|
|
37
50
|
this._endStream = !outputStream || options.end !== false;
|
|
38
51
|
this._pending = 0;
|
|
52
|
+
|
|
53
|
+
/** @type {Done[]} */
|
|
39
54
|
this._waiting = [];
|
|
55
|
+
|
|
56
|
+
/** @type {Error | null} */
|
|
40
57
|
this._error = null;
|
|
41
58
|
this._started = false;
|
|
42
59
|
this._ended = false;
|
|
60
|
+
this._open = false;
|
|
61
|
+
this._count = 0; // messages begun so far: the index of the next message
|
|
43
62
|
this._declared = Object.assign({}, options.prefixes);
|
|
63
|
+
|
|
64
|
+
/** @type {Record<string, string>} */
|
|
44
65
|
this._newPrefixes = {};
|
|
45
66
|
// The N3.js writer writes to this sink, which it never ends
|
|
67
|
+
/** @type {Pick<Output, 'write'>} */
|
|
46
68
|
this._sink = {
|
|
47
69
|
write: (chunk, encoding, done) => this._write(chunk, done)
|
|
48
70
|
};
|
|
71
|
+
|
|
72
|
+
/** @type {LogWriter | null} */
|
|
49
73
|
this._writer = null;
|
|
50
74
|
}
|
|
51
75
|
|
|
52
76
|
// ### `addMessage` writes the quads of one message, followed by a delimiter.
|
|
53
77
|
// The callback (or returned promise) completes once the output is flushed.
|
|
78
|
+
/** @param {import('@rdfjs/types').BaseQuad[]} quads
|
|
79
|
+
* @param {Done} [done] */
|
|
54
80
|
addMessage(quads, done) {
|
|
55
81
|
return this._complete(done, () => {
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
82
|
+
if (this._open) throw new Error('A message is already open');
|
|
83
|
+
this._begin();
|
|
84
|
+
for (const quad of quads || []) this._add(quad);
|
|
85
|
+
this._close();
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ### `beginMessage` opens a message. It is optional: the first `addQuad` opens one implicitly.
|
|
90
|
+
/** @param {Done} [done] */
|
|
91
|
+
beginMessage(done) {
|
|
92
|
+
return this._complete(done, () => {
|
|
93
|
+
if (this._open) throw new Error('A message is already open');
|
|
94
|
+
this._begin();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ### `addQuad` writes a quad into the open message right away (a message is opened if there is none).
|
|
99
|
+
// With a `messageIndex` (0-based), a change of index ends the current message and writes the empty
|
|
100
|
+
// messages in between, as rdf-writer-ts does; a lower index than the current one is an error.
|
|
101
|
+
/** @param {import('@rdfjs/types').BaseQuad} quad
|
|
102
|
+
* @param {number | Done} [messageIndex]
|
|
103
|
+
* @param {Done} [done] */
|
|
104
|
+
addQuad(quad, messageIndex, done) {
|
|
105
|
+
if (typeof messageIndex === 'function') done = messageIndex, messageIndex = undefined;
|
|
106
|
+
return this._complete(done, () => {
|
|
107
|
+
if (messageIndex !== undefined && messageIndex !== null) this._moveTo(messageIndex);else if (!this._open) this._begin();
|
|
108
|
+
this._add(quad);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ### `endMessage` ends the open message with a delimiter. Without an open message, it writes an empty one.
|
|
113
|
+
/** @param {Done} [done] */
|
|
114
|
+
endMessage(done) {
|
|
115
|
+
return this._complete(done, () => {
|
|
116
|
+
if (!this._open) this._begin();
|
|
117
|
+
this._close();
|
|
58
118
|
});
|
|
59
119
|
}
|
|
60
120
|
|
|
61
121
|
// ### `addPrefix` declares a prefix, which is written before the next message
|
|
62
122
|
// and stays in effect for all messages after it
|
|
123
|
+
/** @param {string} prefix
|
|
124
|
+
* @param {string | import('@rdfjs/types').NamedNode} iri
|
|
125
|
+
* @param {Done} [done] */
|
|
63
126
|
addPrefix(prefix, iri, done) {
|
|
64
127
|
return this._complete(done, () => {
|
|
65
|
-
if (!this._format.lineMode && this._declared[prefix] !== (iri
|
|
128
|
+
if (!this._format.lineMode && this._declared[prefix] !== (typeof iri === 'string' ? iri : iri.value)) this._newPrefixes[prefix] = typeof iri === 'string' ? iri : iri.value;
|
|
66
129
|
});
|
|
67
130
|
}
|
|
68
131
|
|
|
69
132
|
// ### `end` ends the log and, unless disabled, the output stream.
|
|
70
133
|
// The callback receives the output as a string if no output stream was given.
|
|
134
|
+
/** @overload
|
|
135
|
+
* @returns {Promise<string | void>} */
|
|
136
|
+
/** @overload
|
|
137
|
+
* @param {End} done
|
|
138
|
+
* @returns {void} */
|
|
139
|
+
/** @param {End} [done]
|
|
140
|
+
* @returns {Promise<string | void> | void} */
|
|
71
141
|
end(done) {
|
|
72
142
|
// Ending twice is harmless
|
|
73
143
|
if (this._ended) return typeof done === 'function' ? done(null) : Promise.resolve();
|
|
74
144
|
this._start();
|
|
145
|
+
if (this._open) this._close();
|
|
75
146
|
if (typeof done === 'function') return this._finish(done);
|
|
76
147
|
return new Promise((resolve, reject) => this._finish((error, result) => error ? reject(error) : resolve(result)));
|
|
77
148
|
}
|
|
@@ -79,40 +150,53 @@ class MessageWriter {
|
|
|
79
150
|
// ## Private methods
|
|
80
151
|
|
|
81
152
|
// Runs an action and reports completion with a callback or a promise
|
|
153
|
+
/** @param {Done | undefined} done
|
|
154
|
+
* @param {() => void} action
|
|
155
|
+
* @returns {Promise<void> | void} */
|
|
82
156
|
_complete(done, action) {
|
|
83
157
|
if (this._ended) this._error = this._error || new Error('Cannot write after end');else try {
|
|
84
158
|
action();
|
|
85
159
|
} catch (error) {
|
|
86
|
-
this._error = this._error || error;
|
|
160
|
+
this._error = this._error || (/** @type {Error} */error);
|
|
87
161
|
}
|
|
88
162
|
if (typeof done === 'function') return this._whenFlushed(done);
|
|
89
163
|
return new Promise((resolve, reject) => this._whenFlushed(error => error ? reject(error) : resolve()));
|
|
90
164
|
}
|
|
91
165
|
|
|
92
166
|
// Ends the output once all queued writes were accepted
|
|
167
|
+
/** @param {End} callback */
|
|
93
168
|
_finish(callback) {
|
|
94
169
|
this._ended = true;
|
|
95
170
|
this._whenFlushed(error => this._endOutput(error, callback));
|
|
96
171
|
}
|
|
172
|
+
|
|
173
|
+
/** @param {Error | null | undefined} error
|
|
174
|
+
* @param {End} callback */
|
|
97
175
|
_endOutput(error, callback) {
|
|
98
176
|
if (error || !this._endStream) return callback(error);
|
|
99
177
|
if (!this._stream) return callback(null, this._output);
|
|
100
178
|
try {
|
|
101
|
-
this._stream.end(endError => callback(endError));
|
|
179
|
+
(/** @type {Required<Output>} */this._stream).end(endError => callback(endError));
|
|
102
180
|
} catch (endError) {
|
|
103
|
-
callback(endError);
|
|
181
|
+
callback(/** @type {Error} */endError);
|
|
104
182
|
}
|
|
105
183
|
}
|
|
106
184
|
|
|
107
185
|
// Calls back once all queued writes were accepted by the output
|
|
186
|
+
/** @param {Done} done */
|
|
108
187
|
_whenFlushed(done) {
|
|
109
188
|
if (this._pending === 0) this._settle(done);else this._waiting.push(done);
|
|
110
189
|
}
|
|
190
|
+
|
|
191
|
+
/** @param {Done} done */
|
|
111
192
|
_settle(done) {
|
|
112
193
|
const error = this._error;
|
|
113
194
|
this._error = null;
|
|
114
195
|
done(error || null);
|
|
115
196
|
}
|
|
197
|
+
|
|
198
|
+
/** @param {string} chunk
|
|
199
|
+
* @param {Done} [done] */
|
|
116
200
|
_write(chunk, done) {
|
|
117
201
|
if (!this._stream) {
|
|
118
202
|
this._output += chunk;
|
|
@@ -122,11 +206,13 @@ class MessageWriter {
|
|
|
122
206
|
try {
|
|
123
207
|
this._stream.write(chunk, 'utf8', error => this._written(error, done));
|
|
124
208
|
} catch (error) {
|
|
125
|
-
this._written(error, done);
|
|
209
|
+
this._written(/** @type {Error} */error, done);
|
|
126
210
|
}
|
|
127
211
|
}
|
|
128
212
|
|
|
129
213
|
// Registers that the output accepted a write, and wakes up those waiting for the output
|
|
214
|
+
/** @param {Error | null | undefined} error
|
|
215
|
+
* @param {Done} [done] */
|
|
130
216
|
_written(error, done) {
|
|
131
217
|
this._pending--;
|
|
132
218
|
this._error = this._error || error || null;
|
|
@@ -150,30 +236,67 @@ class MessageWriter {
|
|
|
150
236
|
});
|
|
151
237
|
}
|
|
152
238
|
}
|
|
153
|
-
|
|
154
|
-
|
|
239
|
+
|
|
240
|
+
// Opens a message: declares the prefixes that were added since the previous one
|
|
241
|
+
_begin() {
|
|
242
|
+
this._start();
|
|
243
|
+
const writer = /** @type {LogWriter} */this._writer;
|
|
155
244
|
for (const prefix of Object.keys(this._newPrefixes)) {
|
|
156
|
-
|
|
157
|
-
|
|
245
|
+
const iri = /** @type {string} */this._newPrefixes[prefix];
|
|
246
|
+
writer.addPrefix(prefix, iri);
|
|
247
|
+
this._declared[prefix] = iri;
|
|
158
248
|
}
|
|
159
249
|
this._newPrefixes = {};
|
|
250
|
+
this._open = true;
|
|
251
|
+
this._count++;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** @param {import('@rdfjs/types').BaseQuad} quad */
|
|
255
|
+
_add(quad) {
|
|
256
|
+
/** @type {Done} */
|
|
160
257
|
const record = error => error && (this._error = this._error || error);
|
|
161
|
-
|
|
162
|
-
|
|
258
|
+
(/** @type {LogWriter} */this._writer).addQuad(quad.subject, quad.predicate, quad.object, quad.graph, record);
|
|
259
|
+
}
|
|
260
|
+
_close() {
|
|
261
|
+
this._open = false;
|
|
262
|
+
(/** @type {LogWriter} */this._writer).addDelimiter();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Makes message `index` the open message, writing empty messages for the gap
|
|
266
|
+
/** @param {number} index */
|
|
267
|
+
_moveTo(index) {
|
|
268
|
+
const current = this._count - 1;
|
|
269
|
+
if (!Number.isInteger(index) || index < 0) throw new RangeError(`Invalid message index: ${index}`);
|
|
270
|
+
if (this._open && index === current) return;
|
|
271
|
+
if (index <= current) throw new RangeError(`Message index ${index} is lower than the current message index ${current}`);
|
|
272
|
+
if (this._open) this._close();
|
|
273
|
+
while (this._count < index) {
|
|
274
|
+
this._begin();
|
|
275
|
+
this._close();
|
|
276
|
+
}
|
|
277
|
+
this._begin();
|
|
163
278
|
}
|
|
164
279
|
}
|
|
165
280
|
|
|
281
|
+
/** @param {Iterable<import('@rdfjs/types').BaseQuad[]>} messages
|
|
282
|
+
* @param {Options} [options]
|
|
283
|
+
* @returns {string} */
|
|
166
284
|
// ### `writeMessages` synchronously serializes an array of messages to a string
|
|
167
285
|
exports.default = MessageWriter;
|
|
168
286
|
function writeMessages(messages, options) {
|
|
169
287
|
const writer = new MessageWriter(options);
|
|
288
|
+
|
|
289
|
+
/** @type {Error[]} */
|
|
170
290
|
const errors = [];
|
|
171
|
-
let output;
|
|
291
|
+
let output = '';
|
|
292
|
+
|
|
293
|
+
/** @param {Error | null | undefined} error */
|
|
172
294
|
function collect(error) {
|
|
173
295
|
if (error) errors.push(error);
|
|
174
296
|
}
|
|
175
297
|
for (const message of messages) writer.addMessage(message, collect);
|
|
176
|
-
writer.end((error, result) => (collect(error), output = result));
|
|
298
|
+
writer.end((error, result) => (collect(error), output = /** @type {string} */result));
|
|
177
299
|
if (errors.length > 0) throw errors[0];
|
|
178
300
|
return output;
|
|
179
|
-
}
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=MessageWriter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageWriter.js","names":["Writer","resolveFormat","isMessagesVersion","isSupportedVersion","baseVersion"],"sources":["../src/MessageWriter.js"],"sourcesContent":["// **MessageWriter** writes RDF Message Logs (Turtle, TriG, N-Triples and N-Quads).\n//\n// One N3.js writer writes the whole log: its `version` option announces the log,\n// and after each message, `_endStatement` finishes the pending statement (and graph block)\n// before a delimiter is written (`MESSAGE` in line formats, `@message .` in Turtle and TriG).\n// That way, consumers receive a message as soon as it is written, no serialization state\n// (current graph, subject, predicate) leaks from one message into the next, and trailing\n// empty messages survive a round trip (a delimiter before the end of the input does not create a message).\nimport { Writer } from 'n3';\nimport { resolveFormat, isMessagesVersion, baseVersion, isSupportedVersion } from './formats.js';\n\n/** @extends {Writer<import('@rdfjs/types').BaseQuad>} */\nclass LogWriter extends Writer {\n // ### `addDelimiter` ends the current message\n addDelimiter() {\n this._endStatement();\n this._write(this._lineMode ? 'MESSAGE\\n' : '@message .\\n');\n }\n}\n\n/** @typedef {import('./internal.js').Done} Done */\n/** @typedef {import('./internal.js').End} End */\n/** @typedef {import('../common.js').MessageWriterOptions} Options */\n/** @typedef {Pick<import('./internal.js').Output, 'write'> & Partial<Pick<import('./internal.js').Output, 'end'>>} Output */\nexport default class MessageWriter {\n // `outputStream` is optional: without it, `end` returns the output as a string\n /** @overload\n * @param {Options} [options] */\n /** @overload\n * @param {Output | null} outputStream\n * @param {Options} [options] */\n /** @param {Output | Options | null} [outputStream]\n * @param {Options} [options] */\n constructor(outputStream, options) {\n if (outputStream && typeof /** @type {Output} */ (outputStream).write !== 'function')\n options = /** @type {Options} */ (outputStream), outputStream = null;\n options = options || {};\n this._format = resolveFormat(options.format);\n this._options = options;\n this._version = options.version === undefined ? '1.2-messages' : options.version;\n if (!isMessagesVersion(this._version) || !isSupportedVersion(baseVersion(this._version)))\n throw new TypeError(`Unsupported RDF Messages version: \"${this._version}\"`);\n\n this._output = '';\n this._stream = /** @type {Output | null | undefined} */ (outputStream);\n this._endStream = !outputStream || options.end !== false;\n this._pending = 0;\n\n /** @type {Done[]} */\n this._waiting = [];\n\n /** @type {Error | null} */\n this._error = null;\n this._started = false;\n this._ended = false;\n this._open = false;\n this._count = 0; // messages begun so far: the index of the next message\n this._declared = Object.assign({}, options.prefixes);\n\n /** @type {Record<string, string>} */\n this._newPrefixes = {};\n // The N3.js writer writes to this sink, which it never ends\n /** @type {Pick<Output, 'write'>} */\n this._sink = { write: (chunk, encoding, done) => this._write(chunk, done) };\n\n /** @type {LogWriter | null} */\n this._writer = null;\n }\n\n // ### `addMessage` writes the quads of one message, followed by a delimiter.\n // The callback (or returned promise) completes once the output is flushed.\n /** @param {import('@rdfjs/types').BaseQuad[]} quads\n * @param {Done} [done] */\n addMessage(quads, done) {\n return this._complete(done, () => {\n if (this._open) throw new Error('A message is already open');\n this._begin();\n for (const quad of quads || []) this._add(quad);\n this._close();\n });\n }\n\n // ### `beginMessage` opens a message. It is optional: the first `addQuad` opens one implicitly.\n /** @param {Done} [done] */\n beginMessage(done) {\n return this._complete(done, () => {\n if (this._open) throw new Error('A message is already open');\n this._begin();\n });\n }\n\n // ### `addQuad` writes a quad into the open message right away (a message is opened if there is none).\n // With a `messageIndex` (0-based), a change of index ends the current message and writes the empty\n // messages in between, as rdf-writer-ts does; a lower index than the current one is an error.\n /** @param {import('@rdfjs/types').BaseQuad} quad\n * @param {number | Done} [messageIndex]\n * @param {Done} [done] */\n addQuad(quad, messageIndex, done) {\n if (typeof messageIndex === 'function') done = messageIndex, messageIndex = undefined;\n return this._complete(done, () => {\n if (messageIndex !== undefined && messageIndex !== null) this._moveTo(messageIndex);\n else if (!this._open) this._begin();\n this._add(quad);\n });\n }\n\n // ### `endMessage` ends the open message with a delimiter. Without an open message, it writes an empty one.\n /** @param {Done} [done] */\n endMessage(done) {\n return this._complete(done, () => {\n if (!this._open) this._begin();\n this._close();\n });\n }\n\n // ### `addPrefix` declares a prefix, which is written before the next message\n // and stays in effect for all messages after it\n /** @param {string} prefix\n * @param {string | import('@rdfjs/types').NamedNode} iri\n * @param {Done} [done] */\n addPrefix(prefix, iri, done) {\n return this._complete(done, () => {\n if (!this._format.lineMode && this._declared[prefix] !== (typeof iri === 'string' ? iri : iri.value))\n this._newPrefixes[prefix] = typeof iri === 'string' ? iri : iri.value;\n });\n }\n\n // ### `end` ends the log and, unless disabled, the output stream.\n // The callback receives the output as a string if no output stream was given.\n /** @overload\n * @returns {Promise<string | void>} */\n /** @overload\n * @param {End} done\n * @returns {void} */\n /** @param {End} [done]\n * @returns {Promise<string | void> | void} */\n end(done) {\n // Ending twice is harmless\n if (this._ended)\n return typeof done === 'function' ? done(null) : Promise.resolve();\n this._start();\n if (this._open)\n this._close();\n if (typeof done === 'function')\n return this._finish(done);\n return new Promise((resolve, reject) => this._finish((error, result) => error ? reject(error) : resolve(result)));\n }\n\n // ## Private methods\n\n // Runs an action and reports completion with a callback or a promise\n /** @param {Done | undefined} done\n * @param {() => void} action\n * @returns {Promise<void> | void} */\n _complete(done, action) {\n if (this._ended)\n this._error = this._error || new Error('Cannot write after end');\n else\n try {\n action();\n }\n catch (error) {\n this._error = this._error || /** @type {Error} */ (error);\n }\n if (typeof done === 'function')\n return this._whenFlushed(done);\n return new Promise((resolve, reject) => this._whenFlushed(error => error ? reject(error) : resolve()));\n }\n\n // Ends the output once all queued writes were accepted\n /** @param {End} callback */\n _finish(callback) {\n this._ended = true;\n this._whenFlushed(error => this._endOutput(error, callback));\n }\n\n /** @param {Error | null | undefined} error\n * @param {End} callback */\n _endOutput(error, callback) {\n if (error || !this._endStream)\n return callback(error);\n if (!this._stream)\n return callback(null, this._output);\n try {\n (/** @type {Required<Output>} */ (this._stream)).end(endError => callback(endError));\n }\n catch (endError) {\n callback(/** @type {Error} */ (endError));\n }\n }\n\n // Calls back once all queued writes were accepted by the output\n /** @param {Done} done */\n _whenFlushed(done) {\n if (this._pending === 0)\n this._settle(done);\n else\n this._waiting.push(done);\n }\n\n /** @param {Done} done */\n _settle(done) {\n const error = this._error;\n this._error = null;\n done(error || null);\n }\n\n /** @param {string} chunk\n * @param {Done} [done] */\n _write(chunk, done) {\n if (!this._stream) {\n this._output += chunk;\n return done && done();\n }\n this._pending++;\n try {\n this._stream.write(chunk, 'utf8', error => this._written(error, done));\n }\n catch (error) {\n this._written(/** @type {Error} */ (error), done);\n }\n }\n\n // Registers that the output accepted a write, and wakes up those waiting for the output\n /** @param {Error | null | undefined} error\n * @param {Done} [done] */\n _written(error, done) {\n this._pending--;\n this._error = this._error || error || null;\n done && done(error);\n if (this._pending === 0)\n this._waiting.splice(0).forEach(callback => this._settle(callback));\n }\n\n // Announces the RDF Messages version, which makes parsers expect delimiters,\n // and declares the base and prefixes, which stay in effect for all messages\n _start() {\n if (!this._started) {\n this._started = true;\n const options = this._options;\n this._writer = new LogWriter(this._sink, {\n format: this._format.name,\n end: false,\n version: this._version,\n baseIRI: options.baseIRI,\n writeBase: options.writeBase,\n prefixes: this._declared,\n });\n }\n }\n\n // Opens a message: declares the prefixes that were added since the previous one\n _begin() {\n this._start();\n const writer = /** @type {LogWriter} */ (this._writer);\n for (const prefix of Object.keys(this._newPrefixes)) {\n const iri = /** @type {string} */ (this._newPrefixes[prefix]);\n writer.addPrefix(prefix, iri);\n this._declared[prefix] = iri;\n }\n this._newPrefixes = {};\n this._open = true;\n this._count++;\n }\n\n /** @param {import('@rdfjs/types').BaseQuad} quad */\n _add(quad) {\n /** @type {Done} */\n const record = error => error && (this._error = this._error || error);\n (/** @type {LogWriter} */ (this._writer)).addQuad(quad.subject, quad.predicate, quad.object, quad.graph, record);\n }\n _close() {\n this._open = false;\n (/** @type {LogWriter} */ (this._writer)).addDelimiter();\n }\n\n // Makes message `index` the open message, writing empty messages for the gap\n /** @param {number} index */\n _moveTo(index) {\n const current = this._count - 1;\n if (!Number.isInteger(index) || index < 0) throw new RangeError(`Invalid message index: ${index}`);\n if (this._open && index === current) return;\n if (index <= current) throw new RangeError(`Message index ${index} is lower than the current message index ${current}`);\n if (this._open) this._close();\n while (this._count < index) {\n this._begin();\n this._close();\n }\n this._begin();\n }\n}\n\n/** @param {Iterable<import('@rdfjs/types').BaseQuad[]>} messages\n * @param {Options} [options]\n * @returns {string} */\n// ### `writeMessages` synchronously serializes an array of messages to a string\nexport function writeMessages(messages, options) {\n const writer = new MessageWriter(options);\n\n /** @type {Error[]} */\n const errors = [];\n let output = '';\n\n /** @param {Error | null | undefined} error */\n function collect(error) {\n if (error)\n errors.push(error);\n }\n for (const message of messages)\n writer.addMessage(message, collect);\n writer.end((error, result) => (collect(error), output = /** @type {string} */ (result)));\n if (errors.length > 0)\n throw errors[0];\n return output;\n}\n"],"mappings":"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","ignoreList":[]}
|
package/lib/formats.js
CHANGED
|
@@ -9,6 +9,7 @@ exports.isSupportedVersion = isSupportedVersion;
|
|
|
9
9
|
exports.resolveFormat = resolveFormat;
|
|
10
10
|
// **formats** describes the RDF syntaxes that support RDF Messages.
|
|
11
11
|
|
|
12
|
+
/** @type {Record<string, { name: string; lineMode: boolean }>} */
|
|
12
13
|
const FORMATS = {
|
|
13
14
|
turtle: {
|
|
14
15
|
name: 'Turtle',
|
|
@@ -33,23 +34,27 @@ const BASE_VERSIONS = ['1.2', '1.2-basic', '1.1'];
|
|
|
33
34
|
|
|
34
35
|
// ### `resolveFormat` maps a format name or media type to a supported syntax
|
|
35
36
|
function resolveFormat(format = 'TriG') {
|
|
36
|
-
const key = String(format).toLowerCase().
|
|
37
|
+
const key = String(format).toLowerCase().replace(/;[\s\S]*$/, '').trim().replace(/^(?:text|application)\//, '').replace(/^x-/, '').replace(/[-_ ]/g, '');
|
|
37
38
|
const resolved = FORMATS[key];
|
|
38
39
|
if (!resolved) throw new TypeError(`Unsupported RDF Messages format: "${format}". ` + 'Supported formats are Turtle, TriG, N-Triples and N-Quads.');
|
|
39
40
|
return resolved;
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
/** @param {unknown} version */
|
|
42
44
|
// ### `isMessagesVersion` checks whether a version label announces RDF Messages
|
|
43
45
|
function isMessagesVersion(version) {
|
|
44
46
|
return typeof version === 'string' && version.endsWith('-messages');
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
/** @param {string} version */
|
|
47
50
|
// ### `baseVersion` strips the `-messages` suffix of a version label
|
|
48
51
|
function baseVersion(version) {
|
|
49
52
|
return isMessagesVersion(version) ? version.slice(0, -'-messages'.length) : version;
|
|
50
53
|
}
|
|
51
54
|
|
|
55
|
+
/** @param {string} version */
|
|
52
56
|
// ### `isSupportedVersion` checks whether a (base) version label is supported
|
|
53
57
|
function isSupportedVersion(version, supported = BASE_VERSIONS) {
|
|
54
58
|
return supported.includes(version);
|
|
55
|
-
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=formats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formats.js","names":[],"sources":["../src/formats.js"],"sourcesContent":["// **formats** describes the RDF syntaxes that support RDF Messages.\n\n/** @type {Record<string, { name: string; lineMode: boolean }>} */\nconst FORMATS = {\n turtle: { name: 'Turtle', lineMode: false },\n trig: { name: 'TriG', lineMode: false },\n ntriples: { name: 'N-Triples', lineMode: true },\n nquads: { name: 'N-Quads', lineMode: true },\n};\n\n// The version labels of RDF 1.2 syntaxes, as accepted by N3.js\nconst BASE_VERSIONS = ['1.2', '1.2-basic', '1.1'];\n\n// ### `resolveFormat` maps a format name or media type to a supported syntax\nexport function resolveFormat(format = 'TriG') {\n const key = String(format).toLowerCase().replace(/;[\\s\\S]*$/, '').trim()\n .replace(/^(?:text|application)\\//, '')\n .replace(/^x-/, '')\n .replace(/[-_ ]/g, '');\n const resolved = FORMATS[key];\n if (!resolved)\n throw new TypeError(`Unsupported RDF Messages format: \"${format}\". ` +\n 'Supported formats are Turtle, TriG, N-Triples and N-Quads.');\n return resolved;\n}\n\n/** @param {unknown} version */\n// ### `isMessagesVersion` checks whether a version label announces RDF Messages\nexport function isMessagesVersion(version) {\n return typeof version === 'string' && version.endsWith('-messages');\n}\n\n/** @param {string} version */\n// ### `baseVersion` strips the `-messages` suffix of a version label\nexport function baseVersion(version) {\n return isMessagesVersion(version) ? version.slice(0, -'-messages'.length) : version;\n}\n\n/** @param {string} version */\n// ### `isSupportedVersion` checks whether a (base) version label is supported\nexport function isSupportedVersion(version, supported = BASE_VERSIONS) {\n return supported.includes(version);\n}\n"],"mappings":";;;;;;;;;AAAA;;AAEA;AACA,MAAM,OAAO,GAAG;EACd,MAAM,EAAE;IAAE,IAAI,EAAE,QAAQ;IAAE,QAAQ,EAAE;EAAM,CAAC;EAC3C,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM;IAAE,QAAQ,EAAE;EAAM,CAAC;EACvC,QAAQ,EAAE;IAAE,IAAI,EAAE,WAAW;IAAE,QAAQ,EAAE;EAAK,CAAC;EAC/C,MAAM,EAAE;IAAE,IAAI,EAAE,SAAS;IAAE,QAAQ,EAAE;EAAK;AAC5C,CAAC;;AAED;AACA,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC;;AAEjD;AACO,SAAS,aAAa,CAAC,MAAM,GAAG,MAAM,EAAE;EAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CACrE,OAAO,CAAC,yBAAyB,EAAE,EAAE,CAAC,CACtC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAClB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;EACxB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;EAC7B,IAAI,CAAC,QAAQ,EACX,MAAM,IAAI,SAAS,CAAC,qCAAqC,MAAM,KAAK,GAChD,4DAA4D,CAAC;EACnF,OAAO,QAAQ;AACjB;;AAEA;AACA;AACO,SAAS,iBAAiB,CAAC,OAAO,EAAE;EACzC,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;AACrE;;AAEA;AACA;AACO,SAAS,WAAW,CAAC,OAAO,EAAE;EACnC,OAAO,iBAAiB,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO;AACrF;;AAEA;AACA;AACO,SAAS,kBAAkB,CAAC,OAAO,EAAE,SAAS,GAAG,aAAa,EAAE;EACrE,OAAO,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC;AACpC","ignoreList":[]}
|
package/lib/index.js
CHANGED
|
@@ -45,4 +45,5 @@ var _MessageWriter = _interopRequireWildcard(require("./MessageWriter.js"));
|
|
|
45
45
|
var _MessageStreamWriter = _interopRequireDefault(require("./MessageStreamWriter.js"));
|
|
46
46
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
47
47
|
var cache;
|
|
48
|
-
function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
|
|
48
|
+
function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.js"],"sourcesContent":["export { default as MessageParser, parseMessages } from './MessageParser.js';\nexport { default as MessageStreamParser } from './MessageStreamParser.js';\nexport { default as MessageWriter, writeMessages } from './MessageWriter.js';\nexport { default as MessageStreamWriter } from './MessageStreamWriter.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AAA0E;AAAA;AAAA","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n3.js-messages",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "RDF Messages (message-delimited Turtle, TriG, N-Triples and N-Quads) for N3.js: message-aware parser, streaming parser and writer.",
|
|
5
5
|
"author": "Pieter Colpaert",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,20 +21,35 @@
|
|
|
21
21
|
"types": "./index.d.ts",
|
|
22
22
|
"exports": {
|
|
23
23
|
".": {
|
|
24
|
+
"browser": {
|
|
25
|
+
"types": "./browser.d.ts",
|
|
26
|
+
"default": "./browser/index.js"
|
|
27
|
+
},
|
|
24
28
|
"types": "./index.d.ts",
|
|
25
29
|
"import": "./src/index.js",
|
|
26
30
|
"require": "./lib/index.js"
|
|
27
31
|
},
|
|
28
|
-
"./package.json": "./package.json"
|
|
32
|
+
"./package.json": "./package.json",
|
|
33
|
+
"./browser": {
|
|
34
|
+
"types": "./browser.d.ts",
|
|
35
|
+
"import": "./browser/index.js",
|
|
36
|
+
"default": "./browser/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./browser/global": "./browser/index.global.js"
|
|
29
39
|
},
|
|
30
|
-
"sideEffects":
|
|
40
|
+
"sideEffects": [
|
|
41
|
+
"./browser/index.global.js"
|
|
42
|
+
],
|
|
31
43
|
"engines": {
|
|
32
44
|
"node": ">=18"
|
|
33
45
|
},
|
|
34
46
|
"files": [
|
|
35
47
|
"src",
|
|
36
48
|
"lib",
|
|
37
|
-
"index.d.ts"
|
|
49
|
+
"index.d.ts",
|
|
50
|
+
"browser",
|
|
51
|
+
"browser.d.ts",
|
|
52
|
+
"common.d.ts"
|
|
38
53
|
],
|
|
39
54
|
"peerDependencies": {
|
|
40
55
|
"n3": ">=2.13.7 <3"
|
|
@@ -48,35 +63,47 @@
|
|
|
48
63
|
},
|
|
49
64
|
"homepage": "https://github.com/pietercolpaert/n3.js-messages#readme",
|
|
50
65
|
"scripts": {
|
|
51
|
-
"build": "
|
|
66
|
+
"build": "node scripts/build.js",
|
|
52
67
|
"prepack": "npm run build",
|
|
53
68
|
"test": "jest",
|
|
54
69
|
"coverage": "jest --coverage",
|
|
55
|
-
"lint": "eslint
|
|
70
|
+
"lint": "eslint . && knip",
|
|
56
71
|
"test:spec": "node spec/runner.js",
|
|
57
72
|
"test:spec:earl": "node spec/runner.js --earl > spec/earl-report.ttl",
|
|
58
73
|
"test:types": "tsc -p test/types/tsconfig.json",
|
|
59
74
|
"test:package": "node scripts/test-package.js",
|
|
60
75
|
"perf": "node perf/run.js",
|
|
61
76
|
"perf:compare": "node perf/compare.js",
|
|
62
|
-
"spec:update": "node scripts/update-spec.js"
|
|
77
|
+
"spec:update": "node scripts/update-spec.js",
|
|
78
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
79
|
+
"check": "npm run lint && npm run typecheck && npm run test:types && npm run build && npm test -- --runInBand && npm run test:spec",
|
|
80
|
+
"ci": "npm run check && npm run test:package && npm run test:browser && npm run perf:regression",
|
|
81
|
+
"test:browser": "node scripts/test-browser.js",
|
|
82
|
+
"hooks:install": "node scripts/install-hooks.js",
|
|
83
|
+
"perf:regression": "node perf/regression.js",
|
|
84
|
+
"test:n3-extract": "node scripts/extract-n3-parser-tests.cjs"
|
|
63
85
|
},
|
|
64
86
|
"devDependencies": {
|
|
65
87
|
"@babel/cli": "^8.0.6",
|
|
66
|
-
"@babel/core": "^8.0.
|
|
88
|
+
"@babel/core": "^8.0.9",
|
|
67
89
|
"@babel/preset-env": "^8.0.7",
|
|
68
|
-
"@types/n3": "^1.26.
|
|
69
|
-
"@types/node": "^26.6.
|
|
90
|
+
"@types/n3": "^1.26.5",
|
|
91
|
+
"@types/node": "^26.6.5",
|
|
70
92
|
"babel-jest": "^30.5.2",
|
|
71
|
-
"
|
|
93
|
+
"esbuild": "^0.28.2",
|
|
94
|
+
"eslint": "^10.13.0",
|
|
72
95
|
"eslint-plugin-import-x": "^4.17.1",
|
|
73
|
-
"eslint-plugin-jest": "^29.
|
|
96
|
+
"eslint-plugin-jest": "^29.17.0",
|
|
97
|
+
"events": "^3.3.0",
|
|
74
98
|
"globals": "^17.13.0",
|
|
75
99
|
"jest": "^30.5.2",
|
|
76
|
-
"
|
|
100
|
+
"knip": "^6.43.0",
|
|
101
|
+
"n3": "^2.13.12",
|
|
102
|
+
"playwright": "^1.64.1",
|
|
77
103
|
"rdf-isomorphic": "^2.0.1",
|
|
78
104
|
"rdf-parser-ts": "^0.4.0",
|
|
79
105
|
"rdf-writer-ts": "^0.2.1",
|
|
106
|
+
"string_decoder": "^1.3.0",
|
|
80
107
|
"typescript": "^7.0.2"
|
|
81
108
|
},
|
|
82
109
|
"jest": {
|
|
@@ -103,5 +130,6 @@
|
|
|
103
130
|
},
|
|
104
131
|
"dependencies": {
|
|
105
132
|
"@rdfjs/types": "^2.0.1"
|
|
106
|
-
}
|
|
133
|
+
},
|
|
134
|
+
"browser": "./browser/index.js"
|
|
107
135
|
}
|
package/src/MessageParser.js
CHANGED
|
@@ -2,13 +2,18 @@
|
|
|
2
2
|
import { StringDecoder } from 'string_decoder';
|
|
3
3
|
import MessageParserCore from './MessageParserCore.js';
|
|
4
4
|
|
|
5
|
+
/** @template {import('@rdfjs/types').BaseQuad} [Q=import('@rdfjs/types').Quad] */
|
|
5
6
|
export default class MessageParser {
|
|
7
|
+
/** @param {import('../common.js').MessageParserOptions<Q>} [options] */
|
|
6
8
|
constructor(options) {
|
|
9
|
+
/** @type {import('../common.js').MessageParserOptions<Q>} */
|
|
7
10
|
this._options = options || {};
|
|
8
11
|
// Fail early on unsupported options
|
|
9
|
-
this.
|
|
12
|
+
// Construction only validates options; this core never receives input.
|
|
13
|
+
this._createCore(/** @type {import('./internal.js').ParserSink<Q>} */ ({}));
|
|
10
14
|
}
|
|
11
15
|
|
|
16
|
+
/** @param {import('./internal.js').ParserSink<Q>} sink */
|
|
12
17
|
_createCore(sink) {
|
|
13
18
|
return new MessageParserCore(this._options, sink);
|
|
14
19
|
}
|
|
@@ -21,23 +26,45 @@ export default class MessageParser {
|
|
|
21
26
|
// callbacks `onMessage(error, message, prefixes)`, `onQuad(error, quad, messageIndex)`,
|
|
22
27
|
// `onPrefix(prefix, term)` and `onVersion(label)`, messages are reported as soon
|
|
23
28
|
// as they are complete. The final call has `null` as message.
|
|
29
|
+
/**
|
|
30
|
+
* @overload
|
|
31
|
+
* @param {string} input
|
|
32
|
+
* @returns {Q[][]}
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* @overload
|
|
36
|
+
* @param {string | NodeJS.ReadableStream} input
|
|
37
|
+
* @param {import('../common.js').MessageCallback<Q> | import('../common.js').MessageParseCallbacks<Q>} [callbacks]
|
|
38
|
+
* @returns {void}
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* @param {string | NodeJS.ReadableStream} input
|
|
42
|
+
* @param {import('../common.js').MessageCallback<Q> | import('../common.js').MessageParseCallbacks<Q>} [callbacks]
|
|
43
|
+
* @returns {Q[][] | undefined}
|
|
44
|
+
*/
|
|
24
45
|
parse(input, callbacks) {
|
|
25
46
|
if (typeof callbacks === 'function')
|
|
26
47
|
callbacks = { onMessage: callbacks };
|
|
48
|
+
|
|
49
|
+
/** @type {Q[][] | null} */
|
|
27
50
|
const messages = callbacks ? null : [];
|
|
51
|
+
|
|
52
|
+
/** @type {Error | null} */
|
|
28
53
|
let error = null;
|
|
29
54
|
callbacks = callbacks || {};
|
|
55
|
+
|
|
56
|
+
/** @type {import('./internal.js').ParserSink<Q>} */
|
|
30
57
|
const sink = {
|
|
31
58
|
message: (quads, index) => callbacks.onMessage ? callbacks.onMessage(null, quads, undefined, index) : messages && messages.push(quads),
|
|
32
59
|
end: prefixes => callbacks.onMessage && callbacks.onMessage(null, null, prefixes),
|
|
33
60
|
error: e => {
|
|
34
61
|
error = e;
|
|
35
|
-
callbacks.onMessage && callbacks.onMessage(e);
|
|
62
|
+
callbacks.onMessage && callbacks.onMessage(e, null);
|
|
36
63
|
callbacks.onQuad && callbacks.onQuad(e);
|
|
37
64
|
},
|
|
38
65
|
};
|
|
39
66
|
if (callbacks.onQuad)
|
|
40
|
-
sink.quad = (quad, index) => callbacks.onQuad(null, quad, index);
|
|
67
|
+
sink.quad = (quad, index) => callbacks.onQuad?.(null, quad, index);
|
|
41
68
|
if (callbacks.onPrefix)
|
|
42
69
|
sink.prefix = callbacks.onPrefix;
|
|
43
70
|
if (callbacks.onVersion)
|
|
@@ -65,6 +92,11 @@ export default class MessageParser {
|
|
|
65
92
|
}
|
|
66
93
|
}
|
|
67
94
|
|
|
95
|
+
/**
|
|
96
|
+
* @template {import('@rdfjs/types').BaseQuad} [Q=import('@rdfjs/types').Quad]
|
|
97
|
+
* @param {string} input
|
|
98
|
+
* @param {import('../common.js').MessageParserOptions<Q>} [options]
|
|
99
|
+
*/
|
|
68
100
|
// ### `parseMessages` synchronously parses a string into an array of messages
|
|
69
101
|
export function parseMessages(input, options) {
|
|
70
102
|
return new MessageParser(options).parse(input);
|