Skip to content

Commit

Permalink
Render sticky headings (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
keynmol committed Mar 15, 2022
1 parent ebfed21 commit ebcb3ed
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 34 deletions.
17 changes: 17 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,20 @@ runner.dialect = scala213source3
align.preset = "more"

maxColumn = 120
fileOverride {
"glob:**/modules/builders/target/jvm-3/src_managed/main/**" {
runner.dialect = scala3
}
"glob:**/modules/search/shared/target/js-3/src_managed/main/**" {
runner.dialect = scala3
}
"glob:**/modules/core/target/jvm-3/src_managed/main/**" {
runner.dialect = scala3
}
"glob:**/modules/core/src/test/scala-3/**" {
runner.dialect = scala3
}
"glob:**/modules/search/shared/target/jvm-3/src_managed/main/**" {
runner.dialect = scala3
}
}
7 changes: 7 additions & 0 deletions docs/blog/content/other-post-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Other post 1
date: 2022-03-14
tags: subatomic,blog,development,css
description: Where we pad our blogpost with enough content for it to be a feasible test of blog theme
---

7 changes: 7 additions & 0 deletions docs/blog/content/other-post-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Other post 2
date: 2022-03-10
tags: subatomic,blog,development,css
description: Where we pad our blogpost with enough content for it to be a feasible test of blog theme
---

7 changes: 7 additions & 0 deletions docs/blog/content/other-post.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Other post
date: 2022-03-15
tags: subatomic,blog,development,css
description: Where we pad our blogpost with enough content for it to be a feasible test of blog theme
---

94 changes: 73 additions & 21 deletions modules/builders/src/main/scala/Blog.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,16 @@ case class Post(
description: Option[String],
tags: List[String],
mdocConfig: Option[MdocConfiguration],
archived: Boolean
archived: Boolean,
headings: Vector[Heading]
) extends Doc {
def scalajsEnabled: Boolean = mdocConfig.exists(_.scalajsConfig.nonEmpty)
}
object Post {
implicit val ordering: Ordering[Post] = Ordering.by(_.date.toEpochDay())
}

case class Heading(level: Int, title: String, url: String)

case class TagPage(
tag: String,
Expand Down Expand Up @@ -94,11 +100,13 @@ object Blog {
}

def createNavigation(linker: Linker, content: Vector[Doc]): Doc => Vector[NavLink] = {

val all = content
.collect {
case doc: Post if !doc.archived => doc -> NavLink(linker.find(doc), doc.title, selected = false)
}
.sortBy(-_._1.date.toEpochDay())
.sortBy(_._1)
.reverse

{ piece =>
all.map {
Expand Down Expand Up @@ -130,14 +138,20 @@ object Blog {

val mdocConfig = MdocConfiguration.fromAttrs(attributes)

val md = Markdown(YamlFrontMatterExtension.create(), AnchorLinkExtension.create())
val headings =
md.extractMarkdownSections("", "", path).collect { case Markdown.Section(title, level, Some(url), _) =>
Heading(level, title, url)
}
val post = Post(
title,
path,
date,
description,
tags,
mdocConfig,
archived
archived,
headings
): Doc

sitePath -> post
Expand All @@ -153,7 +167,8 @@ object Blog {
.groupBy(_._1)
.toVector
.map { case (tag, posts) =>
SiteRoot / "tags" / s"$tag.html" -> TagPage(tag, posts.map(_._2).toList)
SiteRoot / "tags" / s"$tag.html" ->
TagPage(tag, posts.map(_._2).sorted.reverse.toList)
}

posts ++ tagPages
Expand Down Expand Up @@ -185,7 +200,7 @@ object Blog {
val mdocProcessor =
if (!buildConfig.disableMdoc)
MdocProcessor.create[Post]() {
case Post(_, path, _, _, _, Some(config), _) if config.scalajsConfig.nonEmpty => MdocFile(path, config)
case Post(_, path, _, _, _, Some(config), _, _) if config.scalajsConfig.nonEmpty => MdocFile(path, config)
}
else {
Processor.simple[Post, MdocResult[Post]](doc => MdocResult(doc, doc.path))
Expand All @@ -195,19 +210,27 @@ object Blog {
if (!buildConfig.disableMdoc)
MdocJSProcessor
.create[Post]() {
case Post(_, path, _, _, _, Some(config), _) if config.scalajsConfig.nonEmpty => MdocFile(path, config)
case Post(_, path, _, _, _, Some(config), _, _) if config.scalajsConfig.nonEmpty => MdocFile(path, config)
}
.map { result =>
result.original -> Option(result)
}
else {
Processor.simple(doc => doc -> None)
}
def renderPost(title: String, tags: Seq[String], file: os.Path, links: Vector[NavLink]) = {

def renderPost(
title: String,
tags: Seq[String],
file: os.Path,
links: Vector[NavLink],
headings: Vector[Heading]
) = {
val renderedMarkdown = markdown.renderToString(file)
val renderedHtml =
template.post(
links,
headings,
title,
tags,
renderedMarkdown
Expand All @@ -222,7 +245,8 @@ object Blog {
mdocResult.original.title,
mdocResult.original.tags,
mdocResult.resultFile,
navigation(mdocResult.original)
navigation(mdocResult.original),
mdocResult.original.headings
)
}
val mdocJSPageRenderer: Processor[Post, Map[SitePath => SitePath, SiteAsset]] = mdocJSProcessor
Expand All @@ -232,7 +256,7 @@ object Blog {
case (doc, Some(mdocResult)) =>
Map(
(identity[SitePath] _) ->
renderPost(doc.title, doc.tags, mdocResult.markdownFile, navigation(doc)),
renderPost(doc.title, doc.tags, mdocResult.markdownFile, navigation(doc), doc.headings),
((sp: SitePath) => sp.up / mdocResult.jsSnippetsFile.last) ->
CopyOf(mdocResult.jsSnippetsFile),
((sp: SitePath) => sp.up / mdocResult.jsInitialisationFile.last) ->
Expand All @@ -243,7 +267,7 @@ object Blog {

case (doc, None) =>
Map(
(identity[SitePath] _) -> renderPost(doc.title, doc.tags, doc.path, navigation(doc))
(identity[SitePath] _) -> renderPost(doc.title, doc.tags, doc.path, navigation(doc), doc.headings)
)
}
}
Expand All @@ -262,7 +286,7 @@ object Blog {
doc
)
case (sitePath, doc: Post) =>
site.add(sitePath, renderPost(doc.title, doc.tags, doc.path, navigation(doc)))
site.add(sitePath, renderPost(doc.title, doc.tags, doc.path, navigation(doc), doc.headings))
case (sitePath, doc: TagPage) =>
site.addPage(sitePath, template.tagPage(navigation(doc), doc.tag, doc.posts).render)
}
Expand Down Expand Up @@ -351,7 +375,7 @@ trait Template {

def Nav(navigation: Vector[NavLink]) = {
div(
navigation.sortBy(_.title).map {
navigation.map {
case NavLink(_, title, selected) if selected =>
p(strong(title))
case NavLink(url, title, _) =>
Expand Down Expand Up @@ -403,7 +427,7 @@ trait Template {
BuilderTemplate.managedStylesBlock(linker, paths)
}

def basePage(navigation: Option[Vector[NavLink]], content: TypedTag[_]) = {
def basePage(navigation: Option[Vector[NavLink]], headings: Option[Vector[Heading]], content: TypedTag[_]) = {
val pageTitle = navigation
.flatMap(_.find(_.selected))
.map(_.title)
Expand Down Expand Up @@ -437,7 +461,8 @@ trait Template {
searchSection,
tagCloud,
archiveLink,
navigationSection(navigation)
navigationSection(navigation),
headingsSection(headings)
),
article(cls := "content-wrapper", content)
),
Expand Down Expand Up @@ -466,6 +491,23 @@ trait Template {
case None => span()
}

private def headingsSection(headings: Option[Vector[Heading]]) =
headings match {
case None => span()
case Some(value) =>
div(
style := "position: sticky; position: -webkit-sticky; top: 0",
h4("contents"),
value.filter(_.level <= 3).map { hd =>
span(
raw("&nbsp;&nbsp;" * (hd.level - 1)),
a(href := hd.url, cls := "heading-link", small(hd.title)),
br
)
}
)
}

private def blogTitleSection =
section(
cls := "site-title",
Expand All @@ -478,18 +520,20 @@ trait Template {
div(id := "searchContainer", cls := "searchContainer")
)

def page(navigation: Vector[NavLink], content: TypedTag[_]) =
basePage(Some(navigation), content)
def page(navigation: Vector[NavLink], headings: Option[Vector[Heading]], content: TypedTag[_]) =
basePage(Some(navigation), headings, content)

def post(
navigation: Vector[NavLink],
headings: Vector[Heading],
title: String,
tags: Seq[String],
content: String
): String = post(navigation, title, tags, rawHtml(content))
): String = post(navigation, headings, title, tags, rawHtml(content))

def post(
navigation: Vector[NavLink],
headings: Vector[Heading],
title: String,
tags: Seq[String],
content: TypedTag[_]
Expand All @@ -500,7 +544,11 @@ trait Template {
a(href := linker.unsafe(_ / "tags" / s"$tag.html"), small(tag))
)
}
"<!DOCTYPE html>" + page(navigation, div(h2(cls := "blog-post-title", title), p(tagline), hr, content)).render
"<!DOCTYPE html>" + page(
navigation,
Some(headings),
div(h2(cls := "blog-post-title", title), p(tagline), hr, content)
).render
}

def tagPage(
Expand All @@ -510,6 +558,7 @@ trait Template {
) = {
page(
navigation,
None,
div(
h3(span("Posts tagged with ", span(cls := "blog-tag", tag))),
div(cls := "card-columns", blogs.map(blogCard).toVector)
Expand Down Expand Up @@ -562,10 +611,11 @@ trait Template {
blogs: Seq[Post]
) = {
basePage(
None,
None,
div(
h3(title),
div(cls := "card-columns", blogs.sortBy(-_.date.toEpochDay()).map(blogCard).toVector)
div(cls := "card-columns", blogs.sorted.reverse.map(blogCard).toVector)
)
)
}
Expand All @@ -574,9 +624,10 @@ trait Template {
blogs: Seq[Post]
) = {
basePage(
None,
None,
div(
div(cls := "card-columns", blogs.sortBy(-_.date.toEpochDay()).map(blogCard).toVector)
div(cls := "card-columns", blogs.sorted.reverse.map(blogCard).toVector)
)
)
}
Expand All @@ -585,10 +636,11 @@ trait Template {
blogs: Seq[Post]
) = {
basePage(
None,
None,
div(
h3("Archive"),
div(cls := "card-columns", blogs.sortBy(-_.date.toEpochDay()).map(blogCard).toVector)
div(cls := "card-columns", blogs.sorted.reverse.map(blogCard).toVector)
)
)
}
Expand Down
8 changes: 4 additions & 4 deletions modules/builders/src/main/scala/Builder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ object BuilderTemplate {
| background-color: white;
| border:2px solid darkslategrey;
| border-radius: 2px;
| min-width: 500px;
| max-width: 600px;
| z-index: 100;
| right: auto;
| position: absolute;
| top: 100%; z-index: 100; left: 0px; right: auto
| top: 100%;
| z-index: 100;
| left: 0px;
| right: auto
|}
|
""".stripMargin.trim
Expand Down
2 changes: 1 addition & 1 deletion modules/builders/src/main/scala/BuilderSteps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class BuilderSteps(markdown: Markdown) {
subatomic.search.Document(
doc.title,
linker.find(raw),
markdownSections.map { case Markdown.Section(title, url, text) =>
markdownSections.map { case Markdown.Section(title, _, url, text) =>
subatomic.search.Section(title, url, title + "\n\n" + text)
}
)
Expand Down
6 changes: 5 additions & 1 deletion modules/builders/src/main/scala/LibrarySite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,11 @@ trait Template {
templateStyles,
searchScripts,
searchStyles,
meta(charset := "UTF-8")
meta(charset := "UTF-8"),
meta(
name := "viewport",
attr("content") := "width=device-width, initial-scale=1"
)
),
body(
div(
Expand Down
4 changes: 4 additions & 0 deletions modules/builders/src/main/scala/themes/blog.scala
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,9 @@ object default extends StyleSheet.Standalone {
paddingLeft(1.em)
)

"a.heading-link" - (
textDecorationLine.none,
)

def asString: String = this.renderA[String]
}
2 changes: 1 addition & 1 deletion modules/builders/src/main/scala/themes/librarysite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object default extends StyleSheet.Standalone {
backgroundColor(rgb(254, 255, 248)),
borderRadius(5.px),
padding(30.px),
width(80.pc),
width(80.%%),
margin(30.px),
media.screen.minWidth(1600.px) - (
width(50.%%),
Expand Down

0 comments on commit ebcb3ed

Please sign in to comment.