@@ -156,8 +156,34 @@ def add_link(origin_link: str):
156156 for m in re .finditer (r'[\*-] (.*?)\[link (.*?)\]' , line ):
157157 add_link (m .group (2 ))
158158
159+ # Markdownの参照スタイルリンク定義 (`[label]: url`) も参照として扱う。
160+ # 例: `[max_size]: ./scoped_allocator_adaptor/max_size.md`
161+ # (脚注 `[^label]:` は除外)
162+ for line in text .split ("\n " ):
163+ m = re .match (r'\s{0,3}\[([^\^\]][^\]]*)\]:\s+(\S+)' , line )
164+ if m :
165+ add_link (m .group (2 ))
166+
159167 return inner_links , outer_links
160168
169+ # --- 孤立ページ (lonely page) チェック用 ---
170+ # 「孤立ページ」とは、どのページからもリンクされていない .md のこと。
171+ # reference/ 配下の .md は、リンク先パスをtypoすると「ページは存在するのに
172+ # どこからもリンクされない」孤立ページになる。そうしたリンクミスを検出するため、
173+ # 内部リンクチェックの一部として、reference/ 配下の全 .md が最低1箇所から
174+ # 参照されているかを確認する。
175+
176+ # どこからもリンクされていなくてよいページ (意図的に他ページから参照されないもの)。
177+ # ここに載せるのは「意図的にスタンドアロンなページ」だけにすること。
178+ # リンクミスで孤立したページは、ここに登録せず親ページ側のリンクを修正すること。
179+ LONELY_PAGE_ALLOWLIST = {
180+ "reference.md" , # リファレンスのトップ索引 (index.md からのリンクはグローバルナビ扱い)
181+ "reference/node_handle.md" , # node_handleを説明する説明用カテゴリ概要ページ
182+ # C++26の説明専用ヘルパー。Senderアルゴリズムの仕様定義で用いられるが、
183+ # 現状どのアルゴリズムページの仕様記述からも参照されていない。
184+ "reference/execution/execution/query-with-default.md" ,
185+ }
186+
161187def check (check_inner_link : bool , check_outer_link : bool , url : str ) -> bool :
162188 if not check_inner_link and not check_outer_link :
163189 print ("unchecked" , file = sys .stderr )
@@ -166,6 +192,7 @@ def check(check_inner_link: bool, check_outer_link: bool, url: str) -> bool:
166192 found_error = False
167193 current_dir = os .getcwd ()
168194 outer_link_dict = dict ()
195+ referenced = set () # 内部リンクの参照先 (repo相対パスに正規化)。孤立ページ検出用
169196 if len (url ) <= 0 :
170197 path_list = [(p , False ) for p in glob .glob ("**/*.md" , recursive = True )]
171198 path_list .append (("GLOBAL_QUALIFY_LIST.txt" , True ))
@@ -198,6 +225,25 @@ def check(check_inner_link: bool, check_outer_link: bool, url: str) -> bool:
198225 if not os .path .exists (rel_link ):
199226 print ("{} href {} not found." .format (p , link ), file = sys .stderr )
200227 found_error = True
228+ # 孤立ページ検出用に、.md への参照先をrepo相対で記録する
229+ if link .endswith (".md" ):
230+ if link .startswith ("/" ):
231+ referenced .add (os .path .normpath (link .lstrip ("/" )))
232+ else :
233+ referenced .add (os .path .normpath (os .path .join (dirname , link )))
234+
235+ # 孤立ページ (lonely page) チェック: reference/ 配下に、どのページからも
236+ # リンクされていない .md ファイルが無いか確認する (リンク先パスのtypo等で発生する)。
237+ if check_inner_link :
238+ for p in sorted (glob .glob ("reference/**/*.md" , recursive = True )):
239+ norm = os .path .normpath (p )
240+ if norm in LONELY_PAGE_ALLOWLIST :
241+ continue
242+ if norm not in referenced :
243+ print ("{} is a lonely page (どこからもリンクされていない孤立ページです。"
244+ "リンク先のtypo等が原因の可能性があります)" .format (p ),
245+ file = sys .stderr )
246+ found_error = True
201247
202248 if check_outer_link :
203249 # GitHub-hosted runnerはIPv6アウトバウンド経路を持たない
0 commit comments