prettier-plugin-multiline-arrays-2 1.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 (69) hide show
  1. package/LICENSE +3 -0
  2. package/LICENSE-CC0 +121 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +91 -0
  5. package/dist/augments/array.d.ts +3 -0
  6. package/dist/augments/array.js +21 -0
  7. package/dist/augments/array.test.d.ts +1 -0
  8. package/dist/augments/array.test.js +34 -0
  9. package/dist/augments/doc.d.ts +5 -0
  10. package/dist/augments/doc.js +30 -0
  11. package/dist/augments/string.d.ts +1 -0
  12. package/dist/augments/string.js +6 -0
  13. package/dist/index.d.ts +11 -0
  14. package/dist/index.js +46 -0
  15. package/dist/options.d.ts +32 -0
  16. package/dist/options.js +71 -0
  17. package/dist/options.test.d.ts +1 -0
  18. package/dist/options.test.js +48 -0
  19. package/dist/plugin-marker.d.ts +1 -0
  20. package/dist/plugin-marker.js +2 -0
  21. package/dist/preprocessing.d.ts +2 -0
  22. package/dist/preprocessing.js +94 -0
  23. package/dist/printer/child-docs.d.ts +18 -0
  24. package/dist/printer/child-docs.js +89 -0
  25. package/dist/printer/comment-triggers.d.ts +25 -0
  26. package/dist/printer/comment-triggers.js +327 -0
  27. package/dist/printer/comments.d.ts +2 -0
  28. package/dist/printer/comments.js +34 -0
  29. package/dist/printer/insert-new-lines.d.ts +15 -0
  30. package/dist/printer/insert-new-lines.js +580 -0
  31. package/dist/printer/insert-new-lines.test.d.ts +1 -0
  32. package/dist/printer/insert-new-lines.test.js +36 -0
  33. package/dist/printer/leading-new-line.d.ts +7 -0
  34. package/dist/printer/leading-new-line.js +31 -0
  35. package/dist/printer/multiline-array-printer.d.ts +4 -0
  36. package/dist/printer/multiline-array-printer.js +42 -0
  37. package/dist/printer/original-printer.d.ts +3 -0
  38. package/dist/printer/original-printer.js +10 -0
  39. package/dist/printer/supported-node-types.d.ts +9 -0
  40. package/dist/printer/supported-node-types.js +16 -0
  41. package/dist/printer/trailing-comma.d.ts +6 -0
  42. package/dist/printer/trailing-comma.js +28 -0
  43. package/dist/readme-examples/formatted-with-comments.example.d.ts +3 -0
  44. package/dist/readme-examples/formatted-with-comments.example.js +16 -0
  45. package/dist/readme-examples/formatted.example.d.ts +2 -0
  46. package/dist/readme-examples/formatted.example.js +12 -0
  47. package/dist/readme-examples/not-formatted.example.d.ts +2 -0
  48. package/dist/readme-examples/not-formatted.example.js +6 -0
  49. package/dist/readme-examples/prettier-options.example.d.ts +4 -0
  50. package/dist/readme-examples/prettier-options.example.js +5 -0
  51. package/dist/test/babel-ts.test.d.ts +1 -0
  52. package/dist/test/babel-ts.test.js +10 -0
  53. package/dist/test/javascript.test.d.ts +1 -0
  54. package/dist/test/javascript.test.js +702 -0
  55. package/dist/test/json.test.d.ts +1 -0
  56. package/dist/test/json.test.js +403 -0
  57. package/dist/test/json5.test.d.ts +1 -0
  58. package/dist/test/json5.test.js +210 -0
  59. package/dist/test/prettier-config.d.ts +2 -0
  60. package/dist/test/prettier-config.js +12 -0
  61. package/dist/test/prettier-versions.mock.script.d.ts +1 -0
  62. package/dist/test/prettier-versions.mock.script.js +123 -0
  63. package/dist/test/run-tests.mock.d.ts +17 -0
  64. package/dist/test/run-tests.mock.js +95 -0
  65. package/dist/test/typescript-tests.mock.d.ts +2 -0
  66. package/dist/test/typescript-tests.mock.js +1575 -0
  67. package/dist/test/typescript.test.d.ts +1 -0
  68. package/dist/test/typescript.test.js +10 -0
  69. package/package.json +117 -0
