convert script to python
This commit is contained in:
parent
08ed9d67ca
commit
7c5b082ee3
5
Makefile
5
Makefile
@ -1,8 +1,9 @@
|
||||
install:
|
||||
cp notes2web /usr/local/bin
|
||||
cp notes2web.py /usr/local/bin
|
||||
pip install -r requirement.txt
|
||||
mkdir -p /opt/notes2web
|
||||
cp -r templates /opt/notes2web
|
||||
cp styles.css /opt/notes2web
|
||||
|
||||
uninstall:
|
||||
rm -rf /usr/local/bin/notes2web/opt/notes2web
|
||||
rm -rf /usr/local/bin/notes2web.py /opt/notes2web
|
||||
|
137
notes2web
137
notes2web
@ -1,137 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
# set default config values, load user config, export config variables
|
||||
name=""
|
||||
output="web"
|
||||
article_template="/opt/notes2web/templates/article.html"
|
||||
textarticlehead_template="/opt/notes2web/templates/textarticlehead.html"
|
||||
textarticlefoot_template="/opt/notes2web/templates/textarticlefoot.html"
|
||||
listitem_template="/opt/notes2web/templates/listitem.html"
|
||||
index_template="/opt/notes2web/templates/index.html"
|
||||
stylesheet="/opt/notes2web/styles.css"
|
||||
|
||||
for configpath in "$HOME/.notes2web.conf" "$HOME/.config/notes2web/config" ".notes2web.conf"
|
||||
do
|
||||
[[ -f "$configpath" ]] && source "$configpath"
|
||||
done
|
||||
|
||||
export name
|
||||
export output
|
||||
export article_template
|
||||
export textarticlehead_template
|
||||
export textarticlefoot_template
|
||||
export listitem_template
|
||||
export index_template
|
||||
export stylesheet
|
||||
|
||||
|
||||
[[ "$1" == "--help" ]] && echo "USAGE: $0 [NOTES_DIRECTORY_1 [NOTES_DIRECTORY_2 [...]]]" && exit 0
|
||||
[[ "$1" == "--clean" ]] && {
|
||||
find -name ".2web" -exec rm {} \;
|
||||
rm -rf "$output"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
mkdir -p "$output"
|
||||
|
||||
|
||||
function _renderarticle {
|
||||
echo "rendering $1"
|
||||
mkdir -p "$(dirname "$output/${1}.html")"
|
||||
pandoc\
|
||||
--toc\
|
||||
--standalone\
|
||||
-t html\
|
||||
--template "$article_template"\
|
||||
-o "$output/${1}.html"\
|
||||
"$1"\
|
||||
--mathjax
|
||||
}
|
||||
|
||||
|
||||
function _rendertextarticle {
|
||||
[[ "$(file -b "$1")" == "ASCII text" ]] || exit
|
||||
echo "rendering text file $1"
|
||||
mkdir -p "$(dirname "$output/${1}.html")"
|
||||
sed -e "s#\\\$title\\\$#$1#" "$textarticlehead_template"\
|
||||
> "$output/${1}.html"
|
||||
cat "$1" >> "$output/${1}.html"
|
||||
cat "$textarticlefoot_template" >> "$output/${1}.html"
|
||||
}
|
||||
|
||||
|
||||
function _adddirtoindex {
|
||||
dir="$(dirname "$1")"
|
||||
echo "<h2>$(basename "$dir") notes</h2>" >> $output/index.md
|
||||
find "$dir" -name '*.md' -exec bash -c "_addarticletoindex '{}'" \;
|
||||
find "$dir" -not -path '**/.git/**' -not -name '*.md' -type f -exec bash -c "_addtextarticletoindex '{}'" \;
|
||||
}
|
||||
|
||||
|
||||
function _addtextarticletoindex {
|
||||
[[ "$(file -b "$1")" == "ASCII text" ]] || exit
|
||||
pandoc\
|
||||
-t html\
|
||||
-V "filepath=${1}.html"\
|
||||
-V "title=$1"\
|
||||
--template "$listitem_template"\
|
||||
"$1"\
|
||||
>> $output/index.md
|
||||
}
|
||||
|
||||
|
||||
function _addarticletoindex {
|
||||
echo "adding $1 to list of notes"
|
||||
pandoc\
|
||||
-t html\
|
||||
-V "filepath=${1}.html"\
|
||||
--template "$listitem_template"\
|
||||
"$1"\
|
||||
>> $output/index.md
|
||||
}
|
||||
|
||||
|
||||
export -f _renderarticle
|
||||
export -f _rendertextarticle
|
||||
export -f _adddirtoindex
|
||||
export -f _addarticletoindex
|
||||
export -f _addtextarticletoindex
|
||||
|
||||
|
||||
#render each markdown file in every folder passed in args
|
||||
for dir in "$@"
|
||||
do
|
||||
find "$dir" -name '*.md' -exec bash -c "_renderarticle '{}'" \;
|
||||
find "$dir" -not -path '**/.git/**' -not -name '*.md' -type f -exec bash -c "_rendertextarticle '{}'" \;
|
||||
done
|
||||
|
||||
|
||||
# create an intermediate markdown file of links to each article
|
||||
echo "---" > $output/index.md
|
||||
[[ -z "$name" ]] && echo "title: notes" >> $output/index.md || echo "title: ${name}'s notes" >> $output/index.md
|
||||
echo "---" >> $output/index.md
|
||||
|
||||
|
||||
# mark folders to be included in notes2web's index
|
||||
for file in "$@"
|
||||
do
|
||||
[[ ! -f "$file" ]] && echo "the presence of this files tells notes2web that it should be added to the notes2web index" > "$file/.2web"
|
||||
done
|
||||
|
||||
|
||||
# add articles to index and render
|
||||
find -name '.2web' -exec bash -c "_adddirtoindex '{}'" \;
|
||||
|
||||
|
||||
echo "copying styles.css to current directory"
|
||||
cp "$stylesheet" "$output/styles.css"
|
||||
|
||||
|
||||
echo "rendering index.md"
|
||||
pandoc\
|
||||
-t html\
|
||||
--template "$index_template"\
|
||||
-o "$output/index.html"\
|
||||
"$output/index.md"
|
169
notes2web.py
Executable file
169
notes2web.py
Executable file
@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
from bs4 import BeautifulSoup as bs
|
||||
import magic
|
||||
import sys
|
||||
import pathlib
|
||||
import pypandoc
|
||||
import shutil
|
||||
import os
|
||||
import re
|
||||
|
||||
TEXT_ARTICLE_TEMPLATE_FOOT = None
|
||||
TEXT_ARTICLE_TEMPLATE_HEAD = None
|
||||
INDEX_TEMPLATE_FOOT = None
|
||||
INDEX_TEMPLATE_HEAD = None
|
||||
|
||||
def get_files(folder):
|
||||
markdown = []
|
||||
plaintext = []
|
||||
other = []
|
||||
|
||||
for root, folders, files in os.walk(folder):
|
||||
for filename in files:
|
||||
name = os.path.join(root, filename)
|
||||
if os.path.splitext(name)[1] == '.md':
|
||||
markdown.append(name)
|
||||
elif re.match(r'^text/', magic.from_file(name, mime=True)):
|
||||
plaintext.append(name)
|
||||
other.append(name)
|
||||
else:
|
||||
other.append(name)
|
||||
|
||||
return markdown, plaintext, other
|
||||
|
||||
def get_dirs(folder):
|
||||
r = []
|
||||
|
||||
for root, folders, files in os.walk(folder):
|
||||
[r.append(os.path.join(root, folder)) for folder in folders]
|
||||
|
||||
return r
|
||||
|
||||
|
||||
def get_args():
|
||||
""" Get command line arguments """
|
||||
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('notes', type=pathlib.Path)
|
||||
parser.add_argument('-o', '--output-dir', type=pathlib.Path, default='web')
|
||||
parser.add_argument('-t', '--template', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/templates/article.html'))
|
||||
parser.add_argument('-H', '--template-text-head', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/templates/textarticlehead.html'))
|
||||
parser.add_argument('-f', '--template-text-foot', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/templates/textarticlefoot.html'))
|
||||
parser.add_argument('-i', '--template-index-head', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/templates/indexhead.html'))
|
||||
parser.add_argument('-I', '--template-index-foot', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/templates/indexfoot.html'))
|
||||
parser.add_argument('-s', '--stylesheet', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/styles.css'))
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main(args):
|
||||
""" Entry point for script """
|
||||
|
||||
with open(args.template_text_foot) as fp:
|
||||
TEXT_ARTICLE_TEMPLATE_FOOT = fp.read()
|
||||
|
||||
with open(args.template_text_head) as fp:
|
||||
TEXT_ARTICLE_TEMPLATE_HEAD = fp.read()
|
||||
|
||||
with open(args.template_index_foot) as fp:
|
||||
INDEX_TEMPLATE_FOOT = fp.read()
|
||||
|
||||
with open(args.template_index_head) as fp:
|
||||
INDEX_TEMPLATE_HEAD = fp.read()
|
||||
|
||||
if not os.path.exists(args.output_dir):
|
||||
os.makedirs(args.output_dir, exist_ok=True)
|
||||
|
||||
if os.path.isfile(args.output_dir):
|
||||
print("Output directory ({output_dir}) cannot be a file.")
|
||||
|
||||
|
||||
markdown_files, plaintext_files, other_files = get_files(args.notes)
|
||||
|
||||
print(f"{markdown_files=}")
|
||||
for filename in markdown_files:
|
||||
html = pypandoc.convert_file(filename, 'html', extra_args=[f'--template={args.template}'])
|
||||
output_filename = os.path.splitext(re.sub(f"^{args.notes.name}", args.output_dir.name, filename))[0] + '.html'
|
||||
os.makedirs(os.path.dirname(output_filename), exist_ok=True)
|
||||
|
||||
with open(output_filename, 'w+') as fp:
|
||||
fp.write(html)
|
||||
|
||||
print(f"{plaintext_files=}")
|
||||
for filename in plaintext_files:
|
||||
output_filename = re.sub(f"^{args.notes.name}", args.output_dir.name, filename) + '.html'
|
||||
os.makedirs(os.path.dirname(output_filename), exist_ok=True)
|
||||
title = os.path.basename(output_filename)
|
||||
html = re.sub(r'\$title\$', title, TEXT_ARTICLE_TEMPLATE_HEAD)
|
||||
html = re.sub(r'\$raw\$', os.path.basename(filename), html)
|
||||
with open(filename) as fp:
|
||||
html += fp.read()
|
||||
html += TEXT_ARTICLE_TEMPLATE_FOOT
|
||||
|
||||
with open(output_filename, 'w+') as fp:
|
||||
fp.write(html)
|
||||
|
||||
print(f"{other_files=}")
|
||||
for filename in other_files:
|
||||
output_filename = re.sub(f"^{args.notes.name}", args.output_dir.name, filename)
|
||||
os.makedirs(os.path.dirname(output_filename), exist_ok=True)
|
||||
shutil.copyfile(filename, output_filename)
|
||||
|
||||
|
||||
dirs_to_index = [args.output_dir.name] + get_dirs(args.output_dir)
|
||||
print(f"{dirs_to_index=}")
|
||||
for directory in dirs_to_index:
|
||||
paths = os.listdir(directory)
|
||||
print(f"{paths=}")
|
||||
|
||||
indexentries = []
|
||||
|
||||
for path in paths:
|
||||
if path == 'index.html':
|
||||
continue
|
||||
|
||||
fullpath = os.path.join(directory, path)
|
||||
print(fullpath)
|
||||
if os.path.splitext(path)[1] == '.html':
|
||||
with open(fullpath) as fp:
|
||||
soup = bs(fp.read(), 'html.parser')
|
||||
|
||||
try:
|
||||
title = soup.find('title').get_text()
|
||||
except AttributeError:
|
||||
title = path
|
||||
else:
|
||||
title = path
|
||||
|
||||
if title.strip() == '':
|
||||
title = path
|
||||
|
||||
indexentries.append({
|
||||
'title': title,
|
||||
'path': path,
|
||||
'isdirectory': os.path.isdir(fullpath)
|
||||
})
|
||||
|
||||
indexentries.sort(key=lambda entry: entry['title'])
|
||||
indexentries.sort(key=lambda entry: entry['isdirectory'], reverse=True)
|
||||
|
||||
html = re.sub(r'\$title\$', directory, INDEX_TEMPLATE_HEAD)
|
||||
for entry in indexentries:
|
||||
html += f"<div class=\"article\"><a href=\"{entry['path']}\">{entry['title']}{'/' if entry['isdirectory'] else ''}</a></div>"
|
||||
html += INDEX_TEMPLATE_FOOT
|
||||
|
||||
with open(os.path.join(directory, 'index.html'), 'w+') as fp:
|
||||
fp.write(html)
|
||||
|
||||
shutil.copyfile(args.stylesheet, os.path.join(args.output_dir.name, 'styles.css'))
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
sys.exit(main(get_args()))
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(0)
|
@ -18,7 +18,7 @@ View your notes as a static html site.
|
||||
## Usage
|
||||
|
||||
```
|
||||
$ notes2web NOTES_DIRECTORY_1 [NOTES_DIRECTORY_2 [...]]
|
||||
$ notes2web.py NOTES_DIRECTORY_1 [NOTES_DIRECTORY_2 [...]]
|
||||
```
|
||||
|
||||
The command will generate a website in the `$output` directory (`./web` by default).
|
||||
@ -28,6 +28,8 @@ Then you just have to point a webserver at `$output`.
|
||||
|
||||
## Config
|
||||
|
||||
NOT CURRENTLY IMPLEMENTED
|
||||
|
||||
`notes2web` looks for a config file called `.notes2web.conf` in your current directory and your home
|
||||
directory.
|
||||
Default config values:
|
||||
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
beautifulsoup4==4.9.3
|
||||
pypandoc==1.5
|
||||
soupsieve==2.2.1
|
2
templates/indexfoot.html
Normal file
2
templates/indexfoot.html
Normal file
@ -0,0 +1,2 @@
|
||||
<p style="font-size: 0.7em;"> page generated by <a href="https://github.com/alvierahman90/notes2web">notes2web</a></p>
|
||||
</body>
|
11
templates/indexhead.html
Normal file
11
templates/indexhead.html
Normal file
@ -0,0 +1,11 @@
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-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="/styles.css" />
|
||||
<title>$title$</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>$title$</h1>
|
||||
<div class="article"><a href="..">../</a></div>
|
@ -10,6 +10,7 @@
|
||||
<h1>$title$</h1>
|
||||
<p> This file was not rendered by notes2web because it is a plaintext file, not a markdown
|
||||
file.
|
||||
You access the raw file <a href="$raw$">here</a>.
|
||||
Below is an unformatted representation of the file:
|
||||
</p>
|
||||
<pre>
|
||||
|
Reference in New Issue
Block a user