2023-08-23 08:50:31 +02:00
"""
2023-08-26 13:21:40 +02:00
pydoc – Create a simple HTML website from multiple Markdown files
with Python using Pandoc
2023-08-23 08:50:31 +02:00
Copyright ( c ) 2023 Helmut Kaczmarek < code @helmutkaczmarek.de >
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : / / www . gnu . org / licenses / > .
"""
import os
import shutil
import subprocess
import configparser
# Load settings from the configuration file
def load_settings ( config_path ) :
config = configparser . ConfigParser ( )
config . read ( config_path )
settings = config [ ' Settings ' ]
return settings
# Function for converting the Markdown files to HTML
def convert_to_html ( markdown_file , html_file , template_file ) :
pandoc_cmd = [
' pandoc ' , markdown_file , ' -o ' , html_file ,
' --template ' , template_file
]
subprocess . run ( pandoc_cmd )
# Function for processing the Markdown files
def process_markdown_files ( src_dir , dest_dir , settings ) :
converted_count = 0
template_file = settings [ ' template_file ' ]
css_path = settings [ ' css_path ' ]
for root , _ , files in os . walk ( src_dir ) :
for file in files :
if file . lower ( ) . endswith ( ' .md ' ) :
markdown_path = os . path . join ( root , file )
relative_path = os . path . relpath ( markdown_path , src_dir )
html_path = os . path . join ( dest_dir , os . path . splitext ( relative_path ) [ 0 ] + ' .html ' )
if not os . path . exists ( markdown_path ) :
if os . path . exists ( html_path ) :
os . remove ( html_path )
continue
os . makedirs ( os . path . dirname ( html_path ) , exist_ok = True )
print ( f " Converting { markdown_path } to { html_path } " )
convert_to_html ( markdown_path , html_path , template_file )
converted_count + = 1
return converted_count
# Copy asset files from source to destination directory
def copy_assets ( src_dir , dest_dir ) :
for item in os . listdir ( src_dir ) :
src_item = os . path . join ( src_dir , item )
dest_item = os . path . join ( dest_dir , item )
if os . path . isfile ( src_item ) :
shutil . copy ( src_item , dest_item )
elif os . path . isdir ( src_item ) :
shutil . copytree ( src_item , dest_item , dirs_exist_ok = True )
# Main function
def main ( ) :
try :
settings = load_settings ( ' settings.conf ' )
markdown_dir = settings [ ' markdown_dir ' ]
html_dir = settings [ ' html_dir ' ]
assets_dir = settings [ ' assets_dir ' ]
print ( " Starting Pydoc... " )
# Backup original content of the template file
original_template_content = None
with open ( settings [ ' template_file ' ] , ' r ' , encoding = ' utf-8 ' ) as f :
original_template_content = f . read ( )
# Update template file to include the correct CSS path
updated_template_content = original_template_content . replace ( ' {{ css_path }} ' , settings [ ' css_path ' ] )
with open ( settings [ ' template_file ' ] , ' w ' , encoding = ' utf-8 ' ) as f :
f . write ( updated_template_content )
# Delete and create HTML directory
shutil . rmtree ( html_dir , ignore_errors = True )
os . makedirs ( html_dir , exist_ok = True )
# Convert markdown files
num_converted = process_markdown_files ( markdown_dir , html_dir , settings )
# Copy asset files
copy_assets ( assets_dir , html_dir )
# Restore original content of the template file
with open ( settings [ ' template_file ' ] , ' w ' , encoding = ' utf-8 ' ) as f :
f . write ( original_template_content )
if num_converted > 0 :
print ( f " Finished converting { num_converted } files and copying assets. Everything seems to be finde. Note: If the CSS in subdirectories does not look as expected, check whether the full path to the style sheet is specified in ' css_path ' (see ' settings.conf ' ). " )
else :
print ( " No files converted. Check the source directories. " )
# Check if Pandoc template file contains "{{ css_path }}"
if ' <link rel= " stylesheet " href= " {{ css_path }} " > ' not in original_template_content :
print ( " INFO: The template.txt should contain ' {{ css_path }} ' as a placeholder for the path to the CSS file, so that the paths to the CSS file in subdirectories are set correctly. " )
except FileNotFoundError :
print ( " Cannot convert Markdown files. Missing configuration file. Here is an example for ' settings.conf ' : \n "
" \n "
" [Settings] \n "
" markdown_dir = C: \\ Path \\ to \\ Markdown \n "
" html_dir = C: \\ Path \\ To \\ HTML \n "
" assets_dir = C: \\ Path \\ To \\ Assets \n "
" template_file = C: \\ Path \\ to \\ template.txt \n "
" css_path = C: \\ Path \\ to \\ style.css # The full path to the CSS file is important for the style sheet to work in subdirectories. " )
except ( KeyError , ValueError , configparser . MissingSectionHeaderError ) :
print ( " There are problems in the ' settings.conf ' . Maybe a typo crept in? Here is an example for ' settings.conf ' : \n "
" \n "
" [Settings] \n "
" markdown_dir = C: \\ Path \\ to \\ Markdown \n "
" html_dir = C: \\ Path \\ To \\ HTML \n "
" assets_dir = C: \\ Path \\ To \\ Assets \n "
" template_file = C: \\ Path \\ to \\ template.txt \n "
" css_path = C: \\ Path \\ to \\ style.css # The full path to the CSS file is important for the style sheet to work in subdirectories. " )
if __name__ == " __main__ " :
main ( )