diff --git a/index.html b/index.html index e852dd7..b852d1d 100644 --- a/index.html +++ b/index.html @@ -1446,6 +1446,7 @@ function addStepNumberText( ol, depth = 0, + indent = '', special = [...ol.classList].some(c => c.startsWith('nested-')), ) { let counter = !special && counterByDepth[depth]; @@ -1469,8 +1470,11 @@ let i = (Number(ol.getAttribute('start')) || 1) - 1; for (const li of ol.children) { const marker = document.createElement('span'); - marker.textContent = `${i < cache.length ? cache[i] : getTextForIndex(i)}. `; + const markerText = i < cache.length ? cache[i] : getTextForIndex(i); + const extraIndent = ' '.repeat(markerText.length + 2); + marker.textContent = `${indent}${markerText}. `; marker.setAttribute('aria-hidden', 'true'); + marker.setAttribute('class', 'list-marker'); const attributesContainer = li.querySelector('.attributes-tag'); if (attributesContainer == null) { li.prepend(marker); @@ -1478,7 +1482,7 @@ attributesContainer.insertAdjacentElement('afterend', marker); } for (const sublist of li.querySelectorAll(':scope > ol')) { - addStepNumberText(sublist, depth + 1, special); + addStepNumberText(sublist, depth + 1, indent + extraIndent, special); } i++; } @@ -1490,6 +1494,52 @@ }); }); +// Omit indendation when copying a single algorithm step. +document.addEventListener('copy', evt => { + // Construct a DOM from the selection. + const doc = document.implementation.createHTMLDocument(''); + const domRoot = doc.createElement('div'); + const html = evt.clipboardData.getData('text/html'); + if (html) { + domRoot.innerHTML = html; + } else { + const selection = getSelection(); + const singleRange = selection?.rangeCount === 1 && selection.getRangeAt(0); + const container = singleRange?.commonAncestorContainer; + if (!container?.querySelector?.('.list-marker')) { + return; + } + domRoot.append(singleRange.cloneContents()); + } + + // Preserve the indentation if there is no hidden list marker, or if selection + // of more than one step is indicated by either multiple such markers or by + // visible text before the first one. + const listMarkers = domRoot.querySelectorAll('.list-marker'); + if (listMarkers.length !== 1) { + return; + } + const treeWalker = document.createTreeWalker(domRoot, undefined, { + acceptNode(node) { + return node.nodeType === Node.TEXT_NODE || node === listMarkers[0] + ? NodeFilter.FILTER_ACCEPT + : NodeFilter.FILTER_SKIP; + }, + }); + while (treeWalker.nextNode()) { + const node = treeWalker.currentNode; + if (node.nodeType === Node.ELEMENT_NODE) break; + if (/\S/u.test(node.data)) return; + } + + // Strip leading indentation from the plain text representation. + evt.clipboardData.setData('text/plain', domRoot.textContent.trimStart()); + if (!html) { + evt.clipboardData.setData('text/html', domRoot.innerHTML); + } + evt.preventDefault(); +}); + 'use strict'; // Update superscripts to not suffer misinterpretation when copied and pasted as plain text. @@ -1691,6 +1741,7 @@ span[aria-hidden='true'] { font-size: 0; + white-space: pre; } a { @@ -1788,6 +1839,10 @@ font: inherit; color: inherit; } +/* suppress line break opportunities between `.` and `[[FieldName]]` */ +var.field::before { + content: '\2060' +} var.referenced { color: inherit; @@ -3151,7 +3206,91 @@ } } -
?
u
/
p
1-9