@@ -0,0 +1,245 @@
|
||||
/** Flow HTML to wrapped lines + link/form hit targets. */
|
||||
|
||||
var BARE_SUMMON_BLOCK = {
|
||||
address: 1,
|
||||
article: 1,
|
||||
aside: 1,
|
||||
blockquote: 1,
|
||||
body: 1,
|
||||
div: 1,
|
||||
dl: 1,
|
||||
dt: 1,
|
||||
dd: 1,
|
||||
fieldset: 1,
|
||||
figcaption: 1,
|
||||
figure: 1,
|
||||
footer: 1,
|
||||
form: 1,
|
||||
h1: 1,
|
||||
h2: 1,
|
||||
h3: 1,
|
||||
h4: 1,
|
||||
h5: 1,
|
||||
h6: 1,
|
||||
header: 1,
|
||||
hr: 1,
|
||||
li: 1,
|
||||
main: 1,
|
||||
nav: 1,
|
||||
ol: 1,
|
||||
p: 1,
|
||||
pre: 1,
|
||||
section: 1,
|
||||
table: 1,
|
||||
tr: 1,
|
||||
ul: 1
|
||||
}
|
||||
|
||||
function bareSummonIsBlock(name, style) {
|
||||
var d = bareSummonDisplay(style)
|
||||
if (d === 'none') return false
|
||||
if (d === 'inline') return false
|
||||
if (d === 'block') return true
|
||||
return !!BARE_SUMMON_BLOCK[name]
|
||||
}
|
||||
|
||||
function bareSummonLayout(doc, opts) {
|
||||
opts = opts || {}
|
||||
var cols = Math.max(20, opts.cols || 80)
|
||||
var sheets = opts.sheets || []
|
||||
var numbers = opts.numbers !== false
|
||||
var lines = []
|
||||
var links = []
|
||||
var forms = []
|
||||
var cur = ''
|
||||
var curMarks = []
|
||||
|
||||
function flush() {
|
||||
if (cur === '' && !curMarks.length) return
|
||||
lines.push({ text: cur, marks: curMarks })
|
||||
cur = ''
|
||||
curMarks = []
|
||||
}
|
||||
|
||||
function emitNl() {
|
||||
flush()
|
||||
}
|
||||
|
||||
function emitText(s, mark) {
|
||||
s = String(s || '')
|
||||
if (!s) return
|
||||
var i = 0
|
||||
while (i < s.length) {
|
||||
var ch = s.charAt(i)
|
||||
if (ch === '\n') {
|
||||
emitNl()
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if (ch === '\r') {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if (cur.length >= cols) emitNl()
|
||||
if (mark) {
|
||||
curMarks.push({
|
||||
col: cur.length,
|
||||
ch: ch,
|
||||
link: mark.link,
|
||||
form: mark.form,
|
||||
bold: mark.bold,
|
||||
dim: mark.dim
|
||||
})
|
||||
}
|
||||
cur += ch
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
function emitSpace() {
|
||||
if (cur && cur.charAt(cur.length - 1) !== ' ') emitText(' ')
|
||||
}
|
||||
|
||||
function walk(node, mark) {
|
||||
if (!node) return
|
||||
if (node.type === 'text') {
|
||||
var t = node.text || ''
|
||||
if (!mark || !mark.pre) t = t.replace(/\s+/g, ' ')
|
||||
if (t === ' ' || t === '') {
|
||||
if (t === ' ') emitSpace()
|
||||
return
|
||||
}
|
||||
emitText(t, mark)
|
||||
return
|
||||
}
|
||||
if (node.type !== 'element') return
|
||||
var st = bareSummonComputedStyle(node, sheets)
|
||||
if (bareSummonDisplay(st) === 'none') return
|
||||
var name = node.name
|
||||
var nextMark = {
|
||||
link: mark && mark.link,
|
||||
form: mark && mark.form,
|
||||
bold: mark && mark.bold,
|
||||
dim: mark && mark.dim,
|
||||
pre: mark && mark.pre
|
||||
}
|
||||
if (
|
||||
st['font-weight'] === 'bold' ||
|
||||
name === 'b' ||
|
||||
name === 'strong' ||
|
||||
/^h[1-6]$/.test(name)
|
||||
)
|
||||
nextMark.bold = true
|
||||
if (name === 'pre' || name === 'code' || st['font-family'] === 'monospace')
|
||||
nextMark.dim = true
|
||||
if (name === 'pre' || st['white-space'] === 'pre') nextMark.pre = true
|
||||
|
||||
if (name === 'a' && node.attrs.href) {
|
||||
var id = links.length
|
||||
links.push({
|
||||
id: id,
|
||||
href: node.attrs.href,
|
||||
text: bareSummonTextContent(node).replace(/\s+/g, ' ').trim()
|
||||
})
|
||||
nextMark.link = id
|
||||
if (numbers) emitText('[' + (id + 1) + ']', nextMark)
|
||||
}
|
||||
if (name === 'br') {
|
||||
emitNl()
|
||||
return
|
||||
}
|
||||
if (name === 'hr') {
|
||||
emitNl()
|
||||
emitText('\u2500'.repeat(Math.min(cols, 40)))
|
||||
emitNl()
|
||||
return
|
||||
}
|
||||
if (name === 'img') {
|
||||
var alt = node.attrs.alt || node.attrs.src || 'img'
|
||||
emitText('[IMG ' + alt + ']')
|
||||
return
|
||||
}
|
||||
if (
|
||||
name === 'input' ||
|
||||
name === 'textarea' ||
|
||||
name === 'select' ||
|
||||
name === 'button'
|
||||
) {
|
||||
var fid = forms.length
|
||||
forms.push({
|
||||
id: fid,
|
||||
name: node.attrs.name || '',
|
||||
type: (node.attrs.type || name).toLowerCase(),
|
||||
value: node.attrs.value || '',
|
||||
node: node
|
||||
})
|
||||
nextMark.form = fid
|
||||
emitText('[' + (node.attrs.type || name) + ']')
|
||||
if (name === 'input' && BARE_SUMMON_VOID[name]) return
|
||||
}
|
||||
if (name === 'iframe' || name === 'video' || name === 'audio') {
|
||||
emitText(
|
||||
'[' +
|
||||
name.toUpperCase() +
|
||||
(node.attrs.src ? ' ' + node.attrs.src : '') +
|
||||
']'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
var block = bareSummonIsBlock(name, st)
|
||||
if (block) emitNl()
|
||||
if (name === 'li') emitText('\u2022 ')
|
||||
var ch = node.children || []
|
||||
for (var i = 0; i < ch.length; i++) walk(ch[i], nextMark)
|
||||
if (block) emitNl()
|
||||
}
|
||||
|
||||
walk(doc.body, {})
|
||||
flush()
|
||||
while (lines.length && !String(lines[0].text || '').trim()) lines.shift()
|
||||
while (lines.length && !String(lines[lines.length - 1].text || '').trim())
|
||||
lines.pop()
|
||||
|
||||
var plain = lines.map(function (l) {
|
||||
return l.text
|
||||
})
|
||||
return {
|
||||
cols: cols,
|
||||
lines: lines,
|
||||
plain: plain,
|
||||
links: links,
|
||||
forms: forms,
|
||||
title: doc.title || ''
|
||||
}
|
||||
}
|
||||
|
||||
function bareSummonReaderText(doc) {
|
||||
var bits = []
|
||||
function keep(n) {
|
||||
return (
|
||||
n &&
|
||||
n.type === 'element' &&
|
||||
(n.name === 'p' ||
|
||||
n.name === 'h1' ||
|
||||
n.name === 'h2' ||
|
||||
n.name === 'h3' ||
|
||||
n.name === 'li' ||
|
||||
n.name === 'pre' ||
|
||||
n.name === 'blockquote' ||
|
||||
n.name === 'article')
|
||||
)
|
||||
}
|
||||
function walk(n) {
|
||||
if (!n) return
|
||||
if (keep(n)) {
|
||||
var t = bareSummonTextContent(n).replace(/\s+/g, ' ').trim()
|
||||
if (t) bits.push(t)
|
||||
return
|
||||
}
|
||||
var ch = n.children || []
|
||||
for (var i = 0; i < ch.length; i++) walk(ch[i])
|
||||
}
|
||||
walk(doc.body)
|
||||
return bits.join('\n\n')
|
||||
}
|
||||
Reference in New Issue
Block a user