Я создаю приложение для iOS, которое позволяет пользователям выделять текст в веб -статьях. Эти основные моменты сохраняются на базе знаний пользователя.
в swiftui).
[*] Inject JavaScript, чтобы включить выделение текста.
[*] Сохраните диапазоны выделения для постоянного хранения. /> Отдельная работа и сохранение работы отлично.
Выделите работу по восстановлению простые сайты like:
// Function to restore highlights (called from Swift)
function restoreHighlights(highlights) {
console.log('Restoring', highlights.length, 'highlights');
highlights.forEach((highlight, index) => {
setTimeout(() => {
try {
console.log('Attempting to restore highlight:', highlight.text.substring(0, 50) + '...');
// Try to find the element by XPath first
let targetElement = null;
let textNode = null;
// Try direct XPath evaluation
try {
const result = document.evaluate(
highlight.xpath,
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
targetElement = result.singleNodeValue;
if (targetElement) {
console.log('Found element via XPath:', targetElement.tagName);
}
} catch (e) {
console.log('XPath evaluation failed:', e);
}
// If XPath didn't work, try a more general approach
if (!targetElement) {
console.log('XPath method failed, trying text search...');
// Search for text in the document
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
let node;
while ((node = walker.nextNode())) {
if (node.textContent.includes(highlight.text)) {
textNode = node;
targetElement = node.parentElement;
console.log('Found text via search in element:', targetElement.tagName);
break;
}
}
}
// If we found the element via XPath
if (targetElement && !textNode) {
console.log('Searching for text within element...');
// Try to find the text within the element
const walker = document.createTreeWalker(
targetElement,
NodeFilter.SHOW_TEXT,
null,
false
);
let node;
while ((node = walker.nextNode())) {
if (node.textContent.includes(highlight.text)) {
textNode = node;
console.log('Found text within element');
break;
}
}
}
// If we found the text node, create the highlight
if (textNode) {
console.log('Found text node, creating highlight...');
// Find the exact position of the text
const textContent = textNode.textContent;
const startIndex = textContent.indexOf(highlight.text);
if (startIndex !== -1) {
try {
const range = document.createRange();
range.setStart(textNode, startIndex);
range.setEnd(textNode, startIndex + highlight.text.length);
// Create highlight span
const span = document.createElement('span');
span.className = 'user-highlight';
span.setAttribute('data-highlight-id', highlight.id);
range.surroundContents(span);
console.log('Successfully restored highlight:', highlight.text.substring(0, 30) + '...');
} catch (e) {
// If surroundContents fails, try a different approach
console.log('Could not surround contents, trying alternative method:', e);
// Create a new text node with the highlighted part
const beforeText = textContent.substring(0, startIndex);
const highlightedText = textContent.substring(startIndex, startIndex + highlight.text.length);
const afterText = textContent.substring(startIndex + highlight.text.length);
if (beforeText.length > 0) {
textNode.parentNode.insertBefore(document.createTextNode(beforeText), textNode);
}
const span = document.createElement('span');
span.className = 'user-highlight';
span.setAttribute('data-highlight-id', highlight.id);
span.textContent = highlightedText;
textNode.parentNode.insertBefore(span, textNode);
if (afterText.length > 0) {
textNode.parentNode.insertBefore(document.createTextNode(afterText), textNode);
}
// Remove the original text node
textNode.parentNode.removeChild(textNode);
console.log('Successfully restored highlight with alternative method:', highlight.text.substring(0, 30) + '...');
}
} else {
console.log('Could not find exact text match for highlight:', highlight.text.substring(0, 30) + '...');
}
} else {
console.log('Could not find text node for highlight:', highlight.text.substring(0, 30) + '...');
}
} catch (e) {
console.error('Error restoring highlight:', e);
}
}, index * 100); // Increased delay to 100ms for better reliability
});
}
Зачем, зачем это восстановление, последовательно работает на статических/простых сайтах, но не сбои на динамических/сложных сайтах?
Я создаю приложение для iOS, которое позволяет пользователям выделять текст в веб -статьях. Эти основные моменты сохраняются на базе знаний пользователя.[code]UIViewRepresentable[/code] в swiftui). [*] Inject JavaScript, чтобы включить выделение текста. [*] Сохраните диапазоны выделения для постоянного хранения. /> Отдельная работа и сохранение работы отлично. Выделите работу по восстановлению [b] простые сайты [/b] like: [list] https://www.swift.org/blog/redesigned-swift-org-is-now-live/>
>
al>
сложных/динамических сайтах like:
/>[*]https://www.iana.org/help/example-domains [/list] Я создал минимальный публичный репо, который воспроизводит проблему: 👉 [b] github demo [/b] ниже. Восстановление сохраненных основных моментов: < /p> [code]// Function to restore highlights (called from Swift) function restoreHighlights(highlights) { console.log('Restoring', highlights.length, 'highlights');
// Try to find the element by XPath first let targetElement = null; let textNode = null;
// Try direct XPath evaluation try { const result = document.evaluate( highlight.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ); targetElement = result.singleNodeValue; if (targetElement) { console.log('Found element via XPath:', targetElement.tagName); } } catch (e) { console.log('XPath evaluation failed:', e); }
// If XPath didn't work, try a more general approach if (!targetElement) { console.log('XPath method failed, trying text search...'); // Search for text in the document const walker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, null, false );
let node; while ((node = walker.nextNode())) { if (node.textContent.includes(highlight.text)) { textNode = node; targetElement = node.parentElement; console.log('Found text via search in element:', targetElement.tagName); break; } } }
// If we found the element via XPath if (targetElement && !textNode) { console.log('Searching for text within element...'); // Try to find the text within the element const walker = document.createTreeWalker( targetElement, NodeFilter.SHOW_TEXT, null, false );
let node; while ((node = walker.nextNode())) { if (node.textContent.includes(highlight.text)) { textNode = node; console.log('Found text within element'); break; } } }
// If we found the text node, create the highlight if (textNode) { console.log('Found text node, creating highlight...'); // Find the exact position of the text const textContent = textNode.textContent; const startIndex = textContent.indexOf(highlight.text);
if (startIndex !== -1) { try { const range = document.createRange(); range.setStart(textNode, startIndex); range.setEnd(textNode, startIndex + highlight.text.length);
range.surroundContents(span); console.log('Successfully restored highlight:', highlight.text.substring(0, 30) + '...'); } catch (e) { // If surroundContents fails, try a different approach console.log('Could not surround contents, trying alternative method:', e);
// Create a new text node with the highlighted part const beforeText = textContent.substring(0, startIndex); const highlightedText = textContent.substring(startIndex, startIndex + highlight.text.length); const afterText = textContent.substring(startIndex + highlight.text.length);
if (beforeText.length > 0) { textNode.parentNode.insertBefore(document.createTextNode(beforeText), textNode); }
if (afterText.length > 0) { textNode.parentNode.insertBefore(document.createTextNode(afterText), textNode); }
// Remove the original text node textNode.parentNode.removeChild(textNode);
console.log('Successfully restored highlight with alternative method:', highlight.text.substring(0, 30) + '...'); } } else { console.log('Could not find exact text match for highlight:', highlight.text.substring(0, 30) + '...'); } } else { console.log('Could not find text node for highlight:', highlight.text.substring(0, 30) + '...'); } } catch (e) { console.error('Error restoring highlight:', e); } }, index * 100); // Increased delay to 100ms for better reliability }); } [/code] Зачем, зачем это восстановление, последовательно работает на статических/простых сайтах, но не сбои на динамических/сложных сайтах?