Как заменить свойство класса необработанным исходным кодом в babel? - PullRequest
0 голосов
/ 13 марта 2020

Я хочу создать плагин 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...