[{"data":1,"prerenderedAt":3528},["ShallowReactive",2],{"content-/search-implementation":3,"all-pages-for-dir":3505,"related-/search-implementation":3506,"og-image-/search-implementation":3527},{"id":4,"title":5,"body":6,"category":3489,"concepts":3490,"description":3491,"extension":3492,"meta":3493,"navigation":297,"ogImage":3490,"path":3494,"project_name":3495,"published":3496,"publishedAt":3497,"seo":3498,"stem":3499,"tags":3500,"todo":3503,"unpublished":3496,"updatedAt":3490,"__hash__":3504},"pages/2025-11/2025-11-01/search-implementation.md","デバウンス処理と本文検索の実装ガイド",{"type":7,"value":8,"toc":3453},"minimark",[9,12,16,20,23,64,67,72,80,83,87,139,144,159,162,166,173,177,180,188,191,195,198,204,207,494,499,522,526,533,536,699,704,718,721,880,884,891,895,898,903,941,946,1052,1055,1390,1395,1401,1405,1409,1575,1578,1581,1853,1857,1859,1862,2243,2246,2393,2398,2461,2466,2585,2589,2592,2835,2840,2863,2867,2871,2874,2924,2929,3098,3101,3105,3217,3223,3227,3267,3273,3277,3280,3283,3286,3303,3306,3326,3329,3343,3346,3349,3362,3365,3368,3371,3374,3385,3388,3396,3399,3407,3410,3413,3446,3449],[10,11,5],"h1",{"id":5},[13,14,15],"p",{},"このドキュメントでは、Nuxt Contentサイトに実装した高度な検索機能について、初心者向けに詳しく解説します。",[17,18,19],"h2",{"id":19},"実装の概要",[13,21,22],{},"今回の実装では、以下の機能を追加しました：",[24,25,26,34,40,46,52,58],"ol",{},[27,28,29,33],"li",{},[30,31,32],"strong",{},"全文検索機能"," - タイトル、説明文、本文から検索",[27,35,36,39],{},[30,37,38],{},"デバウンス処理"," - 入力中の無駄な検索を防ぐ",[27,41,42,45],{},[30,43,44],{},"MDC ASTからのテキスト抽出"," - Nuxt Contentの特殊な形式に対応",[27,47,48,51],{},[30,49,50],{},"検索結果のハイライト"," - 見つかったキーワードを強調表示",[27,53,54,57],{},[30,55,56],{},"スニペット生成"," - 本文でヒットした場合に前後の文脈を表示",[27,59,60,63],{},[30,61,62],{},"ページネーション"," - 大量の検索結果を分割表示",[17,65,66],{"id":66},"追加されたファイルとパッケージ",[68,69,71],"h3",{"id":70},"_1-新規ファイル","1. 新規ファイル",[73,74,76],"h4",{"id":75},"appswebapppagessearchvue",[77,78,79],"code",{},"apps/web/app/pages/search.vue",[13,81,82],{},"検索機能の全てを含むページコンポーネントです。",[68,84,86],{"id":85},"_2-追加パッケージ","2. 追加パッケージ",[88,89,94],"pre",{"className":90,"code":91,"language":92,"meta":93,"style":93},"language-json shiki shiki-themes vitesse-light vitesse-light","{\n  \"flexsearch\": \"^0.8.212\"\n}\n","json","",[77,95,96,105,133],{"__ignoreMap":93},[97,98,101],"span",{"class":99,"line":100},"line",1,[97,102,104],{"class":103},"shFtX","{\n",[97,106,108,112,116,119,122,126,130],{"class":99,"line":107},2,[97,109,111],{"class":110},"sqvqQ","  \"",[97,113,115],{"class":114},"sz8Xr","flexsearch",[97,117,118],{"class":110},"\"",[97,120,121],{"class":103},":",[97,123,125],{"class":124},"sMJiu"," \"",[97,127,129],{"class":128},"sdGka","^0.8.212",[97,131,132],{"class":124},"\"\n",[97,134,136],{"class":99,"line":135},3,[97,137,138],{"class":103},"}\n",[13,140,141],{},[30,142,143],{},"FlexSearchとは？",[145,146,147,150,153,156],"ul",{},[27,148,149],{},"高速で軽量な全文検索ライブラリ",[27,151,152],{},"クライアントサイド（ブラウザ上）で動作",[27,154,155],{},"日本語を含む多言語に対応",[27,157,158],{},"サジェスト（おすすめ検索）機能付き",[17,160,161],{"id":161},"主要機能の詳細解説",[68,163,165],{"id":164},"_1-デバウンス処理の仕組み","1. デバウンス処理の仕組み",[13,167,168,169,172],{},"デバウンスとは、",[30,170,171],{},"連続して発生するイベントを制限する技術","です。",[73,174,176],{"id":175},"問題点デバウンスなし","問題点（デバウンスなし）",[13,178,179],{},"ユーザーが「検索」と入力すると：",[88,181,186],{"className":182,"code":184,"language":185},[183],"language-text","け → 検索実行\nけん → 検索実行\nけんさ → 検索実行\nけんさく → 検索実行\n","text",[77,187,184],{"__ignoreMap":93},[13,189,190],{},"4回も検索が実行されてしまいます！",[73,192,194],{"id":193},"解決策デバウンスあり","解決策（デバウンスあり）",[13,196,197],{},"300ミリ秒（0.3秒）待ってから検索します：",[88,199,202],{"className":200,"code":201,"language":185},[183],"け → 待機中...\nけん → 待機中...\nけんさ → 待機中...\nけんさく → 待機中... → 300ms経過 → 検索実行！\n",[77,203,201],{"__ignoreMap":93},[73,205,206],{"id":206},"実装コード",[88,208,212],{"className":209,"code":210,"language":211,"meta":93,"style":93},"language-javascript shiki shiki-themes vitesse-light vitesse-light","// 検索キーワードの状態管理\nconst searchQuery = ref('')        // ユーザーが入力中の文字列\nconst debouncedQuery = ref('')     // 実際に検索に使う文字列\nconst isSearching = ref(false)     // 「検索中...」表示の制御\n\nlet debounceTimeout = null\n\nwatch(searchQuery, (newQuery) => {\n  isSearching.value = true  // 「検索中...」を表示\n\n  // 前のタイマーがあればキャンセル\n  if (debounceTimeout) {\n    clearTimeout(debounceTimeout)\n  }\n\n  // 300ms後に検索を実行\n  debounceTimeout = setTimeout(() => {\n    debouncedQuery.value = newQuery  // 検索実行\n    isSearching.value = false        // 「検索中...」を非表示\n  }, 300)\n})\n","javascript",[77,213,214,220,249,269,292,299,313,318,346,366,371,377,392,405,411,416,422,440,458,476,488],{"__ignoreMap":93},[97,215,216],{"class":99,"line":100},[97,217,219],{"class":218},"sxvE3","// 検索キーワードの状態管理\n",[97,221,222,226,230,233,237,240,243,246],{"class":99,"line":107},[97,223,225],{"class":224},"stQ0i","const",[97,227,229],{"class":228},"s4oTP"," searchQuery",[97,231,232],{"class":103}," =",[97,234,236],{"class":235},"senZ8"," ref",[97,238,239],{"class":103},"(",[97,241,242],{"class":124},"''",[97,244,245],{"class":103},")",[97,247,248],{"class":218},"        // ユーザーが入力中の文字列\n",[97,250,251,253,256,258,260,262,264,266],{"class":99,"line":135},[97,252,225],{"class":224},[97,254,255],{"class":228}," debouncedQuery",[97,257,232],{"class":103},[97,259,236],{"class":235},[97,261,239],{"class":103},[97,263,242],{"class":124},[97,265,245],{"class":103},[97,267,268],{"class":218},"     // 実際に検索に使う文字列\n",[97,270,272,274,277,279,281,283,287,289],{"class":99,"line":271},4,[97,273,225],{"class":224},[97,275,276],{"class":228}," isSearching",[97,278,232],{"class":103},[97,280,236],{"class":235},[97,282,239],{"class":103},[97,284,286],{"class":285},"sHkkW","false",[97,288,245],{"class":103},[97,290,291],{"class":218},"     // 「検索中...」表示の制御\n",[97,293,295],{"class":99,"line":294},5,[97,296,298],{"emptyLinePlaceholder":297},true,"\n",[97,300,302,305,308,310],{"class":99,"line":301},6,[97,303,304],{"class":224},"let",[97,306,307],{"class":228}," debounceTimeout",[97,309,232],{"class":103},[97,311,312],{"class":224}," null\n",[97,314,316],{"class":99,"line":315},7,[97,317,298],{"emptyLinePlaceholder":297},[97,319,321,324,326,329,332,335,338,340,343],{"class":99,"line":320},8,[97,322,323],{"class":235},"watch",[97,325,239],{"class":103},[97,327,328],{"class":228},"searchQuery",[97,330,331],{"class":103},",",[97,333,334],{"class":103}," (",[97,336,337],{"class":228},"newQuery",[97,339,245],{"class":103},[97,341,342],{"class":103}," =>",[97,344,345],{"class":103}," {\n",[97,347,349,352,355,358,360,363],{"class":99,"line":348},9,[97,350,351],{"class":228},"  isSearching",[97,353,354],{"class":103},".",[97,356,357],{"class":228},"value",[97,359,232],{"class":103},[97,361,362],{"class":285}," true",[97,364,365],{"class":218},"  // 「検索中...」を表示\n",[97,367,369],{"class":99,"line":368},10,[97,370,298],{"emptyLinePlaceholder":297},[97,372,374],{"class":99,"line":373},11,[97,375,376],{"class":218},"  // 前のタイマーがあればキャンセル\n",[97,378,380,383,385,388,390],{"class":99,"line":379},12,[97,381,382],{"class":285},"  if",[97,384,334],{"class":103},[97,386,387],{"class":228},"debounceTimeout",[97,389,245],{"class":103},[97,391,345],{"class":103},[97,393,395,398,400,402],{"class":99,"line":394},13,[97,396,397],{"class":235},"    clearTimeout",[97,399,239],{"class":103},[97,401,387],{"class":228},[97,403,404],{"class":103},")\n",[97,406,408],{"class":99,"line":407},14,[97,409,410],{"class":103},"  }\n",[97,412,414],{"class":99,"line":413},15,[97,415,298],{"emptyLinePlaceholder":297},[97,417,419],{"class":99,"line":418},16,[97,420,421],{"class":218},"  // 300ms後に検索を実行\n",[97,423,425,428,430,433,436,438],{"class":99,"line":424},17,[97,426,427],{"class":228},"  debounceTimeout",[97,429,232],{"class":103},[97,431,432],{"class":235}," setTimeout",[97,434,435],{"class":103},"(()",[97,437,342],{"class":103},[97,439,345],{"class":103},[97,441,443,446,448,450,452,455],{"class":99,"line":442},18,[97,444,445],{"class":228},"    debouncedQuery",[97,447,354],{"class":103},[97,449,357],{"class":228},[97,451,232],{"class":103},[97,453,454],{"class":228}," newQuery",[97,456,457],{"class":218},"  // 検索実行\n",[97,459,461,464,466,468,470,473],{"class":99,"line":460},19,[97,462,463],{"class":228},"    isSearching",[97,465,354],{"class":103},[97,467,357],{"class":228},[97,469,232],{"class":103},[97,471,472],{"class":285}," false",[97,474,475],{"class":218},"        // 「検索中...」を非表示\n",[97,477,479,482,486],{"class":99,"line":478},20,[97,480,481],{"class":103},"  },",[97,483,485],{"class":484},"sM54T"," 300",[97,487,404],{"class":103},[97,489,491],{"class":99,"line":490},21,[97,492,493],{"class":103},"})\n",[13,495,496],{},[30,497,498],{},"ポイント：",[145,500,501,506,512],{},[27,502,503,505],{},[77,504,328],{},"：入力フォームにバインド（即座に更新）",[27,507,508,511],{},[77,509,510],{},"debouncedQuery","：実際の検索に使用（300ms遅延）",[27,513,514,517,518,521],{},[77,515,516],{},"setTimeout","で遅延実行、",[77,519,520],{},"clearTimeout","で前の予約をキャンセル",[68,523,525],{"id":524},"_2-flexsearchインデックスの構築","2. FlexSearchインデックスの構築",[13,527,528,529,532],{},"FlexSearchは事前に「インデックス」を作る必要があります。インデックスとは",[30,530,531],{},"検索用の目次","のようなものです。",[73,534,535],{"id":535},"インデックスの初期化",[88,537,539],{"className":209,"code":538,"language":211,"meta":93,"style":93},"const searchIndex = ref(null)\n\n// FlexSearchのDocumentインデックスを作成\nsearchIndex.value = new Document({\n  document: {\n    id: 'path',                           // 記事を識別するキー\n    index: ['title', 'description', 'body'] // 検索対象のフィールド\n  },\n  tokenize: 'full',   // 完全なトークン化（柔軟な検索）\n  cache: true         // 検索結果をキャッシュして高速化\n})\n",[77,540,541,559,563,568,588,597,618,659,664,683,695],{"__ignoreMap":93},[97,542,543,545,548,550,552,554,557],{"class":99,"line":100},[97,544,225],{"class":224},[97,546,547],{"class":228}," searchIndex",[97,549,232],{"class":103},[97,551,236],{"class":235},[97,553,239],{"class":103},[97,555,556],{"class":224},"null",[97,558,404],{"class":103},[97,560,561],{"class":99,"line":107},[97,562,298],{"emptyLinePlaceholder":297},[97,564,565],{"class":99,"line":135},[97,566,567],{"class":218},"// FlexSearchのDocumentインデックスを作成\n",[97,569,570,573,575,577,579,582,585],{"class":99,"line":271},[97,571,572],{"class":228},"searchIndex",[97,574,354],{"class":103},[97,576,357],{"class":228},[97,578,232],{"class":103},[97,580,581],{"class":224}," new",[97,583,584],{"class":235}," Document",[97,586,587],{"class":103},"({\n",[97,589,590,593,595],{"class":99,"line":294},[97,591,592],{"class":114},"  document",[97,594,121],{"class":103},[97,596,345],{"class":103},[97,598,599,602,604,607,610,613,615],{"class":99,"line":301},[97,600,601],{"class":114},"    id",[97,603,121],{"class":103},[97,605,606],{"class":124}," '",[97,608,609],{"class":128},"path",[97,611,612],{"class":124},"'",[97,614,331],{"class":103},[97,616,617],{"class":218},"                           // 記事を識別するキー\n",[97,619,620,623,625,628,630,633,635,637,639,642,644,646,648,651,653,656],{"class":99,"line":315},[97,621,622],{"class":114},"    index",[97,624,121],{"class":103},[97,626,627],{"class":103}," [",[97,629,612],{"class":124},[97,631,632],{"class":128},"title",[97,634,612],{"class":124},[97,636,331],{"class":103},[97,638,606],{"class":124},[97,640,641],{"class":128},"description",[97,643,612],{"class":124},[97,645,331],{"class":103},[97,647,606],{"class":124},[97,649,650],{"class":128},"body",[97,652,612],{"class":124},[97,654,655],{"class":103},"]",[97,657,658],{"class":218}," // 検索対象のフィールド\n",[97,660,661],{"class":99,"line":320},[97,662,663],{"class":103},"  },\n",[97,665,666,669,671,673,676,678,680],{"class":99,"line":348},[97,667,668],{"class":114},"  tokenize",[97,670,121],{"class":103},[97,672,606],{"class":124},[97,674,675],{"class":128},"full",[97,677,612],{"class":124},[97,679,331],{"class":103},[97,681,682],{"class":218},"   // 完全なトークン化（柔軟な検索）\n",[97,684,685,688,690,692],{"class":99,"line":368},[97,686,687],{"class":114},"  cache",[97,689,121],{"class":103},[97,691,362],{"class":285},[97,693,694],{"class":218},"         // 検索結果をキャッシュして高速化\n",[97,696,697],{"class":99,"line":373},[97,698,493],{"class":103},[13,700,701],{},[30,702,703],{},"tokenizeオプション：",[145,705,706,712],{},[27,707,708,711],{},[77,709,710],{},"'forward'","：前方一致のみ（例：「検索」で「検索エンジン」は見つかるが「全文検索」は見つからない）",[27,713,714,717],{},[77,715,716],{},"'full'","：部分一致も可能（例：「検索」で「全文検索」も見つかる）",[73,719,720],{"id":720},"記事データの登録",[88,722,724],{"className":209,"code":723,"language":211,"meta":93,"style":93},"articles.forEach(article => {\n  // MDC ASTから本文テキストを抽出\n  const bodyText = extractTextFromAST(article.body.value)\n  \n  // FlexSearchインデックスに追加\n  searchIndex.value.add({\n    path: article.path,\n    title: article.title || '',\n    description: article.description || '',\n    body: bodyText\n  })\n})\n",[77,725,726,745,750,777,783,788,804,821,842,861,871,876],{"__ignoreMap":93},[97,727,728,731,733,736,738,741,743],{"class":99,"line":100},[97,729,730],{"class":228},"articles",[97,732,354],{"class":103},[97,734,735],{"class":235},"forEach",[97,737,239],{"class":103},[97,739,740],{"class":228},"article",[97,742,342],{"class":103},[97,744,345],{"class":103},[97,746,747],{"class":99,"line":107},[97,748,749],{"class":218},"  // MDC ASTから本文テキストを抽出\n",[97,751,752,755,758,760,763,765,767,769,771,773,775],{"class":99,"line":135},[97,753,754],{"class":224},"  const",[97,756,757],{"class":228}," bodyText",[97,759,232],{"class":103},[97,761,762],{"class":235}," extractTextFromAST",[97,764,239],{"class":103},[97,766,740],{"class":228},[97,768,354],{"class":103},[97,770,650],{"class":228},[97,772,354],{"class":103},[97,774,357],{"class":228},[97,776,404],{"class":103},[97,778,779],{"class":99,"line":271},[97,780,782],{"class":781},"sG7-3","  \n",[97,784,785],{"class":99,"line":294},[97,786,787],{"class":218},"  // FlexSearchインデックスに追加\n",[97,789,790,793,795,797,799,802],{"class":99,"line":301},[97,791,792],{"class":228},"  searchIndex",[97,794,354],{"class":103},[97,796,357],{"class":228},[97,798,354],{"class":103},[97,800,801],{"class":235},"add",[97,803,587],{"class":103},[97,805,806,809,811,814,816,818],{"class":99,"line":315},[97,807,808],{"class":114},"    path",[97,810,121],{"class":103},[97,812,813],{"class":228}," article",[97,815,354],{"class":103},[97,817,609],{"class":228},[97,819,820],{"class":103},",\n",[97,822,823,826,828,830,832,834,837,840],{"class":99,"line":320},[97,824,825],{"class":114},"    title",[97,827,121],{"class":103},[97,829,813],{"class":228},[97,831,354],{"class":103},[97,833,632],{"class":228},[97,835,836],{"class":224}," ||",[97,838,839],{"class":124}," ''",[97,841,820],{"class":103},[97,843,844,847,849,851,853,855,857,859],{"class":99,"line":348},[97,845,846],{"class":114},"    description",[97,848,121],{"class":103},[97,850,813],{"class":228},[97,852,354],{"class":103},[97,854,641],{"class":228},[97,856,836],{"class":224},[97,858,839],{"class":124},[97,860,820],{"class":103},[97,862,863,866,868],{"class":99,"line":368},[97,864,865],{"class":114},"    body",[97,867,121],{"class":103},[97,869,870],{"class":228}," bodyText\n",[97,872,873],{"class":99,"line":373},[97,874,875],{"class":103},"  })\n",[97,877,878],{"class":99,"line":379},[97,879,493],{"class":103},[68,881,883],{"id":882},"_3-mdc-astからのテキスト抽出","3. MDC ASTからのテキスト抽出",[13,885,886,887,890],{},"Nuxt Contentの記事本文は",[30,888,889],{},"AST（抽象構文木）","という特殊な形式で保存されています。",[73,892,894],{"id":893},"astとは","ASTとは？",[13,896,897],{},"Markdown/MDXを構造化したデータ形式です：",[13,899,900],{},[30,901,902],{},"元のMarkdown：",[88,904,908],{"className":905,"code":906,"language":907,"meta":93,"style":93},"language-markdown shiki shiki-themes vitesse-light vitesse-light","# 見出し\n\nこれは本文です。**太字**もあります。\n","markdown",[77,909,910,920,924],{"__ignoreMap":93},[97,911,912,916],{"class":99,"line":100},[97,913,915],{"class":914},"sFA8A","#",[97,917,919],{"class":918},"syTZV"," 見出し\n",[97,921,922],{"class":99,"line":107},[97,923,298],{"emptyLinePlaceholder":297},[97,925,926,929,932,936,938],{"class":99,"line":135},[97,927,928],{"class":781},"これは本文です。",[97,930,931],{"class":914},"**",[97,933,935],{"class":934},"s9pho","太字",[97,937,931],{"class":914},[97,939,940],{"class":781},"もあります。\n",[13,942,943],{},[30,944,945],{},"ASTの形式：",[88,947,949],{"className":209,"code":948,"language":211,"meta":93,"style":93},"[\n  [\"h1\", {}, \"見出し\"],\n  [\"p\", {}, \n    \"これは本文です。\",\n    [\"strong\", {}, \"太字\"],\n    \"もあります。\"\n  ]\n]\n",[77,950,951,956,982,999,1010,1033,1042,1047],{"__ignoreMap":93},[97,952,953],{"class":99,"line":100},[97,954,955],{"class":103},"[\n",[97,957,958,961,963,965,967,969,972,974,977,979],{"class":99,"line":107},[97,959,960],{"class":103},"  [",[97,962,118],{"class":124},[97,964,10],{"class":128},[97,966,118],{"class":124},[97,968,331],{"class":103},[97,970,971],{"class":103}," {},",[97,973,125],{"class":124},[97,975,976],{"class":128},"見出し",[97,978,118],{"class":124},[97,980,981],{"class":103},"],\n",[97,983,984,986,988,990,992,994,996],{"class":99,"line":135},[97,985,960],{"class":103},[97,987,118],{"class":124},[97,989,13],{"class":128},[97,991,118],{"class":124},[97,993,331],{"class":103},[97,995,971],{"class":103},[97,997,998],{"class":781}," \n",[97,1000,1001,1004,1006,1008],{"class":99,"line":271},[97,1002,1003],{"class":124},"    \"",[97,1005,928],{"class":128},[97,1007,118],{"class":124},[97,1009,820],{"class":103},[97,1011,1012,1015,1017,1019,1021,1023,1025,1027,1029,1031],{"class":99,"line":294},[97,1013,1014],{"class":103},"    [",[97,1016,118],{"class":124},[97,1018,30],{"class":128},[97,1020,118],{"class":124},[97,1022,331],{"class":103},[97,1024,971],{"class":103},[97,1026,125],{"class":124},[97,1028,935],{"class":128},[97,1030,118],{"class":124},[97,1032,981],{"class":103},[97,1034,1035,1037,1040],{"class":99,"line":301},[97,1036,1003],{"class":124},[97,1038,1039],{"class":128},"もあります。",[97,1041,132],{"class":124},[97,1043,1044],{"class":99,"line":315},[97,1045,1046],{"class":103},"  ]\n",[97,1048,1049],{"class":99,"line":320},[97,1050,1051],{"class":103},"]\n",[73,1053,1054],{"id":1054},"テキスト抽出関数",[88,1056,1058],{"className":209,"code":1057,"language":211,"meta":93,"style":93},"function extractTextFromAST(nodes) {\n  if (!nodes || !Array.isArray(nodes)) return ''\n\n  return nodes.map(node => {\n    // 1. 文字列ノード（直接的なテキスト）\n    if (typeof node === 'string') {\n      return node\n    }\n    \n    // 2. 配列ノード（MDC形式: [\"タグ名\", {属性}, ...子要素]）\n    if (Array.isArray(node)) {\n      const children = node.slice(2)  // 3番目以降が子要素\n      return extractTextFromAST(children)  // 再帰的に処理\n    }\n    \n    // 3. オブジェクトノード（従来のAST形式）\n    if (node.type === 'text') {\n      return node.value || ''\n    }\n    if (node.children) {\n      return extractTextFromAST(node.children)  // 再帰的に処理\n    }\n    \n    return ''\n  }).join(' ')  // スペースで連結\n}\n",[77,1059,1060,1076,1113,1117,1139,1144,1171,1179,1184,1189,1194,1214,1241,1257,1261,1265,1270,1295,1309,1313,1329,1347,1352,1357,1365,1385],{"__ignoreMap":93},[97,1061,1062,1065,1067,1069,1072,1074],{"class":99,"line":100},[97,1063,1064],{"class":224},"function",[97,1066,762],{"class":235},[97,1068,239],{"class":103},[97,1070,1071],{"class":228},"nodes",[97,1073,245],{"class":103},[97,1075,345],{"class":103},[97,1077,1078,1080,1082,1085,1087,1089,1092,1095,1097,1100,1102,1104,1107,1110],{"class":99,"line":107},[97,1079,382],{"class":285},[97,1081,334],{"class":103},[97,1083,1084],{"class":224},"!",[97,1086,1071],{"class":228},[97,1088,836],{"class":224},[97,1090,1091],{"class":224}," !",[97,1093,1094],{"class":228},"Array",[97,1096,354],{"class":103},[97,1098,1099],{"class":235},"isArray",[97,1101,239],{"class":103},[97,1103,1071],{"class":228},[97,1105,1106],{"class":103},"))",[97,1108,1109],{"class":285}," return",[97,1111,1112],{"class":124}," ''\n",[97,1114,1115],{"class":99,"line":135},[97,1116,298],{"emptyLinePlaceholder":297},[97,1118,1119,1122,1125,1127,1130,1132,1135,1137],{"class":99,"line":271},[97,1120,1121],{"class":285},"  return",[97,1123,1124],{"class":228}," nodes",[97,1126,354],{"class":103},[97,1128,1129],{"class":235},"map",[97,1131,239],{"class":103},[97,1133,1134],{"class":228},"node",[97,1136,342],{"class":103},[97,1138,345],{"class":103},[97,1140,1141],{"class":99,"line":294},[97,1142,1143],{"class":218},"    // 1. 文字列ノード（直接的なテキスト）\n",[97,1145,1146,1149,1151,1154,1157,1160,1162,1165,1167,1169],{"class":99,"line":301},[97,1147,1148],{"class":285},"    if",[97,1150,334],{"class":103},[97,1152,1153],{"class":224},"typeof",[97,1155,1156],{"class":228}," node",[97,1158,1159],{"class":224}," ===",[97,1161,606],{"class":124},[97,1163,1164],{"class":128},"string",[97,1166,612],{"class":124},[97,1168,245],{"class":103},[97,1170,345],{"class":103},[97,1172,1173,1176],{"class":99,"line":315},[97,1174,1175],{"class":285},"      return",[97,1177,1178],{"class":228}," node\n",[97,1180,1181],{"class":99,"line":320},[97,1182,1183],{"class":103},"    }\n",[97,1185,1186],{"class":99,"line":348},[97,1187,1188],{"class":781},"    \n",[97,1190,1191],{"class":99,"line":368},[97,1192,1193],{"class":218},"    // 2. 配列ノード（MDC形式: [\"タグ名\", {属性}, ...子要素]）\n",[97,1195,1196,1198,1200,1202,1204,1206,1208,1210,1212],{"class":99,"line":373},[97,1197,1148],{"class":285},[97,1199,334],{"class":103},[97,1201,1094],{"class":228},[97,1203,354],{"class":103},[97,1205,1099],{"class":235},[97,1207,239],{"class":103},[97,1209,1134],{"class":228},[97,1211,1106],{"class":103},[97,1213,345],{"class":103},[97,1215,1216,1219,1222,1224,1226,1228,1231,1233,1236,1238],{"class":99,"line":379},[97,1217,1218],{"class":224},"      const",[97,1220,1221],{"class":228}," children",[97,1223,232],{"class":103},[97,1225,1156],{"class":228},[97,1227,354],{"class":103},[97,1229,1230],{"class":235},"slice",[97,1232,239],{"class":103},[97,1234,1235],{"class":484},"2",[97,1237,245],{"class":103},[97,1239,1240],{"class":218},"  // 3番目以降が子要素\n",[97,1242,1243,1245,1247,1249,1252,1254],{"class":99,"line":394},[97,1244,1175],{"class":285},[97,1246,762],{"class":235},[97,1248,239],{"class":103},[97,1250,1251],{"class":228},"children",[97,1253,245],{"class":103},[97,1255,1256],{"class":218},"  // 再帰的に処理\n",[97,1258,1259],{"class":99,"line":407},[97,1260,1183],{"class":103},[97,1262,1263],{"class":99,"line":413},[97,1264,1188],{"class":781},[97,1266,1267],{"class":99,"line":418},[97,1268,1269],{"class":218},"    // 3. オブジェクトノード（従来のAST形式）\n",[97,1271,1272,1274,1276,1278,1280,1283,1285,1287,1289,1291,1293],{"class":99,"line":424},[97,1273,1148],{"class":285},[97,1275,334],{"class":103},[97,1277,1134],{"class":228},[97,1279,354],{"class":103},[97,1281,1282],{"class":228},"type",[97,1284,1159],{"class":224},[97,1286,606],{"class":124},[97,1288,185],{"class":128},[97,1290,612],{"class":124},[97,1292,245],{"class":103},[97,1294,345],{"class":103},[97,1296,1297,1299,1301,1303,1305,1307],{"class":99,"line":442},[97,1298,1175],{"class":285},[97,1300,1156],{"class":228},[97,1302,354],{"class":103},[97,1304,357],{"class":228},[97,1306,836],{"class":224},[97,1308,1112],{"class":124},[97,1310,1311],{"class":99,"line":460},[97,1312,1183],{"class":103},[97,1314,1315,1317,1319,1321,1323,1325,1327],{"class":99,"line":478},[97,1316,1148],{"class":285},[97,1318,334],{"class":103},[97,1320,1134],{"class":228},[97,1322,354],{"class":103},[97,1324,1251],{"class":228},[97,1326,245],{"class":103},[97,1328,345],{"class":103},[97,1330,1331,1333,1335,1337,1339,1341,1343,1345],{"class":99,"line":490},[97,1332,1175],{"class":285},[97,1334,762],{"class":235},[97,1336,239],{"class":103},[97,1338,1134],{"class":228},[97,1340,354],{"class":103},[97,1342,1251],{"class":228},[97,1344,245],{"class":103},[97,1346,1256],{"class":218},[97,1348,1350],{"class":99,"line":1349},22,[97,1351,1183],{"class":103},[97,1353,1355],{"class":99,"line":1354},23,[97,1356,1188],{"class":781},[97,1358,1360,1363],{"class":99,"line":1359},24,[97,1361,1362],{"class":285},"    return",[97,1364,1112],{"class":124},[97,1366,1368,1371,1374,1376,1378,1380,1382],{"class":99,"line":1367},25,[97,1369,1370],{"class":103},"  }).",[97,1372,1373],{"class":235},"join",[97,1375,239],{"class":103},[97,1377,612],{"class":124},[97,1379,606],{"class":124},[97,1381,245],{"class":103},[97,1383,1384],{"class":218},"  // スペースで連結\n",[97,1386,1388],{"class":99,"line":1387},26,[97,1389,138],{"class":103},[13,1391,1392],{},[30,1393,1394],{},"再帰処理の流れ：",[88,1396,1399],{"className":1397,"code":1398,"language":185},[183],"[\"p\", {}, \"これは\", [\"strong\", {}, \"太字\"], \"です\"]\n  ↓\n\"これは\" + extractTextFromAST([[\"strong\", {}, \"太字\"]]) + \"です\"\n  ↓\n\"これは\" + \"太字\" + \"です\"\n  ↓\n\"これは 太字 です\"\n",[77,1400,1398],{"__ignoreMap":93},[68,1402,1404],{"id":1403},"_4-検索の実行とフォールバック","4. 検索の実行とフォールバック",[73,1406,1408],{"id":1407},"flexsearchによる検索","FlexSearchによる検索",[88,1410,1412],{"className":209,"code":1411,"language":211,"meta":93,"style":93},"const searchResults = searchIndex.value.search(query, {\n  limit: 1000,     // 最大1000件まで検索\n  suggest: true    // サジェスト機能を有効化\n})\n\n// 検索結果のパスを集約\nconst matchedPaths = new Set()\nsearchResults.forEach(fieldResult => {\n  if (fieldResult.result) {\n    fieldResult.result.forEach(path => matchedPaths.add(path))\n  }\n})\n",[77,1413,1414,1443,1458,1470,1474,1478,1483,1500,1518,1535,1567,1571],{"__ignoreMap":93},[97,1415,1416,1418,1421,1423,1425,1427,1429,1431,1434,1436,1439,1441],{"class":99,"line":100},[97,1417,225],{"class":224},[97,1419,1420],{"class":228}," searchResults",[97,1422,232],{"class":103},[97,1424,547],{"class":228},[97,1426,354],{"class":103},[97,1428,357],{"class":228},[97,1430,354],{"class":103},[97,1432,1433],{"class":235},"search",[97,1435,239],{"class":103},[97,1437,1438],{"class":228},"query",[97,1440,331],{"class":103},[97,1442,345],{"class":103},[97,1444,1445,1448,1450,1453,1455],{"class":99,"line":107},[97,1446,1447],{"class":114},"  limit",[97,1449,121],{"class":103},[97,1451,1452],{"class":484}," 1000",[97,1454,331],{"class":103},[97,1456,1457],{"class":218},"     // 最大1000件まで検索\n",[97,1459,1460,1463,1465,1467],{"class":99,"line":135},[97,1461,1462],{"class":114},"  suggest",[97,1464,121],{"class":103},[97,1466,362],{"class":285},[97,1468,1469],{"class":218},"    // サジェスト機能を有効化\n",[97,1471,1472],{"class":99,"line":271},[97,1473,493],{"class":103},[97,1475,1476],{"class":99,"line":294},[97,1477,298],{"emptyLinePlaceholder":297},[97,1479,1480],{"class":99,"line":301},[97,1481,1482],{"class":218},"// 検索結果のパスを集約\n",[97,1484,1485,1487,1490,1492,1494,1497],{"class":99,"line":315},[97,1486,225],{"class":224},[97,1488,1489],{"class":228}," matchedPaths",[97,1491,232],{"class":103},[97,1493,581],{"class":224},[97,1495,1496],{"class":235}," Set",[97,1498,1499],{"class":103},"()\n",[97,1501,1502,1505,1507,1509,1511,1514,1516],{"class":99,"line":320},[97,1503,1504],{"class":228},"searchResults",[97,1506,354],{"class":103},[97,1508,735],{"class":235},[97,1510,239],{"class":103},[97,1512,1513],{"class":228},"fieldResult",[97,1515,342],{"class":103},[97,1517,345],{"class":103},[97,1519,1520,1522,1524,1526,1528,1531,1533],{"class":99,"line":348},[97,1521,382],{"class":285},[97,1523,334],{"class":103},[97,1525,1513],{"class":228},[97,1527,354],{"class":103},[97,1529,1530],{"class":228},"result",[97,1532,245],{"class":103},[97,1534,345],{"class":103},[97,1536,1537,1540,1542,1544,1546,1548,1550,1552,1554,1556,1558,1560,1562,1564],{"class":99,"line":368},[97,1538,1539],{"class":228},"    fieldResult",[97,1541,354],{"class":103},[97,1543,1530],{"class":228},[97,1545,354],{"class":103},[97,1547,735],{"class":235},[97,1549,239],{"class":103},[97,1551,609],{"class":228},[97,1553,342],{"class":103},[97,1555,1489],{"class":228},[97,1557,354],{"class":103},[97,1559,801],{"class":235},[97,1561,239],{"class":103},[97,1563,609],{"class":228},[97,1565,1566],{"class":103},"))\n",[97,1568,1569],{"class":99,"line":373},[97,1570,410],{"class":103},[97,1572,1573],{"class":99,"line":379},[97,1574,493],{"class":103},[73,1576,1577],{"id":1577},"フォールバック検索",[13,1579,1580],{},"FlexSearchで見つからない場合、シンプルな部分一致検索にフォールバックします：",[88,1582,1584],{"className":209,"code":1583,"language":211,"meta":93,"style":93},"if (matchedPaths.size === 0) {\n  const lowerQuery = query.toLowerCase()\n  results.forEach(article => {\n    const title = (article.title || '').toLowerCase()\n    const description = (article.description || '').toLowerCase()\n    const bodyText = articleBodies.value.get(article.path) || ''\n    const lowerBody = bodyText.toLowerCase()\n\n    // いずれかにキーワードが含まれていれば追加\n    if (title.includes(lowerQuery) || \n        description.includes(lowerQuery) || \n        lowerBody.includes(lowerQuery)) {\n      matchedPaths.add(article.path)\n    }\n  })\n}\n",[77,1585,1586,1610,1629,1646,1675,1702,1736,1753,1757,1762,1786,1805,1822,1841,1845,1849],{"__ignoreMap":93},[97,1587,1588,1591,1593,1596,1598,1601,1603,1606,1608],{"class":99,"line":100},[97,1589,1590],{"class":285},"if",[97,1592,334],{"class":103},[97,1594,1595],{"class":228},"matchedPaths",[97,1597,354],{"class":103},[97,1599,1600],{"class":228},"size",[97,1602,1159],{"class":224},[97,1604,1605],{"class":484}," 0",[97,1607,245],{"class":103},[97,1609,345],{"class":103},[97,1611,1612,1614,1617,1619,1622,1624,1627],{"class":99,"line":107},[97,1613,754],{"class":224},[97,1615,1616],{"class":228}," lowerQuery",[97,1618,232],{"class":103},[97,1620,1621],{"class":228}," query",[97,1623,354],{"class":103},[97,1625,1626],{"class":235},"toLowerCase",[97,1628,1499],{"class":103},[97,1630,1631,1634,1636,1638,1640,1642,1644],{"class":99,"line":135},[97,1632,1633],{"class":228},"  results",[97,1635,354],{"class":103},[97,1637,735],{"class":235},[97,1639,239],{"class":103},[97,1641,740],{"class":228},[97,1643,342],{"class":103},[97,1645,345],{"class":103},[97,1647,1648,1651,1654,1656,1658,1660,1662,1664,1666,1668,1671,1673],{"class":99,"line":271},[97,1649,1650],{"class":224},"    const",[97,1652,1653],{"class":228}," title",[97,1655,232],{"class":103},[97,1657,334],{"class":103},[97,1659,740],{"class":228},[97,1661,354],{"class":103},[97,1663,632],{"class":228},[97,1665,836],{"class":224},[97,1667,839],{"class":124},[97,1669,1670],{"class":103},").",[97,1672,1626],{"class":235},[97,1674,1499],{"class":103},[97,1676,1677,1679,1682,1684,1686,1688,1690,1692,1694,1696,1698,1700],{"class":99,"line":294},[97,1678,1650],{"class":224},[97,1680,1681],{"class":228}," description",[97,1683,232],{"class":103},[97,1685,334],{"class":103},[97,1687,740],{"class":228},[97,1689,354],{"class":103},[97,1691,641],{"class":228},[97,1693,836],{"class":224},[97,1695,839],{"class":124},[97,1697,1670],{"class":103},[97,1699,1626],{"class":235},[97,1701,1499],{"class":103},[97,1703,1704,1706,1708,1710,1713,1715,1717,1719,1722,1724,1726,1728,1730,1732,1734],{"class":99,"line":301},[97,1705,1650],{"class":224},[97,1707,757],{"class":228},[97,1709,232],{"class":103},[97,1711,1712],{"class":228}," articleBodies",[97,1714,354],{"class":103},[97,1716,357],{"class":228},[97,1718,354],{"class":103},[97,1720,1721],{"class":235},"get",[97,1723,239],{"class":103},[97,1725,740],{"class":228},[97,1727,354],{"class":103},[97,1729,609],{"class":228},[97,1731,245],{"class":103},[97,1733,836],{"class":224},[97,1735,1112],{"class":124},[97,1737,1738,1740,1743,1745,1747,1749,1751],{"class":99,"line":315},[97,1739,1650],{"class":224},[97,1741,1742],{"class":228}," lowerBody",[97,1744,232],{"class":103},[97,1746,757],{"class":228},[97,1748,354],{"class":103},[97,1750,1626],{"class":235},[97,1752,1499],{"class":103},[97,1754,1755],{"class":99,"line":320},[97,1756,298],{"emptyLinePlaceholder":297},[97,1758,1759],{"class":99,"line":348},[97,1760,1761],{"class":218},"    // いずれかにキーワードが含まれていれば追加\n",[97,1763,1764,1766,1768,1770,1772,1775,1777,1780,1782,1784],{"class":99,"line":368},[97,1765,1148],{"class":285},[97,1767,334],{"class":103},[97,1769,632],{"class":228},[97,1771,354],{"class":103},[97,1773,1774],{"class":235},"includes",[97,1776,239],{"class":103},[97,1778,1779],{"class":228},"lowerQuery",[97,1781,245],{"class":103},[97,1783,836],{"class":224},[97,1785,998],{"class":781},[97,1787,1788,1791,1793,1795,1797,1799,1801,1803],{"class":99,"line":373},[97,1789,1790],{"class":228},"        description",[97,1792,354],{"class":103},[97,1794,1774],{"class":235},[97,1796,239],{"class":103},[97,1798,1779],{"class":228},[97,1800,245],{"class":103},[97,1802,836],{"class":224},[97,1804,998],{"class":781},[97,1806,1807,1810,1812,1814,1816,1818,1820],{"class":99,"line":379},[97,1808,1809],{"class":228},"        lowerBody",[97,1811,354],{"class":103},[97,1813,1774],{"class":235},[97,1815,239],{"class":103},[97,1817,1779],{"class":228},[97,1819,1106],{"class":103},[97,1821,345],{"class":103},[97,1823,1824,1827,1829,1831,1833,1835,1837,1839],{"class":99,"line":394},[97,1825,1826],{"class":228},"      matchedPaths",[97,1828,354],{"class":103},[97,1830,801],{"class":235},[97,1832,239],{"class":103},[97,1834,740],{"class":228},[97,1836,354],{"class":103},[97,1838,609],{"class":228},[97,1840,404],{"class":103},[97,1842,1843],{"class":99,"line":407},[97,1844,1183],{"class":103},[97,1846,1847],{"class":99,"line":413},[97,1848,875],{"class":103},[97,1850,1851],{"class":99,"line":418},[97,1852,138],{"class":103},[68,1854,1856],{"id":1855},"_5-スニペット生成とハイライト","5. スニペット生成とハイライト",[73,1858,56],{"id":56},[13,1860,1861],{},"検索キーワード周辺の文章を切り出します：",[88,1863,1865],{"className":209,"code":1864,"language":211,"meta":93,"style":93},"function generateSnippet(text, query, maxLength = 200) {\n  if (!text || !query) return ''\n  \n  // キーワードの位置を探す\n  const lowerText = text.toLowerCase()\n  const lowerQuery = query.toLowerCase()\n  const index = lowerText.indexOf(lowerQuery)\n  \n  if (index === -1) return ''\n  \n  // キーワードを中心に前後100文字ずつ取得\n  const start = Math.max(0, index - Math.floor(maxLength / 2))\n  const end = Math.min(text.length, index + query.length + Math.floor(maxLength / 2))\n  \n  let snippet = text.slice(start, end)\n  \n  // 省略記号を追加\n  if (start > 0) snippet = '...' + snippet\n  if (end \u003C text.length) snippet = snippet + '...'\n  \n  return snippet\n}\n",[77,1866,1867,1896,1918,1922,1927,1945,1961,1983,1987,2010,2014,2019,2067,2123,2127,2154,2158,2163,2194,2229,2233,2239],{"__ignoreMap":93},[97,1868,1869,1871,1874,1876,1878,1880,1882,1884,1887,1889,1892,1894],{"class":99,"line":100},[97,1870,1064],{"class":224},[97,1872,1873],{"class":235}," generateSnippet",[97,1875,239],{"class":103},[97,1877,185],{"class":228},[97,1879,331],{"class":103},[97,1881,1621],{"class":228},[97,1883,331],{"class":103},[97,1885,1886],{"class":228}," maxLength",[97,1888,232],{"class":103},[97,1890,1891],{"class":484}," 200",[97,1893,245],{"class":103},[97,1895,345],{"class":103},[97,1897,1898,1900,1902,1904,1906,1908,1910,1912,1914,1916],{"class":99,"line":107},[97,1899,382],{"class":285},[97,1901,334],{"class":103},[97,1903,1084],{"class":224},[97,1905,185],{"class":228},[97,1907,836],{"class":224},[97,1909,1091],{"class":224},[97,1911,1438],{"class":228},[97,1913,245],{"class":103},[97,1915,1109],{"class":285},[97,1917,1112],{"class":124},[97,1919,1920],{"class":99,"line":135},[97,1921,782],{"class":781},[97,1923,1924],{"class":99,"line":271},[97,1925,1926],{"class":218},"  // キーワードの位置を探す\n",[97,1928,1929,1931,1934,1936,1939,1941,1943],{"class":99,"line":294},[97,1930,754],{"class":224},[97,1932,1933],{"class":228}," lowerText",[97,1935,232],{"class":103},[97,1937,1938],{"class":228}," text",[97,1940,354],{"class":103},[97,1942,1626],{"class":235},[97,1944,1499],{"class":103},[97,1946,1947,1949,1951,1953,1955,1957,1959],{"class":99,"line":301},[97,1948,754],{"class":224},[97,1950,1616],{"class":228},[97,1952,232],{"class":103},[97,1954,1621],{"class":228},[97,1956,354],{"class":103},[97,1958,1626],{"class":235},[97,1960,1499],{"class":103},[97,1962,1963,1965,1968,1970,1972,1974,1977,1979,1981],{"class":99,"line":315},[97,1964,754],{"class":224},[97,1966,1967],{"class":228}," index",[97,1969,232],{"class":103},[97,1971,1933],{"class":228},[97,1973,354],{"class":103},[97,1975,1976],{"class":235},"indexOf",[97,1978,239],{"class":103},[97,1980,1779],{"class":228},[97,1982,404],{"class":103},[97,1984,1985],{"class":99,"line":320},[97,1986,782],{"class":781},[97,1988,1989,1991,1993,1996,1998,2001,2004,2006,2008],{"class":99,"line":348},[97,1990,382],{"class":285},[97,1992,334],{"class":103},[97,1994,1995],{"class":228},"index",[97,1997,1159],{"class":224},[97,1999,2000],{"class":224}," -",[97,2002,2003],{"class":484},"1",[97,2005,245],{"class":103},[97,2007,1109],{"class":285},[97,2009,1112],{"class":124},[97,2011,2012],{"class":99,"line":368},[97,2013,782],{"class":781},[97,2015,2016],{"class":99,"line":373},[97,2017,2018],{"class":218},"  // キーワードを中心に前後100文字ずつ取得\n",[97,2020,2021,2023,2026,2028,2031,2033,2036,2038,2041,2043,2045,2047,2049,2051,2054,2056,2059,2062,2065],{"class":99,"line":379},[97,2022,754],{"class":224},[97,2024,2025],{"class":228}," start",[97,2027,232],{"class":103},[97,2029,2030],{"class":228}," Math",[97,2032,354],{"class":103},[97,2034,2035],{"class":235},"max",[97,2037,239],{"class":103},[97,2039,2040],{"class":484},"0",[97,2042,331],{"class":103},[97,2044,1967],{"class":228},[97,2046,2000],{"class":224},[97,2048,2030],{"class":228},[97,2050,354],{"class":103},[97,2052,2053],{"class":235},"floor",[97,2055,239],{"class":103},[97,2057,2058],{"class":228},"maxLength",[97,2060,2061],{"class":224}," /",[97,2063,2064],{"class":484}," 2",[97,2066,1566],{"class":103},[97,2068,2069,2071,2074,2076,2078,2080,2083,2085,2087,2089,2092,2094,2096,2099,2101,2103,2105,2107,2109,2111,2113,2115,2117,2119,2121],{"class":99,"line":394},[97,2070,754],{"class":224},[97,2072,2073],{"class":228}," end",[97,2075,232],{"class":103},[97,2077,2030],{"class":228},[97,2079,354],{"class":103},[97,2081,2082],{"class":235},"min",[97,2084,239],{"class":103},[97,2086,185],{"class":228},[97,2088,354],{"class":103},[97,2090,2091],{"class":114},"length",[97,2093,331],{"class":103},[97,2095,1967],{"class":228},[97,2097,2098],{"class":224}," +",[97,2100,1621],{"class":228},[97,2102,354],{"class":103},[97,2104,2091],{"class":114},[97,2106,2098],{"class":224},[97,2108,2030],{"class":228},[97,2110,354],{"class":103},[97,2112,2053],{"class":235},[97,2114,239],{"class":103},[97,2116,2058],{"class":228},[97,2118,2061],{"class":224},[97,2120,2064],{"class":484},[97,2122,1566],{"class":103},[97,2124,2125],{"class":99,"line":407},[97,2126,782],{"class":781},[97,2128,2129,2132,2135,2137,2139,2141,2143,2145,2148,2150,2152],{"class":99,"line":413},[97,2130,2131],{"class":224},"  let",[97,2133,2134],{"class":228}," snippet",[97,2136,232],{"class":103},[97,2138,1938],{"class":228},[97,2140,354],{"class":103},[97,2142,1230],{"class":235},[97,2144,239],{"class":103},[97,2146,2147],{"class":228},"start",[97,2149,331],{"class":103},[97,2151,2073],{"class":228},[97,2153,404],{"class":103},[97,2155,2156],{"class":99,"line":418},[97,2157,782],{"class":781},[97,2159,2160],{"class":99,"line":424},[97,2161,2162],{"class":218},"  // 省略記号を追加\n",[97,2164,2165,2167,2169,2171,2174,2176,2178,2180,2182,2184,2187,2189,2191],{"class":99,"line":442},[97,2166,382],{"class":285},[97,2168,334],{"class":103},[97,2170,2147],{"class":228},[97,2172,2173],{"class":103}," >",[97,2175,1605],{"class":484},[97,2177,245],{"class":103},[97,2179,2134],{"class":228},[97,2181,232],{"class":103},[97,2183,606],{"class":124},[97,2185,2186],{"class":128},"...",[97,2188,612],{"class":124},[97,2190,2098],{"class":224},[97,2192,2193],{"class":228}," snippet\n",[97,2195,2196,2198,2200,2203,2206,2208,2210,2212,2214,2216,2218,2220,2222,2224,2226],{"class":99,"line":460},[97,2197,382],{"class":285},[97,2199,334],{"class":103},[97,2201,2202],{"class":228},"end",[97,2204,2205],{"class":103}," \u003C",[97,2207,1938],{"class":228},[97,2209,354],{"class":103},[97,2211,2091],{"class":114},[97,2213,245],{"class":103},[97,2215,2134],{"class":228},[97,2217,232],{"class":103},[97,2219,2134],{"class":228},[97,2221,2098],{"class":224},[97,2223,606],{"class":124},[97,2225,2186],{"class":128},[97,2227,2228],{"class":124},"'\n",[97,2230,2231],{"class":99,"line":478},[97,2232,782],{"class":781},[97,2234,2235,2237],{"class":99,"line":490},[97,2236,1121],{"class":285},[97,2238,2193],{"class":228},[97,2240,2241],{"class":99,"line":1349},[97,2242,138],{"class":103},[73,2244,2245],{"id":2245},"キーワードのハイライト",[88,2247,2249],{"className":209,"code":2248,"language":211,"meta":93,"style":93},"function highlightKeyword(text, query) {\n  if (!text || !query) return text\n  \n  // 正規表現で検索（大文字小文字を区別しない）\n  const regex = new RegExp(`(${escapeRegex(query)})`, 'gi')\n  \n  // \u003Cmark>タグで囲む\n  return text.replace(regex, '\u003Cmark class=\"highlight\">$1\u003C/mark>')\n}\n",[77,2250,2251,2270,2293,2297,2302,2353,2357,2362,2389],{"__ignoreMap":93},[97,2252,2253,2255,2258,2260,2262,2264,2266,2268],{"class":99,"line":100},[97,2254,1064],{"class":224},[97,2256,2257],{"class":235}," highlightKeyword",[97,2259,239],{"class":103},[97,2261,185],{"class":228},[97,2263,331],{"class":103},[97,2265,1621],{"class":228},[97,2267,245],{"class":103},[97,2269,345],{"class":103},[97,2271,2272,2274,2276,2278,2280,2282,2284,2286,2288,2290],{"class":99,"line":107},[97,2273,382],{"class":285},[97,2275,334],{"class":103},[97,2277,1084],{"class":224},[97,2279,185],{"class":228},[97,2281,836],{"class":224},[97,2283,1091],{"class":224},[97,2285,1438],{"class":228},[97,2287,245],{"class":103},[97,2289,1109],{"class":285},[97,2291,2292],{"class":228}," text\n",[97,2294,2295],{"class":99,"line":135},[97,2296,782],{"class":781},[97,2298,2299],{"class":99,"line":271},[97,2300,2301],{"class":218},"  // 正規表現で検索（大文字小文字を区別しない）\n",[97,2303,2304,2306,2309,2311,2313,2316,2318,2321,2323,2326,2329,2331,2333,2335,2338,2340,2342,2344,2346,2349,2351],{"class":99,"line":294},[97,2305,754],{"class":224},[97,2307,2308],{"class":228}," regex",[97,2310,232],{"class":103},[97,2312,581],{"class":224},[97,2314,2315],{"class":235}," RegExp",[97,2317,239],{"class":103},[97,2319,2320],{"class":124},"`",[97,2322,239],{"class":128},[97,2324,2325],{"class":285},"${",[97,2327,2328],{"class":235},"escapeRegex",[97,2330,239],{"class":103},[97,2332,1438],{"class":128},[97,2334,245],{"class":103},[97,2336,2337],{"class":285},"}",[97,2339,245],{"class":128},[97,2341,2320],{"class":124},[97,2343,331],{"class":103},[97,2345,606],{"class":124},[97,2347,2348],{"class":128},"gi",[97,2350,612],{"class":124},[97,2352,404],{"class":103},[97,2354,2355],{"class":99,"line":301},[97,2356,782],{"class":781},[97,2358,2359],{"class":99,"line":315},[97,2360,2361],{"class":218},"  // \u003Cmark>タグで囲む\n",[97,2363,2364,2366,2368,2370,2373,2375,2378,2380,2382,2385,2387],{"class":99,"line":320},[97,2365,1121],{"class":285},[97,2367,1938],{"class":228},[97,2369,354],{"class":103},[97,2371,2372],{"class":235},"replace",[97,2374,239],{"class":103},[97,2376,2377],{"class":228},"regex",[97,2379,331],{"class":103},[97,2381,606],{"class":124},[97,2383,2384],{"class":128},"\u003Cmark class=\"highlight\">$1\u003C/mark>",[97,2386,612],{"class":124},[97,2388,404],{"class":103},[97,2390,2391],{"class":99,"line":348},[97,2392,138],{"class":103},[13,2394,2395],{},[30,2396,2397],{},"結果の表示：",[88,2399,2403],{"className":2400,"code":2401,"language":2402,"meta":93,"style":93},"language-html shiki shiki-themes vitesse-light vitesse-light","\u003C!-- v-htmlで安全にHTMLとして表示 -->\n\u003Cp v-if=\"article.snippet\" class=\"result-snippet\" v-html=\"article.snippet\">\u003C/p>\n","html",[77,2404,2405,2410],{"__ignoreMap":93},[97,2406,2407],{"class":99,"line":100},[97,2408,2409],{"class":218},"\u003C!-- v-htmlで安全にHTMLとして表示 -->\n",[97,2411,2412,2415,2417,2420,2423,2425,2428,2430,2433,2435,2437,2440,2442,2445,2447,2449,2451,2453,2456,2458],{"class":99,"line":107},[97,2413,2414],{"class":103},"\u003C",[97,2416,13],{"class":285},[97,2418,2419],{"class":228}," v-if",[97,2421,2422],{"class":103},"=",[97,2424,118],{"class":124},[97,2426,2427],{"class":128},"article.snippet",[97,2429,118],{"class":124},[97,2431,2432],{"class":228}," class",[97,2434,2422],{"class":103},[97,2436,118],{"class":124},[97,2438,2439],{"class":128},"result-snippet",[97,2441,118],{"class":124},[97,2443,2444],{"class":228}," v-html",[97,2446,2422],{"class":103},[97,2448,118],{"class":124},[97,2450,2427],{"class":128},[97,2452,118],{"class":124},[97,2454,2455],{"class":103},">\u003C/",[97,2457,13],{"class":285},[97,2459,2460],{"class":103},">\n",[13,2462,2463],{},[30,2464,2465],{},"CSSスタイル：",[88,2467,2471],{"className":2468,"code":2469,"language":2470,"meta":93,"style":93},"language-css shiki shiki-themes vitesse-light vitesse-light",".result-snippet :deep(mark.highlight) {\n  background: #fef3c7;   /* 黄色の背景 */\n  color: #92400e;        /* 茶色の文字 */\n  font-weight: 600;      /* 太字 */\n  padding: 0.125rem 0.25rem;\n  border-radius: 0.125rem;\n}\n","css",[77,2472,2473,2495,2515,2532,2547,2568,2581],{"__ignoreMap":93},[97,2474,2475,2477,2479,2482,2485,2487,2490,2493],{"class":99,"line":100},[97,2476,354],{"class":103},[97,2478,2439],{"class":228},[97,2480,2481],{"class":781}," :deep(",[97,2483,2484],{"class":285},"mark",[97,2486,354],{"class":103},[97,2488,2489],{"class":228},"highlight",[97,2491,2492],{"class":781},") ",[97,2494,104],{"class":103},[97,2496,2497,2500,2502,2505,2509,2512],{"class":99,"line":107},[97,2498,2499],{"class":114},"  background",[97,2501,121],{"class":103},[97,2503,2504],{"class":103}," #",[97,2506,2508],{"class":2507},"snbK4","fef3c7",[97,2510,2511],{"class":103},";",[97,2513,2514],{"class":218},"   /* 黄色の背景 */\n",[97,2516,2517,2520,2522,2524,2527,2529],{"class":99,"line":135},[97,2518,2519],{"class":114},"  color",[97,2521,121],{"class":103},[97,2523,2504],{"class":103},[97,2525,2526],{"class":2507},"92400e",[97,2528,2511],{"class":103},[97,2530,2531],{"class":218},"        /* 茶色の文字 */\n",[97,2533,2534,2537,2539,2542,2544],{"class":99,"line":271},[97,2535,2536],{"class":114},"  font-weight",[97,2538,121],{"class":103},[97,2540,2541],{"class":484}," 600",[97,2543,2511],{"class":103},[97,2545,2546],{"class":218},"      /* 太字 */\n",[97,2548,2549,2552,2554,2557,2560,2563,2565],{"class":99,"line":294},[97,2550,2551],{"class":114},"  padding",[97,2553,121],{"class":103},[97,2555,2556],{"class":484}," 0.125",[97,2558,2559],{"class":224},"rem",[97,2561,2562],{"class":484}," 0.25",[97,2564,2559],{"class":224},[97,2566,2567],{"class":103},";\n",[97,2569,2570,2573,2575,2577,2579],{"class":99,"line":301},[97,2571,2572],{"class":114},"  border-radius",[97,2574,121],{"class":103},[97,2576,2556],{"class":484},[97,2578,2559],{"class":224},[97,2580,2567],{"class":103},[97,2582,2583],{"class":99,"line":315},[97,2584,138],{"class":103},[68,2586,2588],{"id":2587},"_6-ページネーション","6. ページネーション",[13,2590,2591],{},"大量の検索結果を20件ずつ分割表示します：",[88,2593,2595],{"className":209,"code":2594,"language":211,"meta":93,"style":93},"const currentPage = ref(1)\nconst itemsPerPage = 20\n\n// 総ページ数の計算\nconst totalPages = computed(() => {\n  return Math.ceil(filteredArticles.value.length / itemsPerPage)\n})\n\n// 現在のページの記事のみ取得\nconst paginatedResults = computed(() => {\n  const start = (currentPage.value - 1) * itemsPerPage  // 開始位置\n  const end = start + itemsPerPage                       // 終了位置\n  return filteredArticles.value.slice(start, end)\n})\n\n// 検索クエリが変わったらページをリセット\nwatch(debouncedQuery, () => {\n  currentPage.value = 1\n})\n",[77,2596,2597,2614,2626,2630,2635,2653,2683,2687,2691,2696,2713,2745,2762,2787,2791,2795,2800,2817,2831],{"__ignoreMap":93},[97,2598,2599,2601,2604,2606,2608,2610,2612],{"class":99,"line":100},[97,2600,225],{"class":224},[97,2602,2603],{"class":228}," currentPage",[97,2605,232],{"class":103},[97,2607,236],{"class":235},[97,2609,239],{"class":103},[97,2611,2003],{"class":484},[97,2613,404],{"class":103},[97,2615,2616,2618,2621,2623],{"class":99,"line":107},[97,2617,225],{"class":224},[97,2619,2620],{"class":228}," itemsPerPage",[97,2622,232],{"class":103},[97,2624,2625],{"class":484}," 20\n",[97,2627,2628],{"class":99,"line":135},[97,2629,298],{"emptyLinePlaceholder":297},[97,2631,2632],{"class":99,"line":271},[97,2633,2634],{"class":218},"// 総ページ数の計算\n",[97,2636,2637,2639,2642,2644,2647,2649,2651],{"class":99,"line":294},[97,2638,225],{"class":224},[97,2640,2641],{"class":228}," totalPages",[97,2643,232],{"class":103},[97,2645,2646],{"class":235}," computed",[97,2648,435],{"class":103},[97,2650,342],{"class":103},[97,2652,345],{"class":103},[97,2654,2655,2657,2659,2661,2664,2666,2669,2671,2673,2675,2677,2679,2681],{"class":99,"line":301},[97,2656,1121],{"class":285},[97,2658,2030],{"class":228},[97,2660,354],{"class":103},[97,2662,2663],{"class":235},"ceil",[97,2665,239],{"class":103},[97,2667,2668],{"class":228},"filteredArticles",[97,2670,354],{"class":103},[97,2672,357],{"class":228},[97,2674,354],{"class":103},[97,2676,2091],{"class":114},[97,2678,2061],{"class":224},[97,2680,2620],{"class":228},[97,2682,404],{"class":103},[97,2684,2685],{"class":99,"line":315},[97,2686,493],{"class":103},[97,2688,2689],{"class":99,"line":320},[97,2690,298],{"emptyLinePlaceholder":297},[97,2692,2693],{"class":99,"line":348},[97,2694,2695],{"class":218},"// 現在のページの記事のみ取得\n",[97,2697,2698,2700,2703,2705,2707,2709,2711],{"class":99,"line":368},[97,2699,225],{"class":224},[97,2701,2702],{"class":228}," paginatedResults",[97,2704,232],{"class":103},[97,2706,2646],{"class":235},[97,2708,435],{"class":103},[97,2710,342],{"class":103},[97,2712,345],{"class":103},[97,2714,2715,2717,2719,2721,2723,2726,2728,2730,2732,2735,2737,2740,2742],{"class":99,"line":373},[97,2716,754],{"class":224},[97,2718,2025],{"class":228},[97,2720,232],{"class":103},[97,2722,334],{"class":103},[97,2724,2725],{"class":228},"currentPage",[97,2727,354],{"class":103},[97,2729,357],{"class":228},[97,2731,2000],{"class":224},[97,2733,2734],{"class":484}," 1",[97,2736,245],{"class":103},[97,2738,2739],{"class":224}," *",[97,2741,2620],{"class":228},[97,2743,2744],{"class":218},"  // 開始位置\n",[97,2746,2747,2749,2751,2753,2755,2757,2759],{"class":99,"line":379},[97,2748,754],{"class":224},[97,2750,2073],{"class":228},[97,2752,232],{"class":103},[97,2754,2025],{"class":228},[97,2756,2098],{"class":224},[97,2758,2620],{"class":228},[97,2760,2761],{"class":218},"                       // 終了位置\n",[97,2763,2764,2766,2769,2771,2773,2775,2777,2779,2781,2783,2785],{"class":99,"line":394},[97,2765,1121],{"class":285},[97,2767,2768],{"class":228}," filteredArticles",[97,2770,354],{"class":103},[97,2772,357],{"class":228},[97,2774,354],{"class":103},[97,2776,1230],{"class":235},[97,2778,239],{"class":103},[97,2780,2147],{"class":228},[97,2782,331],{"class":103},[97,2784,2073],{"class":228},[97,2786,404],{"class":103},[97,2788,2789],{"class":99,"line":407},[97,2790,493],{"class":103},[97,2792,2793],{"class":99,"line":413},[97,2794,298],{"emptyLinePlaceholder":297},[97,2796,2797],{"class":99,"line":418},[97,2798,2799],{"class":218},"// 検索クエリが変わったらページをリセット\n",[97,2801,2802,2804,2806,2808,2810,2813,2815],{"class":99,"line":424},[97,2803,323],{"class":235},[97,2805,239],{"class":103},[97,2807,510],{"class":228},[97,2809,331],{"class":103},[97,2811,2812],{"class":103}," ()",[97,2814,342],{"class":103},[97,2816,345],{"class":103},[97,2818,2819,2822,2824,2826,2828],{"class":99,"line":442},[97,2820,2821],{"class":228},"  currentPage",[97,2823,354],{"class":103},[97,2825,357],{"class":228},[97,2827,232],{"class":103},[97,2829,2830],{"class":484}," 1\n",[97,2832,2833],{"class":99,"line":460},[97,2834,493],{"class":103},[13,2836,2837],{},[30,2838,2839],{},"計算例（全45件の場合）：",[145,2841,2842,2849,2856],{},[27,2843,2844,2845,2848],{},"ページ1: ",[77,2846,2847],{},"slice(0, 20)"," → 1〜20件目",[27,2850,2851,2852,2855],{},"ページ2: ",[77,2853,2854],{},"slice(20, 40)"," → 21〜40件目",[27,2857,2858,2859,2862],{},"ページ3: ",[77,2860,2861],{},"slice(40, 60)"," → 41〜45件目",[17,2864,2866],{"id":2865},"uiの変更","UIの変更",[68,2868,2870],{"id":2869},"indexvueへのリンク追加","index.vueへのリンク追加",[13,2872,2873],{},"トップページに検索ページへのリンクを追加しました：",[88,2875,2879],{"className":2876,"code":2877,"language":2878,"meta":93,"style":93},"language-vue shiki shiki-themes vitesse-light vitesse-light","\u003Cp class=\"search-link-wrapper\">\n  \u003CNuxtLink to=\"/search\" class=\"search-link\">\n    🔍 コンテンツを検索する\n  \u003C/NuxtLink>\n\u003C/p>\n","vue",[77,2880,2881,2900,2905,2910,2915],{"__ignoreMap":93},[97,2882,2883,2885,2887,2889,2891,2893,2896,2898],{"class":99,"line":100},[97,2884,2414],{"class":103},[97,2886,13],{"class":285},[97,2888,2432],{"class":228},[97,2890,2422],{"class":103},[97,2892,118],{"class":124},[97,2894,2895],{"class":128},"search-link-wrapper",[97,2897,118],{"class":124},[97,2899,2460],{"class":103},[97,2901,2902],{"class":99,"line":107},[97,2903,2904],{"class":781},"  \u003CNuxtLink to=\"/search\" class=\"search-link\">\n",[97,2906,2907],{"class":99,"line":135},[97,2908,2909],{"class":781},"    🔍 コンテンツを検索する\n",[97,2911,2912],{"class":99,"line":271},[97,2913,2914],{"class":781},"  \u003C/NuxtLink>\n",[97,2916,2917,2920,2922],{"class":99,"line":294},[97,2918,2919],{"class":103},"\u003C/",[97,2921,13],{"class":285},[97,2923,2460],{"class":103},[13,2925,2926],{},[30,2927,2928],{},"スタイル：",[88,2930,2932],{"className":2468,"code":2931,"language":2470,"meta":93,"style":93},".search-link {\n  display: inline-block;\n  padding: 0.75rem 1.5rem;\n  background: #3b82f6;      /* 青色の背景 */\n  color: white;\n  text-decoration: none;\n  border-radius: 0.375rem;\n  font-weight: 600;\n  transition: background 0.2s;  /* ホバー時のアニメーション */\n}\n\n.search-link:hover {\n  background: #2563eb;      /* ホバー時は少し濃い青 */\n}\n",[77,2933,2934,2943,2955,2973,2989,3000,3012,3025,3035,3057,3061,3065,3078,3094],{"__ignoreMap":93},[97,2935,2936,2938,2941],{"class":99,"line":100},[97,2937,354],{"class":103},[97,2939,2940],{"class":228},"search-link",[97,2942,345],{"class":103},[97,2944,2945,2948,2950,2953],{"class":99,"line":107},[97,2946,2947],{"class":114},"  display",[97,2949,121],{"class":103},[97,2951,2952],{"class":2507}," inline-block",[97,2954,2567],{"class":103},[97,2956,2957,2959,2961,2964,2966,2969,2971],{"class":99,"line":135},[97,2958,2551],{"class":114},[97,2960,121],{"class":103},[97,2962,2963],{"class":484}," 0.75",[97,2965,2559],{"class":224},[97,2967,2968],{"class":484}," 1.5",[97,2970,2559],{"class":224},[97,2972,2567],{"class":103},[97,2974,2975,2977,2979,2981,2984,2986],{"class":99,"line":271},[97,2976,2499],{"class":114},[97,2978,121],{"class":103},[97,2980,2504],{"class":103},[97,2982,2983],{"class":2507},"3b82f6",[97,2985,2511],{"class":103},[97,2987,2988],{"class":218},"      /* 青色の背景 */\n",[97,2990,2991,2993,2995,2998],{"class":99,"line":294},[97,2992,2519],{"class":114},[97,2994,121],{"class":103},[97,2996,2997],{"class":2507}," white",[97,2999,2567],{"class":103},[97,3001,3002,3005,3007,3010],{"class":99,"line":301},[97,3003,3004],{"class":114},"  text-decoration",[97,3006,121],{"class":103},[97,3008,3009],{"class":2507}," none",[97,3011,2567],{"class":103},[97,3013,3014,3016,3018,3021,3023],{"class":99,"line":315},[97,3015,2572],{"class":114},[97,3017,121],{"class":103},[97,3019,3020],{"class":484}," 0.375",[97,3022,2559],{"class":224},[97,3024,2567],{"class":103},[97,3026,3027,3029,3031,3033],{"class":99,"line":320},[97,3028,2536],{"class":114},[97,3030,121],{"class":103},[97,3032,2541],{"class":484},[97,3034,2567],{"class":103},[97,3036,3037,3040,3042,3046,3049,3052,3054],{"class":99,"line":348},[97,3038,3039],{"class":114},"  transition",[97,3041,121],{"class":103},[97,3043,3045],{"class":3044},"sPP4b"," background",[97,3047,3048],{"class":484}," 0.2",[97,3050,3051],{"class":224},"s",[97,3053,2511],{"class":103},[97,3055,3056],{"class":218},"  /* ホバー時のアニメーション */\n",[97,3058,3059],{"class":99,"line":368},[97,3060,138],{"class":103},[97,3062,3063],{"class":99,"line":373},[97,3064,298],{"emptyLinePlaceholder":297},[97,3066,3067,3069,3071,3073,3076],{"class":99,"line":379},[97,3068,354],{"class":103},[97,3070,2940],{"class":228},[97,3072,121],{"class":103},[97,3074,3075],{"class":228},"hover",[97,3077,345],{"class":103},[97,3079,3080,3082,3084,3086,3089,3091],{"class":99,"line":394},[97,3081,2499],{"class":114},[97,3083,121],{"class":103},[97,3085,2504],{"class":103},[97,3087,3088],{"class":2507},"2563eb",[97,3090,2511],{"class":103},[97,3092,3093],{"class":218},"      /* ホバー時は少し濃い青 */\n",[97,3095,3096],{"class":99,"line":407},[97,3097,138],{"class":103},[17,3099,3100],{"id":3100},"パフォーマンスの最適化",[68,3102,3104],{"id":3103},"_1-記事本文のキャッシュ","1. 記事本文のキャッシュ",[88,3106,3108],{"className":209,"code":3107,"language":211,"meta":93,"style":93},"const articleBodies = ref(new Map())\n\n// インデックス構築時にキャッシュ\narticles.forEach(article => {\n  const bodyText = extractTextFromAST(article.body.value)\n  articleBodies.value.set(article.path, bodyText)\n  // ...\n})\n",[77,3109,3110,3131,3135,3140,3156,3180,3208,3213],{"__ignoreMap":93},[97,3111,3112,3114,3116,3118,3120,3122,3125,3128],{"class":99,"line":100},[97,3113,225],{"class":224},[97,3115,1712],{"class":228},[97,3117,232],{"class":103},[97,3119,236],{"class":235},[97,3121,239],{"class":103},[97,3123,3124],{"class":224},"new",[97,3126,3127],{"class":235}," Map",[97,3129,3130],{"class":103},"())\n",[97,3132,3133],{"class":99,"line":107},[97,3134,298],{"emptyLinePlaceholder":297},[97,3136,3137],{"class":99,"line":135},[97,3138,3139],{"class":218},"// インデックス構築時にキャッシュ\n",[97,3141,3142,3144,3146,3148,3150,3152,3154],{"class":99,"line":271},[97,3143,730],{"class":228},[97,3145,354],{"class":103},[97,3147,735],{"class":235},[97,3149,239],{"class":103},[97,3151,740],{"class":228},[97,3153,342],{"class":103},[97,3155,345],{"class":103},[97,3157,3158,3160,3162,3164,3166,3168,3170,3172,3174,3176,3178],{"class":99,"line":294},[97,3159,754],{"class":224},[97,3161,757],{"class":228},[97,3163,232],{"class":103},[97,3165,762],{"class":235},[97,3167,239],{"class":103},[97,3169,740],{"class":228},[97,3171,354],{"class":103},[97,3173,650],{"class":228},[97,3175,354],{"class":103},[97,3177,357],{"class":228},[97,3179,404],{"class":103},[97,3181,3182,3185,3187,3189,3191,3194,3196,3198,3200,3202,3204,3206],{"class":99,"line":301},[97,3183,3184],{"class":228},"  articleBodies",[97,3186,354],{"class":103},[97,3188,357],{"class":228},[97,3190,354],{"class":103},[97,3192,3193],{"class":235},"set",[97,3195,239],{"class":103},[97,3197,740],{"class":228},[97,3199,354],{"class":103},[97,3201,609],{"class":228},[97,3203,331],{"class":103},[97,3205,757],{"class":228},[97,3207,404],{"class":103},[97,3209,3210],{"class":99,"line":315},[97,3211,3212],{"class":218},"  // ...\n",[97,3214,3215],{"class":99,"line":320},[97,3216,493],{"class":103},[13,3218,3219,3222],{},[30,3220,3221],{},"理由："," ASTからのテキスト抽出は計算コストが高いため、一度だけ実行して結果を保存します。",[68,3224,3226],{"id":3225},"_2-flexsearchのキャッシュ機能","2. FlexSearchのキャッシュ機能",[88,3228,3230],{"className":209,"code":3229,"language":211,"meta":93,"style":93},"searchIndex.value = new Document({\n  // ...\n  cache: true  // 検索結果をキャッシュ\n})\n",[77,3231,3232,3248,3252,3263],{"__ignoreMap":93},[97,3233,3234,3236,3238,3240,3242,3244,3246],{"class":99,"line":100},[97,3235,572],{"class":228},[97,3237,354],{"class":103},[97,3239,357],{"class":228},[97,3241,232],{"class":103},[97,3243,581],{"class":224},[97,3245,584],{"class":235},[97,3247,587],{"class":103},[97,3249,3250],{"class":99,"line":107},[97,3251,3212],{"class":218},[97,3253,3254,3256,3258,3260],{"class":99,"line":135},[97,3255,687],{"class":114},[97,3257,121],{"class":103},[97,3259,362],{"class":285},[97,3261,3262],{"class":218},"  // 検索結果をキャッシュ\n",[97,3264,3265],{"class":99,"line":271},[97,3266,493],{"class":103},[13,3268,3269,3272],{},[30,3270,3271],{},"効果："," 同じキーワードを再検索する際に高速化されます。",[68,3274,3276],{"id":3275},"_3-デバウンスによる検索回数の削減","3. デバウンスによる検索回数の削減",[13,3278,3279],{},"前述の通り、300ms待つことで無駄な検索実行を防ぎます。",[17,3281,3282],{"id":3282},"使い方",[68,3284,3285],{"id":3285},"基本的な検索",[24,3287,3288,3294,3297,3300],{},[27,3289,3290,3293],{},[77,3291,3292],{},"/search","ページにアクセス",[27,3295,3296],{},"「キーワード検索」欄に検索したい言葉を入力",[27,3298,3299],{},"300ms後に自動的に検索が実行されます",[27,3301,3302],{},"結果一覧が表示されます",[68,3304,3305],{"id":3305},"検索対象",[145,3307,3308,3314,3320],{},[27,3309,3310,3313],{},[30,3311,3312],{},"タイトル","：記事のタイトル",[27,3315,3316,3319],{},[30,3317,3318],{},"説明文","：記事の説明（frontmatterのdescription）",[27,3321,3322,3325],{},[30,3323,3324],{},"本文","：記事の全文",[68,3327,3328],{"id":3328},"検索結果の表示",[145,3330,3331,3337],{},[27,3332,3333,3336],{},[30,3334,3335],{},"タイトル・説明文にヒット","：そのまま表示",[27,3338,3339,3342],{},[30,3340,3341],{},"本文にヒット","：キーワード周辺のスニペットを表示し、キーワードをハイライト",[68,3344,3345],{"id":3345},"並び順の変更",[13,3347,3348],{},"「並び順」ドロップダウンで以下を選択できます：",[145,3350,3351,3357],{},[27,3352,3353,3356],{},[30,3354,3355],{},"新しい順","（デフォルト）",[27,3358,3359],{},[30,3360,3361],{},"古い順",[68,3363,3364],{"id":3364},"ページ送り",[13,3366,3367],{},"検索結果が20件を超える場合、「前へ」「次へ」ボタンでページを切り替えられます。",[17,3369,3370],{"id":3370},"トラブルシューティング",[68,3372,3373],{"id":3373},"検索結果が表示されない",[24,3375,3376,3379,3382],{},[27,3377,3378],{},"キーワードのスペルを確認してください",[27,3380,3381],{},"より短いキーワードで試してください",[27,3383,3384],{},"フォールバック検索も動作するため、部分一致は必ず検出されるはずです",[68,3386,3387],{"id":3387},"検索が遅い",[145,3389,3390,3393],{},[27,3391,3392],{},"初回のインデックス構築には時間がかかる場合があります",[27,3394,3395],{},"記事数が多い場合（1000件以上）は検索に数秒かかる可能性があります",[68,3397,3398],{"id":3398},"ハイライトが表示されない",[145,3400,3401,3404],{},[27,3402,3403],{},"本文以外（タイトル・説明文）でヒットした場合はハイライトは表示されません",[27,3405,3406],{},"これは仕様です",[17,3408,3409],{"id":3409},"まとめ",[13,3411,3412],{},"この実装により、以下が実現できました：",[13,3414,3415,3416,3419,3420,3423,3424,3427,3428,3423,3430,3433,3434,3423,3436,3439,3440,3423,3442,3445],{},"✅ ",[30,3417,3418],{},"高速な全文検索"," - FlexSearchによる効率的なインデックス検索",[3421,3422],"br",{},"\n✅ ",[30,3425,3426],{},"快適な入力体験"," - デバウンスによる無駄な検索の削減",[3421,3429],{},[30,3431,3432],{},"柔軟な検索"," - タイトル、説明文、本文すべてから検索",[3421,3435],{},[30,3437,3438],{},"わかりやすい結果表示"," - スニペットとハイライトで視認性向上",[3421,3441],{},[30,3443,3444],{},"大量データ対応"," - ページネーションによる快適な閲覧",[13,3447,3448],{},"これらの技術を組み合わせることで、ユーザーフレンドリーで高性能な検索機能を実現しています。",[3450,3451,3452],"style",{},"html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sqvqQ, html code.shiki .sqvqQ{--shiki-default:#99841877;--shiki-dark:#99841877}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}html pre.shiki code .sG7-3, html code.shiki .sG7-3{--shiki-default:#393A34;--shiki-dark:#393A34}html pre.shiki code .sFA8A, html code.shiki .sFA8A{--shiki-default:#999999;--shiki-default-font-weight:bold;--shiki-dark:#999999;--shiki-dark-font-weight:bold}html pre.shiki code .syTZV, html code.shiki .syTZV{--shiki-default:#1C6B48;--shiki-default-font-weight:bold;--shiki-dark:#1C6B48;--shiki-dark-font-weight:bold}html pre.shiki code .s9pho, html code.shiki .s9pho{--shiki-default:#393A34;--shiki-default-font-weight:bold;--shiki-dark:#393A34;--shiki-dark-font-weight:bold}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}html pre.shiki code .sPP4b, html code.shiki .sPP4b{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#B31D28;--shiki-dark-font-style:italic}",{"title":93,"searchDepth":107,"depth":107,"links":3454},[3455,3456,3460,3468,3471,3476,3483,3488],{"id":19,"depth":107,"text":19},{"id":66,"depth":107,"text":66,"children":3457},[3458,3459],{"id":70,"depth":135,"text":71},{"id":85,"depth":135,"text":86},{"id":161,"depth":107,"text":161,"children":3461},[3462,3463,3464,3465,3466,3467],{"id":164,"depth":135,"text":165},{"id":524,"depth":135,"text":525},{"id":882,"depth":135,"text":883},{"id":1403,"depth":135,"text":1404},{"id":1855,"depth":135,"text":1856},{"id":2587,"depth":135,"text":2588},{"id":2865,"depth":107,"text":2866,"children":3469},[3470],{"id":2869,"depth":135,"text":2870},{"id":3100,"depth":107,"text":3100,"children":3472},[3473,3474,3475],{"id":3103,"depth":135,"text":3104},{"id":3225,"depth":135,"text":3226},{"id":3275,"depth":135,"text":3276},{"id":3282,"depth":107,"text":3282,"children":3477},[3478,3479,3480,3481,3482],{"id":3285,"depth":135,"text":3285},{"id":3305,"depth":135,"text":3305},{"id":3328,"depth":135,"text":3328},{"id":3345,"depth":135,"text":3345},{"id":3364,"depth":135,"text":3364},{"id":3370,"depth":107,"text":3370,"children":3484},[3485,3486,3487],{"id":3373,"depth":135,"text":3373},{"id":3387,"depth":135,"text":3387},{"id":3398,"depth":135,"text":3398},{"id":3409,"depth":107,"text":3409},"dev",null,"Nuxt Contentの検索機能にデバウンス処理とFlexSearchによる全文検索を実装した詳細解説","md",{},"/search-implementation","blog-platform",false,"2025-11-01T00:00:00.000Z",{"title":5,"description":3491},"2025-11/2025-11-01/search-implementation",[3501,1433,115,3502,2878],"nuxt","debounce","done","KPVe7kyHyQHA867M7YKXbqrPxTC-ihjTwtHCdyektGw",[],[3507,3511,3515,3519,3523],{"title":3508,"path":3509,"publishedAt":3510},"Webサービスの技術構成 2026年版 — Vue.js/Nuxt/Astroの使い分けとその理由","/web-tech-stack-2026","2026-07-22T00:00:00.000Z",{"title":3512,"path":3513,"publishedAt":3514},"英語の図解Artifactを日本語化して単独Vueページで公開するまで - AI導入5ステップの移植記録","/ai-adoption-steps-page","2026-07-17T00:00:00.000Z",{"title":3516,"path":3517,"publishedAt":3518},"過去記事に散らばったSVG図版を一覧するギャラリービューアを作った","/svg-gallery-viewer","2026-07-01T00:00:00.000Z",{"title":3520,"path":3521,"publishedAt":3522},"Nuxt Content の記事タイトルが本文に出ない問題を DocPage 側の自動分岐で解消した","/docpage-auto-title-display","2026-06-29T00:00:00.000Z",{"title":3524,"path":3525,"publishedAt":3526},"キオクシア決算サマリー記事公開と beat-monitoring/285A の途中対応 — アナリストコンセンサスがない銘柄をどう扱うか","/kioxia-fy25-q4-summary-and-beat-monitoring-todo","2026-06-25T00:00:00.000Z","https://log.eurekapu.com/og/blog/search-implementation.png?v=2025-11-01T00%3A00%3A00.000Z&title=%E3%83%87%E3%83%90%E3%82%A6%E3%83%B3%E3%82%B9%E5%87%A6%E7%90%86%E3%81%A8%E6%9C%AC%E6%96%87%E6%A4%9C%E7%B4%A2%E3%81%AE%E5%AE%9F%E8%A3%85%E3%82%AC%E3%82%A4%E3%83%89&author=Kei%20Komatsu&sig=16986908cb0b04dd",1784786187195]