""" This module emits the content for your archive. It emits HTML, and YAML, mostly by calling into other modules. As of April 2021, the generated html pages can be hosted simply with `python -m http.server`. This module is probably the most likely module to be forked if you have unique requirements for how your archive should look. If you are interested in porting this system away from Python to your language of choice, this is probably the best place to start. """ from pathlib import Path from distutils.dir_util import copy_tree import html from shutil import copyfile from .url import ( sanitize_stream, sanitize, ) from .files import ( open_main_page, open_stream_topics_page, open_topic_messages_page, read_zulip_messages_for_topic, read_zulip_stream_info, ) from .html import ( format_message_html, last_updated_footer_html, topic_page_links_html, stream_list_page_html, topic_list_page_html, ) from .url import ( archive_stream_url, ) def to_topic_page_head_html(title): return f'\n{title}\n' def build_website( json_root, md_root, site_url, html_root, title, zulip_url, zulip_icon_url, repo_root, page_head_html, page_footer_html, ): stream_info = read_zulip_stream_info(json_root) streams = stream_info["streams"] date_footer_html = last_updated_footer_html(stream_info) write_main_page( md_root, site_url, html_root, title, streams, date_footer_html, page_head_html, page_footer_html, ) write_css(md_root) for stream_name in streams: print("building: ", stream_name) stream_data = streams[stream_name] topic_data = stream_data["topic_data"] write_stream_topics( md_root, site_url, html_root, title, stream_name, stream_data, date_footer_html, page_head_html, page_footer_html, ) for topic_name in topic_data: write_topic_messages( json_root, md_root, site_url, html_root, title, zulip_url, zulip_icon_url, stream_name, streams[stream_name], topic_name, date_footer_html, page_head_html, page_footer_html, ) # Copy the entire content of /assets into md_root. # We use copy_tree from distutils instead of shutil.copytree so that it # doesn't raise an error when assets/ already exists inside the md_root. copy_tree(str(Path(repo_root) / "assets"), str(Path(md_root) / "assets")) # Copy .nojekyll into md_root as well. copyfile(str(Path(repo_root) / ".nojekyll"), str(Path(md_root) / ".nojekyll")) # writes the index page listing all streams. # `streams`: a dict mapping stream names to stream json objects as described in the header. def write_main_page( md_root, site_url, html_root, title, streams, date_footer_html, page_head_html, page_footer_html, ): """ The main page in our website lists streams: Streams: general (70 topics) announce (42 topics) """ outfile = open_main_page(md_root) content_html = stream_list_page_html(streams) outfile.write(page_head_html) outfile.write(content_html) outfile.write(date_footer_html) outfile.write(page_footer_html) outfile.close() def write_stream_topics( md_root, site_url, html_root, title, stream_name, stream, date_footer_html, page_head_html, page_footer_html, ): """ A stream page lists all topics for the stream: Stream: social Topics: lunch (4 messages) happy hour (1 message) """ sanitized_stream_name = sanitize_stream(stream_name, stream["id"]) outfile = open_stream_topics_page(md_root, sanitized_stream_name) stream_url = archive_stream_url(site_url, html_root, sanitized_stream_name) topic_data = stream["topic_data"] content_html = topic_list_page_html(stream_name, stream_url, topic_data) outfile.write(page_head_html) outfile.write(content_html) outfile.write(date_footer_html) outfile.write(page_footer_html) outfile.close() def write_topic_messages( json_root, md_root, site_url, html_root, title, zulip_url, zulip_icon_url, stream_name, stream, topic_name, date_footer_html, page_head_html, page_footer_html, ): """ Writes the topics page, which lists all messages for one particular topic within a stream: Stream: social Topic: lunch Alice: I want pizza! Bob: No, let's get tacos! """ stream_id = stream["id"] sanitized_stream_name = sanitize_stream(stream_name, stream_id) sanitized_topic_name = sanitize(topic_name) messages = read_zulip_messages_for_topic( json_root, sanitized_stream_name, sanitized_topic_name ) outfile = open_topic_messages_page( md_root, sanitized_stream_name, sanitized_topic_name, ) topic_links = topic_page_links_html( site_url, html_root, zulip_url, sanitized_stream_name, sanitized_topic_name, stream_name, topic_name, ) # We use a topic-specific title instead of `page_head_html` to improve # search engine indexing. outfile.write( to_topic_page_head_html( html.escape(topic_name) + " · " + html.escape(stream_name) + " · " + title ) ) outfile.write(topic_links) outfile.write( f'\n\n' ) for msg in messages: msg_html = format_message_html( site_url, html_root, zulip_url, zulip_icon_url, stream_name, stream_id, topic_name, msg, ) outfile.write(msg_html) outfile.write("\n\n") outfile.write(date_footer_html) outfile.write(page_footer_html) outfile.close() def write_css(md_root): copyfile("style.css", md_root / "style.css")