You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/src/utils/CodeBuilder.ts

164 lines
3.5 KiB

import repeat from './repeat';
enum ChunkType {
Line,
Block
}
interface Condition {
condition: string;
used: boolean;
}
export default class CodeBuilder {
result: string;
first: ChunkType;
last: ChunkType;
lastCondition: string;
conditionStack: Condition[];
indent: string;
constructor(str = '') {
this.result = str;
const initial = str
? /\n/.test(str) ? ChunkType.Block : ChunkType.Line
: null;
this.first = initial;
this.last = initial;
this.lastCondition = null;
this.conditionStack = [];
this.indent = '';
}
addConditional(condition: string, body: string) {
this.reifyConditions();
body = body.replace(/^/gm, `${this.indent}\t`);
if (condition === this.lastCondition) {
this.result += `\n${body}`;
} else {
if (this.lastCondition) {
this.result += `\n${this.indent}}`;
}
this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}${this.indent}if ( ${condition} ) {\n${body}`;
this.lastCondition = condition;
}
this.last = ChunkType.Block;
}
addLine(line: string) {
this.reifyConditions();
if (this.lastCondition) {
this.result += `\n${this.indent}}`;
this.lastCondition = null;
}
if (this.last === ChunkType.Block) {
this.result += `\n\n${this.indent}${line}`;
} else if (this.last === ChunkType.Line) {
this.result += `\n${this.indent}${line}`;
} else {
this.result += line;
}
this.last = ChunkType.Line;
if (!this.first) this.first = ChunkType.Line;
}
addLineAtStart(line: string) {
this.reifyConditions();
if (this.first === ChunkType.Block) {
this.result = `${line}\n\n${this.indent}${this.result}`;
} else if (this.first === ChunkType.Line) {
this.result = `${line}\n${this.indent}${this.result}`;
} else {
this.result += line;
}
this.first = ChunkType.Line;
if (!this.last) this.last = ChunkType.Line;
}
addBlock(block: string) {
this.reifyConditions();
if (this.indent) block = block.replace(/^/gm, `${this.indent}`);
if (this.lastCondition) {
this.result += `\n${this.indent}}`;
this.lastCondition = null;
}
if (this.result) {
this.result += `\n\n${this.indent}${block}`;
} else {
this.result += block;
}
this.last = ChunkType.Block;
if (!this.first) this.first = ChunkType.Block;
}
addBlockAtStart(block: string) {
this.reifyConditions();
if (this.result) {
this.result = `${block}\n\n${this.indent}${this.result}`;
} else {
this.result += block;
}
this.first = ChunkType.Block;
if (!this.last) this.last = ChunkType.Block;
}
isEmpty() {
return this.result === '';
}
pushCondition(condition: string) {
this.conditionStack.push({ condition, used: false });
}
popCondition() {
const { used } = this.conditionStack.pop();
this.indent = repeat('\t', this.conditionStack.length);
if (used) this.addLine('}');
}
reifyConditions() {
for (let i = 0; i < this.conditionStack.length; i += 1) {
const condition = this.conditionStack[i];
if (!condition.used) {
const line = `if (${condition.condition}) {`;
if (this.last === ChunkType.Block) {
this.result += `\n\n${this.indent}${line}`;
} else if (this.last === ChunkType.Line) {
this.result += `\n${this.indent}${line}`;
} else {
this.result += line;
}
this.last = ChunkType.Line;
if (!this.first) this.first = ChunkType.Line;
this.indent = repeat('\t', this.conditionStack.length);
condition.used = true;
}
}
}
toString() {
return this.result.trim() + (this.lastCondition ? `\n}` : ``);
}
}