- Fix a few issues with podcast feed generation

- Tweak styles for devotional theme
- Fix bug with page cache building
This commit is contained in:
Daniel J. Summers 2022-06-04 20:49:14 -04:00
parent b367229814
commit 2394f03b3b
9 changed files with 68 additions and 38 deletions

View File

@ -312,10 +312,15 @@ module WebLog =
let _, leadPath = hostAndPath webLog
$"{leadPath}/{Permalink.toString permalink}"
/// Convert a date/time to the web log's local date/time
/// Convert a UTC date/time to the web log's local date/time
let localTime webLog (date : DateTime) =
let tz = TimeZoneInfo.FindSystemTimeZoneById webLog.timeZone
TimeZoneInfo.ConvertTimeFromUtc (DateTime (date.Ticks, DateTimeKind.Utc), tz)
TimeZoneInfo.ConvertTimeFromUtc
(DateTime (date.Ticks, DateTimeKind.Utc), TimeZoneInfo.FindSystemTimeZoneById webLog.timeZone)
/// Convert a date/time in the web log's local date/time to UTC
let utcTime webLog (date : DateTime) =
TimeZoneInfo.ConvertTimeToUtc
(DateTime (date.Ticks, DateTimeKind.Unspecified), TimeZoneInfo.FindSystemTimeZoneById webLog.timeZone)
/// A user of the web log

View File

@ -65,7 +65,10 @@ module PageListCache =
let update (ctx : HttpContext) = backgroundTask {
let webLog = ctx.WebLog
let! pages = Data.Page.findListed webLog.id ctx.Conn
_cache[webLog.urlBase] <- pages |> List.map (DisplayPage.fromPage webLog) |> Array.ofList
_cache[webLog.urlBase] <-
pages
|> List.map (fun pg -> DisplayPage.fromPage webLog { pg with text = "" })
|> Array.ofList
}

View File

