Created
April 15, 2019 00:04
-
-
Save ndvo/a898bea33b62e0fd780892067be43b17 to your computer and use it in GitHub Desktop.
Generate static website
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 python3 | |
import os | |
import re | |
def truncate_html_words(s, num, delimiter): | |
length = int(num) | |
if length <=0: | |
return '' | |
html4_singlets = ('br', 'col', 'link', 'base', 'img', 'param', 'area', 'hr', 'input') | |
re_words = re.compile(r'&.*?;|<.*?>|([A-Za-z0-9][\w-]*)') | |
re_tag = re.compile(r'<(/)?([^ ]+?)(?: (/)| .*?)?>') | |
pos = 0 | |
ellipsis_pos = 0 | |
words = 0 | |
open_tags = [] | |
while words <= length: | |
m = re_words.search(s, pos) | |
if not m: | |
break | |
pos = m.end(0) | |
if m.group(1): | |
words +=1 | |
if words==length: | |
ellipsis_pos = pos | |
continue | |
tag=re_tag.match(m.group(0)) | |
if not tag or ellipsis_pos: | |
continue | |
closing_tag, tagname, self_closing = tag.groups() | |
tagname = tagname.lower() | |
if self_closing or tagname in html4_singlets: | |
pass | |
elif closing_tag: | |
try: | |
i = open_tags.index(tagname) | |
except ValueError: | |
pass | |
else: | |
open_tags = open_tags[i+1:] | |
else: | |
open_tags.insert(0,tagname) | |
if words<=length: | |
return s | |
out=s[:ellipsis_pos]+delimiter | |
for tag in open_tags: | |
out+= '</%s>' % tag | |
return out | |
def folder_to_name(string, language=None): | |
string = string.replace('-',' ').title() | |
special={ | |
'pt-br':r'[^^]\b(Com|Que|D[eao]|Para|[\w]|N[oa]|[UE]m)\b', | |
'en': r'[^^]\b(In)\b', | |
} | |
pattern = re.compile(special[language if language else 'pt-br'],re.IGNORECASE) | |
return pattern.sub(lambda obj: obj.group(0).lower(),string ) | |
class Folder(): | |
special_files = ['index.html','conteudo', 'log'] | |
languages = ['pt-br','en'] | |
def __init__(self,path): | |
self.split = path.split('/') | |
self.path = j(cwd,path) | |
self.url = j('/',path) | |
self.all_contents = [i for i in os.listdir(self.path)] | |
self.special = {i:os.path.exists(j(self.path,i)) for i in self.special_files} | |
self.contents =[i for i in self.all_contents if i not in self.special_files] | |
self.files=[i for i in self.all_contents if os.path.isfile(j(self.path,i))] | |
self.dirs= [i for i in self.all_contents if os.path.isdir(j(self.path,i))] | |
self.root = self.split[0] | |
self.leave = self.split[-1] | |
self.language=self.root if self.root in self.languages else 'en' | |
self.name = folder_to_name(self.leave,self.language) | |
self.content = os.path.exists(j(self.path,'conteudo')) | |
self.updated = self.get_log().readline() if self.special['log'] else '000000000' | |
self.siblings=[] | |
try: | |
if self.split[-2]: | |
parent = self.split[0:-1] | |
for i in os.listdir(j(*[cwd]+parent)) : | |
brother=j(*parent+[i]) | |
if brother!= path and os.path.isdir(brother) and 'conteudo' in os.listdir(brother): | |
self.siblings.append(j(*['/']+parent+[i])) | |
except IndexError: | |
pass | |
if self.siblings: | |
print(self.siblings) | |
print(brother,path) | |
def folder_list(self, contents=None): | |
if not contents: | |
contents=self.dirs | |
text='<ul>' | |
for ii in sorted(contents,key=lambda m: (open(j(self.path,m,'log')).readline() if os.path.exists(j(self.path,m,'log')) else '000000'),reverse=True) : | |
text+='<li>{}</li>'.format(folder_to_name(ii)) | |
text+='</ul>' | |
return text | |
def get_conteudo(self): | |
return open(j(self.path,'conteudo')).read() if self.special['conteudo'] else None | |
def get_log(self): | |
if 'log' in self.all_contents: | |
return open(j(self.path,'log'),'r') | |
class Menu(): | |
def __init__(self,root,name=None): | |
self.name = name | |
self.items = [] | |
self.main_list = [] | |
self.generate_menu(root) | |
if self.name=='main': | |
self.main_list.sort() | |
result = '\n'.join(self.main_list) | |
main_list = open(j(cwd, 'main.list'),'w') | |
main_list.write(result) | |
main_list.close() | |
def generate_menu(self, folder, ignore_links=True): | |
contents = os.listdir(j(cwd,folder)) | |
for i in contents: | |
uri = j(cwd,folder,i) | |
if ignore_links and os.path.islink(uri): | |
continue | |
if os.path.isdir(uri): | |
if self.name: | |
self.generate_menu(j(folder,i)) | |
else: | |
self.items.append(Link(j(folder,i), None, None,None)) | |
elif i == 'menu' and self.name: | |
menudescription = open(j(cwd,folder, i),'r').read() | |
if re.search(self.name+'\s*$',menudescription, re.MULTILINE): | |
self.items.append(Link(folder, | |
re.search('label:\s*(\w+)\s*$',menudescription, re.MULTILINE), | |
re.search('title:\s*(\w+)\s*$',menudescription, re.MULTILINE), | |
re.search('target:\s*(\w+)\s*$',menudescription, re.MULTILINE), | |
)) | |
elif self.name == 'main' and i == 'log': | |
date = open(j(cwd,folder,i)).readline() | |
self.main_list.append(str(date)[0:-1]+' '+folder) | |
def __str__(self): | |
result = "\n<ul>\n" | |
for i in self.items: | |
result+="\t<li>"+str(i)+"</li>\n" | |
result+= "</ul>\n" | |
return result | |
class Link(): | |
def __init__(self, folder, label, title=None, target=None): | |
if not label: | |
self.label = folder.split('/')[-1].replace('-',' ') | |
else: | |
self.label= label | |
self.href= '/'+folder | |
self.title = title | |
self.target=target | |
def __str__(self): | |
resultado = '<a href="'+self.href+'" ' | |
if self.title: | |
resultado += 'title="'+self.title+'" ' | |
if self.target: | |
resultado += 'target="'+self.target+'" ' | |
resultado += '>'+self.label+'</a>' | |
return resultado | |
def generate_index(folder,toc): | |
folder_contents = os.listdir(j(cwd,folder)) | |
link_list = '' | |
index = open(j(cwd,folder,'index.html'),'w') | |
pagetitle = folder_to_name(folder.split('/')[-1]) | |
if 'conteudo' in folder_contents: | |
conteudo = open(j(cwd,folder,'conteudo'),'r').read() | |
content=html_filter(conteudo) if conteudo else "" | |
template = main_template | |
index.write(template.format( | |
main_menu = str(main_menu), | |
pagetitle= pagetitle, | |
title=pagetitle, | |
toc = toc_template.format(str(toc)) if toc else "", | |
content=content, | |
link_list=link_list | |
)) | |
else: | |
template=front_template | |
contents = [] | |
for subfolder in sorted([Folder(j(folder,a)) for a in folder_contents if os.path.isdir(j(cwd,folder,a))], key=lambda m: m.updated, reverse=True): | |
if subfolder.special['conteudo']: | |
text = truncate_html_words(subfolder.get_conteudo(), 150, ' <a class="read-more" href="'+subfolder.url+'">Leia mais</a>') | |
else: | |
text = subfolder.folder_list() | |
contents.append(subfolder.updated+"$$$$"+post_item_template.format( | |
title='<a href="'+subfolder.url+'">'+subfolder.name+'</a>', | |
contents=text | |
)) | |
contents = sorted(contents, reverse=True) | |
content = '\n'.join([i.split('$$$$')[1] for i in contents]) | |
index.write(template.format( | |
main_menu = str(main_menu), | |
pagetitle= pagetitle, | |
title=pagetitle, | |
toc = toc_template.format(str(toc)) if toc else "", | |
content=content, | |
link_list=link_list | |
)) | |
index.close() | |
def html_filter(content): | |
replacements = { | |
r'\n\s*\n\s*([\w\W]+?)(?=\n\s*\n)':r'\n\n<P>\1</P>', | |
r'(</h[1-9]>)\n([\w\W]+)(?=\n\s*\n)':r'\1\n\n<P>\2</P>', | |
r'^([\w\W]+[?!"\w\.])(?=\n\s*\n)':r'<P>\1</P>', | |
r'<blockcode\s+language\s*=\s*"(\w+)">([\w\W]+?)</blockcode>':r'<pre class="\1"><code>\2</code></pre>', | |
r'<code>([\w\W\s]+?)(?=</code>)':replace_code, | |
} | |
for k,v in replacements.items(): | |
content = re.sub(k, v, content, re.MULTILINE) | |
return content | |
def replace_code(matchobj): | |
return '<code>'+matchobj.group(1).replace('<','<').replace('>','>') | |
def varrer_diretorio(folder, ignore_links=True): | |
contents = os.listdir(j(cwd,folder)) | |
toc = None | |
if folder not in ("sites",): | |
for i in contents: | |
uri = j(cwd,folder,i) | |
if ignore_links and os.path.islink(uri): | |
continue | |
if os.path.isdir(uri): | |
if not toc: | |
toc = Menu(folder,None) | |
varrer_diretorio(j(folder,i)) | |
generate_index(folder, toc) | |
def create_front_page(): | |
posts_per_page = 15 | |
contents = os.listdir(cwd) | |
list_title = [ | |
'Posts Recentes', 'Posts anteriores' | |
] | |
link_list = '<a href="/">⌂</a> ' | |
for i in range(1,(len(main_menu.main_list)//posts_per_page) ): | |
link_list+='<a href="/older'+str(i)+'.html">'+str(i)+'</a>' | |
if 'main.list' in contents: | |
counting = 0 | |
while len(main_menu.main_list) > 0: | |
posts = [] | |
for i in range(counting, counting+posts_per_page): | |
try: | |
posts.append(main_menu.main_list.pop()) | |
except IndexError: | |
break | |
to_open = 'older'+str(counting) if counting else 'index' | |
index = open(j(cwd,to_open+'.html'),'w') | |
if not counting: | |
index = open(j(cwd,'index.html'),'w') | |
else: | |
index = open(j(cwd, 'older'+str(counting)+'.html'),'w') | |
contents = [] | |
for i in posts: | |
link = i.split(' ')[1] | |
name = i.split('/')[-1] if '/' in i else i.split(' ')[-1] | |
name = name.replace('-',' ') | |
contents.append(post_item_template.format( | |
title='<a href="'+link+'">'+name+'</a>', | |
contents=truncate_html_words(open(j(cwd,i.split(' ')[1],'conteudo'), 'r').read(), 150, ' <a class="read-more" href="'+link+'">Leia mais</a>') | |
)) | |
index.write(front_template.format( | |
main_menu = str(main_menu), | |
title = list_title[0] if not counting else list_title[1], | |
content = html_filter('\n'.join(contents)), | |
link_list = link_list | |
)) | |
index.close() | |
counting +=1 | |
j = os.path.join | |
cwd = os.getcwd() | |
main_template = open(j(cwd, 'template.html'),'r').read() | |
toc_template = open(j(cwd, 'toc.html'),'r').read() | |
post_item_template = open(j(cwd,'post.item.html'),'r').read() | |
front_template = open(j(cwd,'front.html'),'r').read() | |
main_menu = Menu('','main') | |
varrer_diretorio('') | |
create_front_page() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment