rawsql-ts 0.11.41-beta → 0.11.43-beta

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 (46) hide show
  1. package/README.md +6 -6
  2. package/dist/esm/index.min.js +18 -9
  3. package/dist/esm/index.min.js.map +2 -2
  4. package/dist/esm/src/parsers/KeywordParser.js +4 -2
  5. package/dist/esm/src/parsers/KeywordParser.js.map +1 -1
  6. package/dist/esm/src/parsers/SqlPrintTokenParser.d.ts +11 -18
  7. package/dist/esm/src/parsers/SqlPrintTokenParser.js +126 -218
  8. package/dist/esm/src/parsers/SqlPrintTokenParser.js.map +1 -1
  9. package/dist/esm/src/parsers/SqlTokenizer.js +26 -13
  10. package/dist/esm/src/parsers/SqlTokenizer.js.map +1 -1
  11. package/dist/esm/src/transformers/LinePrinter.d.ts +1 -0
  12. package/dist/esm/src/transformers/LinePrinter.js +22 -1
  13. package/dist/esm/src/transformers/LinePrinter.js.map +1 -1
  14. package/dist/esm/src/transformers/SqlFormatter.d.ts +6 -4
  15. package/dist/esm/src/transformers/SqlFormatter.js +2 -2
  16. package/dist/esm/src/transformers/SqlFormatter.js.map +1 -1
  17. package/dist/esm/src/transformers/SqlPrinter.d.ts +40 -2
  18. package/dist/esm/src/transformers/SqlPrinter.js +489 -27
  19. package/dist/esm/src/transformers/SqlPrinter.js.map +1 -1
  20. package/dist/esm/src/utils/stringUtils.d.ts +1 -1
  21. package/dist/esm/src/utils/stringUtils.js +8 -2
  22. package/dist/esm/src/utils/stringUtils.js.map +1 -1
  23. package/dist/esm/tsconfig.browser.tsbuildinfo +1 -1
  24. package/dist/index.min.js +18 -9
  25. package/dist/index.min.js.map +2 -2
  26. package/dist/src/parsers/KeywordParser.js +4 -2
  27. package/dist/src/parsers/KeywordParser.js.map +1 -1
  28. package/dist/src/parsers/SqlPrintTokenParser.d.ts +11 -18
  29. package/dist/src/parsers/SqlPrintTokenParser.js +126 -218
  30. package/dist/src/parsers/SqlPrintTokenParser.js.map +1 -1
  31. package/dist/src/parsers/SqlTokenizer.js +26 -13
  32. package/dist/src/parsers/SqlTokenizer.js.map +1 -1
  33. package/dist/src/transformers/LinePrinter.d.ts +1 -0
  34. package/dist/src/transformers/LinePrinter.js +22 -1
  35. package/dist/src/transformers/LinePrinter.js.map +1 -1
  36. package/dist/src/transformers/SqlFormatter.d.ts +6 -4
  37. package/dist/src/transformers/SqlFormatter.js +2 -2
  38. package/dist/src/transformers/SqlFormatter.js.map +1 -1
  39. package/dist/src/transformers/SqlPrinter.d.ts +40 -2
  40. package/dist/src/transformers/SqlPrinter.js +489 -27
  41. package/dist/src/transformers/SqlPrinter.js.map +1 -1
  42. package/dist/src/utils/stringUtils.d.ts +1 -1
  43. package/dist/src/utils/stringUtils.js +8 -2
  44. package/dist/src/utils/stringUtils.js.map +1 -1
  45. package/dist/tsconfig.tsbuildinfo +1 -1
  46. package/package.json +1 -1
