complete app

This commit is contained in:
thomasabishop 2024-10-19 13:03:04 +01:00
parent 8886be3b6f
commit f9e11e2b71
13 changed files with 203 additions and 19 deletions

3
.gitignore vendored
View file

@ -5,3 +5,6 @@ __pycache__/
*.pyd *.pyd
.pytest_cache/ .pytest_cache/
data/*.db data/*.db
build/
dist/
app.spec

View file

@ -1,6 +1,32 @@
# `neuron-zk-generator`
This is a basic Python application that reads data from [my](https://github.com/thomasabishop/eolas) [zettelkasten](https://en.wikipedia.org/wiki/Zettelkasten) and
formats it so that it can be compiled as a [Neuron](https://neuron.zettel.page/) project and from there published as a static-site on the web.
## Running app in local development ## Running app in local development
``` ```sh
source venv/bin/activate source venv/bin/activate
pip install -r requirements.txt
neuron-zk-generator neuron-zk-generator
``` ```
## Build standalone executable
Use `pyinstaller` to create single executable file. `pyinstaller` is installed
along with other packages in `requirements.txt`.
From root:
```sh
pyinstaller -F src/app.py
# -F compiles to single file
```
Outputs to `neuron-zk-generator/dist/app`.
Sourcing the executable:
```sh
/home/thomas/repos/neuron-zk-generator/dist/app
```

2
requirements.txt Normal file
View file

@ -0,0 +1,2 @@
termcolor==2.5.0
pyinstaller===6.11.0

View file

@ -5,9 +5,7 @@ setup(
version="0.1", version="0.1",
packages=find_packages(where="src"), packages=find_packages(where="src"),
package_dir={"": "src"}, package_dir={"": "src"},
install_requires=[ install_requires=["termcolor", "pyinstaller"],
# List your project dependencies here
],
entry_points={ entry_points={
"console_scripts": [ "console_scripts": [
"neuron-zk-generator=app:main", "neuron-zk-generator=app:main",

View file

@ -1,12 +1,37 @@
from constants import SOURCE import subprocess
from constants import TARGET
from lib.create_target_dir import create_target_dir from lib.create_target_dir import create_target_dir
from lib.transfer_files import transfer_files from lib.transfer_files import transfer_files
from lib.transform_links import transform_links
from lib.generate_index_file import generate_index_file
SOURCE = "/home/thomas/repos/eolas"
TARGET = "/home/thomas/repos/eolas/neuron"
SLACK_NOTIFIER = "/home/thomas/repos/slack-notifier/src/index.js"
def main(): def main():
target_dir = create_target_dir(TARGET, SOURCE) try:
transfer_files(f"{TARGET}/{target_dir}", SOURCE) build_id = create_target_dir(TARGET, SOURCE)
transfer_files(f"{TARGET}/{build_id}", SOURCE)
transform_links(f"{TARGET}/{build_id}")
generate_index_file(f"{TARGET}/{build_id}", build_id, SOURCE)
subprocess.run(
[
"node",
SLACK_NOTIFIER,
"eolas",
f"✅ Neuron static site successfully generated locally for Eolas. Build: {build_id}",
]
)
except Exception as e:
subprocess.run(
[
"node",
SLACK_NOTIFIER,
"eolas",
f"⛔ Neuron static site generation failed for Eolas: {e}",
]
)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -1,2 +0,0 @@
SOURCE = "/home/thomas/repos/eolas"
TARGET = "/home/thomas/Desktop/output"

3
src/lib/constants.py Normal file
View file

@ -0,0 +1,3 @@
SOURCE = "/home/thomas/repos/eolas"
TARGET = "/home/thomas/repos/eolas/neuron"
SLACK_NOTIFIER = "/home/thomas/repos/slack-notifier/src/index.js"

View file

@ -24,5 +24,7 @@ def create_target_dir(target_dir, source_dir):
except Exception as e: except Exception as e:
print( print(
colored(f" Error occurred when creating target directory: {str(e)}", "red") colored(
f"  Error occurred when creating target directory: {str(e)}", "red"
)
) )

View file

@ -0,0 +1,51 @@
from datetime import datetime
from termcolor import colored
from lib.list_entries import list_entries
def get_entry_titles(entries):
return [entry["file_name"] for entry in entries if entry["file_name"] != "index"]
def generate_wikilinks(entries):
return [f"- [[{entry}]] \n" for entry in entries]
def generate_index_file(target_dir, unique_dir_name, source_dir):
try:
print(colored("  Creating index file...", "blue"))
index_file = f"{target_dir}/index.md"
build_date = datetime.now()
build_date = build_date.strftime("%a %d %b %Y %H:%M:%S")
build_info = (
f""" \n**Build ID:** {unique_dir_name}\n\n**Published:** {build_date}\n\n"""
)
all_notes = list_entries(f"{target_dir}")
notes_count = len(all_notes)
note_titles = sorted(get_entry_titles(all_notes))
note_titles_formatted = generate_wikilinks(note_titles)
recent_notes = list_entries(f"{source_dir}/zk")
recents = sorted(recent_notes, key=lambda item: item["modified"], reverse=True)
recents = recents[:8]
recents = get_entry_titles(recents)
recents_formatted = generate_wikilinks(recents)
f = open(index_file, "a")
f.write(build_info)
f.write("### Recent edits \n\n")
for recent in recents_formatted:
f.write(recent)
f.write("\n\n")
f.write(f"### All notes ({notes_count}) \n\n")
for note in note_titles_formatted:
f.write(note)
f.close()
print(colored("  Index file created!", "green"))
except Exception as e:
print(colored(f"  Error occurred when transferring files: {str(e)}", "red"))

13
src/lib/list_entries.py Normal file
View file

@ -0,0 +1,13 @@
import os
from pathlib import Path
def list_entries(source_dir):
entries = []
with os.scandir(source_dir) as dir_contents:
for entry in dir_contents:
if Path(entry).suffix == ".md":
file_name = Path(entry).stem
info = entry.stat()
entries.append({"file_name": file_name, "modified": info.st_mtime})
return entries

View file

@ -4,14 +4,27 @@ from termcolor import colored
def transfer_files(target_dir, source_dir): def transfer_files(target_dir, source_dir):
try: try:
# Copy templates
print(colored("  Copying HTML/MD templates...", "blue"))
shutil.copytree(
f"{source_dir}/.neuron-generator/templates", target_dir, dirs_exist_ok=True
)
neuron_template = open(f"{target_dir}/neuron.dhall", "x")
neuron_template.close()
print(colored("  Templates transferred!", "green"))
# Copy images to /static # Copy images to /static
print(colored("  Copying static files...", "blue")) print(colored("  Copying static files...", "blue"))
shutil.copytree(f"{source_dir}/img", f"{target_dir}/static") shutil.copytree(
f"{source_dir}/img",
f"{target_dir}/static",
)
print(colored("  Static files transferred!", "green")) print(colored("  Static files transferred!", "green"))
print(colored("  Copying zettels...", "blue")) print(colored("  Copying zettels...", "blue"))
# Copy notes # Copy notes
shutil.copytree(f"{source_dir}/zk", f"{target_dir}", dirs_exist_ok=True) shutil.copytree(f"{source_dir}/zk", f"{target_dir}", dirs_exist_ok=True)
print(colored("  Zettels transferred!", "green")) print(colored("  Zettels transferred!", "green"))
except Exception as e: except Exception as e:
print(colored(f"Error occurred when transferring files: {str(e)}", "red")) print(colored(f"Error occurred when transferring files: {str(e)}", "red"))

View file

@ -0,0 +1,50 @@
import os
import re
from termcolor import colored
image_rgx = r"!\[.*?\]\((.*?)\)"
def process_image_links(line, links):
try:
for link in links:
stripped_img_ref = re.search(r"[^/\\]+$", link)
if stripped_img_ref:
stripped_img_ref = stripped_img_ref.group()
new_img_ref = f"/static/{stripped_img_ref}"
line = line.replace(f"({link})", f"({new_img_ref})")
# print(colored(f"  {links}", "green"))
return line
except Exception as e:
print(colored(f" Error when transforming link: {str(e)}", "red"))
def transform_links(target_dir):
print(colored("  Updating links...", "blue"))
for filename in os.listdir(target_dir):
if filename.endswith(".md"):
file_path = os.path.join(target_dir, filename)
with open(file_path, "r") as f:
lines = f.readlines()
modified = False
new_lines = []
for line in lines:
img_links = re.findall(image_rgx, line)
if img_links:
new_line = process_image_links(line, img_links)
new_lines.append(new_line)
modified = True
else:
new_lines.append(line)
if modified:
with open(file_path, "w") as f:
f.writelines(new_lines)
print(
colored(
"  Links updated!",
"green",
)
)