Skip to content

Commit 915aa4c

Browse files
authored
ENH: Directly add SVG instead of linking via IMG (#161)
1 parent cb68662 commit 915aa4c

File tree

5 files changed

+102
-38
lines changed

5 files changed

+102
-38
lines changed

docs/conf.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@
100100
#
101101
# html_sidebars = {}
102102

103+
myst_enable_extensions = ["colon_fence"]
104+
103105
# CopyButton configuration
104106
copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: "
105107
copybutton_prompt_is_regexp = True
@@ -108,7 +110,14 @@
108110
# Switches for testing but shouldn't be activated in the live docs
109111
# copybutton_only_copy_prompt_lines = False
110112
# copybutton_remove_prompts = False
111-
# copybutton_image_path = "clipboard.svg"
113+
# copybutton_image_path = "_static/clipboard.svg" # DEPRECATED: remove after next release # noqa: E501
114+
# copybutton_image_svg = """
115+
# <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
116+
# <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
117+
# <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
118+
# <rect x="9" y="3" width="6" height="4" rx="2" />
119+
# </svg>
120+
# """
112121
# copybutton_selector = "div"
113122

114123

docs/use.md

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -235,34 +235,35 @@ encountered in a line.
235235
236236
To use a different image for your copy buttons, do the following:
237237
238-
1. Place the image in the `_static/` folder of your site.
239-
2. Set the `copybutton_image_path` variable in your `conf.py` to be the
240-
path to your image file, **relative to** `_static/`.
238+
1. Find the `<svg>` code for the image that you'd like to use.
239+
For example, find an SVG from [Font Awesome](https://fontawesome.com/), [Tabler](https://tablericons.com/), or [Octicons](https://primer.style/octicons/).
240+
2. Set the `copybutton_image_svg` variable in your `conf.py` to the SVG that you'd like to use.
241241
242242
For example, if you wanted to use a **clipboard icon** instead of the default copy button icon, do the following:
243243
244244
1. Copy the `Clipboard Icon SVG` from [the Tabular icons pack](https://tablericons.com/).
245245
Here is the SVG for reference:
246246
247-
```svg
247+
```
248248
<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">
249249
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
250250
<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" />
251251
<rect x="9" y="3" width="6" height="4" rx="2" />
252252
</svg>
253253
```
254254
255-
2. Create a file at `_static/clipboard.svg` from your documentation root.
256-
Paste in the SVG above into that file.
257-
258-
3. Ensure that your `_static` folder is added to your `html_static_paths` configuration in Sphinx.
259-
260-
4. Configure `sphinx_copybutton` to use this icon instead, via the following configuration:
255+
2. Configure `sphinx_copybutton` to use this icon instead, via the following configuration:
261256
262257
```python
263258
# Note that we do not include `_static`
264259
# because the path should be *relative* to the static folder.
265-
copybutton_image_path = "clipboard.svg"
260+
copybutton_image_svg = """
261+
<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">
262+
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
263+
<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" />
264+
<rect x="9" y="3" width="6" height="4" rx="2" />
265+
</svg>
266+
"""
266267
```
267268
268269
When you re-build your documentation, you should see this new icon in your copy buttons.
@@ -288,27 +289,37 @@ added to them.
288289
## Modify the copy button's CSS
289290
290291
You can style the CSS of the copy button however you'd like by writing your own CSS with your Sphinx build.
291-
To do so, add a CSS rule that uses the `.copybtn` selector and the CSS that you'd like to apply.
292-
293-
For example, to make the copy button visible by default (not just when a code cell is hovered), do the following:
292+
To do so, first create a custom CSS file and add it to your Sphinx build:
294293
295294
1. Create a `custom.css` file in the `_static/` folder of your documentation.
296-
297-
2. Add the following rule to it:
298-
299-
```css
300-
button.copybtn {
301-
opacity: 1;
302-
}
303-
```
304-
305-
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)):
295+
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)):
306296
307297
```python
308298
html_static_path = ["_static"]
309299
html_css_files = ["custom.css"]
310300
```
311301
302+
Next you can add CSS rules that use the `.copybtn` selector to modify the behavior of the button.
303+
304+
:::{admonition} example: button visibility
305+
:class: tip
306+
To make the copy button visible by default (not just when a code cell is hovered):
307+
308+
```css
309+
button.copybtn {
310+
opacity: 1;
311+
}
312+
```
313+
:::
314+
315+
:::{admonition} example: style the color of the button
316+
```css
317+
button.copybtn {
318+
color: red;
319+
}
320+
```
321+
:::
322+
312323
See the [Sphinx documentation on custom CSS for more information](https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_static_path).
313324
314325
[regex101]: https://regex101.com

sphinx_copybutton/__init__.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,19 @@ def add_to_context(app, config):
4040
config.html_context.update(
4141
{"copybutton_here_doc_delimiter": config.copybutton_here_doc_delimiter}
4242
)
43-
config.html_context.update({"copybutton_image_path": config.copybutton_image_path})
43+
44+
# Old image path deprecation
45+
# REMOVE after next release
46+
if config.copybutton_image_path:
47+
path = Path(app.srcdir) / config.copybutton_image_path
48+
logger.warning("copybutton_image_path is deprecated, use copybutton_image_svg")
49+
if not path.exists():
50+
raise ValueError("copybutton_img_path does not exist")
51+
if not path.suffix == ".svg":
52+
raise ValueError("copybutton_img_path must be an SVG")
53+
config.copybutton_image_svg = path.read_text()
54+
55+
config.html_context.update({"copybutton_image_svg": config.copybutton_image_svg})
4456
config.html_context.update({"copybutton_selector": config.copybutton_selector})
4557
config.html_context.update(
4658
{
@@ -66,9 +78,12 @@ def setup(app):
6678
app.add_config_value("copybutton_copy_empty_lines", True, "html")
6779
app.add_config_value("copybutton_line_continuation_character", "", "html")
6880
app.add_config_value("copybutton_here_doc_delimiter", "", "html")
69-
app.add_config_value("copybutton_image_path", "copy-button.svg", "html")
81+
app.add_config_value("copybutton_image_svg", "", "html")
7082
app.add_config_value("copybutton_selector", "div.highlight pre", "html")
7183

84+
# DEPRECATE THIS AFTER THE NEXT RELEASE
85+
app.add_config_value("copybutton_image_path", "", "html")
86+
7287
# Add configuration value to the template
7388
app.connect("config-inited", add_to_context)
7489

sphinx_copybutton/_static/copybutton.css

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ button.copybtn {
33
position: absolute;
44
display: flex;
55
top: .3em;
6-
right: .5em;
6+
right: .3em;
77
width: 1.7em;
88
height: 1.7em;
99
opacity: 0;
@@ -13,17 +13,22 @@ button.copybtn {
1313
border: none;
1414
outline: none;
1515
border-radius: 0.4em;
16-
border: #e1e1e1 1px solid;
17-
background-color: rgb(245, 245, 245);
16+
/* The colors that GitHub uses */
17+
border: #1b1f2426 1px solid;
18+
background-color: #f6f8fa;
19+
color: #57606a;
1820
}
1921

2022
button.copybtn.success {
2123
border-color: #22863a;
24+
color: #22863a;
2225
}
2326

24-
button.copybtn img {
25-
width: 100%;
26-
padding: .2em;
27+
button.copybtn svg {
28+
stroke: currentColor;
29+
width: 1.5em;
30+
height: 1.5em;
31+
padding: 0.1em;
2732
}
2833

2934
div.highlight {
@@ -79,3 +84,10 @@ div.highlight {
7984
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);
8085
transition-delay: .5s;
8186
}
87+
88+
/* By default the copy button shouldn't show up when printing a page */
89+
@media print {
90+
button.copybtn {
91+
display: none;
92+
}
93+
}

sphinx_copybutton/_static/copybutton.js_t

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,25 @@ if (doc_url_root == '#') {
5555
doc_url_root = '';
5656
}
5757

58-
const path_static = `${doc_url_root}_static/`;
58+
/**
59+
* SVG files for our copy buttons
60+
*/
61+
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">
62+
<title>${messages[locale]['copy_success']}</title>
63+
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
64+
<path d="M5 12l5 5l10 -10" />
65+
</svg>`
66+
67+
// If the user specified their own SVG use that, otherwise use the default
68+
let iconCopy = `{{ copybutton_image_svg }}`;
69+
if (!iconCopy) {
70+
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">
71+
<title>${messages[locale]['copy_to_clipboard']}</title>
72+
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
73+
<rect x="8" y="8" width="12" height="12" rx="2" />
74+
<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" />
75+
</svg>`
76+
}
5977

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

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

102119
const addCopyButtonToCodeCells = () => {
@@ -115,7 +132,7 @@ const addCopyButtonToCodeCells = () => {
115132

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

0 commit comments

Comments
 (0)