mirror of
https://github.com/tridactyl/tridactyl.git
synced 2026-09-10 07:16:33 -04:00
Fix #1933: make :find work on :viewsource and :reader
This is quite a big piece of work that moves :viewsource out into its own tab and iframe, because Firefox can't find text the old way. Then, we fix an iframe bug where :find was not working across iframes, such as on :reader
This commit is contained in:
parent
8dd6e14550
commit
e7993f216c
|
|
@ -49,7 +49,7 @@ class FindHighlight extends HTMLSpanElement {
|
|||
}
|
||||
|
||||
static fromFindApi(found, allTextNode: Text[]) {
|
||||
const range = document.createRange()
|
||||
const range = allTextNode[0].ownerDocument.createRange()
|
||||
range.setStart(allTextNode[found.startTextNodePos], found.startOffset)
|
||||
range.setEnd(allTextNode[found.endTextNodePos], found.endOffset)
|
||||
if (range.getClientRects().length < 1)
|
||||
|
|
@ -146,6 +146,7 @@ class FindHighlight extends HTMLSpanElement {
|
|||
queryInRange(selector: string): HTMLElement | null {
|
||||
const range = this.range
|
||||
const rangeEndNode = range.endContainer
|
||||
if (range.startContainer.ownerDocument !== document) return null
|
||||
|
||||
// start and end of range is always text node because fromFindApi()
|
||||
|
||||
|
|
@ -186,6 +187,7 @@ customElements.define("find-highlight", FindHighlight, { extends: "span" })
|
|||
const HIGHLIGHT_NAME = "tridactyl-find-highlight"
|
||||
const ACTIVE_HIGHLIGHT_NAME = "tridactyl-find-highlight-active"
|
||||
let nativeHighlights: { normal: Highlight; active: Highlight }
|
||||
let nativeRegistry = CSS.highlights
|
||||
|
||||
function isHighlightVisible(highlight: FindHighlight) {
|
||||
return DOM.isVisible(nativeHighlights ? highlight.range : highlight)
|
||||
|
|
@ -199,18 +201,18 @@ function setNativeFocus(range: Range, active: boolean) {
|
|||
|
||||
function clearNativeHighlights() {
|
||||
if (!nativeHighlights) return
|
||||
if (CSS.highlights.get(HIGHLIGHT_NAME) === nativeHighlights.normal)
|
||||
CSS.highlights.delete(HIGHLIGHT_NAME)
|
||||
if (CSS.highlights.get(ACTIVE_HIGHLIGHT_NAME) === nativeHighlights.active)
|
||||
CSS.highlights.delete(ACTIVE_HIGHLIGHT_NAME)
|
||||
if (nativeRegistry.get(HIGHLIGHT_NAME) === nativeHighlights.normal)
|
||||
nativeRegistry.delete(HIGHLIGHT_NAME)
|
||||
if (nativeRegistry.get(ACTIVE_HIGHLIGHT_NAME) === nativeHighlights.active)
|
||||
nativeRegistry.delete(ACTIVE_HIGHLIGHT_NAME)
|
||||
nativeHighlights = undefined
|
||||
}
|
||||
|
||||
function highlightsDrawn() {
|
||||
if (!nativeHighlights) return !!host?.firstChild
|
||||
return (
|
||||
CSS.highlights.get(HIGHLIGHT_NAME) === nativeHighlights.normal &&
|
||||
CSS.highlights.get(ACTIVE_HIGHLIGHT_NAME) === nativeHighlights.active &&
|
||||
nativeRegistry.get(HIGHLIGHT_NAME) === nativeHighlights.normal &&
|
||||
nativeRegistry.get(ACTIVE_HIGHLIGHT_NAME) === nativeHighlights.active &&
|
||||
nativeHighlights.normal.size + nativeHighlights.active.size ===
|
||||
lastHighlights.length
|
||||
)
|
||||
|
|
@ -260,26 +262,26 @@ export async function jumpToMatch(searchQuery, option) {
|
|||
lastHighlights = []
|
||||
removeHighlighting()
|
||||
|
||||
// We need to grab all text nodes in order to find the corresponding element
|
||||
const walker = document.createTreeWalker(
|
||||
document,
|
||||
NodeFilter.SHOW_TEXT,
|
||||
null,
|
||||
)
|
||||
const documents = [document]
|
||||
for (const frame of DOM.getAllDocumentFrames())
|
||||
if (frame.contentDocument) documents.push(frame.contentDocument)
|
||||
const nodeSets = documents.map(doc => {
|
||||
const walker = doc.createTreeWalker(doc, NodeFilter.SHOW_TEXT)
|
||||
const nodes = []
|
||||
let node
|
||||
do {
|
||||
node = walker.nextNode()
|
||||
nodes.push(node)
|
||||
} while (node)
|
||||
while (walker.nextNode()) nodes.push(walker.currentNode)
|
||||
return nodes
|
||||
})
|
||||
|
||||
for (let i = 0; i < results.count; ++i) {
|
||||
const range = results.rangeData[i]
|
||||
for (const nodes of nodeSets) {
|
||||
try {
|
||||
const high = FindHighlight.fromFindApi(range, nodes)
|
||||
lastHighlights.push(high)
|
||||
break
|
||||
} catch (_) {} // Inaccessible range, eg cross-origin iframe - ignore
|
||||
}
|
||||
}
|
||||
if (lastHighlights.length < 1) {
|
||||
throw new Error("Pattern not found: " + searchQuery)
|
||||
}
|
||||
|
|
@ -307,13 +309,16 @@ export async function jumpToMatch(searchQuery, option) {
|
|||
|
||||
function drawHighlights(highlights) {
|
||||
if (NATIVE_HIGHLIGHTS) {
|
||||
const normal = new Highlight()
|
||||
const doc = highlights[0].range.startContainer.ownerDocument
|
||||
const win: any = doc.defaultView
|
||||
const normal = new win.Highlight()
|
||||
highlights.forEach(highlight => normal.add(highlight.nativeRange))
|
||||
const active = new Highlight()
|
||||
const active = new win.Highlight()
|
||||
nativeRegistry = win.CSS.highlights
|
||||
normal.priority = 2147483646
|
||||
active.priority = 2147483647
|
||||
CSS.highlights.set(HIGHLIGHT_NAME, normal)
|
||||
CSS.highlights.set(ACTIVE_HIGHLIGHT_NAME, active)
|
||||
nativeRegistry.set(HIGHLIGHT_NAME, normal)
|
||||
nativeRegistry.set(ACTIVE_HIGHLIGHT_NAME, active)
|
||||
nativeHighlights = { normal, active }
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1754,18 +1754,6 @@ export async function url2args() {
|
|||
return UrlUtil.searchUrlToArgs(document.location.href, await config.getAsync("searchurls"))
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
//#content_helper
|
||||
let sourceElement: Element
|
||||
/** @hidden */
|
||||
//#content_helper
|
||||
function removeSource() {
|
||||
if (sourceElement) {
|
||||
sourceElement.remove()
|
||||
sourceElement = undefined
|
||||
}
|
||||
}
|
||||
|
||||
/** Display the (HTML) source of the current page.
|
||||
|
||||
Behaviour can be changed by the 'viewsource' setting.
|
||||
|
|
@ -1775,27 +1763,16 @@ function removeSource() {
|
|||
Otherwise, the source of the current document will be displayed.
|
||||
*/
|
||||
//#content
|
||||
export function viewsource(url = "") {
|
||||
export async function viewsource(url = "") {
|
||||
if (window.location.href.includes("static/reader.html?source#")) return tabclose()
|
||||
if (url === "") url = window.location.href
|
||||
if (config.get("viewsource") === "default") {
|
||||
window.location.href = "view-source:" + url
|
||||
return
|
||||
}
|
||||
if (!sourceElement) {
|
||||
sourceElement = CommandLineContent.executeWithoutCommandLine(() => {
|
||||
const pre = document.createElement("pre")
|
||||
pre.id = "TridactylViewsourceElement"
|
||||
pre.className = "cleanslate " + config.get("theme")
|
||||
pre.innerText = document.documentElement.innerHTML
|
||||
document.documentElement.appendChild(pre)
|
||||
window.addEventListener("popstate", removeSource)
|
||||
return pre
|
||||
})
|
||||
} else {
|
||||
sourceElement.parentNode.removeChild(sourceElement)
|
||||
sourceElement = undefined
|
||||
window.removeEventListener("popstate", removeSource)
|
||||
}
|
||||
pre.textContent = CommandLineContent.executeWithoutCommandLine(() => document.documentElement.innerHTML)
|
||||
return tabopen(await readerurl({ content: pre.outerHTML, link: url, source: true }))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -6583,11 +6560,13 @@ import { Readability } from "@mozilla/readability"
|
|||
* @hidden
|
||||
*/
|
||||
//#content_helper
|
||||
export async function readerurl() {
|
||||
export async function readerurl(article: any = undefined) {
|
||||
if (!article) {
|
||||
document.querySelectorAll(".TridactylStatusIndicator").forEach(ind => ind.parentNode.removeChild(ind))
|
||||
const article = new Readability(document.cloneNode(true) as any as Document).parse()
|
||||
article = new Readability(document.cloneNode(true) as any as Document).parse()
|
||||
article["link"] = window.location.href
|
||||
article["favicon"] = (await ownTab()).favIconUrl
|
||||
}
|
||||
let hash = ""
|
||||
const article_encoded = btoa(encodeURIComponent(JSON.stringify(article)))
|
||||
if (!(await browserBg.windows.getCurrent()).incognito) {
|
||||
|
|
@ -6597,7 +6576,7 @@ export async function readerurl() {
|
|||
} else {
|
||||
hash = article_encoded
|
||||
}
|
||||
return browser.runtime.getURL("static/reader.html#" + hash)
|
||||
return browser.runtime.getURL(`static/reader.html${article.source ? "?source" : ""}#${hash}`)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ export function isVisible(thing: Element | Range) {
|
|||
return false
|
||||
}
|
||||
|
||||
if (thing instanceof Range) return true
|
||||
if ("startContainer" in thing) return true
|
||||
|
||||
const element = thing
|
||||
// remove elements that are barely within the viewport, tiny, or invisible
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ async function updatePage() {
|
|||
: staticThemes.includes(theme)
|
||||
? `@import url("${browser.runtime.getURL("static/themes/" + theme + "/" + theme + ".css")}");`
|
||||
: (await config.getAsync("customthemes", theme)) || ""
|
||||
readerContent.srcdoc = `<!doctype html><html lang="en" class="TridactylOwnNamespace"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="${readerCsp}"><link rel="stylesheet" href="${browser.runtime.getURL("static/css/reader.css")}"><style>${themeCss}</style></head><body id="tridactyl-reader" dir="auto">${headerHtml}<main>${article.content}</main></body></html>`
|
||||
readerContent.srcdoc = `<!doctype html><html lang="en" class="TridactylOwnNamespace"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="${readerCsp}"><link rel="stylesheet" href="${browser.runtime.getURL("static/css/" + (article.source ? "viewsource.css" : "reader.css"))}"><link rel="stylesheet" href="${browser.runtime.getURL("static/css/content.css")}"><style>${themeCss}</style></head><body id="tridactyl-reader" dir="auto">${headerHtml}<main>${article.content}</main></body></html>`
|
||||
if (article.link !== undefined) {
|
||||
const link =
|
||||
(document.getElementById("tricanonlink") as HTMLLinkElement) ??
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
@import url("../themes/auto/auto.css");
|
||||
|
||||
#TridactylViewsourceElement {
|
||||
pre {
|
||||
position: absolute !important;
|
||||
/* This is the z-index of hint.css and content.css -1 */
|
||||
z-index: 2147483646 !important;
|
||||
|
|
|
|||
Loading…
Reference in a new issue