|
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