prettier-plugin-multiline-arrays-2 1.0.0 → 5.0.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 (62) hide show
  1. package/README.md +5 -19
  2. package/dist/augments/array.d.ts +8 -2
  3. package/dist/augments/array.js +11 -5
  4. package/dist/augments/doc.d.ts +2 -2
  5. package/dist/augments/doc.js +12 -9
  6. package/dist/augments/string.js +1 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.js +42 -20
  9. package/dist/options.d.ts +6 -9
  10. package/dist/options.js +20 -25
  11. package/dist/plugin-marker.js +1 -1
  12. package/dist/preprocessing.d.ts +1 -1
  13. package/dist/preprocessing.js +60 -30
  14. package/dist/printer/child-docs.d.ts +9 -7
  15. package/dist/printer/child-docs.js +89 -63
  16. package/dist/printer/comment-triggers.d.ts +5 -7
  17. package/dist/printer/comment-triggers.js +104 -134
  18. package/dist/printer/comments.d.ts +1 -1
  19. package/dist/printer/comments.js +15 -16
  20. package/dist/printer/insert-new-lines.d.ts +10 -6
  21. package/dist/printer/insert-new-lines.js +260 -277
  22. package/dist/printer/leading-new-line.d.ts +2 -2
  23. package/dist/printer/leading-new-line.js +2 -1
  24. package/dist/printer/multiline-array-printer.js +4 -2
  25. package/dist/printer/original-printer.js +6 -4
  26. package/dist/printer/supported-node-types.d.ts +1 -1
  27. package/dist/printer/supported-node-types.js +6 -5
  28. package/dist/printer/trailing-comma.d.ts +1 -1
  29. package/dist/printer/trailing-comma.js +1 -1
  30. package/package.json +56 -29
  31. package/dist/augments/array.test.d.ts +0 -1
  32. package/dist/augments/array.test.js +0 -34
  33. package/dist/options.test.d.ts +0 -1
  34. package/dist/options.test.js +0 -48
  35. package/dist/printer/insert-new-lines.test.d.ts +0 -1
  36. package/dist/printer/insert-new-lines.test.js +0 -36
  37. package/dist/readme-examples/formatted-with-comments.example.d.ts +0 -3
  38. package/dist/readme-examples/formatted-with-comments.example.js +0 -16
  39. package/dist/readme-examples/formatted.example.d.ts +0 -2
  40. package/dist/readme-examples/formatted.example.js +0 -12
  41. package/dist/readme-examples/not-formatted.example.d.ts +0 -2
  42. package/dist/readme-examples/not-formatted.example.js +0 -6
  43. package/dist/readme-examples/prettier-options.example.d.ts +0 -4
  44. package/dist/readme-examples/prettier-options.example.js +0 -5
  45. package/dist/test/babel-ts.test.d.ts +0 -1
  46. package/dist/test/babel-ts.test.js +0 -10
  47. package/dist/test/javascript.test.d.ts +0 -1
  48. package/dist/test/javascript.test.js +0 -702
  49. package/dist/test/json.test.d.ts +0 -1
  50. package/dist/test/json.test.js +0 -403
  51. package/dist/test/json5.test.d.ts +0 -1
  52. package/dist/test/json5.test.js +0 -210
  53. package/dist/test/prettier-config.d.ts +0 -2
  54. package/dist/test/prettier-config.js +0 -12
  55. package/dist/test/prettier-versions.mock.script.d.ts +0 -1
  56. package/dist/test/prettier-versions.mock.script.js +0 -123
  57. package/dist/test/run-tests.mock.d.ts +0 -17
  58. package/dist/test/run-tests.mock.js +0 -95
  59. package/dist/test/typescript-tests.mock.d.ts +0 -2
  60. package/dist/test/typescript-tests.mock.js +0 -1575
  61. package/dist/test/typescript.test.d.ts +0 -1
  62. package/dist/test/typescript.test.js +0 -10
package/README.md CHANGED
@@ -1,12 +1,11 @@
1
1
  # prettier-plugin-multiline-arrays-2
2
2
 
