UNPKG

hfill

Version:

A speculative polyfill to use the h element in HTML

107 lines (87 loc) 2.58 kB
// polyfill contextual headings export function observe(scope, rawtag) { const tag = rawtag ? rawtag.toLowerCase() : 'x-h'; // polyfill existing contextual headings [].forEach.call( scope.getElementsByTagName(tag), polyfillContextualHeading ); // polyfill new contextual headings (new MutationObserver( (mutations) => mutations.forEach( (mutation) => { [].forEach.call( mutation.addedNodes, (node) => { if (tag === node.nodeName.toLowerCase()) { polyfillContextualHeading(node); } else if (node.getElementsByTagName) { [].forEach.call( node.getElementsByTagName(tag), polyfillContextualHeading ); } } ); } ) )).observe( scope, { childList: true, subtree: true } ); // polyfill a contextual heading function polyfillContextualHeading(h) { // default level is 1 let level = 1; // increase the level for each sectioning ancestor let ascend = h; while (ascend = ascend.parentElement) { if (sectionsMatch.test(ascend.nodeName)) { ++level; } else if (ascend.nodeName.toLowerCase() === tag) { return; } } // assign the heading role and aria-level h.setAttribute('role', 'heading'); h.setAttribute('aria-level', level); } } // style contextual headings export function style(scope, rawtag, cssText, sizes) { // eslint-disable-line max-params const tag = rawtag ? rawtag.toLowerCase() : 'x-h'; if (scope.querySelector('style#hfill-style')) { return; } const hstyle = document.createElement('style'); hstyle.setAttribute('id', 'hfill-style'); hstyle.textContent = [].concat( sizes || ['2em', '1.5em', '1.17em', '1em', '.83em', '.67em'] ).reduce( (css, value, level, levels) => { // eslint-disable-line max-params const total = Math.pow(sectionsLength, level); const selectors = []; for (let i = -1; ++i < total;) { const selector = []; for (let ii = i, j = -1; ++j < level;) { let modulus = ii % sectionsLength; selector.push(sections[modulus]); ii = (ii - modulus) / sectionsLength; } selectors.push(selector); } return `${ css + selectors.map( (x) => x.length ? x.join(' ').concat(` ${ tag }`) : tag ).join(',') }{font-size:${ levels[level] }}`; }, `${ tag }{${ cssText || 'display:block;font-weight:bold' }}` ); scope.appendChild(hstyle); } // contextual heading sectioning elements const sections = ['article', 'aside', 'nav', 'section']; const sectionsMatch = RegExp(`^(${ sections.join('|') })$`, 'i'); const sectionsLength = sections.length;