
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
prettier-plugin-pdx-script
Advanced tools
Prettier plugin for formatting PDXScript (Paradox game script) files
A Prettier plugin for formatting PDXScript (Paradox game script) files. Powered by tree-sitter-pdx_script.
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.
npm install --save-dev prettier-plugin-pdx-script
Prettier will automatically discover the plugin. No additional configuration is needed.
# 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"
| 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 |
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 = {}
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
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.
Tab indentation: Paradox script files conventionally use tab indentation, which is preserved in this plugin.
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.
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().
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.
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:
tree-sitter.wasm, loaded by web-tree-sitter's Parser.init() via locateFiletree-sitter-pdx_script.wasm, loaded by our setGrammarBinary() callbackIf either fails to resolve, the plugin will throw at init time.
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);
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.
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).
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
| 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. |
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 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 |
^3.8.1 — Code formatter plugin API^0.26.7 — WASM runtime for tree-sitter parsersThe 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/
Build the compiled output (ESM + CJS via tsup):
bun run build
Run the test suite:
bun test
MIT
FAQs
Prettier plugin for formatting PDXScript (Paradox game script) files
We found that prettier-plugin-pdx-script demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.