Commit e5b7600703e9

Vincent Demeester <vincent@sbr.pm>
2026-01-29 14:43:50
feat(slack-archive): display messages newest-first in HTML output
Add post-processing step to reverse message order in generated HTML, so channels show newest messages at the top instead of oldest first. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 20bd682
Changed files (1)
tools
slack-archive
tools/slack-archive/slack-archive.sh
@@ -93,6 +93,116 @@ generate_html() {
     log "Fixing empty links..."
     find "$HTML_DIR" -name "*.html" -exec sed -i -E "s|<a href='([^']+)'></a>|<a href='\\1'>\\1</a>|g" {} \;
 
+    # Reverse message order (newest first)
+    log "Reversing message order (newest first)..."
+    find "$HTML_DIR" -name "*.html" -exec python3 -c '
+import sys
+from pathlib import Path
+from html.parser import HTMLParser
+
+class MessageReverser(HTMLParser):
+    def __init__(self):
+        super().__init__()
+        self.output = []
+        self.in_messages = False
+        self.messages_depth = 0
+        self.message_containers = []
+        self.current_container = []
+        self.in_container = False
+        self.container_depth = 0
+
+    def handle_starttag(self, tag, attrs):
+        attrs_dict = dict(attrs)
+        class_attr = attrs_dict.get("class", "")
+
+        raw = self.get_starttag_text()
+
+        if tag == "div" and "messages" in class_attr.split():
+            self.in_messages = True
+            self.messages_depth = 1
+            self.output.append(raw)
+            return
+
+        if self.in_messages and not self.in_container:
+            if tag == "div" and "message-container" in class_attr:
+                self.in_container = True
+                self.container_depth = 1
+                self.current_container = [raw]
+                return
+            elif tag == "div":
+                self.messages_depth += 1
+
+        if self.in_container:
+            self.current_container.append(raw)
+            if tag == "div":
+                self.container_depth += 1
+        else:
+            self.output.append(raw)
+
+    def handle_endtag(self, tag):
+        raw = f"</{tag}>"
+
+        if self.in_container:
+            if tag == "div":
+                self.container_depth -= 1
+            self.current_container.append(raw)
+            if self.container_depth == 0:
+                self.message_containers.append("".join(self.current_container))
+                self.current_container = []
+                self.in_container = False
+        elif self.in_messages:
+            if tag == "div":
+                self.messages_depth -= 1
+            if self.messages_depth == 0:
+                # Flush reversed containers
+                for container in reversed(self.message_containers):
+                    self.output.append(container)
+                self.message_containers = []
+                self.in_messages = False
+            self.output.append(raw)
+        else:
+            self.output.append(raw)
+
+    def handle_data(self, data):
+        if self.in_container:
+            self.current_container.append(data)
+        else:
+            self.output.append(data)
+
+    def handle_entityref(self, name):
+        raw = f"&{name};"
+        if self.in_container:
+            self.current_container.append(raw)
+        else:
+            self.output.append(raw)
+
+    def handle_charref(self, name):
+        raw = f"&#{name};"
+        if self.in_container:
+            self.current_container.append(raw)
+        else:
+            self.output.append(raw)
+
+    def handle_comment(self, data):
+        raw = f"<!--{data}-->"
+        if self.in_container:
+            self.current_container.append(raw)
+        else:
+            self.output.append(raw)
+
+    def handle_decl(self, decl):
+        self.output.append(f"<!{decl}>")
+
+    def get_result(self):
+        return "".join(self.output)
+
+path = Path(sys.argv[1])
+content = path.read_text()
+parser = MessageReverser()
+parser.feed(content)
+path.write_text(parser.get_result())
+' {} \;
+
     log "HTML generated at: $HTML_DIR"
 }