Welcome to the contribution guide, and I hope you are enjoying the grammar. Here you will find out how the grammar is organised and how you can contribute, so that it adheres to the grammar styles.
- You need to know how to use the tree-sitter cli for generating and testing
- Make sure you are familiar with this chapter from tree-sitter especially the functions.
- In-depth knowledge is not necessary unless you are contributing to the core.
The grammar is pretty abstracted, i.e., there are many aliases and hidden rules. However I personally believe it is easy to read and follow. This was intentional so that it is future proof, extensible and maintainable. Thanks to this, there is a 98% chance that the future new directive rules can be added with no more than 6 lines of code!
- Clone this repo
- Install the dependancies:
npm i
- To check if your setup is working, simply run:
npm run test
: This will run the Unit Test to ensure you have not broken functionalitiesnpm run example-test
: This will try to parse alot of common Laravel Method for an automated test drive :)Make sure you have set up your
tree-sitter
'sparser-directories
path correctly in your config file see path
Go ahead open up the grammar.js
in the root directory.
Everything is organized in the order they appear in the document
inside $._definition
. The rules
are then made up like lego using
the "building block" rules that were written at the bottom of the
grammar.js
. As a result, any changes below the 'warning comment'
This is basically what the parser uses as a starting point to read the
blade
document. The following explains the grouping/name convention:
These are the stand-alone directives that can appear anywhere in the document, with NO parameters for example:
@csrf
These are the directives or rules that need their content parsed as
php_only
{{}}
{!! !!}
- ...
Blade attributes, such as:
@class()
@style()
- ...
These are the directives that take on parameters.
@yield()
@extends()
- ...
Names starting with
_
are hiddent when parsing. see tree-sitter
Directive that have start and end directive, with a body
@if() @endif
@error @enderror
- ...
Very unlikely you would need to touch this, but these are loop operators that can appear in any subtree.
@break
@continue
- ...
Integral node, which is used for php_only
injections. This is based
on the $._text
node
This is a general use text node. In this grammar it can be used,
alongside predicates in the injection.scm
to achieve interesting
outcome. Such as injecting normal text
, html
or even shell
. This
is also built on $._text
This should not be used, instead you should opt for $.text
or
$.php_only
if needed
The first thing to do is to determine what category it belongs to.
Look at the $._definition
, pick a rule group, and dig in, to get an
idea.
As an example look below on how the @if
directive is defined:
graph TD;
A($._definition)-->B($._nested_directive)-->C($.conditional)-->D[/Directives\];
D---> E($._if);
D--> G(...);
E --> H($.directive_start) & I($._if_statement_body) & J($.directive_end)
Whenever you define a new rule, you need to test it in two ways:
- You could use the automated parsing to test drive the parser
- You would need to run the following command.
- This will download a few of the Laravel-based repositories and parse the blade files.
npm run test-example
- To ensure your rule is not breaking any other rules, just do the following to run the unit test:
npm run test
If all green you are good to go 👍
Once happy with your result, write the appropriate unit test
in
test/corpus/
. You could either use any of the categories or make
your own.
- Just follow the pull request template and ensure you have completed all necessary steps. 😊"