New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

prettier-plugin-pdx-script

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prettier-plugin-pdx-script

Prettier plugin for formatting PDXScript (Paradox game script) files

latest
Source
npmnpm
Version
0.1.0-rc.6
Version published
Maintainers
1
Created
Source

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

RuleBeforeAfter
Indentation4 spaces or mixedTabs (one per nesting level)
Empty blocksmy_decl = { }my_decl = {}
Block valueskey = { nested = val }key = {
    nested = val
}
Comments # comment# comment
OperatorsPreserved 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

  • 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.

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:

  • tree-sitter runtime WASMtree-sitter.wasm, loaded by web-tree-sitter's Parser.init() via locateFile
  • 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

FilePurpose
index.tsExports languages, parsers, printers for Prettier. Defines the parser with caching, configurable WASM loading (setGrammarBinary, setLocateFile), and ESM/CJS __dirname resolution.
printer.tsExports the printers object with a print function that walks the AST and produces formatted Prettier Doc output. Handles all PDXScript node types.
tsup.config.tsBuild 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 TypeDescriptionExample
source_fileRoot node containing all declarations
declarationTop-level named blockmy_event = { ... }
blockCurly-brace delimited contents{ key = value }
key_valueKey-operator-value pairkey = value
valueWrapper for one of: quoted string, localisation key, word, or block
quoted_stringDouble-quoted string literal"hello world"
localisation_keyLocalisation reference[MY_KEY]
wordIdentifier, number, or unquoted valuemy_var, 42
commentLine 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

Keywords

prettier

FAQs

Package last updated on 26 Mar 2026

Did you know?

Socket

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.

Install

Related posts