mirror of
https://github.com/tridactyl/tridactyl.git
synced 2026-09-10 07:16:33 -04:00
Update to ts6
Most of the changed lines in this are from random breaking changes in typedoc meaning that lots of docstrings needed to be rewritten
This commit is contained in:
parent
15aee6cf3f
commit
fcb55685d2
56
.eslintrc.js
56
.eslintrc.js
|
|
@ -50,35 +50,16 @@ module.exports = {
|
||||||
"@typescript-eslint/array-type": "off",
|
"@typescript-eslint/array-type": "off",
|
||||||
"@typescript-eslint/await-thenable": "error",
|
"@typescript-eslint/await-thenable": "error",
|
||||||
"@typescript-eslint/ban-ts-comment": "error",
|
"@typescript-eslint/ban-ts-comment": "error",
|
||||||
"@typescript-eslint/ban-types": [
|
"@typescript-eslint/no-restricted-types": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
"types": {
|
"types": {
|
||||||
"Object": {
|
|
||||||
"message": "Avoid using the `Object` type. Did you mean `object`?"
|
|
||||||
},
|
|
||||||
"Function": {
|
|
||||||
"message": "Avoid using the `Function` type. Prefer a specific function type, like `() => void`."
|
|
||||||
},
|
|
||||||
"Boolean": {
|
|
||||||
"message": "Avoid using the `Boolean` type. Did you mean `boolean`?"
|
|
||||||
},
|
|
||||||
"Number": {
|
|
||||||
"message": "Avoid using the `Number` type. Did you mean `number`?"
|
|
||||||
},
|
|
||||||
"String": {
|
|
||||||
"message": "Avoid using the `String` type. Did you mean `string`?"
|
|
||||||
},
|
|
||||||
"KeyboardEvent": {
|
"KeyboardEvent": {
|
||||||
"message": "Use `TrustedKeyboardEvent` to prevent remote code injection from hostile pages."
|
"message": "Use `TrustedKeyboardEvent` to prevent remote code injection from hostile pages."
|
||||||
},
|
|
||||||
"Symbol": {
|
|
||||||
"message": "Avoid using the `Symbol` type. Did you mean `symbol`?"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@typescript-eslint/class-name-casing": "off",
|
|
||||||
"@typescript-eslint/consistent-type-assertions": "error",
|
"@typescript-eslint/consistent-type-assertions": "error",
|
||||||
"@typescript-eslint/consistent-type-definitions": "error",
|
"@typescript-eslint/consistent-type-definitions": "error",
|
||||||
"@typescript-eslint/dot-notation": "off", // this should be "error" but the fix silently breaks code almost 100% of the time. not worth the headaches
|
"@typescript-eslint/dot-notation": "off", // this should be "error" but the fix silently breaks code almost 100% of the time. not worth the headaches
|
||||||
|
|
@ -89,28 +70,14 @@ module.exports = {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@typescript-eslint/explicit-module-boundary-types": "off", //"warn", // This is another hard one to enable
|
"@typescript-eslint/explicit-module-boundary-types": "off", //"warn", // This is another hard one to enable
|
||||||
"@typescript-eslint/indent": "off",
|
|
||||||
"@typescript-eslint/interface-name-prefix": "off",
|
|
||||||
"@typescript-eslint/member-delimiter-style": [
|
|
||||||
"off",
|
|
||||||
{
|
|
||||||
"multiline": {
|
|
||||||
"delimiter": "none",
|
|
||||||
"requireLast": true
|
|
||||||
},
|
|
||||||
"singleline": {
|
|
||||||
"delimiter": "semi",
|
|
||||||
"requireLast": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"@typescript-eslint/member-ordering": [
|
"@typescript-eslint/member-ordering": [
|
||||||
"error",
|
"error",
|
||||||
{ "default": ["field", "constructor", "method"] },
|
{ "default": ["field", "constructor", "method"] },
|
||||||
],
|
],
|
||||||
|
"@typescript-eslint/no-array-delete": "off",
|
||||||
"@typescript-eslint/no-array-constructor": "error",
|
"@typescript-eslint/no-array-constructor": "error",
|
||||||
|
"@typescript-eslint/no-base-to-string": "off",
|
||||||
"@typescript-eslint/no-empty-function": "error",
|
"@typescript-eslint/no-empty-function": "error",
|
||||||
"@typescript-eslint/no-empty-interface": "error",
|
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/no-extra-non-null-assertion": "error",
|
"@typescript-eslint/no-extra-non-null-assertion": "error",
|
||||||
"@typescript-eslint/no-floating-promises": "off", //"error", // We should turn this on eventually but it will take a while to fix
|
"@typescript-eslint/no-floating-promises": "off", //"error", // We should turn this on eventually but it will take a while to fix
|
||||||
|
|
@ -126,7 +93,7 @@ module.exports = {
|
||||||
"@typescript-eslint/no-namespace": "error",
|
"@typescript-eslint/no-namespace": "error",
|
||||||
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
|
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
|
||||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||||
"@typescript-eslint/no-parameter-properties": "off",
|
"@typescript-eslint/no-redundant-type-constituents": "off",
|
||||||
"@typescript-eslint/no-this-alias": "error",
|
"@typescript-eslint/no-this-alias": "error",
|
||||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
"@typescript-eslint/no-unsafe-assignment": "off", //"error",
|
"@typescript-eslint/no-unsafe-assignment": "off", //"error",
|
||||||
|
|
@ -146,17 +113,19 @@ module.exports = {
|
||||||
{
|
{
|
||||||
"args": "after-used",
|
"args": "after-used",
|
||||||
"argsIgnorePattern": "^_",
|
"argsIgnorePattern": "^_",
|
||||||
|
"caughtErrors": "none",
|
||||||
"varsIgnorePattern": "^_",
|
"varsIgnorePattern": "^_",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"@typescript-eslint/no-use-before-define": "off",
|
"@typescript-eslint/no-use-before-define": "off",
|
||||||
"@typescript-eslint/no-var-requires": "error",
|
"@typescript-eslint/only-throw-error": "off",
|
||||||
"@typescript-eslint/prefer-as-const": "error",
|
"@typescript-eslint/prefer-as-const": "error",
|
||||||
"@typescript-eslint/prefer-for-of": "error",
|
"@typescript-eslint/prefer-for-of": "error",
|
||||||
"@typescript-eslint/prefer-function-type": "error",
|
"@typescript-eslint/prefer-function-type": "error",
|
||||||
"@typescript-eslint/prefer-namespace-keyword": "error",
|
"@typescript-eslint/prefer-namespace-keyword": "error",
|
||||||
|
"@typescript-eslint/prefer-promise-reject-errors": "off",
|
||||||
"@typescript-eslint/prefer-regexp-exec": "error",
|
"@typescript-eslint/prefer-regexp-exec": "error",
|
||||||
"@typescript-eslint/quotes": [
|
"quotes": [
|
||||||
"error",
|
"error",
|
||||||
"double",
|
"double",
|
||||||
{
|
{
|
||||||
|
|
@ -167,10 +136,6 @@ module.exports = {
|
||||||
"@typescript-eslint/require-await": "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-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/restrict-template-expressions": "off",
|
||||||
"@typescript-eslint/semi": [
|
|
||||||
"off",
|
|
||||||
null
|
|
||||||
],
|
|
||||||
"@typescript-eslint/triple-slash-reference": [
|
"@typescript-eslint/triple-slash-reference": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
|
|
@ -179,7 +144,6 @@ module.exports = {
|
||||||
"lib": "always"
|
"lib": "always"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@typescript-eslint/type-annotation-spacing": "error",
|
|
||||||
"@typescript-eslint/unbound-method": "error",
|
"@typescript-eslint/unbound-method": "error",
|
||||||
"@typescript-eslint/unified-signatures": "error",
|
"@typescript-eslint/unified-signatures": "error",
|
||||||
"arrow-body-style": "error",
|
"arrow-body-style": "error",
|
||||||
|
|
@ -207,7 +171,6 @@ module.exports = {
|
||||||
"import/order": "off",
|
"import/order": "off",
|
||||||
"jsdoc/check-alignment": "off",
|
"jsdoc/check-alignment": "off",
|
||||||
"jsdoc/check-indentation": "off",
|
"jsdoc/check-indentation": "off",
|
||||||
"jsdoc/newline-after-description": "off",
|
|
||||||
"max-classes-per-file": "off",
|
"max-classes-per-file": "off",
|
||||||
"max-len": "off",
|
"max-len": "off",
|
||||||
"new-parens": "error",
|
"new-parens": "error",
|
||||||
|
|
@ -296,10 +259,9 @@ module.exports = {
|
||||||
"files": ["src/content.ts", "src/commandline_frame.ts"],
|
"files": ["src/content.ts", "src/commandline_frame.ts"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/no-explicit-any": "error",
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
"@typescript-eslint/ban-types": [
|
"@typescript-eslint/no-restricted-types": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
"extendDefaults": true,
|
|
||||||
"types": {
|
"types": {
|
||||||
"TrustedKeyboardEvent": {
|
"TrustedKeyboardEvent": {
|
||||||
"message": "Events must be validated with `isTrustedKeyboardEvent` at runtime"
|
"message": "Events must be validated with `isTrustedKeyboardEvent` at runtime"
|
||||||
|
|
|
||||||
2
.github/workflows/e2e.yml
vendored
2
.github/workflows/e2e.yml
vendored
|
|
@ -42,7 +42,7 @@ jobs:
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
|
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: yarn install
|
run: yarn install --frozen-lockfile
|
||||||
|
|
||||||
- name: Setup Firefox
|
- name: Setup Firefox
|
||||||
uses: browser-actions/setup-firefox@v1
|
uses: browser-actions/setup-firefox@v1
|
||||||
|
|
|
||||||
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
|
|
@ -20,8 +20,12 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
cache: 'yarn'
|
||||||
- name: Setup
|
- name: Setup
|
||||||
run: yarn install
|
run: yarn install --frozen-lockfile
|
||||||
- name: ${{ matrix.step }}
|
- name: ${{ matrix.step }}
|
||||||
env:
|
env:
|
||||||
STEP: ${{ matrix.step }}
|
STEP: ${{ matrix.step }}
|
||||||
|
|
|
||||||
2
.github/workflows/website.yml
vendored
2
.github/workflows/website.yml
vendored
|
|
@ -47,7 +47,7 @@ jobs:
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd tridactyl
|
cd tridactyl
|
||||||
yarn install
|
yarn install --frozen-lockfile
|
||||||
yarn run build
|
yarn run build
|
||||||
find . -iname "*.html" -exec sed 's@href="/static@href="/build/static@' -i '{}' ';' # ideally this url would be less gnarly
|
find . -iname "*.html" -exec sed 's@href="/static@href="/build/static@' -i '{}' ';' # ideally this url would be less gnarly
|
||||||
cd ../site
|
cd ../site
|
||||||
|
|
|
||||||
10
package.json
10
package.json
|
|
@ -26,7 +26,7 @@
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"tridactyl-arg": "git+https://github.com/GHolk/arg.git#v5.1.0",
|
"tridactyl-arg": "git+https://github.com/GHolk/arg.git#v5.1.0",
|
||||||
"tsdef": "^0.0.14",
|
"tsdef": "^0.0.14",
|
||||||
"typedoc": "0.22.18",
|
"typedoc": "0.28.20",
|
||||||
"xss": "^1.0.15"
|
"xss": "^1.0.15"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -35,10 +35,10 @@
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "29.5.12",
|
||||||
"@types/nearley": "^2.11.5",
|
"@types/nearley": "^2.11.5",
|
||||||
"@types/selenium-webdriver": "^4.1.10",
|
"@types/selenium-webdriver": "^4.1.10",
|
||||||
"@typescript-eslint/eslint-plugin": "5.25.0",
|
"@typescript-eslint/eslint-plugin": "8.64.0",
|
||||||
"@typescript-eslint/parser": "5.25.0",
|
"@typescript-eslint/parser": "8.64.0",
|
||||||
"command-line-args": "^6.0.1",
|
"command-line-args": "^6.0.1",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "8.57.1",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-jsdoc": "^50.6.1",
|
"eslint-plugin-jsdoc": "^50.6.1",
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"selenium-webdriver": "^4.7.1",
|
"selenium-webdriver": "^4.7.1",
|
||||||
"ts-jest": "29.4.11",
|
"ts-jest": "29.4.11",
|
||||||
"typescript": "4.7.4",
|
"typescript": "6.0.3",
|
||||||
"web-ext": "^7.10.0",
|
"web-ext": "^7.10.0",
|
||||||
"yaml-lint": "^1.7.0"
|
"yaml-lint": "^1.7.0"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -57,16 +57,19 @@ if [ "$QUICK_BUILD" != "1" ]; then
|
||||||
"$(yarn bin)/nearleyc" src/grammars/bracketexpr.ne > \
|
"$(yarn bin)/nearleyc" src/grammars/bracketexpr.ne > \
|
||||||
src/grammars/.bracketexpr.generated.ts
|
src/grammars/.bracketexpr.generated.ts
|
||||||
|
|
||||||
|
printf '{"version":1,"commands":{},"settings":{}}' > src/.metadata.generated.json
|
||||||
|
printf 'export * from "./lib/metadata"\n' > src/.metadata.generated.ts
|
||||||
|
node -e "var fs=require('fs');fs.writeFileSync('src/.themes.generated.json',JSON.stringify(fs.readdirSync('src/static/themes').sort()))"
|
||||||
|
|
||||||
# Generate runtime metadata via typedoc. The generated TypeScript shim
|
# Generate runtime metadata via typedoc. The generated TypeScript shim
|
||||||
# routes the public @src/.metadata.generated import to the JSON loader.
|
# routes the public @src/.metadata.generated import to the JSON loader.
|
||||||
"$(yarn bin)/typedoc" --json src/.metadata.generated.json \
|
"$(yarn bin)/typedoc" --json src/.metadata.generated.json \
|
||||||
--excludeExternals --disableSources --plugin none --readme none \
|
--excludeExternals --disableSources --readme none \
|
||||||
|
--excludePrivate false --excludePrivateClassFields false \
|
||||||
--validation.notExported false \
|
--validation.notExported false \
|
||||||
--exclude 'src/.excmds_*.generated.ts' \
|
--exclude 'src/.excmds_*.generated.ts' \
|
||||||
src/excmds.ts src/lib/config.ts src/content/state_content.ts
|
src/excmds.ts src/lib/config.ts src/content/state_content.ts
|
||||||
node scripts/minify_json.js src/.metadata.generated.json
|
node scripts/convert_typedoc_metadata.js src/.metadata.generated.json
|
||||||
node -e "var fs=require('fs');fs.writeFileSync('src/.themes.generated.json',JSON.stringify(fs.readdirSync('src/static/themes').sort()))"
|
|
||||||
printf 'export * from "./lib/metadata"\n' > src/.metadata.generated.ts
|
|
||||||
|
|
||||||
scripts/newtab.md.sh
|
scripts/newtab.md.sh
|
||||||
scripts/make_tutorial.sh
|
scripts/make_tutorial.sh
|
||||||
|
|
|
||||||
190
scripts/convert_typedoc_metadata.js
Normal file
190
scripts/convert_typedoc_metadata.js
Normal file
|
|
@ -0,0 +1,190 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const fs = require("fs")
|
||||||
|
|
||||||
|
const TYPEDOC_SCHEMA_VERSION = "2.0"
|
||||||
|
const METADATA_VERSION = 1
|
||||||
|
const KIND = { Module: 2, Function: 64, Class: 128 }
|
||||||
|
|
||||||
|
const compareNames = (a, b) => (a < b ? -1 : a > b ? 1 : 0)
|
||||||
|
const sortedRecord = entries =>
|
||||||
|
Object.fromEntries(entries.sort(([a], [b]) => compareNames(a, b)))
|
||||||
|
|
||||||
|
function convertMetadata(project) {
|
||||||
|
if (project.schemaVersion !== TYPEDOC_SCHEMA_VERSION)
|
||||||
|
throw new Error(
|
||||||
|
`Unsupported TypeDoc schemaVersion ${JSON.stringify(project.schemaVersion)}; expected ${TYPEDOC_SCHEMA_VERSION}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
const reflections = {}
|
||||||
|
const collect = value => {
|
||||||
|
if (!value || typeof value !== "object") return
|
||||||
|
if (Array.isArray(value)) return value.forEach(collect)
|
||||||
|
if (value.id !== undefined) reflections[value.id] = value
|
||||||
|
Object.values(value).forEach(collect)
|
||||||
|
}
|
||||||
|
collect(project)
|
||||||
|
|
||||||
|
const accessor = node => node?.getSignature || node?.setSignature
|
||||||
|
const memberType = node => node?.type || accessor(node)?.type
|
||||||
|
const commentText = comment =>
|
||||||
|
(comment?.summary || [])
|
||||||
|
.map(part => part.text || "")
|
||||||
|
.join("")
|
||||||
|
.replace(/\n+$/, "")
|
||||||
|
|
||||||
|
const normalizeParameter = (parameter, resolving) => ({
|
||||||
|
name: parameter.name,
|
||||||
|
type: normalizeType(parameter.type, resolving),
|
||||||
|
...(parameter.flags?.isRest ? { flags: { isRest: true } } : {}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const normalizeType = (type, resolving = new Set()) => {
|
||||||
|
if (!type) return { type: "intrinsic", name: "any" }
|
||||||
|
if (
|
||||||
|
type.type === "reference" &&
|
||||||
|
typeof type.target === "number" &&
|
||||||
|
!type.typeArguments?.length &&
|
||||||
|
reflections[type.target]?.type &&
|
||||||
|
!resolving.has(type.target)
|
||||||
|
) {
|
||||||
|
const next = new Set(resolving)
|
||||||
|
next.add(type.target)
|
||||||
|
return normalizeType(reflections[type.target].type, next)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type.type) {
|
||||||
|
case "intrinsic":
|
||||||
|
return { type: "intrinsic", name: type.name }
|
||||||
|
case "array":
|
||||||
|
return {
|
||||||
|
type: "array",
|
||||||
|
elementType: normalizeType(type.elementType, resolving),
|
||||||
|
}
|
||||||
|
case "tuple":
|
||||||
|
return {
|
||||||
|
type: "tuple",
|
||||||
|
elements: (type.elements || []).map(element =>
|
||||||
|
normalizeType(element, resolving),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
case "union":
|
||||||
|
return {
|
||||||
|
type: "union",
|
||||||
|
types: (type.types || []).map(member =>
|
||||||
|
normalizeType(member, resolving),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
case "literal":
|
||||||
|
return { type: "literal", value: type.value }
|
||||||
|
case "reference":
|
||||||
|
return {
|
||||||
|
type: "reference",
|
||||||
|
name: type.name,
|
||||||
|
...(type.typeArguments?.length
|
||||||
|
? {
|
||||||
|
typeArguments: type.typeArguments.map(argument =>
|
||||||
|
normalizeType(argument, resolving),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
}
|
||||||
|
case "reflection": {
|
||||||
|
const source = type.declaration || {}
|
||||||
|
const declaration = {}
|
||||||
|
const signature = source.signatures?.[0]
|
||||||
|
if (signature)
|
||||||
|
declaration.signatures = [
|
||||||
|
{
|
||||||
|
parameters: (signature.parameters || []).map(
|
||||||
|
parameter =>
|
||||||
|
normalizeParameter(parameter, resolving),
|
||||||
|
),
|
||||||
|
type: normalizeType(signature.type, resolving),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const children = (source.children || [])
|
||||||
|
.map(child => {
|
||||||
|
const type = memberType(child)
|
||||||
|
return type
|
||||||
|
? {
|
||||||
|
name: child.name,
|
||||||
|
type: normalizeType(type, resolving),
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
})
|
||||||
|
.filter(Boolean)
|
||||||
|
.sort((a, b) => compareNames(a.name, b.name))
|
||||||
|
if (children.length) declaration.children = children
|
||||||
|
|
||||||
|
const indexSignatures = (source.indexSignatures || []).map(
|
||||||
|
signature => ({
|
||||||
|
type: normalizeType(signature.type, resolving),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
if (indexSignatures.length)
|
||||||
|
declaration.indexSignatures = indexSignatures
|
||||||
|
return { type: "reflection", declaration }
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return { type: "intrinsic", name: "any" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const modules = Object.fromEntries(
|
||||||
|
(project.children || [])
|
||||||
|
.filter(node => node.kind === KIND.Module)
|
||||||
|
.map(node => [
|
||||||
|
(node.name || "").replace(/^"|"$/g, "").replace(/\\/g, "/"),
|
||||||
|
node,
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
const excmds = modules.excmds
|
||||||
|
const configClass = modules["lib/config"]?.children?.find(
|
||||||
|
node => node.kind === KIND.Class && node.name === "default_config",
|
||||||
|
)
|
||||||
|
if (!excmds || !configClass)
|
||||||
|
throw new Error("TypeDoc output is missing excmds or default_config")
|
||||||
|
|
||||||
|
const commands = sortedRecord(
|
||||||
|
(excmds.children || [])
|
||||||
|
.filter(node => node.kind === KIND.Function)
|
||||||
|
.map(node => {
|
||||||
|
const signature = node.signatures?.[0]
|
||||||
|
return [
|
||||||
|
node.name,
|
||||||
|
{
|
||||||
|
doc:
|
||||||
|
commentText(signature?.comment) ||
|
||||||
|
commentText(node.comment),
|
||||||
|
params: (signature?.parameters || []).map(parameter =>
|
||||||
|
normalizeParameter(parameter),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
const settings = sortedRecord(
|
||||||
|
(configClass.children || []).map(node => [
|
||||||
|
node.name,
|
||||||
|
{
|
||||||
|
doc:
|
||||||
|
commentText(accessor(node)?.comment) ||
|
||||||
|
commentText(node.comment),
|
||||||
|
type: normalizeType(memberType(node)),
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
return { version: METADATA_VERSION, commands, settings }
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { convertMetadata, METADATA_VERSION, TYPEDOC_SCHEMA_VERSION }
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
const file = process.argv[2]
|
||||||
|
if (!file) throw new Error("Usage: convert_typedoc_metadata.js FILE")
|
||||||
|
const metadata = convertMetadata(JSON.parse(fs.readFileSync(file, "utf8")))
|
||||||
|
fs.writeFileSync(file, JSON.stringify(metadata))
|
||||||
|
}
|
||||||
|
|
@ -201,5 +201,5 @@ def main():
|
||||||
print(output.rstrip(), file=sink)
|
print(output.rstrip(), file=sink)
|
||||||
|
|
||||||
|
|
||||||
PRELUDE = "/** Generated from excmds.ts. Don't edit this file! */"
|
PRELUDE = "/* Generated from excmds.ts. Don't edit this file! */"
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,18 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
dest=generated/static/docs
|
dest=generated/static/docs
|
||||||
"$(yarn bin)/typedoc" --plugin ./scripts/typedoc-theme.js --theme tridactyl \
|
if revision=$(git rev-parse HEAD 2>/dev/null); then
|
||||||
|
set -- --basePath src --disableGit --gitRevision "$revision" \
|
||||||
|
--sourceLinkTemplate 'https://github.com/tridactyl/tridactyl/blob/{gitRevision}/src/{path}#L{line}'
|
||||||
|
else
|
||||||
|
set -- --disableSources
|
||||||
|
fi
|
||||||
|
"$(yarn bin)/typedoc" --plugin ./scripts/typedoc-theme.mjs \
|
||||||
|
--theme tridactyl --router tridactyl \
|
||||||
|
"$@" \
|
||||||
--entryPointStrategy expand --validation.notExported false \
|
--entryPointStrategy expand --validation.notExported false \
|
||||||
|
--excludePrivate false --excludePrivateClassFields false \
|
||||||
|
--includeHierarchySummary false \
|
||||||
--exclude "src/**/?(test_utils|*.test).ts" \
|
--exclude "src/**/?(test_utils|*.test).ts" \
|
||||||
--out "$dest" src
|
--out "$dest" src
|
||||||
rm -rf build/static/docs
|
rm -rf build/static/docs
|
||||||
|
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
const {
|
|
||||||
Converter,
|
|
||||||
DefaultTheme,
|
|
||||||
IntrinsicType,
|
|
||||||
JSX,
|
|
||||||
ReflectionKind,
|
|
||||||
ReflectionType,
|
|
||||||
TypeScript: ts,
|
|
||||||
} = require("typedoc")
|
|
||||||
|
|
||||||
const h = JSX.createElement
|
|
||||||
const css = href => h("link", { rel: "stylesheet", href })
|
|
||||||
|
|
||||||
function restoreObjectLiteral(context, reflection, node) {
|
|
||||||
const initializer = node && node.initializer
|
|
||||||
if (!initializer || !ts.isObjectLiteralExpression(initializer)) return
|
|
||||||
if (!initializer.properties.length) return
|
|
||||||
|
|
||||||
if (reflection.type instanceof ReflectionType)
|
|
||||||
context.project.removeReflection(reflection.type.declaration)
|
|
||||||
const inferred = context.converter.convertType(
|
|
||||||
context.withScope(reflection),
|
|
||||||
context.checker.getTypeAtLocation(initializer),
|
|
||||||
)
|
|
||||||
if (!(inferred instanceof ReflectionType)) return
|
|
||||||
|
|
||||||
const children = inferred.declaration.children || []
|
|
||||||
inferred.declaration.children = undefined
|
|
||||||
context.project.removeReflection(inferred.declaration)
|
|
||||||
|
|
||||||
reflection.kind = ReflectionKind.ObjectLiteral
|
|
||||||
reflection.type = new IntrinsicType("object")
|
|
||||||
reflection.children = children
|
|
||||||
for (const child of children) child.parent = reflection
|
|
||||||
}
|
|
||||||
|
|
||||||
class TridactylTheme extends DefaultTheme {
|
|
||||||
constructor(renderer) {
|
|
||||||
super(renderer)
|
|
||||||
this.defaultLayoutTemplate = page => {
|
|
||||||
const context = this.getRenderContext(page)
|
|
||||||
const navigations = context.navigation(page).children
|
|
||||||
const navigation = navigations[1] || navigations[0]
|
|
||||||
navigation.props.class = "tsd-navigation secondary scroller"
|
|
||||||
|
|
||||||
return h(
|
|
||||||
"html",
|
|
||||||
{ class: "minimal no-js TridactylOwnNamespace" },
|
|
||||||
h(
|
|
||||||
"head",
|
|
||||||
null,
|
|
||||||
h("meta", { charset: "utf-8" }),
|
|
||||||
h("meta", {
|
|
||||||
"http-equiv": "X-UA-Compatible",
|
|
||||||
content: "IE=edge",
|
|
||||||
}),
|
|
||||||
h(
|
|
||||||
"title",
|
|
||||||
null,
|
|
||||||
`${page.model.name} | ${page.project.name}`,
|
|
||||||
),
|
|
||||||
h("meta", {
|
|
||||||
name: "viewport",
|
|
||||||
content: "width=device-width, initial-scale=1",
|
|
||||||
}),
|
|
||||||
css(context.relativeURL("assets/style.css")),
|
|
||||||
css(context.relativeURL("assets/highlight.css")),
|
|
||||||
h("script", { src: "/content.js" }),
|
|
||||||
h("script", { src: "/help.js" }),
|
|
||||||
css("/static/css/content.css"),
|
|
||||||
css("/static/css/hint.css"),
|
|
||||||
css("/static/css/viewsource.css"),
|
|
||||||
css("/static/typedoc/assets/css/main.css"),
|
|
||||||
),
|
|
||||||
h(
|
|
||||||
"body",
|
|
||||||
null,
|
|
||||||
navigation,
|
|
||||||
h(
|
|
||||||
"div",
|
|
||||||
{ class: "container container-main scroller" },
|
|
||||||
h(
|
|
||||||
"div",
|
|
||||||
{ class: "content-wrap" },
|
|
||||||
page.template(page),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getUrls(project) {
|
|
||||||
for (const child of project.children || []) {
|
|
||||||
if (child.kind === ReflectionKind.Module)
|
|
||||||
child.name = `"src/${child.name}"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const names = Object.values(project.reflections).map(reflection => [
|
|
||||||
reflection,
|
|
||||||
reflection.name,
|
|
||||||
])
|
|
||||||
for (const [reflection] of names)
|
|
||||||
reflection.name = reflection.name
|
|
||||||
.replace(/[^a-z0-9]/gi, "_")
|
|
||||||
.toLowerCase()
|
|
||||||
|
|
||||||
const urls = super.getUrls(project)
|
|
||||||
for (const [reflection, name] of names) reflection.name = name
|
|
||||||
|
|
||||||
const globals = urls.find(mapping => mapping.url === "modules.html")
|
|
||||||
if (globals) globals.url = project.url = "globals.html"
|
|
||||||
return urls
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.load = app => {
|
|
||||||
app.converter.on(Converter.EVENT_CREATE_DECLARATION, restoreObjectLiteral, 100)
|
|
||||||
app.renderer.defineTheme("tridactyl", TridactylTheme)
|
|
||||||
}
|
|
||||||
343
scripts/typedoc-theme.mjs
Normal file
343
scripts/typedoc-theme.mjs
Normal file
|
|
@ -0,0 +1,343 @@
|
||||||
|
import {
|
||||||
|
Converter,
|
||||||
|
DefaultTheme,
|
||||||
|
IntrinsicType,
|
||||||
|
JSX,
|
||||||
|
KindRouter,
|
||||||
|
PageKind,
|
||||||
|
Reflection,
|
||||||
|
ReflectionKind,
|
||||||
|
ReflectionType,
|
||||||
|
Slugger,
|
||||||
|
TypeScript as ts,
|
||||||
|
} from "typedoc"
|
||||||
|
|
||||||
|
const h = JSX.createElement
|
||||||
|
const css = href => h("link", { rel: "stylesheet", href })
|
||||||
|
const cleanName = name => name.replace(/[^a-z0-9]/gi, "_").toLowerCase()
|
||||||
|
const isGeneratedSource = source =>
|
||||||
|
/\/\.[^/]+\.generated\.ts$/.test(source.fullFileName)
|
||||||
|
|
||||||
|
function rewriteWikiLinks(parts, owner, reflections) {
|
||||||
|
return parts.flatMap(part => {
|
||||||
|
if (part.kind !== "text" || !part.text.includes("[[")) return part
|
||||||
|
|
||||||
|
const out = []
|
||||||
|
let end = 0
|
||||||
|
for (const match of part.text.matchAll(
|
||||||
|
/\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/g,
|
||||||
|
)) {
|
||||||
|
if (match.index > end)
|
||||||
|
out.push({
|
||||||
|
kind: "text",
|
||||||
|
text: part.text.slice(end, match.index),
|
||||||
|
})
|
||||||
|
const candidates = reflections.get(match[1]) || []
|
||||||
|
const ownerModule = getModule(owner)
|
||||||
|
const target =
|
||||||
|
(!owner.kindOf(
|
||||||
|
ReflectionKind.Module | ReflectionKind.Namespace,
|
||||||
|
) &&
|
||||||
|
candidates.find(
|
||||||
|
candidate => candidate.parent === owner.parent,
|
||||||
|
)) ||
|
||||||
|
candidates.find(
|
||||||
|
candidate => getModule(candidate) === ownerModule,
|
||||||
|
) ||
|
||||||
|
candidates.find(
|
||||||
|
candidate =>
|
||||||
|
!candidate.kindOf(
|
||||||
|
ReflectionKind.Module | ReflectionKind.Namespace,
|
||||||
|
) &&
|
||||||
|
!candidate.sources?.some(isGeneratedSource),
|
||||||
|
) ||
|
||||||
|
candidates.find(
|
||||||
|
candidate =>
|
||||||
|
!candidate.kindOf(
|
||||||
|
ReflectionKind.Module | ReflectionKind.Namespace,
|
||||||
|
),
|
||||||
|
) ||
|
||||||
|
candidates[0]
|
||||||
|
out.push(
|
||||||
|
target
|
||||||
|
? {
|
||||||
|
kind: "inline-tag",
|
||||||
|
tag: "@link",
|
||||||
|
text: match[2] || match[1],
|
||||||
|
target,
|
||||||
|
}
|
||||||
|
: { kind: "text", text: match[2] || match[1] },
|
||||||
|
)
|
||||||
|
end = match.index + match[0].length
|
||||||
|
}
|
||||||
|
if (end < part.text.length)
|
||||||
|
out.push({ kind: "text", text: part.text.slice(end) })
|
||||||
|
return out
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModule(reflection) {
|
||||||
|
while (reflection.parent && !reflection.parent.isProject())
|
||||||
|
reflection = reflection.parent
|
||||||
|
return reflection
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeDependencyTags(parts) {
|
||||||
|
return parts.map(part =>
|
||||||
|
part.kind === "text"
|
||||||
|
? {
|
||||||
|
...part,
|
||||||
|
text: part.text.replace(
|
||||||
|
/<(\/?)(iframe|object|frame)>/gi,
|
||||||
|
"<$1$2>",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: part,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreWikiLinks(context) {
|
||||||
|
const reflections = new Map()
|
||||||
|
for (const reflection of Object.values(context.project.reflections)) {
|
||||||
|
if (!reflection.isDeclaration()) continue
|
||||||
|
const matches = reflections.get(reflection.name) || []
|
||||||
|
matches.push(reflection)
|
||||||
|
reflections.set(reflection.name, matches)
|
||||||
|
}
|
||||||
|
for (const reflection of Object.values(context.project.reflections)) {
|
||||||
|
const fromDependency = reflection.sources?.some(source =>
|
||||||
|
source.fullFileName.includes("/node_modules/"),
|
||||||
|
)
|
||||||
|
for (const source of reflection.sources || [])
|
||||||
|
if (
|
||||||
|
source.fullFileName.includes("/node_modules/") ||
|
||||||
|
isGeneratedSource(source)
|
||||||
|
)
|
||||||
|
source.url = undefined
|
||||||
|
const comment = reflection.comment
|
||||||
|
if (!comment) continue
|
||||||
|
comment.summary = rewriteWikiLinks(
|
||||||
|
comment.summary,
|
||||||
|
reflection,
|
||||||
|
reflections,
|
||||||
|
)
|
||||||
|
for (const tag of comment.blockTags)
|
||||||
|
tag.content = rewriteWikiLinks(tag.content, reflection, reflections)
|
||||||
|
if (fromDependency) {
|
||||||
|
comment.summary = escapeDependencyTags(comment.summary)
|
||||||
|
for (const tag of comment.blockTags)
|
||||||
|
tag.content = escapeDependencyTags(tag.content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (context.project.readme)
|
||||||
|
context.project.readme = rewriteWikiLinks(
|
||||||
|
context.project.readme,
|
||||||
|
context.project,
|
||||||
|
reflections,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreObjectLiteral(context, reflection) {
|
||||||
|
const node = context.getSymbolFromReflection(reflection)?.valueDeclaration
|
||||||
|
const initializer = node && "initializer" in node && node.initializer
|
||||||
|
if (!initializer || !ts.isObjectLiteralExpression(initializer)) return
|
||||||
|
if (!initializer.properties.length) return
|
||||||
|
|
||||||
|
if (reflection.type instanceof ReflectionType)
|
||||||
|
context.project.removeTypeReflections(reflection.type)
|
||||||
|
const inferred = context.converter.convertType(
|
||||||
|
context.withScope(reflection),
|
||||||
|
context.checker.getTypeAtLocation(initializer),
|
||||||
|
)
|
||||||
|
if (!(inferred instanceof ReflectionType)) return
|
||||||
|
|
||||||
|
reflection.type = new IntrinsicType("object")
|
||||||
|
context.project.mergeReflections(inferred.declaration, reflection)
|
||||||
|
}
|
||||||
|
|
||||||
|
class LegacySlugger extends Slugger {
|
||||||
|
serialize(value) {
|
||||||
|
return value.startsWith("\0") ? value.slice(1) : super.serialize(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TridactylRouter extends KindRouter {
|
||||||
|
aliases = new Map()
|
||||||
|
aliasCounts = new Map()
|
||||||
|
|
||||||
|
getSlugger(target) {
|
||||||
|
while (!this.sluggers.has(target)) target = target.parent
|
||||||
|
let slugger = this.sluggers.get(target)
|
||||||
|
if (!(slugger instanceof LegacySlugger)) {
|
||||||
|
slugger = new LegacySlugger(this.sluggerConfiguration)
|
||||||
|
this.sluggers.set(target, slugger)
|
||||||
|
}
|
||||||
|
return slugger
|
||||||
|
}
|
||||||
|
|
||||||
|
getPageKind(target) {
|
||||||
|
if (!(target instanceof Reflection)) return
|
||||||
|
if (
|
||||||
|
target.kindOf(
|
||||||
|
ReflectionKind.Class |
|
||||||
|
ReflectionKind.Interface |
|
||||||
|
ReflectionKind.Enum |
|
||||||
|
ReflectionKind.Module |
|
||||||
|
ReflectionKind.Namespace,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return PageKind.Reflection
|
||||||
|
if (target.kindOf(ReflectionKind.Document)) return PageKind.Document
|
||||||
|
}
|
||||||
|
|
||||||
|
getIdealBaseName(reflection) {
|
||||||
|
const directory = this.directories.get(reflection.kind)
|
||||||
|
const parts = []
|
||||||
|
do {
|
||||||
|
let name = reflection.name
|
||||||
|
if (
|
||||||
|
reflection.parent?.isProject() &&
|
||||||
|
reflection.kind === ReflectionKind.Module
|
||||||
|
)
|
||||||
|
name = `"src/${name}"`
|
||||||
|
parts.unshift(cleanName(name))
|
||||||
|
reflection = reflection.parent
|
||||||
|
} while (reflection && !reflection.isProject())
|
||||||
|
return `${directory}/${parts.join(".")}`
|
||||||
|
}
|
||||||
|
|
||||||
|
getLegacyAlias(reflection, pageTarget) {
|
||||||
|
if (this.aliases.has(reflection)) return this.aliases.get(reflection)
|
||||||
|
|
||||||
|
const base = cleanName(reflection.name) || `reflection-${reflection.id}`
|
||||||
|
let counts = this.aliasCounts.get(pageTarget)
|
||||||
|
if (!counts) this.aliasCounts.set(pageTarget, (counts = new Map()))
|
||||||
|
const count = counts.get(base) || 0
|
||||||
|
const alias = count ? `${base}-${count}` : base
|
||||||
|
counts.set(base, count + 1)
|
||||||
|
this.aliases.set(reflection, alias)
|
||||||
|
return alias
|
||||||
|
}
|
||||||
|
|
||||||
|
createAnchor(target, pageTarget) {
|
||||||
|
if (!target.isDeclaration())
|
||||||
|
return super.createAnchor(target, pageTarget)
|
||||||
|
|
||||||
|
const parts = []
|
||||||
|
for (
|
||||||
|
let current = target;
|
||||||
|
current !== pageTarget;
|
||||||
|
current = current.parent
|
||||||
|
)
|
||||||
|
parts.unshift(this.getLegacyAlias(current, pageTarget))
|
||||||
|
return this.getSlugger(pageTarget).slug("\0" + parts.join("."))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildPages(project) {
|
||||||
|
this.aliases.clear()
|
||||||
|
this.aliasCounts.clear()
|
||||||
|
const pages = super.buildPages(project)
|
||||||
|
const globals = pages.find(page => page.url === "modules.html")
|
||||||
|
if (globals) {
|
||||||
|
globals.url = "globals.html"
|
||||||
|
this.fullUrls.set(project, "globals.html")
|
||||||
|
}
|
||||||
|
return pages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TridactylTheme extends DefaultTheme {
|
||||||
|
getReflectionClasses(reflection) {
|
||||||
|
const kind = ReflectionKind.classString(reflection.kind)
|
||||||
|
const parent =
|
||||||
|
reflection.parent &&
|
||||||
|
ReflectionKind.classString(reflection.parent.kind).replace(
|
||||||
|
"tsd-kind-",
|
||||||
|
"tsd-parent-kind-",
|
||||||
|
)
|
||||||
|
return [super.getReflectionClasses(reflection), kind, parent]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(" ")
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(renderer) {
|
||||||
|
super(renderer)
|
||||||
|
const reflectionTemplate = this.reflectionTemplate
|
||||||
|
this.reflectionTemplate = page => {
|
||||||
|
const content = reflectionTemplate(page)
|
||||||
|
if (
|
||||||
|
!page.model.kindOf(
|
||||||
|
ReflectionKind.Module | ReflectionKind.Namespace,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return content
|
||||||
|
|
||||||
|
const context = this.getRenderContext(page)
|
||||||
|
page.pageSections.length = 0
|
||||||
|
const renderMember = context.member
|
||||||
|
context.member = reflection =>
|
||||||
|
reflection.isReference() ? null : renderMember(reflection)
|
||||||
|
return h(JSX.Fragment, null, content, context.members(page.model))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.defaultLayoutTemplate = (page, template) => {
|
||||||
|
const context = this.getRenderContext(page)
|
||||||
|
const content = template(page)
|
||||||
|
return h(
|
||||||
|
"html",
|
||||||
|
{ class: "minimal no-js TridactylOwnNamespace" },
|
||||||
|
h(
|
||||||
|
"head",
|
||||||
|
null,
|
||||||
|
h("meta", { charset: "utf-8" }),
|
||||||
|
h("meta", {
|
||||||
|
"http-equiv": "X-UA-Compatible",
|
||||||
|
content: "IE=edge",
|
||||||
|
}),
|
||||||
|
h(
|
||||||
|
"title",
|
||||||
|
null,
|
||||||
|
`${page.model.name} | ${page.project.name}`,
|
||||||
|
),
|
||||||
|
h("meta", {
|
||||||
|
name: "viewport",
|
||||||
|
content: "width=device-width, initial-scale=1",
|
||||||
|
}),
|
||||||
|
css(context.relativeURL("assets/style.css")),
|
||||||
|
css(context.relativeURL("assets/highlight.css")),
|
||||||
|
h("script", { src: "/content.js" }),
|
||||||
|
h("script", { src: "/help.js" }),
|
||||||
|
css("/static/css/content.css"),
|
||||||
|
css("/static/css/hint.css"),
|
||||||
|
css("/static/css/viewsource.css"),
|
||||||
|
css("/static/typedoc/assets/css/main.css"),
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
"body",
|
||||||
|
null,
|
||||||
|
h(
|
||||||
|
"nav",
|
||||||
|
{ class: "tsd-navigation secondary scroller" },
|
||||||
|
context.pageNavigation(page),
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
"div",
|
||||||
|
{ class: "container container-main scroller" },
|
||||||
|
h("div", { class: "content-wrap" }, content),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function load(app) {
|
||||||
|
app.converter.on(Converter.EVENT_RESOLVE_END, restoreWikiLinks, 100)
|
||||||
|
app.converter.on(
|
||||||
|
Converter.EVENT_CREATE_DECLARATION,
|
||||||
|
restoreObjectLiteral,
|
||||||
|
100,
|
||||||
|
)
|
||||||
|
app.renderer.defineRouter("tridactyl", TridactylRouter)
|
||||||
|
app.renderer.defineTheme("tridactyl", TridactylTheme)
|
||||||
|
}
|
||||||
|
|
@ -79,10 +79,10 @@ export async function downloadUrl(url: string, saveAs: boolean) {
|
||||||
*
|
*
|
||||||
* Note: this requires a native messenger >=0.1.9. Make sure to nativegate for this.
|
* Note: this requires a native messenger >=0.1.9. Make sure to nativegate for this.
|
||||||
*
|
*
|
||||||
* @param URL the URL to download
|
* @param url the URL to download
|
||||||
* @param saveAs If beginning with a slash, this is the absolute path the document should be moved to. If the first character of the string is a tilda, it will be expanded to an absolute path to the user's home directory. If saveAs begins with any other character, it will be considered a path relative to where the native messenger binary is located (e.g. "$HOME/.local/share/tridactyl" on linux).
|
* @param saveAs If beginning with a slash, this is the absolute path the document should be moved to. If the first character of the string is a tilda, it will be expanded to an absolute path to the user's home directory. If saveAs begins with any other character, it will be considered a path relative to where the native messenger binary is located (e.g. "$HOME/.local/share/tridactyl" on linux).
|
||||||
* @param If true, overwrite the destination file, returns error code 1 otherwise if file exists
|
* @param overwrite If true, overwrite the destination file, returns error code 1 otherwise if file exists
|
||||||
* @param If true, cleans up temporary downloaded source file e.g. in $HOME/Downlods/downloaded.doc when the move operation fails e.g. due to target destination exists, OS error etc.
|
* @param cleanup If true, cleans up temporary downloaded source file e.g. in $HOME/Downlods/downloaded.doc when the move operation fails e.g. due to target destination exists, OS error etc.
|
||||||
*/
|
*/
|
||||||
export async function downloadUrlAs(
|
export async function downloadUrlAs(
|
||||||
url: string,
|
url: string,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export const requestEventExpraInfoSpecMap = {
|
||||||
export const requestEvents = Object.keys(requestEventExpraInfoSpecMap)
|
export const requestEvents = Object.keys(requestEventExpraInfoSpecMap)
|
||||||
|
|
||||||
// I'm being lazy - strictly the functions map strings to void | blocking responses
|
// I'm being lazy - strictly the functions map strings to void | blocking responses
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
export const LISTENERS: Record<string, Record<string, Function>> = {}
|
export const LISTENERS: Record<string, Record<string, Function>> = {}
|
||||||
|
|
||||||
export const registerWebRequestAutocmd = async (
|
export const registerWebRequestAutocmd = async (
|
||||||
|
|
@ -21,7 +21,7 @@ export const registerWebRequestAutocmd = async (
|
||||||
func: string,
|
func: string,
|
||||||
) => {
|
) => {
|
||||||
// I'm being lazy - strictly the functions map strings to void | blocking responses
|
// I'm being lazy - strictly the functions map strings to void | blocking responses
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
const listener = eval(func) as Function
|
const listener = eval(func) as Function
|
||||||
|
|
||||||
if (!LISTENERS[requestEvent]) LISTENERS[requestEvent] = {}
|
if (!LISTENERS[requestEvent]) LISTENERS[requestEvent] = {}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export class ExcmdCompletionOption extends Completions.CompletionOptionHTML impl
|
||||||
public fuseKeys = []
|
public fuseKeys = []
|
||||||
constructor(
|
constructor(
|
||||||
public value: string,
|
public value: string,
|
||||||
public documentation: string = "",
|
public documentation = "",
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
this.fuseKeys.push(this.value)
|
this.fuseKeys.push(this.value)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ export class ThemeCompletionOption
|
||||||
extends Completions.CompletionOptionHTML
|
extends Completions.CompletionOptionHTML
|
||||||
implements Completions.CompletionOptionFuse {
|
implements Completions.CompletionOptionFuse {
|
||||||
public fuseKeys = []
|
public fuseKeys = []
|
||||||
constructor(public value: string, public documentation: string = "") {
|
constructor(public value: string, public documentation = "") {
|
||||||
super()
|
super()
|
||||||
this.fuseKeys.push(this.value)
|
this.fuseKeys.push(this.value)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export const CmdlineCmds = new Proxy(functions as any, {
|
||||||
get(target, property) {
|
get(target, property) {
|
||||||
if (target[property]) {
|
if (target[property]) {
|
||||||
return (...args) =>
|
return (...args) =>
|
||||||
messageOwnTab("commandline_cmd", property as string, args)
|
messageOwnTab("commandline_cmd", property, args)
|
||||||
}
|
}
|
||||||
return target[property]
|
return target[property]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ export async function jumpToMatch(searchQuery, option) {
|
||||||
const sensitive =
|
const sensitive =
|
||||||
findcase === "sensitive" ||
|
findcase === "sensitive" ||
|
||||||
(findcase === "smart" && /[A-Z]/.test(searchQuery))
|
(findcase === "smart" && /[A-Z]/.test(searchQuery))
|
||||||
const findPromise = await browserBg.find.find(searchQuery, {
|
const results = await browserBg.find.find(searchQuery, {
|
||||||
tabId: await activeTabId(),
|
tabId: await activeTabId(),
|
||||||
caseSensitive: sensitive,
|
caseSensitive: sensitive,
|
||||||
entireWord: false,
|
entireWord: false,
|
||||||
|
|
@ -208,8 +208,6 @@ export async function jumpToMatch(searchQuery, option) {
|
||||||
nodes.push(node)
|
nodes.push(node)
|
||||||
} while (node)
|
} while (node)
|
||||||
|
|
||||||
const results = await findPromise
|
|
||||||
|
|
||||||
const host = getFindHost()
|
const host = getFindHost()
|
||||||
for (let i = 0; i < results.count; ++i) {
|
for (let i = 0; i < results.count; ++i) {
|
||||||
const range = results.rangeData[i]
|
const range = results.rangeData[i]
|
||||||
|
|
|
||||||
340
src/excmds.ts
340
src/excmds.ts
|
|
@ -224,7 +224,7 @@ export async function getRssLinks(): Promise<Array<{ type: string; url: string;
|
||||||
}
|
}
|
||||||
if (seen.has(e.href)) return acc
|
if (seen.has(e.href)) return acc
|
||||||
seen.add(e.href)
|
seen.add(e.href)
|
||||||
return acc.concat({ type, url: e.href, title: e.title || e.innerText } as { type: string; url: string; title: string })
|
return acc.concat({ type, url: e.href, title: e.title || e.innerText })
|
||||||
}, [])
|
}, [])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,7 +340,7 @@ import { getEditor } from "editor-adapter"
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Your editor of choice may need to run in a terminal. For example, this command opens neovim with kitty and exits after closing the editor:
|
* Your editor of choice may need to run in a terminal. For example, this command opens neovim with kitty and exits after closing the editor:
|
||||||
* ```vim
|
* ```text
|
||||||
* set editorcmd kitty nvim
|
* set editorcmd kitty nvim
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
|
@ -1071,7 +1071,7 @@ export async function curJumps() {
|
||||||
return jumps
|
return jumps
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calls [[jumpprev]](-n) */
|
/** Calls [[jumpprev]] with `-n`. */
|
||||||
//#content
|
//#content
|
||||||
export function jumpnext(n = 1) {
|
export function jumpnext(n = 1) {
|
||||||
return jumpprev(-n)
|
return jumpprev(-n)
|
||||||
|
|
@ -1465,6 +1465,7 @@ export function scrollpage(n = 1, count = 1) {
|
||||||
/**
|
/**
|
||||||
* Rudimentary find mode, left unbound by default as we don't currently support `incsearch`. Suggested binds:
|
* Rudimentary find mode, left unbound by default as we don't currently support `incsearch`. Suggested binds:
|
||||||
*
|
*
|
||||||
|
* ```text
|
||||||
* bind / fillcmdline find
|
* bind / fillcmdline find
|
||||||
* bind ? fillcmdline find --reverse
|
* bind ? fillcmdline find --reverse
|
||||||
* bind n findnext --search-from-view
|
* bind n findnext --search-from-view
|
||||||
|
|
@ -1472,6 +1473,7 @@ export function scrollpage(n = 1, count = 1) {
|
||||||
* bind gn findselect
|
* bind gn findselect
|
||||||
* bind gN composite findnext --search-from-view --reverse; findselect
|
* bind gN composite findnext --search-from-view --reverse; findselect
|
||||||
* bind ,<Space> nohlsearch
|
* bind ,<Space> nohlsearch
|
||||||
|
* ```
|
||||||
*
|
*
|
||||||
* Argument: A string you want to search for.
|
* Argument: A string you want to search for.
|
||||||
*
|
*
|
||||||
|
|
@ -1512,7 +1514,7 @@ export function find(...args: string[]) {
|
||||||
* - `-f` or `--search-from-view` to search from the current view instead of the previous match
|
* - `-f` or `--search-from-view` to search from the current view instead of the previous match
|
||||||
* - `-?` or `--reverse` to reverse the sign of the number
|
* - `-?` or `--reverse` to reverse the sign of the number
|
||||||
*
|
*
|
||||||
* @param number - number of words to advance down the page (use 1 for next word, -1 for previous), default to 1
|
* @param args - flags and number of words to advance down the page (use 1 for next word, -1 for previous), default to 1
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
//#content
|
//#content
|
||||||
|
|
@ -2219,7 +2221,7 @@ export function urlparent(count = 1) {
|
||||||
* * -Q delete the given query
|
* * -Q delete the given query
|
||||||
* * -g graft a new path onto URL or parent path of it
|
* * -g graft a new path onto URL or parent path of it
|
||||||
* * -*u Use last argument as URL input instead of current URL
|
* * -*u Use last argument as URL input instead of current URL
|
||||||
* @param replacement the replacement arguments (depends on mode):
|
* @param args the replacement arguments (depends on mode):
|
||||||
* * -t <old> <new>
|
* * -t <old> <new>
|
||||||
* * -r <regexp> <new> [flags]
|
* * -r <regexp> <new> [flags]
|
||||||
* * -s <query> <value>
|
* * -s <query> <value>
|
||||||
|
|
@ -3187,18 +3189,18 @@ export async function undo(item = "recent"): Promise<number> {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Move the current tab to be just in front of the index specified.
|
/**
|
||||||
|
* Move the current tab to be just in front of the index specified.
|
||||||
Known bug: This supports relative movement with `tabmove +pos` and `tabmove -pos`, but autocomplete doesn't know that yet and will override positive and negative indexes.
|
*
|
||||||
|
* Known bug: This supports relative movement with `tabmove +pos` and `tabmove -pos`, but autocomplete doesn't know that yet and will override positive and negative indexes.
|
||||||
Put a space in front of tabmove if you want to disable completion and have the relative indexes at the command line.
|
*
|
||||||
|
* Put a space in front of tabmove if you want to disable completion and have the relative indexes at the command line.
|
||||||
Binds are unaffected.
|
*
|
||||||
|
* Binds are unaffected.
|
||||||
@param index
|
*
|
||||||
New index for the current tab.
|
* @param index New index for the current tab.
|
||||||
|
*
|
||||||
1,start,^ are aliases for the first index. 0,end,$ are aliases for the last index.
|
* 1,start,^ are aliases for the first index. 0,end,$ are aliases for the last index.
|
||||||
*/
|
*/
|
||||||
//#background
|
//#background
|
||||||
export async function tabmove(index = "$") {
|
export async function tabmove(index = "$") {
|
||||||
|
|
@ -3297,7 +3299,7 @@ export async function pin(index: string) {
|
||||||
Passing "all" to the excmd will operate on the mute state of all tabs.
|
Passing "all" to the excmd will operate on the mute state of all tabs.
|
||||||
Passing "unmute" to the excmd will unmute.
|
Passing "unmute" to the excmd will unmute.
|
||||||
Passing "toggle" to the excmd will toggle the state of `browser.tabs.tab.MutedInfo`
|
Passing "toggle" to the excmd will toggle the state of `browser.tabs.tab.MutedInfo`
|
||||||
@param string[] muteArgs
|
@param muteArgs
|
||||||
*/
|
*/
|
||||||
//#background
|
//#background
|
||||||
export async function mute(...muteArgs: string[]): Promise<void> {
|
export async function mute(...muteArgs: string[]): Promise<void> {
|
||||||
|
|
@ -3419,7 +3421,7 @@ export async function winopen(...args: string[]) {
|
||||||
/**
|
/**
|
||||||
* Close a window.
|
* Close a window.
|
||||||
*
|
*
|
||||||
* @param id - The window id. Defaults to the id of the current window.
|
* @param ids - The window ids. Defaults to the id of the current window.
|
||||||
*
|
*
|
||||||
* Example: `winclose`
|
* Example: `winclose`
|
||||||
*/
|
*/
|
||||||
|
|
@ -4245,7 +4247,7 @@ export async function clipboard(excmd: "open" | "yank" | "yankshort" | "yankcano
|
||||||
/** Copy an image to the clipboard.
|
/** Copy an image to the clipboard.
|
||||||
|
|
||||||
@param url
|
@param url
|
||||||
Absolute URL to the image to be copied. You can obtain an absolute URL from a relative one using [tri.urlutils.getAbsoluteURL](_src_lib_url_util_.html#getabsoluteurl).
|
Absolute URL to the image to be copied. You can obtain an absolute URL from a relative one using <a href="/static/docs/modules/_src_lib_url_util_.html#getabsoluteurl">tri.urlutils.getAbsoluteURL</a>.
|
||||||
*/
|
*/
|
||||||
//#background
|
//#background
|
||||||
export async function yankimage(url: string): Promise<void> {
|
export async function yankimage(url: string): Promise<void> {
|
||||||
|
|
@ -4265,16 +4267,16 @@ export async function yankimage(url: string): Promise<void> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Change active tab.
|
/**
|
||||||
|
* Change active tab.
|
||||||
@param id
|
*
|
||||||
A bare number means the current window is used. Starts at 1. 0 refers to last tab of the current window, -1 to penultimate tab, etc.
|
* @param id A bare number means the current window is used. Starts at 1. 0 refers to last tab of the current window, -1 to penultimate tab, etc.
|
||||||
|
*
|
||||||
A string following the following format: "[0-9]+.[0-9]+" means the first number being the index of the window that should be selected and the second one being the index of the tab within that window. [[taball]] has completions for this format.
|
* A string following the following format: "[0-9]+.[0-9]+" means the first number being the index of the window that should be selected and the second one being the index of the tab within that window. [[taball]] has completions for this format.
|
||||||
|
*
|
||||||
"%" denotes the current tab and "#" denotes the tab that was last accessed in this window. "P", "A", "M" and "D" indicate tab status (i.e. a pinned, audible, muted or discarded tab). Use `:set completions.Tab.statusstylepretty true` to display unicode characters instead. "P","A","M","D" can be used to filter by tab status in either setting.
|
* "%" denotes the current tab and "#" denotes the tab that was last accessed in this window. "P", "A", "M" and "D" indicate tab status (i.e. a pinned, audible, muted or discarded tab). Use `:set completions.Tab.statusstylepretty true` to display unicode characters instead. "P","A","M","D" can be used to filter by tab status in either setting.
|
||||||
|
*
|
||||||
A non integer string means to search the URL and title for matches, in this window if called from tab, all windows if called from taball. Title matches can contain '*' as a wildcard.
|
* A non integer string means to search the URL and title for matches, in this window if called from tab, all windows if called from taball. Title matches can contain '*' as a wildcard.
|
||||||
*/
|
*/
|
||||||
//#background
|
//#background
|
||||||
export async function tab(...id: string[]) {
|
export async function tab(...id: string[]) {
|
||||||
|
|
@ -4753,62 +4755,65 @@ const AUCMDS = ["DocStart", "DocLoad", "DocEnd", "TriStart", "TabEnter", "TabLef
|
||||||
export function getAutocmdEvents() {
|
export function getAutocmdEvents() {
|
||||||
return AUCMDS
|
return AUCMDS
|
||||||
}
|
}
|
||||||
/** Set autocmds to run when certain events happen.
|
/**
|
||||||
|
* Set autocmds to run when certain events happen.
|
||||||
*
|
*
|
||||||
* @param event Currently, 'TriStart', 'DocStart', 'DocLoad', 'DocEnd', 'TabEnter', 'TabLeft', 'FullscreenChange', 'FullscreenEnter', 'FullscreenLeft', 'HistoryState', 'HistoryPushState', 'HistoryReplace', 'UriChange', 'AuthRequired', 'BeforeRedirect', 'BeforeRequest', 'BeforeSendHeaders', 'Completed', 'ErrorOccured', 'HeadersReceived', 'ResponseStarted', and 'SendHeaders' are supported
|
* @param event Currently, 'TriStart', 'DocStart', 'DocLoad', 'DocEnd', 'TabEnter', 'TabLeft', 'FullscreenChange', 'FullscreenEnter', 'FullscreenLeft', 'HistoryState', 'HistoryPushState', 'HistoryReplace', 'UriChange', 'AuthRequired', 'BeforeRedirect', 'BeforeRequest', 'BeforeSendHeaders', 'Completed', 'ErrorOccured', 'HeadersReceived', 'ResponseStarted', and 'SendHeaders' are supported
|
||||||
*
|
*
|
||||||
- DocStart: When a webpage loading. Exactly, when tridactyl is loading in a page.
|
* - DocStart: When a webpage loading. Exactly, when tridactyl is loading in a page.
|
||||||
- DocLoad: When the whole html parsed, not including image/css loaded. (Just like jquery $(fn) or the [DOMContentLoaded event](https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event).)
|
* - DocLoad: When the whole html parsed, not including image/css loaded. (Just like jquery $(fn) or the [DOMContentLoaded event](https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event).)
|
||||||
- DocEnd: When a webpage unloaded/closed or backward/forward in history. Exactly, the [pagehide event](https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event).
|
* - DocEnd: When a webpage unloaded/closed or backward/forward in history. Exactly, the [pagehide event](https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event).
|
||||||
- TabEnter: When a tab get focus.
|
* - TabEnter: When a tab get focus.
|
||||||
- TabLeft: When a tab lost focus or closed.
|
* - TabLeft: When a tab lost focus or closed.
|
||||||
|
|
||||||
- A supported webRequest event (AuthRequired, BeforeRedirect, BeforeRequest, BeforeSendHeaders, Completed, ErrorOccured, HeadersReceived, ResponseStarted and SendHeaders): the corresponding [WebExtension webRequest event](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest#Events)
|
* - A supported webRequest event (AuthRequired, BeforeRedirect, BeforeRequest, BeforeSendHeaders, Completed, ErrorOccured, HeadersReceived, ResponseStarted and SendHeaders): the corresponding [WebExtension webRequest event](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest#Events)
|
||||||
|
|
||||||
- The 'HistoryState' event is triggered when a page uses the web history API to change the page location / URI. It should be used in preference to 'UriChange' below since it will use almost no resources. The 'UriChange' event may work on websites where 'HistoryState' does not.
|
* - The 'HistoryState' event is triggered when a page uses the web history API to change the page location / URI. It should be used in preference to 'UriChange' below since it will use almost no resources. The 'UriChange' event may work on websites where 'HistoryState' does not.
|
||||||
- The 'HistoryPushState' is triggered only when a page calls 'history.pushState' to change URI, and 'HistoryReplace' is for 'history.replace'. By the way, the HistoryPopState is not implemented.
|
* - The 'HistoryPushState' is triggered only when a page calls 'history.pushState' to change URI, and 'HistoryReplace' is for 'history.replace'. By the way, the HistoryPopState is not implemented.
|
||||||
- The 'UriChange' event is for "single page applications" which change their URIs without triggering DocStart or DocLoad events. It uses a timer to check whether the URI has changed, which has a small impact on battery life on pages matching the `url` parameter. We suggest using it sparingly.
|
* - The 'UriChange' event is for "single page applications" which change their URIs without triggering DocStart or DocLoad events. It uses a timer to check whether the URI has changed, which has a small impact on battery life on pages matching the `url` parameter. We suggest using it sparingly.
|
||||||
*
|
*
|
||||||
* @param url type depends on the event
|
* @param url type depends on the event
|
||||||
*
|
*
|
||||||
- For most events (DocStart, DocEnd, TabEnter, TabLeft, ...): a JavaScript regex (e.g. `www\.amazon\.co.*`)
|
* - For most events (DocStart, DocEnd, TabEnter, TabLeft, ...): a JavaScript regex (e.g. `www\.amazon\.co.*`)
|
||||||
- We just use [URL.search](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search)
|
* - We just use [URL.search](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search)
|
||||||
- For TriStart: regular expression that matches the hostname of the computer the autocmd should be run on. This requires the native messenger to be installed, except for the ".*" regular expression which will always be triggered, even without the native messenger.
|
* - For TriStart: regular expression that matches the hostname of the computer the autocmd should be run on. This requires the native messenger to be installed, except for the ".*" regular expression which will always be triggered, even without the native messenger.
|
||||||
- For webRequest events (AuthRequired, BeforeRedirect, BeforeRequest, BeforeSendHeaders, Completed, ErrorOccured, HeadersReceived, ResponseStarted and SendHeaders): a [URL match pattern](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns)
|
* - For webRequest events (AuthRequired, BeforeRedirect, BeforeRequest, BeforeSendHeaders, Completed, ErrorOccured, HeadersReceived, ResponseStarted and SendHeaders): a [URL match pattern](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns)
|
||||||
*
|
*
|
||||||
* @param command type depends on the event
|
* @param excmd type depends on the event
|
||||||
|
|
||||||
- For most events (DocStart, DocEnd, TabEnter, TabLeft, ...): the excmd to run (use [[composite]] to run multiple commands).
|
* - For most events (DocStart, DocEnd, TabEnter, TabLeft, ...): the excmd to run (use [[composite]] to run multiple commands).
|
||||||
- Example for zooming in more on a website:
|
* - Example for zooming in more on a website:
|
||||||
```
|
*
|
||||||
autocmd DocStart .*example\.com.* zoom 150 false TRI_FIRED_MOZ_TABID
|
* ```text
|
||||||
```
|
* autocmd DocStart .*example\.com.* zoom 150 false TRI_FIRED_MOZ_TABID
|
||||||
|
* ```
|
||||||
|
|
||||||
- For webRequest events (AuthRequired, BeforeRedirect, BeforeRequest, BeforeSendHeaders, Completed, ErrorOccured, HeadersReceived, ResponseStarted and SendHeaders): the text of a javascript function that should accept a [details objects specific to the event](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest#Events) and return a [blocking response](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/BlockingResponse). This JavaScript function will run in the background context.
|
* - For webRequest events (AuthRequired, BeforeRedirect, BeforeRequest, BeforeSendHeaders, Completed, ErrorOccured, HeadersReceived, ResponseStarted and SendHeaders): the text of a javascript function that should accept a [details objects specific to the event](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest#Events) and return a [blocking response](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/BlockingResponse). This JavaScript function will run in the background context.
|
||||||
- Example for redirecting from new to old reddit:
|
* - Example for redirecting from new to old reddit:
|
||||||
```
|
*
|
||||||
autocmd BeforeRequest https://www.reddit.com/r/* (details) => ({redirectUrl: details.url.replace(/^https:\/\/www\./, "https://old.")})
|
* ```text
|
||||||
```
|
* autocmd BeforeRequest https://www.reddit.com/r/* (details) => ({redirectUrl: details.url.replace(/^https:\/\/www\./, "https://old.")})
|
||||||
|
* ```
|
||||||
|
|
||||||
* For non-webRequest events, magic variables are available which are replaced with the relevant string at runtime:
|
* For non-webRequest events, magic variables are available which are replaced with the relevant string at runtime:
|
||||||
|
|
||||||
- `TRI_FIRED_MOZ_TABID`: Provides Mozilla's `tabID` associated with the fired event.
|
* - `TRI_FIRED_MOZ_TABID`: Provides Mozilla's `tabID` associated with the fired event.
|
||||||
- `TRI_FIRED_TRI_TABINDEX`: Provides tridactyls internal tab index associated with the fired event.
|
* - `TRI_FIRED_TRI_TABINDEX`: Provides tridactyls internal tab index associated with the fired event.
|
||||||
- `TRI_FIRED_MOZ_WINID`: Provides Mozilla's `windowId` associated with the fired event.
|
* - `TRI_FIRED_MOZ_WINID`: Provides Mozilla's `windowId` associated with the fired event.
|
||||||
- `TRI_FIRED_MOZ_OPENERTABID`: The ID of the tab that opened this tab.
|
* - `TRI_FIRED_MOZ_OPENERTABID`: The ID of the tab that opened this tab.
|
||||||
- `TRI_FIRED_ACTIVE`: Whether the tab is active in its window. This may be true even if the tab's window is not currently focused.
|
* - `TRI_FIRED_ACTIVE`: Whether the tab is active in its window. This may be true even if the tab's window is not currently focused.
|
||||||
- `TRI_FIRED_AUDIBLE`: Indicates whether the tab is producing sound (even if muted).
|
* - `TRI_FIRED_AUDIBLE`: Indicates whether the tab is producing sound (even if muted).
|
||||||
- `TRI_FIRED_MUTED`: Indicates whether the tab is muted.
|
* - `TRI_FIRED_MUTED`: Indicates whether the tab is muted.
|
||||||
- `TRI_FIRED_DISCARDED`: Whether the tab is discarded. A discarded tab is one whose content has been unloaded from memory.
|
* - `TRI_FIRED_DISCARDED`: Whether the tab is discarded. A discarded tab is one whose content has been unloaded from memory.
|
||||||
- `TRI_FIRED_HEIGHT`: The height of the tab in pixels.
|
* - `TRI_FIRED_HEIGHT`: The height of the tab in pixels.
|
||||||
- `TRI_FIRED_WIDTH`: The width of the tab in pixels.
|
* - `TRI_FIRED_WIDTH`: The width of the tab in pixels.
|
||||||
- `TRI_FIRED_HIDDEN`: Whether the tab is hidden.
|
* - `TRI_FIRED_HIDDEN`: Whether the tab is hidden.
|
||||||
- `TRI_FIRED_INCOGNITO`: Whether the tab is in a private browsing window.
|
* - `TRI_FIRED_INCOGNITO`: Whether the tab is in a private browsing window.
|
||||||
- `TRI_FIRED_ISARTICLE`: True if the tab can be rendered in Reader Mode, false otherwise.
|
* - `TRI_FIRED_ISARTICLE`: True if the tab can be rendered in Reader Mode, false otherwise.
|
||||||
- `TRI_FIRED_LASTACCESSED`: Time at which the tab was last accessed, in milliseconds since the epoch.
|
* - `TRI_FIRED_LASTACCESSED`: Time at which the tab was last accessed, in milliseconds since the epoch.
|
||||||
- `TRI_FIRED_PINNED`: Whether the tab is pinned.
|
* - `TRI_FIRED_PINNED`: Whether the tab is pinned.
|
||||||
- `TRI_FIRED_TITLE`: The title of the tab.
|
* - `TRI_FIRED_TITLE`: The title of the tab.
|
||||||
- `TRI_FIRED_URL`: The URL of the document that the tab is displaying.
|
* - `TRI_FIRED_URL`: The URL of the document that the tab is displaying.
|
||||||
|
|
||||||
* For debugging, use `:set logging.autocmds debug` and check the Firefox web console. `WebRequest` events have no logging.
|
* For debugging, use `:set logging.autocmds debug` and check the Firefox web console. `WebRequest` events have no logging.
|
||||||
*
|
*
|
||||||
|
|
@ -5297,98 +5302,103 @@ export function setnull(...keys: string[]) {
|
||||||
const KILL_STACK: Element[] = []
|
const KILL_STACK: Element[] = []
|
||||||
// {{{ HINTMODE
|
// {{{ HINTMODE
|
||||||
|
|
||||||
/** Hint a page.
|
/**
|
||||||
|
* Hint a page.
|
||||||
@param args Arguments to the `:hint` command. Multiple flags can be combined as long as they don't conflict.
|
*
|
||||||
Selectors can be specified either standalone (without a flag preceding them) or with the `-c` option. Arguments that
|
* @param args Arguments to the `:hint` command. Multiple flags can be combined as long as they don't conflict.
|
||||||
take callbacks (`-F` or `-W`) should be specified last, as they consume the rest of the command line.
|
* Selectors can be specified either standalone (without a flag preceding them) or with the `-c` option. Arguments that
|
||||||
|
* take callbacks (`-F` or `-W`) should be specified last, as they consume the rest of the command line.
|
||||||
Hinting action flags (only one can be specified):
|
*
|
||||||
- -t open in a new foreground tab
|
* Hinting action flags (only one can be specified):
|
||||||
- -b open in background
|
*
|
||||||
- -y copy (yank) link's target to clipboard
|
* - -t open in a new foreground tab
|
||||||
- -p copy an element's text to the clipboard
|
* - -b open in background
|
||||||
- -h select an element (as if you click-n-dragged over it)
|
* - -y copy (yank) link's target to clipboard
|
||||||
- -P copy an element's title/alt text to the clipboard
|
* - -p copy an element's text to the clipboard
|
||||||
- -r read an element's text with text-to-speech
|
* - -h select an element (as if you click-n-dragged over it)
|
||||||
- -i view an image
|
* - -P copy an element's title/alt text to the clipboard
|
||||||
- -I view an image in a new tab
|
* - -r read an element's text with text-to-speech
|
||||||
- -k irreversibly deletes an element from the page (until reload)
|
* - -i view an image
|
||||||
- -K hides an element on the page; hidden elements can be restored using [[elementunhide]].
|
* - -I view an image in a new tab
|
||||||
- -s save (download) the linked resource
|
* - -k irreversibly deletes an element from the page (until reload)
|
||||||
- -S save the linked image
|
* - -K hides an element on the page; hidden elements can be restored using [[elementunhide]].
|
||||||
- -a save-as the linked resource
|
* - -s save (download) the linked resource
|
||||||
- -A save-as the linked image
|
* - -S save the linked image
|
||||||
- -; focus an element and set it as the element or the child of the element to scroll
|
* - -a save-as the linked resource
|
||||||
- -# yank an element's anchor URL to clipboard
|
* - -A save-as the linked image
|
||||||
- -w open in new window
|
* - -; focus an element and set it as the element or the child of the element to scroll
|
||||||
- -wp open in new private window
|
* - -# yank an element's anchor URL to clipboard
|
||||||
- -z scroll an element to the top of the viewport
|
* - -w open in new window
|
||||||
- `-pipe selector key` e.g, `-pipe a href` returns the URL of the chosen link on a page. Only makes sense with `composite`, e.g, `composite hint -pipe .some-class>a textContent | yank`. If you don't select a hint (i.e. press <Esc>), will return an empty string. Most useful when used like `-c` to do things other than opening links. NB: the query selector cannot contain any spaces.
|
* - -wp open in new private window
|
||||||
- `-W excmd...` append hint href to excmd and execute, e.g, `hint -W mpvsafe` to open YouTube videos. NB: appending to bare [[exclaim]] is dangerous - see `get exaliases.mpvsafe` for an example of how to to it safely. If you need to use a query selector, use `-pipe` instead.
|
* - -z scroll an element to the top of the viewport
|
||||||
- -F [callback] - run a custom callback on the selected hint, e.g. `hint -JF e => {tri.excmds.tabopen("-b",e.href); e.remove()}`.
|
* - `-pipe selector key` e.g, `-pipe a href` returns the URL of the chosen link on a page. Only makes sense with `composite`, e.g, `composite hint -pipe .some-class>a textContent | yank`. If you don't select a hint (i.e. press `<Esc>`), will return an empty string. Most useful when used like `-c` to do things other than opening links. NB: the query selector cannot contain any spaces.
|
||||||
|
* - `-W excmd...` append hint href to excmd and execute, e.g, `hint -W mpvsafe` to open YouTube videos. NB: appending to bare [[exclaim]] is dangerous - see `get exaliases.mpvsafe` for an example of how to to it safely. If you need to use a query selector, use `-pipe` instead.
|
||||||
Element selection flags:
|
* - -F [callback] - run a custom callback on the selected hint, e.g. `hint -JF e => {tri.excmds.tabopen("-b",e.href); e.remove()}`.
|
||||||
- -c [selector] hint links that match the css selector
|
*
|
||||||
- `bind ;c hint -c [class*="expand"],[class*="togg"]` works particularly well on reddit and HN
|
* Element selection flags:
|
||||||
- this works with most other hint modes, with the caveat that if other hint mode takes arguments your selector must contain no spaces, i.e. `hint -c[yourOtherFlag] [selector] [your other flag's arguments, which may contain spaces]`
|
*
|
||||||
- -C [selector] like `-c [selector]` but also hints all elements that would normally be hinted given the other options selected
|
* - -c [selector] hint links that match the css selector
|
||||||
- -x [selector] exclude the matched elements from hinting
|
* - `bind ;c hint -c [class*="expand"],[class*="togg"]` works particularly well on reddit and HN
|
||||||
- -f [text] hint links and inputs that display the given text
|
* - this works with most other hint modes, with the caveat that if other hint mode takes arguments your selector must contain no spaces, i.e. `hint -c[yourOtherFlag] [selector] [your other flag's arguments, which may contain spaces]`
|
||||||
- `bind <c-e> hint -f Edit`
|
* - -C [selector] like `-c [selector]` but also hints all elements that would normally be hinted given the other options selected
|
||||||
- Backslashes can escape spaces: `bind <c-s> hint -f Save\ as`
|
* - -x [selector] exclude the matched elements from hinting
|
||||||
- -fr [text] use RegExp to hint the links and inputs
|
* - -f [text] hint links and inputs that display the given text
|
||||||
- -J* disable javascript hints. Don't generate hints related to javascript events. This is particularly useful when used with the `-c` option when you want to generate only hints for the specified css selectors. Also useful on sites with plenty of useless javascript elements such as google.com
|
* - `bind <c-e> hint -f Edit`
|
||||||
- -V create hints for invisible elements. By default, elements outside the viewport when calling :hint are not hinted, this includes them anyways.
|
* - Backslashes can escape spaces: `bind <c-s> hint -f Save\ as`
|
||||||
|
* - -fr [text] use RegExp to hint the links and inputs
|
||||||
Hinting mode selection:
|
* - -J* disable javascript hints. Don't generate hints related to javascript events. This is particularly useful when used with the `-c` option when you want to generate only hints for the specified css selectors. Also useful on sites with plenty of useless javascript elements such as google.com
|
||||||
- -q* quick (or rapid) hints mode. Stay in hint mode until you press <Esc>, e.g. `:hint -qb` to open multiple hints in the background or `:hint -qW excmd` to execute excmd once for each hint. This will return an array containing all elements or the result of executed functions (e.g. `hint -qpipe a href` will return an array of links).
|
* - -V create hints for invisible elements. By default, elements outside the viewport when calling :hint are not hinted, this includes them anyways.
|
||||||
- For example, use `bind ;jg hint -Jc .rc > .r > a` on google.com to generate hints only for clickable search results of a given query
|
*
|
||||||
- -! execute all hints without waiting for a selection
|
* Hinting mode selection:
|
||||||
- For example, `hint -!bf Comments` opens in background tabs all visible links whose text matches `Comments`
|
*
|
||||||
|
* - -q* quick (or rapid) hints mode. Stay in hint mode until you press `<Esc>`, e.g. `:hint -qb` to open multiple hints in the background or `:hint -qW excmd` to execute excmd once for each hint. This will return an array containing all elements or the result of executed functions (e.g. `hint -qpipe a href` will return an array of links).
|
||||||
Deprecated options:
|
* - For example, use `bind ;jg hint -Jc .rc > .r > a` on google.com to generate hints only for clickable search results of a given query
|
||||||
- -br deprecated, use `-qb` instead
|
* - -! execute all hints without waiting for a selection
|
||||||
|
* - For example, `hint -!bf Comments` opens in background tabs all visible links whose text matches `Comments`
|
||||||
Excepting the custom selector mode, background hint mode and the "immediate" modifier, each of these hint modes is available by default as `;<option character>`, so e.g. `;y` to yank a link's target; `;g<option character>` starts rapid hint mode for all modes where it makes sense, and some others.
|
*
|
||||||
|
* Deprecated options:
|
||||||
To open a hint in the background, the default bind is `F`.
|
*
|
||||||
|
* - -br deprecated, use `-qb` instead
|
||||||
Ex-commands available exclusively in hint mode are listed [here](/static/docs/modules/_src_content_hinting_.html)
|
*
|
||||||
|
* Excepting the custom selector mode, background hint mode and the "immediate" modifier, each of these hint modes is available by default as `;<option character>`, so e.g. `;y` to yank a link's target; `;g<option character>` starts rapid hint mode for all modes where it makes sense, and some others.
|
||||||
Related settings:
|
*
|
||||||
- "hintchars": "hjklasdfgyuiopqwertnmzxcvb"
|
* To open a hint in the background, the default bind is `F`.
|
||||||
- "hintfiltermode": "simple" | "vimperator" | "vimperator-reflow"
|
*
|
||||||
- "relatedopenpos": "related" | "next" | "last"
|
* Ex-commands available exclusively in hint mode are listed [here](/static/docs/modules/_src_content_hinting_.html)
|
||||||
- "hintuppercase": "true" | "false"
|
*
|
||||||
- "hintnames": "short" | "uniform" | "numeric"
|
* Related settings:
|
||||||
- "hintdelay": 300
|
*
|
||||||
- "hintshift": "true" | "false"
|
* - "hintchars": "hjklasdfgyuiopqwertnmzxcvb"
|
||||||
- "hintautoselect": "true" | "false"
|
* - "hintfiltermode": "simple" | "vimperator" | "vimperator-reflow"
|
||||||
|
* - "relatedopenpos": "related" | "next" | "last"
|
||||||
With "short" names, Tridactyl will generate short hints that
|
* - "hintuppercase": "true" | "false"
|
||||||
are never prefixes of each other. With "uniform", Tridactyl
|
* - "hintnames": "short" | "uniform" | "numeric"
|
||||||
will generate hints of uniform length. In either case, the
|
* - "hintdelay": 300
|
||||||
hints are generated from the set in "hintchars".
|
* - "hintshift": "true" | "false"
|
||||||
|
* - "hintautoselect": "true" | "false"
|
||||||
With "numeric" names, hints are always assigned using
|
*
|
||||||
sequential integers, and "hintchars" is ignored. This has the
|
* With "short" names, Tridactyl will generate short hints that
|
||||||
disadvantage that some hints are prefixes of others (and you
|
* are never prefixes of each other. With "uniform", Tridactyl
|
||||||
need to hit space or enter to select such a hint). But it has
|
* will generate hints of uniform length. In either case, the
|
||||||
the advantage that the hints tend to be more predictable
|
* hints are generated from the set in "hintchars".
|
||||||
(e.g., a news site will have the same hints for its
|
*
|
||||||
boilerplate each time you visit it, even if the number of
|
* With "numeric" names, hints are always assigned using
|
||||||
links in the main body changes).
|
* sequential integers, and "hintchars" is ignored. This has the
|
||||||
|
* disadvantage that some hints are prefixes of others (and you
|
||||||
There are some extra hint "modes" that are actually just normal-mode binds. We'll list them here:
|
* need to hit space or enter to select such a hint). But it has
|
||||||
|
* the advantage that the hints tend to be more predictable
|
||||||
- `;gv` - "open link in MPV" - only available if you have [[native]] installed and `mpv` on your PATH
|
* (e.g., a news site will have the same hints for its
|
||||||
- `;m` and `;M` - do a reverse image search using Google in the current tab and a new tab
|
* boilerplate each time you visit it, even if the number of
|
||||||
- `;x` and `;X` - move cursor to element and perform a real click or ctrl-shift-click (to open in a new foreground tab). Only available on Linux, if you have [[native]] installed and `xdotool` on your PATH
|
* links in the main body changes).
|
||||||
- `;d` and `;gd` - open links in discarded background tabs (defer loading until tab is switched to)
|
*
|
||||||
|
* There are some extra hint "modes" that are actually just normal-mode binds. We'll list them here:
|
||||||
NB: by default, hinting respects whether links say they should be opened in new tabs (i.e. `target=_blank`). If you wish to override this you can use `:hint -JW open` to force the hints to open in the current tab. JavaScript hints (grey ones) will always open wherever they want, but if you want to include these anyway you can use `:hint -W open`.
|
*
|
||||||
|
* - `;gv` - "open link in MPV" - only available if you have [[native]] installed and `mpv` on your PATH
|
||||||
|
* - `;m` and `;M` - do a reverse image search using Google in the current tab and a new tab
|
||||||
|
* - `;x` and `;X` - move cursor to element and perform a real click or ctrl-shift-click (to open in a new foreground tab). Only available on Linux, if you have [[native]] installed and `xdotool` on your PATH
|
||||||
|
* - `;d` and `;gd` - open links in discarded background tabs (defer loading until tab is switched to)
|
||||||
|
*
|
||||||
|
* NB: by default, hinting respects whether links say they should be opened in new tabs (i.e. `target=_blank`). If you wish to override this you can use `:hint -JW open` to force the hints to open in the current tab. JavaScript hints (grey ones) will always open wherever they want, but if you want to include these anyway you can use `:hint -W open`.
|
||||||
*/
|
*/
|
||||||
//#content
|
//#content
|
||||||
export async function hint(...args: string[]): Promise<any> {
|
export async function hint(...args: string[]): Promise<any> {
|
||||||
|
|
@ -5777,7 +5787,7 @@ export async function ttscontrol(action: string) {
|
||||||
throw new Error("Unknown text-to-speech action: " + action)
|
throw new Error("Unknown text-to-speech action: " + action)
|
||||||
}
|
}
|
||||||
|
|
||||||
return TTS.doAction(action as TTS.Action)
|
return TTS.doAction(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
//}}}
|
//}}}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ function initTridactylSettingElem(
|
||||||
bindingNode = document.createElement("p")
|
bindingNode = document.createElement("p")
|
||||||
bindingNode.className = `TridactylSetting Tridactyl${kind}`
|
bindingNode.className = `TridactylSetting Tridactyl${kind}`
|
||||||
bindingNode.textContent = kind + ": "
|
bindingNode.textContent = kind + ": "
|
||||||
elem.insertBefore(bindingNode, elem.children[2])
|
elem.insertBefore(bindingNode, elem.children[1])
|
||||||
}
|
}
|
||||||
return bindingNode as HTMLElement
|
return bindingNode as HTMLElement
|
||||||
}
|
}
|
||||||
|
|
@ -137,9 +137,11 @@ function addSettingInputs() {
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
Array.from(
|
Array.from(
|
||||||
document.querySelectorAll<HTMLAnchorElement>("a.tsd-anchor"),
|
document.querySelectorAll<HTMLHeadingElement>(
|
||||||
|
".tsd-panel.tsd-member > h3.tsd-anchor-link[id]",
|
||||||
|
),
|
||||||
).map(
|
).map(
|
||||||
async (a: HTMLAnchorElement) => {
|
async (a: HTMLHeadingElement) => {
|
||||||
const section = a.parentNode
|
const section = a.parentNode
|
||||||
|
|
||||||
const settingName = a.id.split(".")
|
const settingName = a.id.split(".")
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@ import * as binding from "@src/lib/binding"
|
||||||
import * as platform from "@src/lib/platform"
|
import * as platform from "@src/lib/platform"
|
||||||
import { DeepPartial } from "tsdef"
|
import { DeepPartial } from "tsdef"
|
||||||
|
|
||||||
declare function structuredClone<T>(value: T): T // delete me once we move off typescript 3
|
|
||||||
|
|
||||||
/* Remove all nulls from objects recursively
|
/* Remove all nulls from objects recursively
|
||||||
* NB: also applies to arrays
|
* NB: also applies to arrays
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -100,9 +100,7 @@ export async function remove(name: string) {
|
||||||
TODO: pass an object to this when tridactyl gets proper flag parsing
|
TODO: pass an object to this when tridactyl gets proper flag parsing
|
||||||
NOTE: while browser.contextualIdentities.create does check for valid color/icon combos, browser.contextualIdentities.update does not.
|
NOTE: while browser.contextualIdentities.create does check for valid color/icon combos, browser.contextualIdentities.update does not.
|
||||||
@param containerId Expects a cookieStringId e.g. "firefox-container-n".
|
@param containerId Expects a cookieStringId e.g. "firefox-container-n".
|
||||||
@param name the new name of the container
|
@param updateObj the new name, color, and icon of the container
|
||||||
@param color the new color of the container
|
|
||||||
@param icon the new icon of the container
|
|
||||||
*/
|
*/
|
||||||
export function update(
|
export function update(
|
||||||
containerId: string,
|
containerId: string,
|
||||||
|
|
@ -139,7 +137,7 @@ export async function getFromId(
|
||||||
|
|
||||||
/** Fetches all containers from Firefox's contextual identities API and checks if one exists with the specified name.
|
/** Fetches all containers from Firefox's contextual identities API and checks if one exists with the specified name.
|
||||||
Note: This operation is entirely case-insensitive.
|
Note: This operation is entirely case-insensitive.
|
||||||
@param string cname
|
@param cname
|
||||||
@returns boolean Returns true when cname matches an existing container or on query error.
|
@returns boolean Returns true when cname matches an existing container or on query error.
|
||||||
*/
|
*/
|
||||||
export async function exists(cname: string): Promise<boolean> {
|
export async function exists(cname: string): Promise<boolean> {
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ export function setContentEditableValues(e, text, start, end) {
|
||||||
/**
|
/**
|
||||||
* Take an editor function as parameter and return it wrapped in a function that will handle grabbing text and caret position from the HTML element it takes as parameter
|
* Take an editor function as parameter and return it wrapped in a function that will handle grabbing text and caret position from the HTML element it takes as parameter
|
||||||
*
|
*
|
||||||
* @param editor_function A function that takes a [string, selectionStart, selectionEnd] tuple as argument and returns a [string, selectionStart, selectionEnd] tuple corresponding to the new state of the text.
|
* @param fn A function that takes a [string, selectionStart, selectionEnd] tuple as argument and returns a [string, selectionStart, selectionEnd] tuple corresponding to the new state of the text.
|
||||||
*
|
*
|
||||||
* @return boolean Whether the editor function was actually called or not
|
* @return boolean Whether the editor function was actually called or not
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ const bracketexpr_parser = new Parser(bracketexpr_grammar)
|
||||||
|
|
||||||
// unspoofable keyboard events
|
// unspoofable keyboard events
|
||||||
// this should be ~the only place in the code that accepts KeyboardEvent
|
// this should be ~the only place in the code that accepts KeyboardEvent
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/no-restricted-types
|
||||||
export type TrustedKeyboardEvent = KeyboardEvent & { readonly isTrusted: true }
|
export type TrustedKeyboardEvent = KeyboardEvent & { readonly isTrusted: true }
|
||||||
|
|
||||||
export const guarded = memoise(
|
export const guarded = memoise(
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ function backgroundHandler<
|
||||||
return handler.apply(receiver, message.args)
|
return handler.apply(receiver, message.args)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupListener<Root>(root: Root) {
|
export function setupListener<Root extends object>(root: Root) {
|
||||||
browser.runtime.onMessage.addListener(
|
browser.runtime.onMessage.addListener(
|
||||||
(message: any) => {
|
(message: any) => {
|
||||||
if (message.type in root) {
|
if (message.type in root) {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Runtime metadata over `typedoc --json` output for src/excmds.ts and
|
* Runtime helpers over the compact metadata schema generated at build time.
|
||||||
* src/lib/config.ts. Exposes plain-object indexes (keyed by symbol name) plus
|
* TypeDoc-specific conversion stays in scripts/convert_typedoc_metadata.js.
|
||||||
* a small set of free helpers that operate on raw typedoc nodes.
|
|
||||||
*
|
|
||||||
* @hidden symbols are dropped by typedoc itself before they reach this loader,
|
|
||||||
* so consumers never see them.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import metadataJson from "../.metadata.generated.json"
|
import metadataJson from "../.metadata.generated.json"
|
||||||
|
|
@ -12,123 +8,33 @@ import staticThemesJson from "../.themes.generated.json"
|
||||||
|
|
||||||
export const staticThemes: string[] = staticThemesJson
|
export const staticThemes: string[] = staticThemesJson
|
||||||
|
|
||||||
// =============================================================================
|
type Node = Record<string, any>
|
||||||
// Indexes — built once at module load by walking the typedoc tree.
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
type Node = any
|
const metadata = metadataJson as unknown as {
|
||||||
|
version: number
|
||||||
const reflections: Record<number, Node> = {}
|
commands: Record<string, Node>
|
||||||
const fileBuckets: Record<
|
settings: Record<string, Node>
|
||||||
string,
|
|
||||||
{ functions: Record<string, Node>; classes: Record<string, Node> }
|
|
||||||
> = {
|
|
||||||
excmds: { functions: {}, classes: {} },
|
|
||||||
"lib/config": { functions: {}, classes: {} },
|
|
||||||
}
|
}
|
||||||
|
if (metadata.version !== 1)
|
||||||
|
throw new Error(`Unsupported metadata version: ${metadata.version}`)
|
||||||
|
|
||||||
function moduleName(node: Node): string {
|
export const excmdsFunctions = metadata.commands
|
||||||
return (node.name || "").replace(/^"|"$/g, "").replace(/\\/g, "/")
|
export const defaultConfigMembers = metadata.settings
|
||||||
}
|
|
||||||
|
|
||||||
function walk(node: Node) {
|
|
||||||
if (!node || typeof node !== "object") return
|
|
||||||
if (Array.isArray(node)) {
|
|
||||||
for (const v of node) walk(v)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (node.id !== undefined) reflections[node.id] = node
|
|
||||||
if (node.kindString === "Module") {
|
|
||||||
const bucket = fileBuckets[moduleName(node)]
|
|
||||||
for (const child of bucket ? node.children || [] : []) {
|
|
||||||
if (child.kindString === "Function") {
|
|
||||||
bucket.functions[child.name] = child
|
|
||||||
} else if (child.kindString === "Class") {
|
|
||||||
bucket.classes[child.name] = child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node.children) walk(node.children)
|
|
||||||
}
|
|
||||||
walk(metadataJson)
|
|
||||||
|
|
||||||
export const excmdsFunctions: Record<string, Node> =
|
|
||||||
fileBuckets.excmds.functions
|
|
||||||
|
|
||||||
const defaultConfig: Node | undefined =
|
|
||||||
fileBuckets["lib/config"].classes["default_config"]
|
|
||||||
|
|
||||||
export const defaultConfigMembers: Record<string, Node> = (() => {
|
|
||||||
const out: Record<string, Node> = {}
|
|
||||||
for (const ch of defaultConfig?.children || []) out[ch.name] = ch
|
|
||||||
return out
|
|
||||||
})()
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Doc / type access on function and class-member nodes.
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
function readComment(c: Node | undefined): string {
|
|
||||||
if (!c) return ""
|
|
||||||
let s: string = c.shortText || ""
|
|
||||||
if (c.text) s += (s ? "\n\n" : "") + c.text
|
|
||||||
return s.replace(/\n+$/, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getDoc(node: Node | undefined): string {
|
export function getDoc(node: Node | undefined): string {
|
||||||
if (!node) return ""
|
return node?.doc || ""
|
||||||
return (
|
|
||||||
readComment(node.signatures?.[0]?.comment) || readComment(node.comment)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function memberDoc(node: Node | undefined): string {
|
export function memberDoc(node: Node | undefined): string {
|
||||||
if (!node) return ""
|
return node?.doc || ""
|
||||||
if (node.kindString === "Accessor") {
|
|
||||||
const sig = (node.getSignature || [])[0] || (node.setSignature || [])[0]
|
|
||||||
if (sig?.comment) return readComment(sig.comment)
|
|
||||||
}
|
|
||||||
return readComment(node.comment)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a typedoc type node for a class member, preserving the children of
|
|
||||||
* inferred object literals so downstream helpers can inspect their types.
|
|
||||||
*/
|
|
||||||
export function memberType(node: Node | undefined): Node | undefined {
|
export function memberType(node: Node | undefined): Node | undefined {
|
||||||
if (!node) return undefined
|
return node?.type
|
||||||
if (node.kindString === "Object literal") {
|
|
||||||
return { type: "reflection", declaration: node }
|
|
||||||
}
|
|
||||||
if (node.type) return node.type
|
|
||||||
if (node.kindString === "Accessor") {
|
|
||||||
const sig = (node.getSignature || [])[0] || (node.setSignature || [])[0]
|
|
||||||
return sig?.type
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Parameter list for a function node — each entry has `name`, `type`, `flags`. */
|
|
||||||
export function paramTypes(fnNode: Node | undefined): Node[] {
|
export function paramTypes(fnNode: Node | undefined): Node[] {
|
||||||
return fnNode?.signatures?.[0]?.parameters || []
|
return fnNode?.params || []
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Type coercion + stringification over typedoc type nodes.
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
function resolveType(t: Node | undefined): Node | undefined {
|
|
||||||
const seen = new Set<number>()
|
|
||||||
while (
|
|
||||||
t?.type === "reference" &&
|
|
||||||
t.id !== undefined &&
|
|
||||||
!t.typeArguments?.length &&
|
|
||||||
!seen.has(t.id)
|
|
||||||
) {
|
|
||||||
seen.add(t.id)
|
|
||||||
t = reflections[t.id]?.type || t
|
|
||||||
}
|
|
||||||
return t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function intrinsicName(t) {
|
function intrinsicName(t) {
|
||||||
|
|
@ -149,7 +55,6 @@ function intrinsicName(t) {
|
||||||
|
|
||||||
/** Normalised kind: "string" | "number" | "boolean" | "object" | "array" | "void" | "any" | ... */
|
/** Normalised kind: "string" | "number" | "boolean" | "object" | "array" | "void" | "any" | ... */
|
||||||
export function typeKind(t: Node | undefined): string {
|
export function typeKind(t: Node | undefined): string {
|
||||||
t = resolveType(t)
|
|
||||||
if (!t) return "any"
|
if (!t) return "any"
|
||||||
switch (t.type) {
|
switch (t.type) {
|
||||||
case "intrinsic":
|
case "intrinsic":
|
||||||
|
|
@ -170,7 +75,6 @@ export function typeKind(t: Node | undefined): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function typeToString(t: Node | undefined): string {
|
export function typeToString(t: Node | undefined): string {
|
||||||
t = resolveType(t)
|
|
||||||
if (!t) return "any"
|
if (!t) return "any"
|
||||||
switch (t.type) {
|
switch (t.type) {
|
||||||
case "intrinsic":
|
case "intrinsic":
|
||||||
|
|
@ -235,7 +139,6 @@ function convertIntrinsic(t, value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convert(t: Node | undefined, value: any): any {
|
export function convert(t: Node | undefined, value: any): any {
|
||||||
t = resolveType(t)
|
|
||||||
if (!t) return value
|
if (!t) return value
|
||||||
switch (t.type) {
|
switch (t.type) {
|
||||||
case "intrinsic":
|
case "intrinsic":
|
||||||
|
|
@ -314,7 +217,6 @@ export function convertMember(
|
||||||
path: string[],
|
path: string[],
|
||||||
value: any,
|
value: any,
|
||||||
): any {
|
): any {
|
||||||
t = resolveType(t)
|
|
||||||
const decl = t?.type === "reflection" ? t.declaration : undefined
|
const decl = t?.type === "reflection" ? t.declaration : undefined
|
||||||
const named: Record<string, Node> = {}
|
const named: Record<string, Node> = {}
|
||||||
let indexSig: Node | undefined
|
let indexSig: Node | undefined
|
||||||
|
|
@ -322,9 +224,8 @@ export function convertMember(
|
||||||
const childType = memberType(ch)
|
const childType = memberType(ch)
|
||||||
if (ch.name && childType) named[ch.name] = childType
|
if (ch.name && childType) named[ch.name] = childType
|
||||||
}
|
}
|
||||||
const idx = decl?.indexSignature
|
for (const sig of decl?.indexSignatures || [])
|
||||||
const idxArr = Array.isArray(idx) ? idx : idx ? [idx] : []
|
if (sig?.type) indexSig = sig.type
|
||||||
for (const sig of idxArr) if (sig?.type) indexSig = sig.type
|
|
||||||
|
|
||||||
const sub = named[path[0]] ?? indexSig
|
const sub = named[path[0]] ?? indexSig
|
||||||
if (!sub) return value
|
if (!sub) return value
|
||||||
|
|
|
||||||
|
|
@ -232,8 +232,8 @@ export async function getBestEditor(): Promise<string> {
|
||||||
* helpful error message in the command line if the native messenger is not
|
* helpful error message in the command line if the native messenger is not
|
||||||
* installed, or is the wrong version.
|
* installed, or is the wrong version.
|
||||||
*
|
*
|
||||||
* @arg version: A string representing the minimal required version.
|
* @param version A string representing the minimal required version.
|
||||||
* @arg interactive: True if a message should be displayed on version mismatch.
|
* @param interactive True if a message should be displayed on version mismatch.
|
||||||
* @return false if the required version is higher than the currently available
|
* @return false if the required version is higher than the currently available
|
||||||
* native messenger version.
|
* native messenger version.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -139,11 +139,9 @@ async function tabIdsOrCurrent(ids?: number | number[]): Promise<number[]> {
|
||||||
*/
|
*/
|
||||||
export async function setTabTgroup(name: string, id?: number | number[]) {
|
export async function setTabTgroup(name: string, id?: number | number[]) {
|
||||||
const ids = await tabIdsOrCurrent(id)
|
const ids = await tabIdsOrCurrent(id)
|
||||||
return Promise.all(
|
return ids.map(id => {
|
||||||
ids.map(id => {
|
|
||||||
browserBg.sessions.setTabValue(id, "tridactyl-tgroup", name)
|
browserBg.sessions.setTabValue(id, "tridactyl-tgroup", name)
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -154,11 +152,9 @@ export async function setTabTgroup(name: string, id?: number | number[]) {
|
||||||
*/
|
*/
|
||||||
export async function clearTabTgroup(id?: number | number[]) {
|
export async function clearTabTgroup(id?: number | number[]) {
|
||||||
const ids = await tabIdsOrCurrent(id)
|
const ids = await tabIdsOrCurrent(id)
|
||||||
return Promise.all(
|
return ids.map(id => {
|
||||||
ids.map(id => {
|
|
||||||
browserBg.sessions.removeTabValue(id, "tridactyl-tgroup")
|
browserBg.sessions.removeTabValue(id, "tridactyl-tgroup")
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -209,7 +205,7 @@ export async function tgroupLastTabId(name: string, previous = false) {
|
||||||
/**
|
/**
|
||||||
* Clear stored information for a tab group.
|
* Clear stored information for a tab group.
|
||||||
*
|
*
|
||||||
* @param name The name of the tab group.
|
* @param oldName The name of the tab group.
|
||||||
* @param newName A name to rename the group to.
|
* @param newName A name to rename the group to.
|
||||||
* @param id The id of the window. Use the current window if not specified.
|
* @param id The id of the window. Use the current window if not specified.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ function getExtensionForMimetype(mime: string): string {
|
||||||
* - otherwise, use the hostname of the URL
|
* - otherwise, use the hostname of the URL
|
||||||
* - if that fails, "download"
|
* - if that fails, "download"
|
||||||
*
|
*
|
||||||
* @param URL the URL to make a filename for
|
* @param url the URL to make a filename for
|
||||||
* @return the filename according to the above rules
|
* @return the filename according to the above rules
|
||||||
*/
|
*/
|
||||||
export function getDownloadFilenameForUrl(url: URL): string {
|
export function getDownloadFilenameForUrl(url: URL): string {
|
||||||
|
|
@ -260,7 +260,7 @@ function setUrlQueries(url: URL, qys: string[]) {
|
||||||
* all instances are removed
|
* all instances are removed
|
||||||
*
|
*
|
||||||
* @param url the URL to act on
|
* @param url the URL to act on
|
||||||
* @param query the query to delete
|
* @param matchQuery the query to delete
|
||||||
*
|
*
|
||||||
* @return the modified URL
|
* @return the modified URL
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export function measured(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like the @measured decorator, but properly handles async functions
|
* Like the `@measured` decorator, but properly handles async functions
|
||||||
* by chaining a resolution onto the promise that marks completion
|
* by chaining a resolution onto the promise that marks completion
|
||||||
* when the function resolves its promise.
|
* when the function resolves its promise.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ const state = new Proxy(overlay, {
|
||||||
}
|
}
|
||||||
browser.storage.local.set({
|
browser.storage.local.set({
|
||||||
state: R.pick(PERSISTENT_KEYS, target),
|
state: R.pick(PERSISTENT_KEYS, target),
|
||||||
} as any)
|
})
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2915,6 +2915,7 @@ img {
|
||||||
* THE FOLLOWING CSS SOURCE CODE WAS ADDED BY THE TRIDACTYL PROJECT
|
* THE FOLLOWING CSS SOURCE CODE WAS ADDED BY THE TRIDACTYL PROJECT
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
.container.container-main {
|
.container.container-main {
|
||||||
|
display: block;
|
||||||
padding-top: 0px !important;
|
padding-top: 0px !important;
|
||||||
}
|
}
|
||||||
.tsd-navigation {
|
.tsd-navigation {
|
||||||
|
|
@ -2942,6 +2943,11 @@ body {
|
||||||
background: var(--tridactyl-bg);
|
background: var(--tridactyl-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tsd-panel.tsd-member,
|
||||||
|
.tsd-member .tsd-description {
|
||||||
|
color: var(--tridactyl-fg);
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #05a805;
|
color: #05a805;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
107
src/tridactyl.d.ts
vendored
107
src/tridactyl.d.ts
vendored
|
|
@ -9,103 +9,25 @@ interface Number {
|
||||||
clamp(lo: number, hi: number): number
|
clamp(lo: number, hi: number): number
|
||||||
}
|
}
|
||||||
|
|
||||||
// Firefox-specific dom properties
|
// Record that we've added convenience objects to window.
|
||||||
interface Window {
|
|
||||||
scrollByLines(n: number): void
|
|
||||||
scrollByPages(n: number): void
|
|
||||||
eval(str: string): any
|
|
||||||
}
|
|
||||||
interface Selection {
|
|
||||||
modify(
|
|
||||||
alter: "move" | "extend",
|
|
||||||
direction: "forward" | "backward" | "left" | "right",
|
|
||||||
granularity: "character" | "word" | "line",
|
|
||||||
): void
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record that we've added a property with convenience objects to the
|
|
||||||
// window object:
|
|
||||||
interface Window {
|
interface Window {
|
||||||
tri: any
|
tri: any
|
||||||
}
|
}
|
||||||
|
|
||||||
// This isn't an actual firefox type but it's nice to have one for this kind of object
|
|
||||||
// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/find/find
|
|
||||||
interface findResult {
|
|
||||||
count: number
|
|
||||||
rangeData: Array<{
|
|
||||||
framePos: number
|
|
||||||
startTextNodePos: number
|
|
||||||
endTextNodePos: number
|
|
||||||
startOffset: number
|
|
||||||
endOffset: number
|
|
||||||
text: string
|
|
||||||
}>
|
|
||||||
rectData: {
|
|
||||||
rectsAndTexts: Array<{
|
|
||||||
top: number
|
|
||||||
left: number
|
|
||||||
bottom: number
|
|
||||||
right: number
|
|
||||||
}>
|
|
||||||
textList: string[]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface HTMLElement {
|
interface HTMLElement {
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert
|
|
||||||
inert: boolean
|
|
||||||
|
|
||||||
// Firefox-only (?) Element attribute
|
// Firefox-only (?) Element attribute
|
||||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dom/openOrClosedShadowRoot
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dom/openOrClosedShadowRoot
|
||||||
openOrClosedShadowRoot: ShadowRoot | null
|
openOrClosedShadowRoot: ShadowRoot | null
|
||||||
|
|
||||||
// Let's be future proof:
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
|
|
||||||
focus(options?: any): void
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren
|
|
||||||
replaceChildren(...nodes: Node[]): void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/ban-types */
|
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
|
||||||
// these functions really can be anything, ditto for the objects
|
// these functions really can be anything, ditto for the objects
|
||||||
declare function exportFunction(
|
declare function exportFunction(
|
||||||
func: Function,
|
func: Function,
|
||||||
targetScope: object,
|
targetScope: object,
|
||||||
options?: { defineAs?: string; allowCrossOriginArguments?: boolean },
|
options?: { defineAs?: string; allowCrossOriginArguments?: boolean },
|
||||||
): Function
|
): Function
|
||||||
/* eslint-enable @typescript-eslint/ban-types */
|
/* eslint-enable @typescript-eslint/no-unsafe-function-type */
|
||||||
|
|
||||||
// Web extension types not in web-ext-types yet
|
|
||||||
declare namespace browser.find {
|
|
||||||
function find(query, object): any
|
|
||||||
}
|
|
||||||
|
|
||||||
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>
|
|
||||||
}
|
|
||||||
|
|
||||||
// web-ext-browser barely declares a third of the management
|
|
||||||
// interface, and we can't switch to @types/firefox-webext-browser yet
|
|
||||||
// because their enums are all messed up (see
|
|
||||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/28369)
|
|
||||||
// Instead, we'll copy-paste as much as we need from the fixed branch:
|
|
||||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/d1180e5218a7bf69e6f0da5ac2e2584bd57a1cdf/types/firefox-webext-browser/index.d.ts
|
|
||||||
interface WebExtEventBase<
|
|
||||||
TAddListener extends (...args: any[]) => any,
|
|
||||||
TCallback,
|
|
||||||
> {
|
|
||||||
addListener: TAddListener
|
|
||||||
|
|
||||||
removeListener(cb: TCallback): void
|
|
||||||
|
|
||||||
hasListener(cb: TCallback): boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
// html-tagged-template.js
|
// html-tagged-template.js
|
||||||
declare function html(
|
declare function html(
|
||||||
|
|
@ -113,30 +35,9 @@ declare function html(
|
||||||
...values: any[]
|
...values: any[]
|
||||||
): HTMLElement
|
): HTMLElement
|
||||||
|
|
||||||
declare namespace browser.search {
|
// Custom matcher from src/lib/mod.test.ts.
|
||||||
function search(searchProperties: {
|
|
||||||
query: string
|
|
||||||
engine?: string
|
|
||||||
tabId?: number
|
|
||||||
}): void
|
|
||||||
function get(): Promise<
|
|
||||||
Array<{
|
|
||||||
name: string
|
|
||||||
isDefault: boolean
|
|
||||||
alias?: string
|
|
||||||
faviconURL?: string
|
|
||||||
}>
|
|
||||||
>
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop typedoc complaining about toBeAll.
|
|
||||||
declare namespace jest {
|
declare namespace jest {
|
||||||
interface Matchers<R> {
|
interface Matchers<R> {
|
||||||
toBeAll: any
|
toBeAll: any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// jest-webextension-mock doesn't know about this Firefox specific API
|
|
||||||
declare namespace browser.commands {
|
|
||||||
function update(details)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "bundler",
|
||||||
"module": "es2020",
|
"module": "es2020",
|
||||||
|
"strict": false,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
|
|
@ -15,10 +16,9 @@
|
||||||
"strictBindCallApply": true,
|
"strictBindCallApply": true,
|
||||||
"noImplicitThis": true,
|
"noImplicitThis": true,
|
||||||
"strictFunctionTypes": true,
|
"strictFunctionTypes": true,
|
||||||
"baseUrl": "src/",
|
|
||||||
"types": ["@types/firefox-webext-browser"],
|
"types": ["@types/firefox-webext-browser"],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@src/*": ["*"]
|
"@src/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue