diff --git a/_config.yml b/_config.yml index 86706fb8d650817ba775a0911ac7fee2c0c285b2..2273e8b7b575539932f377bcc30472b763422dda 100644 --- a/_config.yml +++ b/_config.yml @@ -73,6 +73,9 @@ search: # Supports true or false (default) button: false +# For copy button on code +enable_copy_code_button: true + # To disable support for mermaid diagrams (https://mermaid-js.github.io/mermaid/), # comment out the `mermaid` and `version` keys below # By default, consuming the theme as a gem leaves mermaid disabled; it is opt-in diff --git a/_includes/icons/code_copy.html b/_includes/icons/code_copy.html new file mode 100644 index 0000000000000000000000000000000000000000..02f5068c0f171a904b72f92ad63e811b83fb725a --- /dev/null +++ b/_includes/icons/code_copy.html @@ -0,0 +1,15 @@ +<!-- Feather. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md --> +<symbol id="svg-copy" viewBox="0 0 16 16"> + <title>Copy</title> + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"> + <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/> + <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/> + </svg> +</symbol> +<symbol id="svg-copied" viewBox="0 0 16 16"> + <title>Copied</title> + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16"> + <path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/> + <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/> + </svg> +</symbol> \ No newline at end of file diff --git a/_layouts/default.html b/_layouts/default.html index f80f52df51ff3191740c4bd5b7938f2f44ef3a5d..7ac9269b71ed7bc2467885c6a5a8707b733796d8 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -40,6 +40,7 @@ layout: table_wrappers </svg> </symbol> {% include icons/external_link.html %} + {% include icons/code_copy.html %} </svg> <div class="side-bar"> diff --git a/_sass/code.scss b/_sass/code.scss index 1ac7adc7d9ce541fcd3500abcfbba146abcbd964..c12421b65a6ad1919a755be124c0ea8d4c2b2f2f 100644 --- a/_sass/code.scss +++ b/_sass/code.scss @@ -3,12 +3,15 @@ // {% raw %} -code { - padding: 0.2em 0.15em; - font-weight: 400; - background-color: $code-background-color; - border: $border $border-color; - border-radius: $border-radius; +// This instruction applies to all queues not within 'pre', avoiding 'code' generated by the highlight. +:not(pre) { + & > code { + padding: 0.2em 0.15em; + font-weight: 400; + background-color: $code-background-color; + border: $border $border-color; + border-radius: $border-radius; + } } // Avoid appearance of dark border around visited code links in Safari @@ -47,18 +50,77 @@ a:visited code { // Kramdown line_numbers = true: fences have a wider gutter than with Liquid? // ```[LANG]...``` + +// the code may appear with 3 different types: +// container \ case: default case, code with line number, code with html rendering +// top level: div.highlighter-rouge, div.listingblock > div.content, figure.highlight +// second level: div.highlight, .table-wrapper, pre +// third level: pre.highlight, td.code, absent +// last level: code, pre, code (optionality) +// highlighter level: span, span, span +// the spacing are only in the second level for case 1, 3 and in the thirt level for case 2 + +// select top level container div.highlighter-rouge, -div.listingblock > div.content { - padding: $sp-3; +div.listingblock > div.content, +figure.highlight { margin-top: 0; margin-bottom: $sp-3; - overflow-x: auto; background-color: $code-background-color; border-radius: $border-radius; box-shadow: none; -webkit-overflow-scrolling: touch; + position: relative; + padding: 0; + + // copy button (or other button) + // the button appear only when there is a hover on the code or focus on button + > button { + width: $sp-3; + opacity: 0; + position: absolute; + top: 0; + right: 0; + border: $sp-3 solid $code-background-color; + background-color: $code-background-color; + color: $body-text-color; + box-sizing: content-box; + + svg { + fill: $body-text-color; + } + + &:active { + text-decoration: none; + outline: none; + opacity: 1; + } + + &:focus { + opacity: 1; + } + } + + // the button can be seen by doing a simple hover in the code, there is no need to go over the location of the button + &:hover { + > button { + cursor: copy; + opacity: 1; + } + } +} + +// setting the spacing and scrollbar on the second level for the first case +// remove all space on the second and thirt level +div.highlighter-rouge, +div.listingblock { + div.highlight { + overflow-x: auto; + padding: $sp-3; + margin: 0; + border: 0; + } - div.highlight, pre.highlight, code { padding: 0; @@ -69,19 +131,15 @@ div.listingblock > div.content { // {% highlight LANG %}...{% endhighlight %}, // {% highlight LANG linenos %}...{% endhighlight %}: -figure.highlight { - padding: $sp-3; - margin-top: 0; - margin-bottom: $sp-3; - overflow-x: auto; - background-color: $code-background-color; - border-radius: $border-radius; - box-shadow: none; - -webkit-overflow-scrolling: touch; +// setting the spacing and scrollbar on the second level for the thirt case +// the css rule are apply only to the last code enviroment +// setting the scroolbar +figure.highlight { pre, - code { - padding: 0; + :not(pre) > code { + overflow-x: auto; + padding: $sp-3; margin: 0; border: 0; } @@ -89,6 +147,8 @@ figure.highlight { // ```[LANG]...```, kramdown line_numbers = true, // {% highlight LANG linenos %}...{% endhighlight %}: + +// setting the spacing and scrollbar on the thirt level for the second case .highlight .table-wrapper { padding: 0; margin: 0; @@ -108,6 +168,7 @@ figure.highlight { td.gl { width: 1em; padding-right: $sp-3; + padding-left: $sp-3; } pre { @@ -116,10 +177,7 @@ figure.highlight { } } -// -// Code examples (rendered) -// - +// Code examples: html render of a code .code-example, .listingblock > .title { padding: $sp-3; diff --git a/assets/js/just-the-docs.js b/assets/js/just-the-docs.js index f3bd813ab1fea7cc1be2780bd34055efd4dd5e41..223f28b8b76fa3ee3974acf56f8fa8355d4e417b 100644 --- a/assets/js/just-the-docs.js +++ b/assets/js/just-the-docs.js @@ -479,6 +479,47 @@ jtd.onReady(function(){ scrollNav(); }); +// Copy button on code + + +{%- if site.enable_copy_code_button != false %} + +jtd.onReady(function(){ + + var codeBlocks = document.querySelectorAll('div.highlighter-rouge, div.listingblock, figure.highlight'); + + var svgCopied = '<svg viewBox="0 0 24 24" class="copy-icon"><use xlink:href="#svg-copied"></use></svg>'; + var svgCopy = '<svg viewBox="0 0 24 24" class="copy-icon"><use xlink:href="#svg-copy"></use></svg>'; + + codeBlocks.forEach(codeBlock => { + var copyButton = document.createElement('button'); + var timeout = null; + copyButton.type = 'button'; + copyButton.ariaLabel = 'Copy code to clipboard'; + copyButton.innerHTML = svgCopy; + codeBlock.append(copyButton); + + copyButton.addEventListener('click', function () { + if(timeout === null) { + var code = codeBlock.querySelector('code').innerText.trim(); + window.navigator.clipboard.writeText(code); + + copyButton.innerHTML = svgCopied; + + var timeoutSetting = 4000; + + timeout = setTimeout(function () { + copyButton.innerHTML = svgCopy; + timeout = null; + }, timeoutSetting); + } + }); + }); + +}); + +{%- endif %} + })(window.jtd = window.jtd || {}); {% include js/custom.js %} diff --git a/docs/ui-components/code.md b/docs/ui-components/code.md index 1cac8aa5606622a395df9782a0f3aa287208e671..a4092f1ae44576759597a2d9d6faaa2fa3819141 100644 --- a/docs/ui-components/code.md +++ b/docs/ui-components/code.md @@ -143,3 +143,14 @@ graph TD; ``` *Note: for demonstration purposes, we've enabled mermaid on this site. It is still disabled by default, and users need to opt-in to use it.* + +## Copy button + +The copy button for code blocks can be enabled or disabled via the `enable_copy_code_button` key in `_config.yml`. By default, the value of this key is `false`; users need to opt-in. + +```yaml +# For copy button on code +enable_copy_code_button: true +``` + +Note that this feature requires JavaScript; if JavaScript is disabled in the browser, this feature will not work. \ No newline at end of file