Skip to content

Commit

Permalink
Make copying code blocks easier
Browse files Browse the repository at this point in the history
When hovering over code blocks, we now show a copy button. When clicked,
the textual representation of a code block is copied to the clipboard.
  • Loading branch information
yorickpeterse committed Jul 3, 2024
1 parent 46b1854 commit efba0cf
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 5 deletions.
5 changes: 4 additions & 1 deletion docs/source/css/icons.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@font-face {
font-family: 'icons';
src: url(data:font/woff2;base64,d09GMgABAAAAAAUEAAsAAAAACLQAAAS5AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmAAdBEIColYiDQLFAABNgIkAyQEIAWCbgcgGzsHID4NcHK76gfI8srYRpikabpkmJAS9kTyyUHXefpFSA4e+v3Rn4sFNZ0drqCb74vrvEnsauu0s8nJDfw/vz/yPl/iSRYSb8SJUpnf+tRjZ4fG5d1TaNBApS2qEQxp1aFt2uWloSc0Fi/gLtFJgfRrkYzSXk/4p4fHrjCJLEiy4oRSDHGehgTy+3/ga2tqqRkmQA9bAo/3D38/00UURtuABzijt/cXVVhpUbhLwAS5AV1EWpXI8R3YqYDnyCqdL14BpYLEFDgAch59Bua6ScQbyQJPp094s24a8L1DG2mKQBgBLkS7VJgKB7JcJAgbRdT/9oUGEhQEpe80ZA1Avb2w8zr12hEcFqwVlJ/YyCEqQMABXjHFBacvqYgFQK4YIQtp2DiYCAVTJzoHONCjheTkhST19UVV3JDhc0oLI4KAhe20Fght3SzdPQdMIrb3cV3fIowoTmPgsFlikYjIvkNi+wyb9iyDXgH3M4rGJ7tBH2YRVuGf6oMxwgp0udqagi9XY7HrZAR3IxZWJO9W7DYV/vXaOcxNDWpc9bS8RbGqACeXXlYsceVFbqixLf573GqevrjmpllwpJcDFvrefib9vtEy3Wf5fXoNxeazYP1dn3pYYK6bk2c5FxfYuyZMclnz+8R2y5sXfLX9f9AaFbxf0GnmCG29sJZjrH2d9lfgZhlMr56HVzI7nk1nYFZ9WmCPX8XETZ51cYnbtyBrvujOvojmB4CprBDVE30I/QWr7VBQA2v7uHkwxA/lGmc54cqfG8689IfblPfDtZzDcNbLdDY2OpG3t72OMNnkgEz3MTcXFkNbqSMiPcZsT0n3/4+ZXZNPCxy2ViWU96jKgVOK4M7AQP/wCxW8VsvpZdoygT6m9uJonNNK5duzLEixzjYgMS97ZleBct0Cp5P8f5WKQOXAigoaVYmNjUEPRKgEoaEaZYLxQpAdLChmHDuFNbzuu7GrdL7zKUVIJ/QDrcAFNShVjHAy3qdrY5TFMFyD4xOd7XxEgEkB2P/7914S2V3CZMTKrANVlza7LqTjFgmSQ+6o9iWiDal0h6Fe0d7+0DAwEIFbbaZjIRVumKfXIqJDkoA9SLoYvDnJVrMqFZMJaNXi9WmSwfl9nnRwChVL9mvJlMgN89SMqPaE6QWzUmVWPktaQkBTd9Us0zWM1TVSfu/u0NDMy31PtOnKuYtVC7d+Nhc61jvSR/88Qfdi7nLeenJ+fw+jyP72j10bWjNSGMrdrhtRogqp/Reh8PcRX8lR4dTdbwByS2b0/twdvOcPjmvq2XSN5Tq7GFtaGLuwfzk2AcYNAGygDgO6atDRQ9OQZX5cAORWL+f+F/rvTNQA8PT6P7S4teAMCmTIGaEThzG6RTPPRYtkpE81EFwPNJNlvk8ATlBNCbvRQ8KT1QrCUwQgKiQUAQoFgRFa41MVDrAIKhwhcDzeFRk6wUC0CwgMRKBAESBcgcFgjsbxWQoCCQQKEga3AoMZY5du25VCNqkUUkDpLd91jA2MoIh0SrAj2WRK2LFgcxmlMb2p3i9BCOlkUk4eyZT08L7+odtHVm8M/AsVAxADtZehRDPpFCyCZjJlpJPWXEc1SiRnl/CnsF65AUgG);
src: url(data:font/woff2;base64,d09GMgABAAAAAAVIAAsAAAAACWgAAAT6AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmAAdBEICosEiT8LFgABNgIkAygEIAWCbgcgG8oHIB6HsXvknFHsX5N8+HfTPzcJ0qSF8l4KNTWqxrQmTA02h82RqcJMDHhi+k09wTew2W3/oWulMxcRFi16gGc0O5dz2R/dVuAJ8gf0URhNgVGAz//Yy9gcYOVafeYZQNOZZCMEALWNeg5gw1AO+RUpxAWTM+KOLQuBv36lbzuhkI5aAIQJGKgE6ApfkCinQaQMOv73A7iDBgWCwL8Kdx2+8q/OO50AIKb/8gWI81vpfalVulOqlfqDBkEixLDohDTSWcIHIOeQT4RUdaYGDngmZUAHKJKaLiT2EMgC3X393BVxcaw77f9hcCmB+2lvbmsAB25Ea2J1Br7XYIDGyOnNigGzmbS19rJkgWYr39LWbj7C6Q95tBq3YQoxT7A0Rk4BVBkOzAZuejPpIloka56saXn/fq5jdW12u45o2x0OHadvtdlCC6iFYTXf+GXF2lSipNxUx3hDzehsUyzQJJ72P+Rh+OX3qYaDPKszyYlpnGy9FWC3E23KuVU+ZNIZtGret+y6EWU08sRgkJsOyy/asw/eZ3X2OuMhTp9xyZFzLcfhINrd3jYb3KQ0q7MQwjILtobpCtxGd3JtkynNUVZiQVzx6UVaKyfVHwOMRo9W4xmMaAyszkS09vxZzJzeBk4bf/Jl+kVWl3r+eexxaM5EGY95nLD5cXscCWarwnqOcJr3kcff+xq3QbOVB2DMXWa3VhLdVe9uRGtWmLYH5o7m3fZ4i71+f8IpR/UzTq98Yos7gemoLytTVqxIyVMq86Jlwn4BXSRLS5PxVG8QUkVBqYf6j/3++yef/PFHetBBydU1EybU15gwfptVIrVuW7lizVUpKg+qxNvEGWHiY6JLKTdOtL2JX8qoOCoxAcpXOlXqsFq4pVpkGfteFVwfVD97Ns4Fq1QJjYjFQhSoZjYVTsvhM0NdLVm1hE0qH4+JdojHxFYR4ljEt7Qdz1266dAg2WRmMTM5KIinxd3Cy+Ih8VEBkpuQ999/oyrlxVVavPmZWfUh1rMz7lDCY0Io5pdREd+WRjTNKTMD30FlornFGLHIrXveJ5vKm2aX2ryBCKpsvgKiK5PuzDhrqQ/NnMF7162JaD69yTX+4YUmr8ZuUXlKzepa+UhLRUTbvApcgvoPhVPx+6ebXUIyQsUW0WYkEYeKwOYRm+ZaLZbQfzUNCQ1xVQYmCBy1fLtrzeaSn352JsfBnUb5VPuVeskZKLpqREdMgiomMejPBaPhEaMjfyYlxviW8fNka97FtRYsK8B3/m6NbB5f5quM9a358nZ+W97DjyVs90B/Nyv56GJansi3y/PyCx+fz496dfmK8tIufmTA7R/IffwwzyF2+0vHTWOz1+9pLCpOykhPKiY/c896LLkNAE4AfRuEdLcDNZ8Bc1KU8iYEAAF2Fq77fKI0938xxwAAvrEGPwNf1w9iUEDhOk8OwWEepocgrJgJLqg43Y0YagEDDqVMgKQGzANTzTF1SHASZNUVAoA1UxChzkxDgETIMHvMAnCQmoUQoKA7C29MB11qGReQsCCYKUjQaqbBIg0yzEGzAHJ4m4VgUdrKIhVrL2z3moEh9GAK1JhxQ3ybpPhEtKEP06HHRXmBSEI8El1mk3je4++D0IQ+DGAWRjEZ00f80MOMm2sFZc+Uf3QxiXKjsTMRiAH0Qb0J9pMxE33o7duNeQiEcnWkFmHz9ceDxgQAAAA=);
font-weight: normal;
font-style: normal;
font-display: block;
Expand Down Expand Up @@ -31,6 +31,9 @@ i {
.icon-comments:before {
content: "\f086";
}
.icon-clipboard:before {
content: "\f0ea";
}
.icon-lightbulb-o:before {
content: "\f0eb";
}
33 changes: 33 additions & 0 deletions docs/source/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,39 @@ table tr:last-child td {
border-bottom: 0;
}

div.highlight {
position: relative;
}

div.highlight .copy {
background: var(--white);
display: none;
border-radius: var(--border-radius);
border: 1px solid var(--border);
cursor: pointer;
font-size: 12px;
padding: 5px;
position: absolute;
right: 5px;
top: 5px;
}

div.highlight .copy .copied-text {
display: none;
}

div.highlight .copy.copied .copied-text {
display: inline;
}

div.highlight .copy.copied .copy-text {
display: none;
}

div.highlight:hover .copy {
display: block;
}

.highlight .k {
font-weight: bold;
}
Expand Down
23 changes: 20 additions & 3 deletions docs/source/js/main.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
(function() {
"use strict";

document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.expand-menus a').forEach(function(button) {
button.addEventListener('click', function(event) {
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.expand-menus a').forEach((button) => {
button.addEventListener('click', (event) => {
event.preventDefault();

let query = button.dataset.toggle;
Expand All @@ -15,5 +15,22 @@
document.querySelector(query).classList.toggle('visible');
});
});

document.querySelectorAll('.highlight .copy').forEach((el) => {
let timer = null;

el.addEventListener('click', (e) => {
e.preventDefault();

if (timer) {
clearTimeout(timer);
timer = null;
}

el.classList.add('copied');
navigator.clipboard.writeText(el.previousSibling.textContent);
timer = setTimeout(function() { el.classList.remove('copied'); }, 2000);
});
});
});
})();
28 changes: 28 additions & 0 deletions docs/src/docs/filters.inko
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,34 @@ impl Filter for AutoTableOfContents {
}
}

