Added page model, beautified code, created index page(finally)

This commit is contained in:
thematdev 2022-07-15 16:18:12 +03:00
parent 98a8fbdc0c
commit f46fd4bf72
Signed by: thematdev
GPG Key ID: D12878639B090D90
6 changed files with 325 additions and 286 deletions

View File

@ -6,6 +6,7 @@ name = "pypi"
[packages] [packages]
gunicorn = "*" gunicorn = "*"
flask = "*" flask = "*"
pydantic = "*"
[dev-packages] [dev-packages]

211
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "ceeddd812b1d235750e064b323a1270b3505e56f3a9357c569fd3757db6f5432" "sha256": "e5763a4e03fd7bbaf97329e36f64ad1722c518ac89f9ecdb8329ad8bcd8431db"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -18,19 +18,19 @@
"default": { "default": {
"click": { "click": {
"hashes": [ "hashes": [
"sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a", "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
"sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6" "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.7'",
"version": "==8.0.1" "version": "==8.1.3"
}, },
"flask": { "flask": {
"hashes": [ "hashes": [
"sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55", "sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb",
"sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9" "sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.0.1" "version": "==2.1.3"
}, },
"gunicorn": { "gunicorn": {
"hashes": [ "hashes": [
@ -40,89 +40,148 @@
"index": "pypi", "index": "pypi",
"version": "==20.1.0" "version": "==20.1.0"
}, },
"importlib-metadata": {
"hashes": [
"sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670",
"sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"
],
"markers": "python_version < '3.10'",
"version": "==4.12.0"
},
"itsdangerous": { "itsdangerous": {
"hashes": [ "hashes": [
"sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c", "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
"sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0" "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.7'",
"version": "==2.0.1" "version": "==2.1.2"
}, },
"jinja2": { "jinja2": {
"hashes": [ "hashes": [
"sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4", "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
"sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4" "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.7'",
"version": "==3.0.1" "version": "==3.1.2"
}, },
"markupsafe": { "markupsafe": {
"hashes": [ "hashes": [
"sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298", "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003",
"sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64", "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88",
"sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b", "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5",
"sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567", "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7",
"sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff", "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a",
"sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724", "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603",
"sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74", "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1",
"sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646", "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135",
"sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35", "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247",
"sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6", "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6",
"sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6", "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601",
"sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad", "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77",
"sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26", "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02",
"sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38", "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e",
"sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac", "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63",
"sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7", "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f",
"sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6", "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980",
"sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75", "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b",
"sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f", "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812",
"sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135", "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff",
"sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8", "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96",
"sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a", "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1",
"sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a", "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925",
"sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9", "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a",
"sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864", "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6",
"sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914", "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e",
"sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18", "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f",
"sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8", "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4",
"sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2", "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f",
"sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d", "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3",
"sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b", "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c",
"sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b", "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a",
"sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f", "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417",
"sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb", "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a",
"sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833", "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a",
"sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28", "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37",
"sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415", "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452",
"sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902", "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933",
"sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d", "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
"sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9", "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
"sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
"sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145",
"sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
"sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c",
"sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1",
"sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
"sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53",
"sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134",
"sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85",
"sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
"sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
"sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
"sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
"sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.7'",
"version": "==2.0.1" "version": "==2.1.1"
},
"pydantic": {
"hashes": [
"sha256:02eefd7087268b711a3ff4db528e9916ac9aa18616da7bca69c1871d0b7a091f",
"sha256:059b6c1795170809103a1538255883e1983e5b831faea6558ef873d4955b4a74",
"sha256:0bf07cab5b279859c253d26a9194a8906e6f4a210063b84b433cf90a569de0c1",
"sha256:1542636a39c4892c4f4fa6270696902acb186a9aaeac6f6cf92ce6ae2e88564b",
"sha256:177071dfc0df6248fd22b43036f936cfe2508077a72af0933d0c1fa269b18537",
"sha256:18f3e912f9ad1bdec27fb06b8198a2ccc32f201e24174cec1b3424dda605a310",
"sha256:1dd8fecbad028cd89d04a46688d2fcc14423e8a196d5b0a5c65105664901f810",
"sha256:1ed987c3ff29fff7fd8c3ea3a3ea877ad310aae2ef9889a119e22d3f2db0691a",
"sha256:447d5521575f18e18240906beadc58551e97ec98142266e521c34968c76c8761",
"sha256:494f7c8537f0c02b740c229af4cb47c0d39840b829ecdcfc93d91dcbb0779892",
"sha256:4988c0f13c42bfa9ddd2fe2f569c9d54646ce84adc5de84228cfe83396f3bd58",
"sha256:4ce9ae9e91f46c344bec3b03d6ee9612802682c1551aaf627ad24045ce090761",
"sha256:5d93d4e95eacd313d2c765ebe40d49ca9dd2ed90e5b37d0d421c597af830c195",
"sha256:61b6760b08b7c395975d893e0b814a11cf011ebb24f7d869e7118f5a339a82e1",
"sha256:72ccb318bf0c9ab97fc04c10c37683d9eea952ed526707fabf9ac5ae59b701fd",
"sha256:79b485767c13788ee314669008d01f9ef3bc05db9ea3298f6a50d3ef596a154b",
"sha256:7eb57ba90929bac0b6cc2af2373893d80ac559adda6933e562dcfb375029acee",
"sha256:8bc541a405423ce0e51c19f637050acdbdf8feca34150e0d17f675e72d119580",
"sha256:969dd06110cb780da01336b281f53e2e7eb3a482831df441fb65dd30403f4608",
"sha256:985ceb5d0a86fcaa61e45781e567a59baa0da292d5ed2e490d612d0de5796918",
"sha256:9bcf8b6e011be08fb729d110f3e22e654a50f8a826b0575c7196616780683380",
"sha256:9ce157d979f742a915b75f792dbd6aa63b8eccaf46a1005ba03aa8a986bde34a",
"sha256:9f659a5ee95c8baa2436d392267988fd0f43eb774e5eb8739252e5a7e9cf07e0",
"sha256:a4a88dcd6ff8fd47c18b3a3709a89adb39a6373f4482e04c1b765045c7e282fd",
"sha256:a955260d47f03df08acf45689bd163ed9df82c0e0124beb4251b1290fa7ae728",
"sha256:a9af62e9b5b9bc67b2a195ebc2c2662fdf498a822d62f902bf27cccb52dbbf49",
"sha256:ae72f8098acb368d877b210ebe02ba12585e77bd0db78ac04a1ee9b9f5dd2166",
"sha256:b83ba3825bc91dfa989d4eed76865e71aea3a6ca1388b59fc801ee04c4d8d0d6",
"sha256:c11951b404e08b01b151222a1cb1a9f0a860a8153ce8334149ab9199cd198131",
"sha256:c320c64dd876e45254bdd350f0179da737463eea41c43bacbee9d8c9d1021f11",
"sha256:c8098a724c2784bf03e8070993f6d46aa2eeca031f8d8a048dff277703e6e193",
"sha256:d12f96b5b64bec3f43c8e82b4aab7599d0157f11c798c9f9c528a72b9e0b339a",
"sha256:e565a785233c2d03724c4dc55464559639b1ba9ecf091288dd47ad9c629433bd",
"sha256:f0f047e11febe5c3198ed346b507e1d010330d56ad615a7e0a89fae604065a0e",
"sha256:fe4670cb32ea98ffbf5a1262f14c3e102cccd92b1869df3bb09538158ba90fe6"
],
"index": "pypi",
"version": "==1.9.1"
},
"setuptools": {
"hashes": [
"sha256:0d33c374d41c7863419fc8f6c10bfe25b7b498aa34164d135c622e52580c6b16",
"sha256:c04b44a57a6265fe34a4a444e965884716d34bae963119a76353434d6f18e450"
],
"markers": "python_version >= '3.7'",
"version": "==63.2.0"
},
"typing-extensions": {
"hashes": [
"sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02",
"sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"
],
"markers": "python_version >= '3.7'",
"version": "==4.3.0"
}, },
"werkzeug": { "werkzeug": {
"hashes": [ "hashes": [
"sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42", "sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6",
"sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8" "sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.7'",
"version": "==2.0.1" "version": "==2.1.2"
},
"zipp": {
"hashes": [
"sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2",
"sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"
],
"markers": "python_version >= '3.7'",
"version": "==3.8.1"
} }
}, },
"develop": {} "develop": {}

View File

@ -1,9 +1,9 @@
from flask import Flask, url_for, render_template, abort from flask import Flask, url_for, render_template, abort
import os import os
import json
from app.config import PANDOC_LINK, PANDOC_PATH, WHITELIST_PATH from app.config import PANDOC_LINK, PANDOC_PATH, WHITELIST_PATH
from app.hash_manager import hash_file_sha512 from app.hash_manager import hash_file_sha512
import subprocess from app.page_model import WikiPage
from typing import List
app = Flask(__name__) app = Flask(__name__)
@ -13,7 +13,24 @@ def override_url_for():
return dict(url_for=dated_url_for) return dict(url_for=dated_url_for)
#TODO: make instead of datetime hash of commit def get_all_names():
whitelist = WHITELIST_PATH
with open(whitelist, 'r') as f:
lines = f.read().splitlines()
return lines
def get_page(name: str) -> WikiPage:
if name not in get_all_names():
raise Exception("Page doesn't exist!")
path = f'{PANDOC_PATH}/{name}'
with open(f'{path}/config.json', 'r') as f:
page = WikiPage.parse_raw(f.read())
return page
def get_all_pages() -> List[WikiPage]:
return [get_page(name) for name in get_all_names()]
def dated_url_for(endpoint, **values): def dated_url_for(endpoint, **values):
@ -25,53 +42,36 @@ def dated_url_for(endpoint, **values):
return url_for(endpoint, **values) return url_for(endpoint, **values)
def render_page(page): def render_page(page: WikiPage):
path = f'{PANDOC_PATH}/{page}' if page.name not in get_all_names():
whitelist = WHITELIST_PATH
with open(whitelist, 'r') as f:
lines = f.read().splitlines()
if page not in lines:
raise Exception("Page doesn't exist!")
if not os.path.exists(f'{path}'):
raise Exception("Page doesn't exist!") raise Exception("Page doesn't exist!")
in_filename = f'{path}/main.md' in_filename = page.get_file('main.md')
out_filename = f'{path}/render.html' out_filename = page.get_file('render.html')
os.system(f'pandoc {in_filename} --to html --mathjax --output {out_filename}') os.system(f'pandoc {in_filename} --to html --mathjax --output {out_filename}')
print('Creating lock file') print('Creating lock file')
os.system(f'echo {hash_file_sha512(in_filename)} > {out_filename}.lock') os.system(f'echo {hash_file_sha512(in_filename)} > {out_filename}.lock')
@app.route(f'/{PANDOC_LINK}/<page>') @app.route(f'/{PANDOC_LINK}/<name>')
def get_pandoc_page(page): def get_pandoc_page(name: str):
path = f'{PANDOC_PATH}/{page}' page = get_page(name)
whitelist = WHITELIST_PATH if not os.path.exists(page.get_file('render.html')) or not os.path.exists(page.get_file('render.html.lock')):
with open(whitelist, 'r') as f: print(f'Rendered page or lockfile for {name} does not exist! Rendering {name}')
lines = f.read().splitlines()
if page not in lines:
print(f'Access to page not in list {page}')
return 'This page does not exist'
if not os.path.exists(f'{path}'):
# TODO: Add 404 handler
return 'This page does not exist'
with open(f'{path}/config.json') as f:
data = json.loads(f.read())
if not os.path.exists(f'{path}/render.html') or not os.path.exists(f'{path}/render.html.lock'):
print(f'Rendered page or lockfile for {page} does not exist! Rendering {page}')
render_page(page) render_page(page)
else: else:
with open(f'{path}/render.html.lock', 'r') as f: with open(page.get_file('render.html.lock'), 'r') as f:
rendered_hash = f.read().strip() rendered_hash = f.read().strip()
current_hash = hash_file_sha512(f'{path}/main.md') current_hash = hash_file_sha512(page.get_file('main.md'))
if rendered_hash != current_hash: if rendered_hash != current_hash:
print(f'CURRENT: {current_hash}, RENDERED: {rendered_hash}') print(f'CURRENT: {current_hash}, RENDERED: {rendered_hash}')
print(f'Integrity test failed, rendering {page}!') print(f'Integrity test failed, rendering {name}!')
render_page(page) render_page(page)
template = data['template'] template = page.template
with open(f'{path}/render.html', 'r') as f: with open(page.get_file('render.html'), 'r') as f:
inserted = f.read() inserted = f.read()
return render_template(template, markdown=inserted, config=data) return render_template(template, markdown=inserted, config=page)
@app.route('/') @app.route('/')
def index(): def index():
return render_template('index.html') return render_template('index.html', pages=get_all_pages(), PANDOC_LINK=PANDOC_LINK)

14
app/page_model.py Normal file
View File

@ -0,0 +1,14 @@
from pydantic import BaseModel
from typing import List
from app.config import PANDOC_PATH
class WikiPage(BaseModel):
name: str
title: str
credits: List[str]
standalone: bool
template: str
def get_file(self, filename: str) -> str:
return f'{PANDOC_PATH}/{self.name}/{filename}'

View File

@ -40,7 +40,7 @@ a {
/* BEGIN ALGORITHMICA OLD STYLE */ /* BEGIN ALGORITHMICA OLD STYLE */
body { .pagebody {
/* color: #444; */ /* color: #444; */
font-family: "Times New Roman", Times, "Tinos", serif; font-family: "Times New Roman", Times, "Tinos", serif;
font-size: 16px; font-size: 16px;
@ -53,7 +53,7 @@ body {
padding-bottom: 25px; padding-bottom: 25px;
} }
.credits { .pagebody .credits {
font-size: 14px; font-size: 14px;
margin: 25px 10px -40px 15px; margin: 25px 10px -40px 15px;
padding: 16px 50px 0 50px; padding: 16px 50px 0 50px;
@ -62,26 +62,26 @@ body {
color: black; color: black;
} }
.credits table { .pagebody .credits table {
border: none; border: none;
margin-left: 46px; margin-left: 46px;
margin-bottom: 10px; margin-bottom: 10px;
} }
.credits table td{ .pagebody .credits table td{
border: none; border: none;
padding: 0; padding: 0;
padding-left: 1.5em; padding-left: 1.5em;
} }
#header { .pagebody #header {
height: 55px; height: 55px;
margin-top: -8px; margin-top: -8px;
margin-bottom: 20px; margin-bottom: 20px;
border-bottom: 1px solid #666; border-bottom: 1px solid #666;
} }
#links { .pagebody #links {
display: inline-block; display: inline-block;
text-align: right; text-align: right;
font-size: 16px; font-size: 16px;
@ -90,27 +90,27 @@ body {
margin-right: 12px; margin-right: 12px;
} }
#links a { .pagebody #links a {
margin-left: 20px; margin-left: 20px;
} }
#header a:hover { .pagebody #header a:hover {
color: #0645ad!important; color: #0645ad!important;
} }
#header a { .pagebody #header a {
color: #111 !important; color: #111 !important;
display: inline-block; display: inline-block;
} }
#logo { .pagebody #logo {
margin-top: 10px; margin-top: 10px;
font-size: 22px; font-size: 22px;
height: 0; height: 0;
font-family: 'Garamond', serif; font-family: 'Garamond', serif;
} }
.contents { .pagebody .contents {
position: inline-block; position: inline-block;
float: left; float: left;
position: relative; position: relative;
@ -119,13 +119,13 @@ body {
text-align: left; text-align: left;
} }
.contents ul { .pagebody .contents ul {
padding-left: 22px; padding-left: 22px;
margin-top: 10px; margin-top: 10px;
list-style-type: none; list-style-type: none;
} }
.contents li { .pagebody .contents li {
font-size: 8px; font-size: 8px;
color: lightgrey; color: lightgrey;
font-family: 'Open Sans', sans; font-family: 'Open Sans', sans;
@ -135,16 +135,16 @@ body {
white-space: pre-line; white-space: pre-line;
} }
.contents li:hover { .pagebody .contents li:hover {
color: black; color: black;
} }
.contents li:first-letter { .pagebody .contents li:first-letter {
font-size: 13px; font-size: 13px;
height: 0; height: 0;
} }
.contents a { .pagebody .contents a {
font-family: "Times New Roman", Times, "Tinos", serif; font-family: "Times New Roman", Times, "Tinos", serif;
font-size: 16px; font-size: 16px;
line-height: 1em; line-height: 1em;
@ -152,16 +152,16 @@ body {
width: 252px; width: 252px;
} }
.contents a:first-letter { .pagebody .contents a:first-letter {
font-size: 16px; /* the only way to fix */ font-size: 16px; /* the only way to fix */
} }
.contents a:after { .pagebody .contents a:after {
content: "\A"; content: "\A";
white-space: pre; white-space: pre;
} }
.contents li:before { .pagebody .contents li:before {
content: '•'; content: '•';
display: inline-block; display: inline-block;
position: absolute; position: absolute;
@ -171,45 +171,45 @@ body {
font-size: 18px; font-size: 18px;
} }
a { .pagebody a {
color: #0645ad; color: #0645ad;
text-decoration: none; text-decoration: none;
} }
a:visited { .pagebody a:visited {
color: #0b0080; color: #0b0080;
} }
a:hover { .pagebody a:hover {
color: #06e; color: #06e;
} }
a:active { .pagebody a:active {
color: #faa700; color: #faa700;
} }
a:focus { .pagebody a:focus {
outline: thin dotted; outline: thin dotted;
} }
p { .pagebody p {
margin: 0.5em 0; margin: 0.5em 0;
} }
img { .pagebody img {
max-width: 100%; max-width: 100%;
} }
.title { .pagebody .title {
display: none; display: none;
} }
h1 { .pagebody h1 {
text-align: center; text-align: center;
margin-bottom: 0.8em !important; margin-bottom: 0.8em !important;
} }
h1, h2, h3, h4, h5, h6 { .pagebody h1, h2, h3, h4, h5, h6 {
font-family: 'Garamond', serif; font-family: 'Garamond', serif;
color: #111; color: #111;
line-height: 125%; line-height: 125%;
@ -218,54 +218,54 @@ h1, h2, h3, h4, h5, h6 {
font-weight: normal; font-weight: normal;
} }
h2, h3 { .pagebody h2, h3 {
padding-bottom: 5px; padding-bottom: 5px;
border-bottom: 1px solid #eaecef; border-bottom: 1px solid #eaecef;
} }
.contents h2, .contents h3 { .pagebody .contents h2, .contents h3 {
padding-bottom: 0; padding-bottom: 0;
border-bottom: none; border-bottom: none;
margin-top: 5px; margin-top: 5px;
} }
h4, h5, h6 { .pagebody h4, h5, h6 {
font-weight: bold; font-weight: bold;
} }
h1 { .pagebody h1 {
font-size: 2.5em; font-size: 2.5em;
margin-top: 0.8em; margin-top: 0.8em;
} }
h2 { .pagebody h2 {
font-size: 2em; font-size: 2em;
} }
h3 { .pagebody h3 {
font-size: 1.5em; font-size: 1.5em;
} }
h4 { .pagebody h4 {
font-size: 1.2em; font-size: 1.2em;
} }
h5 { .pagebody h5 {
font-size: 1em; font-size: 1em;
} }
h6 { .pagebody h6 {
font-size: 0.9em; font-size: 0.9em;
} }
blockquote { .pagebody blockquote {
color: #666666; color: #666666;
margin: 0; margin: 0;
padding-left: 1em; padding-left: 1em;
border-left: 0.5em #EEE solid; border-left: 0.5em #EEE solid;
} }
hr { .pagebody hr {
display: block; display: block;
width: 100%; width: 100%;
height: 0px; height: 0px;
@ -275,101 +275,101 @@ hr {
clear: both; clear: both;
} }
pre, code, kbd, samp { .pagebody pre, code, kbd, samp {
color: #000; color: #000;
font-family: 'Inconsolata', monospace; font-family: 'Inconsolata', monospace;
} }
pre { .pagebody pre {
white-space: pre; white-space: pre;
white-space: pre-wrap; white-space: pre-wrap;
word-wrap: break-word; word-wrap: break-word;
} }
b, strong { .pagebody b, strong {
font-weight: bold; font-weight: bold;
} }
dfn { .pagebody dfn {
font-style: italic; font-style: italic;
} }
ins { .pagebody ins {
background: #ff9; background: #ff9;
color: #000; color: #000;
text-decoration: none; text-decoration: none;
} }
mark { .pagebody mark {
background: #ff0; background: #ff0;
color: #000; color: #000;
font-style: italic; font-style: italic;
font-weight: bold; font-weight: bold;
} }
sub, sup { .pagebody sub, sup {
font-size: 75%; font-size: 75%;
line-height: 0; line-height: 0;
position: relative; position: relative;
vertical-align: baseline; vertical-align: baseline;
} }
sup { .pagebody sup {
top: -0.5em; top: -0.5em;
} }
sub { .pagebody sub {
bottom: -0.25em; bottom: -0.25em;
} }
ul, ol { .pagebody ul, ol {
margin: 1em 0; margin: 1em 0;
padding: 0 0 0 2em; padding: 0 0 0 2em;
} }
li p:last-child { .pagebody li p:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
li ul { .pagebody li ul {
padding-left: 18px; padding-left: 18px;
padding-top: 1px; padding-top: 1px;
} }
ul ul, ol ol { .pagebody ul ul, ol ol {
margin: .3em 0; margin: .3em 0;
} }
dl { .pagebody dl {
margin-bottom: 1em; margin-bottom: 1em;
} }
dt { .pagebody dt {
font-weight: bold; font-weight: bold;
margin-bottom: .8em; margin-bottom: .8em;
} }
dd { .pagebody dd {
margin: 0 0 .8em 2em; margin: 0 0 .8em 2em;
} }
dd:last-child { .pagebody dd:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
img { .pagebody img {
border: 0; border: 0;
-ms-interpolation-mode: bicubic; -ms-interpolation-mode: bicubic;
vertical-align: middle; vertical-align: middle;
} }
figure { .pagebody figure {
display: block; display: block;
text-align: center; text-align: center;
margin: 1em 0; margin: 1em 0;
} }
img { .pagebody img {
border: none; border: none;
margin: auto; margin: auto;
display: block; display: block;
@ -377,13 +377,13 @@ img {
max-height: 320px; max-height: 320px;
} }
figcaption { .pagebody figcaption {
font-size: 0.8em; font-size: 0.8em;
font-style: italic; font-style: italic;
margin: 0 0 .8em; margin: 0 0 .8em;
} }
table { .pagebody table {
margin-bottom: 2em; margin-bottom: 2em;
border-bottom: 1px solid #ddd; border-bottom: 1px solid #ddd;
border-right: 1px solid #ddd; border-right: 1px solid #ddd;
@ -391,21 +391,21 @@ table {
border-collapse: collapse; border-collapse: collapse;
} }
table th { .pagebody table th {
padding: .2em 1em; padding: .2em 1em;
background-color: #eee; background-color: #eee;
border-top: 1px solid #ddd; border-top: 1px solid #ddd;
border-left: 1px solid #ddd; border-left: 1px solid #ddd;
} }
table td { .pagebody table td {
padding: .2em 1em; padding: .2em 1em;
border-top: 1px solid #ddd; border-top: 1px solid #ddd;
border-left: 1px solid #ddd; border-left: 1px solid #ddd;
vertical-align: top; vertical-align: top;
} }
.author { .pagebody .author {
display: block; display: block;
width: 100%; width: 100%;
text-align: right; text-align: right;
@ -417,7 +417,7 @@ table td {
font-size: 0.8em; font-size: 0.8em;
} }
code:not([class]) { .pagebody code:not([class]) {
border: 1px solid #ddd !important; border: 1px solid #ddd !important;
background-color: #f8f8f8 !important; background-color: #f8f8f8 !important;
border-radius: 3px !important; border-radius: 3px !important;
@ -426,7 +426,7 @@ code:not([class]) {
font-size: 0.85em; font-size: 0.85em;
} }
pre { .pagebody pre {
border: 1px solid #ddd !important; border: 1px solid #ddd !important;
background-color: #f8f8f8 !important; background-color: #f8f8f8 !important;
border-radius: 3px !important; border-radius: 3px !important;
@ -436,7 +436,7 @@ pre {
} }
@media print { @media print {
body { .pagebody {
font-size: 12pt; font-size: 12pt;
width: 190mm; width: 190mm;
margin: 0; margin: 0;
@ -449,11 +449,11 @@ pre {
display: none; display: none;
} }
pre, ul, ol { .pagebody pre, ul, ol {
page-break-inside: avoid; page-break-inside: avoid;
} }
h1::after, h2::after, h3::after { .pagebody h1::after, h2::after, h3::after {
/* page-break-after: avoid; */ /* page-break-after: avoid; */
content: ""; content: "";
display: block; display: block;
@ -470,7 +470,7 @@ pre {
} }
*/ */
a, a:visited { .pagebody a, a:visited {
text-decoration: underline; text-decoration: underline;
} }
@ -480,68 +480,25 @@ pre {
} }
*/ */
p, h2, h3 { .pagebody p, h2, h3 {
orphans: 3; orphans: 3;
widows: 3; widows: 3;
} }
} }
/* .pagebody a[href^='https://neerc.ifmo.ru']:before {
a[href^='http://sereja.me']:before {
content: url('http://sereja.me/favicon.ico');
margin-right: 4px;
}
*/
a[href^='http://e-maxx.ru']:before {
content: "";
display: inline-block;
position: relative;
top: 4px;
width: 20px;
height: 20px;
background: url('http://e-maxx.ru/favicon.ico') no-repeat;
background-size: 18px;
}
/*
a[href^='https://algorithmica.org']:before {
content: "";
display: inline-block;
position: relative;
top: 4px;
width: 20px;
height: 20px;
background: url('https://algorithmica.org/favicon.ico') no-repeat;
background-size: 18px;
}
*/
/* https://habrahabr.ru/favicon.ico */
a[href^='https://neerc.ifmo.ru']:before {
content: url('https://neerc.ifmo.ru/favicon.ico'); content: url('https://neerc.ifmo.ru/favicon.ico');
margin-right: 4px; margin-right: 4px;
position: relative; position: relative;
top: 4px; top: 4px;
} }
a[href^='https://www.youtube.com']:before { .pagebody a[href^='https://codeforces.com']:before {
content: url('https://www.youtube.com/favicon.ico');
margin-right: 4px;
}
a[href^='https://codeforces.com']:before {
content: url('http://codeforces.com/favicon.ico'); content: url('http://codeforces.com/favicon.ico');
margin-right: 4px; margin-right: 4px;
} }
a[href^='https://www.topcoder.com/']:before { .pagebody a[href=''] {
content: url('https://s3.amazonaws.com/app.topcoder.com/favicon.ico');
margin-right: 4px;
}
a[href=''] {
color: black; color: black;
cursor: default; cursor: default;
} }
@ -550,32 +507,29 @@ a[href=''] {
/* BEGIN PANDOC EMBEDDED STYLE FOR CODE */ /* BEGIN PANDOC EMBEDDED STYLE FOR CODE */
code{white-space: pre-wrap;} .pagebody code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;} .pagebody span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;} .pagebody span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;} .pagebody div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} .pagebody div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;} .pagebody ul.task-list{list-style: none;}
pre > code.sourceCode { white-space: pre; position: relative; } .pagebody pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } .pagebody pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; } .pagebody pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; } .pagebody .sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; } .pagebody code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; } .pagebody div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; } .pagebody pre.sourceCode { margin: 0; }
@media screen { @media screen {
div.sourceCode { overflow: auto; } .pagebody div.sourceCode { overflow: auto; }
} }
@media print { @media print {
pre > code.sourceCode { white-space: pre-wrap; } .pagebody pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } .pagebody pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
} }
pre.numberSource code .pagebody pre.numberSource code { counter-reset: source-line 0; }
{ counter-reset: source-line 0; } .pagebody pre.numberSource code > span { position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span .pagebody pre.numberSource code > span > a:first-child::before { content: counter(source-line);
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline; position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block; border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none; -webkit-touch-callout: none; -webkit-user-select: none;
@ -584,40 +538,39 @@ pre.numberSource code > span > a:first-child::before
padding: 0 4px; width: 4em; padding: 0 4px; width: 4em;
color: #aaaaaa; color: #aaaaaa;
} }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; } .pagebody pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode .pagebody div.sourceCode { }
{ }
@media screen { @media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } .pagebody pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
} }
code span.al { color: #ff0000; font-weight: bold; } /* Alert */ .pagebody code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */ .pagebody code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */ .pagebody code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */ .pagebody code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */ .pagebody code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */ .pagebody code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */ .pagebody code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */ .pagebody code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */ .pagebody code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */ .pagebody code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */ .pagebody code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */ .pagebody code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */ .pagebody code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */ .pagebody code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */ .pagebody code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */ .pagebody code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */ .pagebody code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */ .pagebody code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */ .pagebody code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */ .pagebody code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */ .pagebody code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */ .pagebody code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */ .pagebody code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */ .pagebody code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */ .pagebody code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */ .pagebody code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */ .pagebody code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */ .pagebody code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */ .pagebody code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
/* END PANDOC EMBEDDED STYLE FOR CODE */ /* END PANDOC EMBEDDED STYLE FOR CODE */

View File

@ -1 +1,13 @@
Wiki index page <!DOCTYPE html>
<html lang="ru">
<head>
</head>
<body>
Статьи:
{% for page in pages %}
<br>
<a href="/{{PANDOC_LINK}}/{{page.name}}">{{page.title}}</a>(Авторы: {{', '.join(page.credits)}})
{% endfor %}
</body>
</html>