From 1041c5e32bd6e597efc5b169ab7b27e2b36a899a Mon Sep 17 00:00:00 2001 From: likho Date: Sun, 13 Mar 2022 19:58:00 -0700 Subject: [PATCH] new-prototype to master (#2) First version without unwanted hardcoded vars. --- Makefile | 4 ++ microblog.py | 153 ++++++++++++++++++++++++++++++++++++++++++ template-generic.html | 36 ++++++++++ timeline-generic.css | 85 +++++++++++++++++++++++ 4 files changed, 278 insertions(+) create mode 100644 Makefile create mode 100644 microblog.py create mode 100644 template-generic.html create mode 100644 timeline-generic.css diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c9df9d5 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ + + +all: + python microblog.py ./template.html ./content.txt > result.html diff --git a/microblog.py b/microblog.py new file mode 100644 index 0000000..4dfdee7 --- /dev/null +++ b/microblog.py @@ -0,0 +1,153 @@ + +import sys + +import subprocess + +def make_post(num, timestamp, email, msg): + # used for name and email but it's not actually needed. + # %s + # (%s) + output = "" + fmt = "" + part = ''' +
+ +
%s
+''' + if email != None: + fmt = part + "
" + output = fmt % (num, num, timestamp, msg, email, num) + else: + fmt += part + "" + output = fmt % (num, num, timestamp, msg) + return output + +def make_gallery(i, w): + tag = [] + if i == []: + return tag + tag.append("
") + for index in reversed(i): + image = w.pop(index) + template = ''' +
+ +
+''' + tag.append(template % (image, image)) + tag.append("
") + 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 = ("%s") % (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 = "%s" % (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, "
".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 = "%s(%i)" + 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() + diff --git a/template-generic.html b/template-generic.html new file mode 100644 index 0000000..f95d138 --- /dev/null +++ b/template-generic.html @@ -0,0 +1,36 @@ + + + + + + Microblog + + + + + + +
+ + +

A Microblog in Plain HTML

+ +
+
+ Avatar + Your Name Here +

+
TDescription +

Tags

+

%s

+
+ +
+ +
+%s +
+ +
+ + diff --git a/timeline-generic.css b/timeline-generic.css new file mode 100644 index 0000000..6fef8ba --- /dev/null +++ b/timeline-generic.css @@ -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%); +}