Skip to content

Instantly share code, notes, and snippets.

@joshski
Created May 16, 2019 16:13
Show Gist options
  • Save joshski/3958d4299868610797efcc95c97cae7b to your computer and use it in GitHub Desktop.
Save joshski/3958d4299868610797efcc95c97cae7b to your computer and use it in GitHub Desktop.
function getMicroDataFromElement(element) {
element = element || document.body
function descendToAttribute(scope, attribute) {
return [].slice.apply(scope.children).reduce(function(props, child) {
return props.concat(
child.hasAttribute(attribute) ? [child] : descendToAttribute(child, attribute)
)
}, [])
}
function scopesUnder(scope) {
return [].slice.apply(scope.children).reduce(function(props, child) {
if (child.hasAttribute('itemprop')) {
throw new Error(
'Found itemprop="' + child.getAttribute('itemprop') + '" outside an itemscope.'
)
}
return props.concat(child.hasAttribute('itemscope') ? [child] : scopesUnder(child))
}, [])
}
function propsUnder(scope) {
return descendToAttribute(scope, 'itemprop')
}
function dataAtScope(scope) {
if (scope.hasAttribute('itemtype') || scope.tagName === 'TIME') return dataInPropElement(scope)
return propsUnder(scope).reduce(function(props, element) {
var propValue = element.hasAttribute('itemscope')
? dataAtScope(element)
: dataInPropElement(element)
props[element.getAttribute('itemprop')] = propValue
return props
}, {})
}
function dataInPropElement(element) {
var type = element.getAttribute('itemtype')
switch (type) {
case 'http://schema.org/Text':
case null:
if (element.tagName === 'TIME') return element.getAttribute('datetime')
if (element.tagName === 'IMG') {
return element.getAttribute('src')
}
if (element.hasAttribute('content')) return element.getAttribute('content')
return element.textContent ? element.textContent : null
case 'http://schema.org/Integer':
case 'http://schema.org/Number':
return Number(element.textContent)
case 'null':
return null
case 'http://schema.org/Boolean':
return element.getAttribute('content') === 'true' || element.textContent === 'true'
case 'http://schema.org/ItemList':
return scopesUnder(element).map(dataAtScope)
default:
throw new Error(
"Unable to parse element with itemtype '" +
type +
'\' (itemprop="' +
element.getAttribute('itemprop') +
')"'
)
}
}
var scopes = scopesUnder(element)
if (scopes.length !== 1)
throw new Error('Found ' + scopes.length + ' itemscope elements in HTML:\n' + element.innerHTML)
return dataAtScope(scopes[0])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment