3
0
mirror of https://github.com/larvit/adf-codec.git synced 2026-11-12 11:48:29 +01:00
Files
adf-codec/corpus-gathering/select.mjs
T

71 lines
2.3 KiB
JavaScript

function markSet(node) {
return (node.marks ?? []).map((mark) => mark.type).sort().join('+')
}
function inlineLabel(node) {
return node.type === 'text' ? `text[${markSet(node)}]` : node.type
}
function collect(node, parentType, found) {
found.add(`node:${node.type}`)
if (parentType !== undefined) found.add(`child:${parentType}>${node.type}`)
for (const key of Object.keys(node.attrs ?? {})) found.add(`attr:${node.type}.${key}`)
for (const mark of node.marks ?? []) {
found.add(`mark:${mark.type}`)
for (const key of Object.keys(mark.attrs ?? {})) found.add(`attr:${mark.type}.${key}`)
}
if (node.type === 'text' && (node.marks ?? []).length > 1) found.add(`marks:${markSet(node)}`)
const children = node.content ?? []
children.forEach((child, index) => {
collect(child, node.type, found)
const next = children[index + 1]
if (next !== undefined) found.add(`beside:${inlineLabel(child)}|${inlineLabel(next)}`)
})
}
// A document's features: its node and mark types, attribute keys, nesting, marks held together and neighbours such as bold beside a code span.
export function features(document) {
const found = new Set()
collect(document, undefined, found)
return found
}
function isType(feature) {
return feature.startsWith('node:') || feature.startsWith('mark:')
}
function bestCandidate(candidates, covered) {
let best
let bestScore = 0
let bestShowsType = false
for (const candidate of candidates) {
let added = 0
let showsType = false
for (const feature of candidate.features) {
if (covered.has(feature)) continue
added += 1
showsType ||= isType(feature)
}
const score = added / candidate.size
if (showsType && !bestShowsType || showsType === bestShowsType && score > bestScore) {
best = candidate
bestScore = score
bestShowsType = showsType
}
}
return best
}
// Takes the candidate showing the most new features per byte, new node and mark types first, until `limit` or until none shows a new one.
export function selectDocuments(candidates, limit) {
const covered = new Set()
const chosen = []
while (chosen.length < limit) {
const best = bestCandidate(candidates, covered)
if (best === undefined) break
chosen.push(best)
for (const feature of best.features) covered.add(feature)
}
return chosen
}