32 lines
1.2 KiB
JavaScript
32 lines
1.2 KiB
JavaScript
import { parse } from 'parse5'
|
|
|
|
const attribute = (node, name) => node.attrs?.find((item) => item.name === name)?.value
|
|
|
|
export const htmlFacts = (html) => {
|
|
const facts = {
|
|
ids: [], hrefs: [], languages: [],
|
|
hasViewport: false, hasHeadingElement: false, isDraft: false,
|
|
}
|
|
const visit = (node) => {
|
|
if (node.tagName) {
|
|
const id = attribute(node, 'id')
|
|
if (id !== undefined) facts.ids.push(id)
|
|
const href = attribute(node, 'href')
|
|
if (href !== undefined) facts.hrefs.push(href)
|
|
for (const className of (attribute(node, 'class') ?? '').split(/\s+/)) {
|
|
if (className.startsWith('language-')) facts.languages.push(className.slice('language-'.length))
|
|
}
|
|
if (node.tagName === 'heading') facts.hasHeadingElement = true
|
|
if (node.tagName === 'meta') {
|
|
const name = attribute(node, 'name')?.toLowerCase()
|
|
if (name === 'viewport') facts.hasViewport = true
|
|
if (name === 'robots' && /(?:^|[,\s])noindex(?:$|[,\s])/i.test(attribute(node, 'content') ?? '')) facts.isDraft = true
|
|
}
|
|
}
|
|
for (const child of node.childNodes ?? []) visit(child)
|
|
if (node.content) visit(node.content)
|
|
}
|
|
visit(parse(html))
|
|
return facts
|
|
}
|