atmosphere explorer

add opensearch support

handle.invalid 7dd0cc1e fbdda4e2

verified
+76 -37
+1
.gitignore
··· 3 3 .env 4 4 .DS_Store 5 5 public/oauth-client-metadata.json 6 + public/opensearch.xml
+6
index.html
··· 10 10 <meta property="og:description" content="Browse the public data on atproto" /> 11 11 <meta property="description" content="Browse the public data on atproto" /> 12 12 <link rel="manifest" href="/manifest.json" /> 13 + <link 14 + rel="search" 15 + type="application/opensearchdescription+xml" 16 + href="/opensearch.xml" 17 + title="PDSls" 18 + /> 13 19 <link rel="preconnect" href="https://fonts.bunny.net" /> 14 20 <link href="https://fonts.bunny.net/css?family=roboto-mono:400" rel="stylesheet" /> 15 21 <link href="https://fonts.cdnfonts.com/css/pecita" rel="stylesheet" />
+2 -2
package.json
··· 4 4 "type": "module", 5 5 "scripts": { 6 6 "start": "vite", 7 - "predev": "node scripts/generate-oauth-metadata.js", 7 + "predev": "node scripts/generate-metadata.js", 8 8 "dev": "vite", 9 - "prebuild": "node scripts/generate-oauth-metadata.js", 9 + "prebuild": "node scripts/generate-metadata.js", 10 10 "build": "vite build", 11 11 "serve": "vite preview" 12 12 },
+59
scripts/generate-metadata.js
··· 1 + import { mkdirSync, writeFileSync } from "fs"; 2 + import { dirname } from "path"; 3 + import { fileURLToPath } from "url"; 4 + 5 + const __filename = fileURLToPath(import.meta.url); 6 + const __dirname = dirname(__filename); 7 + 8 + const domain = process.env.APP_DOMAIN || "pdsls.dev"; 9 + const protocol = process.env.APP_PROTOCOL || "https"; 10 + const baseUrl = `${protocol}://${domain}`; 11 + 12 + const configs = { 13 + oauth: { 14 + name: "OAuth metadata", 15 + path: `${__dirname}/../public/oauth-client-metadata.json`, 16 + content: 17 + JSON.stringify( 18 + { 19 + client_id: `${baseUrl}/oauth-client-metadata.json`, 20 + client_name: "PDSls", 21 + client_uri: baseUrl, 22 + logo_uri: `${baseUrl}/favicon.ico`, 23 + redirect_uris: [`${baseUrl}/`], 24 + scope: "atproto repo:*?action=create repo:*?action=update repo:*?action=delete blob:*/*", 25 + grant_types: ["authorization_code", "refresh_token"], 26 + response_types: ["code"], 27 + token_endpoint_auth_method: "none", 28 + application_type: "web", 29 + dpop_bound_access_tokens: true, 30 + }, 31 + null, 32 + 2, 33 + ) + "\n", 34 + }, 35 + opensearch: { 36 + name: "OpenSearch XML", 37 + path: `${__dirname}/../public/opensearch.xml`, 38 + content: `<?xml version="1.0" encoding="UTF-8"?> 39 + <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/"> 40 + <ShortName>PDSls</ShortName> 41 + <Description>Search the Atmosphere</Description> 42 + <InputEncoding>UTF-8</InputEncoding> 43 + <Image width="16" height="16" type="image/x-icon">${baseUrl}/favicon.ico</Image> 44 + <Url type="text/html" method="get" template="${baseUrl}/?q={searchTerms}"/> 45 + <moz:SearchForm>${baseUrl}</moz:SearchForm> 46 + </OpenSearchDescription>`, 47 + }, 48 + }; 49 + 50 + try { 51 + Object.values(configs).forEach((config) => { 52 + mkdirSync(dirname(config.path), { recursive: true }); 53 + writeFileSync(config.path, config.content); 54 + console.log(`Generated ${config.name} for ${baseUrl}`); 55 + }); 56 + } catch (error) { 57 + console.error("Failed to generate files:", error); 58 + process.exit(1); 59 + }
-35
scripts/generate-oauth-metadata.js
··· 1 - import { mkdirSync, writeFileSync } from "fs"; 2 - import { dirname } from "path"; 3 - import { fileURLToPath } from "url"; 4 - 5 - const __filename = fileURLToPath(import.meta.url); 6 - const __dirname = dirname(__filename); 7 - 8 - const domain = process.env.APP_DOMAIN || "pdsls.dev"; 9 - const protocol = process.env.APP_PROTOCOL || "https"; 10 - const baseUrl = `${protocol}://${domain}`; 11 - 12 - const metadata = { 13 - client_id: `${baseUrl}/oauth-client-metadata.json`, 14 - client_name: "PDSls", 15 - client_uri: baseUrl, 16 - logo_uri: `${baseUrl}/favicon.ico`, 17 - redirect_uris: [`${baseUrl}/`], 18 - scope: "atproto repo:*?action=create repo:*?action=update repo:*?action=delete blob:*/*", 19 - grant_types: ["authorization_code", "refresh_token"], 20 - response_types: ["code"], 21 - token_endpoint_auth_method: "none", 22 - application_type: "web", 23 - dpop_bound_access_tokens: true, 24 - }; 25 - 26 - const outputPath = `${__dirname}/../public/oauth-client-metadata.json`; 27 - 28 - try { 29 - mkdirSync(dirname(outputPath), { recursive: true }); 30 - writeFileSync(outputPath, JSON.stringify(metadata, null, 2) + "\n"); 31 - console.log(`Generated OAuth metadata for ${baseUrl}`); 32 - } catch (error) { 33 - console.error("Failed to generate OAuth metadata:", error); 34 - process.exit(1); 35 - }
+8
src/components/search.tsx
··· 128 128 129 129 window.addEventListener("paste", handlePaste); 130 130 onCleanup(() => window.removeEventListener("paste", handlePaste)); 131 + 132 + const requestUrl = new URL(location.href); 133 + const requestQuery = requestUrl.searchParams.get("q"); 134 + if (requestQuery !== null) { 135 + requestUrl.searchParams.delete("q"); 136 + history.replaceState(null, "", requestUrl.toString()); 137 + processInput(requestQuery); 138 + } 131 139 }); 132 140 133 141 createEffect(() => {