import $ivy.`com.lihaoyi::scalatags:0.6.5` import scalatags.Text.all._, scalatags.Text.tags2 import java.time.LocalDate import $file.pageStyles, pageStyles._ case class PostInfo(name: String, headers: Seq[(String, Int)], rawHtmlContent: String) def sanitize(s: String): String = { s.split(" |-", -1).map(_.filter(_.isLetterOrDigit)).mkString("-").toLowerCase } def pageChrome(titleText: Option[String], homePage: Boolean, contents: Frag, contentHeaders: Seq[(String, Int)], pageHeaders: Seq[String]): String = { val pageTitle = titleText.getOrElse("Mill") val sheets = Seq( "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css", "https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css", "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" ) html( head( meta(charset := "utf-8"), for(sheet <- sheets) yield link(href := sheet, rel := "stylesheet", `type` := "text/css" ), tags2.title(pageTitle), tags2.style(s"@media (min-width: 60em) {${WideStyles.styleSheetText}}"), tags2.style(s"@media (max-width: 60em) {${NarrowStyles.styleSheetText}}"), tags2.style(Styles.styleSheetText), script(src:="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"), script(src:="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"), script(raw("hljs.initHighlightingOnLoad();")), // This makes media queries work on iphone (???) // http://stackoverflow.com/questions/13002731/responsive-design-media-query-not-working-on-iphone meta(name:="viewport", content:="initial-scale = 1.0,maximum-scale = 1.0") ), body(margin := 0, backgroundColor := "#f8f8f8")( navBar(homePage, contentHeaders, pageHeaders), div( WideStyles.content, NarrowStyles.content, maxWidth := 900, titleText.map(h1(_)), contents ), if (contentHeaders.nonEmpty) frag() else div( WideStyles.footer, Styles.footerStyle, "Last published ", currentTimeText ) ) ).render } def navBar(homePage: Boolean, contentHeaders: Seq[(String, Int)], pageHeaders: Seq[String]) = { def navList(navLabel: String, frags: Frag, narrowHide: Boolean) = { div( WideStyles.tableOfContents, if(narrowHide) NarrowStyles.disappear else frag(), color := "#f8f8f8" )( div(paddingLeft := 40, NarrowStyles.disappear)( b(navLabel) ), div(overflowY.auto, flexShrink := 1, minHeight := 0)( ul( overflow.hidden, textAlign.start, marginTop := 10, whiteSpace.nowrap, textOverflow.ellipsis, marginRight := 10 )( frags ) ) ) } val pageList = navList( "Pages", for((header, i) <- pageHeaders.zipWithIndex) yield li( WideStyles.marginLeftZero, NarrowStyles.floatLeft )( a( color := "#f8f8f8", WideStyles.tableOfContentsItem, href := { (homePage, i == 0) match { case (true, true) => s"index.html" case (true, false) => s"page/${sanitize(header)}.html" case (false, true) => s"../index.html" case (false, false) => s"${sanitize(header)}.html" } } )( header ) ), narrowHide = false ) val headerBox = div( NarrowStyles.headerContent, h1( textAlign.center, a( // img( // src := {homePage match{ // case false => s"../logo-white.svg" // case true => "logo-white.svg" // }}, // height := 30, // marginTop := -5 // ), color := "#f8f8f8", " Cask", href := (if (homePage) "" else ".."), Styles.subtleLink, NarrowStyles.flexFont, fontWeight.bold ), padding := "30px 30px", margin := 0 ), div( Styles.headerLinkBox, pageList ) ) val tableOfContents = navList( "Table of Contents", for { (header, indent) <- contentHeaders offset <- indent match{ case 2 => Some(0) case 3 => Some(20) case _ => None } } yield li(marginLeft := offset)( a( color := "#f8f8f8", WideStyles.tableOfContentsItem, href := s"#${sanitize(header)}" )( header ) ), narrowHide = true ) div( WideStyles.header, NarrowStyles.header, Styles.headerStyle, headerBox, hr(NarrowStyles.disappear, backgroundColor := "#f8f8f8", width := "80%"), tableOfContents ) } val currentTimeText = LocalDate.now.toString def renderAdjacentLink(next: Boolean, name: String, url: String) = { a(href := url)( if(next) frag(name, " ", i(cls:="fa fa-arrow-right" , aria.hidden:=true)) else frag(i(cls:="fa fa-arrow-left" , aria.hidden:=true), " ", name) ) } def postContent(homePage: Boolean, post: PostInfo, adjacentLinks: Frag, posts: Seq[String]) = pageChrome( Some(post.name), homePage, Seq[Frag]( div(adjacentLinks, marginBottom := 10), raw(post.rawHtmlContent), adjacentLinks ), post.headers, pageHeaders = posts )