Add .config/helix/.chezmoiignore

Add .config/helix/.gitignore
Add .config/helix/runtime/grammars/.gitkeep
Add .config/helix/runtime/grammars/astro.so
Add .config/helix/runtime/grammars/awk.so
Add .config/helix/runtime/grammars/bash.so
Add .config/helix/runtime/grammars/bass.so
Add .config/helix/runtime/grammars/beancount.so
Add .config/helix/runtime/grammars/bibtex.so
Add .config/helix/runtime/grammars/bicep.so
Add .config/helix/runtime/grammars/blueprint.so
Add .config/helix/runtime/grammars/c-sharp.so
Add .config/helix/runtime/grammars/c.so
Add .config/helix/runtime/grammars/capnp.so
Add .config/helix/runtime/grammars/clojure.so
Add .config/helix/runtime/grammars/cmake.so
Add .config/helix/runtime/grammars/comment.so
Add .config/helix/runtime/grammars/cpon.so
Add .config/helix/runtime/grammars/cpp.so
Add .config/helix/runtime/grammars/css.so
Add .config/helix/runtime/grammars/cue.so
Add .config/helix/runtime/grammars/d.so
Add .config/helix/runtime/grammars/dart.so
Add .config/helix/runtime/grammars/devicetree.so
Add .config/helix/runtime/grammars/dhall.so
Add .config/helix/runtime/grammars/diff.so
Add .config/helix/runtime/grammars/dockerfile.so
Add .config/helix/runtime/grammars/dot.so
Add .config/helix/runtime/grammars/dtd.so
Add .config/helix/runtime/grammars/edoc.so
Add .config/helix/runtime/grammars/eex.so
Add .config/helix/runtime/grammars/elixir.so
Add .config/helix/runtime/grammars/elm.so
Add .config/helix/runtime/grammars/elvish.so
Add .config/helix/runtime/grammars/embedded-template.so
Add .config/helix/runtime/grammars/erlang.so
Add .config/helix/runtime/grammars/esdl.so
Add .config/helix/runtime/grammars/fish.so
Add .config/helix/runtime/grammars/forth.so
Add .config/helix/runtime/grammars/fortran.so
Add .config/helix/runtime/grammars/fsharp.so
Add .config/helix/runtime/grammars/gdscript.so
Add .config/helix/runtime/grammars/git-commit.so
Add .config/helix/runtime/grammars/git-config.so
Add .config/helix/runtime/grammars/git-rebase.so
Add .config/helix/runtime/grammars/gitattributes.so
Add .config/helix/runtime/grammars/gitignore.so
Add .config/helix/runtime/grammars/gleam.so
Add .config/helix/runtime/grammars/glsl.so
Add .config/helix/runtime/grammars/go.so
Add .config/helix/runtime/grammars/godot-resource.so
Add .config/helix/runtime/grammars/gomod.so
Add .config/helix/runtime/grammars/gotmpl.so
Add .config/helix/runtime/grammars/gowork.so
Add .config/helix/runtime/grammars/graphql.so
Add .config/helix/runtime/grammars/hare.so
Add .config/helix/runtime/grammars/haskell-persistent.so
Add .config/helix/runtime/grammars/haskell.so
Add .config/helix/runtime/grammars/hcl.so
Add .config/helix/runtime/grammars/heex.so
Add .config/helix/runtime/grammars/hosts.so
Add .config/helix/runtime/grammars/html.so
Add .config/helix/runtime/grammars/hurl.so
Add .config/helix/runtime/grammars/iex.so
Add .config/helix/runtime/grammars/ini.so
Add .config/helix/runtime/grammars/java.so
Add .config/helix/runtime/grammars/javascript.so
Add .config/helix/runtime/grammars/jinja2.so
Add .config/helix/runtime/grammars/jsdoc.so
Add .config/helix/runtime/grammars/json.so
Add .config/helix/runtime/grammars/jsonnet.so
Add .config/helix/runtime/grammars/julia.so
Add .config/helix/runtime/grammars/just.so
Add .config/helix/runtime/grammars/kdl.so
Add .config/helix/runtime/grammars/kotlin.so
Add .config/helix/runtime/grammars/latex.so
Add .config/helix/runtime/grammars/lean.so
Add .config/helix/runtime/grammars/ledger.so
Add .config/helix/runtime/grammars/llvm-mir.so
Add .config/helix/runtime/grammars/llvm.so
Add .config/helix/runtime/grammars/lua.so
Add .config/helix/runtime/grammars/make.so
Add .config/helix/runtime/grammars/markdoc.so
Add .config/helix/runtime/grammars/markdown.so
Add .config/helix/runtime/grammars/markdown_inline.so
Add .config/helix/runtime/grammars/matlab.so
Add .config/helix/runtime/grammars/mermaid.so
Add .config/helix/runtime/grammars/meson.so
Add .config/helix/runtime/grammars/nasm.so
Add .config/helix/runtime/grammars/nickel.so
Add .config/helix/runtime/grammars/nim.so
Add .config/helix/runtime/grammars/nix.so
Add .config/helix/runtime/grammars/nu.so
Add .config/helix/runtime/grammars/ocaml-interface.so
Add .config/helix/runtime/grammars/ocaml.so
Add .config/helix/runtime/grammars/odin.so
Add .config/helix/runtime/grammars/opencl.so
Add .config/helix/runtime/grammars/openscad.so
Add .config/helix/runtime/grammars/org.so
Add .config/helix/runtime/grammars/pascal.so
Add .config/helix/runtime/grammars/passwd.so
Add .config/helix/runtime/grammars/pem.so
Add .config/helix/runtime/grammars/perl.so
Add .config/helix/runtime/grammars/php.so
Add .config/helix/runtime/grammars/po.so
Add .config/helix/runtime/grammars/pod.so
Add .config/helix/runtime/grammars/ponylang.so
Add .config/helix/runtime/grammars/prisma.so
Add .config/helix/runtime/grammars/protobuf.so
Add .config/helix/runtime/grammars/prql.so
Add .config/helix/runtime/grammars/python.so
Add .config/helix/runtime/grammars/qmljs.so
Add .config/helix/runtime/grammars/r.so
Add .config/helix/runtime/grammars/regex.so
Add .config/helix/runtime/grammars/rego.so
Add .config/helix/runtime/grammars/rescript.so
Add .config/helix/runtime/grammars/robot.so
Add .config/helix/runtime/grammars/rst.so
Add .config/helix/runtime/grammars/ruby.so
Add .config/helix/runtime/grammars/rust.so
Add .config/helix/runtime/grammars/scala.so
Add .config/helix/runtime/grammars/scheme.so
Add .config/helix/runtime/grammars/scss.so
Add .config/helix/runtime/grammars/slint.so
Add .config/helix/runtime/grammars/smithy.so
Add .config/helix/runtime/grammars/sml.so
Add .config/helix/runtime/grammars/solidity.so
Add .config/helix/runtime/grammars/sources/astro/Cargo.toml
Add .config/helix/runtime/grammars/sources/astro/README.md
Add .config/helix/runtime/grammars/sources/astro/binding.gyp
Add .config/helix/runtime/grammars/sources/astro/bindings/node/binding.cc
Add .config/helix/runtime/grammars/sources/astro/bindings/node/index.js
Add .config/helix/runtime/grammars/sources/astro/bindings/rust/build.rs
Add .config/helix/runtime/grammars/sources/astro/bindings/rust/lib.rs
Add .config/helix/runtime/grammars/sources/astro/.gitignore
Add .config/helix/runtime/grammars/sources/astro/flake.lock
Add .config/helix/runtime/grammars/sources/astro/flake.nix
Add .config/helix/runtime/grammars/sources/astro/grammar.js
Add .config/helix/runtime/grammars/sources/astro/package-lock.json
Add .config/helix/runtime/grammars/sources/astro/package.json
Add .config/helix/runtime/grammars/sources/astro/queries/highlights.scm
Add .config/helix/runtime/grammars/sources/astro/queries/injections.scm
Add .config/helix/runtime/grammars/sources/astro/src/grammar.json
Add .config/helix/runtime/grammars/sources/astro/src/node-types.json
Add .config/helix/runtime/grammars/sources/astro/src/parser.c
Add .config/helix/runtime/grammars/sources/astro/src/scanner.cc
Add .config/helix/runtime/grammars/sources/astro/src/tag.h
Add .config/helix/runtime/grammars/sources/astro/src/tree_sitter/parser.h
Add .config/helix/runtime/grammars/sources/astro/test.astro
Add .config/helix/runtime/grammars/sources/astro/test2.astro
Add .config/helix/runtime/grammars/sources/astro/test3.astro
Add .config/helix/runtime/grammars/sources/astro/test4.astro
Add .config/helix/runtime/grammars/sources/astro/test5.astro
Add .config/helix/runtime/grammars/sources/astro/test6.astro
Add .config/helix/runtime/grammars/sources/awk/Cargo.toml
Add .config/helix/runtime/grammars/sources/awk/LICENSE
Add .config/helix/runtime/grammars/sources/awk/README.md
Add .config/helix/runtime/grammars/sources/awk/binding.gyp
Add .config/helix/runtime/grammars/sources/awk/bindings/node/binding.cc
Add .config/helix/runtime/grammars/sources/awk/bindings/node/index.js
Add .config/helix/runtime/grammars/sources/awk/bindings/rust/build.rs
Add .config/helix/runtime/grammars/sources/awk/bindings/rust/lib.rs
Add .config/helix/runtime/grammars/sources/awk/.github/workflows/tests.yml
Add .config/helix/runtime/grammars/sources/awk/.gitignore
Add .config/helix/runtime/grammars/sources/awk/.npmignore
Add .config/helix/runtime/grammars/sources/awk/.prettierrc
Add .config/helix/runtime/grammars/sources/awk/.vscode/launch.json
Add .config/helix/runtime/grammars/sources/awk/examples/example.awk
Add .config/helix/runtime/grammars/sources/awk/grammar.d.ts
Add .config/helix/runtime/grammars/sources/awk/grammar.js
Add .config/helix/runtime/grammars/sources/awk/jsconfig.json
Add .config/helix/runtime/grammars/sources/awk/package.json
Add .config/helix/runtime/grammars/sources/awk/queries/highlights.scm
Add .config/helix/runtime/grammars/sources/awk/scripts/update_highlights_version.sh
Add .config/helix/runtime/grammars/sources/awk/scripts/generate_types.js
Add .config/helix/runtime/grammars/sources/awk/scripts/generate_types_watch.js
Add .config/helix/runtime/grammars/sources/awk/src/grammar.json
Add .config/helix/runtime/grammars/sources/awk/src/node-types.json
Add .config/helix/runtime/grammars/sources/awk/src/parser.c
Add .config/helix/runtime/grammars/sources/awk/src/scanner.c
Add .config/helix/runtime/grammars/sources/awk/src/tree_sitter/parser.h
Add .config/helix/runtime/grammars/sources/awk/test/corpus/crlf.txt
Add .config/helix/runtime/grammars/sources/awk/test/corpus/expression.txt
Add .config/helix/runtime/grammars/sources/awk/test/corpus/function.txt
Add .config/helix/runtime/grammars/sources/awk/test/corpus/pattern.txt
Add .config/helix/runtime/grammars/sources/awk/test/corpus/program.txt
Add .config/helix/runtime/grammars/sources/awk/test/corpus/statement.txt
Add .config/helix/runtime/grammars/sources/awk/yarn.lock
Add .config/helix/runtime/grammars/sources/bash/Cargo.toml
Add .config/helix/runtime/grammars/sources/bash/LICENSE
Add .config/helix/runtime/grammars/sources/bash/.gitattributes
Add .config/helix/runtime/grammars/sources/bash/.github/workflows/ci.yml
Add .config/helix/runtime/grammars/sources/bash/.gitignore
Add .config/helix/runtime/grammars/sources/bash/.gitmodules
Add .config/helix/runtime/grammars/sources/bash/.npmignore
Add .config/helix/runtime/grammars/sources/bash/.travis.yml
Remove .config/helix/runtime
This commit is contained in:
2023-08-23 21:33:06 +02:00
parent 55029adf4e
commit ede75502d9
197 changed files with 113552 additions and 1 deletions

