Skip to content

Commit

Permalink
Add TextTransform and .text
Browse files Browse the repository at this point in the history
  • Loading branch information
iamgio committed Jul 7, 2024
1 parent ebe2108 commit 48d2753
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package eu.iamgio.quarkdown.ast.quarkdown

import eu.iamgio.quarkdown.ast.NestableNode
import eu.iamgio.quarkdown.ast.Node
import eu.iamgio.quarkdown.rendering.representable.RenderRepresentable
import eu.iamgio.quarkdown.rendering.representable.RenderRepresentableVisitor
import eu.iamgio.quarkdown.visitor.node.NodeVisitor

/**
* Text transformation a portion of text can undergo.
* If a property is set to `null` it is not specified, hence ignored.
* @param size font size
* @param weight font weight
* @param style font style
* @param decoration text decoration
* @param case text case
* @param variant font variant
*/
class TextTransformData(
val size: Size? = null,
val weight: Weight? = null,
val style: Style? = null,
val decoration: Decoration? = null,
val case: Case? = null,
val variant: Variant? = null,
) {
enum class Size : RenderRepresentable {
TINY,
SMALL,
NORMAL,
MEDIUM,
LARGE,
;

override fun <T> accept(visitor: RenderRepresentableVisitor<T>): T = visitor.visit(this)
}

enum class Weight : RenderRepresentable {
NORMAL,
BOLD,
;

override fun <T> accept(visitor: RenderRepresentableVisitor<T>): T = visitor.visit(this)
}

enum class Style : RenderRepresentable {
NORMAL,
ITALIC,
;

override fun <T> accept(visitor: RenderRepresentableVisitor<T>): T = visitor.visit(this)
}

enum class Decoration : RenderRepresentable {
NONE,
UNDERLINE,
STRIKETHROUGH,
;

override fun <T> accept(visitor: RenderRepresentableVisitor<T>): T = visitor.visit(this)
}

enum class Case : RenderRepresentable {
NONE,
UPPERCASE,
LOWERCASE,
CAPITALIZE,
;

override fun <T> accept(visitor: RenderRepresentableVisitor<T>): T = visitor.visit(this)
}

enum class Variant : RenderRepresentable {
NORMAL,
SMALL_CAPS,
;

override fun <T> accept(visitor: RenderRepresentableVisitor<T>): T = visitor.visit(this)
}
}

