Compare commits

...

8 Commits

17 changed files with 259 additions and 372 deletions

View File

@@ -3,71 +3,83 @@ td.linenos .normal { color: inherit; background-color: transparent; padding-left
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.codehilite .hll { background-color: #ffffcc }
.codehilite .c { color: #3D7B7B; font-style: italic } /* Comment */ /* From https://github.com/richleland/pygments-css/blob/master/native.css */
.codehilite .err { border: 1px solid #FF0000 } /* Error */ .codehilite .hll { background-color: #404040 }
.codehilite .k { color: #008000; font-weight: bold } /* Keyword */ .codehilite { background: #202020; color: #d0d0d0 }
.codehilite .o { color: #666666 } /* Operator */ .codehilite .c { color: #999999; font-style: italic } /* Comment */
.codehilite .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ .codehilite .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.codehilite .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ .codehilite .esc { color: #d0d0d0 } /* Escape */
.codehilite .cp { color: #9C6500 } /* Comment.Preproc */ .codehilite .g { color: #d0d0d0 } /* Generic */
.codehilite .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ .codehilite .k { color: #6ab825; font-weight: bold } /* Keyword */
.codehilite .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ .codehilite .l { color: #d0d0d0 } /* Literal */
.codehilite .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ .codehilite .n { color: #d0d0d0 } /* Name */
.codehilite .gd { color: #A00000 } /* Generic.Deleted */ .codehilite .o { color: #d0d0d0 } /* Operator */
.codehilite .ge { font-style: italic } /* Generic.Emph */ .codehilite .x { color: #d0d0d0 } /* Other */
.codehilite .gr { color: #E40000 } /* Generic.Error */ .codehilite .p { color: #d0d0d0 } /* Punctuation */
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .codehilite .ch { color: #999999; font-style: italic } /* Comment.Hashbang */
.codehilite .gi { color: #008400 } /* Generic.Inserted */ .codehilite .cm { color: #999999; font-style: italic } /* Comment.Multiline */
.codehilite .go { color: #717171 } /* Generic.Output */ .codehilite .cp { color: #cd2828; font-weight: bold } /* Comment.Preproc */
.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ .codehilite .cpf { color: #999999; font-style: italic } /* Comment.PreprocFile */
.codehilite .gs { font-weight: bold } /* Generic.Strong */ .codehilite .c1 { color: #999999; font-style: italic } /* Comment.Single */
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .codehilite .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */
.codehilite .gt { color: #0044DD } /* Generic.Traceback */ .codehilite .gd { color: #d22323 } /* Generic.Deleted */
.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ .codehilite .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */
.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ .codehilite .gr { color: #d22323 } /* Generic.Error */
.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ .codehilite .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */
.codehilite .kp { color: #008000 } /* Keyword.Pseudo */ .codehilite .gi { color: #589819 } /* Generic.Inserted */
.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ .codehilite .go { color: #cccccc } /* Generic.Output */
.codehilite .kt { color: #B00040 } /* Keyword.Type */ .codehilite .gp { color: #aaaaaa } /* Generic.Prompt */
.codehilite .m { color: #666666 } /* Literal.Number */ .codehilite .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */
.codehilite .s { color: #BA2121 } /* Literal.String */ .codehilite .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */
.codehilite .na { color: #687822 } /* Name.Attribute */ .codehilite .gt { color: #d22323 } /* Generic.Traceback */
.codehilite .nb { color: #008000 } /* Name.Builtin */ .codehilite .kc { color: #6ab825; font-weight: bold } /* Keyword.Constant */
.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */ .codehilite .kd { color: #6ab825; font-weight: bold } /* Keyword.Declaration */
.codehilite .no { color: #880000 } /* Name.Constant */ .codehilite .kn { color: #6ab825; font-weight: bold } /* Keyword.Namespace */
.codehilite .nd { color: #AA22FF } /* Name.Decorator */ .codehilite .kp { color: #6ab825 } /* Keyword.Pseudo */
.codehilite .ni { color: #717171; font-weight: bold } /* Name.Entity */ .codehilite .kr { color: #6ab825; font-weight: bold } /* Keyword.Reserved */
.codehilite .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ .codehilite .kt { color: #6ab825; font-weight: bold } /* Keyword.Type */
.codehilite .nf { color: #0000FF } /* Name.Function */ .codehilite .ld { color: #d0d0d0 } /* Literal.Date */
.codehilite .nl { color: #767600 } /* Name.Label */ .codehilite .m { color: #3677a9 } /* Literal.Number */
.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ .codehilite .s { color: #ed9d13 } /* Literal.String */
.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */ .codehilite .na { color: #bbbbbb } /* Name.Attribute */
.codehilite .nv { color: #19177C } /* Name.Variable */ .codehilite .nb { color: #24909d } /* Name.Builtin */
.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ .codehilite .nc { color: #447fcf; text-decoration: underline } /* Name.Class */
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */ .codehilite .no { color: #40ffff } /* Name.Constant */
.codehilite .mb { color: #666666 } /* Literal.Number.Bin */ .codehilite .nd { color: #ffa500 } /* Name.Decorator */
.codehilite .mf { color: #666666 } /* Literal.Number.Float */ .codehilite .ni { color: #d0d0d0 } /* Name.Entity */
.codehilite .mh { color: #666666 } /* Literal.Number.Hex */ .codehilite .ne { color: #bbbbbb } /* Name.Exception */
.codehilite .mi { color: #666666 } /* Literal.Number.Integer */ .codehilite .nf { color: #447fcf } /* Name.Function */
.codehilite .mo { color: #666666 } /* Literal.Number.Oct */ .codehilite .nl { color: #d0d0d0 } /* Name.Label */
.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */ .codehilite .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */
.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */ .codehilite .nx { color: #d0d0d0 } /* Name.Other */
.codehilite .sc { color: #BA2121 } /* Literal.String.Char */ .codehilite .py { color: #d0d0d0 } /* Name.Property */
.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */ .codehilite .nt { color: #6ab825; font-weight: bold } /* Name.Tag */
.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ .codehilite .nv { color: #40ffff } /* Name.Variable */
.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */ .codehilite .ow { color: #6ab825; font-weight: bold } /* Operator.Word */
.codehilite .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ .codehilite .w { color: #666666 } /* Text.Whitespace */
.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */ .codehilite .mb { color: #3677a9 } /* Literal.Number.Bin */
.codehilite .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ .codehilite .mf { color: #3677a9 } /* Literal.Number.Float */
.codehilite .sx { color: #008000 } /* Literal.String.Other */ .codehilite .mh { color: #3677a9 } /* Literal.Number.Hex */
.codehilite .sr { color: #A45A77 } /* Literal.String.Regex */ .codehilite .mi { color: #3677a9 } /* Literal.Number.Integer */
.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */ .codehilite .mo { color: #3677a9 } /* Literal.Number.Oct */
.codehilite .ss { color: #19177C } /* Literal.String.Symbol */ .codehilite .sa { color: #ed9d13 } /* Literal.String.Affix */
.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */ .codehilite .sb { color: #ed9d13 } /* Literal.String.Backtick */
.codehilite .fm { color: #0000FF } /* Name.Function.Magic */ .codehilite .sc { color: #ed9d13 } /* Literal.String.Char */
.codehilite .vc { color: #19177C } /* Name.Variable.Class */ .codehilite .dl { color: #ed9d13 } /* Literal.String.Delimiter */
.codehilite .vg { color: #19177C } /* Name.Variable.Global */ .codehilite .sd { color: #ed9d13 } /* Literal.String.Doc */
.codehilite .vi { color: #19177C } /* Name.Variable.Instance */ .codehilite .s2 { color: #ed9d13 } /* Literal.String.Double */
.codehilite .vm { color: #19177C } /* Name.Variable.Magic */ .codehilite .se { color: #ed9d13 } /* Literal.String.Escape */
.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */ .codehilite .sh { color: #ed9d13 } /* Literal.String.Heredoc */
.codehilite .si { color: #ed9d13 } /* Literal.String.Interpol */
.codehilite .sx { color: #ffa500 } /* Literal.String.Other */
.codehilite .sr { color: #ed9d13 } /* Literal.String.Regex */
.codehilite .s1 { color: #ed9d13 } /* Literal.String.Single */
.codehilite .ss { color: #ed9d13 } /* Literal.String.Symbol */
.codehilite .bp { color: #24909d } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #447fcf } /* Name.Function.Magic */
.codehilite .vc { color: #40ffff } /* Name.Variable.Class */
.codehilite .vg { color: #40ffff } /* Name.Variable.Global */
.codehilite .vi { color: #40ffff } /* Name.Variable.Instance */
.codehilite .vm { color: #40ffff } /* Name.Variable.Magic */
.codehilite .il { color: #3677a9 } /* Literal.Number.Integer.Long */

View File

@@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJMBAABCAA2FiEEvBU+39pRCqHFhwUCToYVYy9G5oAFAmGjjaYYHHBhcGF0dXR1
d2F3YUBwb2x5bm9tLm1lAAoJEE6GFWMvRuaA5/4P/1SU69isY6/kRRc2VpZ9MYni
/pCd1yNtoYYC3yuMij22k7nx1osoEGofjdNiSp15DOZI/RVhKdeppU2BxJ8LuejB
wllqjhU5sS2fa9Me0P7Sv33o9jQAUmPKVY3KmdwkNj+/Vd1gmxAYEhoU/9KhzRcF
fF1wVFTfFbtRmHan/3yQbW807W2TnkqOi1c6i6PSCgf20H5rHglOdYzKr1+suQ6T
nx1+2hYlKzPkMyU9+R21PPdU7+3lUMxuvJ301xIOGD3ri45FHKgg5rpagdJctC1w
sVccXQERn0yuU40YHyAmXFy6BOuJk+8Eh7bb/8X/ASpuIjZccyyGlja/h5w3gYYm
rni4ApdH+VtNZtSwTb4plxaktgEXiOvIvF0u7z2Xs4J4XPorvjFwq5nZU2A6MeNd
hDfdmAOOfjfafgigQRSRbx35YInw45USccE9kyib/YlBDf2snCYXgGqGiREBmehf
7tGS10NWidomhn14otlXB/H4kQ8PwjrfpwmDCXPhtCZAQ8g+YF5ynvzjcalQCxEK
D1+0ADpmX7Gbz0AXrRu2mSbYJyJD+11+35KOM6mV1BMU8f3VVRB3FIwb8/jcU4T9
V+Jcnz2KSjxKS9UXVXeGkXcYPEx3zYXwHOwlzfsLmq7wsvjZKSqqOCSicERP5KA2
yZI/9w2nH5fS9S5ZP4rw
=4/jw
-----END PGP SIGNATURE-----

View File

@@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJMBAABCAA2FiEEvBU+39pRCqHFhwUCToYVYy9G5oAFAmPQYqwYHHBhcGF0dXR1
d2F3YUBwb2x5bm9tLm1lAAoJEE6GFWMvRuaAo3cP/2tX/q14L8SJInyupwlHyFUN
fiENN4uLFdr0Uab6VtFIWWGJhmNasKC4uGbEb2YkRuLirtQYjSimTZKk47qOQ9AB
UBE+FC8ryY3bfg6q+rleJFr4ElkpL6XcmYU5pTCcejRH9IrR/wptSmm7fdjiA/eN
udwh9hTUvahLwkYOjKFJICj57lSqxrHZFbcS4qJiNrpMfqAjHJxnPbhADySf/gpd
SNtlcTa+YezvJBsz6GDdBiRMBowFDVfswSYfyrtM+7V2CHOG4K0atVtg/2XlnegN
L1Pu+vd+fXR7u03k08/3ru9qq6FhDFw+Kz9Obq3OlladkU5dCWvhTo0q/BJZQCDh
xcWYua1bGJcziwcJwVHj9d8bfIqVBKF4xX+REG29I7OzxDaiVwUIWxPbz3X/R+d8
ovmpMtLGA9HBvdiCj6dmnZgFWnTk/qacFbYNm2CN9XBBHy4SSwx7/hVyuU1i8RSh
6Md7grZPlku3C3QrtuVDRZmWqxbKqdFcrD38SrV5n7ZyD2Az0hQVUFr9UEPp4smm
2YbtL/iFpaJiMNL9nWTAx/B7td+3IuntYP81KLmPChhRguiE1mtufLh1j37Ibs6k
YopFRISU/FSXZQg8STmDSxcussJYtThfoTCCmwk1JC/ABqxV4zlClmpkQa6r9Ua6
q55Bvt0JMv+dfao4cydb
=PTZb
-----END PGP SIGNATURE-----

View File

@@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJMBAABCAA2FiEEvBU+39pRCqHFhwUCToYVYy9G5oAFAmGjjakYHHBhcGF0dXR1
d2F3YUBwb2x5bm9tLm1lAAoJEE6GFWMvRuaAGeIP/0hNo1wq7xXKWYhQUVqk5mNq
2sPPfxg3+6KNuidUmxnwIpXsIPEw7jJ3xh74hb6afWHH0ZitrIUoLszkcOkEJaNe
Zz+5UfsQybdYbWUsmpJCNK9QKEvwOa7B1TLUeI1ZR6B9KVVIUApg8AEYzBGce5ON
MroYc/oQgEZCm5cSmuVc/+yds/gFwvJUmEZOFbXyhl1jGr499fG5Q/khZ0bwPZP5
swbUBij0A8nBHiso5k+pDPEUIS6mE6hKZBH+gr9/CefCj1LCyiKRDjeNujZqmiRH
r2w/3nARAfr0Vd7X7P/Zsz3iKfP4/SEbHqY6mSGTWyahWajuiJWDMnM6HhIFHXbE
RdH1HSDB2bj93TGHaNDwG/4l0FHyqGHmhtVMo243fXJv1zaLlSabTcXFa0wPEToA
Z4OQcZWjDzumz2OnbBInaev8Q3aQsvkQERs3jbAw9HaKJqn/tOhPCFqrZRlvyhmV
IvcWoPYtqaRA0MCjK7eDlMN1vcllR8owNXLN/xTKoNDPDAKOezalF2NgwNrBDqIM
WEQBHRRa3Atm4aAOH8h8SZ+zYO63cmndCdpRA6eSmZ1lOO5NhmN9OfUX/ulLKFP9
YEefJ0bfANnz2tjaogWAwQeZYSH5Pj51VvmQnwX5D1taBQXqMJbyMFfdsU45JQNu
GYM5qpVHR7NDrj5X4uAG
=t56n
-----END PGP SIGNATURE-----

View File

@@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJMBAABCAA2FiEEvBU+39pRCqHFhwUCToYVYy9G5oAFAmGjjakYHHBhcGF0dXR1
d2F3YUBwb2x5bm9tLm1lAAoJEE6GFWMvRuaA91MP+wX5e2v6CuaOEewjOFwhPWa1
Naq31RhJvuYD3/leIVy4fZa+EkBgk9QNgnavOeKkM1bHlc6bZggE/sLwnTuhoXFX
xSHil8oaF/7rNdgjjNUq8+N3Zo7GSGWJzOyZua/B91mubEDbwF9soqo2mXFzZBC3
ZJODsWcK+l3lz9oiNGGxfa3NbkoNRF2falEYckeUoGg84xYknoSx8aGo8cbmyiRO
aorTF7NtQMyhMXC4CfSoy/wjit1x+JYa11lr7epF4oy7yx+n0e5b58COkA5AEiL9
XGzKe5IfphENj6tL6fnoiO80rXRQ34FaIjSLr/8kwKz/AQ5UIGeRybGPUdTaOz5D
u9AVGD5HvLeUdwVilCf5Lhmutu9+0y86HImPoGYS6n7jZApIDelayaRHhmrcYT29
yxCxHg9ulKBjq6Owbdqhfyf9oWB2gnHYnM8iD7bvJGkHJlLvIDaSsNyiOJeLs50S
hU/UGuAnKRAqHRhZuYhW7Z8NVwxXeJ21lwCF3scxfSn65oAJKwSjIWIXnoEhzRaA
hkLiL4Gq22simb/coNn94VC7xvY439Rvaes86ZYaLsyi5lMJUGtOFrmL33v0iCDB
FS2l42UtMJxQsRezd8gd7IVRJrJynwymHwpu/8YuNP3n1kzv9cva/B7fsccBS5li
1/lQA/A75nkqAqKyO/16
=iSmJ
-----END PGP SIGNATURE-----

View File

@@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJMBAABCAA2FiEEvBU+39pRCqHFhwUCToYVYy9G5oAFAmGjjakYHHBhcGF0dXR1
d2F3YUBwb2x5bm9tLm1lAAoJEE6GFWMvRuaACLAP/2b44Gl5t6beFRRTDuwEWTtY
q+88M9VFYJqoU9Fmvjeeiz5cdBi4PJRVK+U3He+Mxp8EcL64u3XUsKY6OnVJQ2t5
dm1/uWEI8TUIYHGOKyqZtn0TrWUF6NoFsE/KmSWCq307dD0RRtLzDm6ztkE1XoPJ
U/NP54ScCHA9StZPMA6UkLqv6pfV42eiCz3c42m4OfhAq4Ch1q5Nyuyh+GokQVA0
wFtTLzXbJxJZgRvxLhT2tyBMWn2+kp6TfR6ZGkbzzdSObM7v1Cj5ZY0IVAt5wVQC
JEXY5GZ/nyw5zzLyqkZjoDvzlhDCOKz4866uZr87rMAeFpmFb7YKed7sWD/72a8b
z2dg+i8HOM7fm2FFffyPVROZ8WS1v3sZBayFQsNCMZ5hCKJfzqsIIUCYwZ6frNJ/
BMv4bB5tSjmcEMD+pCQNTnRdqLdlZfRRAVIpwyPGPlzS9y+v6wNniyupM0AkeQii
xS5rSXWEBok7Z8hOSX0J206aDDdXVkHhnR80JU3DC3SfDBohAMSfG/9bwnlYBZcS
o3/P3q0u1alfKOgCJorb4sq3t2OdHsTrS3MYWgiyLNFKKfQktenAkToSecP0zgXe
qVbrCuQmZnFuDjtPh45kEK61i/5YveLfHaZX2unHsja4V/vXPOsinvJVMnBsfEzp
1SnNcGw4v1jzT/7Gx8Z3
=eW+1
-----END PGP SIGNATURE-----

View File

@@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJMBAABCAA2FiEEvBU+39pRCqHFhwUCToYVYy9G5oAFAmGjjakYHHBhcGF0dXR1
d2F3YUBwb2x5bm9tLm1lAAoJEE6GFWMvRuaAymcQAKoksLNNyoEuE4/wzaNv56UA
yqg+ylYz0vHnDYPgvawLolkQfrgbKzGa0zN3ugMvHR7sVQxdsT4BqmjSSs0CR1P9
aWIfBBoPAB0OzKh7M64/K2vVeok/tbfa2Y5DFYGZbBuKDxJwr40Tfu4kJNk89LZQ
KGed9+ZJo8STtdy7VjNL5sQIBMtGfFtNW9cYVR5Fr4uF/m2FKc6zYLXA5t3tbIWD
RzIjD1s6GYLeLmj0ZGtgopLWX6ERIAtiveCn+LmPYtU+wsPBOv8Xg8+nQWq6bwpO
8WHuQD049MZ/XRmeNnlBcfg7b1TIsZD5fya+rD85sKEXFWs4QMraDeAII+aJoZpd
QyDafn7gj37E6ej+Q5qCuh7hsWslC4YaQek0GRlCygz/+Jn+NtnwXaNVEJs22j7V
Lj6+2cUExQAX7MySNDdbwyS/PUrYrVLLagx6NW2OdII3UBz+A4srFb9RQ6dttWOE
CzTHVY7BX4QalJyjc7Yex5do8lH/PZ23IsCSFE/r0I0kJes2Raq9eTyAISpvQSeZ
HfvkiyrW3feOVfSjp64L7Y+lxmtgfo6HJhUZcb21OwlpLYJxRin+QOWHWbeg+fx0
0EpJoKETofj8g5ErdZajFezr6odM27M3XGrTJIJJO6OqLv7fUYWc2Xmuf9+DXGTR
fjVwJtmEIo/jR92saXgg
=OXjT
-----END PGP SIGNATURE-----

View File

@@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJMBAABCAA2FiEEvBU+39pRCqHFhwUCToYVYy9G5oAFAmGjjakYHHBhcGF0dXR1
d2F3YUBwb2x5bm9tLm1lAAoJEE6GFWMvRuaAFAEP/0MMomPeqy56TnDjvG+fFEPC
PPDexOXD8h0KVBGUdFGS7FPBn/O4ByKVE6Ki/y/2YttBt+P3RceT1eNjY+rPxFu9
B7hcjli72G6dZ4bzofbNl3huG4oWmDEpX9CT87lL8vGU/4CqaKIk/dfBxuFPwqus
5CyMX/ECMTjRNbQ75EKGE4vINht45pWFLzZUp+DKw4K2idOaQ8T+8vAKF0o10/Qr
npDCAy0hIY9HWmYEI7JheUfMrw5jxYJ6vXIGHmsiVqX8DXxGpXXqevDhkFa6QEbA
sgENJr5EvCR2ZeM3e566qYXSibCSfq58aXEVkt9yXrNrj0Q7Iz/uD7J5lR64e+rD
Hv43p/lKbFRi7UAYpWR8nUXSX8wbzTETgT/WUeExD0AWIsyYAj33R7U1UngCL9qI
IrkrPKnxBFRQTxl6v+MxEN7xAtKf9BWtbm+VQv+xuPtIE1dUof6oUKGA+f9qFrnR
XucIZrGNbOfwfJ3P4w+crvI2WgqvH7vQSJbQPKNEXvQP9rYh5L7nG1IXqaHRQnuO
kn9EcG/uQOkZUeo+8uvBJvSmcE9DiyYFfWvoDvpqtMfdolD+n8HXNfGFaGkHZ7+b
RgFWmIGshVZo968y6iP9zyubdViF5JWl8r4pR6Y9MIbjiXOfgTPMpYpFL7lJQ2kr
S1EEc4E/Axw0VYSk2jTw
=WyMf
-----END PGP SIGNATURE-----

View File

@@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJMBAABCAA2FiEEvBU+39pRCqHFhwUCToYVYy9G5oAFAmGjjakYHHBhcGF0dXR1
d2F3YUBwb2x5bm9tLm1lAAoJEE6GFWMvRuaAE28P/0MZqiLeSDVP+W8eKaXrWh5i
BfKDbRefdtV8/Ybs0MSCU9FyRv/PAvN7uA6KsBwptyJD8YMcJt1f8npjjN/E4In6
uHz3EjjQmM5h4GIvnchN6IKL0CzkZspLH7thd5HXDYey7iEnu/b2P3W8MGdJbBYx
x9dnGTDLm0y+x5FV8Lpe/UCgL1xTli0lpmUMKqzg58WFtrU2YD0y6jircxOKxyeO
Rp0Sb2G/vfZL9oKVdK28zZ6CINCmNbYTaI/tqwTxoM9tB/+He+H4RaiAfFzU2/Ri
jOm48xwr2Vmx2jvBk6mvQppIRtmy5tUOB9pFSTjQBCHL3hBUbN/nImAhpDl5u7CQ
Y1xK60i42YFyiOj6vD551XoQNmgiJ7zVuJ3wy+k03wl1RujbRxnPkm2vwhPVPBBL
1IWxoUPyTwpD6f/td2sZdqYGa8H+lRx8hjzwAw55zCF6KdCvLSWz6DBZUrQo1Wji
nwVHcOtidfo3l9fH3xR8tshM2Rsv6XuKtyp3WkLJajW0r2et/bAyz29oU0BtGUlE
dmjhCllGgtfJWz8r/XGiHgNQqiuJT3fMoQ2kVDrDMU1W4ffxleJGQbYDfhPOq1Pa
JGE/JhaDAxhRXUlPdmVkkzuYE6WVwJu6FvaBzi9DJ2CkUl1UYk6jXl8n0pFrplXc
AG9V+U0UmrLXc5ILN0Y6
=bWDk
-----END PGP SIGNATURE-----

View File

@@ -1,90 +0,0 @@
-----BEGIN PGP MESSAGE-----
owGtWWuQHFUVTkIipIWAIvhCuOwq2Z2a6dnsbjbJAJE8DKwmm4VdxdQYd+5039np
THfftm/3zg4QiSLxVSg+QAWjxip8loUYgfLBU4KApVaBYLBKRIlaphA18vKB5Tn3
3n7M7qr8cJNKtrtv33vOd875zqOvPuGYRcctHtt7ilXe8rs9i79x+kj9jMGBwaHS
wJrSqtWlIOSC251SFFLWcFqlQdOz7QMnLznnzFKJRE7ksgq5KPZ9x58m42ot4T4Z
52FEhoeHyEbWdHyb6NfJYIW8yWVWFDoW2bB1fIyUSusNuZfNhBU6QeRwv0JGfRI1
HUHqLp8mARdRkYySiLku6fCYNHkbLq0m9aeZTbwOESyKA9LgIQFxZzsoC9x9+7bx
cXgUzrCQxAJvJlKkh4bMt1lYIR0m5M0L4AhOGLzR4T4zyVaObzkeKxKfw2pqm4YB
wgFAAyhSENddRzRBCirFVIjYpKf64jHZ2deMokBUymXU1gy42/G5Z3qsrPcojXfb
wGxGntvfUyTtJgsZSKGgq8O5Cpkw9ufob9T1kU1GemgQuI5FEWmFVw+pFvTehUya
aSdqxnXT4l5ZP0z+7zcNONSxtY2YRWOBcrSpH4EQEV9AAlLQnlRAKAINRZEIDrvQ
SEpmuQ7zI0Es7vvgI8w2YCtpXrmDRX1S7wRUCNJwQtamrivUy9x3OwQuQfs2qyOw
jYZjmeTipuMytQSUDjm1mqTNwxaziwbHLfFUl6LdmiFj4AY0FAu5lh1SDwCz4IwO
eIDa13OmQ7ipnI27diJnI+QeKWxmdYf6BUSjMObMbp8oFKWpLMdGjFCmFDGKYgsn
YkYTnAhvKEAE9RixuUcdHxbjs7mo0sgkk2CFIpoe/Ra8ggpw1gj9UTh1kLMNhjRS
A5M6tVq4u59azskjyJSX1C6A0ybGRmtgS5ehrzkAnu00GuBzfuTQCEJmcuuEoY0F
ziSSKEPJYQ0pTCghx1CNUd/WTldQIhP4S9EBQUavmApDSbYj2r+WBURNbq2hIhT8
ed7DPDZ1HjUhZkXsRsTxM0BBKzgNJDWklPVO7kwQX3khWHmCw2IMfnCRCJEdJSKK
vToGeByAF1cLQrjNhUOmE8aRsJouK+Oa/gRA1Bm04i4Rjue4NJT+kdpGignGB4tI
YwhpdOlioIUTuEwq51gAPs+phPFUxFeMLgvZqBwuQpULBUCsUJDXknrBtZPn89WX
S4oEKLWwIeOL0lbaAWSBkCJugRJjbJrjSWjVolTOJ2w2Yr7Q1gMP0ZprfRaAGiGg
NlgscgST4gR6/z7Rj1C0eQzR5TothkvBSQwHDrDVWuZbYSdAXQUTeCyp9gkehxbr
zwzDfLPttJyA2Q41eThdxqvyPMWmEsWmcor1AxaCiNhqKsaPDGV2NBaEOsjPGxiW
mRXRMyMkBEfqFvI40p6pmYn0gfRgooYDYmN4Im4IuAFb1Wa9ICgpaGr9RFGgJs80
7OEEmaWAgQFH5gqmF2ZSqKUZCTrCUNwHEeS6RQQvxGiCf6I2B+OJmImKYawyJTEp
Egl1GstUdoCgqz1wii8Cio5GPG6znhcRBJjf6mUP6JaFZZtbZfCEhjMNBUVvbruS
TEklEQfo1GnggNXBCBiRDepbHQKVAkVyQ3YS0oMk/Svu0RGik56ygmBsIedbKTCt
u2R0HHzQBrYAXvJBQmqjWXfFQLm1VYNrzAH4s6pmkgsSmpW5L2TviiEVCcAgZDpX
wFmIc47kfAWuLFBS4ZRazIebFqgB0Qoe7gG6ReXphTEIpE0uj23lUIUNrRZkAiDP
0QbEPkPxQFsJS7LnNAPjNB0Z1h71O1I+JnBPgKcbHIkHCJ0sUWkrp6s81aNIELHI
CUj6QI069fvzi4vEY9RX7E8leZESeqhPXAYO4Xj4eik7TJ6cbslsiDHbdjDcMMUW
cx4oYljqNDArSxqQJomF8ugsvBBkH3wORRgdnxlJjsIVXXJmPOzjwuHE7KYxaJLt
gKtN4XwqtAhxYKc5XkUUCgeCAYh2piw8xcojsy6T0ApIEza+jbFKBHgo1A9kQwMi
QDmzy3kLn1PQwreL0lfj0IetQSu1vQ49SBotQut4ezWcA45s59TPqwzWrsMqBE8q
mNyWPKYKN3ymihyAQZNIX50hqWqVWeotLIQgjLjCG8CBLaiXmaaNMjahvGIgNWTN
zTFTq5nIE0tX8YOl9IwjHFXlwD3aVcU6flJRYU0Ne/b2QjCxtJaewDgzjO1+kixk
dSwzggwK0EadN0dTQBsuuIdEY2shs2PUC1khZaj6jqnAkDUR+DK1OlNgkKlCjfBA
VT16I5+B0UnNGhRTNnCCFU1Frsit065nVEMWuNRSAEP0eyzMyLMJDYDSx3Sw7o79
VrkB/F2G5C850+Y0MGc9t9dds3otFOLGJERnMZ8iFKvGoSrwQxA5lC6ohJIZOV+z
+cCa6IVCJ1iwMiSBWq3mxtSYowwysiDnkkvJ6sHBIbJ77nMABp8aBH6quGRneok/
LdaB654yi6yylrZsQdoX5ayMM2FRz9npK/gY0qSFdvifr1phpF/dfbaxG3VIXacw
maTFzHnSVDnPdWQ1jByrIgMTBNzQXQF2p90JoklnZAzLZKSKYCOtnxVdtIElBE/y
Ra7lSS2h6oC5NWxaF4n/WCLkKE0EEGGyqFD1rlGVbU8QYjGo94UlmbvhPrIeSos2
UZ5lQWlgaGStajNNsgXdH/zLBrflHQ+ONNhswEI43GIqsSSNG/bosn/pK2ziPkgu
pBMKqA0LG11ar7MQfz2f7nI8/GWz43P8fxvSPvxS3cZnZzuZeB5eonz9/dBnhOhn
rmzJsiK2jY1MLqvPOBQMsaCvy5K+u0bqjpUsFJCble3ToCB9Y1gPMZWfsqbXBWlk
f2dMAwOGCXNSK4qhrFAHKEIGuoNtVCZQxX+/irQO9VwjsoKKsVyyeQgRmAQAWih3
iT8ANVS83AHEux/gT4n0SPR6up6gY1ZIj/bJvnzb1E/OOktC2dddeHZvoBNbJWGZ
rocQ+vMFwT4dumoeTzcrUPfGLF3RS6qmae40cvvm3tcHdG/ocmpvpC5Ufiycf5SK
lQVkUIDoBA/6p3VABcmpxzAQKvXaPOAhnZcgzUKK+3+i3w39f8AYO1w1tlm+fLkE
V1LZpOx2ktNJTZ5UQ5+SLCTDgoPDQgT62B3WKsPDQzVdh7aprKpwhpJWDMOyxMPS
wcjVCMhTkDWVG9fmmbGW9NKSThRsUETXQM4ayoBRKGSRGqn615ClghKuJncoqvFD
FoaqwYONoHxLAiiL25Vy0JC2d3XWwGIbBUOixbVQr9AkDefYEwK+u1xX0Qh8LSS7
a16vwy1ZpMi5Iw9tAB42A1ZnXQOHbDbTNXao6zLJ1uMPkBWRVq/zhK2MOUjRKIJi
B26ZKj8lWBiQ5GMkWUVJgnb0jKunAJDKkcYFk5MJ8EJacHJTdq3Nr8Aw5HBA+gxR
Liuh73qh7QCB40iwkyCLK/JnSGP6wJw0slQ+xPsG4NnAolW2NXN21Raeu5M6LKJA
qTh+Mws9xgLNOiBgJqNOh6fDR9wDTi/rvcq9im/dqVWqDOoagtmc6faBMQ/RqGuv
okJ2EzQvF7TjsuJks9QL9MCMQMjND1i42S8hpzlt/9vr89hW7qAbg8Rl0UrG3BFN
Xj50WOy757gO+papZuXgIKhacd6rWJjTUBgKAqvJLJwANJwQGAMVkRbBmtiljl9E
aNLxncyvjoIxaziNqtweH4qczQB2l0NVYHr8EthSTVmYX3rrBNpTlM93uRA07JTx
RWgo0GlSwMBXjFwOV3GEgZyOXiAIJXfpVQlyUpRk3Kd7Hu363TwwGiVIaGdIm3KJ
XTXtaaiLqqIJX8wkvKyam/K6dYOD/SrLY51nqNqRRgl8DWcWe1woP6BECrFAs53p
6azxQ05NKWAlEpWtBpxqMc4tYkSKNwxVo8q9EMN0RK3HDnnqUVFdldQXYPAuqNI4
DehkHMUX0zZN9YIH0JeXh0YaA2zIWjuw2qLDbGR4dWNoaNVQY2RkDR2pDzUaq9lg
gw3Tdf1dY0yTXKxqWRoph1RIF7QFCtoZpwGlokpB0rbUsnD8IjlO9dPpnHfO1Ds/
+tTjcVylbhvpRNQkm9NUJuvtBIfELHEgIkgCHkKshx11uG6RBOQtiDDDtlzOzuDO
xjjSCPsr5XgsmXci5HK0gSPTnCmBddm0LjDxkNjHtlfmWtmdQKFsubGcl0oSy75U
CO7OAIvpCTkZJI0Y0xVuktxbBfpAeyA/S+R6HNwFh2PJeMDoTqjoX0kxLckKyN1m
LlYI+e5YDR6AYJRT46EzckAwZ9hhpJ3LvOmaWJkbrLHkA4GM2iZ0UCq5RClb5whc
H2bMsbwali44xssO0iWPmhdhekYg9aBVTl0sFw8x8CtkC8pxPXHD74ty1pnWJWra
LFWrFsYv2v72HYV0Nv2i81UCU7lXTTaTDfrn9S4RT6rfoiEnvD5YMfmiUq35LJqS
W9TyHZKNA9D80ABuTaVLVRNH1LJsemloksAg6GCBImlGEi1VfIKBi0WfmvbIpgVq
YYfHIpsLhh39+S2OTOODS7YuXbT4uEUjp5659PunrP/VLy409h98/7IlyZflZUvw
s/GrTguAbiKgmzbQzXlZZlxkLD8pWbpp+KRFN/V+uvLeFZWr1n9/8v4PjZ94fbv4
0YnK/W/ufc1zf/GW3HHmimXs/OvdO676zqf3P/rAfvvua/be1PuxI49NHvVae7xH
nv3w7Uuvmrrs7nO8zXde/cTDB/f9ZOmPq6f+48KfH/7Ifc9Et19/3tlX9jbLn9m5
67rByZsX/35F+ex/lqOdj/i3HPPQkieqPznmDU9969rOvTc8N3b+L9k4O+Fb+647
+e/71nzqLVfeevwn9tsHfnzePQ/ecHTsTRddvfcLV7xmYsMLbXHo5511fzrr619b
9f7H9x7/9Cs/f/jMH9z21UO/vP69teW33bH5td/b9Id7//zuLdfO7jr+nIvv+trK
G+u/vv+dG75+8w8fe/iaVxz+7NHBu55+nr/8tPVi95Mv+cynfnX6e06vvOyylzy7
60sr9t+7d+WOY29o9R677+OltV9ed/Czj1829Y6By9eecfDWu/Y99b4jJ3zjA2/c
uv6e1t9etWTzw1ecdlvpzfXBPau3P/W2z22//IV3/fSSq4+cSx7aeu2Pnmr8effn
Zq57tG//Q1/+ypKBf23b4i37yJ8+f9/DD377vH0vfehHu/751xPffeTAih0HLn/m
wHffeMuhxss/dnCbsfiJ3z535NEdz//1L8OHvmge/dknP/Cz+nHffPr5V5/x65kH
1t/Y9+r4pOk9X3jhuHte5x5bOXbp1I4nLzUvdK45cMWKvU8SY8+XXvqvt009c2K8
4a2Ha6dddCU/dfzQPTvO/c2zXxmeaN558i333bis9/G7Xz975HBr0cab/ni0/cjz
P208uOWxmfX/Bg==
=/2ew
-----END PGP MESSAGE-----

View File

@@ -0,0 +1,102 @@
<!-- title: Signing Android Apps Using a YubiKey (on NixOS) -->
<!-- render: yes -->
In my spare time, I currently develop two Android apps using *Flutter*: [AniTrack](https://codeberg.org/PapaTutuWawa/anitrack), a
simple anime and manga tracker based on my own needs, and [Moxxy](https://moxxy.org), a modern XMPP
client. While I don't provide release builds for AniTrack, I do for Moxxy. Those
are signed using the key-pair that Flutter generates. I thought to myself: "Wouldn't it be cool if I could keep
the key-pair on a separate device which does the signing for me?". The consequence
of this thought is that I bought a *YubiKey 5c*. However, as always, using it for my
purposes did not go without issues.
The first issue is that the official [*Android* documentation](https://developer.android.com/build/building-cmdline#deploy_from_bundle)
says to use the `apksigner` tool for creating the signature. [The *YubiKey* documentation](https://developers.yubico.com/PIV/Guides/Android_code_signing.html), however,
uses `jarsigner`. While I, at first, did not think much of it, *Android* has
[different versions of the signature algorithm](https://source.android.com/docs/security/features/apksigning/): `v1` (what `jarsigner` does), `v2`, `v3`, `v3.1` and
`v4`. While it seems like it would be no problem to just use `v1` signatures, *Flutter*, by default,
generates `v1` and `v2` signatures, so I thought that I should keep it like that.
So, the solution is to just use `apksigner` instead of `jarsigner`, like [another person on the Internet](https://geoffreymetais.github.io/code/key-signing/) did.
But that did not work for me. Running `apksigner` like that makes it complain that `apksigner` cannot
access the required `sun.security.pkcs11.SunPKCS11` Java class.
```
> /nix/store/ib27l0593bi4ybff06ndhpb8gyhx5zfv-android-sdk-env/share/android-sdk/build-tools/34.0.0/apksigner sign \
--ks NONE \
--ks-pass "pass:<YubiKey PIN>" \
--provider-class sun.security.pkcs11.SunPKCS11 \
--provider-arg ./provider.cfg \
--ks-type PKCS11 \
--min-sdk-version 24 \
--max-sdk-version 34 \
--in unsigned.apk \
--out signed.apk
Exception in thread "main" java.lang.IllegalAccessException: class com.android.apksigner.ApkSignerTool$ProviderInstallSpec cannot access class sun.security.pkcs11.SunPKCS11 (in module jdk.crypto.cryptoki) because module jdk.crypto.cryptoki does not export sun.security.pkcs11 to unnamed module @75640fdb
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:489)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at com.android.apksigner.ApkSignerTool$ProviderInstallSpec.installProvider(ApkSignerTool.java:1233)
at com.android.apksigner.ApkSignerTool$ProviderInstallSpec.access$200(ApkSignerTool.java:1201)
at com.android.apksigner.ApkSignerTool.sign(ApkSignerTool.java:343)
at com.android.apksigner.ApkSignerTool.main(ApkSignerTool.java:92)
```
It may only be an issue because I use NixOS, as I
cannot find another instance of someone else having this issue. But I still want my APK signed using the key-pair
on my *YubiKey*. After a lot of trial and error, I found out that I can force Java to export certain classes
using the `--add-exports` flag. Since `apksigner` complained that the security classes are not exported to its
unnamed class, I had to specify `--add-exports sun.security.pkcs11.SunPKCS11=ALL-UNNAMED`.
## My Setup
TL;DR: I wrapped this entire setup (minus the Gradle config as that's a per-project thing) into a fancy [script](https://codeberg.org/PapaTutuWawa/bits-and-bytes/src/branch/master/src/flutter/build.sh).
My provider configuration for the signature is exactly like the one provided in [previously mentioned blog post](https://geoffreymetais.github.io/code/key-signing/#set-up-your-own-management-key),
with the difference that I cannot use the specified path to the `opensc-pkcs11.so` as I am on NixOS, where such
paths are not used. So in my setup, I either use the Nix REPL to build the derivation for `opensc` and then
use its `lib/opensc-pkcs11.so` path (`/nix/store/h2bn9iz4zqzmkmmjw9b43v30vhgillw4-opensc-0.22.0` in this case) for testing or, as
used in [AniTrack](https://codeberg.org/PapaTutuWawa/anitrack/src/branch/master/flake.nix), let Nix figure out the path by building
the config file from within my Nix Flake:
```nix
{
# ...
providerArg = pkgs.writeText "provider-arg.cfg" ''
name = OpenSC-PKCS11
description = SunPKCS11 via OpenSC
library = ${pkgs.opensc}/lib/opensc-pkcs11.so
slotListIndex = 0
'';
# ...
}
```
Next, to force Java to export the `sun.security.pkcs11.SunPKCS11` class to `apksigner`'s unnamed class, I added `--add-exports sun.security.pkcs11.SunPKCS11`
to the Java command line. There are two ways of doing this:
1. Since `apksigner` is just a wrapper script around calling `apksigner.jar`, we could patch the wrapper script to include this parameter.
2. Use the wrapper script's built-in mechanism to pass arguments to the `java` command.
While option 1 would work, it would require, in my case, to override the derivation that builds my Android SDK environment, which I am not that fond of.
Using `apksigner`'s way of specifying Java arguments (`-J`) is much easier. However, there is a little trick to it: When you pass `-Jsomething` to `apksigner`,
the wrapper scripts transforms it to `java -something`. As such, we cannot pass `-Jadd-exports sun.security.pkcs11.SunPKCS11` because it would get transformed
to `java -add-exports sun.security.[...]`, which is not what we want. To work around this, I quote the entire parameter to trick Bash into thinking that I'm
passing a single argument: `-J"-add-exports sun.security.pkcs11.SunPKCS11"`. This makes the wrapper append `--add-exports sun.security.pkcs11.SunPKCS11` to the
Java command line, ultimately allowing me to sign unsigned Android APKs with the key-pair on my *YubiKey*.
Since signing a signed APK makes little sense, we also need to tell Gradle to *not* sign the APK. In the case of Flutter apps, I modified the `android/app/build.gradle`
file to use a null signing config:
```gradle
android {
// ...
buildTypes {
release {
// This prevents Gradle from signing release builds.
// I don't care what happens to debug builds as I'm not distributing them.
signingConfig null
}
}
}
```

View File

@@ -2,10 +2,6 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
html {
background-color: #212121;
}
@layer base { @layer base {
article > p > a, h1, h2, h3, h4, h5, h6 { article > p > a, h1, h2, h3, h4, h5, h6 {
@apply text-indigo-400 !important; @apply text-indigo-400 !important;
@@ -17,4 +13,16 @@ html {
article > h1, h2, h3, h4, h5, h6 { article > h1, h2, h3, h4, h5, h6 {
@apply text-indigo-400 !important; @apply text-indigo-400 !important;
} }
body {
background-color: #212121;
}
html {
@apply text-white;
}
a {
@apply text-indigo-400 !important;
}
} }

View File

@@ -1,14 +1,10 @@
<!-- Post item --> <!-- Post item -->
<div class="w-4/5 py-4"> <div class="flex flex-col pt-4">
<a href="/{{ slug }}.html"> <a href="/{{ slug }}.html"><h1 class="text-indigo-400 prose prose-lg text-xl">{{ title }}</h1></a>
<h1 class="prose prose-h1 text-2xl text-indigo-400">{{ title }}</h1> <span class="text-md mt-2">Posted on {{ date }}</span>
</a>
<p class="prose prose-xs text-white"> <!-- Blurp -->
Posted on {{ date }} <span class="prose text-white mt-4">
</p> {{ summary }}
</span>
<p class="prose text-white py-2">
{{ summary }}...
</p>
</div> </div>

View File

@@ -1,4 +1,4 @@
<!-- Posts wrapper --> <!-- Container for posts -->
<div class="flex flex-col items-center"> <div class="mx-auto">
{{ content }} {{ content }}
</div> </div>

View File

@@ -1,19 +1,14 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<title>{{ title }}</title>
<meta property="og:title" content="{{ title }}" />
<meta property="og:description" content="{{ description }}" />
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="/assets/css/index.css" rel="stylesheet" /> <link href="/assets/css/index.css" rel="stylesheet" />
<link href="/assets/css/code.css" rel="stylesheet" /> <link href="/assets/css/code.css" rel="stylesheet" />
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Moxxy Blog" />
<!-- Optional MathJax --> <meta property="og:title" content="{{ title }}" />
{{ mathjax_include }} <meta property="og:description" content="{{ description }}" />
<!-- Blog --> <!-- Blog -->
<link rel="alternative" <link rel="alternative"
@@ -21,29 +16,28 @@
title="PapaTutuWawa's Blog" title="PapaTutuWawa's Blog"
href="https://{{ blog_url }}/atom.xml" /> href="https://{{ blog_url }}/atom.xml" />
<!-- Optional MathJax -->
{{ mathjax_include }}
<title>{{ title }}</title>
</head> </head>
<body>
<div class="flex flex-col p-2 md:p-8 items-start md:w-4/5 mx-auto">
<!-- Header -->
<div class="flex flex-row self-center">
<img class="w-12 h-12 md:w-24 md:h-24 rounded-lg" src="{{ page_assets }}/img/avatar.jpg" alt="Profile picture"/>
<div class="ml-4 self-center">
<a class="self-center text-2xl font-bold" href="/">PapaTutuWawa's Blog</a>
<body class="min-h-screen h-full flex flex-col p-8 h-full"> <ul class="list-none">
<div class="flex flex-col items-center"> <li class="inline mr-8"><a href="/index.html">Posts</a></li>
<!-- Allow the header to be independently sized from the content --> <li class="inline mr-8"><a href="/atom.xml">RSS</a></li>
<div> <li class="inline mr-8"><a href="https://polynom.me">About</a></li>
<div class="flex flex-row"> </ul>
<img class="w-32 md:w-36 lg:w-48 h-32 md:h-36 lg:h-48 rounded-lg" src="https://cdn.polynom.me/img/avatar.jpg" />
<div class="flex flex-col justify-center px-8">
<h1 class="text-xl lg:text-4xl text-white">PapaTutuWawa's blog</h1>
<div class="flex flex-row justify-between">
<a class="text-indigo-400" href="/index.html">Posts</a>
<a class="text-indigo-400" href="/atom.xml">RSS</a>
<a class="text-indigo-400" href="https://polynom.me">About</a>
</div>
</div>
</div> </div>
</div> </div>
{{ content }} {{ content }}
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,18 +1,19 @@
<!-- Post wrapper --> <!-- Container for posts -->
<div class="flex flex-col items-center pt-8"> <div class="mx-auto mt-4 w-full md:max-w-prose">
<h1 class="prose prose-h1 text-2xl text-indigo-400 self-start">{{ title }}</h1> <h1 class="text-indigo-400 text-3xl">{{ title }}</h1>
<p class="prose prose-xs text-white self-start">Posted on {{ date }}</p> <span class="text-md mt-2">Posted on {{ date }}</span>
<article class="text-white prose prose-lg pt-8"> <!-- Actual article -->
<article class="prose lg:prose-lg text-white mt-4">
{{ content }} {{ content }}
</article> </article>
<!-- Post ending --> <!-- Common post footer -->
<span class="text-white prose prose-lg self-start pt-8"> <div class="mt-6">
If you have any questions or comments, then feel free to send me an email (Preferably with GPG encryption) to <span class="prose lg:prose-lg text-md text-white">
{{ email_user }} [at] {{ email_domain }} or If you have any questions or comments, then feel free to send me an email (Preferably with GPG encryption)
reach out to me on the Fediverse at <a class="text-indigo-400" to {{ email_user }} [at] {{ email_domain }} or reach out to me on the Fediverse at <a href="https://{{ fediverse_url }}">{{ fediverse_handle }}</a>.
href="https://{{ fediverse_url }}">{{ fediverse_handle }}</a>.
</span> </span>
</div> </div>
</div>

View File

@@ -8,7 +8,7 @@
pythonEnv = python3.withPackages (ps: with ps; [markdown pygments]); pythonEnv = python3.withPackages (ps: with ps; [markdown pygments]);
in stdenv.mkDerivation { in stdenv.mkDerivation {
pname = "blog"; pname = "blog";
version = "20231507"; version = "20230722";
src = ../.; src = ../.;