custom element for embedding Bluesky posts and feeds mary-ext.github.io/bluesky-embed
typescript npm bluesky atcute

chore: make it easier to dev on post embeds

mary.my.id 63224d3a 469a8de0

verified
+11
packages/bluesky-post-embed/index.html
··· 1 + <!doctype html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 + <title>Bluesky post embed</title> 7 + </head> 8 + <body> 9 + <script type="module" src="./src/main.tsx"></script> 10 + </body> 11 + </html>
+2
packages/bluesky-post-embed/package.json
··· 32 32 "@atcute/client": "^2.0.6" 33 33 }, 34 34 "devDependencies": { 35 + "@preact/preset-vite": "^2.9.2", 35 36 "@tsconfig/svelte": "^5.0.4", 36 37 "@types/node": "^22.10.1", 37 38 "internal": "workspace:^", 39 + "preact": "^10.25.1", 38 40 "svelte": "catalog:", 39 41 "svelte-check": "^4.1.1", 40 42 "vite": "^6.0.3",
+53
packages/bluesky-post-embed/src/app.tsx
··· 1 + import { useEffect, useMemo, useState } from 'preact/hooks'; 2 + 3 + import type { PostData } from 'internal/types/post.js'; 4 + import { fetchPost, renderPost } from '../lib/core'; 5 + 6 + const uri = `at://did:plc:ragtjsm2j2vknwkz3zp4oxrd/app.bsky.feed.post/3kj2umze7zj2n`; 7 + 8 + const App = () => { 9 + const [state, setState] = useState<{ uri: string; data: PostData }>(); 10 + 11 + useEffect(() => { 12 + if (state && state.uri === uri) { 13 + return; 14 + } 15 + 16 + const controller = new AbortController(); 17 + const promise = fetchPost({ 18 + uri: uri, 19 + signal: controller.signal, 20 + allowUnauthenticated: true, 21 + }); 22 + 23 + promise.then((data) => { 24 + setState({ uri, data }); 25 + }); 26 + 27 + return () => { 28 + controller.abort(); 29 + }; 30 + }, [uri]); 31 + 32 + return <div class="app">{state && <BlueskyPost data={state.data} />}</div>; 33 + }; 34 + 35 + export default App; 36 + 37 + const BlueskyPost = ({ data }: { data: PostData }) => { 38 + const html = useMemo(() => renderPost(data), [data]); 39 + 40 + return <bluesky-post src={data.thread?.post.uri} dangerouslySetInnerHTML={{ __html: html }}></bluesky-post>; 41 + }; 42 + 43 + declare module 'preact' { 44 + namespace JSX { 45 + interface BlueskyPostAttributes extends HTMLAttributes<HTMLElement> { 46 + src?: string; 47 + } 48 + 49 + interface IntrinsicElements { 50 + 'bluesky-post': BlueskyPostAttributes; 51 + } 52 + } 53 + }
+8
packages/bluesky-post-embed/src/main.tsx
··· 1 + import { render } from 'preact'; 2 + 3 + import App from './app'; 4 + 5 + import '../../../themes/light.css'; 6 + import './styles/main.css'; 7 + 8 + render(<App />, document.body);
+8
packages/bluesky-post-embed/src/styles/main.css
··· 1 + @import './normalize.css'; 2 + 3 + .app { 4 + margin: 0 auto; 5 + padding: 36px 16px; 6 + width: 100%; 7 + max-width: calc(550px + (16 * 2px)); 8 + }
+199
packages/bluesky-post-embed/src/styles/normalize.css
··· 1 + /*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */ 2 + 3 + /* 4 + Document 5 + ======== 6 + */ 7 + 8 + /** 9 + Use a better box model (opinionated). 10 + */ 11 + 12 + *, 13 + ::before, 14 + ::after { 15 + box-sizing: border-box; 16 + } 17 + 18 + html { 19 + line-height: 1.15; /* 1. Correct the line height in all browsers. */ 20 + /* Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) */ 21 + font-family: 'Inter', 'Roboto', ui-sans-serif, sans-serif, 'Noto Color Emoji', 'Twemoji Mozilla'; 22 + -webkit-text-size-adjust: 100%; /* 2. Prevent adjustments of font size after orientation changes in iOS. */ 23 + tab-size: 4; /* 3. Use a more readable tab size (opinionated). */ 24 + } 25 + 26 + /* 27 + Sections 28 + ======== 29 + */ 30 + 31 + body { 32 + margin: 0; /* Remove the margin in all browsers. */ 33 + } 34 + 35 + /* 36 + Text-level semantics 37 + ==================== 38 + */ 39 + 40 + /** 41 + Add the correct font weight in Chrome and Safari. 42 + */ 43 + 44 + b, 45 + strong { 46 + font-weight: bolder; 47 + } 48 + 49 + /** 50 + 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) 51 + 2. Correct the odd 'em' font sizing in all browsers. 52 + */ 53 + 54 + code, 55 + kbd, 56 + samp, 57 + pre { 58 + font-size: 1em; /* 2 */ 59 + font-family: 'JetBrains Mono NL', ui-monospace, monospace; /* 1 */ 60 + } 61 + 62 + /** 63 + Add the correct font size in all browsers. 64 + */ 65 + 66 + small { 67 + font-size: 80%; 68 + } 69 + 70 + /** 71 + Prevent 'sub' and 'sup' elements from affecting the line height in all browsers. 72 + */ 73 + 74 + sub, 75 + sup { 76 + position: relative; 77 + vertical-align: baseline; 78 + font-size: 75%; 79 + line-height: 0; 80 + } 81 + 82 + sub { 83 + bottom: -0.25em; 84 + } 85 + 86 + sup { 87 + top: -0.5em; 88 + } 89 + 90 + /* 91 + Tabular data 92 + ============ 93 + */ 94 + 95 + /** 96 + Correct table border color inheritance in Chrome and Safari. (https://issues.chromium.org/issues/40615503, https://bugs.webkit.org/show_bug.cgi?id=195016) 97 + */ 98 + 99 + table { 100 + border-color: currentcolor; 101 + } 102 + 103 + /* 104 + Forms 105 + ===== 106 + */ 107 + 108 + /** 109 + 1. Change the font styles in all browsers. 110 + 2. Remove the margin in Firefox and Safari. 111 + */ 112 + 113 + button, 114 + input, 115 + optgroup, 116 + select, 117 + textarea { 118 + margin: 0; /* 2 */ 119 + font-size: 100%; /* 1 */ 120 + line-height: 1.15; /* 1 */ 121 + font-family: inherit; /* 1 */ 122 + } 123 + 124 + /** 125 + Correct the inability to style clickable types in iOS and Safari. 126 + */ 127 + 128 + button, 129 + [type='button'], 130 + [type='reset'], 131 + [type='submit'] { 132 + -webkit-appearance: button; 133 + } 134 + 135 + /** 136 + Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers. 137 + */ 138 + 139 + legend { 140 + padding: 0; 141 + } 142 + 143 + /** 144 + Add the correct vertical alignment in Chrome and Firefox. 145 + */ 146 + 147 + progress { 148 + vertical-align: baseline; 149 + } 150 + 151 + /** 152 + Correct the cursor style of increment and decrement buttons in Safari. 153 + */ 154 + 155 + ::-webkit-inner-spin-button, 156 + ::-webkit-outer-spin-button { 157 + height: auto; 158 + } 159 + 160 + /** 161 + 1. Correct the odd appearance in Chrome and Safari. 162 + 2. Correct the outline style in Safari. 163 + */ 164 + 165 + [type='search'] { 166 + -webkit-appearance: textfield; /* 1 */ 167 + outline-offset: -2px; /* 2 */ 168 + } 169 + 170 + /** 171 + Remove the inner padding in Chrome and Safari on macOS. 172 + */ 173 + 174 + ::-webkit-search-decoration { 175 + -webkit-appearance: none; 176 + } 177 + 178 + /** 179 + 1. Correct the inability to style clickable types in iOS and Safari. 180 + 2. Change font properties to 'inherit' in Safari. 181 + */ 182 + 183 + ::-webkit-file-upload-button { 184 + -webkit-appearance: button; /* 1 */ 185 + font: inherit; /* 2 */ 186 + } 187 + 188 + /* 189 + Interactive 190 + =========== 191 + */ 192 + 193 + /* 194 + Add the correct display in Chrome and Safari. 195 + */ 196 + 197 + summary { 198 + display: list-item; 199 + }
+14
packages/bluesky-post-embed/tsconfig.build.json
··· 1 + { 2 + "extends": "@tsconfig/svelte/tsconfig.json", 3 + "compilerOptions": { 4 + "types": [], 5 + "target": "ESNext", 6 + "useDefineForClassFields": true, 7 + "module": "ESNext", 8 + "resolveJsonModule": true, 9 + "isolatedModules": true, 10 + "moduleDetection": "force", 11 + "noEmit": true, 12 + }, 13 + "include": ["lib"], 14 + }
+3 -1
packages/bluesky-post-embed/tsconfig.json
··· 9 9 "isolatedModules": true, 10 10 "moduleDetection": "force", 11 11 "noEmit": true, 12 + "jsx": "react-jsx", 13 + "jsxImportSource": "preact", 12 14 }, 13 - "include": ["lib"], 15 + "include": ["lib", "src"], 14 16 "references": [{ "path": "./tsconfig.node.json" }], 15 17 }
+2
packages/bluesky-post-embed/vite.config.ts
··· 3 3 import { compile as compileSvelte } from 'svelte/compiler'; 4 4 import { type Plugin, createFilter, defineConfig } from 'vite'; 5 5 6 + import preact from '@preact/preset-vite'; 6 7 import dts from 'vite-plugin-dts'; 7 8 8 9 export default defineConfig({ ··· 29 30 }, 30 31 plugins: [ 31 32 svelte(), 33 + preact(), 32 34 dts({ 33 35 rollupTypes: true, 34 36 beforeWriteFile(filePath, content) {
+6
pnpm-lock.yaml
··· 44 44 specifier: ^2.0.6 45 45 version: 2.0.6 46 46 devDependencies: 47 + '@preact/preset-vite': 48 + specifier: ^2.9.2 49 + version: 2.9.2(@babel/core@7.26.0)(preact@10.25.1)(vite@6.0.3(@types/node@22.10.1)) 47 50 '@tsconfig/svelte': 48 51 specifier: ^5.0.4 49 52 version: 5.0.4 ··· 53 56 internal: 54 57 specifier: workspace:^ 55 58 version: link:../internal 59 + preact: 60 + specifier: ^10.25.1 61 + version: 10.25.1 56 62 svelte: 57 63 specifier: 'catalog:' 58 64 version: 5.8.1(patch_hash=6qynve6ufonlwufsl6x7wujmdu)