Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 0 additions & 59 deletions components/embed.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,59 +21,6 @@ function TweetSkeleton ({ className }) {
)
}

export const NostrEmbed = memo(function NostrEmbed ({ className, darkMode, id }) {
const [show, setShow] = useState(false)
const iframeRef = useRef(null)

useEffect(() => {
if (!iframeRef.current) return

const setHeightFromIframe = (e) => {
if (e.origin !== 'https://njump.me' || !e?.data?.height || e.source !== iframeRef.current.contentWindow) return
iframeRef.current.height = `${e.data.height}px`
}

window?.addEventListener('message', setHeightFromIframe)

const handleIframeLoad = () => {
iframeRef.current.contentWindow.postMessage({ setDarkMode: darkMode }, '*')
}

if (iframeRef.current.complete) {
handleIframeLoad()
} else {
iframeRef.current.addEventListener('load', handleIframeLoad)
}

// https://github.com/vercel/next.js/issues/39451
iframeRef.current.src = `https://njump.me/${id}?embed=yes`

return () => {
window?.removeEventListener('message', setHeightFromIframe)
iframeRef.current?.removeEventListener('load', handleIframeLoad)
}
}, [iframeRef.current, darkMode])

return (
<div className={classNames('sn-nostr-container', !show && 'sn-embed-contained', className)}>
<iframe
ref={iframeRef}
width='100%'
style={{ maxWidth: '100%' }}
height={iframeRef.current?.height || '100%'}
frameBorder='0'
sandbox='allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox'
allow=''
/>
{!show &&
<Button size='md' variant='info' className='sn-embed-show-full' onClick={() => setShow(true)}>
<div>show full note</div>
<small className='fw-normal fst-italic'>or other stuff</small>
</Button>}
</div>
)
})

