mirror of
https://github.com/clearlinux/clear-linux-documentation.git
synced 2026-04-28 11:03:58 +00:00
Implements copy button (#1180)
* Adds support for sphinx_copybutton. Closes #1134 Signed-off-by: Michael Vincerra <michael.vincerra@intel.com> * Additional config. Signed-off-by: Michael Vincerra <michael.vincerra@intel.com> * Remove cruft.;) Signed-off-by: Michael Vincerra <michael.vincerra@intel.com> * **DO NOT MERGE** Please verify changes with tutorials/proxy.rst. Once verified remove changes to proxy.rst. Signed-off-by: Kevin Putnam <kevin.putnam@intel.com> * Provides example usage of new codeblock copy behavior: 1. ShellSession (line 228 in kernel-modules-dkms.rst) - will copy everything except prompt. 2. Console (line 74 in kernel-modules-dkms.rst) - will copy only the input line without the prompt. Signed-off-by: Kevin Putnam <kevin.putnam@intel.com> Co-authored-by: Michael Vincerra <michael.vincerra@intel.com>
This commit is contained in:
1
make.bat
1
make.bat
@@ -80,6 +80,7 @@ if "%1" == "html" (
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
copy source\_scripts\js\copybutton.js %BUILDDIR%\html\_static
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
@@ -7,3 +7,4 @@ sphinx-sitemap==1.0.2
|
||||
Jinja2==2.10.1
|
||||
GitPython==3.0.8
|
||||
sphinx-tabs
|
||||
sphinx-copybutton
|
||||
|
||||
@@ -73,6 +73,7 @@ htmlzh:
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
cp _scripts/js/copybutton.js $(BUILDDIR)/html/_static
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
|
||||
147
source/_scripts/js/copybutton.js
Normal file
147
source/_scripts/js/copybutton.js
Normal file
@@ -0,0 +1,147 @@
|
||||
// introduces special behavior for ShellSession
|
||||
|
||||
// Localization support
|
||||
const messages = {
|
||||
'en': {
|
||||
'copy': 'Copy',
|
||||
'copy_to_clipboard': 'Copy to clipboard',
|
||||
'copy_success': 'Copied!',
|
||||
'copy_failure': 'Failed to copy',
|
||||
},
|
||||
'es' : {
|
||||
'copy': 'Copiar',
|
||||
'copy_to_clipboard': 'Copiar al portapapeles',
|
||||
'copy_success': '¡Copiado!',
|
||||
'copy_failure': 'Error al copiar',
|
||||
},
|
||||
'de' : {
|
||||
'copy': 'Kopieren',
|
||||
'copy_to_clipboard': 'In die Zwischenablage kopieren',
|
||||
'copy_success': 'Kopiert!',
|
||||
'copy_failure': 'Fehler beim Kopieren',
|
||||
}
|
||||
}
|
||||
|
||||
let locale = 'en'
|
||||
if( document.documentElement.lang !== undefined
|
||||
&& messages[document.documentElement.lang] !== undefined ) {
|
||||
locale = document.documentElement.lang
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up copy/paste for code blocks
|
||||
*/
|
||||
|
||||
const runWhenDOMLoaded = cb => {
|
||||
if (document.readyState != 'loading') {
|
||||
cb()
|
||||
} else if (document.addEventListener) {
|
||||
document.addEventListener('DOMContentLoaded', cb)
|
||||
} else {
|
||||
document.attachEvent('onreadystatechange', function() {
|
||||
if (document.readyState == 'complete') cb()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const codeCellId = index => `codecell${index}`
|
||||
|
||||
// Clears selected text since ClipboardJS will select the text when copying
|
||||
const clearSelection = () => {
|
||||
if (window.getSelection) {
|
||||
window.getSelection().removeAllRanges()
|
||||
} else if (document.selection) {
|
||||
document.selection.empty()
|
||||
}
|
||||
}
|
||||
|
||||
// Changes tooltip text for two seconds, then changes it back
|
||||
const temporarilyChangeTooltip = (el, newText) => {
|
||||
const oldText = el.getAttribute('data-tooltip')
|
||||
el.setAttribute('data-tooltip', newText)
|
||||
setTimeout(() => el.setAttribute('data-tooltip', oldText), 2000)
|
||||
}
|
||||
|
||||
// Callback when a copy button is clicked. Will be passed the node that was clicked
|
||||
// should then grab the text and replace pieces of text that shouldn't be used in output
|
||||
var copyTargetText = (trigger) => {
|
||||
var target = document.querySelector(trigger.attributes['data-clipboard-target'].value);
|
||||
var textContent = target.innerText.split('\n');
|
||||
var copybuttonPromptText = '$ '; // Inserted from config
|
||||
var onlyCopyPromptLines = true; // Inserted from config
|
||||
var removePrompts = true; // Inserted from config
|
||||
|
||||
grandParent = target.parentElement.parentElement;
|
||||
blockType = grandParent.classList;
|
||||
if (blockType[0].includes("ShellSession")) {
|
||||
onlyCopyPromptLines = false;
|
||||
}
|
||||
|
||||
// Text content line filtering based on prompts (if a prompt text is given)
|
||||
if (copybuttonPromptText.length > 0) {
|
||||
// If only copying prompt lines, remove all lines that don't start w/ prompt
|
||||
if (onlyCopyPromptLines) {
|
||||
linesWithPrompt = textContent.filter((line) => {
|
||||
return line.startsWith(copybuttonPromptText) || (line.length == 0); // Keep newlines
|
||||
});
|
||||
// Check to make sure we have at least one non-empty line
|
||||
var nonEmptyLines = linesWithPrompt.filter((line) => {return line.length > 0});
|
||||
// If we detected lines w/ prompt, then overwrite textContent w/ those lines
|
||||
if ((linesWithPrompt.length > 0) && (nonEmptyLines.length > 0)) {
|
||||
textContent = linesWithPrompt;
|
||||
}
|
||||
}
|
||||
// Remove the starting prompt from any remaining lines
|
||||
if (removePrompts) {
|
||||
textContent.forEach((line, index) => {
|
||||
if (line.startsWith(copybuttonPromptText)) {
|
||||
textContent[index] = line.slice(copybuttonPromptText.length);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
textContent = textContent.join('\n');
|
||||
// Remove a trailing newline to avoid auto-running when pasting
|
||||
if (textContent.endsWith("\n")) {
|
||||
textContent = textContent.slice(0, -1)
|
||||
}
|
||||
return textContent
|
||||
}
|
||||
|
||||
const addCopyButtonToCodeCells = () => {
|
||||
// If ClipboardJS hasn't loaded, wait a bit and try again. This
|
||||
// happens because we load ClipboardJS asynchronously.
|
||||
if (window.ClipboardJS === undefined) {
|
||||
setTimeout(addCopyButtonToCodeCells, 250)
|
||||
return
|
||||
}
|
||||
|
||||
// Add copybuttons to all of our code cells
|
||||
const codeCells = document.querySelectorAll('div.highlight pre')
|
||||
codeCells.forEach((codeCell, index) => {
|
||||
const id = codeCellId(index)
|
||||
codeCell.setAttribute('id', id)
|
||||
const pre_bg = getComputedStyle(codeCell).backgroundColor;
|
||||
|
||||
const clipboardButton = id =>
|
||||
`<a class="copybtn o-tooltip--left" style="background-color: ${pre_bg}" data-tooltip="${messages[locale]['copy']}" data-clipboard-target="#${id}">
|
||||
<img src="${DOCUMENTATION_OPTIONS.URL_ROOT}_static/copy-button.svg" alt="${messages[locale]['copy_to_clipboard']}">
|
||||
</a>`
|
||||
codeCell.insertAdjacentHTML('afterend', clipboardButton(id))
|
||||
})
|
||||
|
||||
// Initialize with a callback so we can modify the text before copy
|
||||
const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText})
|
||||
|
||||
// Update UI with error/success messages
|
||||
clipboard.on('success', event => {
|
||||
clearSelection()
|
||||
temporarilyChangeTooltip(event.trigger, messages[locale]['copy_success'])
|
||||
})
|
||||
|
||||
clipboard.on('error', event => {
|
||||
temporarilyChangeTooltip(event.trigger, messages[locale]['copy_failure'])
|
||||
})
|
||||
}
|
||||
|
||||
runWhenDOMLoaded(addCopyButtonToCodeCells)
|
||||
@@ -368,6 +368,15 @@ div.highlight-python .highlight:before{
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
div.highlight-ShellSession .highlight:before{
|
||||
background: #909090;
|
||||
color: white;
|
||||
content: " Shell ";
|
||||
font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;
|
||||
font-size: 14px;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
div.highlight-console .highlight:before{
|
||||
background: #909090;
|
||||
color: white;
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
#support for modified code block
|
||||
from pygments.lexers.shell import BashSessionLexer
|
||||
from sphinx.highlighting import lexers
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
@@ -26,6 +29,17 @@ import shlex
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
#############
|
||||
#
|
||||
# Add a special lexer to add a class to console lexer
|
||||
#
|
||||
#############
|
||||
|
||||
class copyAllConsole (BashSessionLexer):
|
||||
name = 'ShellSession'
|
||||
|
||||
lexers['ShellSession'] = copyAllConsole(startinLine=True)
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
@@ -34,7 +48,8 @@ import shlex
|
||||
#]
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx_sitemap', 'sphinx_tabs.tabs'
|
||||
'sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx_sitemap',
|
||||
'sphinx_tabs.tabs', 'sphinx_copybutton'
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
@@ -174,7 +189,8 @@ html_favicon = '_images/favicon.ico'
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
#html_static_path = ['_static']
|
||||
# html_static_path = ['_scripts']
|
||||
copybutton_prompt_text = "$ "
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
|
||||
@@ -71,7 +71,7 @@ bundle:
|
||||
and *lts* kernels are enabled to build and load out-of-tree kernel modules
|
||||
with DKMS.
|
||||
|
||||
.. code-block:: bash
|
||||
.. code-block:: console
|
||||
|
||||
$ uname -r
|
||||
5.XX.YY-ZZZZ.native
|
||||
@@ -225,9 +225,9 @@ The instructions below show a generic example:
|
||||
#. Create or modify the :file:`dkms.conf` file inside of the extracted source
|
||||
code directory.
|
||||
|
||||
.. code-block:: bash
|
||||
.. code-block:: ShellSession
|
||||
|
||||
$EDITOR dkms.conf
|
||||
$ EDITOR dkms.conf
|
||||
|
||||
MAKE="make -C src/ KERNELDIR=/lib/modules/${kernelver}/build"
|
||||
CLEAN="make -C src/ clean"
|
||||
|
||||
Reference in New Issue
Block a user