@ -1,75 +1,80 @@
import base64
import os
import subprocess
from io import BytesIO
import magic
from PIL import Image
from jinja2 import Environment , FileSystemLoader
from distribusi . page_template import html_footer , html_head
from distribusi . mappings import CODE_TYPES , FILE_TYPES , SUB_TYPES
MIME_TYPE = magic . Magic ( mime = True )
def caption ( image ) :
def add_alttext ( full_path_ image) :
try :
process = subprocess . Popen (
[ ' exiftool ' , ' -Comment ' , image ] , stdout = subprocess . PIPE )
out , err = process . communicate ( )
image_filename_no_ext = os . path . splitext ( full_path_image ) [ 0 ]
alttext_filename = f " { image_filename_no_ext } _alttext.txt "
return _read_matching_text_file (
image_filename_no_ext , alttext_filename
)
except Exception as e :
print ( e )
print ( ' Do you have exiftool installed? ' )
print ( f " exception { e } raised while making alttext " )
return
def add_description ( full_path_image ) :
try :
caption = out . decode ( " utf-8 " ) . split ( " : " , 1 ) [ 1 ]
image_filename_no_ext = os . path . splitext ( full_path_image ) [ 0 ]
description_filename = f " { image_filename_no_ext } _dv_description.txt "
return _read_matching_text_file (
image_filename_no_ext , description_filename
)
except Exception as e :
caption = ' '
print ( e )
return caption
print ( f " exception { e } raised while adding description " )
return
def thumbnail ( image , name , args ) :
def _read_matching_text_file ( image_filename_no_ext , filename ) :
if not os . path . isfile ( filename ) :
return
print ( f " { image_filename_no_ext } has { filename } " )
with open ( filename , " r " ) as text_file :
return text_file . read ( )
def thumbnail ( full_path_image , name , args ) :
if full_path_image . endswith ( " _thumbnail.jpg " ) :
return
try :
size = ( 450 , 450 )
im = Image . open ( image )
im . thumbnail ( size )
if ( im . mode == ' RGBA ' ) :
bg = Image . new ( ' RGBA ' , im . size , ( 255 , 255 , 255 ) )
composite = Image . alpha_composite ( bg , im )
im = composite . convert ( ' RGB ' )
output = BytesIO ( )
im . save ( output , format = ' JPEG ' )
im_data = output . getvalue ( )
data_url = base64 . b64encode ( im_data ) . decode ( )
if args . captions :
cap = caption ( image )
else :
cap = name
return (
" <figure><a href= ' {} ' ><img class= ' thumbnail ' src= ' data:image/jpg;base64, {} ' ></a><figcaption> {} </figcaption></figure> "
) . format ( name , data_url , cap )
thumbnail_image = Image . open ( full_path_image )
thumbnail_image . thumbnail ( size )
if thumbnail_image . mode == " RGBA " :
bg = Image . new ( " RGBA " , thumbnail_image . size , ( 255 , 255 , 255 ) )
composite = Image . alpha_composite ( bg , thumbnail_image )
thumbnail_image = composite . convert ( " RGB " )
image_filename_no_ext = os . path . splitext ( full_path_image ) [ 0 ]
thumbnail_filename = f " { image_filename_no_ext } _thumbnail.jpg "
thumbnail_image . save ( thumbnail_filename , format = " JPEG " )
return os . path . basename ( thumbnail_filename )
except Exception as e :
print ( ' Thumbnailer: ' , e )
return " <figure><a href= ' {} ' ><img src= ' {} ' ></a><figcaption> {} </figcaption></figure> " . format ( name , name , name )
print ( " Thumbnailer: " , e )
return
def div ( args , type_ , subtype , tag , name ) :
id_name = name . split ( ' . ' ) [ 0 ] . replace ( ' ' , ' _ ' )
if args . no_filenames :
filename = ' '
else :
filename = ' <span class= " filename " > {} </span> ' . format ( name )
def format_div ( args , type_ , subtype , tag , name ) :
id_name = name . split ( " . " ) [ 0 ] . replace ( " " , " _ " )
filename = f ' <span class= " filename " > { name } </span> '
if ' image ' in type_ :
if " image " in type_ :
html = ' <div id= " {} " class= " {} " > {} </div> '
elif ' pdf ' in subtype :
html = ' <div id= " {} " class= " {} " > {} ' + filename + ' </div> '
elif ' dir ' in type_ or ' html ' in subtype or ' unkown-file ' in subtype :
elif " pdf " in subtype :
html = ' <div id= " {} " class= " {} " > {} ' + filename + " </div> "
elif " dir " in type_ or " html " in subtype or " unkown-file " in subtype :
html = ' <div id= " {} " class= " {} " > {} </div> '
else :
html = ' <div id= " {} " class= " {} " > {} ' + filename + ' </div> '
html = ' <div id= " {} " class= " {} " > {} ' + filename + " </div> "
return html . format ( id_name , subtype , tag )
@ -78,142 +83,168 @@ def check_distribusi_index(args, index):
"""
check whether a index . html file is generated by distribusi
"""
if not args . force :
with open ( index , ' r ' ) as f :
with open ( index , " r " ) as f :
if ' <meta name= " generator " content= " distribusi " /> ' in f . read ( ) :
return True
else :
if args . verbose :
print ( index , ' not generated by distribusi, skipping ' )
print ( index , " not generated by distribusi, skipping " )
return False
elif args . force :
return True
def write_index ( args , index , html , html_head , html_footer ) :
with open ( index , ' w ' ) as f :
if not args . no_template :
if args . style :
fs = open ( args . style , " r " )
style = fs . read ( )
styled_html_head = html_head % style
else :
styled_html_head = html_head % ' '
f . write ( styled_html_head )
for line in html :
f . write ( line + ' \n ' )
def write_index ( args , index , html ) :
env = Environment ( loader = FileSystemLoader ( ' templates ' ) )
template = env . get_template ( ' main.jinja ' )
with open ( index , " w " ) as index_file :
rendered_html = template . render ( content = html )
index_file . write ( rendered_html )
def handle_text_files ( name , full_path , subtype ) :
if name . endswith ( " .html " ) or subtype == " html " :
subtype = " html "
# what types of text files to expand
tag = ' <section id= " {} " > {} </section> ' . format (
name , open ( full_path ) . read ( )
)
elif subtype in CODE_TYPES or name . endswith ( " .txt " ) :
# if the plain text is code,
# which types do we wrap in pre-tags?
tag = " <pre> " + open ( full_path ) . read ( ) + " </pre> "
else :
subtype = subtype + " unkown-file "
tag = " <a href= ' {} ' > {} </a> "
# a = FILE_TYPES[type_]
return subtype , tag
def handle_image_files ( name , full_path , args ) :
if args . thumbnail :
thumbnail_filename = thumbnail ( full_path , name , args )
if thumbnail_filename is None :
return
if args . alttexts :
image_alttext = add_alttext ( full_path )
if args . alttexts :
image_description = add_description ( full_path )
if image_alttext is None :
if image_description is None :
return f ' <a href= " { name } " ><img class= " thumbnail " src= " { thumbnail_filename } " alt= " { name } " ></a> '
return f ' <figure><a href= " { name } " ><img class= " thumbnail " src= " { thumbnail_filename } " ></a><figcaption> { image_description } </figcaption></figure> '
if image_description is None :
return f ' <a href= " { name } " ><img class= " thumbnail " src= " { thumbnail_filename } " alt= " { image_alttext } " ></a> '
return f ' <figure><a href= " { name } " ><img class= " thumbnail " src= " { thumbnail_filename } " alt= " { image_alttext } " ></a><figcaption> { image_description } </figcaption></figure> '
return FILE_TYPES [ " image " ] . format ( name , image_alttext )
def remove_index_html ( root , files , args ) :
index = os . path . join ( root , " index.html " )
if " index.html " in files :
try :
if check_distribusi_index ( args , index ) :
if args . verbose :
print ( " Removing index.html from " , root )
os . remove ( index )
except Exception as e :
print ( e )
return
if not args . no_template :
f . write ( html_footer )
def remove_hidden_files_and_folders ( dirs , files ) :
dirs = list ( filter ( lambda d : not d . startswith ( " . " ) , dirs ) )
files = list ( filter ( lambda f : not f . startswith ( " . " ) , files ) )
return dirs , files
def distribusify ( args , directory ) : # noqa
for root , dirs , files in os . walk ( directory ) :
html = [ ]
if args . exclude_directory :
if args . verbose :
print ( ' Excluding directory: ' , " , " . join ( args . exclude_directory ) )
print (
" Excluding directory: " , " , " . join ( args . exclude_directory )
)
dirs [ : ] = [ d for d in dirs if d not in args . exclude_directory ]
if args . no_hidden :
dirs = list ( filter ( lambda d : not d . startswith ( ' . ' ) , dirs ) )
files = list ( filter ( lambda f : not f . startswith ( ' . ' ) , files ) )
dirs , files = remove_hidden_files_and_folders ( dirs , files )
dirs . sort ( )
files . sort ( )
if args . remove_index :
remove_index_html ( root , files , args )
if not args . remove_index :
html = [ ]
if args . verbose :
print ( " Generating directory listing for " , root )
for name in sorted ( files ) :
if " index.html " in name :
continue
if name . endswith ( " _thumbnail.jpg " ) :
continue
if name . endswith ( " _alttext.txt " ) :
continue
if name . endswith ( " _dv_description.txt " ) :
continue
full_path = os . path . join ( root , name )
mime = MIME_TYPE . from_file ( full_path )
type_ , subtype = mime . split ( " / " )
alttext = name
if args . verbose :
print ( ' Generating directory listing for ' , root )
for name in sorted ( files ) :
if ' index.html ' not in name :
full_path = os . path . join ( root , name )
mime = MIME_TYPE . from_file ( full_path )
# example: MIME plain/text becomes 'type' plain 'subtype' text
type_ , subtype = mime . split ( ' / ' )
caption = name
if args . verbose :
print ( ' Found ' , name , ' as ' , mime )
if type_ in FILE_TYPES :
a = FILE_TYPES [ type_ ] . format ( name , caption )
# expansion for different kind of text files
if type_ == ' text ' :
if name . endswith ( ' .html ' ) or subtype == ' html ' :
subtype = ' html '
# what types of text files to expand
a = ' <section id= " {} " > {} </section> ' . format ( name , open ( full_path ) . read ( ) )
elif subtype in CODE_TYPES or name . endswith ( ' .txt ' ) :
# if the plain text is code,
# which types do we wrap in pre-tags?
a = " <pre> " + open ( full_path ) . read ( ) + " </pre> "
else :
subtype = subtype + ' unkown-file '
a = " <a href= ' {} ' > {} </a> "
# a = FILE_TYPES[type_]
if type_ == ' image ' :
if args . thumbnail :
a = thumbnail ( full_path , name , args )
if args . no_filenames :
caption = " "
a = FILE_TYPES [ type_ ] . format ( name , caption )
if args . captions :
caption = caption ( full_path )
a = FILE_TYPES [ type_ ] . format ( name , caption )
if subtype in SUB_TYPES :
a = SUB_TYPES [ subtype ]
if type_ not in FILE_TYPES and subtype not in SUB_TYPES :
# catch exceptions not yet defined in FILE_TYPES or SUB_TYPES
a = " <a href= ' {} ' > {} </a> "
if args . verbose :
message = ' not in list of file types, adding as plain href: \n '
print ( type_ , subtype , message , name )
subtype = subtype + ' unkown-file '
a = a . replace ( ' {} ' , name )
html . append ( div ( args , type_ , subtype , a , name ) )
if root != directory :
if args . menu_with_index :
html . append ( ' <a href= " ../index.html " >../</a> ' )
else :
html . append ( ' <a href= " ../ " >../</a> ' )
for name in dirs :
if args . menu_with_index :
a = " <a href= ' {} /index.html ' > {} </a> " . replace ( ' {} ' , name )
else :
a = " <a href= ' {} ' > {} /</a> " . replace ( ' {} ' , name )
html . insert ( 0 , div ( args , ' dir ' , ' dir ' , a , ' folder ' ) )
index = os . path . join ( root , ' index.html ' )
if os . path . exists ( index ) :
if check_distribusi_index ( args , index ) :
write_index ( args , index , html , html_head , html_footer )
elif not os . path . exists ( index ) :
write_index ( args , index , html , html_head , html_footer )
print ( " Found " , name , " as " , mime )
if type_ in FILE_TYPES :
match type_ :
case " text " :
subtype , tag = handle_text_files (
name , full_path , subtype
)
case " image " :
tag = handle_image_files ( name , full_path , args )
if tag is None :
continue
case _ :
tag = FILE_TYPES [ type_ ] . format ( name , alttext )
if subtype in SUB_TYPES :
tag = SUB_TYPES [ subtype ]
if type_ not in FILE_TYPES and subtype not in SUB_TYPES :
# catch exceptions not yet defined in FILE_TYPES or SUB_TYPES
tag = " <a href= ' {} ' > {} </a> "
if args . verbose :
message = (
" not in list of file types, adding as plain href: \n "
)
print ( type_ , subtype , message , name )
subtype = subtype + " unkown-file "
tag = tag . replace ( " {} " , name )
html . append ( format_div ( args , type_ , subtype , tag , name ) )
if root != directory :
if args . menu_with_index :
html . append ( ' <a href= " ../index.html " >../</a> ' )
else :
html . append ( ' <a href= " ../ " >../</a> ' )
if args . remove_index :
index = os . path . join ( root , ' index.html ' )
if ' index.html ' in files :
try :
if check_distribusi_index ( args , index ) :
if args . verbose :
print ( ' Removing index.html from ' , root )
os . remove ( index )
except Exception as e :
print ( e )
for name in sorted ( dirs ) :
if args . menu_with_index :
tag = " <a href= ' {} /index.html ' > {} </a> " . replace ( " {} " , name )
else :
tag = " <a href= ' {} ' > {} /</a> " . replace ( " {} " , name )
html . insert ( 0 , format_div ( args , " dir " , " dir " , tag , " folder " ) )
index = os . path . join ( root , " index.html " )
if os . path . exists ( index ) :
if check_distribusi_index ( args , index ) :
write_index ( args , index , html )
elif not os . path . exists ( index ) :
write_index ( args , index , html )