@takagaki/cortex-decisions-viewer 0.12.84 → 0.12.85

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/README.md CHANGED
@@ -40,7 +40,7 @@ cortex-decisions-viewer build [dir] [options]
40
40
  | --- | --- | --- |
41
41
  | `[dir]` | `Decisions` | Decisionsディレクトリ(リポジトリルートからの相対 or 絶対) |
42
42
  | `-o, --out <dir>` | `site` | 出力ディレクトリ |
43
- | `-t, --title <title>` | `Decisions` | サイトタイトル |
43
+ | `-t, --title <title>` | `Decisions` | サイトタイトル(`Cortex/Home.md` の frontmatter `project` が読めればそちらを優先。これは読めないときの控え) |
44
44
  | `--repo-url <url>` | (git remoteから解決) | GitHubリポジトリURL。CIで git remote が引けない場合に明示指定 |
45
45
  | `--branch <branch>` | `main`(環境変数 `AWS_BRANCH` があればそれ) | 編集リンク・参照リンクが指すブランチ |
46
46
  | `--exclude <files...>` | (なし) | 一覧から除外する追加ファイル名。既定で `README.md` / `template.md` は除外 |
package/dist/build.js CHANGED
@@ -96,6 +96,7 @@ function takeProposals(filePath) {
96
96
  return hit;
97
97
  }
98
98
  const external_id_1 = require("./external-id");
99
+ const home_project_1 = require("./home-project");
99
100
  const render_1 = require("./render");
