1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-09-13 06:05:32 -04:00

okay preact is actually pretty cool tbh. (now using it for copy to clipboard buttons)

This commit is contained in:
2021-12-07 08:11:38 -05:00
parent b4cd9eea59
commit 6d64ea647e
6 changed files with 95 additions and 83 deletions

View File

@@ -1,35 +1,51 @@
import { h, render } from "preact";
import { useState } from "preact/hooks";
import copy from "clipboard-copy";
import trimNewlines from "trim-newlines";
// the default text of the copy button:
const defaultText = "Copy";
const successText = "Copied!";
// shared react components:
import { CopyIcon, CheckIcon } from "@primer/octicons-react";
const CopyButton = (props) => {
const [copied, setCopied] = useState(false);
const handleCopy = (e) => {
// stop browser from navigating away from page (this shouldn't happen anyways)
e.preventDefault();
// prevent unintentional double-clicks by unfocusing button
e.target.blur();
// trim any surrounding whitespace from target block's content and send it to the clipboard
copy(trimNewlines(props.content));
// indicate success...
setCopied(true);
// ...but reset everything after 2 seconds
setTimeout(() => {
setCopied(false);
}, 2000);
};
return (
<button
class="copy-button"
title="Copy to clipboard"
aria-label="Copy to clipboard"
onClick={handleCopy}
disabled={copied}
>
{copied ? <CheckIcon size={16} /> : <CopyIcon size={16} />}
</button>
);
};
// loop through each code fence on page (if any)
document.querySelectorAll("div.highlight").forEach((highlightDiv) => {
// bind a new button to the copy action
const button = document.createElement("button");
button.className = "copy-button";
button.textContent = defaultText;
button.addEventListener("click", () => {
// prevent unintentional double-clicks by unfocusing button
button.blur();
// actual code element will have class "language-*" (even if plaintext)
const codeElement = highlightDiv.querySelector('code[class^="language-"]');
// actual code element will have class "language-*", even if plaintext
if (copy(trimNewlines(highlightDiv.querySelector('code[class^="language-"]').textContent))) {
// show a subtle indication of success
button.textContent = successText;
// reset button to original text after 2 seconds
setTimeout(() => {
button.textContent = defaultText;
}, 2000);
}
});
// add Hugo's code block to a new wrapper element, and insert the copy button as a sibling to it
const wrapperDiv = document.createElement("div");
wrapperDiv.className = "highlight-clipboard-enabled";
highlightDiv.before(wrapperDiv);
wrapperDiv.append(highlightDiv, button);
if (codeElement) {
// add the button as a sibling to the original Hugo block whose contents we're copying
render(<CopyButton content={codeElement.textContent} />, highlightDiv);
}
});

View File