View File

@@ -0,0 +1,26 @@
[package]
name = "tree-sitter-astro"
description = "astro grammar for the tree-sitter parsing library"
version = "0.0.1"
keywords = ["incremental", "parsing", "astro"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-astro"
edition = "2018"
license = "MIT"
build = "bindings/rust/build.rs"
include = [
"bindings/rust/*",
"grammar.js",
"queries/*",
"src/*",
]
[lib]
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter = "~0.20"
[build-dependencies]
cc = "1.0"

View File

@@ -0,0 +1,43 @@
# tree-sitter-astro
Tree-sitter grammar for the Astro web framework.
## Specification
This parser just uses the general idea that the document looks like
<pre><code>---
<i>{typescript}</i>
---
<i>{html}</i>
</pre></code>
and is essentially [tree-sitter-html](https://github.com/tree-sitter/tree-sitter-html) plus two snazzy ways to write `<script>` tags.
## Troubleshooting
### Filetype
Neovim doesn't mark `.astro` files with the Astro filetype by default yet, so nvim-treesitter can't tell that tree-sitter-astro must be used for `.astro` files. Either put
```
autocmd BufRead,BufEnter *.astro set filetype=astro
```
in `~/.config/nvim/ftdetect/astro.vim`, or put
```
vim.filetype.add({
extension = {
astro = "astro"
}
})
```
in `~/.config/nvim/ftdetect/astro.lua`.
### Parser dependencies
If the syntax highlighting doesn't work for embedded CSS/JSX, make sure you have all of the following tree-sitter parsers installed:
- `css` (for CSS in `style` elements)
- `typescript` (for the frontmatter)
- `tsx` (for interpolations)
If it still doesn't work after that, open an issue.

View File

@@ -0,0 +1,19 @@
{
"targets": [
{
"target_name": "tree_sitter_astro_binding",
"include_dirs": [
"<!(node -e \"require('nan')\")",
"src"
],
"sources": [
"bindings/node/binding.cc",
"src/parser.c",
# If your language uses an external scanner, add it here.
],
"cflags_c": [
"-std=c99",
]
}
]
}

View File

@@ -0,0 +1,28 @@
#include "tree_sitter/parser.h"
#include <node.h>
#include "nan.h"
using namespace v8;
extern "C" TSLanguage * tree_sitter_astro();
namespace {
NAN_METHOD(New) {}
void Init(Local<Object> exports, Local<Object> module) {
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Language").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
Nan::SetInternalFieldPointer(instance, 0, tree_sitter_astro());
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("astro").ToLocalChecked());
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
}
NODE_MODULE(tree_sitter_astro_binding, Init)
} // namespace

View File

@@ -0,0 +1,19 @@
try {
module.exports = require("../../build/Release/tree_sitter_astro_binding");
} catch (error1) {
if (error1.code !== 'MODULE_NOT_FOUND') {
throw error1;
}
try {
module.exports = require("../../build/Debug/tree_sitter_astro_binding");
} catch (error2) {
if (error2.code !== 'MODULE_NOT_FOUND') {
throw error2;
}
throw error1
}
}
try {
module.exports.nodeTypeInfo = require("../../src/node-types.json");
} catch (_) {}

View File

@@ -0,0 +1,40 @@
fn main() {
let src_dir = std::path::Path::new("src");
let mut c_config = cc::Build::new();
c_config.include(&src_dir);
c_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable")
.flag_if_supported("-Wno-trigraphs");
let parser_path = src_dir.join("parser.c");
c_config.file(&parser_path);
// If your language uses an external scanner written in C,
// then include this block of code:
/*
let scanner_path = src_dir.join("scanner.c");
c_config.file(&scanner_path);
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
*/
c_config.compile("parser");
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
// If your language uses an external scanner written in C++,
// then include this block of code:
/*
let mut cpp_config = cc::Build::new();
cpp_config.cpp(true);
cpp_config.include(&src_dir);
cpp_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable");
let scanner_path = src_dir.join("scanner.cc");
cpp_config.file(&scanner_path);
cpp_config.compile("scanner");
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
*/
}

View File

@@ -0,0 +1,52 @@
//! This crate provides astro language support for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [language][language func] function to add this language to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! let code = "";
//! let mut parser = tree_sitter::Parser::new();
//! parser.set_language(tree_sitter_astro::language()).expect("Error loading astro grammar");
//! let tree = parser.parse(code, None).unwrap();
//! ```
//!
//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
//! [language func]: fn.language.html
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/
use tree_sitter::Language;
extern "C" {
fn tree_sitter_astro() -> Language;
}
/// Get the tree-sitter [Language][] for this grammar.
///
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
pub fn language() -> Language {
unsafe { tree_sitter_astro() }
}
/// The content of the [`node-types.json`][] file for this grammar.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
// Uncomment these to include any queries that this grammar contains
// pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
#[cfg(test)]
mod tests {
#[test]
fn test_can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(super::language())
.expect("Error loading astro language");
}
}

