Skip to content

Instantly share code, notes, and snippets.

@ndvo
Created April 15, 2019 00:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ndvo/a898bea33b62e0fd780892067be43b17 to your computer and use it in GitHub Desktop.
Save ndvo/a898bea33b62e0fd780892067be43b17 to your computer and use it in GitHub Desktop.
Generate static website
#!/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('<','&lt;').replace('>','&gt;')
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