Merge pull request #2509 from tridactyl/more_rules

More rules
This commit is contained in:
Oliver Blanthorn 2020-06-19 18:58:37 +01:00 committed by GitHub
commit 65869e7530
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 586 additions and 521 deletions

View file

@ -129,17 +129,18 @@ module.exports = {
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/prefer-regexp-exec": "off", //"error",
"@typescript-eslint/prefer-regexp-exec": "error",
"@typescript-eslint/quotes": [
"off", //"error",
"error",
"double",
{
"avoidEscape": true
}
"avoidEscape": true,
"allowTemplateLiterals": true,
},
],
"@typescript-eslint/require-await": "off", //"error",
"@typescript-eslint/restrict-plus-operands": "off", //"error",
"@typescript-eslint/restrict-template-expressions": "off", //"error",
"@typescript-eslint/require-await": "error",
"@typescript-eslint/restrict-plus-operands": "off", //"error", // We use this a lot - fixing it is a problem for a rainy day
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/semi": [
"off",
null
@ -153,15 +154,15 @@ module.exports = {
}
],
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unbound-method": "off", //"error",
"@typescript-eslint/unified-signatures": "off", //"error",
"arrow-body-style": "off", //"error",
"@typescript-eslint/unbound-method": "error",
"@typescript-eslint/unified-signatures": "error",
"arrow-body-style": "error",
"arrow-parens": [
"off",
"always"
],
"brace-style": [
"off", //"error",
"error",
"1tbs"
],
"camelcase": "off",
@ -174,7 +175,7 @@ module.exports = {
"off",
"always"
],
"guard-for-in": "off", //"error",
"guard-for-in": "error",
"id-blacklist": "off",
"id-match": "off",
"import/order": "off",
@ -198,7 +199,7 @@ module.exports = {
],
"no-empty-function": "off",
"no-eval": "off",
"no-extra-semi": "off", //"off",
"no-extra-semi": "error",
"no-fallthrough": "off",
"no-invalid-this": "off",
"no-multiple-empty-lines": "error",
@ -252,11 +253,12 @@ module.exports = {
"use-isnan": "error",
"valid-typeof": "off"
},
// // We ultimately didn't need this but I thought I should document it anyway
// "overrides": [{
// "files": ["src/completions/*.ts",],
// "rules": {
// "@typescript-eslint/no-empty-function": "off",
// },
// }],
"overrides": [{
"files": ["src/completions/*.ts", "src/excmds.ts"],
"rules": {
// We have methods that must be async in some classes but not in others
// In src/excmds anything that crosses between content<->background must be async even if it looks like it isn't
"@typescript-eslint/require-await": "off",
},
}],
};

View file

@ -40,7 +40,7 @@ main() {
lock .git/index.lock
case "$file" in
*.md | *.css) prettier --write "$file";;
*) eslint --fix "$file";;
*) prettier --write "$file"; eslint --fix "$file";;
esac
unlock .git/index.lock
git add "$file"

View file

