add hover cards to wiki links

This commit is contained in:
hzrd149
2024-04-27 21:17:19 -05:00
parent 9efbb2eb58
commit 0d4e8c32a0
7 changed files with 302 additions and 62 deletions

View File

@@ -88,6 +88,7 @@
"react-use": "^17.4.0",
"react-virtualized-auto-sizer": "^1.0.20",
"remark-gfm": "^4.0.0",
"remark-wiki-link": "^2.0.1",
"three": "^0.160.0",
"three-spritetext": "^1.8.1",
"three-stdlib": "^2.29.4",

View File

@@ -1,6 +1,5 @@
import {
Code,
CodeProps,
Heading,
HeadingProps,
Image,
@@ -8,6 +7,15 @@ import {
LinkProps,
ListItem,
OrderedList,
Popover,
PopoverArrow,
PopoverBody,
PopoverCloseButton,
PopoverContent,
PopoverHeader,
PopoverTrigger,
Portal,
Spinner,
Table,
TableContainer,
TableProps,
@@ -20,12 +28,23 @@ import {
Thead,
Tr,
UnorderedList,
useDisclosure,
} from "@chakra-ui/react";
import styled from "@emotion/styled";
import { NostrEvent } from "nostr-tools";
import { forwardRef } from "react";
import Markdown, { Components } from "react-markdown";
import { forwardRef, useCallback, useMemo, useState } from "react";
import Markdown, { Components, ExtraProps } from "react-markdown";
import remarkGfm from "remark-gfm";
import wikiLinkPlugin from "remark-wiki-link";
import { Link as RouterLink } from "react-router-dom";
import { useReadRelays } from "../../../hooks/use-client-relays";
import { subscribeMany } from "../../../helpers/relay";
import { WIKI_PAGE_KIND, getPageSummary } from "../../../helpers/nostr/wiki";
import replaceableEventsService from "../../../services/replaceable-events";
import { getEventUID } from "nostr-idb";
import UserName from "../../../components/user/user-name";
import { getWebOfTrust } from "../../../services/web-of-trust";
import { getSharableEventAddress } from "../../../helpers/nip19";
const StyledMarkdown = styled(Markdown)`
pre > code {
@@ -35,63 +54,151 @@ const StyledMarkdown = styled(Markdown)`
}
`;
function H1({ children, ...props }: HeadingProps) {
function H1({ children, node, ...props }: HeadingProps & ExtraProps) {
return (
<Heading as="h1" size="2xl" mt="6" mb="2" {...props}>
{children}
</Heading>
);
}
function H2({ children, ...props }: HeadingProps) {
function H2({ children, node, ...props }: HeadingProps & ExtraProps) {
return (
<Heading as="h2" size="xl" mt="6" mb="2" {...props}>
{children}
</Heading>
);
}
function H3({ children, ...props }: HeadingProps) {
function H3({ children, node, ...props }: HeadingProps & ExtraProps) {
return (
<Heading as="h3" size="lg" mt="4" mb="2" {...props}>
{children}
</Heading>
);
}
function H4({ children, ...props }: HeadingProps) {
function H4({ children, node, ...props }: HeadingProps & ExtraProps) {
return (
<Heading as="h4" size="md" my="2" {...props}>
{children}
</Heading>
);
}
function H5({ children, ...props }: HeadingProps) {
function H5({ children, node, ...props }: HeadingProps & ExtraProps) {
return (
<Heading as="h5" size="sm" my="2" {...props}>
{children}
</Heading>
);
}
function H6({ children, ...props }: HeadingProps) {
function H6({ children, node, ...props }: HeadingProps & ExtraProps) {
return (
<Heading as="h6" size="xs" my="2" {...props}>
{children}
</Heading>
);
}
function A({ children, ...props }: LinkProps) {
const MAX_VERSIONS = 4;
function WikiLink({ children, node, href, ...props }: LinkProps & ExtraProps) {
const { isOpen, onClose, onOpen } = useDisclosure();
const readRelays = useReadRelays();
const properties = node!.properties as { className: string; href: string };
const topic = properties.href.replace(/^#\/page\//, "");
const [events, setEvents] = useState<NostrEvent[]>();
const load = useCallback(() => {
const arr: NostrEvent[] = [];
const sub = subscribeMany(Array.from(readRelays), [{ kinds: [WIKI_PAGE_KIND], "#d": [topic] }], {
onevent: (event) => {
replaceableEventsService.handleEvent(event);
if (event.content) arr.push(event);
},
oneose: () => {
setEvents(arr);
sub.close();
},
});
}, [topic, setEvents, readRelays]);
const open = useCallback(() => {
if (!events) load();
onOpen();
}, [onOpen, events]);
const sorted = useMemo(() => {
if (!events) return [];
const arr = getWebOfTrust().sortByDistanceAndConnections(events, (e) => e.pubkey);
const seen = new Set<string>();
const unique: NostrEvent[] = [];
for (const event of arr) {
const summary = getPageSummary(event);
if (!seen.has(summary)) {
seen.add(summary);
unique.push(event);
if (unique.length >= MAX_VERSIONS) break;
}
}
return unique;
}, [events]);
// if there is only one result, redirect to it
const to = events?.length === 1 ? "/wiki/page/" + getSharableEventAddress(events[0]) : "/wiki/topic/" + topic;
return (
<Link color="blue.500" isExternal {...props}>
<Popover returnFocusOnClose={false} isOpen={isOpen} onClose={onClose} placement="top" closeOnBlur={true}>
<PopoverTrigger>
<Link as={RouterLink} color="blue.500" {...props} to={to} onMouseEnter={open} onMouseLeave={onClose}>
{children}
</Link>
</PopoverTrigger>
<Portal>
<PopoverContent w="lg">
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader fontWeight="bold">{children}</PopoverHeader>
<PopoverBody>
{events === undefined && <Spinner />}
{sorted.map((page) => (
<Text key={getEventUID(page)} noOfLines={2} mb="2">
<UserName pubkey={page.pubkey} />: {getPageSummary(page)}
</Text>
))}
{events?.length === 0 && <Text fontStyle="italic">There is no entry for this topic</Text>}
</PopoverBody>
</PopoverContent>
</Portal>
</Popover>
);
}
function A({ children, node, href, ...props }: LinkProps & ExtraProps) {
const properties: { className?: string; href?: string } | undefined = node?.properties;
if (properties?.className?.includes("internal") && properties.href) {
return (
<WikiLink href={href} node={node} {...props}>
{children}
</WikiLink>
);
}
return (
<Link color="blue.500" isExternal href={href} {...props}>
{children}
</Link>
);
}
function P({ children, ...props }: TextProps) {
function P({ children, node, ...props }: TextProps & ExtraProps) {
return (
<Text my="2" {...props}>
{children}
</Text>
);
}
function TableWithContainer({ children, ...props }: TableProps) {
function TableWithContainer({ children, node, ...props }: TableProps & ExtraProps) {
return (
<TableContainer>
<Table size="sm" mb="4" {...props}>
@@ -127,7 +234,7 @@ const components: Partial<Components> = {
export const CharkaMarkdown = forwardRef<HTMLDivElement, { children: string }>(({ children }, ref) => {
return (
<div ref={ref}>
<StyledMarkdown remarkPlugins={[remarkGfm]} components={components}>
<StyledMarkdown remarkPlugins={[remarkGfm, wikiLinkPlugin]} components={components}>
{children}
</StyledMarkdown>
</div>

View File

@@ -11,6 +11,7 @@ import Timestamp from "../../../components/timestamp";
import FileSearch01 from "../../../components/icons/file-search-01";
import GitBranch01 from "../../../components/icons/git-branch-01";
import UserName from "../../../components/user/user-name";
import UserAvatar from "../../../components/user/user-avatar";
export default function WikiPageResult({ page, compare }: { page: NostrEvent; compare?: NostrEvent }) {
const topic = getPageTopic(page);
@@ -20,41 +21,42 @@ export default function WikiPageResult({ page, compare }: { page: NostrEvent; co
return (
<Flex as={LinkBox} py="2" px="4" direction="column">
<Box overflow="hidden">
<Heading size="md">
<HoverLinkOverlay as={RouterLink} to={`/wiki/page/${getSharableEventAddress(page)}`}>
{getPageTitle(page)}
</HoverLinkOverlay>
</Heading>
<Text>
by <UserLink pubkey={page.pubkey} fontWeight="bold " /> - <Timestamp timestamp={page.created_at} />
</Text>
<Text color="GrayText" noOfLines={2}>
{getPageSummary(page)}
</Text>
<Flex gap="2" wrap="wrap">
<Heading size="md">
<HoverLinkOverlay as={RouterLink} to={`/wiki/page/${getSharableEventAddress(page)}`}>
{getPageTitle(page)}
</HoverLinkOverlay>
</Heading>
</Flex>
<Text noOfLines={2}>{getPageSummary(page)}</Text>
</Box>
<ButtonGroup variant="link" mt="auto">
{address && (
<Button
as={RouterLink}
to={`/wiki/page/${nip19.naddrEncode(address)}`}
p="2"
colorScheme="blue"
leftIcon={<GitBranch01 />}
>
<UserName pubkey={address.pubkey} />
</Button>
)}
{compare && (
<Button
as={RouterLink}
to={`/wiki/compare/${topic}/${compare.pubkey}/${page.pubkey}`}
leftIcon={<FileSearch01 />}
ml="auto"
>
Compare
</Button>
)}
</ButtonGroup>
<Flex gap="2" alignItems="center" mt="auto">
<UserAvatar pubkey={page.pubkey} size="xs" />
<UserLink pubkey={page.pubkey} fontWeight="bold " />
<ButtonGroup variant="link" flex={1}>
{address && (
<Button
as={RouterLink}
to={`/wiki/page/${nip19.naddrEncode(address)}`}
p="2"
colorScheme="blue"
leftIcon={<GitBranch01 />}
>
<UserName pubkey={address.pubkey} />
</Button>
)}
{compare && (
<Button
as={RouterLink}
to={`/wiki/compare/${topic}/${compare.pubkey}/${page.pubkey}`}
leftIcon={<FileSearch01 />}
ml="auto"
>
Compare
</Button>
)}
</ButtonGroup>
</Flex>
</Flex>
);
}

View File

@@ -1,12 +1,13 @@
import { useMemo, useRef, useState } from "react";
import { Button, Flex, FormControl, FormLabel, Heading, Input, VisuallyHidden, useToast } from "@chakra-ui/react";
import SimpleMDE, { SimpleMDEReactProps } from "react-simplemde-editor";
import { useNavigate } from "react-router-dom";
import { useNavigate, useSearchParams } from "react-router-dom";
import ReactDOMServer from "react-dom/server";
import { useForm } from "react-hook-form";
import { EventTemplate } from "nostr-tools";
import dayjs from "dayjs";
import EasyMDE from "easymde";
import "easymde/dist/easymde.min.css";
import VerticalPageLayout from "../../components/vertical-page-layout";
@@ -16,8 +17,7 @@ import { WIKI_PAGE_KIND } from "../../helpers/nostr/wiki";
import { getSharableEventAddress } from "../../helpers/nip19";
import { WIKI_RELAYS } from "../../const";
import useAppSettings from "../../hooks/use-app-settings";
import EasyMDE from "easymde";
import { getServersFromEvent, uploadFileToServers } from "../../helpers/media-upload/blossom";
import { uploadFileToServers } from "../../helpers/media-upload/blossom";
import useUsersMediaServers from "../../hooks/use-user-media-servers";
import { useSigningContext } from "../../providers/global/signing-provider";
import useCurrentAccount from "../../hooks/use-current-account";
@@ -27,18 +27,27 @@ import useCacheForm from "../../hooks/use-cache-form";
export default function CreateWikiPageView() {
const account = useCurrentAccount();
const { mediaUploadService } = useAppSettings();
const servers = useUsersMediaServers(account?.pubkey);
const { servers } = useUsersMediaServers(account?.pubkey);
const toast = useToast();
const { requestSignature } = useSigningContext();
const publish = usePublishEvent();
const navigate = useNavigate();
const [search] = useSearchParams();
const presetTopic = search.get("topic");
const presetTitle = search.get("title");
const { register, setValue, getValues, handleSubmit, watch, formState, reset } = useForm({
defaultValues: { content: "", title: "", topic: "" },
defaultValues: { content: "", title: presetTitle || presetTopic || "", topic: presetTopic || "" },
mode: "all",
});
// @ts-expect-error
useCacheForm("wiki-page", getValues, setValue, formState);
const clearFormCache = useCacheForm(
presetTopic ? "wiki-" + presetTopic : "wiki-create-page",
// @ts-expect-error
getValues,
setValue,
formState,
);
watch("content");
register("content", {
@@ -59,6 +68,7 @@ export default function CreateWikiPageView() {
};
const pub = await publish("Publish Page", draft, WIKI_RELAYS, false);
clearFormCache();
navigate(`/wiki/page/${getSharableEventAddress(pub.event)}`);
} catch (error) {
if (error instanceof Error) toast({ description: error.message, status: "error" });
@@ -72,7 +82,7 @@ export default function CreateWikiPageView() {
async function imageUploadFunction(file: File, onSuccess: (url: string) => void, onError: (error: string) => void) {
if (!servers) return onError("No media servers set");
try {
const blob = await uploadFileToServers(getServersFromEvent(servers), file, requestSignature);
const blob = await uploadFileToServers(servers, file, requestSignature);
if (blob) onSuccess(blob.url);
} catch (error) {
if (error instanceof Error) onError(error.message);

View File

@@ -1,4 +1,4 @@
import { Box, Button, Flex, Heading, SimpleGrid } from "@chakra-ui/react";
import { Button, Flex, Heading, SimpleGrid } from "@chakra-ui/react";
import { Link } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";
import { NostrEvent } from "nostr-tools";
@@ -9,7 +9,6 @@ import { WIKI_PAGE_KIND, validatePage } from "../../helpers/nostr/wiki";
import useTimelineLoader from "../../hooks/use-timeline-loader";
import { useReadRelays } from "../../hooks/use-client-relays";
import useSubject from "../../hooks/use-subject";
import { getWebOfTrust } from "../../services/web-of-trust";
import WikiPageResult from "./components/wiki-page-result";
import TimelineActionAndStatus from "../../components/timeline-page/timeline-action-and-status";
import { ErrorBoundary } from "../../components/error-boundary";
@@ -26,7 +25,6 @@ export default function WikiHomeView() {
const timeline = useTimelineLoader(`wiki-recent-pages`, relays, [{ kinds: [WIKI_PAGE_KIND] }], { eventFilter });
const pages = useSubject(timeline.timeline).filter((p) => p.content.length > 0);
const sorted = getWebOfTrust().sortByDistanceAndConnections(pages, (p) => p.pubkey);
return (
<VerticalPageLayout>
@@ -49,7 +47,7 @@ export default function WikiHomeView() {
Recent Updates:
</Heading>
<SimpleGrid spacing="2" columns={{ base: 1, lg: 2, xl: 3 }}>
{sorted.map((page) => (
{pages.slice(0, 32).map((page) => (
<ErrorBoundary key={page.id}>
<WikiPageResult page={page} />
</ErrorBoundary>

View File

@@ -1,5 +1,5 @@
import { Heading } from "@chakra-ui/react";
import { Navigate, useParams } from "react-router-dom";
import { Heading, Link } from "@chakra-ui/react";
import { Navigate, useParams, Link as RouterLink } from "react-router-dom";
import VerticalPageLayout from "../../components/vertical-page-layout";
import useSubject from "../../hooks/use-subject";
@@ -23,6 +23,15 @@ export default function WikiTopicView() {
{sorted.map((page) => (
<WikiPageResult key={page.id} page={page} />
))}
{sorted.length === 0 && (
<Heading mx="auto" size="md" mt="8">
Looks like there are no pages,{" "}
<Link as={RouterLink} to={{ pathname: "/wiki/create", search: "topic=" + topic }} color="blue.500">
Create one?
</Link>
</Heading>
)}
</VerticalPageLayout>
);
}

113
yarn.lock
View File

@@ -942,6 +942,13 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.12.1", "@babel/runtime@^7.4.4":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd"
integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.22.15", "@babel/template@^7.23.9":
version "7.23.9"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a"
@@ -3577,16 +3584,31 @@ character-entities-html4@^2.0.0:
resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b"
integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==
character-entities-legacy@^1.0.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1"
integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==
character-entities-legacy@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b"
integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==
character-entities@^1.0.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b"
integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==
character-entities@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22"
integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==
character-reference-invalid@^1.0.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560"
integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==
character-reference-invalid@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9"
@@ -4989,11 +5011,24 @@ invariant@^2.2.4:
dependencies:
loose-envify "^1.0.0"
is-alphabetical@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d"
integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==
is-alphabetical@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz#01072053ea7c1036df3c7d19a6daaec7f19e789b"
integrity sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==
is-alphanumerical@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf"
integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==
dependencies:
is-alphabetical "^1.0.0"
is-decimal "^1.0.0"
is-alphanumerical@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz#7c03fbe96e3e931113e57f964b0a368cc2dfd875"
@@ -5049,6 +5084,11 @@ is-date-object@^1.0.1:
dependencies:
has-tostringtag "^1.0.0"
is-decimal@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5"
integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==
is-decimal@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-2.0.1.tgz#9469d2dc190d0214fd87d78b78caecc0cc14eef7"
@@ -5071,6 +5111,11 @@ is-glob@^4.0.1:
dependencies:
is-extglob "^2.1.1"
is-hexadecimal@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7"
integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==
is-hexadecimal@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027"
@@ -5414,6 +5459,11 @@ lodash@^4.17.20, lodash@^4.17.21:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
longest-streak@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4"
integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==
longest-streak@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4"
@@ -5642,6 +5692,18 @@ mdast-util-to-hast@^13.0.0:
unist-util-visit "^5.0.0"
vfile "^6.0.0"
mdast-util-to-markdown@^0.6.5:
version "0.6.5"
resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe"
integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==
dependencies:
"@types/unist" "^2.0.0"
longest-streak "^2.0.0"
mdast-util-to-string "^2.0.0"
parse-entities "^2.0.0"
repeat-string "^1.0.0"
zwitch "^1.0.0"
mdast-util-to-markdown@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz#9813f1d6e0cdaac7c244ec8c6dabfdb2102ea2b4"
@@ -5656,6 +5718,11 @@ mdast-util-to-markdown@^2.0.0:
unist-util-visit "^5.0.0"
zwitch "^2.0.0"
mdast-util-to-string@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b"
integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==
mdast-util-to-string@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814"
@@ -5663,6 +5730,14 @@ mdast-util-to-string@^4.0.0:
dependencies:
"@types/mdast" "^4.0.0"
mdast-util-wiki-link@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/mdast-util-wiki-link/-/mdast-util-wiki-link-0.1.2.tgz#df664e4a22ef533666f5012cf0b34ba187b9f1c0"
integrity sha512-DTcDyOxKDo3pB3fc0zQlD8myfQjYkW4hazUKI9PUyhtoj9JBeHC2eIdlVXmaT22bZkFAVU2d47B6y2jVKGoUQg==
dependencies:
"@babel/runtime" "^7.12.1"
mdast-util-to-markdown "^0.6.5"
mdn-data@2.0.14:
version "2.0.14"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
@@ -5806,6 +5881,13 @@ micromark-extension-gfm@^3.0.0:
micromark-util-combine-extensions "^2.0.0"
micromark-util-types "^2.0.0"
micromark-extension-wiki-link@^0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/micromark-extension-wiki-link/-/micromark-extension-wiki-link-0.0.4.tgz#f4750a0f24051bf0521bbafaf64f291f9266d2a4"
integrity sha512-dJc8AfnoU8BHkN+7fWZvIS20SMsMS1ZlxQUn6We67MqeKbOiEDZV5eEvCpwqGBijbJbxX3Kxz879L4K9HIiOvw==
dependencies:
"@babel/runtime" "^7.12.1"
micromark-factory-destination@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz#857c94debd2c873cba34e0445ab26b74f6a6ec07"
@@ -6300,6 +6382,18 @@ parent-module@^1.0.0:
dependencies:
callsites "^3.0.0"
parse-entities@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8"
integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==
dependencies:
character-entities "^1.0.0"
character-entities-legacy "^1.0.0"
character-reference-invalid "^1.0.0"
is-alphanumerical "^1.0.0"
is-decimal "^1.0.0"
is-hexadecimal "^1.0.0"
parse-entities@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.1.tgz#4e2a01111fb1c986549b944af39eeda258fc9e4e"
@@ -6916,11 +7010,25 @@ remark-stringify@^11.0.0:
mdast-util-to-markdown "^2.0.0"
unified "^11.0.0"
remark-wiki-link@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/remark-wiki-link/-/remark-wiki-link-2.0.1.tgz#52ffdcfe16e3e018874b890387ea02668e882d10"
integrity sha512-F8Eut1E7GWfFm4ZDTI6/4ejeZEHZgnVk6E933Yqd/ssYsc4AyI32aGakxwsGcEzbbE7dkWi1EfLlGAdGgOZOsA==
dependencies:
"@babel/runtime" "^7.4.4"
mdast-util-wiki-link "^0.1.2"
micromark-extension-wiki-link "^0.0.4"
remove-accents@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.5.0.tgz#77991f37ba212afba162e375b627631315bed687"
integrity sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==
repeat-string@^1.0.0:
version "1.6.1"
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -8254,6 +8362,11 @@ zustand@^4.4.7:
dependencies:
use-sync-external-store "1.2.0"
zwitch@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"
integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==
zwitch@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"