Reveal URLs — Arhitektuur
See dokument kirjeldab, kuidas Reveal URLs-i laiendus on üles ehitatud ja
kuidas selle põhiloogika töötab, tehnilistele lugejatele ja kaasaaitajatele.
See viitab järjepidevalt päris failidele ja sümbolitele kujul path
symbol, et iga väide oleks kontrollitav lähtekoodis. Kasutajale suunatud
kirjelduse jaoks vaadake manual. Käsitsi kontrollimise sammude
jaoks vaadake
manual test plan.
Ülevaade
Reveal URLs on üks MV3 WebExtension, mis ehitatakse Chrome'i, Edge'i, Opera,
Firefoxi ja Thunderbirdi jaoks ühest jagatud puhtast koodituumast. Safari on
edasi lükatud: tal on manifest ja ta on nimeliselt build-itav, kuid ta on
vaikebuild-ist ja CI-st välja jäetud. Laiendus kuvab iga lingi siht-URL-i
renderdatud e-kirjas lingi kõrval ning märgib lingi ära siis, kui nähtav
tekst nimetab teist registrable domeeni kui see, mis asub selle href-is.
Hoidla on pnpm-i ja TypeScripti monorepo, mida kirjeldavad
pnpm-workspace.yaml ja package.json, ning "private": true hoiab selle
paketina avaldamisest eemal. Bundlingut juhib tooling/build.mjs, mis
kompileerib jagatud paketid ja õhukesed entry points kõigi engine'ite jaoks
laaditavasse dist/<target>/ kataloogi. webextension-polyfill pakitakse
iga script bundle'i sisse, selle asemel et eeldada runtime global-it.
Kaks native e-posti lisandit laiendavad sama tuvastusloogikat pindadele, kuhu
WebExtension ei ulatu: Outlook Add-in Office.js-il ja Gmail Add-on
Apps Script CardService'il. Mõlemad kasutavad uuesti ainult PURE analüüsi
failist packages/core/src/findings.ts, koos analyseAnchors,
analyseHtml, neutraalse mudeliga Finding[], loogikaga hostMismatch ja
registrable domeeni tuletamisega tldts kaudu. Erinevaks jäävad ainult
host-adapter ja esitlus. Outlook kasutab DOMParser-it ja töötab
client-side. Gmail kasutab node-html-parser-it ja töötab
server-side Google'i Apps Script V8 infrastruktuuris. Kuna kumbki raamistik
ei luba loetud sõnumi DOM-i muuta, näitavad mõlemad paneeli või kaarti
tulemustega, mitte inline annotation-it. linkProcessor.ts DOM-mutation
rada ja REVEAL_URLS_CSS ei kasutata seal uuesti. Suhteline href
lahendatakse ainult usaldusväärse <base href> suhtes e-kirja sees ja muul
juhul jäetakse see vahele.
Koodibaas jaotab vastutused selgelt:
packages/corehoiab PURE loogikat, ilma browser APIs-ideta, ilma storage'ita ja ilma markup sinks-ideta. See on ainsaks tõeallikaks annotation'i, config'i kontrolli ja host-ide võrdlemise jaoks.packages/webextmähib selle ümber WebExtension APIs-id, content'i lifecycle'i, dynamic registration'i, options UI ja background wiring'u.extensions/<engine>hoiab engine-põhiseid entry points'e ja nendemanifest.json-e.toolinghoiab build'i, version-stamping'u ja ikoonide skripte.featureshoiab Cucumber BDD stsenaariume ja test doubles'e.
Hoidla paigutus
packages/core — puhas tuum
Ükski siin olev moodul ei impordi extension API-t nagu browser.*,
chrome.* või messenger.*, ning ükski ei kasuta string-to-markup DOM
sinks'e nagu innerHTML või insertAdjacentHTML. Seda lepingut jõustab
mehaaniliselt packages/core/test/purity.test.ts, mis kogub src/**/*.ts,
eemaldab kommentaaride kehad stripComments abil ning kontrollib, et
EXTENSION_API_PATTERN ega UNSAFE_DOM_PATTERN ei vastaks ühelegi moodulile.
Avalik pind eksporditakse uuesti failist packages/core/src/index.ts, ning
ainus runtime sõltuvus on tldts.
Põhimoodulid on:
packages/core/src/config.ts— skeemidConfigjaSiteRule, vaikeväärtused ning funnelnormaliseConfigpackages/core/src/matchPattern.ts— mustrite grammatika, matcher ja specificity reeglidpackages/core/src/linkProcessor.ts— annotator dokumendi tasemelpackages/core/src/hostMismatch.ts— registrable domeeni ebakõla kontrollpackages/core/src/styles.tsjapackages/core/src/contrast.ts— injectable stylesheet ja kontrastiloogikapackages/core/src/safeColour.ts— predikaatisSafeColour
packages/webext — browser API ümbrised
Need moodulid VÕIVAD kasutada browser.* ning see on ainus koht, kus
WebExtension APIs-e puudutatakse. Avalik pind eksporditakse uuesti failist
packages/webext/src/index.ts. Siin asuvad content.ts,
contentRegistration.ts, storage.ts, background.ts, toolbarAction.ts,
messageDisplay.ts, messageDisplayBackground.ts ja options/options.ts.
extensions/<engine> — õhukesed sisenemispunktid ja manifestid
Iga engine kannab oma manifest.json-i ja icons/ kataloogi. Chrome,
Firefox ja Thunderbird kannavad lisaks src/ kataloogi entry points'idega.
Edge, Opera ja Safari kannavad ainult manifesti ja ikoone ning kasutavad
uuesti Chrome'i src/-i. Näiteks extensions/chrome/src/content.ts
sisaldab ainult void createContentController().bootstrap();, samal ajal kui
extensions/chrome/src/background.ts kutsub registerBackground,
registerContentReconciliation ja registerToolbarToggle.
extensions/thunderbird/src/background.ts kutsub registerBackground ja
registerMessageDisplay. extensions/_template on scaffold, mitte build target.
tooling, features ja smoke testid
tooling sisaldab faile build.mjs, version.mjs ja icons.mjs.
features sisaldab Gherkini stsenaariume, step definitions'e ja usaldusväärseid
doubles'e failides features/support/webext.ts ja
features/support/world.ts. Igal engine'il on ka
extensions/<engine>/test/manifest.smoke.test.mjs, samal ajal kui
_template kasutab template.smoke.test.mjs.
Paljastamise voog
Content'i tee algab engine'i entry point'ist, näiteks
extensions/chrome/src/content.ts, mis kutsub
createContentController().bootstrap() failist
packages/webext/src/content.ts.
Bootstrap
createContentController bootstrap käivitub kord iga frame'i kohta. See
võtab frame'i enda kontrolli alla enne iga await-i läbi claimBootstrap,
laeb config'i läbi loadConfigWithRetry, injekteerib stylesheet'i läbi
injectStyles alles pärast edukat lugemist ning taastab marker-i läbi
releaseBootstrap, kui laadimine täielikult ebaõnnestub. Kui
config.enabled on tõene, kutsub see start, ning alati registreerib ka
listener'i onConfigChanged.
Aktiivse saidi reegli lahendamine
start ja applyConfig kasutavad resolveSiteRule-i, et otsustada, kas ja
kus annotation tehakse. Kõigepealt proovitakse dokumendi enda asukohta
resolveForHref kaudu, mis filtreerib config.sites lubatud reeglitele ja
jätab valiku selectMostSpecific hoolde. Kui dokument ei sobi ning selle
päritolu on opaque või inherited, nagu kontrollib hasOpaqueOrigin, järgnevad
fallback-id readTopHref, readOpenerHref ja readReferrer kaudu,
kaitstult cross-origin lugemise eest.
Sisujuure piiramine ja muudatuste jälgimine
start salvestab contentRoot-i, loob annotator'i createAnnotator(config)
abil ning töötleb iga sobiva juure failist selectRoots(doc, contentRoot),
mis mähib querySelectorAll-i try/catch-i, nii et vigane selector kukub
ohutult väärtusele []. Seejärel jälgib see doc.body-d
OBSERVER_OPTIONS-iga. processMutations filtreerib iga muutuse root'i
järgi ning processAddedNode katab juure sees olevad sõlmed, juure enda ja
seda sisaldavad sõlmed. applyConfig teeb teardown'i, restart'i või
reflow'd olenevalt aktiivsest reeglist ja contentRoot-i muutumisest.
Üksiku lingi märgistamine
Annotator elab failis packages/core/src/linkProcessor.ts.
createAnnotator tagastab Annotator-i koos Map-iga, data-ru token'iga
failist generateToken ja aktiivse config'iga. process(root) puhastab
lahtiühendatud kirjed, kogub a[href] elemendid läbi collectAnchors,
lahendab URL-id läbi resolveAnnotatableUrl, kasutab fast path'i
isAnnotationIntact, kui render on puutumata, ning arvutab mismatch'i
läbi hostMismatch-i enne annotateAnchor-i kutsumist.
annotateAnchor renderdab ainult SAFE-DOM-i. Režiimis "inline" lisab see
<span class="reveal-urls-url"> koos textContent-iga ja <br>-i.
Režiimis "title" salvestab see olemasoleva title-i, asendab selle URL-iga
ja lisab rõhutatud mismatch'i korral <span class="reveal-urls-warn">
elemendi väärtusega REVEAL_URLS_WARN_LABEL. Loodud sõlmed saavad
data-ru="<token>", ning configFingerprint käivitab vajadusel reflow.
truncateUrl töötab üle [...displayHref] ja kasutab URL_ELLIPSIS-t.
Host-i ebakõla
packages/core/src/hostMismatch.ts hostMismatch võrdleb lingi nähtavat
teksti selle href-iga registrable domeeni tasemel, mitte toor-hostname'i
põhjal. extractHostCandidates jagab teksti token'iteks ja taandab need läbi
hostCandidate, mis nõuab punkti ja tldts-i poolt tunnustatud public
suffix'it. Href-i host ja kandidaadid taandatakse tldts.getDomain
abil. Iga kandidaat erineva domeeniga tekitab mismatch'i.
Stiilid ja kontrast
packages/core/src/styles.ts hoiab REVEAL_URLS_CSS-i ja helper'eid
applyColour, applyFontOverrides ning applyContrastBackdrop.
applyContrastBackdrop loeb elemendi arvutatud värvi ja esimese opaque
tausta getComputedStyle kaudu, seejärel kasutab
needsWhiteBackdrop-i failist packages/core/src/contrast.ts, et otsustada,
kas määrata style.backgroundColor = "white". contrast.ts annab
parseColour, relativeLuminance ja contrastRatio.
Seadistatavad host-id ja sisu piiramine
Üks SiteRule failis packages/core/src/config.ts määrab, KUS annotation
töötab läbi match ja allFrames, ning MILLINE container seda piirab läbi
contentRoot, koos enabled-i ja märgiga builtin. DEFAULT_SITES
katavad Gmaili, Protoni koos allFrames-iga ja mõlemad Outlooki host-id.
Config ühendab globaalsed toggles, colours, font overrides ja loendi sites.
Match pattern'i mehhanism
packages/core/src/matchPattern.ts hoiab restrictive grammatikat
MATCH_PATTERN: ainult http ja https, valikuline *. wildcard host, glob
path, ilma port'ita, ilma * scheme'ita ja ilma <all_urls>-ita.
matchesPattern võrdleb URL-i valideeritud mustriga ja delegeerib path'i
pathGlobMatches-ile. parsePatternParts jagab mustri host-iks, path-iks,
scheme-iks ja wildcardHost-iks.
Reeglite kattumisel kehtib põhimõte "most specific wins".
compareSiteSpecificity järjestab exact host'i wildcard host'ist ettepoole,
seejärel pikema literal host'i, seejärel sõnasõnalisema path'i läbi
literalPathLength-i ja lõpuks ASCII tiebreak'i. selectMostSpecific
tagastab kõige spetsiifilisema lubatud reegli, mis URL-iga sobib.
permissions.getAll() võib raporteerida grants'e täielikus WebExtensioni
grammatikas (<all_urls>, *://*/*, https://*/*, *://*.host/*,
https://host/*), mille MATCH_PATTERN tagasi lükkaks.
parseGrantedOrigin teeb neist GrantedOriginParts, originCovers
kontrollib katvust üle match-i ja matchAllowsOriginFallback ütleb,
kas path on täpselt ORIGIN_FALLBACK_PATH, st /*.
Dünaamiline registreerimine
packages/webext/src/contentRegistration.ts registreerib iga kasutaja lisatud
reegli jaoks ühe dynamic content script'i. Built-ins teenindatakse läbi
static content_scripts entries'e ega registreerita kunagi dünaamiliselt.
desiredContentScripts filtreerib config.sites-i, kasutab
isOriginGranted, originCovers ja contentScriptId ning paneb
matchOriginAsFallback: true ainult siis, kui seda lubab
matchAllowsOriginFallback(rule.match).
reconcileContentScriptsOnce loeb grantitud originid, salvestatud config'i ja
live registrations'e ning viib need kokku property-aware diff'iga.
sameRegistration normaliseerib nii soovitud descriptor'i kui ka live
read-back'i. Kuna updateContentScripts puudub, eemaldatakse muudetud
script ja registreeritakse uuesti. reconcileContentScripts kasutab
promise'i inFlight, et järjestada trigger'id, mis võivad juhtuda
lähestikku.
Selgesõnalise loa voog
Static manifest'id deklareerivad optional_host_permissions
(http://*/*, https://*/*), et kasutaja saaks runtime'i ajal anda loa
lisahost-ile. packages/webext/src/options/options.ts addSite
valideerib kogu kandidaatreegli läbi normaliseSiteRule, tuletab origin'i
läbi matchOrigin ja kutsub browser.permissions.request-i Add nupu
click gesture'i seest. Alles pärast kinnitamist lisab see rea
builtin:false.
Config, storage ja kanooniline muster
Üks valideerimisfunnel
normaliseConfig failis packages/core/src/config.ts on ainus kanooniline
lugemistee. See teisendab ja piirab iga välja, langeb vigase sisendi korral
vaikeväärtusele tagasi ega viska kunagi exception'it. See on ehitatud
validatoritest nagu normaliseBoolean, normaliseRenderMode,
normaliseMaxLength, normaliseIgnoreHosts, normaliseMatchColour,
normaliseMismatchColour, normaliseCssSize, normaliseFontWeight,
normaliseContentRoot, normaliseMatchPattern ja normaliseSites.
normaliseSites eemaldab vigased entries'ed, eemaldab duplikaadid võtme
match järgi, sunnib builtin: true-d kattuvatel built-in reeglitel ja
taastab puuduvad built-ins.
Salvestamine
packages/webext/src/storage.ts mähib WebExtension storage API ümber.
configArea kasutab browser.storage.sync-i, kui see on olemas, ja teeb
fallback'i browser.storage.local-ile, näiteks Thunderbirdis.
getConfig, setConfig ja onConfigChanged lasevad väärtused alati läbi
normaliseConfig-i, nii et katkine store ei saa kunagi tagastada vigast
Config-i. Mõlemad add-on vormid kasutavad sama funnel'it omaenda
host-storage'ite kohal.
Kanooniline config-muster ja sihitud uuendused
Kolm write path'i loevad kanoonilist config'it, muudavad täpselt üht asja ja kirjutavad selle tagasi, salvestamata pooleliolevaid form edits'e:
removeSitefailisoptions.tsaddSitefailisoptions.tstoggleEnabledfailisoptions.ts
toggleEnabled failis packages/webext/src/toolbarAction.ts järgib sama
mustrit ka background'i poolel.
Build engine'i järgi ja manifesti leping
tooling/build.mjs juhib ühtset esbuild build'i iga WebExtension target'i
jaoks. Descriptor TARGETS määrab SOURCE TARGET-i igale target'ile.
Chrome'il, Firefoxil ja Thunderbirdil on oma src/. Edge, Opera ja Safari
kasutavad chrome-i allikana. Outlook add-in'il on oma allikas.
ACTIVE_TARGETS, st Chrome, Edge, Firefox, Opera ja Thunderbird, on need,
mida build'itakse --all ja --package kaudu. Safari ja Outlook
build'itakse ainult siis, kui need on nimeliselt küsitud, ning Gmail kasutab
make build-gmail.
Gmaili bundle sihib Apps Script V8 runtime'i, millel puuduvad ES modules ja
native URL. Seepärast ehitatakse see ESM-ina ja seejärel eemaldatakse
export {…}, et trigger funktsioonid jääksid globaalseks. Väike URL
polyfill lisatakse ainult vajadusel. buildTarget puhastab dist/<target>/,
kopeerib manifest.json-i ja icons/, pakib scripts'id IIFE-na ning
options lehe ESM-ina ja kopeerib options.html ning options.css.
tooling/version.mjs stamp-ib versioonid. See võtab MAJOR.MINOR väärtuse
root package.json-ist, leiab kõrgeima BUILD number'i ja lisab selle igale
target manifestile. Outlook add-in kannab nii manifest.json-i kui ka
manifest.xml-i. tooling/icons.mjs, mis töötab käsuga make icons,
rasterises assets/icon.svg failiks icon48.png ja icon128.png.
Manifesti leping on määratletud failides
extensions/<engine>/test/manifest.smoke.test.mjs, kus kontrollitakse iga
manifesti täpset kuju ja iga referenced file'i olemasolu.
Rahvusvahelistamine (i18n)
Reveal URLs on lokaliseeritud paljudesse keeltesse peale inglise keele.
Ainsaks allikaks sellele komplektile on packages/core/src/locales.json,
mis sisaldab SUPPORTED_LOCALES, emakeelseid nimesid ja vaikekeelt. Iga
mitteingliskeelne string on machine-translated ja ootab inimülevaatust.
Provenientsi marker erineb vormiti: _locales kannavad seda
description-is, site catalogues märgivad seda failis
site/i18n/README.md ning tõlgitud docs kannavad esimesel real HTML kommentaari.
Lokaliseerimisvahendeid on kolm sõltumatut:
- The options page (AD-1). Staatiline markup tarnitakse inglise keeles,
kuid iga tõlgitav sõlm kannab
data-i18n="<key>"võidata-i18n-<attr>="<key>". Runtime'is laebpackages/webext/src/options/locale.tsfaili_locales/<code>/messages.json, kirjutab teksti ületextContent-iga ja seab<html lang>. - The website chrome (AD-2).
tooling/site.mjsrenderdab saidi chrome'i inglise keeles koosdata-i18n-iga ja<html lang="en-GB">-ga. Seejärelsite/scripts/i18n.mjsvahetab selle külastaja keele vastu failistsite/i18n/<code>.json. - The documentation pages (AD-8/AD-9). Dokumentatsioonilehed renderdatakse
iga locale'i jaoks build time'is ja kasutavad failinimesid failist
packages/core/src/site-page-names.json, näiteksnl/handleiding.html. - Internal-link localisation (Finding 2). Sisemised docs-lingid kannavad
data-doc-link="<page>", ning runtime loader suunab need sama locale'i sibling variandile, säilitades#hashja?query.
“Aktiivsete saitide” peitmine meilikliendis (AD-3)
Mail client target nagu Thunderbird näeb juba kõiki rendered messages'e, seega
on host-põhine “Active sites” editor seal üleliigne. Otsus kandub läbi
mailClient: true välja failis tooling/build.mjs.
- Build-time.
copyAssetskontrollibdescriptorFor(target).mailClient-i ning eemaldab selle puhul<section class="sites">funktsioonigaremoveSitesSection(html). - Runtime.
packages/webext/src/options/options.tstalub sektsiooni puudumist, ei viskaOptionsFieldMissingError-it ning taastab salvestatudsitesväärtuse enne normalisation'it.
Turvalisuse ja privaatsuse hoiak
- Ei mingeid võrgupäringuid ega andmete väljastamist. Ükski moodul ei tee
fetch,XHRega muid võrgukõnesid. Laiendus loeb ainult salvestatud config'i ja lehe DOM-i. - Ainult SAFE-DOM. Annotation ja injekteeritud stylesheet kasutavad ainult
createElement,textContentjastyle.*, mitteinnerHTML,insertAdjacentHTMLegaeval. - Kogu väline sisend normaliseeritakse. Iga lugemine ja kirjutamine läbib
normaliseConfig-i. Värvid läbivadisSafeColour-i, mustrid läbivadMATCH_PATTERN-i ja content-root selectors piiratakseCONTENT_ROOT_PATTERN-iga. - Minimaalne privileeg. Sisseehitatud webmail origin-id asuvad
host_permissions-is. Lisahost-id on opt-in kauduoptional_host_permissionsjapermissions.request. - Andmekogumine Geckos. Firefoxi ja Thunderbirdi manifestid deklareerivad
browser_specific_settings.gecko.data_collection_permissions.required: ["none"]. - Litsents. Projekt on AGPL-3.0-only, nagu on kirjas failides
LICENSEjapackage.json.
Testimine
- Vitest unit tests katavad
packages/core/test/*japackages/webext/test/*. - Cucumber BDD stsenaariumid elavad kataloogis
features/ning kasutavad failefeatures/support/webext.tsjafeatures/support/world.ts. - Per-target manifest smoke tests failides
extensions/<engine>/test/manifest.smoke.test.mjskasutavadnode:test-i ning kontrollivad manifestide kuju ja referenced files'e. - CI failis
.github/workflows/ci.ymlpeatab iga push'i ja pull request'i, kuimake test,make bddjamake lintläbi ei lähe. Version-stamping ja packaging elavad failis.github/workflows/release.yml.