Skip to content

Commit 8aea972

Browse files
authored
chore(website): add copy button the code blocks (#9750)
1 parent 7e5e422 commit 8aea972

File tree

6 files changed

+95
-3
lines changed

6 files changed

+95
-3
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ website/build
1010
website/node_modules
1111
website/i18n/*.js
1212
website/translated_docs
13+
website/static
1314
!.eslintrc.js

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@
9595
"jest-coverage": "yarn jest --coverage",
9696
"lint": "eslint . --cache --ext js,jsx,ts,tsx,md",
9797
"lint-es5-build": "eslint --no-eslintrc --no-ignore --env=browser packages/*/build-es5",
98-
"lint:prettier": "prettier '**/*.{md,yml,yaml}' --write --ignore-path .gitignore",
99-
"lint:prettier:ci": "prettier '**/*.{md,yml,yaml}' --check --ignore-path .gitignore",
98+
"lint:prettier": "prettier '**/*.{md,yml,yaml}' 'website/static/**/*.{css,js}' --write --ignore-path .gitignore",
99+
"lint:prettier:ci": "prettier '**/*.{md,yml,yaml}' 'website/static/**/*.{css,js}' --check --ignore-path .gitignore",
100100
"postinstall": "opencollective postinstall && yarn build",
101101
"install-no-ts-build": "node ./scripts/remove-postinstall && yarn --no-progress --frozen-lockfile && node ./scripts/build",
102102
"remove-prettier-dep": "node ./scripts/remove-prettier-dep",

scripts/checkCopyrightHeaders.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ const CUSTOM_IGNORED_PATTERNS = [
102102
'^packages/expect/src/jasmineUtils\\.ts$',
103103
'^packages/jest-config/src/vendor/jsonlint\\.js$',
104104
'^packages/jest-diff/src/cleanupSemantic\\.ts$',
105+
'^website/static/css/code-block-buttons\\.css$',
106+
'^website/static/js/code-block-buttons\\.js',
105107
].map(createRegExp);
106108

107109
const IGNORED_PATTERNS = [

website/siteConfig.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,12 @@ const siteConfig = {
121121
secondaryColor: '#095708',
122122
prismColor: 'rgba(153, 66, 79, 0.03)',
123123
},
124-
scripts: ['https://buttons.github.io/buttons.js'],
124+
scripts: [
125+
'https://buttons.github.io/buttons.js',
126+
'https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js',
127+
'/js/code-block-buttons.js',
128+
],
129+
stylesheets: ['/css/code-block-buttons.css'],
125130
repoUrl,
126131
siteConfigUrl:
127132
'https://github.com/facebook/jest/edit/master/website/siteConfig.js',
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* "Copy" code block button */
2+
pre {
3+
position: relative;
4+
}
5+
6+
pre .btnIcon {
7+
position: absolute;
8+
top: 4px;
9+
z-index: 2;
10+
cursor: pointer;
11+
border: 1px solid transparent;
12+
padding: 0;
13+
color: var(--green);
14+
background-color: transparent;
15+
height: 30px;
16+
transition: all 0.25s ease-out;
17+
}
18+
19+
pre .btnIcon:hover {
20+
text-decoration: none;
21+
}
22+
23+
.btnIcon__body {
24+
align-items: center;
25+
display: flex;
26+
}
27+
28+
.btnIcon svg {
29+
fill: currentColor;
30+
margin-right: 0.4em;
31+
}
32+
33+
.btnIcon__label {
34+
font-size: 11px;
35+
}
36+
37+
.btnClipboard {
38+
right: 10px;
39+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
window.addEventListener('load', function () {
2+
function button(label, ariaLabel, icon, className) {
3+
const btn = document.createElement('button');
4+
btn.classList.add('btnIcon', className);
5+
btn.setAttribute('type', 'button');
6+
btn.setAttribute('aria-label', ariaLabel);
7+
btn.innerHTML =
8+
'<div class="btnIcon__body">' +
9+
icon +
10+
'<strong class="btnIcon__label">' +
11+
label +
12+
'</strong>' +
13+
'</div>';
14+
return btn;
15+
}
16+
17+
function addButtons(codeBlockSelector, btn) {
18+
document.querySelectorAll(codeBlockSelector).forEach(function (code) {
19+
code.parentNode.appendChild(btn.cloneNode(true));
20+
});
21+
}
22+
23+
const copyIcon =
24+
'<svg width="12" height="12" viewBox="340 364 14 15" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M342 375.974h4v.998h-4v-.998zm5-5.987h-5v.998h5v-.998zm2 2.994v-1.995l-3 2.993 3 2.994v-1.996h5v-1.995h-5zm-4.5-.997H342v.998h2.5v-.997zm-2.5 2.993h2.5v-.998H342v.998zm9 .998h1v1.996c-.016.28-.11.514-.297.702-.187.187-.422.28-.703.296h-10c-.547 0-1-.452-1-.998v-10.976c0-.546.453-.998 1-.998h3c0-1.107.89-1.996 2-1.996 1.11 0 2 .89 2 1.996h3c.547 0 1 .452 1 .998v4.99h-1v-2.995h-10v8.98h10v-1.996zm-9-7.983h8c0-.544-.453-.996-1-.996h-1c-.547 0-1-.453-1-.998 0-.546-.453-.998-1-.998-.547 0-1 .452-1 .998 0 .545-.453.998-1 .998h-1c-.547 0-1 .452-1 .997z" fill-rule="evenodd"/></svg>';
25+
26+
addButtons(
27+
'.hljs',
28+
button('Copy', 'Copy code to clipboard', copyIcon, 'btnClipboard')
29+
);
30+
31+
const clipboard = new ClipboardJS('.btnClipboard', {
32+
target: function (trigger) {
33+
return trigger.parentNode.querySelector('code');
34+
},
35+
});
36+
37+
clipboard.on('success', function (event) {
38+
event.clearSelection();
39+
const textEl = event.trigger.querySelector('.btnIcon__label');
40+
textEl.textContent = 'Copied';
41+
setTimeout(function () {
42+
textEl.textContent = 'Copy';
43+
}, 2000);
44+
});
45+
});

0 commit comments

Comments
 (0)