- relative urls!

- got rid of bleach and reacji detection, nobody is using it
- removed google vision and google text classification
- 410 for ^/tag and ^/comment
- 80x15 SVG bottom banners
- better code syntax hightlight CSS
This commit is contained in:
Peter Molnar 2019-02-16 00:14:12 +00:00
parent f47ed93fa0
commit 9a5c4708d2
18 changed files with 555 additions and 328 deletions

27
Pipfile
View file

@ -1,22 +1,19 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[packages]
wand = "*"
arrow = "*"
unicode-slugify = "*"
requests = "*"
python-frontmatter = "*"
langdetect = "*"
jinja2 = "*"
feedgen = "*"
[dev-packages]
[packages]
arrow = "*"
bleach = "*"
emoji = "*"
feedgen = "*"
langdetect = "*"
requests = "*"
unicode-slugify = "*"
Jinja2 = "*"
Wand = "*"
pyyaml = "*"
python-frontmatter = "*"
[requires]
python_version = "3.7"

91
Pipfile.lock generated
View file

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "61a7889c295e0054b0526ddb11e48b5f8297c57bc7ce3196e9d49c602146e208"
"sha256": "da45b393e04bad2e1be92dde0f79ba517e3cb90e0db5f76afdc3754f638b38bf"
},
"pipfile-spec": 6,
"requires": {
@ -10,7 +10,7 @@
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"url": "https://pypi.python.org/simple",
"verify_ssl": true
}
]
@ -18,18 +18,11 @@
"default": {
"arrow": {
"hashes": [
"sha256:9cb4a910256ed536751cd5728673bfb53e6f0026e240466f90c2a92c0b79c895"
"sha256:3397e5448952e18e1295bf047014659effa5ae8da6a5371d37ff0ddc46fa6872",
"sha256:6f54d9f016c0b7811fac9fb8c2c7fa7421d80c54dbdd75ffb12913c55db60b8a"
],
"index": "pypi",
"version": "==0.13.0"
},
"bleach": {
"hashes": [
"sha256:213336e49e102af26d9cde77dd2d0397afabc5a6bf2fed985dc35b5d1e285a16",
"sha256:3fdf7f77adcf649c9911387df51254b813185e32b2c6619f690b593a617e19fa"
],
"index": "pypi",
"version": "==3.1.0"
"version": "==0.13.1"
},
"certifi": {
"hashes": [
@ -45,14 +38,6 @@
],
"version": "==3.0.4"
},
"emoji": {
"hashes": [
"sha256:1e959336dafc7a5ed2c0256ee587bbd38a7187d772141f0b5ba42de9e08599a8",
"sha256:a9e9c08be9907c0042212c86dfbea0f61f78e9897d4df41a1d6307017763ad3e"
],
"index": "pypi",
"version": "==0.5.1"
},
"feedgen": {
"hashes": [
"sha256:82c9e29884e137c3e3e7959a02f142d1f7a46cd387d572e9e40150112a27604f"
@ -84,34 +69,34 @@
},
"lxml": {
"hashes": [
"sha256:0dd6589fa75d369ba06d2b5f38dae107f76ea127f212f6a7bee134f6df2d1d21",
"sha256:1afbac344aa68c29e81ab56c1a9411c3663157b5aee5065b7fa030b398d4f7e0",
"sha256:1baad9d073692421ad5dbbd81430aba6c7f5fdc347f03537ae046ddf2c9b2297",
"sha256:1d8736421a2358becd3edf20260e41a06a0bf08a560480d3a5734a6bcbacf591",
"sha256:1e1d9bddc5afaddf0de76246d3f2152f961697ad7439c559f179002682c45801",
"sha256:1f179dc8b2643715f020f4d119d5529b02cd794c1c8f305868b73b8674d2a03f",
"sha256:241fb7bdf97cb1df1edfa8f0bcdfd80525d4023dac4523a241907c8b2f44e541",
"sha256:2f9765ee5acd3dbdcdc0d0c79309e01f7c16bc8d39b49250bf88de7b46daaf58",
"sha256:312e1e1b1c3ce0c67e0b8105317323e12807955e8186872affb667dbd67971f6",
"sha256:3273db1a8055ca70257fd3691c6d2c216544e1a70b673543e15cc077d8e9c730",
"sha256:34dfaa8c02891f9a246b17a732ca3e99c5e42802416628e740a5d1cb2f50ff49",
"sha256:3aa3f5288af349a0f3a96448ebf2e57e17332d99f4f30b02093b7948bd9f94cc",
"sha256:51102e160b9d83c1cc435162d90b8e3c8c93b28d18d87b60c56522d332d26879",
"sha256:56115fc2e2a4140e8994eb9585119a1ae9223b506826089a3ba753a62bd194a6",
"sha256:69d83de14dbe8fe51dccfd36f88bf0b40f5debeac763edf9f8325180190eba6e",
"sha256:99fdce94aeaa3ccbdfcb1e23b34273605c5853aa92ec23d84c84765178662c6c",
"sha256:a7c0cd5b8a20f3093ee4a67374ccb3b8a126743b15a4d759e2a1bf098faac2b2",
"sha256:abe12886554634ed95416a46701a917784cb2b4c77bfacac6916681d49bbf83d",
"sha256:b4f67b5183bd5f9bafaeb76ad119e977ba570d2b0e61202f534ac9b5c33b4485",
"sha256:bdd7c1658475cc1b867b36d5c4ed4bc316be8d3368abe03d348ba906a1f83b0e",
"sha256:c6f24149a19f611a415a51b9bc5f17b6c2f698e0d6b41ffb3fa9f24d35d05d73",
"sha256:d1e111b3ab98613115a208c1017f266478b0ab224a67bc8eac670fa0bad7d488",
"sha256:d6520aa965773bbab6cb7a791d5895b00d02cf9adc93ac2bf4edb9ac1a6addc5",
"sha256:dd185cde2ccad7b649593b0cda72021bc8a91667417001dbaf24cd746ecb7c11",
"sha256:de2e5b0828a9d285f909b5d2e9d43f1cf6cf21fe65bc7660bdaa1780c7b58298",
"sha256:f726444b8e909c4f41b4fde416e1071cf28fa84634bfb4befdf400933b6463af"
"sha256:0537eee4902e8bf4f41bfee8133f7edf96533dd175930a12086d6a40d62376b2",
"sha256:0562ec748abd230ab87d73384e08fa784f9b9cee89e28696087d2d22c052cc27",
"sha256:09e91831e749fbf0f24608694e4573be0ef51430229450c39c83176cc2e2d353",
"sha256:1ae4c0722fc70c0d4fba43ae33c2885f705e96dce1db41f75ae14a2d2749b428",
"sha256:1c630c083d782cbaf1f7f37f6cac87bda9cff643cf2803a5f180f30d97955cef",
"sha256:2fe74e3836bd8c0fa7467ffae05545233c7f37de1eb765cacfda15ad20c6574a",
"sha256:37af783c2667ead34a811037bda56a0b142ac8438f7ed29ae93f82ddb812fbd6",
"sha256:3f2d9eafbb0b24a33f56acd16f39fc935756524dcb3172892721c54713964c70",
"sha256:47d8365a8ef14097aa4c65730689be51851b4ade677285a3b2daa03b37893e26",
"sha256:510e904079bc56ea784677348e151e1156040dbfb736f1d8ea4b9e6d0ab2d9f4",
"sha256:58d0851da422bba31c7f652a7e9335313cf94a641aa6d73b8f3c67602f75b593",
"sha256:7940d5c2185ffb989203dacbb28e6ae88b4f1bb25d04e17f94b0edd82232bcbd",
"sha256:7cf39bb3a905579836f7a8f3a45320d9eb22f16ab0c1e112efb940ced4d057a5",
"sha256:9563a23c1456c0ab550c087833bc13fcc61013a66c6420921d5b70550ea312bf",
"sha256:95b392952935947e0786a90b75cc33388549dcb19af716b525dae65b186138fc",
"sha256:983129f3fd3cef5c3cf067adcca56e30a169656c00fcc6c648629dbb850b27fa",
"sha256:a0b75b1f1854771844c647c464533def3e0a899dd094a85d1d4ed72ecaaee93d",
"sha256:b5db89cc0ef624f3a81214b7961a99f443b8c91e88188376b6b322fd10d5b118",
"sha256:c0a7751ba1a4bfbe7831920d98cee3ce748007eab8dfda74593d44079568219a",
"sha256:c0c5a7d4aafcc30c9b6d8613a362567e32e5f5b708dc41bc3a81dac56f8af8bb",
"sha256:d4d63d85eacc6cb37b459b16061e1f100d154bee89dc8d8f9a6128a5a538e92e",
"sha256:da5e7e941d6e71c9c9a717c93725cda0708c2474f532e3680ac5e39ec57d224d",
"sha256:dccad2b3c583f036f43f80ac99ee212c2fa9a45151358d55f13004d095e683b2",
"sha256:df46307d39f2aeaafa1d25309b8a8d11738b73e9861f72d4d0a092528f498baa",
"sha256:e70b5e1cb48828ddd2818f99b1662cb9226dc6f57d07fc75485405c77da17436",
"sha256:ea825562b8cd057cbc9810d496b8b5dec37a1e2fc7b27bc7c1e72ce94462a09a"
],
"version": "==4.3.0"
"version": "==4.3.1"
},
"markupsafe": {
"hashes": [
@ -175,7 +160,6 @@
"sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537",
"sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"
],
"index": "pypi",
"version": "==3.13"
},
"requests": {
@ -216,17 +200,10 @@
},
"wand": {
"hashes": [
"sha256:3e59e4bda9ef9d643d90e881cc950c8eee1508ec2cde1c150a1cbd5a12c1c007",
"sha256:52763dbf65d00cf98d7bc910b49329eea15896249c5555d47e169f2b6efbe166"
"sha256:7d6b8dc9d4eaccc430b9c86e6b749013220c994970a3f39e902b397e2fa732c3",
"sha256:cc0b5c9cd50fecd10dc8888b739dd5984c6f8085d2954f34903b83ca39a91236"
],
"index": "pypi",
"version": "==0.5.0"
},
"webencodings": {
"hashes": [
"sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78",
"sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"
],
"version": "==0.5.1"
}
},

18
assets/cc-button.svg Normal file
View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80" height="15" version="1.1" viewBox="0 0 80 15" xmlns="http://www.w3.org/2000/svg">
<rect y="0" width="80" height="15"/>
<rect x="1" y="1" width="78" height="13" fill="#fff"/>
<rect x="2" y="2" width="76" height="11"/>
<path d="m42 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m31 5h2v1h1v1h-1v-1h-2v3h2v-1h1v1h-1v1h-2v-1h-1v-3h1z" fill="#fff"/>
<path d="m37 5v1h2v-1zm2 1v3h1v-3zm0 3h-2v1h2zm-2 0v-3h-1v3z" fill="#fff"/>
<path d="m57 5v1h2v-1zm2 1v3h1v-3zm0 3h-2v1h2zm-2 0v-3h-1v3z" fill="#fff"/>
<path d="m49 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m70 5h3v1h-3v1h2v1h1v1h-1v1h-3v-1h3v-1h-2v-1h-1v-1h1" fill="#fff"/>
<path d="m62 5h1v1h1v1h1v1h1v-3h1v5h-1v-1h-1v-1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m2 2v11h19.891a8.5136 8.5 0 0 0 2.1088-5.5898 8.5136 8.5 0 0 0-1.9563-5.4102h-13.119z" fill="#abb1aa"/>
<path d="m6.0195 2a8.5 8.5 0 0 0-2.0195 5.5 8.5 8.5 0 0 0 2.0312 5.5h12.949a8.5 8.5 0 0 0 2.0195-5.5 8.5 8.5 0 0 0-2.0312-5.5z"/>
<circle cx="12.5" cy="7.5" r="6.5" fill="#feffff"/>
<path d="m9 5h2v1h1v1h-1v-1h-2v3h2v-1h1v1h-1v1h-2v-1h-1v-3h1z"/>
<path d="m14 5h2v1h1v1h-1v-1h-2v3h2v-1h1v1h-1v1h-2v-1h-1v-3h1z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80" height="15" version="1.1" viewBox="0 0 80 15" xmlns="http://www.w3.org/2000/svg">
<rect width="80" height="15" fill="#666"/>
<rect x="1" y="1" width="78" height="13" fill="#fff"/>
<path d="m3 4v2h7v-2h-7zm0 3v4h7v-4h-7z" fill="#fc0d1b"/>
<path d="m11 4v2h1v-2h-1zm1 2v3h1v-3h-1zm1 0h1v3h1v2h2v-2h1v-3h1v-2h-6v2zm1 3h-1v2h1v-2z" fill="#fc5d20"/>
<polygon points="21 4 25 4 25 5 26 5 26 7 22 7 22 8 26 8 26 10 25 10 25 11 21 11 21 10 20 10 20 8 19 8 19 7 20 7 20 5 21 5" fill="#fdb02a"/>
<rect x="29" y="2" width="49" height="1" fill="#fda829"/>
<rect x="29" y="3" width="49" height="1" fill="#fd9c27"/>
<rect x="29" y="4" width="49" height="1" fill="#fd9025"/>
<rect x="29" y="5" width="49" height="1" fill="#fd8124"/>
<rect x="29" y="6" width="49" height="1" fill="#fd7222"/>
<rect x="29" y="7" width="49" height="1" fill="#fd6420"/>
<rect x="29" y="8" width="49" height="1" fill="#fc561f"/>
<rect x="29" y="9" width="49" height="1" fill="#fc481e"/>
<rect x="29" y="10" width="49" height="1" fill="#fc371d"/>
<rect x="29" y="11" width="49" height="1" fill="#fc291c"/>
<rect x="29" y="12" width="49" height="1" fill="#fc1c1c"/>
<path d="m34 5h1v5h-1z" fill="#fff"/>
<path d="m37 5h1v1h1v1h1v1h1v-3h1v5h-1v-1h-1v-1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m44 5v5h3v-1h-2v-3h2v-1h-3zm3 1v3h1v-3h-1z" fill="#fff"/>
<path d="m50 5h1v5h-1z" fill="#fff"/>
<path d="m53 5h3v1h-2v1h2v1h-2v1h2v1h-3z" fill="#fff"/>
<path d="m58 5h1v4h1v-3h1v3h1v-4h1v4h-1v1h-1v-1h-1v1h-1v-1h-1z" fill="#fff"/>
<path d="m65 5h3v1h-2v1h2v1h-2v1h2v1h-3z" fill="#fff"/>
<path d="m70 5v5h3v-1h-2v-1h2v-1h-2v-1h2v-1h-3zm3 1v1h1v-1h-1zm0 2v1h1v-1h-1z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80" height="15" version="1.1" viewBox="0 0 80 15" xmlns="http://www.w3.org/2000/svg">
<rect width="80" height="15" fill="#666"/>
<rect x="1" y="1" width="78" height="13" fill="#fff"/>
<rect x="18" y="2" width="2" height="11" fill="#5d8f17"/>
<rect x="20" y="2" width="2" height="11" fill="#609218"/>
<rect x="22" y="2" width="2" height="11" fill="#639519"/>
<rect x="24" y="2" width="2" height="11" fill="#66981a"/>
<rect x="26" y="2" width="2" height="11" fill="#699b1b"/>
<rect x="28" y="2" width="2" height="11" fill="#6c9e1b"/>
<rect x="30" y="2" width="2" height="11" fill="#6fa11c"/>
<rect x="32" y="2" width="2" height="11" fill="#72a51d"/>
<rect x="34" y="2" width="2" height="11" fill="#76a81e"/>
<rect x="36" y="2" width="2" height="11" fill="#78aa1f"/>
<rect x="38" y="2" width="2" height="11" fill="#7cae20"/>
<rect x="40" y="2" width="2" height="11" fill="#7eb120"/>
<rect x="42" y="2" width="2" height="11" fill="#82b421"/>
<rect x="44" y="2" width="2" height="11" fill="#85b722"/>
<rect x="46" y="2" width="2" height="11" fill="#88ba23"/>
<rect x="48" y="2" width="2" height="11" fill="#8bbd24"/>
<rect x="50" y="2" width="2" height="11" fill="#8ec125"/>
<rect x="52" y="2" width="2" height="11" fill="#91c325"/>
<rect x="54" y="2" width="2" height="11" fill="#94c626"/>
<rect x="56" y="2" width="2" height="11" fill="#97ca27"/>
<rect x="58" y="2" width="2" height="11" fill="#9acd28"/>
<rect x="60" y="2" width="2" height="11" fill="#9dd029"/>
<rect x="62" y="2" width="2" height="11" fill="#a0d32a"/>
<rect x="64" y="2" width="2" height="11" fill="#a4d62b"/>
<rect x="66" y="2" width="2" height="11" fill="#a6d92b"/>
<rect x="68" y="2" width="2" height="11" fill="#a8db2c"/>
<rect x="70" y="2" width="2" height="11" fill="#acdf2d"/>
<rect x="72" y="2" width="2" height="11" fill="#b0e32e"/>
<rect x="74" y="2" width="2" height="11" fill="#b3e62f"/>
<rect x="76" y="2" width="2" height="11" fill="#b6e92f"/>
<polygon points="4 4 6 4 6 9 7 9 7 10 12 10 12 12 11 12 11 13 4 13 4 12 3 12 3 5 4 5" fill="#5c8d17"/>
<polygon points="7 3 9 3 9 6 10 6 10 7 13 7 13 9 8 9 8 8 7 8" fill="#8dc024"/>
<polygon points="10 2 13 2 13 3 14 3 14 6 11 6 11 5 10 5" fill="#a5d82b"/>
<path d="m20 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m26 5h1v5h-1z" fill="#fff"/>
<path d="m29 5h2v1h1v1h-1v-1h-2v3h2v-1h1v1h-1v1h-2v-1h-1v-3h1z" fill="#fff"/>
<path d="m33 5v5h1v-2h1v1h1v-2h-2v-1h2v-1h-3zm3 1v1h1v-1h-1zm0 3v1h1v-1h-1z" fill="#fff"/>
<path d="m39 5v1h2v-1h-2zm2 1v1 1 1h1v-1-1-1h-1zm0 3h-2v1h2v-1zm-2 0v-3h-1v3h1z" fill="#fff"/>
<path d="m43 5h3v1h-2v1h2v1h-2v2h-1z" fill="#fff"/>
<path d="m48 5v1h2v-1h-2zm2 1v1 1 1h1v-1-1-1h-1zm0 3h-2v1h2v-1zm-2 0v-3h-1v3h1z" fill="#fff"/>
<path d="m52 5v5h1v-2h1v1h1v-2h-2v-1h2v-1h-3zm3 1v1h1v-1h-1zm0 3v1h1v-1h-1z" fill="#fff"/>
<path d="m57 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m64 5v1h2v-1h-2zm2 1v1h-2v-1h-1v4h1v-2h2v2h1v-4h-1z" fill="#fff"/>
<path d="m68 5h3v1h-1v4h-1v-4h-1" fill="#fff"/>
<path d="m73 5h3v1h-3v1h2v1h1v1h-1v1h-3v-1h3v-1h-2v-1h-1v-1h1" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80" height="15" version="1.1" viewBox="0 0 80 15" xmlns="http://www.w3.org/2000/svg">
<rect width="80" height="15" fill="#666"/>
<rect x="1" y="1" width="78" height="13" fill="#fff" style="paint-order:markers fill stroke"/>
<path d="m13 1v1h-1v1h-1v1h1 1v1h-1v2h-1v2h-1v-3h-1v-2h-1v2h-1v3h-1v-2h-1v-3h-1v-2h-1-1v2h1v3h1v3h1v3h1 1v-3h1v-2h1v2h1v3h1 1v-3h1v-3h1v-3h1 1v-1h-1v-1h-1v-1h-1z" fill="#610371"/>
<rect x="19" y="2" width="59" height="11" fill="#850e9a"/>
<path d="m33 5v5h3v-1h-2v-1h2v-1h-2v-1h2v-1h-3zm3 1v1h1v-1h-1zm0 2v1h1v-1h-1z" fill="#fff"/>
<path d="m28 5h3v1h-2v1h2v1h-2v1h2v1h-3z" fill="#fff"/>
<path d="m21 5h1v4h1v-3h1v3h1v-4h1v4h-1v1h-1v-1h-1v1h-1v-1h-1z" fill="#fff"/>
<path d="m39 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m51 5h1v1h1v1h1v1h1v-3h1v5h-1v-1h-1v-1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m58 5h3v1h-1v4h-1v-4h-1" fill="#fff"/>
<path d="m63 5h1v5h-1z" fill="#fff"/>
<path d="m67 5v1h2v-1zm2 1v3h1v-3zm0 3h-2v1h2zm-2 0v-3h-1v3z" fill="#fff"/>
<path d="m71 5h1v1h1v1h1v1h1v-3h1v5h-1v-1h-1v-1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m46 5h3v1h-2v1h2v1h-2v1h2v1h-3z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

126
meta.py
View file

@ -13,8 +13,6 @@ import requests
import keys
import settings
from pprint import pprint
EXIFDATE = re.compile(
r'^(?P<year>[0-9]{4}):(?P<month>[0-9]{2}):(?P<day>[0-9]{2})\s+'
r'(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2})$'
@ -69,130 +67,6 @@ class CachedMeta(dict):
for k, v in data.items():
self[k] = v
class GoogleClassifyText(CachedMeta):
def __init__(self, fpath, txt, lang='en'):
self.fpath = fpath
self.txt = txt
self.lang = lang
self._read()
def _call_tool(self):
params = {
"document": {
"type": "PLAIN_TEXT",
"content": self.txt,
"language": self.lang,
}
}
url = "https://language.googleapis.com/v1beta2/documents:classifyText?key=%s" % (
keys.gcloud.get('key')
)
logging.info(
"calling Google classifyText for %s",
self.fpath
)
try:
r = requests.post(url, json=params)
resp = r.json()
for cat in resp.get('categories', []):
self[cat.get('name')] = cat.get('confidence')
except Exception as e:
logging.error(
'failed to call Google Vision API on: %s, reason: %s',
self.fpath,
e
)
class GoogleVision(CachedMeta):
def __init__(self, fpath, imgurl):
self.fpath = fpath
self.imgurl = imgurl
self._read()
@property
def response(self):
if 'responses' not in self:
return {}
if not len(self['responses']):
return {}
if 'labelAnnotations' not in self['responses'][0]:
return {}
return self['responses'][0]
@property
def tags(self):
tags = []
if 'labelAnnotations' in self.response:
for label in self.response['labelAnnotations']:
tags.append(label['description'])
if 'webDetection' in self.response:
if 'webEntities' in self.response['webDetection']:
for label in self.response['webDetection']['webEntities']:
tags.append(label['description'])
return tags
@property
def landmark(self):
landmark = None
if 'landmarkAnnotations' in self.response:
if len(self.response['landmarkAnnotations']):
match = self.response['landmarkAnnotations'].pop()
landmark = {
'name': match['description'],
'latitude': match['locations'][0]['latLng']['latitude'],
'longitude': match['locations'][0]['latLng']['longitude']
}
return landmark
@property
def onlinecopies(self):
copies = []
if 'webDetection' in self.response:
if 'pagesWithMatchingImages' in self.response['webDetection']:
for match in self.response['webDetection']['pagesWithMatchingImages']:
copies.append(match['url'])
return copies
def _call_tool(self):
params = {
"requests": [{
"image": {"source": {"imageUri": self.imgurl}},
"features": [
{
"type": "LANDMARK_DETECTION",
},
{
"type": "WEB_DETECTION",
},
{
"type": "LABEL_DETECTION",
}
]
}]
}
url = "https://vision.googleapis.com/v1/images:annotate?key=%s" % (
keys.gcloud.get('key')
)
logging.info(
"calling Google Vision for %s",
self.fpath
)
try:
r = requests.post(url, json=params)
resp = r.json()
for k, v in resp.items():
self[k] = v
except Exception as e:
logging.error(
'failed to call Google Vision API on: %s, reason: %s',
self.fpath,
e
)
class Exif(CachedMeta):
def __init__(self, fpath):

238
nasg.py
View file

@ -15,11 +15,13 @@ import asyncio
import sqlite3
import json
import queue
import base64
from shutil import copy2 as cp
from math import ceil
from urllib.parse import urlparse
from collections import OrderedDict, namedtuple
import logging
import arrow
import langdetect
import wand.image
@ -27,17 +29,15 @@ import jinja2
import yaml
import frontmatter
from feedgen.feed import FeedGenerator
from bleach import clean
from emoji import UNICODE_EMOJI
from slugify import slugify
import requests
from pandoc import PandocMarkdown
from meta import Exif
import settings
from settings import struct
import keys
from pprint import pprint
logger = logging.getLogger('NASG')
MarkdownImage = namedtuple(
@ -45,8 +45,6 @@ MarkdownImage = namedtuple(
['match', 'alt', 'fname', 'title', 'css']
)
REPLY_TYPES = ['webmention', 'in-reply-to', 'reply']
J2 = jinja2.Environment(
loader=jinja2.FileSystemLoader(searchpath=settings.paths.get('tmpl')),
lstrip_blocks=True,
@ -60,7 +58,7 @@ RE_MDIMG = re.compile(
)
RE_CODE = re.compile(
r'^(?:[~`]{3}).+$',
r'^(?:[~`]{3,4}).+$',
re.MULTILINE
)
@ -68,6 +66,11 @@ RE_PRECODE = re.compile(
r'<pre class="([^"]+)"><code>'
)
def mtime(path):
if os.path.exists(path):
return int(os.path.getmtime(path))
return 0
def utfyamldump(data):
return yaml.dump(
data,
@ -83,12 +86,43 @@ def url2slug(url, limit=200):
lower=True
)[:limit]
J2.filters['url2slug'] = url2slug
def rfc3339todt(rfc3339):
t = arrow.get(rfc3339).format('YYYY-MM-DD HH:mm ZZZ')
return "%s" % (t)
J2.filters['printdate'] = rfc3339todt
J2.filters['url2slug'] = url2slug
RE_MYURL = re.compile(
r'(^(%s[^"]+)$|"(%s[^"]+)")' % (
settings.site.url,
settings.site.url
)
)
def relurl(text, baseurl=None):
if not baseurl:
baseurl = settings.site.url
for match, standalone, href in RE_MYURL.findall(text):
needsquotes = False
if len(href):
needsquotes = True
url = href
else:
url = standalone
r = os.path.relpath(url, baseurl)
if url.endswith('/') and not r.endswith('/'):
r = "%s/index.html" % r
if needsquotes:
r = '"%s"' % r
logger.debug("RELURL: %s => %s (base: %s)", match, r, baseurl)
text = text.replace(match, r)
return text
J2.filters['relurl'] = relurl
def writepath(fpath, content, mtime=0):
d = os.path.dirname(fpath)
@ -126,6 +160,7 @@ class cached_property(object):
class AQ:
""" Async queue which starts execution right on population """
def __init__(self):
self.loop = asyncio.get_event_loop()
self.queue = asyncio.Queue(loop=self.loop)
@ -145,6 +180,7 @@ class AQ:
class Webmention(object):
""" outgoing webmention class """
def __init__(self, source, target, dpath, mtime=0):
self.source = source
self.target = target
@ -166,7 +202,7 @@ class Webmention(object):
def exists(self):
if not os.path.isfile(self.fpath):
return False
elif os.path.getmtime(self.fpath) > self.mtime:
elif mtime(self.fpath) > self.mtime:
return True
else:
return False
@ -196,9 +232,10 @@ class Webmention(object):
class MarkdownDoc(object):
""" Base class for anything that is stored as .md """
@property
def mtime(self):
return os.path.getmtime(self.fpath)
return mtime(self.fpath)
@property
def dt(self):
@ -234,7 +271,7 @@ class MarkdownDoc(object):
def content(self):
return self._parsed[1]
def __pandoc(self, c):
def pandoc(self, c):
if c and len(c):
c = PandocMarkdown(c)
c = RE_PRECODE.sub(
@ -247,7 +284,7 @@ class MarkdownDoc(object):
if hasattr(self, 'images') and len(self.images):
for match, img in self.images.items():
c = c.replace(match, str(img))
return self.__pandoc(c)
return self.pandoc(c)
class Comment(MarkdownDoc):
@ -260,7 +297,7 @@ class Comment(MarkdownDoc):
if maybe and 'null' != maybe:
dt = arrow.get(maybe)
else:
dt = arrow.get(os.path.getmtime(self.fpath))
dt = arrow.get(mtime(self.fpath))
return dt
@property
@ -295,11 +332,12 @@ class Comment(MarkdownDoc):
@property
def type(self):
if len(self.content):
maybe = clean(self.content, strip=True)
if maybe in UNICODE_EMOJI:
return maybe
return self.meta.get('type', 'webmention')
#if len(self.content):
#maybe = clean(self.content, strip=True)
#if maybe in UNICODE_EMOJI:
#return maybe
@cached_property
def jsonld(self):
@ -322,7 +360,7 @@ class Gone(object):
def __init__(self, fpath):
self.fpath = fpath
self.mtime = os.path.getmtime(fpath)
self.mtime = mtime(fpath)
@property
def source(self):
@ -472,7 +510,7 @@ class Singular(MarkdownDoc):
def html_summary(self):
c = self.summary
if c and len(c):
c = PandocMarkdown(self.summary)
c = self.pandoc(self.summary)
return c
@property
@ -531,13 +569,14 @@ class Singular(MarkdownDoc):
@property
def to_ping(self):
urls = []
w = Webmention(
self.url,
'https://fed.brid.gy/',
os.path.dirname(self.fpath),
self.dt
)
urls.append(w)
if not self.is_page and self.is_front:
w = Webmention(
self.url,
'https://fed.brid.gy/',
os.path.dirname(self.fpath),
self.dt
)
urls.append(w)
if self.is_reply:
w = Webmention(
self.url,
@ -589,6 +628,47 @@ class Singular(MarkdownDoc):
else:
return False
#@cached_property
#def oembed_xml(self):
#oembed = etree.Element("oembed", version="1.0")
#xmldoc = etree.ElementTree(oembed)
#for k, v in self.oembed_json.items():
#x = etree.SubElement(oembed, k).text = "%s" % (v)
#s = etree.tostring(
#xmldoc,
#encoding='utf-8',
#xml_declaration=True,
#pretty_print=True
#)
#return s
#@cached_property
#def oembed_json(self):
#r = {
#"version": "1.0",
#"provider_name": settings.site.name,
#"provider_url": settings.site.url,
#"author_name": settings.author.name,
#"author_url": settings.author.url,
#"title": self.title,
#"type": "link",
#"html": self.html_content,
#}
#img = None
#if self.is_photo:
#img = self.photo
#elif not self.is_photo and len(self.images):
#img = list(self.images.values())[0]
#if img:
#r.update({
#"type": "rich",
#"thumbnail_url": img.jsonld.thumbnail.url,
#"thumbnail_width": img.jsonld.thumbnail.width,
#"thumbnail_height": img.jsonld.thumbnail.height
#})
#return r
@cached_property
def review(self):
if 'review' not in self.meta:
@ -632,7 +712,6 @@ class Singular(MarkdownDoc):
}
return r
@cached_property
def jsonld(self):
r = {
@ -665,11 +744,6 @@ class Singular(MarkdownDoc):
"@type": "Photograph",
"image": self.photo.jsonld,
})
elif not self.is_photo and len(self.images):
img = list(self.images.values())[0]
r.update({
"image": img.jsonld,
})
elif self.has_code:
r.update({
"@type": "TechArticle",
@ -678,7 +752,11 @@ class Singular(MarkdownDoc):
r.update({
"@type": "WebPage",
})
if not self.is_photo and len(self.images):
img = list(self.images.values())[0]
r.update({
"image": img.jsonld,
})
if self.is_reply:
r.update({
@ -708,7 +786,7 @@ class Singular(MarkdownDoc):
for mtime in sorted(self.comments.keys()):
r["comment"].append(self.comments[mtime].jsonld)
return r
return struct(r)
@property
def template(self):
@ -734,7 +812,7 @@ class Singular(MarkdownDoc):
elif not os.path.exists(self.renderfile):
logger.debug('rendering required: no html yet')
return False
elif self.dt > os.path.getmtime(self.renderfile):
elif self.dt > mtime(self.renderfile):
logger.debug('rendering required: self.dt > html mtime')
return False
else:
@ -768,31 +846,40 @@ class Singular(MarkdownDoc):
self.name,
os.path.basename(f)
)
if os.path.exists(t) and os.path.getmtime(
f) <= os.path.getmtime(t):
if os.path.exists(t) and mtime(
f) <= mtime(t):
continue
logger.info("copying '%s' to '%s'", f, t)
cp(f, t)
async def render(self):
if self.exists:
return
logger.info("rendering %s", self.name)
r = J2.get_template(self.template).render({
@cached_property
def html(self):
r = J2.get_template(self.template).render({
'baseurl': self.url,
'post': self.jsonld,
'site': settings.site,
'menu': settings.menu,
'meta': settings.meta,
})
return r
async def render(self):
if self.exists:
return
logger.info("rendering %s", self.name)
writepath(
self.renderfile,
r
self.html
)
j = settings.site.copy()
j.update({
"mainEntity": self.jsonld
})
writepath(
self.renderfile.replace('.html', '.json'),
json.dumps(self.jsonld, indent=4, ensure_ascii=False)
os.path.join(self.renderdir,'index.json'),
json.dumps(j, indent=4, ensure_ascii=False)
)
del(j)
class Home(Singular):
@ -844,7 +931,7 @@ class WebImage(object):
self.mdimg = mdimg
self.fpath = fpath
self.parent = parent
self.mtime = os.path.getmtime(self.fpath)
self.mtime = mtime(self.fpath)
self.fname, self.fext = os.path.splitext(os.path.basename(fpath))
self.resized_images = [
(k, self.Resized(self, k))
@ -863,20 +950,20 @@ class WebImage(object):
return True
return False
@cached_property
@property
def jsonld(self):
r = {
"@context": "http://schema.org",
"@type": "ImageObject",
"url": self.href,
"image": self.href,
"thumbnail": {
"thumbnail": struct({
"@context": "http://schema.org",
"@type": "ImageObject",
"url": self.src,
"width": self.displayed.width,
"height": self.displayed.height,
},
}),
"name": os.path.basename(self.fpath),
"encodingFormat": self.mime_type,
"contentSize": self.mime_size,
@ -902,21 +989,7 @@ class WebImage(object):
})
if self.is_mainimg:
r.update({"representativeOfPage": True})
return r
#@cached_property
#def tmplvars(self):
#return {
#'src': self.src,
#'href': self.href,
#'width': self.displayed.width,
#'height': self.displayed.height,
#'title': self.title,
#'caption': self.caption,
#'exif': self.exif,
#'is_photo': self.is_photo,
#'is_mainimg': self.is_mainimg
#}
return struct(r)
def __str__(self):
if len(self.mdimg.css):
@ -966,7 +1039,12 @@ class WebImage(object):
@property
def mime_size(self):
return os.path.getsize(self.linked.fpath)
try:
size = os.path.getsize(self.linked.fpath)
except Exception as e:
logger.error('Failed to get mime size of %s', self.linked.fpath)
size = self.meta.get('FileSize', 0)
return size
@property
def displayed(self):
@ -1101,6 +1179,12 @@ class WebImage(object):
self.size = size
self.crop = crop
@property
def data(self):
with open(self.fpath, 'rb') as f:
encoded = base64.b64encode(f.read())
return "data:%s;base64,%s" % (self.parent.mime_type, encoded.decode('utf-8'))
@property
def suffix(self):
return settings.photo.get('sizes').get(self.size, '')
@ -1144,7 +1228,7 @@ class WebImage(object):
@property
def exists(self):
if os.path.isfile(self.fpath):
if os.path.getmtime(self.fpath) >= self.parent.mtime:
if mtime(self.fpath) >= self.parent.mtime:
return True
return False
@ -1216,13 +1300,13 @@ class PHPFile(object):
return False
if not os.path.exists(self.renderfile):
return False
if self.mtime > os.path.getmtime(self.renderfile):
if self.mtime > mtime(self.renderfile):
return False
return True
@property
def mtime(self):
return os.path.getmtime(
return mtime(
os.path.join(
settings.paths.get('tmpl'),
self.templatefile
@ -1238,8 +1322,8 @@ class PHPFile(object):
raise ValueError('Not implemented')
async def render(self):
if self.exists:
return
#if self.exists:
#return
await self._render()
@ -1532,7 +1616,7 @@ class Category(dict):
return False
if not os.path.exists(fpath):
return False
if os.path.getmtime(fpath) >= ts:
if mtime(fpath) >= ts:
return True
return False
@ -1554,10 +1638,10 @@ class Category(dict):
'title': self.title,
}
def tmplvars(self, posts=[], year=False):
def tmplvars(self, posts=[], year=None):
baseurl = self.url
if year:
baseurl = '%s/%s/' % (baseurl, year)
baseurl = '%s%s/' % (baseurl, year)
return {
'baseurl': baseurl,
'site': settings.site,
@ -1672,8 +1756,10 @@ class Category(dict):
for year in self.years.keys():
if year == self.newest_year:
fpath = self.indexfpath()
tyear = None
else:
fpath = self.indexfpath("%d" % (year))
tyear = year
y = arrow.get("%d" % year, self.trange).to('utc')
tsmin = y.floor('year').timestamp
tsmax = y.ceil('year').timestamp
@ -1697,7 +1783,7 @@ class Category(dict):
# some posts disappear
# TODO figure this out...
self.get_posts(start, end+1),
year
tyear
)
)
writepath(fpath, r)
@ -1752,7 +1838,7 @@ class Sitemap(dict):
def mtime(self):
r = 0
if os.path.exists(self.renderfile):
r = os.path.getmtime(self.renderfile)
r = mtime(self.renderfile)
return r
def append(self, post):
@ -1969,7 +2055,7 @@ def make():
if e.endswith('.md'):
continue
t = os.path.join(settings.paths.get('build'),os.path.basename(e))
if os.path.exists(t) and os.path.getmtime(e) <= os.path.getmtime(t):
if os.path.exists(t) and mtime(e) <= mtime(t):
continue
cp(e, t)

View file

@ -9,6 +9,13 @@ import re
import argparse
import logging
class struct(dict):
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
base = os.path.abspath(os.path.expanduser('~/Projects/petermolnar.net'))
syncserver = 'liveserver:/web/petermolnar.net'
@ -17,12 +24,12 @@ notinfeed = ['note']
flat = ['article', 'journal']
displaydate = 'YYYY-MM-DD HH:mm'
class struct(dict):
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
licence = struct({
'article': 'CC-BY-4.0',
'journal': 'CC-BY-NC-4.0',
'_default': 'CC-BY-NC-ND-4.0'
})
# full author, only for h-card generation
author = struct({
"@context": "http://schema.org",
"@type": "Person",
@ -39,6 +46,7 @@ site = struct({
"url": "https://petermolnar.net",
"name": "petermolnar.net",
"image": "https://petermolnar.net/favicon.ico",
"license": "https://spdx.org/licenses/%s.html" % (licence['_default']),
"author": {
"@context": "http://schema.org",
"@type": "Person",
@ -128,12 +136,6 @@ menu = {
}
}
licence = struct({
'article': 'CC-BY-4.0',
'journal': 'CC-BY-NC-4.0',
'_default': 'CC-BY-NC-ND-4.0'
})
meta = struct({
'webmention': 'https://webmention.io/petermolnar.net/webmention',
'pingback': 'https://webmention.io/petermolnar.net/xmlrpc',

View file

@ -23,6 +23,8 @@ $gone = array(
$gone_re = array(
'^cache\/.*$',
'^tag\/.*$',
'^comment\/.*$',
'^files\/.*$',
'^wp-content\/.*$',
'^broadcast\/wp-ffpc\.message$',
@ -50,12 +52,12 @@ function gone($uri) {
<body>
<h1><center>This content was deleted.</center></h1>
<hr>
<p><center>{{ site.domain }}</center></p>
<p><center>'.$uri.'</center></p>
</body>
</html>');
}
function notfound() {
function notfound($uri) {
header('HTTP/1.0 404 Not Found');
die('<!DOCTYPE html>
<html lang="en">
@ -70,13 +72,15 @@ function notfound() {
<h2><center>Please search for it instead.</center></h2>
<p>
<center>
<form action="/search.php" class="search-form" method="get" role="search">
<label for="search">Search</label>
<input id="q" name="q" placeholder="search..." title="Search for:" type="search" value=""/>
<input type="submit" value="OK"/>
</form>
<form action="/search.php" class="search-form" method="get" role="search">
<label for="search">Search</label>
<input id="q" name="q" placeholder="search..." title="Search for:" type="search" value=""/>
<input type="submit" value="OK"/>
</form>
</center>
</p>
<hr>
<p><center>'.$uri.'</center></p>
</body>
</html>');
}
@ -120,5 +124,5 @@ elseif (strstr($uri, '_')) {
maybe_redirect(str_replace('_', '-', $uri));
}
else {
notfound();
notfound($uri);
}

View file

@ -13,7 +13,7 @@
<nav>
<ul>
{% for y, url in category.years.items() %}
{% if y == category.year %}
{% if (y == category.year) or (not category.year and loop.first) %}
<li>
<span>
{{ y }}
@ -21,7 +21,7 @@
</li>
{% else %}
<li>
<a href="{{ url }}">
<a href="{{ url|relurl(baseurl) }}">
<strong>{{ y }}</strong>
</a>
</li>
@ -53,7 +53,7 @@
{% endif %}
{% set _ = year.append(post.copyrightYear)%}
{% include 'meta-article.j2.html' %}
{% if loop.last %}
{% if not category.paginated and loop.last %}
</section>
{% endif %}
{% endfor %}

View file

@ -24,7 +24,7 @@
{% for category, post in posts %}
<section>
<h2>in:
<a href="{{ category.url }}/">
<a href="{{ category.url|relurl(baseurl) }}/">
<svg width="16" height="16"><use xlink:href="#icon-{{ category.name }}" /></svg>
{{ category.name }}
</a>

View file

@ -7,6 +7,9 @@
{% block meta %}
<meta name="description" content="{{ post.description|striptags|e }}" />
<link rel="canonical" href="{{ post.url }}" />
<link rel="alternate" type="application/json" href="{{ post.url }}index.json" />
<link rel="alternate" type="application/ld+json" href="{{ post.url }}index.json" />
<link rel="alternate" type="application/mf2+json" href="https://pin13.net/mf2/?url={{ post.url|urlencode }}" />
<meta property="og:title" content="{{ post.headline }}" />
<meta property="og:type" content="article" />
<meta property="og:url" content="{{ post.url }}" />
@ -38,6 +41,16 @@
{% endif %}
{% endblock %}
{% block cc %}
<li>
<a href="{{ post.license }}">
<svg width="80" height="15">
<use xlink:href="#button-cc"/>
</svg>
</a>
</li>
{% endblock %}
{% block content %}
<main>
<article class="h-entry hentry" lang="{{ post.inLanguage }}" id="article">
@ -48,7 +61,7 @@
<svg width="16" height="16">
<use xlink:href="#icon-reply" />
</svg>
<a href="{{ post.url }}">
<a href="{{ post.url|relurl(baseurl) }}">
RE:
</a>
<a href="{{ post.mentions.url }}" class="u-in-reply-to">
@ -56,7 +69,7 @@
</a>
</span>
{% else %}
<a href="{{ post.url }}">
<a href="{{ post.url|relurl(baseurl) }}">
{{ post.headline }}
</a>
{% endif %}
@ -65,7 +78,7 @@
{% if post.review %}
<div class="h-review hreview">
<strong>Review summary of: <a href="{{ post.review.url }}" class="p-name u-url p-item h-product item fn">{{ post.review.name }}</a></strong>
<strong>Review summary of: <a href="{{ post.review.url }}" class="p-name u-url p-item h-product item fn url">{{ post.review.name }}</a></strong>
<p>
By
<span class="p-author h-card reviewer vcard">
@ -86,12 +99,12 @@
{% if post.description|length %}
<div class="e-summary entry-summary">
{{ post.description }}
{{ post.description|relurl(baseurl) }}
</div>
{% endif %}
<div class="e-content entry-content">
{{ post.text }}
{{ post.text|relurl(baseurl) }}
</div>
<footer>
@ -164,7 +177,7 @@
<dt>Author</dt>
<dd class="p-author h-card vcard">
<img class="u-photo photo" src="{{ post.author.image }}" alt="" />
<img class="u-photo photo" src="{{ post.author.image|relurl(baseurl) }}" alt="" />
<a class="p-name u-url fn url" href="{{ post.author.url }}">{{ post.author.name }}</a>
<a class="u-email email" href="mailto:{{ post.author.email }}">{{ post.author.email }}</a>
</dd>
@ -227,13 +240,24 @@
<ol>
{% for comment in post.comment %}
<li class="h-entry p-comment hentry">
<a href="{{ comment.url }}">
{{ comment.disambiguatingDescription }}
</a>
<i>
{% if 'like-of' == comment.disambiguatingDescription %}
{% set icon = 'star' %}
{% elif 'bookmark-of' == comment.disambiguatingDescription %}
{% set icon = 'bookmark' %}
{% elif 'reply' == comment.disambiguatingDescription %}
{% set icon = 'reply' %}
{% else %}
{% set icon = 'link' %}
{% endif %}
<svg width="16" height="16">
<use xlink:href="#icon-{{ icon }}"></use>
</svg>
</i>
from
<span class="p-author h-card vcard">
{% if comment.author.url %}
<a class="u-url p-name fn" href="{{ comment.author.url }}">
<a class="u-url p-name fn url org" href="{{ comment.author.url }}">
{{ comment.author.name }}
</a>
{% else %}
@ -247,9 +271,6 @@
{{ comment.datePublished|printdate }}
</time>
<br />
<svg width="16" height="16">
<use xlink:href="#icon-link"></use>
</svg>
<a class="u-url" href="{{ comment.url }}">
{{ comment.url }}
</a>

View file

@ -1,11 +1,15 @@
<!DOCTYPE html>
<html{% block lang %}{% endblock %} prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#">
<head>
<!--[if lt IE 9]>
<script src="{{ site.url}}/html5shiv-printshiv.js"></script>
<![endif]-->
<title>{% block title %}{% endblock %}</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1" />
<meta name="author" content="{{ site.author.name }} ({{ site.author.email }})" />
<link rel="icon" href="{{ site.image }}" />
<!-- <base href="{{ baseurl }}" /> -->
{% for key, value in meta.items() %}
<link rel="{{ key }}" href="{{ value }}" />
{% endfor %}
@ -35,7 +39,7 @@
<ul>
{% for key, data in menu.items() %}
<li>
<a title="{{ data.text }}" href="{{ data.url }}" {{ activemenu(key) }} >
<a title="{{ data.text }}" href="{{ data.url|relurl(baseurl) }}" {{ activemenu(key) }} >
<svg width="16" height="16">
<use xlink:href="#icon-{{ key }}" />
</svg>
@ -62,7 +66,7 @@
</form>
{% for action in site.potentialAction %}
{% if 'SearchAction' == action['@type'] %}
<form role="search" method="get" action="{{ action.url }}">
<form role="search" method="get" action="{{ action.url|relurl(baseurl) }}">
<label for="qsub">
<input type="submit" value="search" id="qsub" name="qsub" />
<svg width="16" height="16">
@ -88,7 +92,7 @@
<p>
<a href="https://creativecommons.org/">CC</a>,
1999-2019,
<img class="u-photo photo" src="{{ site.author.image }}" alt="Photo of {{ site.author.name }}" />
<img class="u-photo photo" src="{{ site.author.image|relurl(baseurl) }}" alt="Photo of {{ site.author.name }}" />
<a class="p-name u-url fn url" href="{{ site.author.url }}" rel="me"> {{ site.author.name }}</a>
<a class="u-email email" rel="me" href="mailto:{{ site.author.email }}">
<svg width="16" height="16">
@ -138,6 +142,42 @@
<a href="https://xn--sr8hvo.ws/🇻🇮📢/next"></a>
</nav>
</section>
<section>
<nav>
<ul>
<li>
<a href="https://indieweb.org/">
<svg width="80" height="15">
<use xlink:href="#button-indieweb"/>
</svg>
</a>
</li>
<li>
<a href="http://microformats.org/">
<svg width="80" height="15">
<use xlink:href="#button-microformats"/>
</svg>
</a>
</li>
<li>
<a href="https://www.w3.org/TR/webmention/">
<svg width="80" height="15">
<use xlink:href="#button-webmention"/>
</svg>
</a>
</li>
{% block cc %}
<li>
<a href="{{ site.license }}">
<svg width="80" height="15">
<use xlink:href="#button-cc"/>
</svg>
</a>
</li>
{% endblock %}
</ul>
</nav>
</section>
</footer>
<script>

View file

@ -6,7 +6,7 @@
<svg width="16" height="16">
<use xlink:href="#icon-reply" />
</svg>
<a href="{{ post.url }}">
<a href="{{ post.url|relurl(baseurl) }}">
RE:
</a>
<a href="{{ post.mentions.url }}" class="u-in-reply-to">
@ -14,7 +14,7 @@
</a>
</span>
{% else %}
<a href="{{ post.url }}">
<a href="{{ post.url|relurl(baseurl) }}">
{{ post.headline }}
</a>
{% endif %}
@ -25,16 +25,16 @@
{% if post.description|length %}
<div class="e-summary entry-summary">
{{ post.description }}
{{ post.description|relurl(baseurl) }}
<span class="more">
<a href="{{ post.url }}">
<a href="{{ post.url|relurl(baseurl) }}">
{% if post.inLanguage == 'hu' %}Tovább »{% else %}Continue »{% endif %}
</a>
</span>
</div>
{% else %}
<div class="e-content entry-content">
{{ post.text }}
{{ post.text|relurl(baseurl) }}
</div>
{% endif %}
@ -44,8 +44,8 @@
<time datetime="{{ post.dateModified }}" class="dt-updated updated"></time>
by
<span class="p-author h-card vcard">
<img class="u-photo photo" src="{{ post.author.image }}" alt="" />
<a class="p-name u-url fn url" href="{{ post.author.url }}">{{ post.author.name }}</a>
<img class="u-photo photo" src="{{ post.author.image|relurl(baseurl) }}" alt="" />
<a class="p-name u-url fn url org" href="{{ post.author.url }}">{{ post.author.name }}</a>
<a class="u-email email" href="mailto:{{ post.author.email }}">{{ post.author.email }}</a>
</span>
</footer>

View file

@ -1,4 +1,3 @@
.token.comment,
.token.prolog,
.token.doctype,
@ -20,7 +19,7 @@
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
color: #f05;
}
.token.selector,
@ -29,7 +28,7 @@
.token.char,
.token.builtin,
.token.inserted {
color: #690;
color: #7a0;
}
.token.operator,
@ -43,7 +42,7 @@
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
color: #09c;
}
.token.function,
@ -67,4 +66,4 @@
.token.entity {
cursor: help;
}
}

View file

@ -1,5 +1,3 @@
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
@ -358,4 +356,4 @@ body > img {
right: 0;
width: 10em;
height: auto;
}
}

View file

@ -71,4 +71,121 @@
<symbol id="icon-resume" viewBox="0 0 16 16">
<path d="M13.5 0h-12c-0.825 0-1.5 0.675-1.5 1.5v13c0 0.825 0.675 1.5 1.5 1.5h12c0.825 0 1.5-0.675 1.5-1.5v-13c0-0.825-0.675-1.5-1.5-1.5zM13 14h-11v-12h11v12zM4 9h7v1h-7zM4 11h7v1h-7zM5 4.5c0-0.828 0.672-1.5 1.5-1.5s1.5 0.672 1.5 1.5c0 0.828-0.672 1.5-1.5 1.5s-1.5-0.672-1.5-1.5zM7.5 6h-2c-0.825 0-1.5 0.45-1.5 1v1h5v-1c0-0.55-0.675-1-1.5-1z"></path>
</symbol>
<symbol id="icon-bookmark" viewBox="0 0 16 16">
<path d="M4 2v14l5-5 5 5v-14zM12 0h-10v14l1-1v-12h9z"></path>
</symbol>
<symbol id="icon-star" viewBox="0 0 16 16">
<path d="M16 6.204l-5.528-0.803-2.472-5.009-2.472 5.009-5.528 0.803 4 3.899-0.944 5.505 4.944-2.599 4.944 2.599-0.944-5.505 4-3.899z"></path>
</symbol>
<symbol id="icon-reply" viewBox="0 0 16 16">
<path d="M7 12.119v3.881l-6-6 6-6v3.966c6.98 0.164 6.681-4.747 4.904-7.966 4.386 4.741 3.455 12.337-4.904 12.119z"></path>
</symbol>
<symbol id="button-indieweb" viewBox="0 0 80 15">
<rect width="80" height="15" fill="#666"/>
<rect x="1" y="1" width="78" height="13" fill="#fff"/>
<path d="m3 4v2h7v-2h-7zm0 3v4h7v-4h-7z" fill="#fc0d1b"/>
<path d="m11 4v2h1v-2h-1zm1 2v3h1v-3h-1zm1 0h1v3h1v2h2v-2h1v-3h1v-2h-6v2zm1 3h-1v2h1v-2z" fill="#fc5d20"/>
<polygon points="21 4 25 4 25 5 26 5 26 7 22 7 22 8 26 8 26 10 25 10 25 11 21 11 21 10 20 10 20 8 19 8 19 7 20 7 20 5 21 5" fill="#fdb02a"/>
<rect x="29" y="2" width="49" height="1" fill="#fda829"/>
<rect x="29" y="3" width="49" height="1" fill="#fd9c27"/>
<rect x="29" y="4" width="49" height="1" fill="#fd9025"/>
<rect x="29" y="5" width="49" height="1" fill="#fd8124"/>
<rect x="29" y="6" width="49" height="1" fill="#fd7222"/>
<rect x="29" y="7" width="49" height="1" fill="#fd6420"/>
<rect x="29" y="8" width="49" height="1" fill="#fc561f"/>
<rect x="29" y="9" width="49" height="1" fill="#fc481e"/>
<rect x="29" y="10" width="49" height="1" fill="#fc371d"/>
<rect x="29" y="11" width="49" height="1" fill="#fc291c"/>
<rect x="29" y="12" width="49" height="1" fill="#fc1c1c"/>
<path d="m34 5h1v5h-1z" fill="#fff"/>
<path d="m37 5h1v1h1v1h1v1h1v-3h1v5h-1v-1h-1v-1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m44 5v5h3v-1h-2v-3h2v-1h-3zm3 1v3h1v-3h-1z" fill="#fff"/>
<path d="m50 5h1v5h-1z" fill="#fff"/>
<path d="m53 5h3v1h-2v1h2v1h-2v1h2v1h-3z" fill="#fff"/>
<path d="m58 5h1v4h1v-3h1v3h1v-4h1v4h-1v1h-1v-1h-1v1h-1v-1h-1z" fill="#fff"/>
<path d="m65 5h3v1h-2v1h2v1h-2v1h2v1h-3z" fill="#fff"/>
<path d="m70 5v5h3v-1h-2v-1h2v-1h-2v-1h2v-1h-3zm3 1v1h1v-1h-1zm0 2v1h1v-1h-1z" fill="#fff"/>
</symbol>
<symbol id="button-webmention" viewBox="0 0 80 15">
<rect width="80" height="15" fill="#666"/>
<rect x="1" y="1" width="78" height="13" fill="#fff" style="paint-order:markers fill stroke"/>
<path d="m13 1v1h-1v1h-1v1h1 1v1h-1v2h-1v2h-1v-3h-1v-2h-1v2h-1v3h-1v-2h-1v-3h-1v-2h-1-1v2h1v3h1v3h1v3h1 1v-3h1v-2h1v2h1v3h1 1v-3h1v-3h1v-3h1 1v-1h-1v-1h-1v-1h-1z" fill="#610371"/>
<rect x="19" y="2" width="59" height="11" fill="#850e9a"/>
<path d="m33 5v5h3v-1h-2v-1h2v-1h-2v-1h2v-1h-3zm3 1v1h1v-1h-1zm0 2v1h1v-1h-1z" fill="#fff"/>
<path d="m28 5h3v1h-2v1h2v1h-2v1h2v1h-3z" fill="#fff"/>
<path d="m21 5h1v4h1v-3h1v3h1v-4h1v4h-1v1h-1v-1h-1v1h-1v-1h-1z" fill="#fff"/>
<path d="m39 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m51 5h1v1h1v1h1v1h1v-3h1v5h-1v-1h-1v-1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m58 5h3v1h-1v4h-1v-4h-1" fill="#fff"/>
<path d="m63 5h1v5h-1z" fill="#fff"/>
<path d="m67 5v1h2v-1zm2 1v3h1v-3zm0 3h-2v1h2zm-2 0v-3h-1v3z" fill="#fff"/>
<path d="m71 5h1v1h1v1h1v1h1v-3h1v5h-1v-1h-1v-1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m46 5h3v1h-2v1h2v1h-2v1h2v1h-3z" fill="#fff"/>
</symbol>
<symbol id="button-microformats" viewBox="0 0 80 15">
<rect width="80" height="15" fill="#666"/>
<rect x="1" y="1" width="78" height="13" fill="#fff"/>
<rect x="18" y="2" width="2" height="11" fill="#5d8f17"/>
<rect x="20" y="2" width="2" height="11" fill="#609218"/>
<rect x="22" y="2" width="2" height="11" fill="#639519"/>
<rect x="24" y="2" width="2" height="11" fill="#66981a"/>
<rect x="26" y="2" width="2" height="11" fill="#699b1b"/>
<rect x="28" y="2" width="2" height="11" fill="#6c9e1b"/>
<rect x="30" y="2" width="2" height="11" fill="#6fa11c"/>
<rect x="32" y="2" width="2" height="11" fill="#72a51d"/>
<rect x="34" y="2" width="2" height="11" fill="#76a81e"/>
<rect x="36" y="2" width="2" height="11" fill="#78aa1f"/>
<rect x="38" y="2" width="2" height="11" fill="#7cae20"/>
<rect x="40" y="2" width="2" height="11" fill="#7eb120"/>
<rect x="42" y="2" width="2" height="11" fill="#82b421"/>
<rect x="44" y="2" width="2" height="11" fill="#85b722"/>
<rect x="46" y="2" width="2" height="11" fill="#88ba23"/>
<rect x="48" y="2" width="2" height="11" fill="#8bbd24"/>
<rect x="50" y="2" width="2" height="11" fill="#8ec125"/>
<rect x="52" y="2" width="2" height="11" fill="#91c325"/>
<rect x="54" y="2" width="2" height="11" fill="#94c626"/>
<rect x="56" y="2" width="2" height="11" fill="#97ca27"/>
<rect x="58" y="2" width="2" height="11" fill="#9acd28"/>
<rect x="60" y="2" width="2" height="11" fill="#9dd029"/>
<rect x="62" y="2" width="2" height="11" fill="#a0d32a"/>
<rect x="64" y="2" width="2" height="11" fill="#a4d62b"/>
<rect x="66" y="2" width="2" height="11" fill="#a6d92b"/>
<rect x="68" y="2" width="2" height="11" fill="#a8db2c"/>
<rect x="70" y="2" width="2" height="11" fill="#acdf2d"/>
<rect x="72" y="2" width="2" height="11" fill="#b0e32e"/>
<rect x="74" y="2" width="2" height="11" fill="#b3e62f"/>
<rect x="76" y="2" width="2" height="11" fill="#b6e92f"/>
<polygon points="4 4 6 4 6 9 7 9 7 10 12 10 12 12 11 12 11 13 4 13 4 12 3 12 3 5 4 5" fill="#5c8d17"/>
<polygon points="7 3 9 3 9 6 10 6 10 7 13 7 13 9 8 9 8 8 7 8" fill="#8dc024"/>
<polygon points="10 2 13 2 13 3 14 3 14 6 11 6 11 5 10 5" fill="#a5d82b"/>
<path d="m20 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m26 5h1v5h-1z" fill="#fff"/>
<path d="m29 5h2v1h1v1h-1v-1h-2v3h2v-1h1v1h-1v1h-2v-1h-1v-3h1z" fill="#fff"/>
<path d="m33 5v5h1v-2h1v1h1v-2h-2v-1h2v-1h-3zm3 1v1h1v-1h-1zm0 3v1h1v-1h-1z" fill="#fff"/>
<path d="m39 5v1h2v-1h-2zm2 1v1 1 1h1v-1-1-1h-1zm0 3h-2v1h2v-1zm-2 0v-3h-1v3h1z" fill="#fff"/>
<path d="m43 5h3v1h-2v1h2v1h-2v2h-1z" fill="#fff"/>
<path d="m48 5v1h2v-1h-2zm2 1v1 1 1h1v-1-1-1h-1zm0 3h-2v1h2v-1zm-2 0v-3h-1v3h1z" fill="#fff"/>
<path d="m52 5v5h1v-2h1v1h1v-2h-2v-1h2v-1h-3zm3 1v1h1v-1h-1zm0 3v1h1v-1h-1z" fill="#fff"/>
<path d="m57 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m64 5v1h2v-1h-2zm2 1v1h-2v-1h-1v4h1v-2h2v2h1v-4h-1z" fill="#fff"/>
<path d="m68 5h3v1h-1v4h-1v-4h-1" fill="#fff"/>
<path d="m73 5h3v1h-3v1h2v1h1v1h-1v1h-3v-1h3v-1h-2v-1h-1v-1h1" fill="#fff"/>
</symbol>
<symbol id="button-cc" viewBox="0 0 80 15">
<rect y="0" width="80" height="15" fill="#000"/>
<rect x="1" y="1" width="78" height="13" fill="#fff"/>
<rect x="2" y="2" width="76" height="11" fill="#000"/>
<path d="m42 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m31 5h2v1h1v1h-1v-1h-2v3h2v-1h1v1h-1v1h-2v-1h-1v-3h1z" fill="#fff"/>
<path d="m37 5v1h2v-1zm2 1v3h1v-3zm0 3h-2v1h2zm-2 0v-3h-1v3z" fill="#fff"/>
<path d="m57 5v1h2v-1zm2 1v3h1v-3zm0 3h-2v1h2zm-2 0v-3h-1v3z" fill="#fff"/>
<path d="m49 5h1v1h1v1h1v-1h1v-1h1v5h-1v-3h-1v1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m70 5h3v1h-3v1h2v1h1v1h-1v1h-3v-1h3v-1h-2v-1h-1v-1h1" fill="#fff"/>
<path d="m62 5h1v1h1v1h1v1h1v-3h1v5h-1v-1h-1v-1h-1v-1h-1v3h-1z" fill="#fff"/>
<path d="m2 2v11h19.891a8.5136 8.5 0 0 0 2.1088-5.5898 8.5136 8.5 0 0 0-1.9563-5.4102h-13.119z" fill="#aaa"/>
<path d="m6.0195 2a8.5 8.5 0 0 0-2.0195 5.5 8.5 8.5 0 0 0 2.0312 5.5h12.949a8.5 8.5 0 0 0 2.0195-5.5 8.5 8.5 0 0 0-2.0312-5.5z" fill="#000"/>
<circle cx="12.5" cy="7.5" r="6.5" fill="#fff"/>
<path d="m9 5h2v1h1v1h-1v-1h-2v3h2v-1h1v1h-1v1h-2v-1h-1v-3h1z" fill="#000"/>
<path d="m14 5h2v1h1v1h-1v-1h-2v3h2v-1h1v1h-1v1h-2v-1h-1v-3h1z" fill="#000"/>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 21 KiB