@@ -0,0 +1,94 @@
1
+ import { stringify } from "@augment-vir/common";
2
+ import { createWrappedMultiTargetProxy } from "proxy-vir";
3
+ import { pluginMarker } from "./plugin-marker.js";
4
+ import { createMultilineArrayPrinter } from "./printer/multiline-array-printer.js";
5
+ import { setOriginalPrinter } from "./printer/original-printer.js";
6
+ function addMultilinePrinter(options) {
7
+ if ("printer" in options) {
8
+ setOriginalPrinter(options.printer);
9
+ /** Overwrite the printer with ours. */
10
+ options.printer = createMultilineArrayPrinter(options.printer);
11
+ }
12
+ else {
13
+ const astFormat = options.astFormat;
14
+ if (!astFormat) {
15
+ throw new Error("Could not find astFormat while adding printer.");
16
+ }
17
+ /**
18
+ * If the printer hasn't already been assigned in options, rearrange
19
+ * plugins so that ours gets chosen.
20
+ */
21
+ const plugins = options.plugins ?? [];
22
+ const firstMatchedPlugin = plugins.find((plugin) => typeof plugin !== "string" &&
23
+ !(plugin instanceof URL) &&
24
+ !!plugin.printers &&
25
+ !!plugin.printers[astFormat]);
26
+ if (!firstMatchedPlugin || typeof firstMatchedPlugin === "string") {
27
+ throw new Error(`Matched invalid first plugin: ${firstMatchedPlugin}`);
28
+ }
29
+ const matchedPrinter = firstMatchedPlugin.printers?.[astFormat];
30
+ if (!matchedPrinter) {
31
+ throw new Error(`Printer not found on matched plugin: ${stringify(firstMatchedPlugin)}`);
32
+ }
33
+ setOriginalPrinter(matchedPrinter);
34
+ const thisPluginIndex = plugins.findIndex((plugin) => {
35
+ return (plugin.pluginMarker === pluginMarker);
36
+ });
37
+ const thisPlugin = plugins[thisPluginIndex];
38
+ if (!thisPlugin) {
39
+ throw new Error("This plugin was not found.");
40
+ }
41
+ /**
42
+ * Add this plugin to the beginning of the array so its printer is found
43
+ * first.
44
+ */
45
+ plugins.splice(thisPluginIndex, 1);
46
+ plugins.splice(0, 0, thisPlugin);
47
+ }
48
+ }
49
+ function findPluginsByParserName(parserName, plugins) {
50
+ return plugins.filter((plugin) => {
51
+ return (typeof plugin === "object" &&
52
+ !(plugin instanceof URL) &&
53
+ plugin.pluginMarker !== pluginMarker &&
54
+ !!plugin.parsers?.[parserName]);
55
+ });
56
+ }
57
+ export function wrapParser(originalParser, parserName) {
58
+ /**
59
+ * Create a multi-target proxy of parsers so that we don't block other
60
+ * plugins.
61
+ */
62
+ const parserProxy = createWrappedMultiTargetProxy({
63
+ initialTarget: originalParser,
64
+ });
65
+ async function multilineArraysPluginPreprocess(text, options) {
66
+ const pluginsFromOptions = options.plugins ?? [];
67
+ const pluginsWithRelevantParsers = findPluginsByParserName(parserName, pluginsFromOptions);
68
+ pluginsWithRelevantParsers.forEach((plugin) => {
69
+ const currentParser = plugin.parsers?.[parserName];
70
+ if (currentParser &&
71
+ plugin?.name?.includes("prettier-plugin-sort-json")) {
72
+ parserProxy.proxyModifier.addOverrideTarget(currentParser);
73
+ }
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, {
79
+ ...options,
80
+ plugins: pluginsFromOptions.filter((plugin) => plugin.pluginMarker !==
81
+ pluginMarker),
82
+ });
83
+ if (nextText != undefined) {
84
+ processedText = nextText;
85
+ }
86
+ }
87
+ addMultilinePrinter(options);
88
+ return processedText;
89
+ }
90
+ parserProxy.proxyModifier.addOverrideTarget({
91
+ preprocess: multilineArraysPluginPreprocess,
92
+ });
93
+ return parserProxy.proxy;
94
+ }
@@ -0,0 +1,18 @@
1
+ import type { Doc } from "prettier";
2
+ type Parents = {
3
+ parent: Doc;
4
+ childIndexInThisParent: number | undefined;
5
+ };
6
+ /**
7
+ * @returns Boolean true means keep walking children and siblings, false means
8
+ * stop walking children and siblings. Returning false does not stop walking
9
+ * of aunts/uncles or ancestors.
10
+ */
11
+ export declare function walkDoc({ startDoc, debug, callback, parents, index, }: Readonly<{
12
+ startDoc: Doc;
13
+ debug: boolean;
14
+ callback: (currentDoc: Doc, parents: Parents[], index: number | undefined) => boolean | void | undefined;
15
+ parents?: Parents[];
16
+ index?: number | undefined;
17
+ }>): boolean;
18
+ export {};
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @returns Boolean true means keep walking children and siblings, false means
3
+ * stop walking children and siblings. Returning false does not stop walking
4
+ * of aunts/uncles or ancestors.
5
+ */
6
+ export function walkDoc({ startDoc, debug, callback, parents = [], index, }) {
7
+ if (!startDoc) {
8
+ return true;
9
+ }
10
+ if (debug) {
11
+ const parent = parents[0];
12
+ console.info({
13
+ firingCallbackFor: startDoc,
14
+ status: "Calling callback",
15
+ parent: parent
16
+ ? {
17
+ isArray: Array.isArray(parent),
18
+ type: parent?.type ?? typeof parent,
19
+ }
20
+ : undefined,
21
+ index,
22
+ });
23
+ }
24
+ if (!callback(startDoc, parents, index)) {
25
+ // if the callback returns something falsy, don't try to walk its children
26
+ return false;
27
+ }
28
+ else if (typeof startDoc === "string") {
29
+ return true;
30
+ }
31
+ else if (Array.isArray(startDoc)) {
32
+ if (debug) {
33
+ console.info("walking array children");
34
+ }
35
+ // one a child returns false, abort walking this array
36
+ startDoc.every((innerDoc, index) => {
37
+ return walkDoc({
38
+ startDoc: innerDoc,
39
+ debug,
40
+ callback,
41
+ parents: [
42
+ {
43
+ parent: startDoc,
44
+ childIndexInThisParent: index,
45
+ },
46
+ ...parents,
47
+ ],
48
+ index,
49
+ });
50
+ });
51
+ }
52
+ else if ("contents" in startDoc) {
53
+ if (debug) {
54
+ console.info("walking contents property");
55
+ }
56
+ return walkDoc({
57
+ startDoc: startDoc.contents,
58
+ debug,
59
+ callback,
60
+ parents: [
61
+ {
62
+ parent: startDoc,
63
+ childIndexInThisParent: undefined,
64
+ },
65
+ ...parents,
66
+ ],
67
+ index: undefined,
68
+ });
69
+ }
70
+ else if ("parts" in startDoc) {
71
+ if (debug) {
72
+ console.info("walking parts property");
73
+ }
74
+ return walkDoc({
75
+ startDoc: startDoc.parts,
76
+ debug,
77
+ callback,
78
+ parents: [
79
+ {
80
+ parent: startDoc,
81
+ childIndexInThisParent: undefined,
82
+ },
83
+ ...parents,
84
+ ],
85
+ index: undefined,
86
+ });
87
+ }
88
+ return true;
89
+ }
@@ -0,0 +1,25 @@
1
+ import type { Node } from "estree";
2
+ type LineNumberDetails<T> = {
3
+ [lineNumber: string]: T;
4
+ };
5
+ export type LineCounts = LineNumberDetails<number[]>;
6
+ export type WrapThresholds = LineNumberDetails<number>;
7
+ export type CommentTriggerWithEnding<T> = {
8
+ [P in keyof T]: {
9
+ data: T[P];
10
+ lineEnd: number;
11
+ };
12
+ };
13
+ export type CommentTriggers = {
14
+ nextLineCounts: LineCounts;
15
+ setLineCounts: CommentTriggerWithEnding<LineCounts>;
16
+ nextWrapThresholds: WrapThresholds;
17
+ setWrapThresholds: CommentTriggerWithEnding<WrapThresholds>;
18
+ };
19
+ export declare function getCommentTriggers(key: Node, debug: boolean): CommentTriggers;
20
+ export declare function parseNextLineCounts({ input, nextOnly, debug, }: Readonly<{
21
+ input: string;
22
+ nextOnly: boolean;
23
+ debug: boolean;
24
+ }>): number[];
25
+ export {};
@@ -0,0 +1,327 @@
1
+ import { check } from "@augment-vir/assert";
2
+ import { getObjectTypedKeys } from "@augment-vir/common";
3
+ import { nextLinePatternComment, nextWrapThresholdComment, resetComment, setLinePatternComment, setWrapThresholdComment, untilNextLinePatternCommentRegExp, untilNextWrapThresholdCommentRegExp, untilSetLinePatternCommentRegExp, untilSetWrapThresholdCommentRegExp, } from "../options.js";
4
+ import { extractComments } from "./comments.js";
5
+ import { isArrayLikeNode } from "./supported-node-types.js";
6
+ const mappedCommentTriggers = new WeakMap();
7
+ const ignoredAstChildKeys = [
8
+ "comments",
9
+ "leadingComments",
10
+ "loc",
11
+ "range",
12
+ "raw",
13
+ "tokens",
14
+ "trailingComments",
15
+ "value",
16
+ ];
17
+ const descendantBoundaryTypes = [
18
+ "ArrowFunctionExpression",
19
+ "ClassDeclaration",
20
+ "ClassExpression",
21
+ "FunctionDeclaration",
22
+ "FunctionExpression",
23
+ ];
24
+ export function getCommentTriggers(key, debug) {
25
+ const alreadyExisting = mappedCommentTriggers.get(key);
26
+ if (!alreadyExisting) {
27
+ return setCommentTriggers(key, debug);
28
+ }
29
+ return alreadyExisting;
30
+ }
31
+ function setCommentTriggers(rootNode, debug) {
32
+ // parse comments only on the root node so it only happens once
33
+ const comments = extractComments(rootNode);
34
+ if (debug) {
35
+ console.info({
36
+ comments,
37
+ });
38
+ }
39
+ const starterTriggers = {
40
+ nextLineCounts: {},
41
+ setLineCounts: {},
42
+ nextWrapThresholds: {},
43
+ setWrapThresholds: {},
44
+ resets: [],
45
+ };
46
+ const internalCommentTriggers = comments.reduce((accum, currentComment) => {
47
+ const commentText = currentComment.value?.replace(/\n/g, " ");
48
+ if (!currentComment.loc) {
49
+ throw new Error(`Cannot read line location for comment ${currentComment.value}`);
50
+ }
51
+ const nextLineCounts = getLineCounts({
52
+ commentText,
53
+ nextOnly: true,
54
+ debug,
55
+ });
56
+ if (nextLineCounts.length) {
57
+ accum.nextLineCounts[currentComment.loc.end.line] =
58
+ nextLineCounts;
59
+ }
60
+ const nextWrapThreshold = getWrapThreshold(commentText, true);
61
+ if (nextWrapThreshold != undefined) {
62
+ accum.nextWrapThresholds[currentComment.loc.end.line] =
63
+ nextWrapThreshold;
64
+ }
65
+ const setLineCounts = getLineCounts({
66
+ commentText,
67
+ nextOnly: false,
68
+ debug,
69
+ });
70
+ if (setLineCounts.length) {
71
+ accum.setLineCounts[currentComment.loc.end.line] = {
72
+ data: setLineCounts,
73
+ lineEnd: Infinity,
74
+ };
75
+ }
76
+ const setWrapThreshold = getWrapThreshold(commentText, false);
77
+ if (setWrapThreshold != undefined) {
78
+ accum.setWrapThresholds[currentComment.loc.end.line] = {
79
+ data: setWrapThreshold,
80
+ lineEnd: Infinity,
81
+ };
82
+ }
83
+ const resetComment = isResetComment(commentText);
84
+ if (resetComment) {
85
+ accum.resets.push(currentComment.loc.end.line);
86
+ }
87
+ return accum;
88
+ }, starterTriggers);
89
+ internalCommentTriggers.resets.sort();
90
+ setResets(internalCommentTriggers);
91
+ mapNextCommentTriggers({
92
+ internalCommentTriggers,
93
+ rootNode,
94
+ });
95
+ const commentTriggers = {
96
+ ...internalCommentTriggers,
97
+ };
98
+ delete commentTriggers.resets;
99
+ // save to a map so we don't have to recalculate these every time
100
+ mappedCommentTriggers.set(rootNode, commentTriggers);
101
+ return commentTriggers;
102
+ }
103
+ function mapNextCommentTriggers({ internalCommentTriggers, rootNode, }) {
104
+ internalCommentTriggers.nextLineCounts = mapNextLineTriggers({
105
+ rootNode,
106
+ triggers: internalCommentTriggers.nextLineCounts,
107
+ });
108
+ internalCommentTriggers.nextWrapThresholds = mapNextLineTriggers({
109
+ rootNode,
110
+ triggers: internalCommentTriggers.nextWrapThresholds,
111
+ });
112
+ }
113
+ function mapNextLineTriggers({ rootNode, triggers, }) {
114
+ return getObjectTypedKeys(triggers).reduce((mappedTriggers, triggerLineNumber) => {
115
+ const trigger = triggers[triggerLineNumber];
116
+ const targetLineNumber = findArrayLikeTargetLine({
117
+ nextLineNumber: Number(triggerLineNumber) + 1,
118
+ rootNode,
119
+ });
120
+ if (targetLineNumber == undefined || trigger == undefined) {
121
+ return mappedTriggers;
122
+ }
123
+ return {
124
+ ...mappedTriggers,
125
+ [targetLineNumber]: trigger,
126
+ };
127
+ }, {});
128
+ }
129
+ function findArrayLikeTargetLine({ rootNode, nextLineNumber, }) {
130
+ return findAstNodesStartingOnLine({
131
+ lineNumber: nextLineNumber,
132
+ rootNode,
133
+ })
134
+ .flatMap((node) => {
135
+ return findArrayLikeDescendantLines({
136
+ rootNode: node,
137
+ });
138
+ })
139
+ .toSorted((firstLine, secondLine) => {
140
+ return firstLine - secondLine;
141
+ })[0];
142
+ }
143
+ function findAstNodesStartingOnLine({ rootNode, lineNumber, }) {
144
+ return collectAstNodes({
145
+ input: rootNode,
146
+ shouldInclude: (node) => {
147
+ return node.loc?.start.line === lineNumber;
148
+ },
149
+ });
150
+ }
151
+ function findArrayLikeDescendantLines({ rootNode, }) {
152
+ return collectAstNodes({
153
+ input: rootNode,
154
+ shouldInclude: (node) => {
155
+ return isArrayLikeNode(node) && !!node.loc;
156
+ },
157
+ shouldWalkChildren: (node, isRootNode) => {
158
+ return isRootNode || !descendantBoundaryTypes.includes(node.type);
159
+ },
160
+ }).flatMap((node) => {
161
+ if (!node.loc) {
162
+ return [];
163
+ }
164
+ return [node.loc.start.line];
165
+ });
166
+ }
167
+ function collectAstNodes({ input, shouldInclude, shouldWalkChildren = () => true, seenInputs = new WeakSet(), isRootNode = true, }) {
168
+ if (check.isArray(input)) {
169
+ return input.flatMap((child) => {
170
+ return collectAstNodes({
171
+ input: child,
172
+ isRootNode: false,
173
+ seenInputs,
174
+ shouldInclude,
175
+ shouldWalkChildren,
176
+ });
177
+ });
178
+ }
179
+ else if (!check.isObject(input)) {
180
+ return [];
181
+ }
182
+ else if (seenInputs.has(input)) {
183
+ return [];
184
+ }
185
+ seenInputs.add(input);
186
+ if (!isAstNode(input)) {
187
+ return [];
188
+ }
189
+ const matchingNode = shouldInclude(input, isRootNode) ? [input] : [];
190
+ const childNodes = shouldWalkChildren(input, isRootNode)
191
+ ? getObjectTypedKeys(input).flatMap((nodeKey) => {
192
+ if (ignoredAstChildKeys.includes(String(nodeKey))) {
193
+ return [];
194
+ }
195
+ return collectAstNodes({
196
+ input: Reflect.get(input, nodeKey),
197
+ isRootNode: false,
198
+ seenInputs,
199
+ shouldInclude,
200
+ shouldWalkChildren,
201
+ });
202
+ })
203
+ : [];
204
+ return [...matchingNode, ...childNodes];
205
+ }
206
+ function isAstNode(input) {
207
+ return check.isObject(input) && check.isString(input.type);
208
+ }
209
+ function setResets(internalCommentTriggers) {
210
+ if (!internalCommentTriggers.resets.length) {
211
+ return;
212
+ }
213
+ const setLineCountLineNumbers = getObjectTypedKeys(internalCommentTriggers.setLineCounts);
214
+ if (setLineCountLineNumbers.length) {
215
+ setLineCountLineNumbers.forEach((lineNumber) => {
216
+ const currentLineNumberStats = internalCommentTriggers.setLineCounts[lineNumber];
217
+ if (!currentLineNumberStats) {
218
+ throw new Error(`Line number stats were undefined for "${lineNumber}" in "${JSON.stringify(internalCommentTriggers.setLineCounts)}"`);
219
+ }
220
+ const endLineNumber = internalCommentTriggers.resets.find((resetLineNumber) => {
221
+ return Number(lineNumber) < resetLineNumber;
222
+ }) ?? currentLineNumberStats.lineEnd;
223
+ currentLineNumberStats.lineEnd = endLineNumber;
224
+ });
225
+ }
226
+ }
227
+ function getWrapThreshold(commentText, nextOnly) {
228
+ const searchText = nextOnly
229
+ ? nextWrapThresholdComment
230
+ : setWrapThresholdComment;
231
+ const searchRegExp = nextOnly
232
+ ? untilNextWrapThresholdCommentRegExp
233
+ : untilSetWrapThresholdCommentRegExp;
234
+ if (commentText?.toLowerCase().includes(searchText)) {
235
+ const thresholdValue = Number(commentText.toLowerCase().replace(searchRegExp, "").trim());
236
+ if (isNaN(thresholdValue)) {
237
+ return undefined;
238
+ }
239
+ else {
240
+ return thresholdValue;
241
+ }
242
+ }
243
+ else {
244
+ return undefined;
245
+ }
246
+ }
247
+ export function parseNextLineCounts({ input, nextOnly, debug, }) {
248
+ if (!input) {
249
+ return [];
250
+ }
251
+ const searchRegExp = nextOnly
252
+ ? untilNextLinePatternCommentRegExp
253
+ : untilSetLinePatternCommentRegExp;
254
+ const split = input
255
+ .toLowerCase()
256
+ .replace(searchRegExp, "")
257
+ .replace(/,/g, "")
258
+ .split(" ")
259
+ .filter((entry) => !!entry);
260
+ const firstSplit = split[0];
261
+ if (firstSplit === "[") {
262
+ split.splice(0, 1);
263
+ }
264
+ else if (firstSplit?.startsWith("[")) {
265
+ split[0] = firstSplit.replace(/^\[/, "");
266
+ }
267
+ const lastSplitIndex = split.length - 1;
268
+ const lastSplit = split[lastSplitIndex];
269
+ if (lastSplit === "]") {
270
+ split.splice(split.length - 1, 1);
271
+ }
272
+ else if (lastSplit?.endsWith("]")) {
273
+ split[lastSplitIndex] = lastSplit.replace(/\]$/, "");
274
+ }
275
+ const numbers = split.map((entry) => entry && !!entry.trim().match(/^\d+$/) ? Number(entry.trim()) : NaN);
276
+ const invalidNumbers = numbers
277
+ .map((entry, index) => {
278
+ return {
279
+ index,
280
+ entry,
281
+ original: split[index],
282
+ };
283
+ })
284
+ .filter((entry) => {
285
+ return isNaN(entry.entry);
286
+ });
287
+ if (invalidNumbers.length) {
288
+ if (debug) {
289
+ console.error(invalidNumbers.map((entry) => {
290
+ return {
291
+ index: entry.index,
292
+ original: entry.original,
293
+ parsed: entry,
294
+ split,
295
+ input,
296
+ numbers,
297
+ trim: entry.original?.trim(),
298
+ match: entry.original?.trim().match(/^\d+$/),
299
+ matched: !!entry.original?.trim().match(/^\d+$/),
300
+ };
301
+ }));
302
+ }
303
+ console.error(`Invalid number(s) for elements per line option/comment: ${invalidNumbers
304
+ .map((entry) => entry.original)
305
+ .join()}`);
306
+ return [];
307
+ }
308
+ return numbers;
309
+ }
310
+ function isResetComment(commentText) {
311
+ return !!commentText?.toLowerCase().includes(resetComment);
312
+ }
313
+ function getLineCounts({ commentText, nextOnly, debug, }) {
314
+ const searchText = nextOnly
315
+ ? nextLinePatternComment
316
+ : setLinePatternComment;
317
+ if (commentText?.toLowerCase().includes(searchText)) {
318
+ return parseNextLineCounts({
319
+ input: commentText,
320
+ nextOnly,
321
+ debug,
322
+ });
323
+ }
324
+ else {
325
+ return [];
326
+ }
327
+ }
@@ -0,0 +1,2 @@
1
+ import type { Comment } from "estree";
2
+ export declare function extractComments(node: any): Comment[];
@@ -0,0 +1,34 @@
1
+ const ignoreTheseKeys = ["tokens"];
2
+ const ignoreTheseChildTypes = ["string", "number"];
3
+ const commentTypes = [
4
+ "Line",
5
+ "Block",
6
+ "CommentBlock",
7
+ "CommentLine",
8
+ ];
9
+ function isMaybeComment(input) {
10
+ return !(!input ||
11
+ typeof input !== "object" ||
12
+ !("type" in input) ||
13
+ !commentTypes.includes(input.type) ||
14
+ !("value" in input));
15
+ }
16
+ export function extractComments(node) {
17
+ if (!node || typeof node !== "object") {
18
+ return [];
19
+ }
20
+ const comments = [];
21
+ if (Array.isArray(node)) {
22
+ comments.push(...node.filter(isMaybeComment));
23
+ }
24
+ Object.keys(node).forEach((nodeKey) => {
25
+ if (!ignoreTheseKeys.includes(nodeKey)) {
26
+ const nodeChild = node[nodeKey];
27
+ if (!ignoreTheseChildTypes.includes(typeof nodeChild)) {
28
+ comments.push(...extractComments(nodeChild));
29
+ }
30
+ }
31
+ });
32
+ // this might duplicate comments but our later code doesn't care
33
+ return comments;
34
+ }
@@ -0,0 +1,15 @@
1
+ import type { AstPath, Doc, ParserOptions } from "prettier";
2
+ import { type MultilineArrayOptions } from "../options.js";
3
+ export declare function insertLinesIntoArray({ inputDoc, manualWrap, lineCounts, wrapThreshold, debug, }: Readonly<{
4
+ inputDoc: Doc;
5
+ manualWrap: boolean;
6
+ lineCounts: number[];
7
+ wrapThreshold: number;
8
+ debug: boolean;
9
+ }>): Doc;
10
+ export declare function printWithMultilineArrays({ originalFormattedOutput, path, inputOptions, debug, }: Readonly<{
11
+ originalFormattedOutput: Doc;
12
+ path: AstPath;
13
+ inputOptions: MultilineArrayOptions & ParserOptions;
14
+ debug: boolean;
15
+ }>): Doc;