Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #1101

Merged
merged 7 commits into from Apr 1, 2024
Merged

Dev #1101

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion builds/compromise.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion builds/one/compromise-one.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion builds/one/compromise-one.mjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion builds/three/compromise-three.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion builds/three/compromise-three.mjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion builds/two/compromise-two.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion builds/two/compromise-two.mjs

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions changelog.md
Expand Up @@ -20,6 +20,12 @@ While all _Major_ releases should be reviewed, our only _large_ releases are **v
- **[fix]** - .before() .after()
-->

#### 14.13.0 [Apr 2024]

- **[new]** - .compute('freeze')
- **[new]** - .debug('freeze')
- **[change]** - allow 3-slashes in a word

#### 14.12.0 [Feb 2024]

- **[new]** - .payload() plugin
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -2,7 +2,7 @@
"author": "Spencer Kelly <spencermountain@gmail.com> (http://spencermounta.in)",
"name": "compromise",
"description": "modest natural language processing",
"version": "14.12.0",
"version": "14.13.0",
"module": "./src/three.js",
"main": "./src/three.js",
"unpkg": "./builds/compromise.js",
Expand Down
19 changes: 15 additions & 4 deletions scratch.js
Expand Up @@ -4,10 +4,21 @@ import nlp from './src/three.js'
// nlp.plugin(plg)
// nlp.verbose('tagger')

let doc = nlp(`john jacob and john. foobar`)
let m = doc.split('.')
let res = m.joinIf('john', '.')
res.debug()
var doc = nlp('Poincare\u0301')
console.log(doc.docs[0])
// console.log(nlp(`IEEE/WIC`).debug().docs[0][0])

// const prependingText = 'the patient will need an '
// let doc = nlp('ECG')
// doc.prepend(prependingText)
// doc.debug('freeze')

// nlp('i play dr who').debug()

