├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ ├── ci.yml │ ├── fuzz.yml │ ├── lint.yml │ └── publish.yml ├── .gitignore ├── CMakeLists.txt ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── Makefile ├── Package.swift ├── README.md ├── binding.gyp ├── bindings ├── c │ ├── tree-sitter-jsdoc.h │ └── tree-sitter-jsdoc.pc.in ├── go │ ├── binding.go │ └── binding_test.go ├── node │ ├── binding.cc │ ├── binding_test.js │ ├── index.d.ts │ └── index.js ├── python │ ├── tests │ │ └── test_binding.py │ └── tree_sitter_jsdoc │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ ├── binding.c │ │ └── py.typed ├── rust │ ├── build.rs │ └── lib.rs └── swift │ ├── TreeSitterJSDoc │ └── jsdoc.h │ └── TreeSitterJSDocTests │ └── TreeSitterJSDocTests.swift ├── eslint.config.mjs ├── go.mod ├── go.sum ├── grammar.js ├── package-lock.json ├── package.json ├── pyproject.toml ├── queries └── highlights.scm ├── setup.py ├── src ├── grammar.json ├── node-types.json ├── parser.c ├── scanner.c └── tree_sitter │ ├── alloc.h │ ├── array.h │ └── parser.h ├── test └── corpus │ ├── braces.txt │ ├── crlf.txt │ └── main.txt └── tree-sitter.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | 6 | [*.{json,toml,yml,gyp}] 7 | indent_style = space 8 | indent_size = 2 9 | 10 | [*.js] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.scm] 15 | indent_style = space 16 | indent_size = 2 17 | 18 | [*.{c,cc,h}] 19 | indent_style = space 20 | indent_size = 4 21 | 22 | [*.rs] 23 | indent_style = space 24 | indent_size = 4 25 | 26 | [*.{py,pyi}] 27 | indent_style = space 28 | indent_size = 4 29 | 30 | [*.swift] 31 | indent_style = space 32 | indent_size = 4 33 | 34 | [*.go] 35 | indent_style = tab 36 | indent_size = 8 37 | 38 | [Makefile] 39 | indent_style = tab 40 | indent_size = 8 41 | 42 | [parser.c] 43 | indent_size = 2 44 | 45 | [{alloc,array,parser}.h] 46 | indent_size = 2 47 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | # Generated source files 4 | src/*.json linguist-generated 5 | src/parser.c linguist-generated 6 | src/tree_sitter/* linguist-generated 7 | 8 | # C bindings 9 | bindings/c/* linguist-generated 10 | CMakeLists.txt linguist-generated 11 | Makefile linguist-generated 12 | 13 | # Rust bindings 14 | bindings/rust/* linguist-generated 15 | Cargo.toml linguist-generated 16 | Cargo.lock linguist-generated 17 | 18 | # Node.js bindings 19 | bindings/node/* linguist-generated 20 | binding.gyp linguist-generated 21 | package.json linguist-generated 22 | package-lock.json linguist-generated 23 | 24 | # Python bindings 25 | bindings/python/** linguist-generated 26 | setup.py linguist-generated 27 | pyproject.toml linguist-generated 28 | 29 | # Go bindings 30 | bindings/go/* linguist-generated 31 | go.mod linguist-generated 32 | go.sum linguist-generated 33 | 34 | # Swift bindings 35 | bindings/swift/** linguist-generated 36 | Package.swift linguist-generated 37 | Package.resolved linguist-generated 38 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: tree-sitter 4 | patreon: # Replace with a single Patreon username 5 | open_collective: tree-sitter # Replace with a single Open Collective username 6 | ko_fi: amaanq 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - grammar.js 8 | - src/** 9 | - test/** 10 | - bindings/** 11 | - binding.gyp 12 | pull_request: 13 | paths: 14 | - grammar.js 15 | - src/** 16 | - test/** 17 | - bindings/** 18 | - binding.gyp 19 | 20 | concurrency: 21 | group: ${{github.workflow}}-${{github.ref}} 22 | cancel-in-progress: true 23 | 24 | jobs: 25 | test: 26 | name: Test parser 27 | runs-on: ${{matrix.os}} 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | os: [ubuntu-latest, windows-latest, macos-14] 32 | steps: 33 | - name: Checkout repository 34 | uses: actions/checkout@v4 35 | - name: Set up tree-sitter 36 | uses: tree-sitter/setup-action/cli@v1 37 | - name: Run tests 38 | uses: tree-sitter/parser-test-action@v2 39 | with: 40 | test-rust: true 41 | test-node: true 42 | test-python: true 43 | test-go: true 44 | test-swift: true 45 | -------------------------------------------------------------------------------- /.github/workflows/fuzz.yml: -------------------------------------------------------------------------------- 1 | name: Fuzz Parser 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - src/scanner.c 8 | pull_request: 9 | paths: 10 | - src/scanner.c 11 | 12 | jobs: 13 | fuzz: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v4 18 | - name: Run fuzzer 19 | uses: tree-sitter/fuzz-action@v4 20 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - grammar.js 8 | pull_request: 9 | paths: 10 | - grammar.js 11 | 12 | jobs: 13 | lint: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v4 18 | - name: Set up Node.js 19 | uses: actions/setup-node@v4 20 | with: 21 | cache: npm 22 | node-version: ${{vars.NODE_VERSION}} 23 | - name: Install modules 24 | run: npm ci --legacy-peer-deps 25 | - name: Run ESLint 26 | run: npm run lint 27 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish packages 2 | 3 | on: 4 | push: 5 | tags: ["*"] 6 | 7 | permissions: 8 | contents: write 9 | id-token: write 10 | attestations: write 11 | 12 | jobs: 13 | github: 14 | uses: tree-sitter/workflows/.github/workflows/release.yml@main 15 | with: 16 | generate: true 17 | attestations: true 18 | npm: 19 | uses: tree-sitter/workflows/.github/workflows/package-npm.yml@main 20 | secrets: 21 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 22 | with: 23 | generate: true 24 | crates: 25 | uses: tree-sitter/workflows/.github/workflows/package-crates.yml@main 26 | secrets: 27 | CARGO_REGISTRY_TOKEN: ${{secrets.CARGO_REGISTRY_TOKEN}} 28 | with: 29 | generate: true 30 | pypi: 31 | uses: tree-sitter/workflows/.github/workflows/package-pypi.yml@main 32 | secrets: 33 | PYPI_API_TOKEN: ${{secrets.PYPI_API_TOKEN}} 34 | with: 35 | generate: true 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Rust artifacts 2 | target/ 3 | 4 | # Node artifacts 5 | build/ 6 | prebuilds/ 7 | node_modules/ 8 | 9 | # Swift artifacts 10 | .build/ 11 | 12 | # Go artifacts 13 | _obj/ 14 | 15 | # Python artifacts 16 | .venv/ 17 | dist/ 18 | *.egg-info 19 | *.whl 20 | 21 | # C artifacts 22 | *.a 23 | *.so 24 | *.so.* 25 | *.dylib 26 | *.dll 27 | *.pc 28 | 29 | # Example dirs 30 | /examples/*/ 31 | 32 | # Grammar volatiles 33 | *.wasm 34 | *.obj 35 | *.o 36 | 37 | # Archives 38 | *.tar.gz 39 | *.tgz 40 | *.zip 41 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | project(tree-sitter-jsdoc 4 | VERSION "0.23.2" 5 | DESCRIPTION "JSDoc grammar for tree-sitter" 6 | HOMEPAGE_URL "https://github.com/tree-sitter/tree-sitter-jsdoc" 7 | LANGUAGES C) 8 | 9 | option(BUILD_SHARED_LIBS "Build using shared libraries" ON) 10 | option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF) 11 | 12 | set(TREE_SITTER_ABI_VERSION 14 CACHE STRING "Tree-sitter ABI version") 13 | if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$") 14 | unset(TREE_SITTER_ABI_VERSION CACHE) 15 | message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer") 16 | endif() 17 | 18 | find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI") 19 | 20 | add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c" 21 | DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json" 22 | COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json 23 | --abi=${TREE_SITTER_ABI_VERSION} 24 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 25 | COMMENT "Generating parser.c") 26 | 27 | add_library(tree-sitter-jsdoc src/parser.c) 28 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c) 29 | target_sources(tree-sitter-jsdoc PRIVATE src/scanner.c) 30 | endif() 31 | target_include_directories(tree-sitter-jsdoc PRIVATE src) 32 | 33 | target_compile_definitions(tree-sitter-jsdoc PRIVATE 34 | $<$:TREE_SITTER_REUSE_ALLOCATOR> 35 | $<$:TREE_SITTER_DEBUG>) 36 | 37 | set_target_properties(tree-sitter-jsdoc 38 | PROPERTIES 39 | C_STANDARD 11 40 | POSITION_INDEPENDENT_CODE ON 41 | SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}" 42 | DEFINE_SYMBOL "") 43 | 44 | configure_file(bindings/c/tree-sitter-jsdoc.pc.in 45 | "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-jsdoc.pc" @ONLY) 46 | 47 | include(GNUInstallDirs) 48 | 49 | install(FILES bindings/c/tree-sitter-jsdoc.h 50 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tree_sitter") 51 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-jsdoc.pc" 52 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig") 53 | install(TARGETS tree-sitter-jsdoc 54 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") 55 | 56 | add_custom_target(ts-test "${TREE_SITTER_CLI}" test 57 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 58 | COMMENT "tree-sitter test") 59 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "cc" 16 | version = "1.1.37" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" 19 | dependencies = [ 20 | "shlex", 21 | ] 22 | 23 | [[package]] 24 | name = "memchr" 25 | version = "2.7.4" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 28 | 29 | [[package]] 30 | name = "regex" 31 | version = "1.11.1" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 34 | dependencies = [ 35 | "aho-corasick", 36 | "memchr", 37 | "regex-automata", 38 | "regex-syntax", 39 | ] 40 | 41 | [[package]] 42 | name = "regex-automata" 43 | version = "0.4.8" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" 46 | dependencies = [ 47 | "aho-corasick", 48 | "memchr", 49 | "regex-syntax", 50 | ] 51 | 52 | [[package]] 53 | name = "regex-syntax" 54 | version = "0.8.5" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 57 | 58 | [[package]] 59 | name = "shlex" 60 | version = "1.3.0" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 63 | 64 | [[package]] 65 | name = "streaming-iterator" 66 | version = "0.1.9" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" 69 | 70 | [[package]] 71 | name = "tree-sitter" 72 | version = "0.24.4" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "b67baf55e7e1b6806063b1e51041069c90afff16afcbbccd278d899f9d84bca4" 75 | dependencies = [ 76 | "cc", 77 | "regex", 78 | "regex-syntax", 79 | "streaming-iterator", 80 | "tree-sitter-language", 81 | ] 82 | 83 | [[package]] 84 | name = "tree-sitter-jsdoc" 85 | version = "0.23.2" 86 | dependencies = [ 87 | "cc", 88 | "tree-sitter", 89 | "tree-sitter-language", 90 | ] 91 | 92 | [[package]] 93 | name = "tree-sitter-language" 94 | version = "0.1.2" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "e8ddffe35a0e5eeeadf13ff7350af564c6e73993a24db62caee1822b185c2600" 97 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tree-sitter-jsdoc" 3 | description = "JSDoc grammar for tree-sitter" 4 | version = "0.23.2" 5 | authors = [ 6 | "Max Brunsfeld ", 7 | "Amaan Qureshi ", 8 | ] 9 | license = "MIT" 10 | readme = "README.md" 11 | keywords = ["incremental", "parsing", "tree-sitter", "jsdoc"] 12 | categories = ["parsing", "text-editors"] 13 | repository = "https://github.com/tree-sitter/tree-sitter-jsdoc" 14 | edition = "2021" 15 | autoexamples = false 16 | 17 | build = "bindings/rust/build.rs" 18 | include = ["bindings/rust/*", "grammar.js", "queries/*", "src/*", "tree-sitter.json"] 19 | 20 | [lib] 21 | path = "bindings/rust/lib.rs" 22 | 23 | [dependencies] 24 | tree-sitter-language = "0.1" 25 | 26 | [build-dependencies] 27 | cc = "1.1" 28 | 29 | [dev-dependencies] 30 | tree-sitter = "0.24" 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Max Brunsfeld 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(OS),Windows_NT) 2 | $(error Windows is not supported) 3 | endif 4 | 5 | LANGUAGE_NAME := tree-sitter-jsdoc 6 | HOMEPAGE_URL := https://github.com/tree-sitter/tree-sitter-jsdoc 7 | VERSION := 0.23.2 8 | 9 | # repository 10 | SRC_DIR := src 11 | 12 | TS ?= tree-sitter 13 | 14 | # install directory layout 15 | PREFIX ?= /usr/local 16 | INCLUDEDIR ?= $(PREFIX)/include 17 | LIBDIR ?= $(PREFIX)/lib 18 | PCLIBDIR ?= $(LIBDIR)/pkgconfig 19 | 20 | # source/object files 21 | PARSER := $(SRC_DIR)/parser.c 22 | EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c)) 23 | OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS)) 24 | 25 | # flags 26 | ARFLAGS ?= rcs 27 | override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC 28 | 29 | # ABI versioning 30 | SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER)) 31 | SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION))) 32 | 33 | # OS-specific bits 34 | ifeq ($(shell uname),Darwin) 35 | SOEXT = dylib 36 | SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT) 37 | SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT) 38 | LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks 39 | else 40 | SOEXT = so 41 | SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR) 42 | SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR) 43 | LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER) 44 | endif 45 | ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),) 46 | PCLIBDIR := $(PREFIX)/libdata/pkgconfig 47 | endif 48 | 49 | all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc 50 | 51 | lib$(LANGUAGE_NAME).a: $(OBJS) 52 | $(AR) $(ARFLAGS) $@ $^ 53 | 54 | lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS) 55 | $(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@ 56 | ifneq ($(STRIP),) 57 | $(STRIP) $@ 58 | endif 59 | 60 | $(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in 61 | sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \ 62 | -e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \ 63 | -e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \ 64 | -e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \ 65 | -e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \ 66 | -e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@ 67 | 68 | $(PARSER): $(SRC_DIR)/grammar.json 69 | $(TS) generate $^ 70 | 71 | install: all 72 | install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)' 73 | install -m644 bindings/c/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h 74 | install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc 75 | install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a 76 | install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) 77 | ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) 78 | ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) 79 | 80 | uninstall: 81 | $(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \ 82 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \ 83 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \ 84 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \ 85 | '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \ 86 | '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc 87 | 88 | clean: 89 | $(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) 90 | 91 | test: 92 | $(TS) test 93 | 94 | .PHONY: all install uninstall clean test 95 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "TreeSitterJSDoc", 6 | products: [ 7 | .library(name: "TreeSitterJSDoc", targets: ["TreeSitterJSDoc"]), 8 | ], 9 | dependencies: [ 10 | .package(url: "https://github.com/ChimeHQ/SwiftTreeSitter", from: "0.8.0"), 11 | ], 12 | targets: [ 13 | .target( 14 | name: "TreeSitterJSDoc", 15 | dependencies: [], 16 | path: ".", 17 | sources: [ 18 | "src/parser.c", 19 | "src/scanner.c", 20 | ], 21 | resources: [ 22 | .copy("queries") 23 | ], 24 | publicHeadersPath: "bindings/swift", 25 | cSettings: [.headerSearchPath("src")] 26 | ), 27 | .testTarget( 28 | name: "TreeSitterJSDocTests", 29 | dependencies: [ 30 | "SwiftTreeSitter", 31 | "TreeSitterJSDoc", 32 | ], 33 | path: "bindings/swift/TreeSitterJSDocTests" 34 | ) 35 | ], 36 | cLanguageStandard: .c11 37 | ) 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-jsdoc 2 | 3 | [![CI][ci]](https://github.com/tree-sitter/tree-sitter-jsdoc/actions/workflows/ci.yml) 4 | [![discord][discord]](https://discord.gg/w7nTvsVJhm) 5 | [![matrix][matrix]](https://matrix.to/#/#tree-sitter-chat:matrix.org) 6 | [![crates][crates]](https://crates.io/crates/tree-sitter-jsdoc) 7 | [![npm][npm]](https://www.npmjs.com/package/tree-sitter-jsdoc) 8 | [![pypi][pypi]](https://pypi.org/project/tree-sitter-jsdoc) 9 | 10 | [JSDoc](<(https://jsdoc.app/)>) grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter). 11 | 12 | [ci]: https://img.shields.io/github/actions/workflow/status/tree-sitter/tree-sitter-jsdoc/ci.yml?logo=github&label=CI 13 | [discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord 14 | [matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix 15 | [npm]: https://img.shields.io/npm/v/tree-sitter-jsdoc?logo=npm 16 | [crates]: https://img.shields.io/crates/v/tree-sitter-jsdoc?logo=rust 17 | [pypi]: https://img.shields.io/pypi/v/tree-sitter-jsdoc?logo=pypi&logoColor=ffd242 18 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_jsdoc_binding", 5 | "dependencies": [ 6 | " 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | extern "C" TSLanguage *tree_sitter_jsdoc(); 6 | 7 | // "tree-sitter", "language" hashed with BLAKE2 8 | const napi_type_tag LANGUAGE_TYPE_TAG = { 9 | 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16 10 | }; 11 | 12 | Napi::Object Init(Napi::Env env, Napi::Object exports) { 13 | exports["name"] = Napi::String::New(env, "jsdoc"); 14 | auto language = Napi::External::New(env, tree_sitter_jsdoc()); 15 | language.TypeTag(&LANGUAGE_TYPE_TAG); 16 | exports["language"] = language; 17 | return exports; 18 | } 19 | 20 | NODE_API_MODULE(tree_sitter_jsdoc_binding, Init) 21 | -------------------------------------------------------------------------------- /bindings/node/binding_test.js: -------------------------------------------------------------------------------- 1 | const assert = require("node:assert"); 2 | const { test } = require("node:test"); 3 | 4 | const Parser = require("tree-sitter"); 5 | 6 | test("can load grammar", () => { 7 | const parser = new Parser(); 8 | assert.doesNotThrow(() => parser.setLanguage(require("."))); 9 | }); 10 | -------------------------------------------------------------------------------- /bindings/node/index.d.ts: -------------------------------------------------------------------------------- 1 | type BaseNode = { 2 | type: string; 3 | named: boolean; 4 | }; 5 | 6 | type ChildNode = { 7 | multiple: boolean; 8 | required: boolean; 9 | types: BaseNode[]; 10 | }; 11 | 12 | type NodeInfo = 13 | | (BaseNode & { 14 | subtypes: BaseNode[]; 15 | }) 16 | | (BaseNode & { 17 | fields: { [name: string]: ChildNode }; 18 | children: ChildNode[]; 19 | }); 20 | 21 | type Language = { 22 | name: string; 23 | language: unknown; 24 | nodeTypeInfo: NodeInfo[]; 25 | }; 26 | 27 | declare const language: Language; 28 | export = language; 29 | -------------------------------------------------------------------------------- /bindings/node/index.js: -------------------------------------------------------------------------------- 1 | const root = require("path").join(__dirname, "..", ".."); 2 | 3 | module.exports = 4 | typeof process.versions.bun === "string" 5 | // Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time 6 | ? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-jsdoc.node`) 7 | : require("node-gyp-build")(root); 8 | 9 | try { 10 | module.exports.nodeTypeInfo = require("../../src/node-types.json"); 11 | } catch (_) {} 12 | -------------------------------------------------------------------------------- /bindings/python/tests/test_binding.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | import tree_sitter, tree_sitter_jsdoc 4 | 5 | 6 | class TestLanguage(TestCase): 7 | def test_can_load_grammar(self): 8 | try: 9 | tree_sitter.Language(tree_sitter_jsdoc.language()) 10 | except Exception: 11 | self.fail("Error loading JSDoc grammar") 12 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_jsdoc/__init__.py: -------------------------------------------------------------------------------- 1 | """JSDoc grammar for tree-sitter""" 2 | 3 | from importlib.resources import files as _files 4 | 5 | from ._binding import language 6 | 7 | 8 | def _get_query(name, file): 9 | query = _files(f"{__package__}.queries") / file 10 | globals()[name] = query.read_text() 11 | return globals()[name] 12 | 13 | 14 | def __getattr__(name): 15 | if name == "HIGHLIGHTS_QUERY": 16 | return _get_query("HIGHLIGHTS_QUERY", "highlights.scm") 17 | 18 | raise AttributeError(f"module {__name__!r} has no attribute {name!r}") 19 | 20 | 21 | __all__ = [ 22 | "language", 23 | "HIGHLIGHTS_QUERY", 24 | ] 25 | 26 | 27 | def __dir__(): 28 | return sorted(__all__ + [ 29 | "__all__", "__builtins__", "__cached__", "__doc__", "__file__", 30 | "__loader__", "__name__", "__package__", "__path__", "__spec__", 31 | ]) 32 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_jsdoc/__init__.pyi: -------------------------------------------------------------------------------- 1 | from typing import Final 2 | 3 | HIGHLIGHTS_QUERY: Final[str] 4 | 5 | def language() -> object: ... 6 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_jsdoc/binding.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | TSLanguage *tree_sitter_jsdoc(void); 6 | 7 | static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { 8 | return PyCapsule_New(tree_sitter_jsdoc(), "tree_sitter.Language", NULL); 9 | } 10 | 11 | static PyMethodDef methods[] = { 12 | {"language", _binding_language, METH_NOARGS, 13 | "Get the tree-sitter language for this grammar."}, 14 | {NULL, NULL, 0, NULL} 15 | }; 16 | 17 | static struct PyModuleDef module = { 18 | .m_base = PyModuleDef_HEAD_INIT, 19 | .m_name = "_binding", 20 | .m_doc = NULL, 21 | .m_size = -1, 22 | .m_methods = methods 23 | }; 24 | 25 | PyMODINIT_FUNC PyInit__binding(void) { 26 | return PyModule_Create(&module); 27 | } 28 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_jsdoc/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tree-sitter/tree-sitter-jsdoc/a417db5dbdd869fccb6a8b75ec04459e1d4ccd2c/bindings/python/tree_sitter_jsdoc/py.typed -------------------------------------------------------------------------------- /bindings/rust/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let src_dir = std::path::Path::new("src"); 3 | 4 | let mut c_config = cc::Build::new(); 5 | c_config 6 | .std("c11") 7 | .include(src_dir) 8 | .flag_if_supported("-Wno-unused-parameter"); 9 | 10 | #[cfg(target_env = "msvc")] 11 | c_config.flag("-utf-8"); 12 | 13 | let parser_path = src_dir.join("parser.c"); 14 | c_config.file(&parser_path); 15 | println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); 16 | 17 | let scanner_path = src_dir.join("scanner.c"); 18 | c_config.file(&scanner_path); 19 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 20 | 21 | c_config.compile("tree-sitter-jsdoc"); 22 | } 23 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides JSDoc language support for the [tree-sitter][] parsing library. 2 | //! 3 | //! Typically, you will use the [LANGUAGE][] constant to add this language to a 4 | //! tree-sitter [Parser][], and then use the parser to parse some code: 5 | //! 6 | //! ``` 7 | //! use tree_sitter::Parser; 8 | //! 9 | //! let code = r#" 10 | //! /** 11 | //! * This is a JSDoc comment 12 | //! * 13 | //! * @param {string} foo 14 | //! */ 15 | //! "#; 16 | //! let mut parser = Parser::new(); 17 | //! let language = tree_sitter_jsdoc::LANGUAGE; 18 | //! parser 19 | //! .set_language(&language.into()) 20 | //! .expect("Error loading JSDoc parser"); 21 | //! let tree = parser.parse(code, None).unwrap(); 22 | //! assert!(!tree.root_node().has_error()); 23 | //! ``` 24 | //! 25 | //! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html 26 | //! [tree-sitter]: https://tree-sitter.github.io/ 27 | 28 | use tree_sitter_language::LanguageFn; 29 | 30 | extern "C" { 31 | fn tree_sitter_jsdoc() -> *const (); 32 | } 33 | 34 | /// The tree-sitter [`LanguageFn`][LanguageFn] for this grammar. 35 | /// 36 | /// [LanguageFn]: https://docs.rs/tree-sitter-language/*/tree_sitter_language/struct.LanguageFn.html 37 | pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_jsdoc) }; 38 | 39 | /// The content of the [`node-types.json`][] file for this grammar. 40 | /// 41 | /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types 42 | pub const NODE_TYPES: &str = include_str!("../../src/node-types.json"); 43 | 44 | /// The syntax highlighting query for this grammar. 45 | pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm"); 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | #[test] 50 | fn test_can_load_grammar() { 51 | let mut parser = tree_sitter::Parser::new(); 52 | parser 53 | .set_language(&super::LANGUAGE.into()) 54 | .expect("Error loading JSDoc parser"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterJSDoc/jsdoc.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_JSDOC_H_ 2 | #define TREE_SITTER_JSDOC_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | const TSLanguage *tree_sitter_jsdoc(void); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_JSDOC_H_ 17 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterJSDocTests/TreeSitterJSDocTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import SwiftTreeSitter 3 | import TreeSitterJSDoc 4 | 5 | final class TreeSitterJSDocTests: XCTestCase { 6 | func testCanLoadGrammar() throws { 7 | let parser = Parser() 8 | let language = Language(language: tree_sitter_jsdoc()) 9 | XCTAssertNoThrow(try parser.setLanguage(language), 10 | "Error loading JSDoc grammar") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import treesitter from 'eslint-config-treesitter'; 2 | 3 | export default [ 4 | ...treesitter, 5 | ]; 6 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tree-sitter/tree-sitter-jsdoc 2 | 3 | go 1.22 4 | 5 | require github.com/tree-sitter/go-tree-sitter v0.24.0 6 | 7 | require github.com/mattn/go-pointer v0.0.1 // indirect 8 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= 4 | github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= 5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 8 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 9 | github.com/tree-sitter/go-tree-sitter v0.24.0 h1:kRZb6aBNfcI/u0Qh8XEt3zjNVnmxTisDBN+kXK0xRYQ= 10 | github.com/tree-sitter/go-tree-sitter v0.24.0/go.mod h1:x681iFVoLMEwOSIHA1chaLkXlroXEN7WY+VHGFaoDbk= 11 | github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb h1:A8425heRM8mylnv4H58FPUiH+aYivyitre0PzxrfmWs= 12 | github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb/go.mod h1:dOF6gtQiF9UwNh995T5OphYmtIypkjsp3ap7r9AN/iA= 13 | github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148 h1:AfFPZwtwGN01BW1jDdqBVqscTwetvMpydqYZz57RSlc= 14 | github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148/go.mod h1:Bh6U3viD57rFXRYIQ+kmiYtr+1Bx0AceypDLJJSyi9s= 15 | github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33 h1:TwqSV3qLp3tKSqirGLRHnjFk9Tc2oy57LIl+FQ4GjI4= 16 | github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33/go.mod h1:CvCKCt3v04Ufos1zZnNCelBDeCGRpPucaN8QczoUsN4= 17 | github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012 h1:Xvxck3tE5FW7F7bTS97iNM2ADMyCMJztVqn5HYKdJGo= 18 | github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012/go.mod h1:T40D0O1cPvUU/+AmiXVXy1cncYQT6wem4Z0g4SfAYvY= 19 | github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0 h1:c46K6uh5Dz00zJeU9BfjXdb8I+E4RkUdfnWJpQADXFo= 20 | github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0/go.mod h1:hcNt/kOJHcIcuMvouE7LJcYdeFUFbVpBJ6d4wmOA+tU= 21 | github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495 h1:jrt4qbJVEFs4H93/ITxygHc6u0TGqAkkate7TQ4wFSA= 22 | github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495/go.mod h1:oyaR7fLnRV0hT9z6qwE9GkaeTom/hTDwK3H2idcOJFc= 23 | github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5 h1:om4X9AVg3asL8gxNJDcz4e/Wp+VpQj1PY3uJXKr6EOg= 24 | github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5/go.mod h1:nNqgPoV/h9uYWk6kYEFdEAhNVOacpfpRW5SFmdaP4tU= 25 | github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5 h1:pfV3G3k7NCKqKk8THBmyuh2zA33lgYHS3GVrzRR8ry4= 26 | github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5/go.mod h1:GbMKRjLfk0H+PI7nLi1Sx5lHf5wCpLz9al8tQYSxpEk= 27 | github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1 h1:ZXZMDwE+IhUtGug4Brv6NjJWUU3rfkZBKpemf6RY8/g= 28 | github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1/go.mod h1:UKCLuYnJ312Mei+3cyTmGOHzn0YAnaPRECgJmHtzrqs= 29 | github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb h1:EXEM82lFM7JjJb6qiKZXkpIDaCcbV2obNn82ghwj9lw= 30 | github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb/go.mod h1:lXCF1nGG5Dr4J3BTS0ObN4xJCCICiSu/b+Xe/VqMV7g= 31 | github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d h1:fcYCvoXdcP1uRQYXqJHRy6Hec+uKScQdKVtMwK9JeCI= 32 | github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d/go.mod h1:T1nShQ4v5AJtozZ8YyAS4uzUtDAJj/iv4YfwXSbUHzg= 33 | github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447 h1:o9alBu1J/WjrcTKEthYtXmdkDc5OVXD+PqlvnEZ0Lzc= 34 | github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447/go.mod h1:1Oh95COkkTn6Ezp0vcMbvfhRP5gLeqqljR0BYnBzWvc= 35 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 36 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 37 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file JSDoc grammar for tree-sitter 3 | * @author Max Brunsfeld 4 | * @author Amaan Qureshi 5 | * @license MIT 6 | */ 7 | 8 | /// 9 | // @ts-check 10 | 11 | module.exports = grammar({ 12 | name: 'jsdoc', 13 | 14 | externals: $ => [ 15 | $.type, 16 | ], 17 | 18 | extras: _ => [ 19 | token(choice( 20 | // Skip over stars at the beginnings of lines 21 | seq(/\n/, /[ \t]*/, repeat(seq('*', /[ \t]*/))), 22 | /\s/, 23 | )), 24 | ], 25 | 26 | rules: { 27 | document: $ => seq( 28 | $._begin, 29 | optional($.description), 30 | repeat($.tag), 31 | $._end, 32 | ), 33 | 34 | description: $ => seq( 35 | $._text, 36 | repeat(choice($._text, $.inline_tag, $._inline_tag_false_positive)), 37 | ), 38 | 39 | tag: $ => choice( 40 | // type, name, and description 41 | seq( 42 | alias($.tag_name_with_argument, $.tag_name), 43 | optional(seq('{', $.type, '}')), 44 | optional($._expression), 45 | optional($.description), 46 | ), 47 | 48 | // type and description 49 | seq( 50 | alias($.tag_name_with_type, $.tag_name), 51 | optional(seq('{', $.type, '}')), 52 | optional($.description), 53 | ), 54 | 55 | // description only 56 | seq( 57 | $.tag_name, 58 | optional($.description), 59 | ), 60 | ), 61 | 62 | inline_tag: $ => seq( 63 | '{', 64 | $.tag_name, 65 | $.description, 66 | '}', 67 | ), 68 | 69 | _inline_tag_false_positive: _ => token(prec.left(1, /\{[^@}]+\}?/)), 70 | 71 | tag_name_with_argument: _ => token(choice( 72 | '@access', 73 | '@alias', 74 | '@api', 75 | '@augments', 76 | '@borrows', 77 | '@callback', 78 | '@constructor', 79 | '@event', 80 | '@exports', 81 | '@external', 82 | '@extends', 83 | '@fires', 84 | '@function', 85 | '@mixes', 86 | '@name', 87 | '@namespace', 88 | '@param', 89 | '@property', 90 | '@prop', 91 | '@satisfies', 92 | '@typedef', 93 | )), 94 | 95 | tag_name_with_type: _ => token(choice( 96 | '@return', 97 | '@returns', 98 | '@throw', 99 | '@throws', 100 | '@type', 101 | )), 102 | 103 | tag_name: _ => /@[a-zA-Z_]+/, 104 | 105 | _expression: $ => choice( 106 | $.identifier, 107 | $.optional_identifier, 108 | $.member_expression, 109 | $.path_expression, 110 | $.qualified_expression, 111 | ), 112 | 113 | qualified_expression: $ => prec(1, seq( 114 | $.identifier, 115 | ':', 116 | $._expression, 117 | )), 118 | 119 | path_expression: $ => prec(2, seq( 120 | $.identifier, 121 | token.immediate('/'), 122 | $.identifier, 123 | )), 124 | 125 | member_expression: $ => seq( 126 | $._expression, 127 | choice( 128 | '.', 129 | '#', 130 | '~', 131 | ), 132 | choice( 133 | $.identifier, 134 | $.qualified_expression, 135 | ), 136 | ), 137 | 138 | optional_identifier: $ => seq('[', $.identifier, ']'), 139 | 140 | identifier: _ => /[a-zA-Z_$][a-zA-Z_$0-9]*/, 141 | 142 | _text: _ => token(prec(-1, /[^*{}@\s][^*{}\n]*([^*/{}\n][^*{}\n]*\*+)*/)), 143 | 144 | _begin: _ => token(seq('/', repeat('*'))), 145 | 146 | _end: _ => '/', 147 | }, 148 | }); 149 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-jsdoc", 3 | "version": "0.23.2", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "tree-sitter-jsdoc", 9 | "version": "0.23.2", 10 | "hasInstallScript": true, 11 | "license": "MIT", 12 | "dependencies": { 13 | "node-addon-api": "^8.2.2", 14 | "node-gyp-build": "^4.8.2" 15 | }, 16 | "devDependencies": { 17 | "eslint": ">=9.14.0", 18 | "eslint-config-treesitter": "^1.0.2", 19 | "prebuildify": "^6.0.1", 20 | "tree-sitter-cli": "^0.24.4" 21 | }, 22 | "peerDependencies": { 23 | "tree-sitter": "^0.21.1" 24 | }, 25 | "peerDependenciesMeta": { 26 | "tree-sitter": { 27 | "optional": true 28 | } 29 | } 30 | }, 31 | "node_modules/@aashutoshrathi/word-wrap": { 32 | "version": "1.2.6", 33 | "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", 34 | "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", 35 | "dev": true, 36 | "engines": { 37 | "node": ">=0.10.0" 38 | } 39 | }, 40 | "node_modules/@es-joy/jsdoccomment": { 41 | "version": "0.49.0", 42 | "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz", 43 | "integrity": "sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==", 44 | "dev": true, 45 | "dependencies": { 46 | "comment-parser": "1.4.1", 47 | "esquery": "^1.6.0", 48 | "jsdoc-type-pratt-parser": "~4.1.0" 49 | }, 50 | "engines": { 51 | "node": ">=16" 52 | } 53 | }, 54 | "node_modules/@eslint-community/eslint-utils": { 55 | "version": "4.4.0", 56 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", 57 | "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", 58 | "dev": true, 59 | "dependencies": { 60 | "eslint-visitor-keys": "^3.3.0" 61 | }, 62 | "engines": { 63 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 64 | }, 65 | "peerDependencies": { 66 | "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" 67 | } 68 | }, 69 | "node_modules/@eslint-community/regexpp": { 70 | "version": "4.12.1", 71 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", 72 | "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", 73 | "dev": true, 74 | "engines": { 75 | "node": "^12.0.0 || ^14.0.0 || >=16.0.0" 76 | } 77 | }, 78 | "node_modules/@eslint/config-array": { 79 | "version": "0.18.0", 80 | "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", 81 | "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", 82 | "dev": true, 83 | "dependencies": { 84 | "@eslint/object-schema": "^2.1.4", 85 | "debug": "^4.3.1", 86 | "minimatch": "^3.1.2" 87 | }, 88 | "engines": { 89 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 90 | } 91 | }, 92 | "node_modules/@eslint/core": { 93 | "version": "0.7.0", 94 | "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", 95 | "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", 96 | "dev": true, 97 | "engines": { 98 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 99 | } 100 | }, 101 | "node_modules/@eslint/eslintrc": { 102 | "version": "3.1.0", 103 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", 104 | "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", 105 | "dev": true, 106 | "dependencies": { 107 | "ajv": "^6.12.4", 108 | "debug": "^4.3.2", 109 | "espree": "^10.0.1", 110 | "globals": "^14.0.0", 111 | "ignore": "^5.2.0", 112 | "import-fresh": "^3.2.1", 113 | "js-yaml": "^4.1.0", 114 | "minimatch": "^3.1.2", 115 | "strip-json-comments": "^3.1.1" 116 | }, 117 | "engines": { 118 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 119 | }, 120 | "funding": { 121 | "url": "https://opencollective.com/eslint" 122 | } 123 | }, 124 | "node_modules/@eslint/js": { 125 | "version": "9.14.0", 126 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", 127 | "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", 128 | "dev": true, 129 | "engines": { 130 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 131 | } 132 | }, 133 | "node_modules/@eslint/object-schema": { 134 | "version": "2.1.4", 135 | "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", 136 | "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", 137 | "dev": true, 138 | "engines": { 139 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 140 | } 141 | }, 142 | "node_modules/@eslint/plugin-kit": { 143 | "version": "0.2.0", 144 | "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", 145 | "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", 146 | "dev": true, 147 | "dependencies": { 148 | "levn": "^0.4.1" 149 | }, 150 | "engines": { 151 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 152 | } 153 | }, 154 | "node_modules/@humanfs/core": { 155 | "version": "0.19.1", 156 | "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", 157 | "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", 158 | "dev": true, 159 | "engines": { 160 | "node": ">=18.18.0" 161 | } 162 | }, 163 | "node_modules/@humanfs/node": { 164 | "version": "0.16.6", 165 | "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", 166 | "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", 167 | "dev": true, 168 | "dependencies": { 169 | "@humanfs/core": "^0.19.1", 170 | "@humanwhocodes/retry": "^0.3.0" 171 | }, 172 | "engines": { 173 | "node": ">=18.18.0" 174 | } 175 | }, 176 | "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { 177 | "version": "0.3.1", 178 | "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", 179 | "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", 180 | "dev": true, 181 | "engines": { 182 | "node": ">=18.18" 183 | }, 184 | "funding": { 185 | "type": "github", 186 | "url": "https://github.com/sponsors/nzakas" 187 | } 188 | }, 189 | "node_modules/@humanwhocodes/module-importer": { 190 | "version": "1.0.1", 191 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 192 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 193 | "dev": true, 194 | "engines": { 195 | "node": ">=12.22" 196 | }, 197 | "funding": { 198 | "type": "github", 199 | "url": "https://github.com/sponsors/nzakas" 200 | } 201 | }, 202 | "node_modules/@humanwhocodes/retry": { 203 | "version": "0.4.1", 204 | "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", 205 | "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", 206 | "dev": true, 207 | "engines": { 208 | "node": ">=18.18" 209 | }, 210 | "funding": { 211 | "type": "github", 212 | "url": "https://github.com/sponsors/nzakas" 213 | } 214 | }, 215 | "node_modules/@pkgr/core": { 216 | "version": "0.1.1", 217 | "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", 218 | "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", 219 | "dev": true, 220 | "engines": { 221 | "node": "^12.20.0 || ^14.18.0 || >=16.0.0" 222 | }, 223 | "funding": { 224 | "url": "https://opencollective.com/unts" 225 | } 226 | }, 227 | "node_modules/@types/estree": { 228 | "version": "1.0.6", 229 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 230 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 231 | "dev": true 232 | }, 233 | "node_modules/@types/json-schema": { 234 | "version": "7.0.15", 235 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", 236 | "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", 237 | "dev": true 238 | }, 239 | "node_modules/acorn": { 240 | "version": "8.14.0", 241 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 242 | "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 243 | "dev": true, 244 | "bin": { 245 | "acorn": "bin/acorn" 246 | }, 247 | "engines": { 248 | "node": ">=0.4.0" 249 | } 250 | }, 251 | "node_modules/acorn-jsx": { 252 | "version": "5.3.2", 253 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 254 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 255 | "dev": true, 256 | "peerDependencies": { 257 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 258 | } 259 | }, 260 | "node_modules/ajv": { 261 | "version": "6.12.6", 262 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 263 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 264 | "dev": true, 265 | "dependencies": { 266 | "fast-deep-equal": "^3.1.1", 267 | "fast-json-stable-stringify": "^2.0.0", 268 | "json-schema-traverse": "^0.4.1", 269 | "uri-js": "^4.2.2" 270 | }, 271 | "funding": { 272 | "type": "github", 273 | "url": "https://github.com/sponsors/epoberezkin" 274 | } 275 | }, 276 | "node_modules/ansi-styles": { 277 | "version": "4.3.0", 278 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 279 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 280 | "dev": true, 281 | "dependencies": { 282 | "color-convert": "^2.0.1" 283 | }, 284 | "engines": { 285 | "node": ">=8" 286 | }, 287 | "funding": { 288 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 289 | } 290 | }, 291 | "node_modules/are-docs-informative": { 292 | "version": "0.0.2", 293 | "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", 294 | "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", 295 | "dev": true, 296 | "engines": { 297 | "node": ">=14" 298 | } 299 | }, 300 | "node_modules/argparse": { 301 | "version": "2.0.1", 302 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 303 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 304 | "dev": true 305 | }, 306 | "node_modules/balanced-match": { 307 | "version": "1.0.2", 308 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 309 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 310 | "dev": true 311 | }, 312 | "node_modules/base64-js": { 313 | "version": "1.5.1", 314 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 315 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 316 | "dev": true, 317 | "funding": [ 318 | { 319 | "type": "github", 320 | "url": "https://github.com/sponsors/feross" 321 | }, 322 | { 323 | "type": "patreon", 324 | "url": "https://www.patreon.com/feross" 325 | }, 326 | { 327 | "type": "consulting", 328 | "url": "https://feross.org/support" 329 | } 330 | ] 331 | }, 332 | "node_modules/bl": { 333 | "version": "4.1.0", 334 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 335 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 336 | "dev": true, 337 | "dependencies": { 338 | "buffer": "^5.5.0", 339 | "inherits": "^2.0.4", 340 | "readable-stream": "^3.4.0" 341 | } 342 | }, 343 | "node_modules/brace-expansion": { 344 | "version": "1.1.11", 345 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 346 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 347 | "dev": true, 348 | "dependencies": { 349 | "balanced-match": "^1.0.0", 350 | "concat-map": "0.0.1" 351 | } 352 | }, 353 | "node_modules/buffer": { 354 | "version": "5.7.1", 355 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 356 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 357 | "dev": true, 358 | "funding": [ 359 | { 360 | "type": "github", 361 | "url": "https://github.com/sponsors/feross" 362 | }, 363 | { 364 | "type": "patreon", 365 | "url": "https://www.patreon.com/feross" 366 | }, 367 | { 368 | "type": "consulting", 369 | "url": "https://feross.org/support" 370 | } 371 | ], 372 | "dependencies": { 373 | "base64-js": "^1.3.1", 374 | "ieee754": "^1.1.13" 375 | } 376 | }, 377 | "node_modules/callsites": { 378 | "version": "3.1.0", 379 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 380 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 381 | "dev": true, 382 | "engines": { 383 | "node": ">=6" 384 | } 385 | }, 386 | "node_modules/chalk": { 387 | "version": "4.1.2", 388 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 389 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 390 | "dev": true, 391 | "dependencies": { 392 | "ansi-styles": "^4.1.0", 393 | "supports-color": "^7.1.0" 394 | }, 395 | "engines": { 396 | "node": ">=10" 397 | }, 398 | "funding": { 399 | "url": "https://github.com/chalk/chalk?sponsor=1" 400 | } 401 | }, 402 | "node_modules/chownr": { 403 | "version": "1.1.4", 404 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 405 | "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", 406 | "dev": true 407 | }, 408 | "node_modules/color-convert": { 409 | "version": "2.0.1", 410 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 411 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 412 | "dev": true, 413 | "dependencies": { 414 | "color-name": "~1.1.4" 415 | }, 416 | "engines": { 417 | "node": ">=7.0.0" 418 | } 419 | }, 420 | "node_modules/color-name": { 421 | "version": "1.1.4", 422 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 423 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 424 | "dev": true 425 | }, 426 | "node_modules/comment-parser": { 427 | "version": "1.4.1", 428 | "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", 429 | "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", 430 | "dev": true, 431 | "engines": { 432 | "node": ">= 12.0.0" 433 | } 434 | }, 435 | "node_modules/concat-map": { 436 | "version": "0.0.1", 437 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 438 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 439 | "dev": true 440 | }, 441 | "node_modules/cross-spawn": { 442 | "version": "7.0.3", 443 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 444 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 445 | "dev": true, 446 | "dependencies": { 447 | "path-key": "^3.1.0", 448 | "shebang-command": "^2.0.0", 449 | "which": "^2.0.1" 450 | }, 451 | "engines": { 452 | "node": ">= 8" 453 | } 454 | }, 455 | "node_modules/debug": { 456 | "version": "4.3.7", 457 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 458 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 459 | "dev": true, 460 | "dependencies": { 461 | "ms": "^2.1.3" 462 | }, 463 | "engines": { 464 | "node": ">=6.0" 465 | }, 466 | "peerDependenciesMeta": { 467 | "supports-color": { 468 | "optional": true 469 | } 470 | } 471 | }, 472 | "node_modules/deep-is": { 473 | "version": "0.1.4", 474 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 475 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 476 | "dev": true 477 | }, 478 | "node_modules/end-of-stream": { 479 | "version": "1.4.4", 480 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 481 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 482 | "dev": true, 483 | "dependencies": { 484 | "once": "^1.4.0" 485 | } 486 | }, 487 | "node_modules/es-module-lexer": { 488 | "version": "1.5.4", 489 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", 490 | "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", 491 | "dev": true 492 | }, 493 | "node_modules/escape-string-regexp": { 494 | "version": "4.0.0", 495 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 496 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 497 | "dev": true, 498 | "engines": { 499 | "node": ">=10" 500 | }, 501 | "funding": { 502 | "url": "https://github.com/sponsors/sindresorhus" 503 | } 504 | }, 505 | "node_modules/eslint": { 506 | "version": "9.14.0", 507 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", 508 | "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", 509 | "dev": true, 510 | "dependencies": { 511 | "@eslint-community/eslint-utils": "^4.2.0", 512 | "@eslint-community/regexpp": "^4.12.1", 513 | "@eslint/config-array": "^0.18.0", 514 | "@eslint/core": "^0.7.0", 515 | "@eslint/eslintrc": "^3.1.0", 516 | "@eslint/js": "9.14.0", 517 | "@eslint/plugin-kit": "^0.2.0", 518 | "@humanfs/node": "^0.16.6", 519 | "@humanwhocodes/module-importer": "^1.0.1", 520 | "@humanwhocodes/retry": "^0.4.0", 521 | "@types/estree": "^1.0.6", 522 | "@types/json-schema": "^7.0.15", 523 | "ajv": "^6.12.4", 524 | "chalk": "^4.0.0", 525 | "cross-spawn": "^7.0.2", 526 | "debug": "^4.3.2", 527 | "escape-string-regexp": "^4.0.0", 528 | "eslint-scope": "^8.2.0", 529 | "eslint-visitor-keys": "^4.2.0", 530 | "espree": "^10.3.0", 531 | "esquery": "^1.5.0", 532 | "esutils": "^2.0.2", 533 | "fast-deep-equal": "^3.1.3", 534 | "file-entry-cache": "^8.0.0", 535 | "find-up": "^5.0.0", 536 | "glob-parent": "^6.0.2", 537 | "ignore": "^5.2.0", 538 | "imurmurhash": "^0.1.4", 539 | "is-glob": "^4.0.0", 540 | "json-stable-stringify-without-jsonify": "^1.0.1", 541 | "lodash.merge": "^4.6.2", 542 | "minimatch": "^3.1.2", 543 | "natural-compare": "^1.4.0", 544 | "optionator": "^0.9.3", 545 | "text-table": "^0.2.0" 546 | }, 547 | "bin": { 548 | "eslint": "bin/eslint.js" 549 | }, 550 | "engines": { 551 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 552 | }, 553 | "funding": { 554 | "url": "https://eslint.org/donate" 555 | }, 556 | "peerDependencies": { 557 | "jiti": "*" 558 | }, 559 | "peerDependenciesMeta": { 560 | "jiti": { 561 | "optional": true 562 | } 563 | } 564 | }, 565 | "node_modules/eslint-config-treesitter": { 566 | "version": "1.0.2", 567 | "resolved": "https://registry.npmjs.org/eslint-config-treesitter/-/eslint-config-treesitter-1.0.2.tgz", 568 | "integrity": "sha512-OkzjA0oaNgYUFkGmo9T2cvRE7cxzh1dgSt0laO8Hdcypp9di8lebldoPivALXFusRb7s54J5exIw1w7l+g85Rg==", 569 | "dev": true, 570 | "dependencies": { 571 | "eslint-plugin-jsdoc": "^50.2.4" 572 | }, 573 | "peerDependencies": { 574 | "eslint": ">= 9" 575 | } 576 | }, 577 | "node_modules/eslint-plugin-jsdoc": { 578 | "version": "50.4.1", 579 | "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.4.1.tgz", 580 | "integrity": "sha512-OXIq+JJQPCLAKL473/esioFOwbXyRE5MAQ4HbZjcp3e+K3zdxt2uDpGs3FR+WezUXNStzEtTfgx15T+JFrVwBA==", 581 | "dev": true, 582 | "dependencies": { 583 | "@es-joy/jsdoccomment": "~0.49.0", 584 | "are-docs-informative": "^0.0.2", 585 | "comment-parser": "1.4.1", 586 | "debug": "^4.3.6", 587 | "escape-string-regexp": "^4.0.0", 588 | "espree": "^10.1.0", 589 | "esquery": "^1.6.0", 590 | "parse-imports": "^2.1.1", 591 | "semver": "^7.6.3", 592 | "spdx-expression-parse": "^4.0.0", 593 | "synckit": "^0.9.1" 594 | }, 595 | "engines": { 596 | "node": ">=18" 597 | }, 598 | "peerDependencies": { 599 | "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" 600 | } 601 | }, 602 | "node_modules/eslint-scope": { 603 | "version": "8.2.0", 604 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", 605 | "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", 606 | "dev": true, 607 | "dependencies": { 608 | "esrecurse": "^4.3.0", 609 | "estraverse": "^5.2.0" 610 | }, 611 | "engines": { 612 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 613 | }, 614 | "funding": { 615 | "url": "https://opencollective.com/eslint" 616 | } 617 | }, 618 | "node_modules/eslint-visitor-keys": { 619 | "version": "3.4.3", 620 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", 621 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", 622 | "dev": true, 623 | "engines": { 624 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 625 | }, 626 | "funding": { 627 | "url": "https://opencollective.com/eslint" 628 | } 629 | }, 630 | "node_modules/eslint/node_modules/eslint-visitor-keys": { 631 | "version": "4.2.0", 632 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", 633 | "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", 634 | "dev": true, 635 | "engines": { 636 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 637 | }, 638 | "funding": { 639 | "url": "https://opencollective.com/eslint" 640 | } 641 | }, 642 | "node_modules/espree": { 643 | "version": "10.3.0", 644 | "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", 645 | "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", 646 | "dev": true, 647 | "dependencies": { 648 | "acorn": "^8.14.0", 649 | "acorn-jsx": "^5.3.2", 650 | "eslint-visitor-keys": "^4.2.0" 651 | }, 652 | "engines": { 653 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 654 | }, 655 | "funding": { 656 | "url": "https://opencollective.com/eslint" 657 | } 658 | }, 659 | "node_modules/espree/node_modules/eslint-visitor-keys": { 660 | "version": "4.2.0", 661 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", 662 | "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", 663 | "dev": true, 664 | "engines": { 665 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 666 | }, 667 | "funding": { 668 | "url": "https://opencollective.com/eslint" 669 | } 670 | }, 671 | "node_modules/esquery": { 672 | "version": "1.6.0", 673 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", 674 | "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", 675 | "dev": true, 676 | "dependencies": { 677 | "estraverse": "^5.1.0" 678 | }, 679 | "engines": { 680 | "node": ">=0.10" 681 | } 682 | }, 683 | "node_modules/esrecurse": { 684 | "version": "4.3.0", 685 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 686 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 687 | "dev": true, 688 | "dependencies": { 689 | "estraverse": "^5.2.0" 690 | }, 691 | "engines": { 692 | "node": ">=4.0" 693 | } 694 | }, 695 | "node_modules/estraverse": { 696 | "version": "5.3.0", 697 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 698 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 699 | "dev": true, 700 | "engines": { 701 | "node": ">=4.0" 702 | } 703 | }, 704 | "node_modules/esutils": { 705 | "version": "2.0.3", 706 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 707 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 708 | "dev": true, 709 | "engines": { 710 | "node": ">=0.10.0" 711 | } 712 | }, 713 | "node_modules/fast-deep-equal": { 714 | "version": "3.1.3", 715 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 716 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 717 | "dev": true 718 | }, 719 | "node_modules/fast-json-stable-stringify": { 720 | "version": "2.1.0", 721 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 722 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 723 | "dev": true 724 | }, 725 | "node_modules/fast-levenshtein": { 726 | "version": "2.0.6", 727 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 728 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 729 | "dev": true 730 | }, 731 | "node_modules/file-entry-cache": { 732 | "version": "8.0.0", 733 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", 734 | "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", 735 | "dev": true, 736 | "dependencies": { 737 | "flat-cache": "^4.0.0" 738 | }, 739 | "engines": { 740 | "node": ">=16.0.0" 741 | } 742 | }, 743 | "node_modules/find-up": { 744 | "version": "5.0.0", 745 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 746 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 747 | "dev": true, 748 | "dependencies": { 749 | "locate-path": "^6.0.0", 750 | "path-exists": "^4.0.0" 751 | }, 752 | "engines": { 753 | "node": ">=10" 754 | }, 755 | "funding": { 756 | "url": "https://github.com/sponsors/sindresorhus" 757 | } 758 | }, 759 | "node_modules/flat-cache": { 760 | "version": "4.0.1", 761 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", 762 | "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", 763 | "dev": true, 764 | "dependencies": { 765 | "flatted": "^3.2.9", 766 | "keyv": "^4.5.4" 767 | }, 768 | "engines": { 769 | "node": ">=16" 770 | } 771 | }, 772 | "node_modules/flatted": { 773 | "version": "3.3.1", 774 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", 775 | "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", 776 | "dev": true 777 | }, 778 | "node_modules/fs-constants": { 779 | "version": "1.0.0", 780 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 781 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", 782 | "dev": true 783 | }, 784 | "node_modules/glob-parent": { 785 | "version": "6.0.2", 786 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 787 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 788 | "dev": true, 789 | "dependencies": { 790 | "is-glob": "^4.0.3" 791 | }, 792 | "engines": { 793 | "node": ">=10.13.0" 794 | } 795 | }, 796 | "node_modules/globals": { 797 | "version": "14.0.0", 798 | "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", 799 | "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", 800 | "dev": true, 801 | "engines": { 802 | "node": ">=18" 803 | }, 804 | "funding": { 805 | "url": "https://github.com/sponsors/sindresorhus" 806 | } 807 | }, 808 | "node_modules/has-flag": { 809 | "version": "4.0.0", 810 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 811 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 812 | "dev": true, 813 | "engines": { 814 | "node": ">=8" 815 | } 816 | }, 817 | "node_modules/ieee754": { 818 | "version": "1.2.1", 819 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 820 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 821 | "dev": true, 822 | "funding": [ 823 | { 824 | "type": "github", 825 | "url": "https://github.com/sponsors/feross" 826 | }, 827 | { 828 | "type": "patreon", 829 | "url": "https://www.patreon.com/feross" 830 | }, 831 | { 832 | "type": "consulting", 833 | "url": "https://feross.org/support" 834 | } 835 | ] 836 | }, 837 | "node_modules/ignore": { 838 | "version": "5.3.2", 839 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", 840 | "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", 841 | "dev": true, 842 | "engines": { 843 | "node": ">= 4" 844 | } 845 | }, 846 | "node_modules/import-fresh": { 847 | "version": "3.3.0", 848 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 849 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 850 | "dev": true, 851 | "dependencies": { 852 | "parent-module": "^1.0.0", 853 | "resolve-from": "^4.0.0" 854 | }, 855 | "engines": { 856 | "node": ">=6" 857 | }, 858 | "funding": { 859 | "url": "https://github.com/sponsors/sindresorhus" 860 | } 861 | }, 862 | "node_modules/imurmurhash": { 863 | "version": "0.1.4", 864 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 865 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 866 | "dev": true, 867 | "engines": { 868 | "node": ">=0.8.19" 869 | } 870 | }, 871 | "node_modules/inherits": { 872 | "version": "2.0.4", 873 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 874 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 875 | "dev": true 876 | }, 877 | "node_modules/is-extglob": { 878 | "version": "2.1.1", 879 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 880 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 881 | "dev": true, 882 | "engines": { 883 | "node": ">=0.10.0" 884 | } 885 | }, 886 | "node_modules/is-glob": { 887 | "version": "4.0.3", 888 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 889 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 890 | "dev": true, 891 | "dependencies": { 892 | "is-extglob": "^2.1.1" 893 | }, 894 | "engines": { 895 | "node": ">=0.10.0" 896 | } 897 | }, 898 | "node_modules/isexe": { 899 | "version": "2.0.0", 900 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 901 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 902 | "dev": true 903 | }, 904 | "node_modules/js-yaml": { 905 | "version": "4.1.0", 906 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 907 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 908 | "dev": true, 909 | "dependencies": { 910 | "argparse": "^2.0.1" 911 | }, 912 | "bin": { 913 | "js-yaml": "bin/js-yaml.js" 914 | } 915 | }, 916 | "node_modules/jsdoc-type-pratt-parser": { 917 | "version": "4.1.0", 918 | "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", 919 | "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", 920 | "dev": true, 921 | "engines": { 922 | "node": ">=12.0.0" 923 | } 924 | }, 925 | "node_modules/json-buffer": { 926 | "version": "3.0.1", 927 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 928 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", 929 | "dev": true 930 | }, 931 | "node_modules/json-schema-traverse": { 932 | "version": "0.4.1", 933 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 934 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 935 | "dev": true 936 | }, 937 | "node_modules/json-stable-stringify-without-jsonify": { 938 | "version": "1.0.1", 939 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 940 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 941 | "dev": true 942 | }, 943 | "node_modules/keyv": { 944 | "version": "4.5.4", 945 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", 946 | "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", 947 | "dev": true, 948 | "dependencies": { 949 | "json-buffer": "3.0.1" 950 | } 951 | }, 952 | "node_modules/levn": { 953 | "version": "0.4.1", 954 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 955 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 956 | "dev": true, 957 | "dependencies": { 958 | "prelude-ls": "^1.2.1", 959 | "type-check": "~0.4.0" 960 | }, 961 | "engines": { 962 | "node": ">= 0.8.0" 963 | } 964 | }, 965 | "node_modules/locate-path": { 966 | "version": "6.0.0", 967 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 968 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 969 | "dev": true, 970 | "dependencies": { 971 | "p-locate": "^5.0.0" 972 | }, 973 | "engines": { 974 | "node": ">=10" 975 | }, 976 | "funding": { 977 | "url": "https://github.com/sponsors/sindresorhus" 978 | } 979 | }, 980 | "node_modules/lodash.merge": { 981 | "version": "4.6.2", 982 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 983 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 984 | "dev": true 985 | }, 986 | "node_modules/minimatch": { 987 | "version": "3.1.2", 988 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 989 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 990 | "dev": true, 991 | "dependencies": { 992 | "brace-expansion": "^1.1.7" 993 | }, 994 | "engines": { 995 | "node": "*" 996 | } 997 | }, 998 | "node_modules/minimist": { 999 | "version": "1.2.8", 1000 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1001 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 1002 | "dev": true, 1003 | "funding": { 1004 | "url": "https://github.com/sponsors/ljharb" 1005 | } 1006 | }, 1007 | "node_modules/mkdirp-classic": { 1008 | "version": "0.5.3", 1009 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 1010 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", 1011 | "dev": true 1012 | }, 1013 | "node_modules/ms": { 1014 | "version": "2.1.3", 1015 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1016 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1017 | "dev": true 1018 | }, 1019 | "node_modules/natural-compare": { 1020 | "version": "1.4.0", 1021 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1022 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 1023 | "dev": true 1024 | }, 1025 | "node_modules/node-abi": { 1026 | "version": "3.62.0", 1027 | "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.62.0.tgz", 1028 | "integrity": "sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==", 1029 | "dev": true, 1030 | "dependencies": { 1031 | "semver": "^7.3.5" 1032 | }, 1033 | "engines": { 1034 | "node": ">=10" 1035 | } 1036 | }, 1037 | "node_modules/node-addon-api": { 1038 | "version": "8.2.2", 1039 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.2.2.tgz", 1040 | "integrity": "sha512-9emqXAKhVoNrQ792nLI/wpzPpJ/bj/YXxW0CvAau1+RdGBcCRF1Dmz7719zgVsQNrzHl9Tzn3ImZ4qWFarWL0A==", 1041 | "engines": { 1042 | "node": "^18 || ^20 || >= 21" 1043 | } 1044 | }, 1045 | "node_modules/node-gyp-build": { 1046 | "version": "4.8.2", 1047 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", 1048 | "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", 1049 | "bin": { 1050 | "node-gyp-build": "bin.js", 1051 | "node-gyp-build-optional": "optional.js", 1052 | "node-gyp-build-test": "build-test.js" 1053 | } 1054 | }, 1055 | "node_modules/npm-run-path": { 1056 | "version": "3.1.0", 1057 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", 1058 | "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", 1059 | "dev": true, 1060 | "dependencies": { 1061 | "path-key": "^3.0.0" 1062 | }, 1063 | "engines": { 1064 | "node": ">=8" 1065 | } 1066 | }, 1067 | "node_modules/once": { 1068 | "version": "1.4.0", 1069 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1070 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1071 | "dev": true, 1072 | "dependencies": { 1073 | "wrappy": "1" 1074 | } 1075 | }, 1076 | "node_modules/optionator": { 1077 | "version": "0.9.3", 1078 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", 1079 | "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", 1080 | "dev": true, 1081 | "dependencies": { 1082 | "@aashutoshrathi/word-wrap": "^1.2.3", 1083 | "deep-is": "^0.1.3", 1084 | "fast-levenshtein": "^2.0.6", 1085 | "levn": "^0.4.1", 1086 | "prelude-ls": "^1.2.1", 1087 | "type-check": "^0.4.0" 1088 | }, 1089 | "engines": { 1090 | "node": ">= 0.8.0" 1091 | } 1092 | }, 1093 | "node_modules/p-limit": { 1094 | "version": "3.1.0", 1095 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1096 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1097 | "dev": true, 1098 | "dependencies": { 1099 | "yocto-queue": "^0.1.0" 1100 | }, 1101 | "engines": { 1102 | "node": ">=10" 1103 | }, 1104 | "funding": { 1105 | "url": "https://github.com/sponsors/sindresorhus" 1106 | } 1107 | }, 1108 | "node_modules/p-locate": { 1109 | "version": "5.0.0", 1110 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1111 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1112 | "dev": true, 1113 | "dependencies": { 1114 | "p-limit": "^3.0.2" 1115 | }, 1116 | "engines": { 1117 | "node": ">=10" 1118 | }, 1119 | "funding": { 1120 | "url": "https://github.com/sponsors/sindresorhus" 1121 | } 1122 | }, 1123 | "node_modules/parent-module": { 1124 | "version": "1.0.1", 1125 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1126 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1127 | "dev": true, 1128 | "dependencies": { 1129 | "callsites": "^3.0.0" 1130 | }, 1131 | "engines": { 1132 | "node": ">=6" 1133 | } 1134 | }, 1135 | "node_modules/parse-imports": { 1136 | "version": "2.2.1", 1137 | "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", 1138 | "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", 1139 | "dev": true, 1140 | "dependencies": { 1141 | "es-module-lexer": "^1.5.3", 1142 | "slashes": "^3.0.12" 1143 | }, 1144 | "engines": { 1145 | "node": ">= 18" 1146 | } 1147 | }, 1148 | "node_modules/path-exists": { 1149 | "version": "4.0.0", 1150 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1151 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1152 | "dev": true, 1153 | "engines": { 1154 | "node": ">=8" 1155 | } 1156 | }, 1157 | "node_modules/path-key": { 1158 | "version": "3.1.1", 1159 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1160 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1161 | "dev": true, 1162 | "engines": { 1163 | "node": ">=8" 1164 | } 1165 | }, 1166 | "node_modules/prebuildify": { 1167 | "version": "6.0.1", 1168 | "resolved": "https://registry.npmjs.org/prebuildify/-/prebuildify-6.0.1.tgz", 1169 | "integrity": "sha512-8Y2oOOateom/s8dNBsGIcnm6AxPmLH4/nanQzL5lQMU+sC0CMhzARZHizwr36pUPLdvBnOkCNQzxg4djuFSgIw==", 1170 | "dev": true, 1171 | "dependencies": { 1172 | "minimist": "^1.2.5", 1173 | "mkdirp-classic": "^0.5.3", 1174 | "node-abi": "^3.3.0", 1175 | "npm-run-path": "^3.1.0", 1176 | "pump": "^3.0.0", 1177 | "tar-fs": "^2.1.0" 1178 | }, 1179 | "bin": { 1180 | "prebuildify": "bin.js" 1181 | } 1182 | }, 1183 | "node_modules/prelude-ls": { 1184 | "version": "1.2.1", 1185 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1186 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1187 | "dev": true, 1188 | "engines": { 1189 | "node": ">= 0.8.0" 1190 | } 1191 | }, 1192 | "node_modules/pump": { 1193 | "version": "3.0.0", 1194 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1195 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1196 | "dev": true, 1197 | "dependencies": { 1198 | "end-of-stream": "^1.1.0", 1199 | "once": "^1.3.1" 1200 | } 1201 | }, 1202 | "node_modules/punycode": { 1203 | "version": "2.3.1", 1204 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 1205 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 1206 | "dev": true, 1207 | "engines": { 1208 | "node": ">=6" 1209 | } 1210 | }, 1211 | "node_modules/readable-stream": { 1212 | "version": "3.6.2", 1213 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1214 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1215 | "dev": true, 1216 | "dependencies": { 1217 | "inherits": "^2.0.3", 1218 | "string_decoder": "^1.1.1", 1219 | "util-deprecate": "^1.0.1" 1220 | }, 1221 | "engines": { 1222 | "node": ">= 6" 1223 | } 1224 | }, 1225 | "node_modules/resolve-from": { 1226 | "version": "4.0.0", 1227 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1228 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1229 | "dev": true, 1230 | "engines": { 1231 | "node": ">=4" 1232 | } 1233 | }, 1234 | "node_modules/safe-buffer": { 1235 | "version": "5.2.1", 1236 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1237 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1238 | "dev": true, 1239 | "funding": [ 1240 | { 1241 | "type": "github", 1242 | "url": "https://github.com/sponsors/feross" 1243 | }, 1244 | { 1245 | "type": "patreon", 1246 | "url": "https://www.patreon.com/feross" 1247 | }, 1248 | { 1249 | "type": "consulting", 1250 | "url": "https://feross.org/support" 1251 | } 1252 | ] 1253 | }, 1254 | "node_modules/semver": { 1255 | "version": "7.6.3", 1256 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", 1257 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", 1258 | "dev": true, 1259 | "bin": { 1260 | "semver": "bin/semver.js" 1261 | }, 1262 | "engines": { 1263 | "node": ">=10" 1264 | } 1265 | }, 1266 | "node_modules/shebang-command": { 1267 | "version": "2.0.0", 1268 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1269 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1270 | "dev": true, 1271 | "dependencies": { 1272 | "shebang-regex": "^3.0.0" 1273 | }, 1274 | "engines": { 1275 | "node": ">=8" 1276 | } 1277 | }, 1278 | "node_modules/shebang-regex": { 1279 | "version": "3.0.0", 1280 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1281 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1282 | "dev": true, 1283 | "engines": { 1284 | "node": ">=8" 1285 | } 1286 | }, 1287 | "node_modules/slashes": { 1288 | "version": "3.0.12", 1289 | "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", 1290 | "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", 1291 | "dev": true 1292 | }, 1293 | "node_modules/spdx-exceptions": { 1294 | "version": "2.5.0", 1295 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", 1296 | "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", 1297 | "dev": true 1298 | }, 1299 | "node_modules/spdx-expression-parse": { 1300 | "version": "4.0.0", 1301 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", 1302 | "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", 1303 | "dev": true, 1304 | "dependencies": { 1305 | "spdx-exceptions": "^2.1.0", 1306 | "spdx-license-ids": "^3.0.0" 1307 | } 1308 | }, 1309 | "node_modules/spdx-license-ids": { 1310 | "version": "3.0.20", 1311 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", 1312 | "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", 1313 | "dev": true 1314 | }, 1315 | "node_modules/string_decoder": { 1316 | "version": "1.3.0", 1317 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1318 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1319 | "dev": true, 1320 | "dependencies": { 1321 | "safe-buffer": "~5.2.0" 1322 | } 1323 | }, 1324 | "node_modules/strip-json-comments": { 1325 | "version": "3.1.1", 1326 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1327 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1328 | "dev": true, 1329 | "engines": { 1330 | "node": ">=8" 1331 | }, 1332 | "funding": { 1333 | "url": "https://github.com/sponsors/sindresorhus" 1334 | } 1335 | }, 1336 | "node_modules/supports-color": { 1337 | "version": "7.2.0", 1338 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1339 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1340 | "dev": true, 1341 | "dependencies": { 1342 | "has-flag": "^4.0.0" 1343 | }, 1344 | "engines": { 1345 | "node": ">=8" 1346 | } 1347 | }, 1348 | "node_modules/synckit": { 1349 | "version": "0.9.2", 1350 | "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", 1351 | "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", 1352 | "dev": true, 1353 | "dependencies": { 1354 | "@pkgr/core": "^0.1.0", 1355 | "tslib": "^2.6.2" 1356 | }, 1357 | "engines": { 1358 | "node": "^14.18.0 || >=16.0.0" 1359 | }, 1360 | "funding": { 1361 | "url": "https://opencollective.com/unts" 1362 | } 1363 | }, 1364 | "node_modules/tar-fs": { 1365 | "version": "2.1.1", 1366 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", 1367 | "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", 1368 | "dev": true, 1369 | "dependencies": { 1370 | "chownr": "^1.1.1", 1371 | "mkdirp-classic": "^0.5.2", 1372 | "pump": "^3.0.0", 1373 | "tar-stream": "^2.1.4" 1374 | } 1375 | }, 1376 | "node_modules/tar-stream": { 1377 | "version": "2.2.0", 1378 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", 1379 | "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", 1380 | "dev": true, 1381 | "dependencies": { 1382 | "bl": "^4.0.3", 1383 | "end-of-stream": "^1.4.1", 1384 | "fs-constants": "^1.0.0", 1385 | "inherits": "^2.0.3", 1386 | "readable-stream": "^3.1.1" 1387 | }, 1388 | "engines": { 1389 | "node": ">=6" 1390 | } 1391 | }, 1392 | "node_modules/text-table": { 1393 | "version": "0.2.0", 1394 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1395 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", 1396 | "dev": true 1397 | }, 1398 | "node_modules/tree-sitter": { 1399 | "version": "0.21.1", 1400 | "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz", 1401 | "integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==", 1402 | "hasInstallScript": true, 1403 | "optional": true, 1404 | "peer": true, 1405 | "dependencies": { 1406 | "node-addon-api": "^8.0.0", 1407 | "node-gyp-build": "^4.8.0" 1408 | } 1409 | }, 1410 | "node_modules/tree-sitter-cli": { 1411 | "version": "0.24.4", 1412 | "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.24.4.tgz", 1413 | "integrity": "sha512-I4sdtDidnujYL0tR0Re9q0UJt5KrITf2m+GMHjT4LH6IC6kpM6eLzSR7RS36Z4t5ZQBjDHvg2QUJHAWQi3P2TA==", 1414 | "dev": true, 1415 | "hasInstallScript": true, 1416 | "bin": { 1417 | "tree-sitter": "cli.js" 1418 | }, 1419 | "engines": { 1420 | "node": ">=12.0.0" 1421 | } 1422 | }, 1423 | "node_modules/tslib": { 1424 | "version": "2.7.0", 1425 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", 1426 | "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", 1427 | "dev": true 1428 | }, 1429 | "node_modules/type-check": { 1430 | "version": "0.4.0", 1431 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1432 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1433 | "dev": true, 1434 | "dependencies": { 1435 | "prelude-ls": "^1.2.1" 1436 | }, 1437 | "engines": { 1438 | "node": ">= 0.8.0" 1439 | } 1440 | }, 1441 | "node_modules/uri-js": { 1442 | "version": "4.4.1", 1443 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1444 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1445 | "dev": true, 1446 | "dependencies": { 1447 | "punycode": "^2.1.0" 1448 | } 1449 | }, 1450 | "node_modules/util-deprecate": { 1451 | "version": "1.0.2", 1452 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1453 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 1454 | "dev": true 1455 | }, 1456 | "node_modules/which": { 1457 | "version": "2.0.2", 1458 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1459 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1460 | "dev": true, 1461 | "dependencies": { 1462 | "isexe": "^2.0.0" 1463 | }, 1464 | "bin": { 1465 | "node-which": "bin/node-which" 1466 | }, 1467 | "engines": { 1468 | "node": ">= 8" 1469 | } 1470 | }, 1471 | "node_modules/wrappy": { 1472 | "version": "1.0.2", 1473 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1474 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 1475 | "dev": true 1476 | }, 1477 | "node_modules/yocto-queue": { 1478 | "version": "0.1.0", 1479 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 1480 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 1481 | "dev": true, 1482 | "engines": { 1483 | "node": ">=10" 1484 | }, 1485 | "funding": { 1486 | "url": "https://github.com/sponsors/sindresorhus" 1487 | } 1488 | } 1489 | } 1490 | } 1491 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-jsdoc", 3 | "version": "0.23.2", 4 | "description": "JSDoc grammar for tree-sitter", 5 | "repository": "https://github.com/tree-sitter/tree-sitter-jsdoc", 6 | "license": "MIT", 7 | "author": { 8 | "name": "Max Brunsfeld", 9 | "email": "maxbrunsfeld@gmail.com" 10 | }, 11 | "maintainers": [ 12 | { 13 | "name": "Amaan Qureshi", 14 | "email": "amaanq12@gmail.com" 15 | } 16 | ], 17 | "main": "bindings/node", 18 | "types": "bindings/node", 19 | "keywords": [ 20 | "incremental", 21 | "parsing", 22 | "tree-sitter", 23 | "jsdoc" 24 | ], 25 | "files": [ 26 | "grammar.js", 27 | "tree-sitter.json", 28 | "binding.gyp", 29 | "prebuilds/**", 30 | "bindings/node/*", 31 | "queries/*", 32 | "src/**", 33 | "*.wasm" 34 | ], 35 | "dependencies": { 36 | "node-addon-api": "^8.2.2", 37 | "node-gyp-build": "^4.8.2" 38 | }, 39 | "devDependencies": { 40 | "eslint": ">=9.14.0", 41 | "eslint-config-treesitter": "^1.0.2", 42 | "tree-sitter-cli": "^0.24.4", 43 | "prebuildify": "^6.0.1" 44 | }, 45 | "peerDependencies": { 46 | "tree-sitter": "^0.21.1" 47 | }, 48 | "peerDependenciesMeta": { 49 | "tree-sitter": { 50 | "optional": true 51 | } 52 | }, 53 | "scripts": { 54 | "install": "node-gyp-build", 55 | "lint": "eslint grammar.js", 56 | "prestart": "tree-sitter build --wasm", 57 | "start": "tree-sitter playground", 58 | "test": "node --test bindings/node/*_test.js" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "tree-sitter-jsdoc" 7 | description = "JSDoc grammar for tree-sitter" 8 | version = "0.23.2" 9 | keywords = ["incremental", "parsing", "tree-sitter", "jsdoc"] 10 | classifiers = [ 11 | "Intended Audience :: Developers", 12 | "License :: OSI Approved :: MIT License", 13 | "Topic :: Software Development :: Compilers", 14 | "Topic :: Text Processing :: Linguistic", 15 | "Typing :: Typed", 16 | ] 17 | authors = [ 18 | { name = "Max Brunsfeld", email = "maxbrunsfeld@gmail.com" }, 19 | { name = "Amaan Qureshi", email = "amaanq12@gmail.com" }, 20 | ] 21 | requires-python = ">=3.9" 22 | license.text = "MIT" 23 | readme = "README.md" 24 | 25 | [project.urls] 26 | Homepage = "https://github.com/tree-sitter/tree-sitter-jsdoc" 27 | 28 | [project.optional-dependencies] 29 | core = ["tree-sitter~=0.22"] 30 | 31 | [tool.cibuildwheel] 32 | build = "cp39-*" 33 | build-frontend = "build" 34 | -------------------------------------------------------------------------------- /queries/highlights.scm: -------------------------------------------------------------------------------- 1 | (tag_name) @keyword 2 | (type) @type 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from os.path import isdir, join 2 | from platform import system 3 | 4 | from setuptools import Extension, find_packages, setup 5 | from setuptools.command.build import build 6 | from wheel.bdist_wheel import bdist_wheel 7 | 8 | 9 | class Build(build): 10 | def run(self): 11 | if isdir("queries"): 12 | dest = join(self.build_lib, "tree_sitter_jsdoc", "queries") 13 | self.copy_tree("queries", dest) 14 | super().run() 15 | 16 | 17 | class BdistWheel(bdist_wheel): 18 | def get_tag(self): 19 | python, abi, platform = super().get_tag() 20 | if python.startswith("cp"): 21 | python, abi = "cp39", "abi3" 22 | return python, abi, platform 23 | 24 | 25 | setup( 26 | packages=find_packages("bindings/python"), 27 | package_dir={"": "bindings/python"}, 28 | package_data={ 29 | "tree_sitter_jsdoc": ["*.pyi", "py.typed"], 30 | "tree_sitter_jsdoc.queries": ["*.scm"], 31 | }, 32 | ext_package="tree_sitter_jsdoc", 33 | ext_modules=[ 34 | Extension( 35 | name="_binding", 36 | sources=[ 37 | "bindings/python/tree_sitter_jsdoc/binding.c", 38 | "src/parser.c", 39 | "src/scanner.c", 40 | ], 41 | extra_compile_args=[ 42 | "-std=c11", 43 | "-fvisibility=hidden", 44 | ] if system() != "Windows" else [ 45 | "/std:c11", 46 | "/utf-8", 47 | ], 48 | define_macros=[ 49 | ("Py_LIMITED_API", "0x03090000"), 50 | ("PY_SSIZE_T_CLEAN", None), 51 | ("TREE_SITTER_HIDE_SYMBOLS", None), 52 | ], 53 | include_dirs=["src"], 54 | py_limited_api=True, 55 | ) 56 | ], 57 | cmdclass={ 58 | "build": Build, 59 | "bdist_wheel": BdistWheel 60 | }, 61 | zip_safe=False 62 | ) 63 | -------------------------------------------------------------------------------- /src/grammar.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json", 3 | "name": "jsdoc", 4 | "rules": { 5 | "document": { 6 | "type": "SEQ", 7 | "members": [ 8 | { 9 | "type": "SYMBOL", 10 | "name": "_begin" 11 | }, 12 | { 13 | "type": "CHOICE", 14 | "members": [ 15 | { 16 | "type": "SYMBOL", 17 | "name": "description" 18 | }, 19 | { 20 | "type": "BLANK" 21 | } 22 | ] 23 | }, 24 | { 25 | "type": "REPEAT", 26 | "content": { 27 | "type": "SYMBOL", 28 | "name": "tag" 29 | } 30 | }, 31 | { 32 | "type": "SYMBOL", 33 | "name": "_end" 34 | } 35 | ] 36 | }, 37 | "description": { 38 | "type": "SEQ", 39 | "members": [ 40 | { 41 | "type": "SYMBOL", 42 | "name": "_text" 43 | }, 44 | { 45 | "type": "REPEAT", 46 | "content": { 47 | "type": "CHOICE", 48 | "members": [ 49 | { 50 | "type": "SYMBOL", 51 | "name": "_text" 52 | }, 53 | { 54 | "type": "SYMBOL", 55 | "name": "inline_tag" 56 | }, 57 | { 58 | "type": "SYMBOL", 59 | "name": "_inline_tag_false_positive" 60 | } 61 | ] 62 | } 63 | } 64 | ] 65 | }, 66 | "tag": { 67 | "type": "CHOICE", 68 | "members": [ 69 | { 70 | "type": "SEQ", 71 | "members": [ 72 | { 73 | "type": "ALIAS", 74 | "content": { 75 | "type": "SYMBOL", 76 | "name": "tag_name_with_argument" 77 | }, 78 | "named": true, 79 | "value": "tag_name" 80 | }, 81 | { 82 | "type": "CHOICE", 83 | "members": [ 84 | { 85 | "type": "SEQ", 86 | "members": [ 87 | { 88 | "type": "STRING", 89 | "value": "{" 90 | }, 91 | { 92 | "type": "SYMBOL", 93 | "name": "type" 94 | }, 95 | { 96 | "type": "STRING", 97 | "value": "}" 98 | } 99 | ] 100 | }, 101 | { 102 | "type": "BLANK" 103 | } 104 | ] 105 | }, 106 | { 107 | "type": "CHOICE", 108 | "members": [ 109 | { 110 | "type": "SYMBOL", 111 | "name": "_expression" 112 | }, 113 | { 114 | "type": "BLANK" 115 | } 116 | ] 117 | }, 118 | { 119 | "type": "CHOICE", 120 | "members": [ 121 | { 122 | "type": "SYMBOL", 123 | "name": "description" 124 | }, 125 | { 126 | "type": "BLANK" 127 | } 128 | ] 129 | } 130 | ] 131 | }, 132 | { 133 | "type": "SEQ", 134 | "members": [ 135 | { 136 | "type": "ALIAS", 137 | "content": { 138 | "type": "SYMBOL", 139 | "name": "tag_name_with_type" 140 | }, 141 | "named": true, 142 | "value": "tag_name" 143 | }, 144 | { 145 | "type": "CHOICE", 146 | "members": [ 147 | { 148 | "type": "SEQ", 149 | "members": [ 150 | { 151 | "type": "STRING", 152 | "value": "{" 153 | }, 154 | { 155 | "type": "SYMBOL", 156 | "name": "type" 157 | }, 158 | { 159 | "type": "STRING", 160 | "value": "}" 161 | } 162 | ] 163 | }, 164 | { 165 | "type": "BLANK" 166 | } 167 | ] 168 | }, 169 | { 170 | "type": "CHOICE", 171 | "members": [ 172 | { 173 | "type": "SYMBOL", 174 | "name": "description" 175 | }, 176 | { 177 | "type": "BLANK" 178 | } 179 | ] 180 | } 181 | ] 182 | }, 183 | { 184 | "type": "SEQ", 185 | "members": [ 186 | { 187 | "type": "SYMBOL", 188 | "name": "tag_name" 189 | }, 190 | { 191 | "type": "CHOICE", 192 | "members": [ 193 | { 194 | "type": "SYMBOL", 195 | "name": "description" 196 | }, 197 | { 198 | "type": "BLANK" 199 | } 200 | ] 201 | } 202 | ] 203 | } 204 | ] 205 | }, 206 | "inline_tag": { 207 | "type": "SEQ", 208 | "members": [ 209 | { 210 | "type": "STRING", 211 | "value": "{" 212 | }, 213 | { 214 | "type": "SYMBOL", 215 | "name": "tag_name" 216 | }, 217 | { 218 | "type": "SYMBOL", 219 | "name": "description" 220 | }, 221 | { 222 | "type": "STRING", 223 | "value": "}" 224 | } 225 | ] 226 | }, 227 | "_inline_tag_false_positive": { 228 | "type": "TOKEN", 229 | "content": { 230 | "type": "PREC_LEFT", 231 | "value": 1, 232 | "content": { 233 | "type": "PATTERN", 234 | "value": "\\{[^@}]+\\}?" 235 | } 236 | } 237 | }, 238 | "tag_name_with_argument": { 239 | "type": "TOKEN", 240 | "content": { 241 | "type": "CHOICE", 242 | "members": [ 243 | { 244 | "type": "STRING", 245 | "value": "@access" 246 | }, 247 | { 248 | "type": "STRING", 249 | "value": "@alias" 250 | }, 251 | { 252 | "type": "STRING", 253 | "value": "@api" 254 | }, 255 | { 256 | "type": "STRING", 257 | "value": "@augments" 258 | }, 259 | { 260 | "type": "STRING", 261 | "value": "@borrows" 262 | }, 263 | { 264 | "type": "STRING", 265 | "value": "@callback" 266 | }, 267 | { 268 | "type": "STRING", 269 | "value": "@constructor" 270 | }, 271 | { 272 | "type": "STRING", 273 | "value": "@event" 274 | }, 275 | { 276 | "type": "STRING", 277 | "value": "@exports" 278 | }, 279 | { 280 | "type": "STRING", 281 | "value": "@external" 282 | }, 283 | { 284 | "type": "STRING", 285 | "value": "@extends" 286 | }, 287 | { 288 | "type": "STRING", 289 | "value": "@fires" 290 | }, 291 | { 292 | "type": "STRING", 293 | "value": "@function" 294 | }, 295 | { 296 | "type": "STRING", 297 | "value": "@mixes" 298 | }, 299 | { 300 | "type": "STRING", 301 | "value": "@name" 302 | }, 303 | { 304 | "type": "STRING", 305 | "value": "@namespace" 306 | }, 307 | { 308 | "type": "STRING", 309 | "value": "@param" 310 | }, 311 | { 312 | "type": "STRING", 313 | "value": "@property" 314 | }, 315 | { 316 | "type": "STRING", 317 | "value": "@prop" 318 | }, 319 | { 320 | "type": "STRING", 321 | "value": "@satisfies" 322 | }, 323 | { 324 | "type": "STRING", 325 | "value": "@typedef" 326 | } 327 | ] 328 | } 329 | }, 330 | "tag_name_with_type": { 331 | "type": "TOKEN", 332 | "content": { 333 | "type": "CHOICE", 334 | "members": [ 335 | { 336 | "type": "STRING", 337 | "value": "@return" 338 | }, 339 | { 340 | "type": "STRING", 341 | "value": "@returns" 342 | }, 343 | { 344 | "type": "STRING", 345 | "value": "@throw" 346 | }, 347 | { 348 | "type": "STRING", 349 | "value": "@throws" 350 | }, 351 | { 352 | "type": "STRING", 353 | "value": "@type" 354 | } 355 | ] 356 | } 357 | }, 358 | "tag_name": { 359 | "type": "PATTERN", 360 | "value": "@[a-zA-Z_]+" 361 | }, 362 | "_expression": { 363 | "type": "CHOICE", 364 | "members": [ 365 | { 366 | "type": "SYMBOL", 367 | "name": "identifier" 368 | }, 369 | { 370 | "type": "SYMBOL", 371 | "name": "optional_identifier" 372 | }, 373 | { 374 | "type": "SYMBOL", 375 | "name": "member_expression" 376 | }, 377 | { 378 | "type": "SYMBOL", 379 | "name": "path_expression" 380 | }, 381 | { 382 | "type": "SYMBOL", 383 | "name": "qualified_expression" 384 | } 385 | ] 386 | }, 387 | "qualified_expression": { 388 | "type": "PREC", 389 | "value": 1, 390 | "content": { 391 | "type": "SEQ", 392 | "members": [ 393 | { 394 | "type": "SYMBOL", 395 | "name": "identifier" 396 | }, 397 | { 398 | "type": "STRING", 399 | "value": ":" 400 | }, 401 | { 402 | "type": "SYMBOL", 403 | "name": "_expression" 404 | } 405 | ] 406 | } 407 | }, 408 | "path_expression": { 409 | "type": "PREC", 410 | "value": 2, 411 | "content": { 412 | "type": "SEQ", 413 | "members": [ 414 | { 415 | "type": "SYMBOL", 416 | "name": "identifier" 417 | }, 418 | { 419 | "type": "IMMEDIATE_TOKEN", 420 | "content": { 421 | "type": "STRING", 422 | "value": "/" 423 | } 424 | }, 425 | { 426 | "type": "SYMBOL", 427 | "name": "identifier" 428 | } 429 | ] 430 | } 431 | }, 432 | "member_expression": { 433 | "type": "SEQ", 434 | "members": [ 435 | { 436 | "type": "SYMBOL", 437 | "name": "_expression" 438 | }, 439 | { 440 | "type": "CHOICE", 441 | "members": [ 442 | { 443 | "type": "STRING", 444 | "value": "." 445 | }, 446 | { 447 | "type": "STRING", 448 | "value": "#" 449 | }, 450 | { 451 | "type": "STRING", 452 | "value": "~" 453 | } 454 | ] 455 | }, 456 | { 457 | "type": "CHOICE", 458 | "members": [ 459 | { 460 | "type": "SYMBOL", 461 | "name": "identifier" 462 | }, 463 | { 464 | "type": "SYMBOL", 465 | "name": "qualified_expression" 466 | } 467 | ] 468 | } 469 | ] 470 | }, 471 | "optional_identifier": { 472 | "type": "SEQ", 473 | "members": [ 474 | { 475 | "type": "STRING", 476 | "value": "[" 477 | }, 478 | { 479 | "type": "SYMBOL", 480 | "name": "identifier" 481 | }, 482 | { 483 | "type": "STRING", 484 | "value": "]" 485 | } 486 | ] 487 | }, 488 | "identifier": { 489 | "type": "PATTERN", 490 | "value": "[a-zA-Z_$][a-zA-Z_$0-9]*" 491 | }, 492 | "_text": { 493 | "type": "TOKEN", 494 | "content": { 495 | "type": "PREC", 496 | "value": -1, 497 | "content": { 498 | "type": "PATTERN", 499 | "value": "[^*{}@\\s][^*{}\\n]*([^*/{}\\n][^*{}\\n]*\\*+)*" 500 | } 501 | } 502 | }, 503 | "_begin": { 504 | "type": "TOKEN", 505 | "content": { 506 | "type": "SEQ", 507 | "members": [ 508 | { 509 | "type": "STRING", 510 | "value": "/" 511 | }, 512 | { 513 | "type": "REPEAT", 514 | "content": { 515 | "type": "STRING", 516 | "value": "*" 517 | } 518 | } 519 | ] 520 | } 521 | }, 522 | "_end": { 523 | "type": "STRING", 524 | "value": "/" 525 | } 526 | }, 527 | "extras": [ 528 | { 529 | "type": "TOKEN", 530 | "content": { 531 | "type": "CHOICE", 532 | "members": [ 533 | { 534 | "type": "SEQ", 535 | "members": [ 536 | { 537 | "type": "PATTERN", 538 | "value": "\\n" 539 | }, 540 | { 541 | "type": "PATTERN", 542 | "value": "[ \\t]*" 543 | }, 544 | { 545 | "type": "REPEAT", 546 | "content": { 547 | "type": "SEQ", 548 | "members": [ 549 | { 550 | "type": "STRING", 551 | "value": "*" 552 | }, 553 | { 554 | "type": "PATTERN", 555 | "value": "[ \\t]*" 556 | } 557 | ] 558 | } 559 | } 560 | ] 561 | }, 562 | { 563 | "type": "PATTERN", 564 | "value": "\\s" 565 | } 566 | ] 567 | } 568 | } 569 | ], 570 | "conflicts": [], 571 | "precedences": [], 572 | "externals": [ 573 | { 574 | "type": "SYMBOL", 575 | "name": "type" 576 | } 577 | ], 578 | "inline": [], 579 | "supertypes": [] 580 | } 581 | -------------------------------------------------------------------------------- /src/node-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "description", 4 | "named": true, 5 | "fields": {}, 6 | "children": { 7 | "multiple": true, 8 | "required": false, 9 | "types": [ 10 | { 11 | "type": "inline_tag", 12 | "named": true 13 | } 14 | ] 15 | } 16 | }, 17 | { 18 | "type": "document", 19 | "named": true, 20 | "root": true, 21 | "fields": {}, 22 | "children": { 23 | "multiple": true, 24 | "required": false, 25 | "types": [ 26 | { 27 | "type": "description", 28 | "named": true 29 | }, 30 | { 31 | "type": "tag", 32 | "named": true 33 | } 34 | ] 35 | } 36 | }, 37 | { 38 | "type": "inline_tag", 39 | "named": true, 40 | "fields": {}, 41 | "children": { 42 | "multiple": true, 43 | "required": true, 44 | "types": [ 45 | { 46 | "type": "description", 47 | "named": true 48 | }, 49 | { 50 | "type": "tag_name", 51 | "named": true 52 | } 53 | ] 54 | } 55 | }, 56 | { 57 | "type": "member_expression", 58 | "named": true, 59 | "fields": {}, 60 | "children": { 61 | "multiple": true, 62 | "required": true, 63 | "types": [ 64 | { 65 | "type": "identifier", 66 | "named": true 67 | }, 68 | { 69 | "type": "member_expression", 70 | "named": true 71 | }, 72 | { 73 | "type": "optional_identifier", 74 | "named": true 75 | }, 76 | { 77 | "type": "path_expression", 78 | "named": true 79 | }, 80 | { 81 | "type": "qualified_expression", 82 | "named": true 83 | } 84 | ] 85 | } 86 | }, 87 | { 88 | "type": "optional_identifier", 89 | "named": true, 90 | "fields": {}, 91 | "children": { 92 | "multiple": false, 93 | "required": true, 94 | "types": [ 95 | { 96 | "type": "identifier", 97 | "named": true 98 | } 99 | ] 100 | } 101 | }, 102 | { 103 | "type": "path_expression", 104 | "named": true, 105 | "fields": {}, 106 | "children": { 107 | "multiple": true, 108 | "required": true, 109 | "types": [ 110 | { 111 | "type": "identifier", 112 | "named": true 113 | } 114 | ] 115 | } 116 | }, 117 | { 118 | "type": "qualified_expression", 119 | "named": true, 120 | "fields": {}, 121 | "children": { 122 | "multiple": true, 123 | "required": true, 124 | "types": [ 125 | { 126 | "type": "identifier", 127 | "named": true 128 | }, 129 | { 130 | "type": "member_expression", 131 | "named": true 132 | }, 133 | { 134 | "type": "optional_identifier", 135 | "named": true 136 | }, 137 | { 138 | "type": "path_expression", 139 | "named": true 140 | }, 141 | { 142 | "type": "qualified_expression", 143 | "named": true 144 | } 145 | ] 146 | } 147 | }, 148 | { 149 | "type": "tag", 150 | "named": true, 151 | "fields": {}, 152 | "children": { 153 | "multiple": true, 154 | "required": true, 155 | "types": [ 156 | { 157 | "type": "description", 158 | "named": true 159 | }, 160 | { 161 | "type": "identifier", 162 | "named": true 163 | }, 164 | { 165 | "type": "member_expression", 166 | "named": true 167 | }, 168 | { 169 | "type": "optional_identifier", 170 | "named": true 171 | }, 172 | { 173 | "type": "path_expression", 174 | "named": true 175 | }, 176 | { 177 | "type": "qualified_expression", 178 | "named": true 179 | }, 180 | { 181 | "type": "tag_name", 182 | "named": true 183 | }, 184 | { 185 | "type": "type", 186 | "named": true 187 | } 188 | ] 189 | } 190 | }, 191 | { 192 | "type": "#", 193 | "named": false 194 | }, 195 | { 196 | "type": ".", 197 | "named": false 198 | }, 199 | { 200 | "type": "/", 201 | "named": false 202 | }, 203 | { 204 | "type": ":", 205 | "named": false 206 | }, 207 | { 208 | "type": "[", 209 | "named": false 210 | }, 211 | { 212 | "type": "]", 213 | "named": false 214 | }, 215 | { 216 | "type": "identifier", 217 | "named": true 218 | }, 219 | { 220 | "type": "tag_name", 221 | "named": true 222 | }, 223 | { 224 | "type": "type", 225 | "named": true 226 | }, 227 | { 228 | "type": "{", 229 | "named": false 230 | }, 231 | { 232 | "type": "}", 233 | "named": false 234 | }, 235 | { 236 | "type": "~", 237 | "named": false 238 | } 239 | ] -------------------------------------------------------------------------------- /src/scanner.c: -------------------------------------------------------------------------------- 1 | #include "tree_sitter/parser.h" 2 | 3 | enum TokenType { TYPE_TOKEN }; 4 | 5 | void *tree_sitter_jsdoc_external_scanner_create() { return NULL; } 6 | 7 | void tree_sitter_jsdoc_external_scanner_destroy(void *payload) {} 8 | 9 | unsigned tree_sitter_jsdoc_external_scanner_serialize(void *payload, char *buffer) { return 0; } 10 | 11 | void tree_sitter_jsdoc_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {} 12 | 13 | // Scan to the next balanced `}` character. 14 | static bool scan_for_type(TSLexer *lexer) { 15 | int stack = 0; 16 | while (true) { 17 | if (lexer->eof(lexer)) { 18 | return false; 19 | } 20 | switch (lexer->lookahead) { 21 | case '{': 22 | stack++; 23 | break; 24 | case '}': 25 | stack--; 26 | if (stack == -1) { 27 | return true; 28 | } 29 | break; 30 | case '\n': 31 | case '\0': // fallthrough 32 | // Something's gone wrong. 33 | return false; 34 | default:; 35 | } 36 | lexer->advance(lexer, false); 37 | } 38 | } 39 | 40 | bool tree_sitter_jsdoc_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) { 41 | if (valid_symbols[TYPE_TOKEN] && scan_for_type(lexer)) { 42 | lexer->result_symbol = TYPE_TOKEN; 43 | lexer->mark_end(lexer); 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | -------------------------------------------------------------------------------- /src/tree_sitter/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ALLOC_H_ 2 | #define TREE_SITTER_ALLOC_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // Allow clients to override allocation functions 13 | #ifdef TREE_SITTER_REUSE_ALLOCATOR 14 | 15 | extern void *(*ts_current_malloc)(size_t size); 16 | extern void *(*ts_current_calloc)(size_t count, size_t size); 17 | extern void *(*ts_current_realloc)(void *ptr, size_t size); 18 | extern void (*ts_current_free)(void *ptr); 19 | 20 | #ifndef ts_malloc 21 | #define ts_malloc ts_current_malloc 22 | #endif 23 | #ifndef ts_calloc 24 | #define ts_calloc ts_current_calloc 25 | #endif 26 | #ifndef ts_realloc 27 | #define ts_realloc ts_current_realloc 28 | #endif 29 | #ifndef ts_free 30 | #define ts_free ts_current_free 31 | #endif 32 | 33 | #else 34 | 35 | #ifndef ts_malloc 36 | #define ts_malloc malloc 37 | #endif 38 | #ifndef ts_calloc 39 | #define ts_calloc calloc 40 | #endif 41 | #ifndef ts_realloc 42 | #define ts_realloc realloc 43 | #endif 44 | #ifndef ts_free 45 | #define ts_free free 46 | #endif 47 | 48 | #endif 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif // TREE_SITTER_ALLOC_H_ 55 | -------------------------------------------------------------------------------- /src/tree_sitter/array.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ARRAY_H_ 2 | #define TREE_SITTER_ARRAY_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./alloc.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef _MSC_VER 17 | #pragma warning(disable : 4101) 18 | #elif defined(__GNUC__) || defined(__clang__) 19 | #pragma GCC diagnostic push 20 | #pragma GCC diagnostic ignored "-Wunused-variable" 21 | #endif 22 | 23 | #define Array(T) \ 24 | struct { \ 25 | T *contents; \ 26 | uint32_t size; \ 27 | uint32_t capacity; \ 28 | } 29 | 30 | /// Initialize an array. 31 | #define array_init(self) \ 32 | ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) 33 | 34 | /// Create an empty array. 35 | #define array_new() \ 36 | { NULL, 0, 0 } 37 | 38 | /// Get a pointer to the element at a given `index` in the array. 39 | #define array_get(self, _index) \ 40 | (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) 41 | 42 | /// Get a pointer to the first element in the array. 43 | #define array_front(self) array_get(self, 0) 44 | 45 | /// Get a pointer to the last element in the array. 46 | #define array_back(self) array_get(self, (self)->size - 1) 47 | 48 | /// Clear the array, setting its size to zero. Note that this does not free any 49 | /// memory allocated for the array's contents. 50 | #define array_clear(self) ((self)->size = 0) 51 | 52 | /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is 53 | /// less than the array's current capacity, this function has no effect. 54 | #define array_reserve(self, new_capacity) \ 55 | _array__reserve((Array *)(self), array_elem_size(self), new_capacity) 56 | 57 | /// Free any memory allocated for this array. Note that this does not free any 58 | /// memory allocated for the array's contents. 59 | #define array_delete(self) _array__delete((Array *)(self)) 60 | 61 | /// Push a new `element` onto the end of the array. 62 | #define array_push(self, element) \ 63 | (_array__grow((Array *)(self), 1, array_elem_size(self)), \ 64 | (self)->contents[(self)->size++] = (element)) 65 | 66 | /// Increase the array's size by `count` elements. 67 | /// New elements are zero-initialized. 68 | #define array_grow_by(self, count) \ 69 | do { \ 70 | if ((count) == 0) break; \ 71 | _array__grow((Array *)(self), count, array_elem_size(self)); \ 72 | memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ 73 | (self)->size += (count); \ 74 | } while (0) 75 | 76 | /// Append all elements from one array to the end of another. 77 | #define array_push_all(self, other) \ 78 | array_extend((self), (other)->size, (other)->contents) 79 | 80 | /// Append `count` elements to the end of the array, reading their values from the 81 | /// `contents` pointer. 82 | #define array_extend(self, count, contents) \ 83 | _array__splice( \ 84 | (Array *)(self), array_elem_size(self), (self)->size, \ 85 | 0, count, contents \ 86 | ) 87 | 88 | /// Remove `old_count` elements from the array starting at the given `index`. At 89 | /// the same index, insert `new_count` new elements, reading their values from the 90 | /// `new_contents` pointer. 91 | #define array_splice(self, _index, old_count, new_count, new_contents) \ 92 | _array__splice( \ 93 | (Array *)(self), array_elem_size(self), _index, \ 94 | old_count, new_count, new_contents \ 95 | ) 96 | 97 | /// Insert one `element` into the array at the given `index`. 98 | #define array_insert(self, _index, element) \ 99 | _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) 100 | 101 | /// Remove one element from the array at the given `index`. 102 | #define array_erase(self, _index) \ 103 | _array__erase((Array *)(self), array_elem_size(self), _index) 104 | 105 | /// Pop the last element off the array, returning the element by value. 106 | #define array_pop(self) ((self)->contents[--(self)->size]) 107 | 108 | /// Assign the contents of one array to another, reallocating if necessary. 109 | #define array_assign(self, other) \ 110 | _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) 111 | 112 | /// Swap one array with another 113 | #define array_swap(self, other) \ 114 | _array__swap((Array *)(self), (Array *)(other)) 115 | 116 | /// Get the size of the array contents 117 | #define array_elem_size(self) (sizeof *(self)->contents) 118 | 119 | /// Search a sorted array for a given `needle` value, using the given `compare` 120 | /// callback to determine the order. 121 | /// 122 | /// If an existing element is found to be equal to `needle`, then the `index` 123 | /// out-parameter is set to the existing value's index, and the `exists` 124 | /// out-parameter is set to true. Otherwise, `index` is set to an index where 125 | /// `needle` should be inserted in order to preserve the sorting, and `exists` 126 | /// is set to false. 127 | #define array_search_sorted_with(self, compare, needle, _index, _exists) \ 128 | _array__search_sorted(self, 0, compare, , needle, _index, _exists) 129 | 130 | /// Search a sorted array for a given `needle` value, using integer comparisons 131 | /// of a given struct field (specified with a leading dot) to determine the order. 132 | /// 133 | /// See also `array_search_sorted_with`. 134 | #define array_search_sorted_by(self, field, needle, _index, _exists) \ 135 | _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) 136 | 137 | /// Insert a given `value` into a sorted array, using the given `compare` 138 | /// callback to determine the order. 139 | #define array_insert_sorted_with(self, compare, value) \ 140 | do { \ 141 | unsigned _index, _exists; \ 142 | array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ 143 | if (!_exists) array_insert(self, _index, value); \ 144 | } while (0) 145 | 146 | /// Insert a given `value` into a sorted array, using integer comparisons of 147 | /// a given struct field (specified with a leading dot) to determine the order. 148 | /// 149 | /// See also `array_search_sorted_by`. 150 | #define array_insert_sorted_by(self, field, value) \ 151 | do { \ 152 | unsigned _index, _exists; \ 153 | array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ 154 | if (!_exists) array_insert(self, _index, value); \ 155 | } while (0) 156 | 157 | // Private 158 | 159 | typedef Array(void) Array; 160 | 161 | /// This is not what you're looking for, see `array_delete`. 162 | static inline void _array__delete(Array *self) { 163 | if (self->contents) { 164 | ts_free(self->contents); 165 | self->contents = NULL; 166 | self->size = 0; 167 | self->capacity = 0; 168 | } 169 | } 170 | 171 | /// This is not what you're looking for, see `array_erase`. 172 | static inline void _array__erase(Array *self, size_t element_size, 173 | uint32_t index) { 174 | assert(index < self->size); 175 | char *contents = (char *)self->contents; 176 | memmove(contents + index * element_size, contents + (index + 1) * element_size, 177 | (self->size - index - 1) * element_size); 178 | self->size--; 179 | } 180 | 181 | /// This is not what you're looking for, see `array_reserve`. 182 | static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { 183 | if (new_capacity > self->capacity) { 184 | if (self->contents) { 185 | self->contents = ts_realloc(self->contents, new_capacity * element_size); 186 | } else { 187 | self->contents = ts_malloc(new_capacity * element_size); 188 | } 189 | self->capacity = new_capacity; 190 | } 191 | } 192 | 193 | /// This is not what you're looking for, see `array_assign`. 194 | static inline void _array__assign(Array *self, const Array *other, size_t element_size) { 195 | _array__reserve(self, element_size, other->size); 196 | self->size = other->size; 197 | memcpy(self->contents, other->contents, self->size * element_size); 198 | } 199 | 200 | /// This is not what you're looking for, see `array_swap`. 201 | static inline void _array__swap(Array *self, Array *other) { 202 | Array swap = *other; 203 | *other = *self; 204 | *self = swap; 205 | } 206 | 207 | /// This is not what you're looking for, see `array_push` or `array_grow_by`. 208 | static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { 209 | uint32_t new_size = self->size + count; 210 | if (new_size > self->capacity) { 211 | uint32_t new_capacity = self->capacity * 2; 212 | if (new_capacity < 8) new_capacity = 8; 213 | if (new_capacity < new_size) new_capacity = new_size; 214 | _array__reserve(self, element_size, new_capacity); 215 | } 216 | } 217 | 218 | /// This is not what you're looking for, see `array_splice`. 219 | static inline void _array__splice(Array *self, size_t element_size, 220 | uint32_t index, uint32_t old_count, 221 | uint32_t new_count, const void *elements) { 222 | uint32_t new_size = self->size + new_count - old_count; 223 | uint32_t old_end = index + old_count; 224 | uint32_t new_end = index + new_count; 225 | assert(old_end <= self->size); 226 | 227 | _array__reserve(self, element_size, new_size); 228 | 229 | char *contents = (char *)self->contents; 230 | if (self->size > old_end) { 231 | memmove( 232 | contents + new_end * element_size, 233 | contents + old_end * element_size, 234 | (self->size - old_end) * element_size 235 | ); 236 | } 237 | if (new_count > 0) { 238 | if (elements) { 239 | memcpy( 240 | (contents + index * element_size), 241 | elements, 242 | new_count * element_size 243 | ); 244 | } else { 245 | memset( 246 | (contents + index * element_size), 247 | 0, 248 | new_count * element_size 249 | ); 250 | } 251 | } 252 | self->size += new_count - old_count; 253 | } 254 | 255 | /// A binary search routine, based on Rust's `std::slice::binary_search_by`. 256 | /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. 257 | #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ 258 | do { \ 259 | *(_index) = start; \ 260 | *(_exists) = false; \ 261 | uint32_t size = (self)->size - *(_index); \ 262 | if (size == 0) break; \ 263 | int comparison; \ 264 | while (size > 1) { \ 265 | uint32_t half_size = size / 2; \ 266 | uint32_t mid_index = *(_index) + half_size; \ 267 | comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ 268 | if (comparison <= 0) *(_index) = mid_index; \ 269 | size -= half_size; \ 270 | } \ 271 | comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ 272 | if (comparison == 0) *(_exists) = true; \ 273 | else if (comparison < 0) *(_index) += 1; \ 274 | } while (0) 275 | 276 | /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) 277 | /// parameter by reference in order to work with the generic sorting function above. 278 | #define _compare_int(a, b) ((int)*(a) - (int)(b)) 279 | 280 | #ifdef _MSC_VER 281 | #pragma warning(default : 4101) 282 | #elif defined(__GNUC__) || defined(__clang__) 283 | #pragma GCC diagnostic pop 284 | #endif 285 | 286 | #ifdef __cplusplus 287 | } 288 | #endif 289 | 290 | #endif // TREE_SITTER_ARRAY_H_ 291 | -------------------------------------------------------------------------------- /src/tree_sitter/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_PARSER_H_ 2 | #define TREE_SITTER_PARSER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define ts_builtin_sym_error ((TSSymbol)-1) 13 | #define ts_builtin_sym_end 0 14 | #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 | 16 | #ifndef TREE_SITTER_API_H_ 17 | typedef uint16_t TSStateId; 18 | typedef uint16_t TSSymbol; 19 | typedef uint16_t TSFieldId; 20 | typedef struct TSLanguage TSLanguage; 21 | #endif 22 | 23 | typedef struct { 24 | TSFieldId field_id; 25 | uint8_t child_index; 26 | bool inherited; 27 | } TSFieldMapEntry; 28 | 29 | typedef struct { 30 | uint16_t index; 31 | uint16_t length; 32 | } TSFieldMapSlice; 33 | 34 | typedef struct { 35 | bool visible; 36 | bool named; 37 | bool supertype; 38 | } TSSymbolMetadata; 39 | 40 | typedef struct TSLexer TSLexer; 41 | 42 | struct TSLexer { 43 | int32_t lookahead; 44 | TSSymbol result_symbol; 45 | void (*advance)(TSLexer *, bool); 46 | void (*mark_end)(TSLexer *); 47 | uint32_t (*get_column)(TSLexer *); 48 | bool (*is_at_included_range_start)(const TSLexer *); 49 | bool (*eof)(const TSLexer *); 50 | void (*log)(const TSLexer *, const char *, ...); 51 | }; 52 | 53 | typedef enum { 54 | TSParseActionTypeShift, 55 | TSParseActionTypeReduce, 56 | TSParseActionTypeAccept, 57 | TSParseActionTypeRecover, 58 | } TSParseActionType; 59 | 60 | typedef union { 61 | struct { 62 | uint8_t type; 63 | TSStateId state; 64 | bool extra; 65 | bool repetition; 66 | } shift; 67 | struct { 68 | uint8_t type; 69 | uint8_t child_count; 70 | TSSymbol symbol; 71 | int16_t dynamic_precedence; 72 | uint16_t production_id; 73 | } reduce; 74 | uint8_t type; 75 | } TSParseAction; 76 | 77 | typedef struct { 78 | uint16_t lex_state; 79 | uint16_t external_lex_state; 80 | } TSLexMode; 81 | 82 | typedef union { 83 | TSParseAction action; 84 | struct { 85 | uint8_t count; 86 | bool reusable; 87 | } entry; 88 | } TSParseActionEntry; 89 | 90 | typedef struct { 91 | int32_t start; 92 | int32_t end; 93 | } TSCharacterRange; 94 | 95 | struct TSLanguage { 96 | uint32_t version; 97 | uint32_t symbol_count; 98 | uint32_t alias_count; 99 | uint32_t token_count; 100 | uint32_t external_token_count; 101 | uint32_t state_count; 102 | uint32_t large_state_count; 103 | uint32_t production_id_count; 104 | uint32_t field_count; 105 | uint16_t max_alias_sequence_length; 106 | const uint16_t *parse_table; 107 | const uint16_t *small_parse_table; 108 | const uint32_t *small_parse_table_map; 109 | const TSParseActionEntry *parse_actions; 110 | const char * const *symbol_names; 111 | const char * const *field_names; 112 | const TSFieldMapSlice *field_map_slices; 113 | const TSFieldMapEntry *field_map_entries; 114 | const TSSymbolMetadata *symbol_metadata; 115 | const TSSymbol *public_symbol_map; 116 | const uint16_t *alias_map; 117 | const TSSymbol *alias_sequences; 118 | const TSLexMode *lex_modes; 119 | bool (*lex_fn)(TSLexer *, TSStateId); 120 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 121 | TSSymbol keyword_capture_token; 122 | struct { 123 | const bool *states; 124 | const TSSymbol *symbol_map; 125 | void *(*create)(void); 126 | void (*destroy)(void *); 127 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 128 | unsigned (*serialize)(void *, char *); 129 | void (*deserialize)(void *, const char *, unsigned); 130 | } external_scanner; 131 | const TSStateId *primary_state_ids; 132 | }; 133 | 134 | static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 135 | uint32_t index = 0; 136 | uint32_t size = len - index; 137 | while (size > 1) { 138 | uint32_t half_size = size / 2; 139 | uint32_t mid_index = index + half_size; 140 | TSCharacterRange *range = &ranges[mid_index]; 141 | if (lookahead >= range->start && lookahead <= range->end) { 142 | return true; 143 | } else if (lookahead > range->end) { 144 | index = mid_index; 145 | } 146 | size -= half_size; 147 | } 148 | TSCharacterRange *range = &ranges[index]; 149 | return (lookahead >= range->start && lookahead <= range->end); 150 | } 151 | 152 | /* 153 | * Lexer Macros 154 | */ 155 | 156 | #ifdef _MSC_VER 157 | #define UNUSED __pragma(warning(suppress : 4101)) 158 | #else 159 | #define UNUSED __attribute__((unused)) 160 | #endif 161 | 162 | #define START_LEXER() \ 163 | bool result = false; \ 164 | bool skip = false; \ 165 | UNUSED \ 166 | bool eof = false; \ 167 | int32_t lookahead; \ 168 | goto start; \ 169 | next_state: \ 170 | lexer->advance(lexer, skip); \ 171 | start: \ 172 | skip = false; \ 173 | lookahead = lexer->lookahead; 174 | 175 | #define ADVANCE(state_value) \ 176 | { \ 177 | state = state_value; \ 178 | goto next_state; \ 179 | } 180 | 181 | #define ADVANCE_MAP(...) \ 182 | { \ 183 | static const uint16_t map[] = { __VA_ARGS__ }; \ 184 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 185 | if (map[i] == lookahead) { \ 186 | state = map[i + 1]; \ 187 | goto next_state; \ 188 | } \ 189 | } \ 190 | } 191 | 192 | #define SKIP(state_value) \ 193 | { \ 194 | skip = true; \ 195 | state = state_value; \ 196 | goto next_state; \ 197 | } 198 | 199 | #define ACCEPT_TOKEN(symbol_value) \ 200 | result = true; \ 201 | lexer->result_symbol = symbol_value; \ 202 | lexer->mark_end(lexer); 203 | 204 | #define END_STATE() return result; 205 | 206 | /* 207 | * Parse Table Macros 208 | */ 209 | 210 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 211 | 212 | #define STATE(id) id 213 | 214 | #define ACTIONS(id) id 215 | 216 | #define SHIFT(state_value) \ 217 | {{ \ 218 | .shift = { \ 219 | .type = TSParseActionTypeShift, \ 220 | .state = (state_value) \ 221 | } \ 222 | }} 223 | 224 | #define SHIFT_REPEAT(state_value) \ 225 | {{ \ 226 | .shift = { \ 227 | .type = TSParseActionTypeShift, \ 228 | .state = (state_value), \ 229 | .repetition = true \ 230 | } \ 231 | }} 232 | 233 | #define SHIFT_EXTRA() \ 234 | {{ \ 235 | .shift = { \ 236 | .type = TSParseActionTypeShift, \ 237 | .extra = true \ 238 | } \ 239 | }} 240 | 241 | #define REDUCE(symbol_name, children, precedence, prod_id) \ 242 | {{ \ 243 | .reduce = { \ 244 | .type = TSParseActionTypeReduce, \ 245 | .symbol = symbol_name, \ 246 | .child_count = children, \ 247 | .dynamic_precedence = precedence, \ 248 | .production_id = prod_id \ 249 | }, \ 250 | }} 251 | 252 | #define RECOVER() \ 253 | {{ \ 254 | .type = TSParseActionTypeRecover \ 255 | }} 256 | 257 | #define ACCEPT_INPUT() \ 258 | {{ \ 259 | .type = TSParseActionTypeAccept \ 260 | }} 261 | 262 | #ifdef __cplusplus 263 | } 264 | #endif 265 | 266 | #endif // TREE_SITTER_PARSER_H_ 267 | -------------------------------------------------------------------------------- /test/corpus/braces.txt: -------------------------------------------------------------------------------- 1 | ======================================= 2 | Usages of braces outside of inline tags 3 | ======================================= 4 | 5 | /** This is {something} that should not {error}. */ 6 | 7 | --- 8 | 9 | (document (description)) 10 | 11 | ======================================= 12 | Unmarked code example 13 | ======================================= 14 | 15 | /** 16 | * @alias Apple.Core 17 | * @event module:foo/bar.event:MyEvent 18 | * @fires Hurl#snowball 19 | * @exports hello/world 20 | * @example apple.core({ foo: 'x', bar: true }); 21 | */ 22 | 23 | --- 24 | 25 | (document 26 | (tag 27 | (tag_name) 28 | (member_expression (identifier) (identifier))) 29 | (tag 30 | (tag_name) 31 | (member_expression 32 | (qualified_expression 33 | (identifier) 34 | (path_expression (identifier) (identifier))) 35 | (qualified_expression (identifier) (identifier)))) 36 | (tag 37 | (tag_name) 38 | (member_expression (identifier) (identifier))) 39 | (tag 40 | (tag_name) 41 | (path_expression (identifier) (identifier))) 42 | (tag 43 | (tag_name) (description)) 44 | ) 45 | 46 | ======================================= 47 | Complex types 48 | ======================================= 49 | 50 | /** 51 | * @type {{a: number, b: string, c}} 52 | * @param {[a: number, b:string]} foo A parameter. 53 | * @param {[a: number, { b: string, c: boolean}]} foo A parameter. 54 | */ 55 | 56 | --- 57 | 58 | (document 59 | (tag 60 | (tag_name) 61 | (type)) 62 | (tag 63 | (tag_name) 64 | (type) 65 | (identifier) 66 | (description)) 67 | (tag 68 | (tag_name) 69 | (type) 70 | (identifier) 71 | (description))) 72 | 73 | ======================================= 74 | EOF before balanced braces 75 | ======================================= 76 | 77 | /** 78 | * Here we're testing that the scanner doesn't get stuck in an infinite loop. 79 | * @type {{a: number, b: string, c} 80 | --- 81 | 82 | (ERROR 83 | (description) 84 | (tag_name)) 85 | -------------------------------------------------------------------------------- /test/corpus/crlf.txt: -------------------------------------------------------------------------------- 1 | ============================================ 2 | Multi-line documents with CRLF line endings 3 | ============================================ 4 | 5 | /** 6 | * This is a description 7 | */ 8 | 9 | --- 10 | 11 | (document (description)) 12 | -------------------------------------------------------------------------------- /test/corpus/main.txt: -------------------------------------------------------------------------------- 1 | =================== 2 | One-line documents 3 | =================== 4 | 5 | /** This is a description of the foo function. */ 6 | 7 | --- 8 | 9 | (document (description)) 10 | 11 | ==================== 12 | Multi-line documents 13 | ==================== 14 | 15 | /** 16 | * This is a description 17 | */ 18 | 19 | --- 20 | 21 | (document (description)) 22 | 23 | ============================ 24 | Tags with names 25 | ============================ 26 | 27 | /** 28 | * @alias Apple.Core 29 | * @event module:foo/bar.event:MyEvent 30 | * @fires Hurl#snowball 31 | * @exports hello/world 32 | */ 33 | 34 | --- 35 | 36 | (document 37 | (tag 38 | (tag_name) 39 | (member_expression (identifier) (identifier))) 40 | (tag 41 | (tag_name) 42 | (member_expression 43 | (qualified_expression 44 | (identifier) 45 | (path_expression (identifier) (identifier))) 46 | (qualified_expression (identifier) (identifier)))) 47 | (tag 48 | (tag_name) 49 | (member_expression (identifier) (identifier))) 50 | (tag 51 | (tag_name) 52 | (path_expression (identifier) (identifier)))) 53 | 54 | ====================== 55 | Tags with types and names 56 | ====================== 57 | 58 | /** 59 | * This is a method 60 | * @param name - the name 61 | * @param {string} name - the name 62 | * @param {integer} - the age 63 | */ 64 | 65 | --- 66 | 67 | (document 68 | (description) 69 | (tag (tag_name) (identifier) (description)) 70 | (tag (tag_name) (type) (identifier) (description)) 71 | (tag (tag_name) (type) (description))) 72 | 73 | ============================ 74 | Inline tags 75 | ============================ 76 | 77 | /** 78 | * Set the shoe's color. Use {@link Shoe#setSize} to set the shoe size. 79 | */ 80 | 81 | --- 82 | 83 | (document 84 | (description (inline_tag (tag_name) (description)))) 85 | 86 | ==================================== 87 | Multi-line block tag descriptions 88 | ==================================== 89 | 90 | /** 91 | * Set the shoe's color. 92 | * 93 | * @param {SHOE_COLORS} color - The shoe color. Must be an enumerated 94 | * value of {@link SHOE_COLORS}. 95 | */ 96 | 97 | --- 98 | 99 | (document 100 | (description) 101 | (tag 102 | (tag_name) 103 | (type) 104 | (identifier) 105 | (description 106 | (inline_tag (tag_name) (description))))) 107 | 108 | =============================== 109 | Block tags with no description 110 | ================================ 111 | 112 | /** 113 | * This is a description of the MyClass constructor function. 114 | * @class 115 | * @classdesc This is a description of the MyClass class. 116 | */ 117 | 118 | --- 119 | 120 | (document 121 | (description) 122 | (tag (tag_name)) 123 | (tag (tag_name) (description))) 124 | 125 | =============================== 126 | Newer JSDoc tags 127 | =============================== 128 | 129 | /** 130 | * @typedef {object} Foo 131 | * @prop {string} bar 132 | * @satisfies {Baz} 133 | * @augments Quux 134 | */ 135 | 136 | --- 137 | 138 | (document 139 | (tag (tag_name) (type) (identifier)) 140 | (tag (tag_name) (type) (identifier)) 141 | (tag (tag_name) (type)) 142 | (tag (tag_name) (identifier))) 143 | -------------------------------------------------------------------------------- /tree-sitter.json: -------------------------------------------------------------------------------- 1 | { 2 | "grammars": [ 3 | { 4 | "name": "jsdoc", 5 | "camelcase": "JSDoc", 6 | "scope": "text.jsdoc", 7 | "path": ".", 8 | "file-types": null, 9 | "highlights": [ 10 | "queries/highlights.scm" 11 | ], 12 | "injection-regex": "jsdoc" 13 | } 14 | ], 15 | "metadata": { 16 | "version": "0.23.2", 17 | "license": "MIT", 18 | "description": "JSDoc grammar for tree-sitter", 19 | "authors": [ 20 | { 21 | "name": "Max Brunsfeld", 22 | "email": "maxbrunsfeld@gmail.com" 23 | }, 24 | { 25 | "name": "Amaan Qureshi", 26 | "email": "amaanq12@gmail.com" 27 | } 28 | ], 29 | "links": { 30 | "repository": "https://github.com/tree-sitter/tree-sitter-jsdoc" 31 | } 32 | }, 33 | "bindings": { 34 | "c": true, 35 | "go": true, 36 | "node": true, 37 | "python": true, 38 | "rust": true, 39 | "swift": true 40 | } 41 | } 42 | --------------------------------------------------------------------------------