Add ktlint plugin

This commit is contained in:
Hubert Van De Walle 2020-10-26 17:21:48 +01:00
parent 7995a0b3e0
commit c709f2b44d
40 changed files with 128 additions and 88 deletions

View File

@ -1,7 +1,7 @@
plugins {
`kotlin-dsl`
kotlin("jvm") version "1.4.10"
id("com.github.johnrengelman.shadow") version "6.1.0"
id("com.github.johnrengelman.shadow") version "6.1.0" apply false
}
repositories {
@ -12,4 +12,5 @@ repositories {
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10")
implementation("com.github.jengelman.gradle.plugins:shadow:6.1.0")
implementation("org.jlleitschuh.gradle:ktlint-gradle:9.4.1")
}

View File

@ -6,6 +6,7 @@ plugins {
java
kotlin("jvm")
`java-library`
id("org.jlleitschuh.gradle.ktlint")
}
repositories {
@ -21,6 +22,7 @@ version = "1.0-SNAPSHOT"
dependencies {
implementation(kotlin("stdlib-jdk8"))
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.4.10"))
}
tasks.withType<Test> {

View File

@ -2,10 +2,10 @@ package be.simplenotes.app.api
import be.simplenotes.app.extensions.auto
import be.simplenotes.app.utils.parseSearchTerms
import be.simplenotes.types.PersistedNote
import be.simplenotes.types.PersistedNoteMetadata
import be.simplenotes.domain.usecases.NoteService
import be.simplenotes.types.LoggedInUser
import be.simplenotes.types.PersistedNote
import be.simplenotes.types.PersistedNoteMetadata
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
@ -28,7 +28,7 @@ class ApiNoteController(private val noteService: NoteService, private val json:
)
}
fun notes(request: Request, loggedInUser: LoggedInUser): Response {
fun notes(@Suppress("UNUSED_PARAMETER") request: Request, loggedInUser: LoggedInUser): Response {
val notes = noteService.paginatedNotes(loggedInUser.userId, page = 1).notes
return persistedNotesMetadataLens(notes, Response(OK))
}
@ -40,12 +40,15 @@ class ApiNoteController(private val noteService: NoteService, private val json:
fun update(request: Request, loggedInUser: LoggedInUser): Response {
val content = noteContentLens(request)
return noteService.update(loggedInUser.userId, uuidLens(request), content).fold({
Response(BAD_REQUEST)
}, {
if (it == null) Response(NOT_FOUND)
else Response(OK)
})
return noteService.update(loggedInUser.userId, uuidLens(request), content).fold(
{
Response(BAD_REQUEST)
},
{
if (it == null) Response(NOT_FOUND)
else Response(OK)
}
)
}
fun search(request: Request, loggedInUser: LoggedInUser): Response {
@ -61,7 +64,6 @@ class ApiNoteController(private val noteService: NoteService, private val json:
private val persistedNotesMetadataLens = json.auto<List<PersistedNoteMetadata>>().toLens()
private val persistedNoteLens = json.auto<PersistedNote>().toLens()
private val uuidLens = Path.uuid().of("uuid")
}
@Serializable

View File

@ -7,6 +7,6 @@ import org.http4k.core.Status.Companion.OK
import org.http4k.core.Status.Companion.SERVICE_UNAVAILABLE
class HealthCheckController(private val dbHealthCheck: DbHealthCheck) {
fun healthCheck(request: Request) =
fun healthCheck(@Suppress("UNUSED_PARAMETER") request: Request) =
if (dbHealthCheck.isOk()) Response(OK) else Response(SERVICE_UNAVAILABLE)
}

View File

@ -3,12 +3,12 @@ package be.simplenotes.app.controllers
import be.simplenotes.app.extensions.html
import be.simplenotes.app.extensions.redirect
import be.simplenotes.app.utils.parseSearchTerms
import be.simplenotes.views.NoteView
import be.simplenotes.domain.usecases.NoteService
import be.simplenotes.domain.usecases.markdown.InvalidMeta
import be.simplenotes.domain.usecases.markdown.MissingMeta
import be.simplenotes.domain.usecases.markdown.ValidationError
import be.simplenotes.types.LoggedInUser
import be.simplenotes.views.NoteView
import org.http4k.core.Method
import org.http4k.core.Request
import org.http4k.core.Response
@ -33,8 +33,16 @@ class NoteController(
return noteService.create(loggedInUser.userId, markdownForm).fold(
{
val html = when (it) {
MissingMeta -> view.noteEditor(loggedInUser, error = "Missing note metadata", textarea = markdownForm)
InvalidMeta -> view.noteEditor(loggedInUser, error = "Invalid note metadata", textarea = markdownForm)
MissingMeta -> view.noteEditor(
loggedInUser,
error = "Missing note metadata",
textarea = markdownForm
)
InvalidMeta -> view.noteEditor(
loggedInUser,
error = "Invalid note metadata",
textarea = markdownForm
)
is ValidationError -> view.noteEditor(
loggedInUser,
validationErrors = it.validationErrors,
@ -105,8 +113,16 @@ class NoteController(
return noteService.update(loggedInUser.userId, note.uuid, markdownForm).fold(
{
val html = when (it) {
MissingMeta -> view.noteEditor(loggedInUser, error = "Missing note metadata", textarea = markdownForm)
InvalidMeta -> view.noteEditor(loggedInUser, error = "Invalid note metadata", textarea = markdownForm)
MissingMeta -> view.noteEditor(
loggedInUser,
error = "Missing note metadata",
textarea = markdownForm
)
InvalidMeta -> view.noteEditor(
loggedInUser,
error = "Invalid note metadata",
textarea = markdownForm
)
is ValidationError -> view.noteEditor(
loggedInUser,
validationErrors = it.validationErrors,

View File

@ -2,11 +2,11 @@ package be.simplenotes.app.controllers
import be.simplenotes.app.extensions.html
import be.simplenotes.app.extensions.redirect
import be.simplenotes.views.SettingView
import be.simplenotes.domain.usecases.UserService
import be.simplenotes.domain.usecases.users.delete.DeleteError
import be.simplenotes.domain.usecases.users.delete.DeleteForm
import be.simplenotes.types.LoggedInUser
import be.simplenotes.views.SettingView
import org.http4k.core.*
import org.http4k.core.body.form
import org.http4k.core.cookie.invalidateCookie
@ -67,7 +67,10 @@ class SettingsController(
Response(Status.OK)
.with(attachment("$filename.json", "application/json"))
.body(userService.exportAsJson(loggedInUser.userId))
} else Response(Status.OK).body(userService.exportAsJson(loggedInUser.userId)).header("Content-Type", "application/json")
} else Response(Status.OK).body(userService.exportAsJson(loggedInUser.userId)).header(
"Content-Type",
"application/json"
)
}
private fun Request.deleteForm(loggedInUser: LoggedInUser) =

View File

@ -3,14 +3,14 @@ package be.simplenotes.app.controllers
import be.simplenotes.app.extensions.html
import be.simplenotes.app.extensions.isSecure
import be.simplenotes.app.extensions.redirect
import be.simplenotes.views.UserView
import be.simplenotes.config.JwtConfig
import be.simplenotes.domain.usecases.UserService
import be.simplenotes.domain.usecases.users.login.*
import be.simplenotes.domain.usecases.users.register.InvalidRegisterForm
import be.simplenotes.domain.usecases.users.register.RegisterForm
import be.simplenotes.domain.usecases.users.register.UserExists
import be.simplenotes.config.JwtConfig
import be.simplenotes.types.LoggedInUser
import be.simplenotes.views.UserView
import org.http4k.core.Method.GET
import org.http4k.core.Request
import org.http4k.core.Response

View File

@ -23,7 +23,8 @@ fun Request.isSecure() = header("X-Forwarded-Proto")?.contains("https") ?: false
val bodyLens = httpBodyRoot(
listOf(Meta(true, "body", ParamMeta.ObjectParam, "body")),
ContentType.APPLICATION_JSON.withNoDirectives(), ContentNegotiation.StrictNoDirective
ContentType.APPLICATION_JSON.withNoDirectives(),
ContentNegotiation.StrictNoDirective
).map(
{ it.payload.asString() },
{ Body(it) }

View File

@ -25,7 +25,7 @@ class AuthFilter(
JwtSource.Header -> it.bearerTokenHeader()
JwtSource.Cookie -> it.bearerTokenCookie()
}
val jwtPayload = token?.let { token -> extractor(token) }
val jwtPayload = token?.let { extractor(token) }
when {
jwtPayload != null -> {
ctx[it][authKey] = jwtPayload

View File

@ -12,9 +12,12 @@ import org.http4k.servlet.asServlet
class Jetty(private val port: Int, private val server: Server) : ServerConfig {
constructor(port: Int = 8000) : this(port, http(port))
constructor(port: Int, vararg inConnectors: ConnectorBuilder) : this(port, Server().apply {
inConnectors.forEach { addConnector(it(this)) }
})
constructor(port: Int, vararg inConnectors: ConnectorBuilder) : this(
port,
Server().apply {
inConnectors.forEach { addConnector(it(this)) }
}
)
override fun toServer(httpHandler: HttpHandler): Http4kServer {
server.insertHandler(httpHandler.toJettyHandler())

View File

@ -10,7 +10,6 @@ import be.simplenotes.app.jetty.Jetty
import be.simplenotes.app.routes.Router
import be.simplenotes.app.utils.StaticFileResolver
import be.simplenotes.app.utils.StaticFileResolverImpl
import be.simplenotes.views.ErrorView
import be.simplenotes.config.ServerConfig
import org.eclipse.jetty.server.ServerConnector
import org.http4k.core.Filter

View File

@ -10,7 +10,7 @@ import java.util.*
internal class UuidSerializer : KSerializer<UUID> {
override val descriptor: SerialDescriptor
get() = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING)
get() = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: UUID) {
encoder.encodeString(value.toString())

View File

@ -1,8 +1,8 @@
package be.simplenotes.app.filters
import be.simplenotes.config.JwtConfig
import be.simplenotes.domain.security.JwtPayloadExtractor
import be.simplenotes.domain.security.SimpleJwt
import be.simplenotes.config.JwtConfig
import be.simplenotes.types.LoggedInUser
import com.natpryce.hamkrest.assertion.assertThat
import org.http4k.core.*

View File

@ -30,7 +30,9 @@ internal class SearchTermsParserKtTest {
createResult("tag:'example' title:'other' end", title = "other", tag = "example", all = "end"),
createResult(
"tag:'example abc' title:'other with words' this is the end ",
title = "other with words", tag = "example abc", all = "this is the end"
title = "other with words",
tag = "example abc",
all = "this is the end"
),
)

View File

@ -1,7 +1,7 @@
package be.simplenotes.domain.usecases.export
import be.simplenotes.types.ExportedNote
import be.simplenotes.persistance.repositories.NoteRepository
import be.simplenotes.types.ExportedNote
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry
@ -31,7 +31,6 @@ internal class ExportUseCaseImpl(private val noteRepository: NoteRepository, pri
}
}
class ZipOutput : AutoCloseable {
val outputStream = ByteArrayOutputStream()
private val zipOutputStream = ZipArchiveOutputStream(outputStream)

View File

@ -12,14 +12,15 @@ internal class DeleteUseCaseImpl(
private val userRepository: UserRepository,
private val passwordHash: PasswordHash,
private val searcher: NoteSearcher,
) : DeleteUseCase {
) : DeleteUseCase {
override fun delete(form: DeleteForm) = either.eager<DeleteError, Unit> {
val user = !UserValidations.validateDelete(form)
val persistedUser = !userRepository.find(user.username).rightIfNotNull { DeleteError.Unregistered }
!Either.conditionally(
passwordHash.verify(user.password, persistedUser.password),
{ DeleteError.WrongPassword },
{ Unit })
{ Unit }
)
!Either.conditionally(userRepository.delete(persistedUser.id), { DeleteError.Unregistered }, { Unit })
searcher.dropIndex(persistedUser.id)
}

View File

@ -3,10 +3,10 @@ package be.simplenotes.domain.usecases.users.register
import arrow.core.Either
import arrow.core.filterOrElse
import arrow.core.leftIfNull
import be.simplenotes.types.PersistedUser
import be.simplenotes.domain.security.PasswordHash
import be.simplenotes.domain.validation.UserValidations
import be.simplenotes.persistance.repositories.UserRepository
import be.simplenotes.types.PersistedUser
internal class RegisterUseCaseImpl(
private val userRepository: UserRepository,

View File

@ -1,8 +1,8 @@
package be.simplenotes.domain.usecases.users.register
import arrow.core.Either
import be.simplenotes.types.PersistedUser
import be.simplenotes.domain.usecases.users.login.LoginForm
import be.simplenotes.types.PersistedUser
import io.konform.validation.ValidationErrors
sealed class RegisterError

View File

@ -3,13 +3,13 @@ package be.simplenotes.domain.validation
import arrow.core.Either
import arrow.core.left
import arrow.core.right
import be.simplenotes.types.User
import be.simplenotes.domain.usecases.users.delete.DeleteError
import be.simplenotes.domain.usecases.users.delete.DeleteForm
import be.simplenotes.domain.usecases.users.login.InvalidLoginForm
import be.simplenotes.domain.usecases.users.login.LoginForm
import be.simplenotes.domain.usecases.users.register.InvalidRegisterForm
import be.simplenotes.domain.usecases.users.register.RegisterForm
import be.simplenotes.types.User
import io.konform.validation.Validation
import io.konform.validation.jsonschema.maxLength
import io.konform.validation.jsonschema.minLength

View File

@ -1,7 +1,7 @@
package be.simplenotes.domain.security
import be.simplenotes.domain.usecases.users.login.Token
import be.simplenotes.config.JwtConfig
import be.simplenotes.domain.usecases.users.login.Token
import be.simplenotes.types.LoggedInUser
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm

View File

@ -1,12 +1,12 @@
package be.simplenotes.domain.usecases.users.login
import be.simplenotes.types.PersistedUser
import be.simplenotes.config.JwtConfig
import be.simplenotes.domain.security.BcryptPasswordHash
import be.simplenotes.domain.security.SimpleJwt
import be.simplenotes.persistance.repositories.UserRepository
import be.simplenotes.config.JwtConfig
import be.simplenotes.domain.testutils.isLeftOfType
import be.simplenotes.domain.testutils.isRight
import be.simplenotes.persistance.repositories.UserRepository
import be.simplenotes.types.PersistedUser
import com.natpryce.hamkrest.assertion.assertThat
import io.mockk.*
import org.junit.jupiter.api.BeforeEach

View File

@ -1,10 +1,10 @@
package be.simplenotes.domain.usecases.users.register
import be.simplenotes.types.PersistedUser
import be.simplenotes.domain.security.BcryptPasswordHash
import be.simplenotes.domain.testutils.isLeftOfType
import be.simplenotes.domain.testutils.isRight
import be.simplenotes.persistance.repositories.UserRepository
import be.simplenotes.types.PersistedUser
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import io.mockk.*

View File

@ -1,8 +1,8 @@
package be.simplenotes.persistance
import be.simplenotes.config.DataSourceConfig
import be.simplenotes.persistance.utils.DbType
import be.simplenotes.persistance.utils.type
import be.simplenotes.config.DataSourceConfig
import me.liuwj.ktorm.database.Database
import me.liuwj.ktorm.database.asIterable
import me.liuwj.ktorm.database.use

View File

@ -1,8 +1,8 @@
package be.simplenotes.persistance
import be.simplenotes.config.DataSourceConfig
import be.simplenotes.persistance.utils.DbType
import be.simplenotes.persistance.utils.type
import be.simplenotes.config.DataSourceConfig
import org.flywaydb.core.Flyway
import javax.sql.DataSource

View File

@ -10,7 +10,6 @@ import org.mapstruct.ReportingPolicy
import java.time.LocalDateTime
import java.util.*
/**
* This is an abstract class because kotlin default methods in interface are not seen as default in kapt
* @see [KT-25960](https://youtrack.jetbrains.com/issue/KT-25960)
@ -35,7 +34,11 @@ internal abstract class NoteConverter {
fun toPersistedNote(entity: NoteEntity, tags: Tags) = PersistedNote(
NoteMetadata(title = entity.title, tags = tags),
entity.markdown, entity.html, entity.updatedAt, entity.uuid, entity.public
entity.markdown,
entity.html,
entity.updatedAt,
entity.uuid,
entity.public
)
@Mappings(
@ -46,15 +49,15 @@ internal abstract class NoteConverter {
abstract fun toExportedNote(entity: NoteEntity, tags: Tags): ExportedNote
fun toEntity(note: Note, uuid: UUID, userId: Int, updatedAt: LocalDateTime) = NoteEntity {
this.title = note.meta.title
this.markdown = note.markdown
this.html = note.html
this.uuid = uuid
this.deleted = false
this.public = false
this.user.id = userId
this.updatedAt = updatedAt
}
this.title = note.meta.title
this.markdown = note.markdown
this.html = note.html
this.uuid = uuid
this.deleted = false
this.public = false
this.user.id = userId
this.updatedAt = updatedAt
}
@Mappings(
Mapping(target = ".", source = "note"),
@ -73,7 +76,6 @@ internal abstract class NoteConverter {
@Mapping(target = "deleted", source = "trash")
abstract fun toEntity(exportedNote: ExportedNote): NoteEntity
}
typealias Tags = List<String>

View File

@ -1,11 +1,11 @@
package be.simplenotes.persistance.notes
import be.simplenotes.persistance.converters.NoteConverter
import be.simplenotes.persistance.repositories.NoteRepository
import be.simplenotes.types.ExportedNote
import be.simplenotes.types.Note
import be.simplenotes.types.PersistedNote
import be.simplenotes.types.PersistedNoteMetadata
import be.simplenotes.persistance.converters.NoteConverter
import be.simplenotes.persistance.repositories.NoteRepository
import me.liuwj.ktorm.database.Database
import me.liuwj.ktorm.dsl.*
import me.liuwj.ktorm.entity.*
@ -211,5 +211,4 @@ internal class NoteRepositoryImpl(private val db: Database, private val converte
.filter { it.noteUuid inList map { note -> note.uuid } }
.groupByTo(HashMap(), { it.note.uuid }, { it.name })
}
}

View File

@ -1,9 +1,9 @@
package be.simplenotes.persistance.users
import be.simplenotes.types.PersistedUser
import be.simplenotes.types.User
import be.simplenotes.persistance.converters.UserConverter
import be.simplenotes.persistance.repositories.UserRepository
import be.simplenotes.types.PersistedUser
import be.simplenotes.types.User
import me.liuwj.ktorm.database.Database
import me.liuwj.ktorm.dsl.*
import me.liuwj.ktorm.entity.any

View File

@ -26,10 +26,14 @@ internal class NoteConverterTest {
}
val tags = listOf("a", "b")
val note = converter.toNote(entity, tags)
val expectedNote = Note(NoteMetadata(
title = "title",
tags = tags,
), markdown = "md", html = "html")
val expectedNote = Note(
NoteMetadata(
title = "title",
tags = tags,
),
markdown = "md",
html = "html"
)
assertThat(note).isEqualTo(expectedNote)
}
@ -77,7 +81,6 @@ internal class NoteConverterTest {
)
assertThat(note).isEqualTo(expectedNote)
}
}
@Nested
@ -162,7 +165,5 @@ internal class NoteConverterTest {
.hasFieldOrPropertyWithValue("updatedAt", exportedNote.updatedAt)
.hasFieldOrPropertyWithValue("deleted", true)
}
}
}

View File

@ -1,8 +1,8 @@
package be.simplenotes.persistance.converters
import be.simplenotes.persistance.users.UserEntity
import be.simplenotes.types.PersistedUser
import be.simplenotes.types.User
import be.simplenotes.persistance.users.UserEntity
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.mapstruct.factory.Mappers

View File

@ -1,14 +1,13 @@
package be.simplenotes.persistance.notes
import be.simplenotes.config.DataSourceConfig
import be.simplenotes.persistance.DbMigrations
import be.simplenotes.persistance.converters.NoteConverter
import be.simplenotes.persistance.migrationModule
import be.simplenotes.persistance.persistanceModule
import be.simplenotes.config.DataSourceConfig
import be.simplenotes.persistance.repositories.NoteRepository
import be.simplenotes.persistance.repositories.UserRepository
import be.simplenotes.types.*
import be.simplenotes.types.*
import me.liuwj.ktorm.database.Database
import me.liuwj.ktorm.dsl.eq
import me.liuwj.ktorm.entity.filter

View File

@ -1,11 +1,11 @@
package be.simplenotes.persistance.users
import be.simplenotes.types.User
import be.simplenotes.persistance.repositories.UserRepository
import be.simplenotes.config.DataSourceConfig
import be.simplenotes.persistance.DbMigrations
import be.simplenotes.persistance.migrationModule
import be.simplenotes.persistance.persistanceModule
import be.simplenotes.config.DataSourceConfig
import be.simplenotes.persistance.repositories.UserRepository
import be.simplenotes.types.User
import me.liuwj.ktorm.database.*
import me.liuwj.ktorm.dsl.*
import me.liuwj.ktorm.entity.*

View File

@ -1,7 +1,7 @@
package be.simplenotes.search
import be.simplenotes.types.PersistedNote
import be.simplenotes.search.utils.rmdir
import be.simplenotes.types.PersistedNote
import org.apache.lucene.analysis.standard.StandardAnalyzer
import org.apache.lucene.document.Document
import org.apache.lucene.index.*

View File

@ -24,12 +24,14 @@ internal class NoteSearcherImplTest {
content: String = "",
uuid: UUID = UUID.randomUUID(),
): PersistedNote {
val note = PersistedNote(NoteMetadata(title, tags),
val note = PersistedNote(
NoteMetadata(title, tags),
markdown = content,
html = "",
LocalDateTime.MIN,
uuid,
public = false)
public = false
)
searcher.indexNote(1, note)
return note
}

View File

@ -1,7 +1,6 @@
package be.simplenotes.views
import be.simplenotes.types.LoggedInUser
import be.simplenotes.views.components.noteListHeader
import be.simplenotes.types.PersistedNote
import be.simplenotes.types.PersistedNoteMetadata
import be.simplenotes.views.components.*
@ -38,7 +37,9 @@ class NoteView(styles: String) : View(styles) {
|tags: []
|---
|
""".trimMargin("|")
""".trimMargin(
"|"
)
}
submitButton("Save")
}
@ -128,7 +129,7 @@ class NoteView(styles: String) : View(styles) {
+"You are viewing a public note "
}
hr { }
hr { }
}
div("flex items-center justify-between mb-4") {
@ -151,7 +152,7 @@ class NoteView(styles: String) : View(styles) {
+"/notes/public/${note.uuid}"
}
}
hr { }
hr { }
}
}
@ -182,8 +183,9 @@ class NoteView(styles: String) : View(styles) {
button(
type = ButtonType.submit,
name = if (note.public) "private" else "public",
classes = "font-semibold border-b-4 ${if (!note.public) "border-teal-200" else "border-green-500"}" +
" p-2 rounded-r bg-teal-200 text-gray-800"
classes = "font-semibold border-b-4 " +
if (!note.public) "border-teal-200" else "border-green-500" +
" p-2 rounded-r bg-teal-200 text-gray-800"
) {
+"Public"
}

View File

@ -28,9 +28,11 @@ class SettingView(styles: String) : View(styles) {
section("m-4 p-2 bg-gray-800 rounded flex flex-wrap justify-around items-end") {
form(classes = "m-2", method = FormMethod.post, action = "/export") {
button(name = "display",
button(
name = "display",
classes = "inline btn btn-teal block",
type = submit) { +"Display my data" }
type = submit
) { +"Display my data" }
}
form(classes = "m-2", method = FormMethod.post, action = "/export") {

View File

@ -22,7 +22,7 @@ abstract class View(private val styles: String) {
meta(name = "viewport", content = "width=device-width, initial-scale=1")
title("$title - SimpleNotes")
description?.let { meta(name = "description", content = it) }
link(rel = "preload", href = "/recursive-0.0.1.woff2"){
link(rel = "preload", href = "/recursive-0.0.1.woff2") {
attributes["as"] = "font"
attributes["type"] = "font/woff2"
attributes["crossorigin"] = "anonymous"

View File

@ -4,7 +4,9 @@ import kotlinx.html.*
internal class SUMMARY(consumer: TagConsumer<*>) :
HTMLTag(
"summary", consumer, emptyMap(),
"summary",
consumer,
emptyMap(),
inlineTag = true,
emptyTag = false
),

View File

@ -7,4 +7,6 @@ import java.util.*
private val prettyTime = PrettyTime()
internal fun LocalDateTime.toTimeAgo(): String = prettyTime.format(Date.from(atZone(ZoneId.systemDefault()).toInstant()))
internal fun LocalDateTime.toTimeAgo(): String = prettyTime.format(
Date.from(atZone(ZoneId.systemDefault()).toInstant())
)