-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
934ca3c
commit bdaeced
Showing
10 changed files
with
3,525 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
"astro-loader-bluesky-posts": major | ||
--- | ||
|
||
Support loading Bluesky posts using [AT-URI](https://atproto.com/specs/at-uri-scheme) | ||
- Customizable HTML generation for posts (e.g., render posts with `<Content />` using `render(entry)`) | ||
- Configurable thread loading and recursive filtering of the post author's replies |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# astro-loader-bluesky-posts | ||
|
||
[![version][version-badge]][version-link] | ||
[![jsDocs.io][jsdocs-src]][jsdocs-href] | ||
[![npm downloads][npm-downloads-src]][npm-downloads-href] | ||
|
||
This package provides a Bluesky posts loader for Astro, utilizing [AT-URI](https://atproto.com/specs/at-uri-scheme) to fetch posts for use in Astro projects. Features include customizable HTML rendering, optional threaded loading, and targeted fetching of author-specific replies. | ||
|
||
## Installation | ||
|
||
```sh | ||
npm install -D astro-loader-bluesky-posts | ||
``` | ||
|
||
## Usage | ||
|
||
To use the Astro loader, ensure Astro version `^4.14.0 || ^5.0.0`. For `^4.14.0`, enable the [experimental content layer](https://v4.docs.astro.build/en/reference/configuration-reference/#experimentalcontentlayer) in `astro.config.ts`: | ||
|
||
```ts | ||
export default defineConfig({ | ||
experimental: { | ||
contentLayer: true, | ||
}, | ||
}) | ||
``` | ||
|
||
In `src/content/config.ts` (for `^4.14.0`) or `src/content.config.ts` (for `^5.0.0`), import and configure the loader to define a new content collection: | ||
|
||
```ts | ||
import { defineCollection } from "astro:content" | ||
import { BlueskyPostsLoader } from "astro-loader-bluesky-posts" | ||
|
||
const posts = defineCollection({ | ||
loader: BlueskyPostsLoader({ | ||
uris: ['at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3lax5zxh7bc2p'], | ||
// Check the configuration below | ||
}), | ||
}) | ||
|
||
export const collections = { posts } | ||
``` | ||
|
||
[Query the content collection](https://docs.astro.build/en/guides/content-collections/#querying-collections) like any other Astro content collection to render the loaded posts: | ||
|
||
```astro | ||
--- | ||
import { getCollection } from "astro:content" | ||
const posts = await getCollection("posts") | ||
// Check the entries' Zod schema for available fields below | ||
--- | ||
{ | ||
posts.map(async (post) => { | ||
const { Content } = await render(post) | ||
return ( | ||
<section> | ||
<Content /> | ||
<p>{post.data.indexedAt}</p> | ||
</section> | ||
) | ||
}) | ||
} | ||
``` | ||
|
||
To update the data, trigger a site rebuild, as [the loader fetches data only at build time](https://docs.astro.build/en/reference/content-loader-reference/#object-loaders). | ||
|
||
## Configuration | ||
|
||
This loader retrieves posts via the Bluesky API [`GET /xrpc/app.bsky.feed.getPosts`](https://docs.bsky.app/docs/api/app-bsky-feed-get-posts) and [`GET /xrpc/app.bsky.feed.getPostThread`](https://docs.bsky.app/docs/api/app-bsky-feed-get-post-thread). Options include: | ||
|
||
|
||
| Option (* required) | Type (default) | Description | | ||
| ------------------------ | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| `uris`* | `string[]` | List of post [AT-URIs](https://atproto.com/specs/at-uri-scheme). | | ||
| `linkTextType` | `'domain-path' \| 'display-url'` (default: `'display-url'`) | The type of text to display for links when generating renderable HTML:<br>`'domain-path'`: Displays the link's domain and path.<br>`'display-url'`: Uses the link text as shown in the tweet. | | ||
| `newlineHandling` | `'none' \| 'break' \| 'paragraph'` (default: `'none'`) | The way for processing `\n` when generating renderable HTML:<br>`'none'`: Keep as is.<br>`'break'`: Replace `\n` with `<br>`.<br>`'paragraph'`: Wrap paragraphs with `<p>` while removing standalone `\n`. | | ||
| `fetchThread` | `boolean` (default: `false`) | Whether to fetch the post's thread including replies and parents. | | ||
| `threadDepth` | number (default: `1`) | The depth of the descendant post tree to fetch if fetching the thread. Specifies how many levels of reply depth should be included. | | ||
| `threadParentHeight` | number (default: `1`) | The height of the ancestor post tree to fetch if fetching the thread. Specifies how many levels of parent posts should be included. | | ||
| `fetchOnlyAuthorReplies` | `boolean` (default: `false`) | Whether to include only the replies made by the post author at the specified `threadDepth` if fetching the thread. If `true`, filters replies to include only those authored by the and flatten these replies into a single-level array. | | ||
|
||
## Schema | ||
|
||
See the [source code](https://github.com/lin-stephanie/astro-loaders/blob/main/packages/astro-loader-bluesky-posts/src/schema.ts) for the Zod schema of loaded entries. Astro automatically applies this schema to generate TypeScript interfaces, enabling autocompletion and type-checking for collection queries. | ||
|
||
To [customize the schema](https://docs.astro.build/en/guides/content-collections/#defining-the-collection-schema), ensure compatibility with the loader's built-in Zod schema to prevent errors. For additional fields, consider opening an issue. | ||
|
||
## Changelog | ||
|
||
See [CHANGELOG.md](https://github.com/lin-stephanie/astro-loaders/blob/main/packages/astro-loader-bluesky-posts/CHANGELOG.md) for the change history of this loader. | ||
|
||
## Contribution | ||
|
||
If you see any errors or room for improvement, feel free to open an [issues](https://github.com/lin-stephanie/astro-loaders/issues) or [pull request](https://github.com/lin-stephanie/astro-loaders/pulls) . Thank you in advance for contributing! ❤️ | ||
|
||
<!-- Badges --> | ||
|
||
[version-badge]: https://img.shields.io/npm/v/astro-loader-bluesky-posts?label=release&style=flat&colorA=080f12&colorB=f87171 | ||
[version-link]: https://www.npmjs.com/package/astro-loader-bluesky-posts | ||
[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=f87171 | ||
[jsdocs-href]: https://www.jsdocs.io/package/astro-loader-bluesky-posts | ||
[npm-downloads-src]: https://img.shields.io/npm/dm/astro-loader-bluesky-posts?style=flat&colorA=080f12&colorB=f87171 | ||
[npm-downloads-href]: https://npmjs.com/package/astro-loader-bluesky-posts | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
{ | ||
"name": "astro-loader-bluesky-posts", | ||
"version": "0.0.0", | ||
"description": "Astro loader for loading Bluesky posts and threads using AT-URI.", | ||
"author": "Stephanie Lin <[email protected]>", | ||
"license": "MIT", | ||
"keywords": [ | ||
"withastro", | ||
"astro-loader", | ||
"bluesky", | ||
"posts", | ||
"post", | ||
"thread" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/lin-stephanie/astro-loaders.git", | ||
"directory": "packages/astro-loader-bluesky-posts" | ||
}, | ||
"homepage": "https://github.com/lin-stephanie/astro-loaders/blob/main/packages/astro-loader-bluesky-posts/", | ||
"bugs": "https://github.com/lin-stephanie/astro-loaders/issues", | ||
"type": "module", | ||
"files": [ | ||
"dist" | ||
], | ||
"main": "dist/index.js", | ||
"module": "dist/index.js", | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.js" | ||
} | ||
}, | ||
"types": "./dist/index.d.ts", | ||
"scripts": { | ||
"dev": "tsup src/index.ts --format esm --dts --watch", | ||
"build": "tsup src/index.ts --format esm --dts --clean --treeshake", | ||
"check": "publint && attw $(pnpm pack) --ignore-rules=cjs-resolves-to-esm", | ||
"prepublishOnly": "pnpm build" | ||
}, | ||
"peerDependencies": { | ||
"astro": ">=4.14.0 <6.0.0" | ||
}, | ||
"dependencies": { | ||
"@atproto/api": "^0.13.20" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { z } from 'astro/zod' | ||
|
||
const defaultConfig = { | ||
urlTextType: 'display-url' as const, | ||
newlineHandling: 'none' as const, | ||
fetchThread: false, | ||
threadDepth: 1, | ||
threadParentHeight: 1, | ||
fetchOnlyAuthorReplies: false, | ||
} | ||
|
||
export const BlueskyPostsLoaderConfigSchema = z.object({ | ||
/** | ||
* List of post {@link https://atproto.com/specs/at-uri-scheme AT-URIs} | ||
* to return hydrated views for. | ||
*/ | ||
uris: z.array(z.string()), | ||
|
||
/** | ||
* The type of text to display for links when generating renderable HTML: | ||
* - `'domain-path'`: Displays the link's domain and path. | ||
* - `'display-url'`: Uses the link text as shown in the tweet. | ||
* | ||
* @default 'display-url' | ||
*/ | ||
linkTextType: z | ||
.enum(['domain-path', 'display-url']) | ||
.default(defaultConfig.urlTextType), | ||
|
||
/** | ||
* The way for processing `\n` when generating renderable HTML: | ||
* - `'none'`: Keep as is. | ||
* - `'break'`: Replace `\n` with `<br>`. | ||
* - `'paragraph'`: Wrap paragraphs with `<p>` while removing standalone `\n`. | ||
* | ||
* @default 'none' | ||
*/ | ||
newlineHandling: z | ||
.enum(['none', 'break', 'paragraph']) | ||
.default(defaultConfig.newlineHandling), | ||
|
||
/** | ||
* Whether to fetch the post's thread including replies and parents. | ||
* | ||
* @default false | ||
*/ | ||
fetchThread: z.boolean().default(defaultConfig.fetchThread), | ||
|
||
/** | ||
* The depth of the descendant post tree to fetch if fetching the thread. | ||
* Specifies how many levels of reply depth should be included. | ||
* | ||
* @default 1 | ||
*/ | ||
threadDepth: z.number().min(0).max(1000).default(defaultConfig.threadDepth), | ||
|
||
/** | ||
* The height of the ancestor post tree to fetch if fetching the thread. | ||
* Specifies how many levels of parent posts should be included. | ||
* | ||
* @default 1 | ||
*/ | ||
threadParentHeight: z | ||
.number() | ||
.min(0) | ||
.max(1000) | ||
.default(defaultConfig.threadParentHeight), | ||
|
||
/** | ||
* Whether to include only the replies made by the post author | ||
* at the specified `threadDepth` if fetching the thread. | ||
* | ||
* If `true`, filters replies to include only those authored by the specified DID at any depth | ||
* and flatten these replies into a single-level array. | ||
* The specified `threadParentHeight` will be ignored, and the `parent` field will not be returned. | ||
* | ||
* By default, it fetches all replies without filtering by author and maintains the nested structure. | ||
* | ||
* @default false | ||
*/ | ||
fetchOnlyAuthorReplies: z | ||
.boolean() | ||
.default(defaultConfig.fetchOnlyAuthorReplies), | ||
}) | ||
|
||
export type BlueskyPostsLoaderUserConfig = z.input< | ||
typeof BlueskyPostsLoaderConfigSchema | ||
> |
Oops, something went wrong.