-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
82 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
.DS_Store | ||
*.d.ts | ||
*.log | ||
coverage/ | ||
node_modules/ | ||
*.d.ts | ||
*.log | ||
.DS_Store | ||
yarn.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,94 @@ | ||
import fs from 'node:fs' | ||
import https from 'node:https' | ||
import concat from 'concat-stream' | ||
import concatStream from 'concat-stream' | ||
import {bail} from 'bail' | ||
import {unified} from 'unified' | ||
import html from 'rehype-parse' | ||
import rehypeParse from 'rehype-parse' | ||
import {selectAll} from 'hast-util-select' | ||
import {toString} from 'hast-util-to-string' | ||
import {htmlElementAttributes} from './index.js' | ||
|
||
const processor = unified().use(html) | ||
const own = {}.hasOwnProperty | ||
|
||
// Global attributes. | ||
let globals = htmlElementAttributes['*'] | ||
const processor = unified().use(rehypeParse) | ||
|
||
if (!globals) { | ||
globals = [] | ||
htmlElementAttributes['*'] = globals | ||
if (!('*' in htmlElementAttributes)) { | ||
htmlElementAttributes['*'] = [] | ||
} | ||
|
||
// Global attributes. | ||
const globals = htmlElementAttributes['*'] | ||
|
||
// Crawl WHATWG HTML. | ||
https.get('https://html.spec.whatwg.org/multipage/indices.html', onhtml) | ||
|
||
/** | ||
* @param {import('http').IncomingMessage} response | ||
*/ | ||
function onhtml(response) { | ||
response.pipe(concat(onconcat)).on('error', bail) | ||
|
||
/** | ||
* @param {Buffer} buf | ||
*/ | ||
function onconcat(buf) { | ||
const nodes = selectAll('#attributes-1 tbody tr', processor.parse(buf)) | ||
let index = -1 | ||
const result = {} | ||
/** @type {string} */ | ||
let key | ||
/** @type {string} */ | ||
let name | ||
/** @type {string} */ | ||
let value | ||
/** @type {string[]} */ | ||
let elements | ||
/** @type {string} */ | ||
let tagName | ||
/** @type {string[]} */ | ||
let attributes | ||
/** @type {number} */ | ||
let offset | ||
|
||
// Throw if we didn’t match, e.g., when the spec updates. | ||
if (nodes.length === 0) { | ||
throw new Error('Missing results in html') | ||
} | ||
|
||
while (++index < nodes.length) { | ||
name = toString(nodes[index].children[0]).trim() | ||
value = toString(nodes[index].children[1]).trim() | ||
|
||
if (/custom elements/i.test(value)) { | ||
continue | ||
} | ||
|
||
offset = -1 | ||
elements = /HTML elements/.test(value) | ||
? ['*'] | ||
: value.split(/;/g).map((d) => d.replace(/\([^)]+\)/g, '').trim()) | ||
|
||
while (++offset < elements.length) { | ||
tagName = elements[offset].toLowerCase().trim() | ||
attributes = | ||
htmlElementAttributes[tagName] || | ||
(htmlElementAttributes[tagName] = []) | ||
|
||
if (!attributes.includes(name)) { | ||
attributes.push(name) | ||
https.get('https://html.spec.whatwg.org/multipage/indices.html', (response) => { | ||
response | ||
.pipe( | ||
concatStream((buf) => { | ||
const nodes = selectAll('#attributes-1 tbody tr', processor.parse(buf)) | ||
const result = {} | ||
let index = -1 | ||
|
||
// Throw if we didn’t match, e.g., when the spec updates. | ||
if (nodes.length === 0) { | ||
throw new Error('Missing results in html') | ||
} | ||
|
||
while (++index < nodes.length) { | ||
const name = toString(nodes[index].children[0]).trim() | ||
const value = toString(nodes[index].children[1]).trim() | ||
|
||
if (/custom elements/i.test(value)) { | ||
continue | ||
} | ||
|
||
const elements = /HTML elements/.test(value) | ||
? ['*'] | ||
: value.split(/;/g).map((d) => d.replace(/\([^)]+\)/g, '').trim()) | ||
let offset = -1 | ||
|
||
while (++offset < elements.length) { | ||
const tagName = elements[offset].toLowerCase().trim() | ||
|
||
if (!own.call(htmlElementAttributes, tagName)) { | ||
htmlElementAttributes[tagName] = [] | ||
} | ||
|
||
/** @type {string[]} */ | ||
const attributes = htmlElementAttributes[tagName] | ||
|
||
if (!attributes.includes(name)) { | ||
attributes.push(name) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
const keys = Object.keys(htmlElementAttributes).sort() | ||
index = -1 | ||
const keys = Object.keys(htmlElementAttributes).sort() | ||
index = -1 | ||
|
||
while (++index < keys.length) { | ||
const key = keys[index] | ||
|
||
while (++index < keys.length) { | ||
key = keys[index] | ||
htmlElementAttributes[key].sort() | ||
htmlElementAttributes[key].sort() | ||
|
||
if (key !== '*') { | ||
htmlElementAttributes[key] = htmlElementAttributes[key].filter( | ||
(/** @type {string} */ d) => !globals.includes(d) | ||
if (key !== '*') { | ||
htmlElementAttributes[key] = htmlElementAttributes[key].filter( | ||
(/** @type {string} */ d) => !globals.includes(d) | ||
) | ||
} | ||
|
||
if (htmlElementAttributes[key].length > 0) { | ||
result[key] = htmlElementAttributes[key] | ||
} | ||
} | ||
|
||
fs.writeFile( | ||
'index.js', | ||
'export const htmlElementAttributes = ' + | ||
JSON.stringify(result, null, 2) + | ||
'\n', | ||
bail | ||
) | ||
} | ||
|
||
if (htmlElementAttributes[key].length > 0) { | ||
result[key] = htmlElementAttributes[key] | ||
} | ||
} | ||
|
||
fs.writeFile( | ||
'index.js', | ||
'export const htmlElementAttributes = ' + | ||
JSON.stringify(result, null, 2) + | ||
'\n', | ||
bail | ||
}) | ||
) | ||
} | ||
} | ||
.on('error', bail) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters