inline-sql-toolkit 0.4.11 → 0.4.12

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.12 - 2026-09-24
4
+
5
+ - Feature: added the `inlineSql.format.keepFunctionsInline` setting (default
6
+ `false`). `sql-formatter` has no option that holds function arguments on
7
+ one line — it breaks `CASE` structurally regardless of `wrapAfter` — so the
8
+ extension re-joins the line breaks the engine inserts inside `word(...)`
9
+ groups as a post-pass over its output. With the setting on,
10
+ `COUNT(CASE WHEN a THEN 1 ELSE 0 END)` stays on a single line while select
11
+ lists, clause breaks, and `AND` / `OR` chains keep their usual layout.
12
+ - The same choice is exposed everywhere the other options are: the VS Code
13
+ setting, the CLI flag `--keep-functions-inline`, and
14
+ `"keepFunctionsInline"` in `.inline-sql.json`, under the unchanged CLI
15
+ flags > configuration file > defaults precedence.
16
+ - Safety: only newlines in code state are removed. A newline inside a string
17
+ literal, a `$$ … $$` body, or a block comment is copied verbatim, and the
18
+ newline that terminates a `-- line comment` is kept, so literal content can
19
+ never change and no code can fall into a comment. The default `false`
20
+ reproduces the previous output byte for byte, and the fixed-point loop still
21
+ skips any candidate whose formatting does not converge.
22
+
3
23
  ## 0.4.11 - 2026-09-24
4
24
 
5
25
  - Feature: added the `inlineSql.format.commaPosition` setting (`after` |
package/README.md CHANGED
@@ -113,6 +113,10 @@ later atomic precondition.
113
113
  - `inlineSql.format.commaPosition`: `after` (default) keeps a wrapping comma at
114
114
  the end of the previous line; `before` moves it to the start of the next
115
115
  line.
116
+ - `inlineSql.format.keepFunctionsInline`: re-join the formatter's line breaks
117
+ inside `word(...)` groups so `SUM(...)`, `COUNT(CASE ... END)`, and nested
118
+ calls stay on one line (default `false`). Newlines inside string literals and
119
+ comments are never removed.
116
120
 
117
121
  The extension highlights inline SQL with an injected TextMate grammar: SQL
118
122
  strings that start with `-- sql` (or a leading SQL keyword) are embedded as
@@ -148,6 +152,7 @@ When run without file arguments, the CLI reads Python source from standard input
148
152
  | `--no-space-around-operators` | Keep dense operators | spaced |
149
153
  | `--no-ordinals` | Do not replace `GROUP BY` / `ORDER BY` ordinals with column names | replace |
150
154
  | `--comma-position <pos>` | Where a wrapping comma sits: `after` or `before` | `after` |
155
+ | `--keep-functions-inline` | Keep `SUM(...)` / `COUNT(CASE ... END)` on one line | off |
151
156
  | `-c, --config <file>` | Configuration JSON file | Nearest `.inline-sql.json` |
152
157
  | `-h, --help` | Show usage help | |
153
158
  | `--version` | Show version number | |
@@ -167,7 +172,8 @@ The CLI automatically searches for a `.inline-sql.json` file in the current work
167
172
  "useSpaceAroundOperators": true,
168
173
  "replaceOrdinals": true,
169
174
  "dialect": "postgresql",
170
- "commaPosition": "after"
175
+ "commaPosition": "after",
176
+ "keepFunctionsInline": false
171
177
  }
172
178
  }
