mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(site): migrate search from Pagefind to Algolia DocSearch v4 (#941)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
9ce94ee2d3
commit
9ef1e61b63
Generated
+298
-16
@@ -428,6 +428,12 @@ importers:
|
||||
'@base-ui/react':
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@docsearch/css':
|
||||
specifier: ^4.6.0
|
||||
version: 4.6.0
|
||||
'@docsearch/react':
|
||||
specifier: ^4.6.0
|
||||
version: 4.6.0(@algolia/client-search@5.49.2)(@types/react@19.2.14)(algoliasearch@5.49.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.17.3)
|
||||
'@mux/mux-node':
|
||||
specifier: ^12.8.1
|
||||
version: 12.8.1
|
||||
@@ -437,9 +443,6 @@ importers:
|
||||
'@nanostores/react':
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0(nanostores@1.1.1)(react@19.2.4)
|
||||
'@pagefind/default-ui':
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
'@sentry/astro':
|
||||
specifier: ^10.32.1
|
||||
version: 10.42.0(astro@5.18.0(@netlify/blobs@10.7.0)(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.59.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))(rollup@4.59.0)
|
||||
@@ -567,9 +570,6 @@ importers:
|
||||
prettier-plugin-astro:
|
||||
specifier: ^0.14.1
|
||||
version: 0.14.1
|
||||
sirv:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
tsx:
|
||||
specifier: ^4.21.0
|
||||
version: 4.21.0
|
||||
@@ -615,6 +615,76 @@ packages:
|
||||
'@adobe/css-tools@4.4.4':
|
||||
resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==}
|
||||
|
||||
'@algolia/abtesting@1.15.2':
|
||||
resolution: {integrity: sha512-rF7vRVE61E0QORw8e2NNdnttcl3jmFMWS9B4hhdga12COe+lMa26bQLfcBn/Nbp9/AF/8gXdaRCPsVns3CnjsA==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/autocomplete-core@1.19.2':
|
||||
resolution: {integrity: sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw==}
|
||||
|
||||
'@algolia/autocomplete-plugin-algolia-insights@1.19.2':
|
||||
resolution: {integrity: sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg==}
|
||||
peerDependencies:
|
||||
search-insights: '>= 1 < 3'
|
||||
|
||||
'@algolia/autocomplete-shared@1.19.2':
|
||||
resolution: {integrity: sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==}
|
||||
peerDependencies:
|
||||
'@algolia/client-search': '>= 4.9.1 < 6'
|
||||
algoliasearch: '>= 4.9.1 < 6'
|
||||
|
||||
'@algolia/client-abtesting@5.49.2':
|
||||
resolution: {integrity: sha512-XyvKCm0RRmovMI/ChaAVjTwpZhXdbgt3iZofK914HeEHLqD1MUFFVLz7M0+Ou7F56UkHXwRbpHwb9xBDNopprQ==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/client-analytics@5.49.2':
|
||||
resolution: {integrity: sha512-jq/3qvtmj3NijZlhq7A1B0Cl41GfaBpjJxcwukGsYds6aMSCWrEAJ9pUqw/C9B3hAmILYKl7Ljz3N9SFvekD3Q==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/client-common@5.49.2':
|
||||
resolution: {integrity: sha512-bn0biLequn3epobCfjUqCxlIlurLr4RHu7RaE4trgN+RDcUq6HCVC3/yqq1hwbNYpVtulnTOJzcaxYlSr1fnuw==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/client-insights@5.49.2':
|
||||
resolution: {integrity: sha512-z14wfFs1T3eeYbCArC8pvntAWsPo9f6hnUGoj8IoRUJTwgJiiySECkm8bmmV47/x0oGHfsVn3kBdjMX0yq0sNA==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/client-personalization@5.49.2':
|
||||
resolution: {integrity: sha512-GpRf7yuuAX93+Qt0JGEJZwgtL0MFdjFO9n7dn8s2pA9mTjzl0Sc5+uTk1VPbIAuf7xhCP9Mve+URGb6J+EYxgA==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/client-query-suggestions@5.49.2':
|
||||
resolution: {integrity: sha512-HZwApmNkp0DiAjZcLYdQLddcG4Agb88OkojiAHGgcm5DVXobT5uSZ9lmyrbw/tmQBJwgu2CNw4zTyXoIB7YbPA==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/client-search@5.49.2':
|
||||
resolution: {integrity: sha512-y1IOpG6OSmTpGg/CT0YBb/EAhR2nsC18QWp9Jy8HO9iGySpcwaTvs5kHa17daP3BMTwWyaX9/1tDTDQshZzXdg==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/ingestion@1.49.2':
|
||||
resolution: {integrity: sha512-YYJRjaZ2bqk923HxE4um7j/Cm3/xoSkF2HC2ZweOF8cXL3sqnlndSUYmCaxHFjNPWLaSHk2IfssX6J/tdKTULw==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/monitoring@1.49.2':
|
||||
resolution: {integrity: sha512-9WgH+Dha39EQQyGKCHlGYnxW/7W19DIrEbCEbnzwAMpGAv1yTWCHMPXHxYa+LcL3eCp2V/5idD1zHNlIKmHRHg==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/recommend@5.49.2':
|
||||
resolution: {integrity: sha512-K7Gp5u+JtVYgaVpBxF5rGiM+Ia8SsMdcAJMTDV93rwh00DKNllC19o1g+PwrDjDvyXNrnTEbofzbTs2GLfFyKA==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/requester-browser-xhr@5.49.2':
|
||||
resolution: {integrity: sha512-3UhYCcWX6fbtN8ABcxZlhaQEwXFh3CsFtARyyadQShHMPe3mJV9Wel4FpJTa+seugRkbezFz0tt6aPTZSYTBuA==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/requester-fetch@5.49.2':
|
||||
resolution: {integrity: sha512-G94VKSGbsr+WjsDDOBe5QDQ82QYgxvpxRGJfCHZBnYKYsy/jv9qGIDb93biza+LJWizQBUtDj7bZzp3QZyzhPQ==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@algolia/requester-node-http@5.49.2':
|
||||
resolution: {integrity: sha512-UuihBGHafG/ENsrcTGAn5rsOffrCIRuHMOsD85fZGLEY92ate+BMTUqxz60dv5zerh8ZumN4bRm8eW2z9L11jA==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
'@ampproject/remapping@2.3.0':
|
||||
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
@@ -1031,6 +1101,40 @@ packages:
|
||||
resolution: {integrity: sha512-Y6+WUMsTFWE5jb20IFP4YGa5IrGY/+a/FbOSjDF/wz9gepU2hwCYSXRHP/vPwBvwcY3SVMASt4yXxbXNXigmZQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@docsearch/core@4.6.0':
|
||||
resolution: {integrity: sha512-IqG3oSd529jVRQ4dWZQKwZwQLVd//bWJTz2HiL0LkiHrI4U/vLrBasKB7lwQB/69nBAcCgs3TmudxTZSLH/ZQg==}
|
||||
peerDependencies:
|
||||
'@types/react': '>= 16.8.0 < 20.0.0'
|
||||
react: '>= 16.8.0 < 20.0.0'
|
||||
react-dom: '>= 16.8.0 < 20.0.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
react-dom:
|
||||
optional: true
|
||||
|
||||
'@docsearch/css@4.6.0':
|
||||
resolution: {integrity: sha512-YlcAimkXclvqta47g47efzCM5CFxDwv2ClkDfEs/fC/Ak0OxPH2b3czwa4o8O1TRBf+ujFF2RiUwszz2fPVNJQ==}
|
||||
|
||||
'@docsearch/react@4.6.0':
|
||||
resolution: {integrity: sha512-j8H5B4ArGxBPBWvw3X0J0Rm/Pjv2JDa2rV5OE0DLTp5oiBCptIJ/YlNOhZxuzbO2nwge+o3Z52nJRi3hryK9cA==}
|
||||
peerDependencies:
|
||||
'@types/react': '>= 16.8.0 < 20.0.0'
|
||||
react: '>= 16.8.0 < 20.0.0'
|
||||
react-dom: '>= 16.8.0 < 20.0.0'
|
||||
search-insights: '>= 1 < 3'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
react-dom:
|
||||
optional: true
|
||||
search-insights:
|
||||
optional: true
|
||||
|
||||
'@electric-sql/pglite@0.3.15':
|
||||
resolution: {integrity: sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==}
|
||||
|
||||
@@ -2274,9 +2378,6 @@ packages:
|
||||
'@oxc-project/types@0.95.0':
|
||||
resolution: {integrity: sha512-vACy7vhpMPhjEJhULNxrdR0D943TkA/MigMpJCHmBHvMXxRStRi/dPtTlfQ3uDwWSzRpT8z+7ImjZVf8JWBocQ==}
|
||||
|
||||
'@pagefind/default-ui@1.4.0':
|
||||
resolution: {integrity: sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==}
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.6':
|
||||
resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
@@ -3721,6 +3822,10 @@ packages:
|
||||
ajv@8.18.0:
|
||||
resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==}
|
||||
|
||||
algoliasearch@5.49.2:
|
||||
resolution: {integrity: sha512-1K0wtDaRONwfhL4h8bbJ9qTjmY6rhGgRvvagXkMBsAOMNr+3Q2SffHECh9DIuNVrMA1JwA0zCwhyepgBZVakng==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
|
||||
ansi-align@3.0.1:
|
||||
resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
|
||||
|
||||
@@ -6975,6 +7080,9 @@ packages:
|
||||
schema-dts@1.1.5:
|
||||
resolution: {integrity: sha512-RJr9EaCmsLzBX2NDiO5Z3ux2BVosNZN5jo0gWgsyKvxKIUL5R3swNvoorulAeL9kLB0iTSX7V6aokhla2m7xbg==}
|
||||
|
||||
search-insights@2.17.3:
|
||||
resolution: {integrity: sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==}
|
||||
|
||||
semver@6.3.1:
|
||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||
hasBin: true
|
||||
@@ -8208,6 +8316,112 @@ snapshots:
|
||||
|
||||
'@adobe/css-tools@4.4.4': {}
|
||||
|
||||
'@algolia/abtesting@1.15.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/autocomplete-core@1.19.2(@algolia/client-search@5.49.2)(algoliasearch@5.49.2)(search-insights@2.17.3)':
|
||||
dependencies:
|
||||
'@algolia/autocomplete-plugin-algolia-insights': 1.19.2(@algolia/client-search@5.49.2)(algoliasearch@5.49.2)(search-insights@2.17.3)
|
||||
'@algolia/autocomplete-shared': 1.19.2(@algolia/client-search@5.49.2)(algoliasearch@5.49.2)
|
||||
transitivePeerDependencies:
|
||||
- '@algolia/client-search'
|
||||
- algoliasearch
|
||||
- search-insights
|
||||
|
||||
'@algolia/autocomplete-plugin-algolia-insights@1.19.2(@algolia/client-search@5.49.2)(algoliasearch@5.49.2)(search-insights@2.17.3)':
|
||||
dependencies:
|
||||
'@algolia/autocomplete-shared': 1.19.2(@algolia/client-search@5.49.2)(algoliasearch@5.49.2)
|
||||
search-insights: 2.17.3
|
||||
transitivePeerDependencies:
|
||||
- '@algolia/client-search'
|
||||
- algoliasearch
|
||||
|
||||
'@algolia/autocomplete-shared@1.19.2(@algolia/client-search@5.49.2)(algoliasearch@5.49.2)':
|
||||
dependencies:
|
||||
'@algolia/client-search': 5.49.2
|
||||
algoliasearch: 5.49.2
|
||||
|
||||
'@algolia/client-abtesting@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/client-analytics@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/client-common@5.49.2': {}
|
||||
|
||||
'@algolia/client-insights@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/client-personalization@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/client-query-suggestions@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/client-search@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/ingestion@1.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/monitoring@1.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/recommend@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
'@algolia/requester-browser-xhr@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
|
||||
'@algolia/requester-fetch@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
|
||||
'@algolia/requester-node-http@5.49.2':
|
||||
dependencies:
|
||||
'@algolia/client-common': 5.49.2
|
||||
|
||||
'@ampproject/remapping@2.3.0':
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.13
|
||||
@@ -8796,6 +9010,28 @@ snapshots:
|
||||
gonzales-pe: 4.3.0
|
||||
node-source-walk: 7.0.1
|
||||
|
||||
'@docsearch/core@4.6.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.14
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
|
||||
'@docsearch/css@4.6.0': {}
|
||||
|
||||
'@docsearch/react@4.6.0(@algolia/client-search@5.49.2)(@types/react@19.2.14)(algoliasearch@5.49.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(search-insights@2.17.3)':
|
||||
dependencies:
|
||||
'@algolia/autocomplete-core': 1.19.2(@algolia/client-search@5.49.2)(algoliasearch@5.49.2)(search-insights@2.17.3)
|
||||
'@docsearch/core': 4.6.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@docsearch/css': 4.6.0
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.14
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
search-insights: 2.17.3
|
||||
transitivePeerDependencies:
|
||||
- '@algolia/client-search'
|
||||
- algoliasearch
|
||||
|
||||
'@electric-sql/pglite@0.3.15': {}
|
||||
|
||||
'@emmetio/abbreviation@2.3.3':
|
||||
@@ -10093,8 +10329,6 @@ snapshots:
|
||||
|
||||
'@oxc-project/types@0.95.0': {}
|
||||
|
||||
'@pagefind/default-ui@1.4.0': {}
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.6':
|
||||
optional: true
|
||||
|
||||
@@ -11187,7 +11421,7 @@ snapshots:
|
||||
magic-string: 0.30.21
|
||||
sirv: 3.0.2
|
||||
tinyrainbow: 2.0.0
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
ws: 8.19.0
|
||||
optionalDependencies:
|
||||
playwright: 1.58.2
|
||||
@@ -11197,6 +11431,26 @@ snapshots:
|
||||
- utf-8-validate
|
||||
- vite
|
||||
|
||||
'@vitest/browser@3.2.4(playwright@1.58.2)(vite@8.0.0(@types/node@22.19.15)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4)':
|
||||
dependencies:
|
||||
'@testing-library/dom': 10.4.1
|
||||
'@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1)
|
||||
'@vitest/mocker': 3.2.4(vite@8.0.0(@types/node@22.19.15)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))
|
||||
'@vitest/utils': 3.2.4
|
||||
magic-string: 0.30.21
|
||||
sirv: 3.0.2
|
||||
tinyrainbow: 2.0.0
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
ws: 8.19.0
|
||||
optionalDependencies:
|
||||
playwright: 1.58.2
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- msw
|
||||
- utf-8-validate
|
||||
- vite
|
||||
optional: true
|
||||
|
||||
'@vitest/coverage-v8@3.2.4(@vitest/browser@3.2.4)(vitest@3.2.4)':
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.3.0
|
||||
@@ -11212,9 +11466,9 @@ snapshots:
|
||||
std-env: 3.10.0
|
||||
test-exclude: 7.0.2
|
||||
tinyrainbow: 2.0.0
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
optionalDependencies:
|
||||
'@vitest/browser': 3.2.4(playwright@1.58.2)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4)
|
||||
'@vitest/browser': 3.2.4(playwright@1.58.2)(vite@8.0.0(@types/node@22.19.15)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -11234,6 +11488,15 @@ snapshots:
|
||||
optionalDependencies:
|
||||
vite: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
'@vitest/mocker@3.2.4(vite@8.0.0(@types/node@22.19.15)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.4
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
vite: 8.0.0(@types/node@22.19.15)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)
|
||||
optional: true
|
||||
|
||||
'@vitest/pretty-format@3.2.4':
|
||||
dependencies:
|
||||
tinyrainbow: 2.0.0
|
||||
@@ -11263,7 +11526,7 @@ snapshots:
|
||||
sirv: 3.0.2
|
||||
tinyglobby: 0.2.15
|
||||
tinyrainbow: 2.0.0
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
|
||||
'@vitest/utils@3.2.4':
|
||||
dependencies:
|
||||
@@ -11425,6 +11688,23 @@ snapshots:
|
||||
json-schema-traverse: 1.0.0
|
||||
require-from-string: 2.0.2
|
||||
|
||||
algoliasearch@5.49.2:
|
||||
dependencies:
|
||||
'@algolia/abtesting': 1.15.2
|
||||
'@algolia/client-abtesting': 5.49.2
|
||||
'@algolia/client-analytics': 5.49.2
|
||||
'@algolia/client-common': 5.49.2
|
||||
'@algolia/client-insights': 5.49.2
|
||||
'@algolia/client-personalization': 5.49.2
|
||||
'@algolia/client-query-suggestions': 5.49.2
|
||||
'@algolia/client-search': 5.49.2
|
||||
'@algolia/ingestion': 1.49.2
|
||||
'@algolia/monitoring': 1.49.2
|
||||
'@algolia/recommend': 5.49.2
|
||||
'@algolia/requester-browser-xhr': 5.49.2
|
||||
'@algolia/requester-fetch': 5.49.2
|
||||
'@algolia/requester-node-http': 5.49.2
|
||||
|
||||
ansi-align@3.0.1:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
@@ -15335,6 +15615,8 @@ snapshots:
|
||||
|
||||
schema-dts@1.1.5: {}
|
||||
|
||||
search-insights@2.17.3: {}
|
||||
|
||||
semver@6.3.1: {}
|
||||
|
||||
semver@7.7.4: {}
|
||||
@@ -16254,7 +16536,7 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/debug': 4.1.12
|
||||
'@types/node': 22.19.15
|
||||
'@vitest/browser': 3.2.4(playwright@1.58.2)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4)
|
||||
'@vitest/browser': 3.2.4(playwright@1.58.2)(vite@8.0.0(@types/node@22.19.15)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4)
|
||||
'@vitest/ui': 3.2.4(vitest@3.2.4)
|
||||
happy-dom: 18.0.1
|
||||
jsdom: 27.4.0
|
||||
|
||||
+16
-26
@@ -165,7 +165,6 @@ site/
|
||||
│ └── api-docs-builder/ # Generates API reference from TypeScript
|
||||
├── public/ # Static assets (served untransformed)
|
||||
├── integrations/ # Custom Astro integrations
|
||||
│ ├── pagefind.ts # Pagefind search integration
|
||||
│ └── llms-markdown.ts # LLM-optimized markdown generation
|
||||
├── astro.config.mjs # Astro configuration
|
||||
├── tsconfig.json # TypeScript config with path aliases
|
||||
@@ -554,7 +553,7 @@ vi.mock('@/types/docs', async () => {
|
||||
- **[Tailwind v4](https://tailwindcss.com)**: CSS utility classes via `@tailwindcss/vite`
|
||||
- **[Nanostores 1.0.1](https://github.com/nanostores/nanostores)**: Cross-island state
|
||||
- **[Base UI 1.2.0](https://base-ui.com)**: Headless accessible components
|
||||
- **[Pagefind 1.4.0](https://pagefind.app)**: Static search with build-time indexing
|
||||
- **[Algolia DocSearch v4](https://docsearch.algolia.com)**: Search via Algolia-hosted indexes (docs + blog)
|
||||
- **[Shiki 3.13.0](https://shiki.style)**: Syntax highlighting
|
||||
- **[Vitest 3.2.4](https://vitest.dev)**: Testing framework
|
||||
- **[clsx](https://github.com/lukeed/clsx)**: Class name concatenation utility
|
||||
@@ -582,30 +581,24 @@ import UtilReference from '@/components/docs/api-reference/UtilReference.astro';
|
||||
<UtilReference util="usePlayer" />
|
||||
```
|
||||
|
||||
## Custom Astro Integration: Pagefind
|
||||
## Search: Algolia DocSearch v4
|
||||
|
||||
**Location:** `integrations/pagefind.ts`
|
||||
**Config:** `src/search.config.ts` — Algolia app ID, API key, and index names.
|
||||
|
||||
**Purpose:** Integrates Pagefind static search into Astro build pipeline.
|
||||
**Component:** `src/components/Search.tsx` — React component loaded via `client:load` in the NavBar.
|
||||
|
||||
**Development mode:**
|
||||
- Serves Pagefind index from previous production build
|
||||
- Uses `sirv` middleware to serve `/pagefind/*` routes
|
||||
- Warns if index doesn't exist (needs `pnpm build` first)
|
||||
**Styles:** `src/styles/docsearch.css` — CSS variable overrides mapping DocSearch theming to site tokens (imported via `globals.css`).
|
||||
|
||||
**Production mode:**
|
||||
- Runs Pagefind CLI after Astro build completes
|
||||
- Indexes all HTML files in `dist/`
|
||||
- Maps Astro logger levels to Pagefind CLI flags
|
||||
**How it works:**
|
||||
- `DocSearch` React component provides the trigger button, modal, and keyboard shortcut (Cmd+K)
|
||||
- Two indexes queried via the `indices` prop: `videojs_docs` (filtered by current framework) and `videojs_blog` (unfiltered)
|
||||
- No build-time indexing — search queries hit the Algolia API directly
|
||||
|
||||
**Usage in `astro.config.mjs`:**
|
||||
```js
|
||||
import pagefind from './integrations/pagefind';
|
||||
|
||||
export default defineConfig({
|
||||
integrations: [pagefind()],
|
||||
});
|
||||
```
|
||||
**Data attributes used by the crawler:**
|
||||
- `data-search-content` — marks searchable content regions
|
||||
- `data-search-ignore` — excludes elements from search indexing
|
||||
- `data-framework`, `data-site`, `data-category` — facet/filter attributes
|
||||
- `data-llms-*` attributes are for the LLM markdown integration (unrelated to search)
|
||||
|
||||
## Environment Variables
|
||||
|
||||
@@ -819,12 +812,9 @@ Key points:
|
||||
- Add new guides to `src/docs.config.ts` sidebar
|
||||
- Use `devOnly: true` for internal documentation
|
||||
|
||||
### Search Indexing
|
||||
### Search
|
||||
|
||||
Pagefind indexes HTML files after build. During development:
|
||||
1. Run `pnpm build` at least once to generate search index
|
||||
2. Dev server serves the index from previous build
|
||||
3. Search won't include new content until next build
|
||||
Search is powered by Algolia DocSearch v4 and queries the Algolia API directly — no build-time indexing step needed. Search works in both dev and production as long as the Algolia account is provisioned. See the "Search: Algolia DocSearch v4" section above for details.
|
||||
|
||||
### Adding Framework/Style Support
|
||||
|
||||
|
||||
+8
-3
@@ -13,7 +13,7 @@ Mostly a standard [Astro](https://astro.build/) project.
|
||||
├── public/ # Static assets served as videojs.org/[filename]
|
||||
├── scripts/
|
||||
│ └── api-docs-builder/ # Generates API reference JSON from TypeScript sources
|
||||
├── integrations/ # Custom Astro integrations (pagefind, llms-markdown, etc.)
|
||||
├── integrations/ # Custom Astro integrations (llms-markdown, etc.)
|
||||
├── src/
|
||||
│ ├── assets/ # Assets imported into components, pages, etc.
|
||||
│ ├── components/
|
||||
@@ -164,9 +164,14 @@ See [CLAUDE.md](CLAUDE.md) for details on each plugin.
|
||||
|
||||
## Custom Integrations
|
||||
|
||||
Two custom Astro integrations in `integrations/`:
|
||||
### Search
|
||||
|
||||
Search is powered by [Algolia DocSearch v4](https://docsearch.algolia.com). Configuration is in `src/search.config.ts` and the component is `src/components/Search.tsx`.
|
||||
|
||||
### Custom Integration
|
||||
|
||||
One custom Astro integration in `integrations/`:
|
||||
|
||||
- **pagefind** — Indexes HTML after build for static search; serves previous index in dev
|
||||
- **llms-markdown** — Generates LLM-optimized `.md` files and `llms.txt` index from `[data-llms-content]` elements
|
||||
|
||||
See [CLAUDE.md](CLAUDE.md) for implementation details.
|
||||
|
||||
@@ -11,7 +11,6 @@ import tailwindcss from '@tailwindcss/vite';
|
||||
import { defineConfig, envField, fontProviders } from 'astro/config';
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
import llmsMarkdown from './integrations/llms-markdown';
|
||||
import pagefind from './integrations/pagefind';
|
||||
import rehypePrepareCodeBlocks from './src/utils/rehypePrepareCodeBlocks';
|
||||
import remarkConditionalHeadings from './src/utils/remarkConditionalHeadings';
|
||||
import { remarkReadingTime } from './src/utils/remarkReadingTime.mjs';
|
||||
@@ -77,7 +76,6 @@ export default defineConfig({
|
||||
`${SITE_URL}/docs/framework/react/llms.txt`,
|
||||
],
|
||||
}),
|
||||
pagefind(),
|
||||
llmsMarkdown(),
|
||||
react({
|
||||
babel: {
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
import { spawn } from 'node:child_process';
|
||||
import { existsSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import type { AstroIntegration } from 'astro';
|
||||
import sirv from 'sirv';
|
||||
|
||||
export interface PagefindOptions {
|
||||
/**
|
||||
* The path to the built site to index.
|
||||
* Defaults to the Astro output directory.
|
||||
*/
|
||||
site?: string;
|
||||
}
|
||||
|
||||
export default function pagefind(options: PagefindOptions = {}): AstroIntegration {
|
||||
return {
|
||||
name: 'pagefind',
|
||||
hooks: {
|
||||
'astro:server:setup': ({ server, logger }) => {
|
||||
// Serve Pagefind index from previous build during development
|
||||
const rootDir = server.config.root;
|
||||
const indexDir = join(rootDir, 'dist', 'client');
|
||||
const pagefindDir = join(indexDir, 'pagefind');
|
||||
|
||||
// Warn if index doesn't exist yet
|
||||
if (!existsSync(pagefindDir)) {
|
||||
logger.warn(
|
||||
'Pagefind index not found. Run `pnpm build` first to generate ' + 'the search index for development mode.'
|
||||
);
|
||||
} else {
|
||||
logger.debug(`Serving Pagefind index from ${indexDir}`);
|
||||
}
|
||||
|
||||
// Create sirv middleware to serve static files
|
||||
// approach adapted from https://github.com/shishkin/astro-pagefind
|
||||
const serve = sirv(indexDir, {
|
||||
dev: true, // No caching in dev mode
|
||||
etag: true, // Enable cache validation
|
||||
});
|
||||
|
||||
// Mount middleware for /pagefind/* routes only
|
||||
server.middlewares.use((req, res, next) => {
|
||||
if (req.url?.startsWith('/pagefind/')) {
|
||||
serve(req, res, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'astro:build:done': async ({ dir, logger }) => {
|
||||
// Determine the site directory to index
|
||||
// The dir parameter already points to the correct static output directory
|
||||
const siteDir = options.site || fileURLToPath(dir);
|
||||
|
||||
// Map Astro logger levels to Pagefind CLI flags
|
||||
const logLevel = logger.options.level;
|
||||
const logFlags: string[] = [];
|
||||
|
||||
if (logLevel === 'silent' || logLevel === 'error') {
|
||||
logFlags.push('--silent');
|
||||
} else if (logLevel === 'warn') {
|
||||
logFlags.push('--quiet');
|
||||
} else if (logLevel === 'debug') {
|
||||
logFlags.push('--verbose');
|
||||
}
|
||||
// 'info' level uses no flag (default)
|
||||
|
||||
logger.info('Running Pagefind indexer...');
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const pagefindProcess = spawn('npx', ['-y', 'pagefind', ...logFlags, '--site', siteDir], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
});
|
||||
|
||||
pagefindProcess.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
logger.info('Pagefind indexing complete');
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`Pagefind process exited with code ${code}`));
|
||||
}
|
||||
});
|
||||
|
||||
pagefindProcess.on('error', (error) => {
|
||||
reject(new Error(`Failed to start Pagefind: ${error.message}`));
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
+2
-2
@@ -22,10 +22,11 @@
|
||||
"@astrojs/rss": "^4.0.12",
|
||||
"@astrojs/sitemap": "^3.6.0",
|
||||
"@base-ui/react": "^1.2.0",
|
||||
"@docsearch/css": "^4.6.0",
|
||||
"@docsearch/react": "^4.6.0",
|
||||
"@mux/mux-node": "^12.8.1",
|
||||
"@mux/mux-uploader-react": "^1.4.1",
|
||||
"@nanostores/react": "^1.0.0",
|
||||
"@pagefind/default-ui": "^1.4.0",
|
||||
"@sentry/astro": "^10.32.1",
|
||||
"@shikijs/transformers": "^4.0.2",
|
||||
"@tailwindcss/vite": "^4.2.1",
|
||||
@@ -70,7 +71,6 @@
|
||||
"jsdom": "^27.0.0",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-astro": "^0.14.1",
|
||||
"sirv": "^3.0.2",
|
||||
"tsx": "^4.21.0",
|
||||
"turndown": "^7.2.2",
|
||||
"typescript": "^5.9.3",
|
||||
|
||||
@@ -45,7 +45,7 @@ const { class: className, dark = false } = Astro.props;
|
||||
>
|
||||
<Logo width="100%" />
|
||||
</a>
|
||||
<Search class="mr-4 ml-auto sm:self-center" />
|
||||
<Search client:load className="mr-4 ml-auto sm:self-center" />
|
||||
{/* Desktop nav links */}
|
||||
<div class="hidden md:flex">
|
||||
<GetStartedLink
|
||||
|
||||
@@ -42,7 +42,7 @@ const { class: className } = Astro.props;
|
||||
<LogoDocs width="100%" />
|
||||
</div>
|
||||
</a>
|
||||
<Search class="mr-4 ml-auto sm:self-center" />
|
||||
<Search client:load className="mr-4 ml-auto sm:self-center" />
|
||||
{/* Desktop nav links */}
|
||||
<div class="hidden h-full md:flex">
|
||||
<GetStartedLink
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { DocSearch } from '@docsearch/react';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { GITHUB_REPO_URL } from '@/consts';
|
||||
import { DOCSEARCH_API_KEY, DOCSEARCH_APP_ID, DOCSEARCH_BLOG_INDEX, DOCSEARCH_DOCS_INDEX } from '@/search.config';
|
||||
import { currentFramework } from '@/stores/preferences';
|
||||
|
||||
interface SearchProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function Search({ className }: SearchProps) {
|
||||
const framework = useStore(currentFramework);
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<DocSearch
|
||||
appId={DOCSEARCH_APP_ID}
|
||||
apiKey={DOCSEARCH_API_KEY}
|
||||
indices={[
|
||||
{
|
||||
name: DOCSEARCH_DOCS_INDEX,
|
||||
searchParameters: {
|
||||
facetFilters: framework ? [`framework:${framework}`] : [],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: DOCSEARCH_BLOG_INDEX,
|
||||
},
|
||||
]}
|
||||
getMissingResultsUrl={({ query }) =>
|
||||
`${GITHUB_REPO_URL}issues/new?title=${encodeURIComponent(`Search: no results for "${query}"`)}&labels=search`
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
---
|
||||
|
||||
import { join } from 'node:path/posix';
|
||||
import clsx from 'clsx';
|
||||
/**
|
||||
* We wrap Search.tsx in an .astro entry point for
|
||||
* 1. easy CSS support, since we can't use Tailwind on pagefind-ui
|
||||
* 2. a synchronous script to set the meta key (ctrl or cmd) without FOUC or hydration errors
|
||||
*/
|
||||
import SearchClient from './Search';
|
||||
import SearchIcon from './searchIcon.svg';
|
||||
import searchIconString from './searchIcon.svg?raw';
|
||||
|
||||
const baseUrl = import.meta.env.BASE_URL || '/';
|
||||
const bundlePath = join(baseUrl, 'pagefind/');
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
}
|
||||
const { class: className } = Astro.props;
|
||||
---
|
||||
|
||||
<SearchClient
|
||||
client:load
|
||||
className={clsx(
|
||||
"inline-flex min-h-6 cursor-pointer items-center gap-2 rounded-full border-faded-black px-2 sm:border dark:border-manila-dark intent:border-manila-dark dark:intent:border-warm-gray",
|
||||
className,
|
||||
)}
|
||||
baseUrl={baseUrl}
|
||||
bundlePath={bundlePath}
|
||||
searchId="pagefind-ui"
|
||||
searchStyle={{
|
||||
"--search-icon-url": `url('data:image/svg+xml;utf8,${encodeURIComponent(searchIconString)}')`,
|
||||
} as React.CSSProperties}
|
||||
>
|
||||
<SearchIcon class="h-4 w-4 sm:h-3 sm:w-3" />
|
||||
<kbd data-platform-key="default" class="hidden font-display text-h4 sm:inline"
|
||||
>Ctrl K</kbd
|
||||
>
|
||||
<kbd data-platform-key="mac" class="hidden font-display text-h4 sm:inline"
|
||||
>⌘K</kbd
|
||||
>
|
||||
</SearchClient>
|
||||
|
||||
{
|
||||
/**
|
||||
* Adapted from https://github.com/withastro/starlight/blob/8a72a19e2cfec235941b4e1401b69b44e6695068/packages/starlight/components/Search.astro#L55C1-L75C1
|
||||
* This is intentionally inlined to avoid briefly showing an invalid shortcut.
|
||||
* Purposely using the deprecated `navigator.platform` property to detect Apple devices, as the
|
||||
* user agent is spoofed by some browsers when opening the devtools.
|
||||
*/
|
||||
}
|
||||
<script is:inline>
|
||||
(() => {
|
||||
const defaultPlatformKey = document.querySelector(
|
||||
'kbd[data-platform-key="default"]',
|
||||
);
|
||||
const macPlatformKey = document.querySelector(
|
||||
'kbd[data-platform-key="mac"]',
|
||||
);
|
||||
if (/Mac|iPhone|iPod|iPad/i.test(navigator.platform)) {
|
||||
if (defaultPlatformKey) defaultPlatformKey.style.display = "none";
|
||||
} else {
|
||||
if (macPlatformKey) macPlatformKey.style.display = "none";
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style is:global>
|
||||
@import url("@pagefind/default-ui/css/ui.css");
|
||||
|
||||
#pagefind-ui {
|
||||
--pagefind-ui-scale: 1;
|
||||
--pagefind-ui-primary: var(--color-gold);
|
||||
--pagefind-ui-text: var(--color-faded-black);
|
||||
--pagefind-ui-background: var(--color-manila-50);
|
||||
--pagefind-ui-border: var(--color-manila-75);
|
||||
--pagefind-ui-tag: green;
|
||||
--pagefind-ui-border-width: 1px;
|
||||
--pagefind-ui-border-radius: var(--radius-xs);
|
||||
--pagefind-ui-font: inherit;
|
||||
}
|
||||
|
||||
.dark #pagefind-ui {
|
||||
--pagefind-ui-text: var(--color-manila-light);
|
||||
--pagefind-ui-background: var(--color-warm-gray);
|
||||
--pagefind-ui-border: var(--color-soot);
|
||||
}
|
||||
|
||||
#pagefind-ui .pagefind-ui__form::before {
|
||||
-webkit-mask-image: var(--search-icon-url);
|
||||
mask-image: var(--search-icon-url);
|
||||
}
|
||||
#pagefind-ui .pagefind-ui__search-input {
|
||||
font-size: var(--text-p2);
|
||||
line-height: var(--text-p2--line-height);
|
||||
letter-spacing: var(--text-p2--letter-spacing);
|
||||
font-weight: var(--text-p2--font-weight);
|
||||
}
|
||||
#pagefind-ui .pagefind-ui__filter-block {
|
||||
border-bottom: solid 1px var(--pagefind-ui-border);
|
||||
}
|
||||
#pagefind-ui .pagefind-ui__message {
|
||||
font-weight: var(--font-weight-normal);
|
||||
}
|
||||
#pagefind-ui .pagefind-ui__result-title,
|
||||
#pagefind-ui .pagefind-ui__filter-name {
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
#pagefind-ui .pagefind-ui__result-nested .pagefind-ui__result-link::before {
|
||||
font-weight: var(--font-weight-normal);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
#pagefind-ui mark {
|
||||
background-color: var(--color-gold);
|
||||
color: var(--color-faded-black);
|
||||
}
|
||||
</style>
|
||||
@@ -1,90 +0,0 @@
|
||||
import { Dialog } from '@base-ui/react/dialog';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { currentFramework } from '@/stores/preferences';
|
||||
|
||||
interface SearchProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
baseUrl: string;
|
||||
bundlePath: string;
|
||||
searchId: string;
|
||||
searchStyle?: React.CSSProperties;
|
||||
}
|
||||
export default function Search({ children, className, baseUrl, bundlePath, searchId, searchStyle }: SearchProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const framework = useStore(currentFramework);
|
||||
const searchRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// load Pagefind when opened
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
let search: any;
|
||||
const init = async () => {
|
||||
// default-ui is actually an ultra-lightweight svelte app
|
||||
// ...which we're loading in this react component, in an astro app.
|
||||
// this isn't relevant to dev. I just found it funny.
|
||||
const { PagefindUI } = await import('@pagefind/default-ui');
|
||||
// I'd love if we built our own ui with BaseUI/Autocomplete, but... time, ya know?
|
||||
search = new PagefindUI({
|
||||
element: `#${searchId}`,
|
||||
baseUrl,
|
||||
bundlePath,
|
||||
showImages: false,
|
||||
showSubResults: true,
|
||||
autofocus: true,
|
||||
});
|
||||
search.triggerFilters({
|
||||
framework: [framework],
|
||||
});
|
||||
};
|
||||
init();
|
||||
return () => {
|
||||
search.destroy();
|
||||
};
|
||||
}, [baseUrl, bundlePath, framework, open, searchId]);
|
||||
|
||||
// open with cmd+k or ctrl+k
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
|
||||
e.preventDefault();
|
||||
setOpen((prev) => !prev);
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Dialog.Root
|
||||
open={open}
|
||||
onOpenChange={(newOpen) => {
|
||||
setOpen(newOpen);
|
||||
}}
|
||||
modal
|
||||
>
|
||||
<Dialog.Trigger aria-label="Search" className={className}>
|
||||
{children}
|
||||
</Dialog.Trigger>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Backdrop className="fixed inset-0 flex items-start justify-center bg-faded-black/20 backdrop-blur-xs z-50">
|
||||
<Dialog.Popup
|
||||
initialFocus={false} // pagefind.autofocus = true
|
||||
id={searchId}
|
||||
ref={searchRef}
|
||||
className="w-full max-w-5xl mx-4 mb-4 p-4 rounded-xs bg-manila-light dark:bg-faded-black dark:border-warm-gray border-manila-75 border overflow-y-scroll overflow-x-hidden"
|
||||
style={{
|
||||
minHeight: '50svh',
|
||||
maxHeight: '75svh',
|
||||
marginTop: '12.5svh',
|
||||
...searchStyle,
|
||||
}}
|
||||
/>
|
||||
</Dialog.Backdrop>
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
||||
);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './Search.astro';
|
||||
@@ -1,12 +0,0 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M21 21l-4.34-4.34" vector-effect="non-scaling-stroke" />
|
||||
<circle cx="11" cy="11" r="8" vector-effect="non-scaling-stroke" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 319 B |
@@ -254,7 +254,9 @@ export function Tab({ value, children, initial, variant = 'compact' }: TabProps)
|
||||
)}
|
||||
<span className="relative">
|
||||
{/* to prevent layout shift on state change, we have an invisible bold version of the text preserving space */}
|
||||
<span className="font-bold invisible">{children}</span>
|
||||
<span className="font-bold invisible" data-search-ignore data-llms-ignore>
|
||||
{children}
|
||||
</span>
|
||||
<span className={clsx('absolute top-0 left-0', isActive && 'font-bold')}>{children}</span>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -30,7 +30,7 @@ const shouldRender = !frameworks || frameworks.includes(framework as SupportedFr
|
||||
<div
|
||||
class="contents"
|
||||
hidden={!shouldRender}
|
||||
data-pagefind-ignore={shouldRender ? undefined : "all"}
|
||||
data-search-ignore={shouldRender ? undefined : "all"}
|
||||
data-llms-ignore={shouldRender ? undefined : "all"}
|
||||
>
|
||||
<slot />
|
||||
|
||||
@@ -56,12 +56,11 @@ const jsonLdSchema = createBlogPostingSchema({
|
||||
<JsonLd slot="head" schema={jsonLdSchema} />
|
||||
<article
|
||||
class="@container"
|
||||
data-pagefind-body
|
||||
data-search-content
|
||||
data-llms-content
|
||||
data-llms-description={post.data.description}
|
||||
data-llms-sort={post.data.pubDate.toISOString()}
|
||||
data-site="blog"
|
||||
data-pagefind-filter="site[data-site]"
|
||||
>
|
||||
<header
|
||||
class="relative mx-auto mb-10 max-w-3xl border-y border-faded-black py-10 dark:border-manila-light"
|
||||
@@ -69,12 +68,9 @@ const jsonLdSchema = createBlogPostingSchema({
|
||||
<div
|
||||
class="mb-3 flex flex-col gap-2 font-display text-h4 font-bold text-orange uppercase sm:flex-row sm:gap-4"
|
||||
>
|
||||
<FormattedDate
|
||||
data-pagefind-sort={`date:${post.data.pubDate.toISOString()}`}
|
||||
date={post.data.pubDate}
|
||||
/>
|
||||
<FormattedDate date={post.data.pubDate} />
|
||||
<span class="hidden sm:inline">•</span>
|
||||
<span data-pagefind-ignore data-llms-ignore
|
||||
<span data-search-ignore data-llms-ignore
|
||||
>{remarkPluginFrontmatter.minutesRead}</span
|
||||
>
|
||||
</div>
|
||||
@@ -91,7 +87,6 @@ const jsonLdSchema = createBlogPostingSchema({
|
||||
<a
|
||||
href={`/blog/authors/${authors.find((a) => a.data.name === part.value)?.id}`}
|
||||
class="inline-block intent:underline"
|
||||
data-pagefind-meta="author"
|
||||
>
|
||||
{part.value}
|
||||
</a>
|
||||
|
||||
@@ -129,13 +129,12 @@ const jsonLdSchema = createTechArticleSchema({
|
||||
>
|
||||
<article
|
||||
class="mb-18 flex-1"
|
||||
data-pagefind-body
|
||||
data-search-content
|
||||
data-llms-content
|
||||
data-llms-description={doc.data.description}
|
||||
data-framework={framework}
|
||||
data-site="docs"
|
||||
data-category={sections[0]}
|
||||
data-pagefind-filter="framework[data-framework], section[data-site]"
|
||||
>
|
||||
<header
|
||||
class:list={[
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/** Algolia DocSearch — search API key is public (read-only). */
|
||||
export const DOCSEARCH_APP_ID = '5WD2PWU9HZ';
|
||||
export const DOCSEARCH_API_KEY = '68c102f304dc6e38fa3c2d167d2389ed';
|
||||
export const DOCSEARCH_DOCS_INDEX = 'videojs_docs';
|
||||
export const DOCSEARCH_BLOG_INDEX = 'videojs_blog';
|
||||
@@ -0,0 +1,282 @@
|
||||
@import "@docsearch/css/dist/style.css";
|
||||
/* ── Light theme ── */
|
||||
:root {
|
||||
--docsearch-primary-color: var(--color-gold);
|
||||
--docsearch-text-color: var(--color-faded-black);
|
||||
--docsearch-secondary-text-color: var(--color-soot);
|
||||
--docsearch-background-color: var(--color-manila-50);
|
||||
--docsearch-modal-background: var(--color-manila-50);
|
||||
--docsearch-modal-shadow:
|
||||
0 calc(var(--spacing) * 3) calc(var(--spacing) * 7) color-mix(in srgb, var(--color-faded-black) 15%, transparent),
|
||||
0 calc(var(--spacing) / 2) var(--spacing) color-mix(in srgb, var(--color-faded-black) 8%, transparent);
|
||||
--docsearch-searchbox-background: var(--color-manila-light);
|
||||
--docsearch-searchbox-focus-background: var(--color-manila-light);
|
||||
--docsearch-hit-background: var(--color-manila-light);
|
||||
--docsearch-hit-color: var(--color-faded-black);
|
||||
--docsearch-hit-highlight-color: color-mix(in srgb, var(--color-gold) 15%, var(--color-manila-light));
|
||||
--docsearch-highlight-color: var(--color-orange);
|
||||
--docsearch-soft-primary-color: color-mix(in srgb, var(--color-gold) 10%, transparent);
|
||||
--docsearch-focus-color: var(--color-gold);
|
||||
--docsearch-subtle-color: var(--color-manila-75);
|
||||
--docsearch-muted-color: var(--color-manila-dark);
|
||||
--docsearch-icon-color: var(--color-soot);
|
||||
--docsearch-container-background: color-mix(in srgb, var(--color-faded-black) 20%, transparent);
|
||||
--docsearch-key-background: var(--color-manila-75);
|
||||
--docsearch-key-color: var(--color-faded-black);
|
||||
--docsearch-key-pressed-shadow: inset 0 calc(var(--spacing) / 2) var(--spacing)
|
||||
color-mix(in srgb, var(--color-faded-black) 15%, transparent);
|
||||
--docsearch-footer-background: var(--color-manila-light);
|
||||
--docsearch-footer-shadow: 0 -1px 0 0 var(--color-manila-75); /* 1px hairline */
|
||||
--docsearch-logo-color: currentColor;
|
||||
--docsearch-border-radius: var(--radius-xs);
|
||||
--docsearch-spacing: calc(var(--spacing) * 4);
|
||||
--docsearch-searchbox-height: calc(var(--spacing) * 14);
|
||||
--docsearch-searchbox-initial-height: calc(var(--spacing) * 14);
|
||||
--docsearch-hit-height: calc(var(--spacing) * 14);
|
||||
--docsearch-actions-height: calc(var(--spacing) * 11);
|
||||
--docsearch-footer-height: calc(var(--spacing) * 13);
|
||||
--docsearch-icon-stroke-width: 2;
|
||||
--docsearch-search-button-background: transparent;
|
||||
--docsearch-search-button-text-color: var(--color-faded-black);
|
||||
}
|
||||
|
||||
/* ── Dark theme ── */
|
||||
.dark {
|
||||
--docsearch-text-color: var(--color-manila-light);
|
||||
--docsearch-secondary-text-color: var(--color-manila-dark);
|
||||
--docsearch-background-color: var(--color-warm-gray);
|
||||
--docsearch-modal-background: var(--color-faded-black);
|
||||
--docsearch-modal-shadow:
|
||||
inset 1px 1px 0 0 var(--color-warm-gray),
|
||||
0 calc(var(--spacing) * 0.75) calc(var(--spacing) * 2) color-mix(in srgb, var(--color-black) 50%, transparent);
|
||||
--docsearch-searchbox-background: var(--color-soot);
|
||||
--docsearch-searchbox-focus-background: var(--color-soot);
|
||||
--docsearch-hit-background: var(--color-warm-gray);
|
||||
--docsearch-hit-color: var(--color-manila-light);
|
||||
--docsearch-hit-highlight-color: color-mix(in srgb, var(--color-gold) 10%, var(--color-warm-gray));
|
||||
--docsearch-highlight-color: var(--color-gold);
|
||||
--docsearch-soft-primary-color: color-mix(in srgb, var(--color-gold) 10%, transparent);
|
||||
--docsearch-focus-color: var(--color-gold);
|
||||
--docsearch-subtle-color: var(--color-warm-gray);
|
||||
--docsearch-muted-color: var(--color-manila-dark);
|
||||
--docsearch-icon-color: var(--color-manila-dark);
|
||||
--docsearch-container-background: color-mix(in srgb, var(--color-faded-black) 60%, transparent);
|
||||
--docsearch-key-background: var(--color-soot);
|
||||
--docsearch-key-color: var(--color-manila-light);
|
||||
--docsearch-key-pressed-shadow: inset 0 calc(var(--spacing) / 2) var(--spacing)
|
||||
color-mix(in srgb, var(--color-black) 40%, transparent);
|
||||
--docsearch-footer-background: var(--color-soot);
|
||||
--docsearch-footer-shadow: 0 -1px 0 0 var(--color-warm-gray); /* 1px hairline */
|
||||
--docsearch-logo-color: currentColor;
|
||||
--docsearch-search-button-background: transparent;
|
||||
--docsearch-search-button-text-color: var(--color-manila-light);
|
||||
}
|
||||
|
||||
/* ── Trigger button — match rounded-pill navbar style ── */
|
||||
.DocSearch-Button {
|
||||
box-sizing: border-box;
|
||||
border-radius: 9999px;
|
||||
border: none;
|
||||
padding: 0 calc(var(--spacing) * 2);
|
||||
gap: calc(var(--spacing) * 2);
|
||||
height: auto;
|
||||
min-height: calc(var(--spacing) * 6);
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.DocSearch-Button:hover,
|
||||
.DocSearch-Button:focus-within {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Search-Icon {
|
||||
width: calc(var(--spacing) * 4);
|
||||
height: calc(var(--spacing) * 4);
|
||||
}
|
||||
|
||||
.DocSearch-Search-Icon circle,
|
||||
.DocSearch-Search-Icon path {
|
||||
stroke-width: var(--docsearch-icon-stroke-width);
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Search-Icon circle,
|
||||
.DocSearch-Button .DocSearch-Search-Icon path {
|
||||
stroke-width: calc(var(--docsearch-icon-stroke-width) * 2);
|
||||
}
|
||||
|
||||
/* Hide button label text on small screens, keep icon + keyboard shortcut */
|
||||
.DocSearch-Button-Placeholder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.DocSearch-Button-Keys {
|
||||
display: none;
|
||||
min-width: 0;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.DocSearch-Button-Keys:has(.DocSearch-Button-Key--ctrl) {
|
||||
gap: var(--spacing);
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Button-Key {
|
||||
background: none;
|
||||
border: none;
|
||||
box-shadow: none !important;
|
||||
color: inherit;
|
||||
width: auto;
|
||||
height: auto;
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-h4);
|
||||
line-height: var(--text-h4--line-height);
|
||||
letter-spacing: var(--text-h4--letter-spacing);
|
||||
font-weight: var(--font-weight-bold);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (width >= 40rem) {
|
||||
.DocSearch-Button {
|
||||
border: 1px solid var(--color-faded-black);
|
||||
width: calc(var(--spacing) * 16.5);
|
||||
}
|
||||
|
||||
.DocSearch-Button:has(.DocSearch-Button-Key--ctrl) {
|
||||
width: calc(var(--spacing) * 25);
|
||||
}
|
||||
|
||||
.dark .DocSearch-Button {
|
||||
border-color: var(--color-manila-dark);
|
||||
}
|
||||
|
||||
.DocSearch-Button:hover,
|
||||
.DocSearch-Button:focus-within {
|
||||
border-color: var(--color-manila-dark);
|
||||
}
|
||||
|
||||
.dark .DocSearch-Button:hover,
|
||||
.dark .DocSearch-Button:focus-within {
|
||||
border-color: var(--color-warm-gray);
|
||||
}
|
||||
|
||||
.DocSearch-Button-Keys {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Search-Icon {
|
||||
width: calc(var(--spacing) * 3);
|
||||
height: calc(var(--spacing) * 3);
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Modal backdrop ── */
|
||||
.DocSearch-Container {
|
||||
backdrop-filter: blur(calc(var(--spacing) / 2));
|
||||
}
|
||||
|
||||
/* ── Consistent border-radius — DocSearch hardcodes 4px on these ── */
|
||||
.DocSearch-Modal {
|
||||
border-radius: var(--radius-xs);
|
||||
}
|
||||
|
||||
.DocSearch-Form {
|
||||
border-radius: var(--radius-xs) var(--radius-xs) 0 0;
|
||||
}
|
||||
|
||||
.DocSearch-Footer {
|
||||
border-radius: 0 0 var(--radius-xs) var(--radius-xs);
|
||||
border-block-start: none;
|
||||
}
|
||||
|
||||
.DocSearch-Dropdown + .DocSearch-Footer {
|
||||
border-block-start: 1px solid var(--docsearch-subtle-color);
|
||||
}
|
||||
|
||||
.DocSearch-Hit a {
|
||||
border-radius: var(--radius-xs);
|
||||
}
|
||||
|
||||
/* ── Typography — full text-token treatment (size + leading + tracking + weight) ── */
|
||||
.DocSearch-Modal {
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--text-p2);
|
||||
line-height: var(--text-p2--line-height);
|
||||
letter-spacing: var(--text-p2--letter-spacing);
|
||||
font-weight: var(--text-p2--font-weight);
|
||||
text-underline-offset: 0.25em;
|
||||
}
|
||||
|
||||
.DocSearch-Input {
|
||||
letter-spacing: var(--tracking-tight);
|
||||
font-weight: var(--text-p1--font-weight);
|
||||
}
|
||||
|
||||
.DocSearch-Button-Key,
|
||||
.DocSearch-Escape-Key {
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--text-code);
|
||||
line-height: var(--text-code--line-height);
|
||||
letter-spacing: var(--text-code--letter-spacing);
|
||||
font-weight: var(--text-code--font-weight);
|
||||
font-variant-ligatures: none;
|
||||
text-underline-offset: 0.125em;
|
||||
}
|
||||
|
||||
.DocSearch-Hit-source {
|
||||
font-size: var(--text-p2);
|
||||
line-height: var(--text-p2--line-height);
|
||||
letter-spacing: var(--text-p2--letter-spacing);
|
||||
font-weight: var(--font-weight-bold);
|
||||
padding-block-start: calc(var(--spacing) * 4);
|
||||
padding-block-end: calc(var(--spacing) * 2);
|
||||
}
|
||||
|
||||
.DocSearch-Hit-title {
|
||||
font-size: var(--text-p2);
|
||||
line-height: var(--text-p2--line-height);
|
||||
letter-spacing: var(--text-p2--letter-spacing);
|
||||
}
|
||||
|
||||
.DocSearch-Hit-path {
|
||||
font-size: var(--text-p3);
|
||||
line-height: var(--text-p3--line-height);
|
||||
letter-spacing: var(--text-p3--letter-spacing);
|
||||
font-weight: var(--text-p3--font-weight);
|
||||
}
|
||||
|
||||
.DocSearch-Label,
|
||||
.DocSearch-Help,
|
||||
.DocSearch-NoResults-Help {
|
||||
font-size: var(--text-p3);
|
||||
line-height: var(--text-p3--line-height);
|
||||
letter-spacing: var(--text-p3--letter-spacing);
|
||||
font-weight: var(--text-p3--font-weight);
|
||||
}
|
||||
|
||||
.DocSearch-Clear {
|
||||
font-size: var(--text-p3);
|
||||
font-weight: var(--text-p3--font-weight);
|
||||
}
|
||||
|
||||
.DocSearch-Title strong {
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
/* ── Hit spacing — more breathing room, tighter title/path gap ── */
|
||||
.DocSearch-Hit-content-wrapper {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
/* ── Algolia logo — SVG paths hardcode blue fills via .cls-1/.cls-2 ── */
|
||||
.DocSearch-Logo svg .cls-1,
|
||||
.DocSearch-Logo svg .cls-2 {
|
||||
fill: var(--docsearch-logo-color);
|
||||
}
|
||||
|
||||
/* ── Text match highlight — keep readable in all states ── */
|
||||
.DocSearch-Hit mark,
|
||||
.DocSearch-Hit[aria-selected="true"] mark {
|
||||
text-decoration-color: var(--color-gold);
|
||||
color: currentColor;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
@import "tailwindcss";
|
||||
@import "./shiki-transformers.css";
|
||||
@import "./docsearch.css";
|
||||
|
||||
/**
|
||||
* @license
|
||||
|
||||
Reference in New Issue
Block a user