sql-formatter
Version:
Format whitespace in a SQL query to make it more readable
118 lines • 3.77 kB
JavaScript
import { last } from '../utils.js';
/** Whitespace modifiers to be used with add() method */
export var WS;
(function (WS) {
WS[WS["SPACE"] = 0] = "SPACE";
WS[WS["NO_SPACE"] = 1] = "NO_SPACE";
WS[WS["NO_NEWLINE"] = 2] = "NO_NEWLINE";
WS[WS["NEWLINE"] = 3] = "NEWLINE";
WS[WS["MANDATORY_NEWLINE"] = 4] = "MANDATORY_NEWLINE";
WS[WS["INDENT"] = 5] = "INDENT";
WS[WS["SINGLE_INDENT"] = 6] = "SINGLE_INDENT";
})(WS = WS || (WS = {}));
/**
* API for constructing SQL string (especially the whitespace part).
*
* It hides the internal implementation.
* Originally it used plain string concatenation, which was expensive.
* Now it's storing items to array and builds the string only in the end.
*/
export default class Layout {
constructor(indentation) {
this.indentation = indentation;
this.items = [];
}
/**
* Appends token strings and whitespace modifications to SQL string.
*/
add(...items) {
for (const item of items) {
switch (item) {
case WS.SPACE:
this.items.push(WS.SPACE);
break;
case WS.NO_SPACE:
this.trimHorizontalWhitespace();
break;
case WS.NO_NEWLINE:
this.trimWhitespace();
break;
case WS.NEWLINE:
this.trimHorizontalWhitespace();
this.addNewline(WS.NEWLINE);
break;
case WS.MANDATORY_NEWLINE:
this.trimHorizontalWhitespace();
this.addNewline(WS.MANDATORY_NEWLINE);
break;
case WS.INDENT:
this.addIndentation();
break;
case WS.SINGLE_INDENT:
this.items.push(WS.SINGLE_INDENT);
break;
default:
this.items.push(item);
}
}
}
trimHorizontalWhitespace() {
while (isHorizontalWhitespace(last(this.items))) {
this.items.pop();
}
}
trimWhitespace() {
while (isRemovableWhitespace(last(this.items))) {
this.items.pop();
}
}
addNewline(newline) {
if (this.items.length > 0) {
switch (last(this.items)) {
case WS.NEWLINE:
this.items.pop();
this.items.push(newline);
break;
case WS.MANDATORY_NEWLINE:
// keep as is
break;
default:
this.items.push(newline);
break;
}
}
}
addIndentation() {
for (let i = 0; i < this.indentation.getLevel(); i++) {
this.items.push(WS.SINGLE_INDENT);
}
}
/**
* Returns the final SQL string.
*/
toString() {
return this.items.map(item => this.itemToString(item)).join('');
}
/**
* Returns the internal layout data
*/
getLayoutItems() {
return this.items;
}
itemToString(item) {
switch (item) {
case WS.SPACE:
return ' ';
case WS.NEWLINE:
case WS.MANDATORY_NEWLINE:
return '\n';
case WS.SINGLE_INDENT:
return this.indentation.getSingleIndent();
default:
return item;
}
}
}
const isHorizontalWhitespace = (item) => item === WS.SPACE || item === WS.SINGLE_INDENT;
const isRemovableWhitespace = (item) => item === WS.SPACE || item === WS.SINGLE_INDENT || item === WS.NEWLINE;
//# sourceMappingURL=Layout.js.map