From 48e2459bbddf24dbdd7a8707ece0500727122745 Mon Sep 17 00:00:00 2001 From: halotukozak Date: Mon, 10 Jun 2024 10:01:35 +0200 Subject: [PATCH] remove `inline` modifier from HasInner components, what led to the bug. Inline some methods. Use Scala 3 implicit conversion with context parameter --- src/main/scala/Markdown.scala | 13 ++------ src/main/scala/api.scala | 33 +++++++++---------- src/main/scala/tables/Table.scala | 15 ++++----- src/main/scala/typography/Code.scala | 2 +- src/main/scala/typography/Comment.scala | 9 +++-- src/main/scala/typography/Headings.scala | 7 ++-- src/main/scala/typography/Paragraph.scala | 7 ++-- src/main/scala/typography/Quote.scala | 9 ++--- src/main/scala/utils/HasInner.scala | 10 +++--- src/main/scala/utils/MdElement.scala | 8 +++++ .../scala/integration/IntegrationTest.scala | 7 ++-- src/test/scala/tables/TableTest.scala | 12 ++++--- src/test/scala/typography/HeadingTest.scala | 1 - src/test/scala/typography/OtherTest.scala | 5 ++- 14 files changed, 68 insertions(+), 70 deletions(-) create mode 100644 src/main/scala/utils/MdElement.scala diff --git a/src/main/scala/Markdown.scala b/src/main/scala/Markdown.scala index 1d45c38..d27bcc3 100644 --- a/src/main/scala/Markdown.scala +++ b/src/main/scala/Markdown.scala @@ -1,24 +1,17 @@ package halotukozak.smark import tables.Table -import utils.HasInner +import utils.{HasInner, MdElement} type MdContent = String | MdElement | Table -opaque type MdUnit = Unit -private trait MdElement extends HasInner[MdContent]: - private[smark] def eval: String -end MdElement +opaque type MdUnit = Unit private class Markdown extends MdElement: - private[smark] def eval = inner.mkString("\n\n") - -end Markdown + override def eval: String = evaluated.mkString("\n\n") extension (s: MdContent) private def eval: String = s match case s: String => s case e: MdElement => e.eval case t: Table => t.eval - -implicit def stringToModifier(s: String)(using m: MdElement): MdUnit = m.add(s) \ No newline at end of file diff --git a/src/main/scala/api.scala b/src/main/scala/api.scala index 40ddd47..7e3f874 100644 --- a/src/main/scala/api.scala +++ b/src/main/scala/api.scala @@ -3,11 +3,7 @@ package halotukozak.smark import tables.* import typography.* import typography.macros.* - - -private inline def initAndAdd[T <: MdElement](inline q: T)(inline init: T ?=> MdUnit)(using m: MdElement): MdUnit = - init(using q) - m.add(q) +import utils.MdElement def markdown(init: MdElement ?=> MdUnit): String = given m: MdElement = new Markdown @@ -15,29 +11,28 @@ def markdown(init: MdElement ?=> MdUnit): String = init(using m) m.eval -inline def text[Style <: TextStyle](inline inner: String)(using m: MdElement): MdUnit = m.add(textMacro[Style](inner)) +inline def text[Style <: TextStyle](inner: String)(using m: MdElement): MdUnit = m.add(textMacro[Style](inner)) inline def emoji[E <: Emoji](using m: MdElement): MdUnit = m.add(emojiMacro[E]) -inline def quote[AlertType <: Alert : ValueOf](inline init: MdElement ?=> MdUnit)(using m: MdElement): MdUnit = initAndAdd(new typography.Quote[AlertType])(init) +def quote[AlertType <: Alert : ValueOf](init: MdElement ?=> MdUnit)(using m: MdElement): MdUnit = initAndAdd(new typography.Quote[AlertType])(init) -inline def heading[N <: HeadingLevel : ValueOf](inline init: MdElement ?=> MdUnit)(using m: MdElement): MdUnit = initAndAdd(new typography.Heading[N])(init) +def heading[N <: HeadingLevel : ValueOf](init: MdElement ?=> MdUnit)(using m: MdElement): MdUnit = initAndAdd(new typography.Heading[N])(init) -inline def code[L <: code](inline inner: L)(using m: MdElement): MdUnit = m.add(codeMacro[L](inner)) +inline def code[L <: code](inner: L)(using m: MdElement): MdUnit = m.add(codeMacro[L](inner)) -inline def list[Style <: ListStyle](inline elements: String*)(using m: MdElement): MdUnit = m.add(listMacro[Style](elements)) +inline def list[Style <: ListStyle](elements: String*)(using m: MdElement): MdUnit = m.add(listMacro[Style](elements)) -inline def taskList(inline points: ((Boolean, String) | String)*)(using m: MdElement): MdUnit = m.add(taskListMacro(points *)) +def taskList(points: ((Boolean, String) | String)*)(using m: MdElement): MdUnit = m.add(taskListMacro(points *)) inline def hr(using m: MdElement): MdUnit = m.add("***") -inline def paragraph(inline init: MdElement ?=> MdUnit)(using m: MdElement): MdUnit = initAndAdd(new typography.Paragraph)(init) +def paragraph(init: MdElement ?=> MdUnit)(using m: MdElement): MdUnit = initAndAdd(new typography.Paragraph)(init) +def comment(init: MdElement ?=> MdUnit)(using m: MdElement): MdUnit = initAndAdd(new typography.Comment)(init) -inline def comment(inline init: MdElement ?=> MdUnit)(using m: MdElement): MdUnit = initAndAdd(new typography.Comment)(init) +inline def link[Title <: String](url: String)(using m: MdElement): MdUnit = m.add(linkMacro[Title](url)) -inline def link[Title <: String](inline url: String)(using m: MdElement): MdUnit = m.add(linkMacro[Title](url)) - -inline def image[title <: String](inline url: String)(using m: MdElement): MdUnit = m.add(imageMacro[title](url)) +inline def image[title <: String](url: String)(using m: MdElement): MdUnit = m.add(imageMacro[title](url)) def table(init: Table ?=> MdUnit)(using m: MdElement): MdUnit = given t: Table = new Table @@ -67,6 +62,9 @@ def cell(init: MdElement ?=> MdUnit)(using r: Row): MdUnit = c } +private def initAndAdd[T <: MdElement](q: T)(init: T ?=> MdUnit)(using m: MdElement): MdUnit = + init(using q) + m.add(q) package string: inline def text[Style <: TextStyle](inline inner: String): String = textMacro[Style](inner) @@ -81,5 +79,4 @@ end string import _root_.scala.language.implicitConversions -given Conversion[Unit, MdUnit] with - def apply(u: Unit): MdUnit = ().asInstanceOf \ No newline at end of file +given (using m: MdElement): Conversion[String, MdUnit] = m.add(_) diff --git a/src/main/scala/tables/Table.scala b/src/main/scala/tables/Table.scala index 468da85..b7106b5 100644 --- a/src/main/scala/tables/Table.scala +++ b/src/main/scala/tables/Table.scala @@ -3,25 +3,22 @@ package tables import tables.Column.symbol -import utils.HasInner - -import scala.collection.mutable.ListBuffer +import utils.{HasInner, MdElement} private[smark] final class Table extends HasInner[Row | Header]: extension (ab: Iterable[String]) private def mkRow = ab.mkString("| ", " | ", " |") - private[smark] def eval: String = inner.map { - case r: Row => r.inner.map(_.eval).mkRow - case h: Header => h.inner.map(_.name).mkRow + "\n" + h.inner.map(symbol).mkRow + private[smark] def eval: String = elements.map { + case r: Row => r.elements.map(_.eval).mkRow + case h: Header => h.elements.map(_.name).mkRow + "\n" + h.elements.map(symbol).mkRow }.mkString("\n") private[smark] class Row extends HasInner[Cell] -private[smark] class Header(elements: Seq[Column]) extends HasInner[Column](ListBuffer.from(elements)) - +private[smark] class Header(elements: Seq[Column]) extends HasInner[Column](elements) private[smark] sealed abstract class Column(val name: String) @@ -53,5 +50,5 @@ given Conversion[String, Center] = Column.Center(_) given Conversion[String, None] = Column.None(_) private[smark] final class Cell extends MdElement: - override private[smark] def eval: String = inner.mkString("\n") + override def eval: String = evaluated.mkString("\n") end Cell diff --git a/src/main/scala/typography/Code.scala b/src/main/scala/typography/Code.scala index 71fce9e..0e45097 100644 --- a/src/main/scala/typography/Code.scala +++ b/src/main/scala/typography/Code.scala @@ -14,7 +14,7 @@ type sql <: code type bash <: code type html <: code -implicit class ScalaHelper(private val sc: StringContext) extends AnyVal { +implicit class CodeHelper(private val sc: StringContext) extends AnyVal { def scala(args: Any*): scala = sc.s(args *).asInstanceOf[scala] def python(args: Any*): python = sc.s(args *).asInstanceOf[python] diff --git a/src/main/scala/typography/Comment.scala b/src/main/scala/typography/Comment.scala index 4b00ce9..6fb2b67 100644 --- a/src/main/scala/typography/Comment.scala +++ b/src/main/scala/typography/Comment.scala @@ -1,9 +1,8 @@ package halotukozak.smark package typography -final class Comment extends MdElement: - override private[smark] def eval: String = - val lines = inner.map(e => e.eval).toSeq - commentMacro(if lines.length == 1 then lines.mkString("\n") else lines.mkString("\n", "\n", "\n")) +import utils.MdElement -private[smark] inline def commentMacro(inline inner: String): String = s"" +final class Comment extends MdElement: + override def eval: String = + s"" diff --git a/src/main/scala/typography/Headings.scala b/src/main/scala/typography/Headings.scala index 0fa6ab7..1d9a109 100644 --- a/src/main/scala/typography/Headings.scala +++ b/src/main/scala/typography/Headings.scala @@ -1,10 +1,11 @@ package halotukozak.smark package typography +import utils.MdElement + private[smark] type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6 final class Heading[N <: HeadingLevel : ValueOf] extends MdElement: - override private[smark] def eval: String = inner.map(e => headingMacro[N](e.eval)).mkString("\n") - -private[smark] inline def headingMacro[N <: HeadingLevel : ValueOf](inline inner: String): String = "#" * valueOf[N] + inner + override def eval: String = + evaluated.map(e => s"${"#" * valueOf[N]}$e").mkString("\n") diff --git a/src/main/scala/typography/Paragraph.scala b/src/main/scala/typography/Paragraph.scala index 821f748..fe378c0 100644 --- a/src/main/scala/typography/Paragraph.scala +++ b/src/main/scala/typography/Paragraph.scala @@ -1,8 +1,7 @@ package halotukozak.smark package typography -final class Paragraph extends MdElement: - - override private[smark] def eval: String = paragraphMacro(inner.map(e => e.eval).mkString("\n\n")) +import utils.MdElement -private[smark] inline def paragraphMacro(inline inner: String): String = "\n" + inner +final class Paragraph extends MdElement: + override def eval: String = "\n" + evaluated.mkString("\n\n") diff --git a/src/main/scala/typography/Quote.scala b/src/main/scala/typography/Quote.scala index 9b61350..066eef7 100644 --- a/src/main/scala/typography/Quote.scala +++ b/src/main/scala/typography/Quote.scala @@ -3,11 +3,12 @@ package typography import typography.* import typography.macros.textMacro +import utils.MdElement private[smark] final class Quote[AlertType <: Alert : ValueOf] extends MdElement: - override private[smark] def eval: String = - (s"[!${valueOf[AlertType]}]" +: inner) - .map(e => textMacro[Quoted](e.eval)) + override def eval: String = + (s"[!${valueOf[AlertType]}]" +: evaluated) + .map(textMacro[Quoted]) .mkString("\n") -end Quote \ No newline at end of file +end Quote diff --git a/src/main/scala/utils/HasInner.scala b/src/main/scala/utils/HasInner.scala index de3e8c4..e88b03a 100644 --- a/src/main/scala/utils/HasInner.scala +++ b/src/main/scala/utils/HasInner.scala @@ -1,8 +1,10 @@ package halotukozak.smark package utils -import scala.collection.mutable -import scala.collection.mutable.{ListBuffer, Seq} +private[smark] abstract class HasInner[T](private var inner: Seq[T] = Nil): -private[smark] abstract class HasInner[T](private[smark] val inner: ListBuffer[T] = new ListBuffer[T]): - final def add(e: T): Unit = inner.addOne(e) + final def elements: Seq[T] = inner + + final def add(e: T): MdUnit = { + inner = inner :+ e + }.asInstanceOf diff --git a/src/main/scala/utils/MdElement.scala b/src/main/scala/utils/MdElement.scala new file mode 100644 index 0000000..606d5aa --- /dev/null +++ b/src/main/scala/utils/MdElement.scala @@ -0,0 +1,8 @@ +package halotukozak.smark +package utils + +private[smark] trait MdElement extends HasInner[MdContent]: + def eval: String + + final protected def evaluated: Seq[String] = elements.map(_.eval) + \ No newline at end of file diff --git a/src/test/scala/integration/IntegrationTest.scala b/src/test/scala/integration/IntegrationTest.scala index 2b5db04..139c85f 100644 --- a/src/test/scala/integration/IntegrationTest.scala +++ b/src/test/scala/integration/IntegrationTest.scala @@ -2,8 +2,8 @@ package halotukozak.smark package integration import tables.* -import typography.* import typography.macros.* +import typography.{CodeHelper, *} import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec @@ -41,14 +41,13 @@ final class IntegrationTest extends AnyWordSpec with Matchers: table { row { cell { - text[Bold]("a") - text[Italic]("ba") + string.text[Bold]("a") + string.text[Italic]("ba") } cell("b") } row { cell { - // string.text[Code](scala"val x = 1") + string.text[Code](scala"val x = 1") } cell("d") } diff --git a/src/test/scala/tables/TableTest.scala b/src/test/scala/tables/TableTest.scala index 175545d..387065c 100644 --- a/src/test/scala/tables/TableTest.scala +++ b/src/test/scala/tables/TableTest.scala @@ -2,8 +2,8 @@ package halotukozak.smark package tables import tables.* -import typography.macros.* import typography.* +import typography.macros.* import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec @@ -14,7 +14,11 @@ final class TableTest extends AnyWordSpec with Matchers: "be evaluated" in { markdown { table { - row {} + row{ + cell{ + "" + } + } } } shouldBe "| |" @@ -31,13 +35,13 @@ final class TableTest extends AnyWordSpec with Matchers: table { row { cell { - textMacro[Bold]("a") + text[Bold]("a") } cell("b") } row { cell { - textMacro[Code](scala"val x = 1") + text[Code](scala"val x = 1") } cell("d") } diff --git a/src/test/scala/typography/HeadingTest.scala b/src/test/scala/typography/HeadingTest.scala index a51a7e5..e3af0b1 100644 --- a/src/test/scala/typography/HeadingTest.scala +++ b/src/test/scala/typography/HeadingTest.scala @@ -2,7 +2,6 @@ package halotukozak.smark package typography -import tables.* import typography.* import typography.macros.* diff --git a/src/test/scala/typography/OtherTest.scala b/src/test/scala/typography/OtherTest.scala index c2f2d07..d5dca26 100644 --- a/src/test/scala/typography/OtherTest.scala +++ b/src/test/scala/typography/OtherTest.scala @@ -1,9 +1,8 @@ package halotukozak.smark package typography -import tables.* -import typography.* import typography.macros.* +import utils.MdElement import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec @@ -45,7 +44,7 @@ final class OtherTest extends AnyWordSpec with Matchers: |hello |**boldedHello** |*world* - |-->""".stripMargin + | -->""".stripMargin } }