Tree-Sitter Wikitext Parser
This repository contains the implementation of a Tree-Sitter parser for Wikitext, a markup language used by MediaWiki.
Try the parse in the playground
Overview
Tree-Sitter is a powerful parser generator tool and incremental parsing library. It is designed to build concrete syntax trees for source files and efficiently update them as the source changes. This project leverages Tree-Sitter to parse Wikitext, enabling structured analysis and manipulation of MediaWiki content.
Features
- Incremental Parsing: Efficiently updates syntax trees as the source changes.
- Language Agnostic: Can be embedded in applications written in C, Python, Go, Rust, Node.js, and Swift.
- Robust Parsing: Handles syntax errors gracefully to provide useful results.
- Custom Grammar: Implements a grammar tailored for Wikitext.
Repository Structure
src/: Contains the core C implementation of the parser.bindings/: Language-specific bindings for Python, Go, Node.js, Rust, and Swift.grammar.js: Defines the grammar for Wikitext.queries/: Contains Tree-Sitter query files for extracting specific syntax patterns.tests/: Unit tests for validating the parser's functionality.
Installation
Prerequisites
- A C compiler (e.g., GCC or Clang)
- Node.js (for building the grammar)
- Python 3.6+ (optional, for Python bindings)
Build Instructions
-
Clone the repository:
git clone https://github.com/santhoshtr/tree-sitter-wikitext.git cd tree-sitter-wikitext
-
Build the parser:
npm install -
(Optional) Build language-specific bindings:
- Python: Run
python setup.py build. - Rust: Use
cargo build. - Go: Use
go build.
- Python: Run
Usage
Embedding in Applications
The parser can be embedded in applications written in various languages. For example:
- Python: Use the
tree-sitterPython module to load and use the parser. - Node.js: Import the parser as a Node.js module.
- Rust: Use the
tree-sittercrate to integrate the parser.
Example: Parsing Wikitext in Python
First, install the required dependencies:
pip install tree-sitter
Then use the parser in your Python code:
from tree_sitter import Language, Parser, Query, QueryCursor
import tree_sitter_wikitext as tswikitext
# Create a language object
WIKITEXT_LANGUAGE = Language(tswikitext.language())
# Create a parser
parser = Parser(WIKITEXT_LANGUAGE)
# Parse some wikitext
source_code = b"""
== Introduction ==
This is a '''bold''' text with ''italic'' formatting.
* List item 1
* List item 2
[[Link to another page]]
"""
tree = parser.parse(source_code)
# Print the syntax tree
print(tree.root_node)
# Walk through the tree
def walk_tree(node, depth=0):
indent = " " * depth
print(f"{indent}{node.type}: {node.text.decode('utf-8')[:50]}")
for child in node.children:
walk_tree(child, depth + 1)
walk_tree(tree.root_node)
# Query for specific nodes (e.g., all headings)
query = Query(WIKITEXT_LANGUAGE,
"""
(heading2) @heading
""")
query_cursor = QueryCursor(query)
captures = query_cursor.captures(tree.root_node)
for capture_name in captures:
print(f"Found {capture_name}: {captures[capture_name][0].text.decode('utf-8').strip()}")```
### Example: Parsing Wikitext in Node.js
First, install the parser:
```bash
npm install tree-sitter tree-sitter-wikitext
Then use it in your Node.js application:
const Parser = require('tree-sitter');
const Wikitext = require('tree-sitter-wikitext');
// Create a parser
const parser = new Parser();
parser.setLanguage(Wikitext);
// Parse some wikitext
const sourceCode = `
== Introduction ==
This is a '''bold''' text with ''italic'' formatting.
* List item 1
* List item 2
[[Link to another page]]
`;
const tree = parser.parse(sourceCode);
// Print the syntax tree
console.log(tree.rootNode.toString());
// Walk through the tree
function walkTree(node, depth = 0) {
const indent = " ".repeat(depth);
console.log(`${indent}${node.type}: ${node.text.substring(0, 50)}`);
for (const child of node.children) {
walkTree(child, depth + 1);
}
}
walkTree(tree.rootNode);
// Query for specific nodes
const query = Wikitext.query(`
(heading) @heading
(bold) @bold
(italic) @italic
(link) @link
`);
const captures = query.captures(tree.rootNode);
captures.forEach(capture => {
console.log(`Found ${capture.name}: ${capture.node.text.trim()}`);
});
// Find all headings
function findHeadings(node) {
const headings = [];
if (node.type === 'heading') {
headings.push({
level: node.children.filter(c => c.type === 'heading_marker')[0]?.text.length || 2,
text: node.text.replace(/^=+\s*|\s*=+$/g, '').trim()
});
}
for (const child of node.children) {
headings.push(...findHeadings(child));
}
return headings;
}
const headings = findHeadings(tree.rootNode);
console.log('Headings found:', headings);
Advanced Usage in Node.js
For more advanced use cases, you can create incremental parsers and handle large documents:
const Parser = require('tree-sitter');
const Wikitext = require('tree-sitter-wikitext');
class WikitextProcessor {
constructor() {
this.parser = new Parser();
this.parser.setLanguage(Wikitext);
}
parseDocument(content) {
return this.parser.parse(content);
}
updateDocument(oldTree, content, startIndex, oldEndIndex, newEndIndex) {
// For incremental parsing
oldTree.edit({
startIndex,
oldEndIndex,
newEndIndex,
startPosition: { row: 0, column: startIndex },
oldEndPosition: { row: 0, column: oldEndIndex },
newEndPosition: { row: 0, column: newEndIndex }
});
return this.parser.parse(content, oldTree);
}
extractMetadata(tree) {
const metadata = {
headings: [],
links: [],
templates: [],
categories: []
};
// Implementation would depend on your specific grammar rules
// This is a simplified example
function traverse(node) {
switch (node.type) {
case 'heading':
metadata.headings.push(node.text.trim());
break;
case 'link':
metadata.links.push(node.text.trim());
break;
// Add more cases based on your grammar
}
for (const child of node.children) {
traverse(child);
}
}
traverse(tree.rootNode);
return metadata;
}
}
// Usage
const processor = new WikitextProcessor();
const tree = processor.parseDocument(sourceCode);
const metadata = processor.extractMetadata(tree);
console.log('Document metadata:', metadata);
Example: Parsing Wikitext in Rust
use tree_sitter::{Parser, Language};
fn main() {
// Create a new parser
let mut parser = tree_sitter::Parser::new();
parser.set_language(&tree_sitter_wikitext::LANGUAGE.into()).expect("Error loading wikitext grammar");
// Parse a Wikitext string
let source_code = "== Heading ==\nThis is a paragraph.\n";
let tree = parser.parse(source_code, None).unwrap();
// Print the syntax tree
println!("{}", tree.root_node().to_sexp());
}
Using with Neovim
Checkout the repo, add the following configuration to init.lua of your nvim installation.
--- Refer https://github.com/nvim-treesitter/nvim-treesitter
local parser_config = require("nvim-treesitter.parsers").get_parser_configs()
parser_config.wikitext = {
install_info = {
url = "~/path/to/tree-sitter-wikitext", -- local path or git repo
files = { "src/parser.c" }, -- note that some parsers also require src/scanner.c or src/scanner.cc
-- optional entries:
branch = "main", -- default branch in case of git repo if different from master
generate_requires_npm = false, -- if stand-alone parser without npm dependencies
requires_generate_from_grammar = false, -- if folder contains pre-generated src/parser.c
},
filetype = "wikitext", -- if filetype does not match the parser name
}
vim.filetype.add({
pattern = {
[".*/*.wikitext"] = "wikitext",
},
})
Link the queries folder of tree-sitter-wikitext to queries/wikitext folder of nvim
cd ~/.config/nvim
mkdir -p queries
ln -s path/to/tree-sitter-wikitext/queries queries/wikitext
Re-open nvim. Open any file with .wikitext extension. You should see syntax highlighting. You can also inspect the tree-sitter tree using :InspectTree command
To run queries against a buffer, run :EditQuery wikitext. A scratch buffer will be opened. Write your Tree-Sitter query there, in normal node, move cursor over the capture names. You will see the corresponding text in the buffer get highlighted.
Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository.
- Create a new branch for your feature or bug fix.
- Submit a pull request with a detailed description of your changes.
License
This project is licensed under the MIT License. See the LICENSE.md file for details.
Metadata
Release files for tree-sitter-wikitext 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tree_sitter_wikitext-0.1.3.tar.gz | 98.2 kB | Without provenance | Details |
Built distributions (wheels)
Total release size: 709.0 kB
Release files / tree_sitter_wikitext-0.1.3.tar.gz
| Download URL | tree_sitter_wikitext-0.1.3.tar.gz |
|---|---|
| Size | 98.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bf099470ac851d6f5eb2ee07d18ecb48d0f6de9dac5c10b5f363f2347596ec6f
|
|
BLAKE2b-256 checksum How to use checksums |
a56d0b3f2b905b2878e8eddf964e5fac4955824f547ae81b1da91fe137ad6f7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / tree_sitter_wikitext-0.1.3-cp39-abi3-win_arm64.whl
| Download URL | tree_sitter_wikitext-0.1.3-cp39-abi3-win_arm64.whl |
|---|---|
| Size | 63.8 kB |
| Tags | CPython 3.9 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
dc05bb331ff774a7c32340efcb9714c70ff7c446c1921ac6189d094f98b9a4b0
|
|
BLAKE2b-256 checksum How to use checksums |
785be5b1dabac948854fbee7f41e9000acf0bffdaeb236dc75114a1b56b4e818
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / tree_sitter_wikitext-0.1.3-cp39-abi3-win_amd64.whl
| Download URL | tree_sitter_wikitext-0.1.3-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 65.2 kB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
79c95ecae05d9fc82afd3e6e1be573d1f68c656d2dad2bff40699c5625749422
|
|
BLAKE2b-256 checksum How to use checksums |
f3b654f1d7f8296ecb405082dd3ff75d7e01719038e328fc4598affce8a8c767
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / tree_sitter_wikitext-0.1.3-cp39-abi3-musllinux_1_2_x86_64.whl
| Download URL | tree_sitter_wikitext-0.1.3-cp39-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 87.7 kB |
| Tags | CPython 3.9 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
5a734232268590d1dce40a99c0a2cbf4847515803011c8c4cb61b34762ee42f9
|
|
BLAKE2b-256 checksum How to use checksums |
354a9c67a868ef984fb85df54cf20ca5e0a1e1c00f33af361a9cb1164f14e4f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / tree_sitter_wikitext-0.1.3-cp39-abi3-musllinux_1_2_aarch64.whl
| Download URL | tree_sitter_wikitext-0.1.3-cp39-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 89.0 kB |
| Tags | CPython 3.9 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
51d62657653724fc81687812bb46233d3665629b7053754f5cdd685685fcb883
|
|
BLAKE2b-256 checksum How to use checksums |
f2ca79f08097783d6e6e10104ab97271c5c47f93e4ab78e9d41708b7a60e02ed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / tree_sitter_wikitext-0.1.3-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
| Download URL | tree_sitter_wikitext-0.1.3-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 90.2 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
9c04449cf1e84f414b7c6df6e2f61c0321c92124e96f5ee3748fbd9ad29e3824
|
|
BLAKE2b-256 checksum How to use checksums |
18dd7beee6525ef1f78b849e9e02f4dd177688f567a2d6fee3b3cffa0d7e7b0e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / tree_sitter_wikitext-0.1.3-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
| Download URL | tree_sitter_wikitext-0.1.3-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 87.8 kB |
| Tags | CPython 3.9 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
2870c06bff34b1f9910efd71a14e57a1e5303dee0f5ba8082a7b9108a8bcc866
|
|
BLAKE2b-256 checksum How to use checksums |
0fe907acebb638ef57ca242d07666bb6449a663e45accb348b9e2b8ba1b92367
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / tree_sitter_wikitext-0.1.3-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | tree_sitter_wikitext-0.1.3-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 65.0 kB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
45e2a08fe10257e08a5b5ed1eee89381e8867a27ccfb9212f35c5da48332058d
|
|
BLAKE2b-256 checksum How to use checksums |
2e8743a63ec640699e9118d6086adb9f93aeb8bb34dadb4eac018f38f6a3735e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / tree_sitter_wikitext-0.1.3-cp39-abi3-macosx_10_9_x86_64.whl
| Download URL | tree_sitter_wikitext-0.1.3-cp39-abi3-macosx_10_9_x86_64.whl |
|---|---|
| Size | 61.9 kB |
| Tags | CPython 3.9 abi3 macOS 10.9+ x86-64 |
|
SHA-256 checksum How to use checksums |
1bc0b4426a3753c7cb5cd8d66d4375f688a61a7a5d09f948b5c3e4ec143f62a2
|
|
BLAKE2b-256 checksum How to use checksums |
1182372aa6cf308b8293c7430bc0a97c7ee1e02dbd152fb67a59b4767b0c1bfe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Security for tree-sitter-wikitext 0.1.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.