console-rects 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -0
- package/dist/index.cjs +188 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.mjs +188 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/tests/base.spec.d.ts +1 -0
- package/dist/types/vite.config.d.ts +2 -0
- package/dist/types/vitest.config.d.ts +2 -0
- package/package.json +52 -0
package/README.md
ADDED
|
File without changes
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const UP = 1;
|
|
4
|
+
const DOWN = 2;
|
|
5
|
+
const LEFT = 4;
|
|
6
|
+
const RIGHT = 8;
|
|
7
|
+
const STYLE_CHARS = {
|
|
8
|
+
light: {
|
|
9
|
+
[UP]: "╵",
|
|
10
|
+
[DOWN]: "╷",
|
|
11
|
+
[LEFT]: "╴",
|
|
12
|
+
[RIGHT]: "╶",
|
|
13
|
+
[LEFT | RIGHT]: "─",
|
|
14
|
+
[UP | DOWN]: "│",
|
|
15
|
+
[DOWN | RIGHT]: "┌",
|
|
16
|
+
[DOWN | LEFT]: "┐",
|
|
17
|
+
[UP | RIGHT]: "└",
|
|
18
|
+
[UP | LEFT]: "┘",
|
|
19
|
+
[UP | DOWN | RIGHT]: "├",
|
|
20
|
+
[UP | DOWN | LEFT]: "┤",
|
|
21
|
+
[LEFT | RIGHT | DOWN]: "┬",
|
|
22
|
+
[LEFT | RIGHT | UP]: "┴",
|
|
23
|
+
[UP | DOWN | LEFT | RIGHT]: "┼"
|
|
24
|
+
},
|
|
25
|
+
heavy: {
|
|
26
|
+
[UP]: "╹",
|
|
27
|
+
[DOWN]: "╻",
|
|
28
|
+
[LEFT]: "╸",
|
|
29
|
+
[RIGHT]: "╺",
|
|
30
|
+
[LEFT | RIGHT]: "━",
|
|
31
|
+
[UP | DOWN]: "┃",
|
|
32
|
+
[DOWN | RIGHT]: "┏",
|
|
33
|
+
[DOWN | LEFT]: "┓",
|
|
34
|
+
[UP | RIGHT]: "┗",
|
|
35
|
+
[UP | LEFT]: "┛",
|
|
36
|
+
[UP | DOWN | RIGHT]: "┣",
|
|
37
|
+
[UP | DOWN | LEFT]: "┫",
|
|
38
|
+
[LEFT | RIGHT | DOWN]: "┳",
|
|
39
|
+
[LEFT | RIGHT | UP]: "┻",
|
|
40
|
+
[UP | DOWN | LEFT | RIGHT]: "╋"
|
|
41
|
+
},
|
|
42
|
+
double: {
|
|
43
|
+
[UP]: "║",
|
|
44
|
+
[DOWN]: "║",
|
|
45
|
+
[LEFT]: "═",
|
|
46
|
+
[RIGHT]: "═",
|
|
47
|
+
[LEFT | RIGHT]: "═",
|
|
48
|
+
[UP | DOWN]: "║",
|
|
49
|
+
[DOWN | RIGHT]: "╔",
|
|
50
|
+
[DOWN | LEFT]: "╗",
|
|
51
|
+
[UP | RIGHT]: "╚",
|
|
52
|
+
[UP | LEFT]: "╝",
|
|
53
|
+
[UP | DOWN | RIGHT]: "╠",
|
|
54
|
+
[UP | DOWN | LEFT]: "╣",
|
|
55
|
+
[LEFT | RIGHT | DOWN]: "╦",
|
|
56
|
+
[LEFT | RIGHT | UP]: "╩",
|
|
57
|
+
[UP | DOWN | LEFT | RIGHT]: "╬"
|
|
58
|
+
},
|
|
59
|
+
dashed: {
|
|
60
|
+
[UP]: "╎",
|
|
61
|
+
[DOWN]: "╎",
|
|
62
|
+
[LEFT]: "╌",
|
|
63
|
+
[RIGHT]: "╌",
|
|
64
|
+
[LEFT | RIGHT]: "╌",
|
|
65
|
+
[UP | DOWN]: "╎",
|
|
66
|
+
[DOWN | RIGHT]: "┌",
|
|
67
|
+
[DOWN | LEFT]: "┐",
|
|
68
|
+
[UP | RIGHT]: "└",
|
|
69
|
+
[UP | LEFT]: "┘",
|
|
70
|
+
[UP | DOWN | RIGHT]: "├",
|
|
71
|
+
[UP | DOWN | LEFT]: "┤",
|
|
72
|
+
[LEFT | RIGHT | DOWN]: "┬",
|
|
73
|
+
[LEFT | RIGHT | UP]: "┴",
|
|
74
|
+
[UP | DOWN | LEFT | RIGHT]: "┼"
|
|
75
|
+
},
|
|
76
|
+
"dashed-heavy": {
|
|
77
|
+
[UP]: "╏",
|
|
78
|
+
[DOWN]: "╏",
|
|
79
|
+
[LEFT]: "╍",
|
|
80
|
+
[RIGHT]: "╍",
|
|
81
|
+
[LEFT | RIGHT]: "╍",
|
|
82
|
+
[UP | DOWN]: "╏",
|
|
83
|
+
[DOWN | RIGHT]: "┏",
|
|
84
|
+
[DOWN | LEFT]: "┓",
|
|
85
|
+
[UP | RIGHT]: "┗",
|
|
86
|
+
[UP | LEFT]: "┛",
|
|
87
|
+
[UP | DOWN | RIGHT]: "┣",
|
|
88
|
+
[UP | DOWN | LEFT]: "┫",
|
|
89
|
+
[LEFT | RIGHT | DOWN]: "┳",
|
|
90
|
+
[LEFT | RIGHT | UP]: "┻",
|
|
91
|
+
[UP | DOWN | LEFT | RIGHT]: "╋"
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const STYLES = Object.keys(STYLE_CHARS);
|
|
95
|
+
function findBoundaries(rectangles) {
|
|
96
|
+
let minX = Infinity;
|
|
97
|
+
let minY = Infinity;
|
|
98
|
+
let maxX = -Infinity;
|
|
99
|
+
let maxY = -Infinity;
|
|
100
|
+
for (const rect of rectangles) {
|
|
101
|
+
minX = Math.min(minX, rect.x);
|
|
102
|
+
minY = Math.min(minY, rect.y);
|
|
103
|
+
maxX = Math.max(maxX, rect.x + rect.width);
|
|
104
|
+
maxY = Math.max(maxY, rect.y + rect.height);
|
|
105
|
+
}
|
|
106
|
+
return { minX, minY, maxX, maxY };
|
|
107
|
+
}
|
|
108
|
+
function logRects(rectangles, { sizePerPoint = 10, showLegend = true, startWithNewLine = true, dontLog = false } = {}) {
|
|
109
|
+
if (rectangles.length === 0) {
|
|
110
|
+
return "";
|
|
111
|
+
}
|
|
112
|
+
const { minX, minY, maxX, maxY } = findBoundaries(rectangles);
|
|
113
|
+
const gridWidth = Math.ceil((maxX - minX) / sizePerPoint);
|
|
114
|
+
const gridHeight = Math.ceil((maxY - minY) / sizePerPoint);
|
|
115
|
+
const grid = Array.from(
|
|
116
|
+
{ length: gridHeight },
|
|
117
|
+
() => Array.from({ length: gridWidth }, () => ({ directions: 0, zIndex: -1 }))
|
|
118
|
+
);
|
|
119
|
+
const setCell = (row, col, direction, zIndex) => {
|
|
120
|
+
if (row < 0 || row >= gridHeight || col < 0 || col >= gridWidth) return;
|
|
121
|
+
const cell = grid[row][col];
|
|
122
|
+
if (zIndex >= cell.zIndex) {
|
|
123
|
+
if (zIndex > cell.zIndex) {
|
|
124
|
+
cell.directions = 0;
|
|
125
|
+
cell.zIndex = zIndex;
|
|
126
|
+
}
|
|
127
|
+
cell.directions |= direction;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const drawHorizontal = (row, colStart, colEnd, zIndex) => {
|
|
131
|
+
for (let col = colStart; col <= colEnd; col++) {
|
|
132
|
+
let dirs = 0;
|
|
133
|
+
if (col > colStart) dirs |= LEFT;
|
|
134
|
+
if (col < colEnd) dirs |= RIGHT;
|
|
135
|
+
if (dirs) setCell(row, col, dirs, zIndex);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const drawVertical = (col, rowStart, rowEnd, zIndex) => {
|
|
139
|
+
for (let row = rowStart; row <= rowEnd; row++) {
|
|
140
|
+
let dirs = 0;
|
|
141
|
+
if (row > rowStart) dirs |= UP;
|
|
142
|
+
if (row < rowEnd) dirs |= DOWN;
|
|
143
|
+
if (dirs) setCell(row, col, dirs, zIndex);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
rectangles.forEach((rect, zIndex) => {
|
|
147
|
+
const startCol = Math.floor((rect.x - minX) / sizePerPoint);
|
|
148
|
+
const startRow = Math.floor((rect.y - minY) / sizePerPoint);
|
|
149
|
+
const endCol = Math.ceil((rect.x + rect.width - minX) / sizePerPoint) - 1;
|
|
150
|
+
const endRow = Math.ceil((rect.y + rect.height - minY) / sizePerPoint) - 1;
|
|
151
|
+
drawHorizontal(startRow, startCol, endCol, zIndex);
|
|
152
|
+
drawHorizontal(endRow, startCol, endCol, zIndex);
|
|
153
|
+
drawVertical(startCol, startRow, endRow, zIndex);
|
|
154
|
+
drawVertical(endCol, startRow, endRow, zIndex);
|
|
155
|
+
});
|
|
156
|
+
const charGrid = grid.map(
|
|
157
|
+
(row) => row.map((cell) => {
|
|
158
|
+
if (cell.directions === 0) return " ";
|
|
159
|
+
const style = STYLES[cell.zIndex % STYLES.length];
|
|
160
|
+
return STYLE_CHARS[style][cell.directions] || "?";
|
|
161
|
+
})
|
|
162
|
+
);
|
|
163
|
+
const lines = [];
|
|
164
|
+
if (showLegend) {
|
|
165
|
+
const topLeftLabel = `[${minX}, ${minY}]`;
|
|
166
|
+
const bottomRightLabel = `[${maxX}, ${maxY}]`;
|
|
167
|
+
const padding = " ".repeat(topLeftLabel.length + 1);
|
|
168
|
+
lines.push(topLeftLabel);
|
|
169
|
+
for (const row of charGrid) {
|
|
170
|
+
lines.push(padding + row.join(""));
|
|
171
|
+
}
|
|
172
|
+
lines.push(padding + " ".repeat(gridWidth) + " " + bottomRightLabel);
|
|
173
|
+
} else {
|
|
174
|
+
for (const row of charGrid) {
|
|
175
|
+
lines.push(row.join(""));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (startWithNewLine) {
|
|
179
|
+
lines.unshift("");
|
|
180
|
+
}
|
|
181
|
+
const output = lines.join("\n");
|
|
182
|
+
if (!dontLog) {
|
|
183
|
+
console.info(output);
|
|
184
|
+
}
|
|
185
|
+
return output;
|
|
186
|
+
}
|
|
187
|
+
exports.logRects = logRects;
|
|
188
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../index.ts"],"sourcesContent":["interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n// Direction bitmasks\nconst UP = 1;\nconst DOWN = 2;\nconst LEFT = 4;\nconst RIGHT = 8;\n\n// Box-drawing character maps for each style\nconst STYLE_CHARS = {\n light: {\n [UP]: \"╵\",\n [DOWN]: \"╷\",\n [LEFT]: \"╴\",\n [RIGHT]: \"╶\",\n [LEFT | RIGHT]: \"─\",\n [UP | DOWN]: \"│\",\n [DOWN | RIGHT]: \"┌\",\n [DOWN | LEFT]: \"┐\",\n [UP | RIGHT]: \"└\",\n [UP | LEFT]: \"┘\",\n [UP | DOWN | RIGHT]: \"├\",\n [UP | DOWN | LEFT]: \"┤\",\n [LEFT | RIGHT | DOWN]: \"┬\",\n [LEFT | RIGHT | UP]: \"┴\",\n [UP | DOWN | LEFT | RIGHT]: \"┼\",\n },\n heavy: {\n [UP]: \"╹\",\n [DOWN]: \"╻\",\n [LEFT]: \"╸\",\n [RIGHT]: \"╺\",\n [LEFT | RIGHT]: \"━\",\n [UP | DOWN]: \"┃\",\n [DOWN | RIGHT]: \"┏\",\n [DOWN | LEFT]: \"┓\",\n [UP | RIGHT]: \"┗\",\n [UP | LEFT]: \"┛\",\n [UP | DOWN | RIGHT]: \"┣\",\n [UP | DOWN | LEFT]: \"┫\",\n [LEFT | RIGHT | DOWN]: \"┳\",\n [LEFT | RIGHT | UP]: \"┻\",\n [UP | DOWN | LEFT | RIGHT]: \"╋\",\n },\n double: {\n [UP]: \"║\",\n [DOWN]: \"║\",\n [LEFT]: \"═\",\n [RIGHT]: \"═\",\n [LEFT | RIGHT]: \"═\",\n [UP | DOWN]: \"║\",\n [DOWN | RIGHT]: \"╔\",\n [DOWN | LEFT]: \"╗\",\n [UP | RIGHT]: \"╚\",\n [UP | LEFT]: \"╝\",\n [UP | DOWN | RIGHT]: \"╠\",\n [UP | DOWN | LEFT]: \"╣\",\n [LEFT | RIGHT | DOWN]: \"╦\",\n [LEFT | RIGHT | UP]: \"╩\",\n [UP | DOWN | LEFT | RIGHT]: \"╬\",\n },\n dashed: {\n [UP]: \"╎\",\n [DOWN]: \"╎\",\n [LEFT]: \"╌\",\n [RIGHT]: \"╌\",\n [LEFT | RIGHT]: \"╌\",\n [UP | DOWN]: \"╎\",\n [DOWN | RIGHT]: \"┌\",\n [DOWN | LEFT]: \"┐\",\n [UP | RIGHT]: \"└\",\n [UP | LEFT]: \"┘\",\n [UP | DOWN | RIGHT]: \"├\",\n [UP | DOWN | LEFT]: \"┤\",\n [LEFT | RIGHT | DOWN]: \"┬\",\n [LEFT | RIGHT | UP]: \"┴\",\n [UP | DOWN | LEFT | RIGHT]: \"┼\",\n },\n \"dashed-heavy\": {\n [UP]: \"╏\",\n [DOWN]: \"╏\",\n [LEFT]: \"╍\",\n [RIGHT]: \"╍\",\n [LEFT | RIGHT]: \"╍\",\n [UP | DOWN]: \"╏\",\n [DOWN | RIGHT]: \"┏\",\n [DOWN | LEFT]: \"┓\",\n [UP | RIGHT]: \"┗\",\n [UP | LEFT]: \"┛\",\n [UP | DOWN | RIGHT]: \"┣\",\n [UP | DOWN | LEFT]: \"┫\",\n [LEFT | RIGHT | DOWN]: \"┳\",\n [LEFT | RIGHT | UP]: \"┻\",\n [UP | DOWN | LEFT | RIGHT]: \"╋\",\n },\n} satisfies Record<string, Record<number, string>>;\n\ntype LineStyle = keyof typeof STYLE_CHARS;\n\nconst STYLES: LineStyle[] = Object.keys(STYLE_CHARS) as LineStyle[];\n\ninterface CellData {\n directions: number;\n zIndex: number; // highest z-index that touched this cell\n}\n\nexport interface LogRectsOptions {\n sizePerPoint?: number;\n showLegend?: boolean;\n startWithNewLine?: boolean;\n dontLog?: boolean;\n}\n\nfunction findBoundaries(rectangles: Rect[]) {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const rect of rectangles) {\n minX = Math.min(minX, rect.x);\n minY = Math.min(minY, rect.y);\n maxX = Math.max(maxX, rect.x + rect.width);\n maxY = Math.max(maxY, rect.y + rect.height);\n }\n\n return { minX, minY, maxX, maxY };\n}\n\nexport function logRects(\n rectangles: Rect[],\n { sizePerPoint = 10, showLegend = true, startWithNewLine = true, dontLog = false }: LogRectsOptions = {}\n): string {\n if (rectangles.length === 0) {\n return \"\";\n }\n\n // Find bounding box of all rectangles\n const { minX, minY, maxX, maxY } = findBoundaries(rectangles);\n\n // Calculate grid dimensions based on resolution\n const gridWidth = Math.ceil((maxX - minX) / sizePerPoint);\n const gridHeight = Math.ceil((maxY - minY) / sizePerPoint);\n\n // Create grid to track directions and z-index at each cell\n const grid: CellData[][] = Array.from({ length: gridHeight }, () =>\n Array.from({ length: gridWidth }, () => ({ directions: 0, zIndex: -1 }))\n );\n\n // Helper to set cell data with z-index awareness\n const setCell = (row: number, col: number, direction: number, zIndex: number) => {\n if (row < 0 || row >= gridHeight || col < 0 || col >= gridWidth) return;\n const cell = grid[row][col];\n if (zIndex >= cell.zIndex) {\n // Higher or equal z-index takes over, reset directions\n if (zIndex > cell.zIndex) {\n cell.directions = 0;\n cell.zIndex = zIndex;\n }\n cell.directions |= direction;\n }\n };\n\n // Helper to draw a horizontal line segment\n const drawHorizontal = (row: number, colStart: number, colEnd: number, zIndex: number) => {\n for (let col = colStart; col <= colEnd; col++) {\n let dirs = 0;\n if (col > colStart) dirs |= LEFT;\n if (col < colEnd) dirs |= RIGHT;\n if (dirs) setCell(row, col, dirs, zIndex);\n }\n };\n\n // Helper to draw a vertical line segment\n const drawVertical = (col: number, rowStart: number, rowEnd: number, zIndex: number) => {\n for (let row = rowStart; row <= rowEnd; row++) {\n let dirs = 0;\n if (row > rowStart) dirs |= UP;\n if (row < rowEnd) dirs |= DOWN;\n if (dirs) setCell(row, col, dirs, zIndex);\n }\n };\n\n // Draw each rectangle's outline with z-index = array index\n rectangles.forEach((rect, zIndex) => {\n const startCol = Math.floor((rect.x - minX) / sizePerPoint);\n const startRow = Math.floor((rect.y - minY) / sizePerPoint);\n const endCol = Math.ceil((rect.x + rect.width - minX) / sizePerPoint) - 1;\n const endRow = Math.ceil((rect.y + rect.height - minY) / sizePerPoint) - 1;\n\n // Draw the four edges\n drawHorizontal(startRow, startCol, endCol, zIndex); // Top\n drawHorizontal(endRow, startCol, endCol, zIndex); // Bottom\n drawVertical(startCol, startRow, endRow, zIndex); // Left\n drawVertical(endCol, startRow, endRow, zIndex); // Right\n });\n\n // Convert cell data to characters\n const charGrid: string[][] = grid.map((row) =>\n row.map((cell) => {\n if (cell.directions === 0) return \" \";\n const style = STYLES[cell.zIndex % STYLES.length];\n return STYLE_CHARS[style][cell.directions] || \"?\";\n })\n );\n\n // Build output string\n const lines: string[] = [];\n\n if (showLegend) {\n const topLeftLabel = `[${minX}, ${minY}]`;\n const bottomRightLabel = `[${maxX}, ${maxY}]`;\n const padding = \" \".repeat(topLeftLabel.length + 1);\n\n lines.push(topLeftLabel);\n for (const row of charGrid) {\n lines.push(padding + row.join(\"\"));\n }\n lines.push(padding + \" \".repeat(gridWidth) + \" \" + bottomRightLabel);\n } else {\n for (const row of charGrid) {\n lines.push(row.join(\"\"));\n }\n }\n\n if (startWithNewLine) {\n lines.unshift(\"\");\n }\n\n const output = lines.join(\"\\n\");\n\n if (!dontLog) {\n console.info(output);\n }\n\n return output;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
const UP = 1;
|
|
2
|
+
const DOWN = 2;
|
|
3
|
+
const LEFT = 4;
|
|
4
|
+
const RIGHT = 8;
|
|
5
|
+
const STYLE_CHARS = {
|
|
6
|
+
light: {
|
|
7
|
+
[UP]: "╵",
|
|
8
|
+
[DOWN]: "╷",
|
|
9
|
+
[LEFT]: "╴",
|
|
10
|
+
[RIGHT]: "╶",
|
|
11
|
+
[LEFT | RIGHT]: "─",
|
|
12
|
+
[UP | DOWN]: "│",
|
|
13
|
+
[DOWN | RIGHT]: "┌",
|
|
14
|
+
[DOWN | LEFT]: "┐",
|
|
15
|
+
[UP | RIGHT]: "└",
|
|
16
|
+
[UP | LEFT]: "┘",
|
|
17
|
+
[UP | DOWN | RIGHT]: "├",
|
|
18
|
+
[UP | DOWN | LEFT]: "┤",
|
|
19
|
+
[LEFT | RIGHT | DOWN]: "┬",
|
|
20
|
+
[LEFT | RIGHT | UP]: "┴",
|
|
21
|
+
[UP | DOWN | LEFT | RIGHT]: "┼"
|
|
22
|
+
},
|
|
23
|
+
heavy: {
|
|
24
|
+
[UP]: "╹",
|
|
25
|
+
[DOWN]: "╻",
|
|
26
|
+
[LEFT]: "╸",
|
|
27
|
+
[RIGHT]: "╺",
|
|
28
|
+
[LEFT | RIGHT]: "━",
|
|
29
|
+
[UP | DOWN]: "┃",
|
|
30
|
+
[DOWN | RIGHT]: "┏",
|
|
31
|
+
[DOWN | LEFT]: "┓",
|
|
32
|
+
[UP | RIGHT]: "┗",
|
|
33
|
+
[UP | LEFT]: "┛",
|
|
34
|
+
[UP | DOWN | RIGHT]: "┣",
|
|
35
|
+
[UP | DOWN | LEFT]: "┫",
|
|
36
|
+
[LEFT | RIGHT | DOWN]: "┳",
|
|
37
|
+
[LEFT | RIGHT | UP]: "┻",
|
|
38
|
+
[UP | DOWN | LEFT | RIGHT]: "╋"
|
|
39
|
+
},
|
|
40
|
+
double: {
|
|
41
|
+
[UP]: "║",
|
|
42
|
+
[DOWN]: "║",
|
|
43
|
+
[LEFT]: "═",
|
|
44
|
+
[RIGHT]: "═",
|
|
45
|
+
[LEFT | RIGHT]: "═",
|
|
46
|
+
[UP | DOWN]: "║",
|
|
47
|
+
[DOWN | RIGHT]: "╔",
|
|
48
|
+
[DOWN | LEFT]: "╗",
|
|
49
|
+
[UP | RIGHT]: "╚",
|
|
50
|
+
[UP | LEFT]: "╝",
|
|
51
|
+
[UP | DOWN | RIGHT]: "╠",
|
|
52
|
+
[UP | DOWN | LEFT]: "╣",
|
|
53
|
+
[LEFT | RIGHT | DOWN]: "╦",
|
|
54
|
+
[LEFT | RIGHT | UP]: "╩",
|
|
55
|
+
[UP | DOWN | LEFT | RIGHT]: "╬"
|
|
56
|
+
},
|
|
57
|
+
dashed: {
|
|
58
|
+
[UP]: "╎",
|
|
59
|
+
[DOWN]: "╎",
|
|
60
|
+
[LEFT]: "╌",
|
|
61
|
+
[RIGHT]: "╌",
|
|
62
|
+
[LEFT | RIGHT]: "╌",
|
|
63
|
+
[UP | DOWN]: "╎",
|
|
64
|
+
[DOWN | RIGHT]: "┌",
|
|
65
|
+
[DOWN | LEFT]: "┐",
|
|
66
|
+
[UP | RIGHT]: "└",
|
|
67
|
+
[UP | LEFT]: "┘",
|
|
68
|
+
[UP | DOWN | RIGHT]: "├",
|
|
69
|
+
[UP | DOWN | LEFT]: "┤",
|
|
70
|
+
[LEFT | RIGHT | DOWN]: "┬",
|
|
71
|
+
[LEFT | RIGHT | UP]: "┴",
|
|
72
|
+
[UP | DOWN | LEFT | RIGHT]: "┼"
|
|
73
|
+
},
|
|
74
|
+
"dashed-heavy": {
|
|
75
|
+
[UP]: "╏",
|
|
76
|
+
[DOWN]: "╏",
|
|
77
|
+
[LEFT]: "╍",
|
|
78
|
+
[RIGHT]: "╍",
|
|
79
|
+
[LEFT | RIGHT]: "╍",
|
|
80
|
+
[UP | DOWN]: "╏",
|
|
81
|
+
[DOWN | RIGHT]: "┏",
|
|
82
|
+
[DOWN | LEFT]: "┓",
|
|
83
|
+
[UP | RIGHT]: "┗",
|
|
84
|
+
[UP | LEFT]: "┛",
|
|
85
|
+
[UP | DOWN | RIGHT]: "┣",
|
|
86
|
+
[UP | DOWN | LEFT]: "┫",
|
|
87
|
+
[LEFT | RIGHT | DOWN]: "┳",
|
|
88
|
+
[LEFT | RIGHT | UP]: "┻",
|
|
89
|
+
[UP | DOWN | LEFT | RIGHT]: "╋"
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const STYLES = Object.keys(STYLE_CHARS);
|
|
93
|
+
function findBoundaries(rectangles) {
|
|
94
|
+
let minX = Infinity;
|
|
95
|
+
let minY = Infinity;
|
|
96
|
+
let maxX = -Infinity;
|
|
97
|
+
let maxY = -Infinity;
|
|
98
|
+
for (const rect of rectangles) {
|
|
99
|
+
minX = Math.min(minX, rect.x);
|
|
100
|
+
minY = Math.min(minY, rect.y);
|
|
101
|
+
maxX = Math.max(maxX, rect.x + rect.width);
|
|
102
|
+
maxY = Math.max(maxY, rect.y + rect.height);
|
|
103
|
+
}
|
|
104
|
+
return { minX, minY, maxX, maxY };
|
|
105
|
+
}
|
|
106
|
+
function logRects(rectangles, { sizePerPoint = 10, showLegend = true, startWithNewLine = true, dontLog = false } = {}) {
|
|
107
|
+
if (rectangles.length === 0) {
|
|
108
|
+
return "";
|
|
109
|
+
}
|
|
110
|
+
const { minX, minY, maxX, maxY } = findBoundaries(rectangles);
|
|
111
|
+
const gridWidth = Math.ceil((maxX - minX) / sizePerPoint);
|
|
112
|
+
const gridHeight = Math.ceil((maxY - minY) / sizePerPoint);
|
|
113
|
+
const grid = Array.from(
|
|
114
|
+
{ length: gridHeight },
|
|
115
|
+
() => Array.from({ length: gridWidth }, () => ({ directions: 0, zIndex: -1 }))
|
|
116
|
+
);
|
|
117
|
+
const setCell = (row, col, direction, zIndex) => {
|
|
118
|
+
if (row < 0 || row >= gridHeight || col < 0 || col >= gridWidth) return;
|
|
119
|
+
const cell = grid[row][col];
|
|
120
|
+
if (zIndex >= cell.zIndex) {
|
|
121
|
+
if (zIndex > cell.zIndex) {
|
|
122
|
+
cell.directions = 0;
|
|
123
|
+
cell.zIndex = zIndex;
|
|
124
|
+
}
|
|
125
|
+
cell.directions |= direction;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const drawHorizontal = (row, colStart, colEnd, zIndex) => {
|
|
129
|
+
for (let col = colStart; col <= colEnd; col++) {
|
|
130
|
+
let dirs = 0;
|
|
131
|
+
if (col > colStart) dirs |= LEFT;
|
|
132
|
+
if (col < colEnd) dirs |= RIGHT;
|
|
133
|
+
if (dirs) setCell(row, col, dirs, zIndex);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const drawVertical = (col, rowStart, rowEnd, zIndex) => {
|
|
137
|
+
for (let row = rowStart; row <= rowEnd; row++) {
|
|
138
|
+
let dirs = 0;
|
|
139
|
+
if (row > rowStart) dirs |= UP;
|
|
140
|
+
if (row < rowEnd) dirs |= DOWN;
|
|
141
|
+
if (dirs) setCell(row, col, dirs, zIndex);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
rectangles.forEach((rect, zIndex) => {
|
|
145
|
+
const startCol = Math.floor((rect.x - minX) / sizePerPoint);
|
|
146
|
+
const startRow = Math.floor((rect.y - minY) / sizePerPoint);
|
|
147
|
+
const endCol = Math.ceil((rect.x + rect.width - minX) / sizePerPoint) - 1;
|
|
148
|
+
const endRow = Math.ceil((rect.y + rect.height - minY) / sizePerPoint) - 1;
|
|
149
|
+
drawHorizontal(startRow, startCol, endCol, zIndex);
|
|
150
|
+
drawHorizontal(endRow, startCol, endCol, zIndex);
|
|
151
|
+
drawVertical(startCol, startRow, endRow, zIndex);
|
|
152
|
+
drawVertical(endCol, startRow, endRow, zIndex);
|
|
153
|
+
});
|
|
154
|
+
const charGrid = grid.map(
|
|
155
|
+
(row) => row.map((cell) => {
|
|
156
|
+
if (cell.directions === 0) return " ";
|
|
157
|
+
const style = STYLES[cell.zIndex % STYLES.length];
|
|
158
|
+
return STYLE_CHARS[style][cell.directions] || "?";
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
const lines = [];
|
|
162
|
+
if (showLegend) {
|
|
163
|
+
const topLeftLabel = `[${minX}, ${minY}]`;
|
|
164
|
+
const bottomRightLabel = `[${maxX}, ${maxY}]`;
|
|
165
|
+
const padding = " ".repeat(topLeftLabel.length + 1);
|
|
166
|
+
lines.push(topLeftLabel);
|
|
167
|
+
for (const row of charGrid) {
|
|
168
|
+
lines.push(padding + row.join(""));
|
|
169
|
+
}
|
|
170
|
+
lines.push(padding + " ".repeat(gridWidth) + " " + bottomRightLabel);
|
|
171
|
+
} else {
|
|
172
|
+
for (const row of charGrid) {
|
|
173
|
+
lines.push(row.join(""));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (startWithNewLine) {
|
|
177
|
+
lines.unshift("");
|
|
178
|
+
}
|
|
179
|
+
const output = lines.join("\n");
|
|
180
|
+
if (!dontLog) {
|
|
181
|
+
console.info(output);
|
|
182
|
+
}
|
|
183
|
+
return output;
|
|
184
|
+
}
|
|
185
|
+
export {
|
|
186
|
+
logRects
|
|
187
|
+
};
|
|
188
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../index.ts"],"sourcesContent":["interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n// Direction bitmasks\nconst UP = 1;\nconst DOWN = 2;\nconst LEFT = 4;\nconst RIGHT = 8;\n\n// Box-drawing character maps for each style\nconst STYLE_CHARS = {\n light: {\n [UP]: \"╵\",\n [DOWN]: \"╷\",\n [LEFT]: \"╴\",\n [RIGHT]: \"╶\",\n [LEFT | RIGHT]: \"─\",\n [UP | DOWN]: \"│\",\n [DOWN | RIGHT]: \"┌\",\n [DOWN | LEFT]: \"┐\",\n [UP | RIGHT]: \"└\",\n [UP | LEFT]: \"┘\",\n [UP | DOWN | RIGHT]: \"├\",\n [UP | DOWN | LEFT]: \"┤\",\n [LEFT | RIGHT | DOWN]: \"┬\",\n [LEFT | RIGHT | UP]: \"┴\",\n [UP | DOWN | LEFT | RIGHT]: \"┼\",\n },\n heavy: {\n [UP]: \"╹\",\n [DOWN]: \"╻\",\n [LEFT]: \"╸\",\n [RIGHT]: \"╺\",\n [LEFT | RIGHT]: \"━\",\n [UP | DOWN]: \"┃\",\n [DOWN | RIGHT]: \"┏\",\n [DOWN | LEFT]: \"┓\",\n [UP | RIGHT]: \"┗\",\n [UP | LEFT]: \"┛\",\n [UP | DOWN | RIGHT]: \"┣\",\n [UP | DOWN | LEFT]: \"┫\",\n [LEFT | RIGHT | DOWN]: \"┳\",\n [LEFT | RIGHT | UP]: \"┻\",\n [UP | DOWN | LEFT | RIGHT]: \"╋\",\n },\n double: {\n [UP]: \"║\",\n [DOWN]: \"║\",\n [LEFT]: \"═\",\n [RIGHT]: \"═\",\n [LEFT | RIGHT]: \"═\",\n [UP | DOWN]: \"║\",\n [DOWN | RIGHT]: \"╔\",\n [DOWN | LEFT]: \"╗\",\n [UP | RIGHT]: \"╚\",\n [UP | LEFT]: \"╝\",\n [UP | DOWN | RIGHT]: \"╠\",\n [UP | DOWN | LEFT]: \"╣\",\n [LEFT | RIGHT | DOWN]: \"╦\",\n [LEFT | RIGHT | UP]: \"╩\",\n [UP | DOWN | LEFT | RIGHT]: \"╬\",\n },\n dashed: {\n [UP]: \"╎\",\n [DOWN]: \"╎\",\n [LEFT]: \"╌\",\n [RIGHT]: \"╌\",\n [LEFT | RIGHT]: \"╌\",\n [UP | DOWN]: \"╎\",\n [DOWN | RIGHT]: \"┌\",\n [DOWN | LEFT]: \"┐\",\n [UP | RIGHT]: \"└\",\n [UP | LEFT]: \"┘\",\n [UP | DOWN | RIGHT]: \"├\",\n [UP | DOWN | LEFT]: \"┤\",\n [LEFT | RIGHT | DOWN]: \"┬\",\n [LEFT | RIGHT | UP]: \"┴\",\n [UP | DOWN | LEFT | RIGHT]: \"┼\",\n },\n \"dashed-heavy\": {\n [UP]: \"╏\",\n [DOWN]: \"╏\",\n [LEFT]: \"╍\",\n [RIGHT]: \"╍\",\n [LEFT | RIGHT]: \"╍\",\n [UP | DOWN]: \"╏\",\n [DOWN | RIGHT]: \"┏\",\n [DOWN | LEFT]: \"┓\",\n [UP | RIGHT]: \"┗\",\n [UP | LEFT]: \"┛\",\n [UP | DOWN | RIGHT]: \"┣\",\n [UP | DOWN | LEFT]: \"┫\",\n [LEFT | RIGHT | DOWN]: \"┳\",\n [LEFT | RIGHT | UP]: \"┻\",\n [UP | DOWN | LEFT | RIGHT]: \"╋\",\n },\n} satisfies Record<string, Record<number, string>>;\n\ntype LineStyle = keyof typeof STYLE_CHARS;\n\nconst STYLES: LineStyle[] = Object.keys(STYLE_CHARS) as LineStyle[];\n\ninterface CellData {\n directions: number;\n zIndex: number; // highest z-index that touched this cell\n}\n\nexport interface LogRectsOptions {\n sizePerPoint?: number;\n showLegend?: boolean;\n startWithNewLine?: boolean;\n dontLog?: boolean;\n}\n\nfunction findBoundaries(rectangles: Rect[]) {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const rect of rectangles) {\n minX = Math.min(minX, rect.x);\n minY = Math.min(minY, rect.y);\n maxX = Math.max(maxX, rect.x + rect.width);\n maxY = Math.max(maxY, rect.y + rect.height);\n }\n\n return { minX, minY, maxX, maxY };\n}\n\nexport function logRects(\n rectangles: Rect[],\n { sizePerPoint = 10, showLegend = true, startWithNewLine = true, dontLog = false }: LogRectsOptions = {}\n): string {\n if (rectangles.length === 0) {\n return \"\";\n }\n\n // Find bounding box of all rectangles\n const { minX, minY, maxX, maxY } = findBoundaries(rectangles);\n\n // Calculate grid dimensions based on resolution\n const gridWidth = Math.ceil((maxX - minX) / sizePerPoint);\n const gridHeight = Math.ceil((maxY - minY) / sizePerPoint);\n\n // Create grid to track directions and z-index at each cell\n const grid: CellData[][] = Array.from({ length: gridHeight }, () =>\n Array.from({ length: gridWidth }, () => ({ directions: 0, zIndex: -1 }))\n );\n\n // Helper to set cell data with z-index awareness\n const setCell = (row: number, col: number, direction: number, zIndex: number) => {\n if (row < 0 || row >= gridHeight || col < 0 || col >= gridWidth) return;\n const cell = grid[row][col];\n if (zIndex >= cell.zIndex) {\n // Higher or equal z-index takes over, reset directions\n if (zIndex > cell.zIndex) {\n cell.directions = 0;\n cell.zIndex = zIndex;\n }\n cell.directions |= direction;\n }\n };\n\n // Helper to draw a horizontal line segment\n const drawHorizontal = (row: number, colStart: number, colEnd: number, zIndex: number) => {\n for (let col = colStart; col <= colEnd; col++) {\n let dirs = 0;\n if (col > colStart) dirs |= LEFT;\n if (col < colEnd) dirs |= RIGHT;\n if (dirs) setCell(row, col, dirs, zIndex);\n }\n };\n\n // Helper to draw a vertical line segment\n const drawVertical = (col: number, rowStart: number, rowEnd: number, zIndex: number) => {\n for (let row = rowStart; row <= rowEnd; row++) {\n let dirs = 0;\n if (row > rowStart) dirs |= UP;\n if (row < rowEnd) dirs |= DOWN;\n if (dirs) setCell(row, col, dirs, zIndex);\n }\n };\n\n // Draw each rectangle's outline with z-index = array index\n rectangles.forEach((rect, zIndex) => {\n const startCol = Math.floor((rect.x - minX) / sizePerPoint);\n const startRow = Math.floor((rect.y - minY) / sizePerPoint);\n const endCol = Math.ceil((rect.x + rect.width - minX) / sizePerPoint) - 1;\n const endRow = Math.ceil((rect.y + rect.height - minY) / sizePerPoint) - 1;\n\n // Draw the four edges\n drawHorizontal(startRow, startCol, endCol, zIndex); // Top\n drawHorizontal(endRow, startCol, endCol, zIndex); // Bottom\n drawVertical(startCol, startRow, endRow, zIndex); // Left\n drawVertical(endCol, startRow, endRow, zIndex); // Right\n });\n\n // Convert cell data to characters\n const charGrid: string[][] = grid.map((row) =>\n row.map((cell) => {\n if (cell.directions === 0) return \" \";\n const style = STYLES[cell.zIndex % STYLES.length];\n return STYLE_CHARS[style][cell.directions] || \"?\";\n })\n );\n\n // Build output string\n const lines: string[] = [];\n\n if (showLegend) {\n const topLeftLabel = `[${minX}, ${minY}]`;\n const bottomRightLabel = `[${maxX}, ${maxY}]`;\n const padding = \" \".repeat(topLeftLabel.length + 1);\n\n lines.push(topLeftLabel);\n for (const row of charGrid) {\n lines.push(padding + row.join(\"\"));\n }\n lines.push(padding + \" \".repeat(gridWidth) + \" \" + bottomRightLabel);\n } else {\n for (const row of charGrid) {\n lines.push(row.join(\"\"));\n }\n }\n\n if (startWithNewLine) {\n lines.unshift(\"\");\n }\n\n const output = lines.join(\"\\n\");\n\n if (!dontLog) {\n console.info(output);\n }\n\n return output;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface Rect {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
}
|
|
7
|
+
export interface LogRectsOptions {
|
|
8
|
+
sizePerPoint?: number;
|
|
9
|
+
showLegend?: boolean;
|
|
10
|
+
startWithNewLine?: boolean;
|
|
11
|
+
dontLog?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function logRects(rectangles: Rect[], { sizePerPoint, showLegend, startWithNewLine, dontLog }?: LogRectsOptions): string;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "console-rects",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/types/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/types/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [],
|
|
21
|
+
"author": {
|
|
22
|
+
"name": "Adam Pietrasiak",
|
|
23
|
+
"email": "adam@pietrasiak.com"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/pie6k/console-rects.git"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/pie6k/console-rects/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/pie6k/console-rects#readme",
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "vite build && tsc --emitDeclarationOnly",
|
|
36
|
+
"clean": "rm -rf dist",
|
|
37
|
+
"test": "vitest",
|
|
38
|
+
"test:watch": "vitest --watch",
|
|
39
|
+
"bench": "vitest bench tests/benchmark.bench.ts",
|
|
40
|
+
"readme": "cp ../README.md ./README.md",
|
|
41
|
+
"release": "yarn build && npm publish"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/jsdom": "^27",
|
|
45
|
+
"@types/node": "^24.9.1",
|
|
46
|
+
"@vitest/coverage-v8": "4.0.1",
|
|
47
|
+
"jsdom": "^27.0.1",
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"vite": "^5.0.0",
|
|
50
|
+
"vitest": "^4.0.1"
|
|
51
|
+
}
|
|
52
|
+
}
|