@@ -68,7 +68,7 @@ const RepositoryCard = (repo) => (
target="_blank"
rel="noopener noreferrer"
>
<StarIcon size={16} fill="currentColor" />
<StarIcon size={16} />
<span>{repo.stars.toLocaleString("en-US")}</span>
</a>
</div>
@@ -82,7 +82,7 @@ const RepositoryCard = (repo) => (
target="_blank"
rel="noopener noreferrer"
>
<RepoForkedIcon size={16} fill="currentColor" />
<RepoForkedIcon size={16} />
<span>{repo.forks.toLocaleString("en-US")}</span>
</a>
</div>

View File

@@ -34,6 +34,7 @@ div.highlight {
overflow-x: scroll;
margin: 1em 0;
border: 1px solid;
position: relative;
pre {
padding-left: 1.5em;
@@ -44,23 +45,15 @@ div.highlight {
> pre > code {
padding-right: 1.5em;
}
}
// elements dynamically added by clipboard.js code
div.highlight-clipboard-enabled {
position: relative;
button.copy-button {
position: absolute;
top: 0;
right: 0;
width: 5.5em;
padding: 0.75em 0.25em;
border: 1px solid;
padding: 0.75em;
border-width: 0 0 1px 1px;
border-style: solid;
cursor: pointer;
font-size: 0.85em;
font-weight: 500;
line-height: 1;
&:hover {
@include themes.themed(
@@ -69,6 +62,11 @@ div.highlight-clipboard-enabled {
)
);
}
.octicon {
width: 1em;
height: 1em;
}
}
}
@@ -110,9 +108,6 @@ div.highlight-clipboard-enabled {
}
.kd,
// .nb,
// .nl,
// .nv,
.vc,
.vg,
.vi,

View File

@@ -61,12 +61,12 @@
"babel-loader": "^8.2.3",
"clean-css": "^5.2.2",
"copy-webpack-plugin": "^10.0.0",
"core-js": "^3.19.2",
"core-js": "^3.19.3",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.2.0",
"del": "^6.0.0",
"dotenv": "^10.0.0",
"eslint": "~8.4.0",
"eslint": "~8.4.1",
"eslint-config-preact": "^1.2.0",
"eslint-config-prettier": "~8.3.0",
"eslint-plugin-prettier": "~4.0.0",
@@ -88,7 +88,7 @@
"postcss-svgo": "^5.0.3",
"prettier": "~2.5.1",
"sass": "^1.44.0",
"sass-loader": "^12.3.0",
"sass-loader": "^12.4.0",
"simple-git-hooks": "^2.7.0",
"source-map-loader": "^3.0.0",
"stylelint": "~14.1.0",
@@ -101,7 +101,7 @@
"terser": "^5.10.0",
"terser-webpack-plugin": "^5.2.5",
"web-vitals": "^2.1.2",
"webpack": "^5.64.4",
"webpack": "^5.65.0",
"webpack-assets-manifest": "^5.0.6",
"webpack-bundle-analyzer": "^4.5.0",
"webpack-cli": "^4.9.1",

View File

@@ -31,6 +31,7 @@
- Hugo
- Vercel
- Preact
- FaunaDB
- Airtable
- hCaptcha

View File

@@ -1282,9 +1282,9 @@
integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==
"@types/node@*":
version "16.11.11"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.11.tgz#6ea7342dfb379ea1210835bada87b3c512120234"
integrity sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==
version "16.11.12"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.12.tgz#ac7fb693ac587ee182c3780c26eb65546a1a3c10"
integrity sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==
"@types/normalize-package-data@^2.4.0", "@types/normalize-package-data@^2.4.1":
version "2.4.1"
@@ -2355,9 +2355,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001179, caniuse-lite@^1.0.30001251, caniuse-lite@^1.0.30001272, caniuse-lite@^1.0.30001280:
version "1.0.30001284"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001284.tgz#d3653929ded898cd0c1f09a56fd8ca6952df4fca"
integrity sha512-t28SKa7g6kiIQi6NHeOcKrOrGMzCRrXvlasPwWC26TH2QNdglgzQIRUuJ0cR3NeQPH+5jpuveeeSFDLm2zbkEw==
version "1.0.30001285"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001285.tgz#fe1e52229187e11d6670590790d669b9e03315b7"
integrity sha512-KAOkuUtcQ901MtmvxfKD+ODHH9YVDYnBt+TGYSz2KIfnq22CiArbUxXPN9067gNbgMlnNYRSwho8OPXZPALB9Q==
careful-downloader@^2.0.1:
version "2.0.1"
@@ -2794,17 +2794,17 @@ copy-webpack-plugin@^10.0.0:
serialize-javascript "^6.0.0"
core-js-compat@^3.18.0, core-js-compat@^3.19.1:
version "3.19.2"
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.19.2.tgz#18066a3404a302433cb0aa8be82dd3d75c76e5c4"
integrity sha512-ObBY1W5vx/LFFMaL1P5Udo4Npib6fu+cMokeziWkA8Tns4FcDemKF5j9JvaI5JhdkW8EQJQGJN1EcrzmEwuAqQ==
version "3.19.3"
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.19.3.tgz#de75e5821c5ce924a0a1e7b7d5c2cb973ff388aa"
integrity sha512-59tYzuWgEEVU9r+SRgceIGXSSUn47JknoiXW6Oq7RW8QHjXWz3/vp8pa7dbtuVu40sewz3OP3JmQEcDdztrLhA==
dependencies:
browserslist "^4.18.1"
semver "7.0.0"
core-js@3, core-js@^3.16.2, core-js@^3.19.2:
version "3.19.2"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.19.2.tgz#ae216d7f4f7e924d9a2e3ff1e4b1940220f9157b"
integrity sha512-ciYCResnLIATSsXuXnIOH4CbdfgV+H1Ltg16hJFN7/v6OxqnFr/IFGeLacaZ+fHLAm0TBbXwNK9/DNBzBUrO/g==
core-js@3, core-js@^3.16.2, core-js@^3.19.3:
version "3.19.3"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.19.3.tgz#6df8142a996337503019ff3235a7022d7cdf4559"
integrity sha512-LeLBMgEGSsG7giquSzvgBrTS7V5UL6ks3eQlUSbN8dJStlLFiRzUm5iqsRyzUB8carhfKjkJ2vzKqE6z1Vga9g==
core-util-is@~1.0.0:
version "1.0.3"
@@ -3456,9 +3456,9 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.896:
version "1.4.11"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.11.tgz#303c9deebbe90c68bf5c2c81a88a3bf4522c8810"
integrity sha512-2OhsaYgsWGhWjx2et8kaUcdktPbBGjKM2X0BReUCKcSCPttEY+hz2zie820JLbttU8jwL92+JJysWwkut3wZgA==
version "1.4.12"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.12.tgz#5f73d1278c6205fc41d7a0ebd75563046b77c5d8"
integrity sha512-zjfhG9Us/hIy8AlQ5OzfbR/C4aBv1Dg/ak4GX35CELYlJ4tDAtoEcQivXvyBdqdNQ+R6PhlgQqV8UNPJmhkJog==
emoji-regex@^8.0.0:
version "8.0.0"
@@ -3738,10 +3738,10 @@ eslint-visitor-keys@^3.1.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz#eee4acea891814cda67a7d8812d9647dd0179af2"
integrity sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==
eslint@~8.4.0:
version "8.4.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.4.0.tgz#2fa01b271cafc28addc2719e551acff5e89f5230"
integrity sha512-kv0XQcAQJL/VD9THQKhTQZVqkJKA+tIj/v2ZKNaIHRAADcJWFb+B/BAewUYuF6UVg1s2xC5qXVoDk0G8sKGeTA==
eslint@~8.4.1:
version "8.4.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.4.1.tgz#d6531bbf3e598dffd7c0c7d35ec52a0b30fdfa2d"
integrity sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==
dependencies:
"@eslint/eslintrc" "^1.0.5"
"@humanwhocodes/config-array" "^0.9.2"
@@ -6974,9 +6974,9 @@ object-copy@^0.1.0:
kind-of "^3.0.3"
object-inspect@^1.11.0, object-inspect@^1.9.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
version "1.11.1"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.1.tgz#d4bd7d7de54b9a75599f59a00bd698c1f1c6549b"
integrity sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==
object-is@^1.0.1:
version "1.1.5"
@@ -8555,10 +8555,10 @@ safe-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sass-loader@^12.3.0:
version "12.3.0"
resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.3.0.tgz#93278981c189c36a58cbfc37d4b9cef0cdc02871"
integrity sha512-6l9qwhdOb7qSrtOu96QQ81LVl8v6Dp9j1w3akOm0aWHyrTYtagDt5+kS32N4yq4hHk3M+rdqoRMH+lIdqvW6HA==
sass-loader@^12.4.0:
version "12.4.0"
resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.4.0.tgz#260b0d51a8a373bb8e88efc11f6ba5583fea0bcf"
integrity sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg==
dependencies:
klona "^2.0.4"
neo-async "^2.6.2"
@@ -10131,10 +10131,10 @@ vinyl@^2.0.0, vinyl@^2.2.0:
remove-trailing-separator "^1.0.1"
replace-ext "^1.0.0"
watchpack@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.0.tgz#a41bca3da6afaff31e92a433f4c856a0c25ea0c4"
integrity sha512-MnN0Q1OsvB/GGHETrFeZPQaOelWh/7O+EiFlj8sM9GPjtQkis7k01aAxrg/18kTfoIVcLL+haEVFlXDaSRwKRw==
watchpack@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25"
integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==
dependencies:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"
@@ -10262,10 +10262,10 @@ webpack-sources@^3.0.0, webpack-sources@^3.2.2:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.2.tgz#d88e3741833efec57c4c789b6010db9977545260"
integrity sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==
webpack@^5.64.4:
version "5.64.4"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.64.4.tgz#e1454b6a13009f57cc2c78e08416cd674622937b"
integrity sha512-LWhqfKjCLoYJLKJY8wk2C3h77i8VyHowG3qYNZiIqD6D0ZS40439S/KVuc/PY48jp2yQmy0mhMknq8cys4jFMw==
webpack@^5.65.0:
version "5.65.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.65.0.tgz#ed2891d9145ba1f0d318e4ea4f89c3fa18e6f9be"
integrity sha512-Q5or2o6EKs7+oKmJo7LaqZaMOlDWQse9Tm5l1WAfU/ujLGN5Pb0SqGeVkN/4bpPmEqEP5RnVhiqsOtWtUVwGRw==
dependencies:
"@types/eslint-scope" "^3.7.0"
"@types/estree" "^0.0.50"
@@ -10289,7 +10289,7 @@ webpack@^5.64.4:
schema-utils "^3.1.0"
tapable "^2.1.1"
terser-webpack-plugin "^5.1.3"
watchpack "^2.3.0"
watchpack "^2.3.1"
webpack-sources "^3.2.2"
websocket-driver@>=0.5.1, websocket-driver@^0.7.4: