|  | function escapeRegExp(string) { | 
|  | return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Removes excluded text from a Node. | 
|  | * | 
|  | * @param {Node} target Node to filter. | 
|  | * @param {string} exclude CSS selector of nodes to exclude. | 
|  | * @returns {DOMString} Text from `target` with text removed. | 
|  | */ | 
|  | export function filterText(target, exclude) { | 
|  | const clone = target.cloneNode(true);  // clone as to not modify the live DOM | 
|  | if (exclude) { | 
|  | // remove excluded nodes | 
|  | clone.querySelectorAll(exclude).forEach(node => node.remove()); | 
|  | } | 
|  | return clone.innerText; | 
|  | } | 
|  |  | 
|  | // 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; | 
|  |  | 
|  | // Do we check for line continuation characters and "HERE-documents"? | 
|  | var useLineCont = !!lineContinuationChar | 
|  | var useHereDoc = !!hereDocDelim | 
|  |  | 
|  | // create regexp to capture prompt and remaining line | 
|  | if (isRegexp) { | 
|  | regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') | 
|  | } else { | 
|  | regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') | 
|  | } | 
|  |  | 
|  | const outputLines = []; | 
|  | var promptFound = false; | 
|  | var gotLineCont = false; | 
|  | var gotHereDoc = false; | 
|  | const lineGotPrompt = []; | 
|  | for (const line of textContent.split('\n')) { | 
|  | match = line.match(regexp) | 
|  | if (match || gotLineCont || gotHereDoc) { | 
|  | promptFound = regexp.test(line) | 
|  | lineGotPrompt.push(promptFound) | 
|  | if (removePrompts && promptFound) { | 
|  | outputLines.push(match[2]) | 
|  | } else { | 
|  | outputLines.push(line) | 
|  | } | 
|  | gotLineCont = line.endsWith(lineContinuationChar) & useLineCont | 
|  | if (line.includes(hereDocDelim) & useHereDoc) | 
|  | gotHereDoc = !gotHereDoc | 
|  | } else if (!onlyCopyPromptLines) { | 
|  | outputLines.push(line) | 
|  | } else if (copyEmptyLines && line.trim() === '') { | 
|  | outputLines.push(line) | 
|  | } | 
|  | } | 
|  |  | 
|  | // If no lines with the prompt were found then just use original lines | 
|  | if (lineGotPrompt.some(v => v === true)) { | 
|  | textContent = outputLines.join('\n'); | 
|  | } | 
|  |  | 
|  | // Remove a trailing newline to avoid auto-running when pasting | 
|  | if (textContent.endsWith("\n")) { | 
|  | textContent = textContent.slice(0, -1) | 
|  | } | 
|  | return textContent | 
|  | } |