Skip to content

Commit

Permalink
make tree logging work in the browser
Browse files Browse the repository at this point in the history
whoops forgot this earlier
  • Loading branch information
chearon committed Nov 27, 2024
1 parent 52e661b commit 8056c4f
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 135 deletions.
2 changes: 1 addition & 1 deletion examples/bidi-1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const rootElement = flow.parse(`

const blockContainer = flow.generate(rootElement);

console.log(blockContainer.repr());
blockContainer.log();

const canvas = createCanvas(200, 250);
flow.layout(blockContainer, canvas.width, canvas.height);
Expand Down
2 changes: 1 addition & 1 deletion examples/fallbacks-1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const rootElement = flow.parse(`

const blockContainer = flow.generate(rootElement);

console.log(blockContainer.repr());
blockContainer.log();

const canvas = createCanvas(400, 150);
flow.layout(blockContainer, canvas.width, canvas.height);
Expand Down
2 changes: 1 addition & 1 deletion examples/images-1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const rootElement = flow.dom(

// Normal layout, logging
const blockContainer = flow.generate(rootElement);
console.log(blockContainer.repr());
blockContainer.log();
flow.layout(blockContainer, 600, 400);
const canvas = createCanvas(600, 400);
const ctx = canvas.getContext('2d');
Expand Down
2 changes: 1 addition & 1 deletion examples/inlines-1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const rootElement = flow.parse(`
`);

const blockContainer = flow.generate(rootElement);
console.log(blockContainer.repr(0, {css: 'zoom'}));
blockContainer.log({css: 'zoom'});

const canvas = createCanvas(600, 400);
flow.layout(blockContainer, canvas.width, canvas.height);
Expand Down
2 changes: 1 addition & 1 deletion examples/rtl-1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const rootElement = flow.parse(`

const blockContainer = flow.generate(rootElement);

console.log(blockContainer.repr());
blockContainer.log();

const canvas = createCanvas(200, 600);
flow.layout(blockContainer, canvas.width, canvas.height);
Expand Down
2 changes: 1 addition & 1 deletion examples/svg-1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const doc = flow.parse(`

await flow.loadNotoFonts(doc, {paint: false});
const block = flow.generate(doc);
console.log(block.repr());
block.log();
flow.layout(block, 600, 100);
const svg = flow.paintToSvg(block);

Expand Down
5 changes: 4 additions & 1 deletion site/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ async function render(html) {

ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
flow.renderToCanvas(documentElement, canvas);
const box = flow.generate(documentElement);
box.log();
flow.layout(box, canvas.width, canvas.height);
flow.paintToCanvas(box, canvas.getContext('2d'));
ctx.restore();

window.documentElement = documentElement;
Expand Down
47 changes: 29 additions & 18 deletions src/layout-box.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {id} from './util.js';
import {id, Logger} from './util.js';
import {Style} from './style.js';
import {Run} from './layout-text.js';
import {Break, Inline, IfcInline, BlockContainer} from './layout-flow.js';
Expand All @@ -10,7 +10,7 @@ export interface LogicalArea {
inlineSize: number | undefined;
}

export interface ReprOptions {
export interface RenderItemLogOptions {
containingBlocks?: boolean;
css?: keyof Style
paragraphText?: string;
Expand Down Expand Up @@ -110,38 +110,49 @@ export abstract class RenderItem {
return false;
}

abstract desc(options?: ReprOptions): string;
abstract logName(log: Logger, options?: RenderItemLogOptions): void;

abstract sym(): string;
abstract getLogSymbol(): string;

repr(indent = 0, options?: ReprOptions): string {
let c = '';
log(options?: RenderItemLogOptions, log?: Logger) {
const flush = !log;

log ||= new Logger();

if (this.isIfcInline()) {
options = {...options};
options.paragraphText = this.text;
}

if (this.isBox() && this.children.length) {
c = '\n' + this.children.map(c => c.repr(indent + 1, options)).join('\n');
}

let extra = '';
log.text(`${this.getLogSymbol()} `);
this.logName(log, options);

if (options?.containingBlocks && this.isBlockContainer()) {
extra += ` (cb = ${this.containingBlock ? this.containingBlock.box.id : '(null)'})`;
log.text(` (cb: ${this.containingBlock?.box.id ?? '(null)'})`);
}

if (options?.css) {
const css = this.style[options.css];
extra += ` (${options.css}: ${css && JSON.stringify(css)})`;
log.text(` (${options.css}: ${css && JSON.stringify(css)})`);
}

if (options?.bits && this.isBox()) {
extra += ` (bf: ${this.stringifyBitfield()})`;
log.text(` (bf: ${this.stringifyBitfield()})`);
}

log.text('\n');

if (this.isBox() && this.children.length) {
log.pushIndent();

for (let i = 0; i < this.children.length; i++) {
this.children[i].log(options, log);
}

log.popIndent();
}

return ' '.repeat(indent) + this.sym() + ' ' + this.desc(options) + extra + c;
if (flush) log.flush();
}

preprocess() {
Expand Down Expand Up @@ -266,11 +277,11 @@ export class Box extends RenderItem {
}
}

desc(options?: ReprOptions) {
return 'Box';
logName(log: Logger, options?: RenderItemLogOptions) {
log.text('Box');
}

sym() {
getLogSymbol() {
return '◼︎';
}

Expand Down
37 changes: 16 additions & 21 deletions src/layout-flow.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {binarySearch} from './util.js';
import {binarySearch, Logger} from './util.js';
import {HTMLElement, TextNode} from './dom.js';
import {createStyle, Style, EMPTY_STYLE} from './style.js';
import {
Expand Down Expand Up @@ -43,10 +43,6 @@ function isWsPreserved(whiteSpace: WhiteSpace) {
return whiteSpace === 'pre' || whiteSpace === 'pre-wrap';
}

const reset = '\x1b[0m';
const dim = '\x1b[2m';
const underline = '\x1b[4m';

export interface LayoutContext {
lastBlockContainerArea: BoxArea,
lastPositionedArea: BoxArea,
Expand Down Expand Up @@ -780,7 +776,7 @@ export class BlockContainer extends Box {
}
}

sym() {
getLogSymbol() {
if (this.isFloat()) {
return '○︎';
} else if (this.isInlineLevel()) {
Expand All @@ -790,11 +786,11 @@ export class BlockContainer extends Box {
}
}

desc() {
return (this.isAnonymous() ? dim : '')
+ (this.isBfcRoot() ? underline : '')
+ 'Block ' + this.id
+ reset;
logName(log: Logger) {
if (this.isAnonymous()) log.dim();
if (this.isBfcRoot()) log.underline();
log.text(`Block ${this.id}`);
log.reset();
}

get writingModeAsParticipant() {
Expand Down Expand Up @@ -1293,12 +1289,12 @@ export class Break extends RenderItem {
return true;
}

sym() {
getLogSymbol() {
return '⏎';
}

desc() {
return 'BR';
logName(log: Logger) {
log.text('BR');
}
}

Expand Down Expand Up @@ -1355,16 +1351,15 @@ export class Inline extends Box {
return true;
}

sym() {
getLogSymbol() {
return '▭';
}

desc(): string /* TS 4.9 throws TS7023 - almost certainly a bug */ {
return (this.isAnonymous() ? dim : '')
+ (this.isIfcInline() ? underline : '')
+ 'Inline'
+ ' ' + this.id
+ reset;
logName(log: Logger) {
if (this.isAnonymous()) log.dim();
if (this.isIfcInline()) log.underline();
log.text(`Inline ${this.id}`);
log.reset();
}

assignContainingBlocks(ctx: LayoutContext) {
Expand Down
95 changes: 6 additions & 89 deletions src/layout-text.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {binarySearchTuple, basename, loggableText} from './util.js';
import {RenderItem, ReprOptions} from './layout-box.js';
import {binarySearchTuple, basename, loggableText, Logger} from './util.js';
import {RenderItem, RenderItemLogOptions} from './layout-box.js';
import {Style, Color, TextAlign, WhiteSpace} from './style.js';
import {
BlockContainer,
Expand Down Expand Up @@ -81,7 +81,7 @@ export class Run extends RenderItem {
return this.end - this.start;
}

sym() {
getLogSymbol() {
return 'Ͳ';
}

Expand All @@ -104,12 +104,11 @@ export class Run extends RenderItem {
return true;
}

desc(options?: ReprOptions) {
let ret = `${this.start},${this.end}`;
logName(log: Logger, options?: RenderItemLogOptions) {
log.text(`${this.start},${this.end}`);
if (options?.paragraphText) {
ret += ` "${loggableText(options.paragraphText.slice(this.start, this.end))}"`;
log.text(` "${loggableText(options.paragraphText.slice(this.start, this.end))}"`);
}
return ret;
}
}

Expand Down Expand Up @@ -436,88 +435,6 @@ function nextGlyph(state: GlyphIteratorState) {
}
}

export class Logger {
string: string;
formats: string[]; // only for browsers
indent: string[];
lineIsEmpty: boolean;

constructor() {
this.string = '';
this.formats = [];
this.indent = [];
this.lineIsEmpty = false;
}

bold() {
if (typeof process === 'object') {
this.string += '\x1b[1m';
} else {
this.string += '%c';
this.formats.push('font-weight: bold');
}
}

reset() {
if (typeof process === 'object') {
this.string += '\x1b[0m';
} else {
this.string += '%c';
this.formats.push('font-weight: normal');
}
}

flush() {
console.log(this.string, ...this.formats);
this.string = '';
this.formats = [];
}

text(str: string | number) {
const lines = String(str).split('\n');

const append = (s: string) => {
if (s) {
if (this.lineIsEmpty) this.string += this.indent.join('');
this.string += s;
this.lineIsEmpty = false;
}
};

for (let i = 0; i < lines.length; i++) {
if (i === 0) {
append(lines[i]);
} else {
this.string += '\n';
this.lineIsEmpty = true;
append(lines[i]);
}
}
}

glyphs(glyphs: Int32Array) {
for (let i = 0; i < glyphs.length; i += G_SZ) {
const cl = glyphs[i + G_CL];
const isp = i - G_SZ >= 0 && glyphs[i - G_SZ + G_CL] === cl;
const isn = i + G_SZ < glyphs.length && glyphs[i + G_SZ + G_CL] === cl;
if (isp || isn) this.bold();
if (isn && !isp) this.text('(');
this.text(glyphs[i + G_ID]);
if (!isn && isp) this.text(')');
this.text(' ');
if (isp || isn) this.reset();
}
}

pushIndent(indent = ' ') {
this.indent.push(indent);
}

popIndent() {
this.indent.pop();
}
}

function shiftGlyphs(glyphs: Int32Array, offset: number, dir: 'ltr' | 'rtl') {
if (dir === 'ltr') {
for (let i = 0; i < glyphs.length; i += G_SZ) {
Expand Down
Loading

0 comments on commit 8056c4f

Please sign in to comment.