From a7c23da43606846467e0ae56c2d0db01cfd801fa Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Sun, 25 Apr 2021 11:27:18 -0500 Subject: [PATCH] feat: add estree-util-attach-comments https://github.com/wooorm/estree-util-attach-comments/issues/2 https://github.com/unifiedjs/unified/issues/121 https://github.com/sindresorhus/meta/discussions/15 https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c --- package.json | 1 + vendor/Readme.md | 13 +++ vendor/estree-util-attach-comments.js | 150 ++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 vendor/Readme.md create mode 100644 vendor/estree-util-attach-comments.js diff --git a/package.json b/package.json index 5df00f1..44024d7 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "doctrine": "3.0.0", "eslint": "7.18.0", "espree": "^4", + "estree-util-attach-comments": "^2.0.0", "fs-extra": "9.1.0", "lodash": "4.17.20" }, diff --git a/vendor/Readme.md b/vendor/Readme.md new file mode 100644 index 0000000..669b3f6 --- /dev/null +++ b/vendor/Readme.md @@ -0,0 +1,13 @@ +We cannot use Pure ESM packages (e.g. `estree-util-attach-comments`) because: + +- Node doesn't support mixing `require` and `import`. +- Some people are shipping pure ESM without properly fixing Node. + +This means we should regress to the old days of `vendor` folders. + +See these for more information: + +https://github.com/wooorm/estree-util-attach-comments/issues/2 +https://github.com/unifiedjs/unified/issues/121 +https://github.com/sindresorhus/meta/discussions/15 +https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c diff --git a/vendor/estree-util-attach-comments.js b/vendor/estree-util-attach-comments.js new file mode 100644 index 0000000..098777e --- /dev/null +++ b/vendor/estree-util-attach-comments.js @@ -0,0 +1,150 @@ +"use strict" + +exports.__esModule = true +exports.attachComments = attachComments +var push = [].push +/** + * @typedef {import('estree').BaseNode} EstreeNode + * @typedef {import('estree').Comment} EstreeComment + * + * @typedef State + * @property {EstreeComment[]} comments + * @property {number} index + * + * @typedef Fields + * @property {boolean} leading + * @property {boolean} trailing + */ + +/** + * Attach semistandard estree comment nodes to the tree. + * + * @param {EstreeNode} tree + * @param {EstreeComment[]} [comments] + */ + +function attachComments(tree, comments) { + var list = (comments || []).concat().sort(compare) + if (list.length) + walk(tree, { + comments: list, + index: 0, + }) + return tree +} +/** + * Attach semistandard estree comment nodes to the tree. + * + * @param {EstreeNode} node + * @param {State} state + */ + +function walk(node, state) { + /** @type {EstreeNode[]} */ + var children = [] + /** @type {EstreeComment[]} */ + + var comments = [] + /** @type {string} */ + + var key + /** @type {EstreeNode|EstreeNode[]} */ + + var value + /** @type {number} */ + + var index // Done, we can quit. + + if (state.index === state.comments.length) { + return + } // Find all children of `node` + + for (key in node) { + value = node[key] // Ignore comments. + + if (value && typeof value === "object" && key !== "comments") { + if (Array.isArray(value)) { + index = -1 + + while (++index < value.length) { + if (value[index] && typeof value[index].type === "string") { + children.push(value[index]) + } + } + } else if (typeof value.type === "string") { + children.push(value) + } + } + } // Sort the children. + + children.sort(compare) // Initial comments. + + push.apply( + comments, + slice(state, node, false, { + leading: true, + trailing: false, + }) + ) + index = -1 + + while (++index < children.length) { + walk(children[index], state) + } // Dangling or trailing comments. + + push.apply( + comments, + slice(state, node, true, { + leading: false, + trailing: Boolean(children.length), + }) + ) + + if (comments.length) { + // @ts-ignore, yes, because they’re nonstandard. + node.comments = comments + } +} +/** + * @param {State} state + * @param {EstreeNode} node + * @param {boolean} compareEnd + * @param {Fields} fields + */ + +function slice(state, node, compareEnd, fields) { + /** @type {EstreeComment[]} */ + var result = [] + + while (state.comments[state.index] && compare(state.comments[state.index], node, compareEnd) < 1) { + result.push(Object.assign({}, state.comments[state.index++], fields)) + } + + return result +} +/** + * @param {EstreeNode|EstreeComment} left + * @param {EstreeNode|EstreeComment} right + * @param {boolean} [compareEnd] + * @returns {number} + */ + +function compare(left, right, compareEnd) { + var field = compareEnd ? "end" : "start" // Offsets. + + if (left.range && right.range) { + return left.range[0] - right.range[compareEnd ? 1 : 0] + } // Points. + + if (left.loc && left.loc.start && right.loc && right.loc[field]) { + return left.loc.start.line - right.loc[field].line || left.loc.start.column - right.loc[field].column + } // Just `start` (and `end`) on nodes. + // Default in most parsers. + + if ("start" in left && field in right) { + // @ts-ignore Added by Acorn + return left.start - right[field] + } + + return NaN +}