// let doc = nlp(`john jacob and john. foobar`)
// let m = doc.split('.')
// let res = m.joinIf('john', '.')
// res.debug()
// let doc = nlp('one foo two foo')
// let m = doc.terms()
// m = m.join()
Expand Down
11 changes: 6 additions & 5 deletions src/1-one/change/api/insert.js
Expand Up @@ -3,17 +3,18 @@ import uuid from '../compute/uuid.js'
// are we inserting inside a contraction?
// expand it first
const expand = function (m) {
if (m.has('@hasContraction') && typeof m.contractions === 'function') {//&& m.after('^.').has('@hasContraction')
if (m.has('@hasContraction') && typeof m.contractions === 'function') {
//&& m.after('^.').has('@hasContraction')
let more = m.grow('@hasContraction')
more.contractions().expand()
}
}

const isArray = (arr) => Object.prototype.toString.call(arr) === '[object Array]'
const isArray = arr => Object.prototype.toString.call(arr) === '[object Array]'

// set new ids for each terms
const addIds = function (terms) {
terms = terms.map((term) => {
terms = terms.map(term => {
term.id = uuid(term)
return term
})
Expand Down Expand Up @@ -75,10 +76,11 @@ const insert = function (input, view, prepend) {
// shift our self pointer, if necessary
view.ptrs = selfPtrs
// try to tag them, too
doc.compute(['id', 'index', 'lexicon'])
doc.compute(['id', 'index', 'freeze', 'lexicon'])
if (doc.world.compute.preTagger) {
doc.compute('preTagger')
}
doc.compute('unfreeze')
return doc
}

Expand All @@ -89,7 +91,6 @@ const fns = {
insertBefore: function (input) {
return insert(input, this, true)
},

}
fns.append = fns.insertAfter
fns.prepend = fns.insertBefore
Expand Down
11 changes: 6 additions & 5 deletions src/1-one/change/api/replace.js
Expand Up @@ -2,7 +2,7 @@ const dollarStub = /\$[0-9a-z]+/g
const fns = {}

const titleCase = function (str) {
return str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase())
return str.replace(/\w\S*/g, txt => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase())
}

// doc.replace('foo', (m)=>{})
Expand All @@ -20,7 +20,7 @@ const subDollarSign = function (input, main) {
return input
}
let groups = main.groups()
input = input.replace(dollarStub, (a) => {
input = input.replace(dollarStub, a => {
let num = a.replace(/\$/, '')
if (groups.hasOwnProperty(num)) {
return groups[num].text()
Expand Down Expand Up @@ -65,16 +65,17 @@ fns.replaceWith = function (input, keep = {}) {
let tmp = main.docs[0]
let term = tmp[tmp.length - 1]
if (!term.tags.has('Possessive')) {
term.text += '\'s'
term.normal += '\'s'
term.text += "'s"
term.normal += "'s"
term.tags.add('Possessive')
}
}
// what should we return?
let m = main.toView(ptrs).compute(['index', 'lexicon'])
let m = main.toView(ptrs).compute(['index', 'freeze', 'lexicon'])
if (m.world.compute.preTagger) {
m.compute('preTagger')
}
m.compute('unfreeze')
// replace any old tags
if (keep.tags) {
m.terms().forEach((term, i) => {
Expand Down
46 changes: 46 additions & 0 deletions src/1-one/freeze/compute.js
@@ -0,0 +1,46 @@
const freeze = function (view) {
const world = view.world
const { model, methods } = view.world
const setTag = methods.one.setTag
const { frozenLex } = model.one
const multi = model.one._multiCache || {}

view.docs.forEach(terms => {
for (let i = 0; i < terms.length; i += 1) {
// basic lexicon lookup
let t = terms[i]
let word = t.machine || t.normal

// test a multi-word
if (multi[word] !== undefined && terms[i + 1]) {
let end = i + multi[word] - 1
for (let k = end; k > i; k -= 1) {
let words = terms.slice(i, k + 1)
let str = words.map(term => term.machine || term.normal).join(' ')
// lookup frozen lexicon
if (frozenLex.hasOwnProperty(str) === true) {
setTag(words, frozenLex[str], world, false, '1-frozen-multi-lexicon')
words.forEach(term => (term.frozen = true))
continue
}
}
}
// test single word
if (frozenLex[word] !== undefined && frozenLex.hasOwnProperty(word)) {
setTag([t], frozenLex[word], world, false, '1-freeze-lexicon')
t.frozen = true
continue
}
}
})
}

const unfreeze = function (view) {
view.docs.forEach(ts => {
ts.forEach(term => {
delete term.frozen
})
})
return view
}
export default { frozen: freeze, freeze, unfreeze }
20 changes: 20 additions & 0 deletions src/1-one/freeze/debug.js
@@ -0,0 +1,20 @@
/* eslint-disable no-console */
const blue = str => '\x1b[34m' + str + '\x1b[0m'
const dim = str => '\x1b[3m\x1b[2m' + str + '\x1b[0m'

const debug = function (view) {
view.docs.forEach(terms => {
console.log(blue('\n ┌─────────'))
terms.forEach(t => {
let str = ` ${dim('│')} `
let txt = t.implicit || t.text || '-'
if (t.frozen === true) {
str += `${blue(txt)} ❄️`
} else {
str += dim(txt)
}
console.log(str)
})
})
}
export default debug
25 changes: 13 additions & 12 deletions src/1-one/freeze/plugin.js
@@ -1,13 +1,17 @@
import compute from './compute.js'
import debug from './debug.js'

export default {
// lib: {
// freeze: function (obj) {
// this.world().model.two.freeze = obj
// },
// },
// add .compute('freeze')
compute,

mutate: world => {
const methods = world.methods.one
// add @isFrozen method
world.methods.one.termMethods.isFrozen = term => term.frozen === true
methods.termMethods.isFrozen = term => term.frozen === true
// adds `.debug('frozen')`
methods.debug.freeze = debug
methods.debug.frozen = debug
},

api: function (View) {
Expand All @@ -22,16 +26,13 @@ export default {
}
// reset all terms to allow any desctructive tags
View.prototype.unfreeze = function () {
this.docs.forEach(ts => {
ts.forEach(term => {
delete term.frozen
})
})
return this
this.compute('unfreeze')
}
// return all frozen terms
View.prototype.isFrozen = function () {
return this.match('@isFrozen+')
}
},
// run it in init
hooks: ['freeze'],
}
1 change: 1 addition & 0 deletions src/1-one/lexicon/compute/index.js
Expand Up @@ -5,6 +5,7 @@ import singleWord from './single-word.js'
// rest of pre-tagger is in ./two/preTagger
const lexicon = function (view) {
const world = view.world
// loop through our terms
view.docs.forEach(terms => {
for (let i = 0; i < terms.length; i += 1) {
if (terms[i].tags.size === 0) {
Expand Down
8 changes: 1 addition & 7 deletions src/1-one/lexicon/compute/multi-word.js
Expand Up @@ -3,7 +3,7 @@ const multiWord = function (terms, start_i, world) {
const { model, methods } = world
const setTag = methods.one.setTag
const multi = model.one._multiCache || {}
const { lexicon, frozenLex } = model.one || {}
const { lexicon } = model.one || {}
let t = terms[start_i]
let word = t.machine || t.normal

Expand All @@ -16,12 +16,6 @@ const multiWord = function (terms, start_i, world) {
return false
}
let str = words.map(term => term.machine || term.normal).join(' ')
// lookup frozen lexicon
if (frozenLex.hasOwnProperty(str) === true) {
setTag(words, frozenLex[str], world, false, '1-frozen-multi-lexicon')
words.forEach(term => (term.frozen = true))
return true
}
// lookup regular lexicon
if (lexicon.hasOwnProperty(str) === true) {
let tag = lexicon[str]
Expand Down
8 changes: 1 addition & 7 deletions src/1-one/lexicon/compute/single-word.js
Expand Up @@ -7,17 +7,11 @@ const checkLexicon = function (terms, i, world) {
const { model, methods } = world
// const fastTag = methods.one.fastTag
const setTag = methods.one.setTag
const { lexicon, frozenLex } = model.one
const { lexicon } = model.one

// basic lexicon lookup
let t = terms[i]
let word = t.machine || t.normal
// freeze lex
if (frozenLex[word] !== undefined && frozenLex.hasOwnProperty(word)) {
setTag([t], frozenLex[word], world, false, '1-freeze-lexicon')
t.frozen = true
return true
}
// normal lexicon lookup
if (lexicon[word] !== undefined && lexicon.hasOwnProperty(word)) {
setTag([t], lexicon[word], world, false, '1-lexicon')
Expand Down
2 changes: 1 addition & 1 deletion src/1-one/tokenize/compute/alias.js
Expand Up @@ -16,7 +16,7 @@ const addAliases = function (term, world) {
if (hasSlash.test(str) && !hasDomain.test(str) && !isMath.test(str)) {
let arr = str.split(hasSlash)
// don't split urls and things
if (arr.length <= 2) {
if (arr.length <= 3) {
arr.forEach(word => {
word = word.trim()
if (word !== '') {
Expand Down
2 changes: 1 addition & 1 deletion src/2-two/contraction-two/compute/index.js
Expand Up @@ -28,7 +28,7 @@ const reTag = function (terms, view, start, len) {
end += 1
}
tmp.ptrs = [[0, start, end]]
tmp.compute(['lexicon', 'preTagger'])
tmp.compute(['freeze', 'lexicon', 'preTagger', 'unfreeze'])
// don't for a reindex of the whole document
reIndex(terms)
}
Expand Down
2 changes: 1 addition & 1 deletion src/2-two/postTagger/compute/index.js
Expand Up @@ -20,6 +20,6 @@ const postTagger = function (view) {
}

// helper function for compute('tagger')
const tagger = view => view.compute(['lexicon', 'preTagger', 'postTagger'])
const tagger = view => view.compute(['freeze', 'lexicon', 'preTagger', 'postTagger', 'unfreeze'])

export default { postTagger, tagger }
1 change: 1 addition & 0 deletions src/2-two/preTagger/model/lexicon/frozenLex.js
Expand Up @@ -28,6 +28,7 @@ export default {

'bill gates': 'Person',
'doctor who': 'Person',
'dr who': 'Person',
'he man': 'Person',
'iron man': 'Person',
'kid cudi': 'Person',
Expand Down
14 changes: 7 additions & 7 deletions src/3-three/numbers/plugin.js
Expand Up @@ -10,12 +10,12 @@ export default {
api,

// add @greaterThan, @lessThan
mutate: world => {
let termMethods = world.methods.one.termMethods
// mutate: world => {
// let termMethods = world.methods.one.termMethods

termMethods.lessThan = function (term) {
console.log(term)
// return /[aeiou]/.test(term.text)
}
},
// termMethods.lessThan = function (term) {
// return false //TODO: implement
// // return /[aeiou]/.test(term.text)
// }
// },
}
2 changes: 1 addition & 1 deletion src/3-three/verbs/api/conjugate/toInfinitive.js
Expand Up @@ -24,7 +24,7 @@ const toInf = function (vb, parsed) {
let does = doDoes(vb, parsed)
vb.prepend(does)
}
vb.fullSentence().compute(['lexicon', 'preTagger', 'postTagger', 'chunks'])
vb.fullSentence().compute(['freeze', 'lexicon', 'preTagger', 'postTagger', 'unfreeze', 'chunks'])
return vb
}
export default toInf
12 changes: 7 additions & 5 deletions src/API/View.js
Expand Up @@ -4,13 +4,14 @@ import api from './methods/index.js'
class View {
constructor(document, pointer, groups = {}) {
// invisible props
[
let props = [
['document', document],
['world', world],
['_groups', groups],
['_cache', null],
['viewType', 'View']
].forEach(a => {
['viewType', 'View'],
]
props.forEach(a => {
Object.defineProperty(this, a[0], {
value: a[1],
writable: true,
Expand Down Expand Up @@ -101,15 +102,16 @@ class View {
let document = methods.one.tokenize.fromString(input, this.world)
let doc = new View(document)
doc.world = this.world
doc.compute(['normal', 'lexicon'])
doc.compute(['normal', 'freeze', 'lexicon'])
if (this.world.compute.preTagger) {
doc.compute('preTagger')
}
doc.compute('unfreeze')
return doc
}
clone() {
// clone the whole document
let document = this.document.slice(0) //node 17: structuredClone(document);
let document = this.document.slice(0) //node 17: structuredClone(document);
document = document.map(terms => {
return terms.map(term => {
term = Object.assign({}, term)
Expand Down
2 changes: 1 addition & 1 deletion src/_version.js
@@ -1 +1 @@
export default '14.12.0'
export default '14.13.0'