Skip to content

Commit

Permalink
refactor template, break one big template into many smaller templates (
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenyou authored Jun 8, 2024
1 parent 32c4346 commit 0fc14b3
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 135 deletions.
5 changes: 5 additions & 0 deletions .changeset/many-comics-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"scalawind": patch
---

refactor template, break the one big template into many smaller templates
23 changes: 13 additions & 10 deletions packages/scalawind/src/generate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@ import { createDoc } from './createDoc'

import Handlebars from "handlebars";

const scalawindTemplate = fs.readFileSync(path.join(__dirname, "./templates/scalawind.hbs"), "utf-8")
function readTemplate(filename) {
return fs.readFileSync(path.join(__dirname, `./templates/${filename}.hbs`), "utf-8")
}

Handlebars.registerPartial({
swMacro: Handlebars.compile(readTemplate('swMacro')),
tailwind: Handlebars.compile(readTemplate('tailwind')),
laminar: Handlebars.compile(readTemplate('laminar')),
scalajsReact: Handlebars.compile(readTemplate('scalajsReact')),
});

const template = Handlebars.compile(scalawindTemplate);
const template = Handlebars.compile(readTemplate('scalawind'));

export function generateContent(options) {
const {
userConfig,
packageName = "scalawind",
previewCompliedResult = false,
laminar = false,
scalajsReact = false,
} = options
const { userConfig } = options
const resolvedConfig = resolveConfig(userConfig);
const ctx = createContext(resolvedConfig);

Expand Down Expand Up @@ -106,7 +109,7 @@ export function generateContent(options) {
standard,
arbitrary,
opacityColors,
...options
...options,
})

return generatedScalawind
Expand Down
7 changes: 7 additions & 0 deletions packages/scalawind/src/generate/templates/laminar.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{#if laminar}}
import com.raquo.laminar.api.L.cls

object clx:
def apply(styles: String) = cls(styles)
def :=(styles: String) = cls(styles)
{{/if}}
7 changes: 7 additions & 0 deletions packages/scalawind/src/generate/templates/scalajsReact.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{#if scalajsReact}}
import japgolly.scalajs.react.vdom.html_<^.*

object clx:
def apply(styles: String): TagMod = ^.cls := styles
def :=(styles: String): TagMod = ^.cls := styles
{{/if}}
121 changes: 4 additions & 117 deletions packages/scalawind/src/generate/templates/scalawind.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,121 +3,8 @@ package {{packageName}}
import scala.quoted.*
import scala.annotation.unused
import scala.language.implicitConversions
{{#if laminar}}
import com.raquo.laminar.api.L.cls
{{> laminar this }}
{{> scalajsReact this }}
{{> swMacro this }}

object clx:
def apply(styles: String) = cls(styles)
def :=(styles: String) = cls(styles)
{{/if}}
{{#if scalajsReact}}
import japgolly.scalajs.react.vdom.html_<^.*

object clx:
def apply(styles: String): TagMod = ^.cls := styles
def :=(styles: String): TagMod = ^.cls := styles
{{/if}}

val tw = Tailwind()

implicit inline def sw(inline tailwind: Tailwind): String =
${ swImpl('tailwind) }

def methodNameToTailwindClass(rawName: String) =
val name = if rawName.startsWith("_") && rawName.charAt(1).isDigit then rawName.stripPrefix("_") else rawName
name.replace("_", "-").replace("per", "/").replace("dot", ".")

def swImpl(tailwindExpr: Expr[Tailwind])(using Quotes): Expr[String] =
import quotes.reflect.*

def extractClassNames(term: Term, prefix: String = "", important: Boolean = false): List[String] =
var stack = List((term, prefix, important))
var classNames = List.empty[String]

while
stack.nonEmpty
do
val (currentTerm, currentPrefix, currentImportant) = stack.head
stack = stack.tail

currentTerm match
case Apply(Select(inner, "important"), List(styles)) =>
stack = (styles, currentPrefix, true) :: stack
stack = (inner, currentPrefix, currentImportant) :: stack
case Inlined(_, _, inner) =>
stack = (inner, currentPrefix, currentImportant) :: stack
case Select(inner, name) =>
val methodName = methodNameToTailwindClass(name)
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}"
classNames = classNames :+ className
stack = (inner, currentPrefix, currentImportant) :: stack
case Ident("tw") =>
// No action needed, just continue processing the remaining stack
case Apply(Ident(name), List(arg)) =>
val methodName = methodNameToTailwindClass(name)
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}"
classNames = classNames :+ className
stack = (arg, currentPrefix, currentImportant) :: stack
case Apply(Select(inner, name), List(Literal(StringConstant(value)))) if name == "raw" =>
val className = s"$currentPrefix${if (currentImportant) "!" else ""}$value"
classNames = classNames :+ className
stack = (inner, currentPrefix, currentImportant) :: stack
case Apply(Select(inner, name), List(Literal(StringConstant(opacity)))) if name.endsWith("$") =>
val methodName = methodNameToTailwindClass(name.stripSuffix("$"))
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}/${opacity}"
classNames = classNames :+ className
stack = (inner, currentPrefix, currentImportant) :: stack
case Apply(Select(inner, name), List(Literal(StringConstant(value)))) =>
val methodName = methodNameToTailwindClass(name)
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}[$value]"
classNames = classNames :+ className
stack = (inner, currentPrefix, currentImportant) :: stack
case Apply(Apply(Ident(name), args), List(Literal(StringConstant(value)))) =>
val methodName = methodNameToTailwindClass(name)
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}[$value]"
classNames = classNames :+ className
stack = args.map(arg => (arg, currentPrefix, currentImportant)) ++ stack
case Apply(Select(Ident("tw"), name), List(inner)) =>
val methodName = methodNameToTailwindClass(name)
stack = (inner, s"$currentPrefix${methodName}:", currentImportant) :: stack
case Apply(Select(inner, "variant"), List(Literal(StringConstant(selector)), styles)) =>
val variantPrefix = s"$currentPrefix[$selector]:" // Use the selector as provided
val styleClasses = extractClassNames(styles, variantPrefix, currentImportant) // Extract classes with the variant prefix
classNames = classNames ++ styleClasses
stack = (inner, currentPrefix, currentImportant) :: stack
case Apply(Select(inner, name), args) =>
val methodName = methodNameToTailwindClass(name)
val innerClasses = args.flatMap(arg => extractClassNames(arg, s"$currentPrefix${methodName}:"))
classNames = classNames ++ innerClasses
stack = (inner, currentPrefix, currentImportant) :: stack
case unexpectedTerm =>
report.errorAndAbort(s"Unexpected term: $unexpectedTerm")

classNames
end extractClassNames

val term = tailwindExpr.asTerm
val classNames = extractClassNames(term)
val combinedClasses = classNames.reverse.mkString(" ")
{{#if previewCompliedResult}}
report.info(s"$combinedClasses")
{{/if}}
Expr(combinedClasses)

case class Tailwind():
{{#each modifiers}}
def {{this.name}}(@unused styles: Tailwind): Tailwind = this
{{/each}}
{{#each opacityColors}}
def {{this}}(@unused value: String): Tailwind = this
{{/each}}
{{#each standard}}
{{this.doc}}
def {{this.prop}}: Tailwind = this
{{/each}}
{{#each arbitrary}}
def {{this.methodName}}(value: String): Tailwind = this
{{/each}}
def important(@unused styles: Tailwind): Tailwind = this
def raw(@unused classString: String): Tailwind = this
def variant(selector: String, styles: Tailwind): Tailwind = this
{{> tailwind this }}
83 changes: 83 additions & 0 deletions packages/scalawind/src/generate/templates/swMacro.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
implicit inline def sw(inline tailwind: Tailwind): String =
${ swImpl('tailwind) }

def methodNameToTailwindClass(rawName: String) =
val name = if rawName.startsWith("_") && rawName.charAt(1).isDigit then rawName.stripPrefix("_") else rawName
name.replace("_", "-").replace("per", "/").replace("dot", ".")

def swImpl(tailwindExpr: Expr[Tailwind])(using Quotes): Expr[String] =
import quotes.reflect.*

def extractClassNames(term: Term, prefix: String = "", important: Boolean = false): List[String] =
var stack = List((term, prefix, important))
var classNames = List.empty[String]

while
stack.nonEmpty
do
val (currentTerm, currentPrefix, currentImportant) = stack.head
stack = stack.tail

currentTerm match
case Apply(Select(inner, "important"), List(styles)) =>
stack = (styles, currentPrefix, true) :: stack
stack = (inner, currentPrefix, currentImportant) :: stack
case Inlined(_, _, inner) =>
stack = (inner, currentPrefix, currentImportant) :: stack
case Select(inner, name) =>
val methodName = methodNameToTailwindClass(name)
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}"
classNames = classNames :+ className
stack = (inner, currentPrefix, currentImportant) :: stack
case Ident("tw") =>
// No action needed, just continue processing the remaining stack
case Apply(Ident(name), List(arg)) =>
val methodName = methodNameToTailwindClass(name)
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}"
classNames = classNames :+ className
stack = (arg, currentPrefix, currentImportant) :: stack
case Apply(Select(inner, name), List(Literal(StringConstant(value)))) if name == "raw" =>
val className = s"$currentPrefix${if (currentImportant) "!" else ""}$value"
classNames = classNames :+ className
stack = (inner, currentPrefix, currentImportant) :: stack
case Apply(Select(inner, name), List(Literal(StringConstant(opacity)))) if name.endsWith("$") =>
val methodName = methodNameToTailwindClass(name.stripSuffix("$"))
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}/${opacity}"
classNames = classNames :+ className
stack = (inner, currentPrefix, currentImportant) :: stack
case Apply(Select(inner, name), List(Literal(StringConstant(value)))) =>
val methodName = methodNameToTailwindClass(name)
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}[$value]"
classNames = classNames :+ className
stack = (inner, currentPrefix, currentImportant) :: stack
case Apply(Apply(Ident(name), args), List(Literal(StringConstant(value)))) =>
val methodName = methodNameToTailwindClass(name)
val className = s"$currentPrefix${if (currentImportant) "!" else ""}${methodName}[$value]"
classNames = classNames :+ className
stack = args.map(arg => (arg, currentPrefix, currentImportant)) ++ stack
case Apply(Select(Ident("tw"), name), List(inner)) =>
val methodName = methodNameToTailwindClass(name)
stack = (inner, s"$currentPrefix${methodName}:", currentImportant) :: stack
case Apply(Select(inner, "variant"), List(Literal(StringConstant(selector)), styles)) =>
val variantPrefix = s"$currentPrefix[$selector]:" // Use the selector as provided
val styleClasses = extractClassNames(styles, variantPrefix, currentImportant) // Extract classes with the variant prefix
classNames = classNames ++ styleClasses
stack = (inner, currentPrefix, currentImportant) :: stack
case Apply(Select(inner, name), args) =>
val methodName = methodNameToTailwindClass(name)
val innerClasses = args.flatMap(arg => extractClassNames(arg, s"$currentPrefix${methodName}:"))
classNames = classNames ++ innerClasses
stack = (inner, currentPrefix, currentImportant) :: stack
case unexpectedTerm =>
report.errorAndAbort(s"Unexpected term: $unexpectedTerm")

classNames
end extractClassNames

val term = tailwindExpr.asTerm
val classNames = extractClassNames(term)
val combinedClasses = classNames.reverse.mkString(" ")
{{#if previewCompliedResult}}
report.info(s"$combinedClasses")
{{/if}}
Expr(combinedClasses)
19 changes: 19 additions & 0 deletions packages/scalawind/src/generate/templates/tailwind.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
val tw = Tailwind()

case class Tailwind():
{{#each modifiers}}
def {{this.name}}(@unused styles: Tailwind): Tailwind = this
{{/each}}
{{#each opacityColors}}
def {{this}}(@unused value: String): Tailwind = this
{{/each}}
{{#each standard}}
{{this.doc}}
def {{this.prop}}: Tailwind = this
{{/each}}
{{#each arbitrary}}
def {{this.methodName}}(value: String): Tailwind = this
{{/each}}
def important(@unused styles: Tailwind): Tailwind = this
def raw(@unused classString: String): Tailwind = this
def variant(selector: String, styles: Tailwind): Tailwind = this
7 changes: 3 additions & 4 deletions packages/scalawind/tests/cases/basic/expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ import japgolly.scalajs.react.vdom.html_<^.*
object clx:
def apply(styles: String): TagMod = ^.cls := styles
def :=(styles: String): TagMod = ^.cls := styles

val tw = Tailwind()

implicit inline def sw(inline tailwind: Tailwind): String =
${ swImpl('tailwind) }

Expand Down Expand Up @@ -93,6 +90,8 @@ def swImpl(tailwindExpr: Expr[Tailwind])(using Quotes): Expr[String] =
report.info(s"$combinedClasses")
Expr(combinedClasses)

val tw = Tailwind()

case class Tailwind():
def first_letter(@unused styles: Tailwind): Tailwind = this
def first_line(@unused styles: Tailwind): Tailwind = this
Expand Down Expand Up @@ -867,4 +866,4 @@ case class Tailwind():
def text_(value: String): Tailwind = this
def important(@unused styles: Tailwind): Tailwind = this
def raw(@unused classString: String): Tailwind = this
def variant(selector: String, styles: Tailwind): Tailwind = this
def variant(selector: String, styles: Tailwind): Tailwind = this
7 changes: 3 additions & 4 deletions packages/scalawind/tests/cases/full/expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ import com.raquo.laminar.api.L.cls
object clx:
def apply(styles: String) = cls(styles)
def :=(styles: String) = cls(styles)

val tw = Tailwind()

implicit inline def sw(inline tailwind: Tailwind): String =
${ swImpl('tailwind) }

Expand Down Expand Up @@ -93,6 +90,8 @@ def swImpl(tailwindExpr: Expr[Tailwind])(using Quotes): Expr[String] =
report.info(s"$combinedClasses")
Expr(combinedClasses)

val tw = Tailwind()

case class Tailwind():
def first_letter(@unused styles: Tailwind): Tailwind = this
def first_line(@unused styles: Tailwind): Tailwind = this
Expand Down Expand Up @@ -96398,4 +96397,4 @@ case class Tailwind():
def forced_color_adjust_none_(value: String): Tailwind = this
def important(@unused styles: Tailwind): Tailwind = this
def raw(@unused classString: String): Tailwind = this
def variant(selector: String, styles: Tailwind): Tailwind = this
def variant(selector: String, styles: Tailwind): Tailwind = this

0 comments on commit 0fc14b3

Please sign in to comment.