@ -54,9 +54,9 @@ import { HintingCmds } from "@src/background/hinting"
// here.
controller.setExCmds({
"": excmds_background,
"ex": CmdlineCmds,
"text": EditorCmds,
"hint": HintingCmds
ex: CmdlineCmds,
text: EditorCmds,
hint: HintingCmds,
})
// {{{ tri.contentLocation
@ -78,13 +78,11 @@ browser.tabs.onActivated.addListener(ev => {
})
})
// Update on navigation too (but remember that sometimes people open tabs in the background :) )
browser.webNavigation.onDOMContentLoaded.addListener(
() => {
browser.webNavigation.onDOMContentLoaded.addListener(() => {
browser.tabs.query({ currentWindow: true, active: true }).then(t => {
(window as any).tri.contentLocation = new URL(t[0].url)
})
},
)
})
// Prevent Tridactyl from being updated while it is running in the hope of fixing #290
browser.runtime.onUpdateAvailable.addListener(_ => undefined)
@ -98,7 +96,7 @@ browser.runtime.onStartup.addListener(_ => {
} else {
native.run("hostname").then(hostname => {
for (const host of hosts) {
if (hostname.content.match(host)) {
if ((new RegExp(host)).exec(hostname.content)) {
controller.acceptExCmd(aucmds[host])
}
}
@ -164,9 +162,7 @@ browser.webRequest.onBeforeRequest.addListener(
["blocking"],
)
browser.tabs.onCreated.addListener(
aucon.tabCreatedListener,
)
browser.tabs.onCreated.addListener(aucon.tabCreatedListener)
// }}}
@ -182,7 +178,7 @@ const messages = {
downloadUrl: download_background.downloadUrl,
downloadUrlAs: download_background.downloadUrlAs,
},
browser_proxy_background: {shim: proxy_background.shim}
browser_proxy_background: { shim: proxy_background.shim },
}
export type Messages = typeof messages
@ -211,6 +207,6 @@ omnibox.init()
// {{{ Obey Mozilla's orders https://github.com/tridactyl/tridactyl/issues/1800
native.unfixamo();
native.unfixamo()
/// }}}

View file

@ -4,13 +4,14 @@
*/
import * as controller from "@src/lib/controller"
export async function inputEnteredListener(
input: string, disposition:
browser.omnibox.OnInputEnteredDisposition) {
export function inputEnteredListener(
input: string,
disposition: browser.omnibox.OnInputEnteredDisposition,
) {
controller.acceptExCmd(input)
}
export async function init() {
export function init() {
browser.omnibox.onInputEntered.addListener(inputEnteredListener)
browser.omnibox.setDefaultSuggestion({
description: `Execute a Tridactyl exstr (for example, "tabopen -c container www.google.com")`,

View file

@ -239,9 +239,7 @@ export abstract class CompletionSourceFuse extends CompletionSource {
/** Rtn sorted array of {option, score} */
scoredOptions(query: string, options = this.options): ScoredOption[] {
const searchThis = this.options.map((elem, index) => {
return { index, fuseKeys: elem.fuseKeys }
})
const searchThis = this.options.map((elem, index) => ({ index, fuseKeys: elem.fuseKeys }))
this.fuse = new Fuse(searchThis, this.fuseOptions)
return this.fuse.search(query).map(result => {
// console.log(result, result.item, query)

View file

@ -64,14 +64,12 @@ export class BindingsCompletionSource extends Completions.CompletionSourceFuse {
this.options = Object.keys(patterns)
.filter(pattern => pattern.startsWith(urlPattern))
.sort()
.map(pattern => {
return new BindingsCompletionOption(
.map(pattern => new BindingsCompletionOption(
pattern, {
name: pattern,
value: "",
mode: "URL Pattern",
})
})
}))
return this.updateChain()
}
@ -84,14 +82,12 @@ export class BindingsCompletionSource extends Completions.CompletionSourceFuse {
const modeStr = margs.length > 1 ? margs[1] : ""
this.options = Binding.modes
.filter(k => k.startsWith(modeStr))
.map(name => {
return new BindingsCompletionOption(
.map(name => new BindingsCompletionOption(
options + "--mode=" + name, {
name,
value: "",
mode: "Mode Name",
})
})
}))
return this.updateChain()
}
}
@ -124,14 +120,12 @@ export class BindingsCompletionSource extends Completions.CompletionSourceFuse {
this.options = Object.keys(bindings)
.filter(x => x.toLowerCase().startsWith(query) )
.sort()
.map(keystr => {
return new BindingsCompletionOption(
.map(keystr => new BindingsCompletionOption(
options + keystr + " " + bindings[keystr], {
name: keystr,
value: JSON.stringify(bindings[keystr]),
mode: `${configName} (${modeName})`,
})
})
}))
return this.updateChain()
}

View file

@ -38,16 +38,15 @@ class BufferCompletionOption extends Completions.CompletionOptionHTML
const favIconUrl = tab.favIconUrl
? tab.favIconUrl
: Completions.DEFAULT_FAVICON
this.html = html`<tr class="BufferCompletionOption option container_${container.color} container_${container.icon} container_${container.name}"
this.html = html`<tr
class="BufferCompletionOption option container_${container.color} container_${container.icon} container_${container.name}"
>
<td class="prefix">${pre.padEnd(2)}</td>
<td class="container"></td>
<td class="icon"><img src="${favIconUrl}" /></td>
<td class="title">${tab.index + 1}: ${tab.title}</td>
<td class="content">
<a class="url" target="_blank" href=${tab.url}
>${tab.url}</a
>
<a class="url" target="_blank" href=${tab.url}>${tab.url}</a>
</td>
</tr>`
}
@ -126,15 +125,17 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
/** Return the scoredOption[] result for the nth tab */
private nthTabscoredOptions(
n: number,
options: BufferCompletionOption[]
options: BufferCompletionOption[],
): Completions.ScoredOption[] {
for (const [index, option] of enumerate(options)) {
if (option.tabIndex === n) {
return [{
return [
{
index,
option,
score: 0,
}, ]
},
]
}
}
}
@ -142,10 +143,10 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
/** Return the scoredOption[] result for the tab index startswith n */
private TabscoredOptionsStartsWithN(
n: number,
options: BufferCompletionOption[]
options: BufferCompletionOption[],
): Completions.ScoredOption[] {
const nstr = (n + 1).toString()
const res = [];
const res = []
for (const [index, option] of enumerate(options)) {
if ((option.tabIndex + 1).toString().startsWith(nstr)) {
res.push({
@ -158,7 +159,7 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
// old input will change order: 12 => 123 => 12
res.sort((a, b) => a.option.tabIndex - b.option.tabIndex)
return res;
return res
}
private async fillOptions() {
@ -167,17 +168,19 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
})
const options = []
// Get alternative tab, defined as last accessed tab.
tabs.sort((a, b) => (b.lastAccessed - a.lastAccessed))
tabs.sort((a, b) => b.lastAccessed - a.lastAccessed)
const alt = tabs[1]
const useMruTabOrder = (config.get("tabsort") === "mru")
const useMruTabOrder = config.get("tabsort") === "mru"
if (!useMruTabOrder) {
tabs.sort((a, b) => (a.index - b.index))
tabs.sort((a, b) => a.index - b.index)
}
const container_all = await browserBg.contextualIdentities.query({})
const container_map = new Map()
container_all.forEach(elem => container_map.set(elem.cookieStoreId, elem))
container_all.forEach(elem =>
container_map.set(elem.cookieStoreId, elem),
)
// firefox-default is not in contextualIdenetities
container_map.set("firefox-default", Containers.DefaultContainer)
@ -191,7 +194,7 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
(tab.index + 1).toString(),
tab,
tab === alt,
tab_container
tab_container,
),
)
}
@ -219,7 +222,7 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
// When the user is asking for tabmove completions, don't autoselect if the query looks like a relative move https://github.com/tridactyl/tridactyl/issues/825
this.shouldSetStateFromScore = !(
prefix === "tabmove " && query.match("^[+-][0-9]+$")
prefix === "tabmove " && /^[+-][0-9]+$/.exec(query)
)
if (!this.options) {

View file

@ -35,12 +35,18 @@ import { EditorCmds } from "@src/content/editor"
import * as hinting_content from "@src/content/hinting"
controller.setExCmds({
"": excmds_content,
"ex": CmdlineCmds,
"text": EditorCmds,
"hint": hinting_content.getHintCommands()
ex: CmdlineCmds,
text: EditorCmds,
hint: hinting_content.getHintCommands(),
})
messaging.addListener("excmd_content", messaging.attributeCaller(excmds_content))
messaging.addListener("controller_content", messaging.attributeCaller(controller))
messaging.addListener(
"excmd_content",
messaging.attributeCaller(excmds_content),
)
messaging.addListener(
"controller_content",
messaging.attributeCaller(controller),
)
// Hook the keyboard up to the controller
import * as ContentController from "@src/content/controller_content"
@ -87,7 +93,7 @@ config.getAsync("preventautofocusjackhammer").then(allowautofocus => {
const preventAutoFocus = () => {
// First, blur whatever element is active. This will make sure
// activeElement is the "default" active element
; (document.activeElement as any).blur()
(document.activeElement as any).blur()
const elem = document.activeElement as any
// ???: We need to set tabIndex, otherwise we won't get focus/blur events!
elem.tabIndex = 0
@ -97,7 +103,9 @@ config.getAsync("preventautofocusjackhammer").then(allowautofocus => {
// On top of blur/focusout events, we need to periodically check the
// activeElement is the one we want because blur/focusout events aren't
// always triggered when document.activeElement changes
const interval = setInterval(() => { if (document.activeElement != elem) focusElem() }, 200)
const interval = setInterval(() => {
if (document.activeElement != elem) focusElem()
}, 200)
// When the user starts interacting with the page, stop resetting focus
function stopResettingFocus(event: Event) {
if (!event.isTrusted) return
@ -240,7 +248,9 @@ config.getAsync("modeindicator").then(mode => {
.then(container => {
statusIndicator.setAttribute(
"style",
`border: ${(container as any).colorCode} solid 1.5px !important`,
`border: ${
(container as any).colorCode
} solid 1.5px !important`,
)
})
.catch(error => {
@ -338,14 +348,12 @@ config.getAsync("modeindicator").then(mode => {
function protectSlash(e) {
if (!e.isTrusted) return
config.get("blacklistkeys").map(
protkey => {
config.get("blacklistkeys").map(protkey => {
if (protkey.indexOf(e.key) !== -1 && contentState.mode === "normal") {
e.cancelBubble = true
e.stopImmediatePropagation()
}
}
)
})
}
// Some sites like to prevent firefox's `/` from working so we need to protect
@ -366,11 +374,19 @@ config.getAsync("leavegithubalone").then(v => {
document.addEventListener("selectionchange", () => {
const selection = document.getSelection()
if ((contentState.mode == "visual") && (config.get("visualexitauto") == "true") && (selection.anchorOffset == selection.focusOffset)) {
if (
contentState.mode == "visual" &&
config.get("visualexitauto") == "true" &&
selection.anchorOffset == selection.focusOffset
) {
contentState.mode = "normal"
return
}
if ((contentState.mode !== "normal") || (config.get("visualenterauto") == "false")) return
if (
contentState.mode !== "normal" ||
config.get("visualenterauto") == "false"
)
return
if (selection.anchorOffset !== selection.focusOffset) {
contentState.mode = "visual"
}

View file

@ -62,12 +62,12 @@ class KeyCanceller {
this.keyUp.push(ke)
}
cancelKeyPress(ke: KeyboardEvent) {
public cancelKeyPress = (ke: KeyboardEvent) => {
if (!ke.isTrusted) return
this.cancelKey(ke, this.keyPress)
}
cancelKeyUp(ke: KeyboardEvent) {
public cancelKeyUp = (ke: KeyboardEvent) => {
if (!ke.isTrusted) return
this.cancelKey(ke, this.keyUp)
}

View file

@ -35,7 +35,10 @@ class FindHighlight extends HTMLSpanElement {
}
;(this as any).focus = () => {
if (!DOM.isVisible(this.children[0])) {
this.children[0].scrollIntoView({ block: "center", inline: "center" })
this.children[0].scrollIntoView({
block: "center",
inline: "center",
})
}
let parentNode = this.node.parentNode
while (parentNode && !(parentNode instanceof HTMLAnchorElement)) {
@ -50,8 +53,8 @@ class FindHighlight extends HTMLSpanElement {
}
this.style.position = "absolute"
this.style.top = "0px";
this.style.left = "0px";
this.style.top = "0px"
this.style.left = "0px"
for (const rect of rects) {
if (rect.top < this.top) {
this.top = rect.top
@ -67,9 +70,8 @@ class FindHighlight extends HTMLSpanElement {
highlight.style.pointerEvents = "none"
this.appendChild(highlight)
}
; (this as any).unfocus()
(this as any).unfocus()
}
}
customElements.define("find-highlight", FindHighlight, { extends: "span" })
@ -82,7 +84,9 @@ let selected = 0
export async function jumpToMatch(searchQuery, reverse) {
// First, search for the query
const findcase = config.get("findcase")
const sensitive = findcase === "sensitive" || (findcase === "smart" && /[A-Z]/.test(searchQuery))
const sensitive =
findcase === "sensitive" ||
(findcase === "smart" && /[A-Z]/.test(searchQuery))
const findPromise = await browserBg.find.find(searchQuery, {
tabId: await activeTabId(),
caseSensitive: sensitive,
@ -95,7 +99,12 @@ export async function jumpToMatch(searchQuery, reverse) {
removeHighlighting()
// We need to grab all text nodes in order to find the corresponding element
const walker = document.createTreeWalker(document, NodeFilter.SHOW_TEXT, null, false)
const walker = document.createTreeWalker(
document,
NodeFilter.SHOW_TEXT,
null,
false,
)
const nodes = []
let node
do {
@ -111,10 +120,13 @@ export async function jumpToMatch(searchQuery, reverse) {
const data = results.rectData[i]
if (data.rectsAndTexts.rectList.length < 1) {
// When a result does not have any rectangles, it's not visible
continue;
continue
}
const range = results.rangeData[i]
const high = new FindHighlight(data.rectsAndTexts.rectList, nodes[range.startTextNodePos])
const high = new FindHighlight(
data.rectsAndTexts.rectList,
nodes[range.startTextNodePos],
)
host.appendChild(high)
lastHighlights.push(high)
if (!focused && DOM.isVisible(high)) {
@ -126,8 +138,9 @@ export async function jumpToMatch(searchQuery, reverse) {
if (lastHighlights.length < 1) {
throw new Error("Pattern not found: " + searchQuery)
}
lastHighlights
.sort(reverse ? (a, b) => b.top - a.top : (a, b) => a.top - b.top)
lastHighlights.sort(
reverse ? (a, b) => b.top - a.top : (a, b) => a.top - b.top,
)
if (!focused) {
selected = 0
/* tslint:disable:no-useless-cast */
@ -141,7 +154,7 @@ function drawHighlights(highlights) {
}
export function removeHighlighting() {
const host = getFindHost();
const host = getFindHost()
while (host.firstChild) host.removeChild(host.firstChild)
}
@ -158,7 +171,7 @@ export async function jumpToNextMatch(n: number) {
throw new Error("Pattern not found: " + lastSearchQuery)
}
/* tslint:disable:no-useless-cast */
; (lastHighlights[selected] as any).unfocus()
(lastHighlights[selected] as any).unfocus()
selected = (selected + n + lastHighlights.length) % lastHighlights.length
/* tslint:disable:no-useless-cast */
;(lastHighlights[selected] as any).focus()

View file

@ -122,15 +122,29 @@ class HintState {
const focusedRect = this.focusedHint.rect
// Get all hints from the top area
const topHints = this.activeHints.filter(h => h.rect.top < focusedRect.top && h.rect.bottom < focusedRect.bottom)
const topHints = this.activeHints.filter(
h =>
h.rect.top < focusedRect.top &&
h.rect.bottom < focusedRect.bottom,
)
if (!topHints.length) {
return
}
// Find the next top hint
const nextFocusedHint = topHints.reduce((a, b) => {
const aDistance = distance(a.rect.left, a.rect.right, focusedRect.left, focusedRect.right)
const bDistance = distance(b.rect.left, b.rect.right, focusedRect.left, focusedRect.right)
const aDistance = distance(
a.rect.left,
a.rect.right,
focusedRect.left,
focusedRect.right,
)
const bDistance = distance(
b.rect.left,
b.rect.right,
focusedRect.left,
focusedRect.right,
)
if (aDistance < bDistance) {
return a
} else if (aDistance > bDistance) {
@ -156,15 +170,29 @@ class HintState {
const focusedRect = this.focusedHint.rect
// Get all hints from the bottom area
const bottomHints = this.activeHints.filter(h => h.rect.top > focusedRect.top && h.rect.bottom > focusedRect.bottom)
const bottomHints = this.activeHints.filter(
h =>
h.rect.top > focusedRect.top &&
h.rect.bottom > focusedRect.bottom,
)
if (!bottomHints.length) {
return
}
// Find the next bottom hint
const nextFocusedHint = bottomHints.reduce((a, b) => {
const aDistance = distance(a.rect.left, a.rect.right, focusedRect.left, focusedRect.right)
const bDistance = distance(b.rect.left, b.rect.right, focusedRect.left, focusedRect.right)
const aDistance = distance(
a.rect.left,
a.rect.right,
focusedRect.left,
focusedRect.right,
)
const bDistance = distance(
b.rect.left,
b.rect.right,
focusedRect.left,
focusedRect.right,
)
if (aDistance < bDistance) {
return a
} else if (aDistance > bDistance) {
@ -190,15 +218,29 @@ class HintState {
const focusedRect = this.focusedHint.rect
// Get all hints from the left area
const leftHints = this.activeHints.filter(h => h.rect.left < focusedRect.left && h.rect.right < focusedRect.right)
const leftHints = this.activeHints.filter(
h =>
h.rect.left < focusedRect.left &&
h.rect.right < focusedRect.right,
)
if (!leftHints.length) {
return
}
// Find the next left hint
const nextFocusedHint = leftHints.reduce((a, b) => {
const aDistance = distance(a.rect.top, a.rect.bottom, focusedRect.top, focusedRect.bottom)
const bDistance = distance(b.rect.top, b.rect.bottom, focusedRect.top, focusedRect.bottom)
const aDistance = distance(
a.rect.top,
a.rect.bottom,
focusedRect.top,
focusedRect.bottom,
)
const bDistance = distance(
b.rect.top,
b.rect.bottom,
focusedRect.top,
focusedRect.bottom,
)
if (aDistance < bDistance) {
return a
} else if (aDistance > bDistance) {
@ -224,15 +266,29 @@ class HintState {
const focusedRect = this.focusedHint.rect
// Get all hints from the right area
const rightHints = this.activeHints.filter(h => h.rect.left > focusedRect.left && h.rect.right > focusedRect.right)
const rightHints = this.activeHints.filter(
h =>
h.rect.left > focusedRect.left &&
h.rect.right > focusedRect.right,
)
if (!rightHints.length) {
return
}
// Find the next right hint
const nextFocusedHint = rightHints.reduce((a, b) => {
const aDistance = distance(a.rect.top, a.rect.bottom, focusedRect.top, focusedRect.bottom)
const bDistance = distance(b.rect.top, b.rect.bottom, focusedRect.top, focusedRect.bottom)
const aDistance = distance(
a.rect.top,
a.rect.bottom,
focusedRect.top,
focusedRect.bottom,
)
const bDistance = distance(
b.rect.top,
b.rect.bottom,
focusedRect.top,
focusedRect.bottom,
)
if (aDistance < bDistance) {
return a
} else if (aDistance > bDistance) {
@ -264,8 +320,12 @@ class HintState {
// To do this, compute the number of hints between the last selected
// hint and the hint selected before it
const lastIndex = this.hints.indexOf(this.selectedHints[this.selectedHints.length - 1])
const prevIndex = this.hints.indexOf(this.selectedHints[this.selectedHints.length - 2])
const lastIndex = this.hints.indexOf(
this.selectedHints[this.selectedHints.length - 1],
)
const prevIndex = this.hints.indexOf(
this.selectedHints[this.selectedHints.length - 2],
)
const distance = lastIndex - prevIndex
if (distance > 0) {
@ -302,7 +362,9 @@ class HintState {
// Set the names that should go at the end
for (let i = 0; i < savedNames.length; ++i) {
this.hints[this.hints.length + distance + i].setName(savedNames[i])
this.hints[this.hints.length + distance + i].setName(
savedNames[i],
)
}
}
@ -339,8 +401,11 @@ export function hintPage(
buildHints(hintableElements, hint => {
hint.result = onSelect(hint.target)
modeState.selectedHints.push(hint)
if (modeState.selectedHints.length > 1 && (config.get("hintshift") === "true")) {
modeState.shiftHints();
if (
modeState.selectedHints.length > 1 &&
config.get("hintshift") === "true"
) {
modeState.shiftHints()
}
})
}
@ -363,23 +428,24 @@ export function hintPage(
const firstTarget = modeState.hints[0].target
const firstTargetIsSelectable = (): boolean => {
return firstTarget instanceof HTMLAnchorElement &&
const firstTargetIsSelectable = (): boolean => (
firstTarget instanceof HTMLAnchorElement &&
firstTarget.href !== "" &&
!firstTarget.href.startsWith("javascript:")
}
)
const allTargetsAreEqual = (): boolean => {
return undefined === modeState.hints.find(h => {
return (
const allTargetsAreEqual = (): boolean => (
undefined ===
modeState.hints.find(h => (
!(h.target instanceof HTMLAnchorElement) ||
h.target.href !== (firstTarget as HTMLAnchorElement).href
))
)
})
}
if (modeState.hints.length == 1 ||
(firstTargetIsSelectable() && allTargetsAreEqual())) {
if (
modeState.hints.length == 1 ||
(firstTargetIsSelectable() && allTargetsAreEqual())
) {
// There is just a single link or all the links point to the same
// place. Select it.
modeState.cleanUpHints()
@ -479,9 +545,7 @@ function* hintnames_uniform(
// And return first n permutations
yield* map(
islice(permutationsWithReplacement(hintchars, taglen), n),
perm => {
return perm.join("")
},
perm => perm.join(""),
)
}
}
@ -552,7 +616,7 @@ class Hint {
left: rect.left + offsetLeft,
right: rect.right + offsetLeft,
width: rect.width,
height: rect.height
height: rect.height,
}
this.flag.textContent = name
@ -631,9 +695,13 @@ export const vimpHelper = {
// escape the hintchars string so that strange things don't happen
// when special characters are used as hintchars (for example, ']')
const escapedHintChars = defaultHintChars().replace(
/^\^|[-\\\]]/g, "\\$&")
/^\^|[-\\\]]/g,
"\\$&",
)
const filterableTextFilter = new RegExp(
"[" + escapedHintChars + "]", "g")
"[" + escapedHintChars + "]",
"g",
)
vimpHelper.filterableTextFilter = filterableTextFilter
}
return str.replace(vimpHelper.filterableTextFilter, "")
@ -751,7 +819,9 @@ function filterHintsVimperator(fstr, reflow = false) {
active = active.filter(hint => hint.name.startsWith(run.str))
} else {
// By text
active = active.filter(hint => vimpHelper.matchHint(hint.filterData, run.str))
active = active.filter(hint =>
vimpHelper.matchHint(hint.filterData, run.str),
)
if (reflow) rename(active)
}
@ -848,7 +918,7 @@ export function hintables(selectors = DOM.HINTTAGS_selectors, withjs = false) {
elems = [...elemSet]
}
elems = elems.filter(DOM.isVisible)
return changeHintablesToLargestChild(elems);
return changeHintablesToLargestChild(elems)
}
/**
@ -858,21 +928,24 @@ export function hintables(selectors = DOM.HINTTAGS_selectors, withjs = false) {
*/
function changeHintablesToLargestChild(elements: Element[]): Element[] {
elements.forEach((element, index) => {
if (element.childNodes.length === 0) return;
let largestChild: Element;
if (element.childNodes.length === 0) return
let largestChild: Element
// Find largest child.
element.childNodes.forEach((c) => {
const currentChild = (c as Element);
if (!largestChild || isElementLargerThan(currentChild, largestChild)) {
largestChild = currentChild;
element.childNodes.forEach(c => {
const currentChild = c as Element
if (
!largestChild ||
isElementLargerThan(currentChild, largestChild)
) {
largestChild = currentChild
}
})
// Change element if child is larger
if (isElementLargerThan(largestChild, element)) {
elements[index] = largestChild;
elements[index] = largestChild
}
})
return elements;
return elements
}
/**
@ -881,13 +954,13 @@ function changeHintablesToLargestChild(elements: Element[]): Element[] {
*/
function isElementLargerThan(e1: Element, e2: Element): boolean {
if (typeof e1.getBoundingClientRect !== "function") {
return false;
return false
} else if (typeof e2.getBoundingClientRect !== "function") {
return true;
return true
}
const e1BR = e1.getBoundingClientRect();
const e2BR = e2.getBoundingClientRect();
return e1BR.height > e2BR.height && e1BR.width > e2BR.width;
const e1BR = e1.getBoundingClientRect()
const e2BR = e2.getBoundingClientRect()
return e1BR.height > e2BR.height && e1BR.width > e2BR.width
}
/** Returns elements that point to a saveable resource
@ -924,7 +997,7 @@ export function hintByText(match: string|RegExp) {
} else {
return text.toUpperCase().includes(match.toUpperCase())
}
}
},
])
}
@ -1008,9 +1081,16 @@ function focusRightHint() {
/** @hidden */
export function parser(keys: KeyboardEvent[]) {
const parsed = keyseq.parse(keys,
keyseq.mapstrMapToKeyMap(new Map((Object.entries(config.get("hintmaps")) as any)
.filter(([key, value]) => value != ""))))
const parsed = keyseq.parse(
keys,
keyseq.mapstrMapToKeyMap(
new Map(
(Object.entries(config.get("hintmaps")) as any).filter(
([key, value]) => value != "",
),
),
),
)
if (parsed.isMatch === true) {
return parsed
}
@ -1018,7 +1098,10 @@ export function parser(keys: KeyboardEvent[]) {
const simplekeys = keys.filter(key => !keyseq.hasModifiers(key))
let exstr
if (simplekeys.length > 1) {
exstr = simplekeys.reduce((acc, key) => `hint.pushKey ${key.key};`, "composite ")
exstr = simplekeys.reduce(
(acc, key) => `hint.pushKey ${key.key};`,
"composite ",
)
} else if (simplekeys.length === 1) {
exstr = `hint.pushKeyCodePoint ${simplekeys[0].key.codePointAt(0)}`
} else {
@ -1042,5 +1125,5 @@ export function getHintCommands() {
pushSpace,
pushKeyCodePoint,
popKey,
};
};
}
}

View file

@ -257,7 +257,7 @@ export function fillinput(selector: string, ...content: string[]) {
let inputToFill = document.querySelector(selector)
if (!inputToFill) inputToFill = DOM.getLastUsedInput()
if ("value" in inputToFill) {
; (inputToFill as HTMLInputElement).value = content.join(" ")
(inputToFill as HTMLInputElement).value = content.join(" ")
} else {
inputToFill.textContent = content.join(" ")
}
@ -336,7 +336,7 @@ export async function editor() {
let line = 0
let col = 0
wrap_input((t, start, end) => {
; [text, line, col] = getLineAndColNumber(t, start, end)
[text, line, col] = getLineAndColNumber(t, start, end)
return [null, null, null]
})(elem)
const file = (await Native.temp(text, document.location.hostname)).content
@ -444,16 +444,7 @@ export async function loadtheme(themename: string) {
if (!(await Native.nativegate("0.1.9"))) return
const separator = (await browserBg.runtime.getPlatformInfo()).os === "win" ? "\\" : "/"
// remove the "tridactylrc" bit so that we're left with the directory
const path =
(await Native.getrcpath())
.split(separator)
.slice(0, -1)
.join(separator) +
separator +
"themes" +
separator +
themename +
".css"
const path = (await Native.getrcpath()).split(separator).slice(0, -1).join(separator) + separator + "themes" + separator + themename + ".css"
const file = await Native.read(path)
if (file.code !== 0) throw new Error("Couldn't read theme " + path)
return set("customthemes." + themename, file.content)
@ -1028,7 +1019,7 @@ export async function scrollpx(a: number, b: number) {
*/
//#content
export function scrollto(a: number | string, b: number | "x" | "y" = "y") {
if (typeof a === "string" && a.match(/c$/i)) {
if (typeof a === "string" && /c$/i.exec(a)) {
a = (Number(a.replace(/c$/, "")) * 100) / (2 * Math.PI)
}
a = Number(a)
@ -1208,10 +1199,10 @@ export async function open(...urlarr: string[]) {
const url = urlarr.join(" ")
// Setting window.location to about:blank results in a page we can't access, tabs.update works.
if (!ABOUT_WHITELIST.includes(url) && url.match(/^(about|file):.*/)) {
if (!ABOUT_WHITELIST.includes(url) && /^(about|file):.*/.exec(url)) {
// Open URLs that firefox won't let us by running `firefox <URL>` on the command line
return nativeopen(url)
} else if (url.match(/^javascript:/)) {
} else if (/^javascript:/.exec(url)) {
const bookmarklet = url.replace(/^javascript:/, "")
document.body.append(
html`
@ -1245,7 +1236,7 @@ export async function bmarks(opt: string, ...urlarr: string[]) {
export async function open_quiet(...urlarr: string[]) {
const url = urlarr.join(" ")
if (!ABOUT_WHITELIST.includes(url) && url.match(/^(about|file):.*/)) {
if (!ABOUT_WHITELIST.includes(url) && /^(about|file):.*/.exec(url)) {
return nativeopen(url)
}
@ -2143,7 +2134,7 @@ export async function tabopen(...addressarr: string[]) {
const query = await argParse(addressarr)
const address = query.join(" ")
if (!ABOUT_WHITELIST.includes(address) && address.match(/^(about|file):.*/)) {
if (!ABOUT_WHITELIST.includes(address) && /^(about|file):.*/.exec(address)) {
return nativeopen(address)
}
@ -2186,34 +2177,35 @@ export async function tabopen(...addressarr: string[]) {
export function tabqueue(...addresses: string[]) {
// addresses[0] is a string when called with `tabopen a b c` but an array
// when called from `composite hint -qpipe a href | tabqueue`.
addresses = addresses.flat(Infinity);
addresses = addresses.flat(Infinity)
if (addresses.length === 0) {
return Promise.resolve();
return Promise.resolve()
}
return tabopen("-b", addresses[0]).then(tab =>
return tabopen("-b", addresses[0]).then(
tab =>
new Promise((resolve, reject) => {
function openNextTab(activeInfo) {
if (activeInfo.tabId === tab.id) {
resolve(tabqueue(...(addresses.slice(1))));
removeTabqueueListeners(tab.id);
resolve(tabqueue(...addresses.slice(1)))
removeTabqueueListeners(tab.id)
}
}
function removeTabqueueListeners(tabId) {
if (tabId === tab.id) {
browser.tabs.onActivated.removeListener(openNextTab);
browser.tabs.onRemoved.removeListener(removeTabqueueListeners);
browser.tabs.onActivated.removeListener(openNextTab)
browser.tabs.onRemoved.removeListener(removeTabqueueListeners)
// FIXME: This should actually be `reject(tab)` to
// interrupt pipelines, but this results in an impossible
// to debug `Error: undefined` message being printed on the
// command line. So we silently resolve the promise and
// hope for the best.
resolve(tab);
resolve(tab)
}
}
browser.tabs.onActivated.addListener(openNextTab);
browser.tabs.onRemoved.addListener(removeTabqueueListeners);
})
);
browser.tabs.onActivated.addListener(openNextTab)
browser.tabs.onRemoved.addListener(removeTabqueueListeners)
}),
)
}
/** Resolve a tab index to the tab id of the corresponding tab in this window.
@ -2246,10 +2238,12 @@ async function idFromIndex(index?: number | "%" | "#" | string): Promise<number>
index = (index - 1).mod((await browser.tabs.query({ currentWindow: true })).length) + 1
// Return id of tab with that index.
return (await browser.tabs.query({
return (
await browser.tabs.query({
currentWindow: true,
index: index - 1,
}))[0].id
})
)[0].id
} else {
return activeTabId()
}
@ -2336,7 +2330,7 @@ export async function tabclose(...indexes: string[]) {
*/
//#background
export async function tabcloseallto(side: string) {
if (!(["left", "right"].includes(side))) {
if (!["left", "right"].includes(side)) {
throw "side argument must be left or right"
}
const tabs = await browser.tabs.query({
@ -2585,7 +2579,7 @@ export async function winopen(...args: string[]) {
}
const address = args.join(" ")
if (!ABOUT_WHITELIST.includes(address) && address.match(/^(about|file):.*/)) {
if (!ABOUT_WHITELIST.includes(address) && /^(about|file):.*/.exec(address)) {
return nativeopen(firefoxArgs, address)
}
@ -2626,13 +2620,7 @@ export async function qall() {
//#background
export async function containerclose(name: string) {
const containerId = await Container.getId(name)
return browser.tabs.query({ cookieStoreId: containerId }).then(tabs => {
return browser.tabs.remove(
tabs.map(tab => {
return tab.id
}),
)
})
return browser.tabs.query({ cookieStoreId: containerId }).then(tabs => browser.tabs.remove(tabs.map(tab => tab.id)))
}
/** Creates a new container. Note that container names must be unique and that the checks are case-insensitive.
@ -2679,7 +2667,7 @@ export async function containerupdate(name: string, uname: string, ucolor: strin
logger.debug("containerupdate parameters: " + name + ", " + uname + ", " + ucolor + ", " + uicon)
const containerId = await Container.fuzzyMatch(name)
const containerObj = Container.fromString(uname, ucolor, uicon)
await Container.update(containerId, containerObj)
Container.update(containerId, containerObj)
}
/** Shows a list of the current containers in Firefox's native JSON viewer in the current tab.
@ -2692,11 +2680,7 @@ export async function viewcontainers() {
// # and white space don't agree with FF's JSON viewer.
// Probably other symbols too.
const containers = await browserBg.contextualIdentities.query({}) // Can't access src/lib/containers.ts from a content script.
window.location.href =
"data:application/json," +
JSON.stringify(containers)
.replace(/#/g, "%23")
.replace(/ /g, "%20")
window.location.href = "data:application/json," + JSON.stringify(containers).replace(/#/g, "%23").replace(/ /g, "%20")
}
/** Opens the current tab in another container.
@ -2771,12 +2755,8 @@ async function getnexttabs(tabid: number, n?: number) {
const tabs: browser.tabs.Tab[] = await browser.tabs.query({
currentWindow: true,
})
const indexFilter = ((tab: browser.tabs.Tab) => {
return curIndex <= tab.index && (n ? tab.index < curIndex + Number(n) : true)
}).bind(n)
return tabs.filter(indexFilter).map((tab: browser.tabs.Tab) => {
return tab.id
})
const indexFilter = ((tab: browser.tabs.Tab) => curIndex <= tab.index && (n ? tab.index < curIndex + Number(n) : true)).bind(n)
return tabs.filter(indexFilter).map((tab: browser.tabs.Tab) => tab.id)
}
// Moderately slow; should load in results as they arrive, perhaps
@ -2849,8 +2829,7 @@ export async function composite(...cmds: string[]) {
// For each pipeline, wait for previous pipeline to finish, then
// execute each cmd in pipeline in order, passing the result of the
// previous cmd as the last argument to the next command.
.reduce(
async (prev_pipeline, cmd) => {
.reduce(async (prev_pipeline, cmd) => {
await prev_pipeline
const cmds = cmd.split("|")
@ -2870,9 +2849,7 @@ export async function composite(...cmds: string[]) {
const [fn, args] = excmd_parser.parser(cmd, ALL_EXCMDS)
return fn.call({}, ...args, await pipedValue)
}, first_value)
},
null as any,
)
}, null as any)
)
} catch (e) {
logger.error(e)
@ -3122,7 +3099,7 @@ export async function tab(index: number | "#") {
//#background
export async function taball(id: string) {
const windows = (await browser.windows.getAll()).map(w => w.id).sort((a, b) => a - b)
if (id === null || id === undefined || !id.match(/\d+\.\d+/)) {
if (id === null || id === undefined || /\d+\.\d+/.exec(id)) {
const tab = await activeTab()
const prevId = id
id = windows.indexOf(tab.windowId) + "." + (tab.index + 1)
@ -3590,7 +3567,7 @@ export async function sanitise(...args: string[]) {
// If the -t flag has been given and there is an arg after it
if (flagpos > -1) {
if (flagpos < args.length - 1) {
const match = args[flagpos + 1].match("^([0-9])+(m|h|d|w)$")
const match = /^([0-9])+(m|h|d|w)$/.exec(args[flagpos + 1])
// If the arg of the flag matches Pentadactyl's sanitisetimespan format
if (match !== null && match.length === 3) {
// Compute the timespan in milliseconds and get a Date object
@ -3638,7 +3615,7 @@ export async function sanitise(...args: string[]) {
*/
}
if (args.find(x => x === "all") !== undefined) {
for (const attr in dts) dts[attr] = true
for (const attr in dts) if (Object.prototype.hasOwnProperty.call(dts, attr)) dts[attr] = true
} else {
// We bother checking if dts[x] is false because
// browser.browsingData.remove() is very strict on the format of the
@ -3722,31 +3699,14 @@ export function get(...keys: string[]) {
export function viewconfig(key?: string) {
// # and white space don't agree with FF's JSON viewer.
// Probably other symbols too.
if (!key)
window.location.href =
"data:application/json," +
JSON.stringify(config.get())
.replace(/#/g, "%23")
.replace(/ /g, "%20")
if (!key) window.location.href = "data:application/json," + JSON.stringify(config.get()).replace(/#/g, "%23").replace(/ /g, "%20")
// I think JS casts key to the string "undefined" if it isn't given.
else if (key === "--default") {
window.location.href =
"data:application/json," +
JSON.stringify(config.o(new config.default_config()))
.replace(/#/g, "%23")
.replace(/ /g, "%20")
window.location.href = "data:application/json," + JSON.stringify(config.o(new config.default_config())).replace(/#/g, "%23").replace(/ /g, "%20")
} else if (key === "--user") {
window.location.href =
"data:application/json," +
JSON.stringify(config.USERCONFIG)
.replace(/#/g, "%23")
.replace(/ /g, "%20")
window.location.href = "data:application/json," + JSON.stringify(config.USERCONFIG).replace(/#/g, "%23").replace(/ /g, "%20")
}
window.location.href =
"data:application/json," +
JSON.stringify(config.getDynamic(key))
.replace(/#/g, "%23")
.replace(/ /g, "%20")
window.location.href = "data:application/json," + JSON.stringify(config.getDynamic(key)).replace(/#/g, "%23").replace(/ /g, "%20")
// base 64 encoding is a cleverer way of doing this, but it doesn't seem to work for the whole config.
//window.location.href = "data:application/json;base64," + btoa(JSON.stringify(config.get()))
}
@ -4030,12 +3990,7 @@ export async function hint(option?: string, selectors?: string, ...rest: string[
break
case "-pipe":
selectHints = hinting.pipe(
selectors,
elem => elem[rest.join(" ")],
rapid,
jshints,
)
selectHints = hinting.pipe(selectors, elem => elem[rest.join(" ")], rapid, jshints)
break
case "-i":
@ -4497,8 +4452,7 @@ async function js_helper(str: string[]) {
done = true
break
}
if (!done)
str.shift()
if (!done) str.shift()
}
if (doSource) {
@ -4509,8 +4463,7 @@ async function js_helper(str: string[]) {
sourcePath = [...rcPath, sourcePath].join(sep)
}
const file = await Native.read(sourcePath)
if (file.code !== 0)
throw new Error("Couldn't read js file " + sourcePath)
if (file.code !== 0) throw new Error("Couldn't read js file " + sourcePath)
jsContent = file.content
} else {
jsContent = str.join(" ")

View file

@ -180,9 +180,7 @@ export class AutoContain implements IAutoContain {
}, 2000)
}
getCancelledRequest = (tabId: number): ICancelledRequest => {
return this.cancelledRequests[tabId]
}
getCancelledRequest = (tabId: number): ICancelledRequest => this.cancelledRequests[tabId]
// Clear the cancelled requests.
clearCancelledRequests = (tabId: number): void => {
@ -311,7 +309,5 @@ export class AutoContain implements IAutoContain {
// Parses autocontain directives and returns valid cookieStoreIds or errors.
getAuconForDetails = async (
details: browser.webRequest.IDetails,
): Promise<string> => {
return this.getAuconForUrl(details.url)
}
): Promise<string> => this.getAuconForUrl(details.url)
}

View file

@ -93,16 +93,12 @@ export function getCommandlineFns(cmdline_state) {
/**
* Selects the next history line.
*/
"next_history": () => {
return cmdline_state.history(1)
},
"next_history": () => cmdline_state.history(1),
/**
* Selects the prev history line.
*/
"prev_history": () => {
return cmdline_state.history(-1)
},
"prev_history": () => cmdline_state.history(-1),
/**
* Execute the content of the command line and hide it.
**/

View file

@ -26,8 +26,8 @@ const removeNull = R.when(
R.is(Object),
R.pipe(
R.reject(val => val === null),
R.map(a => removeNull(a))
)
R.map(a => removeNull(a)),
),
)
/** @hidden */
@ -276,7 +276,7 @@ export class default_config {
";y": "hint -y",
";p": "hint -p",
";h": "hint -h",
"v": "hint -h", // Easiest way of entering visual mode for now. Expect this bind to change
v: "hint -h", // Easiest way of entering visual mode for now. Expect this bind to change
";P": "hint -P",
";r": "hint -r",
";s": "hint -s",
@ -339,23 +339,32 @@ export class default_config {
}
vmaps = {
"<Escape>": "composite js document.getSelection().empty(); mode normal; hidecmdline",
"<C-[>": "composite js document.getSelection().empty(); mode normal ; hidecmdline",
"y": "composite js document.getSelection().toString() | clipboard yank",
"s": "composite js document.getSelection().toString() | fillcmdline open search",
"S": "composite js document.getSelection().toString() | fillcmdline tabopen search",
"l": 'js document.getSelection().modify("extend","forward","character")',
"h": 'js document.getSelection().modify("extend","backward","character")',
"e": 'js document.getSelection().modify("extend","forward","word")',
"w": 'js document.getSelection().modify("extend","forward","word"); document.getSelection().modify("extend","forward","character")',
"b": 'js document.getSelection().modify("extend","backward","character"); document.getSelection().modify("extend","backward","word"); document.getSelection().modify("extend","forward","character")',
"j": 'js document.getSelection().modify("extend","forward","line")',
"<Escape>":
"composite js document.getSelection().empty(); mode normal; hidecmdline",
"<C-[>":
"composite js document.getSelection().empty(); mode normal ; hidecmdline",
y: "composite js document.getSelection().toString() | clipboard yank",
s:
"composite js document.getSelection().toString() | fillcmdline open search",
S:
"composite js document.getSelection().toString() | fillcmdline tabopen search",
l: 'js document.getSelection().modify("extend","forward","character")',
h: 'js document.getSelection().modify("extend","backward","character")',
e: 'js document.getSelection().modify("extend","forward","word")',
w:
'js document.getSelection().modify("extend","forward","word"); document.getSelection().modify("extend","forward","character")',
b:
'js document.getSelection().modify("extend","backward","character"); document.getSelection().modify("extend","backward","word"); document.getSelection().modify("extend","forward","character")',
j: 'js document.getSelection().modify("extend","forward","line")',
// "j": 'js document.getSelection().modify("extend","forward","paragraph")', // not implemented in Firefox
"k": 'js document.getSelection().modify("extend","backward","line")',
"$": 'js document.getSelection().modify("extend","forward","lineboundary")',
"0": 'js document.getSelection().modify("extend","backward","lineboundary")',
"=": "js let n = document.getSelection().anchorNode.parentNode; let s = window.getSelection(); let r = document.createRange(); s.removeAllRanges(); r.selectNodeContents(n); s.addRange(r)",
"o": "js tri.visual.reverseSelection(document.getSelection())",
k: 'js document.getSelection().modify("extend","backward","line")',
$:
'js document.getSelection().modify("extend","forward","lineboundary")',
"0":
'js document.getSelection().modify("extend","backward","lineboundary")',
"=":
"js let n = document.getSelection().anchorNode.parentNode; let s = window.getSelection(); let r = document.createRange(); s.removeAllRanges(); r.selectNodeContents(n); s.addRange(r)",
o: "js tri.visual.reverseSelection(document.getSelection())",
"🕷🕷INHERITS🕷🕷": "nmaps",
}
@ -572,14 +581,15 @@ export class default_config {
mkt: "mktridactylrc",
"mkt!": "mktridactylrc -f",
"mktridactylrc!": "mktridactylrc -f",
mpvsafe: "js -p tri.excmds.shellescape(JS_ARG).then(url => tri.excmds.exclaim_quiet('mpv ' + url))",
mpvsafe:
"js -p tri.excmds.shellescape(JS_ARG).then(url => tri.excmds.exclaim_quiet('mpv ' + url))",
exto: "extoptions",
extpreferences: "extoptions",
extp: "extpreferences",
prefset: "setpref",
prefremove: "removepref",
tabclosealltoright: "tabcloseallto right",
tabclosealltoleft: "tabcloseallto left"
tabclosealltoleft: "tabcloseallto left",
}
/**
@ -1059,7 +1069,10 @@ function getDeepProperty(obj, target: string[]) {
if (obj["🕷🕷INHERITS🕷🕷"] === undefined) {
return getDeepProperty(obj[target[0]], target.slice(1))
} else {
return getDeepProperty(mergeDeepCull(get(obj["🕷🕷INHERITS🕷🕷"]), obj)[target[0]], target.slice(1))
return getDeepProperty(
mergeDeepCull(get(obj["🕷🕷INHERITS🕷🕷"]), obj)[target[0]],
target.slice(1),
)
}
} else {
if (obj === undefined || obj === null) return obj
@ -1102,7 +1115,11 @@ export function mergeDeep(o1, o2) {
.filter(
key => typeof o1[key] === "object" && typeof o2[key] === "object",
)
.forEach(key => r[key] == null ? null : Object.assign(r[key], mergeDeep(o1[key], o2[key])))
.forEach(key =>
r[key] == null
? null
: Object.assign(r[key], mergeDeep(o1[key], o2[key])),
)
return r
}
@ -1134,8 +1151,7 @@ export function getURL(url: string, target: string[]) {
(conf.subconfigs[k2].priority || 10),
)
// Merge their corresponding value if they're objects, otherwise return the last value
.reduce(
(acc, curKey) => {
.reduce((acc, curKey) => {
const curVal = getDeepProperty(
conf.subconfigs[curKey],
target,
@ -1143,9 +1159,7 @@ export function getURL(url: string, target: string[]) {
if (acc instanceof Object && curVal instanceof Object)
return mergeDeep(acc, curVal)
return curVal
},
undefined as any,
)
}, undefined as any)
)
}
const user = _getURL(USERCONFIG, url, target)
@ -1266,7 +1280,11 @@ export async function set(...args) {
setDeepProperty(USERCONFIG, value, target)
if (target.length === 1 && target[0] === "storageloc" && previousValue !== value) {
if (
target.length === 1 &&
target[0] === "storageloc" &&
previousValue !== value
) {
// ensure storageloc is saved locally before switching
await save(previousValue)
}
@ -1381,7 +1399,7 @@ export async function update() {
set("configversion", "1.2")
}
case "1.2": {
; ["ignoremaps", "inputmaps", "imaps", "nmaps"]
["ignoremaps", "inputmaps", "imaps", "nmaps"]
.map(mapname => [
mapname,
getDeepProperty(USERCONFIG, [mapname]),
@ -1413,7 +1431,7 @@ export async function update() {
set("configversion", "1.3")
}
case "1.3": {
; [
[
"priority",
"hintdelay",
"scrollduration",
@ -1426,7 +1444,7 @@ export async function update() {
set("configversion", "1.4")
}
case "1.4": {
; (getDeepProperty(USERCONFIG, ["noiframeon"]) || []).forEach(
(getDeepProperty(USERCONFIG, ["noiframeon"]) || []).forEach(
site => {
setURL(site, "noiframe", "true")
},
@ -1444,7 +1462,7 @@ export async function update() {
mapObj["<Space>"] = mapObj[" "]
delete mapObj[" "]
}
; [
[
"<A- >",
"<C- >",
"<M- >",
@ -1464,9 +1482,13 @@ export async function update() {
})
return mapObj
}
; ["nmaps", "exmaps", "imaps", "inputmaps", "ignoremaps"].forEach(
settingName => updateAll([settingName], updateSetting),
)
;[
"nmaps",
"exmaps",
"imaps",
"inputmaps",
"ignoremaps",
].forEach(settingName => updateAll([settingName], updateSetting))
set("configversion", "1.7")
}
case "1.7": {
@ -1487,9 +1509,15 @@ export async function update() {
return val
}, mapObj)
}
; ["nmaps", "exmaps", "imaps", "inputmaps", "ignoremaps", "hintmaps", "vmaps"].forEach(
settingName => updateAll([settingName], updateSetting),
)
;[
"nmaps",
"exmaps",
"imaps",
"inputmaps",
"ignoremaps",
"hintmaps",
"vmaps",
].forEach(settingName => updateAll([settingName], updateSetting))
set("configversion", "1.9")
updated = true // NB: when adding a new updater, move this line to the end of it
}
@ -1516,8 +1544,7 @@ async function init() {
}
const configUpdated = await update()
if (configUpdated)
await save()
if (configUpdated) await save()
INITIALISED = true
for (const waiter of WAITERS) {
@ -1606,9 +1633,7 @@ export function parseConfig(): string {
const ftdetect = `" For syntax highlighting see https://github.com/tridactyl/vim-tridactyl\n" vim: set filetype=tridactyl`
return `${s.general}${s.binds}${s.subconfigs}${s.aliases}${s.aucmds}${
s.aucons
}${s.logging}${s.nulls}${ftdetect}`
return `${s.general}${s.binds}${s.subconfigs}${s.aliases}${s.aucmds}${s.aucons}${s.logging}${s.nulls}${ftdetect}`
}
const parseConfigHelper = (pconf, parseobj, prefix = []) => {
@ -1617,10 +1642,13 @@ const parseConfigHelper = (pconf, parseobj, prefix= []) => {
if (prefix[0] === "subconfigs") {
prefix.shift()
const pattern = prefix.shift()
parseobj.subconfigs.push(`seturl ${pattern} ${[...prefix, i].join(".")} ${pconf[i]}`)
parseobj.subconfigs.push(
`seturl ${pattern} ${[...prefix, i].join(".")} ${pconf[i]}`,
)
} else {
parseobj.conf.push(
`set ${[...prefix, i].join(".")} ${pconf[i]}`)
`set ${[...prefix, i].join(".")} ${pconf[i]}`,
)
}
} else if (pconf[i] === null) {
parseobj.nulls.push(`setnull ${[...prefix, i].join(".")}`)
@ -1710,24 +1738,19 @@ browser.storage.onChanged.addListener((changes, areaname) => {
const unsetKeys = Object.keys(old).filter(
k =>
newValue[k] === undefined &&
JSON.stringify(old[k]) !==
JSON.stringify(DEFAULTS[k]),
JSON.stringify(old[k]) !== JSON.stringify(DEFAULTS[k]),
)
// A key has changed if it is defined in USERCONFIG and its value in USERCONFIG is different from the one in `changes` or if the value in defaultConf is different from the one in `changes`
const changedKeys = Object.keys(
newValue,
).filter(
const changedKeys = Object.keys(newValue).filter(
k =>
JSON.stringify(
old[k] !== undefined
? old[k]
: DEFAULTS[k],
old[k] !== undefined ? old[k] : DEFAULTS[k],
) !== JSON.stringify(newValue[k]),
)
// TODO: this should be a deep comparison but this is better than nothing
changedKeys.forEach(key => USERCONFIG[key] = newValue[key])
changedKeys.forEach(key => (USERCONFIG[key] = newValue[key]))
unsetKeys.forEach(key => delete USERCONFIG[key])
// Trigger listeners

View file

@ -80,7 +80,7 @@ export async function remove(name: string) {
@param color the new color of the container
@param icon the new icon of the container
*/
export async function update(
export function update(
containerId: string,
updateObj: {
name: string
@ -122,9 +122,9 @@ export async function exists(cname: string): Promise<boolean> {
let exists = false
try {
const containers = await getAll()
const res = containers.filter(c => {
return c.name.toLowerCase() === cname.toLowerCase()
})
const res = containers.filter(
c => c.name.toLowerCase() === cname.toLowerCase(),
)
if (res.length > 0) {
exists = true
}

View file

@ -120,12 +120,7 @@ export function mouseEvent(
}
export function elementsWithText() {
return getElemsBySelector("*", [
isVisible,
hint => {
return hint.textContent !== ""
},
])
return getElemsBySelector("*", [isVisible, hint => hint.textContent !== ""])
}
/** Iterable of elements that match xpath.
@ -306,7 +301,7 @@ export function getAllDocumentFrames(doc = document) {
export function getSelector(e: HTMLElement) {
function uniqueSelector(e: HTMLElement) {
// Only matching alphanumeric selectors because others chars might have special meaning in CSS
if (e.id && e.id.match("^[a-zA-Z0-9]+$")) return "#" + e.id
if (e.id && /^[a-zA-Z0-9]+$/.exec(e.id)) return "#" + e.id
// If we reached the top of the document
if (!e.parentElement) return "HTML"
// Compute the position of the element
@ -539,7 +534,10 @@ function onPageFocus(elem: HTMLElement, args: any[]): boolean {
async function setInput(el) {
const tab = await activeTabId()
// store maximum of 10 elements to stop this getting bonkers huge
const arr = (await State.getAsync("prevInputs")).concat({ tab, inputId: el.id })
const arr = (await State.getAsync("prevInputs")).concat({
tab,
inputId: el.id,
})
state.prevInputs = arr.slice(Math.max(arr.length - 10, 0))
}

View file

@ -164,36 +164,30 @@ export const transpose_words = wrap_input(
* Behaves like readline's [upcase_word](http://web.mit.edu/gnu/doc/html/rlman_1.html#SEC14). Makes the word the caret is in uppercase.
**/
export const upcase_word = wrap_input(
needs_text((text, selectionStart, selectionEnd) => {
return applyWord(text, selectionStart, selectionEnd, word =>
needs_text((text, selectionStart, selectionEnd) => applyWord(text, selectionStart, selectionEnd, word =>
word.toUpperCase(),
)
}),
)),
)
/**
* Behaves like readline's [downcase_word](http://web.mit.edu/gnu/doc/html/rlman_1.html#SEC14). Makes the word the caret is in lowercase.
**/
export const downcase_word = wrap_input(
needs_text((text, selectionStart, selectionEnd) => {
return applyWord(text, selectionStart, selectionEnd, word =>
needs_text((text, selectionStart, selectionEnd) => applyWord(text, selectionStart, selectionEnd, word =>
word.toLowerCase(),
)
}),
)),
)
/**
* Behaves like readline's [capitalize_word](http://web.mit.edu/gnu/doc/html/rlman_1.html#SEC14). Makes the initial character of the word the caret is in uppercase.
**/
export const capitalize_word = wrap_input(
needs_text((text, selectionStart, selectionEnd) => {
return applyWord(
needs_text((text, selectionStart, selectionEnd) => applyWord(
text,
selectionStart,
selectionEnd,
word => word[0].toUpperCase() + word.substring(1),
)
}),
)),
)
/**
@ -339,17 +333,13 @@ export const end_of_line = wrap_input(
/**
* Behaves like readline's [forward_char](http://web.mit.edu/gnu/doc/html/rlman_1.html#SEC12). Moves the caret one character to the right.
**/
export const forward_char = wrap_input((text, selectionStart, selectionEnd) => {
return [null, selectionStart + 1, null]
})
export const forward_char = wrap_input((text, selectionStart, selectionEnd) => [null, selectionStart + 1, null])
/**
* Behaves like readline's [backward_char](http://web.mit.edu/gnu/doc/html/rlman_1.html#SEC12). Moves the caret one character to the left.
**/
export const backward_char = wrap_input(
(text, selectionStart, selectionEnd) => {
return [null, selectionStart - 1, null]
},
(text, selectionStart, selectionEnd) => [null, selectionStart - 1, null],
)
/**
@ -383,21 +373,17 @@ export const backward_word = wrap_input(
* Insert text in the current input.
**/
export const insert_text = wrap_input(
(text, selectionStart, selectionEnd, arg) => {
return [
(text, selectionStart, selectionEnd, arg) => [
text.slice(0, selectionStart) + arg + text.slice(selectionEnd),
selectionStart + arg.length,
null,
]
},
],
)
export const rot13 = wrap_input(
(text, selectionStart, selectionEnd) => {
return [
(text, selectionStart, selectionEnd) => [
rot13_helper(text.slice(0, selectionStart) + text.slice(selectionEnd)),
selectionStart,
null,
]
},
],
)

View file

@ -1,4 +1,3 @@
// We have a single dependency on config: getting the value of the WORDPATTERN setting
// Perhaps we could find a way to get rid of it?
import * as config from "@src/lib/config"
@ -165,7 +164,11 @@ export function needs_text(fn: editor_function, arg?: any): editor_function {
/**
* Returns line and column number.
*/
export function getLineAndColNumber(text: string, start: number, end: number): [string, number, number] {
export function getLineAndColNumber(
text: string,
start: number,
end: number,
): [string, number, number] {
const lines = text.split("\n")
let totalChars = 0
for (let i = 0; i < lines.length; ++i) {
@ -188,21 +191,18 @@ export function getWordBoundaries(
): [number, number] {
if (position < 0 || position > text.length)
throw new Error(
`getWordBoundaries: position (${position}) should be within text ("${text}") boundaries (0, ${
text.length
})`,
`getWordBoundaries: position (${position}) should be within text ("${text}") boundaries (0, ${text.length})`,
)
const pattern = new RegExp(config.get("wordpattern"), "g")
let boundary1 = position < text.length ? position : text.length - 1
const direction = before ? -1 : 1
// if the caret is not in a word, try to find the word before or after it
// For `before`, we should check the char before the caret
if (before && boundary1 > 0)
boundary1 -= 1
if (before && boundary1 > 0) boundary1 -= 1
while (
boundary1 >= 0 &&
boundary1 < text.length &&
!text[boundary1].match(pattern)
!pattern.exec(text[boundary1])
) {
boundary1 += direction
}
@ -214,7 +214,7 @@ export function getWordBoundaries(
while (
boundary1 >= 0 &&
boundary1 < text.length &&
!text[boundary1].match(pattern)
!pattern.exec(text[boundary1])
) {
boundary1 -= direction
}
@ -222,12 +222,10 @@ export function getWordBoundaries(
if (boundary1 < 0) boundary1 = 0
else if (boundary1 >= text.length) boundary1 = text.length - 1
if (!text[boundary1].match(pattern)) {
if (!pattern.exec(text[boundary1])) {
// there is no word in text
throw new Error(
`getWordBoundaries: no characters matching wordpattern (${
pattern.source
}) in text (${text})`,
`getWordBoundaries: no characters matching wordpattern (${pattern.source}) in text (${text})`,
)
}
@ -235,7 +233,7 @@ export function getWordBoundaries(
while (
boundary1 >= 0 &&
boundary1 < text.length &&
!!text[boundary1].match(pattern)
!!pattern.exec(text[boundary1])
) {
boundary1 += direction
}
@ -247,7 +245,7 @@ export function getWordBoundaries(
while (
boundary2 >= 0 &&
boundary2 < text.length &&
!!text[boundary2].match(pattern)
!!pattern.exec(text[boundary2])
) {
boundary2 -= direction
}
@ -268,10 +266,10 @@ export function wordAfterPos(text: string, position: number) {
throw new Error(`wordAfterPos: position (${position}) is less that 0`)
const pattern = new RegExp(config.get("wordpattern"), "g")
// move position out of the current word
while (position < text.length && !!text[position].match(pattern))
while (position < text.length && !!pattern.exec(text[position]))
position += 1
// try to find characters that match wordpattern
while (position < text.length && !text[position].match(pattern))
while (position < text.length && !pattern.exec(text[position]))
position += 1
if (position >= text.length) return -1
return position
@ -289,8 +287,8 @@ export const rot13_helper = (s: string, n: number = 13): string => {
export const charesar = (c: string, n: number = 13): string => {
const cn = c.charCodeAt(0)
if (cn >= 65 && cn <= 90)
return String.fromCharCode((((cn - 65) + n) % 26) + 65)
return String.fromCharCode(((cn - 65 + n) % 26) + 65)
if (cn >= 97 && cn <= 122)
return String.fromCharCode((((cn - 97) + n) % 26) + 97)
return String.fromCharCode(((cn - 97 + n) % 26) + 97)
return c
}

View file

@ -1,10 +1,10 @@
;(function(window) {
(function(window) {
"use strict"
// test for es6 support of needed functionality
try {
// spread operator and template strings support
;(function testSpreadOpAndTemplate() {
(function testSpreadOpAndTemplate() {
const tag = function tag(strings, ...values) {
return
}
@ -311,14 +311,13 @@
// use insertBefore() instead of replaceChild() so that the node Iterator
// doesn't think the new tag should be the next node
node.parentNode.insertBefore(tag, node)
}
// special case for script tags:
// using innerHTML with a string that contains a script tag causes the script
// tag to not be executed when added to the DOM. We'll need to create a script
// tag and append its contents which will make it execute correctly.
// @see http://stackoverflow.com/questions/1197575/can-scripts-be-inserted-with-innerhtml
else if (node.nodeName === "SCRIPT") {
} else if (node.nodeName === "SCRIPT") {
const script = document.createElement("script")
tag = script
@ -420,12 +419,11 @@
) {
substitutionValue =
'"' + substitutionValue + '"'
}
// contextual auto-escaping:
// if the attribute is a uri attribute then we need to uri encode it and
// remove bad protocols
else if (
} else if (
URI_ATTRIBUTES.indexOf(name) !== -1 ||
CUSTOM_URI_ATTRIBUTES_REGEX.test(name)
) {
@ -438,10 +436,9 @@
substitutionValue = encodeURIComponent(
substitutionValue,
)
}
// entity encode if value is part of the URL
else {
} else {
substitutionValue = encodeURI(
encodeURIEntities(
substitutionValue,
@ -479,12 +476,11 @@
}
}
}
}
// contextual auto-escaping:
// HTML encode attribute value if it is not a URL or URI to prevent
// DOM Level 0 event handlers from executing xss code
else if (
} else if (
typeof substitutionValue === "string"
) {
substitutionValue = encodeAttributeHTMLEntities(
@ -541,7 +537,7 @@
(node._replacedWith && node.childNodes.length === 0) ||
(parentNode && parentNode.childNodes.length === 0)
) {
;(parentNode || node).remove()
(parentNode || node).remove()
}
// --------------------------------------------------

View file

@ -102,7 +102,8 @@ export async function getBestEditor(): Promise<string> {
const vim_positioning_arg = ` ${arg_quote}+normal!%lGzv%c|${arg_quote}`
if (os === "mac") {
gui_candidates = [
"/Applications/MacVim.app/Contents/bin/mvim -f" + vim_positioning_arg,
"/Applications/MacVim.app/Contents/bin/mvim -f" +
vim_positioning_arg,
"/usr/local/bin/vimr --wait --nvim +only",
]
// if anyone knows of any "sensible" terminals that let you send them commands to run,
@ -149,7 +150,12 @@ export async function getBestEditor(): Promise<string> {
]
}
tui_editors = ["vim" + vim_positioning_arg, "nvim" + vim_positioning_arg, "nano %f", "emacs -nw %f"]
tui_editors = [
"vim" + vim_positioning_arg,
"nvim" + vim_positioning_arg,
"nano %f",
"emacs -nw %f",
]
// Consider GUI editors
let cmd = await firstinpath(gui_candidates)
@ -246,12 +252,17 @@ export async function firstinpath(cmdarray) {
return cmd
}
export async function editor(file: string, line: number, col: number, content?: string) {
export async function editor(
file: string,
line: number,
col: number,
content?: string,
) {
if (content !== undefined) await write(file, content)
const editorcmd =
(config.get("editorcmd") === "auto"
const editorcmd = (config.get("editorcmd") === "auto"
? await getBestEditor()
: config.get("editorcmd"))
: config.get("editorcmd")
)
.replace(/%l/, line)
.replace(/%c/, col)
let exec
@ -260,8 +271,7 @@ export async function editor(file: string, line: number, col: number, content?:
} else {
exec = await run(editorcmd + " " + file)
}
if (exec.code != 0)
return exec
if (exec.code != 0) return exec
return read(file)
}
@ -371,9 +381,7 @@ export async function clipboard(
const result = await run(`${clipcmd} -i`, str)
if (result.code !== 0)
throw new Error(
`External command failed with code ${
result.code
}: ${clipcmd}`,
`External command failed with code ${result.code}: ${clipcmd}`,
)
return ""
} else {
@ -418,12 +426,12 @@ export async function parseProfilesIni(content: string, basePath: string) {
let current = "General"
const result = {}
for (const line of lines) {
let match = line.match(/^\[([^\]]+)\]$/)
let match = /^\[([^\]]+)\]$/.exec(line)
if (match !== null) {
current = match[1]
result[current] = {}
} else {
match = line.match(/^([^=]+)=([^=]+)$/)
match = /^([^=]+)=([^=]+)$/.exec(line)
if (match !== null) {
result[current][match[1]] = match[2]
}
@ -448,9 +456,7 @@ export async function parseProfilesIni(content: string, basePath: string) {
} else if (profile.IsRelative === "0") {
if (profile.Path.substring(0, basePath.length) !== basePath) {
throw new Error(
`Error parsing profiles ini: basePath "${basePath}" doesn't match profile path ${
profile.Path
}`,
`Error parsing profiles ini: basePath "${basePath}" doesn't match profile path ${profile.Path}`,
)
}
profile.relativePath = profile.Path.substring(basePath.length)
@ -509,8 +515,7 @@ export async function getProfileUncached() {
// Then, try to find a profile path in the arguments given to Firefox
const cmdline = await ff_cmdline().catch(e => "")
let profile = cmdline.indexOf("--profile")
if (profile === -1)
profile = cmdline.indexOf("-profile")
if (profile === -1) profile = cmdline.indexOf("-profile")
if (profile >= 0 && profile < cmdline.length - 1) {
const profilePath = cmdline[profile + 1]
if (iniSucceeded) {
@ -545,9 +550,7 @@ export async function getProfileUncached() {
}
}
throw new Error(
`native.ts:getProfile() : '${
cmdline[p]
}' found in command line arguments but no matching profile name found in "${iniPath}"`,
`native.ts:getProfile() : '${cmdline[p]}' found in command line arguments but no matching profile name found in "${iniPath}"`,
)
}
}
@ -562,10 +565,7 @@ export async function getProfileUncached() {
profilecmd.content = profilecmd.content.trim()
// If there's only one profile in use, use that to find the right profile
if (profilecmd.content.split("\n").length === 1) {
const path = profilecmd.content
.split("/")
.slice(0, -1)
.join("/")
const path = profilecmd.content.split("/").slice(0, -1).join("/")
if (iniSucceeded) {
for (const profileName of Object.keys(iniObject)) {
const profile = iniObject[profileName]
@ -602,8 +602,7 @@ export async function getProfileUncached() {
// Disk operations are extremely slow on windows, let's cache our profile info
let cachedProfile
export async function getProfile() {
if (cachedProfile === undefined)
cachedProfile = await getProfileUncached()
if (cachedProfile === undefined) cachedProfile = await getProfileUncached()
return cachedProfile
}
// It makes sense to pre-fetch this value in the background script because it's
@ -627,7 +626,7 @@ export async function getProfileDir() {
return getProfile().then(p => p.absolutePath)
}
export async function parsePrefs(prefFileContent: string) {
export function parsePrefs(prefFileContent: string) {
// This RegExp currently only deals with " but for correctness it should
// also deal with ' and `
// We could also just give up on parsing and eval() the whole thing
@ -636,7 +635,7 @@ export async function parsePrefs(prefFileContent: string) {
)
// Fragile parsing
return prefFileContent.split("\n").reduce((prefs, line) => {
const matches = line.match(regex)
const matches = regex.exec(line)
if (!matches) {
return prefs
}
@ -790,17 +789,23 @@ export async function unfixamo() {
const tridactylPref2 = "tridactyl.unfixedamo_removed"
const restricted = "extensions.webextensions.restrictedDomains"
const amoblocker = "privacy.resistFingerprinting.block_mozAddonManager"
const restrictedDomains = '"accounts-static.cdn.mozilla.net,accounts.firefox.com,addons.cdn.mozilla.net,addons.mozilla.org,api.accounts.firefox.com,content.cdn.mozilla.net,discovery.addons.mozilla.org,install.mozilla.org,oauth.accounts.firefox.com,profile.accounts.firefox.com,support.mozilla.org,sync.services.mozilla.com"'
const restrictedDomains =
'"accounts-static.cdn.mozilla.net,accounts.firefox.com,addons.cdn.mozilla.net,addons.mozilla.org,api.accounts.firefox.com,content.cdn.mozilla.net,discovery.addons.mozilla.org,install.mozilla.org,oauth.accounts.firefox.com,profile.accounts.firefox.com,support.mozilla.org,sync.services.mozilla.com"'
// Exit if we've already run this once
if (userjs[tridactylPref2] === "true") return
if (userjs[restricted] === "" || userjs[restricted] === restrictedDomains) {
if (
userjs[restricted] === "" ||
userjs[restricted] === restrictedDomains
) {
await removePref(tridactylPref) // Clean up after first attempt if it exists
await removePref(restricted)
await removePref(amoblocker)
await writePref(tridactylPref2, "true")
browserBg.tabs.create({url: browserBg.runtime.getURL("static/unfixamo.html")})
browserBg.tabs.create({
url: browserBg.runtime.getURL("static/unfixamo.html"),
})
}
return

View file

@ -254,9 +254,7 @@ export function deleteQuery(url: URL, matchQuery: string): URL {
const qys = getUrlQueries(url)
const new_qys = qys.filter(q => {
return q.split("=")[0] !== matchQuery
})
const new_qys = qys.filter(q => q.split("=")[0] !== matchQuery)
setUrlQueries(newUrl, new_qys)

View file

@ -39,10 +39,12 @@ export const browserBg = inContentScript() ? browserProxy : browser
*
*/
export async function activeTab() {
return (await browserBg.tabs.query({
return (
await browserBg.tabs.query({
active: true,
currentWindow: true,
}))[0]
})
)[0]
}
export async function activeTabId() {
@ -122,9 +124,11 @@ export async function openInNewTab(
break
case "last":
// Infinity can't be serialised, apparently.
options.index = (await browserBg.tabs.query({
options.index = (
await browserBg.tabs.query({
currentWindow: true,
})).length
})
).length
break
case "related":
if (await firefoxVersionAtLeast(57)) {
@ -135,16 +139,20 @@ export async function openInNewTab(
break
}
if (kwargs.active === false) { // load in background
if (kwargs.active === false) {
// load in background
return browserBg.tabs.create(options)
} else { // load in background and then activate, per issue #1993
return browserBg.tabs.create(options).then(newtab => browserBg.tabs.update(newtab.id, { active: true }))
} else {
// load in background and then activate, per issue #1993
return browserBg.tabs
.create(options)
.then(newtab => browserBg.tabs.update(newtab.id, { active: true }))
}
}
// lazily copied from excmds.ts' winopen - forceURI really ought to be moved to lib/webext
// Should consider changing interface of this to match openInNewTab or vice versa
export async function openInNewWindow(createData = {}) {
export function openInNewWindow(createData = {}) {
browserBg.windows.create(createData)
}
@ -254,5 +262,5 @@ export async function openInTab(tab, opts = {}, strarr: string[]) {
// No search engine has been defined in Tridactyl, let's use firefox's default search engine
browserBg.search.search({ tabId: tab.id, query: queryString })
return tab;
return tab
}

View file

@ -278,7 +278,6 @@ export class StatsLogger {
private incrementIdx() {
this.idx = (this.idx + 1) % this.buffersize
}
}
/**
@ -388,7 +387,7 @@ const extractRegExp = new RegExp(
// sample itself.
)
function extractMetricName(counterName: string): MetricNameInfo {
const matchresult = counterName.match(extractRegExp)
const matchresult = extractRegExp.exec(counterName)
if (!matchresult) return
const [ownerName, functionName, uniqueSuffix] = matchresult.slice(1)
@ -416,5 +415,9 @@ class MetricName {
}
function sendStats(list: PerformanceEntryList) {
messaging.message("performance_background", "receiveStatsJson", JSON.stringify(list))
messaging.message(
"performance_background",
"receiveStatsJson",
JSON.stringify(list),
)
}

7
src/tridactyl.d.ts vendored
View file

@ -48,9 +48,7 @@ interface findResult {
interface HTMLElement {
// Let's be future proof:
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
focus(options: any): void
// Let's also implement the current function signature.
focus(): void
focus(options?: any): void
}
/* eslint-disable @typescript-eslint/ban-types */
@ -67,9 +65,10 @@ declare namespace browser.find {
function find(query, object): any
}
// setZoom has an optional first argument of tabId. Unclear how first argument can be optional.
declare namespace browser.tabs {
function setZoom(zoomFactor: number): Promise<void>
// setZoom has an optional first argument of tabId: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/setZoom#Parameters
// eslint-disable-next-line @typescript-eslint/unified-signatures
function setZoom(tabId: number, zoomFactor: number): Promise<void>
function toggleReaderMode(tabId?: number): Promise<void>
}