Repository: Bridgeconn/usfm-grammar (language: python)

Issue:
Kavitharaju patch 1
Moved to Node. Added a test framework.
Proper test cases, yet to be added.


Discussion / hints:

Fix patch:
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
new file mode 100644
index 00000000..257d8ce2
--- /dev/null
+++ b/.bumpversion.cfg
@@ -0,0 +1,39 @@
+[bumpversion]
+current_version = 3.0.0-beta.8
+commit = True
+tag = False
+parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>\w+).(?P<num>\d+)
+serialize = 
+	{major}.{minor}.{patch}-{release}.{num}
+	{major}.{minor}.{patch}
+
+[bumpversion:part:release]
+values = 
+	alpha
+	beta
+
+[bumpversion:file:py-usfm-parser/setup.py]
+search = version="{current_version}"
+replace = version="{new_version}"
+
+[bumpversion:file:py-usfm-parser/pyproject.toml]
+
+[bumpversion:file:py-usfm-parser/src/usfm_grammar/__init__.py]
+search = __version__ = "{current_version}"
+replace = __version__ = "{new_version}"
+
+[bumpversion:file:py-usfm-parser/requirements.txt]
+search = tree-sitter-usfm3=={current_version}
+replace = tree-sitter-usfm3=={new_version}
+
+[bumpversion:file:tree-sitter-usfm3/pyproject.toml]
+search = version = "{current_version}"
+replace = version = "{new_version}"
+
+[bumpversion:file:tree-sitter-usfm3/package.json]
+search = "version": "{current_version}"
+replace = "version": "{new_version}"
+
+[bumpversion:file:tree-sitter-usfm3/package-lock.json]
+search = "version": "{current_version}"
+replace = "version": "{new_version}"
diff --git a/.github/workflows/check-on-push.yml b/.github/workflows/check-on-push.yml
index b8af3e0f..03cd0e5d 100644
--- a/.github/workflows/check-on-push.yml
+++ b/.github/workflows/check-on-push.yml
@@ -20,15 +20,16 @@ jobs:
     steps:
       # Checks out a copy of your repository on the ubuntu-latest machine
       - name: Checkout code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v4
       - name: Setup node and npm
-        uses: actions/setup-node@v2
+        uses: actions/setup-node@v4
         with:
-          node-version: 20.4
+          node-version: 20
       - name: Run tests
         run: |
           cd tree-sitter-usfm3
-          npm install .
+          npm install --save nan
+          npm install --save-dev tree-sitter-cli
           ./node_modules/.bin/tree-sitter generate
           ./node_modules/.bin/tree-sitter test
 
@@ -37,40 +38,38 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout code
-        uses: actions/checkout@v2
-      - uses: actions/setup-python@v2
+        uses: actions/checkout@v4
+      - uses: actions/setup-python@v4
         with:
             python-version: '3.10.6'
 
       - name: Setup node and npm
-        uses: actions/setup-node@v2
+        uses: actions/setup-node@v4
         with:
-          node-version: 20.4
-
-      - name: Create Virtual Environment
-        run: python -m venv ENV-dev
-
-      - name: Use VENV
-        run: source ENV-dev/bin/activate
-
-      - name: Install dependencies
-        run: pip install -r ./py-usfm-parser/dev-requirements.txt
+          node-version: 20
 
       - name: Build grammar binary
         run: |
           cd tree-sitter-usfm3
-          npm install .
+          npm install --save nan
+          npm install --save-dev tree-sitter-cli
           ./node_modules/.bin/tree-sitter generate
-          cd ..
-          python py-usfm-parser/src/grammar_rebuild.py ./tree-sitter-usfm3/ py-usfm-parser/src/usfm_grammar/my-languages.so
 
-      - name: Install python module
+      - name: Install dependencies
         run: |
-          cd py-usfm-parser
+          cd tree-sitter-usfm3
           pip install .
+          cd ../py-usfm-parser
+          sed -i '/tree-sitter-usfm3==.*/d' pyproject.toml
+          pip install . -r ./dev-requirements.txt
+
+      # - name: Install python module
+      #   run: |
+      #     cd py-usfm-parser
+      #     pip install .
 
       - name: Run tests for parsing errors
         working-directory: ./py-usfm-parser
         run:
           # pytest -k "not compare_usx_with_testsuite_samples and not testsuite_usx_with_rnc_grammar and not samples-from-wild and not 57-TIT.partial" -n auto
-          pytest -k "not compare_usx_with_testsuite_samples and not testsuite_usx_with_rnc_grammar and not generated_usx_with_rnc_grammar and not samples-from-wild" -n auto
+          python -m pytest -k "not compare_usx_with_testsuite_samples and not testsuite_usx_with_rnc_grammar and not generated_usx_with_rnc_grammar and not samples-from-wild" -n auto
diff --git a/.github/workflows/lint-on-push.yml b/.github/workflows/lint-on-push.yml
index 1d6e6cf0..ffa9bdb9 100644
--- a/.github/workflows/lint-on-push.yml
+++ b/.github/workflows/lint-on-push.yml
@@ -14,8 +14,8 @@ jobs:
     # Steps represent a sequence of tasks that will be executed as part of the job
     steps:
       # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
-      - uses: actions/checkout@v2
-      - uses: actions/setup-python@v2
+      - uses: actions/checkout@v4
+      - uses: actions/setup-python@v4
         with:
             python-version: '3.10.6' # Version range or exact version of a Python version to use, using SemVer's version range syntax
             architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
@@ -29,6 +29,22 @@ jobs:
       - name: install packages
         working-directory: ./py-usfm-parser
         run: pip install -r dev-requirements.txt
