diff --git a/plugins/payload/src/plugin.js b/plugins/payload/src/plugin.js new file mode 100644 index 0000000..072c728 --- /dev/null +++ b/plugins/payload/src/plugin.js @@ -0,0 +1,79 @@ +import debug from './debug.js' + +export default { + //establish payload db + mutate: function (world) { + world.model.one.db = {} + world.methods.one.debug ||= {} + world.methods.one.debug.payload = debug + }, + + api: function (View) { + /** return any data on our given matches */ + View.prototype.getPayloads = function () { + let res = [] + const db = this.world.model.one.db || {} + this.fullPointer.forEach(ptr => { + const n = ptr[0] + if (Object.hasOwn(db, n)) { + // look at all vals for this sentence + const seeking = this.update([ptr]) + db[n].forEach(obj => { + const m = this.update([obj.ptr]) + if (seeking.has(m)) { + res = res.concat({ + match: m, + val: obj.val, + }) + } + }) + } + }) + return res + } + + /** add data about our current matches */ + View.prototype.addPayload = function (val) { + const db = this.world.model.one.db || {} + this.fullPointer.forEach(ptr => { + const n = ptr[0] + db[n] ||= [] + if (typeof val === 'function') { + //push in whatever the callback wants + const m = this.update([ptr]) + const res = val(m) + if (res !== null && res !== undefined) { + db[n].push({ ptr, val: res }) + } + } else { + db[n].push({ ptr, val }) //push some static data + } + }) + return this + } + + /** remove all payloads in selection */ + View.prototype.clearPayloads = function () { + const db = this.world.model.one.db || {} + // get each payload + const res = this.getPayloads() + res.forEach(obj => { + const ptr = obj.match.fullPointer[0] || [] + const [n, start, end] = ptr + db[n] ||= [] + // remove it from our list of payloads + db[n] = db[n].filter(r => { + if (r.ptr[1] === start && r.ptr[2] === end) { + return false + } + return true + }) + // clean-up any empty arrays + if (db[n].length === 0) { + delete db[n] + } + }) + return this + } + }, +} diff --git a/plugins/payload/tests/payload.test.js b/plugins/payload/tests/payload.test.js new file mode 100644 index 0000000..341644b --- /dev/null +++ b/plugins/payload/tests/payload.test.js @@ -0,0 +1,59 @@ +import test from 'tape' +import nlp from './_lib.js' + +test('payload-misc', function (t) { + const doc = nlp('i saw John Lennon, and tom cruise.') + + doc.match('(john lennon|tom cruise|johnny carson)').forEach(m => { + if (m.has('john lennon')) { + m.addPayload({ height: `5'11` }) + } + if (m.has('tom cruise')) { + m.addPayload({ height: `5'8` }) + } + }) + + t.equal(doc.getPayloads().length, 2, 'full-doc-2') + + const end = doc.match('and tom .') + t.equal(end.getPayloads().length, 1, 'end-1') + + const tom = doc.match('tom') + t.equal(tom.getPayloads().length, 1, 'tom-0') + + tom.clearPayloads() + t.equal(doc.getPayloads().length, 1, 'now-1') + doc.clearPayloads() + t.equal(doc.getPayloads().length, 0, 'now-0') + + t.end() +}) + +test('payload-fn', function (t) { + const doc = nlp('i saw John Lennon, and john smith and bob dylan') + doc.match('(john|bob|dave) .').addPayload(m => { + return /john/i.test(m.text()) ? { isjohn: true } : null + }) + t.equal(doc.getPayloads().length, 2, 'now-2') + t.equal(doc.match('john .').getPayloads().length, 2, 'double-match-still-2') + + doc.match('bob .').clearPayloads() + t.equal(doc.getPayloads().length, 2, 'still-2') + + doc.match('john .').eq(1).clearPayloads() + t.equal(doc.getPayloads().length, 1, 'now-1') + doc.match('john .').clearPayloads() + t.equal(doc.getPayloads().length, 0, 'now-0') + + // add two-payloads per match + doc.match('(john|bob|dave) .').addPayload(m => { + return { lastName: m.terms().last().text() } + }) + t.equal(doc.getPayloads().length, 3, '3-now') + + doc.match('(john lennon|bob dylan)').addPayload(() => { + return { instrument: 'guitar' } + }) + t.equal(doc.getPayloads().length, 5, '5-now') + t.end() +})