UNPKG

@html-validate/plugin-utils

Version:

Plugin utilities and helpers for writing plugins to HTML-Validate

222 lines (217 loc) 6.91 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/entry-cjs.ts var entry_cjs_exports = {}; __export(entry_cjs_exports, { TemplateExtractor: () => TemplateExtractor, positionFromOffset: () => positionFromOffset, positionToOffset: () => positionToOffset }); module.exports = __toCommonJS(entry_cjs_exports); // src/position-from-offset.ts function positionFromOffset(text, offset) { let line = 1; let prev = 0; let pos = text.indexOf("\n"); while (pos !== -1) { if (pos >= offset) { return [line, offset - prev + 1]; } line++; prev = pos + 1; pos = text.indexOf("\n", pos + 1); } return [line, offset - prev + 1]; } // src/position-to-offset.ts function positionToOffset(position, data) { let line = position.line; let column = position.column + 1; for (let i = 0; i < data.length; i++) { if (line > 1) { if (data[i] === "\n") { line--; } } else if (column > 1) { column--; } else { return i; } } throw new Error("Failed to compute location offset from position"); } // src/template-extractor.ts var walk = __toESM(require("acorn-walk")); var espree = __toESM(require("espree")); function joinTemplateLiteral(nodes) { let offset = nodes[0].start + 1; let output = ""; for (const node of nodes) { output += " ".repeat(node.start + 1 - offset); output += node.value.raw; offset = node.end - 2; } return output; } function extractLiteral(node, filename, data) { switch (node.type) { /* ignored nodes */ case "FunctionExpression": case "Identifier": return null; case "Literal": if (typeof node.value !== "string") { return null; } return { data: node.value, filename, line: node.loc.start.line, column: node.loc.start.column + 1, offset: positionToOffset(node.loc.start, data) + 1 }; case "TemplateLiteral": return { data: joinTemplateLiteral(node.quasis), filename, line: node.loc.start.line, column: node.loc.start.column + 1, offset: positionToOffset(node.loc.start, data) + 1 }; case "TaggedTemplateExpression": return { data: joinTemplateLiteral(node.quasi.quasis), filename, line: node.quasi.loc.start.line, column: node.quasi.loc.start.column + 1, offset: positionToOffset(node.quasi.loc.start, data) + 1 }; case "ArrowFunctionExpression": { const whitelist = ["Literal", "TemplateLiteral"]; if (whitelist.includes(node.body.type)) { return extractLiteral(node.body, filename, data); } else { return null; } } /* istanbul ignore next: this only provides a better error, all currently known nodes are tested */ default: { const loc = node.loc.start; const line = String(loc.line); const column = String(loc.column); const context = `${filename}:${line}:${column}`; throw new Error(`Unhandled node type "${node.type}" at "${context}" in extractLiteral`); } } } function compareKey(node, key, filename) { switch (node.type) { case "Identifier": return node.name === key; case "Literal": return node.value === key; /* istanbul ignore next: this only provides a better error, all currently known nodes are tested */ default: { const loc = node.loc.start; const line = String(loc.line); const column = String(loc.column); const context = `${filename}:${line}:${column}`; throw new Error(`Unhandled node type "${node.type}" at "${context}" in compareKey`); } } } var TemplateExtractor = class _TemplateExtractor { ast; filename; data; constructor(ast, filename, data) { this.ast = ast; this.filename = filename; this.data = data; } /** * Create a new [[TemplateExtractor]] from javascript source code. * * `Source` offsets will be relative to the string, i.e. offset 0 is the first * character of the string. If the string is only a subset of a larger string * the offsets must be adjusted manually. * * @param source - Source code. * @param filename - Optional filename to set in the resulting * `Source`. Defauls to `"inline"`. */ static fromString(source, filename) { const ast = espree.parse(source, { ecmaVersion: "latest", sourceType: "module", loc: true }); return new _TemplateExtractor(ast, filename ?? "inline", source); } /** * Extract object properties. * * Given a key `"template"` this method finds all objects literals with a * `"template"` property and creates a [[Source]] instance with proper offsets * with the value of the property. For instance: * * ``` * const myObj = { * foo: 'bar', * }; * ``` * * The above snippet would yield a `Source` with the content `bar`. * */ extractObjectProperty(key) { const result = []; const { filename, data } = this; const node = this.ast; walk.simple(node, { Property(node2) { if (compareKey(node2.key, key, filename)) { const source = extractLiteral(node2.value, filename, data); if (source) { source.filename = filename; result.push(source); } } } }); return result; } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { TemplateExtractor, positionFromOffset, positionToOffset }); //# sourceMappingURL=index.cjs.map