DSL

Synvert provides a simple dsl to define a snippet.

const Synvert = require("synvert-core");

new Synvert.Rewriter("group_name", "snippet_name", () => {
  description "description"

  ifNpm(npm_name, npm_version)

  withinFiles(file_pattern, function () {
    withinNode(rules, () => {
      remove();
    });
  });

  withinFiles(files_pattern, function () {
    withNode(rules, () => {
      unlessExistNode(rules, () => {
        append(code);
      });
    });
  });
});

description

Describe what the snippet does.

description("description of snippet");

ifNode

Checks if current nodejs version is greater than or equal to the specified version.

ifNode("10.0.0")

ifNpm

Checks the npm package version in package-lock.json or yarn.lock, if npm version is less than, greater than or equal to the version in ifNpm, the snippet will be executed, otherwise, the snippet will be ignored.

ifNpm "espree", "= 2.0.0"
ifNpm "espree", "> 2.0.0"
ifNpm "espree", "< 2.0.0"
ifNpm "espree", ">= 2.0.0"
ifNpm "espree", "<= 2.0.0"

withinFile / withinFiles

Find files according to file pattern, the function will be executed only for the matching files.

withinFile("test/utils.js", function () {
  // find nodes
  // check nodes
  // add / replace / remove code
});
withinFiles("test/**/*.spec.js", function () {
  // find nodes
  // check nodes
  // add / replace / remove code
});

withNode / withinNode

Find acorns nodes according to the rules, the function will be executed for the matching nodes.

withNode({ type: "ExpressionStatement", directive: "use strict" }, () => {
  // check nodes
  // add / replace / remove code
});
withNode({ type: "CallExpression", callee: { type: "MemberExpression", property: 'trimLeft' } }, () => {
  // check nodes
  // add / replace / remove code
});

gotoNode

Go to the specified child code.

withNode({ type: "MethodDefinition", key: "handleClick", value: { async: true } }, () => {
  gotoNode("key", () => {
    // change code in method key
  });
});
withNode({ type: "MethodDefinition", key: "handleClick", value: { async: true } }, () => {
  gotoNode("value.body", () => {
    // change code in method value body
  });
});

ifExistNode

Check if the node matches rules exists, if matches, then executes the function.

ifExistNode({ type: 'ExpressionStatement', directive: "use strict" }, () => {
  // add / replace / remove code
});

unlessExistNode

Check if the node matches rules does not exist, if does not match, then executes the function.

unlessExistNode({ type: 'ExpressionStatement', directive: "use strict" }, () => {
  // add / replace / remove code
});

ifOnlyExistNode

Check if the current node contains only one child node and the child node matches rules, if matches, then executes the node.

ifOnlyExistNode({ type: "ExpressionStatement", directive: "use strict" }, () => {
  // add / replace / remove code
});

append

Add the code at the bottom of the current node body.

append("use strict");

prepend

Add the code at the top of the current node body.

prepend("use strict");

insert

Insert the code at the beginning or end of the current node.

insert(",", { at: "end" });
insert("async ", { at: "beginning" });

replaceWith

Replace the current node with the code.


replaceWith("export {{expression.right}}");

replace

Reaplce child node with the code.

replace("callee", { with: "Object.hasOwn" });

remove

Remove the current node.

withNode({ type: "ExpressionStatement", directive: "use strict" }, () => {
  remove();
});

deleteNode

Delete the child nodes

withNode({ type: "MethodDefinition", key: property, value: { async: true } }, function () {
  deleteNode("async");
});

addSnippet

Add other snippet, it’s easy to reuse other snippets.

addSnippet("javascript", "prefer-class-properties");

Check out the source code of DSLs here: this and that