@ggterm/core 0.2.20 → 0.3.1
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/dist/cli-plot.js +703 -12
- package/dist/cli.js +27 -3
- package/dist/index.js +27 -3
- package/dist/pipeline/pipeline.d.ts.map +1 -1
- package/dist/pipeline/render-geoms.d.ts.map +1 -1
- package/dist/serve.d.ts +10 -0
- package/dist/serve.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/cli-plot.js
CHANGED
|
@@ -3708,7 +3708,7 @@ function renderGeomVolcano(data, geom, aes, scales, canvas) {
|
|
|
3708
3708
|
}
|
|
3709
3709
|
if (nLabels > 0 && aes.label) {
|
|
3710
3710
|
const significantPoints = points.filter((p) => p.status !== "ns" && p.label).sort((a, b) => b.significance - a.significance).slice(0, nLabels);
|
|
3711
|
-
const labelColor = { r:
|
|
3711
|
+
const labelColor = { r: 255, g: 255, b: 255, a: 1 };
|
|
3712
3712
|
for (const point of significantPoints) {
|
|
3713
3713
|
const cx = Math.round(scales.x.map(point.x));
|
|
3714
3714
|
const cy = Math.round(scales.y.map(point.y));
|
|
@@ -4486,6 +4486,16 @@ function renderGeomForest(data, geom, aes, scales, canvas) {
|
|
|
4486
4486
|
canvas.drawChar(x2, y, "┤", ciColor);
|
|
4487
4487
|
const px = Math.round(mapX(row.estimate));
|
|
4488
4488
|
canvas.drawChar(px, y, pointChar, pointColor);
|
|
4489
|
+
const label = row.study;
|
|
4490
|
+
const labelColor = { r: 200, g: 200, b: 200, a: 1 };
|
|
4491
|
+
const labelEnd = plotLeft - 1;
|
|
4492
|
+
const labelStart = labelEnd - label.length;
|
|
4493
|
+
for (let c = 0;c < label.length; c++) {
|
|
4494
|
+
const charX = labelStart + c;
|
|
4495
|
+
if (charX >= 0) {
|
|
4496
|
+
canvas.drawChar(charX, y, label[c], labelColor);
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4489
4499
|
}
|
|
4490
4500
|
}
|
|
4491
4501
|
function renderGeomRoc(data, geom, aes, scales, canvas) {
|
|
@@ -7907,11 +7917,23 @@ function calculateLayout(spec, options) {
|
|
|
7907
7917
|
} else if (hasY2) {
|
|
7908
7918
|
rightMargin = 8 + (hasY2Label ? 2 : 0);
|
|
7909
7919
|
}
|
|
7920
|
+
let forestLabelWidth = 0;
|
|
7921
|
+
const isForestPlot = spec.geoms.some((g) => g.type === "forest");
|
|
7922
|
+
if (isForestPlot && Array.isArray(spec.data) && spec.data.length > 0) {
|
|
7923
|
+
const yField = typeof spec.aes.y === "string" ? spec.aes.y : "study";
|
|
7924
|
+
for (const row of spec.data) {
|
|
7925
|
+
const label = String(row[yField] ?? "");
|
|
7926
|
+
if (label.length > forestLabelWidth)
|
|
7927
|
+
forestLabelWidth = label.length;
|
|
7928
|
+
}
|
|
7929
|
+
}
|
|
7930
|
+
const defaultLeft = 8 + (hasYLabel ? 2 : 0);
|
|
7931
|
+
const neededLeft = forestLabelWidth > 0 ? forestLabelWidth + 2 : defaultLeft;
|
|
7910
7932
|
const margins = {
|
|
7911
7933
|
top: hasTitle ? 2 : 1,
|
|
7912
7934
|
right: rightMargin,
|
|
7913
7935
|
bottom: 2 + (hasXLabel ? 1 : 0) + (hasLegend && legendPosition === "bottom" ? 2 : 0),
|
|
7914
|
-
left:
|
|
7936
|
+
left: Math.max(defaultLeft, neededLeft)
|
|
7915
7937
|
};
|
|
7916
7938
|
const plotArea = {
|
|
7917
7939
|
x: margins.left,
|
|
@@ -8125,7 +8147,9 @@ function renderToCanvas(spec, options) {
|
|
|
8125
8147
|
renderTitle(canvas, spec.labels.title, layout.width, spec.theme);
|
|
8126
8148
|
}
|
|
8127
8149
|
renderGridLines(canvas, scales, layout.plotArea, spec.theme);
|
|
8128
|
-
|
|
8150
|
+
const isForest = spec.geoms.some((g) => g.type === "forest");
|
|
8151
|
+
const axisLabels = isForest ? { ...spec.labels, y: undefined } : spec.labels;
|
|
8152
|
+
renderAxes(canvas, scales, layout.plotArea, axisLabels, spec.theme);
|
|
8129
8153
|
for (const geom of spec.geoms) {
|
|
8130
8154
|
let geomData;
|
|
8131
8155
|
let geomAes = spec.aes;
|
|
@@ -14412,11 +14436,6 @@ var init_src = __esm(() => {
|
|
|
14412
14436
|
init_export();
|
|
14413
14437
|
});
|
|
14414
14438
|
|
|
14415
|
-
// src/cli-plot.ts
|
|
14416
|
-
init_src();
|
|
14417
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
14418
|
-
import { join as join3 } from "path";
|
|
14419
|
-
|
|
14420
14439
|
// src/history/index.ts
|
|
14421
14440
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, readdirSync } from "fs";
|
|
14422
14441
|
import { join } from "path";
|
|
@@ -14573,6 +14592,652 @@ function getLatestPlotId() {
|
|
|
14573
14592
|
}
|
|
14574
14593
|
return history[history.length - 1].id;
|
|
14575
14594
|
}
|
|
14595
|
+
var init_history = () => {};
|
|
14596
|
+
|
|
14597
|
+
// src/serve.ts
|
|
14598
|
+
var exports_serve = {};
|
|
14599
|
+
__export(exports_serve, {
|
|
14600
|
+
handleServe: () => handleServe
|
|
14601
|
+
});
|
|
14602
|
+
import { watch, writeFileSync as writeFileSync3, unlinkSync } from "fs";
|
|
14603
|
+
import { join as join3 } from "path";
|
|
14604
|
+
import { createServer } from "http";
|
|
14605
|
+
import { createHash } from "crypto";
|
|
14606
|
+
import { spawn } from "child_process";
|
|
14607
|
+
function plotToVegaLite(plot) {
|
|
14608
|
+
const geomTypes = plot._provenance.geomTypes;
|
|
14609
|
+
const hasCompositeMark = geomTypes.some((t) => COMPOSITE_MARKS.has(t));
|
|
14610
|
+
const spec = plotSpecToVegaLite(plot.spec, { interactive: !hasCompositeMark });
|
|
14611
|
+
return { spec, provenance: plot._provenance };
|
|
14612
|
+
}
|
|
14613
|
+
function getLatestPayload() {
|
|
14614
|
+
const id = getLatestPlotId();
|
|
14615
|
+
if (!id)
|
|
14616
|
+
return null;
|
|
14617
|
+
const plot = loadPlotFromHistory(id);
|
|
14618
|
+
if (!plot)
|
|
14619
|
+
return null;
|
|
14620
|
+
const { spec, provenance } = plotToVegaLite(plot);
|
|
14621
|
+
return JSON.stringify({ type: "plot", spec, provenance });
|
|
14622
|
+
}
|
|
14623
|
+
function encodeWebSocketFrame(data) {
|
|
14624
|
+
const payload = Buffer.from(data, "utf-8");
|
|
14625
|
+
const len = payload.length;
|
|
14626
|
+
let header;
|
|
14627
|
+
if (len < 126) {
|
|
14628
|
+
header = Buffer.alloc(2);
|
|
14629
|
+
header[0] = 129;
|
|
14630
|
+
header[1] = len;
|
|
14631
|
+
} else if (len < 65536) {
|
|
14632
|
+
header = Buffer.alloc(4);
|
|
14633
|
+
header[0] = 129;
|
|
14634
|
+
header[1] = 126;
|
|
14635
|
+
header.writeUInt16BE(len, 2);
|
|
14636
|
+
} else {
|
|
14637
|
+
header = Buffer.alloc(10);
|
|
14638
|
+
header[0] = 129;
|
|
14639
|
+
header[1] = 127;
|
|
14640
|
+
header.writeBigUInt64BE(BigInt(len), 2);
|
|
14641
|
+
}
|
|
14642
|
+
return Buffer.concat([header, payload]);
|
|
14643
|
+
}
|
|
14644
|
+
function jsonResponse(res, data, status = 200) {
|
|
14645
|
+
const body = JSON.stringify(data);
|
|
14646
|
+
res.writeHead(status, { "content-type": "application/json" });
|
|
14647
|
+
res.end(body);
|
|
14648
|
+
}
|
|
14649
|
+
function handleServe(port) {
|
|
14650
|
+
const p = port || 4242;
|
|
14651
|
+
ensureHistoryDirs();
|
|
14652
|
+
const clients = new Set;
|
|
14653
|
+
let debounceTimer = null;
|
|
14654
|
+
const plotsDir = getPlotsDir();
|
|
14655
|
+
watch(plotsDir, (_event, filename) => {
|
|
14656
|
+
if (!filename || !filename.endsWith(".json"))
|
|
14657
|
+
return;
|
|
14658
|
+
if (debounceTimer)
|
|
14659
|
+
clearTimeout(debounceTimer);
|
|
14660
|
+
debounceTimer = setTimeout(() => {
|
|
14661
|
+
const payload = getLatestPayload();
|
|
14662
|
+
if (!payload)
|
|
14663
|
+
return;
|
|
14664
|
+
const frame = encodeWebSocketFrame(payload);
|
|
14665
|
+
for (const client of clients) {
|
|
14666
|
+
try {
|
|
14667
|
+
client.write(frame);
|
|
14668
|
+
} catch {
|
|
14669
|
+
clients.delete(client);
|
|
14670
|
+
}
|
|
14671
|
+
}
|
|
14672
|
+
}, 150);
|
|
14673
|
+
});
|
|
14674
|
+
const server = createServer((req, res) => {
|
|
14675
|
+
const url = new URL(req.url || "/", `http://localhost:${p}`);
|
|
14676
|
+
if (url.pathname === "/api/latest") {
|
|
14677
|
+
const payload = getLatestPayload();
|
|
14678
|
+
if (!payload)
|
|
14679
|
+
return jsonResponse(res, { type: "empty" });
|
|
14680
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
14681
|
+
res.end(payload);
|
|
14682
|
+
return;
|
|
14683
|
+
}
|
|
14684
|
+
if (url.pathname === "/api/history") {
|
|
14685
|
+
const entries = getHistory().slice(-50);
|
|
14686
|
+
jsonResponse(res, entries);
|
|
14687
|
+
return;
|
|
14688
|
+
}
|
|
14689
|
+
if (url.pathname.startsWith("/api/plot/")) {
|
|
14690
|
+
const id = url.pathname.slice("/api/plot/".length);
|
|
14691
|
+
const plot = loadPlotFromHistory(id);
|
|
14692
|
+
if (!plot)
|
|
14693
|
+
return jsonResponse(res, { error: "not found" }, 404);
|
|
14694
|
+
const { spec, provenance } = plotToVegaLite(plot);
|
|
14695
|
+
jsonResponse(res, { type: "plot", spec, provenance });
|
|
14696
|
+
return;
|
|
14697
|
+
}
|
|
14698
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
14699
|
+
res.end(CLIENT_HTML);
|
|
14700
|
+
});
|
|
14701
|
+
server.on("upgrade", (req, socket, _head) => {
|
|
14702
|
+
const url = new URL(req.url || "/", `http://localhost:${p}`);
|
|
14703
|
+
if (url.pathname !== "/ws") {
|
|
14704
|
+
socket.destroy();
|
|
14705
|
+
return;
|
|
14706
|
+
}
|
|
14707
|
+
const key = req.headers["sec-websocket-key"];
|
|
14708
|
+
if (!key) {
|
|
14709
|
+
socket.destroy();
|
|
14710
|
+
return;
|
|
14711
|
+
}
|
|
14712
|
+
const accept = createHash("sha1").update(key + "258EAFA5-E914-47DA-95CA-5AB5DC85B7A8").digest("base64");
|
|
14713
|
+
socket.write(`HTTP/1.1 101 Switching Protocols\r
|
|
14714
|
+
` + `Upgrade: websocket\r
|
|
14715
|
+
` + `Connection: Upgrade\r
|
|
14716
|
+
` + `Sec-WebSocket-Accept: ${accept}\r
|
|
14717
|
+
` + `\r
|
|
14718
|
+
`);
|
|
14719
|
+
clients.add(socket);
|
|
14720
|
+
const payload = getLatestPayload();
|
|
14721
|
+
if (payload)
|
|
14722
|
+
socket.write(encodeWebSocketFrame(payload));
|
|
14723
|
+
socket.on("close", () => clients.delete(socket));
|
|
14724
|
+
socket.on("error", () => clients.delete(socket));
|
|
14725
|
+
socket.on("data", (data) => {
|
|
14726
|
+
if (data.length < 2)
|
|
14727
|
+
return;
|
|
14728
|
+
const opcode = data[0] & 15;
|
|
14729
|
+
if (opcode === 8) {
|
|
14730
|
+
const closeFrame = Buffer.alloc(2);
|
|
14731
|
+
closeFrame[0] = 136;
|
|
14732
|
+
closeFrame[1] = 0;
|
|
14733
|
+
try {
|
|
14734
|
+
socket.write(closeFrame);
|
|
14735
|
+
} catch {}
|
|
14736
|
+
socket.end();
|
|
14737
|
+
clients.delete(socket);
|
|
14738
|
+
return;
|
|
14739
|
+
}
|
|
14740
|
+
if (opcode === 9) {
|
|
14741
|
+
const pong = Buffer.from(data);
|
|
14742
|
+
pong[0] = pong[0] & 240 | 10;
|
|
14743
|
+
try {
|
|
14744
|
+
socket.write(pong);
|
|
14745
|
+
} catch {}
|
|
14746
|
+
}
|
|
14747
|
+
});
|
|
14748
|
+
});
|
|
14749
|
+
server.listen(p, () => {
|
|
14750
|
+
const url = `http://localhost:${p}`;
|
|
14751
|
+
console.log(`ggterm live viewer running at ${url}`);
|
|
14752
|
+
const markerPath = join3(getGGTermDir(), "serve.json");
|
|
14753
|
+
writeFileSync3(markerPath, JSON.stringify({ port: p, pid: process.pid }));
|
|
14754
|
+
const cleanup = () => {
|
|
14755
|
+
try {
|
|
14756
|
+
unlinkSync(markerPath);
|
|
14757
|
+
} catch {}
|
|
14758
|
+
};
|
|
14759
|
+
process.on("SIGINT", () => {
|
|
14760
|
+
cleanup();
|
|
14761
|
+
process.exit(0);
|
|
14762
|
+
});
|
|
14763
|
+
process.on("SIGTERM", () => {
|
|
14764
|
+
cleanup();
|
|
14765
|
+
process.exit(0);
|
|
14766
|
+
});
|
|
14767
|
+
process.on("exit", cleanup);
|
|
14768
|
+
if (process.env.TERM_PROGRAM === "waveterm") {
|
|
14769
|
+
spawn("wsh", ["web", "open", url], { stdio: "ignore", detached: true }).unref();
|
|
14770
|
+
console.log(`Opened Wave panel`);
|
|
14771
|
+
} else {
|
|
14772
|
+
console.log(`Open in browser or Wave panel: wsh web open ${url}`);
|
|
14773
|
+
}
|
|
14774
|
+
console.log(`Watching ${plotsDir} for new plots...`);
|
|
14775
|
+
console.log(`Press Ctrl+C to stop`);
|
|
14776
|
+
});
|
|
14777
|
+
}
|
|
14778
|
+
var COMPOSITE_MARKS, CLIENT_HTML = `<!DOCTYPE html>
|
|
14779
|
+
<html lang="en">
|
|
14780
|
+
<head>
|
|
14781
|
+
<meta charset="utf-8">
|
|
14782
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
14783
|
+
<title>ggterm</title>
|
|
14784
|
+
<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
|
|
14785
|
+
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
|
|
14786
|
+
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
|
|
14787
|
+
<style>
|
|
14788
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
14789
|
+
body {
|
|
14790
|
+
font-family: -apple-system, BlinkMacSystemFont, 'SF Mono', Menlo, monospace;
|
|
14791
|
+
background: #0d1117;
|
|
14792
|
+
color: #c9d1d9;
|
|
14793
|
+
height: 100vh;
|
|
14794
|
+
display: flex;
|
|
14795
|
+
overflow: hidden;
|
|
14796
|
+
}
|
|
14797
|
+
#sidebar {
|
|
14798
|
+
width: 260px;
|
|
14799
|
+
background: #161b22;
|
|
14800
|
+
border-right: 1px solid #30363d;
|
|
14801
|
+
display: flex;
|
|
14802
|
+
flex-direction: column;
|
|
14803
|
+
flex-shrink: 0;
|
|
14804
|
+
transform: translateX(-260px);
|
|
14805
|
+
transition: transform 0.2s ease;
|
|
14806
|
+
position: absolute;
|
|
14807
|
+
top: 0;
|
|
14808
|
+
left: 0;
|
|
14809
|
+
bottom: 0;
|
|
14810
|
+
z-index: 10;
|
|
14811
|
+
}
|
|
14812
|
+
#sidebar.open { transform: translateX(0); }
|
|
14813
|
+
#sidebar-header {
|
|
14814
|
+
padding: 12px;
|
|
14815
|
+
border-bottom: 1px solid #30363d;
|
|
14816
|
+
display: flex;
|
|
14817
|
+
align-items: center;
|
|
14818
|
+
justify-content: space-between;
|
|
14819
|
+
font-size: 12px;
|
|
14820
|
+
font-weight: 600;
|
|
14821
|
+
color: #c9d1d9;
|
|
14822
|
+
}
|
|
14823
|
+
#sidebar-header button {
|
|
14824
|
+
background: none;
|
|
14825
|
+
border: none;
|
|
14826
|
+
color: #8b949e;
|
|
14827
|
+
cursor: pointer;
|
|
14828
|
+
font-size: 14px;
|
|
14829
|
+
padding: 2px 6px;
|
|
14830
|
+
}
|
|
14831
|
+
#sidebar-header button:hover { color: #c9d1d9; }
|
|
14832
|
+
#history-list {
|
|
14833
|
+
flex: 1;
|
|
14834
|
+
overflow-y: auto;
|
|
14835
|
+
padding: 4px 0;
|
|
14836
|
+
}
|
|
14837
|
+
#history-list::-webkit-scrollbar { width: 6px; }
|
|
14838
|
+
#history-list::-webkit-scrollbar-track { background: transparent; }
|
|
14839
|
+
#history-list::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; }
|
|
14840
|
+
.history-item {
|
|
14841
|
+
padding: 8px 12px;
|
|
14842
|
+
cursor: pointer;
|
|
14843
|
+
border-left: 2px solid transparent;
|
|
14844
|
+
transition: background 0.1s;
|
|
14845
|
+
}
|
|
14846
|
+
.history-item:hover { background: #21262d; }
|
|
14847
|
+
.history-item.active { background: #1c2128; border-left-color: #58a6ff; }
|
|
14848
|
+
.history-item .hi-id { font-size: 11px; color: #58a6ff; font-weight: 600; }
|
|
14849
|
+
.history-item .hi-desc { font-size: 11px; color: #8b949e; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
14850
|
+
.history-item .hi-meta { font-size: 10px; color: #484f58; margin-top: 2px; display: flex; gap: 8px; }
|
|
14851
|
+
.history-item .hi-geom {
|
|
14852
|
+
background: #21262d;
|
|
14853
|
+
border: 1px solid #30363d;
|
|
14854
|
+
border-radius: 3px;
|
|
14855
|
+
padding: 0 4px;
|
|
14856
|
+
font-size: 10px;
|
|
14857
|
+
color: #8b949e;
|
|
14858
|
+
}
|
|
14859
|
+
#main {
|
|
14860
|
+
flex: 1;
|
|
14861
|
+
display: flex;
|
|
14862
|
+
flex-direction: column;
|
|
14863
|
+
min-width: 0;
|
|
14864
|
+
}
|
|
14865
|
+
#vis {
|
|
14866
|
+
flex: 1;
|
|
14867
|
+
display: flex;
|
|
14868
|
+
align-items: center;
|
|
14869
|
+
justify-content: center;
|
|
14870
|
+
padding: 16px;
|
|
14871
|
+
}
|
|
14872
|
+
#vis .vega-embed { width: 100%; }
|
|
14873
|
+
#vis .vega-embed canvas,
|
|
14874
|
+
#vis .vega-embed svg {
|
|
14875
|
+
max-width: 100%;
|
|
14876
|
+
max-height: calc(100vh - 80px);
|
|
14877
|
+
}
|
|
14878
|
+
#bar {
|
|
14879
|
+
display: flex;
|
|
14880
|
+
align-items: center;
|
|
14881
|
+
justify-content: space-between;
|
|
14882
|
+
padding: 8px 16px;
|
|
14883
|
+
background: #161b22;
|
|
14884
|
+
border-top: 1px solid #30363d;
|
|
14885
|
+
font-size: 12px;
|
|
14886
|
+
gap: 12px;
|
|
14887
|
+
min-height: 40px;
|
|
14888
|
+
}
|
|
14889
|
+
#meta { display: flex; gap: 16px; align-items: center; flex: 1; min-width: 0; }
|
|
14890
|
+
#plot-id { color: #58a6ff; font-weight: 600; }
|
|
14891
|
+
#plot-desc { color: #8b949e; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
14892
|
+
#plot-time { color: #484f58; }
|
|
14893
|
+
#nav { display: flex; gap: 4px; align-items: center; }
|
|
14894
|
+
.bar-btn {
|
|
14895
|
+
background: #21262d;
|
|
14896
|
+
border: 1px solid #30363d;
|
|
14897
|
+
color: #c9d1d9;
|
|
14898
|
+
border-radius: 4px;
|
|
14899
|
+
padding: 4px 10px;
|
|
14900
|
+
cursor: pointer;
|
|
14901
|
+
font-size: 12px;
|
|
14902
|
+
font-family: inherit;
|
|
14903
|
+
}
|
|
14904
|
+
.bar-btn:hover { background: #30363d; }
|
|
14905
|
+
.bar-btn:disabled { opacity: 0.3; cursor: default; }
|
|
14906
|
+
.bar-btn:disabled:hover { background: #21262d; }
|
|
14907
|
+
.bar-btn.active { background: #30363d; border-color: #58a6ff; }
|
|
14908
|
+
#actions { display: flex; gap: 4px; align-items: center; }
|
|
14909
|
+
#actions button {
|
|
14910
|
+
background: none;
|
|
14911
|
+
border: 1px solid #30363d;
|
|
14912
|
+
color: #8b949e;
|
|
14913
|
+
border-radius: 4px;
|
|
14914
|
+
padding: 4px 8px;
|
|
14915
|
+
cursor: pointer;
|
|
14916
|
+
font-size: 11px;
|
|
14917
|
+
font-family: inherit;
|
|
14918
|
+
}
|
|
14919
|
+
#actions button:hover { color: #c9d1d9; border-color: #58a6ff; }
|
|
14920
|
+
#status {
|
|
14921
|
+
width: 8px; height: 8px;
|
|
14922
|
+
border-radius: 50%;
|
|
14923
|
+
background: #f85149;
|
|
14924
|
+
flex-shrink: 0;
|
|
14925
|
+
}
|
|
14926
|
+
#status.connected { background: #3fb950; }
|
|
14927
|
+
.waiting {
|
|
14928
|
+
color: #484f58;
|
|
14929
|
+
font-size: 14px;
|
|
14930
|
+
text-align: center;
|
|
14931
|
+
}
|
|
14932
|
+
.waiting .hint { font-size: 12px; margin-top: 8px; color: #30363d; }
|
|
14933
|
+
#shortcuts {
|
|
14934
|
+
display: none;
|
|
14935
|
+
position: fixed;
|
|
14936
|
+
top: 50%;
|
|
14937
|
+
left: 50%;
|
|
14938
|
+
transform: translate(-50%, -50%);
|
|
14939
|
+
background: #161b22;
|
|
14940
|
+
border: 1px solid #30363d;
|
|
14941
|
+
border-radius: 8px;
|
|
14942
|
+
padding: 20px 24px;
|
|
14943
|
+
z-index: 20;
|
|
14944
|
+
font-size: 12px;
|
|
14945
|
+
min-width: 220px;
|
|
14946
|
+
}
|
|
14947
|
+
#shortcuts.open { display: block; }
|
|
14948
|
+
#shortcuts h3 { font-size: 13px; margin-bottom: 12px; color: #c9d1d9; }
|
|
14949
|
+
.shortcut-row { display: flex; justify-content: space-between; padding: 4px 0; }
|
|
14950
|
+
.shortcut-row kbd {
|
|
14951
|
+
background: #21262d;
|
|
14952
|
+
border: 1px solid #30363d;
|
|
14953
|
+
border-radius: 3px;
|
|
14954
|
+
padding: 1px 6px;
|
|
14955
|
+
font-family: inherit;
|
|
14956
|
+
font-size: 11px;
|
|
14957
|
+
color: #c9d1d9;
|
|
14958
|
+
}
|
|
14959
|
+
.shortcut-row span { color: #8b949e; }
|
|
14960
|
+
#overlay {
|
|
14961
|
+
display: none;
|
|
14962
|
+
position: fixed;
|
|
14963
|
+
inset: 0;
|
|
14964
|
+
background: rgba(0,0,0,0.5);
|
|
14965
|
+
z-index: 15;
|
|
14966
|
+
}
|
|
14967
|
+
#overlay.open { display: block; }
|
|
14968
|
+
</style>
|
|
14969
|
+
</head>
|
|
14970
|
+
<body>
|
|
14971
|
+
<div id="sidebar">
|
|
14972
|
+
<div id="sidebar-header">
|
|
14973
|
+
<span>History</span>
|
|
14974
|
+
<button onclick="toggleHistory()">×</button>
|
|
14975
|
+
</div>
|
|
14976
|
+
<div id="history-list"></div>
|
|
14977
|
+
</div>
|
|
14978
|
+
<div id="main">
|
|
14979
|
+
<div id="vis">
|
|
14980
|
+
<div class="waiting">
|
|
14981
|
+
<div>waiting for plots...</div>
|
|
14982
|
+
<div class="hint">create a plot in ggterm and it will appear here</div>
|
|
14983
|
+
</div>
|
|
14984
|
+
</div>
|
|
14985
|
+
<div id="bar">
|
|
14986
|
+
<div id="status"></div>
|
|
14987
|
+
<div id="meta">
|
|
14988
|
+
<span id="plot-id"></span>
|
|
14989
|
+
<span id="plot-desc"></span>
|
|
14990
|
+
<span id="plot-time"></span>
|
|
14991
|
+
</div>
|
|
14992
|
+
<div id="nav">
|
|
14993
|
+
<button id="hist-btn" class="bar-btn" onclick="toggleHistory()" title="History (h)">H</button>
|
|
14994
|
+
<button id="prev" class="bar-btn" disabled title="Previous plot (←)">←</button>
|
|
14995
|
+
<button id="next" class="bar-btn" disabled title="Next plot (→)">→</button>
|
|
14996
|
+
</div>
|
|
14997
|
+
<div id="actions">
|
|
14998
|
+
<button onclick="downloadSVG()" title="Download SVG (s)">SVG</button>
|
|
14999
|
+
<button onclick="downloadPNG()" title="Download PNG (p)">PNG</button>
|
|
15000
|
+
<button onclick="toggleShortcuts()" title="Keyboard shortcuts (?)">?</button>
|
|
15001
|
+
</div>
|
|
15002
|
+
</div>
|
|
15003
|
+
</div>
|
|
15004
|
+
<div id="overlay" onclick="closeOverlays()"></div>
|
|
15005
|
+
<div id="shortcuts">
|
|
15006
|
+
<h3>Keyboard Shortcuts</h3>
|
|
15007
|
+
<div class="shortcut-row"><span>Previous plot</span><kbd>←</kbd></div>
|
|
15008
|
+
<div class="shortcut-row"><span>Next plot</span><kbd>→</kbd></div>
|
|
15009
|
+
<div class="shortcut-row"><span>Latest plot</span><kbd>End</kbd></div>
|
|
15010
|
+
<div class="shortcut-row"><span>First plot</span><kbd>Home</kbd></div>
|
|
15011
|
+
<div class="shortcut-row"><span>Toggle history</span><kbd>h</kbd></div>
|
|
15012
|
+
<div class="shortcut-row"><span>Download SVG</span><kbd>s</kbd></div>
|
|
15013
|
+
<div class="shortcut-row"><span>Download PNG</span><kbd>p</kbd></div>
|
|
15014
|
+
<div class="shortcut-row"><span>Fullscreen</span><kbd>f</kbd></div>
|
|
15015
|
+
<div class="shortcut-row"><span>Show shortcuts</span><kbd>?</kbd></div>
|
|
15016
|
+
<div class="shortcut-row"><span>Close panel</span><kbd>Esc</kbd></div>
|
|
15017
|
+
</div>
|
|
15018
|
+
<script>
|
|
15019
|
+
const vis = document.getElementById('vis');
|
|
15020
|
+
const main = document.getElementById('main');
|
|
15021
|
+
const statusEl = document.getElementById('status');
|
|
15022
|
+
const idEl = document.getElementById('plot-id');
|
|
15023
|
+
const descEl = document.getElementById('plot-desc');
|
|
15024
|
+
const timeEl = document.getElementById('plot-time');
|
|
15025
|
+
const prevBtn = document.getElementById('prev');
|
|
15026
|
+
const nextBtn = document.getElementById('next');
|
|
15027
|
+
const histBtn = document.getElementById('hist-btn');
|
|
15028
|
+
const sidebar = document.getElementById('sidebar');
|
|
15029
|
+
const historyList = document.getElementById('history-list');
|
|
15030
|
+
const shortcutsEl = document.getElementById('shortcuts');
|
|
15031
|
+
const overlayEl = document.getElementById('overlay');
|
|
15032
|
+
|
|
15033
|
+
let history = [];
|
|
15034
|
+
let historyIndex = {};
|
|
15035
|
+
let currentIdx = -1;
|
|
15036
|
+
let view = null;
|
|
15037
|
+
let ws = null;
|
|
15038
|
+
|
|
15039
|
+
function updateMeta(prov) {
|
|
15040
|
+
if (!prov) return;
|
|
15041
|
+
idEl.textContent = prov.id;
|
|
15042
|
+
descEl.textContent = prov.description || '';
|
|
15043
|
+
timeEl.textContent = prov.timestamp ? new Date(prov.timestamp).toLocaleTimeString() : '';
|
|
15044
|
+
}
|
|
15045
|
+
|
|
15046
|
+
function updateNav() {
|
|
15047
|
+
prevBtn.disabled = currentIdx <= 0;
|
|
15048
|
+
nextBtn.disabled = currentIdx >= history.length - 1;
|
|
15049
|
+
}
|
|
15050
|
+
|
|
15051
|
+
function updateHistoryHighlight() {
|
|
15052
|
+
historyList.querySelectorAll('.history-item').forEach((el, i) => {
|
|
15053
|
+
el.classList.toggle('active', i === currentIdx);
|
|
15054
|
+
});
|
|
15055
|
+
const active = historyList.querySelector('.active');
|
|
15056
|
+
if (active) active.scrollIntoView({ block: 'nearest' });
|
|
15057
|
+
}
|
|
15058
|
+
|
|
15059
|
+
function addHistoryItem(data, idx) {
|
|
15060
|
+
const prov = data.provenance;
|
|
15061
|
+
if (!prov) return;
|
|
15062
|
+
const div = document.createElement('div');
|
|
15063
|
+
div.className = 'history-item' + (idx === currentIdx ? ' active' : '');
|
|
15064
|
+
div.innerHTML =
|
|
15065
|
+
'<div class="hi-id">' + prov.id + '</div>' +
|
|
15066
|
+
'<div class="hi-desc">' + (prov.description || '') + '</div>' +
|
|
15067
|
+
'<div class="hi-meta">' +
|
|
15068
|
+
'<span class="hi-geom">' + (prov.geomTypes ? prov.geomTypes.join('+') : '') + '</span>' +
|
|
15069
|
+
'<span>' + (prov.timestamp ? new Date(prov.timestamp).toLocaleTimeString() : '') + '</span>' +
|
|
15070
|
+
'</div>';
|
|
15071
|
+
div.onclick = () => navigate(idx);
|
|
15072
|
+
historyList.appendChild(div);
|
|
15073
|
+
}
|
|
15074
|
+
|
|
15075
|
+
function rebuildHistoryList() {
|
|
15076
|
+
historyList.innerHTML = '';
|
|
15077
|
+
history.forEach((data, i) => addHistoryItem(data, i));
|
|
15078
|
+
}
|
|
15079
|
+
|
|
15080
|
+
const embedOpts = {
|
|
15081
|
+
actions: false,
|
|
15082
|
+
theme: 'dark',
|
|
15083
|
+
renderer: 'svg',
|
|
15084
|
+
config: {
|
|
15085
|
+
background: '#0d1117',
|
|
15086
|
+
axis: { domainColor: '#30363d', gridColor: '#21262d', tickColor: '#30363d', labelColor: '#8b949e', titleColor: '#c9d1d9' },
|
|
15087
|
+
legend: { labelColor: '#c9d1d9', titleColor: '#c9d1d9' },
|
|
15088
|
+
title: { color: '#c9d1d9', subtitleColor: '#8b949e' },
|
|
15089
|
+
view: { stroke: null }
|
|
15090
|
+
}
|
|
15091
|
+
};
|
|
15092
|
+
|
|
15093
|
+
async function renderSpec(spec) {
|
|
15094
|
+
vis.innerHTML = '';
|
|
15095
|
+
const vegaSpec = { ...spec, width: 'container', height: 'container', autosize: { type: 'fit', contains: 'padding' } };
|
|
15096
|
+
try {
|
|
15097
|
+
const result = await vegaEmbed(vis, vegaSpec, embedOpts);
|
|
15098
|
+
view = result.view;
|
|
15099
|
+
} catch (e) {
|
|
15100
|
+
// Retry without interactive params (composite marks like boxplot don't support selections)
|
|
15101
|
+
console.warn('Render failed, retrying without params:', e.message);
|
|
15102
|
+
const { params, ...cleanSpec } = vegaSpec;
|
|
15103
|
+
const result = await vegaEmbed(vis, cleanSpec, embedOpts);
|
|
15104
|
+
view = result.view;
|
|
15105
|
+
}
|
|
15106
|
+
}
|
|
15107
|
+
|
|
15108
|
+
async function showPlot(data) {
|
|
15109
|
+
await renderSpec(data.spec);
|
|
15110
|
+
updateMeta(data.provenance);
|
|
15111
|
+
}
|
|
15112
|
+
|
|
15113
|
+
function navigate(idx) {
|
|
15114
|
+
if (idx < 0 || idx >= history.length) return;
|
|
15115
|
+
currentIdx = idx;
|
|
15116
|
+
const data = history[idx];
|
|
15117
|
+
if (data.spec) {
|
|
15118
|
+
showPlot(data);
|
|
15119
|
+
} else {
|
|
15120
|
+
// Lazy-load full spec from server
|
|
15121
|
+
fetch('/api/plot/' + data.provenance.id)
|
|
15122
|
+
.then(r => r.json())
|
|
15123
|
+
.then(full => {
|
|
15124
|
+
history[idx] = full;
|
|
15125
|
+
showPlot(full);
|
|
15126
|
+
});
|
|
15127
|
+
}
|
|
15128
|
+
updateNav();
|
|
15129
|
+
updateHistoryHighlight();
|
|
15130
|
+
}
|
|
15131
|
+
|
|
15132
|
+
prevBtn.onclick = () => navigate(currentIdx - 1);
|
|
15133
|
+
nextBtn.onclick = () => navigate(currentIdx + 1);
|
|
15134
|
+
|
|
15135
|
+
function toggleHistory() {
|
|
15136
|
+
const open = sidebar.classList.toggle('open');
|
|
15137
|
+
histBtn.classList.toggle('active', open);
|
|
15138
|
+
}
|
|
15139
|
+
|
|
15140
|
+
function toggleShortcuts() {
|
|
15141
|
+
const open = shortcutsEl.classList.toggle('open');
|
|
15142
|
+
overlayEl.classList.toggle('open', open);
|
|
15143
|
+
}
|
|
15144
|
+
|
|
15145
|
+
function closeOverlays() {
|
|
15146
|
+
shortcutsEl.classList.remove('open');
|
|
15147
|
+
overlayEl.classList.remove('open');
|
|
15148
|
+
}
|
|
15149
|
+
|
|
15150
|
+
document.addEventListener('keydown', (e) => {
|
|
15151
|
+
// Ignore when typing in an input
|
|
15152
|
+
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
|
|
15153
|
+
|
|
15154
|
+
switch (e.key) {
|
|
15155
|
+
case 'ArrowLeft': navigate(currentIdx - 1); break;
|
|
15156
|
+
case 'ArrowRight': navigate(currentIdx + 1); break;
|
|
15157
|
+
case 'Home': e.preventDefault(); navigate(0); break;
|
|
15158
|
+
case 'End': e.preventDefault(); navigate(history.length - 1); break;
|
|
15159
|
+
case 'h': toggleHistory(); break;
|
|
15160
|
+
case 's': downloadSVG(); break;
|
|
15161
|
+
case 'p': downloadPNG(); break;
|
|
15162
|
+
case 'f':
|
|
15163
|
+
if (!document.fullscreenElement) {
|
|
15164
|
+
document.documentElement.requestFullscreen();
|
|
15165
|
+
} else {
|
|
15166
|
+
document.exitFullscreen();
|
|
15167
|
+
}
|
|
15168
|
+
break;
|
|
15169
|
+
case '?': toggleShortcuts(); break;
|
|
15170
|
+
case 'Escape': closeOverlays(); if (sidebar.classList.contains('open')) toggleHistory(); break;
|
|
15171
|
+
}
|
|
15172
|
+
});
|
|
15173
|
+
|
|
15174
|
+
function downloadSVG() {
|
|
15175
|
+
if (!view) return;
|
|
15176
|
+
view.toSVG().then(svg => {
|
|
15177
|
+
const a = document.createElement('a');
|
|
15178
|
+
a.href = URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));
|
|
15179
|
+
a.download = (idEl.textContent || 'plot') + '.svg';
|
|
15180
|
+
a.click();
|
|
15181
|
+
});
|
|
15182
|
+
}
|
|
15183
|
+
|
|
15184
|
+
function downloadPNG() {
|
|
15185
|
+
if (!view) return;
|
|
15186
|
+
view.toCanvas(2).then(canvas => {
|
|
15187
|
+
const a = document.createElement('a');
|
|
15188
|
+
a.href = canvas.toDataURL('image/png');
|
|
15189
|
+
a.download = (idEl.textContent || 'plot') + '.png';
|
|
15190
|
+
a.click();
|
|
15191
|
+
});
|
|
15192
|
+
}
|
|
15193
|
+
|
|
15194
|
+
function connect() {
|
|
15195
|
+
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
15196
|
+
ws = new WebSocket(proto + '//' + location.host + '/ws');
|
|
15197
|
+
|
|
15198
|
+
ws.onopen = () => { statusEl.classList.add('connected'); };
|
|
15199
|
+
ws.onclose = () => {
|
|
15200
|
+
statusEl.classList.remove('connected');
|
|
15201
|
+
setTimeout(connect, 2000);
|
|
15202
|
+
};
|
|
15203
|
+
ws.onerror = () => ws.close();
|
|
15204
|
+
|
|
15205
|
+
ws.onmessage = (e) => {
|
|
15206
|
+
const data = JSON.parse(e.data);
|
|
15207
|
+
if (data.type === 'plot') {
|
|
15208
|
+
history.push(data);
|
|
15209
|
+
currentIdx = history.length - 1;
|
|
15210
|
+
addHistoryItem(data, history.length - 1);
|
|
15211
|
+
showPlot(data);
|
|
15212
|
+
updateNav();
|
|
15213
|
+
updateHistoryHighlight();
|
|
15214
|
+
}
|
|
15215
|
+
};
|
|
15216
|
+
}
|
|
15217
|
+
|
|
15218
|
+
// Load initial history then connect
|
|
15219
|
+
fetch('/api/history')
|
|
15220
|
+
.then(r => r.json())
|
|
15221
|
+
.then(entries => {
|
|
15222
|
+
// Populate history with provenance-only stubs (lazy-load specs on navigate)
|
|
15223
|
+
history = entries.map(e => ({ provenance: e, spec: null }));
|
|
15224
|
+
rebuildHistoryList();
|
|
15225
|
+
})
|
|
15226
|
+
.then(() => connect());
|
|
15227
|
+
</script>
|
|
15228
|
+
</body>
|
|
15229
|
+
</html>`;
|
|
15230
|
+
var init_serve = __esm(() => {
|
|
15231
|
+
init_history();
|
|
15232
|
+
init_export();
|
|
15233
|
+
COMPOSITE_MARKS = new Set(["boxplot", "violin", "errorband", "errorbar"]);
|
|
15234
|
+
});
|
|
15235
|
+
|
|
15236
|
+
// src/cli-plot.ts
|
|
15237
|
+
init_src();
|
|
15238
|
+
init_history();
|
|
15239
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync4, existsSync as existsSync3 } from "fs";
|
|
15240
|
+
import { join as join4 } from "path";
|
|
14576
15241
|
|
|
14577
15242
|
// src/init.ts
|
|
14578
15243
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync2, existsSync as existsSync2, readdirSync as readdirSync2, statSync } from "fs";
|
|
@@ -15194,6 +15859,18 @@ function handleInit() {
|
|
|
15194
15859
|
}
|
|
15195
15860
|
|
|
15196
15861
|
// src/cli-plot.ts
|
|
15862
|
+
function isServeRunning() {
|
|
15863
|
+
const markerPath = join4(getGGTermDir(), "serve.json");
|
|
15864
|
+
if (!existsSync3(markerPath))
|
|
15865
|
+
return false;
|
|
15866
|
+
try {
|
|
15867
|
+
const info = JSON.parse(readFileSync3(markerPath, "utf-8"));
|
|
15868
|
+
process.kill(info.pid, 0);
|
|
15869
|
+
return true;
|
|
15870
|
+
} catch {
|
|
15871
|
+
return false;
|
|
15872
|
+
}
|
|
15873
|
+
}
|
|
15197
15874
|
var GEOM_TYPES = [
|
|
15198
15875
|
"point",
|
|
15199
15876
|
"line",
|
|
@@ -16043,15 +16720,22 @@ If you want a univariate plot, try: histogram, density, bar, qq, or freqpoly`);
|
|
|
16043
16720
|
if (facetVar && facetVar !== "-") {
|
|
16044
16721
|
plot = plot.facet(facet_wrap(facetVar));
|
|
16045
16722
|
}
|
|
16046
|
-
|
|
16723
|
+
const serveActive = isServeRunning();
|
|
16724
|
+
if (!serveActive) {
|
|
16725
|
+
console.log(plot.render({ width: 70, height: 20, colorMode: "truecolor" }));
|
|
16726
|
+
}
|
|
16047
16727
|
const spec = plot.spec();
|
|
16048
16728
|
const commandStr = `cli-plot.ts ${args.join(" ")}`;
|
|
16049
16729
|
const plotId = savePlotToHistory(spec, {
|
|
16050
16730
|
dataFile,
|
|
16051
16731
|
command: commandStr
|
|
16052
16732
|
});
|
|
16053
|
-
|
|
16733
|
+
if (serveActive) {
|
|
16734
|
+
console.log(`[${plotId}] → live viewer`);
|
|
16735
|
+
} else {
|
|
16736
|
+
console.log(`
|
|
16054
16737
|
[Saved as ${plotId}]`);
|
|
16738
|
+
}
|
|
16055
16739
|
}
|
|
16056
16740
|
function handleHistory(searchQuery) {
|
|
16057
16741
|
const entries = searchQuery ? searchHistory(searchQuery) : getHistory();
|
|
@@ -16130,7 +16814,7 @@ function handleExport(idOrFile, outputFile) {
|
|
|
16130
16814
|
const spec = plotSpecToVegaLite2(plotSpec, {
|
|
16131
16815
|
interactive: true
|
|
16132
16816
|
});
|
|
16133
|
-
|
|
16817
|
+
writeFileSync4(join4(getGGTermDir(), "last-plot-vegalite.json"), JSON.stringify(spec, null, 2));
|
|
16134
16818
|
const title = typeof spec.title === "string" ? spec.title : spec.title?.text || "Plot";
|
|
16135
16819
|
const output = outputFile || `${plotId}.html`;
|
|
16136
16820
|
const html = `<!DOCTYPE html>
|
|
@@ -16187,7 +16871,7 @@ function handleExport(idOrFile, outputFile) {
|
|
|
16187
16871
|
</script>
|
|
16188
16872
|
</body>
|
|
16189
16873
|
</html>`;
|
|
16190
|
-
|
|
16874
|
+
writeFileSync4(output, html);
|
|
16191
16875
|
console.log(`Created ${output} - open in browser to view and export`);
|
|
16192
16876
|
}
|
|
16193
16877
|
function printUsage() {
|
|
@@ -16201,6 +16885,7 @@ Commands:
|
|
|
16201
16885
|
history [search] List all plots (optionally filter by search)
|
|
16202
16886
|
show <id> Re-render a plot from history
|
|
16203
16887
|
export [id] [output.html] Export plot to HTML (latest or by ID)
|
|
16888
|
+
serve [port] Start live plot viewer (default: 4242)
|
|
16204
16889
|
<file> <x> <y> [color] [title] [geom] [facet] Create a plot
|
|
16205
16890
|
|
|
16206
16891
|
Supported formats: CSV, JSON, JSONL (auto-detected by extension)
|
|
@@ -16225,6 +16910,8 @@ Examples:
|
|
|
16225
16910
|
ggterm-plot history
|
|
16226
16911
|
ggterm-plot show 2024-01-26-001
|
|
16227
16912
|
ggterm-plot export 2024-01-26-001 figure.html
|
|
16913
|
+
ggterm-plot serve # Start live plot viewer
|
|
16914
|
+
ggterm-plot serve 8080 # Custom port
|
|
16228
16915
|
`);
|
|
16229
16916
|
}
|
|
16230
16917
|
var args = process.argv.slice(2);
|
|
@@ -16257,6 +16944,10 @@ if (command === "init") {
|
|
|
16257
16944
|
handleShow(args[1]);
|
|
16258
16945
|
} else if (command === "export") {
|
|
16259
16946
|
handleExport(args[1], args[2]);
|
|
16947
|
+
} else if (command === "serve") {
|
|
16948
|
+
Promise.resolve().then(() => (init_serve(), exports_serve)).then(({ handleServe: handleServe2 }) => {
|
|
16949
|
+
handleServe2(args[1] ? parseInt(args[1]) : undefined);
|
|
16950
|
+
});
|
|
16260
16951
|
} else if (command === "help" || command === "--help" || command === "-h") {
|
|
16261
16952
|
printUsage();
|
|
16262
16953
|
} else {
|
package/dist/cli.js
CHANGED
|
@@ -3708,7 +3708,7 @@ function renderGeomVolcano(data, geom, aes, scales, canvas) {
|
|
|
3708
3708
|
}
|
|
3709
3709
|
if (nLabels > 0 && aes.label) {
|
|
3710
3710
|
const significantPoints = points.filter((p) => p.status !== "ns" && p.label).sort((a, b) => b.significance - a.significance).slice(0, nLabels);
|
|
3711
|
-
const labelColor = { r:
|
|
3711
|
+
const labelColor = { r: 255, g: 255, b: 255, a: 1 };
|
|
3712
3712
|
for (const point of significantPoints) {
|
|
3713
3713
|
const cx = Math.round(scales.x.map(point.x));
|
|
3714
3714
|
const cy = Math.round(scales.y.map(point.y));
|
|
@@ -4486,6 +4486,16 @@ function renderGeomForest(data, geom, aes, scales, canvas) {
|
|
|
4486
4486
|
canvas.drawChar(x2, y, "┤", ciColor);
|
|
4487
4487
|
const px = Math.round(mapX(row.estimate));
|
|
4488
4488
|
canvas.drawChar(px, y, pointChar, pointColor);
|
|
4489
|
+
const label = row.study;
|
|
4490
|
+
const labelColor = { r: 200, g: 200, b: 200, a: 1 };
|
|
4491
|
+
const labelEnd = plotLeft - 1;
|
|
4492
|
+
const labelStart = labelEnd - label.length;
|
|
4493
|
+
for (let c = 0;c < label.length; c++) {
|
|
4494
|
+
const charX = labelStart + c;
|
|
4495
|
+
if (charX >= 0) {
|
|
4496
|
+
canvas.drawChar(charX, y, label[c], labelColor);
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4489
4499
|
}
|
|
4490
4500
|
}
|
|
4491
4501
|
function renderGeomRoc(data, geom, aes, scales, canvas) {
|
|
@@ -7907,11 +7917,23 @@ function calculateLayout(spec, options) {
|
|
|
7907
7917
|
} else if (hasY2) {
|
|
7908
7918
|
rightMargin = 8 + (hasY2Label ? 2 : 0);
|
|
7909
7919
|
}
|
|
7920
|
+
let forestLabelWidth = 0;
|
|
7921
|
+
const isForestPlot = spec.geoms.some((g) => g.type === "forest");
|
|
7922
|
+
if (isForestPlot && Array.isArray(spec.data) && spec.data.length > 0) {
|
|
7923
|
+
const yField = typeof spec.aes.y === "string" ? spec.aes.y : "study";
|
|
7924
|
+
for (const row of spec.data) {
|
|
7925
|
+
const label = String(row[yField] ?? "");
|
|
7926
|
+
if (label.length > forestLabelWidth)
|
|
7927
|
+
forestLabelWidth = label.length;
|
|
7928
|
+
}
|
|
7929
|
+
}
|
|
7930
|
+
const defaultLeft = 8 + (hasYLabel ? 2 : 0);
|
|
7931
|
+
const neededLeft = forestLabelWidth > 0 ? forestLabelWidth + 2 : defaultLeft;
|
|
7910
7932
|
const margins = {
|
|
7911
7933
|
top: hasTitle ? 2 : 1,
|
|
7912
7934
|
right: rightMargin,
|
|
7913
7935
|
bottom: 2 + (hasXLabel ? 1 : 0) + (hasLegend && legendPosition === "bottom" ? 2 : 0),
|
|
7914
|
-
left:
|
|
7936
|
+
left: Math.max(defaultLeft, neededLeft)
|
|
7915
7937
|
};
|
|
7916
7938
|
const plotArea = {
|
|
7917
7939
|
x: margins.left,
|
|
@@ -8125,7 +8147,9 @@ function renderToCanvas(spec, options) {
|
|
|
8125
8147
|
renderTitle(canvas, spec.labels.title, layout.width, spec.theme);
|
|
8126
8148
|
}
|
|
8127
8149
|
renderGridLines(canvas, scales, layout.plotArea, spec.theme);
|
|
8128
|
-
|
|
8150
|
+
const isForest = spec.geoms.some((g) => g.type === "forest");
|
|
8151
|
+
const axisLabels = isForest ? { ...spec.labels, y: undefined } : spec.labels;
|
|
8152
|
+
renderAxes(canvas, scales, layout.plotArea, axisLabels, spec.theme);
|
|
8129
8153
|
for (const geom of spec.geoms) {
|
|
8130
8154
|
let geomData;
|
|
8131
8155
|
let geomAes = spec.aes;
|
package/dist/index.js
CHANGED
|
@@ -3707,7 +3707,7 @@ function renderGeomVolcano(data, geom, aes, scales, canvas) {
|
|
|
3707
3707
|
}
|
|
3708
3708
|
if (nLabels > 0 && aes.label) {
|
|
3709
3709
|
const significantPoints = points.filter((p) => p.status !== "ns" && p.label).sort((a, b) => b.significance - a.significance).slice(0, nLabels);
|
|
3710
|
-
const labelColor = { r:
|
|
3710
|
+
const labelColor = { r: 255, g: 255, b: 255, a: 1 };
|
|
3711
3711
|
for (const point of significantPoints) {
|
|
3712
3712
|
const cx = Math.round(scales.x.map(point.x));
|
|
3713
3713
|
const cy = Math.round(scales.y.map(point.y));
|
|
@@ -4485,6 +4485,16 @@ function renderGeomForest(data, geom, aes, scales, canvas) {
|
|
|
4485
4485
|
canvas.drawChar(x2, y, "┤", ciColor);
|
|
4486
4486
|
const px = Math.round(mapX(row.estimate));
|
|
4487
4487
|
canvas.drawChar(px, y, pointChar, pointColor);
|
|
4488
|
+
const label = row.study;
|
|
4489
|
+
const labelColor = { r: 200, g: 200, b: 200, a: 1 };
|
|
4490
|
+
const labelEnd = plotLeft - 1;
|
|
4491
|
+
const labelStart = labelEnd - label.length;
|
|
4492
|
+
for (let c = 0;c < label.length; c++) {
|
|
4493
|
+
const charX = labelStart + c;
|
|
4494
|
+
if (charX >= 0) {
|
|
4495
|
+
canvas.drawChar(charX, y, label[c], labelColor);
|
|
4496
|
+
}
|
|
4497
|
+
}
|
|
4488
4498
|
}
|
|
4489
4499
|
}
|
|
4490
4500
|
function renderGeomRoc(data, geom, aes, scales, canvas) {
|
|
@@ -7906,11 +7916,23 @@ function calculateLayout(spec, options) {
|
|
|
7906
7916
|
} else if (hasY2) {
|
|
7907
7917
|
rightMargin = 8 + (hasY2Label ? 2 : 0);
|
|
7908
7918
|
}
|
|
7919
|
+
let forestLabelWidth = 0;
|
|
7920
|
+
const isForestPlot = spec.geoms.some((g) => g.type === "forest");
|
|
7921
|
+
if (isForestPlot && Array.isArray(spec.data) && spec.data.length > 0) {
|
|
7922
|
+
const yField = typeof spec.aes.y === "string" ? spec.aes.y : "study";
|
|
7923
|
+
for (const row of spec.data) {
|
|
7924
|
+
const label = String(row[yField] ?? "");
|
|
7925
|
+
if (label.length > forestLabelWidth)
|
|
7926
|
+
forestLabelWidth = label.length;
|
|
7927
|
+
}
|
|
7928
|
+
}
|
|
7929
|
+
const defaultLeft = 8 + (hasYLabel ? 2 : 0);
|
|
7930
|
+
const neededLeft = forestLabelWidth > 0 ? forestLabelWidth + 2 : defaultLeft;
|
|
7909
7931
|
const margins = {
|
|
7910
7932
|
top: hasTitle ? 2 : 1,
|
|
7911
7933
|
right: rightMargin,
|
|
7912
7934
|
bottom: 2 + (hasXLabel ? 1 : 0) + (hasLegend && legendPosition === "bottom" ? 2 : 0),
|
|
7913
|
-
left:
|
|
7935
|
+
left: Math.max(defaultLeft, neededLeft)
|
|
7914
7936
|
};
|
|
7915
7937
|
const plotArea = {
|
|
7916
7938
|
x: margins.left,
|
|
@@ -8124,7 +8146,9 @@ function renderToCanvas(spec, options) {
|
|
|
8124
8146
|
renderTitle(canvas, spec.labels.title, layout.width, spec.theme);
|
|
8125
8147
|
}
|
|
8126
8148
|
renderGridLines(canvas, scales, layout.plotArea, spec.theme);
|
|
8127
|
-
|
|
8149
|
+
const isForest = spec.geoms.some((g) => g.type === "forest");
|
|
8150
|
+
const axisLabels = isForest ? { ...spec.labels, y: undefined } : spec.labels;
|
|
8151
|
+
renderAxes(canvas, scales, layout.plotArea, axisLabels, spec.theme);
|
|
8128
8152
|
for (const geom of spec.geoms) {
|
|
8129
8153
|
let geomData;
|
|
8130
8154
|
let geomAes = spec.aes;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/pipeline/pipeline.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAA6C,QAAQ,EAAE,aAAa,EAAQ,MAAM,UAAU,CAAA;AACxG,OAAO,EAAE,cAAc,EAAgB,MAAM,kBAAkB,CAAA;AAmB/D;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,QAAQ,EAAE;QACR,CAAC,EAAE,MAAM,CAAA;QACT,CAAC,EAAE,MAAM,CAAA;QACT,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,UAAU,CAAC,EAAE;QACX,CAAC,EAAE,MAAM,CAAA;QACT,CAAC,EAAE,MAAM,CAAA;QACT,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,aAAa,GACrB,UAAU,
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/pipeline/pipeline.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAA6C,QAAQ,EAAE,aAAa,EAAQ,MAAM,UAAU,CAAA;AACxG,OAAO,EAAE,cAAc,EAAgB,MAAM,kBAAkB,CAAA;AAmB/D;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,QAAQ,EAAE;QACR,CAAC,EAAE,MAAM,CAAA;QACT,CAAC,EAAE,MAAM,CAAA;QACT,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,UAAU,CAAC,EAAE;QACX,CAAC,EAAE,MAAM,CAAA;QACT,CAAC,EAAE,MAAM,CAAA;QACT,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,aAAa,GACrB,UAAU,CA8EZ;AAwJD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,aAAa,GACrB,cAAc,CAmNhB;AAwcD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,aAAa,GACrB,MAAM,CASR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-geoms.d.ts","sourceRoot":"","sources":["../../src/pipeline/render-geoms.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,IAAI,EAAQ,MAAM,UAAU,CAAA;AACxE,OAAO,KAAK,EAAE,YAAY,EAAsB,MAAM,UAAU,CAAA;AAoGhE;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA8CN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,IAAI,EACX,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA2CN;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,IAAI,EACX,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAuCN;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAiFN;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAkEN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAwFN;AAwCD;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CAyIN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,IAAI,EACX,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAiBN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAWN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAWN;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,IAAI,EACX,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAiCN;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,IAAI,EACX,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAqDN;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA0GN;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA6GN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAmFN;AA+CD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAwGN;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA+JN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAmHN;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAgGN;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAmDN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAuDN;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA6BN;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAkCN;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAsFN;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA4BN;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAwFN;AA6BD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA6EN;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAgFN;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAkHN;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAwHN;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAmGN;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAqFN;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAkIN;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAkIN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA8JN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAsHN;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAsMN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CA0QN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAiIN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,cAAc,GACrB,IAAI,CAsIN;
|
|
1
|
+
{"version":3,"file":"render-geoms.d.ts","sourceRoot":"","sources":["../../src/pipeline/render-geoms.ts"],"names":[],"mappings":"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"}
|
package/dist/serve.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live plot viewer server
|
|
3
|
+
*
|
|
4
|
+
* Watches .ggterm/plots/ for new plots and pushes them to connected
|
|
5
|
+
* browsers via WebSocket. Renders interactive Vega-Lite in a dark-themed page.
|
|
6
|
+
*
|
|
7
|
+
* Uses node:http and a minimal WebSocket implementation for Node.js compatibility.
|
|
8
|
+
*/
|
|
9
|
+
export declare function handleServe(port?: number): void;
|
|
10
|
+
//# sourceMappingURL=serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA6gBH,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CA2I/C"}
|