-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exclude unselectable text from being copied #138
Changes from 3 commits
3307827
ce16954
42355fc
e35b070
e683c26
03e46d4
ce20709
acc63cd
e78f41e
0941ef2
d1e4962
5e37a68
95be984
665fe0a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -372,6 +372,22 @@ In this case, all elements that match ``your.selector`` will have a copy button | |
added to them. | ||
|
||
|
||
Exclude unselectable text from copied text | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
By default, ``sphinx-copybutton`` will exclude text that is not selectable by the user. Unselectable text is determined with the CSS style | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you provide an example of what un-selectable text generally is, so that users understand when they'll likely use this? |
||
|
||
.. code-block:: css | ||
|
||
user-select: none | ||
|
||
To change this behavior, use the following configuration in ``conf.py``: | ||
|
||
.. code-block:: python | ||
|
||
copybutton_exclude_unselectable = False | ||
|
||
choldgraf marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Development | ||
=========== | ||
|
||
|
@@ -441,7 +457,7 @@ Then run the docs build: | |
|
||
.. code-block:: console | ||
|
||
$ cd doc | ||
$ cd docs | ||
$ make html | ||
|
||
.. toctree:: | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,5 +18,8 @@ | |
"require": [ | ||
"esm" | ||
] | ||
}, | ||
"dependencies": { | ||
"ci": "^2.1.1" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -118,7 +118,11 @@ const addCopyButtonToCodeCells = () => { | |
|
||
var copyTargetText = (trigger) => { | ||
var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); | ||
return formatCopyText(target.innerText, {{ "{!r}".format(copybutton_prompt_text) }}, {{ copybutton_prompt_is_regexp | lower }}, {{ copybutton_only_copy_prompt_lines | lower }}, {{ copybutton_remove_prompts | lower }}, {{ copybutton_copy_empty_lines | lower }}, {{ "{!r}".format(copybutton_line_continuation_character) }}, {{ "{!r}".format(copybutton_here_doc_delimiter) }}) | ||
let text = ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you provide a comment about what this is doing? This uses some JS syntax that I haven't seen before (with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
{{ copybutton_exclude_unselectable | lower }} ? | ||
filterUnselectableText( target ) : target.innerText | ||
); | ||
return formatCopyText(text, {{ "{!r}".format(copybutton_prompt_text) }}, {{ copybutton_prompt_is_regexp | lower }}, {{ copybutton_only_copy_prompt_lines | lower }}, {{ copybutton_remove_prompts | lower }}, {{ copybutton_copy_empty_lines | lower }}, {{ "{!r}".format(copybutton_line_continuation_character) }}, {{ "{!r}".format(copybutton_here_doc_delimiter) }}) | ||
} | ||
|
||
// Initialize with a callback so we can modify the text before copy | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,10 +2,54 @@ function escapeRegExp(string) { | |
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string | ||
} | ||
|
||
function getUnselectable(target) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide a high-level docstring that describes what this function does |
||
let unselectable = []; | ||
|
||
// get all unselectable elements of children | ||
for (let child of target.children) { | ||
unselectable = unselectable.concat(getUnselectable(child)); | ||
} | ||
|
||
// add self to unselectable if needed | ||
if (getComputedStyle(target)["userSelect"] === "none") { | ||
unselectable.push( target); | ||
} | ||
|
||
return unselectable; | ||
} | ||
|
||
function getFilteredText(target, exclude) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here - please provide a docstring |
||
let text = ''; | ||
for (let child of target.childNodes) { | ||
if (exclude.indexOf(child) > -1) { | ||
// child should be filtered out | ||
continue; | ||
} | ||
|
||
if (child.nodeType === Node.TEXT_NODE) { | ||
// child is a text node, add its contents | ||
text += child.textContent | ||
} | ||
else { | ||
// recurse on non-text nodes | ||
text += getFilteredText(child, exclude); | ||
} | ||
} | ||
|
||
return text; | ||
} | ||
|
||
export function filterUnselectableText(target) { | ||
// get unselectable elements | ||
const unselectable = getUnselectable(target); | ||
|
||
// get text from selectable elements | ||
return getFilteredText(target, unselectable); | ||
} | ||
|
||
// 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 | ||
export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { | ||
|
||
var regexp; | ||
var match; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.