@threenine/nuxstr-comments 1.5.3 → 1.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -3
- package/dist/module.json +1 -1
- package/dist/runtime/components/CommentView.vue +18 -13
- package/dist/runtime/components/NuxstrComments.vue +15 -11
- package/dist/runtime/components/PostComment.vue +29 -22
- package/dist/runtime/components/PostReply.vue +22 -15
- package/dist/runtime/components/ReplyView.vue +5 -3
- package/dist/runtime/components/ScaffoldComment.vue +7 -5
- package/dist/runtime/composables/useNuxstr.js +7 -3
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -23,12 +23,37 @@ Enable [nostr protocol](https://nostr.com/) based comment system on your Nuxt 4
|
|
|
23
23
|
## Features
|
|
24
24
|
|
|
25
25
|
- Nostr-powered comments for Nuxt Content blog posts
|
|
26
|
-
- NIP-07 login prompt if user is not authenticated
|
|
27
|
-
-
|
|
26
|
+
- [NIP-07](https://github.com/nostr-protocol/nips/blob/master/07.md) Browser Extension login prompt if user is not authenticated
|
|
27
|
+
- [NIP-22](https://github.com/nostr-protocol/nips/blob/master/22.md) Plain Text Content - (no HTML, Markdown, or other formatting)
|
|
28
28
|
- Configurable relay list and tagging strategy
|
|
29
|
+
- Comments are published as kind:1111 as Website Url
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"kind": 1111,
|
|
33
|
+
"content": "Nice article!",
|
|
34
|
+
"tags": [
|
|
35
|
+
// referencing the root url
|
|
36
|
+
["I", "https://abc.com/articles/1"],
|
|
37
|
+
// the root "kind": for an url
|
|
38
|
+
["K", "web"],
|
|
39
|
+
|
|
40
|
+
// the parent reference (same as root for top-level comments)
|
|
41
|
+
["i", "https://abc.com/articles/1"],
|
|
42
|
+
// the parent "kind": for an url
|
|
43
|
+
["k", "web"]
|
|
44
|
+
]
|
|
45
|
+
// other fields
|
|
46
|
+
}
|
|
47
|
+
```
|
|
29
48
|
|
|
30
|
-
## Quick Setup
|
|
31
49
|
|
|
50
|
+
> [!WARNING]
|
|
51
|
+
> NuxstrComments [NIP-22] MUST NOT be used to reply to kind 1 notes.
|
|
52
|
+
> NIP-10 should instead be followed.
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## Quick Setup
|
|
56
|
+
|
|
32
57
|
Install the module to your Nuxt application with one command:
|
|
33
58
|
|
|
34
59
|
```bash
|
package/dist/module.json
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
|
|
3
|
-
import { marked } from "marked";
|
|
4
|
-
const props = defineProps({
|
|
2
|
+
defineProps({
|
|
5
3
|
content: { type: String, required: true },
|
|
6
4
|
id: { type: String, required: true }
|
|
7
5
|
});
|
|
8
|
-
async function renderMarkdown(md) {
|
|
9
|
-
return marked.parse(md);
|
|
10
|
-
}
|
|
11
|
-
onMounted(async () => {
|
|
12
|
-
const targetEl = document.getElementById("comment-content");
|
|
13
|
-
if (!targetEl) return;
|
|
14
|
-
targetEl.innerHTML = await renderMarkdown(props.content);
|
|
15
|
-
});
|
|
16
6
|
</script>
|
|
17
7
|
|
|
18
8
|
<template>
|
|
19
9
|
<div class="mt-2 mb-2">
|
|
20
|
-
<
|
|
21
|
-
|
|
10
|
+
<UCard
|
|
11
|
+
variant="subtle"
|
|
12
|
+
class="mt-auto"
|
|
13
|
+
:ui="{ header: 'flex items-center gap-1.5 text-dimmed' }"
|
|
14
|
+
>
|
|
15
|
+
<UTextarea
|
|
16
|
+
:model-value="content"
|
|
17
|
+
color="neutral"
|
|
18
|
+
variant="none"
|
|
19
|
+
autoresize
|
|
20
|
+
readonly
|
|
21
|
+
:rows="4"
|
|
22
|
+
class="w-full"
|
|
23
|
+
:ui="{ base: 'p-0 resize-none' }"
|
|
24
|
+
/>
|
|
25
|
+
</ucard>
|
|
26
|
+
<ReplyButton :content-id="id" />
|
|
22
27
|
</div>
|
|
23
28
|
</template>
|
|
@@ -23,14 +23,16 @@ onMounted(() => {
|
|
|
23
23
|
v-if="!isLoggedIn"
|
|
24
24
|
class="text-sm text-muted-foreground"
|
|
25
25
|
>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
<u-tooltip text="Sign in with NIP07 browser extension like Alby or nos2fx to comment">
|
|
27
|
+
<UButton
|
|
28
|
+
color="primary"
|
|
29
|
+
variant="solid"
|
|
30
|
+
leading-icon="game-icons:ostrich"
|
|
31
|
+
@click="login"
|
|
32
|
+
>
|
|
33
|
+
Sign in
|
|
34
|
+
</UButton>
|
|
35
|
+
</u-tooltip>
|
|
34
36
|
</div>
|
|
35
37
|
</div>
|
|
36
38
|
<ClientOnly>
|
|
@@ -56,11 +58,13 @@ onMounted(() => {
|
|
|
56
58
|
<div v-if="comments.length === 0">
|
|
57
59
|
<scaffold-comment />
|
|
58
60
|
</div>
|
|
59
|
-
<
|
|
61
|
+
<UCard
|
|
60
62
|
v-for="c in comments"
|
|
61
63
|
v-else
|
|
62
64
|
:key="c.id"
|
|
63
|
-
|
|
65
|
+
variant="subtle"
|
|
66
|
+
class="mt-auto"
|
|
67
|
+
:ui="{ header: 'flex items-center gap-1.5 text-dimmed' }"
|
|
64
68
|
>
|
|
65
69
|
<comment-author
|
|
66
70
|
:profile="c.profile"
|
|
@@ -70,7 +74,7 @@ onMounted(() => {
|
|
|
70
74
|
:id="c.id"
|
|
71
75
|
:content="c.content"
|
|
72
76
|
/>
|
|
73
|
-
</
|
|
77
|
+
</UCard>
|
|
74
78
|
|
|
75
79
|
<div
|
|
76
80
|
v-if="isLoggedIn"
|
|
@@ -23,27 +23,34 @@ async function handlePost() {
|
|
|
23
23
|
</script>
|
|
24
24
|
|
|
25
25
|
<template>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
26
|
+
<UCard
|
|
27
|
+
variant="subtle"
|
|
28
|
+
class="mt-auto"
|
|
29
|
+
:ui="{ header: 'flex items-center gap-1.5 text-dimmed' }"
|
|
30
|
+
>
|
|
31
|
+
<form @submit.prevent="handlePost">
|
|
32
|
+
<UTextarea
|
|
33
|
+
v-model="comment"
|
|
34
|
+
color="neutral"
|
|
35
|
+
variant="none"
|
|
36
|
+
required
|
|
37
|
+
autoresize
|
|
38
|
+
placeholder="Write your comment..."
|
|
39
|
+
:rows="4"
|
|
40
|
+
class="w-full"
|
|
41
|
+
:ui="{ base: 'p-0 resize-none' }"
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
<div class="flex items-center justify-end">
|
|
45
|
+
<div class="flex items-center justify-end gap-2">
|
|
46
|
+
<UButton
|
|
47
|
+
type="submit"
|
|
48
|
+
color="primary"
|
|
49
|
+
label="Comment"
|
|
50
|
+
icon="i-lucide-send"
|
|
51
|
+
/>
|
|
52
|
+
</div>
|
|
46
53
|
</div>
|
|
47
|
-
</
|
|
48
|
-
</
|
|
54
|
+
</form>
|
|
55
|
+
</UCard>
|
|
49
56
|
</template>
|
|
@@ -23,25 +23,32 @@ async function postReply(comment) {
|
|
|
23
23
|
</script>
|
|
24
24
|
|
|
25
25
|
<template>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
<UCard
|
|
27
|
+
variant="subtle"
|
|
28
|
+
class="mt-auto"
|
|
29
|
+
:ui="{ header: 'flex items-center gap-1.5 text-dimmed' }"
|
|
30
|
+
>
|
|
31
|
+
<UTextarea
|
|
32
|
+
v-model="content"
|
|
33
|
+
color="neutral"
|
|
34
|
+
variant="none"
|
|
35
|
+
required
|
|
36
|
+
autoresize
|
|
37
|
+
placeholder="Write your comment..."
|
|
38
|
+
:rows="4"
|
|
39
|
+
class="w-full"
|
|
40
|
+
:ui="{ base: 'p-0 resize-none' }"
|
|
41
|
+
/>
|
|
42
|
+
<div class="flex items-center justify-end">
|
|
43
|
+
<div class="flex items-center justify-end gap-2">
|
|
37
44
|
<UButton
|
|
38
|
-
|
|
39
|
-
size="xl"
|
|
45
|
+
type="submit"
|
|
40
46
|
color="primary"
|
|
41
|
-
|
|
47
|
+
label="Reply"
|
|
48
|
+
icon="i-lucide-send"
|
|
42
49
|
@click="postReply(content)"
|
|
43
50
|
/>
|
|
44
51
|
</div>
|
|
45
52
|
</div>
|
|
46
|
-
</
|
|
53
|
+
</UCard>
|
|
47
54
|
</template>
|
|
@@ -6,10 +6,12 @@ const props = defineProps({
|
|
|
6
6
|
|
|
7
7
|
<template>
|
|
8
8
|
<div class="px-10 py-4">
|
|
9
|
-
<
|
|
9
|
+
<UCard
|
|
10
10
|
v-for="reply in props.replies"
|
|
11
11
|
:key="reply.id"
|
|
12
|
-
|
|
12
|
+
variant="subtle"
|
|
13
|
+
class="mt-auto mb-3"
|
|
14
|
+
:ui="{ header: 'flex items-center gap-1.5 text-dimmed' }"
|
|
13
15
|
>
|
|
14
16
|
<div>
|
|
15
17
|
<comment-author
|
|
@@ -20,6 +22,6 @@ const props = defineProps({
|
|
|
20
22
|
{{ reply.content }}
|
|
21
23
|
</p>
|
|
22
24
|
</div>
|
|
23
|
-
</
|
|
25
|
+
</UCard>
|
|
24
26
|
</div>
|
|
25
27
|
</template>
|
|
@@ -7,14 +7,16 @@
|
|
|
7
7
|
<p class="text-xs">
|
|
8
8
|
No comments available
|
|
9
9
|
</p>
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
<UCard
|
|
11
|
+
variant="subtle"
|
|
12
|
+
class="mt-auto"
|
|
13
|
+
:ui="{ header: 'flex items-center gap-1.5 text-dimmed' }"
|
|
14
|
+
>
|
|
15
|
+
<span><USkeleton class="h-4 w-5 rounded-full" /></span><USkeleton class="h-4" />
|
|
14
16
|
<div class="mt-3">
|
|
15
17
|
<USkeleton class="h-4" />
|
|
16
18
|
</div>
|
|
17
|
-
</
|
|
19
|
+
</UCard>
|
|
18
20
|
</div>
|
|
19
21
|
</template>
|
|
20
22
|
|
|
@@ -77,9 +77,13 @@ function useNuxstr() {
|
|
|
77
77
|
async function fetchProfile(pubkey) {
|
|
78
78
|
try {
|
|
79
79
|
const ndk = initializeNDK();
|
|
80
|
-
const user = ndk.
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
const user = await ndk.fetchUser(pubkey);
|
|
81
|
+
if (user !== null) {
|
|
82
|
+
const profile = await user?.fetchProfile();
|
|
83
|
+
if (!profile) return void 0;
|
|
84
|
+
return mapProfile(profile);
|
|
85
|
+
}
|
|
86
|
+
return void 0;
|
|
83
87
|
} catch (error) {
|
|
84
88
|
console.error("Failed to fetch profile for", pubkey, error);
|
|
85
89
|
return void 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threenine/nuxstr-comments",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.4",
|
|
4
4
|
"description": "Nuxt module to enable Nostr Comments on Nuxt 4 based websites",
|
|
5
5
|
"repository": "threenine/nuxstr-comments",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,8 +24,7 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@nostr-dev-kit/ndk": "^2.18.1",
|
|
27
|
-
"defu": "^6.1.4"
|
|
28
|
-
"marked": "^16.2.1"
|
|
27
|
+
"defu": "^6.1.4"
|
|
29
28
|
},
|
|
30
29
|
"devDependencies": {
|
|
31
30
|
"@nuxt/devtools": "^2.6.2",
|
|
@@ -36,7 +35,7 @@
|
|
|
36
35
|
"@nuxt/schema": "^4.2.1",
|
|
37
36
|
"@nuxt/scripts": "0.11.10",
|
|
38
37
|
"@nuxt/test-utils": "^3.19.2",
|
|
39
|
-
"@nuxt/ui": "^4.
|
|
38
|
+
"@nuxt/ui": "^4.3.0",
|
|
40
39
|
"@testing-library/jest-dom": "^6.8.0",
|
|
41
40
|
"@testing-library/vue": "^8.1.0",
|
|
42
41
|
"@types/node": "latest",
|