Cursorless enablement group page (#1660)
See [deploy preview](https://deploy-preview-1660--cursorless.netlify.app/enablement-group) - Also adds support for mdx in our top-level cursorless-org package ## Checklist - [x] Add meta social tags - [x] Use latest logo - [x] Why is logo on social slow? And is it new logo? - [x] Make prices clickable - [x] document that sponsorship levels are yearly - [-] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [-] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [-] I have not broken the cheatsheet --------- Co-authored-by: F-Kunkle <140621314+F-Kunkle@users.noreply.github.com>
BIN
images/logo-white.png
Normal file
After Width: | Height: | Size: 54 KiB |
15
packages/cursorless-org/mdx-components.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import type { MDXComponents } from "mdx/types";
|
||||
|
||||
// This file allows you to provide custom React components
|
||||
// to be used in MDX files. You can import and use any
|
||||
// React component you want, including components from
|
||||
// other libraries.
|
||||
|
||||
// This file is required to use MDX in `app` directory.
|
||||
export function useMDXComponents(components: MDXComponents): MDXComponents {
|
||||
return {
|
||||
// Allows customizing built-in components, e.g. to add styling.
|
||||
// h1: ({ children }) => <h1 style={{ fontSize: "100px" }}>{children}</h1>,
|
||||
...components,
|
||||
};
|
||||
}
|
@ -1,3 +1,9 @@
|
||||
const withMDX = require("@next/mdx")({
|
||||
options: {
|
||||
providerImportSource: "@mdx-js/react",
|
||||
},
|
||||
});
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
webpack(config) {
|
||||
@ -9,7 +15,10 @@ const nextConfig = {
|
||||
|
||||
return config;
|
||||
},
|
||||
experimental: {
|
||||
mdxRs: true,
|
||||
},
|
||||
reactStrictMode: true,
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
module.exports = withMDX(nextConfig);
|
||||
|
@ -14,6 +14,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@cursorless/cheatsheet": "workspace:*",
|
||||
"@mdx-js/loader": "2.3.0",
|
||||
"@mdx-js/react": "2.3.0",
|
||||
"@next/mdx": "13.4.10",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-config-next": "13.5.4",
|
||||
"next": "13.5.4",
|
||||
@ -24,6 +27,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@svgr/webpack": "6.5.1",
|
||||
"@types/mdx": "2.0.5",
|
||||
"@types/mdx-js__react": "1.5.5",
|
||||
"@types/node": "^16.11.3",
|
||||
"@types/react": "18.0.28",
|
||||
"@types/react-dom": "18.0.11",
|
||||
|
BIN
packages/cursorless-org/public/andrew-dant.jpeg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
packages/cursorless-org/public/big-hats.png
Normal file
After Width: | Height: | Size: 118 KiB |
BIN
packages/cursorless-org/public/fonts/Inconsolata-Bold.ttf
Normal file
BIN
packages/cursorless-org/public/fonts/Inconsolata-ExtraLight.ttf
Normal file
BIN
packages/cursorless-org/public/fonts/Inconsolata-Light.ttf
Normal file
BIN
packages/cursorless-org/public/fonts/Inconsolata-Medium.ttf
Normal file
BIN
packages/cursorless-org/public/fonts/Inconsolata-Regular.ttf
Normal file
BIN
packages/cursorless-org/public/fonts/Inconsolata-SemiBold.ttf
Normal file
BIN
packages/cursorless-org/public/james-stout.jpeg
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
packages/cursorless-org/public/max-foxley-marrable.jpeg
Normal file
After Width: | Height: | Size: 148 KiB |
BIN
packages/cursorless-org/public/nathan-heffley.jpeg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
packages/cursorless-org/public/sohee-yang.jpeg
Normal file
After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 166 KiB |
@ -1,17 +1,34 @@
|
||||
import {
|
||||
DESCRIPTION,
|
||||
BASE_URL,
|
||||
VIDEO_SHARE_THUMBNAIL_URL,
|
||||
YOUTUBE_SLUG,
|
||||
TITLE,
|
||||
VIDEO_SHARE_THUMBNAIL_WIDTH,
|
||||
VIDEO_SHARE_THUMBNAIL_HEIGHT,
|
||||
VIDEO_SHARE_THUMBNAIL_URL,
|
||||
VIDEO_SHARE_THUMBNAIL_WIDTH,
|
||||
} from "./constants";
|
||||
|
||||
export default function Social() {
|
||||
export interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
relativeUrl: string;
|
||||
youtubeSlug?: string;
|
||||
thumbnailUrl?: string;
|
||||
thumbnailWidth?: string;
|
||||
thumbnailHeight?: string;
|
||||
}
|
||||
|
||||
export default function BaseSocial({
|
||||
title,
|
||||
description,
|
||||
relativeUrl,
|
||||
youtubeSlug,
|
||||
thumbnailUrl = VIDEO_SHARE_THUMBNAIL_URL,
|
||||
thumbnailWidth = VIDEO_SHARE_THUMBNAIL_WIDTH,
|
||||
thumbnailHeight = VIDEO_SHARE_THUMBNAIL_HEIGHT,
|
||||
}: Props) {
|
||||
const url = `${BASE_URL}/${relativeUrl}`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<meta property="og:title" content={TITLE} key="title" />
|
||||
<meta property="og:title" content={title} key="title" />
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
@ -31,30 +48,63 @@ export default function Social() {
|
||||
/>
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<meta property="og:site_name" content="Cursorless" />
|
||||
<meta property="og:url" content={BASE_URL} />
|
||||
<meta property="og:image" content={VIDEO_SHARE_THUMBNAIL_URL} />
|
||||
<meta property="og:image:width" content={VIDEO_SHARE_THUMBNAIL_WIDTH} />
|
||||
<meta property="og:image:height" content={VIDEO_SHARE_THUMBNAIL_HEIGHT} />
|
||||
<meta property="og:description" content={DESCRIPTION} />
|
||||
<meta property="og:url" content={url} />
|
||||
<meta property="og:image" content={thumbnailUrl} />
|
||||
<meta property="og:image:width" content={thumbnailWidth} />
|
||||
<meta property="og:image:height" content={thumbnailHeight} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:type" content="video" />
|
||||
{youtubeSlug != null ? (
|
||||
<VideoSocial youtubeSlug={youtubeSlug} />
|
||||
) : (
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
)}
|
||||
<meta name="twitter:site" content="@GoCursorless" />
|
||||
<meta name="twitter:url" content={url} />
|
||||
<meta name="twitter:title" content="Cursorless" />
|
||||
<meta name="twitter:description" content={description} />
|
||||
<meta name="twitter:image" content={thumbnailUrl} />
|
||||
<link itemProp="url" href={url} />
|
||||
<meta itemProp="name" content="Cursorless" />
|
||||
<meta itemProp="description" content={description} />
|
||||
<meta name="description" content={description} />
|
||||
<meta itemProp="paid" content="false" />
|
||||
<meta itemProp="channelId" content="UCIh61mLlS6Do3R_8KnEScIQ" />
|
||||
<link itemProp="thumbnailUrl" href={thumbnailUrl} />
|
||||
<meta itemProp="isFamilyFriendly" content="true" />
|
||||
<meta
|
||||
itemProp="regionsAllowed"
|
||||
content="HK,HT,TC,BW,PA,FK,AW,TN,AU,GE,SL,CC,TF,PN,TZ,CL,ET,BN,AR,PH,VI,EE,MY,LB,BM,UG,LU,NZ,KR,GG,BJ,SO,HM,GT,PR,IT,AZ,ZA,MH,MF,CW,UY,MN,MQ,MW,SE,PT,MK,SR,MA,RS,GQ,NP,BD,FM,GD,KI,IL,CK,YE,ML,BF,AO,SG,CG,GS,BI,CY,LR,UM,GH,BR,GY,KP,PM,IO,EH,SK,LV,AQ,IN,RE,LY,ZW,SZ,HR,LT,KE,TT,CR,KW,ER,NF,TK,BE,JM,SA,BH,RO,BO,MM,TH,IE,TD,QA,CN,FR,SC,VU,MG,SY,JP,PS,JO,MV,MD,TL,BY,GN,TJ,DE,TO,TR,BT,FJ,TW,AE,ES,DO,BS,NO,GU,DK,KH,SD,GB,ZM,VE,SS,IQ,AD,KG,NI,PK,PL,CZ,NA,LC,PY,SV,LA,AI,YT,US,VC,IR,NL,NU,AS,AL,GR,SH,GM,LS,ME,TV,EG,CF,DZ,SX,CA,PF,KM,AF,HN,NE,CD,MX,NC,CM,CX,SJ,GW,GF,VG,TG,BA,GP,CV,BQ,MO,SN,CH,BZ,MP,PE,FI,BB,GI,IS,PG,SM,BL,BG,AX,AM,AT,AG,ID,CI,GA,MC,NG,RW,SI,BV,UA,UZ,SB,LI,CU,VN,KN,WS,LK,IM,TM,OM,KY,VA,MT,MZ,DJ,EC,DM,HU,MU,FO,JE,NR,CO,WF,KZ,MR,GL,RU,MS,PW,ST"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface VideoProps {
|
||||
youtubeSlug: string;
|
||||
}
|
||||
|
||||
function VideoSocial({ youtubeSlug }: VideoProps) {
|
||||
return (
|
||||
<>
|
||||
<meta
|
||||
property="og:video:url"
|
||||
content={`https://www.youtube.com/embed/${YOUTUBE_SLUG}`}
|
||||
content={`https://www.youtube.com/embed/${youtubeSlug}`}
|
||||
/>
|
||||
<meta
|
||||
property="og:video:secure_url"
|
||||
content={`https://www.youtube.com/embed/${YOUTUBE_SLUG}`}
|
||||
content={`https://www.youtube.com/embed/${youtubeSlug}`}
|
||||
/>
|
||||
<meta property="og:video:type" content="text/html" />
|
||||
<meta property="og:video:width" content="1280" />
|
||||
<meta property="og:video:height" content="720" />
|
||||
<meta
|
||||
property="og:video:url"
|
||||
content={`http://www.youtube.com/v/${YOUTUBE_SLUG}?version=3&autohide=1`}
|
||||
content={`http://www.youtube.com/v/${youtubeSlug}?version=3&autohide=1`}
|
||||
/>
|
||||
<meta
|
||||
property="og:video:secure_url"
|
||||
content={`https://www.youtube.com/v/${YOUTUBE_SLUG}?version=3&autohide=1`}
|
||||
content={`https://www.youtube.com/v/${youtubeSlug}?version=3&autohide=1`}
|
||||
/>
|
||||
<meta property="og:video:type" content="application/x-shockwave-flash" />
|
||||
<meta property="og:video:width" content="1280" />
|
||||
@ -67,28 +117,12 @@ export default function Social() {
|
||||
<meta property="og:video:tag" content="Talon voice" />
|
||||
|
||||
<meta name="twitter:card" content="player" />
|
||||
<meta name="twitter:site" content="@GoCursorless" />
|
||||
<meta name="twitter:url" content={BASE_URL} />
|
||||
<meta name="twitter:title" content="Cursorless" />
|
||||
<meta name="twitter:description" content={DESCRIPTION} />
|
||||
<meta name="twitter:image" content={VIDEO_SHARE_THUMBNAIL_URL} />
|
||||
<meta
|
||||
name="twitter:player"
|
||||
content={`https://www.youtube.com/embed/${YOUTUBE_SLUG}`}
|
||||
content={`https://www.youtube.com/embed/${youtubeSlug}`}
|
||||
/>
|
||||
<meta name="twitter:player:width" content="1280" />
|
||||
<meta name="twitter:player:height" content="720" />
|
||||
<link itemProp="url" href={BASE_URL} />
|
||||
<meta itemProp="name" content="Cursorless" />
|
||||
<meta itemProp="description" content={DESCRIPTION} />
|
||||
<meta itemProp="paid" content="false" />
|
||||
<meta itemProp="channelId" content="UCIh61mLlS6Do3R_8KnEScIQ" />
|
||||
<link itemProp="thumbnailUrl" href={VIDEO_SHARE_THUMBNAIL_URL} />
|
||||
<meta itemProp="isFamilyFriendly" content="true" />
|
||||
<meta
|
||||
itemProp="regionsAllowed"
|
||||
content="HK,HT,TC,BW,PA,FK,AW,TN,AU,GE,SL,CC,TF,PN,TZ,CL,ET,BN,AR,PH,VI,EE,MY,LB,BM,UG,LU,NZ,KR,GG,BJ,SO,HM,GT,PR,IT,AZ,ZA,MH,MF,CW,UY,MN,MQ,MW,SE,PT,MK,SR,MA,RS,GQ,NP,BD,FM,GD,KI,IL,CK,YE,ML,BF,AO,SG,CG,GS,BI,CY,LR,UM,GH,BR,GY,KP,PM,IO,EH,SK,LV,AQ,IN,RE,LY,ZW,SZ,HR,LT,KE,TT,CR,KW,ER,NF,TK,BE,JM,SA,BH,RO,BO,MM,TH,IE,TD,QA,CN,FR,SC,VU,MG,SY,JP,PS,JO,MV,MD,TL,BY,GN,TJ,DE,TO,TR,BT,FJ,TW,AE,ES,DO,BS,NO,GU,DK,KH,SD,GB,ZM,VE,SS,IQ,AD,KG,NI,PK,PL,CZ,NA,LC,PY,SV,LA,AI,YT,US,VC,IR,NL,NU,AS,AL,GR,SH,GM,LS,ME,TV,EG,CF,DZ,SX,CA,PF,KM,AF,HN,NE,CD,MX,NC,CM,CX,SJ,GW,GF,VG,TG,BA,GP,CV,BQ,MO,SN,CH,BZ,MP,PE,FI,BB,GI,IS,PG,SM,BL,BG,AX,AM,AT,AG,ID,CI,GA,MC,NG,RW,SI,BV,UA,UZ,SB,LI,CU,VN,KN,WS,LK,IM,TM,OM,KY,VA,MT,MZ,DJ,EC,DM,HU,MU,FO,JE,NR,CO,WF,KZ,MR,GL,RU,MS,PW,ST"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
13
packages/cursorless-org/src/components/IndexSocial.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import BaseSocial from "./BaseSocial";
|
||||
import { DESCRIPTION, TITLE, VIDEO_SHARE_THUMBNAIL_URL } from "./constants";
|
||||
|
||||
export default function IndexSocial() {
|
||||
return (
|
||||
<BaseSocial
|
||||
title={TITLE}
|
||||
description={DESCRIPTION}
|
||||
youtubeSlug={VIDEO_SHARE_THUMBNAIL_URL}
|
||||
relativeUrl=""
|
||||
/>
|
||||
);
|
||||
}
|
143
packages/cursorless-org/src/components/Layout.tsx
Normal file
@ -0,0 +1,143 @@
|
||||
import { MDXProvider } from "@mdx-js/react";
|
||||
import type { MDXComponents } from "mdx/types.js";
|
||||
import Head from "next/head";
|
||||
import Logo from "../pages/logo.svg";
|
||||
import BaseSocial from "./BaseSocial";
|
||||
import { SpamProofEmailLink } from "./SpamProofEmailLink";
|
||||
import Link from "next/link";
|
||||
|
||||
const components: MDXComponents = {
|
||||
h1: ({ children }) => (
|
||||
<h1 className="text-center uppercase text-[1.88em] leading-tight mt-7 tracking-[0.14em] font-semibold">
|
||||
{children}
|
||||
</h1>
|
||||
),
|
||||
h2: ({ children }) => (
|
||||
<h2 className="uppercase text-[1.4em] mt-8 mb-4 sm:mb-8 font-semibold tracking-[0.08em]">
|
||||
{children}
|
||||
</h2>
|
||||
),
|
||||
h3: ({ children }) => (
|
||||
<h3 className="uppercase text-[1.5rem] mt-6 mb-3 sm:mb-6 font-medium tracking-[0.08em]">
|
||||
{children}
|
||||
</h3>
|
||||
),
|
||||
h4: ({ children }) => (
|
||||
<h4 className="uppercase text-[1.5rem] mt-11 mb-3 sm:mb-6 font-medium tracking-[0.08em]">
|
||||
{children}
|
||||
</h4>
|
||||
),
|
||||
hr: () => <hr className="my-8 border-teal-400" />,
|
||||
ul: ({ children }) => <ul className="list-disc ml-8">{children}</ul>,
|
||||
ol: ({ children }) => <ol className="list-decimal ml-8">{children}</ol>,
|
||||
li: ({ children }) => <li className="my-2">{children}</li>,
|
||||
img: ({ src, alt }) => (
|
||||
// FIXME: Figure out how to use next/image with MDX
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img
|
||||
className="mx-auto my-12 rounded-[4px] border-teal-400 border-[1.5px]"
|
||||
src={src}
|
||||
alt={alt}
|
||||
style={{ maxWidth: "100%" }}
|
||||
/>
|
||||
),
|
||||
CursorlessScreenshot: ({ src, alt }) => (
|
||||
// FIXME: Figure out how to use next/image with MDX
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img
|
||||
className="mx-auto my-12 border-teal-400 border p-3 sm:p-6 rounded-sm"
|
||||
src={src}
|
||||
alt={alt}
|
||||
style={{ maxWidth: "100%" }}
|
||||
/>
|
||||
),
|
||||
CalloutParent: ({ children }) => (
|
||||
<div className="border-teal-400 border rounded-sm px-7 my-12">
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
CalloutBox: ({ title, children }) => (
|
||||
<div className="my-6">
|
||||
<h4 className="uppercase text-[1.5rem] mb-3 sm:mb-6 leading-tight font-medium tracking-[0.08em]">
|
||||
{title}
|
||||
</h4>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
Testimonials: ({ children }) => (
|
||||
<div className="flex flex-col gap-5 mt-8">{children}</div>
|
||||
),
|
||||
Testimonial: ({ children, src, name, title, company }) => (
|
||||
<div className="flex flex-col items-center bg-teal-100 dark:bg-teal-900 border border-teal-400 text-teal-700 dark:text-teal-300 p-3 sm:p-6 rounded-sm">
|
||||
<blockquote className="mb-5 sm:mb-6 flex flex-col gap-4">
|
||||
{children}
|
||||
</blockquote>
|
||||
<div className="flex items-center gap-4">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
className="rounded-full w-[4.5em] h-[4.5em] border-teal-400 border dark:border-[0.5px]"
|
||||
src={src}
|
||||
alt={name}
|
||||
/>
|
||||
<div className="flex flex-col gap-[0.375rem]">
|
||||
<div className="text-teal-800 dark:text-teal-200 font-semibold text-[1.2em] leading-none">
|
||||
{name}
|
||||
</div>
|
||||
<div className="text-[0.9em] leading-none">{title}</div>
|
||||
<div className="text-[0.9em] leading-none">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
Tiers: ({ children }) => (
|
||||
<div className="my-8 font-medium tracking-[0.1em] text-[1.2em]">
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
Tier: ({ emoji, type, price, address, subject, body }) => (
|
||||
<div className="flex gap-3 leading-8">
|
||||
<span className="">{emoji}</span>
|
||||
<span className="uppercase">{type}</span>
|
||||
<span>{"-"}</span>
|
||||
<SpamProofEmailLink address={address} subject={subject} body={body}>
|
||||
{price} / year
|
||||
</SpamProofEmailLink>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const bodyClasses = "bg-salmon-100 dark:bg-salmon-900";
|
||||
|
||||
export interface Props extends React.PropsWithChildren {
|
||||
title: string;
|
||||
description: string;
|
||||
relativeUrl: string;
|
||||
}
|
||||
|
||||
export function Layout({ title, description, relativeUrl, children }: Props) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
<BaseSocial
|
||||
title={title}
|
||||
description={description}
|
||||
relativeUrl={relativeUrl}
|
||||
/>
|
||||
</Head>
|
||||
<MDXProvider components={components}>
|
||||
<main className="text-salmon-900 dark:text-salmon-100 font-mono font-normal sm:dark:font-light px-4 pt-8 sm:pt-16 lg:pt-20 pb-8 tracking-[0.08em] leading-6">
|
||||
<div className="max-w-prose mx-auto">
|
||||
<Link href="/">
|
||||
<Logo
|
||||
title="Logo"
|
||||
className="mx-auto align-middle w-[6.284em] h-[6.284em]"
|
||||
/>
|
||||
</Link>
|
||||
{children}
|
||||
</div>
|
||||
</main>
|
||||
</MDXProvider>
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
import { EmailAddress } from "../parseEmailAddress";
|
||||
|
||||
interface Props extends React.PropsWithChildren {
|
||||
address: EmailAddress;
|
||||
subject?: string;
|
||||
body?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a string for use in a URL, but unlike encodeURIComponent, it encodes
|
||||
* every character, including regular ASCII characters [a-zA-Z] etc. For example:
|
||||
*
|
||||
* encodeURIComponent("user@example.com") === "%75%73%65%72%40%65%78%61%6D%70%6C%65%2E%63%6F%6D"
|
||||
*
|
||||
* @param str The string to encode
|
||||
* @returns A URL-encoded version of the string, where every character is encoded
|
||||
*/
|
||||
function strictEncodeURIComponent(str: string) {
|
||||
const components: string[] = [];
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
components.push("%" + str.charCodeAt(i).toString(16).toUpperCase());
|
||||
}
|
||||
return components.join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to an email address, attempting to prevent spam bots from finding it.
|
||||
* Encodes the URI for the href using very aggressive uri encoding, and for the
|
||||
* displayed email text, injects dummy text in a hidden span so that bots will
|
||||
* see it but humans won't.
|
||||
*
|
||||
* Tricks taken from https://spencermortensen.com/articles/email-obfuscation/
|
||||
*
|
||||
* @param param0 The email address to use
|
||||
* @returns A link to the email address, attempting to prevent spam bots from
|
||||
* finding it
|
||||
*/
|
||||
export function SpamProofEmailLink({
|
||||
address: { username, domain },
|
||||
subject,
|
||||
body,
|
||||
children,
|
||||
}: Props) {
|
||||
// URL encode every character of the email address, including the mailto: prefix
|
||||
const rawEmailHref = `${username}@${domain}`;
|
||||
let href = `mailto:${strictEncodeURIComponent(rawEmailHref)}`;
|
||||
|
||||
if (subject != null) {
|
||||
const subjectEncoded = encodeURIComponent(subject).replace(/\+/g, "%20");
|
||||
href += `?subject=${subjectEncoded}`;
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
const bodyEncoded = encodeURIComponent(body).replace(/\+/g, "%20");
|
||||
href += (href.includes("?") ? "&" : "?") + `body=${bodyEncoded}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<a href={href} className="text-teal-400 underline underline-offset-4">
|
||||
{children ?? (
|
||||
<>
|
||||
{`${username}@`}
|
||||
<span className="hidden">Die spam!</span>
|
||||
{domain}
|
||||
</>
|
||||
)}
|
||||
</a>
|
||||
);
|
||||
}
|
210
packages/cursorless-org/src/content/enablement-group.mdx
Normal file
@ -0,0 +1,210 @@
|
||||
export const meta = {
|
||||
title: "Cursorless Enablement Group",
|
||||
description:
|
||||
"Help enable the adoption of Cursorless by accelerating its development.",
|
||||
};
|
||||
|
||||
import { SpamProofEmailLink } from "../components/SpamProofEmailLink";
|
||||
export const emailSubject = "Cursorless Enablement Group";
|
||||
export const emailBody = `Hi Pokey,
|
||||
|
||||
I'm interested in joining the Cursorless Enablement Group. Please send me more information.
|
||||
|
||||
Thanks,
|
||||
|
||||
`;
|
||||
|
||||
# {meta.title}
|
||||
|
||||
---
|
||||
|
||||
## {meta.description}
|
||||
|
||||
Cursorless, an open-source spoken language for editing code, enables users to write software entirely by voice faster than with a keyboard and mouse. Software engineers can code using high-level semantic manipulations (increased productivity), and all computer users can reduce strain on their wrists to prevent injury (preventative healthcare).
|
||||
|
||||
<CursorlessScreenshot
|
||||
src="/big-hats.png"
|
||||
alt="Screenshot of Cursorless in action containing javascript code with symbols over characters in the source code"
|
||||
/>
|
||||
|
||||
## Cursorless development is user-led
|
||||
|
||||
Your support will help Cursorless founder, Pokey Rule, and his team develop the following feature requests as quickly as possible:
|
||||
|
||||
- Reduce the learning curve with interactive tutorials, videos, and documentation to increase the rate of adoption.
|
||||
- Launch Cursorless in other IDEs, such as JetBrains, emacs, etc, as well as in a web browser, and even work globally using OCR / accessibility APIs to operate anywhere on the screen.
|
||||
- Further improvements to the Cursorless execution engine to advance the state of the art in voice coding.
|
||||
|
||||
### 🫶 Developers love Cursorless
|
||||
|
||||
<Testimonials>
|
||||
<Testimonial
|
||||
src="/james-stout.jpeg"
|
||||
name="James Stout"
|
||||
title="Director of Accessibility Engineering"
|
||||
company="Google"
|
||||
>
|
||||
"Phenomenal extension. This is the state of the art for coding by voice.
|
||||
Nothing else comes close. Awesome to see this from the open source community!"
|
||||
</Testimonial>
|
||||
|
||||
<Testimonial
|
||||
src="/max-foxley-marrable.jpeg"
|
||||
name="Max Foxley-Marrable"
|
||||
title="Data Scientist"
|
||||
company="Revolution Data Platforms"
|
||||
>
|
||||
"This extension is a genuine game-changer. As someone who suffers with chronic
|
||||
RSI, I was seriously concerned I would be unfit to continue my career
|
||||
long-term. Discovering Talon and Cursorless has given me hope again and has
|
||||
additionally given me the means to write code and interface with my computer
|
||||
in ways I never thought possible. It's also made coding way more fun than
|
||||
before! I often feel like a code-slinging wizard!"
|
||||
</Testimonial>
|
||||
|
||||
<Testimonial
|
||||
src="/sohee-yang.jpeg"
|
||||
name="Sohee Yang"
|
||||
title="Ph.D. student"
|
||||
company="University College London"
|
||||
>
|
||||
|
||||
"For developers turning to Talon due to typing limitations, Cursorless isn’t just beneficial—it’s indispensable. When I lost my ability to type due to RSI, I was consumed with the fear of significantly reduced productivity and potentially not being able to work anymore. However, when I discovered Cursorless, it gave me hope and confidence that I could regain my prior efficiency once I mastered the tool."
|
||||
|
||||
</Testimonial>
|
||||
|
||||
<Testimonial
|
||||
src="/nathan-heffley.jpeg"
|
||||
name="Nathan Heffley"
|
||||
title="Senior Software Engineer"
|
||||
company="Industrial Resolution"
|
||||
>
|
||||
|
||||
"This is fantastic extension that is not only saving my career but is even speeding up my workflow within VS Code more than when I was typing anyway. The best part is you really feel like a hacker when you rattle off a long command and the code does exactly what you wanted!"
|
||||
|
||||
</Testimonial>
|
||||
|
||||
</Testimonials>
|
||||
|
||||
### 🎯 Goals
|
||||
|
||||
Cursorless needs a dedicated, full-time software engineer on staff. This will cost $5,000 USD per month. The Enablement Group guides development and the participation fees contribute to this crucial funding. Cursorless will always be open source.
|
||||
|
||||
## 🙌 <SpamProofEmailLink address={props.emailAddress} subject={emailSubject} body={emailBody}> Join the Cursorless Enablement Group </SpamProofEmailLink>
|
||||
|
||||
The Enablement Group consists of stakeholders whose talents, lived experiences, and career experiences bring vital perspectives to the development of Cursorless. Support and input help increase the speed at which new features can be delivered.
|
||||
|
||||
**To join, send an email to Cursorless founder Pokey Rule**
|
||||
|
||||
<SpamProofEmailLink
|
||||
address={props.emailAddress}
|
||||
subject={emailSubject}
|
||||
body={emailBody}
|
||||
/>
|
||||
|
||||
<CalloutParent>
|
||||
|
||||
<CalloutBox title="Become a Distinguished Accessibility Champion">
|
||||
By joining the Enablement Group, you solidify your position as a dedicated
|
||||
advocate for accessible technology and inclusion. Your active involvement
|
||||
showcases your commitment to driving positive change and making technology
|
||||
more accessible for everyone.
|
||||
</CalloutBox>
|
||||
|
||||
<CalloutBox title="Gain Prominent Visibility Online">
|
||||
As a valued member of the Enablement Group, you gain increased visibility
|
||||
within both the open source and accessible technology communities. Your
|
||||
participation will be recognized on all web properties including GitHub Repo,
|
||||
cursorless.org, social media, via any other acknowledgments in project
|
||||
updates, newsletters, and events to cement your role as a key player in
|
||||
advancing Cursorless.
|
||||
</CalloutBox>
|
||||
|
||||
<CalloutBox title="Empower Future Accessibility">
|
||||
Your commitment to the Enablement Group supports the long-term vision of
|
||||
creating a full-time staff engineer dedicated to developing Cursorless. As the
|
||||
group grows, the possibility of achieving this goal becomes more tangible,
|
||||
contributing to a sustainable and impactful initiative for accessible
|
||||
technology.
|
||||
</CalloutBox>
|
||||
|
||||
<CalloutBox title="Join a Collaboration with Industry Leaders">
|
||||
Joining the Enablement Group provides an opportunity to collaborate with
|
||||
like-minded individuals and industry leaders who share your passion for
|
||||
accessible technology. This network allows you to exchange insights, share
|
||||
best practices, and collectively drive the advancement of inclusive digital
|
||||
solutions.
|
||||
</CalloutBox>
|
||||
|
||||
<CalloutBox title="Obtain Collective Influence on Development">
|
||||
While the development of Cursorless is guided by its community of users, your
|
||||
annual fee directly contributes to the development of these feature requests!
|
||||
Use your expertise and experience to help prioritize and comment on effective
|
||||
solutions around feature requests. You're ensuring that development directly
|
||||
aligns with the needs of users who value inclusive and accessible technology
|
||||
and rely on it to succeed in their lives.
|
||||
</CalloutBox>
|
||||
|
||||
</CalloutParent>
|
||||
|
||||
### All participants also enjoy the following benefits
|
||||
|
||||
Members of the Cursorless Enablement Group enjoy several privileges. The access and public visibility participants receive make for a dynamic combination of benefits. The value that individuals and companies gain from their involvement in the group is tangible.
|
||||
|
||||
#### 🤓 Technical
|
||||
|
||||
- Be the first to access Cursorless feature updates and new versions.
|
||||
- Lead the adoption of Cursorless by understanding its implementation and having superior knowledge of its use.
|
||||
- Have some influence over the direction of the technology through your expertise.
|
||||
- Gain an advanced and deeper knowledge of any outputs of the group (recommended practices, engineering guidelines)
|
||||
|
||||
#### 🥽 Visibility
|
||||
|
||||
- Ability to promote your organization as a champion for accessible technology and in particular Cursorless.
|
||||
- Ability to promote your organization as a leader in the area of accessible technology.
|
||||
- Opportunity to connect with other influencers in software and accessibility.
|
||||
- Networking and ability to cultivate deep relationships and potential partnerships with leaders, founders, and influencers.
|
||||
|
||||
#### 🪖 Strategic
|
||||
|
||||
- Support an initiative targeted at facilitating an increased and more rapid shift of adoption of Cursorless as a faster way to code and a healthier way to code.
|
||||
- Support of open standards approach. Standards are critical to interoperability and openness is consistent with a positive image in the industry.
|
||||
|
||||
## 🚀 <SpamProofEmailLink address={props.emailAddress} subject={emailSubject} body={emailBody}> Join the Cursorless Enablement Group </SpamProofEmailLink>
|
||||
|
||||
Your participation will help Cursorless maintain its growth trajectory and uphold its cutting-edge quality and esteemed 5-star reputation in coding by voice. And you'll make a lasting impact on the direction of accessible technology.
|
||||
|
||||
<Tiers>
|
||||
<Tier
|
||||
emoji="😍️"
|
||||
type="individuals"
|
||||
price="$495"
|
||||
address={props.emailAddress}
|
||||
subject={emailSubject}
|
||||
body={emailBody}
|
||||
/>
|
||||
<Tier
|
||||
emoji="🕊️"
|
||||
type="non-profits"
|
||||
price="$995"
|
||||
address={props.emailAddress}
|
||||
subject={emailSubject}
|
||||
body={emailBody}
|
||||
/>
|
||||
<Tier
|
||||
emoji="🏢"
|
||||
type="companies"
|
||||
price="$2,495"
|
||||
address={props.emailAddress}
|
||||
subject={emailSubject}
|
||||
body={emailBody}
|
||||
/>
|
||||
</Tiers>
|
||||
|
||||
To join, send an email to Cursorless founder Pokey Rule
|
||||
|
||||
<SpamProofEmailLink
|
||||
address={props.emailAddress}
|
||||
subject={emailSubject}
|
||||
body={emailBody}
|
||||
/>
|
6
packages/cursorless-org/src/content/enablement-group.mdx.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export { default } from "*.mdx";
|
||||
|
||||
export const meta: {
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
41
packages/cursorless-org/src/pages/enablement-group.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import {
|
||||
default as EnablementGroup,
|
||||
meta,
|
||||
} from "../content/enablement-group.mdx";
|
||||
import { Layout, bodyClasses } from "../components/Layout";
|
||||
import { env } from "process";
|
||||
import { parseEmailAddress, EmailAddress } from "../parseEmailAddress";
|
||||
|
||||
const RELATIVE_URL = "cursorless-enablement";
|
||||
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {
|
||||
// See https://github.com/vercel/next.js/discussions/12325#discussioncomment-1116108
|
||||
bodyClasses,
|
||||
|
||||
//! IMPORTANT: Don't return the email address unparsed, because it will
|
||||
//! be serialized as JSON and exposed to the client, so spam bots might
|
||||
//! find it. Instead, parse it and return the parsed object.
|
||||
emailAddress: parseEmailAddress(
|
||||
env["ENABLEMENT_GROUP_EMAIL"] ?? "user@example.com",
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
interface Props extends React.PropsWithChildren {
|
||||
emailAddress: EmailAddress;
|
||||
}
|
||||
|
||||
export default function Page({ emailAddress }: Props) {
|
||||
return (
|
||||
<Layout
|
||||
title={meta.title}
|
||||
description={meta.description}
|
||||
relativeUrl={RELATIVE_URL}
|
||||
>
|
||||
<EnablementGroup emailAddress={emailAddress} />
|
||||
</Layout>
|
||||
);
|
||||
}
|
@ -2,7 +2,7 @@ import { EmbeddedVideo } from "../components/embedded-video";
|
||||
import Head from "next/head";
|
||||
import Button from "../components/Button";
|
||||
import { TITLE, YOUTUBE_SLUG } from "../components/constants";
|
||||
import Social from "../components/Social";
|
||||
import IndexSocial from "../components/IndexSocial";
|
||||
import Logo from "./logo.svg";
|
||||
|
||||
// See https://github.com/vercel/next.js/discussions/12325#discussioncomment-1116108
|
||||
@ -19,9 +19,9 @@ export default function LandingPage() {
|
||||
<>
|
||||
<Head>
|
||||
<title>{TITLE}</title>
|
||||
<Social />
|
||||
<IndexSocial />
|
||||
</Head>
|
||||
<main className="items-center justify-center text-salmon-900 dark:text-salmon-100 font-mono font-bold tracking-[0.18em] overflow-auto fixed top-0 bottom-0 left-0 right-0 p-2 sm:p-0 sm:flex ">
|
||||
<main className="items-center justify-center text-salmon-900 dark:text-salmon-100 font-monoWide font-bold tracking-[0.18em] overflow-auto fixed top-0 bottom-0 left-0 right-0 p-2 sm:p-0 sm:flex ">
|
||||
{/*
|
||||
Note that the font scale gets applied to this element so that all nested elements can use
|
||||
`em` units and will automatically be scaled.
|
||||
|
@ -1,6 +1,6 @@
|
||||
<svg width="30" height="30" viewBox="0.4 0.85 29 28.5" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24.8086 22.0457C26.2355 20.0628 27.0758 17.6296 27.0758 15.0002C27.0758 12.3709 26.2355 9.93778 24.8088 7.95489C27.3909 8.60499 29.3385 11.5122 29.3385 15.0003C29.3385 18.4885 27.3908 21.3957 24.8086 22.0457Z" fill="currentColor"/>
|
||||
<path d="M7.95922 5.18788C9.94126 3.7632 12.3726 2.92419 14.9998 2.92419C17.6279 2.92419 20.0598 3.76368 22.0422 5.18911C21.3846 2.61442 18.4819 0.674316 15.0005 0.674316C11.5197 0.674316 8.61735 2.6138 7.95922 5.18788Z" fill="currentColor"/>
|
||||
<path d="M5.22143 7.91264C3.77615 9.90318 2.92383 12.3522 2.92383 15.0002C2.92383 17.6483 3.77621 20.0974 5.22158 22.088C2.54852 21.5326 0.507812 18.5708 0.507812 15.0003C0.507812 11.4298 2.54844 8.46805 5.22143 7.91264Z" fill="currentColor"/>
|
||||
<path d="M22.042 24.8114C20.0597 26.2368 17.6278 27.0762 14.9998 27.0762C12.3726 27.0762 9.94137 26.2373 7.95936 24.8126C8.61775 27.3864 11.5199 29.3257 15.0005 29.3257C18.4817 29.3257 21.3842 27.3858 22.042 24.8114Z" fill="currentColor"/>
|
||||
<svg width="30" height="30" viewBox="0 0 1920 1920" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M960.001 237.896C1140.58 237.896 1306.36 310.143 1436.6 430.88C1388.26 184.524 1193.47 0 960.001 0C726.538 0 531.747 184.524 483.405 431.206C613.645 310.468 779.429 237.896 960.001 237.896Z" fill="currentColor"/>
|
||||
<path d="M960.001 1681.92C779.429 1681.92 613.645 1609.62 483.405 1488.79C531.747 1735.34 726.538 1920 960.001 1920C1193.47 1920 1388.26 1735.34 1436.6 1488.79C1306.36 1609.62 1140.58 1681.92 960.001 1681.92Z" fill="currentColor"/>
|
||||
<path d="M238.075 960C238.075 779.429 310.377 613.644 431.206 483.405C184.663 531.747 0 726.537 0 960C0 1193.47 184.663 1388.26 431.206 1436.6C310.703 1306.36 238.075 1140.58 238.075 960Z" fill="currentColor"/>
|
||||
<path d="M1681.92 960C1681.92 1140.58 1609.62 1306.36 1488.79 1436.6C1735.34 1388.26 1920 1193.47 1920 960C1920 726.537 1735.34 531.747 1488.79 483.405C1609.62 613.644 1681.92 779.429 1681.92 960Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 992 B |
8
packages/cursorless-org/src/parseEmailAddress.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export interface EmailAddress {
|
||||
username: string;
|
||||
domain: string;
|
||||
}
|
||||
export function parseEmailAddress(email: string): EmailAddress {
|
||||
const [username, domain] = email.split("@");
|
||||
return { username, domain };
|
||||
}
|
@ -74,3 +74,67 @@
|
||||
/* Modern Browsers */ url("/fonts/Inconsolata_SemiExpanded-ExtraBold.ttf")
|
||||
format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inconsolata";
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-stretch: 1% 500%; /* Required by Chrome */
|
||||
src:
|
||||
local(""),
|
||||
/* Modern Browsers */ url("/fonts/Inconsolata-ExtraLight.ttf")
|
||||
format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inconsolata";
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-stretch: 1% 500%; /* Required by Chrome */
|
||||
src:
|
||||
local(""),
|
||||
/* Modern Browsers */ url("/fonts/Inconsolata-Light.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inconsolata";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 1% 500%; /* Required by Chrome */
|
||||
src:
|
||||
local(""),
|
||||
/* Modern Browsers */ url("/fonts/Inconsolata-Regular.ttf")
|
||||
format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inconsolata";
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-stretch: 1% 500%; /* Required by Chrome */
|
||||
src:
|
||||
local(""),
|
||||
/* Modern Browsers */ url("/fonts/Inconsolata-Medium.ttf")
|
||||
format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inconsolata";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: 1% 500%; /* Required by Chrome */
|
||||
src:
|
||||
local(""),
|
||||
/* Modern Browsers */ url("/fonts/Inconsolata-SemiBold.ttf")
|
||||
format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inconsolata";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 1% 500%; /* Required by Chrome */
|
||||
src:
|
||||
local(""),
|
||||
/* Modern Browsers */ url("/fonts/Inconsolata-Bold.ttf") format("truetype");
|
||||
}
|
||||
|
@ -58,7 +58,8 @@ module.exports = {
|
||||
stretched: { raw: "(min-aspect-ratio: 2/1), (max-aspect-ratio: 1/1)" },
|
||||
},
|
||||
fontFamily: {
|
||||
mono: ["Inconsolata-SemiExpanded", ...defaultTheme.fontFamily.mono],
|
||||
mono: ["Inconsolata", ...defaultTheme.fontFamily.mono],
|
||||
monoWide: ["Inconsolata-SemiExpanded", ...defaultTheme.fontFamily.mono],
|
||||
},
|
||||
width: {
|
||||
smBase: smallWidth,
|
||||
@ -74,15 +75,26 @@ module.exports = {
|
||||
xs: "1.2em",
|
||||
lg: "1.8em",
|
||||
"2xl": "2.4em",
|
||||
"3xl": "3.6em",
|
||||
},
|
||||
colors: {
|
||||
salmon: {
|
||||
100: "#FFFAF8",
|
||||
300: "#F8C9BA",
|
||||
400: "#FF9273",
|
||||
700: "#372e2a",
|
||||
800: "#161110",
|
||||
900: "#0A0707",
|
||||
},
|
||||
teal: {
|
||||
100: "#F9FFFE",
|
||||
200: "#CDFFF9",
|
||||
300: "#99FFF3",
|
||||
400: "#00907F",
|
||||
700: "#005349",
|
||||
800: "#00443C",
|
||||
900: "#00110F",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -8,7 +8,7 @@
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "nodenext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
|
@ -275,6 +275,15 @@ importers:
|
||||
'@cursorless/cheatsheet':
|
||||
specifier: workspace:*
|
||||
version: link:../cheatsheet
|
||||
'@mdx-js/loader':
|
||||
specifier: 2.3.0
|
||||
version: 2.3.0(webpack@5.88.2)
|
||||
'@mdx-js/react':
|
||||
specifier: 2.3.0
|
||||
version: 2.3.0(react@18.2.0)
|
||||
'@next/mdx':
|
||||
specifier: 13.4.10
|
||||
version: 13.4.10(@mdx-js/loader@2.3.0)(@mdx-js/react@2.3.0)
|
||||
eslint:
|
||||
specifier: ^8.38.0
|
||||
version: 8.38.0
|
||||
@ -300,6 +309,12 @@ importers:
|
||||
'@svgr/webpack':
|
||||
specifier: 6.5.1
|
||||
version: 6.5.1
|
||||
'@types/mdx':
|
||||
specifier: 2.0.5
|
||||
version: 2.0.5
|
||||
'@types/mdx-js__react':
|
||||
specifier: 1.5.5
|
||||
version: 1.5.5
|
||||
'@types/node':
|
||||
specifier: ^16.11.3
|
||||
version: 16.18.13
|
||||
@ -3309,6 +3324,18 @@ packages:
|
||||
/@leichtgewicht/ip-codec@2.0.4:
|
||||
resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==}
|
||||
|
||||
/@mdx-js/loader@2.3.0(webpack@5.88.2):
|
||||
resolution: {integrity: sha512-IqsscXh7Q3Rzb+f5DXYk0HU71PK+WuFsEhf+mSV3fOhpLcEpgsHvTQ2h0T6TlZ5gHOaBeFjkXwB52by7ypMyNg==}
|
||||
peerDependencies:
|
||||
webpack: '>=4'
|
||||
dependencies:
|
||||
'@mdx-js/mdx': 2.3.0
|
||||
source-map: 0.7.4
|
||||
webpack: 5.88.2(webpack-cli@5.1.4)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@mdx-js/mdx@2.3.0:
|
||||
resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==}
|
||||
dependencies:
|
||||
@ -3358,6 +3385,22 @@ packages:
|
||||
glob: 7.1.7
|
||||
dev: false
|
||||
|
||||
/@next/mdx@13.4.10(@mdx-js/loader@2.3.0)(@mdx-js/react@2.3.0):
|
||||
resolution: {integrity: sha512-0ZbUIr3yuFFfkaYth2kNFAT0fbyylJTMqZy5zTdb7YGqvYjKFD8n75L3UYAX0g5mibGp3iETJ0I7730sW13PKQ==}
|
||||
peerDependencies:
|
||||
'@mdx-js/loader': '>=0.15.0'
|
||||
'@mdx-js/react': '>=0.15.0'
|
||||
peerDependenciesMeta:
|
||||
'@mdx-js/loader':
|
||||
optional: true
|
||||
'@mdx-js/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@mdx-js/loader': 2.3.0(webpack@5.88.2)
|
||||
'@mdx-js/react': 2.3.0(react@18.2.0)
|
||||
source-map: 0.7.4
|
||||
dev: false
|
||||
|
||||
/@next/swc-darwin-arm64@13.5.4:
|
||||
resolution: {integrity: sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==}
|
||||
engines: {node: '>= 10'}
|
||||
@ -4758,9 +4801,14 @@ packages:
|
||||
'@types/unist': 2.0.6
|
||||
dev: false
|
||||
|
||||
/@types/mdx-js__react@1.5.5:
|
||||
resolution: {integrity: sha512-k8pnaP6JXVlQh18HgL5X6sYFNC/qZnzO7R2+HsmwrwUd+JnnsU0d9lyyT0RQrHg1anxDU36S98TI/fsGtmYqqg==}
|
||||
dependencies:
|
||||
'@types/react': 18.0.28
|
||||
dev: true
|
||||
|
||||
/@types/mdx@2.0.5:
|
||||
resolution: {integrity: sha512-76CqzuD6Q7LC+AtbPqrvD9AqsN0k8bsYo2bM2J8pmNldP1aIPAbzUQ7QbobyXL4eLr1wK5x8FZFe8eF/ubRuBg==}
|
||||
dev: false
|
||||
|
||||
/@types/mime@3.0.1:
|
||||
resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
|
||||
|