118 lines
3.7 KiB
JavaScript
118 lines
3.7 KiB
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
|