Use CommonMark instead of GFM due to conflict with links

This commit is contained in:
Alexander Nozik 2024-09-28 11:48:25 +03:00
parent cc362ca3d7
commit 81f9997618
9 changed files with 114 additions and 66 deletions

View File

@ -25,10 +25,22 @@ Context("Optional context name"){
} }
``` ```
* Get the loaded plugin instance via `context.request(SnarkHtml)` * Get the loaded plugin instance via `val snarkHtml = context.request(SnarkHtml)`
* Use plugin like
```kotlin
val siteData = snarkHtml.readSiteData(context) {
directory(snark.io, Name.EMPTY, dataDirectory)
}
```
## SNARK-html ## SNARK-html
SNARK-HTML module defines tools to work with HTML output format. SNARK-HTML module defines tools to work with HTML output format.
### Postprocessing
${modules} ${modules}

View File

@ -3,18 +3,13 @@ plugins {
application application
} }
application {
mainClass.set("Mainkt")
val isDevelopment: Boolean = project.ext.has("development")
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment", "-Xmx200M")
}
val snarkVersion: String by extra val snarkVersion: String by extra
val ktorVersion = space.kscience.gradle.KScienceVersions.ktorVersion val ktorVersion = space.kscience.gradle.KScienceVersions.ktorVersion
kscience { kscience {
jvm() jvm{
withJava()
}
useContextReceivers() useContextReceivers()
jvmMain { jvmMain {
@ -30,4 +25,11 @@ kscience {
kotlin { kotlin {
explicitApi = org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode.Disabled explicitApi = org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode.Disabled
}
application {
mainClass.set("center.sciprog.snark.documents.Mainkt")
val isDevelopment: Boolean = project.ext.has("development")
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment", "-Xmx200M")
} }

View File

@ -12,6 +12,12 @@ ${documentMeta.get('metaValue')}
Curabitur hendrerit hendrerit rutrum. Nullam elementum libero a nisi viverra aliquet. Sed ut urna a sem bibendum dictum. Cras non elit sit amet ex ultrices iaculis. Fusce lobortis lacinia fermentum. Fusce in metus id massa mollis consequat. Quisque non dolor quis orci gravida vulputate. Vivamus sed pellentesque orci. Sed aliquet malesuada rhoncus. Mauris id aliquet lorem. Curabitur hendrerit hendrerit rutrum. Nullam elementum libero a nisi viverra aliquet. Sed ut urna a sem bibendum dictum. Cras non elit sit amet ex ultrices iaculis. Fusce lobortis lacinia fermentum. Fusce in metus id massa mollis consequat. Quisque non dolor quis orci gravida vulputate. Vivamus sed pellentesque orci. Sed aliquet malesuada rhoncus. Mauris id aliquet lorem.
Paragraph
$$
\int_a^b {f(x)} = const
$$
### Section ${section(2)} ### Section ${section(2)}
Maecenas at iaculis ipsum. Praesent maximus tristique magna eu faucibus. In tincidunt elementum pharetra. Nam scelerisque eros mattis, suscipit odio sit amet, efficitur mi. Etiam eleifend pulvinar erat a aliquet. Cras pellentesque tincidunt mi eget scelerisque. Proin eget ipsum a velit lobortis commodo. Nulla facilisi. Donec id pretium leo. Ut nec tortor sapien. Praesent vehicula dolor ut laoreet commodo. Pellentesque convallis, sapien et placerat luctus, tortor magna sodales sem, non tristique eros sem vel ipsum. Nulla vulputate accumsan nulla. Duis tempor, mi nec pharetra suscipit, sem odio sagittis mi, ut dignissim odio erat a dolor. Maecenas at iaculis ipsum. Praesent maximus tristique magna eu faucibus. In tincidunt elementum pharetra. Nam scelerisque eros mattis, suscipit odio sit amet, efficitur mi. Etiam eleifend pulvinar erat a aliquet. Cras pellentesque tincidunt mi eget scelerisque. Proin eget ipsum a velit lobortis commodo. Nulla facilisi. Donec id pretium leo. Ut nec tortor sapien. Praesent vehicula dolor ut laoreet commodo. Pellentesque convallis, sapien et placerat luctus, tortor magna sodales sem, non tristique eros sem vel ipsum. Nulla vulputate accumsan nulla. Duis tempor, mi nec pharetra suscipit, sem odio sagittis mi, ut dignissim odio erat a dolor.

View File

@ -1,3 +1,5 @@
package center.sciprog.snark.documents
import io.ktor.server.application.Application import io.ktor.server.application.Application
import io.ktor.server.cio.CIO import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer import io.ktor.server.engine.embeddedServer
@ -5,6 +7,7 @@ import kotlinx.html.ScriptCrossorigin
import kotlinx.html.link import kotlinx.html.link
import kotlinx.html.script import kotlinx.html.script
import space.kscience.snark.html.document.allDocuments import space.kscience.snark.html.document.allDocuments
import space.kscience.snark.ktor.snarkApplication
@Suppress("unused") @Suppress("unused")
fun Application.renderAllDocuments() = snarkApplication { fun Application.renderAllDocuments() = snarkApplication {
@ -35,7 +38,5 @@ fun Application.renderAllDocuments() = snarkApplication {
fun main() { fun main() {
embeddedServer(CIO) { embeddedServer(CIO, module = Application::renderAllDocuments).start(true)
renderAllDocuments()
}.start(true)
} }

View File

@ -1,49 +0,0 @@
import io.ktor.server.application.Application
import io.ktor.server.application.log
import io.ktor.server.http.content.staticResources
import io.ktor.server.routing.routing
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.ContextBuilder
import space.kscience.dataforge.context.request
import space.kscience.dataforge.data.forEach
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.workspace.FileData
import space.kscience.dataforge.workspace.directory
import space.kscience.snark.html.HtmlSite
import space.kscience.snark.html.SnarkHtml
import space.kscience.snark.html.readSiteData
import space.kscience.snark.ktor.site
import kotlin.io.path.Path
import kotlin.io.path.exists
fun Application.snarkApplication(contextBuilder: ContextBuilder.() -> Unit = {}, site: HtmlSite) {
val context = Context {
plugin(SnarkHtml)
contextBuilder()
}
val snark = context.request(SnarkHtml)
val dataDirectoryString = environment.config.propertyOrNull("snark.dataDirectory")?.getString() ?: "data"
val dataDirectory = Path(dataDirectoryString)
if (!dataDirectory.exists()) {
error("Data directory at $dataDirectory is not resolved")
}
val siteData = snark.readSiteData(context) {
directory(snark.io, Name.EMPTY, dataDirectory)
}
siteData.forEach { namedData ->
log.debug("Loading data {} from {}", namedData.name, namedData.meta[FileData.FILE_PATH_KEY])
}
routing {
staticResources("/css","css")
site(context, siteData, content = site)
}
}

View File

@ -46,8 +46,8 @@ public class Snark : WorkspacePlugin() {
override fun build(context: Context, meta: Meta): Snark = Snark() override fun build(context: Context, meta: Meta): Snark = Snark()
private val byteArrayIOReader = IOReader { private val byteArrayIOReader: IOReader<ByteArray> = IOReader { source ->
readByteArray() source.readByteArray()
} }
internal val byteArraySnarkParser = SnarkReader(byteArrayIOReader) internal val byteArraySnarkParser = SnarkReader(byteArrayIOReader)

View File

@ -7,6 +7,7 @@ import org.intellij.markdown.MarkdownElementTypes
import org.intellij.markdown.ast.ASTNode import org.intellij.markdown.ast.ASTNode
import org.intellij.markdown.ast.findChildOfType import org.intellij.markdown.ast.findChildOfType
import org.intellij.markdown.ast.getTextInNode import org.intellij.markdown.ast.getTextInNode
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
import org.intellij.markdown.flavours.space.SFMFlavourDescriptor import org.intellij.markdown.flavours.space.SFMFlavourDescriptor
import org.intellij.markdown.html.* import org.intellij.markdown.html.*
@ -60,7 +61,7 @@ private class SnarkImageGeneratingProvider(
} }
} }
public object SnarkFlavorDescriptor : GFMFlavourDescriptor(false) { public object SnarkFlavorDescriptor : CommonMarkFlavourDescriptor(false) {
override fun createHtmlGeneratingProviders(linkMap: LinkMap, baseURI: URI?): Map<IElementType, GeneratingProvider> = override fun createHtmlGeneratingProviders(linkMap: LinkMap, baseURI: URI?): Map<IElementType, GeneratingProvider> =
super.createHtmlGeneratingProviders(linkMap, baseURI) + mapOf( super.createHtmlGeneratingProviders(linkMap, baseURI) + mapOf(
MarkdownElementTypes.INLINE_LINK to SnarkInlineLinkGeneratingProvider(baseURI, absolutizeAnchorLinks) MarkdownElementTypes.INLINE_LINK to SnarkInlineLinkGeneratingProvider(baseURI, absolutizeAnchorLinks)

View File

@ -134,8 +134,8 @@ public class SnarkHtml : WorkspacePlugin() {
override fun build(context: Context, meta: Meta): SnarkHtml = SnarkHtml() override fun build(context: Context, meta: Meta): SnarkHtml = SnarkHtml()
private val byteArrayIOReader = IOReader { private val byteArrayIOReader = IOReader { source->
readByteArray() source.readByteArray()
} }
internal val byteArraySnarkParser = SnarkReader(byteArrayIOReader) internal val byteArraySnarkParser = SnarkReader(byteArrayIOReader)
@ -158,5 +158,6 @@ public fun SnarkHtml.readSiteData(
public fun SnarkHtml.readSiteData( public fun SnarkHtml.readSiteData(
coroutineScope: CoroutineScope, coroutineScope: CoroutineScope,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
//TODO add IO plugin as a context parameter
builder: DataSink<Binary>.() -> Unit, builder: DataSink<Binary>.() -> Unit,
): DataTree<Any> = readSiteData(ObservableDataTree(coroutineScope) { builder() }, meta) ): DataTree<Any> = readSiteData(ObservableDataTree(coroutineScope) { builder() }, meta)

View File

@ -0,0 +1,74 @@
package space.kscience.snark.ktor
import io.ktor.server.application.Application
import io.ktor.server.application.log
import io.ktor.server.http.content.staticResources
import io.ktor.server.routing.Route
import io.ktor.server.routing.application
import io.ktor.server.routing.routing
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.ContextBuilder
import space.kscience.dataforge.context.request
import space.kscience.dataforge.data.forEach
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.workspace.FileData
import space.kscience.dataforge.workspace.directory
import space.kscience.snark.html.HtmlSite
import space.kscience.snark.html.SnarkHtml
import space.kscience.snark.html.readSiteData
import kotlin.io.path.Path
import kotlin.io.path.exists
private fun Application.defaultDataPath() = environment.config
.propertyOrNull("snark.dataDirectory")?.getString() ?: "data"
/**
* Create a snark site at a given route. Uses [dataPath] as a path to data directory.
*
* The default [dataPath] is taken from "snark.dataDirectory" property.
* If not defined, use "data" directory in current work directory.
*/
public fun Route.site(
contextBuilder: ContextBuilder.() -> Unit = {},
dataPath: String = application.defaultDataPath(),
site: HtmlSite,
) {
val context = Context {
plugin(SnarkHtml)
contextBuilder()
}
val snark = context.request(SnarkHtml)
val dataDirectory = Path(dataPath)
if (!dataDirectory.exists()) {
error("Data directory at $dataDirectory is not resolved")
}
val siteData = snark.readSiteData(context) {
directory(snark.io, Name.EMPTY, dataDirectory)
}
siteData.forEach { namedData ->
application.log.debug("Loading data {} from {}", namedData.name, namedData.meta[FileData.FILE_PATH_KEY])
}
staticResources("/css", "css")
site(context, siteData, content = site)
}
/**
* A Ktor module for snark application builder
*/
public fun Application.snarkApplication(
contextBuilder: ContextBuilder.() -> Unit = {},
dataPath: String = defaultDataPath(),
site: HtmlSite,
) {
routing {
site(contextBuilder, dataPath, site)
}
}