npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

prettier-plugin-pdx-script

v0.1.0-rc.6

Published

Prettier plugin for formatting PDXScript (Paradox game script) files

Readme

prettier-plugin-pdx-script

License: MIT Prettier

A Prettier plugin for formatting PDXScript (Paradox game script) files. Powered by tree-sitter-pdx_script.

Overview

PDXScript is the scripting language used in Paradox Interactive games such as Victoria 3, Hearts of Iron IV, Stellaris, Europa Universalis IV, and Crusader Kings III. These scripts are distributed as .txt files with nested key-value and block structures.

This plugin provides automatic, consistent formatting for PDXScript files using Prettier. It uses a tree-sitter WASM parser to reliably parse PDXScript, then applies opinionated formatting rules. The parser is compiled from tree-sitter-pdx_script, a tree-sitter grammar for Paradox script files.

Installation

npm install --save-dev prettier-plugin-pdx-script

Prettier will automatically discover the plugin. No additional configuration is needed.

Usage

# Format a single file
npx prettier --write path/to/file.txt

# Check formatting without writing
npx prettier --check path/to/file.txt

# Format all .txt files in a directory
npx prettier --write "path/to/scripts/**/*.txt"

Formatting Rules

| Rule | Before | After | | ------------ | ------------------------ | ---------------------------------------------------------- | | Indentation | 4 spaces or mixed | Tabs (one per nesting level) | | Empty blocks | my_decl = { } | my_decl = {} | | Block values | key = { nested = val } | key = {    nested = val} | | Comments | # comment | # comment | | Operators | Preserved as-is | =, >, < all supported |

Example

Input:

my_declaration={
    key1= value1
    key2 =value2
    nested={
        inner_key = "hello world"
    }
    # a comment
}
another_decl = { }

Output:

my_declaration = {
	key1 = value1
	key2 = value2
	nested = {
		inner_key = "hello world"
	}
	# a comment
}
another_decl = {}

Architecture

The plugin follows the standard Prettier plugin architecture with three components:

Input Text
    │
    ▼
┌──────────────┐
│   Parser     │  tree-sitter WASM parser + AST conversion
│  (index.ts)  │  Converts tree-sitter SyntaxNodes → plain objects
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  Printer     │  Walks the AST, produces Prettier Doc output
│(printer.ts)  │  Handles each node type with specific formatting rules
└──────┬───────┘
       │
       ▼
  Formatted Text

Key Design Decisions

  1. Tree-to-plain-object conversion: Tree-sitter nodes use JavaScript getters (e.g., node.children is computed), but Prettier's path.map/path.call traverse node properties directly. The convertTree() function in index.ts converts the tree-sitter AST to plain objects that Prettier can navigate.

  2. Tab indentation: Paradox script files conventionally use tab indentation, which is preserved in this plugin.

  3. Operator preservation: The =, >, and < operators in key-value pairs are preserved from the source. They are anonymous tokens in tree-sitter (not in namedChildren) and are found by iterating node.children.

CJS / ESM Dual Support

This package ships both ESM and CJS entry points:

{
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    },
    "./dist/tree-sitter/tree-sitter-pdx_script.wasm": "./dist/tree-sitter/tree-sitter-pdx_script.wasm",
    "./package.json": "./package.json"
  }
}

ESM consumers use import, CJS consumers use require() — no dynamic await import() needed.

The grammar WASM is also accessible via require.resolve("prettier-plugin-pdx-script/dist/tree-sitter/tree-sitter-pdx_script.wasm") for use with setGrammarBinary().

API

setGrammarBinary(loader)

Override the grammar WASM binary loader. Use this when bundling the plugin (e.g. in a VS Code extension) where the WASM file cannot be loaded from the plugin's package directory.

import { setGrammarBinary } from "prettier-plugin-pdx-script";

// Load from a bundled Uint8Array
setGrammarBinary(() => myWasmBinary);

getGrammarBinary()

Get the current grammar binary loader function. Useful for wrapping the default loader or testing.

setLocateFile(fn)

Override the locateFile callback used to locate web-tree-sitter's own runtime WASM (tree-sitter.wasm). This is passed directly to web-tree-sitter's Parser.init({ locateFile }).

Use this when bundling the plugin and the default resolution (relative to scriptDir) does not point to the correct location.

import { setLocateFile } from "prettier-plugin-pdx-script";

setLocateFile((fileName, _scriptDir) => {
  return path.join(__dirname, "wasm", fileName);
});