100
101
  /**
101
102
  * この画面を作ったパッケージの版。**package.json を唯一の出どころにする。**
@@ -2081,12 +2082,15 @@ async function build(opts) {
2081
2082
  let home = null;
2082
2083
  let homeGrounding;
2083
2084
  let homeUpdatedAt;
2085
+ // Home.md の本文(ヘッダーの案件名を frontmatter の `project` から決めるため。無ければ null)
2086
+ let homeRaw = null;
2084
2087
  const sections = [];
2085
2088
  // グラフに渡す区画(**並べ替える前**の配列を持つ。上の sections とレコードの実体は同じ)
2086
2089
  const graphSections = [];
2087
2090
  if (knowledgeRoot) {
2088
2091
  try {
2089
2092
  const raw = await node_fs_1.promises.readFile(path.join(knowledgeRoot, "Home.md"), "utf8");
2093
+ homeRaw = raw;
2090
2094
  home = await parseGeneric(raw, "Home.md", toRepoRelative(knowledgeRoot), repo.baseUrl, repo.branch);
2091
2095
  // 自己記述の節を取り出し、**本文からは抜く**(最上部に出すので、残すと2度出る)。
2092
2096
  // 旧い使い方の説明もここで落ちる(説明はビューアが持つようになった)
@@ -2194,7 +2198,8 @@ async function build(opts) {
2194
2198
  // 案件アイコン(#348)。Cortex構成でなければ undefined(旧レイアウトには置き場が無い)
2195
2199
  const projectIcon = await findProjectIcon(knowledgeRoot);
2196
2200
  const site = {
2197
- title: opts.title,
2201
+ // 🔴 **案件名の正本は Home.md の `project`**(engine #699 F10)。`--title` は読めないときの控え
2202
+ title: (0, home_project_1.resolveSiteTitle)(homeRaw, opts.title),
2198
2203
  generatedAt: opts.generatedAt,
2199
2204
  // **package.json から読む。** 手で書くと、上げ忘れて嘘の版が出る
2200
2205
  viewerVersion: PKG_VERSION,
package/dist/cli.js CHANGED
@@ -12,7 +12,7 @@ program
12
12
  .description("Decisionsディレクトリを静的サイトにビルドする")
13
13
  .argument("[dir]", "Decisionsディレクトリ(未指定なら Cortex/Decisions/records → Cortex/Decisions → Decisions の順で自動検出)")
14
14
  .option("-o, --out <dir>", "出力ディレクトリ", "site")
15
- .option("-t, --title <title>", "サイトタイトル", "Decisions")
15
+ .option("-t, --title <title>", "サイトタイトル(Cortex/Home.md の project が読めればそちらを優先。これは読めないときの控え)", "Decisions")
16
16
  .option("--repo-url <url>", "GitHubリポジトリURL(未指定なら git remote から解決)")
17
17
  .option("--branch <branch>", "編集リンクが指すブランチ(既定: main / 環境変数 AWS_BRANCH)")
18
18
  .option("--exclude <files...>", "一覧から除外する追加ファイル名(既定で README.md / template.md は除外)", [])
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ /**
3
+ * `Cortex/Home.md` の frontmatter `project`(案件の表示名)を読む(engine #699 F10)。
4
+ *
5
+ * ## なぜビューアが自分で読むのか
6
+ *
7
+ * 案件の表示名の**正本は Home.md の `project`**(`title` は頁の名前 "Home" で、表示名ではない)。
8
+ * これまでヘッダーの案件名は `--title`(engine の viewer-config.json の title、旧 Amplify は
9
+ * `viewerTitle ?? key`)の写しだけを見ていたので、Home.md で改名しても写しを直すまで
10
+ * ヘッダーが古い名前のままだった。build の時点で Home を読んでいるので、ここで正本を直接見る。
11
+ * 読めないとき(Home が無い・`project` が空・`{{プロジェクト名}}` のまま等)は `--title` に倒す。
12
+ *
13
+ * ## 読み方は infra の正本の写し
14
+ *
15
+ * 正本は `infra/scripts/lib/home-md.mjs` の `parseHomeProjectName`(名簿・Apps Script と同じ規則)。
16
+ * ビューアは npm で配る別パッケージなので import できず、写しを持つ。
17
+ * **規則を変えるときは両側を同じ便で直すこと。** 一致は `viewer/test/home-grounding.test.mjs` の
18
+ * parity の節が、infra の題材(`infra/test/fixtures/home-md-cases.mjs`・通る題材と弾く題材の両方)で検査する。
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.parseHomeProjectName = parseHomeProjectName;
22
+ exports.resolveSiteTitle = resolveSiteTitle;
23
+ /** 区切り行か(`---`。行末の空白は許す) */
24
+ const isDelimiter = (line) => /^---[ \t]*$/.test(line);
25
+ /** `project:` の右側を値にする(正本の `parseScalar` と同じ規則) */
26
+ function parseScalar(rest) {
27
+ const raw = rest.trim();
28
+ if (raw === "")
29
+ return { ok: false, reason: "EMPTY" };
30
+ const q = raw.charAt(0);
31
+ if (q === '"') {
32
+ let out = "";
33
+ for (let i = 1; i < raw.length; i += 1) {
34
+ const c = raw.charAt(i);
35
+ if (c === "\\") {
36
+ // `\"` と `\\` だけを剥がす(他のエスケープは原文のまま)
37
+ const n = raw.charAt(i + 1);
38
+ if (n === '"' || n === "\\") {
39
+ out += n;
40
+ i += 1;
41
+ continue;
42
+ }
43
+ out += c;
44
+ continue;
45
+ }
46
+ if (c === '"')
47
+ return { ok: true, value: out };
48
+ out += c;
49
+ }
50
+ return { ok: false, reason: "BROKEN_VALUE" };
51
+ }
52
+ if (q === "'") {
53
+ let out = "";
54
+ for (let i = 1; i < raw.length; i += 1) {
55
+ const c = raw.charAt(i);
56
+ if (c === "'") {
57
+ if (raw.charAt(i + 1) === "'") {
58
+ out += "'";
59
+ i += 1;
60
+ continue;
61
+ }
62
+ return { ok: true, value: out };
63
+ }
64
+ out += c;
65
+ }
66
+ return { ok: false, reason: "BROKEN_VALUE" };
67
+ }
68
+ // 裸の値: 空白の後ろの `#` から先はコメント。行頭の `#` は値が無いのと同じ
69
+ if (q === "#")
70
+ return { ok: false, reason: "EMPTY" };
71
+ const bare = (/^(.*?)(?:[ \t]+#.*)?$/.exec(raw) ?? [raw, raw])[1].trim();
72
+ // YAML の null は「無い」
73
+ if (bare === "null" || bare === "~")
74
+ return { ok: false, reason: "EMPTY" };
75
+ // 1 行の文字列以外(ブロックスカラー・flow・アンカー/エイリアス/タグ)は読まない
76
+ if (/^[|>][+-]?$/.test(bare) || /^[\[{&*!]/.test(bare))
77
+ return { ok: false, reason: "UNSUPPORTED" };
78
+ return { ok: true, value: bare };
79
+ }
80
+ /** Home.md の本文から `project` を読む(純関数。正本 `parseHomeProjectName` の写し) */
81
+ function parseHomeProjectName(markdown) {
82
+ const text = String(markdown ?? "").replace(/^/, "").replace(/\r\n?/g, "\n");
83
+ const lines = text.split("\n");
84
+ if (lines.length === 0 || !isDelimiter(lines[0]))
85
+ return { ok: false, reason: "NO_FRONTMATTER" };
86
+ let end = -1;
87
+ for (let i = 1; i < lines.length; i += 1) {
88
+ if (isDelimiter(lines[i])) {
89
+ end = i;
90
+ break;
91
+ }
92
+ }
93
+ if (end < 0)
94
+ return { ok: false, reason: "UNCLOSED_FRONTMATTER" };
95
+ for (let i = 1; i < end; i += 1) {
96
+ const m = /^project:(.*)$/.exec(lines[i]);
97
+ if (!m)
98
+ continue;
99
+ const scalar = parseScalar(m[1]);
100
+ if (!scalar.ok)
101
+ return scalar;
102
+ const value = scalar.value.trim();
103
+ if (value === "")
104
+ return { ok: false, reason: "EMPTY" };
105
+ if (/\{\{[\s\S]*\}\}/.test(value))
106
+ return { ok: false, reason: "PLACEHOLDER" };
107
+ return { ok: true, project: value };
108
+ }
109
+ return { ok: false, reason: "MISSING" };
110
+ }
111
+ /**
112
+ * ヘッダーに出す案件名を決める。Home.md の `project` が読めればそれ、読めなければ `--title`。
113
+ * @param homeRaw Home.md の本文(無ければ null)
114
+ * @param fallback `--title` の値
115
+ */
116
+ function resolveSiteTitle(homeRaw, fallback) {
117
+ if (homeRaw == null)
118
+ return fallback;
119
+ const parsed = parseHomeProjectName(homeRaw);
120
+ return parsed.ok ? parsed.project : fallback;
121
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takagaki/cortex-decisions-viewer",
3
- "version": "0.12.84",
3
+ "version": "0.12.85",
4
4
  "description": "Cortexの意思決定記録(Decisions/*.md)を静的サイトにビルドして閲覧する。各レコードに「Edit on GitHub」リンクを付与する。",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,