class AddCopyButton {
fn static new -> AddCopyButton {
AddCopyButton()
}
}

impl Filter for AddCopyButton {
fn pub mut run(document: mut Document) {
document.nodes.iter_mut.each(fn (n) {
let el = match n {
case Element(e) if e.name == 'div' -> {
match e.attributes.opt('class') {
case Some('highlight') -> e
case _ -> return
}
}
case _ -> return
}

el.button.attr('class', 'copy').with(fn (btn) {
btn.i.attr('class', 'icon-clipboard')
btn.span.attr('class', 'copy-text').text(' Copy')
btn.span.attr('class', 'copied-text').text(' Copied!')
})
})
}
}

# A filter that turns relative document links (e.g. `[](ivm)`) into the correct
# URLs, optionally setting the link text if left out. This makes it easier to
# link to different documents.
Expand Down
3 changes: 2 additions & 1 deletion docs/src/docs/layouts.inko
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import builder.html
import builder.xml
import docs.config (Config)
import docs.filters (AutoTableOfContents, RelativeLinks)
import docs.filters (AddCopyButton, AutoTableOfContents, RelativeLinks)
import docs.menu (Item, Menu)
import docs.url (link_from)
import markdown.html (Filter, TableOfContents)
Expand All @@ -15,6 +15,7 @@ fn filters(menu: ref Menu, page: ref Page) -> Array[Filter] {
SyntaxHighlight.new as Filter,
Admonitions.new as Filter,
RelativeLinks(menu: menu, page: page) as Filter,
AddCopyButton.new as Filter,
AutoTableOfContents() as Filter, # This filter must come last
]
}
Expand Down

0 comments on commit efba0cf

Please sign in to comment.