Lab
Decorator
interface TextBlock {
render(): string[];
}
// The source: the diagnostic lines themselves.
function plainText(lines: string[]): TextBlock {
return { render: () => [...lines] };
}
// Numbers: the same interface, plus a prefix on every line it gets back.
function withNumbers(inner: TextBlock): TextBlock {
return {
render() {
const lines = inner.render();
return lines.map((line, i) => `${i + 1}: ${line}`);
},
};
}
// Frame: the same interface, plus a border around the lines it gets back.
function withFrame(inner: TextBlock): TextBlock {
return {
render() {
const lines = inner.render();
const width = Math.max(...lines.map((line) => line.length));
const edge = `+${'-'.repeat(width + 2)}+`;
return [edge, ...lines.map((line) => `| ${line.padEnd(width)} |`), edge];
},
};
}
// The command renders any TextBlock and never asks which layers it has.
function display(name: string, block: TextBlock) {
const shown = block.render();
console.log(`${name}:\n${shown.join('\n')}`);
}
const source = plainText(['check: links', 'broken: 2']);
const terminal = withNumbers(source);
const report = withFrame(withNumbers(source));
display('terminal', terminal);
display('report', report);
TODO
Visual to come