@@ -29,9 +29,13 @@ class SqlPrinter {
29
29
  * @param options Optional style settings for pretty printing
30
30
  */
31
31
  constructor(options) {
32
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
32
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
33
33
  /** Track whether we are currently inside a WITH clause for full-oneline formatting */
34
34
  this.insideWithClause = false;
35
+ /** Pending line comment that needs a forced newline before next token */
36
+ this.pendingLineCommentBreak = null;
37
+ /** Accumulates lines when reconstructing multi-line block comments inside CommentBlocks */
38
+ this.smartCommentBlockBuilder = null;
35
39
  // Resolve logical options to their control character representations before applying defaults.
36
40
  const resolvedIndentChar = (0, FormatOptionResolver_1.resolveIndentCharOption)(options === null || options === void 0 ? void 0 : options.indentChar);
37
41
  const resolvedNewline = (0, FormatOptionResolver_1.resolveNewlineOption)(options === null || options === void 0 ? void 0 : options.newline);
@@ -44,9 +48,9 @@ class SqlPrinter {
44
48
  this.cteCommaBreak = (_c = options === null || options === void 0 ? void 0 : options.cteCommaBreak) !== null && _c !== void 0 ? _c : this.commaBreak;
45
49
  this.valuesCommaBreak = (_d = options === null || options === void 0 ? void 0 : options.valuesCommaBreak) !== null && _d !== void 0 ? _d : this.commaBreak;
46
50
  this.andBreak = (_e = options === null || options === void 0 ? void 0 : options.andBreak) !== null && _e !== void 0 ? _e : 'none';
47
- this.keywordCase = (_f = options === null || options === void 0 ? void 0 : options.keywordCase) !== null && _f !== void 0 ? _f : 'none';
48
- this.exportComment = (_g = options === null || options === void 0 ? void 0 : options.exportComment) !== null && _g !== void 0 ? _g : false;
49
- this.strictCommentPlacement = (_h = options === null || options === void 0 ? void 0 : options.strictCommentPlacement) !== null && _h !== void 0 ? _h : false;
51
+ this.orBreak = (_f = options === null || options === void 0 ? void 0 : options.orBreak) !== null && _f !== void 0 ? _f : 'none';
52
+ this.keywordCase = (_g = options === null || options === void 0 ? void 0 : options.keywordCase) !== null && _g !== void 0 ? _g : 'none';
53
+ this.exportComment = (_h = options === null || options === void 0 ? void 0 : options.exportComment) !== null && _h !== void 0 ? _h : false;
50
54
  this.withClauseStyle = (_j = options === null || options === void 0 ? void 0 : options.withClauseStyle) !== null && _j !== void 0 ? _j : 'standard';
51
55
  this.commentStyle = (_k = options === null || options === void 0 ? void 0 : options.commentStyle) !== null && _k !== void 0 ? _k : 'block';
52
56
  this.parenthesesOneLine = (_l = options === null || options === void 0 ? void 0 : options.parenthesesOneLine) !== null && _l !== void 0 ? _l : false;
@@ -55,9 +59,10 @@ class SqlPrinter {
55
59
  this.joinOneLine = (_p = options === null || options === void 0 ? void 0 : options.joinOneLine) !== null && _p !== void 0 ? _p : false;
56
60
  this.caseOneLine = (_q = options === null || options === void 0 ? void 0 : options.caseOneLine) !== null && _q !== void 0 ? _q : false;
57
61
  this.subqueryOneLine = (_r = options === null || options === void 0 ? void 0 : options.subqueryOneLine) !== null && _r !== void 0 ? _r : false;
62
+ this.indentNestedParentheses = (_s = options === null || options === void 0 ? void 0 : options.indentNestedParentheses) !== null && _s !== void 0 ? _s : false;
58
63
  this.linePrinter = new LinePrinter_1.LinePrinter(this.indentChar, this.indentSize, this.newline, this.commaBreak);
59
64
  // Initialize
60
- this.indentIncrementContainers = new Set((_s = options === null || options === void 0 ? void 0 : options.indentIncrementContainerTypes) !== null && _s !== void 0 ? _s : [
65
+ this.indentIncrementContainers = new Set((_t = options === null || options === void 0 ? void 0 : options.indentIncrementContainerTypes) !== null && _t !== void 0 ? _t : [
61
66
  SqlPrintToken_1.SqlPrintTokenContainerType.SelectClause,
62
67
  SqlPrintToken_1.SqlPrintTokenContainerType.FromClause,
63
68
  SqlPrintToken_1.SqlPrintTokenContainerType.WhereClause,
@@ -98,13 +103,15 @@ class SqlPrinter {
98
103
  // initialize
99
104
  this.linePrinter = new LinePrinter_1.LinePrinter(this.indentChar, this.indentSize, this.newline, this.commaBreak);
100
105
  this.insideWithClause = false; // Reset WITH clause context
106
+ this.pendingLineCommentBreak = null;
107
+ this.smartCommentBlockBuilder = null;
101
108
  if (this.linePrinter.lines.length > 0 && level !== this.linePrinter.lines[0].level) {
102
109
  this.linePrinter.lines[0].level = level;
103
110
  }
104
- this.appendToken(token, level, undefined, 0);
111
+ this.appendToken(token, level, undefined, 0, false);
105
112
  return this.linePrinter.print();
106
113
  }
107
- appendToken(token, level, parentContainerType, caseContextDepth = 0) {
114
+ appendToken(token, level, parentContainerType, caseContextDepth = 0, indentParentActive = false) {
108
115
  // Track WITH clause context for full-oneline formatting
109
116
  const wasInsideWithClause = this.insideWithClause;
110
117
  if (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.WithClause && this.withClauseStyle === 'full-oneline') {
@@ -113,9 +120,27 @@ class SqlPrinter {
113
120
  if (this.shouldSkipToken(token)) {
114
121
  return;
115
122
  }
123
+ if (this.smartCommentBlockBuilder && token.containerType !== SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock && token.type !== SqlPrintToken_1.SqlPrintTokenType.commentNewline) {
124
+ this.flushSmartCommentBlockBuilder();
125
+ }
126
+ if (this.pendingLineCommentBreak !== null) {
127
+ if (!this.isOnelineMode()) {
128
+ this.linePrinter.appendNewline(this.pendingLineCommentBreak);
129
+ }
130
+ const shouldSkipToken = token.type === SqlPrintToken_1.SqlPrintTokenType.commentNewline;
131
+ this.pendingLineCommentBreak = null;
132
+ if (shouldSkipToken) {
133
+ return;
134
+ }
135
+ }
136
+ if (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock) {
137
+ this.handleCommentBlockContainer(token, level);
138
+ return;
139
+ }
116
140
  const current = this.linePrinter.getCurrentLine();
117
141
  const isCaseContext = this.isCaseContext(token.containerType);
118
142
  const nextCaseContextDepth = isCaseContext ? caseContextDepth + 1 : caseContextDepth;
143
+ const shouldIndentNested = this.shouldIndentNestedParentheses(token);
119
144
  // Handle different token types
120
145
  if (token.type === SqlPrintToken_1.SqlPrintTokenType.keyword) {
121
146
  this.handleKeywordToken(token, level, parentContainerType, caseContextDepth);
@@ -123,18 +148,21 @@ class SqlPrinter {
123
148
  else if (token.type === SqlPrintToken_1.SqlPrintTokenType.comma) {
124
149
  this.handleCommaToken(token, level, parentContainerType);
125
150
  }
151
+ else if (token.type === SqlPrintToken_1.SqlPrintTokenType.parenthesis) {
152
+ this.handleParenthesisToken(token, level, indentParentActive);
153
+ }
126
154
  else if (token.type === SqlPrintToken_1.SqlPrintTokenType.operator && token.text.toLowerCase() === 'and') {
127
155
  this.handleAndOperatorToken(token, level, parentContainerType, caseContextDepth);
128
156
  }
157
+ else if (token.type === SqlPrintToken_1.SqlPrintTokenType.operator && token.text.toLowerCase() === 'or') {
158
+ this.handleOrOperatorToken(token, level, parentContainerType, caseContextDepth);
159
+ }
129
160
  else if (token.containerType === "JoinClause") {
130
161
  this.handleJoinClauseToken(token, level);
131
162
  }
132
163
  else if (token.type === SqlPrintToken_1.SqlPrintTokenType.comment) {
133
- // Handle comments as regular tokens - let the standard processing handle everything
134
164
  if (this.exportComment) {
135
- // Note: Smart comment processing is handled at SqlPrintTokenParser level
136
- // via positioned comments system, so we don't need additional processing here
137
- this.linePrinter.appendText(token.text);
165
+ this.printCommentToken(token.text, level, parentContainerType);
138
166
  }
139
167
  }
140
168
  else if (token.type === SqlPrintToken_1.SqlPrintTokenType.space) {
@@ -147,7 +175,7 @@ class SqlPrinter {
147
175
  this.handleCteOnelineToken(token, level);
148
176
  return; // Return early to avoid processing innerTokens
149
177
  }
150
- else if ((token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.ParenExpression && this.parenthesesOneLine) ||
178
+ else if ((token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.ParenExpression && this.parenthesesOneLine && !shouldIndentNested) ||
151
179
  (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.BetweenExpression && this.betweenOneLine) ||
152
180
  (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.Values && this.valuesOneLine) ||
153
181
  (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.JoinOnClause && this.joinOneLine) ||
@@ -163,21 +191,34 @@ class SqlPrinter {
163
191
  if (token.keywordTokens && token.keywordTokens.length > 0) {
164
192
  for (let i = 0; i < token.keywordTokens.length; i++) {
165
193
  const keywordToken = token.keywordTokens[i];
166
- this.appendToken(keywordToken, level, token.containerType, nextCaseContextDepth);
194
+ this.appendToken(keywordToken, level, token.containerType, nextCaseContextDepth, indentParentActive);
167
195
  }
168
196
  }
169
197
  let innerLevel = level;
170
- // indent level up
171
- if (!this.isOnelineMode() && current.text !== '' && this.indentIncrementContainers.has(token.containerType)) {
172
- // Skip newline for any container when inside WITH clause with full-oneline style
173
- if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
174
- innerLevel++;
198
+ let increasedIndent = false;
199
+ const shouldIncreaseIndent = this.indentIncrementContainers.has(token.containerType) || shouldIndentNested;
200
+ const delayIndentNewline = shouldIndentNested && token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.ParenExpression;
201
+ if (!this.isOnelineMode() && shouldIncreaseIndent) {
202
+ if (this.insideWithClause && this.withClauseStyle === 'full-oneline') {
203
+ // Keep everything on one line for full-oneline WITH clauses.
204
+ }
205
+ else if (delayIndentNewline) {
206
+ innerLevel = level + 1;
207
+ increasedIndent = true;
208
+ }
209
+ else if (current.text !== '') {
210
+ innerLevel = level + 1;
211
+ increasedIndent = true;
175
212
  this.linePrinter.appendNewline(innerLevel);
176
213
  }
177
214
  }
178
215
  for (let i = 0; i < token.innerTokens.length; i++) {
179
216
  const child = token.innerTokens[i];
180
- this.appendToken(child, innerLevel, token.containerType, nextCaseContextDepth);
217
+ const childIndentParentActive = token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.ParenExpression ? shouldIndentNested : indentParentActive;
218
+ this.appendToken(child, innerLevel, token.containerType, nextCaseContextDepth, childIndentParentActive);
219
+ }
220
+ if (this.smartCommentBlockBuilder && this.smartCommentBlockBuilder.mode === 'line') {
221
+ this.flushSmartCommentBlockBuilder();
181
222
  }
182
223
  // Exit WITH clause context when we finish processing WithClause container
183
224
  if (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.WithClause && this.withClauseStyle === 'full-oneline') {
@@ -187,11 +228,8 @@ class SqlPrinter {
187
228
  return; // Return early to avoid additional newline below
188
229
  }
189
230
  // indent level down
190
- if (innerLevel !== level) {
191
- // Skip newline for any container when inside WITH clause with full-oneline style
192
- if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
193
- this.linePrinter.appendNewline(level);
194
- }
231
+ if (increasedIndent && shouldIncreaseIndent && !(this.insideWithClause && this.withClauseStyle === 'full-oneline') && !delayIndentNewline) {
232
+ this.linePrinter.appendNewline(level);
195
233
  }
196
234
  }
197
235
  isCaseContext(containerType) {
@@ -234,6 +272,10 @@ class SqlPrinter {
234
272
  this.handleAndOperatorToken(token, level, parentContainerType, caseContextDepth);
235
273
  return;
236
274
  }
275
+ else if (lower === 'or' && this.orBreak !== 'none') {
276
+ this.handleOrOperatorToken(token, level, parentContainerType, caseContextDepth);
277
+ return;
278
+ }
237
279
  const text = this.applyKeywordCase(token.text);
238
280
  if (caseContextDepth > 0) {
239
281
  this.linePrinter.appendText(text);
@@ -279,6 +321,9 @@ class SqlPrinter {
279
321
  if (previousCommaBreak !== 'after') {
280
322
  this.linePrinter.commaBreak = 'after';
281
323
  }
324
+ if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
325
+ this.linePrinter.appendNewline(level);
326
+ }
282
327
  this.linePrinter.appendText(text);
283
328
  if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
284
329
  this.linePrinter.appendNewline(level);
@@ -325,6 +370,79 @@ class SqlPrinter {
325
370
  this.linePrinter.appendText(text);
326
371
  }
327
372
  }
373
+ handleParenthesisToken(token, level, indentParentActive) {
374
+ if (token.text === '(') {
375
+ this.linePrinter.appendText(token.text);
376
+ if (indentParentActive && !this.isOnelineMode()) {
377
+ if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
378
+ this.linePrinter.appendNewline(level);
379
+ }
380
+ }
381
+ return;
382
+ }
383
+ if (token.text === ')' && indentParentActive && !this.isOnelineMode()) {
384
+ // Align closing parenthesis with the outer indentation level when nested groups expand.
385
+ const closingLevel = Math.max(level - 1, 0);
386
+ if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
387
+ this.linePrinter.appendNewline(closingLevel);
388
+ }
389
+ }
390
+ this.linePrinter.appendText(token.text);
391
+ }
392
+ handleOrOperatorToken(token, level, parentContainerType, caseContextDepth = 0) {
393
+ const text = this.applyKeywordCase(token.text);
394
+ // Leave OR untouched inside CASE branches to preserve inline evaluation order.
395
+ if (caseContextDepth > 0) {
396
+ this.linePrinter.appendText(text);
397
+ return;
398
+ }
399
+ if (this.orBreak === 'before') {
400
+ // Insert a newline before OR unless WITH full-oneline mode suppresses breaks.
401
+ if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
402
+ this.linePrinter.appendNewline(level);
403
+ }
404
+ this.linePrinter.appendText(text);
405
+ }
406
+ else if (this.orBreak === 'after') {
407
+ this.linePrinter.appendText(text);
408
+ // Break after OR when multi-line formatting is active.
409
+ if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
410
+ this.linePrinter.appendNewline(level);
411
+ }
412
+ }
413
+ else {
414
+ this.linePrinter.appendText(text);
415
+ }
416
+ }
417
+ /**
418
+ * Decide whether a parentheses group should increase indentation when inside nested structures.
419
+ * We only expand groups that contain further parentheses so simple comparisons stay compact.
420
+ */
421
+ shouldIndentNestedParentheses(token) {
422
+ if (!this.indentNestedParentheses) {
423
+ return false;
424
+ }
425
+ if (token.containerType !== SqlPrintToken_1.SqlPrintTokenContainerType.ParenExpression) {
426
+ return false;
427
+ }
428
+ // Look for nested parentheses containers. If present, indent to highlight grouping.
429
+ return token.innerTokens.some((child) => this.containsParenExpression(child));
430
+ }
431
+ /**
432
+ * Recursively inspect descendants to find additional parentheses groups.
433
+ * Helps detect complex boolean groups like ((A) OR (B) OR (C)).
434
+ */
435
+ containsParenExpression(token) {
436
+ if (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.ParenExpression) {
437
+ return true;
438
+ }
439
+ for (const child of token.innerTokens) {
440
+ if (this.containsParenExpression(child)) {
441
+ return true;
442
+ }
443
+ }
444
+ return false;
445
+ }
328
446
  handleJoinClauseToken(token, level) {
329
447
  const text = this.applyKeywordCase(token.text);
330
448
  // before join clause, add newline (skip when inside WITH clause with full-oneline style)
@@ -338,6 +456,9 @@ class SqlPrinter {
338
456
  * Skips spaces in CommentBlocks when in specific CTE modes to prevent duplication.
339
457
  */
340
458
  handleSpaceToken(token, parentContainerType) {
459
+ if (this.smartCommentBlockBuilder && this.smartCommentBlockBuilder.mode === 'line') {
460
+ this.flushSmartCommentBlockBuilder();
461
+ }
341
462
  if (this.shouldSkipCommentBlockSpace(parentContainerType)) {
342
463
  const currentLine = this.linePrinter.getCurrentLine();
343
464
  if (currentLine.text !== '' && !currentLine.text.endsWith(' ')) {
@@ -356,6 +477,337 @@ class SqlPrinter {
356
477
  this.insideWithClause &&
357
478
  this.withClauseStyle === 'full-oneline';
358
479
  }
480
+ printCommentToken(text, level, parentContainerType) {
481
+ const trimmed = text.trim();
482
+ if (!trimmed) {
483
+ return;
484
+ }
485
+ if (this.commentStyle === 'smart' && parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock) {
486
+ if (this.handleSmartCommentBlockToken(text, trimmed, level)) {
487
+ return;
488
+ }
489
+ }
490
+ if (this.commentStyle === 'smart') {
491
+ const normalized = this.normalizeCommentForSmart(trimmed);
492
+ if (normalized.lines.length > 1 || normalized.forceBlock) {
493
+ const blockText = this.buildBlockComment(normalized.lines, level);
494
+ this.linePrinter.appendText(blockText);
495
+ }
496
+ else {
497
+ const content = normalized.lines[0];
498
+ const lineText = content ? `-- ${content}` : '--';
499
+ if (parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock) {
500
+ this.linePrinter.appendText(lineText);
501
+ this.pendingLineCommentBreak = level;
502
+ }
503
+ else {
504
+ this.linePrinter.appendText(lineText);
505
+ this.linePrinter.appendNewline(level);
506
+ }
507
+ }
508
+ }
509
+ else {
510
+ if (trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
511
+ if (/\r?\n/.test(trimmed)) {
512
+ // Keep multi-line block comments intact by normalizing line endings once.
513
+ const newlineReplacement = this.isOnelineMode() ? ' ' : (typeof this.newline === 'string' ? this.newline : '\n');
514
+ const normalized = trimmed.replace(/\r?\n/g, newlineReplacement);
515
+ this.linePrinter.appendText(normalized);
516
+ }
517
+ else {
518
+ this.linePrinter.appendText(trimmed);
519
+ }
520
+ }
521
+ else {
522
+ this.linePrinter.appendText(trimmed);
523
+ }
524
+ if (trimmed.startsWith('--')) {
525
+ if (parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock) {
526
+ this.pendingLineCommentBreak = level;
527
+ }
528
+ else {
529
+ this.linePrinter.appendNewline(level);
530
+ }
531
+ }
532
+ }
533
+ }
534
+ handleSmartCommentBlockToken(raw, trimmed, level) {
535
+ if (!this.smartCommentBlockBuilder) {
536
+ if (trimmed === '/*') {
537
+ // Begin assembling a multi-line block comment that is emitted as split tokens
538
+ this.smartCommentBlockBuilder = { lines: [], level, mode: 'block' };
539
+ return true;
540
+ }
541
+ const lineContent = this.extractLineCommentContent(trimmed);
542
+ if (lineContent !== null) {
543
+ this.smartCommentBlockBuilder = {
544
+ lines: [lineContent],
545
+ level,
546
+ mode: 'line',
547
+ };
548
+ return true;
549
+ }
550
+ return false;
551
+ }
552
+ if (this.smartCommentBlockBuilder.mode === 'block') {
553
+ if (trimmed === '*/') {
554
+ const { lines, level: blockLevel } = this.smartCommentBlockBuilder;
555
+ const blockText = this.buildBlockComment(lines, blockLevel);
556
+ this.linePrinter.appendText(blockText);
557
+ this.pendingLineCommentBreak = blockLevel;
558
+ this.smartCommentBlockBuilder = null;
559
+ return true;
560
+ }
561
+ this.smartCommentBlockBuilder.lines.push(this.normalizeSmartBlockLine(raw));
562
+ return true;
563
+ }
564
+ const content = this.extractLineCommentContent(trimmed);
565
+ if (content !== null) {
566
+ this.smartCommentBlockBuilder.lines.push(content);
567
+ return true;
568
+ }
569
+ this.flushSmartCommentBlockBuilder();
570
+ return false;
571
+ }
572
+ handleCommentBlockContainer(token, level) {
573
+ var _a;
574
+ if (!this.exportComment) {
575
+ return;
576
+ }
577
+ if (this.commentStyle !== 'smart') {
578
+ const rawLines = this.extractRawCommentBlockLines(token);
579
+ if (rawLines.length > 0) {
580
+ const normalizedBlocks = rawLines.map(line => `/* ${line} */`).join(' ');
581
+ const hasTrailingSpace = (_a = token.innerTokens) === null || _a === void 0 ? void 0 : _a.some(child => child.type === SqlPrintToken_1.SqlPrintTokenType.space && child.text.includes(' '));
582
+ this.linePrinter.appendText(hasTrailingSpace ? `${normalizedBlocks} ` : normalizedBlocks);
583
+ return;
584
+ }
585
+ for (const child of token.innerTokens) {
586
+ this.appendToken(child, level, token.containerType, 0, false);
587
+ }
588
+ return;
589
+ }
590
+ const lines = this.collectCommentBlockLines(token);
591
+ if (lines.length === 0 && !this.smartCommentBlockBuilder) {
592
+ // No meaningful content; treat as empty line comment to preserve spacing
593
+ this.smartCommentBlockBuilder = {
594
+ lines: [''],
595
+ level,
596
+ mode: 'line',
597
+ };
598
+ return;
599
+ }
600
+ if (!this.smartCommentBlockBuilder || this.smartCommentBlockBuilder.mode !== 'line') {
601
+ this.smartCommentBlockBuilder = {
602
+ lines: [...lines],
603
+ level,
604
+ mode: 'line',
605
+ };
606
+ }
607
+ else {
608
+ this.smartCommentBlockBuilder.lines.push(...lines);
609
+ }
610
+ }
611
+ normalizeSmartBlockLine(raw) {
612
+ // Remove trailing whitespace that only carries formatting artifacts
613
+ let line = raw.replace(/\s+$/g, '');
614
+ if (!line) {
615
+ return '';
616
+ }
617
+ if (line.startsWith(' ')) {
618
+ line = line.slice(2);
619
+ }
620
+ if (line.startsWith('* ')) {
621
+ return line.slice(2);
622
+ }
623
+ if (line === '*') {
624
+ return '';
625
+ }
626
+ if (line.startsWith('*')) {
627
+ return line.slice(1);
628
+ }
629
+ return line;
630
+ }
631
+ extractLineCommentContent(trimmed) {
632
+ if (trimmed.startsWith('--')) {
633
+ return trimmed.slice(2).trimStart();
634
+ }
635
+ if (trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
636
+ const inner = trimmed.slice(2, -2).trim();
637
+ return inner;
638
+ }
639
+ return null;
640
+ }
641
+ flushSmartCommentBlockBuilder() {
642
+ var _a;
643
+ if (!this.smartCommentBlockBuilder) {
644
+ return;
645
+ }
646
+ const { lines, level, mode } = this.smartCommentBlockBuilder;
647
+ if (mode === 'line') {
648
+ if (lines.length > 1) {
649
+ const blockText = this.buildBlockComment(lines, level);
650
+ this.linePrinter.appendText(blockText);
651
+ }
652
+ else {
653
+ const content = (_a = lines[0]) !== null && _a !== void 0 ? _a : '';
654
+ const lineText = content ? `-- ${content}` : '--';
655
+ this.linePrinter.appendText(lineText);
656
+ }
657
+ if (!this.isOnelineMode()) {
658
+ this.linePrinter.appendNewline(level);
659
+ }
660
+ this.pendingLineCommentBreak = null;
661
+ }
662
+ this.smartCommentBlockBuilder = null;
663
+ }
664
+ collectCommentBlockLines(token) {
665
+ var _a;
666
+ const lines = [];
667
+ let collectingBlock = false;
668
+ for (const child of (_a = token.innerTokens) !== null && _a !== void 0 ? _a : []) {
669
+ if (child.type === SqlPrintToken_1.SqlPrintTokenType.comment) {
670
+ const trimmed = child.text.trim();
671
+ if (trimmed === '/*') {
672
+ collectingBlock = true;
673
+ continue;
674
+ }
675
+ if (trimmed === '*/') {
676
+ collectingBlock = false;
677
+ continue;
678
+ }
679
+ if (collectingBlock) {
680
+ lines.push(this.normalizeSmartBlockLine(child.text));
681
+ continue;
682
+ }
683
+ const content = this.extractLineCommentContent(trimmed);
684
+ if (content !== null) {
685
+ lines.push(content);
686
+ }
687
+ }
688
+ }
689
+ return lines;
690
+ }
691
+ extractRawCommentBlockLines(token) {
692
+ var _a;
693
+ const lines = [];
694
+ let collectingBlock = false;
695
+ for (const child of (_a = token.innerTokens) !== null && _a !== void 0 ? _a : []) {
696
+ if (child.type === SqlPrintToken_1.SqlPrintTokenType.comment) {
697
+ const text = child.text;
698
+ const trimmed = text.trim();
699
+ if (trimmed === '/*') {
700
+ collectingBlock = true;
701
+ continue;
702
+ }
703
+ if (trimmed === '*/') {
704
+ collectingBlock = false;
705
+ continue;
706
+ }
707
+ if (collectingBlock) {
708
+ if (trimmed.length > 0) {
709
+ lines.push(trimmed);
710
+ }
711
+ continue;
712
+ }
713
+ }
714
+ }
715
+ return lines;
716
+ }
717
+ normalizeCommentForSmart(text) {
718
+ const trimmed = text.trim();
719
+ let source = trimmed;
720
+ let forceBlock = false;
721
+ if (trimmed.startsWith('--')) {
722
+ source = trimmed.slice(2);
723
+ }
724
+ else if (trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
725
+ const inner = trimmed.slice(2, -2);
726
+ const normalizedInner = inner.replace(/\r?\n/g, '\n');
727
+ if (normalizedInner.includes('\n')) {
728
+ forceBlock = true;
729
+ source = inner;
730
+ }
731
+ else {
732
+ source = inner;
733
+ if (!source.trim()) {
734
+ source = trimmed;
735
+ }
736
+ }
737
+ }
738
+ const escaped = this.escapeCommentDelimiters(source);
739
+ const normalized = escaped.replace(/\r?\n/g, '\n');
740
+ const rawSegments = normalized.split('\n');
741
+ const processedLines = [];
742
+ const processedRaw = [];
743
+ for (const segment of rawSegments) {
744
+ const rawTrimmed = segment.trim();
745
+ const sanitized = this.sanitizeCommentLine(segment);
746
+ if (sanitized.length > 0) {
747
+ processedLines.push(sanitized);
748
+ processedRaw.push(rawTrimmed);
749
+ }
750
+ }
751
+ let lines = processedLines;
752
+ if (lines.length === 0) {
753
+ lines = [''];
754
+ }
755
+ if (!forceBlock && lines.length === 1 && !lines[0] && trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
756
+ const escapedFull = this.escapeCommentDelimiters(trimmed);
757
+ lines = [this.sanitizeCommentLine(escapedFull)];
758
+ }
759
+ if (!forceBlock && lines.length > 1) {
760
+ forceBlock = true;
761
+ }
762
+ lines = lines.map((line, index) => {
763
+ var _a;
764
+ if (/^[-=_+*#]+$/.test(line)) {
765
+ const rawLine = (_a = processedRaw[index]) !== null && _a !== void 0 ? _a : line;
766
+ const normalizedRaw = rawLine.replace(/\s+/g, '');
767
+ if (normalizedRaw.length >= line.length) {
768
+ return normalizedRaw;
769
+ }
770
+ }
771
+ return line;
772
+ });
773
+ return { lines, forceBlock };
774
+ }
775
+ buildBlockComment(lines, level) {
776
+ var _a, _b, _c;
777
+ if (lines.length <= 1) {
778
+ const content = (_a = lines[0]) !== null && _a !== void 0 ? _a : '';
779
+ return content ? `/* ${content} */` : '/* */';
780
+ }
781
+ const newline = this.newline === ' ' ? '\n' : this.newline;
782
+ const currentLevel = (_c = (_b = this.linePrinter.getCurrentLine()) === null || _b === void 0 ? void 0 : _b.level) !== null && _c !== void 0 ? _c : level;
783
+ const baseIndent = this.getIndentString(currentLevel);
784
+ const unitIndent = ' ';
785
+ const innerIndent = baseIndent + unitIndent;
786
+ const body = lines.map(line => `${innerIndent}${line}`).join(newline);
787
+ const closing = `${baseIndent}*/`;
788
+ return `/*${newline}${body}${newline}${closing}`;
789
+ }
790
+ getIndentString(level) {
791
+ if (level <= 0) {
792
+ return '';
793
+ }
794
+ if (this.indentSize <= 0) {
795
+ return ' '.repeat(level);
796
+ }
797
+ const unit = typeof this.indentChar === 'string' ? this.indentChar : '';
798
+ return unit.repeat(this.indentSize * level);
799
+ }
800
+ sanitizeCommentLine(content) {
801
+ let sanitized = content;
802
+ sanitized = sanitized.replace(/\u2028|\u2029/g, ' ');
803
+ sanitized = sanitized.replace(/\s+/g, ' ').trim();
804
+ return sanitized;
805
+ }
806
+ escapeCommentDelimiters(content) {
807
+ return content
808
+ .replace(/\/\*/g, '\\/\\*')
809
+ .replace(/\*\//g, '*\\/');
810
+ }
359
811
  /**
360
812
  * Handles commentNewline tokens with conditional newline behavior.
361
813
  * In multiline mode (newline !== ' '), adds a newline after comments.
@@ -363,6 +815,14 @@ class SqlPrinter {
363
815
  * Skips newlines in CTE modes (full-oneline, cte-oneline) to maintain one-line format.
364
816
  */
365
817
  handleCommentNewlineToken(token, level) {
818
+ if (this.smartCommentBlockBuilder) {
819
+ return;
820
+ }
821
+ if (this.pendingLineCommentBreak !== null) {
822
+ this.linePrinter.appendNewline(this.pendingLineCommentBreak);
823
+ this.pendingLineCommentBreak = null;
824
+ return;
825
+ }
366
826
  if (this.shouldSkipCommentNewline()) {
367
827
  return;
368
828
  }
@@ -408,10 +868,11 @@ class SqlPrinter {
408
868
  cteCommaBreak: this.cteCommaBreak,
409
869
  valuesCommaBreak: this.valuesCommaBreak,
410
870
  andBreak: this.andBreak,
871
+ orBreak: this.orBreak,
411
872
  keywordCase: this.keywordCase,
412
873
  exportComment: false,
413
- strictCommentPlacement: this.strictCommentPlacement,
414
874
  withClauseStyle: 'standard', // Prevent recursive processing
875
+ indentNestedParentheses: false,
415
876
  });
416
877
  }
417
878
  /**
@@ -437,10 +898,10 @@ class SqlPrinter {
437
898
  commaBreak: 'none', // Disable comma-based line breaks
438
899
  cteCommaBreak: this.cteCommaBreak,
439
900
  valuesCommaBreak: 'none',
440
- andBreak: 'none', // Disable AND/OR-based line breaks
901
+ andBreak: 'none', // Disable AND-based line breaks
902
+ orBreak: 'none', // Disable OR-based line breaks
441
903
  keywordCase: this.keywordCase,
442
904
  exportComment: this.exportComment,
443
- strictCommentPlacement: this.strictCommentPlacement,
444
905
  withClauseStyle: 'standard',
445
906
  parenthesesOneLine: false, // Prevent recursive processing (avoid infinite loops)
446
907
  betweenOneLine: false, // Prevent recursive processing (avoid infinite loops)
@@ -448,6 +909,7 @@ class SqlPrinter {
448
909
  joinOneLine: false, // Prevent recursive processing (avoid infinite loops)
449
910
  caseOneLine: false, // Prevent recursive processing (avoid infinite loops)
450
911
  subqueryOneLine: false, // Prevent recursive processing (avoid infinite loops)
912
+ indentNestedParentheses: false,
451
913
  });
452
914
  }
453
915
  /**