Initial homepage and category page generation scripts

This commit is contained in:
Zachary Talis 2021-06-24 23:52:22 -04:00
parent bf16180810
commit bec8a07195
13 changed files with 174 additions and 28 deletions

View file

@ -3,3 +3,7 @@
Simple leaderboard site template updated via Python scripts!
Designed for use within speedrunning communities.
## About
paceboard is a template-based static site generator for speedrunning leaderboards. Python scripts are used to add runs and categories, and all info is stored in `csv` files.

View file

@ -26,3 +26,7 @@ h1, h2 {
font-family: "Lexend", "Arial", Arial, sans-serif;
text-align: center;
}
.categoryLink {
display: block;
}

View file

@ -1 +1 @@
tk_category_name,tk_category_dashname,tk_category_description,tk_category_rules
tk_category_dashname,tk_category_name,tk_category_description,tk_category_rules

1 tk_category_dashname tk_category_name tk_category_description tk_category_rules

View file

@ -1 +1 @@
id,date,game,category,runner,verifier,link,comment
tk_run_id,tk_run_date,tk_run_game,tk_run_category,tk_run_runner,tk_run_verifier,tk_run_link,tk_run_description

1 id tk_run_id date tk_run_date game tk_run_game category tk_run_category runner tk_run_runner verifier tk_run_verifier link tk_run_link comment tk_run_description

View file

@ -0,0 +1,30 @@
### Script for adding a new category. Handles adding data to config.csv.
from utils import csv as util_csv
divider = "----------"
print(
f"\nWe'll ask for the name, description, and rules of the new category.\n\n{divider}\n"
)
# tk_category_name, tk_category_dashname, tk_category_description, tk_category_rules
tk_category_name = input("Name: ")
tk_category_description = input("Description: ")
tk_category_rules = input("Rules: ")
tk_category_dashname = tk_category_name.replace(" ", "_")
categoryDict = {
"tk_category_name": tk_category_name,
"tk_category_dashname": tk_category_dashname,
"tk_category_description": tk_category_description,
"tk_category_rules": tk_category_rules,
}
util_csv.dictWriter("../csv/config.csv", categoryDict, "a")
print(
f"\n{divider}\n\nAdded category! If you made a mistake, you can manually edit csv/categories.csv (and csv/runs.csv if you've added any runs to the borked category). \n"
)

View file

@ -4,8 +4,13 @@ from utils.gen import index as gen_index
from utils.gen import categories as gen_categories
from utils.gen import runs as gen_runs
print("Generating homepage...")
gen_index.generate("../templates", "..", "index.html")
gen_categories.generate()
gen_runs.generate()
print("Generating leaderboard pages for each category...")
gen_categories.generate("../templates", "../categories", "category.html")
# print("Generating details pages for each run...")
# gen_runs.generate("../templates", "runs", "runs.html")
print("Done generating site!")

View file

@ -1,4 +1,4 @@
### Initial configuration script for paceboard. Handles adding properties to config.csv.
### Initial configuration script for paceboard. Handles adding data to config.csv.
from utils import csv as util_csv
@ -20,7 +20,7 @@ configDict = {
"tk_logo_alt": tk_logo_alt,
}
util_csv.dictWriterSingleDict("../csv/config.csv", configDict)
util_csv.dictWriter("../csv/config.csv", configDict)
print(
f"\n{divider}\n\nPerfect! You can always overwrite the info above by running this script again.\nHere's an overview of how to use paceboard:\n\n- Add a category using scripts/add-category.py\n- Add a run using scripts/add-run.py\n- Use scripts/generate.py to update the site with the info you've added.\n- All categories, runs, and configuration details are stored in csv/\n- Replace the logo saved as assets/img/logo.png\n- For the adventurous, you can restyle your site's pages by editing files within templates/ and css/\n\nRemember to run scripts/generate.py to initialize your site.\nThat's all for now! <3\n"

View file

@ -23,22 +23,29 @@ def readerWithFunction(filepath, function, arg=None):
return value
def dictWriterSingleDict(filepath, dict):
def dictWriter(filepath, dict, flag="w"):
"""Completely rewrite a csv using the values in a single dictionary.
filepath -- the path of the csv, whether or not it exists
dict -- the dictionary to pull all values from
flag -- flag for open() (default "w")
"w" will also activate writeheader()
"""
with open(filepath, "w", newline="") as file:
with open(filepath, flag, newline="") as file:
dictWriter = csv.DictWriter(file, fieldnames=dict.keys(), delimiter=",")
dictWriter.writeheader()
if flag == "w":
dictWriter.writeheader()
dictWriter.writerow(dict)
file.close()
def dictReaderFirstRow(filepath):
"""Get a dictionary of the first (non-header) row of values in a csv
filepath -- the path of the csv, whether or not it exists
"""
with open(filepath, newline="") as file:
print(os.path.abspath(filepath))
dict = {}
dictReader = csv.DictReader(file)
for row in dictReader:
@ -50,6 +57,20 @@ def dictReaderFirstRow(filepath):
return dict
def dictReaderMultiRow(filepath, idName):
"""Get a dictionary of dictionaries of the (non-header) row of values in a csv
filepath -- the path of the csv, whether or not it exists
"""
with open(filepath, newline="") as file:
dict = {}
dictReader = csv.DictReader(file)
for row in dictReader:
dict[row[idName]] = row
file.close()
return dict
def getIndexOfField(filepath, field):
"""Get the index (column number) of a field in a csv.

View file

@ -1,5 +1,39 @@
### Generation helper for category pages
from .. import file as util_file
from .. import csv as util_csv
import shutil
import os
def generate():
print("- categories.py -")
def generate(templatedir, destinationdir, templateFilename):
"""Main generation function for category page generation helper.
templatedir -- the relative path of the template html file's directory
destinationpath -- the directory where category paths should be generated
filename -- the filename of the category template (always category.html)
"""
idName = "tk_category_dashname"
categories = util_csv.dictReaderMultiRow("../csv/categories.csv", idName)
config = util_csv.dictReaderFirstRow("../csv/config.csv")
for category in categories:
path = f"{destinationdir}/{categories[category][idName]}"
currentDir = os.getcwd()
os.makedirs(path, exist_ok=True)
shutil.copy(
f"{currentDir}/{templatedir}/{templateFilename}",
f"{currentDir}/{path}/index.html",
)
for key in categories[category]:
util_file.replaceTextInFile(
f"{path}/index.html", key, categories[category][key]
)
for key in config.keys():
util_file.replaceTextInFile(f"{path}/index.html", key, config[key])

View file

@ -5,18 +5,30 @@ from .. import csv as util_csv
import shutil
def generate(templatedir, destinationdir, filename):
def generate(templatedir, destinationdir, templateFilename):
"""Main generation function for index.html generation helper.
templatedir -- the relative path of the template html file's directory
destinationpath -- the directory where index.html should be generated
filename -- the filename of the index page (always index.html)
filename -- the filename of the index template (always index.html)
"""
print("- index.py -")
shutil.copy(f"{templatedir}/{filename}", destinationdir)
shutil.copy(f"{templatedir}/{templateFilename}", destinationdir)
idName = "tk_category_dashname"
categories = util_csv.dictReaderMultiRow("../csv/categories.csv", idName)
config = util_csv.dictReaderFirstRow("../csv/config.csv")
for key in config.keys():
util_file.replaceTextInFile(f"{destinationdir}/{filename}", key, config[key])
util_file.replaceTextInFile(f"{destinationdir}/index.html", key, config[key])
tk_category_dashname = "tk_category_dashname"
tk_category_name = "tk_category_name"
for category in categories:
util_file.replaceTextInFile(
f"{destinationdir}/index.html",
"lk_categories",
f'<a class="categoryLink" href="categories/{categories[category][tk_category_dashname]}">{categories[category][tk_category_name]}</a>lk_categories',
)
util_file.replaceTextInFile(f"{destinationdir}/index.html", "lk_categories", "")

View file

@ -1,5 +1,41 @@
### Generation helper for run pages
from .. import file as util_file
from .. import csv as util_csv
import shutil
import os
def generate():
print("- runs.py -")
def generate(templatedir, destinationdir, templateFilename):
"""Main generation function for category page generation helper.
templatedir -- the relative path of the template html file's directory
destinationpath -- the directory where run paths should be generated
filename -- the filename of the run template (always run.html)
"""
# TODO fix everything
idName = "tk_category_dashname"
categories = util_csv.dictReaderMultiRow("../csv/categories.csv", idName)
config = util_csv.dictReaderFirstRow("../csv/config.csv")
for category in categories:
path = f"{destinationdir}/{categories[category][idName]}"
currentDir = os.getcwd()
os.makedirs(path, exist_ok=True)
shutil.copy(
f"{currentDir}/{templatedir}/{templateFilename}",
f"{currentDir}/{path}/index.html",
)
for key in categories[category]:
util_file.replaceTextInFile(
f"{path}/index.html", key, categories[category][key]
)
for key in config.keys():
util_file.replaceTextInFile(f"{path}/index.html", key, config[key])

View file

@ -5,15 +5,15 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>tk_title - tk_category_name</title>
<title>tk_game_name - tk_category_name</title>
<link rel="stylesheet" href="css/style.css">
<link rel="icon" href="assets/img/logo.png">
<link rel="stylesheet" href="../../css/style.css">
<link rel="icon" href="../../assets/img/logo.png">
<meta property="og:title" content="tk_game - tk_category_name" />
<meta property="og:title" content="tk_game_name - tk_category_name" />
<meta property="og:type" content="website" />
<meta property="og:description" content="tk_category_description" />
<meta property="og:url" content="tk_url/tk_category_dashname.html" />
<meta property="og:url" content="tk_url/tk_category_dashname/index.html" />
<meta property="og:image:secure_url" content="https://tk_url/assets/img/logo.png" />
<meta property="og:image:alt" content="tk_logo_alt" />
@ -22,11 +22,11 @@
</head>
<body>
<h1>tk_game - tk_category_name</h1>
<h1>tk_game_name - tk_category_name</h1>
<p>tk_category_description</p>
<h2>Leaderboard</h2>
<!-- lk_categories -->
<!-- lk_leaderboard -->
</body>
</html>

View file

@ -26,7 +26,7 @@
<p>tk_game_description</p>
<h2>Categories</h2>
<!-- lk_categories -->
lk_categories
</body>
</html>