mirror of
https://github.com/Anon-Planet/thgtoa.git
synced 2026-06-21 04:58:04 +02:00
1483 lines
57 KiB
HTML
1483 lines
57 KiB
HTML
|
|
<!doctype html>
|
|
<html lang="en" class="no-js">
|
|
<head>
|
|
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
|
|
<meta name="description" content="The comprehensive guide for online anonymity and OpSec.">
|
|
|
|
|
|
<meta name="author" content="Anonymous Planet">
|
|
|
|
|
|
<link rel="canonical" href="https://www.anonymousplanet.org/code/develop/">
|
|
|
|
|
|
<link rel="prev" href="../">
|
|
|
|
|
|
<link rel="next" href="../../contribute/">
|
|
|
|
|
|
<link rel="icon" href="../../media/profile.png">
|
|
<meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.5.17">
|
|
|
|
|
|
|
|
<title>Develop - Hitchhiker's Guide</title>
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../../assets/stylesheets/main.bcfcd587.min.css">
|
|
|
|
|
|
<link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Public+Sans:300,300i,400,400i,700,700i%7CLiberation+Mono:400,400i,700,700i&display=fallback">
|
|
<style>:root{--md-text-font:"Public Sans";--md-code-font:"Liberation Mono"}</style>
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../../stylesheets/extra.css">
|
|
|
|
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<meta property="og:type" content="website" >
|
|
|
|
<meta property="og:title" content="Develop - Hitchhiker's Guide" >
|
|
|
|
<meta property="og:description" content="The comprehensive guide for online anonymity and OpSec." >
|
|
|
|
<meta property="og:image" content="https://www.anonymousplanet.org/assets/images/social/code/develop.png" >
|
|
|
|
<meta property="og:image:type" content="image/png" >
|
|
|
|
<meta property="og:image:width" content="1200" >
|
|
|
|
<meta property="og:image:height" content="630" >
|
|
|
|
<meta property="og:url" content="https://www.anonymousplanet.org/code/develop/" >
|
|
|
|
<meta name="twitter:card" content="summary_large_image" >
|
|
|
|
<meta name="twitter:title" content="Develop - Hitchhiker's Guide" >
|
|
|
|
<meta name="twitter:description" content="The comprehensive guide for online anonymity and OpSec." >
|
|
|
|
<meta name="twitter:image" content="https://www.anonymousplanet.org/assets/images/social/code/develop.png" >
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="green" data-md-color-accent="blue">
|
|
|
|
|
|
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
|
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
|
<label class="md-overlay" for="__drawer"></label>
|
|
<div data-md-component="skip">
|
|
|
|
|
|
<a href="#developer-guide" class="md-skip">
|
|
Skip to content
|
|
</a>
|
|
|
|
</div>
|
|
<div data-md-component="announce">
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<header class="md-header" data-md-component="header">
|
|
<nav class="md-header__inner md-grid" aria-label="Header">
|
|
<a href="../.." title="Hitchhiker's Guide" class="md-header__button md-logo" aria-label="Hitchhiker's Guide" data-md-component="logo">
|
|
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m23 11.5-3.05-1.13c-.26-1.15-.91-1.81-.91-1.81a4.189 4.189 0 0 0-5.93 0l-1.48 1.48L5 3c-1 4 0 8 2.45 11.22L2 19.5s8.89 2 14.07-2.05c2.76-2.16 3.38-3.42 3.77-4.75L23 11.5m-5.29.22c-.39.39-1.03.39-1.42 0a.996.996 0 0 1 0-1.41c.39-.39 1.03-.39 1.42 0 .39.39.39 1.02 0 1.41Z"/></svg>
|
|
|
|
</a>
|
|
<label class="md-header__button md-icon" for="__drawer">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
|
|
</label>
|
|
<div class="md-header__title" data-md-component="header-title">
|
|
<div class="md-header__ellipsis">
|
|
<div class="md-header__topic">
|
|
<span class="md-ellipsis">
|
|
Hitchhiker's Guide
|
|
</span>
|
|
</div>
|
|
<div class="md-header__topic" data-md-component="header-topic">
|
|
<span class="md-ellipsis">
|
|
|
|
Develop
|
|
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<form class="md-header__option" data-md-component="palette">
|
|
|
|
|
|
|
|
|
|
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="green" data-md-color-accent="blue" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
|
|
|
|
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 9a3 3 0 0 1 3 3 3 3 0 0 1-3 3 3 3 0 0 1-3-3 3 3 0 0 1 3-3m0-4.5c5 0 9.27 3.11 11 7.5-1.73 4.39-6 7.5-11 7.5S2.73 16.39 1 12c1.73-4.39 6-7.5 11-7.5M3.18 12a9.821 9.821 0 0 0 17.64 0 9.821 9.821 0 0 0-17.64 0Z"/></svg>
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="grey" data-md-color-accent="teal" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
|
|
|
|
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5 5 5 0 0 1 5-5 5 5 0 0 1 5 5 5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5Z"/></svg>
|
|
</label>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
|
|
<script>var media,input,key,value,palette=__md_get("__palette");if(palette&&palette.color){"(prefers-color-scheme)"===palette.color.media&&(media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']"),palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent"));for([key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
|
|
|
|
|
|
|
|
<label class="md-header__button md-icon" for="__search">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
|
|
</label>
|
|
<div class="md-search" data-md-component="search" role="dialog">
|
|
<label class="md-search__overlay" for="__search"></label>
|
|
<div class="md-search__inner" role="search">
|
|
<form class="md-search__form" name="search">
|
|
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
|
<label class="md-search__icon md-icon" for="__search">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
|
|
</label>
|
|
<nav class="md-search__options" aria-label="Search">
|
|
|
|
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
|
|
</button>
|
|
</nav>
|
|
|
|
<div class="md-search__suggest" data-md-component="search-suggest"></div>
|
|
|
|
</form>
|
|
<div class="md-search__output">
|
|
<div class="md-search__scrollwrap" data-md-scrollfix>
|
|
<div class="md-search-result" data-md-component="search-result">
|
|
<div class="md-search-result__meta">
|
|
Initializing search
|
|
</div>
|
|
<ol class="md-search-result__list" role="presentation"></ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="md-header__source">
|
|
<a href="https://github.com/Anon-Planet/thgtoa" title="Go to repository" class="md-source" data-md-component="source">
|
|
<div class="md-source__icon md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
|
|
</div>
|
|
<div class="md-source__repository">
|
|
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
</nav>
|
|
|
|
</header>
|
|
|
|
<div class="md-container" data-md-component="container">
|
|
|
|
|
|
|
|
|
|
|
|
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
|
|
<div class="md-grid">
|
|
<ul class="md-tabs__list">
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../.." class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
Welcome
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../about/" class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
About
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../verify/" class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
Verify
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../guide/" class="md-tabs__link">
|
|
|
|
|
|
Guide
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item md-tabs__item--active">
|
|
<a href="../" class="md-tabs__link">
|
|
|
|
|
|
Code
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../contribute/" class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
Contribute
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../constitution/" class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
Constitution
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../mirrors/" class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
Mirrors
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../twitter/" class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
Twitter
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../changelog/" class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
Releases
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
|
|
|
|
|
|
<main class="md-main" data-md-component="main">
|
|
<div class="md-main__inner md-grid">
|
|
|
|
|
|
|
|
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
|
<div class="md-sidebar__scrollwrap">
|
|
<div class="md-sidebar__inner">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<nav class="md-nav md-nav--primary md-nav--lifted md-nav--integrated" aria-label="Navigation" data-md-level="0">
|
|
<label class="md-nav__title" for="__drawer">
|
|
<a href="../.." title="Hitchhiker's Guide" class="md-nav__button md-logo" aria-label="Hitchhiker's Guide" data-md-component="logo">
|
|
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m23 11.5-3.05-1.13c-.26-1.15-.91-1.81-.91-1.81a4.189 4.189 0 0 0-5.93 0l-1.48 1.48L5 3c-1 4 0 8 2.45 11.22L2 19.5s8.89 2 14.07-2.05c2.76-2.16 3.38-3.42 3.77-4.75L23 11.5m-5.29.22c-.39.39-1.03.39-1.42 0a.996.996 0 0 1 0-1.41c.39-.39 1.03-.39 1.42 0 .39.39.39 1.02 0 1.41Z"/></svg>
|
|
|
|
</a>
|
|
Hitchhiker's Guide
|
|
</label>
|
|
|
|
<div class="md-nav__source">
|
|
<a href="https://github.com/Anon-Planet/thgtoa" title="Go to repository" class="md-source" data-md-component="source">
|
|
<div class="md-source__icon md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
|
|
</div>
|
|
<div class="md-source__repository">
|
|
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../.." class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Welcome
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../about/" class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
About
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../verify/" class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Verify
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Guide
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_4">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Guide
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../guide/" class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
./
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Code
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
|
|
<label class="md-nav__title" for="__nav_5">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Code
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../" class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Content Contributions
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active">
|
|
|
|
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__link md-nav__link--active" for="__toc">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Develop
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<a href="./" class="md-nav__link md-nav__link--active">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Develop
|
|
</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__title" for="__toc">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Table of contents
|
|
</label>
|
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#prerequisites" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Prerequisites
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#repository-layout" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Repository layout
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#building-locally" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Building locally
|
|
</span>
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="Building locally">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#build-both-pdfs" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Build both PDFs
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#build-only-the-dark-pdf-from-an-existing-light-pdf" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Build only the dark PDF from an existing light PDF
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#preview-the-mkdocs-site" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Preview the MkDocs site
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#pushing-changes" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Pushing changes
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#github-secrets" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
GitHub Secrets
|
|
</span>
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="GitHub Secrets">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#gpg_private_key" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
GPG_PRIVATE_KEY
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#gpg_passphrase" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
GPG_PASSPHRASE
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#vt_api_key" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
VT_API_KEY
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#changelog_pat" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
CHANGELOG_PAT
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#secrets-summary" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Secrets summary
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#cutting-a-release" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Cutting a release
|
|
</span>
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="Cutting a release">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#requirements" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Requirements
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#import-the-release-key-first-time-only" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Import the release key (first time only)
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#run-the-release-tagger" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Run the release tagger
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#push-the-tag" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Push the tag
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#trigger-the-release-workflow" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Trigger the release workflow
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#verifying-a-release" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Verifying a release
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#troubleshooting" class="md-nav__link">
|
|
<span class="md-ellipsis">
|
|
Troubleshooting
|
|
</span>
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../contribute/" class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Contribute
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../constitution/" class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Constitution
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../mirrors/" class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Mirrors
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../twitter/" class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Twitter
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../changelog/" class="md-nav__link">
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Releases
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="md-content" data-md-component="content">
|
|
<article class="md-content__inner md-typeset">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<h1 id="developer-guide">Developer Guide<a class="headerlink" href="#developer-guide" title="Permanent link">¶</a></h1>
|
|
<p>This page covers everything you need to contribute to the project, run the build pipeline locally, configure GitHub secrets, and cut a signed release.</p>
|
|
<hr />
|
|
<h2 id="prerequisites">Prerequisites<a class="headerlink" href="#prerequisites" title="Permanent link">¶</a></h2>
|
|
<p>Install these before anything else.</p>
|
|
<div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Linux / macOS</label><label for="__tabbed_1_2">Windows</label></div>
|
|
<div class="tabbed-content">
|
|
<div class="tabbed-block">
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="c1"># Python 3.11+</span>
|
|
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>python3<span class="w"> </span>--version
|
|
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a>
|
|
<a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="c1"># poppler (pdftoppm) and qpdf</span>
|
|
<a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a>sudo<span class="w"> </span>apt<span class="w"> </span>install<span class="w"> </span>poppler-utils<span class="w"> </span>qpdf<span class="w"> </span><span class="c1"># Debian / Ubuntu</span>
|
|
<a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a>brew<span class="w"> </span>install<span class="w"> </span>poppler<span class="w"> </span>qpdf<span class="w"> </span><span class="c1"># macOS</span>
|
|
<a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a>
|
|
<a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a><span class="c1"># GPG</span>
|
|
<a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a>sudo<span class="w"> </span>apt<span class="w"> </span>install<span class="w"> </span>gnupg<span class="w"> </span><span class="c1"># Debian / Ubuntu</span>
|
|
<a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a>brew<span class="w"> </span>install<span class="w"> </span>gnupg<span class="w"> </span><span class="c1"># macOS</span>
|
|
<a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a>
|
|
<a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a><span class="c1"># Python dependencies</span>
|
|
<a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a>pip<span class="w"> </span>install<span class="w"> </span><span class="s2">"mkdocs-material[imaging]"</span><span class="w"> </span>pillow<span class="w"> </span>numpy
|
|
</code></pre></div>
|
|
</div>
|
|
<div class="tabbed-block">
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="c"># Python 3.11+ from https://python.org</span>
|
|
<a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a>
|
|
<a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a><span class="c"># poppler — download from https://github.com/oschwartz10612/poppler-windows/releases</span>
|
|
<a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a><span class="c"># Extract and add the bin\ folder to PATH</span>
|
|
<a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a>
|
|
<a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a><span class="c"># qpdf — download from https://github.com/qpdf/qpdf/releases</span>
|
|
<a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a><span class="c"># Extract and add the bin\ folder to PATH</span>
|
|
<a id="__codelineno-1-8" name="__codelineno-1-8" href="#__codelineno-1-8"></a>
|
|
<a id="__codelineno-1-9" name="__codelineno-1-9" href="#__codelineno-1-9"></a><span class="c"># GPG — download Gpg4win from https://gpg4win.org</span>
|
|
<a id="__codelineno-1-10" name="__codelineno-1-10" href="#__codelineno-1-10"></a>
|
|
<a id="__codelineno-1-11" name="__codelineno-1-11" href="#__codelineno-1-11"></a><span class="c"># Python dependencies</span>
|
|
<a id="__codelineno-1-12" name="__codelineno-1-12" href="#__codelineno-1-12"></a><span class="n">pip</span> <span class="n">install</span> <span class="s2">"mkdocs-material[imaging]"</span> <span class="n">pillow</span> <span class="n">numpy</span>
|
|
</code></pre></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p>You also need <strong>Google Chrome</strong> or <strong>Microsoft Edge</strong> installed for the light-mode PDF build (headless Chromium).</p>
|
|
<hr />
|
|
<h2 id="repository-layout">Repository layout<a class="headerlink" href="#repository-layout" title="Permanent link">¶</a></h2>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a>.github/
|
|
<a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a> workflows/
|
|
<a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a> build.yml ← builds PDFs, uploads artifact
|
|
<a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a> sign.yml ← hashes + GPG signs, uploads signatures artifact
|
|
<a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a> release.yml ← publishes GitHub Release with all assets
|
|
<a id="__codelineno-2-6" name="__codelineno-2-6" href="#__codelineno-2-6"></a> changelog.yml ← auto-updates docs/changelog/index.md
|
|
<a id="__codelineno-2-7" name="__codelineno-2-7" href="#__codelineno-2-7"></a> publish.yml ← deploys MkDocs site to GitHub Pages
|
|
<a id="__codelineno-2-8" name="__codelineno-2-8" href="#__codelineno-2-8"></a>docs/
|
|
<a id="__codelineno-2-9" name="__codelineno-2-9" href="#__codelineno-2-9"></a> guide/index.md ← the guide (single Markdown file)
|
|
<a id="__codelineno-2-10" name="__codelineno-2-10" href="#__codelineno-2-10"></a> changelog/ ← release notes
|
|
<a id="__codelineno-2-11" name="__codelineno-2-11" href="#__codelineno-2-11"></a> code/ ← this page
|
|
<a id="__codelineno-2-12" name="__codelineno-2-12" href="#__codelineno-2-12"></a>export/ ← PDF output (gitignored except .sha256, .b2, .sig)
|
|
<a id="__codelineno-2-13" name="__codelineno-2-13" href="#__codelineno-2-13"></a>pgp/ ← public signing keys
|
|
<a id="__codelineno-2-14" name="__codelineno-2-14" href="#__codelineno-2-14"></a>scripts/
|
|
<a id="__codelineno-2-15" name="__codelineno-2-15" href="#__codelineno-2-15"></a> build_guide_pdf.py ← MkDocs + Chromium PDF builder
|
|
<a id="__codelineno-2-16" name="__codelineno-2-16" href="#__codelineno-2-16"></a> convert.py ← pixel-based dark mode PDF converter
|
|
<a id="__codelineno-2-17" name="__codelineno-2-17" href="#__codelineno-2-17"></a> tag_release.py ← interactive signed-tag helper for maintainers
|
|
<a id="__codelineno-2-18" name="__codelineno-2-18" href="#__codelineno-2-18"></a> update_changelog.py← auto-generates changelog entries from git log
|
|
<a id="__codelineno-2-19" name="__codelineno-2-19" href="#__codelineno-2-19"></a> setup_workflow.py ← GitHub Secrets setup assistant
|
|
<a id="__codelineno-2-20" name="__codelineno-2-20" href="#__codelineno-2-20"></a> verify_pdf.py ← signature verification helper
|
|
</code></pre></div>
|
|
<hr />
|
|
<h2 id="building-locally">Building locally<a class="headerlink" href="#building-locally" title="Permanent link">¶</a></h2>
|
|
<h3 id="build-both-pdfs">Build both PDFs<a class="headerlink" href="#build-both-pdfs" title="Permanent link">¶</a></h3>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a>python<span class="w"> </span>scripts/build_guide_pdf.py<span class="w"> </span>--both
|
|
</code></pre></div>
|
|
<p>This builds the MkDocs site, renders it to <code>export/thgtoa.pdf</code> via headless Chromium, then calls <code>scripts/convert.py</code> to produce <code>export/thgtoa-dark.pdf</code>.</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Flag</th>
|
|
<th>Effect</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><code>--both</code></td>
|
|
<td>Light PDF then dark PDF</td>
|
|
</tr>
|
|
<tr>
|
|
<td>(no flag)</td>
|
|
<td>Light PDF only</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>--dark</code></td>
|
|
<td>Dark PDF only (light PDF must already exist)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<h3 id="build-only-the-dark-pdf-from-an-existing-light-pdf">Build only the dark PDF from an existing light PDF<a class="headerlink" href="#build-only-the-dark-pdf-from-an-existing-light-pdf" title="Permanent link">¶</a></h3>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a>python<span class="w"> </span>scripts/convert.py<span class="w"> </span>export/thgtoa.pdf<span class="w"> </span>export/thgtoa-dark.pdf
|
|
</code></pre></div>
|
|
<p>Options:</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Flag</th>
|
|
<th>Default</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><code>--dpi</code></td>
|
|
<td><code>200</code></td>
|
|
<td>Rasterization DPI. 150 = smaller file, 300 = sharper but slow</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>--batch-size</code></td>
|
|
<td><code>50</code></td>
|
|
<td>Pages per batch. Reduce if you hit OOM</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>--bg</code></td>
|
|
<td><code>1f1f31</code></td>
|
|
<td>Background colour (hex)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>--text</code></td>
|
|
<td><code>e0e0e0</code></td>
|
|
<td>Body text colour (hex)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>--link</code></td>
|
|
<td><code>5e8bde</code></td>
|
|
<td>Link / blue element colour (hex)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<h3 id="preview-the-mkdocs-site">Preview the MkDocs site<a class="headerlink" href="#preview-the-mkdocs-site" title="Permanent link">¶</a></h3>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a>mkdocs<span class="w"> </span>serve
|
|
</code></pre></div>
|
|
<p>Opens at <code>http://127.0.0.1:8000</code>.</p>
|
|
<hr />
|
|
<h2 id="pushing-changes">Pushing changes<a class="headerlink" href="#pushing-changes" title="Permanent link">¶</a></h2>
|
|
<p>The pipeline triggers automatically when you push to <code>main</code> — no manual steps are needed for normal contributions.</p>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a>push to main
|
|
<a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a> │
|
|
<a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a> ▼
|
|
<a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a>build.yml builds thgtoa.pdf + thgtoa-dark.pdf
|
|
<a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a> │ (workflow_run on success)
|
|
<a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a> ▼
|
|
<a id="__codelineno-6-7" name="__codelineno-6-7" href="#__codelineno-6-7"></a>sign.yml SHA-256 + BLAKE2b hashes, GPG detached signatures
|
|
<a id="__codelineno-6-8" name="__codelineno-6-8" href="#__codelineno-6-8"></a> │ (workflow_run on success)
|
|
<a id="__codelineno-6-9" name="__codelineno-6-9" href="#__codelineno-6-9"></a> ▼
|
|
<a id="__codelineno-6-10" name="__codelineno-6-10" href="#__codelineno-6-10"></a>release.yml VirusTotal scan → tagged GitHub Release
|
|
<a id="__codelineno-6-11" name="__codelineno-6-11" href="#__codelineno-6-11"></a> │
|
|
<a id="__codelineno-6-12" name="__codelineno-6-12" href="#__codelineno-6-12"></a>changelog.yml prepends new ## [vX.Y.Z] entry → commits back to main
|
|
</code></pre></div>
|
|
<p>Each stage runs independently and can be re-triggered manually from the Actions tab. If the build succeeds but signing fails (e.g. an expired key), you can re-run only <code>sign.yml</code> pointing at the existing build artifact without rebuilding the PDFs.</p>
|
|
<div class="admonition warning">
|
|
<p class="admonition-title">Before you push</p>
|
|
<ul>
|
|
<li>Make sure the working tree is clean (<code>git status</code>)</li>
|
|
<li>Run <code>mkdocs build</code> locally if you changed <code>docs/</code> to catch broken links before CI does</li>
|
|
<li>If you added new footnotes, verify they have both a definition <code>[^N]:</code> and at least one inline citation <code>[^N]</code></li>
|
|
</ul>
|
|
</div>
|
|
<hr />
|
|
<h2 id="github-secrets">GitHub Secrets<a class="headerlink" href="#github-secrets" title="Permanent link">¶</a></h2>
|
|
<p>These must be configured in <strong>Settings → Secrets and variables → Actions</strong> before the pipeline will fully work. The build step requires no secrets; signing and releasing require all of them.</p>
|
|
<h3 id="gpg_private_key"><code>GPG_PRIVATE_KEY</code><a class="headerlink" href="#gpg_private_key" title="Permanent link">¶</a></h3>
|
|
<p>The ASCII-armored private key used to sign PDFs and hash files.</p>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="c1"># Export the release signing key</span>
|
|
<a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a>gpg<span class="w"> </span>--armor<span class="w"> </span>--export-secret-keys<span class="w"> </span>C3023DBEA3FB38C438BA1EEDCEC60AEDE8B992A2
|
|
</code></pre></div>
|
|
<p>Copy the entire output (including <code>-----BEGIN PGP PRIVATE KEY BLOCK-----</code> and the closing line) and paste it as the secret value.</p>
|
|
<div class="admonition danger">
|
|
<p class="admonition-title">Key security</p>
|
|
<p>This is the release signing key. Only repository admins should have access to it. Never commit it to the repository or share it outside of GitHub Secrets.</p>
|
|
</div>
|
|
<hr />
|
|
<h3 id="gpg_passphrase"><code>GPG_PASSPHRASE</code><a class="headerlink" href="#gpg_passphrase" title="Permanent link">¶</a></h3>
|
|
<p>The passphrase protecting the private key above. Must match exactly — no trailing newline.</p>
|
|
<hr />
|
|
<h3 id="vt_api_key"><code>VT_API_KEY</code><a class="headerlink" href="#vt_api_key" title="Permanent link">¶</a></h3>
|
|
<p>A <a href="https://www.virustotal.com">VirusTotal</a> API key with file upload permissions. Used by <code>release.yml</code> to scan both PDFs before publishing the release.</p>
|
|
<p>Get one by creating a free account at <code>virustotal.com</code> → API key under your profile. The free tier allows 4 lookups/minute and 500/day, which is sufficient for the two PDFs per release.</p>
|
|
<hr />
|
|
<h3 id="changelog_pat"><code>CHANGELOG_PAT</code><a class="headerlink" href="#changelog_pat" title="Permanent link">¶</a></h3>
|
|
<p>A GitHub <strong>Personal Access Token</strong> with <code>contents: write</code> scope on this repository.</p>
|
|
<p><strong>Why it's needed:</strong> <code>changelog.yml</code> commits back to <code>main</code> after each build. Commits made with the default <code>GITHUB_TOKEN</code> do not trigger further workflow runs (GitHub's loop-prevention policy). A PAT bypasses this so the changelog commit itself can be picked up by downstream workflows if needed.</p>
|
|
<p><strong>Creating one:</strong></p>
|
|
<ol>
|
|
<li>Go to GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens</li>
|
|
<li>Set repository access to <strong>Only select repositories</strong> → this repo</li>
|
|
<li>Under Permissions → Repository permissions, set <strong>Contents</strong> to <strong>Read and write</strong></li>
|
|
<li>Set an expiration and add it as the <code>CHANGELOG_PAT</code> secret</li>
|
|
</ol>
|
|
<p>If this secret is absent, <code>changelog.yml</code> falls back to <code>GITHUB_TOKEN</code> — the commit still happens, it just won't trigger further workflows.</p>
|
|
<hr />
|
|
<h3 id="secrets-summary">Secrets summary<a class="headerlink" href="#secrets-summary" title="Permanent link">¶</a></h3>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Secret</th>
|
|
<th>Required by</th>
|
|
<th>What happens if missing</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><code>GPG_PRIVATE_KEY</code></td>
|
|
<td><code>sign.yml</code></td>
|
|
<td>Signing step fails — no <code>.sig</code> files produced</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>GPG_PASSPHRASE</code></td>
|
|
<td><code>sign.yml</code></td>
|
|
<td>GPG import succeeds but signing fails</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>VT_API_KEY</code></td>
|
|
<td><code>release.yml</code></td>
|
|
<td>VirusTotal step fails — release is not published</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>CHANGELOG_PAT</code></td>
|
|
<td><code>changelog.yml</code></td>
|
|
<td>Falls back to <code>GITHUB_TOKEN</code> — changelog still updates, but commit won't trigger downstream workflows</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<hr />
|
|
<h2 id="cutting-a-release">Cutting a release<a class="headerlink" href="#cutting-a-release" title="Permanent link">¶</a></h2>
|
|
<p>Releases are tagged manually by maintainers. The <code>tag_release.py</code> script handles everything interactively.</p>
|
|
<h3 id="requirements">Requirements<a class="headerlink" href="#requirements" title="Permanent link">¶</a></h3>
|
|
<ul>
|
|
<li>Your GPG keyring must contain the release signing key (<code>C302 3DBE A3FB 38C4 38BA 1EED CEC6 0AED E8B9 92A2</code>)</li>
|
|
<li>The working tree must be clean</li>
|
|
<li>You must be on the <code>main</code> branch</li>
|
|
<li>A <code>## [vX.Y.Z]</code> entry must exist in <code>docs/changelog/index.md</code> for the version you are tagging</li>
|
|
</ul>
|
|
<h3 id="import-the-release-key-first-time-only">Import the release key (first time only)<a class="headerlink" href="#import-the-release-key-first-time-only" title="Permanent link">¶</a></h3>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a>gpg<span class="w"> </span>--import<span class="w"> </span>pgp/anonymousplanet-release.asc
|
|
</code></pre></div>
|
|
<h3 id="run-the-release-tagger">Run the release tagger<a class="headerlink" href="#run-the-release-tagger" title="Permanent link">¶</a></h3>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a>python<span class="w"> </span>scripts/tag_release.py
|
|
</code></pre></div>
|
|
<p>The script will:</p>
|
|
<ol>
|
|
<li>Check the working tree is clean and you are on <code>main</code></li>
|
|
<li>Detect the latest tag and propose the next patch version</li>
|
|
<li>Pull the matching changelog entry and format it as the tag message</li>
|
|
<li>Show you the full tag message for review</li>
|
|
<li>Ask for confirmation before creating anything</li>
|
|
<li>Create a GPG-signed annotated tag with <code>git tag -s</code></li>
|
|
<li>Verify the signature</li>
|
|
<li>Print the push command</li>
|
|
</ol>
|
|
<p>To specify a version explicitly:</p>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a>python<span class="w"> </span>scripts/tag_release.py<span class="w"> </span>--version<span class="w"> </span>v1.2.4
|
|
</code></pre></div>
|
|
<p>To preview without creating the tag:</p>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a>python<span class="w"> </span>scripts/tag_release.py<span class="w"> </span>--dry-run
|
|
</code></pre></div>
|
|
<p>To use a different signing key:</p>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a>python<span class="w"> </span>scripts/tag_release.py<span class="w"> </span>--key<span class="w"> </span><fingerprint>
|
|
</code></pre></div>
|
|
<h3 id="push-the-tag">Push the tag<a class="headerlink" href="#push-the-tag" title="Permanent link">¶</a></h3>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a>git<span class="w"> </span>push<span class="w"> </span>origin<span class="w"> </span>v1.2.4
|
|
</code></pre></div>
|
|
<h3 id="trigger-the-release-workflow">Trigger the release workflow<a class="headerlink" href="#trigger-the-release-workflow" title="Permanent link">¶</a></h3>
|
|
<p>Pushing a tag does <strong>not</strong> automatically trigger <code>release.yml</code> (it listens to <code>workflow_run</code> from <code>sign.yml</code>, not tag pushes). After pushing the tag, go to <strong>Actions → Release → Run workflow</strong> and paste the most recent <code>sign.yml</code> run ID to publish the GitHub Release.</p>
|
|
<hr />
|
|
<h2 id="verifying-a-release">Verifying a release<a class="headerlink" href="#verifying-a-release" title="Permanent link">¶</a></h2>
|
|
<p>Anyone can verify the authenticity of a release download.</p>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="c1"># Import the release signing key</span>
|
|
<a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a>gpg<span class="w"> </span>--import<span class="w"> </span>pgp/anonymousplanet-release.asc
|
|
<a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a>
|
|
<a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a><span class="c1"># Verify the PDFs</span>
|
|
<a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a>gpg<span class="w"> </span>--verify<span class="w"> </span>thgtoa.pdf.sig<span class="w"> </span>thgtoa.pdf
|
|
<a id="__codelineno-14-6" name="__codelineno-14-6" href="#__codelineno-14-6"></a>gpg<span class="w"> </span>--verify<span class="w"> </span>thgtoa-dark.pdf.sig<span class="w"> </span>thgtoa-dark.pdf
|
|
<a id="__codelineno-14-7" name="__codelineno-14-7" href="#__codelineno-14-7"></a>
|
|
<a id="__codelineno-14-8" name="__codelineno-14-8" href="#__codelineno-14-8"></a><span class="c1"># Verify the hash files themselves</span>
|
|
<a id="__codelineno-14-9" name="__codelineno-14-9" href="#__codelineno-14-9"></a>gpg<span class="w"> </span>--verify<span class="w"> </span>sha256sums.txt.sig<span class="w"> </span>sha256sums.txt
|
|
<a id="__codelineno-14-10" name="__codelineno-14-10" href="#__codelineno-14-10"></a>gpg<span class="w"> </span>--verify<span class="w"> </span>b2sums.txt.sig<span class="w"> </span>b2sums.txt
|
|
<a id="__codelineno-14-11" name="__codelineno-14-11" href="#__codelineno-14-11"></a>
|
|
<a id="__codelineno-14-12" name="__codelineno-14-12" href="#__codelineno-14-12"></a><span class="c1"># Check the PDF hashes match</span>
|
|
<a id="__codelineno-14-13" name="__codelineno-14-13" href="#__codelineno-14-13"></a>sha256sum<span class="w"> </span>-c<span class="w"> </span>sha256sums.txt
|
|
<a id="__codelineno-14-14" name="__codelineno-14-14" href="#__codelineno-14-14"></a>b2sum<span class="w"> </span>-c<span class="w"> </span>b2sums.txt
|
|
</code></pre></div>
|
|
<p>A successful verify looks like:</p>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a>gpg: Signature made ...
|
|
<a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a>gpg: Good signature from "Anonymous Planet (Release) ..."
|
|
</code></pre></div>
|
|
<hr />
|
|
<h2 id="troubleshooting">Troubleshooting<a class="headerlink" href="#troubleshooting" title="Permanent link">¶</a></h2>
|
|
<p><strong><code>cairosvg</code> missing during MkDocs build</strong>
|
|
Install the imaging extras: <code>pip install "mkdocs-material[imaging]"</code>. This is required by the <code>social</code> plugin.</p>
|
|
<p><strong><code>KeyError: 'JPEG'</code> in convert.py</strong>
|
|
Pillow needs libjpeg for RGB→PDF encoding. The script works around this by quantizing to palette mode before saving, so this error should not appear with the current code. If it does, reinstall Pillow after installing libjpeg: <code>sudo apt install libjpeg-dev && pip install --force-reinstall pillow</code>.</p>
|
|
<p><strong><code>qpdf: can't find PDF header</code></strong>
|
|
An older version of <code>convert.py</code> tried to pass PNG files to qpdf. Make sure you are running the current version — qpdf only accepts PDF inputs to <code>--pages</code>.</p>
|
|
<p><strong>GPG signing fails on CI with <code>No secret key</code></strong>
|
|
The <code>GPG_PRIVATE_KEY</code> secret is missing or malformed. Re-export with <code>gpg --armor --export-secret-keys <fingerprint></code> and paste the full block including the header and footer lines.</p>
|
|
<p><strong>GPG signing fails with <code>Bad passphrase</code></strong>
|
|
The <code>GPG_PASSPHRASE</code> secret has a trailing space or newline. Paste it again carefully with no surrounding whitespace.</p>
|
|
<p><strong><code>release.yml</code> fails on VirusTotal</strong>
|
|
The <code>VT_API_KEY</code> is missing, invalid, or over the rate limit (500 requests/day on the free tier). Check the secret and re-run the workflow after a few minutes.</p>
|
|
<p><strong>Footnote warnings from MkDocs (<code>link '#fnref:N' has no anchor</code>)</strong>
|
|
A footnote definition <code>[^N]:</code> exists without a matching inline citation <code>[^N]</code> in the body text. Add the citation where it belongs in the guide, or remove the orphaned definition.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</article>
|
|
</div>
|
|
|
|
|
|
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var tab,labels=set.querySelector(".tabbed-labels");for(tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
|
|
|
|
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
|
</div>
|
|
|
|
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12Z"/></svg>
|
|
Back to top
|
|
</button>
|
|
|
|
</main>
|
|
|
|
<footer class="md-footer">
|
|
|
|
<div class="md-footer-meta md-typeset">
|
|
<div class="md-footer-meta__inner md-grid">
|
|
<div class="md-copyright">
|
|
|
|
<div class="md-copyright__highlight">
|
|
<a href="https://anonymousplanet.org/">The Hitchhiker's Guide</a> ©2023-2026 by <a href="https://psa.anonymousplanet.org/">Anonymous Planet</a> is licensed under <a href="https://creativecommons.org/licenses/by-nc/4.0/">CC BY-NC 4.0</a><img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg" alt="" style="max-width: 1em;max-height:1em;margin-left: .2em;"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg" alt="" style="max-width: 1em;max-height:1em;margin-left: .2em;"><img src="https://mirrors.creativecommons.org/presskit/icons/nc.svg" alt="" style="max-width: 1em;max-height:1em;margin-left: .2em;"></a>
|
|
|
|
</div>
|
|
|
|
|
|
Made with
|
|
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
|
Material for MkDocs
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<div class="md-social">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://mastodon.social/@anonymousplanet" target="_blank" rel="noopener me" title="Mastodon" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<a href="http://wmj5kiic7b6kjplpbvwadnht2nh2qnkbnqtcv3dyvpqtz7ssbssftxid.onion/" target="_blank" rel="noopener" title="0xacab" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m23.6 9.593-.033-.086L20.3.98a.851.851 0 0 0-.336-.405.875.875 0 0 0-1 .054.875.875 0 0 0-.29.44L16.47 7.818H7.537L5.332 1.07a.857.857 0 0 0-.29-.441.875.875 0 0 0-1-.054.859.859 0 0 0-.336.405L.433 9.502l-.032.086a6.066 6.066 0 0 0 2.012 7.01l.01.009.03.021 4.977 3.727 2.462 1.863 1.5 1.132a1.008 1.008 0 0 0 1.22 0l1.499-1.132 2.461-1.863 5.006-3.75.013-.01a6.068 6.068 0 0 0 2.01-7.002z"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<a href="http://it7otdanqu7ktntxzm427cba6i53w6wlanlh23v5i3siqmos47pzhvyd.onion/anonymousplanetorg" target="_blank" rel="noopener" title="Darktea" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4.209 4.603c-.247 0-.525.02-.84.088-.333.07-1.28.283-2.054 1.027C-.403 7.25.035 9.685.089 10.052c.065.446.263 1.687 1.21 2.768 1.749 2.141 5.513 2.092 5.513 2.092s.462 1.103 1.168 2.119c.955 1.263 1.936 2.248 2.89 2.367 2.406 0 7.212-.004 7.212-.004s.458.004 1.08-.394c.535-.324 1.013-.893 1.013-.893s.492-.527 1.18-1.73c.21-.37.385-.729.538-1.068 0 0 2.107-4.471 2.107-8.823-.042-1.318-.367-1.55-.443-1.627-.156-.156-.366-.153-.366-.153s-4.475.252-6.792.306c-.508.011-1.012.023-1.512.027v4.474l-.634-.301c0-1.39-.004-4.17-.004-4.17-1.107.016-3.405-.084-3.405-.084s-5.399-.27-5.987-.324c-.187-.011-.401-.032-.648-.032zm.354 1.832h.111s.271 2.269.6 3.597C5.549 11.147 6.22 13 6.22 13s-.996-.119-1.641-.348c-.99-.324-1.409-.714-1.409-.714s-.73-.511-1.096-1.52C1.444 8.73 2.021 7.7 2.021 7.7s.32-.859 1.47-1.145c.395-.106.863-.12 1.072-.12zm8.33 2.554c.26.003.509.127.509.127l.868.422-.529 1.075a.686.686 0 0 0-.614.359.685.685 0 0 0 .072.756l-.939 1.924a.69.69 0 0 0-.66.527.687.687 0 0 0 .347.763.686.686 0 0 0 .867-.206.688.688 0 0 0-.069-.882l.916-1.874a.667.667 0 0 0 .237-.02.657.657 0 0 0 .271-.137 8.826 8.826 0 0 1 1.016.512.761.761 0 0 1 .286.282c.073.21-.073.569-.073.569-.087.29-.702 1.55-.702 1.55a.692.692 0 0 0-.676.477.681.681 0 1 0 1.157-.252c.073-.141.141-.282.214-.431.19-.397.515-1.16.515-1.16.035-.066.218-.394.103-.814-.095-.435-.48-.638-.48-.638-.467-.301-1.116-.58-1.116-.58s0-.156-.042-.27a.688.688 0 0 0-.148-.241l.516-1.062 2.89 1.401s.48.218.583.619c.073.282-.019.534-.069.657-.24.587-2.1 4.317-2.1 4.317s-.232.554-.748.588a1.065 1.065 0 0 1-.393-.045l-.202-.08-4.31-2.1s-.417-.218-.49-.596c-.083-.31.104-.691.104-.691l2.073-4.272s.183-.37.466-.497a.855.855 0 0 1 .35-.077z"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://github.com/anon-planet" target="_blank" rel="noopener" title="Github" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://gitlab.com/anonymousplanetorg" target="_blank" rel="noopener" title="Gitlab" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m23.6 9.593-.033-.086L20.3.98a.851.851 0 0 0-.336-.405.875.875 0 0 0-1 .054.875.875 0 0 0-.29.44L16.47 7.818H7.537L5.332 1.07a.857.857 0 0 0-.29-.441.875.875 0 0 0-1-.054.859.859 0 0 0-.336.405L.433 9.502l-.032.086a6.066 6.066 0 0 0 2.012 7.01l.01.009.03.021 4.977 3.727 2.462 1.863 1.5 1.132a1.008 1.008 0 0 0 1.22 0l1.499-1.132 2.461-1.863 5.006-3.75.013-.01a6.068 6.068 0 0 0 2.01-7.002z"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://codeberg.org/anonymousplanet" target="_blank" rel="noopener" title="Codeberg" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11.955.49A12 12 0 0 0 0 12.49a12 12 0 0 0 1.832 6.373L11.838 5.928a.187.14 0 0 1 .324 0l10.006 12.935A12 12 0 0 0 24 12.49a12 12 0 0 0-12-12 12 12 0 0 0-.045 0zm.375 6.467 4.416 16.553a12 12 0 0 0 5.137-4.213z"/></svg>
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
</div>
|
|
<div class="md-dialog" data-md-component="dialog">
|
|
<div class="md-dialog__inner md-typeset"></div>
|
|
</div>
|
|
|
|
|
|
<script id="__config" type="application/json">{"base": "../..", "features": ["navigation.instant", "navigation.instant.prefetch", "navigation.tabs", "navigation.sections", "toc.integrate", "navigation.top", "search.suggest", "search.highlight", "content.tabs.link", "content.code.annotation", "content.code.copy"], "search": "../../assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
|
|
|
|
|
|
<script src="../../assets/javascripts/bundle.1e8ae164.min.js"></script>
|
|
|
|
|
|
</body>
|
|
</html> |