new-prototype to master (#2)

First version without unwanted hardcoded vars.
This commit is contained in:
likho 2022-03-13 19:58:00 -07:00
parent 16b3063070
commit 1041c5e32b
4 changed files with 278 additions and 0 deletions

4
Makefile Normal file
View File

@ -0,0 +1,4 @@
all:
python microblog.py ./template.html ./content.txt > result.html

153
microblog.py Normal file
View File

@ -0,0 +1,153 @@
import sys
import subprocess
def make_post(num, timestamp, email, msg):
# used <a class> for name and email but it's not actually needed.
# <a class=\"name\">%s</a>
# <a class=\"email\">(%s)</a>
output = ""
fmt = ""
part = '''
<div class=\"postcell\" id=\"%i\">
<div class=\"timestamp\"><a href=#%i>%s</a></div>
<div class=\"message\">%s</div>
'''
if email != None:
fmt = part + "<div class=\"reply\"><a href=\"mailto:%s?subject=p%i\">[reply]</a></div></div>"
output = fmt % (num, num, timestamp, msg, email, num)
else:
fmt += part + "</div>"
output = fmt % (num, num, timestamp, msg)
return output
def make_gallery(i, w):
tag = []
if i == []:
return tag
tag.append("<div class=\"gallery\">")
for index in reversed(i):
image = w.pop(index)
template = '''
<div class=\"panel\">
<a href=\"%s\"><img src=\"%s\" class=\"embed\"></img></a>
</div>
'''
tag.append(template % (image, image))
tag.append("</div>")
return tag
def markup(msg):
result = 0
tagged = ""
words = msg.split()
# support multiple images (gallery style)
images = [] # list of integers
tags = [] # list of strings
for i in range(len(words)):
word = words[i]
# don't help people click http
if word.find("src=") == 0 or word.find("href=") == 0:
continue
elif word.find("https://") != -1:
new_word = ("<a href=\"%s\">%s</a>") % (word, word)
words[i] = new_word
elif word.find("#") != -1 and len(word) > 1:
# split by unicode blank character if present
w = word.split(chr(8206))
# w[0] is the portion closest to the #
tags.append(w[0])
new_word = "<span class=\"hashtag\">%s</span>" % (w[0])
if len(w) > 1:
new_word += w[1]
words[i] = new_word
elif word.find(".jpg") != -1 or word.find(".png") != -1:
images.append(i)
# are .gifs and other media files too much bloat?
gallery = make_gallery(images, words)
words += gallery
return " ".join(words), tags
def parse_txt(filename):
content = []
with open(filename, 'r') as f:
content = f.readlines()
stack = [] # stack of lists - only a stack b/c order of contents
message = [] # queue of lines
# {-1 = init;; 0 = timestamp is next, 1 = message is next}
state = -1
timestamp = ""
for line in content:
# print (line, len(line), state)
if state == -1:
state = 0
continue
elif state == 0:
cmd = ['date', '-d', line, '+%y %b %d']
result = subprocess.run(cmd, stdout=subprocess.PIPE)
timestamp = result.stdout.decode('utf-8')
state = 1
elif state == 1:
if len(line) > 1:
message.append(line)
else:
stack.append([timestamp, "<br>".join(message)])
message = []
state = 0
return stack
def make_timeline(filename, email=None):
timeline = []
tagcloud = dict()
# note: content is ordered from newest to oldest
# format requires two line breaks before EOF
stack_of_posts = parse_txt(filename) # [timestamp, message]
count = len(stack_of_posts)
for post in stack_of_posts:
p, t = markup(post[1])
timeline.append(
make_post(count, post[0], email, p)
)
count -= 1
for tag in t:
if tagcloud.get(tag) == None:
tagcloud[tag] = 0
tagcloud[tag] += 1
return timeline, tagcloud
pass
def make_tagcloud(d):
sorted_d = {k: v for k,
v in sorted(d.items(),
key=lambda item: -item[1])}
output = []
fmt = "<span class=\"hashtag\">%s(%i)</span>"
for key in d.keys():
output.append(fmt % (key, d[key]))
return output
if __name__ == "__main__":
def get_params():
argc = len(sys.argv)
if argc < 3:
msg = '''This is microblog.py. (%s/3 parameters given; 4 maximum)
\tpython microblog.py [template] [content] [optional: email]
'''
print(msg % argc)
# script = argv[0]
return argc
def main():
param_count = get_params()
template = sys.argv[1]
content = sys.argv[2]
email = sys.argv[3] if (param_count >= 4) else None
tl, tc = make_timeline(content, email)
tcl = make_tagcloud(tc)
count = len(tl)
with open(template,'r') as f:
html = f.read()
print(html % (count, "\n".join(tcl), "\n\n".join(tl)))
main()

36
template-generic.html Normal file
View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta content="initial-scale=1.0">
<title>Microblog</title>
<link href="/style.css" rel="stylesheet" type="text/css" media="all">
<!-- local testing -->
<link href="./style.css" rel="stylesheet" type="text/css" media="all">
<link href="./timeline.css" rel="stylesheet" type="text/css" media="all">
</head>
<body>
<div class="content">
<h1>A Microblog in Plain HTML</h1>
<div class = "column">
<div class="profile">
<img src="./images/avatar.jpg" alt="Avatar" class="avatar">
<span class="handle">Your Name Here</span>
<p><span class="email"><a href="mailto:user@host.tld">user@host.tld</a></span></p>
<div class="bio">TDescription</h4>
<h3>Tags</h3>
<p>%s</p>
</div>
</div>
<div class = "timeline">
%s
</div>
</div>
</body>
</html>

85
timeline-generic.css Normal file
View File

@ -0,0 +1,85 @@
.column {
float: left;
width: 30%;
background-color: #1a1a1a;
}
.timeline {
float: right;
width: 67%;
background-color: #1a1a1a;
}
.postcell {
border: 1px solid gray;
text-align: left;
margin: 0.25em 0
}
.message {
margin: 1em 1em 1em 3em;
white-space: pre-wrap;
word-wrap: break-word;
}
.reply {
margin: 0.5em
}
.timestamp {
text-align: right;
margin: 0.5em
}
.hashtag {
font-weight: bold;
}
.profile {
vertical-align: middle;
padding-left: 10px;
}
.avatar {
vertical-align: middle;
width: 50px;
height: 50px;
}
.handle{
font-size: large;
font-weight: bold;
}
.email{
text-align:left;
font-size: x-small;
text-decoration:none;
}
.bio {
vertical-align: middle;
font-size: small;
margin: 1em
}
.gallery {
margin-left: auto ;
margin-right: auto ;
display: flex;
align-items: center;
max-width: 100%;
}
.header {
background: black;
color: white;
font-size: large;
font-weight: bold;
padding: 0.5em;
}
div.panel {
margin: 2px;
/* border: 1px solid #ffbc06; */
width: auto
}
div.panel:hover {
border: 1px solid #777;
}
div.panel img {
width: 100%;
height: 100%;
}
div.panel img:hover {
filter: invert(100%);
}