Botão copy, take 1
   3 min leitura

Na primeira vez em que tentei configurar um botão Copy para as caixas de código, deixei uma nota no GitHub do tema Zdoc.
Há dias um outro utilizador do Zdoc publicou a solução que funcionou para ele, e com esse estímulo, tentei de novo.
Infelizmente, já devo ter manipulado de mais o DOM da minha versão do tema (manter-me compatível com o upstream, infelizmente, não vai dar para já) para poder utilizar directamente o código dele, mas tentei mexer mais um pouco no código que tinha tentado utilizar anteriormente, que era baseado nesta solução proposta por Tom Spencer
Com as minhas alterações, ficou assim:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// insert just before the </script> tag
// tomspencer, https://www.tomspencer.dev/blog/2018/09/14/adding-click-to-copy-buttons-to-a-hugo-powered-blog/
(function() {
  'use strict';

  if(!document.queryCommandSupported('copy')) {
    return;
  }

  function flashCopyMessage(el, msg) {
    el.textContent = msg;
    setTimeout(function() {
      el.textContent = "COPY";
    }, 1000);
  }

  function selectText(node) {
    var selection = window.getSelection();
    var range = document.createRange();
    range.selectNodeContents(node);
    selection.removeAllRanges();
    selection.addRange(range);
    return selection;
  }

  function addCopyButton(containerEl) {
    var copyBtn = document.createElement("button");
    copyBtn.className = "highlight-copy-btn";
    copyBtn.textContent = "COPY";

    var codeEl = containerEl.firstElementChild;
    copyBtn.addEventListener('click', function() {
      try {
        var selection = selectText(codeEl);
        document.execCommand('copy');
        selection.removeAllRanges();

        flashCopyMessage(copyBtn, 'Copied!')
      } catch(e) {
        console && console.log(e);
        flashCopyMessage(copyBtn, 'Failed :\'(')
        }
      });
   
      containerEl.appendChild(copyBtn);
    }

  // Add copy button to code blocks
  var highlightBlocks = document.getElementsByClassName('highlight');
  for (var i = 0; i < highlightBlocks.length; i++) {
    addCopyButton(highlightBlocks[i]);
  }
})();
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.highlight-copy-btn {
  position: relative;
  bottom: 22px;
  right: 0px;
  border: 0;
  border-radius: 4px;
  padding: 1px;
  font-size: 0.6em;
  line-height: 1.0;
  opacity: 0.6;
  min-width: 65px;
  text-align: center;
  letter-spacing: 2px;
  @include themify($codeblock) {
  color: themed('content-pre-color');
  background: themed('content-pre-background-color');
  border: 1.25px solid themed('border-line-color');
  }
  border-top-left-radius: 0;
  border-top-right-radius: 4px;
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 4px;
  white-space: nowrap;
  padding: 4px 4px 5px 4px;
  margin: 0 0 0 1px;
  cursor: pointer;
  opacity: 0.6;

}

.highlight-copy-btn:hover {
  @include themify($themes) {
    color: themed('link');
    background-color: themed('body-background-color');
  }
}

Funciona mais ou menos, mas só nos blocos de código para os quais foi detectada uma sintaxe (ou seja, em que o div class é highlight e o chroma foi activado). Para os outros, como os blocos de código nativos do MarkDown, não, e há ocasiões em que não posso ou não quero activar o chroma. Que fazer nesse caso?

O código do Preston Rodriguez, que agradeço, não funciona com as alterações que já fiz ao tema e que não consigo desfazer nem perceber onde estão a falhar (já disse que não pesco quase nada de JavaScript?)

Tentei repetir, sem sucesso, o código do Tom Spencer em layouts/partials/head/scripts.html, mas usando como selector

var codeBlocks = document.querySelectorAll('pre > code');
codeBlocks.forEach(function(plainBlock) {
  addCopyButton(plainBlock);
}

(um perfeito exemplo da questão - neste momento o botão COPY não aparece aqui, mas se conseguir resolver isto, vai passar a aparecer)

Neste artigo