@nsite/stealthis 0.2.0 → 0.4.0
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 +64 -0
- package/package.json +1 -1
- package/src/widget.ts +14 -10
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# @nsite/stealthis
|
|
2
|
+
|
|
3
|
+
A drop-in web component that adds a "Borrow this" button to any nsite. Visitors can deploy a copy of the current page to their own nostr identity with one click.
|
|
4
|
+
|
|
5
|
+
## How it works
|
|
6
|
+
|
|
7
|
+
When loaded on an nsite, `<nsite-deploy>` detects the site owner's pubkey from the subdomain, fetches the site manifest from nostr relays, and lets authenticated visitors publish a copy under their own npub. Each deployment appends a `muse` tag to the manifest, creating a paper trail of who was inspired by the site.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import '@nsite/stealthis';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The widget auto-injects a fixed-position button in the bottom-right corner.
|
|
16
|
+
|
|
17
|
+
## Manual placement
|
|
18
|
+
|
|
19
|
+
If you want to control where the button appears, add the element yourself (the auto-inject will skip if one already exists):
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<nsite-deploy button-text="Cop this joint" stat-text="%s npubs copped this"></nsite-deploy>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Attributes
|
|
26
|
+
|
|
27
|
+
| Attribute | Default | Description |
|
|
28
|
+
|-----------|---------|-------------|
|
|
29
|
+
| `button-text` | `"Borrow this nsite"` | Button text |
|
|
30
|
+
| `stat-text` | `"%s npubs borrowed this nsite"` | Paper trail summary. `%s` is replaced with the count. |
|
|
31
|
+
| `no-trail` | _(absent)_ | Boolean attribute. When present, hides the paper trail. |
|
|
32
|
+
|
|
33
|
+
The button's `trigger` part is exposed via `::part(trigger)` for CSS customization.
|
|
34
|
+
|
|
35
|
+
## Authentication
|
|
36
|
+
|
|
37
|
+
The widget supports three sign-in methods:
|
|
38
|
+
|
|
39
|
+
- **NIP-07** - Browser extension (e.g. nos2x, Alby)
|
|
40
|
+
- **NIP-46 Bunker URI** - Paste a `bunker://` connection string
|
|
41
|
+
- **NIP-46 QR / Nostr Connect** - Scan a QR code with a signer app
|
|
42
|
+
|
|
43
|
+
## Deploy options
|
|
44
|
+
|
|
45
|
+
- **Root site** - Publishes as the visitor's primary nsite (kind `15128`)
|
|
46
|
+
- **Named site** - Publishes as a named sub-site with a slug (kind `35128`)
|
|
47
|
+
|
|
48
|
+
If the visitor already has a root site, the form defaults to a named site. Overwriting an existing site requires explicit confirmation.
|
|
49
|
+
|
|
50
|
+
## Paper trail
|
|
51
|
+
|
|
52
|
+
Each deployment adds a `muse` tag with the deployer's pubkey and relay list. The widget shows an expandable "Inspired N npubs" counter when muse tags are present. A maximum of 9 muse tags are kept per manifest (originator + 8 most recent), with FIFO truncation of the middle.
|
|
53
|
+
|
|
54
|
+
## Development
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pnpm install
|
|
58
|
+
pnpm run build # builds dist/stealthis.js (IIFE) and dist/stealthis.mjs (ESM)
|
|
59
|
+
pnpm run dev # watch mode
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
MIT
|
package/package.json
CHANGED
package/src/widget.ts
CHANGED
|
@@ -22,7 +22,7 @@ type State =
|
|
|
22
22
|
| 'error';
|
|
23
23
|
|
|
24
24
|
export class NsiteDeployButton extends HTMLElement {
|
|
25
|
-
static observedAttributes = ['
|
|
25
|
+
static observedAttributes = ['button-text', 'stat-text', 'no-trail'];
|
|
26
26
|
|
|
27
27
|
private shadow: ShadowRoot;
|
|
28
28
|
private state: State = 'idle';
|
|
@@ -68,8 +68,12 @@ export class NsiteDeployButton extends HTMLElement {
|
|
|
68
68
|
if (this.state === 'idle') this.render();
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
private get
|
|
72
|
-
return this.getAttribute('
|
|
71
|
+
private get buttonText(): string {
|
|
72
|
+
return this.getAttribute('button-text') || 'Borrow this nsite';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private get statText(): string {
|
|
76
|
+
return this.getAttribute('stat-text') || '%s npubs borrowed this nsite';
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
private esc(s: string): string {
|
|
@@ -90,12 +94,12 @@ export class NsiteDeployButton extends HTMLElement {
|
|
|
90
94
|
|
|
91
95
|
switch (this.state) {
|
|
92
96
|
case 'idle':
|
|
93
|
-
html += `<button class="nd-trigger" part="trigger">${this.esc(this.
|
|
97
|
+
html += `<button class="nd-trigger" part="trigger">${this.esc(this.buttonText)}</button>`;
|
|
94
98
|
html += this.paperTrailContent();
|
|
95
99
|
break;
|
|
96
100
|
|
|
97
101
|
case 'auth':
|
|
98
|
-
html += `<button class="nd-trigger" disabled>${this.esc(this.
|
|
102
|
+
html += `<button class="nd-trigger" disabled>${this.esc(this.buttonText)}</button>`;
|
|
99
103
|
html += this.modal(this.authContent());
|
|
100
104
|
break;
|
|
101
105
|
|
|
@@ -118,12 +122,12 @@ export class NsiteDeployButton extends HTMLElement {
|
|
|
118
122
|
break;
|
|
119
123
|
|
|
120
124
|
case 'form':
|
|
121
|
-
html += `<button class="nd-trigger" disabled>${this.esc(this.
|
|
125
|
+
html += `<button class="nd-trigger" disabled>${this.esc(this.buttonText)}</button>`;
|
|
122
126
|
html += this.modal(this.formContent());
|
|
123
127
|
break;
|
|
124
128
|
|
|
125
129
|
case 'confirm':
|
|
126
|
-
html += `<button class="nd-trigger" disabled>${this.esc(this.
|
|
130
|
+
html += `<button class="nd-trigger" disabled>${this.esc(this.buttonText)}</button>`;
|
|
127
131
|
html += this.modal(this.confirmContent());
|
|
128
132
|
break;
|
|
129
133
|
|
|
@@ -151,7 +155,7 @@ export class NsiteDeployButton extends HTMLElement {
|
|
|
151
155
|
break;
|
|
152
156
|
|
|
153
157
|
case 'error':
|
|
154
|
-
html += `<button class="nd-trigger" part="trigger">${this.esc(this.
|
|
158
|
+
html += `<button class="nd-trigger" part="trigger">${this.esc(this.buttonText)}</button>`;
|
|
155
159
|
html += this.modal(`
|
|
156
160
|
<div class="nd-header">
|
|
157
161
|
<h2 class="nd-title">Error</h2>
|
|
@@ -172,10 +176,10 @@ export class NsiteDeployButton extends HTMLElement {
|
|
|
172
176
|
// --- Content builders ---
|
|
173
177
|
|
|
174
178
|
private paperTrailContent(): string {
|
|
175
|
-
if (this.muses.length === 0) return '';
|
|
179
|
+
if (this.hasAttribute('no-trail') || this.muses.length === 0) return '';
|
|
176
180
|
|
|
177
181
|
let html = `<div class="nd-trail">
|
|
178
|
-
<button class="nd-trail-toggle" data-action="toggle-trail"
|
|
182
|
+
<button class="nd-trail-toggle" data-action="toggle-trail">${this.esc(this.statText.replace('%s', String(this.muses.length)))}</button>`;
|
|
179
183
|
|
|
180
184
|
if (this.musesExpanded) {
|
|
181
185
|
html += `<div class="nd-trail-list">`;
|