prettier-plugin-wolfram 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +290 -0
  3. package/bin/prettier-wolfram.js +55 -0
  4. package/package.json +58 -0
  5. package/src/index.js +80 -0
  6. package/src/options.js +206 -0
  7. package/src/parser/adapter.js +690 -0
  8. package/src/parser/cstEqual.js +18 -0
  9. package/src/parser/index.js +29 -0
  10. package/src/parser/operators.js +35 -0
  11. package/src/parser/position.js +62 -0
  12. package/src/parser/tree-sitter-wolfram.wasm +0 -0
  13. package/src/range.js +98 -0
  14. package/src/rules/index.js +57 -0
  15. package/src/rules/line-width.js +129 -0
  16. package/src/rules/newlines-between-definitions.js +103 -0
  17. package/src/rules/no-bare-symbol-set.js +19 -0
  18. package/src/rules/no-dynamic-module-leak.js +74 -0
  19. package/src/rules/no-general-infix-function.js +52 -0
  20. package/src/rules/no-shadowed-pattern.js +71 -0
  21. package/src/rules/no-unused-module-var.js +84 -0
  22. package/src/rules/prefer-rule-delayed.js +59 -0
  23. package/src/rules/spacing-commas.js +64 -0
  24. package/src/rules/spacing-operators.js +87 -0
  25. package/src/translator/commentSpacing.js +51 -0
  26. package/src/translator/docComments.js +89 -0
  27. package/src/translator/index.js +98 -0
  28. package/src/translator/nodes/binary.js +205 -0
  29. package/src/translator/nodes/call.js +254 -0
  30. package/src/translator/nodes/compound.js +117 -0
  31. package/src/translator/nodes/container.js +194 -0
  32. package/src/translator/nodes/group.js +159 -0
  33. package/src/translator/nodes/infix.js +408 -0
  34. package/src/translator/nodes/leaf.js +605 -0
  35. package/src/translator/nodes/postfix.js +29 -0
  36. package/src/translator/nodes/prefix.js +27 -0
  37. package/src/translator/nodes/ternary.js +82 -0
  38. package/src/translator/ruleAlignment.js +133 -0
  39. package/src/translator/sourceLines.js +49 -0
  40. package/src/translator/sourcePreservation.js +22 -0
  41. package/src/translator/specialForms.js +665 -0
  42. package/src/utils/codeSpacing.js +420 -0
  43. package/src/utils/cstErrors.js +36 -0
  44. package/src/utils/offsets.js +132 -0
  45. package/src/utils/operatorSpacing.js +49 -0
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2026 Antonis Aristeidou
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,290 @@
1
+ <p align="center">
2
+ <img src="vscode-extension/assets/icon.png" width="96" height="96" alt="@wrel/prettier-plugin-wolfram logo">
3
+ </p>
4
+
5
+ <h1 align="center">Wolfram Prettier Plugin — @wrel/prettier-plugin-wolfram</h1>
6
+
7
+ <p align="center">
8
+ <strong>Prettier formatting for Wolfram Language, powered by tree-sitter.</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="#install">Install</a> ·
13
+ <a href="#cli-usage">CLI</a> ·
14
+ <a href="#prettier-configuration">Configuration</a> ·
15
+ <a href="#vs-code-extension">VS Code</a>
16
+ </p>
17
+
18
+ The plugin parses Wolfram Language through a bundled tree-sitter WebAssembly
19
+ grammar and prints the result with Prettier. It supports `.wl`, `.wls`, `.wlt`,
20
+ `.mt`, and `.m` files. No Wolfram Engine or local kernel installation is required.
21
+
22
+ Not affiliated with the original prettier extension.
23
+
24
+ ## At A Glance
25
+
26
+ | Need | What this package provides |
27
+ | ------------------- | -------------------------------------------------------------------------------- |
28
+ | Prettier formatting | A Wolfram parser and printer for Prettier 3 projects. |
29
+ | Editor support | A bundled VS Code extension with document, range, and format-on-save workflows. |
30
+ | Diagnostics | Formatter-backed rule findings, line-width hints, and fixable style diffs. |
31
+ | Zero dependencies | Parsing via a bundled tree-sitter WASM grammar; no Wolfram Engine required. |
32
+
33
+ ## Requirements
34
+
35
+ - Node.js
36
+ - Prettier 3.x
37
+
38
+ ## Install
39
+
40
+ Install Prettier and the plugin in the project that contains your Wolfram
41
+ source:
42
+
43
+ ```bash
44
+ npm install --save-dev prettier @wrel/prettier-plugin-wolfram
45
+ ```
46
+
47
+ Add the plugin to your Prettier configuration for CLI use:
48
+
49
+ ```json
50
+ {
51
+ "plugins": ["@wrel/prettier-plugin-wolfram"]
52
+ }
53
+ ```
54
+
55
+ ## CLI Usage
56
+
57
+ Format a file to stdout:
58
+
59
+ ```bash
60
+ npx prettier --plugin @wrel/prettier-plugin-wolfram --parser wolfram file.wl
61
+ ```
62
+
63
+ Write changes back:
64
+
65
+ ```bash
66
+ npx prettier --plugin @wrel/prettier-plugin-wolfram --parser wolfram --write file.wl
67
+ ```
68
+
69
+ Check whether files would change:
70
+
71
+ ```bash
72
+ npx prettier --plugin @wrel/prettier-plugin-wolfram --parser wolfram --check "src/**/*.wl"
73
+ ```
74
+
75
+ Format a byte range with Prettier's standard range flags:
76
+
77
+ ```bash
78
+ npx prettier --plugin @wrel/prettier-plugin-wolfram --parser wolfram --range-start 0 --range-end 200 file.wl
79
+ ```
80
+
81
+ Range formatting expands to the top-level Wolfram expressions touched by the
82
+ range. This avoids formatting incomplete fragments that the parser cannot
83
+ parse on their own.
84
+
85
+ ## Formatting Features
86
+
87
+ - Formats Wolfram calls, lists, associations, prefix, postfix, infix, binary,
88
+ ternary, compound, and leaf nodes produced by the tree-sitter grammar.
89
+ - Applies specialized layouts to configurable block-style forms such as
90
+ `Module`, `With`, `Block`, and `DynamicModule`.
91
+ - Applies condition-first layout to configurable forms such as `If` and
92
+ `Switch`.
93
+ - Applies alternating condition/body layout to configurable case forms such as
94
+ `Which`.
95
+ - Wraps long string literals and flattens nested `StringJoin[...]` calls into a
96
+ stable multiline `StringJoin[...]` layout when needed.
97
+ - Preserves leading comments, trailing comments, multiline comments, and
98
+ top-level comment blocks.
99
+ - Aligns trailing documentation comments either automatically or at a configured
100
+ column.
101
+ - Preserves ordinary blank lines up to a configured cap and controls spacing
102
+ between adjacent definitions, including separate `Set` and `SetDelayed`
103
+ definition groups.
104
+ - Optionally aligns `Rule` and `RuleDelayed` values in multiline argument, list,
105
+ and association layouts.
106
+ - Normalizes general infix `x ~ f ~ y` to `f[x, y]` unless the function head is
107
+ listed in `wolfram.preserveTildeInfixFunctions`.
108
+ - Leaves parse-error files and unsupported CST nodes as original source instead
109
+ of printing internal parser details.
110
+ - Produces idempotent output: a second format pass should not change the first
111
+ pass result.
112
+
113
+ ## Prettier Configuration
114
+
115
+ Typical `.prettierrc` example:
116
+
117
+ ```json
118
+ {
119
+ "plugins": ["@wrel/prettier-plugin-wolfram"],
120
+ "printWidth": 80,
121
+ "tabWidth": 2,
122
+ "wolfram": {
123
+ "newlinesBetweenDefinitions": 1,
124
+ "newlinesBetweenSameNameDefinitions": 0,
125
+ "maxBlankLinesBetweenCode": 1,
126
+ "trailingNewline": false,
127
+ "spaceAfterComma": true,
128
+ "spaceAroundOperators": true,
129
+ "alignRuleValues": false,
130
+ "documentationCommentColumn": 0,
131
+ "documentationCommentPadding": 2,
132
+ "topLevelSpacingMode": "declarations",
133
+ "preserveTildeInfixFunctions": "",
134
+ "moduleVarsBreakThreshold": 40,
135
+ "conditionFirstFunctions": "If,Switch",
136
+ "blockStructureFunctions": "Module,With,Block,DynamicModule",
137
+ "caseStructureFunctions": "Which",
138
+ "lintRules": "{}"
139
+ }
140
+ }
141
+ ```
142
+
143
+ Use Prettier's standard `printWidth`, `tabWidth`, `useTabs`, `endOfLine`, and
144
+ related options for normal Prettier behavior. The options below are specific to
145
+ this plugin.
146
+
147
+ | Option | Type | Default | Description |
148
+ | ----------------------------------------------------- | ----------- | ----------------------------------- | ----------- |
149
+ | `wolfram.newlinesBetweenDefinitions` | integer | `1` | Blank lines inserted between adjacent top-level definitions such as `Set`, `SetDelayed`, `TagSet`, `TagSetDelayed`, `UpSet`, and `UpSetDelayed`. |
150
+ | `wolfram.newlinesBetweenSetDefinitions` | integer | inherit | Blank lines inserted between adjacent `Set`-family definitions. |
151
+ | `wolfram.newlinesBetweenSetDelayedDefinitions` | integer | inherit | Blank lines inserted between adjacent `SetDelayed`-family definitions. |
152
+ | `wolfram.newlinesBetweenSetAndSetDelayedDefinitions` | integer | inherit | Blank lines inserted between mixed `Set`-family and `SetDelayed`-family definitions. |
153
+ | `wolfram.newlinesBetweenSameNameDefinitions` | integer | `0` | Blank lines inserted between adjacent definitions that belong to the same symbol. |
154
+ | `wolfram.maxBlankLinesBetweenCode` | integer | `1` | Maximum source blank lines preserved between non-definition code statements. |
155
+ | `wolfram.trailingNewline` | boolean | `false` | Emits one trailing newline at the end of non-empty formatted files. |
156
+ | `wolfram.spaceAfterComma` | boolean | `true` | Inserts a space after commas in argument lists, lists, and associations. |
157
+ | `wolfram.spaceAroundOperators` | boolean | `true` | Inserts spaces around most infix, binary, and ternary operators. Operators that are normally tight, such as `::`, `?`, and `;;`, stay tight. |
158
+ | `wolfram.alignRuleValues` | boolean | `false` | Vertically aligns `Rule` and `RuleDelayed` values in multiline argument, list, and association layouts. |
159
+ | `wolfram.documentationCommentColumn` | integer | `0` | Column for trailing documentation comments. `0` computes a column per contiguous block. |
160
+ | `wolfram.documentationCommentPadding` | integer | `2` | Minimum spaces between code and an aligned trailing documentation comment when the column is computed automatically. |
161
+ | `wolfram.topLevelSpacingMode` | string | `"declarations"` | Top-level blank-line policy. Allowed values are `declarations`, `all`, and `none`. |
162
+ | `wolfram.preserveTildeInfixFunctions` | string | `""` | Comma-separated function names that stay in `x ~ f ~ y` form instead of normalizing to `f[x, y]`. |
163
+ | `wolfram.moduleVarsBreakThreshold` | integer | `40` | Character count at which block-structure variable lists break across lines. |
164
+ | `wolfram.conditionFirstFunctions` | string | `"If,Switch"` | Comma-separated heads whose first argument stays on the same line as the head when it fits. |
165
+ | `wolfram.blockStructureFunctions` | string | `"Module,With,Block,DynamicModule"` | Comma-separated heads formatted with block-structure argument layout. |
166
+ | `wolfram.caseStructureFunctions` | string | `"Which"` | Comma-separated heads formatted with alternating condition/body indentation. |
167
+ | `wolfram.lintRules` | string | `"{}"` | JSON object string for rule-level overrides used by lint integrations, for example `{"prefer-rule-delayed":"error"}`. |
168
+
169
+ ### Top-Level Spacing
170
+
171
+ `wolfram.topLevelSpacingMode` controls how the blank-line options are applied:
172
+
173
+ | Value | Behavior |
174
+ | -------------- | ----------- |
175
+ | `declarations` | Adjacent definitions use `wolfram.newlinesBetweenDefinitions` plus any configured `Set`/`SetDelayed` and same-name overrides; other top-level code preserves source blank lines up to `wolfram.maxBlankLinesBetweenCode`. |
176
+ | `all` | All top-level statements require at least one blank line when `wolfram.maxBlankLinesBetweenCode` allows it, while still preserving no more than the configured maximum. |
177
+ | `none` | Removes top-level blank lines. |
178
+
179
+ Set `wolfram.maxBlankLinesBetweenCode` to `0` to remove preserved ordinary code
180
+ gaps. Set `wolfram.newlinesBetweenDefinitions` to `0` to keep adjacent
181
+ definitions together.
182
+
183
+ The `Set`/`SetDelayed` override options inherit
184
+ `wolfram.newlinesBetweenDefinitions` when omitted. Same-name definition groups,
185
+ such as usage messages, options, attributes, and overloads for the same symbol,
186
+ use `wolfram.newlinesBetweenSameNameDefinitions`.
187
+
188
+ ### Custom Form Layout
189
+
190
+ The layout categories are driven by comma-separated symbol lists:
191
+
192
+ ```json
193
+ {
194
+ "wolfram": {
195
+ "conditionFirstFunctions": "If,Switch,MyConditionForm",
196
+ "blockStructureFunctions": "Module,With,Block,DynamicModule,MyBlock",
197
+ "caseStructureFunctions": "Which,MyCaseForm"
198
+ }
199
+ }
200
+ ```
201
+
202
+ Direct comments inside a specialized call cause the formatter to fall back to
203
+ the generic call layout so comments stay attached to the original arguments.
204
+
205
+ ## Lint CLI
206
+
207
+ The package also exposes a small rule runner:
208
+
209
+ ```bash
210
+ npx prettier-wolfram lint "src/**/*.wl"
211
+ ```
212
+
213
+ It prints diagnostics as:
214
+
215
+ ```text
216
+ path/to/file.wl:line:column: WARN [rule-name] message
217
+ ```
218
+
219
+ Override rule levels with `WOLFRAM_LINT_RULES`:
220
+
221
+ ```bash
222
+ WOLFRAM_LINT_RULES='{"no-bare-symbol-set":"off","prefer-rule-delayed":"error"}' \
223
+ npx prettier-wolfram lint "src/**/*.wl"
224
+ ```
225
+
226
+ Rule levels are `off`, `warn`, and `error`.
227
+
228
+ | Rule | Default | Formatter-fixable | Description |
229
+ | ------------------------------ | ------- | ----------------- | ----------- |
230
+ | `line-width` | `warn` | yes | Reports lines exceeding `printWidth`, ignoring comment-only overflow. |
231
+ | `newlines-between-definitions` | `warn` | yes | Reports top-level blank-line spacing that differs from the configured policy. |
232
+ | `spacing-operators` | `warn` | yes | Reports operator spacing inconsistent with `wolfram.spaceAroundOperators`. |
233
+ | `spacing-commas` | `warn` | yes | Reports comma spacing inconsistent with `wolfram.spaceAfterComma`. |
234
+ | `no-general-infix-function` | `warn` | yes | Reports general infix `x ~ f ~ y` forms unless `f` is preserved. |
235
+ | `prefer-rule-delayed` | `warn` | no | Reports definitions where `SetDelayed` is safer because the right-hand side references pattern variables. |
236
+ | `no-bare-symbol-set` | `warn` | no | Reports top-level global symbol assignments such as `x = value`. |
237
+ | `no-dynamic-module-leak` | `warn` | no | Reports assignments inside `Module`, `Block`, or `DynamicModule` to symbols missing from the variable list. |
238
+ | `no-shadowed-pattern` | `error` | no | Reports pattern variables that shadow local variables from `Module`, `With`, or `Block`. |
239
+ | `no-unused-module-var` | `warn` | no | Reports unused variables declared in `Module`, `With`, `Block`, or `DynamicModule`. |
240
+
241
+ ## Parse Runtime
242
+
243
+ The plugin uses a bundled tree-sitter WebAssembly grammar
244
+ (`src/parser/tree-sitter-wolfram.wasm`) to parse Wolfram Language. No Wolfram
245
+ Engine, Mathematica installation, or kernel process is required at runtime.
246
+
247
+ ## VS Code Extension
248
+
249
+ Build the standalone `.vsix` that bundles Prettier and this plugin:
250
+
251
+ ```bash
252
+ npm run package:vscode:standalone
253
+ ```
254
+
255
+ This writes `vscode-extension/wolfram-prettier-vscode-<version>.vsix`.
256
+
257
+ For Marketplace pre-release publishing, use the workspace-safe publish wrapper:
258
+
259
+ ```bash
260
+ npm run publish:vscode:pre-release
261
+ ```
262
+
263
+ The extension README with editor setup, settings, diagnostics, and file
264
+ association behavior lives at `vscode-extension/README.md`.
265
+
266
+ ## Publishing To Verdaccio
267
+
268
+ Log in:
269
+
270
+ ```bash
271
+ npm login --registry http://localhost:4873
272
+ ```
273
+
274
+ Preview package contents:
275
+
276
+ ```bash
277
+ npm pack --dry-run
278
+ ```
279
+
280
+ Publish:
281
+
282
+ ```bash
283
+ npm publish --registry http://localhost:4873
284
+ ```
285
+
286
+ Verify:
287
+
288
+ ```bash
289
+ npm view @wrel/prettier-plugin-wolfram --registry http://localhost:4873
290
+ ```
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ // bin/prettier-wolfram.js
3
+ // Usage: prettier-wolfram lint [options] <glob...>
4
+
5
+ import { readFileSync } from "fs";
6
+ import { globSync } from "fs";
7
+ import { WolframParser } from "../src/parser/index.js";
8
+ import { runRules } from "../src/rules/index.js";
9
+ import { buildOffsetTable, addOffsets } from "../src/utils/offsets.js";
10
+
11
+ const [, , command, ...args] = process.argv;
12
+
13
+ if (command !== "lint") {
14
+ console.error("Usage: prettier-wolfram lint <glob...>");
15
+ process.exit(1);
16
+ }
17
+
18
+ if (args.length === 0) {
19
+ console.error("Error: provide at least one glob pattern");
20
+ process.exit(1);
21
+ }
22
+
23
+ let lintRules = {};
24
+ try {
25
+ lintRules = JSON.parse(process.env.WOLFRAM_LINT_RULES ?? "{}");
26
+ } catch {}
27
+
28
+ const parser = new WolframParser();
29
+ let totalDiagnostics = 0;
30
+
31
+ for (const pattern of args) {
32
+ const files = globSync(pattern, { absolute: true });
33
+ for (const file of files) {
34
+ const source = readFileSync(file, "utf8");
35
+ try {
36
+ const cst = await parser.getCST(source);
37
+ const table = buildOffsetTable(source);
38
+ addOffsets(cst, table);
39
+ const diagnostics = await runRules(cst, lintRules);
40
+
41
+ for (const d of diagnostics) {
42
+ const line = d.node?.source?.[0]?.[0] ?? "?";
43
+ const col = d.node?.source?.[0]?.[1] ?? "?";
44
+ console.log(
45
+ `${file}:${line}:${col}: ${d.level.toUpperCase()} [${d.rule}] ${d.message}`,
46
+ );
47
+ totalDiagnostics++;
48
+ }
49
+ } catch (err) {
50
+ console.error(`${file}: ERROR — ${err.message}`);
51
+ }
52
+ }
53
+ }
54
+
55
+ process.exit(totalDiagnostics > 0 ? 1 : 0);
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "prettier-plugin-wolfram",
3
+ "version": "0.7.0",
4
+ "description": "Prettier plugin for Wolfram Language using tree-sitter",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git://github.com/ToneAr/prettier-plugin-wolfram.git"
9
+ },
10
+ "keywords": [
11
+ "prettier",
12
+ "prettier-plugin",
13
+ "wolfram",
14
+ "wolfram-language",
15
+ "mathematica",
16
+ "formatter"
17
+ ],
18
+ "type": "module",
19
+ "main": "src/index.js",
20
+ "bin": {
21
+ "prettier-wolfram": "bin/prettier-wolfram.js"
22
+ },
23
+ "files": [
24
+ "bin/",
25
+ "src/",
26
+ "src/parser/tree-sitter-wolfram.wasm",
27
+ "README.md"
28
+ ],
29
+ "peerDependencies": {
30
+ "prettier": "^3.0.0"
31
+ },
32
+ "dependencies": {
33
+ "web-tree-sitter": "^0.25.0"
34
+ },
35
+ "devDependencies": {
36
+ "prettier": "^3.4.0",
37
+ "vitest": "^2.0.0",
38
+ "node-gyp": "^10.0.0",
39
+ "tree-sitter-cli": "^0.25.0"
40
+ },
41
+ "scripts": {
42
+ "build:grammar": "node scripts/build-grammar.mjs",
43
+ "bump:version": "node scripts/bump-version.mjs",
44
+ "package:vscode": "node scripts/package-vscode-extension.mjs",
45
+ "package:vscode:standalone": "node scripts/package-vscode-extension.mjs",
46
+ "publish:vscode:standalone": "node scripts/package-vscode-extension.mjs --publish",
47
+ "package:vscode:pre-release": "node scripts/package-vscode-extension.mjs --pre-release",
48
+ "publish:vscode:pre-release": "node scripts/package-vscode-extension.mjs --pre-release --publish",
49
+ "test": "vitest run",
50
+ "test:watch": "vitest"
51
+ },
52
+ "workspaces": [
53
+ "vscode-extension"
54
+ ],
55
+ "engines": {
56
+ "vscode": "^1.105.0"
57
+ }
58
+ }
package/src/index.js ADDED
@@ -0,0 +1,80 @@
1
+ // src/index.js
2
+ import { normalizeWolframOptions, options } from "./options.js";
3
+ import { WolframParser } from "./parser/index.js";
4
+ import { printNode } from "./translator/index.js";
5
+ import { buildOffsetTable, addOffsets } from "./utils/offsets.js";
6
+ import {
7
+ containsCstErrors,
8
+ createUnformattableNode,
9
+ } from "./utils/cstErrors.js";
10
+ import { preprocessRange } from "./range.js";
11
+
12
+ const parser = new WolframParser();
13
+
14
+ function extractLeadingShebang(text) {
15
+ if (!text.startsWith("#!")) {
16
+ return null;
17
+ }
18
+
19
+ const lineBreakMatch = /\r?\n/.exec(text);
20
+ const lineEnd = lineBreakMatch?.index ?? text.length;
21
+ const lineBreak = lineBreakMatch?.[0] ?? "";
22
+ const bodyStart = lineEnd + lineBreak.length;
23
+
24
+ return {
25
+ line: text.slice(0, lineEnd),
26
+ maskedText: " ".repeat(lineEnd) + lineBreak + text.slice(bodyStart),
27
+ };
28
+ }
29
+
30
+ export const languages = [
31
+ {
32
+ name: "Wolfram Language",
33
+ parsers: ["wolfram"],
34
+ extensions: [".wl", ".wls", ".wlt", ".mt", ".m", ".vsnb", ".nb"],
35
+ vscodeLanguageIds: ["wolfram", "wolframscript", "wolfram-notebook"],
36
+ },
37
+ ];
38
+
39
+ export const parsers = {
40
+ wolfram: {
41
+ parse: async (text, parsedOptions) => {
42
+ const normalizedOptions = normalizeWolframOptions(parsedOptions);
43
+ const shebang = extractLeadingShebang(text);
44
+ const cstText = shebang?.maskedText ?? text;
45
+ const cst = await parser.getCST(cstText, normalizedOptions);
46
+ if (!cst || containsCstErrors(cst)) {
47
+ return createUnformattableNode(text);
48
+ }
49
+ const table = buildOffsetTable(
50
+ text,
51
+ normalizedOptions.tabWidth ?? 2,
52
+ );
53
+ const ast = addOffsets(cst, table);
54
+ if (shebang) ast.wlsShebang = shebang.line;
55
+ return ast;
56
+ },
57
+ preprocess: preprocessRange,
58
+ astFormat: "wolfram-cst",
59
+ locStart: (node) => node.locStart,
60
+ locEnd: (node) => node.locEnd,
61
+ },
62
+ };
63
+
64
+ export const printers = {
65
+ "wolfram-cst": {
66
+ print: (path, printOptions, print) =>
67
+ printNode(path, normalizeWolframOptions(printOptions), print),
68
+ /** Let Prettier traverse all non-whitespace nodes when walking the AST
69
+ * to find nodes within the range. */
70
+ canAttachComment: (node) =>
71
+ node.type !== undefined &&
72
+ node.type !== "UnformattableNode" &&
73
+ !(
74
+ node.type === "LeafNode" &&
75
+ ["Token`Whitespace", "Token`Newline"].includes(node.kind)
76
+ ),
77
+ },
78
+ };
79
+
80
+ export { options };