Safari is a supported active target with its own entry points. Built-in providers use static scripts and Safari requests no all-sites access. User-added sites receive a runtime optional permission, then the background injects content.js after navigation only for granted, enabled, non-builtin rules, with allFrames per rule. Safari settings are device-local and do not roam between devices. macOS packaging uses Xcode and the Apple Developer Program/App Store route.
Reveal URLs — Arhitektūra
Šis dokuments apraksta, kā ir strukturēts Reveal URLs paplašinājums un kā
darbojas tā pamatloģika, līdzstrādniekiem un tehniskiem lasītājiem. Tajā
pastāvīgi ir atsauces uz reāliem failiem un simboliem formā path
symbol, lai katru apgalvojumu varētu pārbaudīt pirmkodā. Lietotājam
paredzētajam aprakstam skatiet manual. Manuālās pārbaudes
soļiem skatiet
manual test plan.
Pārskats
Reveal URLs ir viena MV3 WebExtension, kas tiek veidota Chrome, Edge, Opera,
Firefox, Safari un Thunderbird no vienas kopīgas, tīras kodola bāzes. Safari
izmanto statiskus skriptus tikai iebūvētajiem nodrošinātājiem un ir publicēts
App Store.
Paplašinājums atklāj katras saites galamērķa URL blakus pašai saitei
renderētā e-pastā un iezīmē saiti, kuras redzamais teksts nosauc citu
registrable domēnu nekā tas, kurš atrodas tās href.
Repozitorijs ir pnpm un TypeScript monorepo, ko raksturo
pnpm-workspace.yaml un package.json, bet "private": true liedz to
publiskot kā pakotni. Bundling tiek vadīts ar tooling/build.mjs, kas
kompilē kopīgās pakotnes un plānos entry points katram engine ielādējamā
dist/<target>/ direktorijā. webextension-polyfill tiek iepakots katrā
script bundle, nevis atstāts kā runtime global.
Divi native e-pasta papildinājumi paplašina to pašu noteikšanas loģiku uz
virsmām, kuras WebExtension nesasniedz: Outlook Add-in uz Office.js un
Gmail Add-on uz Apps Script CardService. Abi atkārtoti izmanto tikai
PURE analīzi no packages/core/src/findings.ts, ar analyseAnchors,
analyseHtml, neitrālo modeli Finding[], loģiku hostMismatch un
registrable domēna noteikšanu ar tldts. Atšķiras tikai host adapteris un
attēlošana. Outlook izmanto DOMParser un darbojas client-side. Gmail
izmanto node-html-parser un darbojas server-side Google Apps Script V8
infrastruktūrā. Tā kā neviena no šīm platformām neļauj mainīt izlasītā
ziņojuma DOM, abi rāda paneli vai karti ar atradumiem, nevis inline
annotation. linkProcessor.ts DOM-mutation ceļš un REVEAL_URLS_CSS
tur netiek izmantoti. Relatīvs href tiek atrisināts tikai pret uzticamu
<base href> pašā e-pastā un citādi tiek izlaists. Šis vietējo atradumu
ceļš apzināti paliek tikai http:/https:.
Koda bāze skaidri nošķir atbildības:
packages/coresatur PURE loģiku bez browser APIs, bez storage un bez markup sinks. Tas ir vienīgais patiesības avots saites annotation, config pārbaudei un host salīdzināšanai.packages/webextaptin šo kodolu ar WebExtension APIs, content lifecycle, dynamic registration, options UI un background wiring.extensions/<engine>glabā katra engine plānos entry points un tomanifest.json.toolingglabā build, version-stamping un ikonu skriptus.featuresglabā Cucumber BDD scenārijus un test doubles.
Repozitorija izkārtojums
packages/core — tīrais kodols
Neviens modulis šeit neimportē extension API kā browser.*, chrome.* vai
messenger.*, un neviens neizmanto string-to-markup DOM sinks kā
innerHTML vai insertAdjacentHTML. Šis noteikums tiek mehāniski
nodrošināts ar packages/core/test/purity.test.ts, kas savāc src/**/*.ts,
izņem komentāru saturu ar stripComments un pārbauda, ka ne
EXTENSION_API_PATTERN, ne UNSAFE_DOM_PATTERN nesakrīt ar nevienu moduli.
Publiskā virsma tiek reeksportēta no packages/core/src/index.ts, un vienīgā
runtime atkarība ir tldts.
Galvenie moduļi ir:
packages/core/src/config.ts— shēmasConfigunSiteRule, noklusējuma vērtības un funnelnormaliseConfigpackages/core/src/matchPattern.ts— rakstu gramatika, matcher un specificitātes noteikumipackages/core/src/linkProcessor.ts— annotator dokumenta līmenīpackages/core/src/destination.ts— no shēmas atkarīga galamērķa neatbilstības klasifikācija un salīdzināšanapackages/core/src/hostMismatch.ts— registrable domēna neatbilstības pārbaudepackages/core/src/styles.tsunpackages/core/src/contrast.ts— injectable stylesheet un kontrasta loģikapackages/core/src/safeColour.ts— predikātsisSafeColour
packages/webext — browser API ietvari
Šie moduļi DRĪKST izmantot browser.*, un tā ir vienīgā vieta, kur tiek
skartas WebExtension APIs. Publiskā virsma tiek reeksportēta no
packages/webext/src/index.ts. Šeit atrodas content.ts,
contentRegistration.ts, storage.ts, background.ts, toolbarAction.ts,
messageDisplay.ts, messageDisplayBackground.ts un options/options.ts.
extensions/<engine> — plāni ieejas punkti un manifesti
Katrs engine nes savu manifest.json un savu icons/. Chrome, Firefox un
Thunderbird papildus nes src/ direktoriju ar entry points. Edge, Opera un
Safari nes tikai manifestus un ikonas un atkārtoti izmanto Chrome src/.
Piemēram, extensions/chrome/src/content.ts satur tikai
void createContentController().bootstrap();, bet
extensions/chrome/src/background.ts izsauc registerBackground,
registerContentReconciliation un registerToolbarToggle.
extensions/thunderbird/src/background.ts izsauc registerBackground un
registerMessageDisplay. extensions/_template ir scaffold, nevis build target.
tooling, features un smoke testi
tooling ietver build.mjs, version.mjs un icons.mjs. features
ietver Gherkin scenārijus, step definitions un uzticamos doubles failos
features/support/webext.ts un features/support/world.ts. Katram engine ir
arī extensions/<engine>/test/manifest.smoke.test.mjs, bet _template
izmanto template.smoke.test.mjs.
Atklāšanas plūsma
Content ceļš sākas engine entry pointā, piemēram,
extensions/chrome/src/content.ts, kas izsauc
createContentController().bootstrap() no packages/webext/src/content.ts.
Bootstrap
createContentController bootstrap tiek izpildīts reizi katram frame.
Tas iegūst frame savā kontrolē pirms jebkura await ar claimBootstrap,
ielādē config caur loadConfigWithRetry, injicē stylesheet ar
injectStyles tikai pēc veiksmīga lasījuma un atjauno marķieri ar
releaseBootstrap, ja ielāde pilnībā neizdodas. Kad config.enabled ir
ieslēgts, tas izsauc start, bet jebkurā gadījumā reģistrē listeneri
onConfigChanged.
Aktīvās vietnes noteikuma atrisināšana
start un applyConfig izmanto resolveSiteRule, lai izlemtu, vai un kur
veikt annotation. Vispirms tiek pārbaudīta paša dokumenta atrašanās vieta ar
resolveForHref, kas filtrē config.sites līdz ieslēgtajiem noteikumiem un
atstāj izvēli selectMostSpecific ziņā. Ja dokuments nesakrīt un tā izcelsme
ir opaque vai inherited, kā to pārbauda hasOpaqueOrigin, seko fallback ar
readTopHref, readOpenerHref un readReferrer, aizsargāts pret
cross-origin lasījumiem.
Ierobežošana līdz satura saknei un izmaiņu novērošana
start saglabā contentRoot, izveido annotator ar createAnnotator(config)
un apstrādā katru sakni no selectRoots(doc, contentRoot), kas ietin
querySelectorAll try/catch blokā, lai nederīgs selector droši pārvērstos par
[]. Pēc tam tas novēro doc.body ar OBSERVER_OPTIONS.
processMutations filtrē katru izmaiņu pēc root, targetu atkārtoti apstrādā
tikai tad, ja tas ir Element root iekšienē caur isWithinRoot un closest,
un vēlo root atklāšanu uztic ierobežotajam discoverMatchedRoots() gājienam
katram batch ar vienu querySelectorAll(contentRoot) un deduplikāciju ar
WeakSet. pendingShadowHosts atkārtoti pārbauda iepriekš plain hostus, līdz
parādās open shadow root, lai būtu segti arī shadow upgrade-i.
applyConfig veic teardown, restart vai reflow atkarībā no aktīvā noteikuma
un contentRoot izmaiņām.
Vienas saites marķēšana
Annotator dzīvo failā packages/core/src/linkProcessor.ts.
createAnnotator atgriež Annotator ar Map, data-ru tokenu no
generateToken un aktīvo config. Tā metode process(root):
- Iztīra reģistra ierakstus, kuru enkurs vairs nav savienots.
- Savāc kandidātenkurus ar
collectAnchors(pakārtotosa[href]un pašu sakni, ja tā ira[href], atmetot dublikātus). - Atrisina katra enkura galamērķi ar
resolveAnnotatableUrl, kas deleģē uzresolveAnnotatableHref. Tas atgriežnull(izlaist) tikai tukšam / lapas iekšējam vai neparsējamam href, relatīvus href atrisina pretbaseURIun pieņem jebkuru parsējamu shēmu, tostarpmailto:,tel:,sms:un necaurredzamusjavascript:,data:unblob:URL.ignoreHostsattiecas tikai uzhttp:/https:saitēm ar host. - Izvēlas idempotento ātro ceļu, kad
isAnnotationIntactapstiprina, ka renderējuma pirkstu nospiedums nav mainījies un katrs izveidotais mezgls vēl ir savienots un savā vietā; citādi atceļ novecojušo anotāciju un renderē no jauna. - Aprēķina no shēmas atkarīgo neatbilstību ar
destinationMismatchpēc tīrā enkura teksta:classifySchemetīmekļa saites novirza uzhostMismatch, pastu uzmailMismatch, tālruni uzphoneMismatch, bet pārējās uzopaqueMismatch. Tad tas izsaucannotateAnchor;showOnlyOnMismatchapslēpj tikai saites bez neatbilstības redzamo iekļauto atklājumu, bet saglabā tās galamērķatitle.
annotateAnchor renderē tikai SAFE-DOM. Tas vienmēr saglabā sākotnējo
title (TitleSave) un ieraksta galamērķa title — vienīgo rakstīšanu enkurā.
Nav atsevišķa title režīma vai brīdinājuma nozīmītes. Ja showOnlyOnMismatch
neapslēpj saiti bez neatbilstības, tas priekšā ievieto <span class="reveal-urls-url">
un beigu <br>, atstājot saites bērnus neskartus.
needsLeadingInlineRevealBreak pievieno sākuma <br>, kad redzams iekļauts
saturs ir pirms saites tajā pašā rindā. Span rāda autora norādītu absolūtu href
vārds vārdā vai pret baseURI atrisinātu relatīvu href, izmantojot inertu
textContent (ar bultiņu un U+00A0 nedalāmo atstarpi priekšā, pēc tam saīsinātu
ar truncateUrl); pēc savienošanas tas saņem kontrasta fonu caur
applyContrastBackdrop. Pie uzsvērtas neatbilstības
REVEAL_URLS_MISMATCH_CLASS tiek pievienota REVEAL_URLS_URL_CLASS, lietojot
konfigurēto neatbilstības krāsu ar applyColour un pēc noklusējuma treknrakstu
no REVEAL_URLS_CSS; skaidra fonta biezuma pārrakstīšana ar
applyFontOverrides ir prioritāra. Katrs izveidotais mezgls ir marķēts ar
data-ru="<token>" (nekad pats enkurs), un katrs ieraksts glabā savu
configFingerprint, lai renderēšanas konfigurācijas maiņa piespiestu pārliešanu.
revertOwned noņem izveidotos mezglus pēc atsauces un atjauno saglabāto title;
revertAll to dara katram piederošam enkuram un iztīra reģistru.
truncateUrl darbojas ar Unicode KODA PUNKTIEM ([...displayHref]), tādēļ
griezums nekad nesadala surogātpāri; tas saglabā shēmas un host izcelsmi un
saīsina pārējo ar beigu URL_ELLIPSIS.
Host neatbilstība
packages/core/src/hostMismatch.ts hostMismatch ir tīmekļa zars no
destinationMismatch: tas salīdzina saites redzamo tekstu ar tās href pēc
registrable domēna, nevis neapstrādāta host nosaukuma, tādēļ apakšdomēns bez neatbilstības
netiek atzīmēts, bet līdzīgs domēns tiek. extractHostCandidates sadala tekstu
un samazina katru tokenu ar hostCandidate (tam vajadzīgs punkts un tldts
atpazīts ICANN publiskais sufikss, noraidot parastu punktotu tekstu, piemēram,
e.g). Gan href host, gan katrs kandidāts ar tldts.getDomain tiek samazināti
līdz savam registrable domēnam, un JEBKURS kandidāts, kura domēns atšķiras no
href domēna, rada neatbilstību — tādēļ īstā ļaunprātīgā host nosaukšana līdzās
ēsmas host nevar apslāpēt brīdinājumu. Tas nekad nemet izņēmumu.
Pasta saitēm mailMismatch salīdzina visus saņēmēju registrable domēnus,
ieskaitot to, cc un bcc; phoneMismatch salīdzina atrisināmus izsauktos
numurus. opaqueMismatch vienmēr atzīmē SCRIPT_LIKE_SCHEMES —
javascript:, data: un vbscript: — bet citas necaurredzamas shēmas tiek
atzīmētas tikai tad, ja redzamais teksts nosauc konkrētu tīmekļa, e-pasta vai
tālruņa galamērķi.
Stili un kontrasts
packages/core/src/styles.ts glabā REVEAL_URLS_CSS un helper-us
applyColour, applyFontOverrides un applyContrastBackdrop.
applyContrastBackdrop nolasa elementa aprēķināto krāsu un pirmo opaque
fonu ar getComputedStyle, pēc tam izmanto needsWhiteBackdrop no
packages/core/src/contrast.ts, lai izlemtu, vai uzlikt
style.backgroundColor = "white". contrast.ts sniedz parseColour,
relativeLuminance un contrastRatio.
Konfigurējami host un satura ierobežošana
SiteRule failā packages/core/src/config.ts nosaka, KUR annotation
darbojas caur match un allFrames, un KURŠ container to ierobežo caur
contentRoot, kopā ar enabled un atzīmi builtin. DEFAULT_SITES
aptver FastMail, Gmail, Proton ar allFrames, Tuta, Yahoo, Zoho un abus Outlook host-us. Config
apvieno globālos toggles, colours, font overrides un sarakstu sites.
Match pattern mehānisms
packages/core/src/matchPattern.ts glabā restrictive gramatiku
MATCH_PATTERN: tikai http un https, izvēles *. wildcard host, glob path,
bez port, bez * scheme un bez <all_urls>. matchesPattern salīdzina URL
ar validētu pattern un deleģē path daļu pathGlobMatches.
parsePatternParts sadala pattern host, path, scheme un wildcardHost.
Kad noteikumi pārklājas, darbojas princips "most specific wins".
compareSiteSpecificity sarindo exact host pirms wildcard host, pēc tam
garāku literal host, pēc tam literalāku path ar literalPathLength, un
beigās ASCII tiebreak. selectMostSpecific atgriež viskonkrētāko ieslēgto
noteikumu, kas atbilst URL.
permissions.getAll() var ziņot grants pilnajā WebExtension gramatikā
(<all_urls>, *://*/*, https://*/*, *://*.host/*, https://host/*),
kurus MATCH_PATTERN noraidītu. parseGrantedOrigin pārvērš tos par
GrantedOriginParts, originCovers pārbauda pārklājumu pāri match, un
matchAllowsOriginFallback ziņo, vai path ir precīzi
ORIGIN_FALLBACK_PATH, tas ir, /*.
Dinamiskā reģistrācija
packages/webext/src/contentRegistration.ts reģistrē vienu dynamic content
script katram lietotāja pievienotam noteikumam. Built-ins tiek apkalpoti ar
static content_scripts entries un nekad netiek reģistrēti dinamiski.
desiredContentScripts filtrē config.sites, izmanto isOriginGranted,
originCovers un contentScriptId, un iestata
matchOriginAsFallback: true tikai tad, ja to atļauj
matchAllowsOriginFallback(rule.match).
reconcileContentScriptsOnce nolasa piešķirtās izcelsmes, saglabāto config
un live registrations un saskaņo tās ar property-aware diff.
sameRegistration normalizē gan vēlamo descriptor, gan live read-back.
Tā kā nav updateContentScripts, izmainīts script tiek noņemts un
reģistrēts no jauna. reconcileContentScripts izmanto inFlight promise,
lai serializētu trigger-us, kas var notikt tuvu viens otram.
Skaidri piešķirtas atļaujas plūsma
Static manifesti deklarē optional_host_permissions
(http://*/*, https://*/*), lai lietotājs runtime laikā varētu piešķirt
atļauju papildu host-am. packages/webext/src/options/options.ts addSite
validē visu kandidāta rule ar normaliseSiteRule, iegūst origin ar
matchOrigin un izsauc browser.permissions.request Add pogas click gesture
iekšienē. Tikai pēc apstiprinājuma tiek pievienota rinda builtin:false.
Config, storage un kanoniskais modelis
Vienīgais validācijas funnel
normaliseConfig failā packages/core/src/config.ts ir vienīgais
kanoniskais lasīšanas ceļš. Tas pārveido un ierobežo katru lauku, atgriežas
pie noklusējuma vērtības nederīgu datu gadījumā un nekad nemet exception.
Tas ir būvēts no validatoriem kā normaliseBoolean,
normaliseMaxLength, normaliseIgnoreHosts, normaliseMatchColour,
normaliseMismatchColour, normaliseCssSize, normaliseFontWeight,
normaliseContentRoot, normaliseMatchPattern un normaliseSites.
normaliseSites izmet nederīgus entries, noņem dublikātus pēc match,
uzspiež builtin: true pārklājošiem built-in noteikumiem un atjauno trūkstošos built-ins.
Glabāšana
packages/webext/src/storage.ts aptin WebExtension storage API.
configArea izmanto browser.storage.sync, ja tas ir pieejams, un pāriet uz
browser.storage.local, piemēram, Thunderbird. getConfig, setConfig un
onConfigChanged vienmēr laiž vērtības cauri normaliseConfig, tāpēc
bojāts store nekad nevar atdot nederīgu Config. Abas add-on formas izmanto
to pašu funnel virs savām host storage sistēmām.
Kanoniskais config modelis un mērķēti atjauninājumi
Trīs write path lasa kanonisko config, izmaina tieši vienu lietu un raksta to atpakaļ, nesaglabājot nepabeigtus form edits:
removeSitefailāoptions.tsaddSitefailāoptions.tstoggleEnabledfailāoptions.ts
toggleEnabled failā packages/webext/src/toolbarAction.ts seko tam pašam
modelim arī background pusē.
Build pa engine un manifesta līgums
tooling/build.mjs vada vienotu esbuild build katram WebExtension target.
Descriptor TARGETS nosaka SOURCE TARGET katram target. Chrome, Firefox un
Thunderbird ir savs src/. Edge, Opera un Safari izmanto chrome kā avotu.
Outlook add-in ir savs avots. ACTIVE_TARGETS, tas ir, Chrome, Edge,
Firefox, Opera un Thunderbird, ir tie, kas tiek build-oti ar --all un
--package. Safari un Outlook tiek build-oti tikai tad, kad ir skaidri
nosaukti, bet Gmail izmanto make build-gmail.
Gmail bundle mērķē Apps Script V8 runtime, kam nav ne ES modules, ne native
URL. Tādēļ tas tiek build-ots kā ESM, pēc tam no tā tiek noņemts
export {…}, lai trigger funkcijas paliktu globālas. Neliels URL
polyfill tiek iekļauts tikai vajadzības gadījumā. buildTarget iztīra
dist/<target>/, nokopē manifest.json un icons/, iesaiņo scripts kā IIFE,
options lapu kā ESM un nokopē options.html un options.css.
tooling/version.mjs stamp-ē versijas. Tas paņem MAJOR.MINOR no root
package.json, atrod augstāko BUILD number un pievieno to katram
target manifestam. Outlook add-in nes gan manifest.json, gan manifest.xml.
tooling/icons.mjs, kas darbojas ar make icons, rasterises
assets/icon.svg failos icon48.png un icon128.png.
Manifesta līgums ir definēts failos
extensions/<engine>/test/manifest.smoke.test.mjs, kur tiek pārbaudīta katra
manifesta forma un katra referenced file esamība.
Internacionalizācija (i18n)
Reveal URLs ir lokalizēts daudzās valodās līdzās angļu valodai. Vienīgais
šī kopuma avots ir packages/core/src/locales.json, kas satur
SUPPORTED_LOCALES, vietējos nosaukumus un noklusējuma valodu. Katrs
neangļu string ir machine-translated un gaida cilvēka pārskatīšanu.
Izcelsmes marķieris atšķiras pa formātiem: _locales to nes
description, site catalogues to pieraksta site/i18n/README.md, bet
tulkotie docs pirmajā rindā nes HTML komentāru.
Ir trīs neatkarīgas lokalizācijas virsmas:
- The options page (AD-1). Statiskā lapa tiek piegādāta angliski, bet
katrs tulkojamais mezgls nes
data-i18n="<key>"vaidata-i18n-<attr>="<key>". Runtime laikāpackages/webext/src/options/locale.tsielādē_locales/<code>/messages.json, pārraksta tekstu artextContentun iestata<html lang>. - The website chrome (AD-2).
tooling/site.mjsrenderē vietnes chrome angliski ardata-i18nun<html lang="en-GB">. Pēc tamsite/scripts/i18n.mjsto aizvieto ar apmeklētāja valodu nosite/i18n/<code>.json. - The documentation pages (AD-8/AD-9). Dokumentācijas lapas tiek
renderētas katram locale build laikā un izmanto lokalizētus failu nosaukumus
no
packages/core/src/site-page-names.json, piemēram,nl/handleiding.html. - Internal-link localisation (Finding 2). Sešas iekšējās docs lapas
architecture.html,faq.html,index.html,licence.html,manual.html,privacy.htmlnesdata-doc-link="<page>", un runtime loader tās pārraksta uz tā paša locale sibling variantu, saglabājot#hashun?query.
“Aktīvo vietņu” slēpšana pasta klientā (AD-3)
Mail client target, piemēram, Thunderbird, jau redz visus rendered messages,
tāpēc host-os balstītais “Active sites” redaktors tur ir lieks. Lēmums tiek
nests ar mailClient: true failā tooling/build.mjs.
- Build-time.
copyAssetspārbaudadescriptorFor(target).mailClientun, ja tas ir aktīvs, noņem<section class="sites">arremoveSitesSection(html). - Runtime.
packages/webext/src/options/options.tspiecieš sekcijas trūkumu, nemetOptionsFieldMissingErrorun atjauno saglabātositesvērtību pirms normalisation.
Drošības un privātuma nostāja
- Bez tīkla pieprasījumiem un bez datu iznešanas. Neviens modulis neveic
fetch,XHRvai citus tīkla izsaukumus. Paplašinājums lasa tikai saglabāto config un lapas DOM. - Tikai SAFE-DOM. Annotation un injicētais stylesheet izmanto tikai
createElement,textContentunstyle.*, nevisinnerHTML,insertAdjacentHTMLvaieval. - Visa ārējā ievade tiek normalizēta. Katrs lasījums un rakstījums iet
cauri
normaliseConfig. Krāsas iet caurisSafeColour, raksti caurMATCH_PATTERN, bet content-root selectors tiek ierobežoti arCONTENT_ROOT_PATTERN. - Minimālas privilēģijas. Iebūvētie webmail origin atrodas
host_permissions. Papildu host-i ir opt-in cauroptional_host_permissionsunpermissions.request. - Datu vākšana Gecko vidē. Firefox un Thunderbird manifesti deklarē
browser_specific_settings.gecko.data_collection_permissions.required: ["none"]. - Licence. Projekts ir AGPL-3.0-only, kā norādīts
LICENSEunpackage.json.
Testēšana
- Vitest unit tests aptver
packages/core/test/*unpackages/webext/test/*. - Cucumber BDD scenāriji dzīvo mapē
features/un izmantofeatures/support/webext.tsunfeatures/support/world.ts. - Per-target manifest smoke tests mapē
extensions/<engine>/test/manifest.smoke.test.mjsizmantonode:testun pārbauda manifestu formu un referenced files. - CI failā
.github/workflows/ci.ymlaptur katru push un pull request, jamake test,make bddunmake lintneiziet. Version-stamping un packaging dzīvo failā.github/workflows/release.yml.