diff --git a/documentation/_includes/html_include_from_includes_dir.html b/documentation/_includes/html_include_from_includes_dir.html new file mode 100644 index 0000000..b4588d8 --- /dev/null +++ b/documentation/_includes/html_include_from_includes_dir.html @@ -0,0 +1,7 @@ +

File, I am your HTML include

+ +html html html html html html html + +html html html html html html html + +
diff --git a/documentation/_includes/md_include_from_includes_dir.md b/documentation/_includes/md_include_from_includes_dir.md new file mode 100644 index 0000000..5debf2b --- /dev/null +++ b/documentation/_includes/md_include_from_includes_dir.md @@ -0,0 +1,7 @@ +### File, I am your MD include + +md md md md md md md md md md md md + +md md md md md md md md md md md md + + --- diff --git a/documentation/docs/static-page/includes_html.html b/documentation/docs/static-page/includes_html.html new file mode 100644 index 0000000..3557190 --- /dev/null +++ b/documentation/docs/static-page/includes_html.html @@ -0,0 +1,7 @@ +--- +title: Includes HTML +--- + +{% myinclude md_include_from_includes_dir.md %} + +{% myinclude html_include_from_includes_dir.html %} diff --git a/documentation/docs/static-page/includes_md.md b/documentation/docs/static-page/includes_md.md new file mode 100644 index 0000000..86b1386 --- /dev/null +++ b/documentation/docs/static-page/includes_md.md @@ -0,0 +1,7 @@ +--- +title: Includes MD +--- + +{% myinclude md_include_from_includes_dir.md %} + +{% myinclude html_include_from_includes_dir.html %} diff --git a/src/main/kotlin/com/virtuslab/dokka/site/StaticSiteContext.kt b/src/main/kotlin/com/virtuslab/dokka/site/StaticSiteContext.kt index 1fcdc92..d0d5dd6 100644 --- a/src/main/kotlin/com/virtuslab/dokka/site/StaticSiteContext.kt +++ b/src/main/kotlin/com/virtuslab/dokka/site/StaticSiteContext.kt @@ -32,6 +32,11 @@ class StaticSiteContext(val root: File, cxt: DokkaContext) { dirs.map { loadTemplateFile(it) }.map { it.name() to it }.toMap() } + private val includes: Map by lazy { + val includeRoot = File(root, "_includes") + val dirs: Array = includeRoot.listFiles() ?: emptyArray() + dirs.map { loadTemplateFile(it) }.map { it.file.name to it.rawCode }.toMap() + } private fun isValidTemplate(file: File): Boolean = (file.isDirectory && !file.name.startsWith("_")) || @@ -124,7 +129,13 @@ class StaticSiteContext(val root: File, cxt: DokkaContext) { val properties = myTemplate.templateFile.layout() ?.let { mapOf("content" to myTemplate.templateFile.rawCode) } ?: emptyMap() - myTemplate.templateFile.resolveMarkdown(RenderingContext(properties, layouts)) + val ctx = RenderingContext( + properties = properties, + layouts = layouts, + includes = includes + ) + + myTemplate.templateFile.resolveMarkdown(ctx) } catch (e: Throwable) { val msg = "Error rendering $myTemplate: ${e.message}" println("ERROR: $msg") // TODO (#14): provide proper error handling diff --git a/src/main/kotlin/com/virtuslab/dokka/site/templates.kt b/src/main/kotlin/com/virtuslab/dokka/site/templates.kt index 397fefb..944bffa 100644 --- a/src/main/kotlin/com/virtuslab/dokka/site/templates.kt +++ b/src/main/kotlin/com/virtuslab/dokka/site/templates.kt @@ -14,6 +14,9 @@ import com.vladsch.flexmark.parser.ParserEmulationProfile import com.vladsch.flexmark.util.options.DataHolder import com.vladsch.flexmark.util.options.MutableDataSet import liqp.Template +import liqp.TemplateContext +import liqp.nodes.LNode +import liqp.tags.Tag import java.io.File import java.util.* @@ -38,6 +41,7 @@ val defaultMarkdownOptions: DataHolder = data class RenderingContext( val properties: Map, + val includes: Map = emptyMap(), val layouts: Map = emptyMap(), val resolving: Set = emptySet(), val markdownOptions: DataHolder = defaultMarkdownOptions, @@ -105,12 +109,14 @@ data class TemplateFile( fun hasFrame(): Boolean = stringSetting("hasFrame") != "false" - fun resolveMarkdown(ctx: RenderingContext): PreResolvedPage = - resolveInner( - ctx = ctx.copy(properties = HashMap(ctx.properties) + ("page" to mapOf("title" to title()))), + fun resolveMarkdown(ctx: RenderingContext): PreResolvedPage { + val properties = HashMap(ctx.properties) + ("page" to mapOf("title" to title())) + HashMap(ctx.includes) + return resolveInner( + ctx = ctx.copy(properties = properties), stopAtHtml = true, !isHtml // This is toplevel template ) + } fun resolveToHtml(ctx: RenderingContext, hasMarkdown: Boolean): PreResolvedPage = resolveInner(ctx, stopAtHtml = false, hasMarkdown) @@ -130,6 +136,7 @@ data class TemplateFile( return if (stopAtHtml && isHtml) { PreResolvedPage(ctx.properties["content"].toString(), LayoutInfo(this, ctx), hasMarkdown) } else { + Tag.registerTag(MyInclude()) val rendered = Template.parse(this.rawCode).render(HashMap(ctx.properties)) // Library requires mutable maps.. val code = if (!isHtml) rendered else { @@ -166,8 +173,23 @@ fun loadTemplateFile(file: File): TemplateFile { return TemplateFile( file = file, - file.name.endsWith(".html"), + isHtml = file.name.endsWith(".html"), rawCode = content.joinToString(LineSeparator), settings = yamlCollector.data ) } + + +class MyInclude : Tag() { + override fun render(context: TemplateContext, vararg nodes: LNode): Any = try { + if (nodes.size > 1) { + println("ERROR: Multiple include nodes") // TODO (#14): provide proper error handling + } + nodes[0].render(context) + val includeResource = super.asString(context.get(nodes[0].toString())) + Template.parse(includeResource, context.flavor).render(context.variables) + } catch (e: Exception) { + println("ERROR: include rendering failure: $e") // TODO (#14): provide proper error handling + "" + } +}