View File

@@ -0,0 +1,130 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

View File

@@ -0,0 +1,41 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1662096612,
"narHash": "sha256-R+Q8l5JuyJryRPdiIaYpO5O3A55rT+/pItBrKcy7LM4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "21de2b973f9fee595a7a1ac4693efff791245c34",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

View File

@@ -0,0 +1,17 @@
{
description = "Tree-sitter for the Astro SSG";
inputs = {
flake-utils.url = github:numtide/flake-utils;
};
outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
devShell = pkgs.mkShell {
buildInputs = with pkgs; [
tree-sitter
];
};
});
}

View File

@@ -0,0 +1,50 @@
/// <reference types="tree-sitter-cli/dsl" />
const HTML = require('tree-sitter-html/grammar');
module.exports = grammar(HTML, {
name: 'astro',
externals: ($, orig) => [
$._frontmatter_start,
$._interpolation_start,
].concat(orig),
rules: {
fragment: ($, orig) => seq(
optional($.frontmatter),
orig
),
_node: ($, orig) => choice(
$.interpolation,
orig,
),
frontmatter: $ => seq(
alias($._frontmatter_start, '---'),
optional($.raw_text),
'---'
),
attribute: ($, orig) => choice(
orig,
seq(
$.attribute_name,
'=',
$.interpolation
)
),
interpolation: $ => seq(
alias($._interpolation_start, '{'),
optional($.raw_text),
'}'
),
/* Astro doesn't provide any way to escape curly braces apart from
* the standard HTML method of e.g. `&x30;` */
text: $ => /[^<>{}\s]([^<>{}]*[^<>{}\s])?/
}
});

View File

@@ -0,0 +1,65 @@
{
"name": "tree-sitter-astro",
"version": "0.0.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "tree-sitter-astro",
"version": "0.0.1",
"license": "MIT",
"dependencies": {
"nan": "^2.15.0",
"tree-sitter-html": "^0.19.0"
},
"devDependencies": {
"tree-sitter-cli": "^0.20.6"
}
},
"node_modules/nan": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"node_modules/tree-sitter-cli": {
"version": "0.20.6",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.6.tgz",
"integrity": "sha512-tjbAeuGSMhco/EnsThjWkQbDIYMDmdkWsTPsa/NJAW7bjaki9P7oM9TkLxfdlnm4LXd1wR5wVSM2/RTLtZbm6A==",
"dev": true,
"hasInstallScript": true,
"bin": {
"tree-sitter": "cli.js"
}
},
"node_modules/tree-sitter-html": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/tree-sitter-html/-/tree-sitter-html-0.19.0.tgz",
"integrity": "sha512-xH6XGSBWzb4oU/aG6gouMRQKsd96iKuy0zboUqo3wcIWrA++q9a7CmQTSeIINiSfOXjT2ZLJciXFDgAh6h04Bw==",
"hasInstallScript": true,
"dependencies": {
"nan": "^2.14.0"
}
}
},
"dependencies": {
"nan": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"tree-sitter-cli": {
"version": "0.20.6",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.6.tgz",
"integrity": "sha512-tjbAeuGSMhco/EnsThjWkQbDIYMDmdkWsTPsa/NJAW7bjaki9P7oM9TkLxfdlnm4LXd1wR5wVSM2/RTLtZbm6A==",
"dev": true
},
"tree-sitter-html": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/tree-sitter-html/-/tree-sitter-html-0.19.0.tgz",
"integrity": "sha512-xH6XGSBWzb4oU/aG6gouMRQKsd96iKuy0zboUqo3wcIWrA++q9a7CmQTSeIINiSfOXjT2ZLJciXFDgAh6h04Bw==",
"requires": {
"nan": "^2.14.0"
}
}
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "tree-sitter-astro",
"version": "0.0.1",
"description": "Tree-sitter grammar for the Astro framework",
"main": "bindings/node",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/virchau13/tree-sitter-astro.git"
},
"author": "virchau13",
"license": "MIT",
"bugs": {
"url": "https://github.com/virchau13/tree-sitter-astro/issues"
},
"homepage": "https://github.com/virchau13/tree-sitter-astro#readme",
"devDependencies": {
"tree-sitter-cli": "^0.20.6"
},
"dependencies": {
"nan": "^2.15.0",
"tree-sitter-html": "^0.19.0"
},
"tree-sitter": [
{
"scope": "source.astro",
"file-types": [
"astro"
]
}
]
}

View File

@@ -0,0 +1,12 @@
(tag_name) @tag
(erroneous_end_tag_name) @tag.error
(doctype) @constant
(attribute_name) @attribute
(attribute_value) @string
(comment) @comment
[
"<"
">"
"</"
] @punctuation.bracket

View File

