diff --git a/index.html b/index.html index 2735b7a90..02f225f9b 100644 --- a/index.html +++ b/index.html @@ -13,5 +13,11 @@
+ + diff --git a/package.json b/package.json index 8a7e96250..19fb8bfaf 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "framer-motion": "^7.10.3", "idb": "^7.1.1", "identicon.js": "^2.3.3", + "light-bolt11-decoder": "^2.1.0", "moment": "^2.29.4", "noble-secp256k1": "^1.2.14", "react": "^18.2.0", @@ -28,10 +29,13 @@ "react-singleton-hook": "^4.0.1", "react-use": "^17.4.0", "rehype-external-links": "^2.0.1", + "rehype-truncate": "^1.2.2", "remark-gfm": "^3.0.1", "remark-images": "^3.1.0", + "remark-linkify-regex": "^1.2.1", "remark-unwrap-images": "^3.0.1", - "rxjs": "^7.8.0" + "rxjs": "^7.8.0", + "webln": "^0.3.2" }, "devDependencies": { "@changesets/cli": "^2.26.0", diff --git a/src/components/invoice-button.tsx b/src/components/invoice-button.tsx new file mode 100644 index 000000000..954caf775 --- /dev/null +++ b/src/components/invoice-button.tsx @@ -0,0 +1,38 @@ +import { useState } from "react"; +import { Button } from "@chakra-ui/react"; +import { requestProvider } from "webln"; +import { getReadableAmount, parsePaymentRequest } from "../helpers/bolt11"; + +export type InvoiceButtonProps = { + paymentRequest: string; +}; +export const InvoiceButton = ({ paymentRequest }: InvoiceButtonProps) => { + const invoice = parsePaymentRequest(paymentRequest); + const [loading, setLoading] = useState(false); + const handleClick = async () => { + setLoading(true); + try { + const provider = await requestProvider(); + await provider.enable(); + const response = await provider.sendPayment(paymentRequest); + if (response.preimage) { + console.log("Paid"); + } + } catch (e) { + console.log("Failed to pay invoice"); + console.log(e); + } + setLoading(false); + }; + + return ( + + ); +}; diff --git a/src/components/page.tsx b/src/components/page.tsx index 78f5df821..2b64e3648 100644 --- a/src/components/page.tsx +++ b/src/components/page.tsx @@ -23,9 +23,9 @@ const MobileLayout = ({ children }: { children: React.ReactNode }) => { return ( - + {children} - + } @@ -77,9 +77,9 @@ const DesktopLayout = ({ children }: { children: React.ReactNode }) => { - + {children} - + diff --git a/src/components/post-contents.tsx b/src/components/post-contents.tsx index bf3d53566..9ee722719 100644 --- a/src/components/post-contents.tsx +++ b/src/components/post-contents.tsx @@ -1,32 +1,102 @@ -import { Image, Link, LinkProps } from "@chakra-ui/react"; import React from "react"; +import { + AspectRatio, + Image, + ImageProps, + Link, + LinkProps, +} from "@chakra-ui/react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import remarkImages from "remark-images"; import remarkUnwrapImages from "remark-unwrap-images"; import rehypeExternalLinks from "rehype-external-links"; +// @ts-ignore +// import rehypeTruncate from "rehype-truncate"; +// @ts-ignore +import linkifyRegex from "remark-linkify-regex"; +import { InvoiceButton } from "./invoice-button"; +import { TweetEmbed } from "./tweet-embed"; + +const lightningInvoiceRegExp = /(lightning:)?LNBC[A-Za-z0-9]+/i; + +// copied from https://stackoverflow.com/a/37704433 +const youtubeVideoLink = + /^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube(-nocookie)?\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$/i; + +const twitterLink = + /https?:\/\/twitter\.com\/(?:\#!\/)?(\w+)\/status(es)?\/(\d+)/i; const CustomLink = (props: LinkProps) => ; +const CustomImage = (props: ImageProps) => ( + + + +); + +const HandleLinkTypes = (props: LinkProps) => { + let href = props.href; + // @ts-ignore + if (href === "javascript:void(0)") href = String(props.children[0]); + + if (href) { + if (lightningInvoiceRegExp.test(href)) { + return ; + } + if (youtubeVideoLink.test(href)) { + const parts = youtubeVideoLink.exec(href); + + return parts ? ( + + + + ) : ( + + ); + } + if (twitterLink.test(href)) { + return ; + } + } + return ; +}; const components = { - img: Image, - a: CustomLink, + img: CustomImage, + a: HandleLinkTypes, }; export type PostContentsProps = { content: string; + maxChars?: number; }; -export const PostContents = React.memo(({ content }: PostContentsProps) => { - const fixedLines = content.replace(/(? { + const fixedLines = content.replace(/(? - {fixedLines} - - ); -}); + return ( + + {fixedLines} + + ); + } +); diff --git a/src/components/post.tsx b/src/components/post.tsx index be36f5351..ce009c03c 100644 --- a/src/components/post.tsx +++ b/src/components/post.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useRef } from "react"; import { Box, Button, @@ -70,8 +70,8 @@ export const Post = React.memo(({ event }: PostProps) => { - - + + {isLong && ( <> diff --git a/src/components/tweet-embed.tsx b/src/components/tweet-embed.tsx new file mode 100644 index 000000000..5d8bb6bfd --- /dev/null +++ b/src/components/tweet-embed.tsx @@ -0,0 +1,27 @@ +import { useEffect, useRef } from "react"; + +export type TweetEmbedProps = { + href: string; + conversation?: boolean; +}; + +export const TweetEmbed = ({ href, conversation }: TweetEmbedProps) => { + const ref = useRef(null); + + useEffect(() => { + if (ref.current) { + // @ts-ignore + window.twttr.widgets.load(); + } + }, []); + + return ( +
+ +
+ ); +}; diff --git a/src/helpers/bolt11.ts b/src/helpers/bolt11.ts new file mode 100644 index 000000000..8ac7c2587 --- /dev/null +++ b/src/helpers/bolt11.ts @@ -0,0 +1,38 @@ +import { + decode, + Section, + AmountSection, + DescriptionSection, +} from "light-bolt11-decoder"; + +export type ParsedInvoice = { + paymentRequest: string; + description: string; + amount?: number; +}; + +function isDescription(section: Section): section is DescriptionSection { + return section.name === "description"; +} +function isAmount(section: Section): section is AmountSection { + return section.name === "amount"; +} + +export function parsePaymentRequest(paymentRequest: string): ParsedInvoice { + const decoded = decode(paymentRequest); + + return { + paymentRequest: decoded.paymentRequest, + description: decoded.sections.find(isDescription)?.value ?? "", + amount: decoded.sections.find(isAmount)?.value, + }; +} + +export function getReadableAmount(amount: number) { + const amountInSats = amount / 1000; + if (amountInSats > 1000000) { + return `${amountInSats / 1000000}M sats`; + } else if (amountInSats > 1000) { + return `${amountInSats / 1000}K sats`; + } else return `${amountInSats} sats`; +} diff --git a/src/providers/index.tsx b/src/providers/index.tsx index 76a3a8b29..587d20e61 100644 --- a/src/providers/index.tsx +++ b/src/providers/index.tsx @@ -1,10 +1,10 @@ import React from "react"; import { ChakraProvider } from "@chakra-ui/react"; -import { BrowserRouter } from "react-router-dom"; +import { BrowserRouter, HashRouter } from "react-router-dom"; import theme from "../theme"; export const Providers = ({ children }: { children: React.ReactNode }) => ( - {children} + {children} ); diff --git a/src/services/identity.ts b/src/services/identity.ts index 49c2cf635..49a0b6f0e 100644 --- a/src/services/identity.ts +++ b/src/services/identity.ts @@ -1,28 +1,4 @@ import { BehaviorSubject } from "rxjs"; -import { NostrEvent } from "../types/nostr-event"; - -declare global { - interface Window { - nostr?: { - enabled: boolean; - getPublicKey: () => Promise | string; - signEvent: (event: NostrEvent) => Promise | NostrEvent; - getRelays: () => - | Record - | string[]; - nip04?: { - encrypt: ( - pubkey: string, - plaintext: string - ) => Promise | string; - decrypt: ( - pubkey: string, - ciphertext: string - ) => Promise | string; - }; - }; - } -} class IdentityService { setup = new BehaviorSubject(false); diff --git a/src/types/light-bolt11-decoder.d.ts b/src/types/light-bolt11-decoder.d.ts new file mode 100644 index 000000000..5d043e163 --- /dev/null +++ b/src/types/light-bolt11-decoder.d.ts @@ -0,0 +1,151 @@ +declare module "light-bolt11-decoder" { + // types for https://www.npmjs.com/package/light-bolt11-decoder + export type LightningNetworkSection = { + name: "lightning_network"; + letters: string; + }; + export type CoinNetworkSection = { + name: "coin_network"; + letters: string; + }; + export type AmountSection = { + name: "amount"; + letters: string; + value: number; + }; + export type SeparatorSection = { + name: "separator"; + letters: string; + }; + export type TimestampSection = { + name: "timestamp"; + letters: string; + value: number; + }; + export type PaymentHashSection = { + name: "payment_hash"; + tag: "p"; + letters: string; + value: string; + }; + export type DescriptionSection = { + name: "description"; + tag: "d"; + letters: string; + value: string; + }; + export type PaymentSecretSection = { + name: "payment_secret"; + tag: "s"; + letters: string; + value: string; + }; + export type ExpirySection = { + name: "expiry"; + tag: "x"; + letters: string; + value: number; + }; + export type MinFinalCltvExpiry = { + name: "min_final_cltv_expiry"; + tag: "c"; + letters: string; + value: number; + }; + export type FeatureBitsSection = { + name: "feature_bits"; + tag: "9"; + letters: string; + value: { + word_length: number; + option_data_loss_protect: { + required: boolean; + supported: boolean; + }; + initial_routing_sync: { + required: boolean; + supported: boolean; + }; + option_upfront_shutdown_script: { + required: boolean; + supported: boolean; + }; + gossip_queries: { + required: boolean; + supported: boolean; + }; + var_onion_optin: { + required: boolean; + supported: boolean; + }; + gossip_queries_ex: { + required: boolean; + supported: boolean; + }; + option_static_remotekey: { + required: boolean; + supported: boolean; + }; + payment_secret: { + required: boolean; + supported: boolean; + }; + basic_mpp: { + required: boolean; + supported: boolean; + }; + option_support_large_channel: { + required: boolean; + supported: boolean; + }; + extra_bits: { + start_bit: number; + bits: number[]; + has_required: boolean; + }; + }; + }; + export type RouteHintSection = { + name: "route_hint"; + tag: "r"; + letters: string; + value: { + pubkey: string; + short_channel_id: string; + fee_base_msat: number; + fee_proportional_millionths: number; + cltv_expiry_delta: number; + }[]; + }; + export type SignatureSection = { + name: "signature"; + letters: string; + value: string; + }; + export type ChecksumSection = { + name: "checksum"; + letters: string; + }; + + export type Section = + | LightningNetworkSection + | CoinNetworkSection + | AmountSection + | SeparatorSection + | TimestampSection + | PaymentHashSection + | DescriptionSection + | PaymentSecretSection + | ExpirySection + | FeatureBitsSection + | RouteHintSection + | SignatureSection + | ChecksumSection; + + export type ParsedInvoice = { + paymentRequest: string; + sections: Section[]; + expiry: number; + }; + export function decode(paymentRequest: string): ParsedInvoice; +} diff --git a/src/types/nostr-extensions.d.ts b/src/types/nostr-extensions.d.ts new file mode 100644 index 000000000..d08ad9a48 --- /dev/null +++ b/src/types/nostr-extensions.d.ts @@ -0,0 +1,24 @@ +import { NostrEvent } from "./nostr-event"; + +declare global { + interface Window { + nostr?: { + enabled: boolean; + getPublicKey: () => Promise | string; + signEvent: (event: NostrEvent) => Promise | NostrEvent; + getRelays: () => + | Record + | string[]; + nip04?: { + encrypt: ( + pubkey: string, + plaintext: string + ) => Promise | string; + decrypt: ( + pubkey: string, + ciphertext: string + ) => Promise | string; + }; + }; + } +} diff --git a/src/views/user/posts.tsx b/src/views/user/posts.tsx index 2ccdfd4e6..105caea99 100644 --- a/src/views/user/posts.tsx +++ b/src/views/user/posts.tsx @@ -31,7 +31,7 @@ export const UserPostsTab = ({ pubkey }: { pubkey: string }) => { return ; } - if (timeline.length > 20) timeline.length = 20; + if (timeline.length > 30) timeline.length = 30; return ( diff --git a/src/views/user/replies.tsx b/src/views/user/replies.tsx index 4b392be73..c827716fa 100644 --- a/src/views/user/replies.tsx +++ b/src/views/user/replies.tsx @@ -31,7 +31,7 @@ export const UserRepliesTab = ({ pubkey }: { pubkey: string }) => { return ; } - if (timeline.length > 20) timeline.length = 20; + if (timeline.length > 30) timeline.length = 30; return ( diff --git a/yarn.lock b/yarn.lock index 1704124b6..158ebeb8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2441,6 +2441,13 @@ magic-string "^0.25.0" string.prototype.matchall "^4.0.6" +"@types/chrome@^0.0.74": + version "0.0.74" + resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.74.tgz#f69827c48fcf7fecc90c96089807661749a5a5e3" + integrity sha512-hzosS5CkQcIKCgxcsV2AzbJ36KNxG/Db2YEN/erEu7Boprg+KpMDLBQqKFmSo+JkQMGqRcicUyqCowJpuT+C6A== + dependencies: + "@types/filesystem" "*" + "@types/debug@^4.0.0": version "4.1.7" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" @@ -2458,6 +2465,18 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== +"@types/filesystem@*": + version "0.0.32" + resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.32.tgz#307df7cc084a2293c3c1a31151b178063e0a8edf" + integrity sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ== + dependencies: + "@types/filewriter" "*" + +"@types/filewriter@*": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.29.tgz#a48795ecadf957f6c0d10e0c34af86c098fa5bee" + integrity sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ== + "@types/hast@^2.0.0": version "2.3.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" @@ -2731,11 +2750,21 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + bech32-buffer@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/bech32-buffer/-/bech32-buffer-0.2.1.tgz#8106f2f51bcb2ba1d9fb7718905c3042c5be2fcd" integrity sha512-fCG1TyZuCN48Sdw97p/IR39fvqpFlWDVpG7qnuU1Uc3+Xtc/0uqAp8U7bMW/bGuVF5CcNVIXwxQsWwUr6un6FQ== +bech32@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + better-path-resolve@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/better-path-resolve/-/better-path-resolve-1.0.0.tgz#13a35a1104cdd48a7b74bf8758f96a1ee613f99d" @@ -2743,6 +2772,11 @@ better-path-resolve@1.0.0: dependencies: is-windows "^1.0.0" +bn.js@^4.11.8: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2787,6 +2821,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + builtin-modules@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" @@ -3641,6 +3683,11 @@ identicon.js@^2.3.3: resolved "https://registry.yarnpkg.com/identicon.js/-/identicon.js-2.3.3.tgz#c505b8d60ecc6ea13bbd991a33964c44c1ad60a1" integrity sha512-/qgOkXKZ7YbeCYbawJ9uQQ3XJ3uBg9VDpvHjabCAPp6aRMhjLaFAxG90+1TxzrhKaj6AYpVGrx6UXQfQA41UEA== +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.2.0: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" @@ -3982,6 +4029,15 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== +light-bolt11-decoder@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/light-bolt11-decoder/-/light-bolt11-decoder-2.1.0.tgz#46b122790ae0eb415841227eba770eae7303ecf5" + integrity sha512-/AaSWTldx3aaFD7DgMVbX77MVEgLEPI0Zyx4Fjg23u3WpEoc536vz5LTXBU8oXAcrEcyDyn5GpBi2pEYuL351Q== + dependencies: + bech32 "^1.1.2" + bn.js "^4.11.8" + buffer "^6.0.3" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -5108,6 +5164,11 @@ rehype-external-links@^2.0.1: unified "^10.0.0" unist-util-visit "^4.0.0" +rehype-truncate@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/rehype-truncate/-/rehype-truncate-1.2.2.tgz#fbb75bad4ad13d89d7dab2cf88c205fe48a4aa27" + integrity sha512-zj2FxxC3rm8bg6loesMdS/+BuGpp89mu+12VsJrBzN5kKgOxKwtawscQXElyt2BnxU2pG3hkoyb3Euc3Q7F38A== + remark-gfm@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-3.0.1.tgz#0b180f095e3036545e9dddac0e8df3fa5cfee54f" @@ -5129,6 +5190,15 @@ remark-images@^3.1.0: unist-util-is "^5.0.0" unist-util-visit-parents "^5.0.0" +remark-linkify-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/remark-linkify-regex/-/remark-linkify-regex-1.2.1.tgz#5121ad7f8297a7d75e56df4d87c808052d325fc8" + integrity sha512-aKZAFcZWzrw64m1eTKfVgiZ9iKhZ5vxeOVoACjCd9ahPpKpdnAz++z0qVaR7h0z5nryrvUrTQvIyFieHkdEfCA== + dependencies: + unicode-word-regex "^1.0.1" + unist-util-flatmap "1.0.x" + unist-util-visit-parents "2.0.x" + remark-parse@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.1.tgz#6f60ae53edbf0cf38ea223fe643db64d112e0775" @@ -5752,6 +5822,11 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== +unicode-word-regex@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-word-regex/-/unicode-word-regex-1.1.0.tgz#cdd6910e4e413606e704e139079bcab2b91040e3" + integrity sha512-2HlIXyag8yi0+AsB1Rx88gSuzw4hS/PgrcTbzkqIW/RBdi2VSp1rRr55RS+HszErwlSRAoA9jhM6L/x+xtu41w== + unified@^10.0.0: version "10.1.2" resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" @@ -5779,11 +5854,21 @@ unist-builder@^3.0.0: dependencies: "@types/unist" "^2.0.0" +unist-util-flatmap@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unist-util-flatmap/-/unist-util-flatmap-1.0.0.tgz#f914ed6b36ff040afce938d848f379f88b94b448" + integrity sha512-IG32jcKJlhARCYT2LsYPJWdoXYkzz3ESAdl1aa2hn9Auh+cgUmU6wgkII4yCc/1GgeWibRdELdCZh/p3QKQ1dQ== + unist-util-generated@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113" integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw== +unist-util-is@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.3.tgz#459182db31f4742fceaea88d429693cbf0043d20" + integrity sha512-4WbQX2iwfr/+PfM4U3zd2VNXY+dWtZsN1fLnWEi2QQXA4qyDYAZcDMfXUX0Cu6XZUHHAO9q4nyxxLT4Awk1qUA== + unist-util-is@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" @@ -5803,6 +5888,13 @@ unist-util-stringify-position@^3.0.0: dependencies: "@types/unist" "^2.0.0" +unist-util-visit-parents@2.0.x: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz#63fffc8929027bee04bfef7d2cce474f71cb6217" + integrity sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA== + dependencies: + unist-util-is "^2.1.2" + unist-util-visit-parents@^5.0.0, unist-util-visit-parents@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" @@ -5938,6 +6030,13 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== +webln@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/webln/-/webln-0.3.2.tgz#bbadf52916666b6059e3661ef5ab73a76b7cd0f4" + integrity sha512-YYT83aOCLup2AmqvJdKtdeBTaZpjC6/JDMe8o6x1kbTYWwiwrtWHyO//PAsPixF3jwFsAkj5DmiceB6w/QSe7Q== + dependencies: + "@types/chrome" "^0.0.74" + whatwg-url@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"