complete app
This commit is contained in:
parent
8886be3b6f
commit
f9e11e2b71
13 changed files with 203 additions and 19 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -5,3 +5,6 @@ __pycache__/
|
|||
*.pyd
|
||||
.pytest_cache/
|
||||
data/*.db
|
||||
build/
|
||||
dist/
|
||||
app.spec
|
||||
|
|
28
README.md
28
README.md
|
@ -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
|
||||
|
||||
```
|
||||
```sh
|
||||
source venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
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
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
termcolor==2.5.0
|
||||
pyinstaller===6.11.0
|
4
setup.py
4
setup.py
|
@ -5,9 +5,7 @@ setup(
|
|||
version="0.1",
|
||||
packages=find_packages(where="src"),
|
||||
package_dir={"": "src"},
|
||||
install_requires=[
|
||||
# List your project dependencies here
|
||||
],
|
||||
install_requires=["termcolor", "pyinstaller"],
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"neuron-zk-generator=app:main",
|
||||
|
|
33
src/app.py
33
src/app.py
|
@ -1,12 +1,37 @@
|
|||
from constants import SOURCE
|
||||
from constants import TARGET
|
||||
import subprocess
|
||||
from lib.create_target_dir import create_target_dir
|
||||
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():
|
||||
target_dir = create_target_dir(TARGET, SOURCE)
|
||||
transfer_files(f"{TARGET}/{target_dir}", SOURCE)
|
||||
try:
|
||||
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__":
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
SOURCE = "/home/thomas/repos/eolas"
|
||||
TARGET = "/home/thomas/Desktop/output"
|
3
src/lib/constants.py
Normal file
3
src/lib/constants.py
Normal 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"
|
|
@ -24,5 +24,7 @@ def create_target_dir(target_dir, source_dir):
|
|||
|
||||
except Exception as e:
|
||||
print(
|
||||
colored(f" Error occurred when creating target directory: {str(e)}", "red")
|
||||
colored(
|
||||
f" Error occurred when creating target directory: {str(e)}", "red"
|
||||
)
|
||||
)
|
||||
|
|
51
src/lib/generate_index_file.py
Normal file
51
src/lib/generate_index_file.py
Normal 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
13
src/lib/list_entries.py
Normal 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
|
|
@ -4,14 +4,27 @@ from termcolor import colored
|
|||
|
||||
def transfer_files(target_dir, source_dir):
|
||||
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
|
||||
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(" Copying zettels...", "blue"))
|
||||
|
||||
# Copy notes
|
||||
shutil.copytree(f"{source_dir}/zk", f"{target_dir}", dirs_exist_ok=True)
|
||||
print(colored(" Zettels transferred!", "green"))
|
||||
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"))
|
||||
|
|
50
src/lib/transform_links.py
Normal file
50
src/lib/transform_links.py
Normal 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",
|
||||
)
|
||||
)
|
Loading…
Add table
Reference in a new issue