Created
July 26, 2017 09:01
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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