Files
awesome-copilot/extensions/git-worktree-explorer/public/graph-layout.mjs
T
github-actions[bot] dc25d2bc3e chore: publish from main
2026-08-26 00:25:35 +00:00

91 lines
2.5 KiB
JavaScript

// Each color keeps at least 3:1 contrast against both the light (#ffffff)
// and dark (#0d1117) canvas backgrounds so lanes stay traceable in either theme.
const COLORS = [
"#0969da",
"#bf3989",
"#bf8700",
"#1a7f37",
"#8250df",
"#bc4c00",
"#1b7c83",
"#cf222e",
];
export const LANE_COLORS = COLORS;
function nextColor(index) {
return COLORS[index % COLORS.length];
}
export function layoutCommitGraph(commits) {
let lanes = [];
let colorIndex = 0;
let maxLanes = 1;
const rows = commits.map((commit) => {
let laneIndex = lanes.findIndex((lane) => lane.sha === commit.sha);
if (laneIndex === -1) {
lanes.push({ sha: commit.sha, color: nextColor(colorIndex++) });
laneIndex = lanes.length - 1;
}
const before = lanes.map((lane) => ({ ...lane }));
const current = before[laneIndex];
const after = lanes.map((lane) => ({ ...lane }));
const firstParent = commit.parents[0] || null;
if (!firstParent) {
after.splice(laneIndex, 1);
} else {
const existingFirstParent = after.findIndex((lane, index) =>
index !== laneIndex && lane.sha === firstParent
);
if (existingFirstParent >= 0) {
after.splice(laneIndex, 1);
} else {
after[laneIndex] = { sha: firstParent, color: current.color };
}
}
for (const parent of commit.parents.slice(1)) {
if (after.some((lane) => lane.sha === parent)) continue;
const insertAt = Math.min(laneIndex + 1, after.length);
after.splice(insertAt, 0, { sha: parent, color: nextColor(colorIndex++) });
}
const transitions = [];
before.forEach((lane, index) => {
if (index === laneIndex) return;
const target = after.findIndex((candidate) => candidate.sha === lane.sha);
if (target >= 0) {
transitions.push({ from: index, to: target, color: lane.color, kind: "pass" });
}
});
commit.parents.forEach((parent, parentIndex) => {
const target = after.findIndex((lane) => lane.sha === parent);
if (target >= 0) {
transitions.push({
from: laneIndex,
to: target,
color: parentIndex === 0 ? current.color : after[target].color,
kind: parentIndex === 0 ? "first-parent" : "merge-parent",
});
}
});
maxLanes = Math.max(maxLanes, before.length, after.length);
lanes = after;
return {
commit,
laneIndex,
color: current.color,
transitions,
lanesBefore: before.length,
lanesAfter: after.length,
};
});
return { rows, maxLanes };
}