Upstream spencermountain/compromise state of the touched files before 642fe4f40a

This commit is contained in:
upstream committed 2026-10-14 19:27:21 +02:00
1 parent 608ac25b7b
commit 80f71d084f
2 files changed
+138

No files matched your search

+77
View File
@@ -0,0 +1,77 @@
const isClass = /^\../
const isId = /^#./
const escapeXml = str => {
str = str.replaceAll('&', '&')
str = str.replaceAll('<', '&lt;')
str = str.replaceAll('>', '&gt;')
str = str.replaceAll('"', '&quot;')
str = str.replaceAll("'", '&apos;')
return str
}
// interpret .class, #id, tagName
const toTag = function (k) {
let start = ''
let end = '</span>'
k = escapeXml(k)
if (isClass.test(k)) {
start = `<span class="${k.replace(/^\./, '')}"`
} else if (isId.test(k)) {
start = `<span id="${k.replace(/^#/, '')}"`
} else {
start = `<${k}`
end = `</${k}>`
}
start += '>'
return { start, end }
}
const getIndex = function (doc, obj) {
const starts = {}
const ends = {}
Object.keys(obj).forEach(k => {
let res = obj[k]
const tag = toTag(k)
if (typeof res === 'string') {
res = doc.match(res)
}
res.docs.forEach(terms => {
// don't highlight implicit terms
if (terms.every(t => t.implicit)) {
return
}
const a = terms[0].id
starts[a] ||= []
starts[a].push(tag.start)
const b = terms.at(-1).id
ends[b] ||= []
ends[b].push(tag.end)
})
})
return { starts, ends }
}
const html = function (obj) {
// index ids to highlight
const { starts, ends } = getIndex(this, obj)
// create the text output
let out = ''
this.docs.forEach(terms => {
for (let i = 0; i < terms.length; i += 1) {
const t = terms[i]
// do a span tag
if (Object.hasOwn(starts, t.id)) {
out += starts[t.id].join('')
}
out += t.pre || ''
out += t.text || ''
if (Object.hasOwn(ends, t.id)) {
out += ends[t.id].join('')
}
out += t.post || ''
}
})
return out
}
export default { html }
+61
View File
@@ -0,0 +1,61 @@
import test from 'tape'
import nlp from '../../lib/one.js'
const here = '[one/output/html] '
test('html-match', function (t) {
let doc = nlp(`match one two. one match two. one two match.`)
let html = doc.html({ i: 'match' })
t.equal(html, `<i>match</i> one two. one <i>match</i> two. one two <i>match</i>.`, here + 'html tag')
doc = nlp(`match one two. one match two.`)
html = doc.html({ '.foo': 'match' })
t.equal(html, `<span class="foo">match</span> one two. one <span class="foo">match</span> two.`, here + 'html class')
doc = nlp(`one match match two.`)
html = doc.html({ '#foo': 'match+' })
t.equal(html, `one <span id="foo">match match</span> two.`, here + 'html id')
doc = nlp(`one match two.`)
html = doc.html({ '.red': 'match+', '.blue': doc.match('two') })
t.equal(html, `one <span class="red">match</span> <span class="blue">two</span>.`, here + 'html two classes')
doc = nlp(`if i can recall, my grey dog loves pizza crusts (they are really good).`)
html = doc.html({ '.red': 'my grey dog', '.blue': doc.match('loves') })
t.equal(
html,
`if i can recall, <span class="red">my grey dog</span> <span class="blue">loves</span> pizza crusts (they are really good).`,
here + 'html pre test'
)
t.end()
})
test('html-nest', function (t) {
const doc = nlp(`one match two.`)
let html = doc.html({
i: 'match',
b: 'one match two',
})
t.equal(html, `<b>one <i>match</i> two</b>.`, here + 'easy nest')
html = doc.html({
b: 'match two',
i: 'match',
})
t.equal(html, `one <b><i>match</i> two</b>.`, here + 'hard nest')
// html = doc.html({
// i: 'match',
// b: 'match two',
// })
// t.equal(html, `one <b><i>match</i> two</b>.`, here + 'harder nest')
t.end()
})
test('html-implicit', function (t) {
const doc = nlp(`he's cool`)
const out = doc.html({ '.foo': '#Verb' })
t.equal(out, `he's cool`, here + 'implict')
t.end()
})