106 lines
4.1 KiB
JavaScript
106 lines
4.1 KiB
JavaScript
import { StaticArrayProcessor } from "./processors/static-array-processor.js";
|
|
export class JSXProcessor {
|
|
types;
|
|
filename;
|
|
staticArrayProcessor;
|
|
constructor(types, filename) {
|
|
this.types = types;
|
|
this.filename = filename;
|
|
this.staticArrayProcessor = new StaticArrayProcessor(types);
|
|
}
|
|
processJSXElement(path) {
|
|
if (this.hasAttribute(path, "data-source-location"))
|
|
return;
|
|
this.addSourceLocationAttribute(path);
|
|
this.addDynamicContentAttribute(path);
|
|
this.addContentEditableAttribute(path);
|
|
this.staticArrayProcessor.process(path);
|
|
}
|
|
addSourceLocationAttribute(path) {
|
|
const { line, column } = path.node.loc?.start || { line: 1, column: 0 };
|
|
const value = `${this.filename}:${line}:${column}`;
|
|
path.node.attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier("data-source-location"), this.types.stringLiteral(value)));
|
|
}
|
|
addDynamicContentAttribute(path) {
|
|
const parentElement = path.parentPath;
|
|
if (!parentElement?.isJSXElement())
|
|
return;
|
|
const isDynamic = this.checkIfElementHasDynamicContent(parentElement.node);
|
|
path.node.attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier("data-dynamic-content"), this.types.stringLiteral(isDynamic ? "true" : "false")));
|
|
}
|
|
addContentEditableAttribute(path) {
|
|
path.node.attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier("content-editable"), this.types.stringLiteral("true")));
|
|
}
|
|
hasAttribute(path, name) {
|
|
return path.node.attributes.some((attr) => this.types.isJSXAttribute(attr) &&
|
|
this.types.isJSXIdentifier(attr.name) &&
|
|
attr.name.name === name);
|
|
}
|
|
checkIfElementHasDynamicContent(jsxElement) {
|
|
let hasDynamicContent = false;
|
|
const checkNode = (node) => {
|
|
if (this.types.isJSXExpressionContainer(node)) {
|
|
const expression = node.expression;
|
|
if (this.types.isJSXEmptyExpression(expression))
|
|
return false;
|
|
if (!this.types.isLiteral(expression))
|
|
return true;
|
|
}
|
|
if (this.types.isTemplateLiteral(node) &&
|
|
node.expressions.length > 0) {
|
|
return true;
|
|
}
|
|
if (this.types.isMemberExpression(node))
|
|
return true;
|
|
if (this.types.isCallExpression(node))
|
|
return true;
|
|
if (this.types.isConditionalExpression(node))
|
|
return true;
|
|
if (this.types.isIdentifier(node)) {
|
|
const dynamicNames = [
|
|
"props",
|
|
"state",
|
|
"data",
|
|
"item",
|
|
"value",
|
|
"text",
|
|
"content",
|
|
];
|
|
if (dynamicNames.some((name) => node.name.includes(name))) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
const traverseNode = (node) => {
|
|
if (hasDynamicContent)
|
|
return;
|
|
if (checkNode(node)) {
|
|
hasDynamicContent = true;
|
|
return;
|
|
}
|
|
for (const key of Object.keys(node)) {
|
|
if (hasDynamicContent)
|
|
return;
|
|
const value = node[key];
|
|
if (Array.isArray(value)) {
|
|
for (const child of value) {
|
|
if (child && typeof child === "object" && "type" in child) {
|
|
traverseNode(child);
|
|
}
|
|
}
|
|
}
|
|
else if (value && typeof value === "object" && "type" in value) {
|
|
traverseNode(value);
|
|
}
|
|
}
|
|
};
|
|
for (const child of jsxElement.children) {
|
|
if (hasDynamicContent)
|
|
break;
|
|
traverseNode(child);
|
|
}
|
|
return hasDynamicContent;
|
|
}
|
|
}
|
|
//# sourceMappingURL=jsx-processor.js.map
|