Ahhhh you're doing it all wrong!!!

yeah
This commit is contained in:
gnuxie
2023-01-14 18:33:06 +00:00
parent d3e54440b2
commit da94b8d4bc
2 changed files with 58 additions and 28 deletions
@@ -11,17 +11,26 @@ import { DocumentNode, FringeInnerRenderFunction, FringeLeafRenderFunction, Frin
// that renders the node twice.
// The first thing to get full we stop.
// this is possible if we make an iterator that just renders 1 node at a time
export class TransactionalOutputStream {
export class PagedOutputStream {
private buffer: string = '';
public output: string = '';
private pages: string[] = ['']
private lastCommittedNode?: DocumentNode;
constructor(
public readonly sizeLimit = 20_000,
) {
}
public writeString(string: string): TransactionalOutputStream {
private get currentPage(): string {
return this.pages.at(this.pages.length - 1)!;
}
private appendToCurrentPage(string: string) {
const currentIndex = this.pages.length - 1;
this.pages[currentIndex] = this.pages[currentIndex] + string;
}
public writeString(string: string): PagedOutputStream {
this.buffer += string;
return this;
}
@@ -30,34 +39,41 @@ export class TransactionalOutputStream {
return this.buffer.length;
}
private adjust(source: string, target: string): void {
if (source.at(-2) === '\n' && source.at(-1) === '\n') return;
if (source.at(-1) === '\n') {
target += '\n';
return;
public getPages(): string[] {
if (this.buffer.length !== 0) {
throw new TypeError('Stream has uncommitted buffered output');
}
target += '\n\n';
return [...this.pages]
}
public adjustForNextElement(): void {
this.adjust(this.buffer, this.buffer)
public isPageAndBufferOverSize(): boolean {
return (this.currentPage.length + this.buffer.length) > this.sizeLimit;
}
public forceNewPage(node: DocumentNode): void {
if (this.currentPage.length === 0 && (this.buffer.length > this.sizeLimit)) {
throw new TypeError('Commit is too large, could not write a page for this commit');
}
this.pages.push(this.buffer);
this.buffer = '';
this.lastCommittedNode = node;
}
/**
* Attempt to commit the buffer to the output stream.
* @param node The node to associate with the commit.
* @returns True if commited, false if uncomitted. Buffer remains unchanged
* if commit was unsuccessful.
* OR create a new page
* Returns true if a new page was created.
*/
public attemptCommit(node: DocumentNode): boolean {
if ((this.output.length + this.buffer.length) > this.sizeLimit) {
public commit(node: DocumentNode): boolean {
if (this.isPageAndBufferOverSize()) {
this.forceNewPage(node);
return true;
} else {
this.appendToCurrentPage(this.buffer);
this.buffer = '';
this.lastCommittedNode = node;
return false;
}
this.output += this.buffer;
this.buffer = '';
this.adjust(this.output, this.buffer);
this.lastCommittedNode = node;
return true;
}
public getLastCommittedNode(): DocumentNode|undefined {
@@ -66,7 +82,7 @@ export class TransactionalOutputStream {
}
export interface TransactionalOutputContext {
output: TransactionalOutputStream
output: PagedOutputStream
}
export function staticString(string: string): FringeInnerRenderFunction<TransactionalOutputContext> {
@@ -5,7 +5,7 @@
import { AbstractNode, DocumentNode, FringeWalker } from "./DeadDocument";
import { HTML_RENDERER } from "./DeadDocumentHtml";
import { MARKDOWN_RENDERER, TransactionalOutputStream } from "./DeadDocumentMarkdown";
import { MARKDOWN_RENDERER, PagedOutputStream } from "./DeadDocumentMarkdown";
function checkEqual(node1: AbstractNode|undefined, node2: AbstractNode|undefined): true {
if (!Object.is(node1, node2)) {
@@ -15,23 +15,37 @@ function checkEqual(node1: AbstractNode|undefined, node2: AbstractNode|undefined
}
export function renderMatrix(node: DocumentNode) {
const markdownOutput = new TransactionalOutputStream();
const markdownOutput = new PagedOutputStream();
const markdownWalker = new FringeWalker(
node,
{ output: markdownOutput },
MARKDOWN_RENDERER
);
const htmlOutput = new TransactionalOutputStream();
const htmlOutput = new PagedOutputStream();
const htmlWalker = new FringeWalker(
node,
{ output: htmlOutput },
HTML_RENDERER
);
const outputs = [htmlOutput, markdownOutput];
// surely this shit should be internal to the transactional output stream
// and it should be the paged output stream?
// well we can't make it internal if both of the things are writing to it.
// what we can do is make
// Why the hell are we making the pages AOT??
// There should only be one page inside the stream
// and it should have to be consumed before continuing
// otherwise we just stack up tonnes of garbage.
// What if we make a class that eats walkers.
// it creats streams and writes the pa--
// wait a minute that's what this is ?
let currentMarkdownNode = markdownWalker.increment();
let currentHtmlNode = htmlWalker.increment();
checkEqual(currentHtmlNode, currentMarkdownNode);
while (currentHtmlNode) {
htmlOutput.attemptCommit
while (currentHtmlNode !== undefined) {
if (outputs.some(o => o.isPageAndBufferOverSize())) {
outputs.forEach(o => o.forceNewPage(currentHtmlNode!));
}
}
}