Skip to content

Commit

Permalink
Merge pull request #21 from czue/skoch-typescript-component
Browse files Browse the repository at this point in the history
 Add Typescript support, export only components
  • Loading branch information
czue authored Dec 24, 2024
2 parents 3155916 + 6bc702e commit 3e6adb7
Show file tree
Hide file tree
Showing 14 changed files with 1,422 additions and 292 deletions.
221 changes: 124 additions & 97 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,39 @@ Embed Bluesky comments on your website easily.

**[Write up and demo here](https://coryzue.com/writing/bluesky-comments).**

## Installation in a Node.js project as a React component

## Installation via CDNs (easiest)
To use this library in a React project, first install the library:

There are a few ways to set up the library on your website.
```bash
npm install bluesky-comments
```

Then import it (and the CSS) in your React app/page/component:

```tsx
import 'bluesky-comments/bluesky-comments.css'
import { BlueskyComments } from 'bluesky-comments';
```

And use it in any React component like this:

```javascript
function App() {
return (
<>
<div>Comments Will Display Below</div>
<BlueskyComments author="you.bsky.social" />
</>
)
}
```

See the [Usage](#usage) section below for details on the options and API.

## Installation on any website via CDN

To add a comments section to any website, follow these steps

### 1. Add an element to your page where you want the comments to show up

Expand All @@ -17,9 +46,8 @@ Add something like this to your site:
<div id="bluesky-comments"></div>
```

You can use whatever id you want, but it has to match the value used in `BlueskyComments.init`
in the later steps.

You can use whatever id you want, but it has to match the container id used in the `getElementById` call
in the usage step.

### 2. Add the CSS files

Expand All @@ -38,64 +66,66 @@ Add the following importmap to your page anywhere before you use the library:
{
"imports": {
"react": "https://esm.sh/react@18",
"react-dom": "https://esm.sh/react-dom@18"
"react-dom/client": "https://esm.sh/react-dom@18/client"
}
}
</script>
```

### 4. Import and use the library and any other functions you need in an ES module script:
### 4. Import the library and instantiate the component with React in an ES module script:

```html
<script type="module">
import { BlueskyComments } from 'https://unpkg.com/[email protected]/dist/bluesky-comments.es.js';
document.addEventListener('DOMContentLoaded', function() {
const author = 'you.bsky.social';
if (author) {
BlueskyComments.init('bluesky-comments', {author});
}
});
import { createElement } from 'react';
import { createRoot } from 'react-dom/client';
import { BlueskyComments } from 'https://unpkg.com/bluesky-comments@<VERSION>/dist/bluesky-comments.es.js';
const author = 'you.bsky.social';
const container = document.getElementById('bluesky-comments');
const root = createRoot(container);
root.render(
createElement(BlueskyComments, {
"author": author,
})
);
</script>
```

See the [Usage](#usage) section for details on the API.
See the [Usage](#usage) section below for details on the options and API.

### (Deprecated) Installation using `<script>` tags and UMD
## Usage

Previous versions of this library recommended installing like this:
Examples in this section use the React JSX syntax. If you're installing on a project that doens't
use JSX or any build tooling (i.e. a regular website), you can instead use the `createElement`
function and pass the react options in.

```html
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/bluesky-comments@<VERSION>/dist/bluesky-comments.umd.js"></script>
```
For example, the following two examples are equivalent:

And initializing the comments in a standard `<script>` tag. Both of these approaches work:
React JSX:

```html
<script>
document.addEventListener('DOMContentLoaded', function() {
const uri = 'https://bsky.social/coryzue.com/posts/3jxgux';
if (uri) {
// New API
BlueskyComments.init('bluesky-comments', {uri});
// Legacy API (still supported but deprecated)
initBlueskyComments('bluesky-comments', {uri});
}
});
</script>
```javascript
<BlueskyComments
author="you.bsky.social"
uri="https://bsky.app/profile/coryzue.com/post/3lbrko5zsgk24"
/>
```

This option is now deprecated with the introduction of ES modules and will be removed in a future version.
Equivalent without JSX:

## Usage
```javascript
root.render(
createElement(BlueskyComments, {
author: "you.bsky.social",
uri: "https://bsky.app/profile/coryzue.com/post/3lbrko5zsgk24",
})
);
```

### Initializing the library based on the author


```javascript
const author = 'you.bsky.social';
BlueskyComments.init('bluesky-comments', {author});
<BlueskyComments author="you.bsky.social" />
```

If you use this mode, the comments section will use the most popular post by that author that links
Expand All @@ -104,28 +134,28 @@ to the current page.
### Initializing the library based on a post URL

```javascript
const uri = 'https://bsky.social/coryzue.com/posts/3jxgux';
BlueskyComments.init('bluesky-comments', {uri});
<BlueskyComments uri="https://bsky.app/profile/coryzue.com/post/3lbrko5zsgk24" />
```

If you use this mode, the comments section will use the exact post you specify.
This usually means you have to add the comments section only *after* you've linked to the article.


### (Advanced) Providing custom default empty states

You can pass in a `onEmpty` callback to handle the case where there are no comments rendered
(for example, if no post matching the URL is found or there aren't any comments on it yet):

```javascript
BlueskyComments.init('bluesky-comments', {
uri,
author,
onEmpty: (details) => {
console.error('Failed to load comments:', details);
document.getElementById('bluesky-comments').innerHTML =
'No comments on this post yet. Details: ' + details.message;
},
<BlueskyComments
uri="https://bsky.app/profile/coryzue.com/post/3lbrko5zsgk24"
author="you.bsky.social"
onEmpty={
(details) => {
console.error('Failed to load comments:', details);
document.getElementById('bluesky-comments').innerHTML =
'No comments on this post yet. Details: ' + details.message;
}
}
});
```

Expand All @@ -135,26 +165,28 @@ You can pass in an array of filters to the `commentFilters` option. These are fu

A few default filters utilities are provided:

- `BlueskyComments.Filters.NoPins`: Hide comments that are just "📌"
- `BlueskyComments.Filters.NoLikes`: Hide comments with no likes
- `BlueskyFilters.NoPins`: Hide comments that are just "📌"
- `BlueskyFilters.NoLikes`: Hide comments with no likes

You can also use the following utilities to create your own filters:

- `BlueskyComments.Filters.MinLikeCountFilter`: Hide comments with less than a given number of likes
- `BlueskyComments.Filters.MinCharacterCountFilter`: Hide comments with less than a given number of characters
- `BlueskyComments.Filters.TextContainsFilter`: Hide comments that contain specific text (case insensitive)
- `BlueskyComments.Filters.ExactMatchFilter`: Hide comments that match text exactly (case insensitive)
- `BlueskyFilters.MinLikeCountFilter`: Hide comments with less than a given number of likes
- `BlueskyFilters.MinCharacterCountFilter`: Hide comments with less than a given number of characters
- `BlueskyFilters.TextContainsFilter`: Hide comments that contain specific text (case insensitive)
- `BlueskyFilters.ExactMatchFilter`: Hide comments that match text exactly (case insensitive)

Pass filters using the `commentFilters` option:

```javascript
BlueskyComments.init('bluesky-comments', {
import {BlueskyComments, BlueskyFilters} from 'bluesky-comments';

<BlueskyComments
// other options here
commentFilters: [
BlueskyComments.Filters.NoPins, // Hide pinned comments
BlueskyComments.Filters.MinCharacterCountFilter(10), // Hide comments with less than 10 characters
],
});
commentFilters={[
BlueskyFilters.NoPins, // Hide pinned comments
BlueskyFilters.MinCharacterCountFilter(10), // Hide comments with less than 10 characters
]}
/>
```

You can also write your own filters, by returning `true` for comments you want to hide:
Expand All @@ -163,49 +195,41 @@ You can also write your own filters, by returning `true` for comments you want t
const NoTwitterLinksFilter = (comment) => {
return (comment.post.record.text.includes('https://x.com/') || comment.post.record.text.includes('https://twitter.com/'));
}
BlueskyComments.init('bluesky-comments', {
<BlueskyComments
// other options here
commentFilters: [
commentFilters={[
NoTwitterLinksFilter,
]
});
/>
```
## Usage with npm / yarn in a native JavaScript project
### (Removed) Legacy installation using `<script>` tags and UMD
Install the package:
Previous versions of this library recommended installing like this:
```bash
npm install bluesky-comments
```html
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/bluesky-comments@<VERSION>/dist/bluesky-comments.umd.js"></script>
```
Then you can use the library in your projects by importing the CSS and components:

```javascript
import 'bluesky-comments/bluesky-comments.css'
import { CommentSection } from "bluesky-comments";
```
And initializing the comments in a standard `<script>` tag with an `init` function:
And using them in a React component like this:
```html
<script>
document.addEventListener('DOMContentLoaded', function() {
const uri = 'https://bsky.social/coryzue.com/posts/3jxgux';
if (uri) {
BlueskyComments.init('bluesky-comments', {uri});

```javascript
function App() {
return (
<>
<div>Comments Will Display Below</div>
<CommentSection
author="coryzue.com"
uri=""
onEmpty={() => <div>No comments yet</div>}
commentFilters={[]} />
</div>
</>
)
}
// Legacy API (still supported but deprecated)
initBlueskyComments('bluesky-comments', {uri});
}
});
</script>
```

I don't publish a lot of JavaScript packages, but I think this should work!
This option has been removed in version 0.9.0 and new projects should use the ES module syntax above.
## Development
Expand All @@ -214,9 +238,12 @@ To develop on this package, you can run:
```
npm install
npm run watch
npm run dev
```
This will watch for changes and copy the built files to the `dist` directory.
From there you can reference the files in your own project and any updates you make
should show up instantly.
This will set up a local development server with a simple page showing comments,
and watch for changes.
You can also run `npm run build` (build once) or `npm run watch` (watch for changes)
to copy the built files to the `dist` directory.
From there you can reference the files in your own projects.
19 changes: 19 additions & 0 deletions dev/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Bluesky Comments Component Test</title>
<style>
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue',
sans-serif;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="/index.tsx"></script>
</body>
</html>
21 changes: 21 additions & 0 deletions dev/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { createRoot } from 'react-dom/client';

import { BlueskyComments, BlueskyFilters } from '../src/main';

const App = () => (
<div>
<h1>Testing Bluesky Comments Component</h1>
<BlueskyComments
uri="https://bsky.app/profile/coryzue.com/post/3lbrko5zsgk24"
commentFilters={[
BlueskyFilters.NoPins, // Hide pinned comments
BlueskyFilters.MinCharacterCountFilter(10), // Hide comments with less than 10 characters
]}
/>
</div>
);

const container = document.getElementById('app');
const root = createRoot(container!);
root.render(<App />);
Loading

0 comments on commit 3e6adb7

Please sign in to comment.