Add preview links (#29)
This commit is contained in:
parent
6ff3f99f79
commit
3f5e31f794
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "@dappconnect/preview-proxy",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^3.0.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "yarn node src/index.js",
|
||||||
|
"fix": "",
|
||||||
|
"build": "",
|
||||||
|
"test": ""
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import fetch from 'node-fetch'
|
||||||
|
import https from 'https'
|
||||||
|
import fs from 'fs'
|
||||||
|
|
||||||
|
const regEx = new RegExp(/meta +(property|content)="(.+?)" +(property|content)="(.+?)"/g);
|
||||||
|
|
||||||
|
async function listener(req, res){
|
||||||
|
const origin = req?.headers?.origin
|
||||||
|
res.statusCode = 200
|
||||||
|
res.setHeader('Content-Type', 'application/json')
|
||||||
|
if (origin === 'https://0.0.0.0:8080' || origin === 'https://localhost:8080' || origin === 'https://127.0.0.1:8080') {
|
||||||
|
res.setHeader('Access-Control-Allow-Origin', origin);
|
||||||
|
}
|
||||||
|
res.setHeader('Access-Control-Allow-Methods', 'POST');
|
||||||
|
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
|
||||||
|
const requestBody = await new Promise((resolve) => {
|
||||||
|
if (req.method == 'POST') {
|
||||||
|
let body = '';
|
||||||
|
req.on('data', function (data) {
|
||||||
|
body += data;
|
||||||
|
if (body.length > 1e6)
|
||||||
|
req.connection.destroy();
|
||||||
|
});
|
||||||
|
req.on('end', function () {
|
||||||
|
try {
|
||||||
|
resolve(JSON.parse(body))
|
||||||
|
} catch {
|
||||||
|
resolve({})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const obj = {}
|
||||||
|
if ('site' in requestBody) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(requestBody['site'])
|
||||||
|
const body = await response.text()
|
||||||
|
for (const match of body.matchAll(regEx)) {
|
||||||
|
if (match[1] === 'property') {
|
||||||
|
obj[match[2]] = match[4]
|
||||||
|
} else {
|
||||||
|
obj[match[4]] = match[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.end(JSON.stringify(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
key: fs.readFileSync('../../../cert/CA/localhost/localhost.decrypted.key'),
|
||||||
|
cert: fs.readFileSync('../../../cert/CA/localhost/localhost.crt')
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = https.createServer(options, listener);
|
||||||
|
server.listen(3000, () => console.log('server running at port 3000'));
|
|
@ -2,9 +2,32 @@ import { community, lightTheme, ReactChat } from "@dappconnect/react-chat";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
|
|
||||||
|
const fetchMetadata = async (link: string) => {
|
||||||
|
const response = await fetch("https://localhost:3000", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ site: link }),
|
||||||
|
});
|
||||||
|
const body = await response.text();
|
||||||
|
const parsedBody = JSON.parse(body);
|
||||||
|
if (
|
||||||
|
"og:image" in parsedBody &&
|
||||||
|
"og:site_name" in parsedBody &&
|
||||||
|
"og:title" in parsedBody
|
||||||
|
) {
|
||||||
|
return JSON.parse(body);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<div style={{ height: "100%" }}>
|
<div style={{ height: "100%" }}>
|
||||||
<ReactChat theme={lightTheme} community={community} />
|
<ReactChat
|
||||||
|
theme={lightTheme}
|
||||||
|
community={community}
|
||||||
|
fetchMetadata={fetchMetadata}
|
||||||
|
/>
|
||||||
</div>,
|
</div>,
|
||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
);
|
);
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"emoji-mart": "^3.0.1",
|
"emoji-mart": "^3.0.1",
|
||||||
|
"html-entities": "^2.3.2",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-is": "^17.0.2",
|
"react-is": "^17.0.2",
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { useNarrow } from "../contexts/narrowProvider";
|
||||||
import { ChannelData, channels } from "../helpers/channelsMock";
|
import { ChannelData, channels } from "../helpers/channelsMock";
|
||||||
import { CommunityData } from "../helpers/communityMock";
|
import { CommunityData } from "../helpers/communityMock";
|
||||||
import { useMessenger } from "../hooks/useMessenger";
|
import { useMessenger } from "../hooks/useMessenger";
|
||||||
|
import { Metadata } from "../models/Metadata";
|
||||||
import { Theme } from "../styles/themes";
|
import { Theme } from "../styles/themes";
|
||||||
|
|
||||||
import { Channels } from "./Channels";
|
import { Channels } from "./Channels";
|
||||||
|
@ -14,9 +15,10 @@ import { Members } from "./Members";
|
||||||
interface ChatProps {
|
interface ChatProps {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
community: CommunityData;
|
community: CommunityData;
|
||||||
|
fetchMetadata?: (url: string) => Promise<Metadata | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Chat({ theme, community }: ChatProps) {
|
export function Chat({ theme, community, fetchMetadata }: ChatProps) {
|
||||||
const [activeChannel, setActiveChannel] = useState<ChannelData>(channels[0]);
|
const [activeChannel, setActiveChannel] = useState<ChannelData>(channels[0]);
|
||||||
const [showMembers, setShowMembers] = useState(true);
|
const [showMembers, setShowMembers] = useState(true);
|
||||||
const [showChannels, setShowChannels] = useState(true);
|
const [showChannels, setShowChannels] = useState(true);
|
||||||
|
@ -62,6 +64,7 @@ export function Chat({ theme, community }: ChatProps) {
|
||||||
showCommunity={!showChannels}
|
showCommunity={!showChannels}
|
||||||
loadNextDay={() => loadNextDay(activeChannel.name)}
|
loadNextDay={() => loadNextDay(activeChannel.name)}
|
||||||
lastMessage={lastMessage}
|
lastMessage={lastMessage}
|
||||||
|
fetchMetadata={fetchMetadata}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Loading>Connecting to waku</Loading>
|
<Loading>Connecting to waku</Loading>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { useNarrow } from "../../contexts/narrowProvider";
|
||||||
import { ChannelData } from "../../helpers/channelsMock";
|
import { ChannelData } from "../../helpers/channelsMock";
|
||||||
import { CommunityData } from "../../helpers/communityMock";
|
import { CommunityData } from "../../helpers/communityMock";
|
||||||
import { ChatMessage } from "../../models/ChatMessage";
|
import { ChatMessage } from "../../models/ChatMessage";
|
||||||
|
import { Metadata } from "../../models/Metadata";
|
||||||
import { Theme } from "../../styles/themes";
|
import { Theme } from "../../styles/themes";
|
||||||
import { Channel } from "../Channels";
|
import { Channel } from "../Channels";
|
||||||
import { Community } from "../Community";
|
import { Community } from "../Community";
|
||||||
|
@ -30,6 +31,7 @@ interface ChatBodyProps {
|
||||||
activeChannelId: number;
|
activeChannelId: number;
|
||||||
loadNextDay: () => void;
|
loadNextDay: () => void;
|
||||||
lastMessage: Date;
|
lastMessage: Date;
|
||||||
|
fetchMetadata?: (url: string) => Promise<Metadata | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ChatBody({
|
export function ChatBody({
|
||||||
|
@ -46,6 +48,7 @@ export function ChatBody({
|
||||||
activeChannelId,
|
activeChannelId,
|
||||||
loadNextDay,
|
loadNextDay,
|
||||||
lastMessage,
|
lastMessage,
|
||||||
|
fetchMetadata,
|
||||||
}: ChatBodyProps) {
|
}: ChatBodyProps) {
|
||||||
const narrow = useNarrow();
|
const narrow = useNarrow();
|
||||||
const [showChannelsList, setShowChannelsList] = useState(false);
|
const [showChannelsList, setShowChannelsList] = useState(false);
|
||||||
|
@ -103,7 +106,11 @@ export function ChatBody({
|
||||||
Last message date {lastMessage.toDateString()}
|
Last message date {lastMessage.toDateString()}
|
||||||
</button>{" "}
|
</button>{" "}
|
||||||
{messages.length > 0 ? (
|
{messages.length > 0 ? (
|
||||||
<ChatMessages messages={messages} theme={theme} />
|
<ChatMessages
|
||||||
|
messages={messages}
|
||||||
|
theme={theme}
|
||||||
|
fetchMetadata={fetchMetadata}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<EmptyChannel theme={theme} channel={channel} />
|
<EmptyChannel theme={theme} channel={channel} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
import { decode } from "html-entities";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { Metadata } from "../../models/Metadata";
|
||||||
import { Theme } from "../../styles/themes";
|
import { Theme } from "../../styles/themes";
|
||||||
|
|
||||||
/* eslint-disable no-useless-escape */
|
/* eslint-disable no-useless-escape */
|
||||||
|
@ -11,15 +13,19 @@ const regEx =
|
||||||
type ChatMessageContentProps = {
|
type ChatMessageContentProps = {
|
||||||
content: string;
|
content: string;
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
|
fetchMetadata?: (url: string) => Promise<Metadata | undefined>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ChatMessageContent({
|
export function ChatMessageContent({
|
||||||
content,
|
content,
|
||||||
theme,
|
theme,
|
||||||
|
fetchMetadata,
|
||||||
}: ChatMessageContentProps) {
|
}: ChatMessageContentProps) {
|
||||||
const [elements, setElements] = useState<(string | React.ReactElement)[]>([
|
const [elements, setElements] = useState<(string | React.ReactElement)[]>([
|
||||||
content,
|
content,
|
||||||
]);
|
]);
|
||||||
|
const [link, setLink] = useState<string | undefined>(undefined);
|
||||||
|
const [openGraph, setOpenGraph] = useState<Metadata | undefined>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const split = content.split(regEx);
|
const split = content.split(regEx);
|
||||||
|
@ -44,13 +50,101 @@ export function ChatMessageContent({
|
||||||
split[idx + 1]
|
split[idx + 1]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
const match = matches[0];
|
||||||
|
const link =
|
||||||
|
match.startsWith("http://") || match.startsWith("https://")
|
||||||
|
? match
|
||||||
|
: "https://" + match;
|
||||||
|
setLink(link);
|
||||||
setElements(newSplit);
|
setElements(newSplit);
|
||||||
}
|
}
|
||||||
}, [content]);
|
}, [content]);
|
||||||
|
|
||||||
return <>{elements.map((el) => el)}</>;
|
useEffect(() => {
|
||||||
|
const updatePreview = async () => {
|
||||||
|
if (link && fetchMetadata) {
|
||||||
|
try {
|
||||||
|
const metadata = await fetchMetadata(link);
|
||||||
|
if (metadata) {
|
||||||
|
setOpenGraph(metadata);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
updatePreview();
|
||||||
|
}, [link]);
|
||||||
|
if (openGraph) {
|
||||||
|
return (
|
||||||
|
<ContentWrapper>
|
||||||
|
<div>{elements.map((el) => el)}</div>
|
||||||
|
<PreviewWrapper
|
||||||
|
onClick={() => window?.open(link, "_blank", "noopener")?.focus()}
|
||||||
|
>
|
||||||
|
<PreviewImage src={decodeURI(decode(openGraph["og:image"]))} />
|
||||||
|
<PreviewTitleWrapper>{openGraph["og:title"]}</PreviewTitleWrapper>
|
||||||
|
<PreviewSiteNameWrapper>
|
||||||
|
{openGraph["og:site_name"]}
|
||||||
|
</PreviewSiteNameWrapper>
|
||||||
|
</PreviewWrapper>
|
||||||
|
</ContentWrapper>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <>{elements.map((el) => el)}</>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PreviewSiteNameWrapper = styled.div`
|
||||||
|
font-family: Inter;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #939ba1;
|
||||||
|
margin-left: 12px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const PreviewTitleWrapper = styled.div`
|
||||||
|
margin-top: 7px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-family: Inter;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 13px;
|
||||||
|
width: 290px;
|
||||||
|
line-height: 18px;
|
||||||
|
margin-left: 12px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const PreviewImage = styled.img`
|
||||||
|
border-radius: 15px 15px 15px 4px;
|
||||||
|
width: 305px;
|
||||||
|
height: 170px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const PreviewWrapper = styled.div`
|
||||||
|
margin-top: 9px;
|
||||||
|
background: #ffffff;
|
||||||
|
width: 305px;
|
||||||
|
height: 224px;
|
||||||
|
border: 1px solid #eef2f5;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 16px 16px 16px 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ContentWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
`;
|
||||||
|
|
||||||
const Link = styled.a`
|
const Link = styled.a`
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: ${({ theme }) => theme.memberNameColor};
|
color: ${({ theme }) => theme.memberNameColor};
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { ChatMessage } from "../../models/ChatMessage";
|
import { ChatMessage } from "../../models/ChatMessage";
|
||||||
|
import { Metadata } from "../../models/Metadata";
|
||||||
import { Theme } from "../../styles/themes";
|
import { Theme } from "../../styles/themes";
|
||||||
import { UserIcon } from "../Icons/UserIcon";
|
import { UserIcon } from "../Icons/UserIcon";
|
||||||
import { textSmallStyles } from "../Text";
|
import { textSmallStyles } from "../Text";
|
||||||
|
@ -11,9 +12,14 @@ import { ChatMessageContent } from "./ChatMessageContent";
|
||||||
type ChatMessagesProps = {
|
type ChatMessagesProps = {
|
||||||
messages: ChatMessage[];
|
messages: ChatMessage[];
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
|
fetchMetadata?: (url: string) => Promise<Metadata | undefined>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ChatMessages({ messages, theme }: ChatMessagesProps) {
|
export function ChatMessages({
|
||||||
|
messages,
|
||||||
|
theme,
|
||||||
|
fetchMetadata,
|
||||||
|
}: ChatMessagesProps) {
|
||||||
const [scrollOnBot, setScrollOnBot] = useState(false);
|
const [scrollOnBot, setScrollOnBot] = useState(false);
|
||||||
const ref = useRef<HTMLHeadingElement>(null);
|
const ref = useRef<HTMLHeadingElement>(null);
|
||||||
const today = useMemo(() => new Date().getDay(), []);
|
const today = useMemo(() => new Date().getDay(), []);
|
||||||
|
@ -71,7 +77,11 @@ export function ChatMessages({ messages, theme }: ChatMessagesProps) {
|
||||||
</TimeWrapper>
|
</TimeWrapper>
|
||||||
</MessageHeaderWrapper>
|
</MessageHeaderWrapper>
|
||||||
<MessageText theme={theme}>
|
<MessageText theme={theme}>
|
||||||
<ChatMessageContent content={message.content} theme={theme} />
|
<ChatMessageContent
|
||||||
|
content={message.content}
|
||||||
|
theme={theme}
|
||||||
|
fetchMetadata={fetchMetadata}
|
||||||
|
/>
|
||||||
</MessageText>
|
</MessageText>
|
||||||
</ContentWrapper>
|
</ContentWrapper>
|
||||||
</MessageWrapper>
|
</MessageWrapper>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { useRef } from "react";
|
||||||
|
|
||||||
import { NarrowProvider } from "../contexts/narrowProvider";
|
import { NarrowProvider } from "../contexts/narrowProvider";
|
||||||
import { CommunityData } from "../helpers/communityMock";
|
import { CommunityData } from "../helpers/communityMock";
|
||||||
|
import { Metadata } from "../models/Metadata";
|
||||||
import { GlobalStyle } from "../styles/GlobalStyle";
|
import { GlobalStyle } from "../styles/GlobalStyle";
|
||||||
import { Theme } from "../styles/themes";
|
import { Theme } from "../styles/themes";
|
||||||
|
|
||||||
|
@ -10,15 +11,20 @@ import { Chat } from "./Chat";
|
||||||
interface ReactChatProps {
|
interface ReactChatProps {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
community: CommunityData;
|
community: CommunityData;
|
||||||
|
fetchMetadata?: (url: string) => Promise<Metadata | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ReactChat({ theme, community }: ReactChatProps) {
|
export function ReactChat({ theme, community, fetchMetadata }: ReactChatProps) {
|
||||||
const ref = useRef<HTMLHeadingElement>(null);
|
const ref = useRef<HTMLHeadingElement>(null);
|
||||||
return (
|
return (
|
||||||
<NarrowProvider myRef={ref}>
|
<NarrowProvider myRef={ref}>
|
||||||
<div ref={ref}>
|
<div ref={ref}>
|
||||||
<GlobalStyle />
|
<GlobalStyle />
|
||||||
<Chat theme={theme} community={community} />
|
<Chat
|
||||||
|
theme={theme}
|
||||||
|
community={community}
|
||||||
|
fetchMetadata={fetchMetadata}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</NarrowProvider>
|
</NarrowProvider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface Metadata {
|
||||||
|
"og:site_name": string;
|
||||||
|
"og:title": string;
|
||||||
|
"og:image": string;
|
||||||
|
}
|
49
yarn.lock
49
yarn.lock
|
@ -209,6 +209,14 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@dappconnect/preview-proxy@workspace:packages/preview-proxy":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@dappconnect/preview-proxy@workspace:packages/preview-proxy"
|
||||||
|
dependencies:
|
||||||
|
node-fetch: ^3.0.0
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"@dappconnect/react-chat-example@workspace:packages/react-chat-example":
|
"@dappconnect/react-chat-example@workspace:packages/react-chat-example":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@dappconnect/react-chat-example@workspace:packages/react-chat-example"
|
resolution: "@dappconnect/react-chat-example@workspace:packages/react-chat-example"
|
||||||
|
@ -275,6 +283,7 @@ __metadata:
|
||||||
copyfiles: ^2.4.1
|
copyfiles: ^2.4.1
|
||||||
emoji-mart: ^3.0.1
|
emoji-mart: ^3.0.1
|
||||||
eslint: ^7.32.0
|
eslint: ^7.32.0
|
||||||
|
html-entities: ^2.3.2
|
||||||
jsdom: ^16.7.0
|
jsdom: ^16.7.0
|
||||||
jsdom-global: ^3.0.2
|
jsdom-global: ^3.0.2
|
||||||
mocha: ^9.0.3
|
mocha: ^9.0.3
|
||||||
|
@ -3170,6 +3179,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"data-uri-to-buffer@npm:^3.0.1":
|
||||||
|
version: 3.0.1
|
||||||
|
resolution: "data-uri-to-buffer@npm:3.0.1"
|
||||||
|
checksum: c59c3009686a78c071806b72f4810856ec28222f0f4e252aa495ec027ed9732298ceea99c50328cf59b151dd34cbc3ad6150bbb43e41fc56fa19f48c99e9fc30
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"data-urls@npm:^2.0.0":
|
"data-urls@npm:^2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "data-urls@npm:2.0.0"
|
resolution: "data-urls@npm:2.0.0"
|
||||||
|
@ -4506,6 +4522,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"fetch-blob@npm:^3.1.2":
|
||||||
|
version: 3.1.2
|
||||||
|
resolution: "fetch-blob@npm:3.1.2"
|
||||||
|
dependencies:
|
||||||
|
web-streams-polyfill: ^3.0.3
|
||||||
|
checksum: 3e3717cf30da9f204aee83dded63f1a9f9c8bda7a0dc59648f89eeb1e88ee592231f4d922e1f119e1390383520768594dd3a1fe5e844f2f2f014d17ce04213a5
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"file-entry-cache@npm:^6.0.1":
|
"file-entry-cache@npm:^6.0.1":
|
||||||
version: 6.0.1
|
version: 6.0.1
|
||||||
resolution: "file-entry-cache@npm:6.0.1"
|
resolution: "file-entry-cache@npm:6.0.1"
|
||||||
|
@ -5295,6 +5320,13 @@ fsevents@~2.3.2:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"html-entities@npm:^2.3.2":
|
||||||
|
version: 2.3.2
|
||||||
|
resolution: "html-entities@npm:2.3.2"
|
||||||
|
checksum: 522d8d202df301ff51b517a379e642023ed5c81ea9fb5674ffad88cff386165733d00b6089d5c2fcc644e44777d6072017b6216d8fa40f271d3610420d00a886
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"html-minifier-terser@npm:^5.0.1":
|
"html-minifier-terser@npm:^5.0.1":
|
||||||
version: 5.1.1
|
version: 5.1.1
|
||||||
resolution: "html-minifier-terser@npm:5.1.1"
|
resolution: "html-minifier-terser@npm:5.1.1"
|
||||||
|
@ -7872,6 +7904,16 @@ fsevents@~2.3.2:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"node-fetch@npm:^3.0.0":
|
||||||
|
version: 3.0.0
|
||||||
|
resolution: "node-fetch@npm:3.0.0"
|
||||||
|
dependencies:
|
||||||
|
data-uri-to-buffer: ^3.0.1
|
||||||
|
fetch-blob: ^3.1.2
|
||||||
|
checksum: 50224bf682a0bc3d44faee0f38df6269d8ae646de343595ef37f9d94b4322d3763a49819fb7b2df9330fcae16e0a20e5fb129dfed8725cf0e8f720277db7611c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"node-forge@npm:^0.10.0":
|
"node-forge@npm:^0.10.0":
|
||||||
version: 0.10.0
|
version: 0.10.0
|
||||||
resolution: "node-forge@npm:0.10.0"
|
resolution: "node-forge@npm:0.10.0"
|
||||||
|
@ -11635,6 +11677,13 @@ resolve@^2.0.0-next.3:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"web-streams-polyfill@npm:^3.0.3":
|
||||||
|
version: 3.1.1
|
||||||
|
resolution: "web-streams-polyfill@npm:3.1.1"
|
||||||
|
checksum: dac85f0a990fb1ddcd15e2eda8ce4696bc9bc567e34cfdaeb9e740e26417d8649a6f466468907f50fd6e09967c25e0cf1f296c30aef9650ab7b118d5f69fb176
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"webidl-conversions@npm:^5.0.0":
|
"webidl-conversions@npm:^5.0.0":
|
||||||
version: 5.0.0
|
version: 5.0.0
|
||||||
resolution: "webidl-conversions@npm:5.0.0"
|
resolution: "webidl-conversions@npm:5.0.0"
|
||||||
|
|
Loading…
Reference in New Issue