Created
March 7, 2017 18:48
-
-
Save roipoussiere/a907f740325b52816d9d1d1c6dbd91dc to your computer and use it in GitHub Desktop.
A script to convert notes from markdown / PlantUML to HTML and Redmine wiki syntax, then publish files through rsync.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -* | |
""" | |
From a folder containing a set of markdown files, this script: | |
- generate HTML files; | |
- generate RedMine-compliant Textile files; | |
- generate UML diagrams (from PlantUML syntax) and insert the in HTML and Textile files; | |
- send images and HTML files to a server through rsync. | |
""" | |
import os | |
import os.path as op | |
import shlex | |
from subprocess import Popen, PIPE | |
from datetime import datetime | |
import getpass | |
PLANTUML_EXE = 'java -jar /usr/share/plantuml.jar' # PlantUML executable | |
PANDOC_EXE = 'pandoc' # Pandoc executable | |
USERPAGE_DIR = '/home/nathanael/userpage' # local directory where your .md files are | |
USER = 'njourdane' # Your userpages username (LDAP login) | |
PW = 'foo' # Password | |
WEB_DIR = op.join(USERPAGE_DIR, 'public_html') # Directory for HTML files | |
TEXTILE_DIR = op.join(USERPAGE_DIR, 'textile') # Directory for Textile files | |
IMG_DIR = op.join(WEB_DIR, 'images') # Directory for images | |
SERVER = 'userpages.irap.omp.eu' | |
PASSWORD = None # Let empty to enter the password on execution | |
HTML_HEADER = """<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Page perso de %s</title> | |
<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' | |
integrity='sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7' crossorigin='anonymous'> | |
<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css' | |
integrity='sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r' crossorigin='anonymous'> | |
<style> | |
html{ background-color:white } | |
body{ width:800px; margin:auto; padding:10px; background-color:aliceblue } | |
h1{ margin-left:10px; } | |
h3{ margin-left:30px; } | |
</style> | |
</head> | |
<body> | |
<script src='https://code.jquery.com/jquery-2.2.4.min.js' crossorigin='anonymous' | |
integrity='sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44='></script> | |
<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js' crossorigin='anonymous' | |
integrity='sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS'></script> | |
<script> \$(document).ready(function(){\$('table').addClass('table')}); </script> | |
<p><em>Page mise à jour le %s</em></p>""" % (USER, datetime.now().strftime('%d/%m/%y à %H:%M')) | |
HTML_FOOTER = """ | |
</body> | |
</html>""" | |
TEMP_MD = '/tmp/temp.md' | |
TEMP_HTML = '/tmp/temp.html' | |
TEMP_TEXTILE = '/tmp/temp.textile' | |
def exe(cmd): | |
"""Execute the specified command.""" | |
process = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE) | |
stdout, stderr = process.communicate() | |
if stderr: | |
print('--- Error while running command "%s" ---\n%s' % (cmd, stderr.encode())) | |
if stdout: | |
print(stderr.encode()) | |
for d in [WEB_DIR, TEXTILE_DIR, IMG_DIR]: | |
if not op.isdir(d): | |
os.makedirs(d) | |
# Hide main directory | |
index_html = op.join(WEB_DIR, 'index.html') | |
if not op.isfile(index_html): | |
with open(index_html, 'w'): | |
pass | |
for md_path in [op.abspath(op.join(USERPAGE_DIR, f)) for f in os.listdir(USERPAGE_DIR) if f.endswith(".md")]: | |
basename = op.splitext(op.basename(md_path))[0] | |
# Generate UML diagrams and replace UML blocks in markdown files by generated diagrams | |
with open(md_path) as f_md, open(TEMP_MD, 'w') as edited_md: | |
n_uml = 0 | |
uml_block = False | |
for line in f_md: | |
if line.startswith('```@startuml'): | |
img_name = basename + '.png' if n_uml == 0 else '%s_%03d.png' % (basename, n_uml) | |
edited_md.write('![](%s)' % op.join('http://' + SERVER, '~' + USER, 'images', img_name)) | |
n_uml += 1 | |
uml_block = True | |
elif uml_block and line.startswith('@enduml'): | |
edited_md.write('\n') | |
f_md.next() | |
uml_block = False | |
elif not uml_block: | |
edited_md.write(line) | |
if n_uml > 0: | |
exe('%s -nbthread auto %s -o %s' % (PLANTUML_EXE, md_path, IMG_DIR)) | |
# Generate HTML file and add html header and footer | |
exe('%s %s -o %s' % (PANDOC_EXE, TEMP_MD, TEMP_HTML)) | |
with open(TEMP_HTML) as html_in, open(op.join(WEB_DIR, basename + '.html'), 'w') as html_out: | |
html_out.write(HTML_HEADER) | |
html_out.write(html_in.read()) | |
html_out.write(HTML_FOOTER) | |
# Generate Textile file and replace code blocks syntax | |
exe('%s %s -o %s' % (PANDOC_EXE, TEMP_MD, TEMP_TEXTILE)) | |
with open(TEMP_TEXTILE) as textile_in, open(op.join(TEXTILE_DIR, basename + '.textile'), 'w') as textile_out: | |
code_block = False | |
for line in textile_in: | |
if line.startswith('bc. '): | |
textile_out.write('<pre>\n') | |
textile_out.write(line[4:]) | |
code_block = True | |
elif code_block and not line.strip(): | |
textile_out.write('</pre>\n') | |
code_block = False | |
else: | |
textile_out.write(line) | |
print('Converted ' + basename) | |
# Sending through rsync | |
password = PASSWORD if PASSWORD else getpass.getpass("IRAP LDAP password for %s: " % USER) | |
exe('sshpass -p %s rsync -e ssh -av --protocol=29 %s %s@%s:' % (password, WEB_DIR, USER, SERVER)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment