Skip to content

Commit

Permalink
ENH: Directly add SVG instead of linking via IMG (#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
choldgraf authored Feb 6, 2022
1 parent cb68662 commit 915aa4c
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 38 deletions.
11 changes: 10 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@
#
# html_sidebars = {}

myst_enable_extensions = ["colon_fence"]

# CopyButton configuration
copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: "
copybutton_prompt_is_regexp = True
Expand All @@ -108,7 +110,14 @@
# Switches for testing but shouldn't be activated in the live docs
# copybutton_only_copy_prompt_lines = False
# copybutton_remove_prompts = False
# copybutton_image_path = "clipboard.svg"
# copybutton_image_path = "_static/clipboard.svg" # DEPRECATED: remove after next release # noqa: E501
# copybutton_image_svg = """
# <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-clipboard" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round"> # noqa: E501
# <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
# <path d="M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2" /> # noqa: E501
# <rect x="9" y="3" width="6" height="4" rx="2" />
# </svg>
# """
# copybutton_selector = "div"


Expand Down
59 changes: 35 additions & 24 deletions docs/use.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,34 +235,35 @@ encountered in a line.
To use a different image for your copy buttons, do the following:
1. Place the image in the `_static/` folder of your site.
2. Set the `copybutton_image_path` variable in your `conf.py` to be the
path to your image file, **relative to** `_static/`.
1. Find the `<svg>` code for the image that you'd like to use.
For example, find an SVG from [Font Awesome](https://fontawesome.com/), [Tabler](https://tablericons.com/), or [Octicons](https://primer.style/octicons/).
2. Set the `copybutton_image_svg` variable in your `conf.py` to the SVG that you'd like to use.
For example, if you wanted to use a **clipboard icon** instead of the default copy button icon, do the following:
1. Copy the `Clipboard Icon SVG` from [the Tabular icons pack](https://tablericons.com/).
Here is the SVG for reference:
```svg
```
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-clipboard" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2" />
<rect x="9" y="3" width="6" height="4" rx="2" />
</svg>
```
2. Create a file at `_static/clipboard.svg` from your documentation root.
Paste in the SVG above into that file.
3. Ensure that your `_static` folder is added to your `html_static_paths` configuration in Sphinx.
4. Configure `sphinx_copybutton` to use this icon instead, via the following configuration:
2. Configure `sphinx_copybutton` to use this icon instead, via the following configuration:
```python
# Note that we do not include `_static`
# because the path should be *relative* to the static folder.
copybutton_image_path = "clipboard.svg"
copybutton_image_svg = """
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-clipboard" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2" />
<rect x="9" y="3" width="6" height="4" rx="2" />
</svg>
"""
```
When you re-build your documentation, you should see this new icon in your copy buttons.
Expand All @@ -288,27 +289,37 @@ added to them.
## Modify the copy button's CSS
You can style the CSS of the copy button however you'd like by writing your own CSS with your Sphinx build.
To do so, add a CSS rule that uses the `.copybtn` selector and the CSS that you'd like to apply.
For example, to make the copy button visible by default (not just when a code cell is hovered), do the following:
To do so, first create a custom CSS file and add it to your Sphinx build:
1. Create a `custom.css` file in the `_static/` folder of your documentation.
2. Add the following rule to it:
```css
button.copybtn {
opacity: 1;
}
```
3. Add the CSS file to Sphinx by ensuring that the following configuration exists in your `conf.py` file (see [the Sphinx documentation for more details](https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_css_files)):
2. Add the CSS file to Sphinx by ensuring that the following configuration exists in your `conf.py` file (see [the Sphinx documentation for more details](https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_css_files)):
```python
html_static_path = ["_static"]
html_css_files = ["custom.css"]
```
Next you can add CSS rules that use the `.copybtn` selector to modify the behavior of the button.
:::{admonition} example: button visibility
:class: tip
To make the copy button visible by default (not just when a code cell is hovered):
```css
button.copybtn {
opacity: 1;
}
```
:::
:::{admonition} example: style the color of the button
```css
button.copybtn {
color: red;
}
```
:::
See the [Sphinx documentation on custom CSS for more information](https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_static_path).
[regex101]: https://regex101.com
19 changes: 17 additions & 2 deletions sphinx_copybutton/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,19 @@ def add_to_context(app, config):
config.html_context.update(
{"copybutton_here_doc_delimiter": config.copybutton_here_doc_delimiter}
)
config.html_context.update({"copybutton_image_path": config.copybutton_image_path})

# Old image path deprecation
# REMOVE after next release
if config.copybutton_image_path:
path = Path(app.srcdir) / config.copybutton_image_path
logger.warning("copybutton_image_path is deprecated, use copybutton_image_svg")
if not path.exists():
raise ValueError("copybutton_img_path does not exist")
if not path.suffix == ".svg":
raise ValueError("copybutton_img_path must be an SVG")
config.copybutton_image_svg = path.read_text()

config.html_context.update({"copybutton_image_svg": config.copybutton_image_svg})
config.html_context.update({"copybutton_selector": config.copybutton_selector})
config.html_context.update(
{
Expand All @@ -66,9 +78,12 @@ def setup(app):
app.add_config_value("copybutton_copy_empty_lines", True, "html")
app.add_config_value("copybutton_line_continuation_character", "", "html")
app.add_config_value("copybutton_here_doc_delimiter", "", "html")
app.add_config_value("copybutton_image_path", "copy-button.svg", "html")
app.add_config_value("copybutton_image_svg", "", "html")
app.add_config_value("copybutton_selector", "div.highlight pre", "html")

# DEPRECATE THIS AFTER THE NEXT RELEASE
app.add_config_value("copybutton_image_path", "", "html")

# Add configuration value to the template
app.connect("config-inited", add_to_context)

Expand Down
24 changes: 18 additions & 6 deletions sphinx_copybutton/_static/copybutton.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ button.copybtn {
position: absolute;
display: flex;
top: .3em;
right: .5em;
right: .3em;
width: 1.7em;
height: 1.7em;
opacity: 0;
Expand All @@ -13,17 +13,22 @@ button.copybtn {
border: none;
outline: none;
border-radius: 0.4em;
border: #e1e1e1 1px solid;
background-color: rgb(245, 245, 245);
/* The colors that GitHub uses */
border: #1b1f2426 1px solid;
background-color: #f6f8fa;
color: #57606a;
}

button.copybtn.success {
border-color: #22863a;
color: #22863a;
}

button.copybtn img {
width: 100%;
padding: .2em;
button.copybtn svg {
stroke: currentColor;
width: 1.5em;
height: 1.5em;
padding: 0.1em;
}

div.highlight {
Expand Down Expand Up @@ -79,3 +84,10 @@ div.highlight {
transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1);
transition-delay: .5s;
}

/* By default the copy button shouldn't show up when printing a page */
@media print {
button.copybtn {
display: none;
}
}
27 changes: 22 additions & 5 deletions sphinx_copybutton/_static/copybutton.js_t
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,25 @@ if (doc_url_root == '#') {
doc_url_root = '';
}

const path_static = `${doc_url_root}_static/`;
/**
* SVG files for our copy buttons
*/
let iconCheck = `<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#22863a" fill="none" stroke-linecap="round" stroke-linejoin="round">
<title>${messages[locale]['copy_success']}</title>
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M5 12l5 5l10 -10" />
</svg>`

// If the user specified their own SVG use that, otherwise use the default
let iconCopy = `{{ copybutton_image_svg }}`;
if (!iconCopy) {
iconCopy = `<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-copy" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
<title>${messages[locale]['copy_to_clipboard']}</title>
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<rect x="8" y="8" width="12" height="12" rx="2" />
<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" />
</svg>`
}

/**
* Set up copy/paste for code blocks
Expand Down Expand Up @@ -94,9 +112,8 @@ const temporarilyChangeTooltip = (el, oldText, newText) => {

// Changes the copy button icon for two seconds, then changes it back
const temporarilyChangeIcon = (el) => {
img = el.querySelector("img");
img.setAttribute('src', `${path_static}check-solid.svg`)
setTimeout(() => img.setAttribute('src', `${path_static}{{ copybutton_image_path }}`), 2000)
el.innerHTML = iconCheck;
setTimeout(() => {el.innerHTML = iconCopy}, 2000)
}

const addCopyButtonToCodeCells = () => {
Expand All @@ -115,7 +132,7 @@ const addCopyButtonToCodeCells = () => {

const clipboardButton = id =>
`<button class="copybtn o-tooltip--left" data-tooltip="${messages[locale]['copy']}" data-clipboard-target="#${id}">
<img src="${path_static}{{ copybutton_image_path }}" alt="${messages[locale]['copy_to_clipboard']}">
${iconCopy}
</button>`
codeCell.insertAdjacentHTML('afterend', clipboardButton(id))
})
Expand Down

0 comments on commit 915aa4c

Please sign in to comment.