@@ -0,0 +1,15 @@
((script_element
(raw_text) @injection.content)
(#set! injection.language "javascript"))
((style_element
(raw_text) @injection.content)
(#set! injection.language "css"))
((frontmatter
(raw_text) @injection.content)
(#set! injection.language "typescript"))
((interpolation
(raw_text) @injection.content)
(#set! injection.language "tsx"))

View File

@@ -0,0 +1,609 @@
{
"name": "astro",
"rules": {
"fragment": {
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "frontmatter"
},
{
"type": "BLANK"
}
]
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "_node"
}
}
]
},
"doctype": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "<!"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_doctype"
},
"named": false,
"value": "doctype"
},
{
"type": "PATTERN",
"value": "[^>]+"
},
{
"type": "STRING",
"value": ">"
}
]
},
"_doctype": {
"type": "PATTERN",
"value": "[Dd][Oo][Cc][Tt][Yy][Pp][Ee]"
},
"_node": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "interpolation"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "doctype"
},
{
"type": "SYMBOL",
"name": "text"
},
{
"type": "SYMBOL",
"name": "element"
},
{
"type": "SYMBOL",
"name": "script_element"
},
{
"type": "SYMBOL",
"name": "style_element"
},
{
"type": "SYMBOL",
"name": "erroneous_end_tag"
}
]
}
]
},
"element": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "start_tag"
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "_node"
}
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "end_tag"
},
{
"type": "SYMBOL",
"name": "_implicit_end_tag"
}
]
}
]
},
{
"type": "SYMBOL",
"name": "self_closing_tag"
}
]
},
"script_element": {
"type": "SEQ",
"members": [
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "script_start_tag"
},
"named": true,
"value": "start_tag"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "raw_text"
},
{
"type": "BLANK"
}
]
},
{
"type": "SYMBOL",
"name": "end_tag"
}
]
},
"style_element": {
"type": "SEQ",
"members": [
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "style_start_tag"
},
"named": true,
"value": "start_tag"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "raw_text"
},
{
"type": "BLANK"
}
]
},
{
"type": "SYMBOL",
"name": "end_tag"
}
]
},
"start_tag": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "<"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_start_tag_name"
},
"named": true,
"value": "tag_name"
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "attribute"
}
},
{
"type": "STRING",
"value": ">"
}
]
},
"script_start_tag": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "<"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_script_start_tag_name"
},
"named": true,
"value": "tag_name"
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "attribute"
}
},
{
"type": "STRING",
"value": ">"
}
]
},
"style_start_tag": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "<"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_style_start_tag_name"
},
"named": true,
"value": "tag_name"
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "attribute"
}
},
{
"type": "STRING",
"value": ">"
}
]
},
"self_closing_tag": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "<"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_start_tag_name"
},
"named": true,
"value": "tag_name"
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "attribute"
}
},
{
"type": "STRING",
"value": "/>"
}
]
},
"end_tag": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "</"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_end_tag_name"
},
"named": true,
"value": "tag_name"
},
{
"type": "STRING",
"value": ">"
}
]
},
"erroneous_end_tag": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "</"
},
{
"type": "SYMBOL",
"name": "erroneous_end_tag_name"
},
{
"type": "STRING",
"value": ">"
}
]
},
"attribute": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "attribute_name"
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "="
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "attribute_value"
},
{
"type": "SYMBOL",
"name": "quoted_attribute_value"
}
]
}
]
},
{
"type": "BLANK"
}
]
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "attribute_name"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "interpolation"
}
]
}
]
},
"attribute_name": {
"type": "PATTERN",
"value": "[^<>\"'/=\\s]+"
},
"attribute_value": {
"type": "PATTERN",
"value": "[^<>\"'=\\s]+"
},
"quoted_attribute_value": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "'"
},
{
"type": "CHOICE",
"members": [
{
"type": "ALIAS",
"content": {
"type": "PATTERN",
"value": "[^']+"
},
"named": true,
"value": "attribute_value"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "'"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "\""
},
{
"type": "CHOICE",
"members": [
{
"type": "ALIAS",
"content": {
"type": "PATTERN",
"value": "[^\"]+"
},
"named": true,
"value": "attribute_value"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "\""
}
]
}
]
},
"text": {
"type": "PATTERN",
"value": "[^<>{}\\s]([^<>{}]*[^<>{}\\s])?"
},
"frontmatter": {
"type": "SEQ",
"members": [
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_frontmatter_start"
},
"named": false,
"value": "---"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "raw_text"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "---"
}
]
},
"interpolation": {
"type": "SEQ",
"members": [
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_interpolation_start"
},
"named": false,
"value": "{"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "raw_text"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "}"
}
]
}
},
"extras": [
{
"type": "SYMBOL",
"name": "comment"
},
{
"type": "PATTERN",
"value": "\\s+"
}
],
"conflicts": [],
"precedences": [],
"externals": [
{
"type": "SYMBOL",
"name": "_frontmatter_start"
},
{
"type": "SYMBOL",
"name": "_interpolation_start"
},
{
"type": "SYMBOL",
"name": "_start_tag_name"
},
{
"type": "SYMBOL",
"name": "_script_start_tag_name"
},
{
"type": "SYMBOL",
"name": "_style_start_tag_name"
},
{
"type": "SYMBOL",
"name": "_end_tag_name"
},
{
"type": "SYMBOL",
"name": "erroneous_end_tag_name"
},
{
"type": "STRING",
"value": "/>"
},
{
"type": "SYMBOL",
"name": "_implicit_end_tag"
},
{
"type": "SYMBOL",
"name": "raw_text"
},
{
"type": "SYMBOL",
"name": "comment"
}
],
"inline": [],
"supertypes": []
}

View File

@@ -0,0 +1,363 @@
[
{
"type": "attribute",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "attribute_name",
"named": true
},
{
"type": "attribute_value",
"named": true
},
{
"type": "interpolation",
"named": true
},
{
"type": "quoted_attribute_value",
"named": true
}
]
}
},
{
"type": "doctype",
"named": true,
"fields": {}
},
{
"type": "element",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "doctype",
"named": true
},
{
"type": "element",
"named": true
},
{
"type": "end_tag",
"named": true
},
{
"type": "erroneous_end_tag",
"named": true
},
{
"type": "interpolation",
"named": true
},
{
"type": "script_element",
"named": true
},
{
"type": "self_closing_tag",
"named": true
},
{
"type": "start_tag",
"named": true
},
{
"type": "style_element",
"named": true
},
{
"type": "text",
"named": true
}
]
}
},
{
"type": "end_tag",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "tag_name",
"named": true
}
]
}
},
{
"type": "erroneous_end_tag",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "erroneous_end_tag_name",
"named": true
}
]
}
},
{
"type": "fragment",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "doctype",
"named": true
},
{
"type": "element",
"named": true
},
{
"type": "erroneous_end_tag",
"named": true
},
{
"type": "frontmatter",
"named": true
},
{
"type": "interpolation",
"named": true
},
{
"type": "script_element",
"named": true
},
{
"type": "style_element",
"named": true
},
{
"type": "text",
"named": true
}
]
}
},
{
"type": "frontmatter",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": false,
"types": [
{
"type": "raw_text",
"named": true
}
]
}
},
{
"type": "interpolation",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": false,
"types": [
{
"type": "raw_text",
"named": true
}
]
}
},
{
"type": "quoted_attribute_value",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": false,
"types": [
{
"type": "attribute_value",
"named": true
}
]
}
},
{
"type": "script_element",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "end_tag",
"named": true
},
{
"type": "raw_text",
"named": true
},
{
"type": "start_tag",
"named": true
}
]
}
},
{
"type": "self_closing_tag",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "attribute",
"named": true
},
{
"type": "tag_name",
"named": true
}
]
}
},
{
"type": "start_tag",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "attribute",
"named": true
},
{
"type": "tag_name",
"named": true
}
]
}
},
{
"type": "style_element",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "end_tag",
"named": true
},
{
"type": "raw_text",
"named": true
},
{
"type": "start_tag",
"named": true
}
]
}
},
{
"type": "\"",
"named": false
},
{
"type": "'",
"named": false
},
{
"type": "---",
"named": false
},
{
"type": "/>",
"named": false
},
{
"type": "<",
"named": false
},
{
"type": "<!",
"named": false
},
{
"type": "</",
"named": false
},
{
"type": "=",
"named": false
},
{
"type": ">",
"named": false
},
{
"type": "attribute_name",
"named": true
},
{
"type": "attribute_value",
"named": true
},
{
"type": "comment",
"named": true
},
{
"type": "doctype",
"named": false
},
{
"type": "erroneous_end_tag_name",
"named": true
},
{
"type": "raw_text",
"named": true
},
{
"type": "tag_name",
"named": true
},
{
"type": "text",
"named": true
},
{
"type": "{",
"named": false
},
{
"type": "}",
"named": false
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,442 @@
#include <tree_sitter/parser.h>
#include <algorithm>
#include <vector>
#include <string>
#include <cwctype>
#include <cstring>
#include "tag.h"
namespace {
using std::vector;
using std::string;
enum TokenType {
FRONTMATTER_START,
INTERPOLATION_START,
START_TAG_NAME,
SCRIPT_START_TAG_NAME,
STYLE_START_TAG_NAME,
END_TAG_NAME,
ERRONEOUS_END_TAG_NAME,
SELF_CLOSING_TAG_DELIMITER,
IMPLICIT_END_TAG,
RAW_TEXT,
COMMENT
};
struct Scanner {
Scanner() {}
unsigned serialize(char *buffer) {
uint16_t tag_count = tags.size() > UINT16_MAX ? UINT16_MAX : tags.size();
uint16_t serialized_tag_count = 0;
unsigned i = sizeof(tag_count);
std::memcpy(&buffer[i], &tag_count, sizeof(tag_count));
i += sizeof(tag_count);
for (; serialized_tag_count < tag_count; serialized_tag_count++) {
Tag &tag = tags[serialized_tag_count];
if (tag.type == CUSTOM) {
unsigned name_length = tag.custom_tag_name.size();
if (name_length > UINT8_MAX) name_length = UINT8_MAX;
if (i + 2 + name_length >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) break;
buffer[i++] = static_cast<char>(tag.type);
buffer[i++] = name_length;
tag.custom_tag_name.copy(&buffer[i], name_length);
i += name_length;
} else {
if (i + 1 >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) break;
buffer[i++] = static_cast<char>(tag.type);
}
}
std::memcpy(&buffer[0], &serialized_tag_count, sizeof(serialized_tag_count));
return i;
}
void deserialize(const char *buffer, unsigned length) {
tags.clear();
if (length > 0) {
unsigned i = 0;
uint16_t tag_count, serialized_tag_count;
std::memcpy(&serialized_tag_count, &buffer[i], sizeof(serialized_tag_count));
i += sizeof(serialized_tag_count);
std::memcpy(&tag_count, &buffer[i], sizeof(tag_count));
i += sizeof(tag_count);
tags.resize(tag_count);
for (unsigned j = 0; j < serialized_tag_count; j++) {
Tag &tag = tags[j];
tag.type = static_cast<TagType>(buffer[i++]);
if (tag.type == CUSTOM) {
uint16_t name_length = static_cast<uint8_t>(buffer[i++]);
tag.custom_tag_name.assign(&buffer[i], &buffer[i + name_length]);
i += name_length;
}
}
}
}
string scan_tag_name(TSLexer *lexer) {
string tag_name;
while (iswalnum(lexer->lookahead) ||
lexer->lookahead == '-' ||
lexer->lookahead == ':') {
tag_name += lexer->lookahead;
lexer->advance(lexer, false);
}
return tag_name;
}
bool scan_comment(TSLexer *lexer) {
if (lexer->lookahead != '-') return false;
lexer->advance(lexer, false);
if (lexer->lookahead != '-') return false;
lexer->advance(lexer, false);
unsigned dashes = 0;
while (lexer->lookahead) {
switch (lexer->lookahead) {
case '-':
++dashes;
break;
case '>':
if (dashes >= 2) {
lexer->result_symbol = COMMENT;
lexer->advance(lexer, false);
lexer->mark_end(lexer);
return true;
}
default:
dashes = 0;
}
lexer->advance(lexer, false);
}
return false;
}
inline void scan_js_backtick_string(TSLexer *lexer) {
// Advance past backtick
lexer->advance(lexer, false);
while(lexer->lookahead) {
if(lexer->lookahead == '$') {
lexer->advance(lexer, false);
if(lexer->lookahead == '{') {
// String interpolation
lexer->advance(lexer, false);
scan_js_expr(lexer, "}");
// Advance past the final curly
} else {
// Reprocess this character
continue;
}
} else if(lexer->lookahead == '`') {
// End of string
lexer->advance(lexer, false);
break;
}
lexer->advance(lexer, false);
}
}
inline void scan_js_string(TSLexer *lexer) {
// Assumes the lookahead char is actually valid
if (lexer->lookahead == '`') {
scan_js_backtick_string(lexer);
} else {
char str_type = lexer->lookahead;
lexer->advance(lexer, false);
while (lexer->lookahead) {
// Note that this doesn't take into account newlines in basic strings,
// for the same reason why tree-sitter-javascript doesn't.
// https://github.com/tree-sitter/tree-sitter-javascript/blob/fdeb68ac8d2bd5a78b943528bb68ceda3aade2eb/grammar.js#L860
if (lexer->lookahead == '\\') {
// Accept any next char
lexer->advance(lexer, false);
} else if (lexer->lookahead == str_type) {
// End of string
lexer->advance(lexer, false);
return;
}
lexer->advance(lexer, false);
}
}
}
inline void scan_js_expr(TSLexer *lexer, const string& end) {
lexer->mark_end(lexer);
unsigned delimiter_index = 0;
unsigned curly_count = 0;
// Inject an extra newline at the start,
// so in the case of empty JS frontmatter
// where tree-sitter steals the extra newline
// it still parses correctly
// (Yes, I know, I know...)
if(end == "\n---") delimiter_index = 1;
while (lexer->lookahead) {
if(lexer->lookahead == '"' || lexer->lookahead == '\'' || lexer->lookahead == '`') {
scan_js_string(lexer);
lexer->mark_end(lexer);
continue;
}
if(end == "}") {
// we have to balance braces
if(lexer->lookahead == '{') {
curly_count++;
lexer->advance(lexer, false);
continue;
} else if (lexer->lookahead == '}') {
if(curly_count == 0) {
// This should get caught by the delimiter check,
// don't do anything
} else {
curly_count--;
lexer->advance(lexer, false);
continue;
}
}
}
if (lexer->lookahead == end[delimiter_index]) {
delimiter_index++;
if (delimiter_index == end.size()) break;
lexer->advance(lexer, false);
} else {
delimiter_index = 0;
lexer->advance(lexer, false);
lexer->mark_end(lexer);
}
}
}
bool scan_raw_text(TSLexer *lexer) {
if (tags.empty()) {
scan_js_expr(lexer, "\n---");
goto finish;
}
if (tags.back().type == INTERPOLATION) {
scan_js_expr(lexer, "}");
tags.pop_back();
goto finish;
}
{
if (tags.back().type != SCRIPT && tags.back().type != STYLE) return false;
lexer->mark_end(lexer);
const string &end_delimiter =
tags.back().type == SCRIPT ? "</SCRIPT"
/* back().type == STYLE */ : "</STYLE";
unsigned delimiter_index = 0;
while (lexer->lookahead) {
if (towupper(lexer->lookahead) == end_delimiter[delimiter_index]) {
delimiter_index++;
if (delimiter_index == end_delimiter.size()) break;
lexer->advance(lexer, false);
} else {
delimiter_index = 0;
lexer->advance(lexer, false);
lexer->mark_end(lexer);
}
}
}
finish:
lexer->result_symbol = RAW_TEXT;
return true;
}
bool scan_implicit_end_tag(TSLexer *lexer) {
Tag *parent = tags.empty() ? NULL : &tags.back();
bool is_closing_tag = false;
if (lexer->lookahead == '/') {
is_closing_tag = true;
lexer->advance(lexer, false);
} else {
if (parent && parent->is_void()) {
tags.pop_back();
lexer->result_symbol = IMPLICIT_END_TAG;
return true;
}
}
string tag_name = scan_tag_name(lexer);
if (tag_name.empty()) return false;
Tag next_tag = Tag::for_name(tag_name);
if (is_closing_tag) {
// The tag correctly closes the topmost element on the stack
if (!tags.empty() && tags.back() == next_tag) return false;
// Otherwise, dig deeper and queue implicit end tags (to be nice in
// the case of malformed HTML)
if (std::find(tags.begin(), tags.end(), next_tag) != tags.end()) {
tags.pop_back();
lexer->result_symbol = IMPLICIT_END_TAG;
return true;
}
} else if (parent && !parent->can_contain(next_tag)) {
tags.pop_back();
lexer->result_symbol = IMPLICIT_END_TAG;
return true;
}
return false;
}
bool scan_start_tag_name(TSLexer *lexer) {
string tag_name = scan_tag_name(lexer);
if (tag_name.empty()) return false;
Tag tag = Tag::for_name(tag_name);
tags.push_back(tag);
switch (tag.type) {
case SCRIPT:
lexer->result_symbol = SCRIPT_START_TAG_NAME;
break;
case STYLE:
lexer->result_symbol = STYLE_START_TAG_NAME;
break;
default:
lexer->result_symbol = START_TAG_NAME;
break;
}
return true;
}
bool scan_end_tag_name(TSLexer *lexer) {
string tag_name = scan_tag_name(lexer);
if (tag_name.empty()) return false;
Tag tag = Tag::for_name(tag_name);
if (!tags.empty() && tags.back() == tag) {
tags.pop_back();
lexer->result_symbol = END_TAG_NAME;
} else {
lexer->result_symbol = ERRONEOUS_END_TAG_NAME;
}
return true;
}
bool scan_self_closing_tag_delimiter(TSLexer *lexer) {
lexer->advance(lexer, false);
if (lexer->lookahead == '>') {
lexer->advance(lexer, false);
if (!tags.empty()) {
tags.pop_back();
lexer->result_symbol = SELF_CLOSING_TAG_DELIMITER;
}
return true;
}
return false;
}
bool scan(TSLexer *lexer, const bool *valid_symbols) {
while (iswspace(lexer->lookahead)) {
lexer->advance(lexer, true);
}
if (valid_symbols[RAW_TEXT] && !valid_symbols[START_TAG_NAME] && !valid_symbols[END_TAG_NAME]) {
return scan_raw_text(lexer);
}
switch (lexer->lookahead) {
case '<':
lexer->mark_end(lexer);
lexer->advance(lexer, false);
if (lexer->lookahead == '!') {
lexer->advance(lexer, false);
return scan_comment(lexer);
}
if (valid_symbols[IMPLICIT_END_TAG]) {
return scan_implicit_end_tag(lexer);
}
break;
case '\0':
if (valid_symbols[IMPLICIT_END_TAG]) {
return scan_implicit_end_tag(lexer);
}
break;
case '/':
if (valid_symbols[SELF_CLOSING_TAG_DELIMITER]) {
return scan_self_closing_tag_delimiter(lexer);
}
break;
case '{':
if (valid_symbols[INTERPOLATION_START]) {
lexer->advance(lexer, false);
tags.push_back(Tag(INTERPOLATION, string()));
lexer->result_symbol = INTERPOLATION_START;
return true;
}
break;
case '-':
if (valid_symbols[FRONTMATTER_START]) {
lexer->mark_end(lexer);
lexer->advance(lexer, false);
if(lexer->lookahead == '-') {
lexer->advance(lexer, false);
if(lexer->lookahead == '-') {
lexer->advance(lexer, false);
lexer->mark_end(lexer);
lexer->result_symbol = FRONTMATTER_START;
return true;
}
}
}
/* otherwise, no token matched */
/* so fallthrough to default case */
default:
if ((valid_symbols[START_TAG_NAME] || valid_symbols[END_TAG_NAME]) && !valid_symbols[RAW_TEXT]) {
return valid_symbols[START_TAG_NAME]
? scan_start_tag_name(lexer)
: scan_end_tag_name(lexer);
}
}
return false;
}
vector<Tag> tags;
};
}
extern "C" {
void *tree_sitter_astro_external_scanner_create() {
return new Scanner();
}
bool tree_sitter_astro_external_scanner_scan(void *payload, TSLexer *lexer,
const bool *valid_symbols) {
Scanner *scanner = static_cast<Scanner *>(payload);
return scanner->scan(lexer, valid_symbols);
}
unsigned tree_sitter_astro_external_scanner_serialize(void *payload, char *buffer) {
Scanner *scanner = static_cast<Scanner *>(payload);
return scanner->serialize(buffer);
}
void tree_sitter_astro_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
Scanner *scanner = static_cast<Scanner *>(payload);
scanner->deserialize(buffer, length);
}
void tree_sitter_astro_external_scanner_destroy(void *payload) {
Scanner *scanner = static_cast<Scanner *>(payload);
delete scanner;
}
}

