diff --git a/src/element.ts b/src/element.ts index 2ccb1e1b..5f8c3319 100644 --- a/src/element.ts +++ b/src/element.ts @@ -114,6 +114,25 @@ export function handleElement(element: Element, context: Readonly { // SVGs embedded through are never interactive. keepLinks: false, captureArea: svgRoot.viewBox.baseVal, + avoidTextSelection: false }, }) diff --git a/src/text.ts b/src/text.ts index 29bbe820..a8f81334 100644 --- a/src/text.ts +++ b/src/text.ts @@ -55,12 +55,18 @@ export function handleTextNode(textNode: Text, context: TraversalContext): void try { selection.removeAllRanges() selection.addRange(lineRange) - textSpan.textContent = selection - .toString() - // SVG does not support tabs in text. Tabs get rendered as one space character. Convert the - // tabs to spaces according to tab-size instead. - // Ideally we would keep the tab and create offset tspans. - .replace(/\t/g, ' '.repeat(tabSize)) + if (context.options.avoidTextSelection) { + textSpan.textContent = textNode.textContent + ? textNode.textContent.slice(lineRange.startOffset, lineRange.endOffset) + : textNode.textContent + } else { + textSpan.textContent = selection + .toString() + // SVG does not support tabs in text. Tabs get rendered as one space character. Convert the + // tabs to spaces according to tab-size instead. + // Ideally we would keep the tab and create offset tspans. + .replace(/\t/g, ' '.repeat(tabSize)) + } } finally { parentElement.style.userSelect = previousUserSelect selection.removeAllRanges() diff --git a/src/traversal.ts b/src/traversal.ts index c373fbd0..97f08c8c 100644 --- a/src/traversal.ts +++ b/src/traversal.ts @@ -16,6 +16,14 @@ export interface DomToSvgOptions { * @default true */ keepLinks?: boolean + + /** + * Whether to use text selection to fill tspans or use textContent (different whitespace handling). + * textContent works in mobile iOS browsers + * + * @default false + */ + avoidTextSelection?: boolean } export interface TraversalContext {