mirror of
https://github.com/freedoom/freedoom.git
synced 2025-09-01 13:25:46 -04:00
210 lines
6.8 KiB
Python
Executable file
210 lines
6.8 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
#
|
|
# new-to-feed - Convert NEWS.adoc to feed.xml
|
|
#
|
|
# This script converts from "NEWS.adoc" in the main Freedoom repository to
|
|
# "feed.xml" on the Freedoom website, which is an RSS feed.
|
|
#
|
|
# It's possible that there is no need for this script given that GitHub
|
|
# generates an Atom feed based on the releases done on GitHub. It can be
|
|
# found at:
|
|
# https://github.com/freedoom/freedoom/releases.atom
|
|
# Perhaps the website should link to the above in place of the current
|
|
# "atom.xml", and "feed.xml" should be abandon.
|
|
|
|
import datetime
|
|
import os
|
|
import re
|
|
import sys
|
|
from xml.dom.minidom import Document
|
|
|
|
# Globals
|
|
|
|
channel = None
|
|
leading_whitespace = " "
|
|
date = None
|
|
desc_lines = []
|
|
doc = None
|
|
pubdate = None
|
|
ver = None
|
|
|
|
# Regular expressions
|
|
|
|
# A regular expression that matches version / date lines.
|
|
ver_date_patt = re.compile(r'\s*==\s+((?:\d+\.)+\d+)\s+\((\d{4}-\d{2}-\d{2})\)')
|
|
|
|
# Initial document processing and header prior to the first version.
|
|
def add_header():
|
|
global channel
|
|
global doc
|
|
|
|
doc = Document()
|
|
|
|
rss = doc.createElement('rss')
|
|
rss.setAttribute('version', '2.0')
|
|
doc.appendChild(rss)
|
|
|
|
channel = doc.createElement('channel')
|
|
rss.appendChild(channel)
|
|
|
|
title = doc.createElement('title')
|
|
title.appendChild(doc.createTextNode('Freedoom Feed'))
|
|
channel.appendChild(title)
|
|
|
|
link = doc.createElement('link')
|
|
link.appendChild(doc.createTextNode('https://freedoom.github.io'))
|
|
channel.appendChild(link)
|
|
|
|
description = doc.createElement('description')
|
|
description.appendChild(doc.createTextNode('The latest news from Freedoom'))
|
|
channel.appendChild(description)
|
|
|
|
language = doc.createElement('language')
|
|
language.appendChild(doc.createTextNode('en-us'))
|
|
channel.appendChild(language)
|
|
|
|
image = doc.createElement('image')
|
|
channel.appendChild(image)
|
|
|
|
url = doc.createElement('url')
|
|
url.appendChild(doc.createTextNode('https://freedoom.github.io/favicon.ico'))
|
|
image.appendChild(url)
|
|
|
|
|
|
# Called each time we have a complete version section
|
|
def add_version():
|
|
item = doc.createElement('item')
|
|
channel.appendChild(item)
|
|
|
|
title_elem = doc.createElement('title')
|
|
title_elem.appendChild(doc.createTextNode(date + ": Freedoom " + ver + " released"))
|
|
item.appendChild(title_elem)
|
|
|
|
pubdate_elem = doc.createElement('pubDate')
|
|
pubdate_elem.appendChild(doc.createTextNode(pubdate))
|
|
item.appendChild(pubdate_elem)
|
|
|
|
link_elem = doc.createElement('link')
|
|
link_elem.appendChild(doc.createTextNode("https://freedoom.github.io/#freedoom-" + ver))
|
|
item.appendChild(link_elem)
|
|
|
|
# Avoid join() in order to treat newlines specially.
|
|
nl_ws = "\n" + leading_whitespace
|
|
desc_text = "\n"
|
|
for desc_line in desc_lines:
|
|
if desc_line:
|
|
desc_text += leading_whitespace + desc_line + "\n" + leading_whitespace + "<p/>\n"
|
|
else:
|
|
desc_text += "\n"
|
|
desc_elem = doc.createElement('description')
|
|
desc_elem.appendChild(doc.createTextNode(desc_text))
|
|
item.appendChild(desc_elem)
|
|
|
|
|
|
# Iterates through news_adoc in order to process each version found.
|
|
def add_versions():
|
|
global date
|
|
global desc_lines
|
|
global pubdate
|
|
global ver
|
|
|
|
first_section = True
|
|
desc_line = ""
|
|
with open(news_adoc) as news_hand:
|
|
line_num = 0
|
|
for line in news_hand:
|
|
line_num += 1
|
|
line = line.rstrip()
|
|
ver_date_match = ver_date_patt.match(line)
|
|
if ver_date_match:
|
|
ver_date_match_groups = ver_date_match.groups()
|
|
if len(ver_date_match_groups) != 2:
|
|
# Should not happen.
|
|
print("Line number", line_num, "has", len(ver_date_match_groups),
|
|
"groups.", file=sys.stderr)
|
|
sys.exit(1)
|
|
# With the exception of the "HEAD" each new version line indicates
|
|
# that the previous one is complete, so output it before setting
|
|
# "pubdate" to the new value.
|
|
if pubdate:
|
|
add_version()
|
|
desc_lines = []
|
|
ver, date = ver_date_match.groups()
|
|
pubdate = datetime.datetime.strptime(date, '%Y-%m-%d').strftime('%d %b %Y')
|
|
first_section = True
|
|
else:
|
|
# Possible description text, but only after the first version date line.
|
|
if not pubdate:
|
|
continue
|
|
line = line.strip()
|
|
if line.startswith("=== "):
|
|
# Add the existing line, if any.
|
|
if desc_line:
|
|
desc_lines.append(desc_line)
|
|
desc_line = ""
|
|
if first_section:
|
|
first_section = False
|
|
else:
|
|
desc_lines.append("")
|
|
desc_lines.append("> " + line[4:])
|
|
first_section = False
|
|
elif line.startswith("*"):
|
|
if desc_line:
|
|
desc_lines.append(desc_line)
|
|
desc_line = ""
|
|
try:
|
|
space_index = line.index(" ")
|
|
except ValueError:
|
|
# Should not happen.
|
|
print("Line number", line_num, "begins with \"*\", but has no space.")
|
|
sys.exit(1)
|
|
desc_line = ("- " * (space_index - 1) if (space_index > 1) \
|
|
else "") + line[space_index + 1:]
|
|
elif line:
|
|
# Assume it's a continuation of the previous "*" line.
|
|
desc_line += (" " + line)
|
|
else:
|
|
# Blank line marking the end of a bullet.
|
|
if desc_line:
|
|
desc_lines.append(desc_line)
|
|
desc_line = ""
|
|
if not pubdate:
|
|
print("No pubdate at the end.", file=sys.stderr)
|
|
sys.exit(1)
|
|
if desc_line:
|
|
desc_lines.append(desc_line)
|
|
desc_line = ""
|
|
add_version()
|
|
|
|
|
|
# Main enty point.
|
|
def main():
|
|
parse_args()
|
|
add_header()
|
|
add_versions()
|
|
output_feed()
|
|
|
|
|
|
# Write the feed to feed_xml.
|
|
def output_feed():
|
|
with open(feed_xml, "w") as feed_hand:
|
|
print(doc.toprettyxml(indent=" "), file=feed_hand, end="")
|
|
|
|
|
|
# Parse the command line arguments and store the result in 'args'.
|
|
def parse_args():
|
|
global news_adoc
|
|
global feed_xml
|
|
|
|
if len(sys.argv) != 3:
|
|
print("Usage:", os.path.basename(sys.argv[0]), \
|
|
"news-file feed-xml", file=sys.stderr)
|
|
sys.exit(1)
|
|
news_adoc = sys.argv[1]
|
|
feed_xml = sys.argv[2]
|
|
|
|
|
|
# So that this script may be accessed as a module.
|
|
if __name__ == "__main__":
|
|
main()
|