View File

@@ -0,0 +1,394 @@
#include <string>
#include <map>
using std::string;
using std::map;
enum TagType {
AREA,
BASE,
BASEFONT,
BGSOUND,
BR,
COL,
COMMAND,
EMBED,
FRAME,
HR,
IMAGE,
IMG,
INPUT,
ISINDEX,
KEYGEN,
LINK,
MENUITEM,
META,
NEXTID,
PARAM,
SOURCE,
TRACK,
WBR,
END_OF_VOID_TAGS,
A,
ABBR,
ADDRESS,
ARTICLE,
ASIDE,
AUDIO,
B,
BDI,
BDO,
BLOCKQUOTE,
BODY,
BUTTON,
CANVAS,
CAPTION,
CITE,
CODE,
COLGROUP,
DATA,
DATALIST,
DD,
DEL,
DETAILS,
DFN,
DIALOG,
DIV,
DL,
DT,
EM,
FIELDSET,
FIGCAPTION,
FIGURE,
FOOTER,
FORM,
H1,
H2,
H3,
H4,
H5,
H6,
HEAD,
HEADER,
HGROUP,
HTML,
I,
IFRAME,
INS,
KBD,
LABEL,
LEGEND,
LI,
MAIN,
MAP,
MARK,
MATH,
MENU,
METER,
NAV,
NOSCRIPT,
OBJECT,
OL,
OPTGROUP,
OPTION,
OUTPUT,
P,
PICTURE,
PRE,
PROGRESS,
Q,
RB,
RP,
RT,
RTC,
RUBY,
S,
SAMP,
SCRIPT,
SECTION,
SELECT,
SLOT,
SMALL,
SPAN,
STRONG,
STYLE,
SUB,
SUMMARY,
SUP,
SVG,
TABLE,
TBODY,
TD,
TEMPLATE,
TEXTAREA,
TFOOT,
TH,
THEAD,
TIME,
TITLE,
TR,
U,
UL,
VAR,
VIDEO,
// Technically not a 'tag' as such, but rather Astro's curly brace interpolations.
INTERPOLATION,
CUSTOM,
};
static const std::string toLower(std::string str) {
for(char &a: str) {
a = std::tolower(a);
}
return str;
}
static const map<string, TagType> get_tag_map() {
map<string, TagType> result;
#define TAG(name) result[toLower(#name)] = name
TAG(AREA);
TAG(BASE);
TAG(BASEFONT);
TAG(BGSOUND);
TAG(BR);
TAG(COL);
TAG(COMMAND);
TAG(EMBED);
TAG(FRAME);
TAG(HR);
TAG(IMAGE);
TAG(IMG);
TAG(INPUT);
TAG(ISINDEX);
TAG(KEYGEN);
TAG(LINK);
TAG(MENUITEM);
TAG(META);
TAG(NEXTID);
TAG(PARAM);
TAG(SOURCE);
TAG(TRACK);
TAG(WBR);
TAG(A);
TAG(ABBR);
TAG(ADDRESS);
TAG(ARTICLE);
TAG(ASIDE);
TAG(AUDIO);
TAG(B);
TAG(BDI);
TAG(BDO);
TAG(BLOCKQUOTE);
TAG(BODY);
TAG(BUTTON);
TAG(CANVAS);
TAG(CAPTION);
TAG(CITE);
TAG(CODE);
TAG(COLGROUP);
TAG(DATA);
TAG(DATALIST);
TAG(DD);
TAG(DEL);
TAG(DETAILS);
TAG(DFN);
TAG(DIALOG);
TAG(DIV);
TAG(DL);
TAG(DT);
TAG(EM);
TAG(FIELDSET);
TAG(FIGCAPTION);
TAG(FIGURE);
TAG(FOOTER);
TAG(FORM);
TAG(H1);
TAG(H2);
TAG(H3);
TAG(H4);
TAG(H5);
TAG(H6);
TAG(HEAD);
TAG(HEADER);
TAG(HGROUP);
TAG(HTML);
TAG(I);
TAG(IFRAME);
TAG(INS);
TAG(KBD);
TAG(LABEL);
TAG(LEGEND);
TAG(LI);
TAG(MAIN);
TAG(MAP);
TAG(MARK);
TAG(MATH);
TAG(MENU);
TAG(METER);
TAG(NAV);
TAG(NOSCRIPT);
TAG(OBJECT);
TAG(OL);
TAG(OPTGROUP);
TAG(OPTION);
TAG(OUTPUT);
TAG(P);
TAG(PICTURE);
TAG(PRE);
TAG(PROGRESS);
TAG(Q);
TAG(RB);
TAG(RP);
TAG(RT);
TAG(RTC);
TAG(RUBY);
TAG(S);
TAG(SAMP);
TAG(SCRIPT);
TAG(SECTION);
TAG(SELECT);
TAG(SLOT);
TAG(SMALL);
TAG(SPAN);
TAG(STRONG);
TAG(STYLE);
TAG(SUB);
TAG(SUMMARY);
TAG(SUP);
TAG(SVG);
TAG(TABLE);
TAG(TBODY);
TAG(TD);
TAG(TEMPLATE);
TAG(TEXTAREA);
TAG(TFOOT);
TAG(TH);
TAG(THEAD);
TAG(TIME);
TAG(TITLE);
TAG(TR);
TAG(U);
TAG(UL);
TAG(VAR);
TAG(VIDEO);
// INTERPOLATION is deliberately excluded from this list.
#undef TAG
return result;
}
static const map<string, TagType> TAG_TYPES_BY_TAG_NAME = get_tag_map();
static const TagType TAG_TYPES_NOT_ALLOWED_IN_PARAGRAPHS[] = {
ADDRESS,
ARTICLE,
ASIDE,
BLOCKQUOTE,
DETAILS,
DIV,
DL,
FIELDSET,
FIGCAPTION,
FIGURE,
FOOTER,
FORM,
H1,
H2,
H3,
H4,
H5,
H6,
HEADER,
HR,
MAIN,
NAV,
OL,
P,
PRE,
SECTION,
};
static const TagType *TAG_TYPES_NOT_ALLOWED_IN_PARAGRAPHS_END = (
TAG_TYPES_NOT_ALLOWED_IN_PARAGRAPHS +
sizeof(TAG_TYPES_NOT_ALLOWED_IN_PARAGRAPHS) /
sizeof(TagType)
);
struct Tag {
TagType type;
string custom_tag_name;
// This default constructor is used in the case where there is not enough space
// in the serialization buffer to store all of the tags. In that case, tags
// that cannot be serialized will be treated as having an unknown type. These
// tags will be closed via implicit end tags regardless of the next closing
// tag is encountered.
Tag() : type(END_OF_VOID_TAGS) {}
Tag(TagType type, const string &name) : type(type), custom_tag_name(name) {}
bool operator==(const Tag &other) const {
if (type != other.type) return false;
if (type == CUSTOM && custom_tag_name != other.custom_tag_name) return false;
return true;
}
inline bool is_void() const {
return type < END_OF_VOID_TAGS;
}
inline bool can_contain(const Tag &tag) {
TagType child = tag.type;
if(child == INTERPOLATION) {
// can be contained anywhere
return true;
}
switch (type) {
case LI: return child != LI;
case DT:
case DD:
return child != DT && child != DD;
case P:
return std::find(
TAG_TYPES_NOT_ALLOWED_IN_PARAGRAPHS,
TAG_TYPES_NOT_ALLOWED_IN_PARAGRAPHS_END,
tag.type
) == TAG_TYPES_NOT_ALLOWED_IN_PARAGRAPHS_END;
case COLGROUP:
return child == COL;
case RB:
case RT:
case RP:
return child != RB && child != RT && child != RP;
case OPTGROUP:
return child != OPTGROUP;
case TR:
return child != TR;
case TD:
case TH:
return child != TD && child != TH && child != TR;
default:
return true;
}
}
static inline Tag for_name(const string &name) {
map<string, TagType>::const_iterator type = TAG_TYPES_BY_TAG_NAME.find(name);
if (type != TAG_TYPES_BY_TAG_NAME.end()) {
return Tag(type->second, string());
} else {
return Tag(CUSTOM, name);
}
}
};

