add youtube, twitter, and invoice embeds

This commit is contained in:
hzrd149
2023-02-07 17:04:18 -06:00
parent ea605efc60
commit c8bb1f3d3f
15 changed files with 484 additions and 51 deletions

View File

@@ -13,5 +13,11 @@
<body>
<div id="root"></div>
<script type="module" src="./src/index.tsx"></script>
<script
async
src="https://platform.twitter.com/widgets.js"
charset="utf-8"
></script>
</body>
</html>

View File

@@ -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",

View File

@@ -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 (
<Button
colorScheme="yellow"
variant="outline"
onClick={handleClick}
isLoading={loading}
>
Invoice for {invoice.amount ? getReadableAmount(invoice.amount) : "♾️"}
</Button>
);
};

View File

@@ -23,9 +23,9 @@ const MobileLayout = ({ children }: { children: React.ReactNode }) => {
return (
<Flex direction="column" height="100%">
<Box flexGrow={1} overflow="auto">
<Flex flexGrow={1} direction="column" overflow="hidden">
{children}
</Box>
</Flex>
<Flex flexShrink={0} gap="2" padding="2">
<IconButton
icon={<img src={homeIcon} />}
@@ -77,9 +77,9 @@ const DesktopLayout = ({ children }: { children: React.ReactNode }) => {
<Button onClick={() => navigate("/settings")}>Settings</Button>
<ConnectedRelays />
</VStack>
<Box flexGrow={1} overflow="hidden">
<Flex flexGrow={1} direction="column" overflow="hidden">
<ErrorBoundary>{children}</ErrorBoundary>
</Box>
</Flex>
<VStack width="15rem" pt="2" alignItems="stretch" flexShrink={0}>
<Button onClick={() => navigate("/")}>Manage Follows</Button>
</VStack>

View File

@@ -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) => <Link color="blue.500" {...props} />;
const CustomImage = (props: ImageProps) => (
<AspectRatio ratio={16 / 10} maxWidth="30rem">
<Image {...props} />
</AspectRatio>
);
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 <InvoiceButton paymentRequest={href.replace(/lightning:/i, "")} />;
}
if (youtubeVideoLink.test(href)) {
const parts = youtubeVideoLink.exec(href);
return parts ? (
<AspectRatio ratio={16 / 10} maxWidth="30rem">
<iframe
src={`https://www.youtube.com/embed/${parts[6]}`}
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>
</AspectRatio>
) : (
<CustomLink {...props} />
);
}
if (twitterLink.test(href)) {
return <TweetEmbed href={href} conversation={false} />;
}
}
return <CustomLink {...props} />;
};
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(/(?<! )\n/g, " \n");
export const PostContents = React.memo(
({ content, maxChars }: PostContentsProps) => {
const fixedLines = content.replace(/(?<! )\n/g, " \n");
return (
<ReactMarkdown
remarkPlugins={[remarkImages, remarkUnwrapImages, remarkGfm]}
rehypePlugins={[[rehypeExternalLinks, { target: "_blank" }]]}
components={components}
>
{fixedLines}
</ReactMarkdown>
);
});
return (
<ReactMarkdown
remarkPlugins={[
remarkImages,
remarkUnwrapImages,
remarkGfm,
linkifyRegex(lightningInvoiceRegExp),
]}
rehypePlugins={[
[rehypeExternalLinks, { target: "_blank" }],
// [rehypeTruncate, { maxChars, disable: !maxChars }],
]}
components={components}
>
{fixedLines}
</ReactMarkdown>
);
}
);

View File

@@ -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) => {
</CardHeader>
<CardBody pt="2" pb="0" pr="0" pl="0">
<VStack alignItems="flex-start" justifyContent="stretch">
<Box maxHeight="20rem" overflow="hidden" width="100%">
<PostContents content={event.content}/>
<Box overflow="hidden" width="100%">
<PostContents content={event.content} maxChars={300} />
</Box>
{isLong && (
<>

View File

@@ -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<HTMLQuoteElement | null>(null);
useEffect(() => {
if (ref.current) {
// @ts-ignore
window.twttr.widgets.load();
}
}, []);
return (
<blockquote
className="twitter-tweet"
ref={ref}
data-conversation={conversation ? undefined : "none"}
>
<a href={href}></a>
</blockquote>
);
};

38
src/helpers/bolt11.ts Normal file
View File

@@ -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`;
}

View File

@@ -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 }) => (
<ChakraProvider theme={theme}>
<BrowserRouter>{children}</BrowserRouter>
<HashRouter>{children}</HashRouter>
</ChakraProvider>
);

View File

@@ -1,28 +1,4 @@
import { BehaviorSubject } from "rxjs";
import { NostrEvent } from "../types/nostr-event";
declare global {
interface Window {
nostr?: {
enabled: boolean;
getPublicKey: () => Promise<string> | string;
signEvent: (event: NostrEvent) => Promise<NostrEvent> | NostrEvent;
getRelays: () =>
| Record<string, { read: boolean; write: boolean }>
| string[];
nip04?: {
encrypt: (
pubkey: string,
plaintext: string
) => Promise<string> | string;
decrypt: (
pubkey: string,
ciphertext: string
) => Promise<string> | string;
};
};
}
}
class IdentityService {
setup = new BehaviorSubject(false);

151
src/types/light-bolt11-decoder.d.ts vendored Normal file
View File

@@ -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;
}

24
src/types/nostr-extensions.d.ts vendored Normal file
View File

@@ -0,0 +1,24 @@
import { NostrEvent } from "./nostr-event";
declare global {
interface Window {
nostr?: {
enabled: boolean;
getPublicKey: () => Promise<string> | string;
signEvent: (event: NostrEvent) => Promise<NostrEvent> | NostrEvent;
getRelays: () =>
| Record<string, { read: boolean; write: boolean }>
| string[];
nip04?: {
encrypt: (
pubkey: string,
plaintext: string
) => Promise<string> | string;
decrypt: (
pubkey: string,
ciphertext: string
) => Promise<string> | string;
};
};
}
}

View File

@@ -31,7 +31,7 @@ export const UserPostsTab = ({ pubkey }: { pubkey: string }) => {
return <SkeletonText />;
}
if (timeline.length > 20) timeline.length = 20;
if (timeline.length > 30) timeline.length = 30;
return (
<Flex direction="column" gap="2" pr="2" pl="2">

View File

@@ -31,7 +31,7 @@ export const UserRepliesTab = ({ pubkey }: { pubkey: string }) => {
return <SkeletonText />;
}
if (timeline.length > 20) timeline.length = 20;
if (timeline.length > 30) timeline.length = 30;
return (
<Flex direction="column" gap="2" pr="2" pl="2">

View File

@@ -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"