#! /usr/bin/env python3 import os import subprocess def run(*args): subprocess.call(args) def link(active:str, id:str, text:str)->str: items = ['{text}') return str().join(items) def nav(active:str=None)->str: return f'''\ ''' def main(): style = 'css' script = 'js' root = os.path.dirname(os.path.realpath(__file__)) input_directory = os.path.join(root, 'in') out = os.path.join(root, 'out') web = os.path.join(out, 'web') css = os.path.join(web, style) js = os.path.join(web, script) # run('rsync', '--archive', f'{input_directory}/', f'{web}/') for directory in [css, js]: os.makedirs(directory, exist_ok=True) # link_gv = os.path.join(root, 'link.gv') link_svg = os.path.join(web, 'link.svg') run('dot', link_gv, '-Tsvg', '-o', link_svg) with open(link_svg, 'br') as f: link_text = f.read().decode('u8') page_file = os.path.join(web, 'index.html') page_text = f'''\ Marc Beninca

Marc Beninca

{nav('main')} {tabs['main']}
{nav('cv')} {tabs['cv']}
{nav('git')} {tabs['git']}
{nav('health')} {tabs['health']}
{nav('id')} {tabs['id']}
{nav('lib')} {tabs['lib']}
{nav('music')} {tabs['music']}
{nav('pubnix')} {tabs['pubnix']}
{nav('thesis')} {tabs['thesis']}
{nav('vegan')} {tabs['vegan']}
{nav('others')} {tabs['others']}
''' css_file = os.path.join(css, 'index.css') css_text = f'''\ @media screen and (max-width: 1200px) {{ html {{ font-size: 2em; }} }} /* * {{ border: 1px solid; }} /* header {{ background: #800000; }} nav {{ background: #008000; }} section {{ background: #000080; }} /**/ * {{ box-sizing: border-box; //margin: 0; //padding: 0; }} body {{ background: rgb(255,255,255); color: rgb(0,0,0); font-family: sans; font-size: 1.25em; margin: 0 auto; position: relative; }} body.dark {{ background: rgb(0,0,0); color: rgb(160,160,160); }} header {{ background-image: url("../img/debian.jpeg"); background-position: center; background-size: cover; padding: 1vh 1vw 0 1vw; position: absolute; width: 100%; z-index: 1; }} section {{ min-height: 100vh; padding: 7em 1vw 1vh 1vw; position: absolute; top: 0; width: 100%; }} section:not(:target) {{ display: none; }} section:target {{ display: block; }} nav {{ display: flex; flex-wrap: wrap; }} img {{ border: 1px solid; border-color: rgb(192,192,192); border-radius: 1em; height: 8em; }} a {{ text-decoration: none; }} nav a {{ background: linear-gradient(rgba(64,64,64,1), rgba(64,64,64,0)); border-color: rgb(128,128,128); border-radius: .5em; border-style: solid; border-width: 1px 1px 0 1px; #color: rgb(128,128,0); font-weight: bold; padding: .25em .5em; //transition: all .5s; }} nav a.active {{ background: linear-gradient(rgba(128,128,128,1), rgba(128,128,128,0)); }} a {{ color: rgb(0,192,192); }} a:hover {{ color: rgb(192,0,0); }} a:visited {{ color: rgb(0,160,160); }} table {{ empty-cells: hide; }} th,td {{ border-radius: .2em; }} th {{ background: rgb(64,64,64); color: rgb(128,128,0); }} td {{ background: rgb(48,48,48); border: 1px solid; border-color: rgb(192,192,192); text-align: center; }} .cards {{ display: flex; }} .card {{ list-style: none; margin: 0 1em; text-align: center; }} .card img {{ border: none; height: 4em; }} /**/ .tabs {{ display: flex; flex-wrap: wrap; }} .tabs > input {{ display: none; }} .tabs > input:checked + label + div {{ display: block; }} .tabs > label {{ order: 1; }} .tabs > div {{ display: none; flex-basis: 100%; order: 2; }} .tabs {{ border: 1px solid; }} .tabs > input:checked + label {{ background-color: gray; }} .tabs > label {{ padding: 10px; }} .tabs > div {{ padding: 10px; }} ''' js_file = os.path.join(js, 'index.js') js_text = f'''\ function check(tab) {{ const tabs = tab.split('/') let id = 'tab' for (tab of tabs) {{ id = `${{id}}/${{tab}}` document.getElementById(id).checked = true }} }} function push(tab) {{ window.history.pushState(null, null, `?tab=${{tab}}`) }} function update(id) {{ const tab = id.split('/').slice(1).join('/') push(tab) }} function main() {{ let tab = (new URL(document.location)).searchParams.get('tab') if (tab) {{ check(tab) }} else {{ tab = '1/1' check(tab) push(tab) }} }}''' # {link_text} with open(page_file, 'bw') as f: f.write(page_text.encode('u8')) with open(css_file, 'bw') as f: f.write(css_text.encode('u8')) with open(js_file, 'bw') as f: f.write(js_text.encode('u8')) tabs = { #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'main': f'''\ ''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'cv': f'''\ ''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'git': f'''\

''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'health': f'''\
''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'id': f'''\
OpenPGP
marc.beninca.link
meta.sr.ht
keys.openpgp.org
Key
Base
Key
Oxide
Libera
Pay
Patreon Tip
eee
CC / BTC Mastodon Discord
CC / ZEC GitLab YouTube
DMOJ Pleroma FaceBook
GalacticTalk PixelFed OpenStreetMap Instagram
Reddit Twitch Vimeo
Twitter
HackerNews BitBucket
Lobsters LinuxFR
GitHub
DNS
beninca.link
computing.land
marc-beninca.fr
rwx.work
tilde.link
GitLab
Debian
FramaGit
FrogGit
GitGud
Insomnia
Gitea
42l
AFPy
Chapril
CodeBerg
DisRoot
Envs
Froggies
FSFE
GitDab
Gitea
ProjectSegfault
TildeGit
TildeVarsh
StackExchange
Meta
ServerFault
StackOverflow
TeX
Unix
''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'lib': f'''\ ''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'music': f'''\
''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'pubnix': f'''\
''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'thesis': f'''\ ''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'vegan': f'''\
''', #⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ 'others': f'''\

''', } if __name__ == '__main__': main()