View File

@@ -0,0 +1,224 @@
#ifndef TREE_SITTER_PARSER_H_
#define TREE_SITTER_PARSER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define ts_builtin_sym_error ((TSSymbol)-1)
#define ts_builtin_sym_end 0
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
typedef uint16_t TSStateId;
#ifndef TREE_SITTER_API_H_
typedef uint16_t TSSymbol;
typedef uint16_t TSFieldId;
typedef struct TSLanguage TSLanguage;
#endif
typedef struct {
TSFieldId field_id;
uint8_t child_index;
bool inherited;
} TSFieldMapEntry;
typedef struct {
uint16_t index;
uint16_t length;
} TSFieldMapSlice;
typedef struct {
bool visible;
bool named;
bool supertype;
} TSSymbolMetadata;
typedef struct TSLexer TSLexer;
struct TSLexer {
int32_t lookahead;
TSSymbol result_symbol;
void (*advance)(TSLexer *, bool);
void (*mark_end)(TSLexer *);
uint32_t (*get_column)(TSLexer *);
bool (*is_at_included_range_start)(const TSLexer *);
bool (*eof)(const TSLexer *);
};
typedef enum {
TSParseActionTypeShift,
TSParseActionTypeReduce,
TSParseActionTypeAccept,
TSParseActionTypeRecover,
} TSParseActionType;
typedef union {
struct {
uint8_t type;
TSStateId state;
bool extra;
bool repetition;
} shift;
struct {
uint8_t type;
uint8_t child_count;
TSSymbol symbol;
int16_t dynamic_precedence;
uint16_t production_id;
} reduce;
uint8_t type;
} TSParseAction;
typedef struct {
uint16_t lex_state;
uint16_t external_lex_state;
} TSLexMode;
typedef union {
TSParseAction action;
struct {
uint8_t count;
bool reusable;
} entry;
} TSParseActionEntry;
struct TSLanguage {
uint32_t version;
uint32_t symbol_count;
uint32_t alias_count;
uint32_t token_count;
uint32_t external_token_count;
uint32_t state_count;
uint32_t large_state_count;
uint32_t production_id_count;
uint32_t field_count;
uint16_t max_alias_sequence_length;
const uint16_t *parse_table;
const uint16_t *small_parse_table;
const uint32_t *small_parse_table_map;
const TSParseActionEntry *parse_actions;
const char * const *symbol_names;
const char * const *field_names;
const TSFieldMapSlice *field_map_slices;
const TSFieldMapEntry *field_map_entries;
const TSSymbolMetadata *symbol_metadata;
const TSSymbol *public_symbol_map;
const uint16_t *alias_map;
const TSSymbol *alias_sequences;
const TSLexMode *lex_modes;
bool (*lex_fn)(TSLexer *, TSStateId);
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
TSSymbol keyword_capture_token;
struct {
const bool *states;
const TSSymbol *symbol_map;
void *(*create)(void);
void (*destroy)(void *);
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
unsigned (*serialize)(void *, char *);
void (*deserialize)(void *, const char *, unsigned);
} external_scanner;
const TSStateId *primary_state_ids;
};
/*
* Lexer Macros
*/
#define START_LEXER() \
bool result = false; \
bool skip = false; \
bool eof = false; \
int32_t lookahead; \
goto start; \
next_state: \
lexer->advance(lexer, skip); \
start: \
skip = false; \
lookahead = lexer->lookahead;
#define ADVANCE(state_value) \
{ \
state = state_value; \
goto next_state; \
}
#define SKIP(state_value) \
{ \
skip = true; \
state = state_value; \
goto next_state; \
}
#define ACCEPT_TOKEN(symbol_value) \
result = true; \
lexer->result_symbol = symbol_value; \
lexer->mark_end(lexer);
#define END_STATE() return result;
/*
* Parse Table Macros
*/
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
#define STATE(id) id
#define ACTIONS(id) id
#define SHIFT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value \
} \
}}
#define SHIFT_REPEAT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value, \
.repetition = true \
} \
}}
#define SHIFT_EXTRA() \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.extra = true \
} \
}}
#define REDUCE(symbol_val, child_count_val, ...) \
{{ \
.reduce = { \
.type = TSParseActionTypeReduce, \
.symbol = symbol_val, \
.child_count = child_count_val, \
__VA_ARGS__ \
}, \
}}
#define RECOVER() \
{{ \
.type = TSParseActionTypeRecover \
}}
#define ACCEPT_INPUT() \
{{ \
.type = TSParseActionTypeAccept \
}}
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_PARSER_H_

