Remove documentation style sheet, fix code blocks (#1202)

This commit is contained in:
Maciej Mikołajek 2020-10-08 14:59:18 +02:00 committed by GitHub
parent 1fbf3ad692
commit 91346a41fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 483 additions and 894 deletions

View File

@ -169,12 +169,8 @@ object Doc {
* *
* @param elems - lines of code * @param elems - lines of code
*/ */
/*TODO [MM]: Next PR final case class CodeBlock(elems: List1[CodeBlock.Line], isInGui: Boolean)
Code showing button - we need other design here. extends Elem {
Basically we don't want to display always button
we want to be able to display it maybe as a button on website
and completely differently in gui, it should be configurable*/
final case class CodeBlock(elems: List1[CodeBlock.Line]) extends Elem {
val newLn: Elem = Elem.Newline val newLn: Elem = Elem.Newline
val repr: Repr.Builder = R + elems.head + elems.tail.map(R + newLn + _) val repr: Repr.Builder = R + elems.head + elems.tail.map(R + newLn + _)
val html: HTML = { val html: HTML = {
@ -182,22 +178,28 @@ object Doc {
val uniqueIDBtn = Random.alphanumeric.take(8).mkString("") val uniqueIDBtn = Random.alphanumeric.take(8).mkString("")
val htmlIdCode = HTML.`id` := uniqueIDCode val htmlIdCode = HTML.`id` := uniqueIDCode
val htmlIdBtn = HTML.`id` := uniqueIDBtn val htmlIdBtn = HTML.`id` := uniqueIDBtn
val htmlStyle = HTML.`style` := "inline-block"
val elemsHTML = elems.toList.map(elem => elem.html) val elemsHTML = elems.toList.map(elem => elem.html)
val btnAction = onclick := val btnAction = onclick :=
s"""var code = document.getElementById("$uniqueIDCode"); s"""var code = document.getElementById("$uniqueIDCode");
|var btn = document.getElementById("$uniqueIDBtn").firstChild; |var btn = document.getElementById("$uniqueIDBtn").firstChild;
|btn.data = btn.data == "Show" ? "Hide" : "Show"; |btn.data = btn.data == "Show" ? "Hide" : "Show";
|code.style.display = code.style.display == |code.style.display = code.style.display ==
|"inline-block" ? "none" : "inline-block";""".stripMargin |"inline-block" ? "none" : "inline-block";""".stripMargin
.replaceAll("\n", "") .replaceAll("\n", "")
val btn = HTML.button(btnAction)(htmlIdBtn)("Show") val btn = HTML.button(btnAction)(htmlIdBtn)("Show")
Seq(HTML.div(btn, HTML.div(htmlCls())(htmlIdCode)(elemsHTML))) if (isInGui) {
Seq(HTML.div(htmlCls())(htmlStyle)(elemsHTML))
} else {
Seq(HTML.div(btn, HTML.div(htmlCls())(htmlIdCode)(elemsHTML)))
}
} }
} }
object CodeBlock { object CodeBlock {
def apply(elem: CodeBlock.Line): CodeBlock = CodeBlock(List1(elem)) def apply(elem: CodeBlock.Line): CodeBlock =
CodeBlock(List1(elem), isInGui = true)
def apply(elems: CodeBlock.Line*): CodeBlock = def apply(elems: CodeBlock.Line*): CodeBlock =
CodeBlock(List1(elems.head, elems.tail.toList)) CodeBlock(List1(elems.head, elems.tail.toList), isInGui = true)
/** Inline - line of code which is in line with other elements /** Inline - line of code which is in line with other elements
* Line - elem which is a part of Code Block * Line - elem which is a part of Code Block

View File

@ -26,25 +26,27 @@ case class DocParserDef() extends Parser[Doc] {
var doc: Option[Doc] = None var doc: Option[Doc] = None
var stack: List[Elem] = Nil var stack: List[Elem] = Nil
def push(): Unit = logger.trace { def push(): Unit =
if (current.isDefined) { logger.trace {
logger.log(s"Pushed: $current") if (current.isDefined) {
stack +:= current.get logger.log(s"Pushed: $current")
current = None stack +:= current.get
} else { current = None
logger.err("Undefined current") } else {
logger.err("Undefined current")
}
} }
}
def pop(): Unit = logger.trace { def pop(): Unit =
if (stack.nonEmpty) { logger.trace {
current = Some(stack.head) if (stack.nonEmpty) {
stack = stack.tail current = Some(stack.head)
logger.log(s"New result: $current") stack = stack.tail
} else { logger.log(s"New result: $current")
logger.err("Trying to pop empty AST stack") } else {
logger.err("Trying to pop empty AST stack")
}
} }
}
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -71,34 +73,37 @@ case class DocParserDef() extends Parser[Doc] {
/** text - used to manage normal text, made of Strings /** text - used to manage normal text, made of Strings
*/ */
final object text { final object text {
def onPushing(in: String): Unit = logger.trace { def onPushing(in: String): Unit =
if (documentation.isBeginning()) { logger.trace {
if (!tags.checkIfTagExistInPushedText(in)) { if (documentation.isBeginning()) {
if (!tags.checkIfTagExistInPushedText(in)) {
val text = removeWhitespaces(in)
push(text)
}
} else if (section.isBeginning()) {
val text = removeWhitespaces(in) val text = removeWhitespaces(in)
push(text) push(text)
} } else {
} else if (section.isBeginning()) { push(in)
val text = removeWhitespaces(in)
push(text)
} else {
push(in)
}
}
def removeWhitespaces(in: String): String = logger.trace {
var text = in
if (text.nonEmpty) {
while (text.head == ' ' && text.length > 1) {
text = text.tail
} }
} }
text
}
def push(in: String): Unit = logger.trace { def removeWhitespaces(in: String): String =
result.current = Some(Elem.Text(in)) logger.trace {
result.push() var text = in
} if (text.nonEmpty) {
while (text.head == ' ' && text.length > 1) {
text = text.tail
}
}
text
}
def push(in: String): Unit =
logger.trace {
result.current = Some(Elem.Text(in))
result.push()
}
} }
ROOT || normalText || text.onPushing(currentMatch) ROOT || normalText || text.onPushing(currentMatch)
@ -135,33 +140,35 @@ case class DocParserDef() extends Parser[Doc] {
result.current = None result.current = None
} }
def checkIfTagExistInPushedText(in: String): Boolean = logger.trace { def checkIfTagExistInPushedText(in: String): Boolean =
val inArray = in.split(" ") logger.trace {
var containsTag = false val inArray = in.split(" ")
var containsTag = false
def tryFindingTagInAvailableTags(elem: String): Unit = logger.trace { def tryFindingTagInAvailableTags(elem: String): Unit =
for (tagType <- possibleTagsList) { logger.trace {
if (elem == tagType.toString.toUpperCase) { for (tagType <- possibleTagsList) {
containsTag = true if (elem == tagType.toString.toUpperCase) {
val tagDet = in.replaceFirst(tagType.toString.toUpperCase, "") containsTag = true
pushTag(section.currentIndentRaw, tagType, tagDet) val tagDet = in.replaceFirst(tagType.toString.toUpperCase, "")
pushTag(section.currentIndentRaw, tagType, tagDet)
}
}
if (!containsTag && !elem.contains(newline)) {
pushTag(section.currentIndentRaw, Tags.Tag.Unrecognized, in)
containsTag = true
}
}
for (elem <- inArray) {
if (elem.isEmpty) {
section.currentIndentRaw += 1
} else if (elem == elem.toUpperCase) {
tryFindingTagInAvailableTags(elem)
} }
} }
if (!containsTag && !elem.contains(newline)) { containsTag
pushTag(section.currentIndentRaw, Tags.Tag.Unrecognized, in)
containsTag = true
}
} }
for (elem <- inArray) {
if (elem.isEmpty) {
section.currentIndentRaw += 1
} else if (elem == elem.toUpperCase) {
tryFindingTagInAvailableTags(elem)
}
}
containsTag
}
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -171,29 +178,32 @@ case class DocParserDef() extends Parser[Doc] {
/** code - used to manage code in documentation /** code - used to manage code in documentation
*/ */
final object code { final object code {
def onPushingInline(in: String): Unit = logger.trace { def onPushingInline(in: String): Unit =
val code = in.substring(1).dropRight(1) logger.trace {
result.current = Some(Elem.CodeBlock.Inline(code)) val code = in.substring(1).dropRight(1)
result.push() result.current = Some(Elem.CodeBlock.Inline(code))
} result.push()
}
def onPushingMultiline(in: String): Unit = logger.trace {
val dummyLine = Elem.CodeBlock.Line(0, "") def onPushingMultiline(in: String): Unit =
do { logger.trace {
result.pop() val dummyLine = Elem.CodeBlock.Line(0, "")
} while (result.current.get == Elem.Newline) do {
result.current match { result.pop()
case Some(code @ (_: Elem.CodeBlock)) => } while (result.current.get == Elem.Newline)
val newElem = Elem.CodeBlock.Line(indent.current, in) result.current match {
if (code.elems.head == dummyLine) { case Some(code @ (_: Elem.CodeBlock)) =>
result.current = Some(Elem.CodeBlock(newElem)) val newElem = Elem.CodeBlock.Line(indent.current, in)
} else { if (code.elems.head == dummyLine) {
result.current = Some(Elem.CodeBlock(code.elems.append(newElem))) result.current = Some(Elem.CodeBlock(newElem))
} } else {
case Some(_) | None => result.push() result.current =
Some(Elem.CodeBlock(code.elems.append(newElem), isInGui = true))
}
case Some(_) | None => result.push()
}
result.push()
} }
result.push()
}
val inlineCodeTrigger = '`' val inlineCodeTrigger = '`'
val inlinePattern: Pattern = val inlinePattern: Pattern =
@ -204,7 +214,7 @@ case class DocParserDef() extends Parser[Doc] {
val CODE: State = state.define("Code") val CODE: State = state.define("Code")
ROOT || code.inlinePattern || code.onPushingInline(currentMatch) ROOT || code.inlinePattern || code.onPushingInline(currentMatch)
CODE || newline || { state.end(); state.begin(NEWLINE) } CODE || newline || { state.end(); state.begin(NEWLINE) }
CODE || notNewLine || code.onPushingMultiline(currentMatch) CODE || notNewLine || code.onPushingMultiline(currentMatch)
CODE || eof || { state.end(); documentation.onEOF() } CODE || eof || { state.end(); documentation.onEOF() }
@ -237,7 +247,9 @@ case class DocParserDef() extends Parser[Doc] {
def getElemsFromStack(typ: Elem.Formatter.Type): List[Elem] = def getElemsFromStack(typ: Elem.Formatter.Type): List[Elem] =
logger.trace { logger.trace {
var listOfFormattedAST: List[Elem] = Nil var listOfFormattedAST: List[Elem] = Nil
while (result.stack.head != Elem.Formatter(typ) && result.stack.nonEmpty) { while (
result.stack.head != Elem.Formatter(typ) && result.stack.nonEmpty
) {
result.pop() result.pop()
result.current match { result.current match {
case Some(value) => listOfFormattedAST +:= value case Some(value) => listOfFormattedAST +:= value
@ -247,38 +259,41 @@ case class DocParserDef() extends Parser[Doc] {
listOfFormattedAST listOfFormattedAST
} }
def addEmptyToStack(typ: Elem.Formatter.Type): Unit = logger.trace { def addEmptyToStack(typ: Elem.Formatter.Type): Unit =
stack +:= typ logger.trace {
result.current = Some(Elem.Formatter(typ)) stack +:= typ
result.push() result.current = Some(Elem.Formatter(typ))
} result.push()
}
def decideWhichToCheckIfUnclosed( def decideWhichToCheckIfUnclosed(
typ: Elem.Formatter.Type typ: Elem.Formatter.Type
): List[Elem.Formatter.Type] = logger.trace { ): List[Elem.Formatter.Type] =
typ match { logger.trace {
case Elem.Formatter.Strikeout => typ match {
List(Elem.Formatter.Bold, Elem.Formatter.Italic) case Elem.Formatter.Strikeout =>
case Elem.Formatter.Italic => List(Elem.Formatter.Bold, Elem.Formatter.Italic)
List(Elem.Formatter.Bold, Elem.Formatter.Strikeout) case Elem.Formatter.Italic =>
case Elem.Formatter.Bold => List(Elem.Formatter.Bold, Elem.Formatter.Strikeout)
List(Elem.Formatter.Italic, Elem.Formatter.Strikeout) case Elem.Formatter.Bold =>
case _ => throw new Error("Trying to use non-existing formatter") List(Elem.Formatter.Italic, Elem.Formatter.Strikeout)
} case _ => throw new Error("Trying to use non-existing formatter")
} }
}
def checkForUnclosed(typ: Elem.Formatter.Type): Unit = logger.trace {
if (stack.nonEmpty) { def checkForUnclosed(typ: Elem.Formatter.Type): Unit =
if (stack.head == typ) { logger.trace {
val listOfFormattedAST: List[Elem] = getElemsFromStack(typ) if (stack.nonEmpty) {
result.pop() if (stack.head == typ) {
result.current = val listOfFormattedAST: List[Elem] = getElemsFromStack(typ)
Some(Elem.Formatter.Unclosed(typ, listOfFormattedAST)) result.pop()
stack = stack.tail result.current =
result.push() Some(Elem.Formatter.Unclosed(typ, listOfFormattedAST))
stack = stack.tail
result.push()
}
} }
} }
}
val boldTrigger: Char = Elem.Formatter.Bold.marker val boldTrigger: Char = Elem.Formatter.Bold.marker
val italicTrigger: Char = Elem.Formatter.Italic.marker val italicTrigger: Char = Elem.Formatter.Italic.marker
@ -301,31 +316,33 @@ case class DocParserDef() extends Parser[Doc] {
/** header - used to create section headers in Documentation /** header - used to create section headers in Documentation
*/ */
final object header { final object header {
def create(): Unit = logger.trace { def create(): Unit =
section.current match { logger.trace {
case Some(_) => loopThroughStackToFindHeader() section.current match {
case None => case Some(_) => loopThroughStackToFindHeader()
result.pop() case None =>
result.current match { result.pop()
case Some(_: Section.Header) => loopThroughStackToFindHeader() result.current match {
case _ => result.push() case Some(_: Section.Header) => loopThroughStackToFindHeader()
} case _ => result.push()
}
}
} }
}
def loopThroughStackToFindHeader(): Unit = logger.trace { def loopThroughStackToFindHeader(): Unit =
var listForHeader: List[Elem] = Nil logger.trace {
do { var listForHeader: List[Elem] = Nil
result.pop() do {
listForHeader +:= result.current.get result.pop()
} while (result.current.get != Elem.Newline && result.stack.nonEmpty) listForHeader +:= result.current.get
if (result.current.get == Elem.Newline) { } while (result.current.get != Elem.Newline && result.stack.nonEmpty)
if (result.current.get == Elem.Newline) {
result.push()
listForHeader = listForHeader.tail
}
result.current = Some(Section.Header(listForHeader.reverse))
result.push() result.push()
listForHeader = listForHeader.tail
} }
result.current = Some(Section.Header(listForHeader.reverse))
result.push()
}
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -337,53 +354,60 @@ case class DocParserDef() extends Parser[Doc] {
* there are 2 possible link types - Image and normal URL * there are 2 possible link types - Image and normal URL
*/ */
final object link { final object link {
def onCreatingURL(): Unit = logger.trace { def onCreatingURL(): Unit =
if (currentMatch.contains("]") && currentMatch.contains("(")) { logger.trace {
val in = currentMatch.substring(1).dropRight(1).split(']') if (currentMatch.contains("]") && currentMatch.contains("(")) {
val name = in(0) val in = currentMatch.substring(1).dropRight(1).split(']')
val url = in(1).substring(1) val name = in(0)
pushURL(name, url) val url = in(1).substring(1)
} else { pushURL(name, url)
onInvalidLink() } else {
onInvalidLink()
}
} }
}
def pushURL(name: String, url: String): Unit = logger.trace { def pushURL(name: String, url: String): Unit =
result.current = Some(Elem.Link.URL(name, url)) logger.trace {
result.push() result.current = Some(Elem.Link.URL(name, url))
} result.push()
def onCreatingImage(): Unit = logger.trace {
if (currentMatch.contains("]") && currentMatch.contains("(")) {
val in = currentMatch.substring(2).dropRight(1).split(']')
val name = in(0)
val url = in(1).substring(1)
pushImage(name, url)
} else {
onInvalidLink()
} }
}
def pushImage(name: String, url: String): Unit = logger.trace { def onCreatingImage(): Unit =
result.current = Some(Elem.Link.Image(name, url)) logger.trace {
result.push() if (currentMatch.contains("]") && currentMatch.contains("(")) {
} val in = currentMatch.substring(2).dropRight(1).split(']')
val name = in(0)
val url = in(1).substring(1)
pushImage(name, url)
} else {
onInvalidLink()
}
}
def onInvalidLink(): Unit = logger.trace { def pushImage(name: String, url: String): Unit =
result.current = Some(Elem.Link.Invalid(currentMatch)) logger.trace {
result.push() result.current = Some(Elem.Link.Image(name, url))
} result.push()
}
def onInvalidLinkNewline(): Unit = logger.trace { def onInvalidLink(): Unit =
result.current = Some(Elem.Link.Invalid(currentMatch.dropRight(1))) logger.trace {
result.push() result.current = Some(Elem.Link.Invalid(currentMatch))
indent.onPushingNewLine() result.push()
} }
def onInvalidLinkEOF(): Unit = logger.trace { def onInvalidLinkNewline(): Unit =
onInvalidLink() logger.trace {
documentation.onEOF() result.current = Some(Elem.Link.Invalid(currentMatch.dropRight(1)))
} result.push()
indent.onPushingNewLine()
}
def onInvalidLinkEOF(): Unit =
logger.trace {
onInvalidLink()
documentation.onEOF()
}
val urlNameTrigger: String = "[" val urlNameTrigger: String = "["
val imageNameTrigger: String = Elem.Link.Image().marker.get + urlNameTrigger val imageNameTrigger: String = Elem.Link.Image().marker.get + urlNameTrigger
@ -413,65 +437,71 @@ case class DocParserDef() extends Parser[Doc] {
*/ */
final object indent { final object indent {
var stack: List[Int] = Nil var stack: List[Int] = Nil
def current: Int = stack match { def current: Int =
case Nil => 0 stack match {
case ::(head, _) => head case Nil => 0
} case ::(head, _) => head
def onIndent(): Unit = logger.trace {
val diff = currentMatch.length - current
if (diff < 0 && list.inListFlag) {
list.appendInnerToOuter()
stack = stack.tail
} else if (currentMatch.length > section.currentIndentRaw && result.stack.nonEmpty) {
tryToFindCodeInStack()
stack +:= currentMatch.length
state.begin(CODE)
} else {
section.currentIndentRaw = currentMatch.length
} }
}
def tryToFindCodeInStack(): Unit = logger.trace { def onIndent(): Unit =
result.pop() logger.trace {
result.stack.head match { val diff = currentMatch.length - current
case _: Elem.CodeBlock => if (diff < 0 && list.inListFlag) {
case _ => list.appendInnerToOuter()
result.push() stack = stack.tail
val dummyLine = Elem.CodeBlock.Line(0, "") } else if (
result.current = Some(Elem.CodeBlock(dummyLine)) currentMatch.length > section.currentIndentRaw && result.stack.nonEmpty
) {
tryToFindCodeInStack()
stack +:= currentMatch.length
state.begin(CODE)
} else {
section.currentIndentRaw = currentMatch.length
}
}
def tryToFindCodeInStack(): Unit =
logger.trace {
result.pop()
result.stack.head match {
case _: Elem.CodeBlock =>
case _ =>
result.push()
val dummyLine = Elem.CodeBlock.Line(0, "")
result.current = Some(Elem.CodeBlock(dummyLine))
}
result.push()
} }
result.push()
}
def onIndentForListCreation( def onIndentForListCreation(
indent: Int, indent: Int,
typ: Elem.List.Type, typ: Elem.List.Type,
content: String content: String
): Unit = logger.trace { ): Unit =
val diff = indent - current logger.trace {
if (diff > 0) { val diff = indent - current
/* NOTE if (diff > 0) {
* Used to push new line before pushing first list /* NOTE
*/ * Used to push new line before pushing first list
if (!list.inListFlag) onPushingNewLine() */
stack +:= indent if (!list.inListFlag) onPushingNewLine()
list.inListFlag = true stack +:= indent
list.addNew(indent, typ, content) list.inListFlag = true
} else if (diff == 0 && list.inListFlag) { list.addNew(indent, typ, content)
list.addContent(content) } else if (diff == 0 && list.inListFlag) {
} else if (diff < 0 && list.inListFlag) {
if (stack.tail.head != indent) {
onInvalidIndent(indent, typ, content)
} else {
list.appendInnerToOuter()
list.addContent(content) list.addContent(content)
stack = stack.tail } else if (diff < 0 && list.inListFlag) {
if (stack.tail.head != indent) {
onInvalidIndent(indent, typ, content)
} else {
list.appendInnerToOuter()
list.addContent(content)
stack = stack.tail
}
} else {
onInvalidIndent(indent, typ, content)
} }
} else {
onInvalidIndent(indent, typ, content)
} }
}
def onInvalidIndent( def onInvalidIndent(
indent: Int, indent: Int,
@ -493,33 +523,37 @@ case class DocParserDef() extends Parser[Doc] {
} }
} }
def onPushingNewLine(): Unit = logger.trace { def onPushingNewLine(): Unit =
result.current = Some(Elem.Newline) logger.trace {
result.push() result.current = Some(Elem.Newline)
} result.push()
def onEmptyLine(): Unit = logger.trace {
if (list.inListFlag) {
list.appendInnerToOuter()
list.inListFlag = false
} }
onPushingNewLine()
section.onEOS()
}
def onIndentPattern(): Unit = logger.trace { def onEmptyLine(): Unit =
state.end() logger.trace {
if (result.stack.nonEmpty) { if (list.inListFlag) {
list.appendInnerToOuter()
list.inListFlag = false
}
onPushingNewLine()
section.onEOS()
}
def onIndentPattern(): Unit =
logger.trace {
state.end()
if (result.stack.nonEmpty) {
indent.onPushingNewLine()
}
indent.onIndent()
}
def onEOFPattern(): Unit =
logger.trace {
state.end()
indent.onPushingNewLine() indent.onPushingNewLine()
documentation.onEOF()
} }
indent.onIndent()
}
def onEOFPattern(): Unit = logger.trace {
state.end()
indent.onPushingNewLine()
documentation.onEOF()
}
val emptyLine: Pattern = whitespace.opt >> newline val emptyLine: Pattern = whitespace.opt >> newline
val indentPattern: Pattern = whitespace.opt.many val indentPattern: Pattern = whitespace.opt.many
@ -549,55 +583,63 @@ case class DocParserDef() extends Parser[Doc] {
result.push() result.push()
} }
def addContent(content: Elem): Unit = logger.trace { def addContent(content: Elem): Unit =
result.pop() logger.trace {
result.current match { result.pop()
case Some(list @ (_: Elem.List)) => result.current match {
var currentContent = list.elems case Some(list @ (_: Elem.List)) =>
currentContent = currentContent.append(content) var currentContent = list.elems
result.current = currentContent = currentContent.append(content)
Some(Elem.List(list.indent, list.typ, currentContent)) result.current =
case _ => Some(Elem.List(list.indent, list.typ, currentContent))
case _ =>
}
result.push()
} }
result.push()
}
def appendInnerToOuter(): Unit = logger.trace { def appendInnerToOuter(): Unit =
result.pop() logger.trace {
val innerList = result.current.orNull result.pop()
result.stack.head match { val innerList = result.current.orNull
case outerList @ (_: Elem.List) => result.stack.head match {
var outerContent = outerList.elems case outerList @ (_: Elem.List) =>
innerList match { var outerContent = outerList.elems
case Elem.Newline => innerList match {
case _ => outerContent = outerContent.append(innerList) case Elem.Newline =>
} case _ => outerContent = outerContent.append(innerList)
result.pop() }
result.current = result.pop()
Some(Elem.List(outerList.indent, outerList.typ, outerContent)) result.current =
case _ => Some(Elem.List(outerList.indent, outerList.typ, outerContent))
case _ =>
}
result.push()
innerList match {
case Elem.Newline => indent.onPushingNewLine()
case _ =>
}
} }
result.push()
innerList match {
case Elem.Newline => indent.onPushingNewLine()
case _ =>
}
}
def onOrdered(): Unit = logger.trace { def onOrdered(): Unit =
state.end() logger.trace {
val matchedContent = currentMatch.split(orderedListTrigger) state.end()
val listIndent = matchedContent(0).length val matchedContent = currentMatch.split(orderedListTrigger)
val listElems = matchedContent(1) val listIndent = matchedContent(0).length
indent.onIndentForListCreation(listIndent, Elem.List.Ordered, listElems) val listElems = matchedContent(1)
} indent.onIndentForListCreation(listIndent, Elem.List.Ordered, listElems)
def onUnordered(): Unit = logger.trace { }
state.end() def onUnordered(): Unit =
val matchedContent = currentMatch.split(unorderedListTrigger) logger.trace {
val listIndent = matchedContent(0).length state.end()
val listElems = matchedContent(1) val matchedContent = currentMatch.split(unorderedListTrigger)
indent.onIndentForListCreation(listIndent, Elem.List.Unordered, listElems) val listIndent = matchedContent(0).length
} val listElems = matchedContent(1)
indent.onIndentForListCreation(
listIndent,
Elem.List.Unordered,
listElems
)
}
val orderedListTrigger: Char = Elem.List.Ordered.marker val orderedListTrigger: Char = Elem.List.Ordered.marker
val unorderedListTrigger: Char = Elem.List.Unordered.marker val unorderedListTrigger: Char = Elem.List.Unordered.marker
@ -642,11 +684,12 @@ case class DocParserDef() extends Parser[Doc] {
current = typ current = typ
} }
def onNewMarked(typ: Section.Marked.Type): Unit = logger.trace { def onNewMarked(typ: Section.Marked.Type): Unit =
createMarkedSectionIndent(typ) logger.trace {
onNew(Some(typ)) createMarkedSectionIndent(typ)
currentIndentRaw += currentMatch.length onNew(Some(typ))
} currentIndentRaw += currentMatch.length
}
def createMarkedSectionIndent(typ: Section.Marked.Type): Unit = def createMarkedSectionIndent(typ: Section.Marked.Type): Unit =
logger.trace { logger.trace {
@ -663,69 +706,77 @@ case class DocParserDef() extends Parser[Doc] {
indentAfterMarker = inArr.tail.head.length - 1 indentAfterMarker = inArr.tail.head.length - 1
} }
def onNewRaw(): Unit = logger.trace { def onNewRaw(): Unit =
indent.onEmptyLine() logger.trace {
onNew(None) indent.onEmptyLine()
} onNew(None)
}
def onNewRawWithHeader(): Unit = logger.trace { def onNewRawWithHeader(): Unit =
state.end() logger.trace {
onNewRaw() state.end()
result.current = Some(Section.Header()) onNewRaw()
result.push() result.current = Some(Section.Header())
} result.push()
}
def isBeginning(): Boolean = logger.trace { def isBeginning(): Boolean =
result.stack.isEmpty || result.stack.head.isInstanceOf[Section.Header] logger.trace {
} result.stack.isEmpty || result.stack.head.isInstanceOf[Section.Header]
}
//// End of Section //// //// End of Section ////
def checkForUnclosedFormattersOnEOS(): Unit = logger.trace { def checkForUnclosedFormattersOnEOS(): Unit =
formatter.checkForUnclosed(Elem.Formatter.Bold) logger.trace {
formatter.checkForUnclosed(Elem.Formatter.Italic) formatter.checkForUnclosed(Elem.Formatter.Bold)
formatter.checkForUnclosed(Elem.Formatter.Strikeout) formatter.checkForUnclosed(Elem.Formatter.Italic)
} formatter.checkForUnclosed(Elem.Formatter.Strikeout)
def reverseStackOnEOS(): Unit = logger.trace {
result.stack = result.stack.reverse
}
def push(): Unit = logger.trace {
result.stack match {
case Nil =>
/* NOTE
* We don't want to push an empty section into stack
* in case of parsing for example empty file
* Then we want to get back Doc(None) and not Doc(Section())
*/
case _ =>
section.current match {
case Some(marker) =>
section.stack +:= Section.Marked(
indentBeforeMarker,
indentAfterMarker,
marker,
result.stack
)
case None =>
section.stack +:= Section.Raw(currentIndentRaw, result.stack)
}
} }
}
def cleanupOnEOS(): Unit = logger.trace { def reverseStackOnEOS(): Unit =
result.current = None logger.trace {
result.stack = Nil result.stack = result.stack.reverse
formatter.stack = Nil }
}
def onEOS(): Unit = logger.trace { def push(): Unit =
checkForUnclosedFormattersOnEOS() logger.trace {
reverseStackOnEOS() result.stack match {
header.create() case Nil =>
push() /* NOTE
cleanupOnEOS() * We don't want to push an empty section into stack
} * in case of parsing for example empty file
* Then we want to get back Doc(None) and not Doc(Section())
*/
case _ =>
section.current match {
case Some(marker) =>
section.stack +:= Section.Marked(
indentBeforeMarker,
indentAfterMarker,
marker,
result.stack
)
case None =>
section.stack +:= Section.Raw(currentIndentRaw, result.stack)
}
}
}
def cleanupOnEOS(): Unit =
logger.trace {
result.current = None
result.stack = Nil
formatter.stack = Nil
}
def onEOS(): Unit =
logger.trace {
checkForUnclosedFormattersOnEOS()
reverseStackOnEOS()
header.create()
push()
cleanupOnEOS()
}
val importantTrigger: Char = Section.Marked.Important.marker val importantTrigger: Char = Section.Marked.Important.marker
val infoTrigger: Char = Section.Marked.Info.marker val infoTrigger: Char = Section.Marked.Info.marker
@ -763,56 +814,64 @@ case class DocParserDef() extends Parser[Doc] {
* is it just ran as DocParser - for example in test suite * is it just ran as DocParser - for example in test suite
*/ */
final object documentation { final object documentation {
def reverseSectionsStackOnEOF(): Unit = logger.trace { def reverseSectionsStackOnEOF(): Unit =
section.stack = section.stack.reverse logger.trace {
} section.stack = section.stack.reverse
def reverseTagsStackOnEOF(): Unit = logger.trace {
tags.stack = tags.stack.reverse
}
def createDoc(): Unit = logger.trace {
val tags: Option[Tags] = createTags()
val synopsis: Option[Synopsis] = createSynopsis()
val body: Option[Body] = createBody()
result.doc = Some(Doc(tags, synopsis, body))
}
def createTags(): Option[Tags] = logger.trace {
tags.stack match {
case Nil => None
case x :: xs => Some(Tags(List1(x, xs)))
} }
}
def createSynopsis(): Option[Synopsis] = logger.trace { def reverseTagsStackOnEOF(): Unit =
section.stack match { logger.trace {
case Nil => None tags.stack = tags.stack.reverse
case x :: _ => Some(Synopsis(x))
} }
}
def createBody(): Option[Body] = logger.trace { def createDoc(): Unit =
section.stack match { logger.trace {
case Nil => None val tags: Option[Tags] = createTags()
case _ :: xs => val synopsis: Option[Synopsis] = createSynopsis()
xs match { val body: Option[Body] = createBody()
case Nil => None result.doc = Some(Doc(tags, synopsis, body))
case y :: ys => Some(Body(List1(y, ys)))
}
} }
}
def onEOF(): Unit = logger.trace { def createTags(): Option[Tags] =
section.onEOS() logger.trace {
reverseSectionsStackOnEOF() tags.stack match {
reverseTagsStackOnEOF() case Nil => None
createDoc() case x :: xs => Some(Tags(List1(x, xs)))
} }
}
def isBeginning(): Boolean = logger.trace { def createSynopsis(): Option[Synopsis] =
result.stack.isEmpty && section.stack.isEmpty logger.trace {
} section.stack match {
case Nil => None
case x :: _ => Some(Synopsis(x))
}
}
def createBody(): Option[Body] =
logger.trace {
section.stack match {
case Nil => None
case _ :: xs =>
xs match {
case Nil => None
case y :: ys => Some(Body(List1(y, ys)))
}
}
}
def onEOF(): Unit =
logger.trace {
section.onEOS()
reverseSectionsStackOnEOF()
reverseTagsStackOnEOF()
createDoc()
}
def isBeginning(): Boolean =
logger.trace {
result.stack.isEmpty && section.stack.isEmpty
}
} }
ROOT || eof || documentation.onEOF() ROOT || eof || documentation.onEOF()

View File

@ -283,22 +283,17 @@ object DocParserHTMLGenerator {
* reformatted [[AST.Documented]] * reformatted [[AST.Documented]]
* *
* @param ast - parsed AST.Module and reformatted using Doc Parser * @param ast - parsed AST.Module and reformatted using Doc Parser
* @param cssFileName - name of file containing stylesheets for the HTML code
*/ */
def generateHTMLForEveryDocumented( def generateHTMLForEveryDocumented(ast: AST): String = {
ast: AST,
cssFileName: String = "style.css"
): String = {
ast.map { elem => ast.map { elem =>
elem match { elem match {
case AST.Documented.any(documented) => case AST.Documented.any(documented) =>
val file = onHTMLRendering(documented, cssFileName) val file = onHTMLRendering(documented)
return file.code.toString() + generateHTMLForEveryDocumented( return file.code.toString() + generateHTMLForEveryDocumented(
documented, documented
cssFileName
) )
case _ => case _ =>
generateHTMLForEveryDocumented(elem, cssFileName) generateHTMLForEveryDocumented(elem)
} }
elem elem
} }
@ -309,14 +304,10 @@ object DocParserHTMLGenerator {
* Function to generate HTML File from pure doc comment w/o connection to AST * Function to generate HTML File from pure doc comment w/o connection to AST
* *
* @param doc - Doc from Doc Parser * @param doc - Doc from Doc Parser
* @param cssLink - string containing CSS file name
* @return - HTML Code from Doc * @return - HTML Code from Doc
*/ */
def generateHTMLPureDoc( def generateHTMLPureDoc(doc: Doc): String = {
doc: Doc, HTML.html(createHTMLHead(""), HTML.body(doc.html)).toString()
cssLink: String = "style.css"
): String = {
HTML.html(createHTMLHead("", cssLink), HTML.body(doc.html)).toString()
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -328,14 +319,10 @@ object DocParserHTMLGenerator {
* Runner finished it's job * Runner finished it's job
* *
* @param documented - documented made by Doc Parser Runner from AST and Doc * @param documented - documented made by Doc Parser Runner from AST and Doc
* @param cssFileName - name of file containing stylesheets for the HTML code
* @return - HTML code with file name * @return - HTML code with file name
*/ */
def onHTMLRendering( def onHTMLRendering(documented: AST.Documented): htmlFile = {
documented: AST.Documented, val htmlCode = renderHTML(documented.ast, documented.doc)
cssFileName: String
): htmlFile = {
val htmlCode = renderHTML(documented.ast, documented.doc, cssFileName)
val astLines = documented.ast.show().split("\n") val astLines = documented.ast.show().split("\n")
val fileName = val fileName =
astLines.head astLines.head
@ -352,18 +339,13 @@ object DocParserHTMLGenerator {
* *
* @param ast - AST from Parser * @param ast - AST from Parser
* @param doc - Doc from Doc Parser * @param doc - Doc from Doc Parser
* @param cssLink - string containing CSS file name
* @return - HTML Code from Doc and contents of [[AST.Def]] or * @return - HTML Code from Doc and contents of [[AST.Def]] or
* [[AST.App.Infix]], with optional title made from AST * [[AST.App.Infix]], with optional title made from AST
*/ */
def renderHTML( def renderHTML(ast: AST, doc: Doc): TypedTag[String] = {
ast: AST,
doc: Doc,
cssLink: String
): TypedTag[String] = {
val title = ast.show().split("\n").head.split("=").head val title = ast.show().split("\n").head.split("=").head
val documentation = DocumentedToHtml(ast, doc) val documentation = DocumentedToHtml(ast, doc)
HTML.html(createHTMLHead(title, cssLink), HTML.body(documentation)) HTML.html(createHTMLHead(title), HTML.body(documentation))
} }
/** /**
@ -376,10 +358,7 @@ object DocParserHTMLGenerator {
* @return - HTML Code from Doc and contents of [[AST.Def]] or * @return - HTML Code from Doc and contents of [[AST.Def]] or
* [[AST.App.Infix]] * [[AST.App.Infix]]
*/ */
def DocumentedToHtml( def DocumentedToHtml(ast: AST, doc: Doc): TypedTag[String] = {
ast: AST,
doc: Doc
): TypedTag[String] = {
val docClass = HTML.`class` := "Documentation" val docClass = HTML.`class` := "Documentation"
val astHeadCls = HTML.`class` := "ASTHead" val astHeadCls = HTML.`class` := "ASTHead"
val astHTML = createHTMLFromAST(ast) val astHTML = createHTMLFromAST(ast)
@ -576,18 +555,14 @@ object DocParserHTMLGenerator {
* Function invoked by [[DocumentedToHtml]] to create HTML.Head part of file * Function invoked by [[DocumentedToHtml]] to create HTML.Head part of file
* *
* @param title - HTML page title * @param title - HTML page title
* @param cssLink - string containing CSS file name
* @return - HTML Head Code * @return - HTML Head Code
*/ */
def createHTMLHead(title: String, cssLink: String): TypedTag[String] = { def createHTMLHead(title: String): TypedTag[String] = {
val metaEquiv = HTML.httpEquiv := "Content-Type" val metaEquiv = HTML.httpEquiv := "Content-Type"
val metaCont = HTML.content := "text/html" val metaCont = HTML.content := "text/html"
val metaChar = HTML.charset := "UTF-8" val metaChar = HTML.charset := "UTF-8"
val meta = HTML.meta(metaEquiv)(metaCont)(metaChar) val meta = HTML.meta(metaEquiv)(metaCont)(metaChar)
val cssRel = HTML.rel := "stylesheet"
val cssHref = HTML.href := cssLink
val css = HTML.link(cssRel)(cssHref)
val fileTitle = scalatags.Text.tags2.title(title) val fileTitle = scalatags.Text.tags2.title(title)
HTML.head(meta, css)(fileTitle) HTML.head(meta)(fileTitle)
} }
} }

View File

@ -1,446 +0,0 @@
/*///////////
//// DOM ////
///////////*/
$defaultLineHeight: 1.52947
$defaultFontSize: 17px
$defaultFontFamily: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", "Helvetica", "Arial", sans-serif
$defaultFontWeight: 400
$defaultBoldFontWeight: 600
$defaultHeaderFontWeight: 500
$defaultLetterSpacing: -0.021em
$defaultTextColor: #333333
$defaultCodeColor: #0070c9
body
-webkit-font-smoothing: antialiased
font-style: normal
word-wrap: break-word
font-size: $defaultFontSize
line-height: $defaultLineHeight
font-weight: $defaultFontWeight
letter-spacing: $defaultLetterSpacing
font-family: $defaultFontFamily
background-color: white
color: $defaultTextColor
margin: 0
padding: 0
p
display: block
margin-block-start: 1em
margin-block-end: 1em
margin-inline-start: 0
margin-inline-end: 0
a:hover
color: $defaultCodeColor !important
text-decoration: inherit
a
color: $defaultTextColor
background-color: transparent
text-decoration: inherit
display: inline-block
transition: all 0.3s ease
img
display: block
code
color: $defaultCodeColor
background-color: transparent
font-size: inherit
font-family: $defaultFontFamily
line-height: inherit
display: inline-block
white-space: pre-wrap
button
display: inline-block
padding: 8px 30px
margin: 10px 0
outline: none
background-color: transparent
border: 1px solid $defaultTextColor
color: $defaultTextColor
border-radius: 5px
font-size: 13px
vertical-align: top
transition: all 0.3s ease
button:hover
background-color: $defaultTextColor
color: #e5e5e5
b
font-weight: $defaultBoldFontWeight
h1
font-size: 34px
line-height: 1.08824
font-weight: $defaultHeaderFontWeight
letter-spacing: 0.01em
h2
font-size: 28px
line-height: 1.1073
font-weight: $defaultHeaderFontWeight
letter-spacing: 0.012em
.Body h2
margin: 0.65rem 0 0
li
padding-left: 10px
/*///////////////////
//// Invalid AST ////
///////////////////*/
// Creator - a special mode for displaying parsing errors in output
.creator
.Unclosed,
.invalidIndent,
.invalidLink
display: inline
color: orangered
.Tags
.UNRECOGNIZED
border: 2px solid
color: orangered
.Unclosed,
.invalidIndent,
.invalidLink
display: inline
/*//////////////
//// Header ////
//////////////*/
.Header
font-size: 19px
font-weight: $defaultHeaderFontWeight
.Important .Header,
.Info .Header,
.Example .Header
margin-bottom: 0.7em
font-weight: $defaultBoldFontWeight
letter-spacing: $defaultLetterSpacing
line-height: $defaultFontSize
font-synthesis: none
font-family: $defaultFontFamily
/*////////////
//// Tags ////
////////////*/
.Tags
margin-left: auto
margin-right: auto
margin-bottom: 20px
padding-top: 15px
.DEPRECATED,
.MODIFIED,
.ADDED,
.UPCOMING,
.REMOVED,
.UNRECOGNIZED
line-height: 1.5
font-weight: $defaultFontWeight
border-radius: 4px
font-size: 12px
letter-spacing: $defaultLetterSpacing
display: inline-flex
padding: 5px 15px
margin: 2px
white-space: nowrap
background: transparent
.DEPRECATED
$col: #d20606
border: 1px solid $col
color: $col
.MODIFIED
$col: #003ec3
border: 1px solid $col
color: $col
.ADDED
$col: #79A129
border: 1px solid $col
color: $col
.UPCOMING,
.REMOVED,
.UNRECOGNIZED
$col: #666666
border: 1px solid $col
color: $col
.ExtForTagDetails
margin: 0 3px
color: #999999
/*////////////////
//// Sections ////
////////////////*/
.Raw,
.Important,
.Info,
.CodeBlock,
.Example
margin-top: 0
margin-left: auto
margin-right: auto
position: relative
text-decoration: inherit
.Body .Raw
margin-bottom: 0.6rem
font-size: $defaultFontSize
line-height: $defaultLineHeight
font-weight: $defaultFontWeight
letter-spacing: $defaultLetterSpacing
font-family: $defaultFontFamily
color: $defaultTextColor
font-style: normal
.Important,
.Info,
.CodeBlock,
.Example
font-size: $defaultFontSize
padding: 15px 10px 15px 20px
border: 0
border-radius: 6px
margin: 0.7em 0
.Important
background-color: #FBECC2
.Info
background-color: #D6E1CA
.Example
background-color: #fafafa
.CodeBlock
background-color: #fefefe
margin: 10px 20px
display: none
code
font-family: monospace
/*///////////////////////////////////
//// HTML generated - Def, Infix ////
///////////////////////////////////*/
.Def
margin: 40px auto auto
padding: 0 15px
text-decoration: inherit
.Synopsis,
.Body,
.Tags,
.ASTData
padding-left: 0
text-decoration: inherit
.Synopsis
padding: 0
margin-bottom: 15px
font-size: $defaultFontSize
font-weight: $defaultFontWeight
color: $defaultTextColor
font-style: normal
.constr
padding: 25px 0
margin: 0
.DefDoc
.Body
display: none
.documentation
display: inline-flex
width: 100%
margin-bottom: 10px
.ASTHead
width: 30% !important
margin: 10px 0
.DefTitle,
.Infix
padding: 0
font-size: $defaultFontSize
font-weight: $defaultFontWeight
font-style: normal
text-decoration: inherit
.ASTData
width: 70% !important
.Doc
text-decoration: inherit
.Synopsis
text-decoration: inherit
margin: 10px 0
.Tags
margin: 2px 0 0 auto
padding: 0
.DefNoDoc
padding-bottom: 10px
.DefTitle
display: inline-flex
font-size: x-large
font-weight: $defaultFontWeight
margin-bottom: 20px
.DefArgs
margin-left: 5px
font-weight: $defaultFontWeight
color: $defaultCodeColor
/*/////////////////////////
//// Synopsis & Detail ////
/////////////////////////*/
.Synopsis,
.Body
margin: 0 auto
padding: 5px
text-align: left
.Synopsis
margin-top: 35px
font-size: 20px
.Documentation
.ASTData,
.ASTHead
text-align: left
line-height: 1.05
border-radius: 6px
.ASTData
width: 100%
background-color: #fafafa
.ASTHead
margin: 20px auto 5px
background-color: #ffffff
.DefTitle
font-size: 42px
margin: 0
.ASTData
.ASTHead
background-color: #fafafa
.DefTitle
font-size: x-large
.Documented
margin: 0
width: 100%
background-color: #ffffff
.DefNoBody
text-decoration: inherit
/*///////////////////////////
//// RWD ////
///////////////////////////*/
@media (max-width: 500px)
.Synopsis,
.Body,
.Tags,
.Documentation .ASTData .Def
max-width: 380px
.Documentation .ASTHead,
.DefNoBody,
.DefBody
max-width: 400px
.Def
padding: 5px
@media (min-width: 500px)
.Synopsis,
.Body,
.Tags,
.Documentation .ASTData .Def
max-width: 440px
.Documentation .ASTHead,
.DefNoBody,
.DefBody
max-width: 470px
@media (min-width: 600px)
.Synopsis,
.Body,
.Tags,
.Documentation .ASTData .Def
max-width: 490px
.Documentation .ASTHead,
.DefNoBody,
.DefBody
max-width: 520px
@media (min-width: 900px)
.Synopsis,
.Body,
.Tags,
.Documentation .ASTData .Def
max-width: 680px
.Documentation .ASTHead,
.DefNoBody,
.DefBody
max-width: 710px
@media (min-width: 1300px)
.Synopsis,
.Body,
.Tags,
.Documentation .ASTData .Def
max-width: 790px
.Documentation .ASTHead,
.DefNoBody,
.DefBody
max-width: 820px

View File

@ -573,7 +573,6 @@ object Main extends scala.App {
println("===== DOCUMENTATION =====") println("===== DOCUMENTATION =====")
val droppedMeta = parser.dropMacroMeta(mod) val droppedMeta = parser.dropMacroMeta(mod)
val doc = DocParserRunner.createDocs(droppedMeta) val doc = DocParserRunner.createDocs(droppedMeta)
val cssFileName = "style.css"
println(Debug.pretty(doc.toString)) println(Debug.pretty(doc.toString))
println("------") println("------")