Important: setLocateFile() must be called before any parse() invocation (same constraint as setGrammarBinary()).

getLocateFile()

Get the current locateFile callback. Useful for wrapping the default resolver or testing.

Bundling

When bundling this plugin (e.g. in a VS Code extension or webpack/esbuild build), the default WASM loading may fail. There are two WASM files to account for:

  1. tree-sitter runtime WASMtree-sitter.wasm, loaded by web-tree-sitter's Parser.init() via locateFile
  2. grammar WASMtree-sitter-pdx_script.wasm, loaded by our setGrammarBinary() callback

If either fails to resolve, the plugin will throw at init time.

Grammar WASM

Call setGrammarBinary() to supply the grammar WASM directly:

import { setGrammarBinary } from "prettier-plugin-pdx-script";
import wasmBinary from "./tree-sitter-pdx_script.wasm";

setGrammarBinary(() => wasmBinary);

Runtime WASM (locateFile)

Call setLocateFile() to override how web-tree-sitter locates its own runtime WASM:

import { setLocateFile } from "prettier-plugin-pdx-script";

setLocateFile((fileName, _scriptDir) => {
  return path.join(__dirname, "wasm", fileName);
});

Both callbacks must be called before any parse() invocation.

Parser Caching

The tree-sitter parser is initialized once and cached for the lifetime of the module. Parser.init() and Language.load() are only called on the first parse() invocation; subsequent calls reuse the cached parser (~70ms saved per call).

File Structure

prettier-plugin-pdx-script/
├── index.ts                  # Plugin entry point: language definition, parser, API
├── printer.ts                # Prettier printer: AST → Doc formatting
├── tsup.config.ts            # tsup build config (dual CJS/ESM)
├── package.json              # Package metadata and dependencies
├── README.md                 # This file
├── tree-sitter/
│   └── tree-sitter-pdx_script.wasm   # Compiled tree-sitter WASM parser
└── dist/                     # Compiled output (generated by build)
    ├── index.js              # ESM entry point
    ├── index.cjs             # CJS entry point
    ├── index.d.ts            # TypeScript declarations (ESM)
    ├── index.d.cts           # TypeScript declarations (CJS)
    └── tree-sitter/
        └── tree-sitter-pdx_script.wasm

Source Files

| File | Purpose | | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | index.ts | Exports languages, parsers, printers for Prettier. Defines the parser with caching, configurable WASM loading (setGrammarBinary, setLocateFile), and ESM/CJS __dirname resolution. | | printer.ts | Exports the printers object with a print function that walks the AST and produces formatted Prettier Doc output. Handles all PDXScript node types. | | tsup.config.ts | Build configuration for tsup — produces dual CJS/ESM output with TypeScript declarations. |

PDXScript Language Reference

Grammar

source_file  → (declaration | comment)*
declaration  → name = block
block        → { (key_value | comment)* }
key_value    → key (= | > | <) value
value        → quoted_string | localisation_key | word | block
quoted_string → "..."
localisation_key → [word]
comment      → #.*$
word         → [^\s{}\[\]()=#"<>]+

Node Types

| Node Type | Description | Example | | ------------------ | ------------------------------------------------------------------- | --------------------- | | source_file | Root node containing all declarations | — | | declaration | Top-level named block | my_event = { ... } | | block | Curly-brace delimited contents | { key = value } | | key_value | Key-operator-value pair | key = value | | value | Wrapper for one of: quoted string, localisation key, word, or block | — | | quoted_string | Double-quoted string literal | "hello world" | | localisation_key | Localisation reference | [MY_KEY] | | word | Identifier, number, or unquoted value | my_var, 42 | | comment | Line comment starting with # | # this is a comment |

Dependencies

  • prettier ^3.8.1 — Code formatter plugin API
  • web-tree-sitter ^0.26.7 — WASM runtime for tree-sitter parsers

Building the WASM parser

The tree-sitter-pdx_script.wasm file is pre-compiled and included in the package. The grammar lives in a separate repository: tree-sitter-pdx_script.

To rebuild the WASM file (e.g., after modifying the grammar):

git clone https://github.com/Myriad4Link/tree-sitter-pdx_script
cd tree-sitter-pdx_script
npx tree-sitter build --wasm
cp tree-sitter-pdx_script.wasm /path/to/prettier-plugin-pdx-script/tree-sitter/

Development

Build the compiled output (ESM + CJS via tsup):

bun run build

Run the test suite:

bun test

License

MIT