This Livebook shows how to use the to_html/2 function of DatoCMS.GraphQLClient
.
Mix.install([
{:datocms_graphql_client, "0.15.3"}
])
DatoCMS.GraphQLClient.configure(api_key: "b2bf6a03a90e7e800580b535ff55c1")
The DatoCMS site used in these examples has two models: Article
and Item
.
Alongside the basic id
, title
and slug
fields, Article
has a Structured Text field body
.
We can run GraphQL introspection queries to find out about Models:
DatoCMS.GraphQLClient.query!("""
{
__type(name: "ArticleRecord") {
fields {
name
}
}
}
""").__type.fields
|> Enum.map(& &1.name)
|> Enum.filter(&(!String.starts_with?(&1, "_")))
|> Enum.sort()
The 7 Articles
are examples of different types of Structured Text content.
DatoCMS.GraphQLClient.query!("""
query {
allArticles(orderBy: title_ASC) {
id
title
}
}
""").allArticles
Let's render the simplest Article
.
First the query:
article_01 =
DatoCMS.GraphQLClient.query!("""
query {
article(filter: {title: {eq: "001 Plain Text"}}) {
body {
value
}
}
}
""")
Now we call to_html/2
to get an HTML rendering of the body
field:
DatoCMS.StructuredText.to_html(article_01.article.body)
article_02 =
DatoCMS.GraphQLClient.query!("""
query {
article(filter: {title: {eq: "002 Text Styles"}}) {
body {
value
}
}
}
""")
DatoCMS.StructuredText.to_html(article_02.article.body)
Item links require additions to the query and to the rendering call.
First attempt...
article_04 =
DatoCMS.GraphQLClient.query!("""
query {
article(filter: {title: {eq: "004 Item Link"}}) {
body {
value
}
}
}
""")
Here, we can see that the text "link to item" is linked to the Item with id 15236536.
DatoCMS.StructuredText.to_html(article_04.article.body)
Fail!
We need to pass an options
parameter with a custom renderer for links to DatoCMS records.
For now, we'll just supply a rendering function that returns "Hi!" for any node.
render_link_to_record = fn _item, _node, _dast, _options -> "Hi!" end
options = %{renderers: %{render_link_to_record: render_link_to_record}}
DatoCMS.StructuredText.to_html(article_04.article.body, options)
Fail!
Let's update the query to get links
so we have the info about Item 15236536.
article_04 =
DatoCMS.GraphQLClient.query!("""
query {
article(filter: {title: {eq: "004 Item Link"}}) {
body {
value
links {
... on ItemRecord {
id
slug
}
}
}
}
}
""")
render_link_to_record = fn _item, _node, _dast, _options -> "Hi!" end
options = %{renderers: %{render_link_to_record: render_link_to_record}}
DatoCMS.StructuredText.to_html(article_04.article.body, options)
OK, that works, but we want to render a proper link.
Let's create a better function
render_link_to_record = fn item, node, _dast, _options ->
text = hd(node.children).value
~s(<a href="#{item.slug}">#{text}</a>)
end
options = %{renderers: %{render_link_to_record: render_link_to_record}}
DatoCMS.StructuredText.to_html(article_04.article.body, options)
That's OK, but we're cheating a bit - we're taking the value of the first child node.
What if the linked content is not just a simple text?
Nodes have a list of children which could contain any type of content.
We can use DatoCMS.StructuredText.render/3 to get the correct rendering for any content that might be linked there.
render_link_to_record = fn item, node, dast, options ->
content = Enum.flat_map(node.children, &DatoCMS.StructuredText.render(&1, dast, options))
[~s(<a href="#{item.slug}">)] ++ content ++ ["</a>"]
end
options = %{renderers: %{render_link_to_record: render_link_to_record}}
DatoCMS.StructuredText.to_html(article_04.article.body, options)
That's more complex, but it handles any case.
Note that we're switched from returning a String to returning a List,
which is easier for us as content
is a List, being the result of rendering all the
node
's children. Custom rendering functions can return a String or a List,
whatever you find more convenient.
article_05 =
DatoCMS.GraphQLClient.query!("""
query {
article(filter: {title: {eq: "005 Structures"}}) {
body {
value
}
}
}
""")
Here we've got examples of various block types:
article_05.article.body.value.document.children
|> Enum.map(&{&1.type, &1[:style] || &1[:level]})
DatoCMS.StructuredText.to_html(article_05.article.body)
article_06 =
DatoCMS.GraphQLClient.query!("""
{
article(filter: {title: {eq: "006 Inline records"}}) {
body {
value
links {
... on ArticleRecord {
id
title
}
}
}
}
}
""")
render_inline_record = fn item, _, _ -> ~s("#{item.title}") end
options = %{renderers: %{render_inline_record: render_inline_record}}
DatoCMS.StructuredText.to_html(article_06.article.body, options)
article_07 =
DatoCMS.GraphQLClient.query!("""
{
article(filter: {title: {eq: "007 Custom Blocks"}}) {
body {
value
blocks {
... on MyarticleblockRecord {
id
articleBlockTitle
image {
url
}
}
}
}
}
}
""")
render_block = fn block, _, _ -> ~s("#{block.articleBlockTitle}") end
options = %{renderers: %{render_block: render_block}}
DatoCMS.StructuredText.to_html(article_07.article.body, options)