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]
gunicorn = "*"
flask = "*"
pydantic = "*"
[dev-packages]

211
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "ceeddd812b1d235750e064b323a1270b3505e56f3a9357c569fd3757db6f5432"
"sha256": "e5763a4e03fd7bbaf97329e36f64ad1722c518ac89f9ecdb8329ad8bcd8431db"
},
"pipfile-spec": 6,
"requires": {
@ -18,19 +18,19 @@
"default": {
"click": {
"hashes": [
"sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
"sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
"sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
"sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
],
"markers": "python_version >= '3.6'",
"version": "==8.0.1"
"markers": "python_version >= '3.7'",
"version": "==8.1.3"
},
"flask": {
"hashes": [
"sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55",
"sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9"
"sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb",
"sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"
],
"index": "pypi",
"version": "==2.0.1"
"version": "==2.1.3"
},
"gunicorn": {
"hashes": [
@ -40,89 +40,148 @@
"index": "pypi",
"version": "==20.1.0"
},
"importlib-metadata": {
"hashes": [
"sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670",
"sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"
],
"markers": "python_version < '3.10'",
"version": "==4.12.0"
},
"itsdangerous": {
"hashes": [
"sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
"sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
"sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
"sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.1"
"markers": "python_version >= '3.7'",
"version": "==2.1.2"
},
"jinja2": {
"hashes": [
"sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
"sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
"sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
"sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
],
"markers": "python_version >= '3.6'",
"version": "==3.0.1"
"markers": "python_version >= '3.7'",
"version": "==3.1.2"
},
"markupsafe": {
"hashes": [
"sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
"sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
"sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
"sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
"sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
"sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724",
"sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
"sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646",
"sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
"sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6",
"sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6",
"sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad",
"sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
"sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38",
"sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac",
"sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
"sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6",
"sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
"sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
"sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
"sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
"sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a",
"sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
"sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9",
"sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864",
"sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
"sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
"sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
"sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
"sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
"sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b",
"sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
"sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
"sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
"sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
"sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28",
"sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
"sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
"sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d",
"sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
"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"
"sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003",
"sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88",
"sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5",
"sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7",
"sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a",
"sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603",
"sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1",
"sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135",
"sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247",
"sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6",
"sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601",
"sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77",
"sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02",
"sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e",
"sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63",
"sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f",
"sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980",
"sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b",
"sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812",
"sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff",
"sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96",
"sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1",
"sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925",
"sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a",
"sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6",
"sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e",
"sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f",
"sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4",
"sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f",
"sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3",
"sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c",
"sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a",
"sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417",
"sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a",
"sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a",
"sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37",
"sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452",
"sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933",
"sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
"sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.1"
"markers": "python_version >= '3.7'",
"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": {
"hashes": [
"sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42",
"sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"
"sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6",
"sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.1"
"markers": "python_version >= '3.7'",
"version": "==2.1.2"
},
"zipp": {
"hashes": [
"sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2",
"sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"
],
"markers": "python_version >= '3.7'",
"version": "==3.8.1"
}
},
"develop": {}

View File

@ -1,9 +1,9 @@
from flask import Flask, url_for, render_template, abort
import os
import json
from app.config import PANDOC_LINK, PANDOC_PATH, WHITELIST_PATH
from app.hash_manager import hash_file_sha512
import subprocess
from app.page_model import WikiPage
from typing import List
app = Flask(__name__)
@ -13,7 +13,24 @@ def override_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):
@ -25,53 +42,36 @@ def dated_url_for(endpoint, **values):
return url_for(endpoint, **values)
def render_page(page):
path = f'{PANDOC_PATH}/{page}'
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}'):
def render_page(page: WikiPage):
if page.name not in get_all_names():
raise Exception("Page doesn't exist!")
in_filename = f'{path}/main.md'
out_filename = f'{path}/render.html'
in_filename = page.get_file('main.md')
out_filename = page.get_file('render.html')
os.system(f'pandoc {in_filename} --to html --mathjax --output {out_filename}')
print('Creating lock file')
os.system(f'echo {hash_file_sha512(in_filename)} > {out_filename}.lock')
@app.route(f'/{PANDOC_LINK}/<page>')
def get_pandoc_page(page):
path = f'{PANDOC_PATH}/{page}'
whitelist = WHITELIST_PATH
with open(whitelist, 'r') as f:
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}')
@app.route(f'/{PANDOC_LINK}/<name>')
def get_pandoc_page(name: str):
page = get_page(name)
if not os.path.exists(page.get_file('render.html')) or not os.path.exists(page.get_file('render.html.lock')):
print(f'Rendered page or lockfile for {name} does not exist! Rendering {name}')
render_page(page)
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()
current_hash = hash_file_sha512(f'{path}/main.md')
current_hash = hash_file_sha512(page.get_file('main.md'))
if rendered_hash != current_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)
template = data['template']
with open(f'{path}/render.html', 'r') as f:
template = page.template
with open(page.get_file('render.html'), 'r') as f:
inserted = f.read()
return render_template(template, markdown=inserted, config=data)
return render_template(template, markdown=inserted, config=page)
@app.route('/')
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 */
body {
.pagebody {
/* color: #444; */
font-family: "Times New Roman", Times, "Tinos", serif;
font-size: 16px;
@ -53,7 +53,7 @@ body {
padding-bottom: 25px;
}
.credits {
.pagebody .credits {
font-size: 14px;
margin: 25px 10px -40px 15px;
padding: 16px 50px 0 50px;
@ -62,26 +62,26 @@ body {
color: black;
}
.credits table {
.pagebody .credits table {
border: none;
margin-left: 46px;
margin-bottom: 10px;
}
.credits table td{
.pagebody .credits table td{
border: none;
padding: 0;
padding-left: 1.5em;
}
#header {
.pagebody #header {
height: 55px;
margin-top: -8px;
margin-bottom: 20px;
border-bottom: 1px solid #666;
}
#links {
.pagebody #links {
display: inline-block;
text-align: right;
font-size: 16px;
@ -90,27 +90,27 @@ body {
margin-right: 12px;
}
#links a {
.pagebody #links a {
margin-left: 20px;
}
#header a:hover {
.pagebody #header a:hover {
color: #0645ad!important;
}
#header a {
.pagebody #header a {
color: #111 !important;
display: inline-block;
}
#logo {
.pagebody #logo {
margin-top: 10px;
font-size: 22px;
height: 0;
font-family: 'Garamond', serif;
}
.contents {
.pagebody .contents {
position: inline-block;
float: left;
position: relative;
@ -119,13 +119,13 @@ body {
text-align: left;
}
.contents ul {
.pagebody .contents ul {
padding-left: 22px;
margin-top: 10px;
list-style-type: none;
}
.contents li {
.pagebody .contents li {
font-size: 8px;
color: lightgrey;
font-family: 'Open Sans', sans;
@ -135,16 +135,16 @@ body {
white-space: pre-line;
}
.contents li:hover {
.pagebody .contents li:hover {
color: black;
}
.contents li:first-letter {
.pagebody .contents li:first-letter {
font-size: 13px;
height: 0;
}
.contents a {
.pagebody .contents a {
font-family: "Times New Roman", Times, "Tinos", serif;
font-size: 16px;
line-height: 1em;
@ -152,16 +152,16 @@ body {
width: 252px;
}
.contents a:first-letter {
.pagebody .contents a:first-letter {
font-size: 16px; /* the only way to fix */
}
.contents a:after {
.pagebody .contents a:after {
content: "\A";
white-space: pre;
}
.contents li:before {
.pagebody .contents li:before {
content: '•';
display: inline-block;
position: absolute;
@ -171,45 +171,45 @@ body {
font-size: 18px;
}
a {
.pagebody a {
color: #0645ad;
text-decoration: none;
}
a:visited {
.pagebody a:visited {
color: #0b0080;
}
a:hover {
.pagebody a:hover {
color: #06e;
}
a:active {
.pagebody a:active {
color: #faa700;
}
a:focus {
.pagebody a:focus {
outline: thin dotted;
}
p {
.pagebody p {
margin: 0.5em 0;
}
img {
.pagebody img {
max-width: 100%;
}
.title {
.pagebody .title {
display: none;
}
h1 {
.pagebody h1 {
text-align: center;
margin-bottom: 0.8em !important;
}
h1, h2, h3, h4, h5, h6 {
.pagebody h1, h2, h3, h4, h5, h6 {
font-family: 'Garamond', serif;
color: #111;
line-height: 125%;
@ -218,54 +218,54 @@ h1, h2, h3, h4, h5, h6 {
font-weight: normal;
}
h2, h3 {
.pagebody h2, h3 {
padding-bottom: 5px;
border-bottom: 1px solid #eaecef;
}
.contents h2, .contents h3 {
.pagebody .contents h2, .contents h3 {
padding-bottom: 0;
border-bottom: none;
margin-top: 5px;
}
h4, h5, h6 {
.pagebody h4, h5, h6 {
font-weight: bold;
}
h1 {
.pagebody h1 {
font-size: 2.5em;
margin-top: 0.8em;
}
h2 {
.pagebody h2 {
font-size: 2em;
}
h3 {
.pagebody h3 {
font-size: 1.5em;
}
h4 {
.pagebody h4 {
font-size: 1.2em;
}
h5 {
.pagebody h5 {
font-size: 1em;
}
h6 {
.pagebody h6 {
font-size: 0.9em;
}
blockquote {
.pagebody blockquote {
color: #666666;
margin: 0;
padding-left: 1em;
border-left: 0.5em #EEE solid;
}
hr {
.pagebody hr {
display: block;
width: 100%;
height: 0px;
@ -275,101 +275,101 @@ hr {
clear: both;
}
pre, code, kbd, samp {
.pagebody pre, code, kbd, samp {
color: #000;
font-family: 'Inconsolata', monospace;
}
pre {
.pagebody pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
b, strong {
.pagebody b, strong {
font-weight: bold;
}
dfn {
.pagebody dfn {
font-style: italic;
}
ins {
.pagebody ins {
background: #ff9;
color: #000;
text-decoration: none;
}
mark {
.pagebody mark {
background: #ff0;
color: #000;
font-style: italic;
font-weight: bold;
}
sub, sup {
.pagebody sub, sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
.pagebody sup {
top: -0.5em;
}
sub {
.pagebody sub {
bottom: -0.25em;
}
ul, ol {
.pagebody ul, ol {
margin: 1em 0;
padding: 0 0 0 2em;
}
li p:last-child {
.pagebody li p:last-child {
margin-bottom: 0;
}
li ul {
.pagebody li ul {
padding-left: 18px;
padding-top: 1px;
}
ul ul, ol ol {
.pagebody ul ul, ol ol {
margin: .3em 0;
}
dl {
.pagebody dl {
margin-bottom: 1em;
}
dt {
.pagebody dt {
font-weight: bold;
margin-bottom: .8em;
}
dd {
.pagebody dd {
margin: 0 0 .8em 2em;
}
dd:last-child {
.pagebody dd:last-child {
margin-bottom: 0;
}
img {
.pagebody img {
border: 0;
-ms-interpolation-mode: bicubic;
vertical-align: middle;
}
figure {
.pagebody figure {
display: block;
text-align: center;
margin: 1em 0;
}
img {
.pagebody img {
border: none;
margin: auto;
display: block;
@ -377,13 +377,13 @@ img {
max-height: 320px;
}
figcaption {
.pagebody figcaption {
font-size: 0.8em;
font-style: italic;
margin: 0 0 .8em;
}
table {
.pagebody table {
margin-bottom: 2em;
border-bottom: 1px solid #ddd;
border-right: 1px solid #ddd;
@ -391,21 +391,21 @@ table {
border-collapse: collapse;
}
table th {
.pagebody table th {
padding: .2em 1em;
background-color: #eee;
border-top: 1px solid #ddd;
border-left: 1px solid #ddd;
}
table td {
.pagebody table td {
padding: .2em 1em;
border-top: 1px solid #ddd;
border-left: 1px solid #ddd;
vertical-align: top;
}
.author {
.pagebody .author {
display: block;
width: 100%;
text-align: right;
@ -417,7 +417,7 @@ table td {
font-size: 0.8em;
}
code:not([class]) {
.pagebody code:not([class]) {
border: 1px solid #ddd !important;
background-color: #f8f8f8 !important;
border-radius: 3px !important;
@ -426,7 +426,7 @@ code:not([class]) {
font-size: 0.85em;
}
pre {
.pagebody pre {
border: 1px solid #ddd !important;
background-color: #f8f8f8 !important;
border-radius: 3px !important;
@ -436,7 +436,7 @@ pre {
}
@media print {
body {
.pagebody {
font-size: 12pt;
width: 190mm;
margin: 0;
@ -449,11 +449,11 @@ pre {
display: none;
}
pre, ul, ol {
.pagebody pre, ul, ol {
page-break-inside: avoid;
}
h1::after, h2::after, h3::after {
.pagebody h1::after, h2::after, h3::after {
/* page-break-after: avoid; */
content: "";
display: block;
@ -470,7 +470,7 @@ pre {
}
*/
a, a:visited {
.pagebody a, a:visited {
text-decoration: underline;
}
@ -480,68 +480,25 @@ pre {
}
*/
p, h2, h3 {
.pagebody p, h2, h3 {
orphans: 3;
widows: 3;
}
}
/*
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 {
.pagebody a[href^='https://neerc.ifmo.ru']:before {
content: url('https://neerc.ifmo.ru/favicon.ico');
margin-right: 4px;
position: relative;
top: 4px;
}
a[href^='https://www.youtube.com']:before {
content: url('https://www.youtube.com/favicon.ico');
margin-right: 4px;
}
a[href^='https://codeforces.com']:before {
.pagebody a[href^='https://codeforces.com']:before {
content: url('http://codeforces.com/favicon.ico');
margin-right: 4px;
}
a[href^='https://www.topcoder.com/']:before {
content: url('https://s3.amazonaws.com/app.topcoder.com/favicon.ico');
margin-right: 4px;
}
a[href=''] {
.pagebody a[href=''] {
color: black;
cursor: default;
}
@ -550,32 +507,29 @@ a[href=''] {
/* BEGIN PANDOC EMBEDDED STYLE FOR CODE */
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
.pagebody code{white-space: pre-wrap;}
.pagebody span.smallcaps{font-variant: small-caps;}
.pagebody span.underline{text-decoration: underline;}
.pagebody div.column{display: inline-block; vertical-align: top; width: 50%;}
.pagebody div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
.pagebody ul.task-list{list-style: none;}
.pagebody pre > code.sourceCode { white-space: pre; position: relative; }
.pagebody pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
.pagebody pre > code.sourceCode > span:empty { height: 1.2em; }
.pagebody .sourceCode { overflow: visible; }
.pagebody code.sourceCode > span { color: inherit; text-decoration: inherit; }
.pagebody div.sourceCode { margin: 1em 0; }
.pagebody pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
.pagebody div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
.pagebody pre > code.sourceCode { white-space: pre-wrap; }
.pagebody pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
.pagebody pre.numberSource code { counter-reset: source-line 0; }
.pagebody pre.numberSource code > span { position: relative; left: -4em; counter-increment: source-line; }
.pagebody pre.numberSource code > span > a:first-child::before { content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-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;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
.pagebody pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
.pagebody div.sourceCode { }
@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 */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
.pagebody code span.al { color: #ff0000; font-weight: bold; } /* Alert */
.pagebody code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
.pagebody code span.at { color: #7d9029; } /* Attribute */
.pagebody code span.bn { color: #40a070; } /* BaseN */
.pagebody code span.bu { } /* BuiltIn */
.pagebody code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
.pagebody code span.ch { color: #4070a0; } /* Char */
.pagebody code span.cn { color: #880000; } /* Constant */
.pagebody code span.co { color: #60a0b0; font-style: italic; } /* Comment */
.pagebody code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
.pagebody code span.do { color: #ba2121; font-style: italic; } /* Documentation */
.pagebody code span.dt { color: #902000; } /* DataType */
.pagebody code span.dv { color: #40a070; } /* DecVal */
.pagebody code span.er { color: #ff0000; font-weight: bold; } /* Error */
.pagebody code span.ex { } /* Extension */
.pagebody code span.fl { color: #40a070; } /* Float */
.pagebody code span.fu { color: #06287e; } /* Function */
.pagebody code span.im { } /* Import */
.pagebody code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
.pagebody code span.kw { color: #007020; font-weight: bold; } /* Keyword */
.pagebody code span.op { color: #666666; } /* Operator */
.pagebody code span.ot { color: #007020; } /* Other */
.pagebody code span.pp { color: #bc7a00; } /* Preprocessor */
.pagebody code span.sc { color: #4070a0; } /* SpecialChar */
.pagebody code span.ss { color: #bb6688; } /* SpecialString */
.pagebody code span.st { color: #4070a0; } /* String */
.pagebody code span.va { color: #19177c; } /* Variable */
.pagebody code span.vs { color: #4070a0; } /* VerbatimString */
.pagebody code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
/* 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>