@ -95,9 +95,18 @@ let private toFeedItem webLog (authors : MetaItem list) (cats : DisplayCategory[
Content = TextSyndicationContent.CreatePlaintextContent plainText)
item.AddPermalink (Uri item.Id)
let xmlDoc = XmlDocument ()
let encoded =
post.text.Replace("src=\"/", $"src=\"{webLog.urlBase}/").Replace ("href=\"/", $"href=\"{webLog.urlBase}/")
item.ElementExtensions.Add ("encoded", Namespace.content, encoded)
let txt =
post.text
.Replace("src=\"/", $"src=\"{webLog.urlBase}/")
.Replace ("href=\"/", $"href=\"{webLog.urlBase}/")
let it = xmlDoc.CreateElement ("content", "encoded", Namespace.content)
let _ = it.AppendChild (xmlDoc.CreateCDataSection txt)
it
item.ElementExtensions.Add encoded
item.Authors.Add (SyndicationPerson (
Name = (authors |> List.find (fun a -> a.name = WebLogUserId.toString post.authorId)).value))
[ post.categoryIds
@ -124,6 +133,7 @@ let private addEpisode webLog (feed : CustomFeed) (post : Post) (item : Syndicat
let epMediaUrl =
match (meta >> Option.get >> value) "episode_media_file" with
| link when link.StartsWith "http" -> link
| link when Option.isSome podcast.mediaBaseUrl -> $"{podcast.mediaBaseUrl.Value}{link}"
| link -> WebLog.absoluteUrl webLog (Permalink link)
let epMediaType =
match meta "episode_media_type", podcast.defaultMediaType with
@ -142,16 +152,22 @@ let private addEpisode webLog (feed : CustomFeed) (post : Post) (item : Syndicat
with :? ArgumentException -> ExplicitRating.toString podcast.explicit
let xmlDoc = XmlDocument ()
let enclosure = xmlDoc.CreateElement "enclosure"
enclosure.SetAttribute ("url", epMediaUrl)
meta "episode_media_length" |> Option.iter (fun it -> enclosure.SetAttribute ("length", it.value))
epMediaType |> Option.iter (fun typ -> enclosure.SetAttribute ("type", typ))
item.ElementExtensions.Add enclosure
let enclosure =
let it = xmlDoc.CreateElement "enclosure"
it.SetAttribute ("url", epMediaUrl)
meta "episode_media_length" |> Option.iter (fun len -> it.SetAttribute ("length", len.value))
epMediaType |> Option.iter (fun typ -> it.SetAttribute ("type", typ))
it
let image =
let it = xmlDoc.CreateElement ("itunes", "image", Namespace.iTunes)
it.SetAttribute ("href", epImageUrl)
it
item.ElementExtensions.Add enclosure
item.ElementExtensions.Add image
item.ElementExtensions.Add ("creator", Namespace.dc, podcast.displayedAuthor)
item.ElementExtensions.Add ("author", Namespace.iTunes, podcast.displayedAuthor)
item.ElementExtensions.Add ("summary", Namespace.iTunes, stripHtml post.text)
item.ElementExtensions.Add ("image", Namespace.iTunes, epImageUrl)
item.ElementExtensions.Add ("explicit", Namespace.iTunes, epExplicit)
meta "episode_subtitle"
|> Option.iter (fun it -> item.ElementExtensions.Add ("subtitle", Namespace.iTunes, it.value))
@ -218,21 +234,30 @@ let private addPodcast webLog (rssFeed : SyndicationFeed) (feed : CustomFeed) =
"link", feedUrl
]
|> List.fold (fun elt (name, value) -> addChild xmlDoc "" "" name value elt) (xmlDoc.CreateElement "image")
let iTunesImage =
let it = xmlDoc.CreateElement ("itunes", "image", Namespace.iTunes)
it.SetAttribute ("href", imageUrl)
it
let owner =
[ "name", podcast.displayedAuthor
"email", podcast.email
]
|> List.fold (fun elt (name, value) -> addChild xmlDoc Namespace.iTunes "itunes" name value elt)
(xmlDoc.CreateElement ("itunes", "owner", Namespace.iTunes))
let rawVoice =
let it = xmlDoc.CreateElement ("rawvoice", "subscribe", Namespace.rawVoice)
it.SetAttribute ("feed", feedUrl)
it.SetAttribute ("itunes", "")
it
rssFeed.ElementExtensions.Add image
rssFeed.ElementExtensions.Add owner
rssFeed.ElementExtensions.Add categorization
rssFeed.ElementExtensions.Add iTunesImage
rssFeed.ElementExtensions.Add rawVoice
rssFeed.ElementExtensions.Add ("summary", Namespace.iTunes, podcast.summary)
rssFeed.ElementExtensions.Add ("author", Namespace.iTunes, podcast.displayedAuthor)
rssFeed.ElementExtensions.Add ("image", Namespace.iTunes, imageUrl)
rssFeed.ElementExtensions.Add ("explicit", Namespace.iTunes, ExplicitRating.toString podcast.explicit)
rssFeed.ElementExtensions.Add ("subscribe", Namespace.rawVoice, feedUrl)
podcast.subtitle |> Option.iter (fun sub -> rssFeed.ElementExtensions.Add ("subtitle", Namespace.iTunes, sub))
/// Get the feed's self reference and non-feed link
@ -241,9 +266,10 @@ let private selfAndLink webLog feedType =
| StandardFeed path -> path
| CategoryFeed (_, path) -> path
| TagFeed (_, path) -> path
// TODO: get defined path for custom feed
| Custom (_, path) -> path
|> function
| path -> Permalink path, Permalink (path.Replace ($"/{webLog.rss.feedName}", ""))
| path -> Permalink path[1..], Permalink (path.Replace ($"/{webLog.rss.feedName}", ""))
/// Set the title and description of the feed based on its source
let private setTitleAndDescription feedType (webLog : WebLog) (cats : DisplayCategory[]) (feed : SyndicationFeed) =
@ -287,7 +313,7 @@ let createFeed (feedType : FeedType) posts : HttpHandler = fun next ctx -> backg
let toItem post =
let item = toFeedItem webLog authors cats tagMaps post
match podcast with
| Some feed when post.metadata |> List.exists (fun it -> it.name = "media") ->
| Some feed when post.metadata |> List.exists (fun it -> it.name = "episode_media_file") ->
addEpisode webLog feed post item
| Some _ ->
warn "Feed" ctx $"[{webLog.name} {Permalink.toString self}] \"{stripHtml post.title}\" has no media"
@ -298,7 +324,7 @@ let createFeed (feedType : FeedType) posts : HttpHandler = fun next ctx -> backg
addNamespace feed "content" Namespace.content
setTitleAndDescription feedType webLog cats feed
feed.LastUpdatedTime <- DateTimeOffset <| (List.head posts).updatedOn
feed.LastUpdatedTime <- (List.head posts).updatedOn |> DateTimeOffset
feed.Generator <- generator ctx
feed.Items <- posts |> Seq.ofList |> Seq.map toItem
feed.Language <- "en"

View File

@ -336,10 +336,7 @@ let save : HttpHandler = fun next ctx -> task {
let post =
match model.setPublished with
| true ->
let dt =
TimeZoneInfo.ConvertTimeToUtc
(DateTime (model.pubOverride.Value.Ticks, DateTimeKind.Unspecified),
TimeZoneInfo.FindSystemTimeZoneById webLog.timeZone)
let dt = WebLog.utcTime webLog model.pubOverride.Value
match model.setUpdated with
| true ->
{ post with

View File

@ -3,7 +3,7 @@
"hostname": "data02.bitbadger.solutions",
"database": "myWebLog_dev"
},
"Generator": "myWebLog 2.0-alpha30",
"Generator": "myWebLog 2.0-alpha31",
"Logging": {
"LogLevel": {
"MyWebLog.Handlers": "Debug"

View File

@ -19,10 +19,8 @@
</a>
</h1>
<p class="item-meta">
<i class="fa fa-calendar" title="Date"></i> {{ post.published_on | date: "dddd, MMMM d, yyyy" }} &nbsp;
{% comment %} TODO: reading time?
#[i.fa.fa-clock-o(title='Clock' aria-hidden='true')] #[= readingTime(post.content, 'minutes', 175)]
{% endcomment %}
<i class="fa fa-calendar" title="Date"></i> {{ post.published_on | date: "dddd, MMMM d, yyyy" }}
{% if logged_on %} &bull; <a href="{{ post | edit_post_link }}">Edit Post</a>{% endif %}
</p>
{%- assign media = post.metadata | value: "episode_media_file" -%}
{%- unless media == "-- episode_media_file not found --" %}

View File

@ -1,6 +1,7 @@
<div class="content">
<article class="item">
<h1 class="item-heading">{{ page.title }}</h1>
{%- if logged_on %}<p class="item-meta"><a href="{{ page | edit_page_link }}">Edit Page</a></p>{% endif %}
{{ page.text }}
</article>
</div>

View File

@ -5,6 +5,7 @@
<div class="content">
<article class="item">
<h1 class="item-heading">{{ post.title }}</h1>
{%- if logged_on %}<p class="item-meta"><a href="{{ post | edit_post_link }}">Edit Post</a></p>{% endif %}
{% assign media = post.metadata | value: "episode_media_file" %}
{%- unless media == "-- episode_media_file not found --" %}
<aside class="podcast">
@ -44,16 +45,6 @@
{{ post.published_on | date: "dddd, MMMM d, yyyy" }}
</div>
</div>
{% comment %}
TODO: reading time?
<div class="item">
<h4 class="item-heading">Reading Time</h4>
<div class="text-center">
<i class="fa fa-clock-o" title="Clock" aria-hidden="true"></i>
#[= readingTime(page.content, 'minutes', 175)]
</div>
</div>
{% endcomment %}
{%- assign has_ot = false -%}
{%- for ot_id in ot_books -%}
{%- if post.category_ids contains ot_id %}{% assign has_ot = true %}{% endif -%}

View File

@ -67,6 +67,9 @@ h1, h2, h3, h4, p, ul {
margin-top: 0;
margin-bottom: 1rem;
}
sup {
vertical-align: text-top;
}
.site-header {
display: flex;
flex-flow: row wrap;
@ -200,9 +203,10 @@ blockquote p:nth-last-of-type(2) {
blockquote.standard p:nth-last-of-type(2) {
margin-bottom: inherit;
}
blockquote.standard {
blockquote.standard, blockquote blockquote {
margin: 1rem 2rem 1rem 1rem;
border-left: solid 3px var(--accent-color);
border-top: unset;
font-family: inherit;
}
blockquote cite {
@ -225,7 +229,7 @@ blockquote cite::before {
}
blockquote sup {
color: var(--superscript-color);
padding-right: .35rem;
padding-right: .25rem;
}
.lord, .sc {
font-variant: small-caps;
@ -338,3 +342,8 @@ a.dl:link,
a.dl:visited {
color: var(--audio-text-color);
}
@media all and (max-width: 40rem) {
blockquote {
margin: 2rem 0;
}
}