Add Page Find[Full]ById tests
- Add prior permalink to a page
This commit is contained in:
1 parent
0e8044b948
commit
3f269ed3ba
8 files changed
+503
-20
No files matched your search
@@ -53,15 +53,18 @@ type PostgresPageData(log: ILogger) =
|
|||||||
log.LogTrace "Page.countListed"
|
log.LogTrace "Page.countListed"
|
||||||
Count.byContains Table.Page {| webLogDoc webLogId with IsInPageList = true |}
|
Count.byContains Table.Page {| webLogDoc webLogId with IsInPageList = true |}
|
||||||
|
|
||||||
/// Find a page by its ID (without revisions)
|
/// Find a page by its ID (without revisions or prior permalinks)
|
||||||
let findById pageId webLogId =
|
let findById pageId webLogId = backgroundTask {
|
||||||
log.LogTrace "Page.findById"
|
log.LogTrace "Page.findById"
|
||||||
Document.findByIdAndWebLog<PageId, Page> Table.Page pageId webLogId
|
match! Document.findByIdAndWebLog<PageId, Page> Table.Page pageId webLogId with
|
||||||
|
| Some page -> return Some { page with PriorPermalinks = [] }
|
||||||
|
| None -> return None
|
||||||
|
}
|
||||||
|
|
||||||
/// Find a complete page by its ID
|
/// Find a complete page by its ID
|
||||||
let findFullById pageId webLogId = backgroundTask {
|
let findFullById pageId webLogId = backgroundTask {
|
||||||
log.LogTrace "Page.findFullById"
|
log.LogTrace "Page.findFullById"
|
||||||
match! findById pageId webLogId with
|
match! Document.findByIdAndWebLog<PageId, Page> Table.Page pageId webLogId with
|
||||||
| Some page ->
|
| Some page ->
|
||||||
let! withMore = appendPageRevisions page
|
let! withMore = appendPageRevisions page
|
||||||
return Some withMore
|
return Some withMore
|
||||||
|
|||||||
@@ -444,20 +444,27 @@ type RethinkDbData(conn: Net.IConnection, config: DataConfig, log: ILogger<Rethi
|
|||||||
return result.Deleted > 0UL
|
return result.Deleted > 0UL
|
||||||
}
|
}
|
||||||
|
|
||||||
member _.FindById pageId webLogId =
|
member _.FindById pageId webLogId = backgroundTask {
|
||||||
rethink<Page> {
|
let! page =
|
||||||
withTable Table.Page
|
rethink<Page list> {
|
||||||
get pageId
|
withTable Table.Page
|
||||||
without [ nameof Page.Empty.PriorPermalinks; nameof Page.Empty.Revisions ]
|
getAll [ pageId ]
|
||||||
resultOption; withRetryOptionDefault
|
without [ nameof Page.Empty.PriorPermalinks; nameof Page.Empty.Revisions ]
|
||||||
}
|
result; withRetryDefault
|
||||||
|> verifyWebLog webLogId (fun it -> it.WebLogId) <| conn
|
}
|
||||||
|
|> tryFirst <| conn
|
||||||
|
return
|
||||||
|
page
|
||||||
|
|> Option.filter (fun pg -> pg.WebLogId = webLogId)
|
||||||
|
|> Option.map (fun pg -> { pg with Revisions = []; PriorPermalinks = [] })
|
||||||
|
}
|
||||||
|
|
||||||
member _.FindByPermalink permalink webLogId =
|
member _.FindByPermalink permalink webLogId =
|
||||||
rethink<Page list> {
|
rethink<Page list> {
|
||||||
withTable Table.Page
|
withTable Table.Page
|
||||||
getAll [ [| webLogId :> obj; permalink |] ] (nameof Page.Empty.Permalink)
|
getAll [ [| webLogId :> obj; permalink |] ] (nameof Page.Empty.Permalink)
|
||||||
without [ nameof Page.Empty.PriorPermalinks; nameof Page.Empty.Revisions ]
|
merge (r.HashMap(nameof Page.Empty.PriorPermalinks, [||])
|
||||||
|
.With(nameof Page.Empty.Revisions, [||]))
|
||||||
limit 1
|
limit 1
|
||||||
result; withRetryDefault
|
result; withRetryDefault
|
||||||
}
|
}
|
||||||
@@ -474,7 +481,7 @@ type RethinkDbData(conn: Net.IConnection, config: DataConfig, log: ILogger<Rethi
|
|||||||
result; withRetryDefault
|
result; withRetryDefault
|
||||||
}
|
}
|
||||||
|> tryFirst) conn
|
|> tryFirst) conn
|
||||||
return result |> Option.map (fun pg -> pg.Permalink)
|
return result |> Option.map _.Permalink
|
||||||
}
|
}
|
||||||
|
|
||||||
member _.FindFullById pageId webLogId =
|
member _.FindFullById pageId webLogId =
|
||||||
@@ -483,7 +490,7 @@ type RethinkDbData(conn: Net.IConnection, config: DataConfig, log: ILogger<Rethi
|
|||||||
get pageId
|
get pageId
|
||||||
resultOption; withRetryOptionDefault
|
resultOption; withRetryOptionDefault
|
||||||
}
|
}
|
||||||
|> verifyWebLog webLogId (fun it -> it.WebLogId) <| conn
|
|> verifyWebLog webLogId _.WebLogId <| conn
|
||||||
|
|
||||||
member _.FindFullByWebLog webLogId = rethink<Page> {
|
member _.FindFullByWebLog webLogId = rethink<Page> {
|
||||||
withTable Table.Page
|
withTable Table.Page
|
||||||
|
|||||||
@@ -57,15 +57,18 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
|
|||||||
[ webLogParam webLogId ]
|
[ webLogParam webLogId ]
|
||||||
(toCount >> int)
|
(toCount >> int)
|
||||||
|
|
||||||
/// Find a page by its ID (without revisions)
|
/// Find a page by its ID (without revisions and prior permalinks)
|
||||||
let findById pageId webLogId =
|
let findById pageId webLogId = backgroundTask {
|
||||||
log.LogTrace "Page.findById"
|
log.LogTrace "Page.findById"
|
||||||
Document.findByIdAndWebLog<PageId, Page> Table.Page pageId webLogId conn
|
match! Document.findByIdAndWebLog<PageId, Page> Table.Page pageId webLogId conn with
|
||||||
|
| Some page -> return Some { page with PriorPermalinks = [] }
|
||||||
|
| None -> return None
|
||||||
|
}
|
||||||
|
|
||||||
/// Find a complete page by its ID
|
/// Find a complete page by its ID
|
||||||
let findFullById pageId webLogId = backgroundTask {
|
let findFullById pageId webLogId = backgroundTask {
|
||||||
log.LogTrace "Page.findFullById"
|
log.LogTrace "Page.findFullById"
|
||||||
match! findById pageId webLogId with
|
match! Document.findByIdAndWebLog<PageId, Page> Table.Page pageId webLogId conn with
|
||||||
| Some page ->
|
| Some page ->
|
||||||
let! page = appendPageRevisions page
|
let! page = appendPageRevisions page
|
||||||
return Some page
|
return Some page
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
module PageDataTests
|
module PageDataTests
|
||||||
|
|
||||||
|
open System
|
||||||
open Expecto
|
open Expecto
|
||||||
open MyWebLog
|
open MyWebLog
|
||||||
open MyWebLog.Data
|
open MyWebLog.Data
|
||||||
@@ -8,6 +9,12 @@ open NodaTime
|
|||||||
/// The ID of the root web log
|
/// The ID of the root web log
|
||||||
let rootId = WebLogId "uSitJEuD3UyzWC9jgOHc8g"
|
let rootId = WebLogId "uSitJEuD3UyzWC9jgOHc8g"
|
||||||
|
|
||||||
|
/// The ID of the "A cool page" page
|
||||||
|
let coolPageId = PageId "hgc_BLEZ50SoAWLuPNISvA"
|
||||||
|
|
||||||
|
/// The published and updated time of the "A cool page" page
|
||||||
|
let coolPagePublished = Instant.FromDateTimeOffset(DateTimeOffset.Parse "2024-01-20T22:14:28Z")
|
||||||
|
|
||||||
let ``Add succeeds`` (data: IData) = task {
|
let ``Add succeeds`` (data: IData) = task {
|
||||||
let page =
|
let page =
|
||||||
{ Id = PageId "added-page"
|
{ Id = PageId "added-page"
|
||||||
@@ -55,6 +62,8 @@ let ``All succeeds`` (data: IData) = task {
|
|||||||
Expect.isEmpty pg.Metadata $"Page {idx} should have had no metadata"
|
Expect.isEmpty pg.Metadata $"Page {idx} should have had no metadata"
|
||||||
Expect.isEmpty pg.Revisions $"Page {idx} should have had no revisions"
|
Expect.isEmpty pg.Revisions $"Page {idx} should have had no revisions"
|
||||||
Expect.isEmpty pg.PriorPermalinks $"Page {idx} should have had no prior permalinks")
|
Expect.isEmpty pg.PriorPermalinks $"Page {idx} should have had no prior permalinks")
|
||||||
|
let! others = data.Page.All (WebLogId "not-there")
|
||||||
|
Expect.isEmpty others "There should not be pages retrieved"
|
||||||
}
|
}
|
||||||
|
|
||||||
let ``CountAll succeeds`` (data: IData) = task {
|
let ``CountAll succeeds`` (data: IData) = task {
|
||||||
@@ -66,3 +75,54 @@ let ``CountListed succeeds`` (data: IData) = task {
|
|||||||
let! pages = data.Page.CountListed rootId
|
let! pages = data.Page.CountListed rootId
|
||||||
Expect.equal pages 1 "There should have been 1 page in the page list"
|
Expect.equal pages 1 "There should have been 1 page in the page list"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ``FindById succeeds when a page is found`` (data: IData) = task {
|
||||||
|
let! page = data.Page.FindById coolPageId rootId
|
||||||
|
Expect.isSome page "A page should have been returned"
|
||||||
|
let pg = page.Value
|
||||||
|
Expect.equal pg.Id coolPageId "The wrong page was retrieved"
|
||||||
|
Expect.equal pg.WebLogId rootId "The page's web log did not match the called parameter"
|
||||||
|
Expect.equal pg.AuthorId (WebLogUserId "5EM2rimH9kONpmd2zQkiVA") "Author ID is incorrect"
|
||||||
|
Expect.equal pg.Title "Page Title" "Title is incorrect"
|
||||||
|
Expect.equal pg.Permalink (Permalink "a-cool-page.html") "Permalink is incorrect"
|
||||||
|
Expect.equal
|
||||||
|
pg.PublishedOn (Instant.FromDateTimeOffset(DateTimeOffset.Parse "2024-01-20T22:14:28Z")) "Published On is incorrect"
|
||||||
|
Expect.equal pg.UpdatedOn (Instant.FromDateTimeOffset(DateTimeOffset.Parse "2024-01-20T22:14:28Z")) "Updated On is incorrect"
|
||||||
|
Expect.isFalse pg.IsInPageList "Is in page list flag should not have been set"
|
||||||
|
Expect.equal pg.Text "<h1 id=\"a-cool-page\">A Cool Page</h1>\n<p>It really is cool!</p>\n" "Text is incorrect"
|
||||||
|
Expect.hasLength pg.Metadata 2 "There should be 2 metadata items on this page"
|
||||||
|
Expect.equal pg.Metadata[0].Name "Cool" "Meta item 0 name is incorrect"
|
||||||
|
Expect.equal pg.Metadata[0].Value "true" "Meta item 0 value is incorrect"
|
||||||
|
Expect.equal pg.Metadata[1].Name "Warm" "Meta item 1 name is incorrect"
|
||||||
|
Expect.equal pg.Metadata[1].Value "false" "Meta item 1 value is incorrect"
|
||||||
|
Expect.isEmpty pg.Revisions "Revisions should not have been retrieved"
|
||||||
|
Expect.isEmpty pg.PriorPermalinks "Prior permalinks should not have been retrieved"
|
||||||
|
}
|
||||||
|
|
||||||
|
let ``FindById succeeds when a page is not found (incorrect weblog)`` (data: IData) = task {
|
||||||
|
let! page = data.Page.FindById coolPageId (WebLogId "wrong")
|
||||||
|
Expect.isNone page "The page should not have been retrieved"
|
||||||
|
}
|
||||||
|
|
||||||
|
let ``FindById succeeds when a page is not found (bad page ID)`` (data: IData) = task {
|
||||||
|
let! page = data.Page.FindById (PageId "missing") rootId
|
||||||
|
Expect.isNone page "The page should not have been retrieved"
|
||||||
|
}
|
||||||
|
|
||||||
|
let ``FindFullById succeeds when a page is found`` (data: IData) = task {
|
||||||
|
let! page = data.Page.FindFullById coolPageId rootId
|
||||||
|
Expect.isSome page "A page should have been returned"
|
||||||
|
let pg = page.Value
|
||||||
|
Expect.equal pg.Id coolPageId "The wrong page was retrieved"
|
||||||
|
Expect.equal pg.WebLogId rootId "The page's web log did not match the called parameter"
|
||||||
|
Expect.hasLength pg.Revisions 1 "There should be 1 revision"
|
||||||
|
Expect.equal pg.Revisions[0].AsOf coolPagePublished "Revision 0 as-of is incorrect"
|
||||||
|
Expect.equal pg.Revisions[0].Text (Markdown "# A Cool Page\n\nIt really is cool!") "Revision 0 text is incorrect"
|
||||||
|
Expect.hasLength pg.PriorPermalinks 1 "There should be 1 prior permalink"
|
||||||
|
Expect.equal pg.PriorPermalinks[0] (Permalink "a-cool-pg.html") "Prior permalink 0 is incorrect"
|
||||||
|
}
|
||||||
|
|
||||||
|
let ``FindFullById succeeds when a page is not found`` (data: IData) = task {
|
||||||
|
let! page = data.Page.FindFullById (PageId "not-there") rootId
|
||||||
|
Expect.isNone page "A page should not have been retrieved"
|
||||||
|
}
|
||||||
@@ -131,6 +131,25 @@ let pageTests = testList "Page" [
|
|||||||
testTask "CountListed succeeds" {
|
testTask "CountListed succeeds" {
|
||||||
do! PageDataTests.``CountListed succeeds`` (mkData ())
|
do! PageDataTests.``CountListed succeeds`` (mkData ())
|
||||||
}
|
}
|
||||||
|
testList "FindById" [
|
||||||
|
testTask "succeeds when a page is found" {
|
||||||
|
do! PageDataTests.``FindById succeeds when a page is found`` (mkData ())
|
||||||
|
}
|
||||||
|
testTask "succeeds when a page is not found (incorrect weblog)" {
|
||||||
|
do! PageDataTests.``FindById succeeds when a page is not found (incorrect weblog)`` (mkData ())
|
||||||
|
}
|
||||||
|
testTask "succeeds when a page is not found (bad page ID)" {
|
||||||
|
do! PageDataTests.``FindById succeeds when a page is not found (bad page ID)`` (mkData ())
|
||||||
|
}
|
||||||
|
]
|
||||||
|
testList "FindFullById" [
|
||||||
|
testTask "succeeds when a page is found" {
|
||||||
|
do! PageDataTests.``FindFullById succeeds when a page is found`` (mkData ())
|
||||||
|
}
|
||||||
|
testTask "succeeds when a page is not found" {
|
||||||
|
do! PageDataTests.``FindFullById succeeds when a page is not found`` (mkData ())
|
||||||
|
}
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
/// Drop the throwaway PostgreSQL database
|
/// Drop the throwaway PostgreSQL database
|
||||||
|
|||||||
@@ -130,6 +130,25 @@ let pageTests = testList "Page" [
|
|||||||
testTask "CountListed succeeds" {
|
testTask "CountListed succeeds" {
|
||||||
do! PageDataTests.``CountListed succeeds`` data.Value
|
do! PageDataTests.``CountListed succeeds`` data.Value
|
||||||
}
|
}
|
||||||
|
testList "FindById" [
|
||||||
|
testTask "succeeds when a page is found" {
|
||||||
|
do! PageDataTests.``FindById succeeds when a page is found`` data.Value
|
||||||
|
}
|
||||||
|
testTask "succeeds when a page is not found (incorrect weblog)" {
|
||||||
|
do! PageDataTests.``FindById succeeds when a page is not found (incorrect weblog)`` data.Value
|
||||||
|
}
|
||||||
|
testTask "succeeds when a page is not found (bad page ID)" {
|
||||||
|
do! PageDataTests.``FindById succeeds when a page is not found (bad page ID)`` data.Value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
testList "FindFullById" [
|
||||||
|
testTask "succeeds when a page is found" {
|
||||||
|
do! PageDataTests.``FindFullById succeeds when a page is found`` data.Value
|
||||||
|
}
|
||||||
|
testTask "succeeds when a page is not found" {
|
||||||
|
do! PageDataTests.``FindFullById succeeds when a page is not found`` data.Value
|
||||||
|
}
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
/// Drop the throwaway RethinkDB database
|
/// Drop the throwaway RethinkDB database
|
||||||
|
|||||||
@@ -164,6 +164,35 @@ let pageTests = testList "Page" [
|
|||||||
try do! PageDataTests.``CountListed succeeds`` data
|
try do! PageDataTests.``CountListed succeeds`` data
|
||||||
finally dispose data
|
finally dispose data
|
||||||
}
|
}
|
||||||
|
testList "FindById" [
|
||||||
|
testTask "succeeds when a page is found" {
|
||||||
|
let data = mkData ()
|
||||||
|
try do! PageDataTests.``FindById succeeds when a page is found`` data
|
||||||
|
finally dispose data
|
||||||
|
}
|
||||||
|
testTask "succeeds when a page is not found (incorrect weblog)" {
|
||||||
|
let data = mkData ()
|
||||||
|
try do! PageDataTests.``FindById succeeds when a page is not found (incorrect weblog)`` data
|
||||||
|
finally dispose data
|
||||||
|
}
|
||||||
|
testTask "succeeds when a page is not found (bad page ID)" {
|
||||||
|
let data = mkData ()
|
||||||
|
try do! PageDataTests.``FindById succeeds when a page is not found (bad page ID)`` data
|
||||||
|
finally dispose data
|
||||||
|
}
|
||||||
|
]
|
||||||
|
testList "FindFullById" [
|
||||||
|
testTask "succeeds when a page is found" {
|
||||||
|
let data = mkData ()
|
||||||
|
try do! PageDataTests.``FindFullById succeeds when a page is found`` data
|
||||||
|
finally dispose data
|
||||||
|
}
|
||||||
|
testTask "succeeds when a page is not found" {
|
||||||
|
let data = mkData ()
|
||||||
|
try do! PageDataTests.``FindFullById succeeds when a page is not found`` data
|
||||||
|
finally dispose data
|
||||||
|
}
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
/// Delete the SQLite database
|
/// Delete the SQLite database
|
||||||
|
|||||||
@@ -1 +1,344 @@
|
|||||||
{"WebLog":{"Id":"uSitJEuD3UyzWC9jgOHc8g","Name":"Root WebLog","Slug":"root-weblog","Subtitle":"This is the main one","DefaultPage":"posts","PostsPerPage":9,"ThemeId":"default","UrlBase":"http://localhost:8081","TimeZone":"America/Denver","Rss":{"IsFeedEnabled":true,"FeedName":"feed","ItemsInFeed":7,"IsCategoryEnabled":true,"IsTagEnabled":true,"Copyright":"CC40-NC-BY","CustomFeeds":[{"Id":"isPQ6drbDEydxohQzaiYtQ","Source":"tag:podcast","Path":"podcast-feed","Podcast":{"Title":"Root Podcast","ItemsInFeed":23,"Summary":"All things that happen in the domain root","DisplayedAuthor":"Podcaster Extraordinaire","Email":"podcaster@example.com","ImageUrl":"images/cover-art.png","AppleCategory":"Fiction","AppleSubcategory":"Drama","Explicit":"no","DefaultMediaType":"audio/mpeg","MediaBaseUrl":"https://media.example.com/root/","PodcastGuid":"10fd7f79-c719-4e1d-9da7-10405dd4fd96","FundingUrl":"https://example.com/support-us","FundingText":"Support Our Work","Medium":"newsletter"}}]},"AutoHtmx":true,"Uploads":"Database","RedirectRules":[]},"Users":[{"Id":"5EM2rimH9kONpmd2zQkiVA","WebLogId":"uSitJEuD3UyzWC9jgOHc8g","Email":"root@example.com","FirstName":"Root","LastName":"Owner","PreferredName":"Admin","PasswordHash":"AQAAAAIAAYagAAAAEEnq9J9lKZoMQZaTOJHKIQo44skDdzDigzqS+o6myMop38YuHfm/vNs9b/WpYjsOxg==","AccessLevel":"Administrator","CreatedOn":"2024-01-20T21:49:03Z","LastSeenOn":"2024-01-20T22:25:03Z"},{"Id":"GPbJaSOwTkKt14ZKYyveKA","WebLogId":"uSitJEuD3UyzWC9jgOHc8g","Email":"editor@example.com","FirstName":"Ed","LastName":"It-Or","PreferredName":"Edits","PasswordHash":"AQAAAAIAAYagAAAAEA8E3NwJkZO+q35FTmUT0wMNB8IpBOSVACKQcccXpaWfZJMRmZzjPEzd4j/f9h+rEA==","AccessLevel":"Editor","CreatedOn":"2024-01-20T21:58:42Z"},{"Id":"iIRNLSeY0EanxRPyqGuwVg","WebLogId":"uSitJEuD3UyzWC9jgOHc8g","Email":"author@example.com","FirstName":"Author","LastName":"Dude","PreferredName":"Mister","PasswordHash":"AQAAAAIAAYagAAAAEBYNf1sR/pjaX2dZgqlvpH/Tqpz2h/CG3rsk/wH2ReTysjpK/gxSqht7IULWXM7KHQ==","Url":"https://example.com/author","AccessLevel":"Author","CreatedOn":"2024-01-20T21:53:27Z"}],"Theme":{"Id":"default","Name":"myWebLog Default Theme","Version":"2.1.0","Templates":[{"Name":"single-post","Text":"{%- assign post = model.posts | first -%}\n<h1>{{ post.title }}</h1>\n<h4 class=\"item-meta text-muted\">\n {% if post.published_on -%}\n Published {{ post.published_on | date: \"dddd, MMMM d, yyyy\" }}\n at {{ post.published_on | date: \"h:mm tt\" | downcase }}\n {%- else -%}\n **DRAFT**\n {% endif %}\n by {{ model.authors | value: post.author_id }}\n {%- if is_editor or is_author and user_id == post.author_id %}\n • <a hx-boost=false href=\"{{ post | edit_post_link }}\">Edit Post</a>\n {%- endif %}\n</h4>\n<div>\n <article class=\"container mt-3\">\n <div>{{ post.text }}</div>\n {%- assign cat_count = post.category_ids | size -%}\n {% if cat_count > 0 -%}\n <h4 class=\"item-meta text-muted\">\n Categorized under\n {% for cat_id in post.category_ids -%}\n {% assign cat = categories | where: \"Id\", cat_id | first %}\n <span class=text-nowrap>\n <a href=\"{{ cat | category_link }}\" title=\"Categorized under “{{ cat.name | escape }}”\">\n {{ cat.name }}\n </a>\n </span>\n {% unless forloop.last %} • {% endunless %}\n {%- endfor %}\n </h4>\n {%- endif %}\n {%- assign tag_count = post.tags | size -%}\n {% if tag_count > 0 -%}\n <h4 class=\"item-meta text-muted\">\n Tagged\n {% for tag in post.tags %}\n <span class=text-nowrap>\n <a href=\"{{ tag | tag_link }}\" title=\"Posts tagged “{{ tag | escape }}”\" rel=\"tag\">{{ tag }}</a>\n </span>\n {% unless forloop.last %} • {% endunless %}\n {%- endfor %}\n </h4>\n {%- endif %}\n </article>\n <div>\n <nav aria-label=pagination>\n <ul class=\"pagination justify-content-evenly mt-5\">\n {% if model.newer_link -%}\n <li class=page-item>\n <a class=page-link href=\"{{ model.newer_link.value | relative_link }}\">{{ model.newer_name.value }}</a>\n <span class=text-muted>« Previous Post</span>\n {% endif %}\n {% if model.older_link -%}\n <li class=\"page-item text-end\">\n <a class=page-link href=\"{{ model.older_link.value | relative_link }}\">{{ model.older_name.value }}</a>\n <span class=text-muted>Next Post »</span>\n {%- endif -%}\n </ul>\n </nav>\n </div>\n</div>\n"},{"Name":"single-page","Text":"<h2 class=py-3>{{ page.title }}</h2>\n<article class=\"container\">{{ page.text }}</article>\n"},{"Name":"layout","Text":"<!DOCTYPE html>\n<html lang=en>\n <meta charset=utf-8>\n <meta name=viewport content=\"width=device-width\">\n <link rel=stylesheet href=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css\n integrity=sha384-1BmE4kWBq78iYhFldvKLine truncated
|
{
|
||||||
|
"WebLog": {
|
||||||
|
"Id": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"Name": "Root WebLog",
|
||||||
|
"Slug": "root-weblog",
|
||||||
|
"Subtitle": "This is the main one",
|
||||||
|
"DefaultPage": "posts",
|
||||||
|
"PostsPerPage": 9,
|
||||||
|
"ThemeId": "default",
|
||||||
|
"UrlBase": "http://localhost:8081",
|
||||||
|
"TimeZone": "America/Denver",
|
||||||
|
"Rss": {
|
||||||
|
"IsFeedEnabled": true,
|
||||||
|
"FeedName": "feed",
|
||||||
|
"ItemsInFeed": 7,
|
||||||
|
"IsCategoryEnabled": true,
|
||||||
|
"IsTagEnabled": true,
|
||||||
|
"Copyright": "CC40-NC-BY",
|
||||||
|
"CustomFeeds": [
|
||||||
|
{
|
||||||
|
"Id": "isPQ6drbDEydxohQzaiYtQ",
|
||||||
|
"Source": "tag:podcast",
|
||||||
|
"Path": "podcast-feed",
|
||||||
|
"Podcast": {
|
||||||
|
"Title": "Root Podcast",
|
||||||
|
"ItemsInFeed": 23,
|
||||||
|
"Summary": "All things that happen in the domain root",
|
||||||
|
"DisplayedAuthor": "Podcaster Extraordinaire",
|
||||||
|
"Email": "podcaster@example.com",
|
||||||
|
"ImageUrl": "images/cover-art.png",
|
||||||
|
"AppleCategory": "Fiction",
|
||||||
|
"AppleSubcategory": "Drama",
|
||||||
|
"Explicit": "no",
|
||||||
|
"DefaultMediaType": "audio/mpeg",
|
||||||
|
"MediaBaseUrl": "https://media.example.com/root/",
|
||||||
|
"PodcastGuid": "10fd7f79-c719-4e1d-9da7-10405dd4fd96",
|
||||||
|
"FundingUrl": "https://example.com/support-us",
|
||||||
|
"FundingText": "Support Our Work",
|
||||||
|
"Medium": "newsletter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"AutoHtmx": true,
|
||||||
|
"Uploads": "Database",
|
||||||
|
"RedirectRules": []
|
||||||
|
},
|
||||||
|
"Users": [
|
||||||
|
{
|
||||||
|
"Id": "5EM2rimH9kONpmd2zQkiVA",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"Email": "root@example.com",
|
||||||
|
"FirstName": "Root",
|
||||||
|
"LastName": "Owner",
|
||||||
|
"PreferredName": "Admin",
|
||||||
|
"PasswordHash": "AQAAAAIAAYagAAAAEEnq9J9lKZoMQZaTOJHKIQo44skDdzDigzqS+o6myMop38YuHfm/vNs9b/WpYjsOxg==",
|
||||||
|
"AccessLevel": "Administrator",
|
||||||
|
"CreatedOn": "2024-01-20T21:49:03Z",
|
||||||
|
"LastSeenOn": "2024-01-20T22:25:03Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "GPbJaSOwTkKt14ZKYyveKA",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"Email": "editor@example.com",
|
||||||
|
"FirstName": "Ed",
|
||||||
|
"LastName": "It-Or",
|
||||||
|
"PreferredName": "Edits",
|
||||||
|
"PasswordHash": "AQAAAAIAAYagAAAAEA8E3NwJkZO+q35FTmUT0wMNB8IpBOSVACKQcccXpaWfZJMRmZzjPEzd4j/f9h+rEA==",
|
||||||
|
"AccessLevel": "Editor",
|
||||||
|
"CreatedOn": "2024-01-20T21:58:42Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "iIRNLSeY0EanxRPyqGuwVg",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"Email": "author@example.com",
|
||||||
|
"FirstName": "Author",
|
||||||
|
"LastName": "Dude",
|
||||||
|
"PreferredName": "Mister",
|
||||||
|
"PasswordHash": "AQAAAAIAAYagAAAAEBYNf1sR/pjaX2dZgqlvpH/Tqpz2h/CG3rsk/wH2ReTysjpK/gxSqht7IULWXM7KHQ==",
|
||||||
|
"Url": "https://example.com/author",
|
||||||
|
"AccessLevel": "Author",
|
||||||
|
"CreatedOn": "2024-01-20T21:53:27Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Theme": {
|
||||||
|
"Id": "default",
|
||||||
|
"Name": "myWebLog Default Theme",
|
||||||
|
"Version": "2.1.0",
|
||||||
|
"Templates": [
|
||||||
|
{
|
||||||
|
"Name": "single-post",
|
||||||
|
"Text": "{%- assign post = model.posts | first -%}\n<h1>{{ post.title }}</h1>\n<h4 class=\"item-meta text-muted\">\n {% if post.published_on -%}\n Published {{ post.published_on | date: \"dddd, MMMM d, yyyy\" }}\n at {{ post.published_on | date: \"h:mm tt\" | downcase }}\n {%- else -%}\n **DRAFT**\n {% endif %}\n by {{ model.authors | value: post.author_id }}\n {%- if is_editor or is_author and user_id == post.author_id %}\n • <a hx-boost=false href=\"{{ post | edit_post_link }}\">Edit Post</a>\n {%- endif %}\n</h4>\n<div>\n <article class=\"container mt-3\">\n <div>{{ post.text }}</div>\n {%- assign cat_count = post.category_ids | size -%}\n {% if cat_count > 0 -%}\n <h4 class=\"item-meta text-muted\">\n Categorized under\n {% for cat_id in post.category_ids -%}\n {% assign cat = categories | where: \"Id\", cat_id | first %}\n <span class=text-nowrap>\n <a href=\"{{ cat | category_link }}\" title=\"Categorized under “{{ cat.name | escape }}”\">\n {{ cat.name }}\n </a>\n </span>\n {% unless forloop.last %} • {% endunless %}\n {%- endfor %}\n </h4>\n {%- endif %}\n {%- assign tag_count = post.tags | size -%}\n {% if tag_count > 0 -%}\n <h4 class=\"item-meta text-muted\">\n Tagged\n {% for tag in post.tags %}\n <span class=text-nowrap>\n <a href=\"{{ tag | tag_link }}\" title=\"Posts tagged “{{ tag | escape }}”\" rel=\"tag\">{{ tag }}</a>\n </span>\n {% unless forloop.last %} • {% endunless %}\n {%- endfor %}\n </h4>\n {%- endif %}\n </article>\n <div>\n <nav aria-label=pagination>\n <ul class=\"pagination justify-content-evenly mt-5\">\n {% if model.newer_link -%}\n <li class=page-item>\n <a class=page-link href=\"{{ model.newer_link.value | relative_link }}\">{{ model.newer_name.value }}</a>\n <span class=text-muted>« Previous Post</span>\n {% endif %}\n {% if model.older_link -%}\n <li class=\"page-item text-end\">\n <a class=page-link href=\"{{ model.older_link.value | relative_link }}\">{{ model.older_name.value }}</a>\n <span class=text-muted>Next Post »</span>\n {%- endif -%}\n </ul>\n </nav>\n </div>\n</div>\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "single-page",
|
||||||
|
"Text": "<h2 class=py-3>{{ page.title }}</h2>\n<article class=\"container\">{{ page.text }}</article>\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "layout",
|
||||||
|
"Text": "<!DOCTYPE html>\n<html lang=en>\n <meta charset=utf-8>\n <meta name=viewport content=\"width=device-width\">\n <link rel=stylesheet href=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css\n integrity=sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3 crossorigin=anonymous>\n <title>{{ page_title | strip_html }}{% if page_title %} « {% endif %}{{ web_log.name | strip_html }}</title>\n {% page_head -%}\n <header>\n <nav class=\"navbar navbar-light bg-light navbar-expand-md justify-content-start px-2\">\n <div class=container-fluid>\n <a class=navbar-brand href=\"{{ \"\" | relative_link }}\">{{ web_log.name }}</a>\n <button class=navbar-toggler type=button data-bs-toggle=collapse data-bs-target=#navbarText\n aria-controls=navbarText aria-expanded=false aria-label=\"Toggle navigation\">\n <span class=navbar-toggler-icon></span>\n </button>\n <div class=\"collapse navbar-collapse\" id=navbarText>\n {% if web_log.subtitle -%}\n <span class=navbar-text>{{ web_log.subtitle.value }}</span>\n {%- endif %}\n <ul class=navbar-nav>\n {% unless web_log.default_page == \"posts\" %}{{ \"page/1\" | nav_link: \"Posts\" }}{% endunless %}\n {% if page_list -%}\n {% for pg in page_list %}{{ pg.permalink | nav_link: pg.title }}{% endfor %}\n {%- endif %}\n </ul>\n {% user_links %}\n </div>\n </div>\n </nav>\n </header>\n <main class=mx-3>\n {% if messages %}\n <div class=messages>\n {% for msg in messages %}\n <div role=alert class=\"alert alert-{{ msg.level }} alert-dismissible fade show\">\n {{ msg.message }}\n <button type=button class=btn-close data-bs-dismiss=alert aria-label=Close></button>\n {% if msg.detail %}<hr><p>{{ msg.detail.value }}{% endif %}\n </div>\n {% endfor %}\n </div>\n {% endif %}\n {{ content }} \n </main>\n <footer>\n <hr>\n <div class=\"container-fluid text-end\">\n <img src=\"{{ \"themes/admin/logo-dark.png\" | relative_link }}\" alt=myWebLog width=120 height=34>\n </div>\n </footer>\n <script src=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js\n integrity=sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p\n crossorigin=anonymous></script>\n</html>\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "index",
|
||||||
|
"Text": "{%- if is_category or is_tag %}\n <h1 class=index-title>{{ page_title }}</h1>\n {%- if subtitle %}<h4 class=text-muted>{{ subtitle }}</h4>{% endif -%}\n{% endif %}\n{%- assign post_count = model.posts | size -%}\n{%- if post_count > 0 %}\n <section class=\"container mt-3\" aria-label=\"The posts for the page\">\n {%- for post in model.posts %}\n <article>\n <h1>\n <a href=\"{{ post | relative_link }}\" title=\"Permanent link to "{{ post.title | escape }}"\">\n {{ post.title }}\n </a>\n </h1>\n <p>\n Published on {{ post.published_on | date: \"MMMM d, yyyy\" }}\n at {{ post.published_on | date: \"h:mmtt\" | downcase }}\n by {{ model.authors | value: post.author_id }}\n {{ post.text }}\n {%- assign category_count = post.category_ids | size -%}\n {%- assign tag_count = post.tags | size -%}\n {% if category_count > 0 or tag_count > 0 %}\n <footer>\n <p>\n {%- if category_count > 0 -%}\n Categorized under:\n {% for cat in post.category_ids -%}\n {%- assign this_cat = categories | where: \"Id\", cat | first -%}\n {{ this_cat.name }}{% unless forloop.last %}, {% endunless %}\n {%- assign cat_names = this_cat.name | concat: cat_names -%}\n {%- endfor -%}\n {%- assign cat_names = \"\" -%}\n <br>\n {% endif -%}\n {%- if tag_count > 0 %}\n Tagged: {{ post.tags | join: \", \" }}\n {% endif -%}\n </footer>\n {% endif %}\n <hr>\n </article>\n {% endfor %}\n </section>\n <nav aria-label=pagination>\n <ul class=\"pagination justify-content-evenly mt-2\">\n {% if model.newer_link -%}\n <li class=page-item><a class=page-link href=\"{{ model.newer_link.value }}\">« Newer Posts</a>\n {% endif %}\n {% if model.older_link -%}\n <li class=page-item><a class=page-link href=\"{{ model.older_link.value }}\">Older Posts »</a>\n {%- endif -%}\n </ul>\n </nav>\n{%- else %}\n <article><p class=\"text-center mt-3\">No posts found</article>\n{%- endif %}\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Assets": [
|
||||||
|
{
|
||||||
|
"Id": "default/style.css",
|
||||||
|
"UpdatedOn": "2023-07-02T20:36:28Z",
|
||||||
|
"Data": "Lm1lc3NhZ2VzIHsKICBtYXgtd2lkdGg6IDYwcmVtOwogIG1hcmdpbjogYXV0bzsKfQpibG9ja3F1b3RlIHsKICBib3JkZXItbGVmdDogc29saWQgNHB4IGxpZ2h0Z3JheTsKICBwYWRkaW5nLWxlZnQ6IDFyZW07Cn0KLml0ZW0tbWV0YSB7CiAgZm9udC1zaXplOiAxLjFyZW07CiAgZm9udC13ZWlnaHQ6IG5vcm1hbDs7Cn0KLml0ZW0tbWV0YTo6YmVmb3JlIHsKICBjb250ZW50OiAiwrsiOwogIHZlcnRpY2FsLWFsaWduOiB0ZXh0LXRvcDsKfQphOmxpbmssIGE6dmlzaXRlZCB7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CmE6aG92ZXIgewogIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lOwp9Cg=="
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Categories": [
|
||||||
|
{
|
||||||
|
"Id": "S5JflPsJ9EG7gA2LD4m92A",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"Name": "Favorites",
|
||||||
|
"Slug": "favorites",
|
||||||
|
"Description": "Favorite posts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "jw6N69YtTEWVHAO33jHU-w",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"Name": "Spitball",
|
||||||
|
"Slug": "spitball",
|
||||||
|
"Description": "Posts that may or may not work"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "ScVpyu1e7UiP7bDdge3ZEw",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"Name": "Moonshot",
|
||||||
|
"Slug": "moonshot",
|
||||||
|
"ParentId": "jw6N69YtTEWVHAO33jHU-w"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"TagMappings": [
|
||||||
|
{
|
||||||
|
"Id": "Icm027noqE-rPHKZA98vAw",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"Tag": "f#",
|
||||||
|
"UrlValue": "f-sharp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "GdryXh-S0kGsNBs2RIacGA",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"Tag": "ghoti",
|
||||||
|
"UrlValue": "fish"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Pages": [
|
||||||
|
{
|
||||||
|
"Id": "hgc_BLEZ50SoAWLuPNISvA",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"AuthorId": "5EM2rimH9kONpmd2zQkiVA",
|
||||||
|
"Title": "Page Title",
|
||||||
|
"Permalink": "a-cool-page.html",
|
||||||
|
"PublishedOn": "2024-01-20T22:14:28Z",
|
||||||
|
"UpdatedOn": "2024-01-20T22:14:28Z",
|
||||||
|
"IsInPageList": false,
|
||||||
|
"Text": "<h1 id=\"a-cool-page\">A Cool Page</h1>\n<p>It really is cool!</p>\n",
|
||||||
|
"Metadata": [
|
||||||
|
{
|
||||||
|
"Name": "Cool",
|
||||||
|
"Value": "true"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Warm",
|
||||||
|
"Value": "false"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"PriorPermalinks": [
|
||||||
|
"a-cool-pg.html"
|
||||||
|
],
|
||||||
|
"Revisions": [
|
||||||
|
{
|
||||||
|
"AsOf": "2024-01-20T22:14:28Z",
|
||||||
|
"Text": "Markdown: # A Cool Page\n\nIt really is cool!"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "KouRjvSmm0Wz6TMD8xf67A",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"AuthorId": "5EM2rimH9kONpmd2zQkiVA",
|
||||||
|
"Title": "Yet Another Page",
|
||||||
|
"Permalink": "this-again.html",
|
||||||
|
"PublishedOn": "2024-01-20T22:15:08Z",
|
||||||
|
"UpdatedOn": "2024-01-20T22:15:08Z",
|
||||||
|
"IsInPageList": true,
|
||||||
|
"Text": "<h1>Page 2</h1>\n\n<p>It's a trip.",
|
||||||
|
"Metadata": [],
|
||||||
|
"PriorPermalinks": [],
|
||||||
|
"Revisions": [
|
||||||
|
{
|
||||||
|
"AsOf": "2024-01-20T22:15:08Z",
|
||||||
|
"Text": "HTML: <h1>Page 2</h1>\n\n<p>It's a trip."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Posts": [
|
||||||
|
{
|
||||||
|
"Id": "RCsCU2puYEmkpzotoi8p4g",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"AuthorId": "5EM2rimH9kONpmd2zQkiVA",
|
||||||
|
"Status": "Published",
|
||||||
|
"Title": "Test Post 1",
|
||||||
|
"Permalink": "2024/test-post-1.html",
|
||||||
|
"PublishedOn": "2024-01-20T22:17:29Z",
|
||||||
|
"UpdatedOn": "2024-01-20T22:17:29Z",
|
||||||
|
"Text": "<h2 id=\"introduction\">Introduction</h2>\n<p>Visit <a href=\"https://example.com\">my web site</a> or <a href=\"/a-fine-page.html\">my local page</a> for more information.</p>\n",
|
||||||
|
"CategoryIds": [
|
||||||
|
"ScVpyu1e7UiP7bDdge3ZEw"
|
||||||
|
],
|
||||||
|
"Tags": [
|
||||||
|
"f#",
|
||||||
|
"howdy",
|
||||||
|
"intro"
|
||||||
|
],
|
||||||
|
"Metadata": [],
|
||||||
|
"PriorPermalinks": [],
|
||||||
|
"Revisions": [
|
||||||
|
{
|
||||||
|
"AsOf": "2024-01-20T22:17:29Z",
|
||||||
|
"Text": "Markdown: ## Introduction\n\nVisit [my web site](https://example.com) or [my local page](/a-fine-page.html) for more information."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "osxMfWGlAkyugUbJ1-xD1g",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"AuthorId": "5EM2rimH9kONpmd2zQkiVA",
|
||||||
|
"Status": "Published",
|
||||||
|
"Title": "Episode 1",
|
||||||
|
"Permalink": "2024/episode-1.html",
|
||||||
|
"PublishedOn": "2024-01-20T22:24:01Z",
|
||||||
|
"UpdatedOn": "2024-01-20T22:24:01Z",
|
||||||
|
"Text": "<p>It's the launch of my new podcast - y'all come listen!",
|
||||||
|
"CategoryIds": [
|
||||||
|
"S5JflPsJ9EG7gA2LD4m92A"
|
||||||
|
],
|
||||||
|
"Tags": [
|
||||||
|
"general",
|
||||||
|
"podcast"
|
||||||
|
],
|
||||||
|
"Episode": {
|
||||||
|
"Media": "episode-1.mp3",
|
||||||
|
"Length": 124302,
|
||||||
|
"Duration": "0:12:22",
|
||||||
|
"ImageUrl": "images/ep1-cover.png",
|
||||||
|
"Subtitle": "An introduction to this podcast",
|
||||||
|
"Explicit": "clean",
|
||||||
|
"ChapterFile": "uploads/chapters.json",
|
||||||
|
"TranscriptUrl": "uploads/transcript.srt",
|
||||||
|
"TranscriptType": "application/srt",
|
||||||
|
"TranscriptLang": "en",
|
||||||
|
"TranscriptCaptions": true,
|
||||||
|
"SeasonNumber": 1,
|
||||||
|
"SeasonDescription": "The First Season",
|
||||||
|
"EpisodeNumber": 1.0,
|
||||||
|
"EpisodeDescription": "The first episode ever!"
|
||||||
|
},
|
||||||
|
"Metadata": [
|
||||||
|
{
|
||||||
|
"Name": "Density",
|
||||||
|
"Value": "Non-existent"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Intensity",
|
||||||
|
"Value": "Low"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"PriorPermalinks": [],
|
||||||
|
"Revisions": [
|
||||||
|
{
|
||||||
|
"AsOf": "2024-01-20T22:24:01Z",
|
||||||
|
"Text": "HTML: <p>It's the launch of my new podcast - y'all come listen!"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "l4_Eh4aFO06SqqJjOymNzA",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"AuthorId": "5EM2rimH9kONpmd2zQkiVA",
|
||||||
|
"Status": "Published",
|
||||||
|
"Title": "Episode 2",
|
||||||
|
"Permalink": "2024/episode-2.html",
|
||||||
|
"PublishedOn": "2024-01-20T22:31:32Z",
|
||||||
|
"UpdatedOn": "2024-01-20T22:31:32Z",
|
||||||
|
"Text": "<p>m i n i m a l",
|
||||||
|
"CategoryIds": [],
|
||||||
|
"Tags": [
|
||||||
|
"podcast"
|
||||||
|
],
|
||||||
|
"Episode": {
|
||||||
|
"Media": "episode-2.mp3",
|
||||||
|
"Length": 12873952,
|
||||||
|
"Duration": "1:03:24",
|
||||||
|
"SeasonNumber": 1,
|
||||||
|
"SeasonDescription": "The First Season",
|
||||||
|
"EpisodeNumber": 2.0,
|
||||||
|
"EpisodeDescription": "A long update"
|
||||||
|
},
|
||||||
|
"Metadata": [],
|
||||||
|
"PriorPermalinks": [],
|
||||||
|
"Revisions": [
|
||||||
|
{
|
||||||
|
"AsOf": "2024-01-20T22:31:32Z",
|
||||||
|
"Text": "HTML: <p>m i n i m a l"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "QweKbWQiOkqqrjEdgP9wwg",
|
||||||
|
"WebLogId": "uSitJEuD3UyzWC9jgOHc8g",
|
||||||
|
"AuthorId": "5EM2rimH9kONpmd2zQkiVA",
|
||||||
|
"Status": "Published",
|
||||||
|
"Title": "Something May Happen",
|
||||||
|
"Permalink": "2024/something.html",
|
||||||
|
"PublishedOn": "2024-01-20T22:32:59Z",
|
||||||
|
"UpdatedOn": "2024-01-20T22:32:59Z",
|
||||||
|
"Text": "<h2>Hmm</h2>",
|
||||||
|
"CategoryIds": [
|
||||||
|
"jw6N69YtTEWVHAO33jHU-w"
|
||||||
|
],
|
||||||
|
"Tags": [
|
||||||
|
"f#",
|
||||||
|
"ghoti",
|
||||||
|
"speculation"
|
||||||
|
],
|
||||||
|
"Metadata": [],
|
||||||
|
"PriorPermalinks": [],
|
||||||
|
"Revisions": [
|
||||||
|
{
|
||||||
|
"AsOf": "2024-01-20T22:32:59Z",
|
||||||
|
"Text": "HTML: <h2>Hmm</h2>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Uploads": []
|
||||||
|
}
|
||||||
Reference in new issue
Block a user