/**
* A portion of text with a specific visual transformation.
* @param data transformation the text undergoes
*/
data class TextTransform(
val data: TextTransformData,
override val children: List<Node>,
) : NestableNode {
override fun <T> accept(visitor: NodeVisitor<T>): T = visitor.visit(this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import eu.iamgio.quarkdown.ast.quarkdown.PageCounterInitializer
import eu.iamgio.quarkdown.ast.quarkdown.PageMarginContentInitializer
import eu.iamgio.quarkdown.ast.quarkdown.SlidesConfigurationInitializer
import eu.iamgio.quarkdown.ast.quarkdown.Stacked
import eu.iamgio.quarkdown.ast.quarkdown.TextTransform
import eu.iamgio.quarkdown.context.Context
import eu.iamgio.quarkdown.context.resolveOrFallback
import eu.iamgio.quarkdown.rendering.UnsupportedRenderException
Expand Down Expand Up @@ -246,4 +247,6 @@ open class BaseHtmlNodeRenderer(context: Context) : TagNodeRenderer<HtmlTagBuild
override fun visit(node: SlidesConfigurationInitializer): CharSequence = throw UnsupportedRenderException(node)

override fun visit(node: MathSpan): CharSequence = throw UnsupportedRenderException(node)

override fun visit(node: TextTransform): CharSequence = throw UnsupportedRenderException(node)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package eu.iamgio.quarkdown.rendering.html

import eu.iamgio.quarkdown.ast.quarkdown.Clipped
import eu.iamgio.quarkdown.ast.quarkdown.Stacked
import eu.iamgio.quarkdown.ast.quarkdown.TextTransformData
import eu.iamgio.quarkdown.document.page.PageMarginPosition
import eu.iamgio.quarkdown.document.page.Size
import eu.iamgio.quarkdown.document.page.Sizes
Expand Down Expand Up @@ -50,6 +51,25 @@ class CssRepresentableVisitor : RenderRepresentableVisitor<String> {
override fun visit(transition: Transition.Style) = transition.kebabCaseName

override fun visit(speed: Transition.Speed) = speed.kebabCaseName

override fun visit(size: TextTransformData.Size) =
when (size) {
TextTransformData.Size.TINY -> "0.5em"
TextTransformData.Size.SMALL -> "0.75em"
TextTransformData.Size.NORMAL -> "1em"
TextTransformData.Size.MEDIUM -> "1.5em"
TextTransformData.Size.LARGE -> "2em"
}

override fun visit(weight: TextTransformData.Weight) = weight.kebabCaseName

override fun visit(style: TextTransformData.Style) = style.kebabCaseName

override fun visit(decoration: TextTransformData.Decoration) = decoration.kebabCaseName

override fun visit(case: TextTransformData.Case) = case.kebabCaseName

override fun visit(variant: TextTransformData.Variant) = variant.kebabCaseName
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import eu.iamgio.quarkdown.ast.quarkdown.PageCounterInitializer
import eu.iamgio.quarkdown.ast.quarkdown.PageMarginContentInitializer
import eu.iamgio.quarkdown.ast.quarkdown.SlidesConfigurationInitializer
import eu.iamgio.quarkdown.ast.quarkdown.Stacked
import eu.iamgio.quarkdown.ast.quarkdown.TextTransform
import eu.iamgio.quarkdown.context.Context
import eu.iamgio.quarkdown.document.DocumentType
import eu.iamgio.quarkdown.rendering.tag.buildTag
Expand Down Expand Up @@ -105,6 +106,19 @@ class QuarkdownHtmlNodeRenderer(context: Context) : BaseHtmlNodeRenderer(context
// Math is processed by the MathJax library which requires text delimiters instead of tags.
override fun visit(node: MathSpan) = INLINE_MATH_FENCE + "$" + node.expression + "$" + INLINE_MATH_FENCE

override fun visit(node: TextTransform) =
buildTag("span") {
+node.children
style {
"font-size" value node.data.size
"font-weight" value node.data.weight
"font-style" value node.data.style
"font-variant" value node.data.variant
"text-decoration" value node.data.decoration
"text-transform" value node.data.case
}
}

// Invisible nodes

override fun visit(node: PageMarginContentInitializer) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package eu.iamgio.quarkdown.rendering.representable

import eu.iamgio.quarkdown.ast.quarkdown.Clipped
import eu.iamgio.quarkdown.ast.quarkdown.Stacked
import eu.iamgio.quarkdown.ast.quarkdown.TextTransformData
import eu.iamgio.quarkdown.document.page.PageMarginPosition
import eu.iamgio.quarkdown.document.page.Size
import eu.iamgio.quarkdown.document.page.Sizes
Expand Down Expand Up @@ -33,4 +34,16 @@ interface RenderRepresentableVisitor<T> {
fun visit(transition: Transition.Style): T

fun visit(speed: Transition.Speed): T

fun visit(size: TextTransformData.Size): T

fun visit(weight: TextTransformData.Weight): T

fun visit(style: TextTransformData.Style): T

fun visit(decoration: TextTransformData.Decoration): T

fun visit(case: TextTransformData.Case): T

fun visit(variant: TextTransformData.Variant): T
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import eu.iamgio.quarkdown.ast.quarkdown.PageCounterInitializer
import eu.iamgio.quarkdown.ast.quarkdown.PageMarginContentInitializer
import eu.iamgio.quarkdown.ast.quarkdown.SlidesConfigurationInitializer
import eu.iamgio.quarkdown.ast.quarkdown.Stacked
import eu.iamgio.quarkdown.ast.quarkdown.TextTransform

/**
* A visitor for [eu.iamgio.quarkdown.ast.Node]s.
Expand Down Expand Up @@ -130,6 +131,8 @@ interface NodeVisitor<T> {

fun visit(node: MathSpan): T

fun visit(node: TextTransform): T

// Quarkdown invisible nodes

fun visit(node: PageMarginContentInitializer): T
Expand Down
27 changes: 27 additions & 0 deletions stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Text.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package eu.iamgio.quarkdown.stdlib

import eu.iamgio.quarkdown.ast.Code
import eu.iamgio.quarkdown.ast.InlineMarkdownContent
import eu.iamgio.quarkdown.ast.MarkdownContent
import eu.iamgio.quarkdown.ast.quarkdown.TextTransform
import eu.iamgio.quarkdown.ast.quarkdown.TextTransformData
import eu.iamgio.quarkdown.context.MutableContext
import eu.iamgio.quarkdown.function.reflect.Injected
import eu.iamgio.quarkdown.function.reflect.Name
Expand All @@ -15,10 +18,34 @@ import eu.iamgio.quarkdown.util.toPlainText
*/
val Text: Module =
setOf(
::text,
::code,
::loremIpsum,
)

/**
* Creates an inline text node with specified formatting and transformation.
* @param size font size, or default if not specified
* @param weight font weight, or default if not specified
* @param style font style, or default if not specified
* @param decoration text decoration, or default if not specified
* @param case text case, or default if not specified
* @param variant font variant, or default if not specified
*/
fun text(
size: TextTransformData.Size? = null,
weight: TextTransformData.Weight? = null,
style: TextTransformData.Style? = null,
decoration: TextTransformData.Decoration? = null,
case: TextTransformData.Case? = null,
variant: TextTransformData.Variant? = null,
content: InlineMarkdownContent,
): NodeValue =
TextTransform(
TextTransformData(size, weight, style, decoration, case, variant),
content.children,
).wrappedAsValue()

/**
* Creates a code block. Contrary to its standard Markdown implementation with backtick/tilde fences,
* this function accepts Markdown content as its body, hence it can be used - for example -
Expand Down

0 comments on commit 48d2753

Please sign in to comment.