@html-validate/plugin-utils
Version:
Plugin utilities and helpers for writing plugins to HTML-Validate
222 lines (217 loc) • 6.91 kB
JavaScript
;
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