@takagaki/cortex-decisions-viewer 0.4.7 → 0.4.8

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/build.js CHANGED
@@ -472,9 +472,7 @@ function buildGraph(decisions, home, sections, content, targetUrls, repoBaseUrl,
472
472
  for (const sec of sections)
473
473
  for (const r of sec.records)
474
474
  fileNameToId.set(r.fileName, r.id);
475
- // 参照先IDから層を推定してノード化する。
476
- // 外部リンク(http(s))はノード化せず null を返す(外部URLの点はグラフ肥大化=描画負荷の主因。
477
- // リンク自体は各レコードの詳細・参照欄に残るため情報は失われない)。
475
+ // 参照先IDから層を推定してノード化する
478
476
  const classifyTarget = (target) => {
479
477
  if (nodes.has(target))
480
478
  return target;
@@ -498,7 +496,9 @@ function buildGraph(decisions, home, sections, content, targetUrls, repoBaseUrl,
498
496
  return addNode({ id: target, label, group, url });
499
497
  }
500
498
  else if (/^https?:\/\//.test(target)) {
501
- return null; // 外部リンクはノード化しない
499
+ group = "external";
500
+ label = target.replace(/^https?:\/\//, "").slice(0, 60);
501
+ return addNode({ id: target, label, group, url: target });
502
502
  }
503
503
  else if (target.includes("/") || target.toLowerCase().endsWith(".md")) {
504
504
  group = "silver"; // リポジトリ内ファイルへのパス参照 → GitHubのコピーへ飛べるようにする
@@ -508,45 +508,36 @@ function buildGraph(decisions, home, sections, content, targetUrls, repoBaseUrl,
508
508
  }
509
509
  return addNode({ id: target, label, group });
510
510
  };
511
- // 解決先が null(外部リンク等で非ノード化)の辺は張らない
512
- const pushEdge = (fromId, target, rel) => {
513
- if (target)
514
- edges.push({ from: fromId, to: target, rel });
515
- };
516
- // 外部URLノードを作る(source/references の出典用フォールバック)。
517
- const externalNode = (url, label) => addNode({
518
- id: url,
519
- label: (label ?? url.replace(/^https?:\/\//, "")).slice(0, 60),
520
- group: "external",
521
- url,
522
- });
523
- // 出典(source/reference)の解決: Backlog課題URLは実ノード(bronze)へ、議事録ID等は該当ノードへ。
524
- // 解決できない外部URL(Wiki・GitHub等)は外部ノードとして必ず繋ぐ(出典は少数で意味があるため残す。
525
- // 大量の「本文リンク」の騒音は addLinkEdges 側でドロップしたまま)。
526
- const provenanceTarget = (raw, label) => {
527
- const v = raw.trim();
528
- return classifyTarget(backlogViewKey(v) ?? v) ?? externalNode(v, label);
529
- };
530
511
  const addRelationEdges = (fromId, relations) => {
531
- for (const r of relations)
532
- pushEdge(fromId, classifyTarget(r.target), r.rel);
512
+ for (const r of relations) {
513
+ edges.push({ from: fromId, to: classifyTarget(r.target), rel: r.rel });
514
+ }
533
515
  };
534
516
  const addSourceEdge = (fromId, source) => {
535
517
  if (source && source.trim() !== "")
536
- edges.push({ from: fromId, to: provenanceTarget(source), rel: "source" });
518
+ edges.push({ from: fromId, to: classifyTarget(source.trim()), rel: "source" });
537
519
  };
538
520
  const addReferenceEdges = (fromId, references) => {
539
521
  for (const ref of references) {
540
- const to = ref.url ? provenanceTarget(ref.url, ref.label) : classifyTarget(ref.label);
541
- pushEdge(fromId, to, "reference");
522
+ if (ref.url) {
523
+ const id = addNode({
524
+ id: ref.url,
525
+ label: ref.label.slice(0, 60),
526
+ group: "external",
527
+ url: ref.url,
528
+ });
529
+ edges.push({ from: fromId, to: id, rel: "reference" });
530
+ }
531
+ else {
532
+ edges.push({ from: fromId, to: classifyTarget(ref.label), rel: "reference" });
533
+ }
542
534
  }
543
535
  };
544
- // Gold層(Decision/用語/レポート/Home)の本文リンクは必ず繋ぐ(外部URLでも外部ノードとして接続)。
545
- // =frontmatterを持つレコードは孤立させない。大量の騒音は「コンテキスト側の本文リンク」(content edges)
546
- // のみドロップする(下の content ループは classifyTarget のまま)。
547
536
  const addLinkEdges = (fromId, links) => {
548
- for (const link of links)
549
- edges.push({ from: fromId, to: provenanceTarget(link), rel: "link" });
537
+ for (const link of links) {
538
+ const key = backlogViewKey(link);
539
+ edges.push({ from: fromId, to: classifyTarget(key ?? link), rel: "link" });
540
+ }
550
541
  };
551
542
  // Bronze/Silverのノードを先に登録する(Gold・Bronze/Silver双方からの参照が同一ノードに解決されるように)
552
543
  for (const c of content) {
@@ -582,7 +573,7 @@ function buildGraph(decisions, home, sections, content, targetUrls, repoBaseUrl,
582
573
  }
583
574
  for (const c of content) {
584
575
  for (const e of c.edges) {
585
- pushEdge(c.id, classifyTarget(e.target), e.rel);
576
+ edges.push({ from: c.id, to: classifyTarget(e.target), rel: e.rel });
586
577
  }
587
578
  }
588
579
  // 自己ループと重複辺を除去する(同じURLが複数回貼られていても辺は1本)
@@ -596,15 +587,7 @@ function buildGraph(decisions, home, sections, content, targetUrls, repoBaseUrl,
596
587
  seen.add(key);
597
588
  return true;
598
589
  });
599
- // 描画対象は「レコード(Gold) or 辺に接続のあるノード」だけ。外部リンク除去で孤立した
600
- // 非レコードノードは描画もされないため、ペイロードからも落としておく(初期ロードを軽くする)。
601
- const usedIds = new Set();
602
- for (const e of deduped) {
603
- usedIds.add(e.from);
604
- usedIds.add(e.to);
605
- }
606
- const prunedNodes = [...nodes.values()].filter((n) => n.recordId || usedIds.has(n.id));
607
- return { nodes: prunedNodes, edges: deduped };
590
+ return { nodes: [...nodes.values()], edges: deduped };
608
591
  }
609
592
  /**
610
593
  * 各レコードの bodyHtml を out/bodies/<i>.html に書き出し、bodyRef にパスを設定して
package/dist/render.js CHANGED
@@ -1054,22 +1054,25 @@ const CLIENT_JS = `
1054
1054
  var fx = (dx / d) * f, fy = (dy / d) * f;
1055
1055
  e.a.vx += fx; e.a.vy += fy; e.b.vx -= fx; e.b.vy -= fy;
1056
1056
  });
1057
- // 全ノードを中心へ向ける等方的な引力(Goldは強め=中央に、コンテキストは弱め=その周り)。
1058
- // さらに半径 RING の円で外周を押し戻して封じ込める。これで対角の伸び・飛び出したスポークが
1059
- // 抑えられ、全体が円形のディスクに収まる(force-directed本来の「丸める力の不在」を補う)。
1057
+ // Goldは中心への重力、グレーは外周リングへの引力 + 減衰(元のロジック)。
1058
+ // 外周リングを多数のグレー(外部リンク等の枝先)が均等に埋めることで全体が円形になり、
1059
+ // Goldが中心に締まる。この見た目は「点を全部残す」ことで成立する(重さはBarnes-Hut+収束後停止で別途解消)。
1060
1060
  nodes.forEach(function (n) {
1061
- var g = n.recordId ? 0.012 : 0.005;
1062
- n.vx -= n.x * g; n.vy -= n.y * g;
1063
- var r = Math.sqrt(n.x * n.x + n.y * n.y) + 0.01;
1064
- if (r > RING) {
1065
- var rf = (r - RING) * 0.05; // 円の外に出た分だけ内側へ強めに戻す(円形の境界)
1061
+ if (n.recordId) {
1062
+ n.vx -= n.x * 0.012; n.vy -= n.y * 0.012;
1063
+ } else {
1064
+ var r = Math.sqrt(n.x * n.x + n.y * n.y) + 0.01;
1065
+ var rf = (r - RING) * 0.012;
1066
1066
  n.vx -= (n.x / r) * rf; n.vy -= (n.y / r) * rf;
1067
1067
  }
1068
1068
  if (n === draggingNode) { n.vx = 0; n.vy = 0; return; }
1069
1069
  n.vx *= 0.85; n.vy *= 0.85;
1070
1070
  n.x += n.vx * alpha; n.y += n.vy * alpha;
1071
1071
  });
1072
- if (alpha > 0.0015) alpha *= 0.97; // 収束まで減衰しきる(下げ止まりさせず、整定後はループ側で物理計算を止める)
1072
+ // 元のゆっくり減衰(*0.995)に戻す: ウォームアップ320回が高エネルギーで回り、Goldが中心に締まる
1073
+ // 深い平衡(元の見た目)まで到達する。floorは0.05ではなく0.003まで下げ、整定後はループ側で停止できる
1074
+ // ようにする(②の固まり対策と両立)。*0.97の速い減衰だとウォームアップが早期終了し浅い配置で固まっていた。
1075
+ if (alpha > 0.003) alpha *= 0.995;
1073
1076
  }
1074
1077
 
1075
1078
  function nodeRadius(n) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takagaki/cortex-decisions-viewer",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
4
4
  "description": "Cortexの意思決定記録(Decisions/*.md)を静的サイトにビルドして閲覧する。各レコードに「Edit on GitHub」リンクを付与する。",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,