@takagaki/cortex-decisions-viewer 0.12.103 → 0.12.104
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 +6 -2
- package/dist/rederivation.js +39 -27
- package/dist/render.js +104 -214
- package/package.json +1 -1
package/dist/build.js
CHANGED
|
@@ -2361,12 +2361,14 @@ async function build(opts) {
|
|
|
2361
2361
|
// 走るのは latestGeneratedPaths と同じ **リポジトリルート**(process.cwd())——
|
|
2362
2362
|
// Decisions ディレクトリで実行すると pathspec に一致せず常に空になる
|
|
2363
2363
|
const aiHistory = (0, repo_1.collectAiChangeHistory)(process.cwd());
|
|
2364
|
+
// ストーリー(#901 V2-5)の日本時間の今日。日・週・月の3つで同じ日にそろえるため1回だけ計算する
|
|
2365
|
+
const storyToday = (0, story_1.todayJst)(new Date(opts.generatedAt));
|
|
2364
2366
|
// ストーリーの日々の動き(#901 V2-5)。帳簿で on の日のファイルが無ければ null(キーごと出さない)
|
|
2365
2367
|
const story = await (0, story_1.readStory)(repoRoot, renderGroundingSection, (p) => repo.baseUrl ? `${repo.baseUrl}/edit/${repo.branch}/${encodePath(p)}` : null,
|
|
2366
2368
|
// 動きのない日を埋める終点=ビルドの時刻の日本時間の日付(時計を注入できる)
|
|
2367
|
-
|
|
2369
|
+
storyToday);
|
|
2368
2370
|
// 週・月のあらすじ(#901)。週・月のファイルが無ければ null(キーごと出さない=今までと同じ画面)
|
|
2369
|
-
const storyDigest = await (0, story_1.readStoryDigest)(repoRoot, renderGroundingSection, (p) => repo.baseUrl ? `${repo.baseUrl}/edit/${repo.branch}/${encodePath(p)}` : null,
|
|
2371
|
+
const storyDigest = await (0, story_1.readStoryDigest)(repoRoot, renderGroundingSection, (p) => repo.baseUrl ? `${repo.baseUrl}/edit/${repo.branch}/${encodePath(p)}` : null, storyToday);
|
|
2370
2372
|
// 案件アイコン(#348)。Cortex構成でなければ undefined(旧レイアウトには置き場が無い)
|
|
2371
2373
|
const projectIcon = await findProjectIcon(knowledgeRoot);
|
|
2372
2374
|
const site = {
|
|
@@ -2428,6 +2430,8 @@ async function build(opts) {
|
|
|
2428
2430
|
// 載せる日が無い案件(帳簿なし・壊れ・shadow の日だけ・ファイルなし)はキーごと出さない
|
|
2429
2431
|
story: story ?? undefined,
|
|
2430
2432
|
storyDigest: storyDigest ?? undefined,
|
|
2433
|
+
// ストーリーのタブが出る案件だけ(日・週・月のどちらも無ければ出さない=空の器を通さない)
|
|
2434
|
+
storyToday: story || storyDigest ? storyToday : undefined,
|
|
2431
2435
|
};
|
|
2432
2436
|
// サムネイル(デザイン画面等)をサイトに同梱し、ノードのパスをサイト内相対に書き換える
|
|
2433
2437
|
await node_fs_1.promises.mkdir(outAbs, { recursive: true });
|
package/dist/rederivation.js
CHANGED
|
@@ -573,17 +573,19 @@ function rederivedBandOf(recordPath, status, ledgers, nowShaOf, verdict, miss) {
|
|
|
573
573
|
* - 同じ活性度なら元の並び(日付降順 → タイトル昇順がそのまま残る)
|
|
574
574
|
* - 用語集だけ(関係者の並びは `engagement.ts`・便 14b。Decisions と Rules は対象外)
|
|
575
575
|
*
|
|
576
|
-
* ## 強さの段(#790・engine #727)
|
|
576
|
+
* ## 強さの段(#790・engine #727・仕様書 Q5)
|
|
577
577
|
*
|
|
578
|
-
*
|
|
579
|
-
*
|
|
578
|
+
* 🔴 **活性度が主**(engine 仕様書 Q5・2026-10-01 オーナー)。強さ(使った人の数 → 場面の数 → 資料の下地の辞書式降順)は、
|
|
579
|
+
* 活性度で並べた**後に、活性度がちょうど同じ語どうしの順にだけ**使う(`breakTiesByStrength`)。栓 `term_gate` を on にしても
|
|
580
|
+
* 強さ主には並べ替えない。🔴 **engine の目次(`scripts/memory-index.mjs` の `termRows`)の写し**
|
|
580
581
|
* ——画面と目次で同じ語の順番が食い違うと「目次の上から N 件を AI に読ませる」構想(#544)の
|
|
581
582
|
* 土台が崩れるので、**目次と同じ並び**にする。一致は `glossary-activity-parity.test.mjs` の
|
|
582
583
|
* `[強さ]`(engine を実際に呼んで焼いた表)が見る。
|
|
583
584
|
* - 🔴 **帳簿の `state` が `"on"` のときだけ**(`readRederivationLedgers` がそれ以外を空にする)
|
|
584
585
|
* - 強さを持つ語が 1 件も無ければ活性度の並びのまま(帳簿が無い案件は 1 バイトも触らない)
|
|
585
|
-
* -
|
|
586
|
-
* -
|
|
586
|
+
* - 🔴 活性度が違う語の順は 1 つも変えない。活性度を知らない語どうしも同点の 1 塊
|
|
587
|
+
* - 同点の塊の中で、強さを知らない語は塊の**末尾**へ。強さも同じなら活性度の並びのまま(安定)
|
|
588
|
+
* - 🔴 活性度の帳簿が無く強さだけある案件でも並べる(全部が「知らない」の 1 塊になり、その中を強さで並べる)
|
|
587
589
|
*
|
|
588
590
|
* ℹ️ `ledgers` と `statusOf` は**受け取り続ける**。`ledgers` は活性度のために要る。
|
|
589
591
|
* `statusOf` は並びに使わなくなったが、**引数から落とすと「群分けを足し戻す」退行が
|
|
@@ -596,21 +598,18 @@ function rederivedBandOf(recordPath, status, ledgers, nowShaOf, verdict, miss) {
|
|
|
596
598
|
function orderByActivity(records, pathOf, statusOf, ledgers, nowIso) {
|
|
597
599
|
if (!records.length)
|
|
598
600
|
return records;
|
|
599
|
-
// 🔴 **強さの段は活性度の段の後に必ず通す**(活性度が 1
|
|
600
|
-
return
|
|
601
|
+
// 🔴 **強さの段は活性度の段の後に必ず通す**(活性度が 1 件も無い案件でも・上の「強さの段」)。強さは同点の中の順だけ(Q5)
|
|
602
|
+
return breakTiesByStrength(rankByActivity(records, pathOf, ledgers, nowIso), pathOf, ledgers, nowIso);
|
|
603
|
+
}
|
|
604
|
+
/** 1 件の活性度(用語集の区画の外は「知らない」)。活性度の段と強さの段で同じ値を使う */
|
|
605
|
+
function activityOf(r, pathOf, ledgers, nowIso) {
|
|
606
|
+
const p = pathOf(r);
|
|
607
|
+
return ORDER_SECTION_RE.test(p) ? activityScore(ledgers.activity.get(p), nowIso) : null;
|
|
601
608
|
}
|
|
602
609
|
/** 活性度の段。活性度を持つ語が 1 件も無ければ**渡された配列をそのまま返す** */
|
|
603
610
|
function rankByActivity(records, pathOf, ledgers, nowIso) {
|
|
604
611
|
// この区画が並べ替えの対象か(用語集で、活性度の行が 1 件以上あるか)
|
|
605
|
-
const scored = records.map((r, i) => {
|
|
606
|
-
const p = pathOf(r);
|
|
607
|
-
const inSection = ORDER_SECTION_RE.test(p);
|
|
608
|
-
return {
|
|
609
|
-
r: r,
|
|
610
|
-
i: i,
|
|
611
|
-
score: inSection ? activityScore(ledgers.activity.get(p), nowIso) : null,
|
|
612
|
-
};
|
|
613
|
-
});
|
|
612
|
+
const scored = records.map((r, i) => ({ r: r, i: i, score: activityOf(r, pathOf, ledgers, nowIso) }));
|
|
614
613
|
if (!scored.some((s) => s.score != null))
|
|
615
614
|
return records;
|
|
616
615
|
return scored
|
|
@@ -627,26 +626,30 @@ function rankByActivity(records, pathOf, ledgers, nowIso) {
|
|
|
627
626
|
.map((s) => s.r);
|
|
628
627
|
}
|
|
629
628
|
/**
|
|
630
|
-
* 強さの段(#790)。**engine `scripts/glossary/activity.mjs` の `
|
|
629
|
+
* 強さの段(#790・Q5)。**engine `scripts/glossary/activity.mjs` の `breakTiesByStrength` の写し**——塊の切り方・鍵・
|
|
631
630
|
* 「知らない」の扱いを 1 つでも変えると、画面と目次で同じ語の順番が割れる。
|
|
632
631
|
*
|
|
633
632
|
* - 強さを持つ語が 1 件も無ければ**渡された配列をそのまま返す**(`state` が on でない案件はここ)
|
|
634
|
-
* -
|
|
635
|
-
*
|
|
633
|
+
* - `records` は活性度の段を通した後の並び。**活性度がちょうど同じ語**(どちらも知らないも同じ)が隣り合う塊ごとに、
|
|
634
|
+
* 鍵 `[使った人の数, 場面の数, 下地]` の辞書式降順で並べ替える。塊の外へは 1 件も動かさない
|
|
635
|
+
* - 塊の中で知らない語(帳簿に無い・用語集の区画の外)は末尾へ、渡された順のまま。鍵も同じなら渡された順(安定)
|
|
636
636
|
*/
|
|
637
|
-
function
|
|
637
|
+
function breakTiesByStrength(records, pathOf, ledgers, nowIso) {
|
|
638
638
|
if (!ledgers.strength.size)
|
|
639
639
|
return records;
|
|
640
640
|
const scored = records.map((r, i) => {
|
|
641
641
|
const p = pathOf(r);
|
|
642
|
-
return {
|
|
642
|
+
return {
|
|
643
|
+
r: r,
|
|
644
|
+
i: i,
|
|
645
|
+
a: activityOf(r, pathOf, ledgers, nowIso),
|
|
646
|
+
s: ORDER_SECTION_RE.test(p) ? (ledgers.strength.get(p) ?? null) : null,
|
|
647
|
+
};
|
|
643
648
|
});
|
|
644
649
|
if (!scored.some((x) => x.s != null))
|
|
645
650
|
return records;
|
|
646
|
-
const key = (s) => [s.
|
|
647
|
-
|
|
648
|
-
.slice()
|
|
649
|
-
.sort((a, b) => {
|
|
651
|
+
const key = (s) => [s.people, s.scenes, s.base ? 1 : 0];
|
|
652
|
+
const byStrength = (a, b) => {
|
|
650
653
|
if ((a.s == null) !== (b.s == null))
|
|
651
654
|
return a.s == null ? 1 : -1;
|
|
652
655
|
if (a.s != null && b.s != null) {
|
|
@@ -657,8 +660,17 @@ function rankByStrength(records, pathOf, ledgers) {
|
|
|
657
660
|
return kb[k] - ka[k];
|
|
658
661
|
}
|
|
659
662
|
return a.i - b.i;
|
|
660
|
-
}
|
|
661
|
-
|
|
663
|
+
};
|
|
664
|
+
const out = [];
|
|
665
|
+
for (let start = 0; start < scored.length;) {
|
|
666
|
+
let end = start + 1;
|
|
667
|
+
while (end < scored.length && scored[end].a === scored[start].a)
|
|
668
|
+
end += 1;
|
|
669
|
+
for (const x of scored.slice(start, end).sort(byStrength))
|
|
670
|
+
out.push(x.r);
|
|
671
|
+
start = end;
|
|
672
|
+
}
|
|
673
|
+
return out;
|
|
662
674
|
}
|
|
663
675
|
/* ---------------------------------------------------------------------------
|
|
664
676
|
* 決定の「その後」の帳簿(#705・engine #509 便 4)
|
package/dist/render.js
CHANGED
|
@@ -4644,8 +4644,12 @@ button.site-icon[aria-busy="true"] .site-icon-plus { opacity: 0; }
|
|
|
4644
4644
|
.container { max-width: 960px; margin: 0 auto; padding: 24px 20px 64px; }
|
|
4645
4645
|
|
|
4646
4646
|
/* ---- tabs ---- */
|
|
4647
|
-
|
|
4647
|
+
/* 🔴 幅が足りないときはタブの列だけが横にスクロールする(ページ全体は横スクロールさせない・分類B 2026-09-30)。
|
|
4648
|
+
overflow-x を visible 以外にすると overflow-y も auto 相当になり、.tab の margin-bottom: -1px と
|
|
4649
|
+
border-bottom の重なり(下の下線用の1px)が縦のスクロールバーとして見えかねないので、overflow-y は明示的に止める */
|
|
4650
|
+
.tabs { display: flex; gap: 6px; margin-bottom: 18px; border-bottom: 1px solid var(--border); overflow-x: auto; overflow-y: hidden; }
|
|
4648
4651
|
.tab {
|
|
4652
|
+
flex: 0 0 auto; white-space: nowrap;
|
|
4649
4653
|
padding: 8px 16px; font-size: 14px; font-weight: 600; color: var(--muted);
|
|
4650
4654
|
border: none; background: none; cursor: pointer;
|
|
4651
4655
|
border-bottom: 2px solid transparent; margin-bottom: -1px;
|
|
@@ -4693,16 +4697,16 @@ button.site-icon[aria-busy="true"] .site-icon-plus { opacity: 0; }
|
|
|
4693
4697
|
}
|
|
4694
4698
|
.graph-reset:hover { background: rgba(30,40,80,0.9); border-color: rgba(160,180,230,0.7); }
|
|
4695
4699
|
|
|
4696
|
-
/* ---- knowledge view switch ---- */
|
|
4697
|
-
.view-switch {
|
|
4700
|
+
/* ---- knowledge view switch(ストーリーの日次/週次/月次タブも同じ見た目・分類B 2026-09-30) ---- */
|
|
4701
|
+
.view-switch, .story-sub-tabs {
|
|
4698
4702
|
display: inline-flex; border: 1px solid rgba(255,255,255,0.75); border-radius: 999px; overflow: hidden;
|
|
4699
4703
|
margin-bottom: 14px; background: rgba(255,255,255,0.45);
|
|
4700
4704
|
-webkit-backdrop-filter: blur(10px) saturate(150%); backdrop-filter: blur(10px) saturate(150%);
|
|
4701
4705
|
box-shadow: 0 2px 8px rgba(30,60,120,0.1), inset 0 1px 0 rgba(255,255,255,0.85);
|
|
4702
4706
|
}
|
|
4703
|
-
.view-btn { border: none; background: none; padding: 7px 18px; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; }
|
|
4704
|
-
.view-btn.active { background: rgba(37,99,235,0.85); color: #fff; box-shadow: inset 0 1px 0 rgba(255,255,255,0.35); }
|
|
4705
|
-
.view-btn:not(.active):hover { color: var(--accent); }
|
|
4707
|
+
.view-btn, .story-sub-tab { border: none; background: none; padding: 7px 18px; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; }
|
|
4708
|
+
.view-btn.active, .story-sub-tab.active { background: rgba(37,99,235,0.85); color: #fff; box-shadow: inset 0 1px 0 rgba(255,255,255,0.35); }
|
|
4709
|
+
.view-btn:not(.active):hover, .story-sub-tab:not(.active):hover { color: var(--accent); }
|
|
4706
4710
|
|
|
4707
4711
|
/* ---- frontmatter panel ---- */
|
|
4708
4712
|
.fm-panel { margin-top: 32px; }
|
|
@@ -4881,32 +4885,11 @@ button.site-icon[aria-busy="true"] .site-icon-plus { opacity: 0; }
|
|
|
4881
4885
|
.story-card-edit { display: inline-block; margin-top: 8px; font-size: 12.5px; }
|
|
4882
4886
|
.story-card .body h2 { font-size: 14px; margin: 14px 0 6px; }
|
|
4883
4887
|
.story-card .body h3 { font-size: 13.5px; margin: 12px 0 6px; }
|
|
4884
|
-
/*
|
|
4885
|
-
.story-now { display: flex; flex-direction: column; gap: 14px; margin-bottom: 20px; }
|
|
4886
|
-
.story-section-heading { margin: 4px 0 0; font-size: 15px; }
|
|
4888
|
+
/* 週・月のあらすじカード(#901)。週・月のファイルがある案件だけ使う */
|
|
4887
4889
|
.story-empty { margin: 0; font-size: 13px; color: var(--muted); }
|
|
4888
4890
|
.story-phase { margin: 0 0 8px; font-weight: 600; }
|
|
4889
4891
|
.story-phase-label { display: inline-block; margin-right: 8px; font-size: 12px; color: var(--muted); font-weight: 400; }
|
|
4890
4892
|
.story-digest-human h4 { font-size: 13.5px; margin: 12px 0 6px; }
|
|
4891
|
-
.story-switch { display: flex; gap: 8px; margin: 0 0 12px; }
|
|
4892
|
-
.story-switch-btn {
|
|
4893
|
-
padding: 3px 16px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface);
|
|
4894
|
-
color: inherit; font-size: 13px; cursor: pointer;
|
|
4895
|
-
}
|
|
4896
|
-
.story-switch-btn.active { background: #1d4ed8; border-color: #1d4ed8; color: #fff; font-weight: 600; }
|
|
4897
|
-
.story-nav { display: flex; justify-content: space-between; margin: 0 0 10px; }
|
|
4898
|
-
.story-nav-btn {
|
|
4899
|
-
padding: 3px 12px; border-radius: var(--radius); border: 1px solid var(--border); background: var(--surface);
|
|
4900
|
-
color: inherit; font-size: 12.5px; cursor: pointer;
|
|
4901
|
-
}
|
|
4902
|
-
.story-nav-btn:disabled { opacity: 0.4; cursor: default; }
|
|
4903
|
-
.story-browse { display: flex; flex-direction: column; gap: 12px; }
|
|
4904
|
-
.story-days-fold { margin-top: 10px; }
|
|
4905
|
-
.story-days-fold > summary, .story-week-fold > summary { cursor: pointer; font-size: 13px; font-weight: 600; }
|
|
4906
|
-
.story-days-fold > .story-cards { margin-top: 10px; }
|
|
4907
|
-
.story-week-fold { border: 1px solid var(--border); border-radius: var(--radius); padding: 10px 18px; background: var(--surface); }
|
|
4908
|
-
.story-week-fold > .story-digest, .story-week-fold > .story-empty { margin-top: 10px; }
|
|
4909
|
-
.story-month-pick { display: flex; align-items: center; gap: 8px; font-size: 13px; }
|
|
4910
4893
|
/* ---- Home(案件の自己記述)---- */
|
|
4911
4894
|
/* 未記入の警告。**画面でいちばん強い赤にする**——27案件中24案件が未記入のまま
|
|
4912
4895
|
毎晩のAI生成が走っている状態で、控えめに出しても読まれない */
|
|
@@ -8421,6 +8404,10 @@ ${calendarAddUrl.toString()}
|
|
|
8421
8404
|
return new URLSearchParams(location.search).get(name);
|
|
8422
8405
|
}
|
|
8423
8406
|
function tabUrl(tabKey) {
|
|
8407
|
+
// ストーリーは日次/週次/月次のサブタブを持つので、そのURL(storySubUrl)に任せる。
|
|
8408
|
+
// ここで素の "?tab=story" を返すと、他のタブへ移って戻ったときに URL だけ既定(日次)に戻り、
|
|
8409
|
+
// 画面(storySub は変えていない)と URL がずれる(分類B 2026-09-30)
|
|
8410
|
+
if (tabKey === "story") return storySubUrl(storySub);
|
|
8424
8411
|
return tabKey === DEFAULT_TAB ? "?" : "?tab=" + encodeURIComponent(tabKey);
|
|
8425
8412
|
}
|
|
8426
8413
|
/** そのタブが立っているか(案件によっては操作タブが無い) */
|
|
@@ -8501,12 +8488,13 @@ ${calendarAddUrl.toString()}
|
|
|
8501
8488
|
}
|
|
8502
8489
|
|
|
8503
8490
|
// ---------- タブナビ ----------
|
|
8491
|
+
// 🔴 件数(「決定事項(466)」等)は出さない・文字は折り返さない(nowrap)。幅が足りなければ
|
|
8492
|
+
// タブの列だけが横にスクロールする(ページ全体は横にスクロールさせない・分類B 2026-09-30)
|
|
8504
8493
|
function renderTabs() {
|
|
8505
8494
|
if (TABS.length <= 1) return;
|
|
8506
8495
|
var tabs = el("div", { class: "tabs" });
|
|
8507
8496
|
TABS.forEach(function (t) {
|
|
8508
|
-
var
|
|
8509
|
-
var b = el("button", { class: "tab" + (listState.tab === t.key ? " active" : ""), text: label });
|
|
8497
|
+
var b = el("button", { class: "tab" + (listState.tab === t.key ? " active" : ""), text: t.label });
|
|
8510
8498
|
b.addEventListener("click", function () { switchTab(t.key); });
|
|
8511
8499
|
tabs.appendChild(b);
|
|
8512
8500
|
});
|
|
@@ -8544,17 +8532,13 @@ ${calendarAddUrl.toString()}
|
|
|
8544
8532
|
text: "決定・用語・レポートを起点に、つながり(根拠・出典・リンク)を1列ずつ辿る表示です。行をクリックすると右に次の列が開きます。",
|
|
8545
8533
|
},
|
|
8546
8534
|
"story": {
|
|
8547
|
-
text: "
|
|
8548
|
-
},
|
|
8549
|
-
"story-digest": {
|
|
8550
|
-
text: "今週の日々と、週・月のあらすじです。直したいことや足したいことは、各カードの「人の追記」に書けます。",
|
|
8535
|
+
text: "このプロジェクトの日々の動きを、日次・週次・月次に分けてまとめた記録です。直したいことや足したいことは、各カードの「GitHub で追記する」から書けます。",
|
|
8551
8536
|
},
|
|
8552
8537
|
"dir:レポート": {
|
|
8553
8538
|
text: "レポートの生成は終了し、履歴として凍結されています(レポートはSlack配信に一本化されました)。以下は過去に生成されたレコードです。",
|
|
8554
8539
|
},
|
|
8555
8540
|
};
|
|
8556
8541
|
var infoKey = listState.tab === "graph" ? (knowledgeView === "map" ? "graph" : "explorer") : listState.tab;
|
|
8557
|
-
if (infoKey === "story" && SITE.storyDigest) infoKey = "story-digest";
|
|
8558
8542
|
var info = INFO[infoKey];
|
|
8559
8543
|
if (!info) return;
|
|
8560
8544
|
var bar = el("div", { class: "info-bar" }, [ el("span", { text: info.text }) ]);
|
|
@@ -8578,13 +8562,34 @@ ${calendarAddUrl.toString()}
|
|
|
8578
8562
|
renderGenericList();
|
|
8579
8563
|
}
|
|
8580
8564
|
|
|
8581
|
-
// ---------- ストーリー(#901 V2-5
|
|
8582
|
-
//
|
|
8565
|
+
// ---------- ストーリー(#901 V2-5・日次/週次/月次タブへの分割は分類B 2026-09-30) ----------
|
|
8566
|
+
// 「日次」「週次」「月次」の3つのサブタブ。既定は日次。選んだサブタブは URL に添えて覚える
|
|
8567
|
+
// (?tab=story&sub=weekly のように・分類B 2026-09-30)。本文は build の関所(marked → sanitize)を
|
|
8583
8568
|
// 通した HTML で、印のコメントと機械の語の行は build が除いてある。見出しは textContent で入れる
|
|
8584
|
-
|
|
8585
|
-
|
|
8569
|
+
var STORY_SUB_DEFAULT = "daily";
|
|
8570
|
+
var STORY_SUBS = [["daily", "日次"], ["weekly", "週次"], ["monthly", "月次"]];
|
|
8571
|
+
var storySub = STORY_SUB_DEFAULT;
|
|
8572
|
+
|
|
8573
|
+
function storySubUrl(sub) {
|
|
8574
|
+
return sub === STORY_SUB_DEFAULT ? "?tab=story" : "?tab=story&sub=" + encodeURIComponent(sub);
|
|
8575
|
+
}
|
|
8576
|
+
function switchStorySub(sub) {
|
|
8577
|
+
if (storySub === sub) return;
|
|
8578
|
+
storySub = sub;
|
|
8579
|
+
history.replaceState(null, "", storySubUrl(sub));
|
|
8580
|
+
renderList();
|
|
8581
|
+
}
|
|
8582
|
+
|
|
8583
|
+
// 日ごとのカード(新しい日が上=build が並べた順のまま)。動きのない日は「◯月◯日は動きはありませんでした」の1行
|
|
8584
|
+
function renderStoryDaily() {
|
|
8585
|
+
var days = SITE.story || [];
|
|
8586
8586
|
var list = el("div", { class: "story-cards" });
|
|
8587
|
-
(
|
|
8587
|
+
if (!days.length) {
|
|
8588
|
+
list.appendChild(el("p", { class: "story-empty", text: "日々の記録はまだありません" }));
|
|
8589
|
+
app.appendChild(list);
|
|
8590
|
+
return;
|
|
8591
|
+
}
|
|
8592
|
+
days.forEach(function (d) {
|
|
8588
8593
|
// 動きのない日は薄い 1 行(日付+文言。畳んだ行は「9/10〜9/18」)
|
|
8589
8594
|
if (d.quiet) {
|
|
8590
8595
|
list.appendChild(el("div", { class: "story-quiet" }, [
|
|
@@ -8603,184 +8608,62 @@ ${calendarAddUrl.toString()}
|
|
|
8603
8608
|
app.appendChild(list);
|
|
8604
8609
|
}
|
|
8605
8610
|
|
|
8606
|
-
//
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
8619
|
-
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
(SITE.story || []).forEach(function (d) {
|
|
8624
|
-
if (d.quiet) return;
|
|
8625
|
-
pages[d.date] = d;
|
|
8626
|
-
if (oldest === null || d.date < oldest) oldest = d.date;
|
|
8627
|
-
});
|
|
8628
|
-
var weekOf = {};
|
|
8629
|
-
(dg.weeks || []).forEach(function (w) { weekOf[w.key] = w; });
|
|
8630
|
-
var monthOf = {};
|
|
8631
|
-
(dg.months || []).forEach(function (m) { monthOf[m.key] = m; });
|
|
8632
|
-
var thisMon = storyMonday(today);
|
|
8633
|
-
var lastMon = storyDay(storyMs(thisMon) - 7 * 86400000);
|
|
8634
|
-
|
|
8635
|
-
// 日の行(新しい日が上)。from〜to のうち、動きのある日はカード・無い日は薄い 1 行。
|
|
8636
|
-
// 載せた一番古い日より前は分からないので出さない(keepAll の「今週」だけは月曜から全部出す)
|
|
8637
|
-
function dayRows(from, to, keepAll) {
|
|
8638
|
-
var rows = [];
|
|
8639
|
-
for (var ms = storyMs(to); ms >= storyMs(from); ms -= 86400000) {
|
|
8640
|
-
var d = storyDay(ms);
|
|
8641
|
-
var pg = pages[d];
|
|
8642
|
-
if (pg) {
|
|
8643
|
-
rows.push(el("section", { class: "story-card" }, [
|
|
8644
|
-
el("h3", { class: "story-card-heading", text: pg.heading || pg.date }),
|
|
8645
|
-
pg.bodyHtml ? el("div", { class: "body", html: pg.bodyHtml }) : null,
|
|
8646
|
-
pg.editUrl ? el("a", { class: "story-card-edit", href: pg.editUrl, target: "_blank", rel: "noopener", text: "GitHub で追記する" }) : null,
|
|
8647
|
-
]));
|
|
8648
|
-
} else if (keepAll || (oldest !== null && d >= oldest)) {
|
|
8649
|
-
rows.push(el("div", { class: "story-quiet" }, [
|
|
8650
|
-
el("span", { class: "story-quiet-date", text: d + "(" + STORY_WD[new Date(ms).getUTCDay()] + ")" }),
|
|
8651
|
-
el("span", { text: " は動きはありませんでした" }),
|
|
8652
|
-
]));
|
|
8653
|
-
}
|
|
8654
|
-
}
|
|
8655
|
-
return rows;
|
|
8656
|
-
}
|
|
8657
|
-
function pageCount(from, to) {
|
|
8658
|
-
var n = 0;
|
|
8659
|
-
for (var ms = storyMs(from); ms <= storyMs(to); ms += 86400000) if (pages[storyDay(ms)]) n++;
|
|
8660
|
-
return n;
|
|
8661
|
-
}
|
|
8662
|
-
// あらすじの本体(局面・流れ・人の追記・GitHub のリンク)。無ければ 1 行の案内
|
|
8663
|
-
function digestBody(entry, phaseLabel, emptyText) {
|
|
8664
|
-
if (!entry) return el("p", { class: "story-empty", text: emptyText });
|
|
8665
|
-
var human = entry.humanHtml ? el("div", { class: "story-digest-human" }, [
|
|
8666
|
-
el("h4", { text: "人の追記" }),
|
|
8667
|
-
el("div", { class: "body", html: entry.humanHtml }),
|
|
8668
|
-
]) : null;
|
|
8669
|
-
return el("div", { class: "story-digest" }, [
|
|
8670
|
-
entry.phase ? el("p", { class: "story-phase" }, [
|
|
8671
|
-
el("span", { class: "story-phase-label", text: phaseLabel }),
|
|
8672
|
-
el("span", { text: entry.phase }),
|
|
8673
|
-
]) : null,
|
|
8674
|
-
entry.flowHtml ? el("div", { class: "body", html: entry.flowHtml }) : null,
|
|
8675
|
-
human,
|
|
8676
|
-
entry.editUrl ? el("a", { class: "story-card-edit", href: entry.editUrl, target: "_blank", rel: "noopener", text: "GitHub で追記する" }) : null,
|
|
8677
|
-
]);
|
|
8678
|
-
}
|
|
8679
|
-
var WEEK_EMPTY = "あらすじはまだありません(週が閉じて 2 日後の夜に作ります)";
|
|
8680
|
-
var MONTH_EMPTY = "あらすじはまだありません(月が閉じて 3 日後の夜に作ります)";
|
|
8681
|
-
function weekEnd(mon) {
|
|
8682
|
-
var sun = storyDay(storyMs(mon) + 6 * 86400000);
|
|
8683
|
-
return sun < today ? sun : today;
|
|
8684
|
-
}
|
|
8685
|
-
function daysFold(mon) {
|
|
8686
|
-
var rows = dayRows(mon, weekEnd(mon), mon === thisMon);
|
|
8687
|
-
if (!rows.length) return null;
|
|
8688
|
-
return el("details", { class: "story-days-fold" }, [
|
|
8689
|
-
el("summary", { text: "この週の日々(" + pageCount(mon, weekEnd(mon)) + " 日)" }),
|
|
8690
|
-
el("div", { class: "story-cards" }, rows),
|
|
8691
|
-
]);
|
|
8692
|
-
}
|
|
8693
|
-
|
|
8694
|
-
// 一番上: 今週の日々と先週のあらすじ
|
|
8695
|
-
app.appendChild(el("section", { class: "story-now" }, [
|
|
8696
|
-
el("h3", { class: "story-section-heading", text: "今週" }),
|
|
8697
|
-
el("div", { class: "story-cards" }, dayRows(thisMon, today, true)),
|
|
8698
|
-
el("h3", { class: "story-section-heading", text: "先週のあらすじ" }),
|
|
8699
|
-
weekOf[lastMon]
|
|
8700
|
-
? el("section", { class: "story-card" }, [
|
|
8701
|
-
el("h3", { class: "story-card-heading", text: storyWeekLabel(lastMon) }),
|
|
8702
|
-
digestBody(weekOf[lastMon], "この週の局面", ""),
|
|
8703
|
-
])
|
|
8704
|
-
: el("p", { class: "story-empty", text: "先週のあらすじはまだありません" }),
|
|
8705
|
-
]));
|
|
8611
|
+
// 週・月のあらすじカード(局面・流れ・人の追記・GitHub のリンク)。見出し・局面は build が作った文字列(heading/phase)をそのまま使う
|
|
8612
|
+
function storyDigestCard(entry, phaseLabel) {
|
|
8613
|
+
var human = entry.humanHtml ? el("div", { class: "story-digest-human" }, [
|
|
8614
|
+
el("h4", { text: "人の追記" }),
|
|
8615
|
+
el("div", { class: "body", html: entry.humanHtml }),
|
|
8616
|
+
]) : null;
|
|
8617
|
+
return el("section", { class: "story-card" }, [
|
|
8618
|
+
el("h3", { class: "story-card-heading", text: entry.heading }),
|
|
8619
|
+
entry.phase ? el("p", { class: "story-phase" }, [
|
|
8620
|
+
el("span", { class: "story-phase-label", text: phaseLabel }),
|
|
8621
|
+
el("span", { text: entry.phase }),
|
|
8622
|
+
]) : null,
|
|
8623
|
+
entry.flowHtml ? el("div", { class: "body", html: entry.flowHtml }) : null,
|
|
8624
|
+
human,
|
|
8625
|
+
entry.editUrl ? el("a", { class: "story-card-edit", href: entry.editUrl, target: "_blank", rel: "noopener", text: "GitHub で追記する" }) : null,
|
|
8626
|
+
]);
|
|
8627
|
+
}
|
|
8706
8628
|
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
Object.keys(monthOf).forEach(function (k) { mSet[k] = true; });
|
|
8716
|
-
Object.keys(pages).forEach(function (d) { mSet[d.slice(0, 7)] = true; });
|
|
8717
|
-
var months = Object.keys(mSet).sort().reverse();
|
|
8718
|
-
|
|
8719
|
-
var view = "week";
|
|
8720
|
-
var weekAt = mons.indexOf(lastMon);
|
|
8721
|
-
var monthAt = months.length ? months[0] : null;
|
|
8722
|
-
var btnWeek = el("button", { class: "story-switch-btn", type: "button", text: "週" });
|
|
8723
|
-
var btnMonth = el("button", { class: "story-switch-btn", type: "button", text: "月" });
|
|
8724
|
-
var browse = el("div", { class: "story-browse" });
|
|
8725
|
-
app.appendChild(el("div", { class: "story-switch" }, [btnWeek, btnMonth]));
|
|
8726
|
-
app.appendChild(browse);
|
|
8727
|
-
|
|
8728
|
-
function fillWeek() {
|
|
8729
|
-
var mon = mons[weekAt];
|
|
8730
|
-
var prev = el("button", { class: "story-nav-btn", type: "button", text: "← 前の週" });
|
|
8731
|
-
var next = el("button", { class: "story-nav-btn", type: "button", text: "次の週 →" });
|
|
8732
|
-
if (weekAt >= mons.length - 1) prev.disabled = true;
|
|
8733
|
-
if (weekAt <= 0) next.disabled = true;
|
|
8734
|
-
prev.addEventListener("click", function () { if (weekAt < mons.length - 1) { weekAt++; fill(); } });
|
|
8735
|
-
next.addEventListener("click", function () { if (weekAt > 0) { weekAt--; fill(); } });
|
|
8736
|
-
browse.appendChild(el("div", { class: "story-nav" }, [prev, next]));
|
|
8737
|
-
browse.appendChild(el("section", { class: "story-card story-week" }, [
|
|
8738
|
-
el("h3", { class: "story-card-heading", text: storyWeekLabel(mon) }),
|
|
8739
|
-
digestBody(weekOf[mon], "この週の局面", WEEK_EMPTY),
|
|
8740
|
-
daysFold(mon),
|
|
8741
|
-
]));
|
|
8629
|
+
// 週のあらすじを新しい週から順に(build が既に新しい順に並べてある)。まだ1枚も無ければ案内の1行
|
|
8630
|
+
function renderStoryWeekly() {
|
|
8631
|
+
var weeks = (SITE.storyDigest && SITE.storyDigest.weeks) || [];
|
|
8632
|
+
var list = el("div", { class: "story-cards" });
|
|
8633
|
+
if (!weeks.length) {
|
|
8634
|
+
list.appendChild(el("p", { class: "story-empty", text: "あらすじはまだありません(週が閉じて 2 日後の夜に作ります)" }));
|
|
8635
|
+
} else {
|
|
8636
|
+
weeks.forEach(function (w) { list.appendChild(storyDigestCard(w, "この週の局面")); });
|
|
8742
8637
|
}
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
el("
|
|
8755
|
-
digestBody(monthOf[monthAt], "この月の局面", MONTH_EMPTY),
|
|
8638
|
+
app.appendChild(list);
|
|
8639
|
+
}
|
|
8640
|
+
|
|
8641
|
+
// 月のあらすじを新しい月から順に。今月はまだ閉じていないので、あらすじが無ければ案内の1行を先頭に出す
|
|
8642
|
+
function renderStoryMonthly() {
|
|
8643
|
+
var months = (SITE.storyDigest && SITE.storyDigest.months) || [];
|
|
8644
|
+
var list = el("div", { class: "story-cards" });
|
|
8645
|
+
var curMonth = SITE.storyToday ? SITE.storyToday.slice(0, 7) : null;
|
|
8646
|
+
if (curMonth && !months.some(function (m) { return m.key === curMonth; })) {
|
|
8647
|
+
list.appendChild(el("section", { class: "story-card" }, [
|
|
8648
|
+
el("h3", { class: "story-card-heading", text: monthLabel(curMonth) }),
|
|
8649
|
+
el("p", { class: "story-empty", text: "月が閉じて 3 日後の夜に作ります" }),
|
|
8756
8650
|
]));
|
|
8757
|
-
// その月にかかる週(新しい週から。今週も入れる)
|
|
8758
|
-
var first = monthAt + "-01";
|
|
8759
|
-
var mon = storyMonday(first);
|
|
8760
|
-
var inMonth = [];
|
|
8761
|
-
for (var ms = storyMs(mon); storyDay(ms).slice(0, 7) <= monthAt && storyDay(ms) <= today; ms += 7 * 86400000) {
|
|
8762
|
-
var k = storyDay(ms);
|
|
8763
|
-
if (weekOf[k] || pageCount(k, weekEnd(k)) > 0) inMonth.push(k);
|
|
8764
|
-
}
|
|
8765
|
-
inMonth.reverse().forEach(function (k) {
|
|
8766
|
-
browse.appendChild(el("details", { class: "story-week-fold" }, [
|
|
8767
|
-
el("summary", { text: storyWeekLabel(k) }),
|
|
8768
|
-
digestBody(weekOf[k], "この週の局面", WEEK_EMPTY),
|
|
8769
|
-
daysFold(k),
|
|
8770
|
-
]));
|
|
8771
|
-
});
|
|
8772
|
-
}
|
|
8773
|
-
function fill() {
|
|
8774
|
-
browse.innerHTML = "";
|
|
8775
|
-
btnWeek.className = "story-switch-btn" + (view === "week" ? " active" : "");
|
|
8776
|
-
btnMonth.className = "story-switch-btn" + (view === "month" ? " active" : "");
|
|
8777
|
-
btnWeek.setAttribute("aria-pressed", view === "week" ? "true" : "false");
|
|
8778
|
-
btnMonth.setAttribute("aria-pressed", view === "month" ? "true" : "false");
|
|
8779
|
-
if (view === "week") fillWeek(); else fillMonth();
|
|
8780
8651
|
}
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8652
|
+
months.forEach(function (m) { list.appendChild(storyDigestCard(m, "この月の局面")); });
|
|
8653
|
+
app.appendChild(list);
|
|
8654
|
+
}
|
|
8655
|
+
|
|
8656
|
+
function renderStory() {
|
|
8657
|
+
var nav = el("div", { class: "story-sub-tabs" });
|
|
8658
|
+
STORY_SUBS.forEach(function (s) {
|
|
8659
|
+
var b = el("button", { class: "story-sub-tab" + (storySub === s[0] ? " active" : ""), type: "button", text: s[1] });
|
|
8660
|
+
b.addEventListener("click", function () { switchStorySub(s[0]); });
|
|
8661
|
+
nav.appendChild(b);
|
|
8662
|
+
});
|
|
8663
|
+
app.appendChild(nav);
|
|
8664
|
+
if (storySub === "weekly") renderStoryWeekly();
|
|
8665
|
+
else if (storySub === "monthly") renderStoryMonthly();
|
|
8666
|
+
else renderStoryDaily();
|
|
8784
8667
|
}
|
|
8785
8668
|
|
|
8786
8669
|
// 導入経緯(overview.adoption)の表示情報。Home見出し横のチップに出すラベルだけを返す。
|
|
@@ -21203,6 +21086,13 @@ ${calendarAddUrl.toString()}
|
|
|
21203
21086
|
// 値が入っていて知らない語だったときは今までどおり動かさない(壊れた ?tab= で
|
|
21204
21087
|
// 見ていた画面を飛ばさない・go() の行き先も ?tab= か ?id= のどちらかしか作らない)
|
|
21205
21088
|
else if (tab === null) listState.tab = DEFAULT_TAB;
|
|
21089
|
+
// ストーリーのサブタブ(日次/週次/月次)。?sub= が無い・知らない語なら既定(日次)
|
|
21090
|
+
if (listState.tab === "story") {
|
|
21091
|
+
var sub = getParam("sub");
|
|
21092
|
+
var validSub = false;
|
|
21093
|
+
STORY_SUBS.forEach(function (s) { if (s[0] === sub) validSub = true; });
|
|
21094
|
+
storySub = validSub ? sub : STORY_SUB_DEFAULT;
|
|
21095
|
+
}
|
|
21206
21096
|
renderList();
|
|
21207
21097
|
}
|
|
21208
21098
|
}
|
package/package.json
CHANGED