diff --git a/img/json.gif b/img/json.gif
new file mode 100644
index 0000000..af158bc
Binary files /dev/null and b/img/json.gif differ
diff --git a/itsb.xml b/itsb.xml
index 3a50ee2..4fc5194 100644
--- a/itsb.xml
+++ b/itsb.xml
@@ -39,28 +39,28 @@
Canada
Rail, aviation, marine, pipeline
- http://www.bst-tsb.gc.ca/eng/fils-feeds/TSB%20Rail.xml
+ https://www.bst-tsb.gc.ca/eng/fils-feeds/TSB%20Rail.xml
- http://www.bst-tsb.gc.ca/fra/fils-feeds/BST%20Rail.xml
+ https://www.bst-tsb.gc.ca/fra/fils-feeds/BST%20Rail.xml
- http://www.bst-tsb.gc.ca/eng/fils-feeds/TSB%20Air.xml
+ https://www.bst-tsb.gc.ca/eng/fils-feeds/TSB%20Air.xml
- http://www.bst-tsb.gc.ca/fra/fils-feeds/BST%20Aviation.xml
+ https://www.bst-tsb.gc.ca/fra/fils-feeds/BST%20Aviation.xml
- http://www.bst-tsb.gc.ca/eng/fils-feeds/TSB%20Marine.xml
+ https://www.bst-tsb.gc.ca/eng/fils-feeds/TSB%20Marine.xml
- http://www.bst-tsb.gc.ca/fra/fils-feeds/BST%20Marine.xml
+ https://www.bst-tsb.gc.ca/fra/fils-feeds/BST%20Marine.xml
- http://www.bst-tsb.gc.ca/eng/fils-feeds/TSB%20Pipeline.xml
+ https://www.bst-tsb.gc.ca/eng/fils-feeds/TSB%20Pipeline.xml
- http://www.bst-tsb.gc.ca/fra/fils-feeds/BST%20Pipeline.xml
+ https://www.bst-tsb.gc.ca/fra/fils-feeds/BST%20Pipeline.xml
diff --git a/itsb.xsd b/itsb.xsd
index 10cea75..790c34d 100644
--- a/itsb.xsd
+++ b/itsb.xsd
@@ -310,6 +310,7 @@
+
diff --git a/jq/convert/atom2jsonfeed.jq b/jq/convert/atom2jsonfeed.jq
new file mode 100644
index 0000000..02084bc
--- /dev/null
+++ b/jq/convert/atom2jsonfeed.jq
@@ -0,0 +1,52 @@
+# Atom->JSON Feed converter
+# Expects xmltodict JSON output as input, outputs a JSON Feed 1.1 feed backwards-compatible with 1.0
+# Does not support entries without links.
+# Required variables:
+# $feed_url: Absolute URL to the resulting JSON Feed
+
+def ensure_string: if type == "array" then .[0] else . end | if type == "object" then .["#text"] else . end;
+def ensure_array: (. // []) | if type == "array" then . else [.] end;
+def find_links(rel): [(.link // []) | if type == "array" then .[] else . end | select(.["@rel"] == rel)];
+def parse_authors: [
+ ((.author | ensure_array) + (.contributor | ensure_array))[]
+ | . as $author
+ | {"name": .name}
+ | if $author.uri then .url = $author.uri else . end
+ ];
+
+.feed | . as $feed | {
+ "version": "https://jsonfeed.org/version/1.1",
+ "title": (.title | ensure_string),
+ "home_page_url": find_links("alternate")[0]["@href"],
+ "feed_url": $feed_url,
+ "description": (.description | ensure_string // ""),
+ "expired": false,
+ "authors": parse_authors,
+ "items": [
+ .entry | ensure_array[] | select(.link) | . as $entry | {
+ "id": .id,
+ "title": (.title | ensure_string),
+ "url": find_links("alternate")[0]["@href"],
+ "date_published": (.published // .updated),
+ "date_modified": .updated,
+ "authors": parse_authors,
+ "tags": [
+ .category | ensure_array[] | .["@term"]
+ ],
+ "attachments": [
+ find_links("enclosure")[] | {
+ "url": .["@href"],
+ "size_in_bytes": .["@length"],
+ "mime_type": .["@type"]
+ }
+ ],
+ "content_html": (.content | ensure_array[0] | ensure_string // "")
+ }
+ # Optional summary
+ | if $entry.summary then .summary = ($entry.summary | ensure_string // "") else . end
+ # Optional external URL
+ | if ($entry|find_links("related")[0]) then .external_url = ($entry|find_links("related")[0]["@href"]) else . end
+ ]
+}
+# Optional icon
+| if $feed.icon then .icon = $feed.icon else . end
diff --git a/jq/convert/rss2jsonfeed.jq b/jq/convert/rss2jsonfeed.jq
new file mode 100644
index 0000000..01485c2
--- /dev/null
+++ b/jq/convert/rss2jsonfeed.jq
@@ -0,0 +1,43 @@
+# RSS->JSON Feed converter
+# Expects xmltodict JSON output as input, outputs a JSON Feed 1.1 feed backwards-compatible with 1.0
+# Does not support RSS items without links.
+# Required variables:
+# $feed_url: Absolute URL to the resulting JSON Feed
+
+def ensure_string: if type == "array" then .[0] else . end | if type == "object" then .["#text"] else . end;
+def ensure_array: (. // []) | if type == "array" then . else [.] end;
+
+.rss.channel | . as $channel | {
+ "version": "https://jsonfeed.org/version/1.1",
+ "title": (.title | ensure_string),
+ "home_page_url": (.link | ensure_string),
+ "feed_url": $feed_url,
+ "description": (.description | ensure_string),
+ "expired": false,
+ "items": [
+ .item | ensure_array[] | select(.link) | . as $item | {
+ "id": (.guid // .link | ensure_string),
+ "title": .title,
+ "url": .link,
+ "content_html": (.description // "" | ensure_string),
+ "tags": [
+ .category | ensure_array[] | ensure_string
+ ],
+ "attachments": [
+ .enclosure | ensure_array[] | {
+ "url": .["@url"],
+ "size_in_bytes": .["@length"],
+ "mime_type": .["@type"]
+ }
+ ]
+ }
+ # Optional publication date
+ | if $item.pubDate then .date_published = ($item.pubDate | strptime("%a, %d %b %Y %T %z") | mktime | todateiso8601) else . end
+ # Optional author
+ | if $item.author then .author = {"name": $item.author} | .authors = [.author] else . end
+ ]
+}
+# Optional language
+| if $channel.language then .language = $channel.language else . end
+# Optional icon
+| if $channel.image then .icon = $channel.image.url else . end
diff --git a/xslt/itsb.xsl b/xslt/itsb.xsl
index ed7d3d9..3cf84f8 100644
--- a/xslt/itsb.xsl
+++ b/xslt/itsb.xsl
@@ -6,9 +6,10 @@
xmlns:itsb="http://tilde.town/~lucidiot/itsb/">
-
+
+
+
+
@@ -24,58 +25,119 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -rss
-
-
-
-
-
-
-
-
- -2rss
-
- rss
-
-
-
- cat $DIR/feeds/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -json
+
+
+
+
+
+ cat $DIR/feeds/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ convert/
+
+ 2jsonfeed.jq
+
+
+
+ feeds/_json/
+
+ .json
+
+
+
+
+