diff --git a/.gitignore b/.gitignore index 91d4c3a..28a376e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ node_modules +build yarn-error.log SvelteNova.novaextension/README.md SvelteNova.novaextension/CHANGELOG.md SvelteNova.novaextension/LICENSE SvelteNova.novaextension/Scripts/**/* +SvelteNova.novaextension/Syntaxes/tree-sitter-svelte.dylib .DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..85d152a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "tree-sitter-svelte"] + path = tree-sitter-svelte + url = https://github.com/Himujjal/tree-sitter-svelte diff --git a/SvelteNova.novaextension/Queries/highlights.scm b/SvelteNova.novaextension/Queries/highlights.scm new file mode 100644 index 0000000..831f63c --- /dev/null +++ b/SvelteNova.novaextension/Queries/highlights.scm @@ -0,0 +1,74 @@ +; This query file is adopted from https://github.com/Himujjal/tree-sitter-svelte/blob/master/queries/highlights.scm. +; Nova's highlight captures are different from the original one. + +; ((element (start_tag (tag_name) @_tag) (text) @text.title) +; (#match? @_tag "^(h[0-9]|title)$")) +; +; ((element (start_tag (tag_name) @_tag) (text) @text.strong) +; (#match? @_tag "^(strong|b)$")) +; +; ((element (start_tag (tag_name) @_tag) (text) @text.emphasis) +; (#match? @_tag "^(em|i)$")) +; +; ((element (start_tag (tag_name) @_tag) (text) @text.strike) +; (#match? @_tag "^(s|del)$")) +; +; ((element (start_tag (tag_name) @_tag) (text) @text.underline) +; (#eq? @_tag "u")) +; +; ((element (start_tag (tag_name) @_tag) (text) @text.literal) +; (#match? @_tag "^(code|kbd)$")) +; +; ((element (start_tag (tag_name) @_tag) (text) @text.uri) +; (#eq? @_tag "a")) + +((attribute + (attribute_name) @_attr + (quoted_attribute_value (attribute_value) @tag.attribute.value.link)) + (#match? @_attr "^(href|src)$")) + +((attribute + (attribute_name) @tag.attribute.name + ["="]? @tag.attribute.operator + [ + (attribute_value) @tag.attribute.value + (quoted_attribute_value + ["\"" "'"] @tag.attribute.value.delimiter.left + (_)? @tag.attribute.value + ["\"" "'"] @tag.attribute.value.delimiter.right + ) + ]? + ) + (#not-match? @tag.attribute.name "(?i)^(src|href)$") +) + +(tag_name) @tag.name +(erroneous_end_tag_name) @invalid +(comment) @comment + +(if_start_expr (special_block_keyword) @keyword.condition) +(else_expr (special_block_keyword) @keyword.condition) +(else_if_expr (special_block_keyword) @keyword.condition) +(if_end_expr (special_block_keyword) @keyword.condition) + +[ + (special_block_keyword) + (then) + (as) +] @keyword + +[ + "{" + "}" + ("{" "#") + ("{" ":") + ("{" "/") + ("{" "@") +] @tag.framework.bracket + +[ + "<" + ">" + "" +] @tag.bracket diff --git a/SvelteNova.novaextension/Syntaxes/Svelte.xml b/SvelteNova.novaextension/Syntaxes/Svelte.xml index bb4ac45..c13f68e 100644 --- a/SvelteNova.novaextension/Syntaxes/Svelte.xml +++ b/SvelteNova.novaextension/Syntaxes/Svelte.xml @@ -9,11 +9,15 @@ svelte html - + + + + + svelte - + (?x) @@ -30,7 +34,7 @@ ) - + @@ -41,7 +45,7 @@ - + @@ -50,7 +54,7 @@ - + @@ -70,7 +74,7 @@ - + @@ -80,10 +84,10 @@ --> - + - + &\#[0-9]+; @@ -346,7 +350,7 @@ - + @@ -393,7 +397,7 @@ - + @@ -437,7 +441,7 @@ - + @@ -477,7 +481,7 @@ - + @@ -517,7 +521,7 @@ - + @@ -557,7 +561,7 @@ - + @@ -597,7 +601,7 @@ - + @@ -606,7 +610,7 @@ </([a-zA-Z_][a-zA-Z0-9_:-]*)> - + @@ -639,7 +643,7 @@ - + @@ -669,7 +673,7 @@ - + @@ -767,7 +771,7 @@ - + @@ -794,7 +798,7 @@ - + @@ -873,7 +877,7 @@ - + @@ -903,7 +907,7 @@ - + @@ -928,7 +932,7 @@ - + @@ -986,7 +990,7 @@ - + @@ -1042,7 +1046,7 @@ - + @@ -1074,7 +1078,7 @@ - + @@ -1110,7 +1114,7 @@ - + @@ -1127,7 +1131,7 @@ - + @@ -1237,7 +1241,7 @@ - + @@ -1347,7 +1351,7 @@ - + @@ -1369,7 +1373,7 @@ onstorage onundo onunload - + onblur onchange oncontextmenu @@ -1380,11 +1384,11 @@ onreset onselect onsubmit - + onkeydown onkeypress onkeyup - + onclick ondblclick ondrag @@ -1401,7 +1405,7 @@ onmouseup onmousewheel onscroll - + onabort oncanplay oncanplaythrough @@ -1440,7 +1444,7 @@ - + @@ -1490,7 +1494,7 @@ - + @@ -1507,7 +1511,7 @@ - + @@ -1523,7 +1527,7 @@ - + [a-zA-Z0-9-_]+ diff --git a/build_scripts/Makefile b/build_scripts/Makefile new file mode 100644 index 0000000..1bd51e6 --- /dev/null +++ b/build_scripts/Makefile @@ -0,0 +1,65 @@ +# Repository +SRC_DIR := src + +PARSER_REPO_URL ?= $(shell git -C $(SRC_DIR) remote get-url origin ) +# the # in the sed pattern has to be escaped or it will be interpreted as a comment +PARSER_NAME ?= $(shell basename $(PARSER_REPO_URL) | cut -d '-' -f3 | sed 's\#.git\#\#') +UPPER_PARSER_NAME := $(shell echo $(PARSER_NAME) | tr a-z A-Z ) + +# install directory layout +PREFIX ?= /usr/local +INCLUDEDIR ?= $(PREFIX)/include +LIBDIR ?= $(PREFIX)/lib + +# collect sources, and link if necessary +# Some Tree Sitter grammars include .cc files directly in others, +# so we shouldn't just wildcard select them all. +# Only collect known file names. +ifneq ("$(wildcard $(SRC_DIR)/parser.c)", "") + SRC += $(SRC_DIR)/parser.c +endif +ifneq ("$(wildcard $(SRC_DIR)/scanner.c)", "") + SRC += $(SRC_DIR)/scanner.c +endif +ifneq ("$(wildcard $(SRC_DIR)/parser.cc)", "") + CPPSRC += $(SRC_DIR)/parser.cc +endif +ifneq ("$(wildcard $(SRC_DIR)/scanner.cc)", "") + CPPSRC += $(SRC_DIR)/scanner.cc +endif + +ifeq (, $(CPPSRC)) + ADDITIONALLIBS := +else + ADDITIONALLIBS := -lc++ +endif + +SRC += $(CPPSRC) +OBJ := $(addsuffix .o,$(basename $(SRC))) + +CFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR) +CXXFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR) +override CFLAGS += -std=gnu99 -fPIC +override CXXFLAGS += -fPIC + +LINKSHARED := $(LINKSHARED)-dynamiclib -Wl, +ifneq ($(ADDITIONALLIBS),) + LINKSHARED := $(LINKSHARED)$(ADDITIONALLIBS), +endif +LINKSHARED := $(LINKSHARED)-install_name,$(LIBDIR)/libtree-sitter-$(PARSER_NAME).dylib,-rpath,@executable_path/../Frameworks + +all: libtree-sitter-$(PARSER_NAME).dylib + +libtree-sitter-$(PARSER_NAME).dylib: $(OBJ) + $(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@ + +install: all + install -d '$(DESTDIR)$(LIBDIR)' + install -m755 libtree-sitter-$(PARSER_NAME).dylib '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).dylib + install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter + +clean: + rm -f $(OBJ) libtree-sitter-$(PARSER_NAME).dylib + rm -rf build/ + +.PHONY: all install clean diff --git a/build_scripts/README.md b/build_scripts/README.md new file mode 100644 index 0000000..e6c061c --- /dev/null +++ b/build_scripts/README.md @@ -0,0 +1,16 @@ +# `build_scripts` + +Both `compile_parser.sh` and `Makefile` are provided by Panic +[on their doc site](https://docs.nova.app/syntax-reference/tree-sitter/#compiling-a-parser), +and may be retrieved from +[here](https://docs.nova.app/syntax-reference/build_script.zip). + +Run `build_parser.sh` (from project root) to build the +`tree-sitter-svelte.dylib`: + +```sh +./build_scripts/build_parser.sh /Applications/Nova.app +``` + +You may need to adjust the path to `Nova.app`. It will also copy the build +output to correct place and cleanup temp files. diff --git a/build_scripts/build_parser.sh b/build_scripts/build_parser.sh new file mode 100755 index 0000000..6c3afdb --- /dev/null +++ b/build_scripts/build_parser.sh @@ -0,0 +1,18 @@ +#!/bin/zsh + +# This script is supposed to be ran from the project root. +# ./build_scripts/build_parser.sh path/to/Nova.app + +NOVAAPP=$1 + +cp build_scripts/Makefile tree-sitter-svelte/ + +pushd tree-sitter-svelte +../build_scripts/compile_parser.sh . $NOVAAPP +popd + +mv tree-sitter-svelte/build/lib/libtree-sitter-svelte.dylib SvelteNova.novaextension/Syntaxes/tree-sitter-svelte.dylib + +# Clean up the submodule folder to avoid problems +rm -rf tree-sitter-svelte/build +rm tree-sitter-svelte/Makefile diff --git a/build_scripts/compile_parser.sh b/build_scripts/compile_parser.sh new file mode 100755 index 0000000..2490fbf --- /dev/null +++ b/build_scripts/compile_parser.sh @@ -0,0 +1,25 @@ +#!/bin/zsh +set -euxo pipefail + +BASEDIR=$1 +APPBUNDLE=$2 +FRAMEWORKS_PATH="${APPBUNDLE}/Contents/Frameworks/" +WORKINGDIR=$(pwd) + +# - Build both arm64 (Apple Silicon) and x86_64 (Intel) +# - Require a minimum of macOS 11.0 +# - Include the /src/ directory for headers (for `tree_sitter/parser.h`) +BUILD_FLAGS="-arch arm64 -arch x86_64 -mmacosx-version-min=11.0 -I${BASEDIR}/src/" + +# Build in a temporary `build/` directory. +TMP_BUILD_DIR=$WORKINGDIR/build +mkdir -p $TMP_BUILD_DIR + +pushd $BASEDIR + +CFLAGS="${BUILD_FLAGS} -O3" \ +CXXFLAGS="${BUILD_FLAGS} -O3" \ +LDFLAGS="${BUILD_FLAGS} -F${FRAMEWORKS_PATH} -framework SyntaxKit -rpath @loader_path/../Frameworks" \ +PREFIX="$TMP_BUILD_DIR" make install + +popd diff --git a/tree-sitter-svelte b/tree-sitter-svelte new file mode 160000 index 0000000..52e122a --- /dev/null +++ b/tree-sitter-svelte @@ -0,0 +1 @@ +Subproject commit 52e122ae68b316d3aa960a0a422d3645ba717f42