DEV Community

insidewhy
insidewhy

Posted on

Using ast-grep with a vue project

Motivation

The amazing ast-grep tool does not support vue and scss by default but can be configured to do so.

ast-grep is like a much more powerful version of ripgrep or grep when it comes to searching for patterns within code as it understands the structure of the code (via the library tree-sitter).

For example the following command:

ast-grep -p '<h2>$A</h2>'
Enter fullscreen mode Exit fullscreen mode

Will show all <h2> tags in your html (and also vue files after applying the config from this post). Then the following could change all <h2> tags to <h3> tags interactively (each change will be shown and then y can be used to accept it or n to reject it):

ast-grep -p '<h2>$A</h2>' -r '<h3>$A</h3>' -i
Enter fullscreen mode Exit fullscreen mode

-U can be used instead of -i to apply the changes without asking or neither can be used to view all the changes as a patch.

Configuration

All of the following commands should be run from the root directory of your vue project.

First create a "rules" directory and add it to git. This rules directory must exist for the config to be accepted so for now just create an empty directory (later it's possible to create rules based on ast-grep patterns within this directory to scan/fix things in the code based, think of it like writing an eslint library but much easier).

mkdir ast-rules
touch ast-rules/.keep-dir
git add ast-rules/.keep-dir
Enter fullscreen mode Exit fullscreen mode

Then create a file sgconfig.yml:

ruleDirs:
  - ast-rules

customLanguages:
  vue:
    libraryPath: .tree-sitter/vue.so
    extensions: [vue]
    expandoChar: $
  scss:
    libraryPath: .tree-sitter/scss.so
    extensions: [scss]
    expandoChar: $

languageInjections:
  - hostLanguage: vue
    rule:
      pattern: <template>$CONTENT</template>
    injected: html
  - hostLanguage: vue
    rule:
      pattern: <script $$$ lang="ts" $$$>$CONTENT</script>
    injected: typescript
  - hostLanguage: vue
    rule:
      pattern: <style $$$ lang="scss" $$$>$CONTENT</style>
    injected: scss
Enter fullscreen mode Exit fullscreen mode

Now a script is needed to create the libraries that this ast-grep configuration needs to understand vue and scss files. This could be created at scripts/init-ast-grep-config.sh:

#!/usr/bin/env bash

outdir=$PWD/.tree-sitter/
mkdir $outdir

cd /tmp
git clone https://github.com/tree-sitter-grammars/tree-sitter-vue
cd tree-sitter-vue
pnpm dlx tree-sitter-cli build
cp vue.so $outdir/
cd ..
rm -rf tree-sitter-vue

git clone https://github.com/serenadeai/tree-sitter-scss
cd tree-sitter-scss
pnpm dlx tree-sitter-cli build
cp scss.so $outdir/

cd ..
rm -rf tree-sitter-scss
Enter fullscreen mode Exit fullscreen mode

Then ensure this script is executable:

chmod a+x scripts/init-ast-grep-config.sh
Enter fullscreen mode Exit fullscreen mode

This script stores files within a directory .tree-sitter within the project, since these libraries are binaries they are unique to the platform on which they were compiled so it's probably desirable to add the .tree-sitter directory to .gitignore.

Next add a reference to this script to the scripts section of package.json:

{
  "scripts": {
    "init-ast-grep-config": "./scripts/init-ast-grep-config.sh"
  }
}
Enter fullscreen mode Exit fullscreen mode

Now document this in your readme.md, commit everything to git, and developers on the project can begin using ast-grep on your vue project after running pnpm run init-ast-grep-config.

Top comments (1)

Collapse
 
herrington_darkholme profile image
Herrington Darkholme • Edited

Thanks for sharing! This is very helpful and cool!