+
+      - name: Setup node and npm
+        uses: actions/setup-node@v4
+        with:
+          node-version: 20
+
+      - name: Build grammar binary
+        working-directory: ./tree-sitter-usfm3
+        run: |
+          npm install --save nan
+          npm install --save-dev tree-sitter-cli
+          ./node_modules/.bin/tree-sitter generate
+
+      - name: install tree-sitter-usfm3
+        working-directory: ./tree-sitter-usfm3
+        run: pip install .
         
       - name: Run linter
         working-directory: ./py-usfm-parser
diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml
index f7c6eb67..3745eff4 100644
--- a/.github/workflows/npm-publish.yml
+++ b/.github/workflows/npm-publish.yml
@@ -4,6 +4,7 @@
 name: Node.js Package
 
 on:
+  workflow_dispatch:
   release:
     types: [published]
 
@@ -17,15 +18,16 @@ jobs:
     steps:
       # Checks out a copy of your repository on the ubuntu-latest machine
       - name: Checkout code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v4
       - name: Setup node and npm
-        uses: actions/setup-node@v2
+        uses: actions/setup-node@v4
         with:
-          node-version: 20.4
+          node-version: 20
       - name: Run tests
         run: |
           cd tree-sitter-usfm3
-          npm install .
+          npm install --save nan
+          npm install --save-dev tree-sitter-cli
           ./node_modules/.bin/tree-sitter generate
           ./node_modules/.bin/tree-sitter test
 
@@ -40,38 +42,10 @@ jobs:
           registry-url: https://registry.npmjs.org/
       - run: |
           cd tree-sitter-usfm3
-          npm install .
+          npm install --save nan
+          npm install --save-dev tree-sitter-cli
           ./node_modules/.bin/tree-sitter generate
-          npm publish . --tag alpha
+          npm publish . --tag beta
         env:
           NODE_AUTH_TOKEN: ${{secrets.npm_token}}
 
-  # Publish-atom-extension:
-  #   needs: build
-  #   runs-on: ubuntu-latest
-  #   steps:
-  #     - uses: actions/checkout@v2
-  #     - uses: actions/setup-node@v1
-  #       with:
-  #         node-version: 14
-  #         registry-url: https://registry.npmjs.org/
-  #     - run: npm ci
-  #     - run: |
-  #         cd atom-extension
-  #         npm publish . --tag alpha
-  #       env:
-  #         NODE_AUTH_TOKEN: ${{secrets.npm_token}}
-
-  # publish-gpr:
-  #   needs: build
-  #   runs-on: ubuntu-latest
-  #   steps:
-  #     - uses: actions/checkout@v2
-  #     - uses: actions/setup-node@v1
-  #       with:
-  #         node-version: 12
-  #         registry-url: https://npm.pkg.github.com/
-  #     - run: npm ci
-  #     - run: npm publish
-  #       env:
-  #         NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
diff --git a/.github/workflows/pypi_publish.yml b/.github/workflows/pypi_publish.yml
index 26e8c480..9eff2f8d 100644
--- a/.github/workflows/pypi_publish.yml
+++ b/.github/workflows/pypi_publish.yml
@@ -7,60 +7,88 @@ on:
     types: [published]
 
 jobs:
-  build_wheels:
-    name: Build wheels on ${{ matrix.os }}
-    runs-on: ${{ matrix.os }}
-    strategy:
-      matrix:
-        os: [ubuntu-20.04, windows-2019, macos-11]
-        # os: [ubuntu-20.04]
-
+  build-tree-sitter-usfm3:
+    runs-on: ubuntu-latest
+    
     steps:
-      - uses: actions/checkout@v3
+      # Checks out a copy of your repository on the ubuntu-latest machine
+      - name: Checkout code
+        uses: actions/checkout@v4
       - name: Setup node and npm
-        uses: actions/setup-node@v2
+        uses: actions/setup-node@v4
         with:
-          node-version: 20.4
-      - name: Build the tree-sitter parser
+          node-version: 20
+      - name: Run tests
         run: |
           cd tree-sitter-usfm3
-          npm install .
+          npm install --save nan
+          npm install --save-dev tree-sitter-cli
           ./node_modules/.bin/tree-sitter generate
+          ./node_modules/.bin/tree-sitter test
 
-      - name: Build wheels
-        uses: pypa/cibuildwheel@v2.9.0
-        env:
-          CIBW_BEFORE_BUILD: >
-              python -m pip install tree-sitter==0.20.0 &&
-              python py-usfm-parser/src/grammar_rebuild.py tree-sitter-usfm3 py-usfm-parser/src/usfm_grammar/my-languages.so
+      - uses: actions/setup-python@v5
         with:
-          package-dir: py-usfm-parser
-          output-dir: py-usfm-parser/dist
-          config-file: "py-usfm-parser/pyproject.toml"
+          python-version: "3.10"
 
+      - name: Build release distributions
+        run: |
+          cd tree-sitter-usfm3
+          python -m pip install build setuptools
+          python -m build
       - uses: actions/upload-artifact@v3
         with:
