@iebh/reflib 2.5.6 → 2.5.8

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.
@@ -1,44 +1,44 @@
1
- import Emitter from '../../shared/emitter.js';
2
-
3
- export default class BrowserJSONStream {
4
- constructor() {
5
- this.text = '';
6
- this.emitter = Emitter();
7
- this.recNumber = 1;
8
- }
9
-
10
- write(data) {
11
- // CF: TODO: Parse data as it comes in chunks for better memory efficiency
12
- this.text += data;
13
- }
14
-
15
- end() {
16
- try {
17
- // Parse this.text as JSON
18
- const jsonArray = JSON.parse(this.text);
19
-
20
- // Free memory
21
- this.text = '';
22
-
23
- // For each entry in the json array (as ref):
24
- if (Array.isArray(jsonArray))
25
- jsonArray.forEach(ref => {
26
- this.emitter.emit('data', ref);
27
- });
28
-
29
- // Finished
30
- this.emitter.emit('end');
31
- } catch (e) {
32
- console.error('Error parsing final JSON:', e);
33
- this.emitter.emit('error', e);
34
- }
35
- }
36
-
37
- on(event, listener) {
38
- this.emitter.on(event, listener);
39
- }
40
-
41
- static parse() {
42
- return new BrowserJSONStream();
43
- }
1
+ import Emitter from '../../shared/emitter.js';
2
+
3
+ export default class BrowserJSONStream {
4
+ constructor() {
5
+ this.text = '';
6
+ this.emitter = Emitter();
7
+ this.recNumber = 1;
8
+ }
9
+
10
+ write(data) {
11
+ // CF: TODO: Parse data as it comes in chunks for better memory efficiency
12
+ this.text += data;
13
+ }
14
+
15
+ end() {
16
+ try {
17
+ // Parse this.text as JSON
18
+ const jsonArray = JSON.parse(this.text);
19
+
20
+ // Free memory
21
+ this.text = '';
22
+
23
+ // For each entry in the json array (as ref):
24
+ if (Array.isArray(jsonArray))
25
+ jsonArray.forEach(ref => {
26
+ this.emitter.emit('data', ref);
27
+ });
28
+
29
+ // Finished
30
+ this.emitter.emit('end');
31
+ } catch (e) {
32
+ console.error('Error parsing final JSON:', e);
33
+ this.emitter.emit('error', e);
34
+ }
35
+ }
36
+
37
+ on(event, listener) {
38
+ this.emitter.on(event, listener);
39
+ }
40
+
41
+ static parse() {
42
+ return new BrowserJSONStream();
43
+ }
44
44
  }
@@ -1,52 +1,52 @@
1
- import Emitter from '../../shared/emitter.js';
2
- import CacxParser from '@iebh/cacx';
3
-
4
- export class WritableStream {
5
- constructor(passedParserOptions) {
6
- this.emitter = Emitter();
7
- this.parser = new CacxParser({
8
- collect: false,
9
- reAttrSegment: /(?<key>[a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?<escape>["'])(?<val>.*?)\k<escape>)?/ig,
10
- onTagOpen: (node) => {
11
- const name = node.tag;
12
- const attrs = node.attrs || {};
13
- this.emitter.emit('opentag', name, attrs);
14
- },
15
- onTagClose: (node) => {
16
- const name = node.tag;
17
- // Emit text event before closing the tag
18
- if (node.text && node.text.trim()) {
19
- this.emitter.emit('text', node.text.trim());
20
- }
21
- this.emitter.emit('closetag', name);
22
- },
23
- flattenText: false,
24
- keyText: 'text',
25
- keyAttrs: 'attrs',
26
- });
27
-
28
- // Add event listeners to mimic htmlparser2 behavior
29
- this.emitter.on('opentag', passedParserOptions.onopentag);
30
- this.emitter.on('closetag', passedParserOptions.onclosetag);
31
- this.emitter.on('text', passedParserOptions.ontext);
32
- this.emitter.on('end', passedParserOptions.onend);
33
- }
34
-
35
- write(data) {
36
- this.parser.append(data).exec();
37
- }
38
-
39
- end() {
40
- // Process any remaining data
41
- this.parser.exec();
42
-
43
- // Emit text event for the last node if it has text
44
- const lastNode = this.parser.stack.at(-1);
45
- if (lastNode && lastNode.text && lastNode.text.trim()) {
46
- this.emitter.emit('text', lastNode.text.trim());
47
- }
48
-
49
- // Emit end event
50
- this.emitter.emit('end');
51
- }
1
+ import Emitter from '../../shared/emitter.js';
2
+ import CacxParser from '@iebh/cacx';
3
+
4
+ export class WritableStream {
5
+ constructor(passedParserOptions) {
6
+ this.emitter = Emitter();
7
+ this.parser = new CacxParser({
8
+ collect: false,
9
+ reAttrSegment: /(?<key>[a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?<escape>["'])(?<val>.*?)\k<escape>)?/ig,
10
+ onTagOpen: (node) => {
11
+ const name = node.tag;
12
+ const attrs = node.attrs || {};
13
+ this.emitter.emit('opentag', name, attrs);
14
+ },
15
+ onTagClose: (node) => {
16
+ const name = node.tag;
17
+ // Emit text event before closing the tag
18
+ if (node.text && node.text.trim()) {
19
+ this.emitter.emit('text', node.text.trim());
20
+ }
21
+ this.emitter.emit('closetag', name);
22
+ },
23
+ flattenText: false,
24
+ keyText: 'text',
25
+ keyAttrs: 'attrs',
26
+ });
27
+
28
+ // Add event listeners to mimic htmlparser2 behavior
29
+ this.emitter.on('opentag', passedParserOptions.onopentag);
30
+ this.emitter.on('closetag', passedParserOptions.onclosetag);
31
+ this.emitter.on('text', passedParserOptions.ontext);
32
+ this.emitter.on('end', passedParserOptions.onend);
33
+ }
34
+
35
+ write(data) {
36
+ this.parser.append(data).exec();
37
+ }
38
+
39
+ end() {
40
+ // Process any remaining data
41
+ this.parser.exec();
42
+
43
+ // Emit text event for the last node if it has text
44
+ const lastNode = this.parser.stack.at(-1);
45
+ if (lastNode && lastNode.text && lastNode.text.trim()) {
46
+ this.emitter.emit('text', lastNode.text.trim());
47
+ }
48
+
49
+ // Emit end event
50
+ this.emitter.emit('end');
51
+ }
52
52
  }
package/package.json CHANGED
@@ -1,65 +1,65 @@
1
- {
2
- "name": "@iebh/reflib",
3
- "version": "2.5.6",
4
- "description": "Reference / Citation reference library utilities",
5
- "scripts": {
6
- "lint": "eslint .",
7
- "test": "mocha",
8
- "test:browser": "cd test/browser && npm run dev",
9
- "test:watch": "nodemon --exec npm run test"
10
- },
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/IEBH/Reflib.git"
14
- },
15
- "keywords": [
16
- "reflib",
17
- "references",
18
- "citations",
19
- "library"
20
- ],
21
- "author": "Matt Carter <m@ttcarter.com> (https://github.com/hash-bang)",
22
- "contributors": [
23
- "Connor Forbes <cforbes.software@gmail.com> (https://github.com/connorf25)"
24
- ],
25
- "license": "MIT",
26
- "bugs": {
27
- "url": "https://github.com/IEBH/Reflib/issues"
28
- },
29
- "homepage": "https://github.com/IEBH/Reflib",
30
- "enginesStrict": true,
31
- "engines": {
32
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
33
- },
34
- "type": "module",
35
- "exports": {
36
- ".": {
37
- "browser": "./lib/browser.js",
38
- "default": "./lib/default.js"
39
- },
40
- "./*": "./lib/*.js"
41
- },
42
- "browser": {
43
- "htmlparser2/lib/WritableStream": "./modules/shims/WritableStream-browser.js",
44
- "htmlparser2/lib/esm/WritableStream": "./modules/shims/WritableStream-browser.js",
45
- "JSONStream": "./modules/shims/JSONStream-browser.js"
46
- },
47
- "devDependencies": {
48
- "@momsfriendlydevco/eslint-config": "^2.3.1",
49
- "chai": "^5.2.0",
50
- "eslint": "^9.31.0",
51
- "mocha": "^11.1.0",
52
- "mocha-logger": "^1.0.8",
53
- "nodemon": "^3.1.9",
54
- "temp": "^0.9.4",
55
- "vite-plugin-replace": "^0.1.1"
56
- },
57
- "dependencies": {
58
- "@iebh/cacx": "^1.0.3",
59
- "@zip.js/zip.js": "^2.7.57",
60
- "htmlparser2": "^9.1.0",
61
- "JSONStream": "^1.3.5",
62
- "mitt": "^3.0.1",
63
- "sql.js": "^1.12.0"
64
- }
65
- }
1
+ {
2
+ "name": "@iebh/reflib",
3
+ "version": "2.5.8",
4
+ "description": "Reference / Citation reference library utilities",
5
+ "scripts": {
6
+ "lint": "eslint .",
7
+ "test": "mocha",
8
+ "test:browser": "cd test/browser && npm run dev",
9
+ "test:watch": "nodemon --exec npm run test"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/IEBH/Reflib.git"
14
+ },
15
+ "keywords": [
16
+ "reflib",
17
+ "references",
18
+ "citations",
19
+ "library"
20
+ ],
21
+ "author": "Matt Carter <m@ttcarter.com> (https://github.com/hash-bang)",
22
+ "contributors": [
23
+ "Connor Forbes <cforbes.software@gmail.com> (https://github.com/connorf25)"
24
+ ],
25
+ "license": "MIT",
26
+ "bugs": {
27
+ "url": "https://github.com/IEBH/Reflib/issues"
28
+ },
29
+ "homepage": "https://github.com/IEBH/Reflib",
30
+ "enginesStrict": true,
31
+ "engines": {
32
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
33
+ },
34
+ "type": "module",
35
+ "exports": {
36
+ ".": {
37
+ "browser": "./lib/browser.js",
38
+ "default": "./lib/default.js"
39
+ },
40
+ "./*": "./lib/*.js"
41
+ },
42
+ "browser": {
43
+ "htmlparser2/lib/WritableStream": "./modules/shims/WritableStream-browser.js",
44
+ "htmlparser2/lib/esm/WritableStream": "./modules/shims/WritableStream-browser.js",
45
+ "JSONStream": "./modules/shims/JSONStream-browser.js"
46
+ },
47
+ "devDependencies": {
48
+ "@momsfriendlydevco/eslint-config": "^2.3.1",
49
+ "chai": "^5.2.0",
50
+ "eslint": "^9.31.0",
51
+ "mocha": "^11.1.0",
52
+ "mocha-logger": "^1.0.8",
53
+ "nodemon": "^3.1.9",
54
+ "temp": "^0.9.4",
55
+ "vite-plugin-replace": "^0.1.1"
56
+ },
57
+ "dependencies": {
58
+ "@iebh/cacx": "^1.0.3",
59
+ "@zip.js/zip.js": "^2.7.57",
60
+ "htmlparser2": "^9.1.0",
61
+ "JSONStream": "^1.3.5",
62
+ "mitt": "^3.0.1",
63
+ "sql.js": "^1.12.0"
64
+ }
65
+ }
@@ -1,17 +1,17 @@
1
- /**
2
- * Camel case any input string
3
- * This is functionally the same as Lodash's camelCase() function
4
- *
5
- * @param {string} input The input string to camelize
6
- * @returns {string} The input string in camelCase format
7
- * @url https://github.com/MomsFriendlyDevCo/Nodash
8
- */
9
- export default function(input) {
10
- return input
11
- .split(/[\s-]/)
12
- .map((word, offset) => offset == 0
13
- ? word.toLowerCase()
14
- : word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase()
15
- )
16
- .join('')
17
- }
1
+ /**
2
+ * Camel case any input string
3
+ * This is functionally the same as Lodash's camelCase() function
4
+ *
5
+ * @param {string} input The input string to camelize
6
+ * @returns {string} The input string in camelCase format
7
+ * @url https://github.com/MomsFriendlyDevCo/Nodash
8
+ */
9
+ export default function(input) {
10
+ return input
11
+ .split(/[\s-]/)
12
+ .map((word, offset) => offset == 0
13
+ ? word.toLowerCase()
14
+ : word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase()
15
+ )
16
+ .join('')
17
+ }
package/shared/emitter.js CHANGED
@@ -1,23 +1,23 @@
1
- import Mitt from 'mitt';
2
-
3
- /**
4
- * Generic wrapper for an event emitter
5
- * This module returns a wrapped version of `mitt` stand-alone event emitter (+ support for method chaining)
6
- *
7
- * @returns {Object} A wrapped version of the NPM Mitt event emitter with chainable functionality
8
- */
9
- export default function emitter() {
10
- let emitter = Mitt();
11
-
12
- // Add method chaining
13
- emitter.mitt = {};
14
- ['on', 'off', 'emit'].forEach(f => {
15
- emitter.mitt[f] = emitter[f]; // Backup old function into `.mitt.${F}`
16
- emitter[f] = (...args) => {
17
- emitter.mitt[f](...args);
18
- return emitter;
19
- };
20
- });
21
-
22
- return emitter;
23
- }
1
+ import Mitt from 'mitt';
2
+
3
+ /**
4
+ * Generic wrapper for an event emitter
5
+ * This module returns a wrapped version of `mitt` stand-alone event emitter (+ support for method chaining)
6
+ *
7
+ * @returns {Object} A wrapped version of the NPM Mitt event emitter with chainable functionality
8
+ */
9
+ export default function emitter() {
10
+ let emitter = Mitt();
11
+
12
+ // Add method chaining
13
+ emitter.mitt = {};
14
+ ['on', 'off', 'emit'].forEach(f => {
15
+ emitter.mitt[f] = emitter[f]; // Backup old function into `.mitt.${F}`
16
+ emitter[f] = (...args) => {
17
+ emitter.mitt[f](...args);
18
+ return emitter;
19
+ };
20
+ });
21
+
22
+ return emitter;
23
+ }
@@ -1,61 +1,61 @@
1
- import Emitter from '../shared/emitter.js';
2
-
3
- /**
4
- * Wrapper for streams which transforms a given input into an emitter pattern
5
- * This is designed to let regular `node:stream.Readable` objects pass through without alteration but browser based stream objects get wrapped
6
- * @param {stream.Readable|ReadableStream} inStream The input stream to wrap
7
- * @returns {stream.Readable|Emitter} Either the unedited node compatible stream or an event emitter with the same behaviour
8
- *
9
- * @emits data Emitted as `(chunk)` on each data chunk
10
- * @emits end Emitted as `()` when the input stream has closed
11
- * @emits error Emitted as `(Error)` on any read error
12
- */
13
- export default function streamEmitter (inStream) {
14
- if (inStream.getReader) { // Assume browser compatible ReadableStream
15
- /**
16
- * MC's tiny ReadableStream -> stream.Readable / Emitter pattern
17
- * There is a non-zero chance that this is going to break at some future point
18
- * This is really just a shiv for browser functionality to replicate Stream-a-like emitter pattern
19
- * @date 2023-10-19
20
- * @author Matt Carter <m@ttcarter.com>
21
- */
22
- let reader = new Emitter();
23
- Object.assign(reader, {
24
- isBrowser: true, // Tells us we are in browser env
25
- bytesRead: 0,
26
- reader: inStream.getReader(),
27
- textDecoder: new TextDecoder('utf-8'),
28
- read() { // Read one chunk + trigger emitters
29
- this.reader.read()
30
- .then(({done, value}) => {
31
- if (done) {
32
- reader.emit('end');
33
-
34
- if (this.pipeTarget)
35
- this.pipeTarget.end();
36
- } else if (value) {
37
- let data = this.textDecoder.decode(value);
38
- this.bytesRead += data.length;
39
- reader.emit('data', data);
40
-
41
- if (this.pipeTarget)
42
- this.pipeTarget.write(data);
43
-
44
- setTimeout(this.read.bind(this));
45
- }
46
- })
47
- .catch(e => this.emit('error', e))
48
- },
49
- pipeTarget: null,
50
- pipe(target) {
51
- this.pipeTarget = target;
52
- return this;
53
- },
54
- });
55
-
56
- setTimeout(()=> reader.read());
57
- return reader;
58
- } else { // Assume Node native stream.Readable
59
- return inStream;
60
- }
61
- }
1
+ import Emitter from '../shared/emitter.js';
2
+
3
+ /**
4
+ * Wrapper for streams which transforms a given input into an emitter pattern
5
+ * This is designed to let regular `node:stream.Readable` objects pass through without alteration but browser based stream objects get wrapped
6
+ * @param {stream.Readable|ReadableStream} inStream The input stream to wrap
7
+ * @returns {stream.Readable|Emitter} Either the unedited node compatible stream or an event emitter with the same behaviour
8
+ *
9
+ * @emits data Emitted as `(chunk)` on each data chunk
10
+ * @emits end Emitted as `()` when the input stream has closed
11
+ * @emits error Emitted as `(Error)` on any read error
12
+ */
13
+ export default function streamEmitter (inStream) {
14
+ if (inStream.getReader) { // Assume browser compatible ReadableStream
15
+ /**
16
+ * MC's tiny ReadableStream -> stream.Readable / Emitter pattern
17
+ * There is a non-zero chance that this is going to break at some future point
18
+ * This is really just a shiv for browser functionality to replicate Stream-a-like emitter pattern
19
+ * @date 2023-10-19
20
+ * @author Matt Carter <m@ttcarter.com>
21
+ */
22
+ let reader = new Emitter();
23
+ Object.assign(reader, {
24
+ isBrowser: true, // Tells us we are in browser env
25
+ bytesRead: 0,
26
+ reader: inStream.getReader(),
27
+ textDecoder: new TextDecoder('utf-8'),
28
+ read() { // Read one chunk + trigger emitters
29
+ this.reader.read()
30
+ .then(({done, value}) => {
31
+ if (done) {
32
+ reader.emit('end');
33
+
34
+ if (this.pipeTarget)
35
+ this.pipeTarget.end();
36
+ } else if (value) {
37
+ let data = this.textDecoder.decode(value);
38
+ this.bytesRead += data.length;
39
+ reader.emit('data', data);
40
+
41
+ if (this.pipeTarget)
42
+ this.pipeTarget.write(data);
43
+
44
+ setTimeout(this.read.bind(this));
45
+ }
46
+ })
47
+ .catch(e => this.emit('error', e))
48
+ },
49
+ pipeTarget: null,
50
+ pipe(target) {
51
+ this.pipeTarget = target;
52
+ return this;
53
+ },
54
+ });
55
+
56
+ setTimeout(()=> reader.read());
57
+ return reader;
58
+ } else { // Assume Node native stream.Readable
59
+ return inStream;
60
+ }
61
+ }