|
1 | 1 | import { inBrowser } from 'vitepress'
|
2 | 2 |
|
| 3 | +const shellRE = /language-(shellscript|shell|bash|sh|zsh)/ |
| 4 | +const ignoredNodes = ['.vp-copy-ignore', '.diff.remove'].join(', ') |
| 5 | + |
3 | 6 | export function useCopyCode() {
|
4 | 7 | if (inBrowser) {
|
5 | 8 | const timeoutIdMap: WeakMap<HTMLElement, NodeJS.Timeout> = new WeakMap()
|
6 | 9 | window.addEventListener('click', (e) => {
|
7 | 10 | const el = e.target as HTMLElement
|
8 | 11 | if (el.matches('div[class*="language-"] > button.copy')) {
|
9 | 12 | const parent = el.parentElement
|
10 |
| - const sibling = el.nextElementSibling?.nextElementSibling |
| 13 | + const sibling = el.nextElementSibling?.nextElementSibling // <pre> tag |
11 | 14 | if (!parent || !sibling) {
|
12 | 15 | return
|
13 | 16 | }
|
14 | 17 |
|
15 |
| - const isShell = /language-(shellscript|shell|bash|sh|zsh)/.test( |
16 |
| - parent.className |
17 |
| - ) |
18 |
| - |
19 |
| - const ignoredNodes = ['.vp-copy-ignore', '.diff.remove'] |
| 18 | + const isShell = shellRE.test(parent.className) |
20 | 19 |
|
21 | 20 | // Clone the node and remove the ignored nodes
|
22 | 21 | const clone = sibling.cloneNode(true) as HTMLElement
|
23 |
| - clone |
24 |
| - .querySelectorAll(ignoredNodes.join(',')) |
25 |
| - .forEach((node) => node.remove()) |
| 22 | + clone.querySelectorAll(ignoredNodes).forEach((node) => node.remove()) |
| 23 | + // remove extra newlines left after removing ignored nodes (affecting textContent because it is inside `<pre>`) |
| 24 | + // doesn't affect the newlines already in the code because they are rendered as `\n<span class="line"></span>` |
| 25 | + clone.innerHTML = clone.innerHTML.replace(/\n+/g, '\n') |
26 | 26 |
|
27 | 27 | let text = clone.textContent || ''
|
28 | 28 |
|
|
0 commit comments