Skip to content

Instantly share code, notes, and snippets.

@arnaudlewis
Created July 26, 2017 09:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arnaudlewis/3aa806e859d3846c330b7a7a88ed53b6 to your computer and use it in GitHub Desktop.
Save arnaudlewis/3aa806e859d3846c330b7a7a88ed53b6 to your computer and use it in GitHub Desktop.
How to generate a dynamic table of content from a prismic content in slices
class EqWrap[T <: AnyRef](val value: T) {
override def hashCode() = if (value == null) 0 else value.hashCode
override def equals(a: Any) = a match {
case ref: EqWrap[_] => ref.value eq value
case _ => false
}
}
object EqWrap {
def apply[T <: AnyRef](t: T) = new EqWrap(t)
}
def generateId(prefixes: Seq[Int], text: String): String = s"""${prefixes.mkString("_")}-${String.slugifyUID(text)}"""
def HtmlSerializer(headings: Map[EqWrap[Heading], TableEntry]): io.prismic.HtmlSerializer = io.prismic.HtmlSerializer.apply({
case (h @ Heading(text, _, 2, _, _), content) =>
headings.get(EqWrap(h))
.map { entry =>
s"""<h2 id="${entry.id}">$content</h2>"""
}
.getOrElse(s"Missing heading2 in table of content: $h")
case (h @ Heading(text, _, 3, _, _), content) =>
headings.get(EqWrap(h))
.map { entry =>
s"""<h3 id="${entry.id}">$content</h3>"""
}
.getOrElse(s"Missing heading3 in table of content: $h")
})
trait TableLevel
case object Section extends TableLevel
case object Paragraph extends TableLevel
case class TableEntry(id: String, level: TableLevel, label: String)
case class TableOfContent(entries: Seq[TableEntry])
def collectStructuredText(slices: Seq[Slice]): Seq[StructuredText] = {
slices.flatMap {
case SimpleSlice(_, _, value) =>
value match {
case g: Group => g.docs.flatMap(_.fragments.values)
case f => Seq(f)
}
case CompositeSlice(_, _, nonRepeat, repeat) =>
nonRepeat.fragments.values ++ repeat.docs.flatMap(_.fragments.values)
}.collect {
case s: StructuredText => s
}
}
def generateTableOfContent(sliceZone: Option[SliceZone]): (TableOfContent, io.prismic.HtmlSerializer) = {
val slices = sliceZone.toSeq.flatMap(_.slices)
val tableOfContent = collectStructuredText(slices).zipWithIndex.flatMap { case (stext, stextIndex) =>
stext.blocks.zipWithIndex.collect {
case (h @ Heading(text, _, 2, _, _), blockIndex) =>
val prefixes = Seq(stextIndex, blockIndex)
EqWrap(h) -> TableEntry(generateId(prefixes, text), Section, text)
case (h @ Heading(text, _, 3, _, _), blockIndex) =>
val prefixes = Seq(stextIndex, blockIndex)
EqWrap(h) -> TableEntry(generateId(prefixes, text), Paragraph, text)
}
}
TableOfContent(tableOfContent.map(_._2)) -> HtmlSerializer(tableOfContent.toMap)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment