Comments (14)
Any plans to provide this as a default option?
from asciidoctor-extensions-lab.
The following works for me, the button will be shown for pre blocks in the top corner or just below the language. The button will be shown when hovering the pre element. I would love to see that included in asciidoctor.
<script src="assets/clipboard.js"></script>
<style>
.listingblock:hover .clipboard {
display: block;
}
.clipboard {
display: none;
border: 0;
font-size: .75em;
text-transform: uppercase;
font-weight: 500;
padding: 6px;
color: #999;
position: absolute;
top: .425rem;
right: .5rem;
background: transparent;
}
code + .clipboard {
top: 2rem !important;
}
.clipboard:hover, .clipboard:focus, .clipboard:active {
outline: 0;
background-color: #eee9e6;
}
</style>
<script>
$(function() {
var pre = document.getElementsByTagName('pre');
for (var i = 0; i < pre.length; i++) {
var b = document.createElement('button');
b.className = 'clipboard';
b.textContent = 'Copy';
if (pre[i].childNodes.length === 1 && pre[i].childNodes[0].nodeType === 3) {
var div = document.createElement('div');
div.textContent = pre[i].textContent;
pre[i].textContent = '';
pre[i].appendChild(div);
}
pre[i].appendChild(b);
}
new ClipboardJS('.clipboard', {
target: function(b) {
var p = b.parentNode;
return p.className.includes("highlight")
? p.getElementsByClassName("code")[0]
: p.childNodes[0];
}
}).on('success', function(e) {
e.clearSelection();
e.trigger.textContent = 'Copied';
setTimeout(function() {
e.trigger.textContent = 'Copy';
}, 2000);
});
});
</script>
from asciidoctor-extensions-lab.
I implemented this behavior in the default Antora UI using the built-in clipboard API of the browser. I'll share the steps for how to integrate into a standalone HTML document generated by Asciidoctor. Please note that this code is MPL-2.0.
- Download the script https://gitlab.com/antora/antora-ui-default/-/raw/master/src/js/06-copy-to-clipboard.js into your output directory and rename it to copy-to-clipboard.js
- Download the icons SVG https://gitlab.com/antora/antora-ui-default/-/raw/master/src/img/octicons-16.svg into the img folder of the output directory (i.e, img/octicons-16.svg)
- Add
[.doc]
above your document title. The script assumes that the CSS class "doc" is set on the content container. - Define the document attribute
:docinfo: shared-footer
in the document header to enable the docinfo footer. - Create the file docinfo-footer.html in the source directory (which may be the output directory) and populate it with the following contents:
<style>
.doc .listingblock > .content {
position: relative;
}
.doc .listingblock code[data-lang]::before {
content: none;
}
.doc .source-toolbox {
display: flex;
position: absolute;
visibility: hidden;
top: 0.25rem;
right: 0.5rem;
color: #808080;
white-space: nowrap;
font-size: 0.85em;
}
.doc .listingblock:hover .source-toolbox {
visibility: visible;
}
.doc .source-toolbox .source-lang {
font-family: "Droid Sans Mono", "DejaVu Sans Mono", monospace;
text-transform: uppercase;
letter-spacing: 0.075em;
}
.doc .source-toolbox > :not(:last-child)::after {
content: "|";
letter-spacing: 0;
padding: 0 1ch;
}
.doc .source-toolbox .copy-button {
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
background: none;
border: none;
color: inherit;
outline: none;
padding: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
width: 1em;
height: 1em;
}
.doc .source-toolbox .copy-icon {
flex: none;
width: inherit;
height: inherit;
filter: invert(50.2%);
margin-top: 0.05em;
}
.doc .source-toolbox .copy-toast {
flex: none;
position: relative;
display: inline-flex;
justify-content: center;
margin-top: 1em;
border-radius: 0.25em;
padding: 0.5em;
cursor: auto;
opacity: 0;
transition: opacity 0.5s ease 0.75s;
background: rgba(0, 0, 0, 0.8);
color: #fff;
}
.doc .source-toolbox .copy-toast::after {
content: "";
position: absolute;
top: 0;
width: 1em;
height: 1em;
border: 0.55em solid transparent;
border-left-color: rgba(0, 0, 0, 0.8);
transform: rotate(-90deg) translateX(50%) translateY(50%);
transform-origin: left;
}
.doc .source-toolbox .copy-button.clicked .copy-toast {
opacity: 1;
transition: none;
}
</style>
<script src="copy-to-clipboard.js"></script>
Now convert the document using Asciidoctor.
There's a fair amount of CSS required to support this feature since it needs to be placed very specifically within the listing block and react to the interaction.
Please note that the clipboard API is not available when the file is served over http unless the host is localhost.
from asciidoctor-extensions-lab.
To implement the approach shown above in #61 (comment) you could probably just use a Docinfo processor but this wouldn't provide flexibility to enable and disable on particular blocks or documents which might be desirable.
from asciidoctor-extensions-lab.
Agreed! I especially like the "no flash" part.
We'll have to think about where to put the button because we're already using the upper right for the source language. Perhaps we can implement something like a double click to copy. That seems natural. We could put a floating hint under the listing block with the instructions to provide the hint.
Related issues:
from asciidoctor-extensions-lab.
We would really welcome this functionality. Is there a chance that this gets included in the next release?
from asciidoctor-extensions-lab.
I think it can be an extension, perhaps even a dedicated project. It's certainly a great addition, but not something I'm not yet comfortable putting into core. Though we are planning to add it to Antora (see https://gitlab.com/antora/antora-ui-default/issues/70).
from asciidoctor-extensions-lab.
@mojavelinux thanks for the answer.
from asciidoctor-extensions-lab.
Hi, is there any progress on this, please?
from asciidoctor-extensions-lab.
If you use asciidoctorj you could look at the Puravida extension and also the documentation. The way the extension works is shown in the docs.
In this case it's been implemented as a PostProcessor with resources added directly to the output of the processing. It could be implemented in a bunch of different ways but to get similar effect perhaps a Docinfo Processor and a PostProcessor would be one way.
from asciidoctor-extensions-lab.
The following works for me, the button will be shown for pre blocks in the top corner or just below the language. The button will be shown when hovering the pre element. I would love to see that included in asciidoctor.
<script src="assets/clipboard.js"></script> <style> .listingblock:hover .clipboard { display: block; } .clipboard { display: none; border: 0; font-size: .75em; text-transform: uppercase; font-weight: 500; padding: 6px; color: #999; position: absolute; top: .425rem; right: .5rem; background: transparent; } code + .clipboard { top: 2rem !important; } .clipboard:hover, .clipboard:focus, .clipboard:active { outline: 0; background-color: #eee9e6; } </style> <script> $(function() { var pre = document.getElementsByTagName('pre'); for (var i = 0; i < pre.length; i++) { var b = document.createElement('button'); b.className = 'clipboard'; b.textContent = 'Copy'; if (pre[i].childNodes.length === 1 && pre[i].childNodes[0].nodeType === 3) { var div = document.createElement('div'); div.textContent = pre[i].textContent; pre[i].textContent = ''; pre[i].appendChild(div); } pre[i].appendChild(b); } new ClipboardJS('.clipboard', { target: function(b) { var p = b.parentNode; return p.className.includes("highlight") ? p.getElementsByClassName("code")[0] : p.childNodes[0]; } }).on('success', function(e) { e.clearSelection(); e.trigger.textContent = 'Copied'; setTimeout(function() { e.trigger.textContent = 'Copy'; }, 2000); }); }); </script>
@minad Pardon my ignorance of web dev, but I tried pasting the above snippet into the <head>
section of an html file rendered from asciidoctor just to see what would happen, and I wasn't able to get it to work. I made a local clipboard.js
file from the contents here and changed <script src="assets/clipboard.js">
to just <script src="clipboard.js">
since it's all in the same directory. It didn't work for me. I'm sure I'm missing something embarrassingly simple, but I just wanted a quick proof of concept.
Could you explain how to get this to work to a web dev novice?
from asciidoctor-extensions-lab.
Here is a slightly adapted variant, which works for me. You have to provide clipboard.min.js in the assets folder.
<script src="assets/clipboard.min.js"></script>
<style>
.listingblock:hover .clipboard {
display: block;
}
.clipboard {
display: none;
border: 0;
font-size: .75em;
text-transform: uppercase;
font-weight: 500;
padding: 6px;
color: #999;
position: absolute;
top: .425rem;
right: .5rem;
background: transparent;
}
code + .clipboard {
top: 2rem !important;
}
.clipboard:hover, .clipboard:focus, .clipboard:active {
outline: 0;
background-color: #eee9e6;
}
</style>
<script >
window.onload = function() {
var pre = document.getElementsByTagName('pre');
for (var i = 0; i < pre.length; i++) {
var b = document.createElement('button');
b.className = 'clipboard';
b.textContent = 'Copy';
if (pre[i].childNodes.length === 1 && pre[i].childNodes[0].nodeType === 3) {
var div = document.createElement('div');
div.textContent = pre[i].textContent;
pre[i].textContent = '';
pre[i].appendChild(div);
}
pre[i].appendChild(b);
}
var clipboard = new ClipboardJS('.clipboard', {
target: function(b) {
var p = b.parentNode;
if (p.className.includes("highlight")) {
var elems = p.getElementsByTagName("code");
if (elems.length > 0)
return elems[0];
}
return p.childNodes[0];
}
});
clipboard.on('success', function(e) {
e.clearSelection();
e.trigger.textContent = 'Copied';
setTimeout(function() {
e.trigger.textContent = 'Copy';
}, 2000);
});
clipboard.on('error', function(e) {
console.error('Action:', e.action, e);
console.error('Trigger:', e.trigger);
});
};
</script>
from asciidoctor-extensions-lab.
Thanks to you all. I modified the code a little to be more like AsciiDoctor website layout, and I also add a rotation animation instead of copied text:
<script src="assets/clipboard.min.js"></script>
<style>
.listingblock code[data-lang]::before {
display: none;
content: attr(data-lang) " |";
position: absolute;
font-size: 0.75em;
top: 0.425rem;
right: 1.7rem;
line-height: 1;
text-transform: uppercase;
color: inherit;
opacity: 0.5
}
.listingblock:hover code[data-lang]::before {
display: block
}
.listingblock:hover .clipboard {
display: block;
}
.clipboard {
display: none;
content: " ";
position: absolute;
top: 0.3rem;
right: 0.5em;
height: 1em;
color: inherit;
border: none;
opacity: 0.5;
cursor: pointer;
filter: invert(50.2%);
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3E%3Cpath fill-rule='evenodd' d='M5.75 1a.75.75 0 00-.75.75v3c0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75v-3a.75.75 0 00-.75-.75h-4.5zm.75 3V2.5h3V4h-3zm-2.874-.467a.75.75 0 00-.752-1.298A1.75 1.75 0 002 3.75v9.5c0 .966.784 1.75 1.75 1.75h8.5A1.75 1.75 0 0014 13.25v-9.5a1.75 1.75 0 00-.874-1.515.75.75 0 10-.752 1.298.25.25 0 01.126.217v9.5a.25.25 0 01-.25.25h-8.5a.25.25 0 01-.25-.25v-9.5a.25.25 0 01.126-.217z'%3E%3C/path%3E%3C/svg%3E") no-repeat;
}
@keyframes clibpard_rotation_frame {
50% { transform: rotateY(180deg); }
}
.clipboard_success {
filter: invert(100%);
animation: clibpard_rotation_frame 1s;
}
</style>
<script >
window.onload = function() {
var pre = document.getElementsByTagName('pre');
for (var i = 0; i < pre.length; i++) {
var b = document.createElement('button');
b.className = 'clipboard';
b.textContent = ' ';
if (pre[i].childNodes.length === 1 && pre[i].childNodes[0].nodeType === 3) {
var div = document.createElement('div');
div.textContent = pre[i].textContent;
pre[i].textContent = '';
pre[i].appendChild(div);
}
pre[i].appendChild(b);
}
var clipboard = new ClipboardJS('.clipboard', {
target: function(b) {
var p = b.parentNode;
if (p.className.includes("highlight")) {
var elems = p.getElementsByTagName("code");
if (elems.length > 0)
return elems[0];
}
return p.childNodes[0];
}
});
clipboard.on('success', function(e) {
e.clearSelection();
e.trigger.classList.add('clipboard_success');
setTimeout(function() {
e.trigger.classList.remove('clipboard_success');
}, 1300);
});
clipboard.on('error', function(e) {
console.error('Action:', e.action, e);
console.error('Trigger:', e.trigger);
});
};
</script>
from asciidoctor-extensions-lab.
I've gone ahead and added this extension to the lab.
from asciidoctor-extensions-lab.
Related Issues (20)
- Is there a configuration open for using divs instead of tables for admonitions? HOT 1
- mathoid-treeprocessor and new versions of mathoid HOT 4
- npm install mathoid error: Package libffi was not found in the pkg-config search path. HOT 2
- Convert all inline example to use create_inline otherwise it gives "INFO: expected substitution value for custom inline macro to be of type Inline" HOT 5
- Integrate asciidoc-coalescer.rb as extension/converter so as to make it available in the CLI HOT 1
- sectnum offset tree processor always returns 1 or 2 HOT 1
- Make all these extensions installable with gem install HOT 4
- generate pdf with chart block HOT 4
- adding row name to chart HOT 3
- Add a metadata object for year HOT 1
- Add metadata object for tag message HOT 2
- man-inline-macro doesn't generate the correct output in the manpage backend HOT 5
- Section offset plugin fails when creating PDF HOT 4
- Using the Preprocessor ignores ifdef directives HOT 1
- add link to the current script location as comment into the script HOT 6
- Idea: Create file tree containing all included files HOT 2
- Graduate the asciidoc-coalescer.rb script to a separate project HOT 4
- showcomments-preprocessor seems broken with latest asciidoctor HOT 2
- Create summaries from distributed definitions HOT 1
- Help With Callouts: Any Examples? HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from asciidoctor-extensions-lab.