Compare commits
30 Commits
c3c47e418d
...
0dd69c3fe3
Author | SHA1 | Date | |
---|---|---|---|
0dd69c3fe3 | |||
95003803eb | |||
fddbbf4c50 | |||
8b4765e9fb | |||
d83611f12a | |||
1eca81cd1d | |||
91a57aa8c9 | |||
3a9cc4c0f8 | |||
44bea9c982 | |||
5c8e1e5253 | |||
451bc567e2 | |||
80dce5d4ed | |||
48f64bf3d4 | |||
4e5bd41953 | |||
de3d758005 | |||
444c777135 | |||
9c6b2247a7 | |||
09334831f7 | |||
af5bef0125 | |||
b4aa431f4d | |||
49a215a587 | |||
0a0bd542fc | |||
36f40f3269 | |||
b61f1ba3b2 | |||
bef8aeda52 | |||
5bb40a57d1 | |||
29529cfd6a | |||
8bd9173847 | |||
dc4560c232 | |||
da0d9db113 |
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@ -0,0 +1,4 @@
|
||||
.git
|
||||
.env
|
||||
env
|
||||
**/__pycache__
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
*.swp
|
||||
.env
|
||||
env
|
||||
n
|
||||
web
|
||||
planning.txt
|
||||
__pycache__
|
||||
**/__pycache__
|
||||
|
31
Dockerfile
Normal file
31
Dockerfile
Normal file
@ -0,0 +1,31 @@
|
||||
FROM python:3.12-bookworm
|
||||
|
||||
ARG ARCH=
|
||||
|
||||
ENV BUILDARCH=${ARCH}
|
||||
ENV GRONK_CSS_DIR=./css
|
||||
ENV GRONK_JS_DIR=./js
|
||||
ENV GRONK_TEMPLATES_DIR=./templates
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
RUN mkdir /notes
|
||||
RUN mkdir /web
|
||||
|
||||
VOLUME /usr/src/app/notes
|
||||
VOLUME /usr/src/app/web
|
||||
|
||||
RUN apt-get update \
|
||||
&& wget -O ./pandoc.deb https://github.com/jgm/pandoc/releases/download/3.1.11/pandoc-3.1.11-1-${BUILDARCH}.deb \
|
||||
&& apt install -y -f ./pandoc.deb \
|
||||
&& rm ./pandoc.deb
|
||||
|
||||
COPY requirements.txt ./
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
RUN useradd -Ms /bin/nologin user
|
||||
USER user
|
||||
|
||||
COPY . .
|
||||
|
||||
CMD [ "python3", "-u", "gronk.py", "--output-dir", "./web", "./notes" ]
|
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
@ -0,0 +1,11 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
gronk:
|
||||
build:
|
||||
context: '.'
|
||||
args:
|
||||
ARCH: ${ARCH}
|
||||
volumes:
|
||||
- '${SOURCE}:/usr/src/app/notes'
|
||||
- '${OUTPUT}:/usr/src/app/web'
|
66
gronk.py
66
gronk.py
@ -23,14 +23,15 @@ GRONK_COMMIT = "dev"
|
||||
|
||||
PANDOC_SERVER_URL = os.getenv("PANDOC_SERVER_URL", r"http://localhost:3030/")
|
||||
PANDOC_TIMEOUT = int(os.getenv("PANDOC_TIMEOUT", "120"))
|
||||
GRONK_CSS_DIR = Path(os.getenv("CSS_DIR", "/opt/gronk/css"))
|
||||
GRONK_JS_DIR = Path(os.getenv("JS_DIR", "/opt/gronk/js"))
|
||||
GRONK_TEMPLATES_DIR = Path(os.getenv("TEMPLATES_DIR", "/opt/gronk/templates"))
|
||||
GRONK_CSS_DIR = Path(os.getenv("GRONK_CSS_DIR", "/opt/gronk/css"))
|
||||
GRONK_JS_DIR = Path(os.getenv("GRONK_JS_DIR", "/opt/gronk/js"))
|
||||
GRONK_TEMPLATES_DIR = Path(
|
||||
os.getenv("GRONK_TEMPLATES_DIR", "/opt/gronk/templates/"))
|
||||
|
||||
JINJA_ENV = jinja2.Environment(loader=jinja2.PackageLoader("gronk"),
|
||||
autoescape=jinja2.select_autoescape)
|
||||
JINJA_ENV = jinja2.Environment(
|
||||
loader=jinja2.FileSystemLoader(searchpath=GRONK_TEMPLATES_DIR),
|
||||
autoescape=jinja2.select_autoescape)
|
||||
|
||||
JINJA_TEMPLATES = {}
|
||||
JINJA_TEMPLATE_TEXTARTICLE = JINJA_ENV.get_template("article-text.html")
|
||||
JINJA_TEMPLATE_HOME_INDEX = JINJA_ENV.get_template("home.html")
|
||||
JINJA_TEMPLATE_INDEX = JINJA_ENV.get_template("index.html")
|
||||
@ -117,8 +118,8 @@ class FileMap:
|
||||
'tags': [],
|
||||
}
|
||||
|
||||
if 'index.md' in [f.name for f in filepath.iterdir()]:
|
||||
with open(filepath.joinpath('index.md'),
|
||||
if 'readme.md' in [f.name for f in filepath.iterdir()]:
|
||||
with open(filepath.joinpath('readme.md'),
|
||||
encoding='utf-8') as file_pointer:
|
||||
for key, val in frontmatter.load(
|
||||
file_pointer).to_dict().items():
|
||||
@ -138,6 +139,9 @@ class FileMap:
|
||||
entries = []
|
||||
|
||||
for path in filepath.iterdir():
|
||||
if '.git' in path.parts:
|
||||
continue
|
||||
|
||||
if path.is_dir():
|
||||
entry = self._get_directory_properties(
|
||||
path, include_index_entries=False)
|
||||
@ -354,7 +358,7 @@ def process_home_index(args, notes_git_head_sha1=None):
|
||||
"""
|
||||
|
||||
post = {'title': 'gronk', 'content': ''}
|
||||
custom_content_file = args.notes.joinpath('index.md')
|
||||
custom_content_file = args.notes.joinpath('readme.md')
|
||||
if custom_content_file.is_file():
|
||||
fmpost = frontmatter.loads(custom_content_file.read_text()).to_dict()
|
||||
for key, val in fmpost.items():
|
||||
@ -434,6 +438,8 @@ def generate_tag_browser(output_dir):
|
||||
def main(args):
|
||||
""" Entry point for script """
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
global LICENSE
|
||||
global FILEMAP
|
||||
|
||||
@ -462,7 +468,7 @@ def main(args):
|
||||
root_properties = FILEMAP.get(root)
|
||||
root_properties['dst_path']['raw'].mkdir(parents=True, exist_ok=True)
|
||||
|
||||
pprint.pprint(root_properties)
|
||||
#pprint.pprint(root_properties)
|
||||
html = JINJA_TEMPLATE_INDEX.render(
|
||||
gronk_commit=GRONK_COMMIT,
|
||||
title=root_properties.get('title', ''),
|
||||
@ -481,8 +487,8 @@ def main(args):
|
||||
|
||||
# render each file
|
||||
for file in files:
|
||||
# don't render index.md as index as it is used for directory
|
||||
if file == "index.md":
|
||||
# don't render readme.md as index as it is used for directory
|
||||
if file == "readme.md":
|
||||
continue
|
||||
render_file(root.joinpath(file))
|
||||
|
||||
@ -499,16 +505,44 @@ def main(args):
|
||||
generate_tag_browser(args.output_dir.joinpath('tags'))
|
||||
generate_permalink_page(args.output_dir)
|
||||
|
||||
elapsed_time = time.time() - start_time
|
||||
print(f"generated notes {elapsed_time=}")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def start_pandoc_server():
|
||||
"""
|
||||
attempt to get the version of pandoc server in a loop until it is
|
||||
successful and return version as string
|
||||
"""
|
||||
start_time = time.time()
|
||||
process = subprocess.Popen(["/usr/bin/pandoc-server"],
|
||||
stdout=subprocess.PIPE)
|
||||
version = None
|
||||
|
||||
while True:
|
||||
try:
|
||||
resp = requests.get(f"{PANDOC_SERVER_URL}/version")
|
||||
version = resp.content.decode('utf-8')
|
||||
break
|
||||
except requests.ConnectionError:
|
||||
time.sleep(0.1)
|
||||
rc = process.poll()
|
||||
if rc is not None:
|
||||
print(f"PANDOC SERVER FAILED TO START: {rc=}")
|
||||
print(process.stdout.read().decode("utf-8"))
|
||||
raise Exception("Pandoc server failed to start")
|
||||
|
||||
elapsed_time = time.time() - start_time
|
||||
print(f"pandoc-server started {version=} {elapsed_time=}")
|
||||
return process
|
||||
|
||||
|
||||
# TODO implement useful logging and debug printing
|
||||
|
||||
if __name__ == '__main__':
|
||||
pandoc_process = subprocess.Popen(["/usr/bin/pandoc-server"],
|
||||
stdout=subprocess.PIPE)
|
||||
time.sleep(1)
|
||||
print(pandoc_process.stdout)
|
||||
pandoc_process = start_pandoc_server()
|
||||
|
||||
try:
|
||||
sys.exit(main(get_args()))
|
||||
|
56
readme.md
56
readme.md
@ -10,22 +10,39 @@ Tested with [pandoc v2.19.2](https://github.com/jgm/pandoc/releases/tag/2.19.2).
|
||||
## Why?
|
||||
|
||||
- View notes as a website, on any device
|
||||
- Write notes with Pandoc markdown
|
||||
- Easily share notes
|
||||
- Powered by Pandoc, and therefore supports [Pandoc's markdown](https://pandoc.org/MANUAL.html#pandocs-markdown) (I mainly care about equations)
|
||||
- [flatnotes](https://github.com/Dullage/flatnotes) is cool but I really would rather type my notes in Vim
|
||||
- Lightweight HTML generated
|
||||
- Minimal JavaScript
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
0. Install [Pandoc](https://pandoc.org/index.html) and [Pip](https://github.com/pypa/pip)
|
||||
### Docker
|
||||
|
||||
On arch:
|
||||
```
|
||||
# pacman -S pandoc python-pip
|
||||
```
|
||||
Run the following, modifing the `-v` arguments as needed to mount the correct folders and
|
||||
setting the value of `ARCH` to either `amd64` or `arm64` as appropriate.
|
||||
|
||||
1. Run `make install` as root
|
||||
```
|
||||
docker build . -t gronk --build-arg ARCH=amd64
|
||||
docker run -v ./n:/usr/src/app/notes -v ./web:/usr/src/app/web gronk
|
||||
```
|
||||
|
||||
#### Compose
|
||||
|
||||
A [docker compose file](./docker-compose.yml) file has been provided.
|
||||
|
||||
Set the following environment variables (or create a .env file) and run `docker compose up`:
|
||||
|
||||
- `ARCH`
|
||||
- `SOURCE`
|
||||
- `OUTPUT`
|
||||
|
||||
### Locally
|
||||
|
||||
0. Install [Pandoc](https://pandoc.org/index.html) and [Pip](https://github.com/pypa/pip), python3-dev, and a C compiler
|
||||
1. `sudo make install`
|
||||
|
||||
## Other Things to Know
|
||||
|
||||
@ -34,9 +51,9 @@ Tested with [pandoc v2.19.2](https://github.com/jgm/pandoc/releases/tag/2.19.2).
|
||||
- gronk looks for the plaintext file `LICENSE` in the root directory of your notes
|
||||
|
||||
|
||||
## Custom Directory Index
|
||||
## Custom Directory Index and Metadata
|
||||
|
||||
To add custom content to a directory index, put it in a file called `index.md` under the directory.
|
||||
To add custom content to a directory index, put it in a file called `readme.md` under the directory.
|
||||
|
||||
You can set the following frontmatter variables to customise the directory index of a directory:
|
||||
|
||||
@ -44,7 +61,7 @@ You can set the following frontmatter variables to customise the directory index
|
||||
|------------------------|-------------------|--------------------------------------------------------------------------------------------|
|
||||
| `tags` | `[]` | list of tags, used by search and inherited by any notes and subdirectories |
|
||||
| `uuid` | none | unique id to reference directory, used for permalinking |
|
||||
| `content_after_search` | `false` | show custom content in `index.md` after search bar and directory index |
|
||||
| `content_after_search` | `false` | show custom content in `readme.md` after search bar and directory index |
|
||||
| `automatic_index` | `true` | show the automatically generated directory index. required for search bar to function. |
|
||||
| `search_bar` | `true` | show search bar to search directory items. requires `automatic_index` (enabled by default) |
|
||||
|
||||
@ -82,8 +99,8 @@ a file called `styles.css`.
|
||||
To add additional styling, the default styling will attempt to import `styles.css` from the root of the notes
|
||||
directory.
|
||||
|
||||
To add additional content to the homepage, create a file called `index.md` at the top level of your notes directory.
|
||||
To set the HTML `title` tag, set `title` in the frontmatter of `index.md`:
|
||||
To add additional content to the homepage, create a file called `readme.md` at the top level of your notes directory.
|
||||
To set the HTML `title` tag, set `title` in the frontmatter of `readme.md`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
@ -103,7 +120,18 @@ $ gronk.py notes_directory
|
||||
|
||||
Output of `gronk.py --help`:
|
||||
|
||||
TODO add cli output
|
||||
```
|
||||
usage: gronk.py [-h] [-o OUTPUT_DIR] [-F] notes
|
||||
|
||||
positional arguments:
|
||||
notes
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-o OUTPUT_DIR, --output-dir OUTPUT_DIR
|
||||
-F, --force Generate new output html even if source file was modified before output
|
||||
html
|
||||
```
|
||||
|
||||
The command will generate a website in the `output-dir` directory (`./web` by default).
|
||||
It will then generate a list of all note files and put it in `index.html`.
|
||||
@ -121,5 +149,3 @@ Then you just have to point a webserver at `output-dir`.
|
||||
Default synatx highlighting is based off [Pygments](https://pygments.org/)' default theme and
|
||||
made using Pandoc v2.7.2.
|
||||
I found the theme [here](https://github.com/tajmone/pandoc-goodies/blob/master/skylighting/css/built-in-styles/pygments.css).
|
||||
|
||||
Pretty sure the link colours are taken from [thebestmotherfucking.website](https://thebestmotherfucking.website/).
|
||||
|
@ -11,7 +11,9 @@ oyaml==1.0
|
||||
pypandoc==1.5
|
||||
python-frontmatter==1.0.0
|
||||
python-magic==0.4.24
|
||||
PyYAML==6.0.1
|
||||
PyYAML==5.3.1
|
||||
regex==2021.11.10
|
||||
soupsieve==2.2.1
|
||||
regex==2021.11.10
|
||||
requests==2.31.0
|
||||
smmap==5.0.1
|
||||
|
@ -13,6 +13,6 @@
|
||||
<div id="content">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<p class="smallText"> page generated by <a href="https://github.com/alvierahman90/gronk">gronk</a> (commit {{ gronk_commit }}) {% if notes_git_head_sha1 %}notes commit {{ notes_git_head_sha1 }}{% endif %}</p>
|
||||
<p class="smallText"> page generated by <a href="https://github.com/alvierahman90/gronk">gronk</a> <!--(commit {{ gronk_commit }}) {% if notes_git_head_sha1 %}notes commit {{ notes_git_head_sha1 }}{% endif %}--></p>
|
||||
</div>
|
||||
</body>
|
||||
|
Reference in New Issue
Block a user