173
179
  ```
package/dist/cli.js CHANGED
@@ -495,7 +495,8 @@ function resolveFormatOptions(raw) {
495
495
  const replaceOrdinals2 = raw.replaceOrdinals === void 0 ? true : raw.replaceOrdinals;
496
496
  const dialect = raw.dialect === void 0 ? "postgresql" : raw.dialect;
497
497
  const commaPosition = raw.commaPosition === void 0 ? "after" : raw.commaPosition;
498
- if (keywordCase !== "upper" && keywordCase !== "lower" && keywordCase !== "preserve" || !integerBetween(indentWidth, 1, 8) || !integerBetween(wrapAfter, 20, 500) || typeof useSpaceAroundOperators !== "boolean" || typeof replaceOrdinals2 !== "boolean" || dialect !== "sql" && dialect !== "mysql" && dialect !== "postgresql" && dialect !== "sqlite" || commaPosition !== "after" && commaPosition !== "before") {
498
+ const keepFunctionsInline = raw.keepFunctionsInline === void 0 ? false : raw.keepFunctionsInline;
499
+ if (keywordCase !== "upper" && keywordCase !== "lower" && keywordCase !== "preserve" || !integerBetween(indentWidth, 1, 8) || !integerBetween(wrapAfter, 20, 500) || typeof useSpaceAroundOperators !== "boolean" || typeof replaceOrdinals2 !== "boolean" || dialect !== "sql" && dialect !== "mysql" && dialect !== "postgresql" && dialect !== "sqlite" || commaPosition !== "after" && commaPosition !== "before" || typeof keepFunctionsInline !== "boolean") {
499
500
  return { ok: false, reason: "INVALID_CONFIGURATION" };
500
501
  }
501
502
  return {
@@ -507,7 +508,8 @@ function resolveFormatOptions(raw) {
507
508
  useSpaceAroundOperators,
508
509
  replaceOrdinals: replaceOrdinals2,
509
510
  dialect,
510
- commaPosition
511
+ commaPosition,
512
+ keepFunctionsInline
511
513
  }
512
514
  };
513
515
  }
@@ -1618,6 +1620,112 @@ function moveCommasToLineStarts(text) {
1618
1620
  }
1619
1621
  return lines.join("\n");
1620
1622
  }
1623
+ var DOLLAR_QUOTE = /\$[A-Za-z_][A-Za-z0-9_]*\$|\$\$/y;
1624
+ function rejoinFunctionCalls(text) {
1625
+ const stack = [];
1626
+ let out = "";
1627
+ let i = 0;
1628
+ const at = (index) => text.charAt(index);
1629
+ const isCallOpener = () => {
1630
+ const match = /[A-Za-z_][A-Za-z0-9_]*\s*$/.exec(out);
1631
+ if (match === null) return false;
1632
+ const before = out.slice(0, match.index);
1633
+ return before === "" || !/[A-Za-z0-9_]$/.test(before);
1634
+ };
1635
+ while (i < text.length) {
1636
+ const ch = at(i);
1637
+ if (ch === "'" || ch === '"' || ch === "`") {
1638
+ const quote = ch;
1639
+ out += ch;
1640
+ i += 1;
1641
+ while (i < text.length) {
1642
+ if (at(i) === quote && at(i + 1) === quote) {
1643
+ out += at(i) + at(i + 1);
1644
+ i += 2;
1645
+ continue;
1646
+ }
1647
+ out += at(i);
1648
+ i += 1;
1649
+ if (at(i - 1) === quote) break;
1650
+ if (at(i - 1) === "\\" && quote !== "`" && i < text.length) {
1651
+ out += at(i);
1652
+ i += 1;
1653
+ }
1654
+ }
1655
+ continue;
1656
+ }
1657
+ if (ch === "$") {
1658
+ DOLLAR_QUOTE.lastIndex = i;
1659
+ const dollar = DOLLAR_QUOTE.exec(text);
1660
+ if (dollar !== null) {
1661
+ const end = text.indexOf(dollar[0], i + dollar[0].length);
1662
+ const stop = end === -1 ? text.length : end + dollar[0].length;
1663
+ out += text.slice(i, stop);
1664
+ i = stop;
1665
+ continue;
1666
+ }
1667
+ }
1668
+ if (ch === "-" && at(i + 1) === "-" || ch === "#") {
1669
+ while (i < text.length && at(i) !== "\n") {
1670
+ out += at(i);
1671
+ i += 1;
1672
+ }
1673
+ if (i < text.length) {
1674
+ out += at(i);
1675
+ i += 1;
1676
+ }
1677
+ continue;
1678
+ }
1679
+ if (ch === "/" && at(i + 1) === "*") {
1680
+ out += "/*";
1681
+ i += 2;
1682
+ while (i < text.length && !(at(i) === "*" && at(i + 1) === "/")) {
1683
+ out += at(i);
1684
+ i += 1;
1685
+ }
1686
+ if (i < text.length) {
1687
+ out += "*/";
1688
+ i += 2;
1689
+ }
1690
+ continue;
1691
+ }
1692
+ if (ch === "\n") {
1693
+ if (stack.includes(true)) {
1694
+ let indent = i + 1;
1695
+ while (indent < text.length && (at(indent) === " " || at(indent) === " ")) {
1696
+ indent += 1;
1697
+ }
1698
+ let peek = indent;
1699
+ while (peek < text.length && (at(peek) === "\n" || at(peek) === " " || at(peek) === " ")) {
1700
+ peek += 1;
1701
+ }
1702
+ const next = at(peek);
1703
+ const prev = out.slice(-1);
1704
+ i = indent;
1705
+ if (prev !== "(" && next !== "," && next !== ")") out += " ";
1706
+ } else {
1707
+ out += ch;
1708
+ i += 1;
1709
+ }
1710
+ continue;
1711
+ }
1712
+ if (ch === "(") {
1713
+ stack.push(isCallOpener());
1714
+ out += ch;
1715
+ i += 1;
1716
+ continue;
1717
+ }
1718
+ if (ch === ")") {
1719
+ stack.pop();
1720
+ out += ch;
1721
+ i += 1;
1722
+ continue;
1723
+ }
1724
+ out += ch;
1725
+ i += 1;
1726
+ }
1727
+ return out;
1728
+ }
1621
1729
  function formatOnce(analysis, literal, detection, options, nonce, sqlFormatter) {
1622
1730
  const plan = buildProtectionPlan(analysis.sourceMap, literal, detection, nonce);
1623
1731
  let formatted = sqlFormatter(plan.protectedSql, {
@@ -1632,6 +1740,9 @@ function formatOnce(analysis, literal, detection, options, nonce, sqlFormatter)
1632
1740
  }
1633
1741
  formatted = breakTrailingFieldMarkers(formatted);
1634
1742
  formatted = moveCommasBeforeLineComments(formatted);
1743
+ if (options.keepFunctionsInline) {
1744
+ formatted = rejoinFunctionCalls(formatted);
1745
+ }
1635
1746
  if (options.commaPosition === "before") {
1636
1747
  formatted = moveCommasToLineStarts(formatted);
1637
1748
  }
@@ -1861,7 +1972,7 @@ function formatDocument(source, options, target, nonce, sqlFormatter, logger) {
1861
1972
  };
1862
1973
  if (logger !== void 0) {
1863
1974
  logger(
1864
- `format: dialect=${options.dialect} keywordCase=${options.keywordCase} indentWidth=${options.indentWidth} wrapAfter=${options.wrapAfter} useSpaceAroundOperators=${options.useSpaceAroundOperators} replaceOrdinals=${options.replaceOrdinals} commaPosition=${options.commaPosition} discovered=${summary.discovered} selected=${summary.selected} changed=${summary.changed} unchanged=${summary.unchanged} skipped=${summary.skipped}${skipReasons.length > 0 ? ` reasons=[${skipReasons.join(", ")}]` : ""}`
1975
+ `format: dialect=${options.dialect} keywordCase=${options.keywordCase} indentWidth=${options.indentWidth} wrapAfter=${options.wrapAfter} useSpaceAroundOperators=${options.useSpaceAroundOperators} replaceOrdinals=${options.replaceOrdinals} commaPosition=${options.commaPosition} keepFunctionsInline=${options.keepFunctionsInline} discovered=${summary.discovered} selected=${summary.selected} changed=${summary.changed} unchanged=${summary.unchanged} skipped=${summary.skipped}${skipReasons.length > 0 ? ` reasons=[${skipReasons.join(", ")}]` : ""}`
1865
1976
  );
1866
1977
  }
1867
1978
  return {
@@ -22514,6 +22625,7 @@ var USAGE = `Usage: inline-sql-toolkit [options] [files...]
22514
22625
  --no-space-around-operators keep dense operators (default: spaced)
22515
22626
  --no-ordinals do not replace GROUP BY / ORDER BY ordinals
22516
22627
  --comma-position <pos> after | before (default: after)
22628
+ --keep-functions-inline keep SUM(...) / COUNT(CASE ...) on one line
22517
22629
  -c, --config <file> config JSON (default: nearest .inline-sql.json)
22518
22630
  -h, --help / --version`;
22519
22631
  function printError(message) {
@@ -22573,7 +22685,8 @@ function buildRawOptions(fileOptions, cliValues) {
22573
22685
  wrapAfter: cliValues["wrap-after"] !== void 0 ? Number(cliValues["wrap-after"]) : fileOptions.wrapAfter,
22574
22686
  useSpaceAroundOperators: cliValues["no-space-around-operators"] ? false : fileOptions.useSpaceAroundOperators,
22575
22687
  replaceOrdinals: cliValues["no-ordinals"] ? false : fileOptions.replaceOrdinals,
22576
- commaPosition: cliValues["comma-position"] ?? fileOptions.commaPosition
22688
+ commaPosition: cliValues["comma-position"] ?? fileOptions.commaPosition,
22689
+ keepFunctionsInline: cliValues["keep-functions-inline"] ? true : fileOptions.keepFunctionsInline
22577
22690
  };
22578
22691
  }
22579
22692
  function formatPythonSource(text, options, logger) {
@@ -22610,6 +22723,7 @@ function runCli(argv) {
22610
22723
  "no-space-around-operators": { type: "boolean", default: false },
22611
22724
  "no-ordinals": { type: "boolean", default: false },
22612
22725
  "comma-position": { type: "string" },
22726
+ "keep-functions-inline": { type: "boolean", default: false },
22613
22727
  config: { type: "string", short: "c" },
22614
22728
  help: { type: "boolean", short: "h", default: false },
22615
22729
  version: { type: "boolean", default: false }
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "bugs": {
12
12
  "url": "https://github.com/hidenobunagai/inline-sql-toolkit/issues"
13
13
  },
14
- "version": "0.4.11",
14
+ "version": "0.4.12",
15
15
  "icon": "icon.png",
16
16
  "type": "module",
17
17
  "bin": {
@@ -114,6 +114,12 @@
114
114
  "default": "after",
115
115
  "scope": "resource",
116
116
  "description": "%configuration.format.commaPosition.description%"
117
+ },
118
+ "inlineSql.format.keepFunctionsInline": {
119
+ "type": "boolean",
120
+ "default": false,
121
+ "scope": "resource",
122
+ "description": "%configuration.format.keepFunctionsInline.description%"
117
123
  }
118
124
  }
119
125
  },