Improve LightRAG knowledge search locator alignment
This commit is contained in:
@@ -994,6 +994,10 @@ pub struct OfficePreviewQuery {
|
||||
source_map_path: Option<String>,
|
||||
#[serde(default, alias = "blockId")]
|
||||
block_id: Option<String>,
|
||||
#[serde(default, alias = "evidenceText")]
|
||||
evidence_text: Option<String>,
|
||||
#[serde(default, alias = "searchQuery")]
|
||||
search_query: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Response {
|
||||
@@ -1028,6 +1032,8 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
let target_bbox = query.bbox.unwrap_or_default();
|
||||
let target_source_map_path = query.source_map_path.unwrap_or_default();
|
||||
let target_block_id = query.block_id.unwrap_or_default();
|
||||
let target_evidence_text = query.evidence_text.unwrap_or_default();
|
||||
let target_search_query = query.search_query.unwrap_or_default();
|
||||
let html = format!(
|
||||
r#"<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
@@ -1074,7 +1080,7 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body data-file-url="{file_url}" data-file-name="{file_name}" data-file-type="{file_type}" data-page-width-content-type="{page_width_content_type}" data-workspace-id="{workspace_id}" data-mnote-source-kind="{source_kind}" data-mnote-root-uri="{root_uri}" data-document-id="{document_id}" data-evidence-page="{target_page}" data-evidence-bbox="{target_bbox}" data-evidence-source-map-path="{target_source_map_path}" data-evidence-block-id="{target_block_id}">
|
||||
<body data-file-url="{file_url}" data-file-name="{file_name}" data-file-type="{file_type}" data-page-width-content-type="{page_width_content_type}" data-workspace-id="{workspace_id}" data-mnote-source-kind="{source_kind}" data-mnote-root-uri="{root_uri}" data-document-id="{document_id}" data-evidence-page="{target_page}" data-evidence-bbox="{target_bbox}" data-evidence-source-map-path="{target_source_map_path}" data-evidence-block-id="{target_block_id}" data-evidence-text="{target_evidence_text}" data-evidence-search-query="{target_search_query}">
|
||||
<main class="mnote-office-preview">
|
||||
<section class="mnote-office-viewer" id="mnote-office-viewer"></section>
|
||||
</main>
|
||||
@@ -1093,6 +1099,8 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
let evidenceBbox = body.dataset.evidenceBbox || '';
|
||||
let evidenceSourceMapPath = body.dataset.evidenceSourceMapPath || '';
|
||||
let evidenceBlockId = body.dataset.evidenceBlockId || '';
|
||||
let evidenceText = body.dataset.evidenceText || '';
|
||||
let evidenceSearchQuery = body.dataset.evidenceSearchQuery || '';
|
||||
let currentPptxBuffer = null;
|
||||
let pptxRenderToken = 0;
|
||||
let pptxResizeTimer = 0;
|
||||
@@ -1160,7 +1168,13 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
}}
|
||||
|
||||
function normalizeEvidenceText(value) {{
|
||||
return String(value || '').replace(/\s+/g, ' ').trim();
|
||||
return String(value || '')
|
||||
.replace(/<[^>]+>/g, ' ')
|
||||
.replace(/ | /gi, ' ')
|
||||
.replace(/[#*_`~>\[\](){{}}]+/g, ' ')
|
||||
.replace(/[\u200B-\u200D\uFEFF]/g, '')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
}}
|
||||
|
||||
function markEvidenceTarget(target) {{
|
||||
@@ -1266,6 +1280,7 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
if (!viewer) return false;
|
||||
const compactNeedle = normalizeEvidenceText(needle).replace(/\s+/g, '');
|
||||
if (!compactNeedle) return false;
|
||||
if (compactNeedle.length > 160) return false;
|
||||
const refs = [];
|
||||
let compactText = '';
|
||||
const walker = document.createTreeWalker(viewer, NodeFilter.SHOW_TEXT);
|
||||
@@ -1291,6 +1306,12 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
range.setEnd(endRef.node, endRef.offset + 1);
|
||||
const rect = range.getBoundingClientRect();
|
||||
if (!rect || rect.width <= 0 || rect.height <= 0) return false;
|
||||
const rects = Array.from(range.getClientRects()).filter(item => item && item.width > 0 && item.height > 0);
|
||||
if (rects.length > 6 || rect.height > Math.min(140, window.innerHeight * 0.35)) return false;
|
||||
const paragraphTarget = startRef.node?.parentElement?.closest('p, li, td, th, blockquote');
|
||||
if (paragraphTarget instanceof HTMLElement && normalizeEvidenceText(paragraphTarget.textContent).length < 4000) {{
|
||||
return markEvidenceTarget(paragraphTarget);
|
||||
}}
|
||||
let marker = viewer.querySelector('[data-mnote-office-evidence-marker="true"]');
|
||||
if (!(marker instanceof HTMLElement)) {{
|
||||
marker = document.createElement('div');
|
||||
@@ -1361,13 +1382,17 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
let node = walker.nextNode();
|
||||
while (node) {{
|
||||
if (normalizeEvidenceText(node.textContent).includes(needle)) {{
|
||||
const inlineTarget = wrapEvidenceTextNode(node, needle);
|
||||
if (inlineTarget) return markEvidenceTarget(inlineTarget);
|
||||
const target = node.parentElement && node.parentElement.closest('p, div, span, table, section') || node.parentElement;
|
||||
if (target instanceof HTMLElement) {{
|
||||
const rect = target.getBoundingClientRect();
|
||||
if (rect.height > window.innerHeight * 1.8 || normalizeEvidenceText(target.textContent).length > 4000) break;
|
||||
if (needle.length < 20) {{
|
||||
const paragraphTarget = node.parentElement && node.parentElement.closest('p, li, td, th, blockquote') || target;
|
||||
if (paragraphTarget instanceof HTMLElement) return markEvidenceTarget(paragraphTarget);
|
||||
}}
|
||||
}}
|
||||
const inlineTarget = wrapEvidenceTextNode(node, needle);
|
||||
if (inlineTarget) return markEvidenceTarget(inlineTarget);
|
||||
return markEvidenceTarget(target);
|
||||
}}
|
||||
node = walker.nextNode();
|
||||
@@ -1376,6 +1401,278 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
return false;
|
||||
}}
|
||||
|
||||
function evidenceTextCandidates(text) {{
|
||||
const raw = String(text || '');
|
||||
const cleaned = raw
|
||||
.replace(/<[^>]+>/g, ' ')
|
||||
.replace(/[#*_`~>\[\](){{}}]+/g, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
const specific = [];
|
||||
function pushSpecificEvidenceTerm(term) {{
|
||||
let value = normalizeEvidenceText(term);
|
||||
if (!value || value.length < 3) return;
|
||||
const anchor = value.search(/[一二三四五六七八九十甲乙丙丁戊己庚辛壬癸叔仲异正特苯][\u3400-\u9fffA-Za-z0-9()()\\-]{{0,18}}硅/);
|
||||
if (anchor > 0) value = value.slice(anchor);
|
||||
value = value.split(/[::。;;,,\n]/)[0];
|
||||
if (value.length < 3 || value.length > 48) return;
|
||||
specific.push(value);
|
||||
if (/[基酯醚]$/.test(value) && value.length > 3) specific.push(value.slice(0, -1));
|
||||
}}
|
||||
const withoutTags = raw.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
|
||||
const siliconTerms = cleaned.match(/[\u3400-\u9fffA-Za-z0-9()()\\-]{{0,24}}硅(?:基|酯|醚)?/g) || [];
|
||||
siliconTerms.forEach(pushSpecificEvidenceTerm);
|
||||
const cjkTerms = cleaned.match(/[\u3400-\u9fff][\u3400-\u9fffA-Za-z0-9()()\\-]{{2,48}}/g) || [];
|
||||
const fallbackTerms = [];
|
||||
cjkTerms.forEach(term => {{
|
||||
const value = normalizeEvidenceText(term);
|
||||
if (value.length < 3 || /^参考文献$/.test(value) || /^保护$/.test(value)) return;
|
||||
pushSpecificEvidenceTerm(value);
|
||||
const rawIndex = withoutTags.indexOf(value);
|
||||
if (rawIndex >= 0) {{
|
||||
const rawWindow = withoutTags.slice(rawIndex, rawIndex + value.length + 36).split(/[::。;;,,\n]/)[0];
|
||||
specific.push(normalizeEvidenceText(rawWindow));
|
||||
}}
|
||||
const cleanedIndex = cleaned.indexOf(value);
|
||||
if (cleanedIndex >= 0) {{
|
||||
const cleanedWindow = cleaned.slice(cleanedIndex, cleanedIndex + value.length + 36).split(/[::。;;,,\n]/)[0];
|
||||
specific.push(normalizeEvidenceText(cleanedWindow));
|
||||
}}
|
||||
if (value.endsWith('基') && value.length > 3) specific.push(value.slice(0, -1));
|
||||
fallbackTerms.push(value);
|
||||
}});
|
||||
const candidates = [];
|
||||
cleaned.split(/[。;;,,\n]/).forEach(part => {{
|
||||
const value = normalizeEvidenceText(part);
|
||||
if (value.length >= 8) candidates.push(value);
|
||||
if (value.length >= 28) candidates.push(value.slice(0, 28));
|
||||
}});
|
||||
candidates.push(...fallbackTerms);
|
||||
candidates.push(cleaned, raw);
|
||||
const seen = new Set();
|
||||
return specific.concat(candidates)
|
||||
.map(normalizeEvidenceText)
|
||||
.filter(value => value.length >= 3 && !seen.has(value) && seen.add(value))
|
||||
.sort((left, right) => right.length - left.length);
|
||||
}}
|
||||
|
||||
function compactEvidenceText(value) {{
|
||||
return normalizeEvidenceText(value).replace(/[\s\p{{P}}\p{{S}}]+/gu, '');
|
||||
}}
|
||||
|
||||
function compactEvidenceTextWithoutNumbers(value) {{
|
||||
return normalizeEvidenceText(value).replace(/[0-90-9]+/g, '').replace(/[\s\p{{P}}\p{{S}}]+/gu, '');
|
||||
}}
|
||||
|
||||
function evidenceLeadingAnchors(text) {{
|
||||
const raw = String(text || '');
|
||||
const cleaned = normalizeEvidenceText(raw);
|
||||
const anchors = [];
|
||||
const queryCompact = compactEvidenceText(evidenceSearchQuery);
|
||||
function push(value, options) {{
|
||||
const normalized = normalizeEvidenceText(value);
|
||||
const allowShort = options && options.allowShort === true;
|
||||
if (normalized.length < (allowShort ? 3 : 6)) return;
|
||||
anchors.push(normalized.length > 80 ? normalized.slice(0, 80) : normalized);
|
||||
if (normalized.length > 24) anchors.push(normalized.slice(0, 24));
|
||||
}}
|
||||
function pushQueryNearPrefix(value) {{
|
||||
const normalized = normalizeEvidenceText(value);
|
||||
if (!normalized || !queryCompact || !compactEvidenceText(normalized).includes(queryCompact)) return;
|
||||
push(normalized, {{ allowShort: true }});
|
||||
const queryIndex = compactEvidenceText(normalized).indexOf(queryCompact);
|
||||
if (queryIndex >= 0 && normalized.length > 24) push(normalized.slice(0, 36), {{ allowShort: true }});
|
||||
}}
|
||||
const prefixWindow = cleaned.slice(0, 260);
|
||||
const catalogMatches = prefixWindow.match(/[^,,。;;#]{{2,56}}[,,]\s*[0-90-9]{{1,5}}/g) || [];
|
||||
catalogMatches.slice(0, 8).forEach(match => {{
|
||||
const value = normalizeEvidenceText(match);
|
||||
push(value, {{ allowShort: true }});
|
||||
const withoutPage = value.replace(/[,,]\s*[0-90-9]{{1,5}}\s*$/, '');
|
||||
push(withoutPage, {{ allowShort: true }});
|
||||
pushQueryNearPrefix(withoutPage);
|
||||
}});
|
||||
const headingMatches = prefixWindow.match(/[0-90-9]+(?:\.[0-90-9]+){{1,5}}\s+[^。;;]{{2,72}}/g) || [];
|
||||
headingMatches.slice(0, 4).forEach(match => {{
|
||||
const firstPart = normalizeEvidenceText(match).split(/[,,]/)[0];
|
||||
push(firstPart, {{ allowShort: true }});
|
||||
}});
|
||||
raw.split(/[\n。;;]/).slice(0, 4).forEach(part => {{
|
||||
const value = normalizeEvidenceText(part);
|
||||
if (value) push(value);
|
||||
}});
|
||||
cleaned.split(/[。;;]/).slice(0, 4).forEach(part => {{
|
||||
const value = normalizeEvidenceText(part);
|
||||
if (value) push(value);
|
||||
}});
|
||||
evidenceTextCandidates(text).forEach(candidate => {{
|
||||
if (!queryCompact || compactEvidenceText(candidate).includes(queryCompact)) push(candidate);
|
||||
}});
|
||||
const seen = new Set();
|
||||
return anchors
|
||||
.map(normalizeEvidenceText)
|
||||
.filter(value => {{
|
||||
if (!value || seen.has(value)) return false;
|
||||
const compactValue = compactEvidenceText(value);
|
||||
const shortQueryAnchor = queryCompact.length >= 2
|
||||
&& compactValue.includes(queryCompact)
|
||||
&& compactValue.length >= queryCompact.length + 1
|
||||
&& /[0-90-9A-Za-z]/.test(value);
|
||||
if (value.length < 6 && !shortQueryAnchor) return false;
|
||||
seen.add(value);
|
||||
return true;
|
||||
}});
|
||||
}}
|
||||
|
||||
function shortLeadingAnchorTarget(element, elements, index) {{
|
||||
const normalized = normalizeEvidenceText(element && element.textContent || '');
|
||||
if (normalized.length >= 18) return element;
|
||||
for (let offset = 1; offset <= 3; offset += 1) {{
|
||||
const next = elements[index + offset];
|
||||
if (!(next instanceof HTMLElement)) continue;
|
||||
const nextText = normalizeEvidenceText(next.textContent || '');
|
||||
if (nextText.length >= 18 && evidenceElementMatchesSearchQuery(next)) return next;
|
||||
}}
|
||||
return element;
|
||||
}}
|
||||
|
||||
function scrollToEvidenceLeadingAnchor(text) {{
|
||||
if (!viewer) return false;
|
||||
const anchors = evidenceLeadingAnchors(text);
|
||||
if (!anchors.length) return false;
|
||||
const queryCompact = compactEvidenceText(evidenceSearchQuery);
|
||||
const elements = Array.from(viewer.querySelectorAll('p, li, td, th, blockquote'))
|
||||
.filter(node => node instanceof HTMLElement)
|
||||
.filter(node => {{
|
||||
const normalized = normalizeEvidenceText(node.textContent || '');
|
||||
return normalized.length >= 3 && normalized.length <= 1200;
|
||||
}});
|
||||
for (const anchor of anchors) {{
|
||||
const compactAnchor = compactEvidenceText(anchor);
|
||||
const compactAnchorWithoutNumbers = compactEvidenceTextWithoutNumbers(anchor);
|
||||
const shortQueryAnchor = queryCompact.length >= 2
|
||||
&& compactAnchor.includes(queryCompact)
|
||||
&& compactAnchor.length >= queryCompact.length + 1
|
||||
&& /[0-90-9A-Za-z]/.test(anchor);
|
||||
if (!shortQueryAnchor && compactAnchor.length < 6 && compactAnchorWithoutNumbers.length < 6) continue;
|
||||
for (const element of elements) {{
|
||||
const compactElement = compactEvidenceText(element.textContent || '');
|
||||
if ((compactAnchor.length >= 6 || shortQueryAnchor) && compactElement.includes(compactAnchor)) {{
|
||||
return markEvidenceTarget(shortQueryAnchor ? shortLeadingAnchorTarget(element, elements, elements.indexOf(element)) : element);
|
||||
}}
|
||||
if (
|
||||
compactAnchorWithoutNumbers.length >= 8
|
||||
&& /[\u3400-\u9fff]/.test(anchor)
|
||||
&& compactEvidenceTextWithoutNumbers(element.textContent || '').includes(compactAnchorWithoutNumbers)
|
||||
) {{
|
||||
return markEvidenceTarget(element);
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
return false;
|
||||
}}
|
||||
|
||||
function evidenceParagraphAnchors(text) {{
|
||||
const cleaned = normalizeEvidenceText(text);
|
||||
const anchors = [];
|
||||
function push(value) {{
|
||||
const normalized = normalizeEvidenceText(value);
|
||||
if (normalized.length < 6) return;
|
||||
anchors.push(normalized.length > 140 ? normalized.slice(0, 140) : normalized);
|
||||
}}
|
||||
evidenceTextCandidates(text).forEach(push);
|
||||
cleaned.split(/[。;;,,\n]/).forEach(part => {{
|
||||
const value = normalizeEvidenceText(part);
|
||||
if (value.length >= 10) push(value);
|
||||
if (value.length >= 36) push(value.slice(0, 36));
|
||||
}});
|
||||
if (cleaned.length >= 24) {{
|
||||
for (let index = 0; index < cleaned.length; index += 48) {{
|
||||
push(cleaned.slice(index, index + 96));
|
||||
}}
|
||||
}}
|
||||
push(cleaned);
|
||||
const seen = new Set();
|
||||
return anchors
|
||||
.map(normalizeEvidenceText)
|
||||
.filter(value => value.length >= 6 && !seen.has(value) && seen.add(value))
|
||||
.sort((left, right) => right.length - left.length);
|
||||
}}
|
||||
|
||||
function scoreEvidenceParagraphElement(element, anchors) {{
|
||||
if (!(element instanceof HTMLElement)) return 0;
|
||||
const text = normalizeEvidenceText(element.textContent || '');
|
||||
if (!text || text.length < 3 || text.length > 6000) return 0;
|
||||
const compactText = compactEvidenceText(text);
|
||||
const compactSearchQuery = compactEvidenceText(evidenceSearchQuery);
|
||||
let score = 0;
|
||||
if (compactSearchQuery.length >= 2 && compactText.includes(compactSearchQuery)) {{
|
||||
score += 2400;
|
||||
}}
|
||||
for (const anchor of anchors) {{
|
||||
const compactAnchor = compactEvidenceText(anchor);
|
||||
if (!compactAnchor || compactAnchor.length < 4) continue;
|
||||
if (text.includes(anchor)) {{
|
||||
score += anchor.length * anchor.length * 4;
|
||||
continue;
|
||||
}}
|
||||
if (compactText.includes(compactAnchor)) {{
|
||||
score += compactAnchor.length * compactAnchor.length * 2;
|
||||
continue;
|
||||
}}
|
||||
if (compactAnchor.length >= 14) {{
|
||||
const prefix = compactAnchor.slice(0, Math.min(36, compactAnchor.length));
|
||||
if (prefix.length >= 8 && compactText.includes(prefix)) score += prefix.length * 20;
|
||||
}}
|
||||
}}
|
||||
return score;
|
||||
}}
|
||||
|
||||
function evidenceElementMatchesSearchQuery(element) {{
|
||||
if (!(element instanceof HTMLElement)) return false;
|
||||
const compactSearchQuery = compactEvidenceText(evidenceSearchQuery);
|
||||
if (compactSearchQuery.length < 2) return false;
|
||||
return compactEvidenceText(element.textContent || '').includes(compactSearchQuery);
|
||||
}}
|
||||
|
||||
function scrollToEvidenceParagraph(text) {{
|
||||
if (!viewer) return false;
|
||||
if (scrollToEvidenceLeadingAnchor(text)) return true;
|
||||
const anchors = evidenceParagraphAnchors(text);
|
||||
if (!anchors.length) return false;
|
||||
const selector = 'p, li, td, th, blockquote, section.docx, section.mnote-docx, div';
|
||||
const elements = Array.from(viewer.querySelectorAll(selector))
|
||||
.filter(node => node instanceof HTMLElement)
|
||||
.filter(node => {{
|
||||
const normalized = normalizeEvidenceText(node.textContent || '');
|
||||
if (normalized.length < 3 || normalized.length > 6000) return false;
|
||||
const childBlocks = Array.from(node.children || []).filter(child => child instanceof HTMLElement && /^(P|LI|TD|TH|BLOCKQUOTE)$/.test(child.tagName));
|
||||
return childBlocks.length === 0 || /^(TD|TH|SECTION)$/.test(node.tagName);
|
||||
}});
|
||||
let best = null;
|
||||
let bestWithSearchQuery = null;
|
||||
for (const element of elements) {{
|
||||
const score = scoreEvidenceParagraphElement(element, anchors);
|
||||
if (score <= 0) continue;
|
||||
if (!best || score > best.score) best = {{ element, score }};
|
||||
if (evidenceElementMatchesSearchQuery(element) && (!bestWithSearchQuery || score > bestWithSearchQuery.score)) {{
|
||||
bestWithSearchQuery = {{ element, score }};
|
||||
}}
|
||||
}}
|
||||
const threshold = Math.max(180, Math.min(800, anchors[0].length * 4));
|
||||
if (bestWithSearchQuery && bestWithSearchQuery.score >= threshold) return markEvidenceTarget(bestWithSearchQuery.element);
|
||||
if (!best) return false;
|
||||
if (best.score < threshold) return false;
|
||||
return markEvidenceTarget(best.element);
|
||||
}}
|
||||
|
||||
function scrollToEvidenceTextCandidates(text) {{
|
||||
for (const candidate of evidenceTextCandidates(text)) {{
|
||||
if (scrollToEvidenceText(candidate)) return true;
|
||||
}}
|
||||
return false;
|
||||
}}
|
||||
|
||||
function scrollToEvidenceCoordinate(sourceMap, block) {{
|
||||
if (!viewer || !sourceMap || !block) return false;
|
||||
const page = pageForEvidenceBlock(sourceMap, block);
|
||||
@@ -1422,13 +1719,18 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
}}
|
||||
|
||||
async function applyEvidenceLocator() {{
|
||||
if (!viewer || (!evidencePage && !evidenceBlockId && !evidenceBbox)) return;
|
||||
if (!viewer || (!evidencePage && !evidenceBlockId && !evidenceBbox && !evidenceText)) return;
|
||||
try {{
|
||||
const sourceMap = await fetchEvidenceSourceMap();
|
||||
const block = findEvidenceBlockInSourceMap(sourceMap);
|
||||
if (block && scrollToEvidenceText(block.text)) return;
|
||||
if (evidenceText && scrollToEvidenceParagraph(evidenceText)) return;
|
||||
if (block && scrollToEvidenceParagraph(block.text)) return;
|
||||
if (evidenceText && scrollToEvidenceTextCandidates(evidenceText)) return;
|
||||
if (block && scrollToEvidenceTextCandidates(block.text)) return;
|
||||
if (scrollToEvidenceCoordinate(sourceMap, block)) return;
|
||||
}} catch (_) {{}}
|
||||
if (evidenceText && scrollToEvidenceParagraph(evidenceText)) return;
|
||||
if (evidenceText && scrollToEvidenceTextCandidates(evidenceText)) return;
|
||||
scrollToEvidencePageFallback();
|
||||
}}
|
||||
|
||||
@@ -1438,10 +1740,14 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
evidenceBbox = String(next.bbox || '');
|
||||
evidenceSourceMapPath = String(next.sourceMapPath || '');
|
||||
evidenceBlockId = String(next.blockId || '');
|
||||
evidenceText = String(next.evidenceText || next.query || '');
|
||||
evidenceSearchQuery = String(next.searchQuery || '');
|
||||
body.dataset.evidencePage = evidencePage ? String(evidencePage) : '';
|
||||
body.dataset.evidenceBbox = evidenceBbox;
|
||||
body.dataset.evidenceSourceMapPath = evidenceSourceMapPath;
|
||||
body.dataset.evidenceBlockId = evidenceBlockId;
|
||||
body.dataset.evidenceText = evidenceText;
|
||||
body.dataset.evidenceSearchQuery = evidenceSearchQuery;
|
||||
document.documentElement.removeAttribute('data-mnote-office-evidence-applied');
|
||||
void applyEvidenceLocator();
|
||||
}}
|
||||
@@ -1663,6 +1969,7 @@ pub async fn office_preview_page(Query(query): Query<OfficePreviewQuery>) -> Res
|
||||
target_bbox = escape_html(&target_bbox),
|
||||
target_source_map_path = escape_html(&target_source_map_path),
|
||||
target_block_id = escape_html(&target_block_id),
|
||||
target_evidence_text = escape_html(&target_evidence_text),
|
||||
);
|
||||
let mut response = Html(html).into_response();
|
||||
stamp_shell_headers(response.headers_mut(), "office-preview");
|
||||
|
||||
Reference in New Issue
Block a user