-          path: py-usfm-parser/dist/*.whl
+          path: tree-sitter-usfm3/dist/*.tar.gz
+
+  build-py-usfm-parser:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-python@v4
+        with:
+          python-version: "3.10"
+      - name: Build release distributions
+        run: |
+          cd py-usfm-parser
+          python -m pip install build setuptools
+          python -m build
+      - uses: actions/upload-artifact@v3
+        with:
+          path: py-usfm-parser/dist/*.tar.gz
+
 
   publish_to_pypi:
-    needs: [build_wheels]
+    needs: [build-tree-sitter-usfm3, build-py-usfm-parser]
     runs-on: ubuntu-latest
 
     steps:
       - uses: actions/checkout@master
       - name: Set up Python 3.10
-        uses: actions/setup-python@v3
+        uses: actions/setup-python@v4
         with:
           python-version: "3.10"
+      - uses: actions/download-artifact@v3
+        with:
+          name: artifact
+          path: tree-sitter-usfm3/dist/
+
       - uses: actions/download-artifact@v3
         with:
           name: artifact
           path: py-usfm-parser/dist/
 
-      - name: Publish distribution 📦 to PyPI
+      - name: Publish tree-sitter-usfm3 📦 to Test PyPI
         uses: pypa/gh-action-pypi-publish@release/v1
         with:
           user: __token__
           password: ${{ secrets.pypi_token }}
           # repository_url: https://test.pypi.org/legacy/
-          packages_dir: py-usfm-parser/dist/
\ No newline at end of file
+          packages_dir: tree-sitter-usfm3/dist/
+
+      - name: Publish usfm-grammar 📦 to Test PyPI
+        uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          user: __token__
+          password: ${{ ssecrets.pypi_token }}
+          # repository_url: https://test.pypi.org/legacy/
+          packages_dir: py-usfm-parser/dist/
+          
diff --git a/docs/Dev_notes.md b/docs/Dev_notes.md
index 3113d8ec..6356103b 100644
--- a/docs/Dev_notes.md
+++ b/docs/Dev_notes.md
@@ -9,24 +9,25 @@ export PATH=$PATH:./node_modules/.bin
 tree-sitter generate
 tree-sitter test
 ```
-Then run a script from root directory
+To use the grammar module still in developement from within the py-usfm-grammar module
 ```
-cd ..
-python py-usfm-parser/src/grammar_rebuild.py ./tree-sitter-usfm3/ py-usfm-parser/src/usfm_grammar/my-languages.so
+cd py-usfm-parser
+source ENV-dev/bin/actiavte
+pip install ../tree-sitter-usfm3
 ```
 
+To make the changes reflect automatically `pip install -e ../tree-sitter-usfm3`.
+
 ## How to change version number in files?
 
 In python module,
 ```
-cd py-usfm-parser
-source ENV-dev
+cd usfm-grammar
+source py-usfm-parser/ENV-dev/bin/activate
 bumpversion --new-version 3.0.0-alpha.28 num
 ```
-In tree-sitter-usfm3
-> Change the version field in `package.json` and `package-lock.json`
 
-The github action is configured to automatically build and publish to PyPI and NPM upon a github code release. Make sure to use same version number in the python module bump command, package.json and github release.
+The github action is configured to automatically build and publish to PyPI and NPM upon a github code release. Make sure to use same version number in the python module bump command, and github release.
 
 ## Run tests
 To check Syntax trees in Grammar module
@@ -41,7 +42,7 @@ In python module alone
 
 ```
 cd py-usfm-parser
-python -m pytest - auto
+python -m pytest -n auto
 
 # to run selectively
 pytest -k "not compare_usx_with_testsuite_samples and not testsuite_usx_with_rnc_grammar and not generated_usx_with_rnc_grammar and not samples-from-wild" -n auto
diff --git a/py-usfm-parser/.bumpversion.cfg b/py-usfm-parser/.bumpversion.cfg
deleted file mode 100644
index b096cbdc..00000000
--- a/py-usfm-parser/.bumpversion.cfg
+++ /dev/null
@@ -1,25 +0,0 @@
-[bumpversion]
-current_version = 3.0.0-beta.7
-commit = True
-tag = False
-parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>\w+).(?P<num>\d+)
-serialize = 
-	{major}.{minor}.{patch}-{release}.{num}
-	{major}.{minor}.{patch}
-
-[bumpversion:part:release]
-values = 
-	alpha
-	beta
-
-[bumpversion:file:setup.py]
-search = version="{current_version}"
-replace = version="{new_version}"
-
-[bumpversion:file:pyproject.toml]
-search = version = "{current_version}"
-replace = version = "{new_version}"
-
-[bumpversion:file:src/usfm_grammar/__init__.py]
-search = __version__ = "{current_version}"
-replace = __version__ = "{new_version}"
diff --git a/py-usfm-parser/MANIFEST.in b/py-usfm-parser/MANIFEST.in
deleted file mode 100644
index a69b2c23..00000000
--- a/py-usfm-parser/MANIFEST.in
+++ /dev/null
@@ -1,4 +0,0 @@
-
-include src/usfm_grammar/my-languages.so
-
-exclude src/grammar_rebuild.py
diff --git a/py-usfm-parser/dev-requirements.txt b/py-usfm-parser/dev-requirements.txt
index dc7d51fe..77cd1e7b 100644
--- a/py-usfm-parser/dev-requirements.txt
+++ b/py-usfm-parser/dev-requirements.txt
@@ -1,4 +1,4 @@
-tree-sitter==0.21.3
+tree-sitter==0.22.3
 jupyterlab==3.4.4
 rnc2rng==2.6.6
 lxml==5.2.2
diff --git a/py-usfm-parser/pyproject.toml b/py-usfm-parser/pyproject.toml
index e400d1a5..1c313c1b 100644
--- a/py-usfm-parser/pyproject.toml
+++ b/py-usfm-parser/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
 
 [project]
 name = "usfm-grammar"
-version = "3.0.0-beta.7"
+version = "3.0.0-beta.8"
 description = "Python parser for USFM files, based on tree-sitter-usfm3"
 readme = "README.md"
 authors = [{ name = "BCS Team", email = "joel@bridgeconn.com" }]
@@ -22,7 +22,8 @@ classifiers = [
 ]
 keywords = ["usfm", "parser", "grammar", "tree-sitter"]
 dependencies = [
-    'tree-sitter==0.21.3; python_version >= "3.3"',
+    'tree-sitter==0.22.3; python_version >= "3.9"',
+    'tree-sitter-usfm3==3.0.0-beta.8; python_version >="3.8"',
     'lxml==5.2.2; python_version >= "3.5"'
 ]
 requires-python = ">=3.10"
diff --git a/py-usfm-parser/requirements.txt b/py-usfm-parser/requirements.txt
index 008ebc16..5f234fb7 100644
--- a/py-usfm-parser/requirements.txt
+++ b/py-usfm-parser/requirements.txt
@@ -1,2 +1,3 @@
-tree-sitter==0.21.3
+tree-sitter==0.22.3
+tree-sitter-usfm3==3.0.0-beta.8
 lxml==5.2.2
diff --git a/py-usfm-parser/setup.py b/py-usfm-parser/setup.py
index 40bd3b98..a3360415 100644
--- a/py-usfm-parser/setup.py
+++ b/py-usfm-parser/setup.py
@@ -7,11 +7,10 @@ def has_ext_modules(self):
 
 setup(
     name="usfm-grammar",  # Required
-    version="3.0.0-beta.7",  # Required
+    version="3.0.0-beta.8",  # Required
     python_requires=">=3.10",
-    install_requires=["tree-sitter==0.21.3", "lxml==5.2.2"],  # Optional
-    package_data={  # Optional
-        "usfm_grammar": ["my-languages.so"],
-    },
+    # install_requires=["tree-sitter==0.22.3",
+                        # "tree-sitter-usfm3==3.0.0-beta.7",  
+                        # "lxml==5.2.2"],  # Optional
     distclass = BinaryDistribution,
 )
diff --git a/py-usfm-parser/src/grammar_rebuild.py b/py-usfm-parser/src/grammar_rebuild.py
deleted file mode 100644
index a9194e95..00000000
--- a/py-usfm-parser/src/grammar_rebuild.py
+++ /dev/null
@@ -1,23 +0,0 @@
-''' This code is to be run only if we update the grammar and need to use the new one
- and need to be used only in dev(not in the published library)'''
-import sys
-from tree_sitter import Language
-
-if len(sys.argv) == 3 :
-    GRAMMAR_PATH = sys.argv[1]
-    OUTPUT_PATH = sys.argv[2]
-else:
-    raise Exception('''Usage: python python-usfm-parser/src/grammar_rebuild.py \
-./tree-sitter-usfm3/ py-usfm-parser/src/usfm_grammar/my-languages.so
-from the project root directory''')
-
-Language.build_library(
-  # Store the library in the `ext` directory
-  OUTPUT_PATH,
-
-  # Include one or more languages
-  [
-    # '../tree-sitter-exp',
-    GRAMMAR_PATH
-  ]
-)
diff --git a/py-usfm-parser/src/usfm_grammar/__init__.py b/py-usfm-parser/src/usfm_grammar/__init__.py
index 6b89f21b..aea07c13 100755
--- a/py-usfm-parser/src/usfm_grammar/__init__.py
+++ b/py-usfm-parser/src/usfm_grammar/__init__.py
@@ -7,4 +7,4 @@
 Format = usfm_parser.Format
 USFMParser = usfm_parser.USFMParser
 
-__version__ = "3.0.0-beta.7"
+__version__ = "3.0.0-beta.8"
diff --git a/py-usfm-parser/src/usfm_grammar/usfm_parser.py b/py-usfm-parser/src/usfm_grammar/usfm_parser.py
index 94c6759e..9d166c87 100755
--- a/py-usfm-parser/src/usfm_grammar/usfm_parser.py
+++ b/py-usfm-parser/src/usfm_grammar/usfm_parser.py
@@ -1,9 +1,9 @@
 '''The core logics of converting the syntax tree to other formats'''
 
 from enum import Enum
-from importlib import resources
 import re
 
+import tree_sitter_usfm3 as tsusfm
 from tree_sitter import Language, Parser
 from lxml import etree
 
@@ -50,11 +50,8 @@ class Format(str, Enum):
     MD = "markdown"
     USFM = "usfm"
 
-lang_file = resources.path('usfm_grammar','my-languages.so')
-with lang_file as path:
-    USFM_LANGUAGE = Language(str(path), 'usfm3')
-parser = Parser()
-parser.set_language(USFM_LANGUAGE)
+USFM_LANGUAGE = Language(tsusfm.language())
+parser = Parser(USFM_LANGUAGE)
 
 
 # # Handled alike by the node_2_dict_generic method
diff --git a/tree-sitter-usfm3/.editorconfig b/tree-sitter-usfm3/.editorconfig
new file mode 100644
index 00000000..d3a8b5b6
--- /dev/null
+++ b/tree-sitter-usfm3/.editorconfig
@@ -0,0 +1,39 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.{json,toml,yml,gyp}]
+indent_style = space
+indent_size = 2
+
+[*.js]
+indent_style = space
+indent_size = 2
+
+[*.rs]
+indent_style = space
+indent_size = 4
+
+[*.{c,cc,h}]
+indent_style = space
+indent_size = 4
+
+[*.{py,pyi}]
+indent_style = space
+indent_size = 4
+
+[*.swift]
+indent_style = space
+indent_size = 4
+
+[*.go]
+indent_style = tab
+indent_size = 8
+
+[Makefile]
+indent_style = tab
+indent_size = 8
diff --git a/tree-sitter-usfm3/.gitattributes b/tree-sitter-usfm3/.gitattributes
new file mode 100644
index 00000000..ffb52abe
--- /dev/null
+++ b/tree-sitter-usfm3/.gitattributes
@@ -0,0 +1,11 @@
+* text eol=lf
+
+src/*.json linguist-generated
+src/parser.c linguist-generated
+src/tree_sitter/* linguist-generated
+
+bindings/** linguist-generated
+binding.gyp linguist-generated
+setup.py linguist-generated
+Makefile linguist-generated
+Package.swift linguist-generated
diff --git a/tree-sitter-usfm3/.gitignore b/tree-sitter-usfm3/.gitignore
new file mode 100644
index 00000000..27fc43f7
--- /dev/null
+++ b/tree-sitter-usfm3/.gitignore
@@ -0,0 +1,38 @@
+# Rust artifacts
+Cargo.lock
+target/
+
+# Node artifacts
+build/
+prebuilds/
+node_modules/
+*.tgz
+
+# Swift artifacts
+.build/
+
+# Go artifacts
+go.sum
+_obj/
+
+# Python artifacts
+.venv/
+dist/
+*.egg-info
+*.whl
+
+# C artifacts
+*.a
+*.so
+*.so.*
+*.dylib
+*.dll
+*.pc
+
+# Example dirs
+/examples/*/
+
+# Grammar volatiles
+*.wasm
+*.obj
+*.o
diff --git a/tree-sitter-usfm3/Makefile b/tree-sitter-usfm3/Makefile
new file mode 100644
index 00000000..26f2d270
--- /dev/null
+++ b/tree-sitter-usfm3/Makefile
@@ -0,0 +1,112 @@
+VERSION := 0.0.1
+
+LANGUAGE_NAME := tree-sitter-usfm3
+
+# repository
+SRC_DIR := src
+
+PARSER_REPO_URL := $(shell git -C $(SRC_DIR) remote get-url origin 2>/dev/null)
+
+ifeq ($(PARSER_URL),)
+	PARSER_URL := $(subst .git,,$(PARSER_REPO_URL))
+ifeq ($(shell echo $(PARSER_URL) | grep '^[a-z][-+.0-9a-z]*://'),)
+	PARSER_URL := $(subst :,/,$(PARSER_URL))
+	PARSER_URL := $(subst git@,https://,$(PARSER_URL))
+endif
+endif
+
+TS ?= tree-sitter
+
+# ABI versioning
+SONAME_MAJOR := $(word 1,$(subst ., ,$(VERSION)))
+SONAME_MINOR := $(word 2,$(subst ., ,$(VERSION)))
+
+# install directory layout
+PREFIX ?= /usr/local
+INCLUDEDIR ?= $(PREFIX)/include
+LIBDIR ?= $(PREFIX)/lib
+PCLIBDIR ?= $(LIBDIR)/pkgconfig
+
+# source/object files
+PARSER := $(SRC_DIR)/parser.c
+EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c))
+OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS))
+
+# flags
+ARFLAGS ?= rcs
+override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC
+
+# OS-specific bits
+ifeq ($(OS),Windows_NT)
+	$(error "Windows is not supported")
+else ifeq ($(shell uname),Darwin)
+	SOEXT = dylib
+	SOEXTVER_MAJOR = $(SONAME_MAJOR).dylib
+	SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).dylib
+	LINKSHARED := $(LINKSHARED)-dynamiclib -Wl,
+	ifneq ($(ADDITIONAL_LIBS),)
+	LINKSHARED := $(LINKSHARED)$(ADDITIONAL_LIBS),
+	endif
+	LINKSHARED := $(LINKSHARED)-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SONAME_MAJOR).dylib,-rpath,@executable_path/../Frameworks
+else
+	SOEXT = so
+	SOEXTVER_MAJOR = so.$(SONAME_MAJOR)
+	SOEXTVER = so.$(SONAME_MAJOR).$(SONAME_MINOR)
+	LINKSHARED := $(LINKSHARED)-shared -Wl,
+	ifneq ($(ADDITIONAL_LIBS),)
+	LINKSHARED := $(LINKSHARED)$(ADDITIONAL_LIBS)
+	endif
+	LINKSHARED := $(LINKSHARED)-soname,lib$(LANGUAGE_NAME).so.$(SONAME_MAJOR)
+endif
+ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),)
+	PCLIBDIR := $(PREFIX)/libdata/pkgconfig
+endif
+
+all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc
+
+lib$(LANGUAGE_NAME).a: $(OBJS)
+	$(AR) $(ARFLAGS) $@ $^
+
+lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS)
+	$(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
+ifneq ($(STRIP),)
+	$(STRIP) $@
+endif
+
+$(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in
+	sed  -e 's|@URL@|$(PARSER_URL)|' \
+		-e 's|@VERSION@|$(VERSION)|' \
+		-e 's|@LIBDIR@|$(LIBDIR)|' \
+		-e 's|@INCLUDEDIR@|$(INCLUDEDIR)|' \
+		-e 's|@REQUIRES@|$(REQUIRES)|' \
+		-e 's|@ADDITIONAL_LIBS@|$(ADDITIONAL_LIBS)|' \
+		-e 's|=$(PREFIX)|=$${prefix}|' \
+		-e 's|@PREFIX@|$(PREFIX)|' $< > $@
+
+$(PARSER): $(SRC_DIR)/grammar.json
+	$(TS) generate --no-bindings $^
+
+install: all
+	install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)'
+	install -m644 bindings/c/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h
+	install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
+	install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a
+	install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER)
+	ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR)
+	ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT)
+
+uninstall:
+	$(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \
+		'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \
+		'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \
+		'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \
+		'$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \
+		'$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
+
+clean:
+	$(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT)
+
+test:
+	$(TS) test
+
+.PHONY: all install uninstall clean test
diff --git a/tree-sitter-usfm3/Package.swift b/tree-sitter-usfm3/Package.swift
new file mode 100644
index 00000000..9a4b9a0b
--- /dev/null
+++ b/tree-sitter-usfm3/Package.swift
@@ -0,0 +1,47 @@
+// swift-tools-version:5.3
+import PackageDescription
+
+let package = Package(
+    name: "TreeSitterUsfm3",
+    products: [
+        .library(name: "TreeSitterUsfm3", targets: ["TreeSitterUsfm3"]),
+    ],
+    dependencies: [],
+    targets: [
+        .target(name: "TreeSitterUsfm3",
+                path: ".",
+                exclude: [
+                    "Cargo.toml",
+                    "Makefile",
+                    "binding.gyp",
+                    "bindings/c",
+                    "bindings/go",
+                    "bindings/node",
+                    "bindings/python",
+                    "bindings/rust",
+                    "prebuilds",
+                    "grammar.js",
+                    "package.json",
+                    "package-lock.json",
+                    "pyproject.toml",
+                    "setup.py",
+                    "test",
+                    "examples",
+                    ".editorconfig",
+                    ".github",
+                    ".gitignore",
+                    ".gitattributes",
+                    ".gitmodules",
+                ],
+                sources: [
+                    "src/parser.c",
+                    // NOTE: if your language has an external scanner, add it here.
+                ],
+                resources: [
+                    .copy("queries")
+                ],
+                publicHeadersPath: "bindings/swift",
+                cSettings: [.headerSearchPath("src")])
+    ],
+    cLanguageStandard: .c11
+)
diff --git a/tree-sitter-usfm3/package-lock.json b/tree-sitter-usfm3/package-lock.json
index 998f958a..e19ab236 100644
--- a/tree-sitter-usfm3/package-lock.json
+++ b/tree-sitter-usfm3/package-lock.json
@@ -1,18 +1,19 @@
 {
   "name": "tree-sitter-usfm3",
-  "version": "3.0.0-beta.7",
+  "version": "3.0.0-beta.8",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "tree-sitter-usfm3",
-      "version": "3.0.0-beta.5",
+      "version": "3.0.0-beta.8",
       "license": "MIT License",
       "dependencies": {
-        "nan": "^2.15.0"
+        "nan": "^2.15.0",
+        "tree-sitter": "^0.21.1"
       },
       "devDependencies": {
-        "tree-sitter-cli": "^0.20.0"
+        "tree-sitter-cli": "^0.22.6"
       }
     },
     "node_modules/nan": {
@@ -20,10 +21,38 @@
       "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
       "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
     },
+    "node_modules/node-addon-api": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.0.0.tgz",
+      "integrity": "sha512-ipO7rsHEBqa9STO5C5T10fj732ml+5kLN1cAG8/jdHd56ldQeGj3Q7+scUS+VHK/qy1zLEwC4wMK5+yM0btPvw==",
+      "engines": {
+        "node": "^18 || ^20 || >= 21"
+      }
+    },
+    "node_modules/node-gyp-build": {
+      "version": "4.8.1",
+      "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz",
+      "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==",
+      "bin": {
+        "node-gyp-build": "bin.js",
+        "node-gyp-build-optional": "optional.js",
+        "node-gyp-build-test": "build-test.js"
+      }
+    },
+    "node_modules/tree-sitter": {
+      "version": "0.21.1",
+      "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz",
+      "integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==",
+      "hasInstallScript": true,
+      "dependencies": {
+        "node-addon-api": "^8.0.0",
+        "node-gyp-build": "^4.8.0"
+      }
+    },
     "node_modules/tree-sitter-cli": {
-      "version": "0.20.8",
-      "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.8.tgz",
-      "integrity": "sha512-XjTcS3wdTy/2cc/ptMLc/WRyOLECRYcMTrSWyhZnj1oGSOWbHLTklgsgRICU3cPfb0vy+oZCC33M43u6R1HSCA==",
+      "version": "0.22.6",
+      "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.22.6.tgz",
+      "integrity": "sha512-s7mYOJXi8sIFkt/nLJSqlYZP96VmKTc3BAwIX0rrrlRxWjWuCwixFqwzxWZBQz4R8Hx01iP7z3cT3ih58BUmZQ==",
       "dev": true,
       "hasInstallScript": true,
       "bin": {
@@ -37,10 +66,29 @@
       "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
       "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
     },
+    "node-addon-api": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.0.0.tgz",
+      "integrity": "sha512-ipO7rsHEBqa9STO5C5T10fj732ml+5kLN1cAG8/jdHd56ldQeGj3Q7+scUS+VHK/qy1zLEwC4wMK5+yM0btPvw=="
+    },
+    "node-gyp-build": {
+      "version": "4.8.1",
+      "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz",
+      "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw=="
+    },
+    "tree-sitter": {
+      "version": "0.21.1",
+      "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz",
+      "integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==",
+      "requires": {
+        "node-addon-api": "^8.0.0",
+        "node-gyp-build": "^4.8.0"
+      }
+    },
     "tree-sitter-cli": {
-      "version": "0.20.8",
-      "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.8.tgz",
-      "integrity": "sha512-XjTcS3wdTy/2cc/ptMLc/WRyOLECRYcMTrSWyhZnj1oGSOWbHLTklgsgRICU3cPfb0vy+oZCC33M43u6R1HSCA==",
+      "version": "0.22.6",
+      "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.22.6.tgz",
+      "integrity": "sha512-s7mYOJXi8sIFkt/nLJSqlYZP96VmKTc3BAwIX0rrrlRxWjWuCwixFqwzxWZBQz4R8Hx01iP7z3cT3ih58BUmZQ==",
       "dev": true
     }
   }
