Я хочу создать плагин babel, который преобразует что-то вроде этого:
class Main extends Component {
__html__ = `
<div>
<span as="count">0</span>
<button as="btn" class="button">Click me</button>
</div>
`
foo() {}
}
Примерно так:
class Main extends Component {
build() {
// Here I manually build that DOM
}
foo() {}
}
По сути, я хочу, чтобы мой плагин принял значение __html__
и из этого я сгенерирую код JavaScript, который будет составлять метод build()
, а затем заменю свойство __html__
этим методом.
Я сгенерирую тело метода в виде строки Я не хочу построить АСТ. Этот код здесь не показан, все, что я хочу знать, это как заменить узел исходной строкой.
Ниже приведено то, что я пока имел в плагине babel, есть более подробное объяснение. и вопросы в комментариях.
module.exports = () => {
return {
visitor: {
Class(path, state) {
if (path.type == 'ClassDeclaration') {
for (node of path.node.body.body) {
let propName = node.key.name;
if (propName == '__html__') {
/*
There seems to be no way of modifying this "node" object here (unless there
is?)
So we pass it to a secondary visitor using path.traverse()
Note that we can't use the secondary visitor on its own because the
@babel/plugin-proposal-class-properties transforms our __html__ property
before we get a chance to (unless there's a way?)
*/
let htmlString = node.value.quasis[0].value.raw;
path.traverse(HtmlClassPropertyVisitor, {htmlString});
}
}
}
}
}
};
};
const HtmlClassPropertyVisitor = {
ClassProperty(path) {
let code = generateHtmlMethod(this.htmlString)
// code is a string that work as a method in an ES6 class, but let's set it to:
code = 'foo() {}'
// Two things I've tried and can't get to work:
// 1. This adds stupid brackets turning my code to
// '(foo() {})'
// (See link below)
// and is apparently not recommended...
path.replaceWithSourceString(code);
// 2. This adds this line before it:
// /* @babel/template */;
// which messes with the class declaration because of the semicolon...
path.replaceWith(babel.template.ast(code));
}
};
Вот бабел, фактически добавляющий квадратные скобки вокруг моего кода:
https://github.com/babel/babel/blob/eac4c5bc17133c2857f2c94c1a6a8643e3b547a7/packages/babel-traverse/src/path/replacement.js#L75