Add image rendering
This commit is contained in:
parent
7a2b5c1768
commit
21a85b4501
BIN
examples/document/data/loremIpsum/SPC-logo.png
Normal file
BIN
examples/document/data/loremIpsum/SPC-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
type: markdown
|
contentType: markdown
|
||||||
order: 2
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Chapter ${section(1)}
|
## Chapter ${section(1)}
|
||||||
|
@ -4,11 +4,19 @@ authors:
|
|||||||
- name: Alexander Nozik
|
- name: Alexander Nozik
|
||||||
affiliation: MIPT
|
affiliation: MIPT
|
||||||
fragments:
|
fragments:
|
||||||
- name: chapter1
|
- type: image
|
||||||
type: data
|
ref: SPC-logo.png
|
||||||
- name: chapter2
|
meta:
|
||||||
type: data
|
caption: SPC logo
|
||||||
- name: chapter3
|
- type: data
|
||||||
type: data
|
name: chapter1
|
||||||
|
- type: data
|
||||||
|
name: chapter2
|
||||||
|
- type: image
|
||||||
|
ref: SPC-logo.png
|
||||||
|
meta:
|
||||||
|
caption: Another SPC logo
|
||||||
|
- type: data
|
||||||
|
name: chapter3
|
||||||
documentMeta:
|
documentMeta:
|
||||||
metaValue: Hello world!
|
metaValue: Hello world!
|
@ -35,7 +35,6 @@ fun Application.renderAllDocuments() = snarkApplication {
|
|||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
|
||||||
embeddedServer(CIO) {
|
embeddedServer(CIO) {
|
||||||
renderAllDocuments()
|
renderAllDocuments()
|
||||||
}.start(true)
|
}.start(true)
|
||||||
|
@ -6,6 +6,7 @@ import io.ktor.http.ContentType
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.io.readByteArray
|
import kotlinx.io.readByteArray
|
||||||
import space.kscience.dataforge.actions.Action
|
import space.kscience.dataforge.actions.Action
|
||||||
|
import space.kscience.dataforge.actions.mapping
|
||||||
import space.kscience.dataforge.actions.transform
|
import space.kscience.dataforge.actions.transform
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.context.PluginFactory
|
import space.kscience.dataforge.context.PluginFactory
|
||||||
@ -107,6 +108,10 @@ public class SnarkHtml : WorkspacePlugin() {
|
|||||||
|
|
||||||
public val parseAction: Action<Binary, Any> = ParseAction(this)
|
public val parseAction: Action<Binary, Any> = ParseAction(this)
|
||||||
|
|
||||||
|
public val layoutAction: Action<Any, Any> = Action.mapping {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private val allDataNotNull: DataSelector<Any>
|
private val allDataNotNull: DataSelector<Any>
|
||||||
get() = DataSelector { workspace, _ -> workspace.data.filterByType() }
|
get() = DataSelector { workspace, _ -> workspace.data.filterByType() }
|
||||||
|
|
||||||
|
@ -7,14 +7,12 @@ import space.kscience.dataforge.context.info
|
|||||||
import space.kscience.dataforge.context.logger
|
import space.kscience.dataforge.context.logger
|
||||||
import space.kscience.dataforge.context.request
|
import space.kscience.dataforge.context.request
|
||||||
import space.kscience.dataforge.data.*
|
import space.kscience.dataforge.data.*
|
||||||
|
import space.kscience.dataforge.io.Binary
|
||||||
import space.kscience.dataforge.meta.Laminate
|
import space.kscience.dataforge.meta.Laminate
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.meta.string
|
import space.kscience.dataforge.meta.string
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.*
|
||||||
import space.kscience.dataforge.names.cutLast
|
|
||||||
import space.kscience.dataforge.names.endsWith
|
|
||||||
import space.kscience.dataforge.names.parseAsName
|
|
||||||
import space.kscience.snark.SnarkBuilder
|
import space.kscience.snark.SnarkBuilder
|
||||||
import space.kscience.snark.SnarkContext
|
import space.kscience.snark.SnarkContext
|
||||||
import space.kscience.snark.html.*
|
import space.kscience.snark.html.*
|
||||||
@ -26,7 +24,7 @@ import kotlin.reflect.typeOf
|
|||||||
@SnarkBuilder
|
@SnarkBuilder
|
||||||
public interface DocumentBuilder : SnarkContext {
|
public interface DocumentBuilder : SnarkContext {
|
||||||
|
|
||||||
public val documentName: Name
|
public val route: Name
|
||||||
|
|
||||||
public val documentMeta: Meta
|
public val documentMeta: Meta
|
||||||
|
|
||||||
@ -51,7 +49,7 @@ private class PageBasedDocumentBuilder(
|
|||||||
val page: PageContextWithData,
|
val page: PageContextWithData,
|
||||||
private val dataRootName: Name,
|
private val dataRootName: Name,
|
||||||
) : DocumentBuilder {
|
) : DocumentBuilder {
|
||||||
override val documentName: Name get() = page.pageRoute
|
override val route: Name get() = page.pageRoute
|
||||||
override val documentMeta: Meta get() = page.pageMeta
|
override val documentMeta: Meta get() = page.pageMeta
|
||||||
override val data: DataTree<*> = page.data.branch(dataRootName) ?: DataTree.EMPTY
|
override val data: DataTree<*> = page.data.branch(dataRootName) ?: DataTree.EMPTY
|
||||||
|
|
||||||
@ -63,11 +61,10 @@ private class PageBasedDocumentBuilder(
|
|||||||
|
|
||||||
override suspend fun fragment(fragment: DocumentFragment, overrideMeta: Meta?) {
|
override suspend fun fragment(fragment: DocumentFragment, overrideMeta: Meta?) {
|
||||||
when (fragment) {
|
when (fragment) {
|
||||||
|
|
||||||
is ImageDocumentFragment -> fragment {
|
is ImageDocumentFragment -> fragment {
|
||||||
figure("snark-figure") {
|
figure("snark-figure") {
|
||||||
img(classes = "snark-image") {
|
img(classes = "snark-image") {
|
||||||
src = fragment.path
|
src = resolveRef(this@PageBasedDocumentBuilder.route.toWebPath() + "/" + fragment.ref)
|
||||||
alt = fragment.meta["alt"].string ?: ""
|
alt = fragment.meta["alt"].string ?: ""
|
||||||
}
|
}
|
||||||
fragment.meta["caption"].string?.let { caption ->
|
fragment.meta["caption"].string?.let { caption ->
|
||||||
@ -115,53 +112,41 @@ private class PageBasedDocumentBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun SiteContextWithData.document(
|
public fun SiteContextWithData.document(
|
||||||
documentName: Name,
|
|
||||||
documentMeta: Meta = Meta.EMPTY,
|
|
||||||
headers: MetaDataContent.() -> Unit = {},
|
|
||||||
block: suspend DocumentBuilder.() -> Unit,
|
|
||||||
): Unit = page(documentName, documentMeta) {
|
|
||||||
val documentBuilder = runBlocking { PageBasedDocumentBuilder(page, documentName).apply { block() } }
|
|
||||||
head {
|
|
||||||
title(documentMeta["title"].string ?: "Snark document")
|
|
||||||
headers()
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
postprocess(FtlDocumentProcessor(this@document.context, documentBuilder)) {
|
|
||||||
documentBuilder.fragments.forEach {
|
|
||||||
fragment(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun SiteContextWithData.document(
|
|
||||||
route: Name,
|
|
||||||
dataName: Name,
|
dataName: Name,
|
||||||
descriptor: DocumentDescriptor,
|
descriptor: DocumentDescriptor = DocumentDescriptor.empty(),
|
||||||
|
route: Name = dataName,
|
||||||
headers: MetaDataContent.() -> Unit = {},
|
headers: MetaDataContent.() -> Unit = {},
|
||||||
): Unit = page(route, descriptor.documentMeta ?: Meta.EMPTY) {
|
documentBlock: DocumentBuilder.() -> Unit = {},
|
||||||
val documentBuilder = runBlocking {
|
): Unit {
|
||||||
PageBasedDocumentBuilder(page, dataName).apply {
|
siteData.branch(dataName)?.filterByType<Binary>()?.forEach {
|
||||||
descriptor.fragments.forEach {
|
static(route + it.name.last(), it.data)
|
||||||
fragment(it)
|
}
|
||||||
|
page(route, descriptor.documentMeta ?: Meta.EMPTY) {
|
||||||
|
//TODO think about avoiding blocking
|
||||||
|
val documentBuilder = runBlocking {
|
||||||
|
PageBasedDocumentBuilder(page, dataName).apply {
|
||||||
|
descriptor.fragments.forEach {
|
||||||
|
fragment(it)
|
||||||
|
}
|
||||||
|
documentBlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
head {
|
||||||
head {
|
title(descriptor.title ?: "Snark document")
|
||||||
title(descriptor.title ?: "Snark document")
|
headers()
|
||||||
headers()
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
h1("title") { +(descriptor.title ?: dataName.toString()) }
|
|
||||||
descriptor.authors.forEach {
|
|
||||||
div("author") {
|
|
||||||
div("author-name") { +it.name }
|
|
||||||
it.affiliation?.let { affiliation -> div("author-affiliation") { +affiliation } }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
postprocess(FtlDocumentProcessor(this@document.context, documentBuilder)) {
|
body {
|
||||||
documentBuilder.fragments.forEach {
|
h1("title") { +(descriptor.title ?: dataName.toString()) }
|
||||||
fragment(it)
|
descriptor.authors.forEach {
|
||||||
|
div("author") {
|
||||||
|
div("author-name") { +it.name }
|
||||||
|
it.affiliation?.let { affiliation -> div("author-affiliation") { +affiliation } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
postprocess(FtlDocumentProcessor(this@document.context, documentBuilder)) {
|
||||||
|
documentBuilder.fragments.forEach {
|
||||||
|
fragment(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,9 +163,9 @@ public fun SiteContextWithData.allDocuments(
|
|||||||
val route = descriptor.route?.parseAsName(false) ?: directory
|
val route = descriptor.route?.parseAsName(false) ?: directory
|
||||||
context.logger.info { "Loading document $route" }
|
context.logger.info { "Loading document $route" }
|
||||||
document(
|
document(
|
||||||
route = route,
|
|
||||||
dataName = directory,
|
dataName = directory,
|
||||||
descriptor = descriptor,
|
descriptor = descriptor,
|
||||||
|
route = route,
|
||||||
headers = headers
|
headers = headers
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ public class MarkupDocumentFragment(
|
|||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("image")
|
@SerialName("image")
|
||||||
public class ImageDocumentFragment(
|
public class ImageDocumentFragment(
|
||||||
public val path: String,
|
public val ref: String,
|
||||||
override val meta: Meta = Meta.EMPTY,
|
override val meta: Meta = Meta.EMPTY,
|
||||||
) : DocumentFragment
|
) : DocumentFragment
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public class FtlDocumentProcessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val data = mapOf(
|
private val data = mapOf(
|
||||||
"documentName" to document.documentName.toStringUnescaped(),
|
"documentName" to document.route.toStringUnescaped(),
|
||||||
|
|
||||||
"label" to TemplateMethodModelEx { args: List<Any?> ->
|
"label" to TemplateMethodModelEx { args: List<Any?> ->
|
||||||
val counter = args.getOrNull(0)?.toString() ?: "@default"
|
val counter = args.getOrNull(0)?.toString() ?: "@default"
|
||||||
|
@ -42,7 +42,7 @@ public class RegexDocumentProcessor(public val document: DocumentBuilder) : Text
|
|||||||
when (match.groups["function"]?.value) {
|
when (match.groups["function"]?.value) {
|
||||||
|
|
||||||
"documentName" -> {
|
"documentName" -> {
|
||||||
document.documentName.toStringUnescaped()
|
document.route.toStringUnescaped()
|
||||||
}
|
}
|
||||||
|
|
||||||
"label" -> {
|
"label" -> {
|
||||||
@ -77,7 +77,7 @@ public class RegexDocumentProcessor(public val document: DocumentBuilder) : Text
|
|||||||
}.replace(attributeRegex) { match ->
|
}.replace(attributeRegex) { match ->
|
||||||
val uri = URI(match.groups["uri"]!!.value)
|
val uri = URI(match.groups["uri"]!!.value)
|
||||||
val snarkUrl = when (uri.authority) {
|
val snarkUrl = when (uri.authority) {
|
||||||
"documentName" -> document.documentName.toStringUnescaped()
|
"documentName" -> document.route.toStringUnescaped()
|
||||||
// "ref" -> page.resolveRef(uri.path)
|
// "ref" -> page.resolveRef(uri.path)
|
||||||
"meta" -> document.documentMeta[uri.path.parseAsName()].string ?: "@null"
|
"meta" -> document.documentMeta[uri.path.parseAsName()].string ?: "@null"
|
||||||
else -> match.value
|
else -> match.value
|
||||||
|
Loading…
Reference in New Issue
Block a user