3
- [![npm](https://img.shields.io/npm/v/prettier-plugin-multiline-arrays-2.svg)](https://www.npmjs.com/package/prettier-plugin-multiline-arrays-2)
4
- [![CI](https://github.com/Nick2bad4u/prettier-plugin-multiline-arrays-2/actions/workflows/ci.yml/badge.svg)](https://github.com/Nick2bad4u/prettier-plugin-multiline-arrays-2/actions/workflows/ci.yml)
5
- [![License: MIT OR CC0-1.0](https://img.shields.io/badge/license-MIT%20OR%20CC0--1.0-blue.svg)](LICENSE-MIT)
3
+ [![NPM license.](https://flat.badgen.net/npm/license/prettier-plugin-multiline-arrays-2?color=purple)](https://github.com/Nick2bad4u/prettier-plugin-multiline-arrays-2/blob/main/LICENSE) [![NPM total downloads.](https://flat.badgen.net/npm/dt/prettier-plugin-multiline-arrays-2?color=pink)](https://www.npmjs.com/package/prettier-plugin-multiline-arrays-2) [![Latest GitHub release.](https://flat.badgen.net/github/release/Nick2bad4u/prettier-plugin-multiline-arrays-2?color=cyan)](https://github.com/Nick2bad4u/prettier-plugin-multiline-arrays-2/releases) [![GitHub stars.](https://flat.badgen.net/github/stars/Nick2bad4u/prettier-plugin-multiline-arrays-2?color=yellow)](https://github.com/Nick2bad4u/prettier-plugin-multiline-arrays-2/stargazers) [![GitHub forks.](https://flat.badgen.net/github/forks/Nick2bad4u/prettier-plugin-multiline-arrays-2?color=orange)](https://github.com/Nick2bad4u/prettier-plugin-multiline-arrays-2/forks) [![GitHub open issues.](https://flat.badgen.net/github/open-issues/Nick2bad4u/prettier-plugin-multiline-arrays-2?color=red)](https://github.com/Nick2bad4u/prettier-plugin-multiline-arrays-2/issues) [![Codecov.](https://flat.badgen.net/codecov/github/Nick2bad4u/prettier-plugin-multiline-arrays-2?color=blue)](https://codecov.io/gh/Nick2bad4u/prettier-plugin-multiline-arrays-2) [![Repo Checks.](https://flat.badgen.net/github/checks/Nick2bad4u/prettier-plugin-multiline-arrays-2?color=green)](https://github.com/Nick2bad4u/prettier-plugin-multiline-arrays-2/actions)
6
4
 
7
5
  Prettier plugin to force array elements to wrap onto new lines, even when there is only one element. It supports TypeScript, JavaScript, JSON, and JSON5, with options for wrap thresholds and per-line element patterns.
8
6
 
9
- This is a maintained fork of [electrovir/prettier-plugin-multiline-arrays](https://github.com/electrovir/prettier-plugin-multiline-arrays). Credit to the original plugin for the core idea and implementation.
7
+ > [!NOTE]
8
+ > This is a maintained fork of [electrovir/prettier-plugin-multiline-arrays](https://github.com/electrovir/prettier-plugin-multiline-arrays). Credit to the original plugin for the core idea and implementation.
10
9
 
11
10
  ## Install
12
11
 
@@ -27,7 +26,7 @@ When combining this plugin with parser/preprocessor plugins such as `prettier-pl
27
26
  ## Options
28
27
 
29
28
  - `multilineArraysWrapThreshold`: number. Arrays with more elements than this value are forced to wrap. The default is `-1`, which disables automatic threshold wrapping.
30
- - `multilineArraysLinePattern`: string. Space- or comma-separated list of numbers controlling how many elements appear on each line. The pattern repeats for longer arrays. The default is `"1"`.
29
+ - `multilineArraysLinePattern`: string. Space- or comma-separated list of numbers controlling the element count per line. The pattern repeats for longer arrays. The default is `"1"`.
31
30
 
32
31
  Example:
33
32
 
@@ -75,17 +74,4 @@ npm test
75
74
  npm run release:check
76
75
  ```
77
76
 
78
- The test suite runs against Node's built-in test runner through `tsx` and includes a `test:prettier-latest` check to verify compatibility with the current npm `latest` Prettier release.
79
-
80
- ## Publishing
81
-
82
- This package is prepared for npm trusted publishing from GitHub Actions. Before the first release, create the package on npm and add a trusted publisher with these values:
83
-
84
- - Package: `prettier-plugin-multiline-arrays-2`
85
- - Provider: GitHub Actions
86
- - Repository owner: `Nick2bad4u`
87
- - Repository name: `prettier-plugin-multiline-arrays-2`
88
- - Workflow filename: `npm-release.yml`
89
- - Environment: leave unset unless you add a matching GitHub environment to the workflow
90
-
91
- The release workflow uses GitHub OIDC through `id-token: write` and publishes with provenance. It intentionally does not require an npm automation token.
77
+ The test suite runs with Vitest coverage and includes a `test:prettier-latest` check to verify compatibility with the current npm `latest` Prettier release.
@@ -1,3 +1,9 @@
1
1
  import type { SourceLocation } from "estree";
2
- /** Both line and column in "range" are 0 indexed. */
3
- export declare function extractTextBetweenRanges(input: string[], range: Omit<SourceLocation, "source">): string;
2
+ type SourceRange = Pick<SourceLocation, "end" | "start">;
3
+ /**
4
+ * Both line and column in "range" are 0 indexed.
5
+ *
6
+ * @throws If the range starts after it ends.
7
+ */
8
+ export declare function extractTextBetweenRanges(input: string[], range: SourceRange): string;
9
+ export {};
@@ -1,9 +1,14 @@
1
- /** Both line and column in "range" are 0 indexed. */
1
+ import { assertDefined } from "ts-extras";
2
+ /**
3
+ * Both line and column in "range" are 0 indexed.
4
+ *
5
+ * @throws If the range starts after it ends.
6
+ */
2
7
  export function extractTextBetweenRanges(input, range) {
3
8
  if (range.start.line > range.end.line) {
4
9
  throw new Error(`Start line "${range.start.line}" cannot be greater than end line "${range.end.line}"`);
5
10
  }
6
- else if (range.start.line === range.end.line) {
11
+ if (range.start.line === range.end.line) {
7
12
  if (range.start.column >= range.end.column) {
8
13
  throw new Error(`When start and end are on the same line, the start column "${range.start.column}" must be less than the end column "${range.end.column}".`);
9
14
  }
@@ -11,9 +16,10 @@ export function extractTextBetweenRanges(input, range) {
11
16
  }
12
17
  let extractedText = input[range.start.line]?.slice(range.start.column + 1) ?? "";
13
18
  extractedText += "\n";
14
- for (let lineIndex = range.start.line + 1; lineIndex < range.end.line; lineIndex++) {
15
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
16
- extractedText += input[lineIndex];
19
+ for (let lineIndex = range.start.line + 1; lineIndex < range.end.line; lineIndex += 1) {
20
+ const inputLine = input[lineIndex];
21
+ assertDefined(inputLine);
22
+ extractedText += inputLine;
17
23
  extractedText += "\n";
18
24
  }
19
25
  extractedText += input[range.end.line]?.slice(0, range.end.column) ?? "";
@@ -1,5 +1,5 @@
1
1
  import type { Doc, doc } from "prettier";
2
- type NestedStringArray = (string | NestedStringArray)[];
2
+ type NestedStringArray = (NestedStringArray | string)[];
3
3
  export declare function stringifyDoc(input: Doc | null | undefined, recursive?: boolean): NestedStringArray;
4
- export declare function isDocCommand(inputDoc: Doc | undefined | null): inputDoc is doc.builders.DocCommand;
4
+ export declare function isDocCommand(inputDoc: Doc | null | undefined): inputDoc is doc.builders.DocCommand;
5
5
  export {};
@@ -1,4 +1,5 @@
1
1
  import { stringify } from "@augment-vir/common";
2
+ import { objectHasIn } from "ts-extras";
2
3
  const childProperties = [
3
4
  "breakContents",
4
5
  "contents",
@@ -9,22 +10,24 @@ export function stringifyDoc(input, recursive = false) {
9
10
  if (typeof input === "string" || !input) {
10
11
  return [stringify(input)];
11
12
  }
12
- else if (Array.isArray(input)) {
13
+ if (Array.isArray(input)) {
13
14
  return input.map((entry) => stringifyDoc(entry, recursive));
14
15
  }
15
- else if (recursive) {
16
- const children = childProperties.reduce((accum, currentProperty) => {
17
- if (currentProperty in input) {
18
- accum.push(`${currentProperty}:`, stringifyDoc(input[currentProperty], recursive));
16
+ if (recursive) {
17
+ const children = [];
18
+ for (const currentProperty of childProperties) {
19
+ if (objectHasIn(input, currentProperty)) {
20
+ children.push(`${currentProperty}:`, stringifyDoc(input[currentProperty], recursive));
19
21
  }
20
- return accum;
21
- }, []);
22
- if (children.length) {
22
+ }
23
+ if (children.length > 0) {
23
24
  return [`${input.type}:`, stringifyDoc(children, recursive)];
24
25
  }
25
26
  }
26
27
  return [input.type];
27
28
  }
28
29
  export function isDocCommand(inputDoc) {
29
- return (!!inputDoc && typeof inputDoc !== "string" && !Array.isArray(inputDoc));
30
+ return (Boolean(inputDoc) &&
31
+ typeof inputDoc !== "string" &&
32
+ !Array.isArray(inputDoc));
30
33
  }
@@ -2,5 +2,5 @@ export function capitalizeFirst(input) {
2
2
  if (!input) {
3
3
  return input;
4
4
  }
5
- return (input[0] || "").toUpperCase() + input.slice(1);
5
+ return (input[0] ?? "").toUpperCase() + input.slice(1);
6
6
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type Parser, type RequiredOptions, type SupportOption } from "prettier";
1
+ import type { Parser, RequiredOptions, SupportOption } from "prettier";
2
2
  import { type MultilineArrayOptions } from "./options.js";
3
3
  export * from "./options.js";
4
4
  export { pluginMarker } from "./plugin-marker.js";
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { getObjectTypedKeys, mapObjectValues } from "@augment-vir/common";
2
- import {} from "prettier";
3
2
  import { parsers as babelParsers } from "prettier/plugins/babel";
4
3
  import { parsers as tsParsers } from "prettier/plugins/typescript";
5
4
  import { defaultMultilineArrayOptions, optionHelp, } from "./options.js";
@@ -14,30 +13,53 @@ export const parsers = mapObjectValues({
14
13
  "babel-ts": babelParsers["babel-ts"],
15
14
  json: babelParsers.json,
16
15
  json5: babelParsers.json5,
17
- }, (languageName, parserEntry) => {
18
- return wrapParser(parserEntry, languageName);
19
- });
16
+ }, (languageName, parserEntry) => wrapParser(parserEntry, languageName));
20
17
  const printers = {
21
18
  estree: multilineArrayPrinter,
22
19
  "estree-json": multilineArrayPrinter,
23
20
  };
24
- export const options = getObjectTypedKeys(defaultMultilineArrayOptions).reduce((accum, key) => {
25
- const defaultValue = defaultMultilineArrayOptions[key];
26
- const supportOption = {
27
- name: key,
28
- type: (typeof defaultValue === "number"
29
- ? "int"
30
- : typeof defaultValue),
31
- category: "multilineArray",
32
- default: defaultValue,
33
- description: optionHelp[key],
34
- };
35
- accum[key] = supportOption;
36
- return accum;
37
- }, {});
38
- export const defaultOptions = defaultMultilineArrayOptions;
21
+ function createOptions() {
22
+ const output = {};
23
+ for (const key of getObjectTypedKeys(defaultMultilineArrayOptions)) {
24
+ const defaultValue = defaultMultilineArrayOptions[key];
25
+ let supportOption;
26
+ if (typeof defaultValue === "number") {
27
+ supportOption = {
28
+ name: key,
29
+ type: "int",
30
+ category: "multilineArray",
31
+ default: defaultValue,
32
+ description: optionHelp[key],
33
+ };
34
+ }
35
+ else if (typeof defaultValue === "boolean") {
36
+ supportOption = {
37
+ name: key,
38
+ type: "boolean",
39
+ category: "multilineArray",
40
+ default: defaultValue,
41
+ description: optionHelp[key],
42
+ };
43
+ }
44
+ else {
45
+ supportOption = {
46
+ name: key,
47
+ type: "string",
48
+ category: "multilineArray",
49
+ default: defaultValue,
50
+ description: optionHelp[key],
51
+ };
52
+ }
53
+ output[key] = supportOption;
54
+ }
55
+ return output;
56
+ }
57
+ export const options = createOptions();
58
+ export const defaultOptions = {
59
+ ...defaultMultilineArrayOptions,
60
+ };
39
61
  /** Not actually exported: this is just for type checking purposes. */
40
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
62
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- The sentinel validates named exports against Prettier's Plugin shape.
41
63
  const plugin = {
42
64
  options,
43
65
  printers,
package/dist/options.d.ts CHANGED
@@ -1,16 +1,13 @@
1
1
  import { type Values } from "@augment-vir/common";
2
- import type { SupportOptionType as PrettierOptionType } from "prettier";
3
2
  export declare const envDebugKey = "MULTILINE_DEBUG";
4
3
  export declare const nextLinePatternComment = "prettier-multiline-arrays-next-line-pattern:";
5
- export declare const untilNextLinePatternCommentRegExp: RegExp;
6
4
  export declare const setLinePatternComment = "prettier-multiline-arrays-set-line-pattern:";
7
- export declare const untilSetLinePatternCommentRegExp: RegExp;
8
5
  export declare const nextWrapThresholdComment = "prettier-multiline-arrays-next-threshold:";
9
- export declare const untilNextWrapThresholdCommentRegExp: RegExp;
10
6
  export declare const setWrapThresholdComment = "prettier-multiline-arrays-set-threshold:";
11
- export declare const untilSetWrapThresholdCommentRegExp: RegExp;
12
7
  export declare const resetComment = "prettier-multiline-arrays-reset";
13
- export type MultilineArrayOptions = {
8
+ export declare function stripTextUntilCommentTrigger(input: string, commentTrigger: string): string;
9
+ export interface MultilineArrayOptions {
10
+ multilineArraysLinePattern: string;
14
11
  /**
15
12
  * If there are MORE elements in the array than this, the array will be
16
13
  * forced to wrap.
@@ -21,12 +18,12 @@ export type MultilineArrayOptions = {
21
18
  * Set to 2 to only wrap if there are more than 2 element. Etc.
22
19
  */
23
20
  multilineArraysWrapThreshold: number;
24
- multilineArraysLinePattern: string;
25
- };
21
+ }
26
22
  export declare const optionHelp: Record<keyof MultilineArrayOptions, string>;
27
23
  export declare const optionPropertyValidators: {
28
24
  [Property in keyof MultilineArrayOptions]: (input: unknown) => input is MultilineArrayOptions[Property];
29
25
  };
30
26
  export declare const defaultMultilineArrayOptions: MultilineArrayOptions;
31
- export declare function getPrettierOptionType(input: Values<MultilineArrayOptions>): PrettierOptionType;
27
+ export type MultilinePrettierOptionType = "boolean" | "int" | "string";
28
+ export declare function getPrettierOptionType(input: Values<MultilineArrayOptions>): MultilinePrettierOptionType;
32
29
  export declare function fillInOptions<T extends object>(input: T | undefined): MultilineArrayOptions & T;
package/dist/options.js CHANGED
@@ -1,34 +1,32 @@
1
1
  import { getObjectTypedKeys } from "@augment-vir/common";
2
+ import { objectHasIn, safeCastTo, stringSplit } from "ts-extras";
2
3
  export const envDebugKey = "MULTILINE_DEBUG";
3
4
  export const nextLinePatternComment = "prettier-multiline-arrays-next-line-pattern:";
4
- // all the text up until the comment trigger
5
- export const untilNextLinePatternCommentRegExp = new RegExp(`.*${nextLinePatternComment}`);
6
5
  export const setLinePatternComment = "prettier-multiline-arrays-set-line-pattern:";
7
- // all the text up until the comment trigger
8
- export const untilSetLinePatternCommentRegExp = new RegExp(`.*${setLinePatternComment}`);
9
6
  export const nextWrapThresholdComment = "prettier-multiline-arrays-next-threshold:";
10
- // all the text up until the comment trigger
11
- export const untilNextWrapThresholdCommentRegExp = new RegExp(`.*${nextWrapThresholdComment}`);
12
7
  export const setWrapThresholdComment = "prettier-multiline-arrays-set-threshold:";
13
- // all the text up until the comment trigger
14
- export const untilSetWrapThresholdCommentRegExp = new RegExp(`.*${setWrapThresholdComment}`);
15
8
  export const resetComment = "prettier-multiline-arrays-reset";
9
+ export function stripTextUntilCommentTrigger(input, commentTrigger) {
10
+ const triggerIndex = input.indexOf(commentTrigger);
11
+ if (triggerIndex === -1) {
12
+ return input;
13
+ }
14
+ return input.slice(triggerIndex + commentTrigger.length);
15
+ }
16
16
  export const optionHelp = {
17
17
  multilineArraysWrapThreshold: `A number indicating that all arrays should wrap when they have MORE than the specified number. Defaults to -1, indicating that no special wrapping enforcement will take place.\nExample: multilineArraysWrapThreshold: 3\nCan be overridden with a comment starting with ${nextWrapThresholdComment}.\nComment example: // ${nextWrapThresholdComment} 5`,
18
18
  multilineArraysLinePattern: `A string with a space separated list of numbers indicating how many elements should be on each line. The pattern repeats if an array is longer than the pattern. Defaults to an empty string. Any invalid numbers causes the whole pattern to revert to the default. This overrides the wrap threshold option.\nExample: elementsPerLinePattern: "3 2 1"\nCan be overridden with a comment starting with ${nextLinePatternComment}.\nComment example: // ${nextLinePatternComment} 3 2 1\nThis option overrides Prettier's default wrapping; multiple elements on one line will not be wrapped even if they don't fit within the column count.`,
19
19
  };
20
20
  export const optionPropertyValidators = {
21
- multilineArraysWrapThreshold(input) {
22
- return typeof input === "number" && !isNaN(input);
23
- },
21
+ multilineArraysWrapThreshold: (input) => typeof input === "number" && !Number.isNaN(input),
24
22
  multilineArraysLinePattern(input) {
25
23
  if (typeof input !== "string") {
26
24
  return false;
27
25
  }
28
- const splitNumbers = input.split(" ");
26
+ const splitNumbers = stringSplit(input, " ");
29
27
  return splitNumbers.every((splitNumber) => {
30
28
  const numericSplit = Number(splitNumber);
31
- return !isNaN(numericSplit);
29
+ return !Number.isNaN(numericSplit);
32
30
  });
33
31
  },
34
32
  };
@@ -46,9 +44,7 @@ export function getPrettierOptionType(input) {
46
44
  if (mappedType) {
47
45
  return mappedType;
48
46
  }
49
- else {
50
- throw new Error(`Unmapped option type: '${typeof input}'`);
51
- }
47
+ throw new Error(`Unmapped option type: '${typeof input}'`);
52
48
  }
53
49
  export function fillInOptions(input) {
54
50
  if (!input || typeof input !== "object") {
@@ -57,15 +53,14 @@ export function fillInOptions(input) {
57
53
  const newOptions = {
58
54
  ...input,
59
55
  };
60
- getObjectTypedKeys(defaultMultilineArrayOptions).forEach((optionsKey) => {
61
- const inputValue = input[optionsKey];
56
+ for (const optionsKey of getObjectTypedKeys(defaultMultilineArrayOptions)) {
57
+ const inputValue = objectHasIn(input, optionsKey)
58
+ ? input[optionsKey]
59
+ : undefined;
62
60
  const defaultValue = defaultMultilineArrayOptions[optionsKey];
63
- if (optionPropertyValidators[optionsKey](inputValue)) {
64
- newOptions[optionsKey] = inputValue;
65
- }
66
- else {
67
- newOptions[optionsKey] = defaultValue;
68
- }
69
- });
61
+ safeCastTo(newOptions)[optionsKey] = optionPropertyValidators[optionsKey](inputValue)
62
+ ? inputValue
63
+ : defaultValue;
64
+ }
70
65
  return newOptions;
71
66
  }
@@ -1,2 +1,2 @@
1
- // used to find our own plugin
1
+ // Used to find our own plugin
2
2
  export const pluginMarker = {};
@@ -1,2 +1,2 @@
1
1
  import type { Parser } from "prettier";
2
- export declare function wrapParser(originalParser: Parser, parserName: string): Parser<any>;
2
+ export declare function wrapParser(originalParser: Parser, parserName: string): Parser;
@@ -1,13 +1,32 @@
1
1
  import { stringify } from "@augment-vir/common";
2
2
  import { createWrappedMultiTargetProxy } from "proxy-vir";
3
+ import { not, objectHasIn } from "ts-extras";
3
4
  import { pluginMarker } from "./plugin-marker.js";
4
5
  import { createMultilineArrayPrinter } from "./printer/multiline-array-printer.js";
5
6
  import { setOriginalPrinter } from "./printer/original-printer.js";
7
+ function hasThisPluginMarker(plugin) {
8
+ return (typeof plugin === "object" &&
9
+ plugin != undefined &&
10
+ !(plugin instanceof URL) &&
11
+ objectHasIn(plugin, "pluginMarker") &&
12
+ plugin.pluginMarker === pluginMarker);
13
+ }
14
+ async function runPreprocessSteps(preprocessSteps, text, index = 0) {
15
+ const preprocessStep = preprocessSteps[index];
16
+ if (!preprocessStep) {
17
+ return text;
18
+ }
19
+ return runPreprocessSteps(preprocessSteps, await preprocessStep(text), index + 1);
20
+ }
6
21
  function addMultilinePrinter(options) {
7
- if ("printer" in options) {
8
- setOriginalPrinter(options.printer);
22
+ if (objectHasIn(options, "printer")) {
23
+ const originalPrinter = options.printer;
24
+ if (!originalPrinter) {
25
+ throw new Error("Could not find printer while adding printer.");
26
+ }
27
+ setOriginalPrinter(originalPrinter);
9
28
  /** Overwrite the printer with ours. */
10
- options.printer = createMultilineArrayPrinter(options.printer);
29
+ options.printer = createMultilineArrayPrinter(originalPrinter);
11
30
  }
12
31
  else {
13
32
  const astFormat = options.astFormat;
@@ -19,21 +38,26 @@ function addMultilinePrinter(options) {
19
38
  * plugins so that ours gets chosen.
20
39
  */
21
40
  const plugins = options.plugins ?? [];
22
- const firstMatchedPlugin = plugins.find((plugin) => typeof plugin !== "string" &&
23
- !(plugin instanceof URL) &&
24
- !!plugin.printers &&
25
- !!plugin.printers[astFormat]);
41
+ const firstMatchedPlugin = plugins.find((plugin) => {
42
+ if (typeof plugin === "string" || plugin instanceof URL) {
43
+ return false;
44
+ }
45
+ const printers = plugin.printers;
46
+ if (!printers) {
47
+ return false;
48
+ }
49
+ const matchedPrinter = printers[astFormat];
50
+ return Boolean(matchedPrinter);
51
+ });
26
52
  if (!firstMatchedPlugin || typeof firstMatchedPlugin === "string") {
27
- throw new Error(`Matched invalid first plugin: ${firstMatchedPlugin}`);
53
+ throw new Error(`Matched invalid first plugin: ${String(firstMatchedPlugin)}`);
28
54
  }
29
- const matchedPrinter = firstMatchedPlugin.printers?.[astFormat];
55
+ const matchedPrinter = firstMatchedPlugin.printers[astFormat];
30
56
  if (!matchedPrinter) {
31
57
  throw new Error(`Printer not found on matched plugin: ${stringify(firstMatchedPlugin)}`);
32
58
  }
33
59
  setOriginalPrinter(matchedPrinter);
34
- const thisPluginIndex = plugins.findIndex((plugin) => {
35
- return (plugin.pluginMarker === pluginMarker);
36
- });
60
+ const thisPluginIndex = plugins.findIndex((plugin) => hasThisPluginMarker(plugin));
37
61
  const thisPlugin = plugins[thisPluginIndex];
38
62
  if (!thisPlugin) {
39
63
  throw new Error("This plugin was not found.");
@@ -42,16 +66,25 @@ function addMultilinePrinter(options) {
42
66
  * Add this plugin to the beginning of the array so its printer is found
43
67
  * first.
44
68
  */
45
- plugins.splice(thisPluginIndex, 1);
46
- plugins.splice(0, 0, thisPlugin);
69
+ options.plugins = [
70
+ thisPlugin,
71
+ ...plugins.toSpliced(thisPluginIndex, 1),
72
+ ];
47
73
  }
48
74
  }
49
75
  function findPluginsByParserName(parserName, plugins) {
50
76
  return plugins.filter((plugin) => {
51
- return (typeof plugin === "object" &&
52
- !(plugin instanceof URL) &&
53
- plugin.pluginMarker !== pluginMarker &&
54
- !!plugin.parsers?.[parserName]);
77
+ if (typeof plugin !== "object" ||
78
+ plugin instanceof URL ||
79
+ hasThisPluginMarker(plugin)) {
80
+ return false;
81
+ }
82
+ const parsers = plugin.parsers;
83
+ if (!parsers) {
84
+ return false;
85
+ }
86
+ const matchedParser = parsers[parserName];
87
+ return Boolean(matchedParser);
55
88
  });
56
89
  }
57
90
  export function wrapParser(originalParser, parserName) {
@@ -65,25 +98,22 @@ export function wrapParser(originalParser, parserName) {
65
98
  async function multilineArraysPluginPreprocess(text, options) {
66
99
  const pluginsFromOptions = options.plugins ?? [];
67
100
  const pluginsWithRelevantParsers = findPluginsByParserName(parserName, pluginsFromOptions);
68
- pluginsWithRelevantParsers.forEach((plugin) => {
101
+ for (const plugin of pluginsWithRelevantParsers) {
69
102
  const currentParser = plugin.parsers?.[parserName];
70
103
  if (currentParser &&
71
104
  plugin?.name?.includes("prettier-plugin-sort-json")) {
72
105
  parserProxy.proxyModifier.addOverrideTarget(currentParser);
73
106
  }
74
- });
75
- const pluginsWithPreprocessor = pluginsWithRelevantParsers.filter((plugin) => !!plugin.parsers?.[parserName]?.preprocess);
76
- let processedText = text;
77
- for (const pluginWithPreprocessor of pluginsWithPreprocessor) {
78
- const nextText = await pluginWithPreprocessor.parsers?.[parserName]?.preprocess?.(processedText, {
107
+ }
108
+ const pluginsWithPreprocessor = pluginsWithRelevantParsers.filter((plugin) => Boolean(plugin.parsers?.[parserName]?.preprocess));
109
+ const preprocessSteps = pluginsWithPreprocessor.map((pluginWithPreprocessor) => async (previousProcessedText) => {
110
+ const nextText = await pluginWithPreprocessor.parsers?.[parserName]?.preprocess?.(previousProcessedText, {
79
111
  ...options,
80
- plugins: pluginsFromOptions.filter((plugin) => plugin.pluginMarker !==
81
- pluginMarker),
112
+ plugins: pluginsFromOptions.filter(not(hasThisPluginMarker)),
82
113
  });
83
- if (nextText != undefined) {
84
- processedText = nextText;
85
- }
86
- }
114
+ return nextText ?? previousProcessedText;
115
+ });
116
+ const processedText = await runPreprocessSteps(preprocessSteps, text);
87
117
  addMultilinePrinter(options);
88
118
  return processedText;
89
119
  }
@@ -1,18 +1,20 @@
1
1
  import type { Doc } from "prettier";
2
- type Parents = {
3
- parent: Doc;
2
+ interface Parents {
4
3
  childIndexInThisParent: number | undefined;
5
- };
4
+ parent: Doc;
5
+ }
6
6
  /**
7
+ * Walk a Prettier doc tree from the given starting node.
8
+ *
7
9
  * @returns Boolean true means keep walking children and siblings, false means
8
10
  * stop walking children and siblings. Returning false does not stop walking
9
11
  * of aunts/uncles or ancestors.
10
12
  */
11
- export declare function walkDoc({ startDoc, debug, callback, parents, index, }: Readonly<{
12
- startDoc: Doc;
13
+ export declare function walkDoc({ startDoc, debug, callback: visitDoc, parents, index, }: Readonly<{
14
+ callback: (currentDoc: Doc, parents: Parents[], index: number | undefined) => boolean | undefined;
13
15
  debug: boolean;
14
- callback: (currentDoc: Doc, parents: Parents[], index: number | undefined) => boolean | void | undefined;
15
- parents?: Parents[];
16
16
  index?: number | undefined;
17
+ parents?: Parents[];
18
+ startDoc: Doc;
17
19
  }>): boolean;
18
20
  export {};