const SpotifyEmbed = function SpotifyEmbed ({ src, className }) {
const iframeRef = useRef(null)

Expand Down Expand Up @@ -143,12 +90,6 @@ const Embed = memo(function Embed ({ src, provider, id, meta, className, topLeve
)
}

if (provider === 'nostr') {
return (
<NostrEmbed src={src} className={embedClass} id={id} darkMode={darkMode} />
)
}

if (provider === 'wavlake') {
return (
<div className={classNames('sn-wavlake-wrapper', embedClass)}>
Expand Down
2 changes: 1 addition & 1 deletion components/footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const SocialsPopover = (
<Popover.Body style={{ fontWeight: 500, fontSize: '.9rem' }}>
<div className='d-flex justify-content-center'>
<a
href='https://njump.me/npub1jfujw6llhq7wuvu5detycdsq5v5yqf56sgrdq8wlgrryx2a2p09svwm0gx' className='nav-link p-0 d-inline-flex'
href='https://damus.io/npub1jfujw6llhq7wuvu5detycdsq5v5yqf56sgrdq8wlgrryx2a2p09svwm0gx' className='nav-link p-0 d-inline-flex'
target='_blank' rel='noreferrer'
>
nostr
Expand Down
2 changes: 1 addition & 1 deletion components/item-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export default function ItemInfo ({
opentimestamp
</Link>}
{item?.noteId && (
<Dropdown.Item onClick={() => window.open(`https://njump.me/${item.noteId}`, '_blank', 'noopener,noreferrer,nofollow')}>
<Dropdown.Item onClick={() => window.open(`https://damus.io/${item.noteId}`, '_blank', 'noopener,noreferrer,nofollow')}>
nostr note
</Dropdown.Item>
)}
Expand Down
4 changes: 2 additions & 2 deletions components/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,14 +360,14 @@ function NostrZap ({ n }) {
<div className='fw-bold text-nostr'>
<NostrIcon width={24} height={24} className='fill-nostr me-1' />{numWithUnits(n.earnedSats)} zap from
{// eslint-disable-next-line
<Link className='mx-1 text-reset text-underline' target='_blank' href={`https://njump.me/${npub}`} rel={UNKNOWN_LINK_REL}>
<Link className='mx-1 text-reset text-underline' target='_blank' href={`https://damus.io/${npub}`} rel={UNKNOWN_LINK_REL}>
{npub.slice(0, 10)}...
</Link>
}
on {note
? (
// eslint-disable-next-line
<Link className='mx-1 text-reset text-underline' target='_blank' href={`https://njump.me/${note}`} rel={UNKNOWN_LINK_REL}>
<Link className='mx-1 text-reset text-underline' target='_blank' href={`https://damus.io/${note}`} rel={UNKNOWN_LINK_REL}>
{note.slice(0, 12)}...
</Link>)
: 'nostr'}
Expand Down
2 changes: 1 addition & 1 deletion components/user-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ function SocialLink ({ name, id }) {
const npub = hexToBech32(id)
return (
// eslint-disable-next-line
<Link className={className} target='_blank' href={`https://njump.me/${npub}`} rel={UNKNOWN_LINK_REL}>
<Link className={className} target='_blank' href={`https://damus.io/${npub}`} rel={UNKNOWN_LINK_REL}>
<NostrIcon width={20} height={20} className='me-1' />
{npub.slice(0, 10)}...{npub.slice(-10)}
</Link>
Expand Down
6 changes: 3 additions & 3 deletions lib/lexical/mdast/visitors/nostr.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { $createTextNode } from 'lexical'
import { $createLinkNode, $isLinkNode, $isAutoLinkNode } from '@lexical/link'

const NOSTR_ID_PATTERN = /^((npub1|nevent1|nprofile1|note1|naddr1)[02-9ac-hj-np-z]+)$/
const NJUMP_ORIGIN = 'https://njump.me'
const DAMUS_ORIGIN = 'https://damus.io'

function isNostrIdLink (lexicalNode) {
const url = lexicalNode.getURL?.()
if (!url) return null

try {
const u = new URL(url)
if (u.origin !== NJUMP_ORIGIN) return null
if (u.origin !== DAMUS_ORIGIN) return null
if (u.search || u.hash) return null
const id = u.pathname.replace(/^\//, '')
if (!id) return null
Expand All @@ -30,7 +30,7 @@ function isNostrIdLink (lexicalNode) {
export const MdastNostrIdVisitor = {
testNode: 'nostrId',
visitNode ({ mdastNode, actions }) {
const url = `${NJUMP_ORIGIN}/${mdastNode.value}`
const url = `${DAMUS_ORIGIN}/${mdastNode.value}`
const link = $createLinkNode(url, {
target: '_blank',
rel: 'noopener nofollow noreferrer'
Expand Down
22 changes: 0 additions & 22 deletions lib/url.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { nip19 } from 'nostr-tools'
import { DEFAULT_CROSSPOSTING_RELAYS } from './nostr'

export function ensureProtocol (value) {
if (!value) return value
value = value.trim()
Expand Down Expand Up @@ -125,25 +122,6 @@ export function parseEmbedUrl (href) {

const { hostname, pathname, searchParams } = new URL(href)

// nostr prefixes: [npub1, nevent1, nprofile1, note1]
const nostr = href.match(/\/(?<id>(?<type>npub1|nevent1|nprofile1|note1|naddr1)[02-9ac-hj-np-z]+)/)
if (nostr?.groups?.id) {
let id = nostr.groups.id
if (nostr.groups.type === 'npub1') {
const { data } = nip19.decode(id)
id = nip19.nprofileEncode({ pubkey: data })
}
if (nostr.groups.type === 'note1') {
const { data } = nip19.decode(id)
// njump needs relays to embed
id = nip19.neventEncode({ id: data, relays: DEFAULT_CROSSPOSTING_RELAYS, author: '' })
}
return {
provider: 'nostr',
id
}
}

// https://wavlake.com/track/c0aaeff8-5a26-49cf-8dad-2b6909e4aed1
if (hostname.endsWith('wavlake.com') && pathname.startsWith('/track')) {
return {
Expand Down
9 changes: 8 additions & 1 deletion lib/url.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-env jest */

import { parseInternalLinks, isMisleadingLink } from './url.js'
import { parseInternalLinks, parseEmbedUrl, isMisleadingLink } from './url.js'

const internalLinkCases = [
['https://stacker.news/items/123', '#123'],
Expand Down Expand Up @@ -30,6 +30,13 @@ describe('internal links', () => {
)
})

describe('embed links', () => {
test('does not embed nostr links', () => {
expect(parseEmbedUrl('https://damus.io/npub1jfujw6llhq7wuvu5detycdsq5v5yqf56sgrdq8wlgr6ve8znaa3qd6c3hq09ertp')).toBe(null)
expect(parseEmbedUrl('https://njump.me/note1efg2x09zl5gt4wax8nw8zdys8dqz6xvkhk83ehx2pf8wwvfrzwpsef8ysz')).toBe(null)
})
})

const misleadingLinkCases = [
// if text is the same as the link, it's not misleading
['https://stacker.news/items/1234', 'https://stacker.news/items/1234', false],
Expand Down
1 change: 0 additions & 1 deletion pages/settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,6 @@ export default function Settings ({ ssrData }) {
<li>if checked and a link is an image, video or can be embedded in another way, we will do it</li>
<li>we support embeds from following sites:</li>
<ul>
<li>njump.me</li>
<li>youtube.com</li>
<li>twitter.com</li>
<li>spotify.com</li>
Expand Down
2 changes: 1 addition & 1 deletion proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ function applySecurityHeaders (resp) {
// unsafe-inline for styles is not ideal but okay if script-src is using nonces
"style-src 'self' a.stacker.news 'unsafe-inline'",
"manifest-src 'self'",
'frame-src www.youtube.com www.youtube-nocookie.com platform.twitter.com njump.me open.spotify.com rumble.com embed.wavlake.com bitcointv.com peertube.tv',
'frame-src www.youtube.com www.youtube-nocookie.com platform.twitter.com open.spotify.com rumble.com embed.wavlake.com bitcointv.com peertube.tv',
"connect-src 'self' https: wss:" + devSrc,
// disable dangerous plugins like Flash
"object-src 'none'",
Expand Down