I need output to be:
<p>123<span>321</span></p>
But now that's:
<span>321</span><p>123<span>321</span></p>
What is the best option to start execute p() and then span() inside it?
class Templater {
constructor() {
this.output = '';
}
span(...tags) {
const transform = tags => tags.join('');
this.output += `<span>${transform(tags)}</span>`
return this;
}
p(...tags) {
const transform = tags => tags.join('');
this.output += `<p>${transform(tags)}</p>`
return this;
}
toString() {
return this.output;
}
}
const template = new Templater();
console.log(template.p('123', template.span('321')).toString());
The easiest is to just skip the whole this.output
thing altogether and just trust the call stack.
class Templater {
_transform(tags) {
return tags.join("");
}
span(...tags) {
return `<span>${this._transform(tags)}</span>`;
}
p(...tags) {
return `<p>${this._transform(tags)}</p>`;
}
}
const template = new Templater();
console.log(template.p('123', template.span('321')).toString());
Another option is to construct a tree of objects that know how to render themselves into a string:
class Tag {
constructor(tag, children) {
this.tag = tag;
this.children = children;
}
toString() {
const children = this.children.map(c => c.toString()).join("");
return `<${this.tag}>${children}</${this.tag}>`;
}
}
class Templater {
span(...children) {
return new Tag('span', children);
}
p(...children) {
return new Tag('p', children);
}
}
const template = new Templater();
console.log(template.p('123', template.span('321')).toString());