Compare commits
12 Commits
a3f11a4f12
...
c3c47e418d
Author | SHA1 | Date | |
---|---|---|---|
c3c47e418d | |||
27d59af225 | |||
bcb0e28727 | |||
7e6847cf61 | |||
159b93bba7 | |||
a665b4fbe1 | |||
44f491cdca | |||
d2d1a2dee3 | |||
6fb1e6605b | |||
a56ac835f8 | |||
bf2832cdf3 | |||
c165f7bd03 |
2
Makefile
2
Makefile
@ -1,6 +1,8 @@
|
|||||||
install:
|
install:
|
||||||
cp gronk_add_uuid.py /usr/local/bin
|
cp gronk_add_uuid.py /usr/local/bin
|
||||||
sed "s/GRONK_COMMIT = \"dev\"/GRONK_COMMIT = \"$$(git rev-parse --short HEAD)\"/" gronk.py > /usr/local/bin/gronk.py
|
sed "s/GRONK_COMMIT = \"dev\"/GRONK_COMMIT = \"$$(git rev-parse --short HEAD)\"/" gronk.py > /usr/local/bin/gronk.py
|
||||||
|
chmod +x /usr/local/bin/gronk.py
|
||||||
|
chmod +x /usr/local/bin/gronk_add_uuid.py
|
||||||
mkdir -p /opt/gronk
|
mkdir -p /opt/gronk
|
||||||
cp -r templates js css /opt/gronk
|
cp -r templates js css /opt/gronk
|
||||||
pip3 install -r requirements.txt
|
pip3 install -r requirements.txt
|
||||||
|
@ -1,188 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
import frontmatter
|
|
||||||
import copy
|
|
||||||
import magic
|
|
||||||
import regex as re
|
|
||||||
|
|
||||||
|
|
||||||
class FileMap:
|
|
||||||
"""
|
|
||||||
this class is used to read file properties, inherit properties, and have a centralised place to access them
|
|
||||||
"""
|
|
||||||
def __init__(self, input_dir, output_dir):
|
|
||||||
self._map = {}
|
|
||||||
self.input_dir = Path(input_dir)
|
|
||||||
self.output_dir = Path(output_dir)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _path_to_key(path):
|
|
||||||
return str(Path(path))
|
|
||||||
|
|
||||||
def get(self, filepath, default=None, raw=False):
|
|
||||||
"""
|
|
||||||
get the properties of a file at a filepath
|
|
||||||
raw=True to not inherit properties
|
|
||||||
"""
|
|
||||||
#print(f"FileMap.get({filepath=}, {default=}, {raw=})")
|
|
||||||
# TODO maybe store properties of a file once it's in built and mark it as built? might save time but also cba
|
|
||||||
if self._path_to_key(filepath) not in self._map.keys():
|
|
||||||
self.add(filepath)
|
|
||||||
|
|
||||||
properties = copy.deepcopy(self._map.get(self._path_to_key(filepath), default))
|
|
||||||
#print(f"FileMap.get({filepath=}, {default=}, {raw=}): {properties=}")
|
|
||||||
|
|
||||||
if raw:
|
|
||||||
return properties
|
|
||||||
|
|
||||||
parent = filepath
|
|
||||||
while True:
|
|
||||||
parent = parent.parent
|
|
||||||
if parent == Path('.'):
|
|
||||||
break
|
|
||||||
|
|
||||||
parent_properties = self.get(parent, raw=True)
|
|
||||||
# TODO inherit any property that isn't defined, append any lists that exist
|
|
||||||
properties['tags'] = properties.get('tags', []) + parent_properties.get('tags', [])
|
|
||||||
|
|
||||||
if parent == self.input_dir:
|
|
||||||
break
|
|
||||||
|
|
||||||
return properties
|
|
||||||
|
|
||||||
def add(self, filepath):
|
|
||||||
filepath = Path(filepath)
|
|
||||||
#print(f"FileMap.add({filepath=}")
|
|
||||||
if filepath.is_dir():
|
|
||||||
properties = self._get_directory_properties(filepath)
|
|
||||||
else:
|
|
||||||
properties = self._get_file_properties(filepath)
|
|
||||||
|
|
||||||
properties['src_path'] = filepath
|
|
||||||
properties['dst_path'] = self._get_output_filepath(filepath)
|
|
||||||
|
|
||||||
self._map[self._path_to_key(filepath)] = properties
|
|
||||||
|
|
||||||
|
|
||||||
def _get_directory_properties(self, filepath: Path, include_index_entries=True):
|
|
||||||
"""
|
|
||||||
return dict of directory properties to be used in pandoc template
|
|
||||||
"""
|
|
||||||
|
|
||||||
post = {
|
|
||||||
'title': filepath.name,
|
|
||||||
'content_after_search': False,
|
|
||||||
'automatic_index': True,
|
|
||||||
'search_bar': True,
|
|
||||||
'tags': [],
|
|
||||||
}
|
|
||||||
|
|
||||||
if 'index.md' in filepath.iterdir():
|
|
||||||
with open(filepath.joinpath('index.md'), encoding='utf-8') as file_pointer:
|
|
||||||
for key, val in frontmatter.load(file_pointer).to_dict():
|
|
||||||
post[key] = val
|
|
||||||
|
|
||||||
post['is_dir'] = True
|
|
||||||
|
|
||||||
if include_index_entries:
|
|
||||||
post['index_entries'] = self._get_index_entries(filepath)
|
|
||||||
|
|
||||||
return post
|
|
||||||
|
|
||||||
|
|
||||||
def _get_index_entries(self, filepath):
|
|
||||||
"""
|
|
||||||
return sorted list of index entries. alphabetically sorted, folders first
|
|
||||||
"""
|
|
||||||
entries = []
|
|
||||||
|
|
||||||
for path in filepath.iterdir():
|
|
||||||
print(f'{path=}')
|
|
||||||
if path.is_dir():
|
|
||||||
entry = self._get_directory_properties(path, include_index_entries=False)
|
|
||||||
else:
|
|
||||||
entry = self._get_file_properties(path)
|
|
||||||
|
|
||||||
entry['path'] = self._get_output_filepath(path)['web']
|
|
||||||
entries.append(entry)
|
|
||||||
#print(f"FileMap._get_index_entries({filepath=}): {entry=}")
|
|
||||||
|
|
||||||
|
|
||||||
entries.sort(key=lambda entry: str(entry.get('title', '')).lower())
|
|
||||||
entries.sort(key=lambda entry: entry['is_dir'], reverse=True)
|
|
||||||
|
|
||||||
return entries
|
|
||||||
|
|
||||||
def _get_file_properties(self, filepath):
|
|
||||||
#print(f"FileMap._get_file_properties({filepath=}")
|
|
||||||
post = { 'title': filepath.name }
|
|
||||||
|
|
||||||
if filepath.suffix == '.md':
|
|
||||||
with open(filepath, encoding='utf-8') as file_pointer:
|
|
||||||
post = frontmatter.load(file_pointer).to_dict()
|
|
||||||
|
|
||||||
# don't store file contents in memory
|
|
||||||
if 'content' in post.keys():
|
|
||||||
del post['content']
|
|
||||||
post['is_dir'] = False
|
|
||||||
|
|
||||||
return post
|
|
||||||
|
|
||||||
|
|
||||||
def _get_output_filepath(self, input_filepath):
|
|
||||||
|
|
||||||
def webpath(filepath):
|
|
||||||
return Path('/notes').joinpath(filepath.relative_to(self.output_dir))
|
|
||||||
|
|
||||||
|
|
||||||
r = {}
|
|
||||||
r['raw'] = self.output_dir.joinpath(input_filepath.relative_to(self.input_dir))
|
|
||||||
r['web'] = webpath(r['raw'])
|
|
||||||
|
|
||||||
if input_filepath.is_dir():
|
|
||||||
return r
|
|
||||||
|
|
||||||
if input_filepath.suffix == '.md':
|
|
||||||
r['html'] = self.output_dir.joinpath(
|
|
||||||
input_filepath.relative_to(self.input_dir)
|
|
||||||
).with_suffix('.html')
|
|
||||||
r['web'] = webpath(r['html'])
|
|
||||||
|
|
||||||
elif self.is_plaintext(input_filepath):
|
|
||||||
r['html'] = self.output_dir.joinpath(
|
|
||||||
input_filepath.relative_to(self.input_dir)
|
|
||||||
).with_suffix(input_filepath.suffix + '.html')
|
|
||||||
r['raw'] = self.output_dir.joinpath(input_filepath.relative_to(self.input_dir))
|
|
||||||
r['web'] = webpath(r['html'])
|
|
||||||
|
|
||||||
#print(f"{r=}")
|
|
||||||
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def to_list(self):
|
|
||||||
return [ val for _, val in self._map.items() ]
|
|
||||||
|
|
||||||
|
|
||||||
def to_search_data(self):
|
|
||||||
"""
|
|
||||||
returns list of every file in map
|
|
||||||
"""
|
|
||||||
r = []
|
|
||||||
for _, val in self._map.items():
|
|
||||||
r.append({
|
|
||||||
'title': val.get('title', ''),
|
|
||||||
'tags': val.get('tags', []),
|
|
||||||
'path': str(val['dst_path']['web']),
|
|
||||||
'is_dir': val['is_dir']
|
|
||||||
})
|
|
||||||
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def is_plaintext(filename):
|
|
||||||
"""
|
|
||||||
check if file is a plaintext format, such as html, css, etc,
|
|
||||||
return boolean
|
|
||||||
"""
|
|
||||||
return re.match(r'^text/', magic.from_file(str(filename), mime=True)) is not None
|
|
403
gronk.py
403
gronk.py
@ -3,57 +3,235 @@
|
|||||||
gronk --- view your notes as a static html site
|
gronk --- view your notes as a static html site
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import copy
|
||||||
|
import time
|
||||||
|
import magic
|
||||||
|
import regex as re
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
import frontmatter
|
import frontmatter
|
||||||
import git
|
|
||||||
import jinja2
|
import jinja2
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from fileproperties import FileMap
|
|
||||||
|
|
||||||
|
|
||||||
GRONK_COMMIT = "dev"
|
GRONK_COMMIT = "dev"
|
||||||
|
|
||||||
PANDOC_SERVER_URL = os.getenv("PANDOC_SERVER_URL", r"http://localhost:3030/")
|
PANDOC_SERVER_URL = os.getenv("PANDOC_SERVER_URL", r"http://localhost:3030/")
|
||||||
PANDOC_TIMEOUT = int(os.getenv("PANDOC_TIMEOUT", "120"))
|
PANDOC_TIMEOUT = int(os.getenv("PANDOC_TIMEOUT", "120"))
|
||||||
CSS_DIR = Path(os.getenv("CSS_DIR", "/opt/gronk/css"))
|
GRONK_CSS_DIR = Path(os.getenv("CSS_DIR", "/opt/gronk/css"))
|
||||||
JS_DIR = Path(os.getenv("JS_DIR", "/opt/gronk/js"))
|
GRONK_JS_DIR = Path(os.getenv("JS_DIR", "/opt/gronk/js"))
|
||||||
TEMPLATES_DIR = Path(os.getenv("TEMPLATES_DIR", "/opt/gronk/templates"))
|
GRONK_TEMPLATES_DIR = Path(os.getenv("TEMPLATES_DIR", "/opt/gronk/templates"))
|
||||||
|
|
||||||
|
JINJA_ENV = jinja2.Environment(loader=jinja2.PackageLoader("gronk"),
|
||||||
JINJA_ENV = jinja2.Environment(
|
autoescape=jinja2.select_autoescape)
|
||||||
loader=jinja2.PackageLoader("gronk", str(TEMPLATES_DIR)),
|
|
||||||
autoescape=jinja2.select_autoescape
|
|
||||||
)
|
|
||||||
|
|
||||||
JINJA_TEMPLATES = {}
|
JINJA_TEMPLATES = {}
|
||||||
JINJA_TEMPLATE_TEXTARTICLE = JINJA_ENV.get_template("textarticle.html")
|
JINJA_TEMPLATE_TEXTARTICLE = JINJA_ENV.get_template("article-text.html")
|
||||||
JINJA_TEMPLATE_HOME_INDEX = JINJA_ENV.get_template("home_index.html")
|
JINJA_TEMPLATE_HOME_INDEX = JINJA_ENV.get_template("home.html")
|
||||||
JINJA_TEMPLATE_INDEX = JINJA_ENV.get_template("index.html")
|
JINJA_TEMPLATE_INDEX = JINJA_ENV.get_template("index.html")
|
||||||
JINJA_TEMPLATE_ARTICLE = JINJA_ENV.get_template("article.html")
|
JINJA_TEMPLATE_ARTICLE = JINJA_ENV.get_template("article.html")
|
||||||
|
JINJA_TEMPLATE_PERMALINK = JINJA_ENV.get_template("permalink.html")
|
||||||
|
|
||||||
LICENSE = None
|
LICENSE = None
|
||||||
GIT_REPO = None
|
|
||||||
FILEMAP = None
|
FILEMAP = None
|
||||||
|
|
||||||
|
|
||||||
|
class FileMap:
|
||||||
|
"""
|
||||||
|
this class is used to read file properties, inherit properties,
|
||||||
|
and have a centralised place to access them
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, input_dir, output_dir):
|
||||||
|
self._map = {}
|
||||||
|
self.input_dir = Path(input_dir)
|
||||||
|
self.output_dir = Path(output_dir)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _path_to_key(path):
|
||||||
|
return str(path)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_plaintext(filename):
|
||||||
|
return re.match(r'^text/', magic.from_file(str(filename),
|
||||||
|
mime=True)) is not None
|
||||||
|
|
||||||
|
def add(self, filepath):
|
||||||
|
filepath = Path(filepath)
|
||||||
|
if filepath.is_dir():
|
||||||
|
properties = self._get_directory_properties(filepath)
|
||||||
|
else:
|
||||||
|
properties = self._get_file_properties(filepath)
|
||||||
|
|
||||||
|
properties['src_path'] = filepath
|
||||||
|
properties['dst_path'] = self._get_output_filepath(filepath)
|
||||||
|
|
||||||
|
self._map[self._path_to_key(filepath)] = properties
|
||||||
|
|
||||||
|
def get(self, filepath, default=None, raw=False):
|
||||||
|
"""
|
||||||
|
get the properties of a file at a filepath
|
||||||
|
raw=True to not inherit properties
|
||||||
|
"""
|
||||||
|
# TODO maybe store properties of a file once it's in built and mark it
|
||||||
|
# as built? might save time but also cba
|
||||||
|
if self._path_to_key(filepath) not in self._map.keys():
|
||||||
|
self.add(filepath)
|
||||||
|
|
||||||
|
properties = copy.deepcopy(
|
||||||
|
self._map.get(self._path_to_key(filepath), default))
|
||||||
|
|
||||||
|
if raw:
|
||||||
|
return properties
|
||||||
|
|
||||||
|
parent = filepath
|
||||||
|
while True:
|
||||||
|
parent = parent.parent
|
||||||
|
if parent == Path('.'):
|
||||||
|
break
|
||||||
|
|
||||||
|
parent_properties = self.get(parent, raw=True)
|
||||||
|
# TODO inherit any property that isn't defined, append any lists
|
||||||
|
# that exist
|
||||||
|
properties['tags'] = properties.get(
|
||||||
|
'tags', []) + parent_properties.get('tags', [])
|
||||||
|
|
||||||
|
if parent == self.input_dir:
|
||||||
|
break
|
||||||
|
|
||||||
|
return properties
|
||||||
|
|
||||||
|
def _get_directory_properties(self,
|
||||||
|
filepath: Path,
|
||||||
|
include_index_entries=True):
|
||||||
|
post = {
|
||||||
|
'title': filepath.name,
|
||||||
|
'content_after_search': False,
|
||||||
|
'automatic_index': True,
|
||||||
|
'search_bar': True,
|
||||||
|
'tags': [],
|
||||||
|
}
|
||||||
|
|
||||||
|
if 'index.md' in [f.name for f in filepath.iterdir()]:
|
||||||
|
with open(filepath.joinpath('index.md'),
|
||||||
|
encoding='utf-8') as file_pointer:
|
||||||
|
for key, val in frontmatter.load(
|
||||||
|
file_pointer).to_dict().items():
|
||||||
|
post[key] = val
|
||||||
|
|
||||||
|
if 'content' in post.keys():
|
||||||
|
post['content'] = render_markdown(post['content'])
|
||||||
|
|
||||||
|
post['is_dir'] = True
|
||||||
|
|
||||||
|
if include_index_entries:
|
||||||
|
post['index_entries'] = self._get_index_entries(filepath)
|
||||||
|
|
||||||
|
return post
|
||||||
|
|
||||||
|
def _get_index_entries(self, filepath):
|
||||||
|
entries = []
|
||||||
|
|
||||||
|
for path in filepath.iterdir():
|
||||||
|
if path.is_dir():
|
||||||
|
entry = self._get_directory_properties(
|
||||||
|
path, include_index_entries=False)
|
||||||
|
else:
|
||||||
|
entry = self._get_file_properties(path)
|
||||||
|
|
||||||
|
entry['path'] = self._get_output_filepath(path)['web']
|
||||||
|
entries.append(entry)
|
||||||
|
|
||||||
|
entries.sort(key=lambda entry: str(entry.get('title', '')).lower())
|
||||||
|
entries.sort(key=lambda entry: entry['is_dir'], reverse=True)
|
||||||
|
|
||||||
|
return entries
|
||||||
|
|
||||||
|
def _get_file_properties(self, filepath):
|
||||||
|
post = {'title': filepath.name}
|
||||||
|
|
||||||
|
if filepath.suffix == '.md':
|
||||||
|
with open(filepath, encoding='utf-8') as file_pointer:
|
||||||
|
post = frontmatter.load(file_pointer).to_dict()
|
||||||
|
|
||||||
|
# don't store file contents in memory
|
||||||
|
if 'content' in post.keys():
|
||||||
|
del post['content']
|
||||||
|
post['is_dir'] = False
|
||||||
|
|
||||||
|
return post
|
||||||
|
|
||||||
|
def _get_output_filepath(self, input_filepath):
|
||||||
|
|
||||||
|
def webpath(filepath):
|
||||||
|
return Path('/notes').joinpath(
|
||||||
|
filepath.relative_to(self.output_dir))
|
||||||
|
|
||||||
|
r = {}
|
||||||
|
r['raw'] = self.output_dir.joinpath(
|
||||||
|
input_filepath.relative_to(self.input_dir))
|
||||||
|
r['web'] = webpath(r['raw'])
|
||||||
|
|
||||||
|
if input_filepath.is_dir():
|
||||||
|
return r
|
||||||
|
|
||||||
|
if input_filepath.suffix == '.md':
|
||||||
|
r['html'] = self.output_dir.joinpath(
|
||||||
|
input_filepath.relative_to(
|
||||||
|
self.input_dir)).with_suffix('.html')
|
||||||
|
r['web'] = webpath(r['html'])
|
||||||
|
|
||||||
|
elif self.is_plaintext(input_filepath):
|
||||||
|
r['html'] = self.output_dir.joinpath(
|
||||||
|
input_filepath.relative_to(
|
||||||
|
self.input_dir)).with_suffix(input_filepath.suffix +
|
||||||
|
'.html')
|
||||||
|
r['raw'] = self.output_dir.joinpath(
|
||||||
|
input_filepath.relative_to(self.input_dir))
|
||||||
|
r['web'] = webpath(r['html'])
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
def to_list(self):
|
||||||
|
return [val for _, val in self._map.items()]
|
||||||
|
|
||||||
|
def to_search_data(self):
|
||||||
|
"""
|
||||||
|
returns list of every file in map
|
||||||
|
"""
|
||||||
|
r = []
|
||||||
|
for _, val in self._map.items():
|
||||||
|
r.append({
|
||||||
|
'title': val.get('title', ''),
|
||||||
|
'tags': val.get('tags', []),
|
||||||
|
'path': str(val['dst_path']['web']),
|
||||||
|
'is_dir': val['is_dir']
|
||||||
|
})
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
def get_uuid_map(self):
|
||||||
|
d = {}
|
||||||
|
for _, val in self._map.items():
|
||||||
|
if 'uuid' not in val.keys():
|
||||||
|
continue
|
||||||
|
d[val['uuid']] = str(val['dst_path']['web'])
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
def update_required(src_filepath, output_filepath):
|
def update_required(src_filepath, output_filepath):
|
||||||
"""
|
"""
|
||||||
check if file requires an update,
|
check if file requires an update,
|
||||||
return boolean
|
return boolean
|
||||||
"""
|
"""
|
||||||
return not output_filepath.exists() or src_filepath.stat().st_mtime > output_filepath.stat().st_mtimeme()
|
return not output_filepath.exists() or src_filepath.stat(
|
||||||
|
).st_mtime > output_filepath.stat().st_mtimeme()
|
||||||
|
|
||||||
|
|
||||||
def get_args():
|
def get_args():
|
||||||
@ -62,8 +240,13 @@ def get_args():
|
|||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('notes', type=Path)
|
parser.add_argument('notes', type=Path)
|
||||||
parser.add_argument('-o', '--output-dir', type=Path, default='web')
|
parser.add_argument('-o', '--output-dir', type=Path, default='web')
|
||||||
parser.add_argument('-F', '--force', action="store_true",
|
parser.add_argument(
|
||||||
help="Generate new output html even if source file was modified before output html")
|
'-F',
|
||||||
|
'--force',
|
||||||
|
action="store_true",
|
||||||
|
help=
|
||||||
|
"Generate new output html even if source file was modified before output html"
|
||||||
|
)
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
@ -73,17 +256,23 @@ def render_markdown_file(input_filepath):
|
|||||||
write markdown file to args.output_dir in html,
|
write markdown file to args.output_dir in html,
|
||||||
return list of tuple of output filepath, frontmatter post
|
return list of tuple of output filepath, frontmatter post
|
||||||
"""
|
"""
|
||||||
print(f"render_markdown_file({input_filepath})")
|
|
||||||
with open(input_filepath, encoding='utf-8') as file_pointer:
|
with open(input_filepath, encoding='utf-8') as file_pointer:
|
||||||
content = frontmatter.load(file_pointer).content
|
content = frontmatter.load(file_pointer).content
|
||||||
|
|
||||||
properties = FILEMAP.get(input_filepath)
|
properties = FILEMAP.get(input_filepath)
|
||||||
|
|
||||||
# TODO pandoc no longer handles template due to metadata passing issues, use jinja to fill in the metadata
|
|
||||||
html = render_markdown(content)
|
html = render_markdown(content)
|
||||||
|
html = JINJA_TEMPLATE_ARTICLE.render(
|
||||||
|
license=LICENSE,
|
||||||
|
content=html,
|
||||||
|
lecture_slides=properties.get("lecture_slides"),
|
||||||
|
lecture_notes=properties.get("lecture_notes"),
|
||||||
|
uuid=properties.get("uuid"),
|
||||||
|
tags=properties.get("tags"),
|
||||||
|
author=properties.get("author"),
|
||||||
|
title=properties.get("title"))
|
||||||
|
|
||||||
with open(properties['dst_path']['html'], 'w+', encoding='utf-8') as file_pointer:
|
properties['dst_path']['html'].write_text(html)
|
||||||
file_pointer.write(html)
|
|
||||||
|
|
||||||
|
|
||||||
def render_plaintext_file(input_filepath):
|
def render_plaintext_file(input_filepath):
|
||||||
@ -93,18 +282,11 @@ def render_plaintext_file(input_filepath):
|
|||||||
return list of tuple of output filepath, empty dict
|
return list of tuple of output filepath, empty dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with open(input_filepath, encoding='utf-8') as file_pointer:
|
raw_content = input_filepath.read_text()
|
||||||
raw_content = file_pointer.read()
|
|
||||||
|
|
||||||
properties = FILEMAP.get(input_filepath)
|
properties = FILEMAP.get(input_filepath)
|
||||||
|
html = JINJA_TEMPLATE_TEXTARTICLE.render(license=LICENSE, **properties)
|
||||||
html = JINJA_TEMPLATE_TEXTARTICLE.render(license = LICENSE, **properties)
|
properties['dst_path']['raw'].write_text(raw_content)
|
||||||
|
properties['dst_path']['html'].write_text(html)
|
||||||
with open(properties['dst_path']['raw'], "w+", encoding='utf-8') as file_pointer:
|
|
||||||
file_pointer.write(raw_content)
|
|
||||||
|
|
||||||
with open(properties['dst_path']['html'], "w+", encoding='utf-8') as file_pointer:
|
|
||||||
file_pointer.write(html)
|
|
||||||
|
|
||||||
|
|
||||||
def render_generic_file(input_filepath):
|
def render_generic_file(input_filepath):
|
||||||
@ -140,49 +322,39 @@ def render_markdown(content):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
post_body = {
|
post_body = {
|
||||||
'text': content,
|
'text': content,
|
||||||
'toc-depth': 6,
|
'toc-depth': 6,
|
||||||
'highlight-style': 'pygments',
|
'highlight-style': 'pygments',
|
||||||
'html-math-method': 'mathml',
|
'html-math-method': 'mathml',
|
||||||
'to': 'html',
|
'to': 'html',
|
||||||
'files': {
|
'files': {
|
||||||
'data/data/abbreviations': '',
|
'data/data/abbreviations': '',
|
||||||
},
|
},
|
||||||
'standalone': False,
|
'standalone': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
headers = {
|
headers = {'Accept': 'application/json'}
|
||||||
'Accept': 'application/json'
|
|
||||||
}
|
|
||||||
|
|
||||||
response = requests.post(
|
response = requests.post(PANDOC_SERVER_URL,
|
||||||
PANDOC_SERVER_URL,
|
headers=headers,
|
||||||
headers=headers,
|
json=post_body,
|
||||||
json=post_body,
|
timeout=PANDOC_TIMEOUT)
|
||||||
timeout=PANDOC_TIMEOUT
|
|
||||||
)
|
|
||||||
|
|
||||||
response = response.json()
|
response = response.json()
|
||||||
|
|
||||||
|
|
||||||
# TODO look at response['messages'] and log them maybe?
|
# TODO look at response['messages'] and log them maybe?
|
||||||
# https://github.com/jgm/pandoc/blob/main/doc/pandoc-server.md#response
|
# https://github.com/jgm/pandoc/blob/main/doc/pandoc-server.md#response
|
||||||
|
|
||||||
return response['output']
|
return response['output']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def process_home_index(args, notes_git_head_sha1=None):
|
def process_home_index(args, notes_git_head_sha1=None):
|
||||||
"""
|
"""
|
||||||
create home index.html in output_dir
|
create home index.html in output_dir
|
||||||
"""
|
"""
|
||||||
|
|
||||||
post = {
|
post = {'title': 'gronk', 'content': ''}
|
||||||
'title': 'gronk',
|
|
||||||
'content': ''
|
|
||||||
}
|
|
||||||
custom_content_file = args.notes.joinpath('index.md')
|
custom_content_file = args.notes.joinpath('index.md')
|
||||||
print(f'{custom_content_file=}')
|
|
||||||
if custom_content_file.is_file():
|
if custom_content_file.is_file():
|
||||||
fmpost = frontmatter.loads(custom_content_file.read_text()).to_dict()
|
fmpost = frontmatter.loads(custom_content_file.read_text()).to_dict()
|
||||||
for key, val in fmpost.items():
|
for key, val in fmpost.items():
|
||||||
@ -191,16 +363,27 @@ def process_home_index(args, notes_git_head_sha1=None):
|
|||||||
post['content'] = render_markdown(post['content'])
|
post['content'] = render_markdown(post['content'])
|
||||||
|
|
||||||
html = JINJA_TEMPLATE_HOME_INDEX.render(
|
html = JINJA_TEMPLATE_HOME_INDEX.render(
|
||||||
gronk_commit = GRONK_COMMIT,
|
gronk_commit=GRONK_COMMIT,
|
||||||
search_data = FILEMAP.to_search_data(),
|
search_data=FILEMAP.to_search_data(),
|
||||||
notes_git_head_sha1 = notes_git_head_sha1,
|
notes_git_head_sha1=notes_git_head_sha1,
|
||||||
post=post
|
post=post)
|
||||||
)
|
|
||||||
|
|
||||||
args.output_dir.joinpath('index.html').write_text(html)
|
args.output_dir.joinpath('index.html').write_text(html)
|
||||||
|
|
||||||
|
|
||||||
def generate_tag_browser(output_dir) :
|
def generate_permalink_page(output_dir):
|
||||||
|
"""
|
||||||
|
create the directory and index.html for redirecting permalinks
|
||||||
|
"""
|
||||||
|
|
||||||
|
dir = output_dir.joinpath('permalink')
|
||||||
|
dir.mkdir(exist_ok=True)
|
||||||
|
dir.joinpath('index.html').write_text(
|
||||||
|
JINJA_TEMPLATE_PERMALINK.render(gronk_commit=GRONK_COMMIT,
|
||||||
|
data=FILEMAP.get_uuid_map()))
|
||||||
|
|
||||||
|
|
||||||
|
def generate_tag_browser(output_dir):
|
||||||
"""
|
"""
|
||||||
generate a directory that lets you groub by and browse by any given tag. e.g. tags, authors
|
generate a directory that lets you groub by and browse by any given tag. e.g. tags, authors
|
||||||
"""
|
"""
|
||||||
@ -218,36 +401,47 @@ def generate_tag_browser(output_dir) :
|
|||||||
|
|
||||||
tags[tag].append(post)
|
tags[tag].append(post)
|
||||||
|
|
||||||
|
|
||||||
for tag, index_entries in tags.items():
|
for tag, index_entries in tags.items():
|
||||||
output_file = output_dir.joinpath(tag, 'index.html')
|
output_file = output_dir.joinpath(tag, 'index.html')
|
||||||
output_file.parent.mkdir(exist_ok=True, parents=True)
|
output_file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
output_file.write_text(JINJA_TEMPLATE_INDEX.render(
|
output_file.write_text(
|
||||||
|
JINJA_TEMPLATE_INDEX.render(
|
||||||
|
gronk_commit=GRONK_COMMIT,
|
||||||
automatic_index=True,
|
automatic_index=True,
|
||||||
search_bar=True,
|
search_bar=True,
|
||||||
title=tag,
|
title=tag,
|
||||||
index_entries = index_entries
|
index_entries=[{
|
||||||
))
|
'title': entry.get('title', ''),
|
||||||
|
'is_dir': entry.get('is_dir', False),
|
||||||
|
'path': str(entry.get('path', Path(''))),
|
||||||
|
} for entry in index_entries],
|
||||||
|
))
|
||||||
|
|
||||||
output_file = output_dir.joinpath('index.html')
|
output_file = output_dir.joinpath('index.html')
|
||||||
output_file.parent.mkdir(exist_ok=True, parents=True)
|
output_file.parent.mkdir(exist_ok=True, parents=True)
|
||||||
output_file.write_text(JINJA_TEMPLATE_INDEX.render(
|
output_file.write_text(
|
||||||
automatic_index=True,
|
JINJA_TEMPLATE_INDEX.render(automatic_index=True,
|
||||||
search_bar=True,
|
gronk_commit=GRONK_COMMIT,
|
||||||
title='tags',
|
search_bar=True,
|
||||||
index_entries = [{ 'path': tag, 'title': tag, 'is_dir': False, } for tag in tags.keys()]
|
title='tags',
|
||||||
))
|
index_entries=[{
|
||||||
|
'path': tag,
|
||||||
|
'title': tag,
|
||||||
|
'is_dir': False,
|
||||||
|
} for tag in tags.keys()]))
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
""" Entry point for script """
|
""" Entry point for script """
|
||||||
|
|
||||||
global LICENSE
|
global LICENSE
|
||||||
global GIT_REPO
|
|
||||||
global FILEMAP
|
global FILEMAP
|
||||||
|
|
||||||
FILEMAP = FileMap(args.notes, args.output_dir.joinpath('notes'))
|
FILEMAP = FileMap(args.notes, args.output_dir.joinpath('notes'))
|
||||||
|
|
||||||
|
# TODO have some sort of 'site rebuild in progress - come back in a minute
|
||||||
|
# or two!' or auto checking/refreshing page for when site is being built
|
||||||
|
|
||||||
if args.output_dir.is_file():
|
if args.output_dir.is_file():
|
||||||
print(f"Output directory ({args.output_dir}) cannot be a file.")
|
print(f"Output directory ({args.output_dir}) cannot be a file.")
|
||||||
|
|
||||||
@ -256,15 +450,11 @@ def main(args):
|
|||||||
# attempt to get licensing information
|
# attempt to get licensing information
|
||||||
license_path = args.notes.joinpath("LICENSE")
|
license_path = args.notes.joinpath("LICENSE")
|
||||||
if license_path.exists():
|
if license_path.exists():
|
||||||
with open(license_path, encoding='utf-8') as file_pointer:
|
LICENSE = license_path.read_text()
|
||||||
LICENSE = file_pointer.read()
|
|
||||||
|
|
||||||
# create git.Repo object if notes dir is a git repo
|
|
||||||
# TODO git commit log integration
|
# TODO git commit log integration
|
||||||
if '.git' in args.notes.iterdir():
|
|
||||||
GIT_REPO = git.Repo(args.notes)
|
|
||||||
|
|
||||||
for root_str, subdirectories, files in os.walk(args.notes):
|
for root_str, _, files in os.walk(args.notes):
|
||||||
root = Path(root_str)
|
root = Path(root_str)
|
||||||
if '.git' in root.parts:
|
if '.git' in root.parts:
|
||||||
continue
|
continue
|
||||||
@ -272,22 +462,42 @@ def main(args):
|
|||||||
root_properties = FILEMAP.get(root)
|
root_properties = FILEMAP.get(root)
|
||||||
root_properties['dst_path']['raw'].mkdir(parents=True, exist_ok=True)
|
root_properties['dst_path']['raw'].mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
#pprint.pprint(root_properties)
|
pprint.pprint(root_properties)
|
||||||
html = JINJA_TEMPLATE_INDEX.render(**root_properties)
|
html = JINJA_TEMPLATE_INDEX.render(
|
||||||
with open(root_properties['dst_path']['raw'].joinpath('index.html'), 'w+', encoding='utf-8') as file_pointer:
|
gronk_commit=GRONK_COMMIT,
|
||||||
file_pointer.write(html)
|
title=root_properties.get('title', ''),
|
||||||
|
content=root_properties.get('content', ''),
|
||||||
|
content_after_search=root_properties['content_after_search'],
|
||||||
|
automatic_index=root_properties['automatic_index'],
|
||||||
|
search_bar=root_properties['search_bar'],
|
||||||
|
index_entries=[{
|
||||||
|
'title': entry.get('title', ''),
|
||||||
|
'is_dir': entry.get('is_dir', False),
|
||||||
|
'path': str(entry.get('path', Path(''))),
|
||||||
|
} for entry in root_properties.get('index_entries', '')],
|
||||||
|
)
|
||||||
|
root_properties['dst_path']['raw'].joinpath('index.html').write_text(
|
||||||
|
html)
|
||||||
|
|
||||||
# render each file
|
# render each file
|
||||||
for file in files:
|
for file in files:
|
||||||
|
# don't render index.md as index as it is used for directory
|
||||||
|
if file == "index.md":
|
||||||
|
continue
|
||||||
render_file(root.joinpath(file))
|
render_file(root.joinpath(file))
|
||||||
|
|
||||||
process_home_index(args)
|
process_home_index(args)
|
||||||
|
|
||||||
# copy styling and js scripts necessary for function
|
# copy styling and js scripts necessary for function
|
||||||
shutil.copytree(CSS_DIR, args.output_dir.joinpath('css'), dirs_exist_ok=True)
|
shutil.copytree(GRONK_CSS_DIR,
|
||||||
shutil.copytree(JS_DIR, args.output_dir.joinpath('js'), dirs_exist_ok=True)
|
args.output_dir.joinpath('css'),
|
||||||
|
dirs_exist_ok=True)
|
||||||
|
shutil.copytree(GRONK_JS_DIR,
|
||||||
|
args.output_dir.joinpath('js'),
|
||||||
|
dirs_exist_ok=True)
|
||||||
|
|
||||||
generate_tag_browser(args.output_dir.joinpath('tags'))
|
generate_tag_browser(args.output_dir.joinpath('tags'))
|
||||||
|
generate_permalink_page(args.output_dir)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -295,7 +505,14 @@ def main(args):
|
|||||||
# TODO implement useful logging and debug printing
|
# TODO implement useful logging and debug printing
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
pandoc_process = subprocess.Popen(["/usr/bin/pandoc-server"],
|
||||||
|
stdout=subprocess.PIPE)
|
||||||
|
time.sleep(1)
|
||||||
|
print(pandoc_process.stdout)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sys.exit(main(get_args()))
|
sys.exit(main(get_args()))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
finally:
|
||||||
|
pandoc_process.kill()
|
||||||
|
29
gronk_add_uuid.py
Executable file → Normal file
29
gronk_add_uuid.py
Executable file → Normal file
@ -1,36 +1,41 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import editfrontmatter
|
|
||||||
import frontmatter
|
|
||||||
import pathlib
|
import pathlib
|
||||||
import sys
|
import sys
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import editfrontmatter
|
||||||
|
import frontmatter
|
||||||
|
|
||||||
|
|
||||||
def get_args():
|
def get_args():
|
||||||
""" Get command line arguments """
|
""" Get command line arguments """
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('filename', type=pathlib.Path)
|
parser.add_argument('filename', type=pathlib.Path)
|
||||||
parser.add_argument('-w', '--write', action='store_true',
|
parser.add_argument('-w',
|
||||||
help='write to file instead of stdout')
|
'--write',
|
||||||
|
action='store_true',
|
||||||
|
help='write to file instead of stdout')
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
""" Entry point for script """
|
""" Entry point for script """
|
||||||
template_str= [
|
template_str = "\n".join([
|
||||||
"author: {{ author }}"
|
"author: {{ author }}"
|
||||||
"date: {{ date }}"
|
"date: {{ date }}"
|
||||||
"title: {{ title }}"
|
"title: {{ title }}"
|
||||||
"tags: {{ tags }}"
|
"tags: {{ tags }}"
|
||||||
"uuid: {{ uuid }}"
|
"uuid: {{ uuid }}"
|
||||||
].join("\n")
|
])
|
||||||
|
|
||||||
with open(args.filename) as fp:
|
with open(args.filename) as fp:
|
||||||
fm_pre = frontmatter.load(fp)
|
fm_pre = frontmatter.load(fp)
|
||||||
|
|
||||||
processor = editfrontmatter.EditFrontMatter(file_path=args.filename, template_str=template_str)
|
processor = editfrontmatter.EditFrontMatter(file_path=args.filename,
|
||||||
|
template_str=template_str)
|
||||||
fm_data = fm_pre.metadata
|
fm_data = fm_pre.metadata
|
||||||
if 'uuid' not in fm_data.keys():
|
if 'uuid' not in fm_data.keys():
|
||||||
fm_data['uuid'] = str(uuid.uuid4())
|
fm_data['uuid'] = str(uuid.uuid4())
|
||||||
|
@ -76,7 +76,7 @@ Combine it with `find` to UUIDify all your markdown files (but make a backup fir
|
|||||||
|
|
||||||
## Custom Styling
|
## Custom Styling
|
||||||
|
|
||||||
To completely replace the existing styling, set the environment variable `CSS_DIR` to another directory with
|
To completely replace the existing styling, set the environment variable `GRONK_CSS_DIR` to another directory with
|
||||||
a file called `styles.css`.
|
a file called `styles.css`.
|
||||||
|
|
||||||
To add additional styling, the default styling will attempt to import `styles.css` from the root of the notes
|
To add additional styling, the default styling will attempt to import `styles.css` from the root of the notes
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
beautifulsoup4==4.9.3
|
beautifulsoup4==4.9.3
|
||||||
|
certifi==2023.7.22
|
||||||
|
charset-normalizer==3.2.0
|
||||||
editfrontmatter==0.0.1
|
editfrontmatter==0.0.1
|
||||||
|
gitdb==4.0.10
|
||||||
|
GitPython==3.1.36
|
||||||
|
idna==3.4
|
||||||
Jinja2==3.0.3
|
Jinja2==3.0.3
|
||||||
MarkupSafe==2.1.0
|
MarkupSafe==2.1.0
|
||||||
oyaml==1.0
|
oyaml==1.0
|
||||||
pypandoc==1.5
|
pypandoc==1.5
|
||||||
python-frontmatter==1.0.0
|
python-frontmatter==1.0.0
|
||||||
python-magic==0.4.24
|
python-magic==0.4.24
|
||||||
regex==2021.11.10
|
|
||||||
soupsieve==2.2.1
|
|
||||||
PyYAML==6.0.1
|
PyYAML==6.0.1
|
||||||
|
regex==2021.11.10
|
||||||
|
requests==2.31.0
|
||||||
|
smmap==5.0.1
|
||||||
|
soupsieve==2.2.1
|
||||||
|
urllib3==2.0.4
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{% extends "article.html" %}
|
{% extends "article.html" %}
|
||||||
{% block body %}
|
{% block body_content %}
|
||||||
<p> This file was not rendered by gronk because it is a plaintext file, not a markdown
|
<p> This file was not rendered by gronk because it is a plaintext file, not a markdown
|
||||||
file.
|
file.
|
||||||
You access the raw file <a href="{{ raw_link }}">here</a>.
|
You access the raw file <a href="{{ raw_link }}">here</a>.
|
@ -1,8 +1,5 @@
|
|||||||
<head>
|
{% extends "base.html" %}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
{% block head %}
|
||||||
<meta charset="utf-8">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/styles.css" />
|
|
||||||
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
|
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
|
||||||
<script>
|
<script>
|
||||||
MathJax = {
|
MathJax = {
|
||||||
@ -12,62 +9,57 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||||||
<title>{{ title }}</title>
|
{% endblock %}
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
{% block content %}
|
||||||
<div id="contentWrapper">
|
<p class="smallText metadata"> title: {{ title }} </p>
|
||||||
<div id="content">
|
{% if lecture_slides %}
|
||||||
<p class="smallText metadata"> title: {{ title }} </p>
|
<p class="smallText metadata"> lecture_slides: [
|
||||||
{% if lecture_slides %}
|
{% for slide in lecture_slides %}
|
||||||
<p class="smallText metadata"> lecture_slides: [
|
<a href="{{ slide }}">{{ slide }}</a>{% if loop.nextitem %},{% endif %}
|
||||||
{% for slide in lecture_slides %}
|
{% endfor %}
|
||||||
<a href="{{ slide }}">{{ slide }}</a>{% if loop.nextitem %},{% endif %}
|
]</p>
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
]</p>
|
{% if lecture_notes %}
|
||||||
{% endif %}
|
<p class="smallText metadata"> lecture_notes: [
|
||||||
{% if lecture_notes %}
|
{% for note in lecture_notes %}
|
||||||
<p class="smallText metadata"> lecture_notes: [
|
<a href="{{ note }}">{{ note }}</a>{% if loop.nextitem %},{% endif %}
|
||||||
{% for note in lecture_notes %}
|
{% endfor %}
|
||||||
<a href="{{ note }}">{{ note }}</a>{% if loop.nextitem %},{% endif %}
|
]</p>
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
]</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if uuid %}
|
{% if uuid %}
|
||||||
<p class="smallText metadata"> uuid: {{ uuid }} (<a href="/permalink?uuid={{ uuid }}">permalink</a>) </p>
|
<p class="smallText metadata"> uuid: {{ uuid }} (<a href="/permalink?uuid={{ uuid }}">permalink</a>) </p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<p class="smallText metadata"> tags: [
|
<p class="smallText metadata"> tags: [
|
||||||
{% for tag in tags %}
|
{% for tag in tags %}
|
||||||
<a href="/tags/{{ tag }}">{{ tag }}</a>{% if loop.nextitem %},{% endif %}
|
<a href="/tags/{{ tag }}">{{ tag }}</a>{% if loop.nextitem %},{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
]</p>
|
]</p>
|
||||||
<p class="smallText metadata">
|
<p class="smallText metadata">
|
||||||
{% if author is iterable %}
|
{% if author is string %}
|
||||||
written by {{ author }}
|
written by: {{ author }}
|
||||||
{% else %}
|
{% elif author is iterable %}
|
||||||
written by {% for auth in author %}{{ auth }}{% if loop.nextitem %}, {% endif %}{% endfor %}
|
written by: [ {% for auth in author %}{{ auth }}{% if loop.nextitem %}, {% endif %}{% endfor %} ]
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
<p class="smallText metadata">
|
<p class="smallText metadata">
|
||||||
syntax highlighting based on <a href="https://pygments.org/">Pygments'</a> default
|
syntax highlighting based on <a href="https://pygments.org/">Pygments'</a> default
|
||||||
colors
|
colors
|
||||||
</p>
|
</p>
|
||||||
<p class="smallText metadata">
|
<p class="smallText metadata">
|
||||||
page generated by <a href="https://git.alv.cx/alvierahman90/gronk">gronk</a>
|
page generated by <a href="https://git.alv.cx/alvierahman90/gronk">gronk</a>
|
||||||
</p>
|
</p>
|
||||||
{% if license %}
|
{% if license %}
|
||||||
<details id="license">
|
<details id="license">
|
||||||
<summary class="smallText">
|
<summary class="smallText">
|
||||||
License
|
License
|
||||||
</summary>
|
</summary>
|
||||||
<pre>{{ license }}</pre>
|
<pre>{{ license }}</pre>
|
||||||
</details>
|
</details>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% block body %}
|
{% block body_content %}
|
||||||
{{ content }}
|
{{ content|safe }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
{% endblock %}
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
18
templates/base.html
Normal file
18
templates/base.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/styles.css" />
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
{% block head %}
|
||||||
|
{% endblock %}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</body>
|
18
templates/home.html
Normal file
18
templates/home.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{% extends "article.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{{ post['content']|safe }}
|
||||||
|
<p>
|
||||||
|
Browse <a href="/notes">here</a> or by tag <a href="/tags">here</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div id="searchWrapper">
|
||||||
|
<input autocomplete="off" placeholder="search" id="search" autofocus>
|
||||||
|
</div>
|
||||||
|
<p class="smallText" style="margin-top: 0; text-align: center;"> Press <kbd>Enter</kbd> to open first result or <kbd>Shift</kbd>+<kbd>Enter</kbd> to open in new tab</p>
|
||||||
|
<div id="results">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/js/fuse.js"> </script>
|
||||||
|
<script> const search_data = {{ search_data|tojson }} </script>
|
||||||
|
<script src="/js/search.js"> </script>
|
||||||
|
{% endblock %}
|
@ -1,27 +0,0 @@
|
|||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/styles.css" />
|
|
||||||
<title>{{ post['content'] }}</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="content">
|
|
||||||
{{ post['content']|safe }}
|
|
||||||
<p>
|
|
||||||
Browse <a href="/notes">here</a> or by tag <a href="/tags">here</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div id="searchWrapper">
|
|
||||||
<input autocomplete="off" placeholder="search" id="search" autofocus>
|
|
||||||
</div>
|
|
||||||
<p class="smallText" style="margin-top: 0; text-align: center;"> Press <kbd>Enter</kbd> to open first result or <kbd>Shift</kbd>+<kbd>Enter</kbd> to open in new tab</p>
|
|
||||||
<div id="results">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="smallText"> page generated by <a href="https://github.com/alvierahman90/gronk">gronk</a> (commit {{ n2w_commit }}) {% if notes_git_head_sha1 %}notes commit {{ notes_git_head_sha1 }}{% endif %}</p>
|
|
||||||
</div>
|
|
||||||
<script src="/js/fuse.js"> </script>
|
|
||||||
<script> const search_data = {{ search_data|tojson }} </script>
|
|
||||||
<script src="/js/search.js"> </script>
|
|
||||||
</body>
|
|
@ -1,17 +1,9 @@
|
|||||||
<head>
|
{% extends "base.html" %}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
{% block content %}
|
||||||
<meta charset="utf-8">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/styles.css" />
|
|
||||||
<title>{{ title }}</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="content">
|
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
|
|
||||||
{% if not content_after_search %}
|
{% if not content_after_search %}
|
||||||
{{ content }}
|
{{ content|safe }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if automatic_index %}
|
{% if automatic_index %}
|
||||||
@ -33,12 +25,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if content_after_search %}
|
{% if content_after_search %}
|
||||||
{{ content }}
|
{{ content|safe }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p style="font-size: 0.7em;"> page generated by <a href="https://github.com/alvierahman90/gronk">gronk</a></p>
|
|
||||||
</div>
|
|
||||||
<script src="/js/fuse.js"> </script>
|
<script src="/js/fuse.js"> </script>
|
||||||
<script> const search_data = {{ index_entries|tojson }} </script>
|
<script> const search_data = {{ index_entries|tojson }} </script>
|
||||||
<script src="/js/indexsearch.js"> </script>
|
<script src="/js/indexsearch.js"> </script>
|
||||||
</body>
|
{% endblock %}
|
||||||
|
|
||||||
|
10
templates/permalink.html
Normal file
10
templates/permalink.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{% block content %}
|
||||||
|
<p>
|
||||||
|
You should be being redirected...
|
||||||
|
Otherwise, click <a id="manual_redirect">here</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="smallText"> page generated by <a href="https://github.com/alvierahman90/gronk">gronk</a></p>
|
||||||
|
<script> const data = {{ data|tojson }} </script>
|
||||||
|
<script src="/js/permalink.js"> </script>
|
||||||
|
{% endblock %}
|
@ -1,19 +0,0 @@
|
|||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/styles.css" />
|
|
||||||
<title></title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="content">
|
|
||||||
<p>
|
|
||||||
You should be being redirected...
|
|
||||||
Otherwise, click <a id="manual_redirect">here</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="smallText"> page generated by <a href="https://github.com/alvierahman90/gronk">gronk</a></p>
|
|
||||||
</div>
|
|
||||||
<script> const data = {{ data|tojson }} </script>
|
|
||||||
<script src="/js/permalink.js"> </script>
|
|
||||||
</body>
|
|
Reference in New Issue
Block a user