Files
bare-operating-system/packages/bare-os-coreutils/lib/summon-css.js
T
Raven Scott dfb5638c95
Release rolling / release (push) Failing after 5m54s
Update summon browser
2026-08-13 00:42:27 -04:00

313 lines
8.5 KiB
JavaScript

/** Minimal CSS: tag / .class / #id / * plus a few properties. */
var BARE_SUMMON_UA_CSS = [
{ sel: 'a', decl: { color: 'blue', 'text-decoration': 'underline' } },
{ sel: 'b', decl: { 'font-weight': 'bold' } },
{ sel: 'strong', decl: { 'font-weight': 'bold' } },
{ sel: 'em', decl: { 'font-style': 'italic' } },
{ sel: 'i', decl: { 'font-style': 'italic' } },
{
sel: 'h1',
decl: {
'font-weight': 'bold',
'margin-top': '1em',
'margin-bottom': '0.5em'
}
},
{ sel: 'h2', decl: { 'font-weight': 'bold', 'margin-top': '1em' } },
{ sel: 'h3', decl: { 'font-weight': 'bold' } },
{ sel: 'pre', decl: { 'white-space': 'pre', 'font-family': 'monospace' } },
{ sel: 'code', decl: { 'font-family': 'monospace' } },
{ sel: 'script', decl: { display: 'none' } },
{ sel: 'style', decl: { display: 'none' } },
{ sel: 'head', decl: { display: 'none' } },
{ sel: 'title', decl: { display: 'none' } },
{ sel: 'meta', decl: { display: 'none' } },
{ sel: 'link', decl: { display: 'none' } },
{ sel: 'noscript', decl: { display: 'none' } }
]
function bareSummonParseDeclarations(block) {
var decl = {}
var parts = String(block || '').split(';')
for (var i = 0; i < parts.length; i++) {
var p = parts[i]
var c = p.indexOf(':')
if (c < 0) continue
var k = p.slice(0, c).trim().toLowerCase()
var v = p.slice(c + 1).trim()
if (k) decl[k] = v
}
return decl
}
function bareSummonStripAtRules(css) {
var s = String(css || '')
var out = ''
var i = 0
while (i < s.length) {
if (s.charAt(i) === '@') {
var brace = s.indexOf('{', i)
if (brace < 0) break
var depth = 0
var j = brace
for (; j < s.length; j++) {
if (s.charAt(j) === '{') depth++
else if (s.charAt(j) === '}') {
depth--
if (depth === 0) {
j++
break
}
}
}
i = j
continue
}
out += s.charAt(i)
i++
}
return out
}
function bareSummonParseStylesheet(css, maxRules) {
var s = bareSummonStripAtRules(
String(css || '').replace(/\/\*[\s\S]*?\*\//g, '')
)
var rules = []
var cap = maxRules > 0 ? maxRules : 800
var re = /([^{}]+)\{([^{}]*)\}/g
var m
while ((m = re.exec(s)) && rules.length < cap) {
var sels = m[1].split(',')
var decl = bareSummonParseDeclarations(m[2])
for (var i = 0; i < sels.length; i++) {
var sel = sels[i].trim()
if (sel) rules.push({ sel: sel, decl: decl })
}
}
return rules
}
function bareSummonHasClass(node, name) {
var cls = (node.attrs && node.attrs.class ? node.attrs.class : '').split(
/\s+/
)
return cls.indexOf(name) >= 0
}
function bareSummonMatchCompound(sel, node) {
if (!node || node.type !== 'element') return false
sel = String(sel || '').trim()
if (!sel || sel === '*') return true
if (sel.charAt(0) === ':') return false
var i = 0
var tag = ''
if (/^[a-zA-Z]/.test(sel)) {
while (i < sel.length && /[a-zA-Z0-9_-]/.test(sel.charAt(i))) i++
tag = sel.slice(0, i).toLowerCase()
if (node.name !== tag) return false
}
while (i < sel.length) {
var ch = sel.charAt(i)
if (ch === '.') {
i++
var c0 = i
while (i < sel.length && /[a-zA-Z0-9_-]/.test(sel.charAt(i))) i++
if (!bareSummonHasClass(node, sel.slice(c0, i))) return false
} else if (ch === '#') {
i++
var i0 = i
while (i < sel.length && /[a-zA-Z0-9_-]/.test(sel.charAt(i))) i++
if ((node.attrs.id || '') !== sel.slice(i0, i)) return false
} else if (ch === '[') {
var end = sel.indexOf(']', i)
if (end < 0) return false
var inside = sel.slice(i + 1, end)
var eq = inside.indexOf('=')
var an = (eq < 0 ? inside : inside.slice(0, eq)).trim().toLowerCase()
var av =
eq < 0
? null
: inside
.slice(eq + 1)
.trim()
.replace(/^["']|["']$/g, '')
var have = node.attrs ? node.attrs[an] : undefined
if (eq < 0) {
if (have == null) return false
} else if (String(have) !== av) return false
i = end + 1
} else if (ch === ':') {
i++
while (i < sel.length && /[a-zA-Z0-9_-]/.test(sel.charAt(i))) i++
if (sel.charAt(i) === '(') {
var depth = 1
i++
while (i < sel.length && depth) {
if (sel.charAt(i) === '(') depth++
else if (sel.charAt(i) === ')') depth--
i++
}
}
} else return false
}
return true
}
function bareSummonSplitCombinators(sel) {
var parts = []
var cur = ''
var comb = ' '
var i
var s = String(sel || '')
.replace(/\s+/g, ' ')
.trim()
for (i = 0; i < s.length; i++) {
var ch = s.charAt(i)
if (ch === '>' || ch === '+' || ch === '~') {
if (cur.trim()) parts.push({ sel: cur.trim(), comb: comb })
cur = ''
comb = ch
if (s.charAt(i + 1) === ' ') i++
} else if (ch === ' ') {
if (cur.trim()) {
parts.push({ sel: cur.trim(), comb: comb })
cur = ''
comb = ' '
}
} else cur += ch
}
if (cur.trim()) parts.push({ sel: cur.trim(), comb: comb })
return parts
}
function bareSummonPrevElement(node) {
if (!node || !node.parent) return null
var kids = node.parent.children || []
var i
var prev = null
for (i = 0; i < kids.length; i++) {
if (kids[i] === node) return prev
if (kids[i] && kids[i].type === 'element') prev = kids[i]
}
return prev
}
function bareSummonMatches(sel, node) {
if (!node || node.type !== 'element') return false
sel = String(sel || '').trim()
if (!sel) return false
var groups = sel.split(',')
var g
for (g = 0; g < groups.length; g++) {
if (bareSummonMatchesOne(groups[g].trim(), node)) return true
}
return false
}
function bareSummonMatchesOne(sel, node) {
var parts = bareSummonSplitCombinators(sel)
if (!parts.length) return false
var cur = node
var p = parts.length - 1
if (!bareSummonMatchCompound(parts[p].sel, cur)) return false
p--
while (p >= 0 && cur) {
var comb = parts[p + 1] ? parts[p + 1].comb : ' '
if (comb === '>') {
cur = cur.parent
if (!cur || !bareSummonMatchCompound(parts[p].sel, cur)) return false
p--
} else if (comb === '+') {
cur = bareSummonPrevElement(cur)
if (!cur || !bareSummonMatchCompound(parts[p].sel, cur)) return false
p--
} else if (comb === '~') {
var ok = false
var sib = bareSummonPrevElement(cur)
while (sib) {
if (bareSummonMatchCompound(parts[p].sel, sib)) {
ok = true
cur = sib
break
}
sib = bareSummonPrevElement(sib)
}
if (!ok) return false
p--
} else {
var hit = false
var anc = cur.parent
while (anc) {
if (bareSummonMatchCompound(parts[p].sel, anc)) {
hit = true
cur = anc
break
}
anc = anc.parent
}
if (!hit) return false
p--
}
}
return p < 0
}
function bareSummonMatchSimple(sel, node) {
return bareSummonMatches(sel, node)
}
function bareSummonQueryAll(root, sel, cap) {
var out = []
var max = cap > 0 ? cap : 2000
function walk(n) {
if (!n || out.length >= max) return
if (n.type === 'element' && bareSummonMatches(sel, n)) out.push(n)
var ch = n.children || []
var i
for (i = 0; i < ch.length; i++) walk(ch[i])
}
walk(root)
return out
}
function bareSummonComputedStyle(node, sheets) {
var out = {}
function apply(decl) {
var k
for (k in decl) {
if (Object.prototype.hasOwnProperty.call(decl, k)) out[k] = decl[k]
}
}
var i
for (i = 0; i < BARE_SUMMON_UA_CSS.length; i++) {
if (bareSummonMatches(BARE_SUMMON_UA_CSS[i].sel, node))
apply(BARE_SUMMON_UA_CSS[i].decl)
}
if (sheets) {
for (i = 0; i < sheets.length; i++) {
var rules = sheets[i]
for (var r = 0; r < rules.length; r++) {
if (bareSummonMatches(rules[r].sel, node)) apply(rules[r].decl)
}
}
}
if (node && node.attrs && node.attrs.style) {
apply(bareSummonParseDeclarations(node.attrs.style))
}
return out
}
function bareSummonDisplay(style) {
var d = style && style.display ? String(style.display).toLowerCase() : ''
if (d === 'none') return 'none'
if (style && String(style.visibility || '').toLowerCase() === 'hidden')
return 'none'
if (d === 'inline' || d === 'inline-block' || d === 'inline-flex')
return 'inline'
if (d === 'flex' || d === 'grid' || d === 'table' || d === 'list-item')
return 'block'
return ''
}