Improve title parsing
The subtitle has been removed because it's difficult to find and error prone to guess at. It is somewhat accessible from the post's previewContent field in GraphQL but that can be truncated.
This commit is contained in:
parent
2808505b4e
commit
fba87c1076
5 changed files with 25 additions and 117 deletions
|
@ -3,56 +3,26 @@ require "../spec_helper"
|
||||||
include Nodes
|
include Nodes
|
||||||
|
|
||||||
describe PageConverter do
|
describe PageConverter do
|
||||||
it "sets the title and subtitle if present" do
|
it "sets the page title" do
|
||||||
|
title = "Hello, world!"
|
||||||
paragraph_json = <<-JSON
|
paragraph_json = <<-JSON
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"text": "Title",
|
"text": "#{title}",
|
||||||
"type": "H3",
|
"type": "H3",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
"iframe": null,
|
"iframe": null,
|
||||||
"layout": null,
|
"layout": null,
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
|
||||||
{
|
|
||||||
"text": "Subtitle",
|
|
||||||
"type": "H4",
|
|
||||||
"markups": [],
|
|
||||||
"iframe": null,
|
|
||||||
"layout": null,
|
|
||||||
"metadata": null
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
JSON
|
JSON
|
||||||
data_json = default_data_json(paragraph_json)
|
data_json = default_data_json(title, paragraph_json)
|
||||||
data = PostResponse::Data.from_json(data_json)
|
data = PostResponse::Data.from_json(data_json)
|
||||||
|
|
||||||
page = PageConverter.new.convert(data)
|
page = PageConverter.new.convert(data)
|
||||||
|
|
||||||
page.title.should eq "Title"
|
page.title.should eq title
|
||||||
page.subtitle.should eq "Subtitle"
|
|
||||||
end
|
|
||||||
|
|
||||||
it "sets the title to the first paragraph if no title" do
|
|
||||||
paragraph_json = <<-JSON
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"text": "Not a title",
|
|
||||||
"type": "P",
|
|
||||||
"markups": [],
|
|
||||||
"iframe": null,
|
|
||||||
"layout": null,
|
|
||||||
"metadata": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
JSON
|
|
||||||
data_json = default_data_json(paragraph_json)
|
|
||||||
data = PostResponse::Data.from_json(data_json)
|
|
||||||
|
|
||||||
page = PageConverter.new.convert(data)
|
|
||||||
|
|
||||||
page.title.should eq "Not a title"
|
|
||||||
page.subtitle.should eq nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "sets the author" do
|
it "sets the author" do
|
||||||
|
@ -106,25 +76,18 @@ describe PageConverter do
|
||||||
page.created_at.should eq Time.utc(1970, 1, 1, 0, 0, 1)
|
page.created_at.should eq Time.utc(1970, 1, 1, 0, 0, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "calls ParagraphConverter to convert the remaining paragraph content" do
|
it "calls converts the remaining paragraph content" do
|
||||||
|
title = "Title"
|
||||||
paragraph_json = <<-JSON
|
paragraph_json = <<-JSON
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"text": "Title",
|
"text": "#{title}",
|
||||||
"type": "H3",
|
"type": "H3",
|
||||||
"markups": [],
|
"markups": [],
|
||||||
"iframe": null,
|
"iframe": null,
|
||||||
"layout": null,
|
"layout": null,
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"text": "Subtitle",
|
|
||||||
"type": "H4",
|
|
||||||
"markups": [],
|
|
||||||
"iframe": null,
|
|
||||||
"layout": null,
|
|
||||||
"metadata": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"text": "Content",
|
"text": "Content",
|
||||||
"type": "P",
|
"type": "P",
|
||||||
|
@ -135,7 +98,7 @@ describe PageConverter do
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
JSON
|
JSON
|
||||||
data_json = default_data_json(paragraph_json)
|
data_json = default_data_json(title, paragraph_json)
|
||||||
data = PostResponse::Data.from_json(data_json)
|
data = PostResponse::Data.from_json(data_json)
|
||||||
|
|
||||||
page = PageConverter.new.convert(data)
|
page = PageConverter.new.convert(data)
|
||||||
|
@ -148,11 +111,18 @@ describe PageConverter do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_data_json(paragraph_json : String)
|
def default_paragraph_json
|
||||||
|
"[]"
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_data_json(
|
||||||
|
title : String = "This is a story",
|
||||||
|
paragraph_json : String = default_paragraph_json
|
||||||
|
)
|
||||||
<<-JSON
|
<<-JSON
|
||||||
{
|
{
|
||||||
"post": {
|
"post": {
|
||||||
"title": "This is a story",
|
"title": "#{title}",
|
||||||
"createdAt": 1628974309758,
|
"createdAt": 1628974309758,
|
||||||
"creator": {
|
"creator": {
|
||||||
"id": "abc123",
|
"id": "abc123",
|
||||||
|
|
|
@ -6,7 +6,6 @@ describe PageContent do
|
||||||
it "renders a single parent/child node structure" do
|
it "renders a single parent/child node structure" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -24,7 +23,6 @@ describe PageContent do
|
||||||
it "renders multiple childrens" do
|
it "renders multiple childrens" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -53,7 +51,6 @@ describe PageContent do
|
||||||
it "renders an anchor" do
|
it "renders an anchor" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -69,7 +66,6 @@ describe PageContent do
|
||||||
it "renders a blockquote" do
|
it "renders a blockquote" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -87,7 +83,6 @@ describe PageContent do
|
||||||
it "renders code" do
|
it "renders code" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -105,7 +100,6 @@ describe PageContent do
|
||||||
it "renders empasis" do
|
it "renders empasis" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -127,7 +121,6 @@ describe PageContent do
|
||||||
children = [Text.new("A caption")] of Child
|
children = [Text.new("A caption")] of Child
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -155,7 +148,6 @@ describe PageContent do
|
||||||
it "renders a GitHub Gist" do
|
it "renders a GitHub Gist" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -173,7 +165,6 @@ describe PageContent do
|
||||||
it "renders an H3" do
|
it "renders an H3" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -191,7 +182,6 @@ describe PageContent do
|
||||||
it "renders an H4" do
|
it "renders an H4" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -209,7 +199,6 @@ describe PageContent do
|
||||||
it "renders an image" do
|
it "renders an image" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -231,7 +220,6 @@ describe PageContent do
|
||||||
it "renders embedded content" do
|
it "renders embedded content" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -256,7 +244,6 @@ describe PageContent do
|
||||||
it "renders an embedded link container" do
|
it "renders an embedded link container" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -280,7 +267,6 @@ describe PageContent do
|
||||||
it "renders an mixtape embed container" do
|
it "renders an mixtape embed container" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -311,7 +297,6 @@ describe PageContent do
|
||||||
it "renders an ordered list" do
|
it "renders an ordered list" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -330,7 +315,6 @@ describe PageContent do
|
||||||
it "renders an preformatted text" do
|
it "renders an preformatted text" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -348,7 +332,6 @@ describe PageContent do
|
||||||
it "renders an preformatted text" do
|
it "renders an preformatted text" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -366,7 +349,6 @@ describe PageContent do
|
||||||
it "renders strong text" do
|
it "renders strong text" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -384,7 +366,6 @@ describe PageContent do
|
||||||
it "renders an unordered list" do
|
it "renders an unordered list" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
@ -403,7 +384,6 @@ describe PageContent do
|
||||||
it "renders a user anchor" do
|
it "renders a user anchor" do
|
||||||
page = Page.new(
|
page = Page.new(
|
||||||
title: "Title",
|
title: "Title",
|
||||||
subtitle: nil,
|
|
||||||
author: user_anchor_factory,
|
author: user_anchor_factory,
|
||||||
created_at: Time.local,
|
created_at: Time.local,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
|
|
@ -1,57 +1,20 @@
|
||||||
struct HeaderData
|
|
||||||
getter title : String
|
|
||||||
getter subtitle : String?
|
|
||||||
|
|
||||||
def initialize(@title : String, @subtitle : String?)
|
|
||||||
end
|
|
||||||
|
|
||||||
def first_content_paragraph_index : Int32
|
|
||||||
if title.blank?
|
|
||||||
0
|
|
||||||
elsif subtitle.nil? || subtitle.blank?
|
|
||||||
1
|
|
||||||
else
|
|
||||||
2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class PageConverter
|
class PageConverter
|
||||||
def convert(data : PostResponse::Data) : Page
|
def convert(data : PostResponse::Data) : Page
|
||||||
paragraphs = data.post.content.bodyModel.paragraphs
|
title, content = title_and_content(data)
|
||||||
author = data.post.creator
|
author = data.post.creator
|
||||||
created_at = Time.unix_ms(data.post.createdAt)
|
created_at = Time.unix_ms(data.post.createdAt)
|
||||||
header = header_data(paragraphs)
|
|
||||||
if header.first_content_paragraph_index.zero?
|
|
||||||
content = [] of PostResponse::Paragraph
|
|
||||||
else
|
|
||||||
content = paragraphs[header.first_content_paragraph_index..]
|
|
||||||
end
|
|
||||||
Page.new(
|
Page.new(
|
||||||
title: header.title,
|
title: title,
|
||||||
subtitle: header.subtitle,
|
|
||||||
author: author,
|
author: author,
|
||||||
created_at: Time.unix_ms(data.post.createdAt),
|
created_at: Time.unix_ms(data.post.createdAt),
|
||||||
nodes: ParagraphConverter.new.convert(content)
|
nodes: ParagraphConverter.new.convert(content)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def header_data(paragraphs : Array(PostResponse::Paragraph)) : HeaderData
|
def title_and_content(data : PostResponse::Data) : {String, Array(PostResponse::Paragraph)}
|
||||||
if paragraphs.empty?
|
title = data.post.title
|
||||||
return HeaderData.new("", nil)
|
paragraphs = data.post.content.bodyModel.paragraphs
|
||||||
end
|
non_content_paragraphs = paragraphs.reject { |para| para.text == title }
|
||||||
first_two_paragraphs = paragraphs.first(2)
|
{title, non_content_paragraphs}
|
||||||
first_two_types = first_two_paragraphs.map(&.type)
|
|
||||||
if first_two_types == [PostResponse::ParagraphType::H3, PostResponse::ParagraphType::H4]
|
|
||||||
HeaderData.new(
|
|
||||||
title: first_two_paragraphs[0].text,
|
|
||||||
subtitle: first_two_paragraphs[1].text,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
HeaderData.new(
|
|
||||||
title: first_two_paragraphs[0].text,
|
|
||||||
subtitle: nil,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
class Page
|
class Page
|
||||||
getter nodes : Nodes::Children
|
getter nodes : Nodes::Children
|
||||||
getter title : String
|
getter title : String
|
||||||
getter subtitle : String?
|
|
||||||
getter author : PostResponse::Creator
|
getter author : PostResponse::Creator
|
||||||
getter created_at : Time
|
getter created_at : Time
|
||||||
|
|
||||||
def initialize(
|
def initialize(
|
||||||
@title : String,
|
@title : String,
|
||||||
@subtitle : String?,
|
|
||||||
@author : PostResponse::Creator,
|
@author : PostResponse::Creator,
|
||||||
@created_at : Time,
|
@created_at : Time,
|
||||||
@nodes : Nodes::Children = [] of Nodes::Child
|
@nodes : Nodes::Children = [] of Nodes::Child
|
||||||
|
|
|
@ -7,9 +7,6 @@ class Articles::ShowPage < MainLayout
|
||||||
|
|
||||||
def content
|
def content
|
||||||
h1 page.title
|
h1 page.title
|
||||||
if subtitle = page.subtitle
|
|
||||||
para subtitle, class: "subtitle"
|
|
||||||
end
|
|
||||||
para class: "meta" do
|
para class: "meta" do
|
||||||
text "#{author_link(page.author)} on #{page.created_at.to_s("%F")}"
|
text "#{author_link(page.author)} on #{page.created_at.to_s("%F")}"
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue