mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 23:51:31 +03:00
Documentation Parser: Extended HTML Files Generator (#237)
* Update CSS * Add some code - WIP * recursive Documented HTML generation * WIP - Better documentation, better code, better test * documentation wip * code complexity changes * update docs * update docs * move saving out of class * move all html generator code to separate object * Fix documentation * Change example text * 80 chars/ln * Merge remote-tracking branch 'origin/master' into wip/mm/doc-parser-html-output # Conflicts: # Syntax/specialization/src/main/scala/org/enso/syntax/text/Parser.scala * Merge remote-tracking branch 'origin/master' into wip/mm/doc-parser-html-output # Conflicts: # Syntax/specialization/src/main/scala/org/enso/syntax/text/Parser.scala * just add example * add sass * minor fix * cleanup * rm unused func
This commit is contained in:
parent
85272edcb0
commit
05877a7d0c
@ -35,7 +35,7 @@ final case class Doc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Doc {
|
object Doc {
|
||||||
def apply(): Doc = Doc(None, None, None)
|
def apply(): Doc = Doc(None, None, None)
|
||||||
def apply(tags: Tags): Doc = Doc(Some(tags), None, None)
|
def apply(tags: Tags): Doc = Doc(Some(tags), None, None)
|
||||||
def apply(synopsis: Synopsis): Doc =
|
def apply(synopsis: Synopsis): Doc =
|
||||||
Doc(None, Some(synopsis), None)
|
Doc(None, Some(synopsis), None)
|
||||||
@ -61,18 +61,8 @@ object Doc {
|
|||||||
* extending tokens and getting HTML file out of Doc Parser
|
* extending tokens and getting HTML file out of Doc Parser
|
||||||
*/
|
*/
|
||||||
sealed trait Symbol extends Repr.Provider {
|
sealed trait Symbol extends Repr.Provider {
|
||||||
def show() = repr.build()
|
def show(): String = repr.build()
|
||||||
def html: HTML
|
def html: HTML
|
||||||
def renderHTML(cssLink: String): HTMLTag = {
|
|
||||||
val metaEquiv = HTML.httpEquiv := "Content-Type"
|
|
||||||
val metaCont = HTML.content := "text/html"
|
|
||||||
val metaChar = HTML.charset := "UTF-8"
|
|
||||||
val meta = HTML.meta(metaEquiv)(metaCont)(metaChar)
|
|
||||||
val cssRel = HTML.rel := "stylesheet"
|
|
||||||
val cssHref = HTML.href := cssLink
|
|
||||||
val css = HTML.link(cssRel)(cssHref)
|
|
||||||
HTML.html(HTML.head(meta, css), HTML.body(html))
|
|
||||||
}
|
|
||||||
|
|
||||||
def htmlCls(): generic.AttrPair[Builder, String] =
|
def htmlCls(): generic.AttrPair[Builder, String] =
|
||||||
HTML.`class` := getClass.toString.split('$').last.split('.').last
|
HTML.`class` := getClass.toString.split('$').last.split('.').last
|
||||||
@ -155,7 +145,7 @@ object Doc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Unclosed {
|
object Unclosed {
|
||||||
def apply(typ: Type): Unclosed = Unclosed(typ, Nil)
|
def apply(typ: Type): Unclosed = Unclosed(typ, Nil)
|
||||||
def apply(typ: Type, elem: Elem): Unclosed = Unclosed(typ, elem :: Nil)
|
def apply(typ: Type, elem: Elem): Unclosed = Unclosed(typ, elem :: Nil)
|
||||||
def apply(typ: Type, elems: Elem*): Unclosed =
|
def apply(typ: Type, elems: Elem*): Unclosed =
|
||||||
Unclosed(typ, elems.toList)
|
Unclosed(typ, elems.toList)
|
||||||
@ -340,7 +330,7 @@ object Doc {
|
|||||||
*/
|
*/
|
||||||
sealed trait Section extends Symbol {
|
sealed trait Section extends Symbol {
|
||||||
def indent: Int
|
def indent: Int
|
||||||
def elems: List[Elem]
|
def elems: List[Elem]
|
||||||
|
|
||||||
def reprOfNormalText(elem: Elem, prevElem: Elem): Repr.Builder = {
|
def reprOfNormalText(elem: Elem, prevElem: Elem): Repr.Builder = {
|
||||||
prevElem match {
|
prevElem match {
|
||||||
@ -363,7 +353,7 @@ object Doc {
|
|||||||
val html: HTML = Seq(HTML.div(htmlCls())(elems.map(_.html)))
|
val html: HTML = Seq(HTML.div(htmlCls())(elems.map(_.html)))
|
||||||
}
|
}
|
||||||
object Header {
|
object Header {
|
||||||
def apply(elem: Elem): Header = Header(elem :: Nil)
|
def apply(elem: Elem): Header = Header(elem :: Nil)
|
||||||
def apply(elems: Elem*): Header = Header(elems.toList)
|
def apply(elems: Elem*): Header = Header(elems.toList)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,13 +431,13 @@ object Doc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Raw {
|
object Raw {
|
||||||
def apply(indent: Int): Raw = Raw(indent, Nil)
|
def apply(indent: Int): Raw = Raw(indent, Nil)
|
||||||
def apply(indent: Int, elem: Elem): Raw = Raw(indent, elem :: Nil)
|
def apply(indent: Int, elem: Elem): Raw = Raw(indent, elem :: Nil)
|
||||||
def apply(indent: Int, elems: Elem*): Raw = Raw(indent, elems.toList)
|
def apply(indent: Int, elems: Elem*): Raw = Raw(indent, elems.toList)
|
||||||
val defaultIndent = 0
|
val defaultIndent = 0
|
||||||
def apply(): Raw = Raw(defaultIndent, Nil)
|
def apply(): Raw = Raw(defaultIndent, Nil)
|
||||||
def apply(elem: Elem): Raw = Raw(defaultIndent, elem :: Nil)
|
def apply(elem: Elem): Raw = Raw(defaultIndent, elem :: Nil)
|
||||||
def apply(elems: Elem*): Raw = Raw(defaultIndent, elems.toList)
|
def apply(elems: Elem*): Raw = Raw(defaultIndent, elems.toList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,7 +501,7 @@ object Doc {
|
|||||||
val html: HTML = Seq(HTML.div(htmlCls())(elems.toList.map(_.html)))
|
val html: HTML = Seq(HTML.div(htmlCls())(elems.toList.map(_.html)))
|
||||||
}
|
}
|
||||||
object Tags {
|
object Tags {
|
||||||
def apply(elem: Tag): Tags = Tags(List1(elem))
|
def apply(elem: Tag): Tags = Tags(List1(elem))
|
||||||
def apply(elems: Tag*): Tags = Tags(List1(elems.head, elems.tail.toList))
|
def apply(elems: Tag*): Tags = Tags(List1(elems.head, elems.tail.toList))
|
||||||
|
|
||||||
/** Tag - one single tag for Tags
|
/** Tag - one single tag for Tags
|
||||||
@ -535,7 +525,7 @@ object Doc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
object Tag {
|
object Tag {
|
||||||
val defaultIndent = 0
|
val defaultIndent = 0
|
||||||
def apply(typ: Type): Tag = Tag(defaultIndent, typ, None)
|
def apply(typ: Type): Tag = Tag(defaultIndent, typ, None)
|
||||||
def apply(typ: Type, details: String): Tag =
|
def apply(typ: Type, details: String): Tag =
|
||||||
Tag(defaultIndent, typ, Some(details))
|
Tag(defaultIndent, typ, Some(details))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.syntax.text
|
package org.enso.syntax.text
|
||||||
|
|
||||||
|
import java.io.{File, PrintWriter}
|
||||||
import org.enso.flexer
|
import org.enso.flexer
|
||||||
import org.enso.flexer.Reader
|
import org.enso.flexer.Reader
|
||||||
import org.enso.syntax.text.ast.Doc
|
import org.enso.syntax.text.ast.Doc
|
||||||
@ -20,6 +21,7 @@ import org.enso.syntax.text.AST.Block.{LineOf => Line}
|
|||||||
*
|
*
|
||||||
* It is used to create structured documentation from the blocks of commented
|
* It is used to create structured documentation from the blocks of commented
|
||||||
* text created by the main Enso parser.
|
* text created by the main Enso parser.
|
||||||
|
*
|
||||||
* It has been built on the same foundation as Parser, so in order not to
|
* It has been built on the same foundation as Parser, so in order not to
|
||||||
* duplicate information, please refer to Parser documentation.
|
* duplicate information, please refer to Parser documentation.
|
||||||
*/
|
*/
|
||||||
@ -47,65 +49,6 @@ class DocParser {
|
|||||||
* @return - unmatched result possibly containing Doc
|
* @return - unmatched result possibly containing Doc
|
||||||
*/
|
*/
|
||||||
def run(input: String): Result[Doc] = engine.run(new Reader(input))
|
def run(input: String): Result[Doc] = engine.run(new Reader(input))
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//// HTML Rendering of Documentation /////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TODO remove this functionality from parser
|
|
||||||
/**
|
|
||||||
* Used to create HTML files from Doc with or without title after Doc Parser
|
|
||||||
* Runner finished it's job
|
|
||||||
*
|
|
||||||
* @param documented - documented made by Doc Parser Runner from AST and Doc
|
|
||||||
*/
|
|
||||||
def onHTMLRendering(documented: AST.Documented): Unit = {
|
|
||||||
val path = "syntax/specialization/target/"
|
|
||||||
val cssFileName = "style.css"
|
|
||||||
val htmlCode = renderHTML(documented.ast, documented.doc, cssFileName)
|
|
||||||
val astLines = documented.ast.show().split("\n")
|
|
||||||
val fileName = astLines.head.replaceAll("/", "")
|
|
||||||
htmlCode
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function invoked by [[onHTMLRendering]] to render HTML File
|
|
||||||
*
|
|
||||||
* @param ast - ast from Doc Parser Runner
|
|
||||||
* @param doc - Doc from Doc Parser
|
|
||||||
* @param cssLink - string containing CSS file name
|
|
||||||
* @return - HTML Code from Doc with optional title from AST
|
|
||||||
*/
|
|
||||||
def renderHTML(
|
|
||||||
ast: AST,
|
|
||||||
doc: Doc,
|
|
||||||
cssLink: String = "style.css"
|
|
||||||
): TypedTag[String] = {
|
|
||||||
val title = ast.show().split("\n").head
|
|
||||||
val astHtml = Seq(HTML.div(HTML.`class` := "ASTData")(ast.show()))
|
|
||||||
val docClass = HTML.`class` := "Documentation"
|
|
||||||
val documentation = Seq(HTML.div(docClass)(doc.html, astHtml))
|
|
||||||
HTML.html(createHTMLHead(title, cssLink), HTML.body(documentation))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function invoked by [[renderHTML]] to create HTML.Head part of file
|
|
||||||
*
|
|
||||||
* @param title - HTML page title
|
|
||||||
* @param cssLink - string containing CSS file name
|
|
||||||
* @return - HTML Head Code
|
|
||||||
*/
|
|
||||||
def createHTMLHead(title: String, cssLink: String): TypedTag[String] = {
|
|
||||||
val metaEquiv = HTML.httpEquiv := "Content-Type"
|
|
||||||
val metaCont = HTML.content := "text/html"
|
|
||||||
val metaChar = HTML.charset := "UTF-8"
|
|
||||||
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)
|
|
||||||
HTML.head(meta, css)(fileTitle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object DocParser {
|
object DocParser {
|
||||||
@ -117,7 +60,6 @@ object DocParser {
|
|||||||
*/
|
*/
|
||||||
def runMatched(input: String): Doc = new DocParser().runMatched(input)
|
def runMatched(input: String): Doc = new DocParser().runMatched(input)
|
||||||
def run(input: String): Result[Doc] = new DocParser().run(input)
|
def run(input: String): Result[Doc] = new DocParser().run(input)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -130,8 +72,9 @@ object DocParser {
|
|||||||
* Essentially it binds together Enso Parser with Doc Parser.
|
* Essentially it binds together Enso Parser with Doc Parser.
|
||||||
* When Parser finishes its job it invokes runner with AST created by it after
|
* When Parser finishes its job it invokes runner with AST created by it after
|
||||||
* resolving macros. Then Runner does it's job - running Doc Parser on every
|
* resolving macros. Then Runner does it's job - running Doc Parser on every
|
||||||
* [[AST.Comment]], combined with connecting [[Doc]] with AST in [[AST.Documented]]
|
* [[AST.Comment]], combined with connecting [[Doc]] with AST in
|
||||||
* node, which gets AST from [[AST.Def]] and [[AST.App.Infix]]
|
* [[AST.Documented]] node, which gets AST from [[AST.Def]] and
|
||||||
|
* [[AST.App.Infix]]
|
||||||
*/
|
*/
|
||||||
object DocParserRunner {
|
object DocParserRunner {
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -165,8 +108,8 @@ object DocParserRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper functions for [[createDocs]]
|
* This is a helper function for [[createDocs]] to traverse through
|
||||||
* to traverse through Module and Def body
|
* [[AST.Module]] and create Docs from comments with appropriate [[AST]]
|
||||||
*/
|
*/
|
||||||
def createDocsFromModule(m: AST.Module): AST.Module = {
|
def createDocsFromModule(m: AST.Module): AST.Module = {
|
||||||
val emptyLine = List1(AST.Block.OptLine())
|
val emptyLine = List1(AST.Block.OptLine())
|
||||||
@ -175,6 +118,11 @@ object DocParserRunner {
|
|||||||
AST.Module(transformedLines)
|
AST.Module(transformedLines)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a helper function for [[createDocs]] to traverse through
|
||||||
|
* [[AST.Def]] and create Docs from comments inside [[AST.Def]] with
|
||||||
|
* appropriate [[AST]]
|
||||||
|
*/
|
||||||
def createDocsFromDefBody(
|
def createDocsFromDefBody(
|
||||||
name: AST.Cons,
|
name: AST.Cons,
|
||||||
args: List[AST],
|
args: List[AST],
|
||||||
@ -301,6 +249,7 @@ object DocParserRunner {
|
|||||||
* method
|
* method
|
||||||
*
|
*
|
||||||
* @param comment - comment found in AST
|
* @param comment - comment found in AST
|
||||||
|
* @param emptyLines - Empty lines in between Doc and AST
|
||||||
* @param off - line offset
|
* @param off - line offset
|
||||||
* @param ast - AST to go with comment into Documented
|
* @param ast - AST to go with comment into Documented
|
||||||
* @return - [[AST.Documented]]
|
* @return - [[AST.Documented]]
|
||||||
@ -315,24 +264,263 @@ object DocParserRunner {
|
|||||||
val documented = Some(AST.Documented(doc, emptyLines, ast))
|
val documented = Some(AST.Documented(doc, emptyLines, ast))
|
||||||
Line(documented, off)
|
Line(documented, off)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//// Generating HTML for created Doc's ///////////////////////////////////////
|
//// Doc Parser HTML Generator /////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is Doc Parser HTML Generator.
|
||||||
|
*
|
||||||
|
* Essentially it enables Doc Parser to create pretty HTML files from
|
||||||
|
* documented code.
|
||||||
|
*
|
||||||
|
* When Doc Parser finishes its job user can invoke DocParserHTMLGenerator by
|
||||||
|
* simply passing the output of Doc Parser onto function called
|
||||||
|
* [[DocParserHTMLGenerator.generateHTMLForEveryDocumented]], and it will
|
||||||
|
* automatically traverse through AST prepared by Doc Parser and generate
|
||||||
|
* HTML files in all appropriate places.
|
||||||
|
*/
|
||||||
|
object DocParserHTMLGenerator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used for generation of HTML files from parsed and
|
* This method is used for generation of HTML files from parsed and
|
||||||
* 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 path - path to save file
|
||||||
|
* @param cssFileName - name of file containing stylesheets for the HTML code
|
||||||
*/
|
*/
|
||||||
def generateHTMLForEveryDocumented(ast: AST): Unit = {
|
def generateHTMLForEveryDocumented(
|
||||||
|
ast: AST,
|
||||||
|
path: String,
|
||||||
|
cssFileName: String
|
||||||
|
): Unit = {
|
||||||
ast.map { elem =>
|
ast.map { elem =>
|
||||||
elem match {
|
elem match {
|
||||||
case AST.Documented.any(d) => new DocParser().onHTMLRendering(d)
|
case AST.Documented.any(d) =>
|
||||||
case _ => generateHTMLForEveryDocumented(elem)
|
val file = onHTMLRendering(d, cssFileName)
|
||||||
|
saveHTMLToFile(path, file._2, file._1)
|
||||||
|
case _ => generateHTMLForEveryDocumented(elem, path, cssFileName)
|
||||||
}
|
}
|
||||||
elem
|
elem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves HTML code to file
|
||||||
|
*
|
||||||
|
* @param path - path to file
|
||||||
|
* @param name - file name
|
||||||
|
* @param code - HTML code generated with Doc Parser
|
||||||
|
*/
|
||||||
|
def saveHTMLToFile(
|
||||||
|
path: String,
|
||||||
|
name: String,
|
||||||
|
code: TypedTag[String]
|
||||||
|
): Unit = {
|
||||||
|
val writer = new PrintWriter(new File(path + name + ".html"))
|
||||||
|
writer.write(code.toString)
|
||||||
|
writer.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//// HTML Rendering of Documentation /////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to create HTML files from Doc with or without title after Doc Parser
|
||||||
|
* Runner finished it's job
|
||||||
|
*
|
||||||
|
* @param documented - documented made by Doc Parser Runner from AST and Doc
|
||||||
|
* @param cssFileName - name of file containing stylesheets for the HTML code
|
||||||
|
* @return - tuple containing HTML code with file name
|
||||||
|
*/
|
||||||
|
def onHTMLRendering(
|
||||||
|
documented: AST.Documented,
|
||||||
|
cssFileName: String
|
||||||
|
): (TypedTag[String], String) = {
|
||||||
|
val htmlCode = renderHTML(documented.ast, documented.doc, cssFileName)
|
||||||
|
val astLines = documented.ast.show().split("\n")
|
||||||
|
val fileName = astLines.head.replaceAll("/", "")
|
||||||
|
(htmlCode, fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function invoked by [[onHTMLRendering]] to render HTML File
|
||||||
|
*
|
||||||
|
* @param ast - AST from 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
|
||||||
|
* [[AST.App.Infix]], with optional title made from AST
|
||||||
|
*/
|
||||||
|
def renderHTML(
|
||||||
|
ast: AST,
|
||||||
|
doc: Doc,
|
||||||
|
cssLink: String = "style.css"
|
||||||
|
): TypedTag[String] = {
|
||||||
|
val title = ast.show().split("\n").head
|
||||||
|
val documentation = DocumentedToHtml(ast, doc)
|
||||||
|
HTML.html(createHTMLHead(title, cssLink), HTML.body(documentation))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is used to get HTML content of Doc and try to render AST,
|
||||||
|
* by finding if it also contains Documented to retrieve Doc and it's AST,
|
||||||
|
* or simply call show() method on other element of AST.
|
||||||
|
*
|
||||||
|
* @param ast - AST from Parser
|
||||||
|
* @param doc - Doc from Doc Parser
|
||||||
|
* @return - HTML Code from Doc and contents of [[AST.Def]] or
|
||||||
|
* [[AST.App.Infix]]
|
||||||
|
*/
|
||||||
|
def DocumentedToHtml(
|
||||||
|
ast: AST,
|
||||||
|
doc: Doc
|
||||||
|
): TypedTag[String] = {
|
||||||
|
val astCls = HTML.`class` := "ASTData"
|
||||||
|
val astHtml = Seq(HTML.div(astCls)(createHTMLFromAST(ast)))
|
||||||
|
val docClass = HTML.`class` := "Documentation"
|
||||||
|
HTML.div(docClass)(doc.html, astHtml)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function invoked by [[DocumentedToHtml]] to create HTML from AST in
|
||||||
|
* [[AST.Documented]]
|
||||||
|
*
|
||||||
|
* @param ast - AST
|
||||||
|
* @return - HTML Code
|
||||||
|
*/
|
||||||
|
def createHTMLFromAST(ast: AST): TypedTag[String] = {
|
||||||
|
ast match {
|
||||||
|
case AST.Def.any(d) =>
|
||||||
|
d.body match {
|
||||||
|
case Some(body) =>
|
||||||
|
body match {
|
||||||
|
case AST.Block.any(b) => createDefWithBody(d.name, d.args, b)
|
||||||
|
case _ => createDefWithoutBody(d.name, d.args)
|
||||||
|
}
|
||||||
|
case None => createDefWithoutBody(d.name, d.args)
|
||||||
|
}
|
||||||
|
case AST.App.Infix.any(i) => createInfixHtmlRepr(i)
|
||||||
|
case _ => HTML.div()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for [[createHTMLFromAST]] to generate appropriate code
|
||||||
|
* from [[AST.Def]] with traversing through body and creating HTML code
|
||||||
|
* on elements in it
|
||||||
|
*
|
||||||
|
* @param name - Def Name
|
||||||
|
* @param args - Def Arguments
|
||||||
|
* @param body - Def body
|
||||||
|
* @return - HTML code generated from Def
|
||||||
|
*/
|
||||||
|
def createDefWithBody(
|
||||||
|
name: AST.Cons,
|
||||||
|
args: List[AST],
|
||||||
|
body: AST.Block
|
||||||
|
): TypedTag[String] = {
|
||||||
|
val firstLine = Line(Option(body.firstLine.elem), body.firstLine.off)
|
||||||
|
val allLines = firstLine :: body.lines
|
||||||
|
val generatedCode = renderHTMLOnLine(allLines)
|
||||||
|
val head = createDefTitle(name, args)
|
||||||
|
val clsBody = HTML.`class` := "DefBody"
|
||||||
|
val lines = HTML.div(clsBody)(generatedCode)
|
||||||
|
val cls = HTML.`class` := "Def"
|
||||||
|
HTML.div(cls)(head, lines)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for [[createHTMLFromAST]] to generate appropriate code
|
||||||
|
* from [[AST.Def]] when it doesn't contain anything in it's body
|
||||||
|
*
|
||||||
|
* @param name - Def Name
|
||||||
|
* @param args - Def Arguments
|
||||||
|
* @return - HTML code generated from Def
|
||||||
|
*/
|
||||||
|
def createDefWithoutBody(
|
||||||
|
name: AST.Cons,
|
||||||
|
args: List[AST]
|
||||||
|
): TypedTag[String] = {
|
||||||
|
val cls = HTML.`class` := "DefNoBody"
|
||||||
|
HTML.div(cls)(createDefTitle(name, args))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for [[createDefWithBody]] or [[createDefWithoutBody]]
|
||||||
|
* to generate [[AST.Def]] title form it's name and args
|
||||||
|
*
|
||||||
|
* @param name - Def Name
|
||||||
|
* @param args - Def Arguments
|
||||||
|
* @return - Def title in HTML
|
||||||
|
*/
|
||||||
|
def createDefTitle(name: AST.Cons, args: List[AST]): TypedTag[String] = {
|
||||||
|
val clsTitle = HTML.`class` := "DefTitle"
|
||||||
|
val clsArgs = HTML.`class` := "DefArgs"
|
||||||
|
HTML.div(clsTitle)(name.show(), HTML.div(clsArgs)(args.map(_.show())))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for [[createHTMLFromAST]] to generate appropriate HTML
|
||||||
|
* code from [[AST.App.Infix]]
|
||||||
|
*
|
||||||
|
* @param infix - AST Infix
|
||||||
|
* @return - HTML code generated from Infix
|
||||||
|
*/
|
||||||
|
def createInfixHtmlRepr(infix: AST.App.Infix): TypedTag[String] = {
|
||||||
|
val cls = HTML.`class` := "Infix"
|
||||||
|
HTML.div(cls)(infix.larg.show())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for [[createDefWithBody]] to traverse through body's lines
|
||||||
|
* and try to generate HTML code from [[AST.Documented]] parts of it. It also
|
||||||
|
* tries to find nested [[AST.Def]] and [[AST.App.Infix]] inside of body
|
||||||
|
*
|
||||||
|
* @param lines - lines inside of Def body
|
||||||
|
* @return - HTML code generated from contents of lines
|
||||||
|
*/
|
||||||
|
def renderHTMLOnLine(lines: List[AST.Block.OptLine]): List[TypedTag[String]] =
|
||||||
|
lines match {
|
||||||
|
case Line(Some(AST.Documented.any(doc)), _) :: rest =>
|
||||||
|
val cls = HTML.`class` := "DefDoc"
|
||||||
|
val docHtml = DocumentedToHtml(doc.ast, doc.doc)
|
||||||
|
HTML.div(cls)(docHtml) :: renderHTMLOnLine(rest)
|
||||||
|
case x :: rest =>
|
||||||
|
x match {
|
||||||
|
case Line(Some(d), _) =>
|
||||||
|
val cls = HTML.`class` := "DefNoDoc"
|
||||||
|
val astHtml = createHTMLFromAST(d)
|
||||||
|
HTML.div(cls)(astHtml) :: renderHTMLOnLine(rest)
|
||||||
|
case _ => renderHTMLOnLine(rest)
|
||||||
|
}
|
||||||
|
case other =>
|
||||||
|
other match {
|
||||||
|
case Nil => List()
|
||||||
|
case _ :: rest => renderHTMLOnLine(rest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function invoked by [[DocumentedToHtml]] to create HTML.Head part of file
|
||||||
|
*
|
||||||
|
* @param title - HTML page title
|
||||||
|
* @param cssLink - string containing CSS file name
|
||||||
|
* @return - HTML Head Code
|
||||||
|
*/
|
||||||
|
def createHTMLHead(title: String, cssLink: String): TypedTag[String] = {
|
||||||
|
val metaEquiv = HTML.httpEquiv := "Content-Type"
|
||||||
|
val metaCont = HTML.content := "text/html"
|
||||||
|
val metaChar = HTML.charset := "UTF-8"
|
||||||
|
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)
|
||||||
|
HTML.head(meta, css)(fileTitle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,333 +0,0 @@
|
|||||||
/*//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//// UNDER CONSTRUCTION ////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////*/
|
|
||||||
|
|
||||||
|
|
||||||
/*///////////
|
|
||||||
//// DOM ////
|
|
||||||
///////////*/
|
|
||||||
|
|
||||||
body {
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
font-style: normal;
|
|
||||||
word-wrap: break-word;
|
|
||||||
font-size: 17px;
|
|
||||||
line-height: 1.52947;
|
|
||||||
font-weight: 400;
|
|
||||||
letter-spacing: -0.021em;
|
|
||||||
font-family: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", "Helvetica",
|
|
||||||
"Arial", sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
color: #333333;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
display: block;
|
|
||||||
margin-block-start: 1em;
|
|
||||||
margin-block-end: 1em;
|
|
||||||
margin-inline-start: 0px;
|
|
||||||
margin-inline-end: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: #35a5ff !important;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #0070c9;
|
|
||||||
background-color: transparent;
|
|
||||||
text-decoration: none;
|
|
||||||
display: inline-block;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
color: #0070c9;
|
|
||||||
background-color: transparent;
|
|
||||||
font-size: inherit;
|
|
||||||
font-family: monospace;
|
|
||||||
line-height: inherit;
|
|
||||||
display: inline-block;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 8px 30px;
|
|
||||||
margin: 10px 0;
|
|
||||||
outline: none;
|
|
||||||
background-color: #777;
|
|
||||||
border: none;
|
|
||||||
color: #fafafa;
|
|
||||||
border-radius: 5px;
|
|
||||||
box-shadow: 5px 0 #555;
|
|
||||||
font-size: 13px;
|
|
||||||
vertical-align: top;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover {
|
|
||||||
background-color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
b {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 34px;
|
|
||||||
line-height: 1.08824;
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: 0.01em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 28px;
|
|
||||||
line-height: 1.1073;
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: 0.012em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Body h2 {
|
|
||||||
margin: 0;
|
|
||||||
margin-top: 0.65rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*///////////////////
|
|
||||||
//// Invalid AST ////
|
|
||||||
///////////////////*/
|
|
||||||
|
|
||||||
.creator .Unclosed,
|
|
||||||
.creator .invalidIndent,
|
|
||||||
.creator .invalidLink{
|
|
||||||
display: inline;
|
|
||||||
color: orangered;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Unclosed,
|
|
||||||
.invalidIndent,
|
|
||||||
.invalidLink {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*//////////////
|
|
||||||
//// Header ////
|
|
||||||
//////////////*/
|
|
||||||
|
|
||||||
.Header {
|
|
||||||
font-size: 19px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Important .Header,
|
|
||||||
.Info .Header,
|
|
||||||
.Example .Header {
|
|
||||||
margin-bottom: 0.7em;
|
|
||||||
font-weight: 600;
|
|
||||||
letter-spacing: -0.021em;
|
|
||||||
line-height: 17px;
|
|
||||||
font-synthesis: none;
|
|
||||||
font-family: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", "Helvetica",
|
|
||||||
"Arial", sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*////////////
|
|
||||||
//// Tags ////
|
|
||||||
////////////*/
|
|
||||||
|
|
||||||
.Doc .Tags {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
padding: 15px 0;
|
|
||||||
text-align: center;
|
|
||||||
background-color: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Doc .ExtForTagDetails {
|
|
||||||
margin: 0 3px;
|
|
||||||
color: #999999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Doc .Tags .DEPRECATED,
|
|
||||||
.Doc .Tags .MODIFIED,
|
|
||||||
.Doc .Tags .ADDED,
|
|
||||||
.Doc .Tags .UPCOMING,
|
|
||||||
.Doc .Tags .REMOVED,
|
|
||||||
.Doc .Tags .UNRECOGNIZED {
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 400;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: 12px;
|
|
||||||
letter-spacing: -0.021em;
|
|
||||||
border: 1px solid;
|
|
||||||
display: inline-flex;
|
|
||||||
padding: 3px 15px;
|
|
||||||
margin: 2px;
|
|
||||||
white-space: nowrap;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Doc .Tags .DEPRECATED {
|
|
||||||
border-color: #c35400;
|
|
||||||
color: #c35400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Doc .Tags .MODIFIED {
|
|
||||||
border-color: #8A82CF;
|
|
||||||
color: #8A82CF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Doc .Tags .ADDED {
|
|
||||||
border-color: #79A129;
|
|
||||||
color: #79A129;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Doc .Tags .UPCOMING,
|
|
||||||
.Doc .Tags .REMOVED,
|
|
||||||
.Doc .Tags .UNRECOGNIZED {
|
|
||||||
border-color: #888888;
|
|
||||||
color: #666666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.creator .Doc .Tags .UNRECOGNIZED {
|
|
||||||
border: 2px solid;
|
|
||||||
color: orangered;
|
|
||||||
}
|
|
||||||
/*////////////////
|
|
||||||
//// Sections ////
|
|
||||||
////////////////*/
|
|
||||||
|
|
||||||
.Raw,
|
|
||||||
.Important,
|
|
||||||
.Info,
|
|
||||||
.CodeBlock,
|
|
||||||
.Example {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Body .Raw {
|
|
||||||
padding: 0.75em 0;
|
|
||||||
margin-bottom: 0.6rem;
|
|
||||||
font-size: 17px;
|
|
||||||
line-height: 1.52947;
|
|
||||||
font-weight: 400;
|
|
||||||
letter-spacing: -0.021em;
|
|
||||||
font-family: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", "Helvetica",
|
|
||||||
"Arial", sans-serif;
|
|
||||||
background-color: white;
|
|
||||||
color: #333333;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Synopsis .Raw {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Important,
|
|
||||||
.Info,
|
|
||||||
.CodeBlock,
|
|
||||||
.Example {
|
|
||||||
font-size: 17;
|
|
||||||
padding-top: 0.94118rem;
|
|
||||||
padding-bottom: 0.94118rem;
|
|
||||||
padding-left: 18px;
|
|
||||||
padding-right: 10px;
|
|
||||||
border: 1px solid #8a82cf;
|
|
||||||
border-left: 6px solid #8a82cf;
|
|
||||||
border-radius: 6px;
|
|
||||||
margin: 0.7em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Important {
|
|
||||||
border-right: 0px;
|
|
||||||
border-top: 0px;
|
|
||||||
border-bottom: 0px;
|
|
||||||
border-color: #fee450;
|
|
||||||
background-color: #fbf8e8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Info {
|
|
||||||
border-color: 69c5e8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Example {
|
|
||||||
border-color: #8a82cf;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeBlock {
|
|
||||||
border-color: #7cd58b;
|
|
||||||
margin: 10px 20px;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*/////////////////////////
|
|
||||||
//// Synopsis & Detail ////
|
|
||||||
/////////////////////////*/
|
|
||||||
|
|
||||||
.Synopsis,
|
|
||||||
.Body {
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 5px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Synopsis {
|
|
||||||
font-size: 20px;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 300;
|
|
||||||
letter-spacing: 0.017em;
|
|
||||||
border-bottom: 1px solid #d6d6d6
|
|
||||||
}
|
|
||||||
|
|
||||||
.Doc {
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 300px) {
|
|
||||||
.Synopsis,
|
|
||||||
.Body {
|
|
||||||
width: 380px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 500px) {
|
|
||||||
.Synopsis,
|
|
||||||
.Body {
|
|
||||||
width: 440px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 600px) {
|
|
||||||
.Synopsis,
|
|
||||||
.Body {
|
|
||||||
width: 490px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 900px) {
|
|
||||||
.Synopsis,
|
|
||||||
.Body {
|
|
||||||
width: 670px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1300px) {
|
|
||||||
.Synopsis,
|
|
||||||
.Body {
|
|
||||||
width: 780px
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,359 @@
|
|||||||
|
/*///////////
|
||||||
|
//// DOM ////
|
||||||
|
///////////*/
|
||||||
|
|
||||||
|
body
|
||||||
|
-webkit-font-smoothing: antialiased
|
||||||
|
font-style: normal
|
||||||
|
word-wrap: break-word
|
||||||
|
font-size: 17px
|
||||||
|
line-height: 1.52947
|
||||||
|
font-weight: 400
|
||||||
|
letter-spacing: -0.021em
|
||||||
|
font-family: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", "Helvetica","Arial", sans-serif
|
||||||
|
background-color: white
|
||||||
|
color: #333333
|
||||||
|
font-style: normal
|
||||||
|
|
||||||
|
p
|
||||||
|
display: block
|
||||||
|
margin-block-start: 1em
|
||||||
|
margin-block-end: 1em
|
||||||
|
margin-inline-start: 0
|
||||||
|
margin-inline-end: 0
|
||||||
|
|
||||||
|
a:hover
|
||||||
|
color: #35a5ff !important
|
||||||
|
text-decoration: none
|
||||||
|
|
||||||
|
a
|
||||||
|
color: #0070c9
|
||||||
|
background-color: transparent
|
||||||
|
text-decoration: none
|
||||||
|
display: inline-block
|
||||||
|
transition: all 0.3s ease
|
||||||
|
|
||||||
|
img
|
||||||
|
display: block
|
||||||
|
|
||||||
|
code
|
||||||
|
color: #0070c9
|
||||||
|
background-color: transparent
|
||||||
|
font-size: inherit
|
||||||
|
font-family: monospace
|
||||||
|
line-height: inherit
|
||||||
|
display: inline-block
|
||||||
|
white-space: pre-wrap
|
||||||
|
|
||||||
|
button
|
||||||
|
display: inline-block
|
||||||
|
padding: 8px 30px
|
||||||
|
margin: 10px 0
|
||||||
|
outline: none
|
||||||
|
background-color: #777
|
||||||
|
border: none
|
||||||
|
color: #fafafa
|
||||||
|
border-radius: 5px
|
||||||
|
box-shadow: 5px 0 #555
|
||||||
|
font-size: 13px
|
||||||
|
vertical-align: top
|
||||||
|
transition: all 0.3s ease
|
||||||
|
|
||||||
|
button:hover
|
||||||
|
background-color: #333
|
||||||
|
|
||||||
|
b
|
||||||
|
font-weight: 600
|
||||||
|
|
||||||
|
h1
|
||||||
|
font-size: 34px
|
||||||
|
line-height: 1.08824
|
||||||
|
font-weight: 500
|
||||||
|
letter-spacing: 0.01em
|
||||||
|
|
||||||
|
|
||||||
|
h2
|
||||||
|
font-size: 28px
|
||||||
|
line-height: 1.1073
|
||||||
|
font-weight: 500
|
||||||
|
letter-spacing: 0.012em
|
||||||
|
|
||||||
|
|
||||||
|
.Body h2
|
||||||
|
margin: 0
|
||||||
|
margin-top: 0.65rem
|
||||||
|
|
||||||
|
|
||||||
|
/*///////////////////
|
||||||
|
//// 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: 500
|
||||||
|
|
||||||
|
|
||||||
|
.Important .Header,
|
||||||
|
.Info .Header,
|
||||||
|
.Example .Header
|
||||||
|
margin-bottom: 0.7em
|
||||||
|
font-weight: 600
|
||||||
|
letter-spacing: -0.021em
|
||||||
|
line-height: 17px
|
||||||
|
font-synthesis: none
|
||||||
|
font-family: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", "Helvetica","Arial", sans-serif
|
||||||
|
|
||||||
|
|
||||||
|
/*////////////
|
||||||
|
//// Tags ////
|
||||||
|
////////////*/
|
||||||
|
|
||||||
|
.Tags
|
||||||
|
margin-left: auto
|
||||||
|
margin-right: auto
|
||||||
|
margin-bottom: 20px
|
||||||
|
padding: 15px 10px
|
||||||
|
text-align: center
|
||||||
|
background-color: #fafafa
|
||||||
|
border-radius: 8px
|
||||||
|
|
||||||
|
.DEPRECATED,
|
||||||
|
.MODIFIED,
|
||||||
|
.ADDED,
|
||||||
|
.UPCOMING,
|
||||||
|
.REMOVED,
|
||||||
|
.UNRECOGNIZED
|
||||||
|
line-height: 1.5
|
||||||
|
font-weight: 400
|
||||||
|
border-radius: 3px
|
||||||
|
font-size: 12px
|
||||||
|
letter-spacing: -0.021em
|
||||||
|
border: 1px solid
|
||||||
|
display: inline-flex
|
||||||
|
padding: 3px 15px
|
||||||
|
margin: 2px
|
||||||
|
white-space: nowrap
|
||||||
|
background: transparent
|
||||||
|
|
||||||
|
.DEPRECATED
|
||||||
|
border-color: #c35400
|
||||||
|
color: #c35400
|
||||||
|
.MODIFIED
|
||||||
|
border-color: #8A82CF
|
||||||
|
color: #8A82CF
|
||||||
|
.ADDED
|
||||||
|
border-color: #79A129
|
||||||
|
color: #79A129
|
||||||
|
.UPCOMING,
|
||||||
|
.REMOVED,
|
||||||
|
.UNRECOGNIZED
|
||||||
|
border-color: #888888
|
||||||
|
color: #666666
|
||||||
|
|
||||||
|
.ExtForTagDetails
|
||||||
|
margin: 0 3px
|
||||||
|
color: #999999
|
||||||
|
|
||||||
|
/*////////////////
|
||||||
|
//// Sections ////
|
||||||
|
////////////////*/
|
||||||
|
|
||||||
|
.Raw,
|
||||||
|
.Important,
|
||||||
|
.Info,
|
||||||
|
.CodeBlock,
|
||||||
|
.Example
|
||||||
|
margin-top: 0
|
||||||
|
margin-left: auto
|
||||||
|
margin-right: auto
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
|
||||||
|
.Body .Raw
|
||||||
|
padding: 0.75em 0
|
||||||
|
margin-bottom: 0.6rem
|
||||||
|
font-size: 17px
|
||||||
|
line-height: 1.52947
|
||||||
|
font-weight: 400
|
||||||
|
letter-spacing: -0.021em
|
||||||
|
font-family: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", "Helvetica","Arial", sans-serif
|
||||||
|
background-color: white
|
||||||
|
color: #333333
|
||||||
|
font-style: normal
|
||||||
|
|
||||||
|
|
||||||
|
.Synopsis .Raw
|
||||||
|
margin-bottom: 2rem
|
||||||
|
|
||||||
|
|
||||||
|
.Important,
|
||||||
|
.Info,
|
||||||
|
.CodeBlock,
|
||||||
|
.Example
|
||||||
|
font-size: 17px
|
||||||
|
padding-top: 0.94118rem
|
||||||
|
padding-bottom: 0.94118rem
|
||||||
|
padding-left: 18px
|
||||||
|
padding-right: 10px
|
||||||
|
border: 1px solid #8a82cf
|
||||||
|
border-left: 6px solid #8a82cf
|
||||||
|
border-radius: 6px
|
||||||
|
margin: 0.7em 0
|
||||||
|
|
||||||
|
|
||||||
|
.Important
|
||||||
|
border-right: 0
|
||||||
|
border-top: 0
|
||||||
|
border-bottom: 0
|
||||||
|
border-color: #fee450
|
||||||
|
background-color: #fbf8e8
|
||||||
|
|
||||||
|
|
||||||
|
.Info
|
||||||
|
border-color: #69c5e8
|
||||||
|
|
||||||
|
|
||||||
|
.Example
|
||||||
|
border-color: #8a82cf
|
||||||
|
|
||||||
|
|
||||||
|
.CodeBlock
|
||||||
|
border-color: #7cd58b
|
||||||
|
margin: 10px 20px
|
||||||
|
display: none
|
||||||
|
|
||||||
|
|
||||||
|
/*///////////////////////////////////
|
||||||
|
//// HTML generated - Def, Infix ////
|
||||||
|
///////////////////////////////////*/
|
||||||
|
|
||||||
|
.Def
|
||||||
|
padding: 10px 20px
|
||||||
|
|
||||||
|
.Synopsis,
|
||||||
|
.Body,
|
||||||
|
.Tags,
|
||||||
|
.ASTData
|
||||||
|
width: 90% !important
|
||||||
|
|
||||||
|
|
||||||
|
.DefTitle
|
||||||
|
display: inline-flex
|
||||||
|
font-size: x-large
|
||||||
|
font-weight: 600
|
||||||
|
margin-bottom: 20px
|
||||||
|
|
||||||
|
|
||||||
|
.DefArgs
|
||||||
|
margin-left: 5px
|
||||||
|
font-weight: 400
|
||||||
|
color: #0070c9
|
||||||
|
|
||||||
|
|
||||||
|
.Infix
|
||||||
|
font-size: large
|
||||||
|
font-weight: 500
|
||||||
|
margin-bottom: 20px
|
||||||
|
|
||||||
|
|
||||||
|
/*/////////////////////////
|
||||||
|
//// Synopsis & Detail ////
|
||||||
|
/////////////////////////*/
|
||||||
|
|
||||||
|
.Synopsis,
|
||||||
|
.Body
|
||||||
|
margin: 0 auto
|
||||||
|
padding: 5px
|
||||||
|
margin-bottom: 20px
|
||||||
|
text-align: left
|
||||||
|
|
||||||
|
|
||||||
|
.Synopsis
|
||||||
|
font-size: 20px
|
||||||
|
line-height: 1.5
|
||||||
|
font-weight: 300
|
||||||
|
letter-spacing: 0.017em
|
||||||
|
border-bottom: 1px solid #d6d6d6
|
||||||
|
|
||||||
|
|
||||||
|
.Documentation
|
||||||
|
.ASTData
|
||||||
|
margin: 20px auto
|
||||||
|
text-align: left
|
||||||
|
line-height: 1.05
|
||||||
|
letter-spacing: 0.008em
|
||||||
|
background-color: #fafafa
|
||||||
|
border-radius: 6px
|
||||||
|
|
||||||
|
.Documented
|
||||||
|
margin: 0
|
||||||
|
width: 100%
|
||||||
|
background-color: #ffffff
|
||||||
|
|
||||||
|
|
||||||
|
@media (min-width: 300px)
|
||||||
|
.Synopsis,
|
||||||
|
.Body,
|
||||||
|
.Tags,
|
||||||
|
.Documentation .ASTData
|
||||||
|
width: 380px
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@media (min-width: 500px)
|
||||||
|
.Synopsis,
|
||||||
|
.Body,
|
||||||
|
.Tags,
|
||||||
|
.Documentation .ASTData
|
||||||
|
width: 440px
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@media (min-width: 600px)
|
||||||
|
.Synopsis,
|
||||||
|
.Body,
|
||||||
|
.Tags,
|
||||||
|
.Documentation .ASTData
|
||||||
|
width: 490px
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@media (min-width: 900px)
|
||||||
|
.Synopsis,
|
||||||
|
.Body,
|
||||||
|
.Tags,
|
||||||
|
.Documentation .ASTData
|
||||||
|
width: 670px
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@media (min-width: 1300px)
|
||||||
|
.Synopsis,
|
||||||
|
.Body,
|
||||||
|
.Tags,
|
||||||
|
.Documentation .ASTData
|
||||||
|
width: 780px
|
||||||
|
|
||||||
|
|
@ -261,30 +261,72 @@ object Main extends App {
|
|||||||
val in2 = "(a) b = c]"
|
val in2 = "(a) b = c]"
|
||||||
val inp2 = "a (b (c)) x"
|
val inp2 = "a (b (c)) x"
|
||||||
|
|
||||||
val inp = """## This function adds `x` to `y`
|
val inp =
|
||||||
|add x y = x + y
|
"""
|
||||||
|mul x y = x * y
|
|##
|
||||||
|
|
| DEPRECATED
|
||||||
|## This function divides `x` by `y`
|
| REMOVED - replaced by Foo Bar
|
||||||
|div x y = x / y
|
| ADDED
|
||||||
|
|
| MODIFIED
|
||||||
|## Just a comment
|
| UPCOMING
|
||||||
|
|
| ALAMAKOTA a kot ma Ale
|
||||||
|## Doc for infix with empty lines between
|
| This is a test of Enso Documentation Parser. This is a short synopsis.
|
||||||
|
|
|
|
||||||
|sub x y = x - y
|
| Here you can write the body of documentation. On top you can see tags
|
||||||
|
|
| added to this piece of code. You can customise your text with _Italic_
|
||||||
|## Foo bar baz
|
| ~Strikethrough~ or *Bold*. ~_*Combined*_~ is funny
|
||||||
| bax
|
|
|
||||||
|def Maybe a
|
|
|
||||||
| ## test attached to Just
|
| There are 3 kinds of sections
|
||||||
| def Just val:a
|
| - Important
|
||||||
| def Nothing
|
| - Info
|
||||||
|""".stripMargin
|
| - Example
|
||||||
|
| * You can use example to add multiline code to your documentation
|
||||||
|
|
|
||||||
|
| ! Important
|
||||||
|
| Here is a small test of Important Section
|
||||||
|
|
|
||||||
|
| ? Info
|
||||||
|
| Here is a small test of Info Section
|
||||||
|
|
|
||||||
|
| > Example
|
||||||
|
| Here is a small test of Example Section
|
||||||
|
| Import Foo
|
||||||
|
| def Bar a
|
||||||
|
|type Maybe a
|
||||||
|
| ## test attached to Just
|
||||||
|
| type Just val:a
|
||||||
|
| type Nothing
|
||||||
|
|""".stripMargin
|
||||||
|
val inC =
|
||||||
|
"""
|
||||||
|
|## Optional values.
|
||||||
|
| Type `Option` represents an optional value: every `Option` is either `Some`
|
||||||
|
| and contains a value, or `None`, and does not. Option types are very common
|
||||||
|
| in Enso code, as they have a number of uses:
|
||||||
|
| - Initial values.
|
||||||
|
| - Return values for functions that are not defined over their entire input range (partial functions).
|
||||||
|
| - Return value for otherwise reporting simple errors, where `None` is returned on error.
|
||||||
|
| - Optional struct fields.
|
||||||
|
| - Optional function arguments.
|
||||||
|
| `Option`s are commonly paired with pattern matching to query the presence of
|
||||||
|
| a value and take action, always accounting for the None case.
|
||||||
|
|
|
||||||
|
|type Option a
|
||||||
|
| ## The `None` type indicates a presence of a value.
|
||||||
|
| type Some a
|
||||||
|
|
|
||||||
|
| ##
|
||||||
|
| The `None` type indicates a lack of a value.
|
||||||
|
| It is a very common type and is used by such types as `Maybe` or `List`.
|
||||||
|
| Also, `None` is the return value of functions which do not return an
|
||||||
|
| explicit value.
|
||||||
|
| type None
|
||||||
|
|""".stripMargin
|
||||||
|
|
||||||
println("--- PARSING ---")
|
println("--- PARSING ---")
|
||||||
|
|
||||||
val mod = parser.run(new Reader(inp))
|
val mod = parser.run(new Reader(inC))
|
||||||
|
|
||||||
println(Debug.pretty(mod.toString))
|
println(Debug.pretty(mod.toString))
|
||||||
|
|
||||||
@ -297,18 +339,22 @@ object Main extends App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
println("------")
|
println("------")
|
||||||
println(mod.show() == inp)
|
println(mod.show() == inC)
|
||||||
println("------")
|
println("------")
|
||||||
println(mod.show())
|
println(mod.show())
|
||||||
println("------")
|
println("------")
|
||||||
|
|
||||||
/** Invoking the Enso Documentation Parser */
|
/** Invoking the Enso Documentation Parser */
|
||||||
println("===== DOCUMENTATION =====")
|
println("===== DOCUMENTATION =====")
|
||||||
val isGeneratingHTML = false
|
val droppedMeta = parser.dropMacroMeta(mod)
|
||||||
val droppedMeta = parser.dropMacroMeta(mod)
|
val documentation = DocParserRunner.createDocs(droppedMeta)
|
||||||
val documentation = DocParserRunner.createDocs(droppedMeta)
|
val htmlPath = "target/"
|
||||||
val documentationHTML =
|
val cssFileName = "style.css"
|
||||||
DocParserRunner.generateHTMLForEveryDocumented(documentation)
|
DocParserHTMLGenerator.generateHTMLForEveryDocumented(
|
||||||
|
documentation,
|
||||||
|
htmlPath,
|
||||||
|
cssFileName
|
||||||
|
)
|
||||||
println(Debug.pretty(documentation.toString))
|
println(Debug.pretty(documentation.toString))
|
||||||
println("------")
|
println("------")
|
||||||
println(documentation.show())
|
println(documentation.show())
|
||||||
|
Loading…
Reference in New Issue
Block a user