diff --git a/src/assets/images/og/268326b0cbe88cf4d3d52114ead921d7f736edf07b32c65783c5a8697707c8d0.webp b/src/assets/images/og/268326b0cbe88cf4d3d52114ead921d7f736edf07b32c65783c5a8697707c8d0.webp new file mode 100644 index 0000000..d1a2b33 Binary files /dev/null and b/src/assets/images/og/268326b0cbe88cf4d3d52114ead921d7f736edf07b32c65783c5a8697707c8d0.webp differ diff --git a/src/assets/images/og/f857c3263edf21af197b25682bfa2fe2683cebcbc86084afd877e911117edacf.webp b/src/assets/images/og/f857c3263edf21af197b25682bfa2fe2683cebcbc86084afd877e911117edacf.webp new file mode 100644 index 0000000..e60a086 Binary files /dev/null and b/src/assets/images/og/f857c3263edf21af197b25682bfa2fe2683cebcbc86084afd877e911117edacf.webp differ diff --git a/src/content/blog/20240609-learn-rust.md b/src/content/blog/20240609-learn-rust.md index 70694a0..2518ef9 100644 --- a/src/content/blog/20240609-learn-rust.md +++ b/src/content/blog/20240609-learn-rust.md @@ -1,23 +1,28 @@ --- create: '2024-06-09' -update: '2024-06-09' +update: '2024-06-18' title: 'Rust をやってみる' tags: [rust] published: true -noindex: true --- -同居人から風邪を貰い、熱や咳に鼻水と症状が続き、普段通りの生活が阻害されていたので、Rust を触ってみることにした。以前に [RustではじめるOpenGL | インプレス NextPublishing](https://nextpublishing.jp/book/11379.html) という本を読むにあたって、一度だけ Hello world までの初歩的なことはしていた。 - ## はじめに -Rust を触ったら、案の定大変だった・分からなさ過ぎた。でも楽しかった。Rust を使って何かサービスを作る予定は全くないが、過去に勝った技術本を写経したり、画像処理をやるなどして Rust で遊びたい。 ※メモ書きなので**他者が読んでも得るものはありません**。noindex を設定してすらいます。 +Rust を触ったら、大変だったが楽しかった。Rust を使って何かサービスを作る予定は全くないが、以前に購入していた技術本『[RustではじめるOpenGL | インプレス NextPublishing](https://nextpublishing.jp/book/11379.html)』を写経したり、画像処理をやるなどして遊びたい(やった)。 -## Rust とは +### Zenn.dev + +https://zenn.dev/oriverk/articles/432f7c2f17b928 + +大学卒論研究で扱った農作物列画像の画像処理の一部を Rust でやってみた。 -安全性と高パフォーマンスを両立させたシステムプログラミング言語。メモリ安全性を保証し、並行処理も安全に行えるため、信頼性の高いソフトウェア開発に適しています。近年、Next.js や Biome といったフロントエンドの FW や開発ツールが Rust を採用し始めている。 +[![Image from Gyazo](https://i.gyazo.com/d75600f70282b94cfe9891ca63cdd600.jpg "input.png")](https://gyazo.com/d75600f70282b94cfe9891ca63cdd600) + +[![Image from Gyazo](https://i.gyazo.com/f5b0b2ed170f42cf7f15e97459b054bf.jpg "output.png")](https://gyazo.com/f5b0b2ed170f42cf7f15e97459b054bf) + +## Rust とは -https://github.com/biomejs/biome +安全性と高パフォーマンスを両立させたシステムプログラミング言語。メモリ安全性を保証し、並行処理も安全に行えるため、信頼性の高いソフトウェア開発に適しています。近年、[Next.js](https://nextjs.org/) や [biomejs/biome](https://github.com/biomejs/biome) といったフロントエンドの FW や開発ツールが Rust を採用し始めている。 Web ブラウザ上で高速実行が可能で複雑な計算やゲーム開発・マルチメディア処理に適しているとされるバイナリ形式の命令セットで WebAssembly (Wasm) というものがあるが、これを作成するのに Rust などが用いられている。実際に AmazonPrimeVideo の動画再生のパフォーマンス改善に Rust コードから生成した Wasm が利用されたというニュースが2022年にあった。 @@ -101,7 +106,7 @@ fn get_fizz_buzz_match(num: u32) -> String { #### 統計っぽいこと -Rust にも `as` があるんだと思った。JSDoc の様なドキュメンテーションコメントの書き方を知った。この Zenn の [Rustのドキュメンテーションコメントの書き方](https://zenn.dev/masaki_wk/articles/20230715-rust-doc-comment#%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%81%AE%E7%A8%AE%E5%88%A5) が詳しかった。 +Rust にも `as` があるんだと思った。JSDoc の様なドキュメンテーションコメントの書き方を知った。この Zenn の [Rustのドキュメンテーションコメントの書き方](https://zenn.dev/masaki_wk/articles/20230715-rust-doc-comment#ドキュメンテーションコメントの種別) が詳しかった。 ```rust:main.rs use std::collections::HashMap; diff --git a/src/content/blog/20240812-flutter.md b/src/content/blog/20240812-flutter.md new file mode 100644 index 0000000..1709cad --- /dev/null +++ b/src/content/blog/20240812-flutter.md @@ -0,0 +1,327 @@ +--- +create: '2024-07-01' +update: '2024-07-25' +title: 'Flutterをやってみる' +tags: [flutter] +published: true +--- + +「スマホアプリが動かなくなった」という友人の投稿を見て、居住自治体が配布しているアプリをインストールし、複数の不具合等を見つけたのがきっかけでした。アプリに関する知識が全く無い状態で自治体に報告するのも・・・と思ったので、Flutter を触ってみることにしました。 + +ちなみに、このアプリは [Apache Cordova](https://cordova.apache.org/) 製でした。 + +[![Image from Gyazo](https://i.gyazo.com/be4cd4904180fda733f325b17e8f0fc5.png)](https://gyazo.com/be4cd4904180fda733f325b17e8f0fc5) + +## 感想・まとめ + +- RAM 16GB では足りない +- やる前に何度か見かけていた『Flutter はクロスプラットフォーム開発 FW であるが、Android と iOS アプリ開発に要する労力が半分になる訳ではない』という言説の理由が何となく分かりました + - Material Components を使用するならある程度は楽できるが、独自デザインになると難易度が急に上がる + - Dart と Flutter だけなら学習コストは大したことが無いが、必要に応じて Kotolin そして Android 自体をも把握して作成するのは大変・・・iOS だと Swift も + +## not yet / do it later + +- [Riverpod](https://riverpod.dev/ja/) +- [yumemi-inc/flutter-training-template: 株式会社ゆめみ Flutter 研修](https://github.com/yumemi-inc/flutter-training-template) + - Weather Frecast App +- [yumemi-inc/flutter-engineer-codecheck: This is a code check task for Flutter engineers employment in YUMEMI.](https://github.com/yumemi-inc/flutter-engineer-codecheck) + - like GitHub App clone + +## did it + +[Flutter Learn](https://flutter.dev/learn) を手を動かしながら読み終えましたが、Widget に何があるか、Flutter/Dart 特有の書き方といったものを更に理解するため、Zenn や Google Codelab 等のチュートリアルをやりました。 + +[oriverk/learn_flutter](https://github.com/oriverk/learn_flutter) + +- [いちから始めるFlutterモバイルアプリ開発](https://zenn.dev/heyhey1028/books/flutter-basics) + - http, webview_flutter +- [初めての Flutter アプリ](https://codelabs.developers.google.com/codelabs/flutter-codelab-first?hl=ja#0) +- [Flutter アプリのテスト方法](https://codelabs.developers.google.com/codelabs/flutter-app-testing?hl=ja#0) + - routing with go_router, tests; unit test, widget test, perf test +- [Flutter アプリに Google マップを追加する | Google Codelabs](https://codelabs.developers.google.com/codelabs/google-maps-in-flutter?hl=ja#0) + - google_maps_flutter, http, json_serializable +- [MDC-101 Flutter: マテリアル コンポーネントの基本](https://codelabs.developers.google.com/codelabs/mdc-101-flutter?hl=ja#0) + - backdrops, custom fonts, gridview +- [マテリアル 3 でアニメーション化されたレスポンシブ アプリ レイアウトを作成する](https://codelabs.developers.google.com/codelabs/flutter-animated-responsive-layout?hl=ja#0) +- [Flutter アプリを「退屈なアプリ」から「見栄えの良いアプリ」に変える](https://codelabs.developers.google.com/codelabs/flutter-boring-to-beautiful?hl=ja#0) +- [Flutter 用のマテリアル モーションで美しい移行を作成する](https://codelabs.developers.google.com/codelabs/material-motion-flutter?hl=ja#0) +- 電池残量と充電状態を監視するアプリ + - [Platform-specific code | Flutter](https://docs.flutter.dev/platform-integration/platform-channels) + - [電池残量と充電状態を監視する | App quality | Android Developers](https://developer.android.com/training/monitoring-device-state/battery-monitoring?hl=ja#kotlin) +- [Firebase for Flutter を理解する](https://firebase.google.com/codelabs/firebase-get-to-know-flutter?hl=ja#0) +- [codelabs/firebase-get-to-know-flutter at main · flutter/codelabs](https://github.com/flutter/codelabs/tree/main/firebase-get-to-know-flutter) + - [firebase/flutterfire: 🔥 A collection of Firebase plugins for Flutter apps.](https://github.com/firebase/flutterfire) + +## notes + +### commands + +flutter create の後に-e を付ける事で最小構成のプロジェクトを作成できる。 + +```shell title=terminal +flutter create -e [project_name] --platforms=ios,android +``` + +run app + +```shell title=terminal +flutter devices +flutter run -d [device_id] +``` + +### codelabs/google-maps-in-flutter + +- [【Flutter】クレデンシャル情報を.envファイルで取得し、ネイティブファイルで利用する方法【GoogleMap】](https://zenn.dev/ryota_exe/articles/2a42beac4ef1d8) +- [【Flutter】環境ごとのAPIキーをiOS/Androidネイティブ側に設定する【Google Maps API】](https://zenn.dev/altiveinc/articles/flutter-set-native-api-keys-per-env) + +```shell title=terminal +# deprecated +flutter pub run build_runner build --delete-conflicting-outputs +# use +dart run build_runner build --delete-conflicting-outputs +dart run build_runner build -d +``` + +### codelabs/flutter-boring-to-beautiful + +- [Flutter アプリを「退屈なアプリ」から「見栄えの良いアプリ」に変える](https://codelabs.developers.google.com/codelabs/flutter-boring-to-beautiful?hl=ja#0) +- [codelabs/boring_to_beautiful at main · flutter/codelabs](https://github.com/flutter/codelabs/tree/main/boring_to_beautiful) + - [flutter_bloc | Flutter package](https://pub.dev/packages/flutter_bloc) + - Flutter Widgets that make it easy to implement the BLoC (Business Logic Component) design pattern. Built to be used with the bloc state management package +- [Material Theme Builder](https://material-foundation.github.io/material-theme-builder/) +- [Design tokens – Material Design 3](https://m3.material.io/foundations/design-tokens/overview) + - adaptive breakpoints for mobile, tablet, pc + - [Responsive layout grid - Material Design](https://m2.material.io/design/layout/responsive-layout-grid.html) + - [Applying layout – Material Design 3](https://m3.material.io/foundations/layout/applying-layout/window-size-classes) + +#### flutter_bloc + +Flutter アプリケーションにおけるビジネスロジックの管理を簡素化し、UI とビジネスロジックの分離を促進するためのデザインパターン。状態管理が容易になり、コードのテストがしやすくなる。らしい。 + +#### part of + +```dart +part of 'playback_bloc.dart'; +``` + +ライブラリや大規模なコードベースを分割するために使用されるキーワード。複数の Dart ファイルを1つのライブラリとして扱い、モジュール化やコードの整理が容易になる。らしい。 + +#### class A with B {} + +[learn_flutter/boring_to_beautiful/lib/src/shared/playback/bloc/playback_event.dart at main · oriverk/learn_flutter](https://github.com/oriverk/learn_flutter/blob/main/boring_to_beautiful/lib/src/shared/playback/bloc/playback_event.dart) + +- `part of` +- `@Freezed()` +- `class A with B` + - `class A extends B` とは違う様子 + +```dart +part of 'playback_bloc.dart'; + +@Freezed() +class PlaybackEvent with _$PlaybackEvent {} +``` + +- `class A extends B` + - 単一継承 + - クラスAはクラスBのすべての機能を継承し、オーバーライドできる + - 強い継承関係を示す +- `class A with B` + - 複数のミックスインを使用可能 + - クラスAはミックスインBの機能を利用でき、他の継承関係に影響を与えない + - 再利用可能な機能を追加するために使用する + +#### extension A on B {} + +[learn_flutter/boring_to_beautiful/lib/src/shared/extensions.dart at main · oriverk/learn_flutter](https://github.com/oriverk/learn_flutter/blob/main/boring_to_beautiful/lib/src/shared/extensions.dart) + +```dart +extension DurationString on String { + /// Assumes a string (roughly) of the format '\d{1,2}:\d{2}' + Duration toDuration() => switch (split(':')) { + [var minutes, var seconds] => Duration( + minutes: int.parse(minutes.trim()), + seconds: int.parse(seconds.trim()), + ), + [var hours, var minutes, var seconds] => Duration( + hours: int.parse(hours.trim()), + minutes: int.parse(minutes.trim()), + seconds: int.parse(seconds.trim()), + ), + _ => throw Exception('Invalid duration string: $this'), + }; +} +``` + +[learn_flutter/boring_to_beautiful/lib/src/shared/providers/songs.dart at main · oriverk/learn_flutter](https://github.com/oriverk/learn_flutter/blob/main/boring_to_beautiful/lib/src/shared/providers/songs.dart) + +```dart +final _songs = [ + RankedSong( + 1, + 'Before You', + ArtistsProvider.shared.getArtist('jmo')!, + '2:45'.toDuration(), + const MyArtistImage( + image: 'assets/images/albums/artist6-album1.jpg', + sourceLink: 'https://unsplash.com/photos/cTKGZJTMJQU', + sourceName: 'Drew Dizzy Graham', + ), + ), +] +``` + +Dart 言語の機能で、既存のクラスに新しいメソッドやプロパティを追加する方法です。この機能を使用することで、既存のクラスの定義を変更することなく、そのクラスに新しい機能を追加できます。Flutter でもこの機能を利用して、標準ウィジェットや他のクラスにカスタムメソッドを追加できます。(ChatGPT) + +```dart + + +extension StringExtension on String { + bool get isPalindrome { + String normalized = this.toLowerCase().replaceAll(RegExp(r'[\W_]+'), ''); + return normalized == normalized.split('').reversed.join(''); + } +} + +void main() { + String text = 'A man a plan a canal Panama'; + print(text.isPalindrome); // true +} +``` + +### codelabs/material-motion-flutter + +#### InkWell VS GestureDetector + +- [flutterアプリ開発においてInkWellとGestureDetectorどちらを採用するか](https://zenn.dev/yuv_o/articles/e8a3a12e73b8aa) +- [Gestures | Flutter](https://docs.flutter.dev/cookbook/gestures) + +#### SharedAxisTransition; アニメーション パッケージ内の共有軸移行 + +- アニメーション パッケージ内の共有軸移行は、SharedAxisTransition と呼ばれます。このウィジェットには次のプロパティがあります + - fillColor: 移行中の背景に使用される色 + - animation: 子の出入りを操作するアニメーション + - secondaryAnimation: 新しいコンテンツが前面にプッシュされたときに子を移行させるアニメーション + - transitionType: 共有軸移行のタイプを、スケーリング、水平、垂直から選択します + - child: 移行しながら出入りするウィジェット + +慣れの問題だと思うが、`css` と比較して非常に複雑だと感じた。個人的には [boring_to_beautifulのtheme.dart](https://github.com/oriverk/learn_flutter/blob/main/boring_to_beautiful/lib/src/shared/providers/theme.dart) のページ遷移時アニメーションぐらいで十分。 + +```dart +import 'package:flutter/material.dart'; + +class ThemeProvider extends InheritedWidget { + + + final pageTransitionsTheme = const PageTransitionsTheme( + builders: { + TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(), + TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), + TargetPlatform.linux: NoAnimationPageTransitionsBuilder(), + TargetPlatform.macOS: NoAnimationPageTransitionsBuilder(), + TargetPlatform.windows: NoAnimationPageTransitionsBuilder(), + }, + ); + + +} +``` + +### battery level app + +- references + - [Platform-specific code | Flutter](https://docs.flutter.dev/platform-integration/platform-channels) + - [FlutterJourney/Native Code in Flutter at main · EnricoGollner/FlutterJourney](https://github.com/EnricoGollner/FlutterJourney/tree/main/Native%20Code%20in%20Flutter) + - [電池残量と充電状態を監視する | App quality | Android Developers](https://developer.android.com/training/monitoring-device-state/battery-monitoring?hl=ja#kotlin) + +#### Which AndroidManifest.xml to edit in Flutter project? + +- [android studio - Which AndroidManifest.xml to edit in Flutter project? - Stack Overflow](https://stackoverflow.com/questions/60095118/which-androidmanifest-xml-to-edit-in-flutter-project) + +> Main AndroidManifest.xml file is located at 'Project' > app > src > main > AndroidManifest.xml. Other AndroidManifest.xml which are in debug folder and profile folder are systems generated when you are running a flutter app directly to mobile it will generate or while creating a flutter project. E.g: It is used for hot reload when the device is connected. + +#### 電池残量と充電状態を監視する + +- [MainActivity.kt](/batterylevel/android/app/src/main/kotlin/com/example/batterylevel/MainActivity.kt) +- [BatteryEventChannel.kt](/batterylevel/android/app/src/main/kotlin/com/example/batterylevel/BatteryEventChannel.kt) +- [電池残量と充電状態を監視する | App quality | Android Developers](https://developer.android.com/training/monitoring-device-state/battery-monitoring?hl=ja#kotlin) + +充電状態の変化を監視する + +```kotlin +val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter -> + context.registerReceiver(null, ifilter) +} +``` + +```kotlin +val status: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1 +val isCharging: Boolean = status == BatteryManager.BATTERY_STATUS_CHARGING + || status == BatteryManager.BATTERY_STATUS_FULL + +// How are we charging? +val chargePlug: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) ?: -1 +val usbCharge: Boolean = chargePlug == BatteryManager.BATTERY_PLUGGED_USB +val acCharge: Boolean = chargePlug == BatteryManager.BATTERY_PLUGGED_AC +``` + +現在の電池残量を特定する + +```kotlin +private fun getBatteryLevel(): Int { + val batteryLevel: Int + + if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager + batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) + } else { + // val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + // val level: Int = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) + // val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1) + // batteryLevel = level * 100 / scale + + // https://developer.android.com/training/monitoring-device-state/battery-monitoring?hl=ja#kotlin + val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter -> + context.registerReceiver(null, ifilter) + } + val batteryPct: Float? = batteryStatus?.let { intent -> + val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) + val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1) + level * 100 / scale.toFloat() + } + batteryLevel = batteryPct as Int + } + + return batteryLevel + } +``` + +- 条件式 `VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP` + - デバイスが Android Lollipop(API レベル21)以上のバージョンで動作しているかどうかをチェック +- `VERSION.SDK_INT` + - デバイスで実行されている Android のバージョンを取得するための定数 +- `VERSION_CODES.LOLLIPOP` + - Android のバージョン Lollipop(API レベル21)を示す定数 + +### codelabs/firebase-get-to-know-flutter + +firebase setup on Windows + +- [firebase/flutterfire: 🔥 A collection of Firebase plugins for Flutter apps.](https://github.com/firebase/flutterfire) + +```shell title=terminal +dart pub global activate flutterfire_cli +``` + +install through [coreybutler/nvm-windows: A node.js version management utility for Windows. Ironically written in Go.](https://github.com/coreybutler/nvm-windows?tab=readme-ov-file) + +```shell title=terminal +# run codes in administrator mode in powershell +nvm install lts +nmv use blah blah + +npm install -g firebase-tools +firebase login + +flutterfire configure +``` diff --git a/src/content/blog/20240815-flutter-webview.md b/src/content/blog/20240815-flutter-webview.md new file mode 100644 index 0000000..47642a3 --- /dev/null +++ b/src/content/blog/20240815-flutter-webview.md @@ -0,0 +1,15 @@ +--- +create: '2024-08-12' +update: '2024-08-12' +title: '[Flutter] webview_flutter の検証' +tags: [flutter] +published: false +noindex: true +--- + + +## はじめに + +きっかけ + +## おわりに diff --git a/src/content/blog/20240922-pagefind.md b/src/content/blog/20240922-pagefind.md new file mode 100644 index 0000000..b2b57c9 --- /dev/null +++ b/src/content/blog/20240922-pagefind.md @@ -0,0 +1,264 @@ +--- +create: '2024-09-22' +update: '2024-09-22' +title: 'Astro + Svelte v5サイトで、静的サイト向け全文検索ライブラリ Pagefindを使ってみる' +tags: [pagefind] +published: true +noindex: true +--- + +## はじめに + +今までサイト内検索では Algolia を使用していたのですが、検索 API の実行アクセス回数が少ないために無効にされてしまったので、サイト内検索機能を全文検索ライブラリの Pagefind で置換しました。 + +- [Pagefind | Pagefind — Static low-bandwidth search at scale](https://pagefind.app/) + - [CloudCannon/pagefind: Static low-bandwidth search at scale](https://github.com/cloudcannon/pagefind) +- [AI search that understands | Algolia](https://www.algolia.com/) + +## Pagefind とは + +Pagefind は、ユーザーの帯域幅をできるだけ使用せず、インフラストラクチャをホストすることなく、大規模なサイトで優れたパフォーマンスを発揮することを目的とした完全に静的な検索ライブラリです。 + +> Pagefind is a fully static search library that aims to perform well on large sites, while using as little of your users’ bandwidth as possible, and without hosting any infrastructure. + +Pagefind の導入はとても簡単で、サイトのビルド時にインデックスファイルを生成し、そのファイルを利用するだけで検索機能を提供できます。 + +Algolia も有名で優れた検索サービスですが、(個人サイト程度では滅多に支払いは発生しないものの)従量課金制の有料サービスです。 + +## 実装 + +- "astro": "^4.15.5" +- "svelte": "^5.0.0-next.247", + +Astro ファイルに Pagefind を追加する場合は、[Community Educational Content | Astro Docs](https://docs.astro.build/en/community-resources/content/#utilities) で参照されている、[Add Search To Your Astro Static Site](https://blog.otterlord.dev/posts/astro-search/) というページに倣うのが良いと思います。 + +諸々の都合により Svelte で作成した component 中で pagefind を使用することにしました。 + +### install Pagefind and add npm scripts + +```shell +npm install -D pagefind +``` + +Pagefind はサイトビルド時に生成した静的コンテンツを利用してインデックスを作成します。通常の Astro のビルドコマンドを実行した後に、ビルド生成物のあるディレクトリを利用してインデックス作成する様に、npm scripts を記述します。 + +```json title=package.json +{ + "scripts": { + "build": "astro build", + "postbuild": "npx pagefind --site dist", + "preview": "astro preview", + }, +} +``` + +postbuild が完了すると、`/dist/pagefind/` の様になります。 + +### custom indexing + +- reference + - [Setting up metadata | Pagefind — Static low-bandwidth search at scale](https://pagefind.app/docs/metadata/) + +Pagefind はデフォルトで `` 内にあるすべての要素をインデックス化に使用します。それではナビゲーション要素や `noindex` にしてあるページもインデックス化されてしまうので、適宜カスタマイズする必要があります。 + +ただし、`