Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Typescript support, export only components #21

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
213 changes: 107 additions & 106 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,42 @@ Embed Bluesky comments on your website easily.

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

## React Installation

## 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'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to import the CSS, the component is handling that behind the scenes.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found (in my test vite app at least) that I still had to do this. If that's not expected, any idea under what circumstances that might be true?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If using in a React app this shouldn't be needed. Take a look at the index.tsx file in /dev -- no need to import the css since the component itself is importing.

If you are using this in the non JSX way, then yes, you will need to import the CSS.

Copy link
Owner Author

@czue czue Dec 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird, maybe an issue with my dev setup then? What I did:

  1. Run npm run build
  2. In a separate project, add this to package.json:
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "bluesky-comments": "file:../../bluesky-comments"
  },
  1. Import and run like this:
// import 'bluesky-comments/bluesky-comments.css'
import './App.css'
import { BlueskyComments } from "bluesky-comments";


function App() {
return (
  <>
      <BlueskyComments
         uri="https://bsky.app/profile/coryzue.com/post/3lbrko5zsgk24"
          />

  </>
)
}

export default App

If I leave that css import commented out the styles don't work, but if I add it they do.

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="coryzue.com"
uri=""
onEmpty={() => <div>No comments yet</div>}
commentFilters={[]} />
</div>
czue marked this conversation as resolved.
Show resolved Hide resolved
</>
)
}
```

## Non-React Installation via CDN
czue marked this conversation as resolved.
Show resolved Hide resolved

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 +49,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 +69,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": "https://esm.sh/react-dom@18",
czue marked this conversation as resolved.
Show resolved Hide resolved
"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,
}
});
);
czue marked this conversation as resolved.
Show resolved Hide resolved
</script>
```

See the [Usage](#usage) section for details on the API.
See the [Usage](#usage) section below for details on the 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 using a non-React project, 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.
Non-React:
czue marked this conversation as resolved.
Show resolved Hide resolved

## 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 +137,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 +168,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,60 +198,26 @@ 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

Install the package:

```bash
npm install bluesky-comments
```

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 using them in a React component like this:

```javascript
function App() {
return (
<>
<div>Comments Will Display Below</div>
<CommentSection
author="coryzue.com"
uri=""
onEmpty={() => <div>No comments yet</div>}
commentFilters={[]} />
</div>
</>
)
}
/>
```


I don't publish a lot of JavaScript packages, but I think this should work!


## Development

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