diff --git a/docs/plugin-basics.md b/docs/plugin-basics.md index 11d366cd..bcebd642 100644 --- a/docs/plugin-basics.md +++ b/docs/plugin-basics.md @@ -14,6 +14,7 @@ npm install @ezs/basics #### Table of Contents +- [BIBParse](#bibparse) - [BUFObject](#bufobject) - [CSVObject](#csvobject) - [CSVParse](#csvparse) @@ -47,6 +48,24 @@ npm install @ezs/basics - [XMLString](#xmlstring) - [ZIPExtract](#zipextract) +### BIBParse + +Take a `String` and split it at bibtext entry. + +Input: + +```json +["@article{my_article,\ntitle = {Hello world},\n", "journal = \"Some Journal\"\n"] +``` + +Output: + +```json +["a", "b", "c", "d"] +``` + +Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** + ### BUFObject Take `Mixed` and produce Buffer. diff --git a/docs/plugin-core.md b/docs/plugin-core.md index aaf006ab..5ef07845 100644 --- a/docs/plugin-core.md +++ b/docs/plugin-core.md @@ -12,13 +12,13 @@ npm install @ezs/core Plusieurs instructions permettent de créer des sous flux (sub pipeline), à partir d'un fichier d’instructions ou d'instructions imbriquées. Si elles s'utilisent toutes de la même manière (avec les mêmes paramètres) centaines peuvent apparaître comme similaires mais leur fonctionnement est différent : -- [delegate] : 1 sous flux pour tous les éléments -- [swing] : 1 sous flux pour tous les éléments filtrés selon une condition -- [spaw] : 1 sous flux par élément -- [loop] : 1 sous flux par élément -- [expand] : 1 sous flux pour N éléments (N = size), seul le champ sélectionné est envoyé dans le pipeline -- [combine] : 1 sous flux pour tous les éléments, seul le champ sélectionné est comparé avec le résultat du sous flux -- [singleton] : 1 sous flux pour le premier élément +- [delegate] : 1 sous flux pour tous les éléments +- [swing] : 1 sous flux pour tous les éléments filtrés selon une condition +- [spaw] : 1 sous flux par élément +- [loop] : 1 sous flux par élément +- [expand] : 1 sous flux pour N éléments (N = size), seul le champ sélectionné est envoyé dans le pipeline +- [combine] : 1 sous flux pour tous les éléments, seul le champ sélectionné est comparé avec le résultat du sous flux +- [singleton] : 1 sous flux pour le premier élément ## usage diff --git a/packages/basics/README.md b/packages/basics/README.md index 11d366cd..bcebd642 100644 --- a/packages/basics/README.md +++ b/packages/basics/README.md @@ -14,6 +14,7 @@ npm install @ezs/basics #### Table of Contents +- [BIBParse](#bibparse) - [BUFObject](#bufobject) - [CSVObject](#csvobject) - [CSVParse](#csvparse) @@ -47,6 +48,24 @@ npm install @ezs/basics - [XMLString](#xmlstring) - [ZIPExtract](#zipextract) +### BIBParse + +Take a `String` and split it at bibtext entry. + +Input: + +```json +["@article{my_article,\ntitle = {Hello world},\n", "journal = \"Some Journal\"\n"] +``` + +Output: + +```json +["a", "b", "c", "d"] +``` + +Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** + ### BUFObject Take `Mixed` and produce Buffer. diff --git a/packages/basics/package.json b/packages/basics/package.json index d4a9a85c..1ba70bd8 100644 --- a/packages/basics/package.json +++ b/packages/basics/package.json @@ -8,6 +8,7 @@ "JSONStream": "1.3.5", "async-retry": "1.3.3", "better-https-proxy-agent": "1.0.9", + "bib2json": "0.0.1", "csv-string": "3.2.0", "debug": "4.3.3", "fetch-with-proxy": "3.0.1", diff --git a/packages/basics/src/bib-parse.js b/packages/basics/src/bib-parse.js new file mode 100644 index 00000000..8f539749 --- /dev/null +++ b/packages/basics/src/bib-parse.js @@ -0,0 +1,53 @@ +import { StringDecoder } from 'string_decoder'; +import BibtexParser from 'bib2json'; + +function BIBParse(data, feed) { + if (!this.decoder) { + this.decoder = new StringDecoder('utf8'); + this.remainder = ''; + this.counter = 0; + this.parser = new BibtexParser((entry) => { + feed.write(entry); + }); + } + if (this.isLast()) { + this.remainder += this.decoder.end(); + if (this.remainder && this.counter > 1) { + this.parser.parse(this.remainder); + } + return feed.close(); + } + let chunk; + if (Buffer.isBuffer(data)) { + chunk = this.decoder.write(data); + } else if (typeof data === 'string') { + chunk = data; + } else { + chunk = ''; + } + this.parser.parse(chunk); + this.counter += 1; + feed.end(); +} + +/** + * Take a `String` and split it at bibtext entry. + * + * Input: + * + * ```json + * ["@article{my_article,\ntitle = {Hello world},\n", "journal = \"Some Journal\"\n"] + * ``` + * + * Output: + * + * ```json + * ["a", "b", "c", "d"] + * ``` + * + * @name BIBParse + * @returns {Object} + */ +export default { + BIBParse, +}; diff --git a/packages/basics/src/index.js b/packages/basics/src/index.js index 1e091042..7e603df7 100644 --- a/packages/basics/src/index.js +++ b/packages/basics/src/index.js @@ -3,6 +3,7 @@ import OBJCount from './obj-count'; import OBJNamespaces from './obj-namespaces'; import OBJStandardize from './obj-standardize'; import OBJFlatten from './obj-flatten'; +import BIBParse from './bib-parse'; import TXTConcat from './txt-concat'; import TXTObject from './txt-object'; import TXTParse from './txt-parse'; @@ -37,6 +38,7 @@ const funcs = { OBJNamespaces, OBJStandardize, OBJFlatten, + BIBParse, TXTParse, TXTObject, TXTConcat, diff --git a/packages/basics/test/bib-parse.js b/packages/basics/test/bib-parse.js new file mode 100644 index 00000000..dc418054 --- /dev/null +++ b/packages/basics/test/bib-parse.js @@ -0,0 +1,75 @@ +import from from 'from'; +import ezs from '../../core/src'; +import ezsBasics from '../src'; + +ezs.use(ezsBasics); + +describe('BIBParse', () => { + it('should return a entry #1', (done) => { + from(['@article{my_article,\ntitle = {Hello world},\n', 'journal = "Some Journal"\n}']) + .pipe(ezs('BIBParse')) + .on('error', (err) => done(err)) + .on('data', (data) => { + expect(typeof data).toBe('object'); + expect(data.ObjectType).toBe('entry'); + }) + .on('end', () => { + done(); + }); + }); + it('should return a entry #2', (done) => { + from(['@article{my_article,\ntitle = {Hello world},\njournal = "Some Journal"\n}']) + .pipe(ezs('BIBParse')) + .on('error', (err) => done(err)) + .on('data', (data) => { + expect(typeof data).toBe('object'); + expect(data.ObjectType).toBe('entry'); + }) + .on('end', () => { + done(); + }); + }); + it('should return a entry #3', (done) => { + from(['@article{my_article,\ntitle = {Hello world},\n', 1, 'journal = "Some Journal"\n}']) + .pipe(ezs('BIBParse')) + .on('error', (err) => done(err)) + .on('data', (data) => { + expect(typeof data).toBe('object'); + expect(data.ObjectType).toBe('entry'); + }) + .on('end', () => { + done(); + }); + }); + it('should return a entry #3', (done) => { + from([ + Buffer.from('@article{my_article,\ntitle = {Hello world},\n'), + Buffer.from('journal = "Some'), + Buffer.from([0xE2]), + Buffer.from([0x82]), + Buffer.from([0xAC]), + Buffer.from('Journal"\n}'), + Buffer.from([0xC2]), + ]) + .pipe(ezs('BIBParse')) + .on('error', (err) => done(err)) + .on('data', (data) => { + expect(typeof data).toBe('object'); + expect(data.ObjectType).toBe('entry'); + }) + .on('end', () => { + done(); + }); + }); + + it('should return no entry', (done) => { + from(['@my_article,\ntitle = {Hello world},\n', 'journal = ']) + .pipe(ezs('BIBParse')) + .on('error', (err) => done(err)) + .on('data', () => done(new Error('no way'))) + .on('end', () => { + done(); + }); + }); + +}); diff --git a/packages/core/README.md b/packages/core/README.md index aaf006ab..5ef07845 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -12,13 +12,13 @@ npm install @ezs/core Plusieurs instructions permettent de créer des sous flux (sub pipeline), à partir d'un fichier d’instructions ou d'instructions imbriquées. Si elles s'utilisent toutes de la même manière (avec les mêmes paramètres) centaines peuvent apparaître comme similaires mais leur fonctionnement est différent : -- [delegate] : 1 sous flux pour tous les éléments -- [swing] : 1 sous flux pour tous les éléments filtrés selon une condition -- [spaw] : 1 sous flux par élément -- [loop] : 1 sous flux par élément -- [expand] : 1 sous flux pour N éléments (N = size), seul le champ sélectionné est envoyé dans le pipeline -- [combine] : 1 sous flux pour tous les éléments, seul le champ sélectionné est comparé avec le résultat du sous flux -- [singleton] : 1 sous flux pour le premier élément +- [delegate] : 1 sous flux pour tous les éléments +- [swing] : 1 sous flux pour tous les éléments filtrés selon une condition +- [spaw] : 1 sous flux par élément +- [loop] : 1 sous flux par élément +- [expand] : 1 sous flux pour N éléments (N = size), seul le champ sélectionné est envoyé dans le pipeline +- [combine] : 1 sous flux pour tous les éléments, seul le champ sélectionné est comparé avec le résultat du sous flux +- [singleton] : 1 sous flux pour le premier élément ## usage diff --git a/yarn.lock b/yarn.lock index e344c66d..852ded58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3671,6 +3671,11 @@ better-https-proxy-agent@1.0.9: dependencies: duplexify "4.0.0" +bib2json@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/bib2json/-/bib2json-0.0.1.tgz#c33bcf6f35edb4647fd75ff76f25bd7999fc3f31" + integrity sha512-6R9dpnE5FpUSH61Wq00XDcivsPAeH1+u+SeXevDh1eUHTfEiORRve5XpHTbCzwh1XytHotllY+ErUErbdxkFHg== + big-integer@^1.6.17: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"