diff --git a/tree-sitter-usfm3/package.json b/tree-sitter-usfm3/package.json
index 7c1c1301..7dd2c3e3 100644
--- a/tree-sitter-usfm3/package.json
+++ b/tree-sitter-usfm3/package.json
@@ -1,10 +1,13 @@
 {
   "name": "tree-sitter-usfm3",
-  "version": "3.0.0-beta.7",
+  "version": "3.0.0-beta.8",
   "description": "Grammar representation and parser for USFM language using tree-sitter",
   "main": "bindings/node",
+  "types": "bindings/node",
   "scripts": {
-    "test": "tree-sitter test"
+    "test": "tree-sitter test",
+    "install": "node-gyp-build",
+    "prebuildify": "prebuildify --napi --strip"
   },
   "repository": {
     "type": "git",
@@ -17,19 +20,40 @@
     "cfg",
     "json"
   ],
+  "files": [
+    "grammar.js",
+    "binding.gyp",
+    "prebuilds/**",
+    "bindings/node/*",
+    "queries/*",
+    "src/**"
+  ],
   "author": "BCS Team <joel@bridgeconn.com> (https://bridgeconn.com/)",
-  "contributors": ["Kavitha Raju <kavitha.raju@bridgeconn.com> (https://github.com/kavitharaju)",
-    "Joel Mathew <joel@bridgeconn.com> (https://github.com/joelthe1)"],
+  "contributors": [
+    "Kavitha Raju <kavitha.raju@bridgeconn.com> (https://github.com/kavitharaju)",
+    "Joel Mathew <joel@bridgeconn.com> (https://github.com/joelthe1)"
+  ],
   "license": "MIT License",
   "bugs": {
     "url": "https://github.com/Bridgeconn/usfm-grammar/issues"
   },
   "homepage": "https://github.com/Bridgeconn/usfm-grammar/tree-sitter-usfm#readme",
   "dependencies": {
-    "nan": "^2.15.0"
+    "tree-sitter": "^0.21.1",
+    "node-addon-api": "^7.1.0",
+    "node-gyp-build": "^4.8.0"
+  },
+  "peerDependencies": {
+    "tree-sitter": "^0.21.0"
+  },
+  "peerDependenciesMeta": {
+    "tree_sitter": {
+      "optional": true
+    }
   },
   "devDependencies": {
-    "tree-sitter-cli": "^0.20.8"
+    "tree-sitter-cli": "^0.22.6",
+    "prebuildify": "^6.0.0"
   },
   "tree-sitter": [
     {
diff --git a/tree-sitter-usfm3/pyproject.toml b/tree-sitter-usfm3/pyproject.toml
new file mode 100644
index 00000000..ae60b7ec
--- /dev/null
+++ b/tree-sitter-usfm3/pyproject.toml
@@ -0,0 +1,34 @@
+[build-system]
+requires = ["setuptools>=42", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "tree-sitter-usfm3"
+description = "Usfm3 grammar for tree-sitter"
+version = "3.0.0-beta.8"
+keywords = ["incremental", "parsing", "tree-sitter", "usfm3"]
+classifiers = [
+  "Intended Audience :: Developers",
+  "License :: OSI Approved :: MIT License",
+  "Topic :: Software Development :: Compilers",
+  "Topic :: Text Processing :: Linguistic",
+  "Typing :: Typed"
+]
+requires-python = ">=3.8"
+license.text = "MIT"
+readme = "python-Readme.md"
+authors = [{ name = "BCS Team", email = "joel@bridgeconn.com" }]
+maintainers = [{ name = "Kavitha Raju", email = "kavitha.raju@bridgeconn.com" }, 
+            { name= "Joel Mathew", email = 'joel@bridgeconn.com'}]
+
+[project.urls]
+Homepage = "https://github.com/Bridgeconn/usfm-grammar/tree/version-3/tree-sitter-usfm3/python-Readme.md"
+
+
+
+[project.optional-dependencies]
+core = ["tree-sitter~=0.21"]
+
+[tool.cibuildwheel]
+build = "cp38-*"
+build-frontend = "build"
diff --git a/tree-sitter-usfm3/python-Readme.md b/tree-sitter-usfm3/python-Readme.md
new file mode 100644
index 00000000..39b31a15
--- /dev/null
+++ b/tree-sitter-usfm3/python-Readme.md
@@ -0,0 +1,25 @@
+# Tree-sitter-usfm3
+
+[Tree sitter](https://tree-sitter.github.io/tree-sitter/) implementation of the [USFM](https://ubsicap.github.io/usfm/) language.
+
+## Installation
+
+```
+pip install tree=sitter
+pip install tree-sitter-usfm3
+```
+
+## Usage
+
+```
+import tree_sitter_usfm3 as tsusfm
+from tree_sitter import Language, Parser
+
+USFM_LANGUAGE = Language(tsusfm.language())
+parser = Parser(USFM_LANGUAGE)
+
+source_code = '\\id GEN\n\\c 1\n\\p\n\\v 1 In the begining..'.encode('utf-8')
+tree = parser.parse(source_code)
+
+print(str(tree.root_node))
+```
diff --git a/tree-sitter-usfm3/setup.py b/tree-sitter-usfm3/setup.py
new file mode 100644
index 00000000..ef89b7cb
--- /dev/null
+++ b/tree-sitter-usfm3/setup.py
@@ -0,0 +1,63 @@
+from os.path import isdir, join
+from platform import system
+
+from setuptools import Extension, find_packages, setup
+from setuptools.command.build import build
+from wheel.bdist_wheel import bdist_wheel
+
+
+class Build(build):
+    def run(self):
+        if isdir("queries"):
+            dest = join(self.build_lib, "tree_sitter_usfm3", "queries")
+            self.copy_tree("queries", dest)
+        super().run()
+
+
+class BdistWheel(bdist_wheel):
+    def get_tag(self):
+        python, abi, platform = super().get_tag()
+        if python.startswith("cp"):
+            python, abi = "cp38", "abi3"
+        return python, abi, platform
+
+
+setup(
+    packages=find_packages("bindings/python")+["tree_sitter"],
+    package_dir={"tree_sitter_usfm3": "bindings/python/tree_sitter_usfm3",
+                "tree_sitter_usfm3.queries": "queries",
+                "tree_sitter": "src/tree_sitter"},
+    package_data={
+        "tree_sitter_usfm3": ["*.pyi", "py.typed"],
+        "tree_sitter_usfm3.queries": ["*.scm"],
+        "tree_sitter": ["*.h"]
+    },
+    ext_package="tree_sitter_usfm3",
+    ext_modules=[
+        Extension(
+            name="_binding",
+            sources=[
+                "bindings/python/tree_sitter_usfm3/binding.c",
+                "src/parser.c",
+                # NOTE: if your language uses an external scanner, add it here.
+            ],
+            extra_compile_args=[
+                "-std=c11",
+            ] if system() != "Windows" else [
+                "/std:c11",
+                "/utf-8",
+            ],
+            define_macros=[
+                ("Py_LIMITED_API", "0x03080000"),
+                ("PY_SSIZE_T_CLEAN", None)
+            ],
+            include_dirs=["src", "src/tree_sitter"],
+            py_limited_api=True,
+        )
+    ],
+    cmdclass={
+        "build": Build,
+        "bdist_wheel": BdistWheel
+    },
+    zip_safe=False
+)


Test patch:
diff --git a/.github/workflows/testpypi_publish.yml b/.github/workflows/testpypi_publish.yml
index 39a4c0b3..77019292 100644
--- a/.github/workflows/testpypi_publish.yml
+++ b/.github/workflows/testpypi_publish.yml
@@ -1,64 +1,92 @@
-name: Test.PyPI Publish
+name: Publish to TestPyPI 
 
 on:
   # push: # need to use this temporarly to be able to publish
   workflow_dispatch: # works only on default branch
 
 jobs:
-  build_wheels:
-    name: Build wheels on ${{ matrix.os }}
-    runs-on: ${{ matrix.os }}
-    strategy:
-      matrix:
-        os: [ubuntu-20.04, windows-2019, macos-11]
-        # os: [ubuntu-20.04]
-
+  build-tree-sitter-usfm3:
+    runs-on: ubuntu-latest
+    
     steps:
-      - uses: actions/checkout@v3
+      # Checks out a copy of your repository on the ubuntu-latest machine
+      - name: Checkout code
+        uses: actions/checkout@v4
       - name: Setup node and npm
-        uses: actions/setup-node@v2
+        uses: actions/setup-node@v4
         with:
-          node-version: 20.4
-      - name: Build the tree-sitter parser
+          node-version: 20
+      - name: Run tests
         run: |
           cd tree-sitter-usfm3
-          npm install .
+          npm install --save nan
+          npm install --save-dev tree-sitter-cli
           ./node_modules/.bin/tree-sitter generate
+          ./node_modules/.bin/tree-sitter test
+
+      - uses: actions/setup-python@v5
+        with:
+          python-version: "3.10"
 
-      - name: Build wheels
-        uses: pypa/cibuildwheel@v2.9.0
-        env:
-          CIBW_BEFORE_BUILD: >
-              python -m pip install tree-sitter==0.20.0 &&
-              python py-usfm-parser/src/grammar_rebuild.py tree-sitter-usfm3 py-usfm-parser/src/usfm_grammar/my-languages.so
+      - name: Build release distributions
+        run: |
+          cd tree-sitter-usfm3
+          python -m pip install build setuptools
+          python -m build
+      - uses: actions/upload-artifact@v3
         with:
-          package-dir: py-usfm-parser
-          output-dir: py-usfm-parser/dist
-          config-file: "py-usfm-parser/pyproject.toml"
+          path: tree-sitter-usfm3/dist/*.tar.gz
 
+  build-py-usfm-parser:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-python@v4
+        with:
+          python-version: "3.10"
+      - name: Build release distributions
+        run: |
+          cd py-usfm-parser
+          python -m pip install build setuptools
+          python -m build
       - uses: actions/upload-artifact@v3
         with:
-          path: py-usfm-parser/dist/*.whl
+          path: py-usfm-parser/dist/*.tar.gz
+
 
   publish_to_pypi:
-    needs: [build_wheels]
+    needs: [build-tree-sitter-usfm3, build-py-usfm-parser]
     runs-on: ubuntu-latest
 
     steps:
       - uses: actions/checkout@master
       - name: Set up Python 3.10
-        uses: actions/setup-python@v3
+        uses: actions/setup-python@v4
         with:
           python-version: "3.10"
+      - uses: actions/download-artifact@v3
+        with:
+          name: artifact
+          path: tree-sitter-usfm3/dist/
+
       - uses: actions/download-artifact@v3
         with:
           name: artifact
           path: py-usfm-parser/dist/
 
-      - name: Publish distribution 📦 to Test PyPI
+      - name: Publish tree-sitter-usfm3 📦 to Test PyPI
+        uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          user: __token__
+          password: ${{ secrets.PUBLISH_ON_TEST_PYPI }}
+          repository_url: https://test.pypi.org/legacy/
+          packages_dir: tree-sitter-usfm3/dist/
+
+      - name: Publish usfm-grammar 📦 to Test PyPI
         uses: pypa/gh-action-pypi-publish@release/v1
         with:
           user: __token__
           password: ${{ secrets.PUBLISH_ON_TEST_PYPI }}
           repository_url: https://test.pypi.org/legacy/
-          packages_dir: py-usfm-parser/dist/
\ No newline at end of file
+          packages_dir: py-usfm-parser/dist/
+