@takagaki/cortex-decisions-viewer 0.4.78 → 0.4.80

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.
Files changed (2) hide show
  1. package/dist/render.js +196 -25
  2. package/package.json +1 -1
package/dist/render.js CHANGED
@@ -356,6 +356,20 @@ function capabilityState(cap, ctx) {
356
356
  // 途中で壊れたデータで**画面が落ちない**ようにするためだけ——実体(同期ソースの行・
357
357
  // ライブ参照)だけで判定し、無ければ「まだ繋がっていない」側へ倒す。
358
358
  // **ここに宣言を読む道を足さないこと。** 足した瞬間、実態と食い違える経路が復活する。
359
+ // **fleet のデータが1枚も無いときは「未接続」(#138)。** 下の判定は
360
+ // 「行が無い=使っていない」と読んで `off`(未使用)を返すが、立ち上げ直後の案件は
361
+ // まだ夜間バッチが一度も走っていないだけで、何も決めていない。6つの能力に
362
+ // 「未使用」が並ぶと、**繋ぐ入口を出すという目的と逆のことを画面が言う**
363
+ // (「使わないことになっている」と読める)。
364
+ //
365
+ // **分岐は「1つも無い」に限る。** この防御経路は取得に失敗したときにも通るので、
366
+ // 判定材料が1つでもあるなら従来どおり——失敗を「未接続」に塗り替えない。
367
+ if (ctx.internals.length === 0 &&
368
+ ctx.externals.length === 0 &&
369
+ ctx.pipes.length === 0 &&
370
+ Object.keys(ctx.capabilities || {}).length === 0) {
371
+ return "idle";
372
+ }
359
373
  const used = (internal != null && internal.enabled !== false) ||
360
374
  (isLive && liveExts.length > 0);
361
375
  const off = (internal != null && internal.enabled === false) || !used;
@@ -429,11 +443,17 @@ function renderConnectionMap(site) {
429
443
  const externals = site.externalSources ?? [];
430
444
  const pipes = site.pipelines ?? [];
431
445
  const caps = site.capabilities ?? {};
432
- // **fleet のデータが1つでも取れているか、だけで判定する(#125②)。**
433
- // 素の Decisions ビュー(fleet-status.json が無い構成)ではマップを出さない現行の意図は
434
- // そのまま。宣言(`tools`)は条件から外した(⑤)——艦隊の fleet-status.json は
446
+ // **「この画面から接続できる構成か」で判定する(#138)。**
447
+ // 素の Decisions ビュー(投入フォームを持たない構成)ではマップを出さない現行の意図は
448
+ // そのまま。宣言(`tools`)は条件から外してある(#125⑤)——艦隊の fleet-status.json は
435
449
  // すべて capabilities を持つので、宣言はもうマップの有無を左右しない。
436
- if (!internals.length && !externals.length && !pipes.length && !Object.keys(caps).length) {
450
+ //
451
+ // **中身が空でも、intake があるならマップを出す。** 立ち上げ直後の案件は fleet の
452
+ // データが丸ごと無いが、そこは**まさにこれから繋ぐ案件**で、6つの能力とその入口を
453
+ // 一望できる図が一番要る場面だった。中身の有無で消していたので、新規案件の画面からは
454
+ // 「何を繋げばよいのか」を示すものが消えていた。
455
+ if (!site.intake &&
456
+ !internals.length && !externals.length && !pipes.length && !Object.keys(caps).length) {
437
457
  return null;
438
458
  }
439
459
  const hasCaps = Object.keys(caps).length > 0;
@@ -2077,6 +2097,18 @@ ${capabilityState.toString()}
2077
2097
  return row;
2078
2098
  }
2079
2099
 
2100
+ /**
2101
+ * GitHub App のインストール先(#138)。
2102
+ *
2103
+ * **1箇所に持つ。** 組織ごとの行と、読み取りトークンのカードの両方から出すので、
2104
+ * 書き写すと片方だけが古くなる。
2105
+ *
2106
+ * **文書化されている形だけを使う。** target_id に組織のログイン名を渡す形は GitHub の
2107
+ * 文書に無く、未ログインだとログイン画面へ転送されて 200 が返るので、効いているかを
2108
+ * 外から確かめられない。**確かめられないものを顧客に押させない。**
2109
+ */
2110
+ var GITHUB_APP_INSTALL_URL = "https://github.com/apps/classmethod-cortex-app/installations/new";
2111
+
2080
2112
  /**
2081
2113
  * 接続状況のライブ値(op=state の応答)。取得前・取得失敗時は null。
2082
2114
  *
@@ -2218,6 +2250,9 @@ ${capabilityState.toString()}
2218
2250
  // 「これから繋げる入口」も接続マップのアンカーの受け皿も無くなる。
2219
2251
  // 何を繋げるかは製品が決めていて、案件データでは変わらない(#125②)。
2220
2252
  var CAP_ORDER = ["課題管理", "会議", "共有資料", "チャット", "デザイン", "開発"];
2253
+ // internalSources に行が来る能力(チャットと開発は externalSources 側にしか来ない)。
2254
+ // **fleet-status.json がまだ無い案件のために、行が無くても設定を出す**判定に使う(#138)
2255
+ var CAP_INTERNAL = ["課題管理", "会議", "共有資料", "デザイン"];
2221
2256
  var capBox = {};
2222
2257
  var manualBox = {};
2223
2258
  // 対応表は externalCapability が持つ(状態判定・件数の集計と同じものを使う)
@@ -2334,6 +2369,26 @@ ${capabilityState.toString()}
2334
2369
  });
2335
2370
  }
2336
2371
 
2372
+ // **行が1つも無い能力にも、設定の口を出す(#138)。**
2373
+ //
2374
+ // 実機で踏んだ欠陥の本体はここだった。各能力の設定UI一式は internalControls の中に
2375
+ // あり、その呼び出しは上の internals.forEach の内側だけ。行を作っているのは夜間バッチ
2376
+ // (fleet-status.json)なので、**立ち上げ直後の案件には1行も無く、タイルを開いても
2377
+ // 「この能力にはまだ設定できるものがありません。」で終わる**——接続先のフォームを
2378
+ // 出す・出さないの判定を直しても、その手前で画面に到達できていなかった。
2379
+ //
2380
+ // **データの行(カード)は作らない。** 作れば、読めていない件数・最終同期・ラベルを
2381
+ // 画面が装うことになる。ここで足すのは操作だけで、状態の表示はタイルとマップが持つ。
2382
+ //
2383
+ // 状態が分からないと出せない操作(会議・共有資料のトグルや追加フォーム)は
2384
+ // internalControls 側の判断で従来どおり出ない——不明な状態に操作を出さない原則は
2385
+ // 変えていない。ここが変えるのは「呼ばれもしなかった」ことだけ。
2386
+ CAP_INTERNAL.forEach(function (cap) {
2387
+ if (internals.filter(function (s) { return s.kind === cap; }).length) return;
2388
+ var ctl = internalControls({ kind: cap }, false);
2389
+ if (ctl) pushCap(cap, ctl);
2390
+ });
2391
+
2337
2392
  if (sources.length) {
2338
2393
  // **見出しは付けない。** #101 で行は能力ごとのモーダルへ移ったので、
2339
2394
  // ここに見出しを置くと中身ゼロの見出しが節の先頭に立つ(実際に8案件すべてで出ていた)
@@ -2427,12 +2482,9 @@ ${capabilityState.toString()}
2427
2482
  if (!ok && !unsure) {
2428
2483
  row.appendChild(el("a", {
2429
2484
  class: "ds-owner-install",
2430
- // **文書化されている形だけを使う。** target_id に組織のログイン名を渡す形は
2431
- // GitHub の文書に無く(GitHub自身のUIは数値のアカウントIDを入れる)、
2432
- // 未ログインだとログイン画面へ転送されて 200 が返るので、
2433
- // 効いているかを外から確かめられない。**確かめられないものを顧客に押させない。**
2434
- // どの組織かはこの行に出ているので、選ばせる形で足りる
2435
- href: "https://github.com/apps/classmethod-cortex-app/installations/new",
2485
+ // どの組織かはこの行に出ているので、選ばせる形で足りる(URLの形は
2486
+ // GITHUB_APP_INSTALL_URL のコメントを参照)
2487
+ href: GITHUB_APP_INSTALL_URL,
2436
2488
  target: "_blank", rel: "noopener",
2437
2489
  text: "この組織にインストール →",
2438
2490
  }));
@@ -2440,6 +2492,24 @@ ${capabilityState.toString()}
2440
2492
  obox.appendChild(row);
2441
2493
  });
2442
2494
  pushCap("開発", obox);
2495
+ } else {
2496
+ // **組織が1件も無い案件にも、App の入口を置く(#138)。**
2497
+ // githubOwners は夜間バッチの成果物なので、立ち上げ直後の案件には無い。
2498
+ // インストールの導線を「未接続の組織の行」の中にしか置いていなかったため、
2499
+ // **まだ何も繋いでいない案件=一番 App を入れてほしい案件**の画面に、
2500
+ // App へ行く道が1本も無かった(実機で踏んだ)。
2501
+ var obox0 = el("div", { class: "ds-owners" });
2502
+ obox0.appendChild(el("div", { class: "ds-sub", text: "組織ごとの接続状況" }));
2503
+ obox0.appendChild(el("div", { class: "ds-owner" }, [
2504
+ el("span", { class: "ds-owner-state ds-gate-idle", text: "⦿ 未接続 読み取っている組織はまだありません" }),
2505
+ el("a", {
2506
+ class: "ds-owner-install",
2507
+ href: GITHUB_APP_INSTALL_URL,
2508
+ target: "_blank", rel: "noopener",
2509
+ text: "組織に GitHub App をインストール →",
2510
+ }),
2511
+ ]));
2512
+ pushCap("開発", obox0);
2443
2513
  }
2444
2514
 
2445
2515
  pushCap("開発", adders.querySelector('[data-adder="github"]'));
@@ -2458,10 +2528,19 @@ ${capabilityState.toString()}
2458
2528
  *
2459
2529
  * **unknown(確かめられなかった組織)も「要る」側に倒す。** 実態は none かもしれず、
2460
2530
  * 隠す方に倒すと直せなくなる(画面には組織ごとに「確認できませんでした」と出ている)。
2531
+ *
2532
+ * **「無い」と「空」は別物(#138・オーナー判断 2026-08-18)。**
2533
+ * - 値そのものが来ていない(undefined)… fleet-status.json をまだ持っていない、または
2534
+ * 取得に失敗した。**情報が無いので出す**(上の #118 の意図はここが担う)。
2535
+ * - 空の配列([])… 夜間バッチは走ったが、読み取り対象の開発リポジトリが0件。
2536
+ * 読むものが無いのだから鍵も要らない。**出さない**。
2537
+ * 以前はどちらも空配列に丸めていたので、0件の案件にも欄が出続けていた。
2538
+ * **この2つを混ぜると #118 を壊す**(立ち上げ直後の案件から唯一の入口が消える)。
2461
2539
  */
2462
2540
  function githubTokenNeeded() {
2463
- var list = fleetVal("githubOwners") || [];
2464
- if (!list.length) return true;
2541
+ var list = fleetVal("githubOwners");
2542
+ if (!Array.isArray(list)) return true;
2543
+ if (!list.length) return false;
2465
2544
  return list.some(function (o) { return !o || (o.source !== "app" && o.source !== "token"); });
2466
2545
  }
2467
2546
 
@@ -2472,9 +2551,16 @@ ${capabilityState.toString()}
2472
2551
  // 全組織が繋がっているなら、入力欄ではなく**そう言う1行**に畳む(#118)。
2473
2552
  // 何も出さないと「トークンはどこで入れるのか」が分からなくなる
2474
2553
  if (k === "external-sources" && !githubTokenNeeded()) {
2554
+ // **0件の案件に「すべての組織に接続済み」と言わない(#138)。** 組織が1つも無いのに
2555
+ // 接続済みと書けば嘘になる。畳む理由が違うので、文も分ける——次の一歩
2556
+ //(リポジトリを登録する)が同じモーダルの上にあることまで書く
2557
+ var ownersNow = fleetVal("githubOwners");
2558
+ var noRepos = Array.isArray(ownersNow) && ownersNow.length === 0;
2475
2559
  pushCap(SECRET_CAP[k], el("p", {
2476
2560
  class: "sec-how ds-all-connected",
2477
- text: "すべての組織に接続済みです(GitHub App / 登録済みトークン)。読み取りトークンの登録は要りません。",
2561
+ text: noRepos
2562
+ ? "読み取り対象の開発リポジトリがまだありません。このモーダルの上にあるリポジトリの追加フォームで登録すると、トークンが要るかどうかをここに出します。"
2563
+ : "すべての組織に接続済みです(GitHub App / 登録済みトークン)。読み取りトークンの登録は要りません。",
2478
2564
  }));
2479
2565
  return;
2480
2566
  }
@@ -2980,6 +3066,47 @@ ${capabilityState.toString()}
2980
3066
  var TARGETS_RACE_NOTE =
2981
3067
  "他の人が先に接続先を変更しました。最新の一覧に更新しましたので、内容を確かめてもう一度お試しください。";
2982
3068
 
3069
+ /**
3070
+ * この画面から Backlog の接続先を足したり外したりできるか(#138)。
3071
+ *
3072
+ * **同期ミラー(s.url)では判定しない。** 以前は「一度でも同期していれば書き込み先が
3073
+ * 決まる」として s.url を見ていたが、正本(issues-config.json)は雛形から作られるので
3074
+ * 立ち上げ直後の案件にも実在する。ミラーで判定すると、**まだ一度も繋いでいない案件=
3075
+ * これから繋ぎたい案件**だけがフォームを出せない(実機で踏んだ)。
3076
+ *
3077
+ * 出さないのは、この画面からの投入に対応していない固定IP同期の案件だけ。
3078
+ * **その見分けは SITE.secretKinds に backlog が入っているかで行う。**
3079
+ * 固定IPかどうかを直接示す値は画面に来ておらず(インフラ側の設定にしか無い)、
3080
+ * 鍵の欄を出すかどうかの判定が同じ線で引かれているので、代理として正確に使える。
3081
+ * インフラ側で secretKinds の条件を変えるときは、**ここの意味も一緒に変わる**。
3082
+ */
3083
+ function backlogTargetsEditable() {
3084
+ return (SITE.secretKinds || []).indexOf("backlog") >= 0;
3085
+ }
3086
+
3087
+ /**
3088
+ * Backlog のAPIキーを、どのスペースの棚へ入れるか(#138)。
3089
+ *
3090
+ * **名簿(config.ts)の backlogSpace に頼らない。** 立ち上げ直後の案件は接続先を
3091
+ * まだ名簿に書いていないので、サーバ側だけではスペースが決まらない——鍵の欄を出しても
3092
+ * 保存が断られる(#127 で「2つ目以降のスペースの鍵は画面から名乗ってもらう」経路が
3093
+ * 用意してあるので、そこへ載せる)。
3094
+ *
3095
+ * **名乗るのは1つに定まるときだけ。** 画面の接続先が複数のスペースにまたがっているなら、
3096
+ * どちらの鍵として入れたのかは入れた人にしか分からない。勝手に片方を選ぶと、
3097
+ * **読み手が見に行くのと別の棚へ黙って入る**(入れたのに動かない、が一番起きてほしくない形)。
3098
+ * 名乗らなければサーバが従来どおり名簿の値を使う。
3099
+ */
3100
+ function backlogSecretSpace() {
3101
+ var list = backlogTargetsNow(null);
3102
+ var domains = [];
3103
+ for (var i = 0; i < list.length; i++) {
3104
+ var d = String(list[i].domain || "").toLowerCase();
3105
+ if (d && domains.indexOf(d) === -1) domains.push(d);
3106
+ }
3107
+ return domains.length === 1 ? domains[0] : "";
3108
+ }
3109
+
2983
3110
  /**
2984
3111
  * 「課題管理」カードの接続先(一覧+追加+削除・#127)。
2985
3112
  *
@@ -2993,9 +3120,7 @@ ${capabilityState.toString()}
2993
3120
  */
2994
3121
  function backlogTargetsSection(s) {
2995
3122
  var targets = backlogTargetsNow(s);
2996
- // 書き込み先(正本の置き場)が決まらない案件では操作を出さない。判定は呼び出し側と
2997
- // 同じ s.url(同期ミラーが1つでもあるか)で、フォームを出さない条件と揃える
2998
- var editable = !!(s && s.url);
3123
+ var editable = backlogTargetsEditable();
2999
3124
 
3000
3125
  var listEl = el("div", { class: "ds-target-list" });
3001
3126
  var current = el("div", { class: "ds-current" }, [
@@ -3195,12 +3320,13 @@ ${capabilityState.toString()}
3195
3320
  // 伝えてフォームを出さない形なので、課題管理だけ不揃いだった。
3196
3321
  // 一覧そのもの(現在の接続先)は**そういう案件にも出す**——読めているものを隠さない
3197
3322
  //
3198
- // **接続先の正本は issues-config.json(#111)**だが、その置き場は
3199
- // 同期ミラー(backlog-settings.json)の位置から決めている。ミラーが1つも
3200
- // 無い案件では正本をどこへ置けばよいかも決められないので、条件は変わらない
3323
+ // **判定は「同期したことがあるか」ではなく「この画面から投入できる案件か」(#138)。**
3324
+ // 接続先の正本(issues-config.json)は雛形から作られるので、立ち上げ直後の案件にも
3325
+ // 実在する。同期ミラーの有無で門前払いすると、**新規案件がこの画面から
3326
+ // Backlog に繋げない**——設定UIを置いている意味が無くなる
3201
3327
  box.appendChild(backlogTargetsSection(s));
3202
- if (!s.url) {
3203
- box.appendChild(el("p", { class: "sec-how", text: "この案件はまだ一度も Backlog と同期していないため、この画面からは接続先を設定できません。先に初回の同期を実行するか、cortex の担当者にご連絡ください。" }));
3328
+ if (!backlogTargetsEditable()) {
3329
+ box.appendChild(el("p", { class: "sec-how", text: "この案件の Backlog は別の経路で同期しているため、この画面からは接続先を変更できません。変更が必要なときは cortex の担当者にご連絡ください。" }));
3204
3330
  used = true;
3205
3331
  }
3206
3332
  // **接続先の下に置く。** リアルタイム同期は「どのプロジェクトを見るか」が
@@ -4372,8 +4498,19 @@ ${capabilityState.toString()}
4372
4498
  "figma": {
4373
4499
  icon: "🎨",
4374
4500
  title: "Figma のトークン",
4375
- desc: "デザインの画面インベントリを毎晩同期するために使います。",
4376
- how: "Figma Settings → Security → Personal access tokens で発行(file_content:read があれば足ります)",
4501
+ desc: "デザインの画面インベントリと、Figma に付いたコメント(指摘)を毎晩同期するために使います。",
4502
+ // **必要なスコープは実装が叩くAPIから決まる。** sync-designs
4503
+ // GET /v1/files/{key} → file_content:read(画面インベントリ)
4504
+ // GET /v1/files/{key}/comments → file_comments:read(指摘の同期)
4505
+ // の2本だけを呼ぶ。**片方だけだと、もう片方が静かに入ってこない**——
4506
+ // 特に file_comments:read の欠落は「同期は緑なのに指摘だけ増えない」という
4507
+ // 気づきにくい壊れ方をする(コメント同期は後から足した機能で、この案内が追随していなかった)。
4508
+ // 書き込み権限は1つも要らない。files:read(非推奨・広範)は選ばせないこと。
4509
+ how: "Figma → Settings → Security → Personal access tokens で発行。スコープは file_content:read と file_comments:read の2つにチェックを入れてください(どちらも読み取りのみ・書き込み権限は要りません)",
4510
+ // **スコープが正しくても、招待が無いと読めない。** トークンは「そのアカウントが
4511
+ // 見られるファイル」しか読めないので、招待漏れは 404 になる。権限の問題に見えないため
4512
+ // 現場で切り分けに時間がかかる(実際に踏んだ)。入力欄の隣に書いておく。
4513
+ note: "発行したアカウントを、対象の Figma ファイルに閲覧者として招待しておいてください(招待が無いとトークンが正しくても読めません)。",
4377
4514
  },
4378
4515
  "backlog": {
4379
4516
  icon: "📋",
@@ -4399,7 +4536,16 @@ ${capabilityState.toString()}
4399
4536
  icon: "🐙",
4400
4537
  title: "GitHub の読み取りトークン",
4401
4538
  desc: "開発リポジトリの Issues / Discussions を読み、Gold の原料にするために使います。",
4402
- how: "GitHub Settings Developer settings → Personal access tokens で、対象リポジトリに Contents / Issues の Read-only を付けて発行",
4539
+ // **第一の案内は GitHub App(#138)。** 実装の本線は App のインストールトークンで、
4540
+ // 個人トークンは App を入れられない組織のフォールバックでしかない(既存案件は
4541
+ // すでに App で読めている)。画面が個人トークンを勧め続けると、発行と入れ直しが
4542
+ // 要る側に人が流れ続け、**入れ直しの要らない仕組みへ移れない**。
4543
+ // 順序を入れ替えるだけで、どちらも残す——App を入れられない組織は実在する。
4544
+ appFirst: {
4545
+ text: "まず、読み取りたいリポジトリのある組織に Cortex の GitHub App を入れてください。トークンの発行も、期限が来たときの入れ直しも要りません。",
4546
+ linkText: "組織に GitHub App をインストール →",
4547
+ },
4548
+ how: "App を入れられない組織では、代わりにトークンを使います。GitHub → Settings → Developer settings → Personal access tokens で、対象リポジトリに Contents / Issues の Read-only を付けて発行",
4403
4549
  },
4404
4550
  };
4405
4551
 
@@ -4413,6 +4559,15 @@ ${capabilityState.toString()}
4413
4559
  * カードは #101 で能力モーダルの中へ移した(buildDataSources の pushCap 経由)。
4414
4560
  * まとめて並べる renderSecrets() は呼び出し元が無くなったので消してある。
4415
4561
  */
4562
+ function secretPayload(intake, kind, value) {
4563
+ var body = { projectKey: intake.projectKey, kind: kind, value: value };
4564
+ if (kind === "backlog") {
4565
+ var space = backlogSecretSpace();
4566
+ if (space) body.space = space;
4567
+ }
4568
+ return body;
4569
+ }
4570
+
4416
4571
  function secretCard(kind, meta) {
4417
4572
  // **いま何で動いているか**を先に出す。入れ直したのに反映されていない状態が
4418
4573
  // 画面で分かるようにする(接続状況は夜間バッチのスナップショットなので、
@@ -4444,7 +4599,11 @@ ${capabilityState.toString()}
4444
4599
  method: "POST",
4445
4600
  headers: { "content-type": "application/json" },
4446
4601
  // **シークレット名は送らない。** どの連携かだけを送り、書き込み先はサーバが案件から決める。
4447
- body: JSON.stringify({ projectKey: intake.projectKey, kind: kind, value: value }),
4602
+ // **Backlog はスペースだけ名乗る(#138)。** 名前を組み立てるのはサーバで、
4603
+ // こちらが渡すのは「どのスペースの鍵か」という材料だけ。
4604
+ // **押した時点で読む。** 組み立て時に固めると、接続先を登録した直後に
4605
+ // 貼った鍵が「スペースを特定できません」で断られる
4606
+ body: JSON.stringify(secretPayload(intake, kind, value)),
4448
4607
  });
4449
4608
  var j = await res.json().catch(function () { return {}; });
4450
4609
  if (!res.ok) {
@@ -4481,7 +4640,19 @@ ${capabilityState.toString()}
4481
4640
  // **未設定のときだけ、先に試すべき手を出す。** 既に動いているカードに
4482
4641
  // 「まずこれをやれ」と出すと、直す必要が無いものを触らせることになる
4483
4642
  !src && meta.selfServe ? el("p", { class: "sec-preferred", text: meta.selfServe.text }) : null,
4643
+ // **本線(App)はトークンの手順より先に、いつでも出す(#138)。**
4644
+ // トークンで動いている案件こそ App へ移してほしいので、selfServe と違って
4645
+ // 「未設定のときだけ」にはしない
4646
+ meta.appFirst
4647
+ ? el("p", { class: "sec-preferred" }, [
4648
+ document.createTextNode(meta.appFirst.text + " "),
4649
+ el("a", { href: GITHUB_APP_INSTALL_URL, target: "_blank", rel: "noopener", text: meta.appFirst.linkText }),
4650
+ ])
4651
+ : null,
4484
4652
  el("p", { class: "sec-how", text: meta.how }),
4653
+ // **鍵の作り方に付随する注意(招待漏れ等)。** 発行手順(how)とは別に出す——
4654
+ // 「トークンは正しいのに読めない」は権限の問題に見えないので、切り分けに時間がかかる。
4655
+ meta.note ? el("p", { class: "sec-how", text: meta.note }) : null,
4485
4656
  meta.selfServe ? el("p", { class: "sec-how", text: meta.selfServe.note }) : null,
4486
4657
  input,
4487
4658
  // **扱いの説明はカードに持たせる。** 節の見出しの下に置いていたときは、
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takagaki/cortex-decisions-viewer",
3
- "version": "0.4.78",
3
+ "version": "0.4.80",
4
4
  "description": "Cortexの意思決定記録(Decisions/*.md)を静的サイトにビルドして閲覧する。各レコードに「Edit on GitHub」リンクを付与する。",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,