mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-11-02 16:14:03 -05:00
<IFrame /> component
This commit is contained in:
@@ -3,13 +3,6 @@
|
|||||||
line-height: 1.7;
|
line-height: 1.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content blockquote {
|
|
||||||
margin-left: 0;
|
|
||||||
padding-left: 1.5em;
|
|
||||||
border-left: 3px solid var(--link);
|
|
||||||
color: var(--medium-dark);
|
|
||||||
}
|
|
||||||
|
|
||||||
.content h2,
|
.content h2,
|
||||||
.content h3,
|
.content h3,
|
||||||
.content h4 {
|
.content h4 {
|
||||||
@@ -43,6 +36,13 @@
|
|||||||
padding-left: 0.25em;
|
padding-left: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content blockquote {
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 1.5em;
|
||||||
|
border-left: 3px solid var(--link);
|
||||||
|
color: var(--medium-dark);
|
||||||
|
}
|
||||||
|
|
||||||
.content hr {
|
.content hr {
|
||||||
margin: 1.5em auto;
|
margin: 1.5em auto;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
@@ -50,33 +50,6 @@
|
|||||||
background-color: var(--light);
|
background-color: var(--light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content :global(.image_wrapper) {
|
|
||||||
line-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* default to centering all images */
|
|
||||||
.content :global(.image_wrapper),
|
|
||||||
.content figure {
|
|
||||||
margin: 1em auto;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content figure :global(.image_wrapper) {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content figure figcaption {
|
|
||||||
margin-top: 0.75em;
|
|
||||||
font-size: 0.9em;
|
|
||||||
line-height: 1.5;
|
|
||||||
color: var(--medium);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* some figcaptions contain paragraphs, some don't, so reset all of them */
|
|
||||||
.content figure figcaption p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* sub-heading anchor styles */
|
/* sub-heading anchor styles */
|
||||||
.content :global(.h-anchor) {
|
.content :global(.h-anchor) {
|
||||||
margin: 0 0.25em;
|
margin: 0 0.25em;
|
||||||
|
|||||||
15
components/Figure/Figure.module.css
Normal file
15
components/Figure/Figure.module.css
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
.figure {
|
||||||
|
margin: 1em auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caption {
|
||||||
|
font-size: 0.9em;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* some figcaptions contain paragraphs, some don't, so reset all of them */
|
||||||
|
.caption p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ import innerText from "react-innertext";
|
|||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import type { ImageProps as NextImageProps } from "next/image";
|
import type { ImageProps as NextImageProps } from "next/image";
|
||||||
|
|
||||||
|
import styles from "./Figure.module.css";
|
||||||
|
|
||||||
type Props = Omit<NextImageProps, "alt"> & {
|
type Props = Omit<NextImageProps, "alt"> & {
|
||||||
children: ReactNode; // caption (can be in markdown, yay!!!)
|
children: ReactNode; // caption (can be in markdown, yay!!!)
|
||||||
alt?: string; // becomes optional -- pulled from plaintext-ified caption if missing
|
alt?: string; // becomes optional -- pulled from plaintext-ified caption if missing
|
||||||
@@ -10,9 +12,9 @@ type Props = Omit<NextImageProps, "alt"> & {
|
|||||||
|
|
||||||
const Figure = ({ children, alt, ...imageProps }: Props) => {
|
const Figure = ({ children, alt, ...imageProps }: Props) => {
|
||||||
return (
|
return (
|
||||||
<figure>
|
<figure className={styles.figure}>
|
||||||
<Image alt={alt || innerText(children)} {...imageProps} />
|
<Image alt={alt || innerText(children)} {...imageProps} />
|
||||||
<figcaption>{children}</figcaption>
|
<figcaption className={styles.caption}>{children}</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
6
components/IFrame/IFrame.module.css
Normal file
6
components/IFrame/IFrame.module.css
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
.frame {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
margin: 1em auto;
|
||||||
|
border: 2px solid var(--kinda-light);
|
||||||
|
}
|
||||||
28
components/IFrame/IFrame.tsx
Normal file
28
components/IFrame/IFrame.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import styles from "./IFrame.module.css";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
src: string;
|
||||||
|
title?: string;
|
||||||
|
height: number;
|
||||||
|
width?: number; // defaults to 100%
|
||||||
|
allowScripts?: boolean;
|
||||||
|
noScroll?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const IFrame = ({ src, title, height, width, allowScripts, noScroll, ...rest }: Props) => (
|
||||||
|
<iframe
|
||||||
|
className={styles.frame}
|
||||||
|
src={src}
|
||||||
|
title={title}
|
||||||
|
sandbox={allowScripts ? "allow-same-origin allow-scripts allow-popups" : undefined}
|
||||||
|
scrolling={noScroll ? "no" : undefined}
|
||||||
|
loading="lazy"
|
||||||
|
style={{
|
||||||
|
height: `${height}px`,
|
||||||
|
maxWidth: width ? `${width}px` : undefined,
|
||||||
|
}}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default IFrame;
|
||||||
7
components/Image/Image.module.css
Normal file
7
components/Image/Image.module.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.wrapper {
|
||||||
|
line-height: 0;
|
||||||
|
|
||||||
|
/* default to centering all images */
|
||||||
|
margin: 1em auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
import NextImage from "next/image";
|
import NextImage from "next/image";
|
||||||
import type { ImageProps as NextImageProps } from "next/image";
|
import type { ImageProps as NextImageProps } from "next/image";
|
||||||
|
|
||||||
|
import styles from "./Image.module.css";
|
||||||
|
|
||||||
const Image = ({ src, width, height, alt, quality, priority }: NextImageProps) => {
|
const Image = ({ src, width, height, alt, quality, priority }: NextImageProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="image_wrapper">
|
<div className={styles.wrapper}>
|
||||||
<NextImage
|
<NextImage
|
||||||
src={(src as string).replace(/^\/public/g, "")}
|
src={(src as string).replace(/^\/public/g, "")}
|
||||||
layout="intrinsic"
|
layout="intrinsic"
|
||||||
|
|||||||
11
components/OctocatLink/OctocatLink.module.css
Normal file
11
components/OctocatLink/OctocatLink.module.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
.link {
|
||||||
|
margin: 0 0.4em;
|
||||||
|
color: var(--text);
|
||||||
|
background: none !important;
|
||||||
|
padding-bottom: 0;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link:hover {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
@@ -1,17 +1,13 @@
|
|||||||
import { OctocatOcticon } from "../Icons";
|
import { OctocatOcticon } from "../Icons";
|
||||||
|
|
||||||
|
import styles from "./OctocatLink.module.css";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
repo: string;
|
repo: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const OctocatLink = (props: Props) => (
|
const OctocatLink = (props: Props) => (
|
||||||
<a
|
<a className={styles.link} href={`https://github.com/${props.repo}`} target="_blank" rel="noopener noreferrer">
|
||||||
className="no-underline"
|
|
||||||
href={`https://github.com/${props.repo}`}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
style={{ margin: "0 0.4em", color: "var(--text)" }}
|
|
||||||
>
|
|
||||||
<OctocatOcticon fill="currentColor" />
|
<OctocatOcticon fill="currentColor" />
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export { default as code } from "../components/CodeBlock/CodeBlock";
|
|||||||
|
|
||||||
// All of these components are technically passed into all posts, but next/dynamic ensures they're loaded only
|
// All of these components are technically passed into all posts, but next/dynamic ensures they're loaded only
|
||||||
// when they're referenced in the individual mdx files.
|
// when they're referenced in the individual mdx files.
|
||||||
|
export const IFrame = dynamic(() => import("../components/IFrame/IFrame"));
|
||||||
export const Video = dynamic(() => import("../components/Video/Video"));
|
export const Video = dynamic(() => import("../components/Video/Video"));
|
||||||
export const YouTube = dynamic(() => import("../components/YouTubeEmbed/YouTubeEmbed"));
|
export const YouTube = dynamic(() => import("../components/YouTubeEmbed/YouTubeEmbed"));
|
||||||
export const Tweet = dynamic(() => import("../components/TweetEmbed/TweetEmbed"));
|
export const Tweet = dynamic(() => import("../components/TweetEmbed/TweetEmbed"));
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ Below are the code snippets you can grab and customize to make your own ["waving
|
|||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
|
|
||||||
<iframe
|
<IFrame
|
||||||
height="500"
|
|
||||||
width="100%"
|
|
||||||
src="https://codepen.io/jakejarvis/embed/pBZWZw/?theme-id=light&default-tab=css,result"
|
src="https://codepen.io/jakejarvis/embed/pBZWZw/?theme-id=light&default-tab=css,result"
|
||||||
scrolling="no"
|
height={500}
|
||||||
></iframe>
|
allowScripts
|
||||||
|
noScroll
|
||||||
|
/>
|
||||||
|
|
||||||
## CSS
|
## CSS
|
||||||
|
|
||||||
|
|||||||
@@ -29,21 +29,14 @@ I've written a simple implementation below, which...
|
|||||||
|
|
||||||
...meaning that any CSS selectors beginning with `body.dark` or `body.light` will only apply when the respective mode is active. A good place to start is by separating any color rules — your background, text, links, etc. — into a different section of your CSS. Using [SASS or SCSS](https://sass-lang.com/) makes this a whole lot [easier with nesting](https://sass-lang.com/guide#topic-3) but is not required; this was written with a [KISS](https://getyarn.io/yarn-clip/embed/eed08f4f-d1c9-4cc0-b041-f280a5dbf0a5?autoplay=false) mentality.
|
...meaning that any CSS selectors beginning with `body.dark` or `body.light` will only apply when the respective mode is active. A good place to start is by separating any color rules — your background, text, links, etc. — into a different section of your CSS. Using [SASS or SCSS](https://sass-lang.com/) makes this a whole lot [easier with nesting](https://sass-lang.com/guide#topic-3) but is not required; this was written with a [KISS](https://getyarn.io/yarn-clip/embed/eed08f4f-d1c9-4cc0-b041-f280a5dbf0a5?autoplay=false) mentality.
|
||||||
|
|
||||||
<iframe
|
<IFrame
|
||||||
src="https://jakejarvis.github.io/dark-mode-example/"
|
src="https://jakejarvis.github.io/dark-mode-example/"
|
||||||
title="Dark Mode Example"
|
title="Dark Mode Example"
|
||||||
sandbox="allow-same-origin allow-scripts allow-popups"
|
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
style={{
|
height={190}
|
||||||
height: "190px",
|
width={650}
|
||||||
width: "100%",
|
allowScripts
|
||||||
maxWidth: "650px",
|
/>
|
||||||
display: "block",
|
|
||||||
boxSizing: "border-box",
|
|
||||||
margin: "0 auto",
|
|
||||||
border: "2px solid var(--kinda-light)",
|
|
||||||
}}
|
|
||||||
></iframe>
|
|
||||||
|
|
||||||
A _very_ barebones example is embedded above ([view the source here](https://github.com/jakejarvis/dark-mode-example), or [open in a new window](https://jakejarvis.github.io/dark-mode-example/) if your browser is blocking the frame) and you can try it out on this site by clicking the 💡 lightbulb in the upper right corner of this page. You'll notice that the dark theme sticks when refreshing this page, navigating between other pages, or if you were to return to this example weeks from now.
|
A _very_ barebones example is embedded above ([view the source here](https://github.com/jakejarvis/dark-mode-example), or [open in a new window](https://jakejarvis.github.io/dark-mode-example/) if your browser is blocking the frame) and you can try it out on this site by clicking the 💡 lightbulb in the upper right corner of this page. You'll notice that the dark theme sticks when refreshing this page, navigating between other pages, or if you were to return to this example weeks from now.
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ const Note = ({ frontMatter, source }: NoteType) => {
|
|||||||
</Content>
|
</Content>
|
||||||
|
|
||||||
{frontMatter.noComments !== true && (
|
{frontMatter.noComments !== true && (
|
||||||
<InView rootMargin="140px" triggerOnce={true} fallbackInView={true}>
|
<InView rootMargin="140px" triggerOnce fallbackInView>
|
||||||
{({ inView, ref }) => (
|
{({ inView, ref }) => (
|
||||||
<div id="comments" ref={ref}>
|
<div id="comments" ref={ref}>
|
||||||
{inView && <Comments title={frontMatter.title} />}
|
{inView && <Comments title={frontMatter.title} />}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import Image from "next/image";
|
|||||||
import { NextSeo } from "next-seo";
|
import { NextSeo } from "next-seo";
|
||||||
import Content from "../components/Content/Content";
|
import Content from "../components/Content/Content";
|
||||||
import PageTitle from "../components/PageTitle/PageTitle";
|
import PageTitle from "../components/PageTitle/PageTitle";
|
||||||
|
import IFrame from "../components/IFrame/IFrame";
|
||||||
import { FloppyIcon, SirenIcon } from "../components/Icons";
|
import { FloppyIcon, SirenIcon } from "../components/Icons";
|
||||||
|
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
@@ -75,12 +76,14 @@ const Previously = () => (
|
|||||||
experience anyway.
|
experience anyway.
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<figure>
|
<figure>
|
||||||
<iframe
|
<IFrame
|
||||||
className="y2k_frame"
|
|
||||||
src="https://jakejarvis.github.io/my-first-website/"
|
src="https://jakejarvis.github.io/my-first-website/"
|
||||||
title="My Terrible, Horrible, No Good, Very Bad First Website"
|
title="My Terrible, Horrible, No Good, Very Bad First Website"
|
||||||
></iframe>
|
height={500}
|
||||||
|
allowScripts
|
||||||
|
/>
|
||||||
<figcaption>
|
<figcaption>
|
||||||
November 2001 (
|
November 2001 (
|
||||||
<a href="https://github.com/jakejarvis/my-first-website" target="_blank" rel="noopener noreferrer">
|
<a href="https://github.com/jakejarvis/my-first-website" target="_blank" rel="noopener noreferrer">
|
||||||
@@ -236,10 +239,24 @@ const Previously = () => (
|
|||||||
footer > div {
|
footer > div {
|
||||||
font-size: 0.95em !important;
|
font-size: 0.95em !important;
|
||||||
}
|
}
|
||||||
.y2k_frame {
|
figure {
|
||||||
width: 100%;
|
margin: 1em auto;
|
||||||
height: 500px;
|
text-align: center;
|
||||||
border: 2px solid #e3d18c;
|
}
|
||||||
|
figure img {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
figcaption {
|
||||||
|
margin-top: 0.2em;
|
||||||
|
font-size: 0.9em;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--medium);
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
margin: 1em auto !important;
|
||||||
|
}
|
||||||
|
iframe {
|
||||||
|
margin-bottom: 0.6em !important;
|
||||||
}
|
}
|
||||||
.limegreen {
|
.limegreen {
|
||||||
color: #32cd32;
|
color: #32cd32;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import Link from "next/link";
|
|||||||
import { NextSeo } from "next-seo";
|
import { NextSeo } from "next-seo";
|
||||||
import Content from "../components/Content/Content";
|
import Content from "../components/Content/Content";
|
||||||
import PageTitle from "../components/PageTitle/PageTitle";
|
import PageTitle from "../components/PageTitle/PageTitle";
|
||||||
|
import IFrame from "../components/IFrame/IFrame";
|
||||||
import { PrivacyIcon } from "../components/Icons";
|
import { PrivacyIcon } from "../components/Icons";
|
||||||
|
|
||||||
import faunaImg from "../public/static/images/privacy/fauna_hits.png";
|
import faunaImg from "../public/static/images/privacy/fauna_hits.png";
|
||||||
@@ -24,6 +25,7 @@ const Privacy = () => (
|
|||||||
<p>Okay, this is an easy one. 😉</p>
|
<p>Okay, this is an easy one. 😉</p>
|
||||||
|
|
||||||
<h2 id="hosting">Hosting</h2>
|
<h2 id="hosting">Hosting</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Pages and first-party assets on this website are served by{" "}
|
Pages and first-party assets on this website are served by{" "}
|
||||||
<a href="https://vercel.com/" target="_blank" rel="noopener noreferrer">
|
<a href="https://vercel.com/" target="_blank" rel="noopener noreferrer">
|
||||||
@@ -35,6 +37,7 @@ const Privacy = () => (
|
|||||||
</a>{" "}
|
</a>{" "}
|
||||||
for more information.
|
for more information.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
For a likely excessive level of privacy and security, this website is also mirrored on the{" "}
|
For a likely excessive level of privacy and security, this website is also mirrored on the{" "}
|
||||||
<a href="https://www.torproject.org/" target="_blank" rel="noopener noreferrer">
|
<a href="https://www.torproject.org/" target="_blank" rel="noopener noreferrer">
|
||||||
@@ -42,6 +45,7 @@ const Privacy = () => (
|
|||||||
</a>{" "}
|
</a>{" "}
|
||||||
at:
|
at:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>
|
<p>
|
||||||
<a
|
<a
|
||||||
@@ -55,6 +59,7 @@ const Privacy = () => (
|
|||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<h2 id="analytics">Analytics</h2>
|
<h2 id="analytics">Analytics</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A very simple hit counter on each blog post tallies an aggregate number of pageviews (i.e.{" "}
|
A very simple hit counter on each blog post tallies an aggregate number of pageviews (i.e.{" "}
|
||||||
<code>hits = hits + 1</code>) in a{" "}
|
<code>hits = hits + 1</code>) in a{" "}
|
||||||
@@ -64,6 +69,7 @@ const Privacy = () => (
|
|||||||
database. Individual views and identifying (or non-identifying) details are{" "}
|
database. Individual views and identifying (or non-identifying) details are{" "}
|
||||||
<strong>never stored or logged</strong>.
|
<strong>never stored or logged</strong>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The{" "}
|
The{" "}
|
||||||
<a
|
<a
|
||||||
@@ -87,7 +93,9 @@ const Privacy = () => (
|
|||||||
</a>{" "}
|
</a>{" "}
|
||||||
are public.
|
are public.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<Image src={faunaImg} placeholder="blur" alt="The entire database schema." />
|
<Image src={faunaImg} placeholder="blur" alt="The entire database schema." />
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="https://usefathom.com/ref/ZEYG0O" target="_blank" rel="noopener noreferrer">
|
<a href="https://usefathom.com/ref/ZEYG0O" target="_blank" rel="noopener noreferrer">
|
||||||
<strong>Fathom Analytics</strong>
|
<strong>Fathom Analytics</strong>
|
||||||
@@ -103,15 +111,14 @@ const Privacy = () => (
|
|||||||
</a>{" "}
|
</a>{" "}
|
||||||
is completely public, too!)
|
is completely public, too!)
|
||||||
</p>
|
</p>
|
||||||
<iframe src="https://app.usefathom.com/share/wbgnqukw/jarv.is" title="Fathom Analytics dashboard">
|
|
||||||
<style jsx>{`
|
<IFrame
|
||||||
iframe {
|
src="https://app.usefathom.com/share/wbgnqukw/jarv.is"
|
||||||
width: 100%;
|
title="Fathom Analytics dashboard"
|
||||||
height: 500px;
|
height={500}
|
||||||
border: 2px solid var(--kinda-light);
|
allowScripts
|
||||||
}
|
/>
|
||||||
`}</style>
|
|
||||||
</iframe>
|
|
||||||
<p>
|
<p>
|
||||||
<a href="https://vercel.com/analytics" target="_blank" rel="noopener noreferrer">
|
<a href="https://vercel.com/analytics" target="_blank" rel="noopener noreferrer">
|
||||||
<strong>Vercel Analytics</strong>
|
<strong>Vercel Analytics</strong>
|
||||||
@@ -124,10 +131,12 @@ const Privacy = () => (
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="third-party">Third-Party Content</h2>
|
<h2 id="third-party">Third-Party Content</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Occasionally, embedded content from third-party services is included in posts, and some may contain tracking
|
Occasionally, embedded content from third-party services is included in posts, and some may contain tracking
|
||||||
code that is outside of my control. Please refer to their privacy policies for more information:
|
code that is outside of my control. Please refer to their privacy policies for more information:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://blog.codepen.io/documentation/privacy/" target="_blank" rel="noopener noreferrer">
|
<a href="https://blog.codepen.io/documentation/privacy/" target="_blank" rel="noopener noreferrer">
|
||||||
@@ -171,6 +180,7 @@ const Privacy = () => (
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2 id="hcaptcha">Fighting Spam</h2>
|
<h2 id="hcaptcha">Fighting Spam</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Using{" "}
|
Using{" "}
|
||||||
<a href="https://www.hcaptcha.com/" target="_blank" rel="noopener noreferrer">
|
<a href="https://www.hcaptcha.com/" target="_blank" rel="noopener noreferrer">
|
||||||
@@ -186,6 +196,7 @@ const Privacy = () => (
|
|||||||
</a>
|
</a>
|
||||||
.
|
.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You can refer to hCaptcha's{" "}
|
You can refer to hCaptcha's{" "}
|
||||||
<a href="https://www.hcaptcha.com/privacy" target="_blank" rel="noopener noreferrer">
|
<a href="https://www.hcaptcha.com/privacy" target="_blank" rel="noopener noreferrer">
|
||||||
@@ -206,6 +217,7 @@ const Privacy = () => (
|
|||||||
</a>
|
</a>
|
||||||
. 🚗
|
. 🚗
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
I also enabled the setting to donate 100% of my{" "}
|
I also enabled the setting to donate 100% of my{" "}
|
||||||
<a href="https://humanprotocol.org/?lng=en-US" target="_blank" rel="noopener noreferrer">
|
<a href="https://humanprotocol.org/?lng=en-US" target="_blank" rel="noopener noreferrer">
|
||||||
|
|||||||
Reference in New Issue
Block a user