View File

@@ -0,0 +1,12 @@
---
// Anything inside the code fence is your component script.
// This JavaScript code runs at build-time.
// See below to learn more about what you can do.
console.log('This runs at build-time, is visible in the CLI output');
// Tip: TypeScript is also supported out-of-the-box!
const thisWorks: number = 42;
---
<div class="example-1">
<h1>Hello world!</h1>
</div>
<!-- This is the example given in Astro docs -->

View File

@@ -0,0 +1,17 @@
---
let x = `
---
${`
---
`}
---
`;
---
<!-- Some basic tests -->
<MyCustomElement someattr={(function() { return someexpr(like + this); })()}>
{
someOtherExpr(null)
}
</MyCustomElement>
{ "should also work at top level" }
{ array.map(x => <p> should also support JSX </p>) }

View File

@@ -0,0 +1,4 @@
---
/* string directly before end marker */ "x"
---
<p> Hi! </p>

View File

@@ -0,0 +1,4 @@
---
---
<div>
</div>

View File

@@ -0,0 +1,67 @@
---
import Layout from '../layouts/Layout.astro';
---
<!-- Big demo using SVG -->
<Layout title="Learn AWS - The easy way">
<section class="newsletter relative sm:py-16">
<div aria-hidden="true" class="hidden sm:block">
<svg class="absolute top-8 -right-8 -ml-3" width="404" height="392" fill="none" viewBox="0 0 404 392">
<defs>
<pattern id="8228f071-bcee-4ec8-905a-2a059a2cc4fb" x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="4" height="4" class="text-gray-200" fill="currentColor" />
</pattern>
</defs>
<rect width="404" height="392" fill="url(#8228f071-bcee-4ec8-905a-2a059a2cc4fb)" />
</svg>
</div>
<div class="mx-auto max-w-md px-4 sm:max-w-3xl sm:px-6 lg:max-w-7xl lg:px-8">
<div class="relative rounded-2xl px-6 py-10 bg-indigo-600 overflow-hidden shadow-xl sm:px-12 sm:py-20">
<div aria-hidden="true" class="absolute inset-0 -mt-72 sm:-mt-32 md:mt-0">
<svg class="absolute inset-0 h-full w-full" preserveAspectRatio="xMidYMid slice"
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 1463 360">
<path class="text-indigo-500 text-opacity-40" fill="currentColor"
d="M-82.673 72l1761.849 472.086-134.327 501.315-1761.85-472.086z" />
<path class="text-indigo-700 text-opacity-40" fill="currentColor"
d="M-217.088 544.086L1544.761 72l134.327 501.316-1761.849 472.086z" />
</svg>
</div>
<div class="relative grid justify-items-center">
<div class="sm:text-center">
<h2 class="text-3xl font-extrabold text-white tracking-tight sm:text-4xl">
Struggling to learn AWS?<br /> We are here to save you</h2>
<p class="mt-6 mx-auto max-w-2xl text-lg text-indigo-50">We are working hard to launch
some awesome courses which will teach you AWS Lambda, DynamoDB, App Sync, CDK, SES,
SNS, Event Bridge and what not</p>
<h4 class="mt-6 mx-auto max-w-2xl text-xl text-indigo-50 font-bold">Get notified when we launch
our creative AWS Course</h4>
</div>
<form action="#" class="mt-12 sm:mx-auto sm:max-w-lg" id="subscribe-form">
<div class="flex-1 mr-4 sm:col-span-3 mb-4 w-80">
<label for="cta-name" class="sr-only">Name</label>
<input id="cta-name" autocomplete="name" type="text" name="name" required minlength={3}
maxlength={15}
class="block w-full border border-transparent rounded-md px-5 py-3 text-base text-gray-900 placeholder-gray-500 shadow-sm focus:outline-none focus:border-transparent focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600"
placeholder="Your name">
</div>
<div class="flex-1 mr-4 sm:col-span-4 mb-4 w-80">
<label for="cta-email" class="sr-only">Email address</label>
<input id="cta-email" type="email" autocomplete="email" name="email" required
class="block w-full border border-transparent rounded-md px-5 py-3 text-base text-gray-900 placeholder-gray-500 shadow-sm focus:outline-none focus:border-transparent focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600"
placeholder="Your email">
</div>
<label class="text-white" id="error-msg"></label>
<div class="grid justify-items-center">
<div class="sm:mt-4 mr-4 w-80">
<button type="submit"
id="submit-btn"
class="block w-full rounded-md border border-transparent px-5 py-3 bg-indigo-500 text-base font-medium text-white shadow hover:bg-indigo-400 focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600 sm:px-10">Take me in!</button>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
</Layout>

View File

@@ -0,0 +1,7 @@
<!-- Inbuilt tags should not conflict with different-cased components (<meta> vs <Meta>) -->
<Meta>
<p>
</p>
</Meta>
<!-- ...but don't also confuse <meta> with something else -->
<meta charset="utf-8">