Skip to content

Commit

Permalink
Add more JSDocs
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Jan 17, 2023
1 parent 888856f commit 72d8c67
Showing 1 changed file with 87 additions and 15 deletions.
102 changes: 87 additions & 15 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
/**
* @typedef {import('sax').Tag} Tag
* @typedef {import('unist').Point} Point
* @typedef {import('xast').Root} Root
* @typedef {import('xast').Element} Element
* @typedef {import('xast').Comment} Comment
* @typedef {import('xast').Text} Text
* @typedef {import('xast').Doctype} Doctype
* @typedef {import('xast').RootChildMap} RootChildMap
*/

/**
* @typedef {RootChildMap[keyof RootChildMap]} Child
* @typedef {Root|Child} Node
* @typedef {import('unist').Point} Point
* @typedef {import('sax').Tag} Tag
* @typedef {Root | Child} Node
*/

import sax from 'sax'
Expand All @@ -21,12 +23,17 @@ const fromCharCode = String.fromCharCode
const search = /\r?\n|\r/g

/**
* @param {string|Uint8Array} doc
* Parse a string of XML to a xast tree.
*
* @param {string | Uint8Array} doc
* Serialized XML.
* @returns {Root}
* xast root.
*/
export function fromXml(doc) {
// @ts-expect-error `strictEntities` is most definitely fine.
const parser = new Parser(true, {position: true, strictEntities: true})
/** @type {Array<Node>} */
/** @type {[Root, ...Array<Node>]} */
const stack = [{type: 'root', children: []}]
let position = now()

Expand All @@ -48,8 +55,12 @@ export function fromXml(doc) {
return stack[0]

/**
* Crash on a SAX error.
*
* @param {Error} error
* Error.
* @returns {never}
* Never.
*/
function onerror(error) {
const index = error.message.indexOf('\nLine')
Expand All @@ -60,15 +71,22 @@ export function fromXml(doc) {
}

/**
* Crash on an SGML declaration.
*
* @returns {never}
* Never.
*/
function onsgmldeclaration() {
fail('Unexpected SGML declaration', 'unexpected-sgml')
}

/**
* Handle a doctype.
*
* @param {string} value
* Doctype string.
* @returns {void}
* Nothing.
*/
// eslint-disable-next-line complexity
function ondoctype(value) {
Expand All @@ -77,15 +95,15 @@ export function fromXml(doc) {
const node = {type: 'doctype', name: '', public: null, system: null}
let index = -1
let state = 'BEGIN'
/** @type {string|undefined} */
/** @type {string | undefined} */
let returnState
/** @type {string|undefined} */
/** @type {string | undefined} */
let buffer
/** @type {number|undefined} */
/** @type {number | undefined} */
let bufferIndex
/** @type {number|undefined} */
/** @type {number | undefined} */
let start
/** @type {number|undefined} */
/** @type {number | undefined} */
let marker

while (++index <= value.length) {
Expand Down Expand Up @@ -326,17 +344,25 @@ export function fromXml(doc) {
}

/**
* Handle a processing instruction.
*
* @param {{name: string, body: string}} value
* Processing instruction token.
* @returns {void}
* Nothing.
*/
function onprocessinginstruction(value) {
enter({type: 'instruction', name: value.name, value: value.body})
exit()
}

/**
* Handle a comment.
*
* @param {string} value
* Comment value.
* @returns {void}
* Nothing.
*/
function oncomment(value) {
/** @type {Comment} */
Expand Down Expand Up @@ -364,24 +390,35 @@ export function fromXml(doc) {
}

/**
* Handle CDATA opening.
*
* @returns {void}
* Nothing.
*/
function oncdataopen() {
enter({type: 'cdata', value: ''})
}

/**
* Handle CDATA value.
*
* @param {string} value
* CDATA value.
* @returns {void}
* Nothing.
*/
function oncdatavalue(value) {
// @ts-expect-error: assume literal.
stack[stack.length - 1].value += value
}

/**
* Handle text.
*
* @param {string} value
* Text value.
* @returns {void}
* Nothing.
*/
function ontext(value) {
/** @type {Text} */
Expand Down Expand Up @@ -421,8 +458,12 @@ export function fromXml(doc) {
}

/**
* Handle tag opening.
*
* @param {Tag} value
* SAX tag.
* @returns {void}
* Nothing.
*/
function onopen(value) {
enter({
Expand All @@ -434,8 +475,12 @@ export function fromXml(doc) {
}

/**
* Enter a xast node.
*
* @param {Node} node
* xast node.
* @returns {void}
* Nothing.
*/
function enter(node) {
// @ts-expect-error Set later.
Expand All @@ -447,7 +492,10 @@ export function fromXml(doc) {
}

/**
* Exit a xast node.
*
* @returns {void}
* Nothing.
*/
function exit() {
const tail = stack.pop()
Expand All @@ -458,7 +506,10 @@ export function fromXml(doc) {
}

/**
* Get the current point.
*
* @returns {Point}
* Now.
*/
function now() {
return {
Expand All @@ -469,20 +520,29 @@ export function fromXml(doc) {
}

/**
* Crash.
*
* @param {string} reason
* Reason for crash.
* @param {string} id
* Id of rule.
* @returns {never}
* Never.
*/
function fail(reason, id) {
throw new VFileMessage(reason, now(), 'xast-util-from-xml:' + id)
}
}

/**
* Check if a code is a name start character.
*
* See: <https://www.w3.org/TR/xml/#NT-NameStartChar>
*
* @param {number|null} code
* @param {number | null} code
* Code to check.
* @returns {boolean}
* Whether `code` is a name start character.
*/
function isNameStartChar(code) {
return (
Expand All @@ -495,10 +555,14 @@ function isNameStartChar(code) {
}

/**
* Check if a code is a name continuation character.
*
* See: <https://www.w3.org/TR/xml/#NT-NameChar>
*
* @param {number|null} code
* @param {number | null} code
* Code to check.
* @returns {boolean}
* Whether `code` is a name continuation character.
*/
function isNameChar(code) {
return (
Expand All @@ -510,16 +574,24 @@ function isNameChar(code) {
}

/**
* @param {number|null} code
* Check if a code is whitespace.
*
* @param {number | null} code
* Code to check.
* @returns {boolean}
* Whether `code` is whitespace.
*/
function isSpace(code) {
return code !== null && /[\t\n\r ]/.test(fromCharCode(code))
}

/**
* @param {number|null} code
* Check if a code is a public ID character.
* @param {number | null} code
* Code to check.
* @returns {boolean}
* Whether `code` is a public ID character.
*/
function isPubidChar(code) {
return code !== null && /[\n\r !#$%'-;=?-Z_a-z]/.test(fromCharCode(code))
Expand Down

0 comments on commit 72d8c67

Please sign in to comment.