blah blah blah i am text
227 |
This image is very interesting
231 |├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ └── actions.yml ├── .gitignore ├── .mill-version ├── LICENSE ├── build.mill ├── build.sbt ├── example ├── resources │ ├── index-dev.html │ └── index-opt.html └── src │ └── example │ └── ScalaJSExample.scala ├── mill ├── package-lock.json ├── package.json ├── project ├── Constants.scala ├── build.properties └── build.sbt ├── readme.md ├── readme ├── Readme.scalatex └── resources │ ├── Autocomplete.png │ ├── ErrorHighlighting.png │ ├── InlineDocs.png │ └── favicon.png └── scalatags ├── src-2 └── scalatags │ └── stylesheet │ └── SourceClasses.scala ├── src-3 └── scalatags │ └── stylesheet │ └── SourceClasses.scala ├── src-js └── scalatags │ ├── JsDom.scala │ └── jsdom │ ├── Frag.scala │ ├── SvgTags.scala │ ├── TagFactory.scala │ ├── Tags.scala │ └── Tags2.scala ├── src └── scalatags │ ├── DataTypes.scala │ ├── Escaping.scala │ ├── Text.scala │ ├── VirtualDom.scala │ ├── generic │ ├── Attrs.scala │ ├── Bundle.scala │ ├── Core.scala │ ├── Styles.scala │ ├── SvgAttrs.scala │ ├── SvgTags.scala │ ├── Tags.scala │ ├── Tags2.scala │ └── Util.scala │ ├── package.scala │ ├── stylesheet │ ├── Core.scala │ └── StyleSheet.scala │ ├── text │ ├── Builder.scala │ ├── SvgTags.scala │ ├── TagFactory.scala │ ├── Tags.scala │ └── Tags2.scala │ └── vdom │ ├── Builder.scala │ ├── SvgTags.scala │ ├── TagFactory.scala │ ├── Tags.scala │ └── Tags2.scala └── test ├── resource ├── page.jade ├── page.mustache ├── para.jade └── para.mustache ├── src-js └── scalatags │ └── jsdom │ ├── BasicTests.scala │ ├── DomTests.scala │ ├── ExampleTests.scala │ ├── PerfTests.scala │ └── StyleSheetTests.scala ├── src-jvm └── scalatags │ ├── generic │ └── ExampleTestsJvmOnly.scala │ └── text │ └── PerfTests.scala ├── src └── scalatags │ ├── Main.scala │ ├── TestUtil.scala │ ├── generic │ ├── BasicTests.scala │ ├── ExampleTests.scala │ ├── PerfTests.scala │ └── StyleSheetTests.scala │ └── text │ ├── BasicTests.scala │ ├── BundlingTests.scala │ ├── ExampleTests.scala │ ├── PerfTests.scala │ ├── StyleSheetTests.scala │ └── TextTests.scala └── twirl ├── page.scala.html └── para.scala.html /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: lihaoyi 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "monthly" 8 | 9 | - package-ecosystem: "npm" 10 | directory: "/" 11 | schedule: 12 | interval: "monthly" 13 | -------------------------------------------------------------------------------- /.github/workflows/actions.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | tags: 8 | - '*' 9 | pull_request: 10 | branches: 11 | - master 12 | 13 | jobs: 14 | test: 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | java: ['8', '17'] 19 | steps: 20 | - uses: actions/checkout@v3 21 | - uses: actions/setup-java@v3 22 | with: 23 | distribution: 'temurin' 24 | java-version: ${{ matrix.java }} 25 | 26 | - name: Install node and jsdom 27 | run: npm install 28 | 29 | - name: Run tests 30 | run: | 31 | ./mill -i --disable-ticker __.resolvedIvyDeps 32 | ./mill -i --disable-ticker -j 0 __.publishArtifacts __.test 33 | 34 | check-binary-compatibility: 35 | runs-on: ubuntu-latest 36 | steps: 37 | - uses: actions/checkout@v3 38 | with: 39 | fetch-depth: 0 40 | - uses: actions/setup-java@v3 41 | with: 42 | distribution: 'temurin' 43 | java-version: 17 44 | - name: Check Binary Compatibility 45 | run: ./mill -i --disable-ticker __.mimaReportBinaryIssues 46 | 47 | publish-sonatype: 48 | if: github.repository == 'com-lihaoyi/scalatags' && contains(github.ref, 'refs/tags/') 49 | needs: test 50 | runs-on: ubuntu-latest 51 | env: 52 | MILL_SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} 53 | MILL_SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} 54 | MILL_PGP_SECRET_BASE64: ${{ secrets.SONATYPE_PGP_PRIVATE_KEY }} 55 | MILL_PGP_PASSPHRASE: ${{ secrets.SONATYPE_PGP_PRIVATE_KEY_PASSWORD }} 56 | LANG: "en_US.UTF-8" 57 | LC_MESSAGES: "en_US.UTF-8" 58 | LC_ALL: "en_US.UTF-8" 59 | 60 | steps: 61 | - uses: actions/checkout@v3 62 | - uses: actions/setup-java@v3 63 | with: 64 | distribution: 'temurin' 65 | java-version: 11 66 | - name: Publish to Maven Central 67 | run: ./mill -i mill.scalalib.PublishModule/ 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | example/target/* 3 | scalatags/target/* 4 | scalatags/js/target/* 5 | scalatags/jvm/target/* 6 | project/target/* 7 | project/project/target/* 8 | readme/target/* 9 | .idea/* 10 | .idea_modules/* 11 | *.iml 12 | out 13 | /node_modules 14 | /.bsp 15 | -------------------------------------------------------------------------------- /.mill-version: -------------------------------------------------------------------------------- 1 | 0.12.0 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Li Haoyi (haoyi.sg@gmail.com) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /build.mill: -------------------------------------------------------------------------------- 1 | package build 2 | import mill._, scalalib._, scalajslib._, scalanativelib._, publish._ 3 | import $ivy.`de.tototec::de.tobiasroeser.mill.vcs.version::0.4.0` 4 | import $ivy.`com.github.lolgab::mill-mima::0.0.23` 5 | import $ivy.`com.lihaoyi::mill-contrib-buildinfo:` 6 | import mill.contrib.buildinfo._ 7 | import de.tobiasroeser.mill.vcs.version.VcsVersion 8 | 9 | import com.github.lolgab.mill.mima._ 10 | import mill.scalalib.api.ZincWorkerUtil.isScala3 11 | 12 | val dottyVersions = sys.props.get("dottyVersion").toList 13 | 14 | val scalaVersions = List("2.12.17", "2.13.10", "3.3.1") ++ dottyVersions 15 | 16 | trait ScalatagsPublishModule extends CrossScalaModule with PublishModule with PlatformScalaModule with Mima{ 17 | def ivyDeps = Agg( 18 | ivy"com.lihaoyi::sourcecode::0.4.0", 19 | ivy"com.lihaoyi::geny::1.1.0", 20 | ) 21 | 22 | def compileIvyDeps = T { 23 | super.compileIvyDeps() ++ 24 | ( 25 | if (isScala3(crossScalaVersion)) Agg() 26 | else Agg( 27 | ivy"org.scala-lang:scala-reflect:${scalaVersion()}" 28 | ) 29 | ) 30 | } 31 | 32 | def publishVersion = VcsVersion.vcsState().format() 33 | def pomSettings = PomSettings( 34 | description = artifactName(), 35 | organization = "com.lihaoyi", 36 | url = "https://github.com/com-lihaoyi/scalatags", 37 | licenses = Seq(License.MIT), 38 | versionControl = VersionControl( 39 | browsableRepository = Some("git://github.com/com-lihaoyi/scalatags.git"), 40 | connection = Some("scm:git://github.com/com-lihaoyi/scalatags.git") 41 | ), 42 | developers = Seq( 43 | Developer("lihaoyi", "Li Haoyi", "https://github.com/lihaoyi") 44 | ) 45 | ) 46 | 47 | def mimaReportBinaryIssues() = 48 | if (crossScalaVersion.startsWith("3.") || this.isInstanceOf[ScalaNativeModule] || this.isInstanceOf[ScalaJSModule]) T.command() 49 | else super.mimaReportBinaryIssues() 50 | 51 | def mimaPreviousVersions = Seq("0.11.0", "0.11.1", "0.12.0") 52 | } 53 | 54 | trait CommonTestModule extends ScalaModule with TestModule.Utest with BuildInfo { 55 | def ivyDeps = Agg( 56 | ivy"com.lihaoyi::utest::0.8.3", 57 | ivy"org.scala-lang.modules::scala-xml:${if(scalaVersion().startsWith("2.11.")) "1.3.0" else "2.1.0"}" 58 | ) 59 | 60 | override def buildInfoPackageName = "scalatags" 61 | override def buildInfoMembers = Seq( 62 | BuildInfo.Value("scalaMajorVersion", scalaVersion().split('.').head) 63 | ) 64 | } 65 | 66 | 67 | object scalatags extends Module { 68 | object jvm extends Cross[JvmScalatagsModule](scalaVersions) 69 | trait JvmScalatagsModule 70 | extends ScalatagsPublishModule { 71 | 72 | object test extends ScalaTests with CommonTestModule 73 | } 74 | 75 | object js extends Cross[JSScalatagsModule](scalaVersions) 76 | trait JSScalatagsModule 77 | extends ScalaJSModule with ScalatagsPublishModule { 78 | def scalaJSVersion = "1.12.0" 79 | def ivyDeps = super.ivyDeps() ++ Agg(ivy"org.scala-js::scalajs-dom::2.3.0") 80 | private def sourceMapOptions = T.task { 81 | val vcsState = VcsVersion.vcsState() 82 | vcsState.lastTag.collect { 83 | case tag if vcsState.commitsSinceLastTag == 0 => 84 | val baseUrl = 85 | pomSettings().url.replace("github.com", "raw.githubusercontent.com") 86 | val sourcesOptionName = 87 | if (isScala3(crossScalaVersion)) 88 | "-scalajs-mapSourceURI" 89 | else "-P:scalajs:mapSourceURI" 90 | s"$sourcesOptionName:${T.workspace.toIO.toURI}->$baseUrl/$tag/" 91 | } 92 | } 93 | override def scalacOptions = super.scalacOptions() ++ sourceMapOptions() 94 | 95 | object test extends ScalaJSTests with CommonTestModule{ 96 | def ivyDeps = super.ivyDeps() ++ Agg(ivy"org.scala-js::scalajs-env-jsdom-nodejs:1.1.0").map(_.withDottyCompat(crossScalaVersion)) 97 | def jsEnvConfig = mill.scalajslib.api.JsEnvConfig.JsDom() 98 | } 99 | } 100 | 101 | object native extends Cross[NativeScalatagsModule](scalaVersions) 102 | trait NativeScalatagsModule extends ScalaNativeModule with ScalatagsPublishModule { 103 | def scalaNativeVersion = "0.5.0" 104 | // No released Scala Native Scala 3 version yet 105 | def mimaPreviousArtifacts = if(isScala3(crossScalaVersion)) Agg.empty[Dep] else super.mimaPreviousArtifacts() 106 | object test extends ScalaNativeTests with CommonTestModule 107 | } 108 | } 109 | 110 | object example extends ScalaJSModule{ 111 | def scalaVersion = scalaVersions.head 112 | def scalaJSVersion = "1.12.0" 113 | def moduleDeps = Seq(scalatags.js(scalaVersions.head)) 114 | } 115 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | 2 | lazy val readme = scalatex.ScalatexReadme( 3 | projectId = "readme", 4 | wd = file(""), 5 | url = "https://github.com/lihaoyi/scalatags/tree/master", 6 | source = "Readme", 7 | autoResources = Seq("Autocomplete.png", "ErrorHighlighting.png", "InlineDocs.png", "example-opt.js") 8 | ).settings( 9 | scalaVersion := "2.12.8", 10 | (unmanagedSources in Compile) += baseDirectory.value/".."/"project"/"Constants.scala", 11 | (resources in Compile) += (fullOptJS in (example, Compile)).value.data, 12 | (resources in Compile) += (doc in (scalatagsJS, Compile)).value, 13 | (run in Compile) := (run in Compile).dependsOn(Def.task{ 14 | sbt.IO.copyDirectory( 15 | (doc in (scalatagsJS, Compile)).value, 16 | (target in Compile).value/"scalatex"/"api", 17 | overwrite = true 18 | ) 19 | }).evaluated 20 | ) 21 | -------------------------------------------------------------------------------- /example/resources/index-dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |""" 158 | val newAttr = tmpElm.children(0).attributes(0).cloneNode(true) 159 | t.setAttributeNode(newAttr.asInstanceOf[raw.Attr]) 160 | 161 | } 162 | case Some(namespace) => 163 | t.setAttributeNS(namespace.uri, a.name, v.toString) 164 | } 165 | } 166 | } 167 | 168 | class GenericStyle[T] extends StyleValue[T]{ 169 | def apply(t: dom.Element, s: Style, v: T): Unit = { 170 | t.asInstanceOf[html.Html] 171 | .style 172 | .setProperty(s.cssName, v.toString) 173 | } 174 | } 175 | class GenericPixelStyle[T](ev: StyleValue[T]) extends PixelStyleValue[T]{ 176 | def apply(s: Style, v: T) = StylePair(s, v, ev) 177 | } 178 | class GenericPixelStylePx[T](ev: StyleValue[String]) extends PixelStyleValue[T]{ 179 | def apply(s: Style, v: T) = StylePair(s, s"${v}px", ev) 180 | } 181 | case class TypedTag[+Output <: dom.Element](tag: String = "", 182 | modifiers: List[Seq[Modifier]], 183 | void: Boolean = false, 184 | namespace: Namespace) 185 | extends generic.TypedTag[dom.Element, Output, dom.Node] 186 | with jsdom.Frag{ 187 | // unchecked because Scala 2.10.4 seems to not like this, even though 188 | // 2.11.1 works just fine. I trust that 2.11.1 is more correct than 2.10.4 189 | // and so just force this. 190 | protected[this] type Self = TypedTag[Output @uncheckedVariance] 191 | 192 | def render: Output = { 193 | val elem = dom.document.createElementNS(namespace.uri, tag) 194 | build(elem) 195 | elem.asInstanceOf[Output] 196 | } 197 | /** 198 | * Trivial override, not strictly necessary, but it makes IntelliJ happy... 199 | */ 200 | def apply(xs: Modifier*): TypedTag[Output] = { 201 | this.copy(tag = tag, void = void, modifiers = xs :: modifiers) 202 | } 203 | override def toString = render.outerHTML 204 | } 205 | 206 | } 207 | 208 | trait LowPriorityImplicits{ 209 | implicit object bindJsAny extends generic.AttrValue[dom.Element, js.Any]{ 210 | def apply(t: dom.Element, a: generic.Attr, v: js.Any): Unit = { 211 | t.asInstanceOf[js.Dynamic].updateDynamic(a.name)(v) 212 | } 213 | } 214 | implicit def bindJsAnyLike[T](implicit ev: T => js.Any): generic.AttrValue[dom.Element, T] = new generic.AttrValue[dom.Element, T]{ 215 | def apply(t: dom.Element, a: generic.Attr, v: T): Unit = { 216 | t.asInstanceOf[js.Dynamic].updateDynamic(a.name)(ev(v)) 217 | } 218 | } 219 | implicit class bindNode[T <: dom.Node](e: T) extends generic.Frag[dom.Element, T] { 220 | def applyTo(t: Element) = t.appendChild(e) 221 | def render = e 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /scalatags/src-js/scalatags/jsdom/Frag.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package jsdom 3 | import org.scalajs.dom 4 | 5 | trait Frag extends generic.Frag[dom.Element, dom.Node]{ 6 | def render: dom.Node 7 | def applyTo(b: dom.Element) = b.appendChild(this.render) 8 | } 9 | -------------------------------------------------------------------------------- /scalatags/src-js/scalatags/jsdom/SvgTags.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package jsdom 3 | import org.scalajs.dom 4 | import scalatags.generic.{Namespace, Util} 5 | trait SvgTags extends generic.SvgTags[dom.Element, dom.Element, dom.Node] with TagFactory{ 6 | implicit lazy val svgNamespaceConfig: Namespace = Namespace.svgNamespaceConfig 7 | lazy val altGlyph = typedTag[dom.svg.Element]("altGlyph") 8 | lazy val altGlyphDef = typedTag[dom.svg.Element]("altGlyphDef") 9 | lazy val altGlyphItem = typedTag[dom.svg.Element]("altGlyphItem") 10 | lazy val animate = typedTag[dom.svg.Element]("animate") 11 | lazy val animateMotion = typedTag[dom.svg.Element]("animateMotion") 12 | lazy val animateTransform = typedTag[dom.svg.Element]("animateTransform") 13 | lazy val circle = typedTag[dom.svg.Circle]("circle") 14 | lazy val clipPath = typedTag[dom.svg.ClipPath]("clipPath") 15 | lazy val `color-profile` = typedTag[dom.svg.Element]("color-profile") 16 | lazy val cursor = typedTag[dom.svg.Element]("cursor") 17 | lazy val defs = typedTag[dom.svg.Defs]("defs") 18 | lazy val desc = typedTag[dom.svg.Desc]("desc") 19 | lazy val ellipse = typedTag[dom.svg.Ellipse]("ellipse") 20 | lazy val feBlend = typedTag[dom.svg.FEBlend]("feBlend") 21 | lazy val feColorMatrix = typedTag[dom.svg.FEColorMatrix]("feColorMatrix") 22 | lazy val feComponentTransfer = typedTag[dom.svg.ComponentTransferFunction]("feComponentTransfer") 23 | lazy val feComposite = typedTag[dom.svg.FEComposite]("feComposite") 24 | lazy val feConvolveMatrix = typedTag[dom.svg.FEConvolveMatrix]("feConvolveMatrix") 25 | lazy val feDiffuseLighting = typedTag[dom.svg.FEDiffuseLighting]("feDiffuseLighting") 26 | lazy val feDisplacementMap = typedTag[dom.svg.FEDisplacementMap]("feDisplacementMap") 27 | lazy val feDistantLighting = typedTag[dom.svg.FEDistantLight]("feDistantLighting") 28 | lazy val feFlood = typedTag[dom.svg.FEFlood]("feFlood") 29 | lazy val feFuncA = typedTag[dom.svg.FEFuncA]("feFuncA") 30 | lazy val feFuncB = typedTag[dom.svg.FEFuncB]("feFuncB") 31 | lazy val feFuncG = typedTag[dom.svg.FEFuncG]("feFuncG") 32 | lazy val feFuncR = typedTag[dom.svg.FEFuncR]("feFuncR") 33 | lazy val feGaussianBlur = typedTag[dom.svg.FEGaussianBlur]("feGaussianBlur") 34 | lazy val feImage = typedTag[dom.svg.FEImage]("feImage") 35 | lazy val feMerge = typedTag[dom.svg.FEMerge]("feMerge") 36 | lazy val feMergeNode = typedTag[dom.svg.FEMergeNode]("feMergeNode") 37 | lazy val feMorphology = typedTag[dom.svg.FEMorphology]("feMorphology") 38 | lazy val feOffset = typedTag[dom.svg.FEOffset]("feOffset") 39 | lazy val fePointLight = typedTag[dom.svg.FEPointLight]("fePointLight") 40 | lazy val feSpecularLighting = typedTag[dom.svg.FESpecularLighting]("feSpecularLighting") 41 | lazy val feSpotlight = typedTag[dom.svg.FESpotLight]("feSpotlight") 42 | lazy val feTile = typedTag[dom.svg.FETile]("feTile") 43 | lazy val feTurbulance = typedTag[dom.svg.FETurbulence]("feTurbulance") 44 | lazy val filter = typedTag[dom.svg.Filter]("filter") 45 | lazy val font = typedTag[dom.svg.Element]("font") 46 | lazy val `font-face` = typedTag[dom.svg.Element]("font-face") 47 | lazy val `font-face-format` = typedTag[dom.svg.Element]("font-face-format") 48 | lazy val `font-face-name` = typedTag[dom.svg.Element]("font-face-name") 49 | lazy val `font-face-src` = typedTag[dom.svg.Element]("font-face-src") 50 | lazy val `font-face-uri` = typedTag[dom.svg.Element]("font-face-uri") 51 | lazy val foreignObject = typedTag[dom.svg.Element]("foreignObject") 52 | lazy val g = typedTag[dom.svg.G]("g") 53 | lazy val glyph = typedTag[dom.svg.Element]("glyph") 54 | lazy val glyphRef = typedTag[dom.svg.Element]("glyphRef") 55 | lazy val hkern = typedTag[dom.svg.Element]("hkern") 56 | lazy val image = typedTag[dom.svg.Image]("image") 57 | lazy val line = typedTag[dom.svg.Line]("line") 58 | lazy val linearGradient = typedTag[dom.svg.LinearGradient]("linearGradient") 59 | lazy val marker = typedTag[dom.svg.Marker]("marker") 60 | lazy val mask = typedTag[dom.svg.Mask]("mask") 61 | lazy val metadata = typedTag[dom.svg.Metadata]("metadata") 62 | lazy val `missing-glyph` = typedTag[dom.svg.Element]("missing-glyph") 63 | lazy val mpath = typedTag[dom.svg.Element]("mpath") 64 | lazy val path = typedTag[dom.svg.Path]("path") 65 | lazy val pattern = typedTag[dom.svg.Pattern]("pattern") 66 | lazy val polygon = typedTag[dom.svg.Polygon]("polygon") 67 | lazy val polyline = typedTag[dom.svg.Polyline]("polyline") 68 | lazy val radialGradient = typedTag[dom.svg.RadialGradient]("radialGradient") 69 | lazy val rect = typedTag[dom.svg.RectElement]("rect") 70 | lazy val set = typedTag[dom.svg.Element]("set") 71 | lazy val stop = typedTag[dom.svg.Stop]("stop") 72 | lazy val svg = typedTag[dom.svg.SVG]("svg") 73 | lazy val switch = typedTag[dom.svg.Switch]("switch") 74 | lazy val symbol = typedTag[dom.svg.Symbol]("symbol") 75 | lazy val text = typedTag[dom.svg.Text]("text") 76 | lazy val textPath = typedTag[dom.svg.TextPath]("textPath") 77 | lazy val tref = typedTag[dom.svg.Element]("tref") 78 | lazy val tspan = typedTag[dom.svg.TSpan]("tspan") 79 | lazy val use = typedTag[dom.svg.Use]("use") 80 | lazy val view = typedTag[dom.svg.View]("view") 81 | lazy val vkern = typedTag[dom.svg.Element]("vkern") 82 | } 83 | -------------------------------------------------------------------------------- /scalatags/src-js/scalatags/jsdom/TagFactory.scala: -------------------------------------------------------------------------------- 1 | package scalatags.jsdom 2 | 3 | import org.scalajs.dom 4 | 5 | import scalatags.Escaping 6 | import scalatags.generic.Namespace 7 | 8 | /** 9 | * Created by haoyi on 7/9/16. 10 | */ 11 | trait TagFactory extends scalatags.generic.Util[dom.Element, dom.Element, dom.Node]{ 12 | def tag(s: String, void: Boolean = false): ConcreteHtmlTag[dom.Element] = { 13 | typedTag[dom.Element](s, void) 14 | } 15 | def typedTag[T <: dom.Element](s: String, void: Boolean = false) 16 | (implicit ns: Namespace): ConcreteHtmlTag[T] = { 17 | if (!Escaping.validTag(s)) 18 | throw new IllegalArgumentException( 19 | s"Illegal tag name: $s is not a valid XML tag name" 20 | ) 21 | makeAbstractTypedTag[T](s, void, ns) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scalatags/src-js/scalatags/jsdom/Tags.scala: -------------------------------------------------------------------------------- 1 | 2 | package scalatags 3 | package jsdom 4 | import org.scalajs.dom 5 | import scalatags.generic.Util 6 | trait Tags extends generic.Tags[dom.Element, dom.Element, dom.Node] with TagFactory{ 7 | // Root Element 8 | lazy val html: ConcreteHtmlTag[dom.html.Html] = typedTag[dom.html.Html]("html") 9 | // Document Metadata 10 | lazy val head: ConcreteHtmlTag[dom.html.Head] = typedTag[dom.html.Head]("head") 11 | lazy val base: ConcreteHtmlTag[dom.html.Base] = typedTag[dom.html.Base]("base", void = true) 12 | lazy val link: ConcreteHtmlTag[dom.html.Link] = typedTag[dom.html.Link]("link", void = true) 13 | lazy val meta: ConcreteHtmlTag[dom.html.Meta] = typedTag[dom.html.Meta]("meta", void = true) 14 | // Scripting 15 | lazy val script: ConcreteHtmlTag[dom.html.Script] = typedTag[dom.html.Script]("script") 16 | // Sections 17 | lazy val body: ConcreteHtmlTag[dom.html.Body] = typedTag[dom.html.Body]("body") 18 | lazy val h1 = typedTag[dom.html.Heading]("h1") 19 | lazy val h2 = typedTag[dom.html.Heading]("h2") 20 | lazy val h3 = typedTag[dom.html.Heading]("h3") 21 | lazy val h4 = typedTag[dom.html.Heading]("h4") 22 | lazy val h5 = typedTag[dom.html.Heading]("h5") 23 | lazy val h6 = typedTag[dom.html.Heading]("h6") 24 | lazy val header: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("header") 25 | lazy val footer: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("footer") 26 | // Grouping content 27 | lazy val p: ConcreteHtmlTag[dom.html.Paragraph] = typedTag[dom.html.Paragraph]("p") 28 | lazy val hr: ConcreteHtmlTag[dom.html.HR] = typedTag[dom.html.HR]("hr", void = true) 29 | lazy val pre: ConcreteHtmlTag[dom.html.Pre] = typedTag[dom.html.Pre]("pre") 30 | lazy val blockquote: ConcreteHtmlTag[dom.html.Quote] = typedTag[dom.html.Quote]("blockquote") 31 | lazy val ol: ConcreteHtmlTag[dom.html.OList] = typedTag[dom.html.OList]("ol") 32 | lazy val ul: ConcreteHtmlTag[dom.html.UList] = typedTag[dom.html.UList]("ul") 33 | lazy val li: ConcreteHtmlTag[dom.html.LI] = typedTag[dom.html.LI]("li") 34 | lazy val dl: ConcreteHtmlTag[dom.html.DList] = typedTag[dom.html.DList]("dl") 35 | lazy val dt: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("dt") 36 | lazy val dd: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("dd") 37 | lazy val figure: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("figure") 38 | lazy val figcaption: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("figcaption") 39 | lazy val div: ConcreteHtmlTag[dom.html.Div] = typedTag[dom.html.Div]("div") 40 | // Text-level semantics 41 | lazy val a: ConcreteHtmlTag[dom.html.Anchor] = typedTag[dom.html.Anchor]("a") 42 | lazy val em: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("em") 43 | lazy val strong: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("strong") 44 | lazy val small: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("small") 45 | lazy val s: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("s") 46 | lazy val cite: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("cite") 47 | lazy val code: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("code") 48 | lazy val sub: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("sub") 49 | lazy val sup: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("sup") 50 | lazy val i: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("i") 51 | lazy val b: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("b") 52 | lazy val u: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("u") 53 | lazy val span: ConcreteHtmlTag[dom.html.Span] = typedTag[dom.html.Span]("span") 54 | lazy val br: ConcreteHtmlTag[dom.html.BR] = typedTag[dom.html.BR]("br", void = true) 55 | lazy val wbr: ConcreteHtmlTag[dom.html.Element] = typedTag[dom.html.Element]("wbr", void = true) 56 | // Edits 57 | lazy val ins: ConcreteHtmlTag[dom.html.Mod] = typedTag[dom.html.Mod]("ins") 58 | lazy val del: ConcreteHtmlTag[dom.html.Mod] = typedTag[dom.html.Mod]("del") 59 | // Embedded content 60 | lazy val img: ConcreteHtmlTag[dom.html.Image] = typedTag[dom.html.Image]("img", void = true) 61 | lazy val iframe: ConcreteHtmlTag[dom.html.IFrame] = typedTag[dom.html.IFrame]("iframe") 62 | lazy val embed: ConcreteHtmlTag[dom.html.Embed] = typedTag[dom.html.Embed]("embed", void = true) 63 | lazy val `object` = typedTag[dom.html.Object]("object") 64 | lazy val param: ConcreteHtmlTag[dom.html.Param] = typedTag[dom.html.Param]("param", void = true) 65 | lazy val video: ConcreteHtmlTag[dom.html.Video] = typedTag[dom.html.Video]("video") 66 | lazy val audio: ConcreteHtmlTag[dom.html.Audio] = typedTag[dom.html.Audio]("audio") 67 | lazy val source: ConcreteHtmlTag[dom.html.Source] = typedTag[dom.html.Source]("source", void = true) 68 | lazy val track: ConcreteHtmlTag[dom.html.Track] = typedTag[dom.html.Track]("track", void = true) 69 | lazy val canvas: ConcreteHtmlTag[dom.html.Canvas] = typedTag[dom.html.Canvas]("canvas") 70 | lazy val map: ConcreteHtmlTag[dom.html.Map] = typedTag[dom.html.Map]("map") 71 | lazy val area: ConcreteHtmlTag[dom.html.Area] = typedTag[dom.html.Area]("area", void = true) 72 | // Tabular data 73 | lazy val table: ConcreteHtmlTag[dom.html.Table] = typedTag[dom.html.Table]("table") 74 | lazy val caption: ConcreteHtmlTag[dom.html.TableCaption] = typedTag[dom.html.TableCaption]("caption") 75 | lazy val colgroup: ConcreteHtmlTag[dom.html.TableCol] = typedTag[dom.html.TableCol]("colgroup") 76 | lazy val col: ConcreteHtmlTag[dom.html.TableCol] = typedTag[dom.html.TableCol]("col", void = true) 77 | lazy val tbody: ConcreteHtmlTag[dom.html.TableSection] = typedTag[dom.html.TableSection]("tbody") 78 | lazy val thead: ConcreteHtmlTag[dom.html.TableSection] = typedTag[dom.html.TableSection]("thead") 79 | lazy val tfoot: ConcreteHtmlTag[dom.html.TableSection] = typedTag[dom.html.TableSection]("tfoot") 80 | lazy val tr: ConcreteHtmlTag[dom.html.TableRow] = typedTag[dom.html.TableRow]("tr") 81 | lazy val td: ConcreteHtmlTag[dom.html.TableCell] = typedTag[dom.html.TableCell]("td") 82 | lazy val th: ConcreteHtmlTag[dom.html.TableCell] = typedTag[dom.html.TableCell]("th") 83 | // Forms 84 | lazy val form: ConcreteHtmlTag[dom.html.Form] = typedTag[dom.html.Form]("form") 85 | lazy val fieldset: ConcreteHtmlTag[dom.html.FieldSet] = typedTag[dom.html.FieldSet]("fieldset") 86 | lazy val legend: ConcreteHtmlTag[dom.html.Legend] = typedTag[dom.html.Legend]("legend") 87 | lazy val label: ConcreteHtmlTag[dom.html.Label] = typedTag[dom.html.Label]("label") 88 | lazy val input: ConcreteHtmlTag[dom.html.Input] = typedTag[dom.html.Input]("input", void = true) 89 | lazy val button: ConcreteHtmlTag[dom.html.Button] = typedTag[dom.html.Button]("button") 90 | lazy val select: ConcreteHtmlTag[dom.html.Select] = typedTag[dom.html.Select]("select") 91 | lazy val datalist: ConcreteHtmlTag[dom.html.DataList] = typedTag[dom.html.DataList]("datalist") 92 | lazy val optgroup: ConcreteHtmlTag[dom.html.OptGroup] = typedTag[dom.html.OptGroup]("optgroup") 93 | lazy val option: ConcreteHtmlTag[dom.html.Option] = typedTag[dom.html.Option]("option") 94 | lazy val textarea: ConcreteHtmlTag[dom.html.TextArea] = typedTag[dom.html.TextArea]("textarea") 95 | } 96 | -------------------------------------------------------------------------------- /scalatags/src-js/scalatags/jsdom/Tags2.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package jsdom 3 | import org.scalajs.dom 4 | import org.scalajs.dom.html 5 | import scalatags.generic.Util 6 | trait Tags2 extends generic.Tags2[dom.Element, dom.Element, dom.Node] with TagFactory{ 7 | // Document Metadata 8 | lazy val title = typedTag[html.Title]("title") 9 | lazy val style = typedTag[html.Style]("style") 10 | // Scripting 11 | lazy val noscript = typedTag[html.Element]("noscript") 12 | // Sections 13 | lazy val section = typedTag[html.Element]("section") 14 | lazy val nav = typedTag[html.Element]("nav") 15 | lazy val article = typedTag[html.Element]("article") 16 | lazy val aside = typedTag[html.Element]("aside") 17 | lazy val address = typedTag[html.Element]("address") 18 | lazy val main = typedTag[html.Element]("main") 19 | // Text level semantics 20 | lazy val q = typedTag[html.Quote]("q") 21 | lazy val dfn = typedTag[html.Element]("dfn") 22 | lazy val abbr = typedTag[html.Element]("abbr") 23 | lazy val data = typedTag[html.Element]("data") 24 | lazy val time = typedTag[html.Element]("time") 25 | lazy val `var` = typedTag[html.Element]("var") 26 | lazy val samp = typedTag[html.Element]("samp") 27 | lazy val kbd = typedTag[html.Element]("kbd") 28 | lazy val math = typedTag[html.Element]("math") 29 | lazy val mark = typedTag[html.Element]("mark") 30 | lazy val ruby = typedTag[html.Element]("ruby") 31 | lazy val rt = typedTag[html.Element]("rt") 32 | lazy val rp = typedTag[html.Element]("rp") 33 | lazy val bdi = typedTag[html.Element]("bdi") 34 | lazy val bdo = typedTag[html.Element]("bdo") 35 | // Forms 36 | lazy val keygen = typedTag[html.Element]("keygen", void = true) 37 | lazy val output = typedTag[html.Element]("output") 38 | lazy val progress = typedTag[html.Progress]("progress") 39 | lazy val meter = typedTag[html.Element]("meter") 40 | // Interactive elements 41 | lazy val details = typedTag[html.Element]("details") 42 | lazy val summary = typedTag[html.Element]("summary") 43 | lazy val command = typedTag[html.Element]("command", void = true) 44 | lazy val menu = typedTag[html.Menu]("menu") 45 | } 46 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/DataTypes.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | 3 | import scala.language.implicitConversions 4 | 5 | /** 6 | * Module containing convenient ways of constructing CSS data types 7 | */ 8 | object DataConverters extends DataConverters 9 | 10 | 11 | /** 12 | * Trait containing the contents of the [[DataConverters]] module, so it can be 13 | * mixed in to other objects as needed. 14 | */ 15 | trait DataConverters{ 16 | implicit def Int2CssNumber(x: Int): CssNumber[Int] = new CssNumber(x) 17 | implicit def Double2CssNumber(x: Double): CssNumber[Double] = new CssNumber(x) 18 | implicit def Float2CssNumber(x: Float): CssNumber[Float] = new CssNumber(x) 19 | implicit def Long2CssNumber(x: Long): CssNumber[Long] = new CssNumber(x) 20 | implicit def Short2CssNumber(x: Short): CssNumber[Short] = new CssNumber(x) 21 | implicit def Byte2CssNumber(x: Byte): CssNumber[Byte] = new CssNumber(x) 22 | /** 23 | * Extends numbers to provide a bunch of useful methods, allowing you to write 24 | * CSS-lengths in a nice syntax without resorting to strings. 25 | */ 26 | class CssNumber[T: Numeric](x: T){ 27 | 28 | /** 29 | * Relative to the viewing device. For screen display, typically one device 30 | * pixel (dot) of the display. 31 | * 32 | * For printers and very high resolution screens one CSS pixel implies 33 | * multiple device pixels, so that the number of pixel per inch stays around 34 | * 96. 35 | * 36 | * MDN 37 | */ 38 | def px = s"${x}px" 39 | 40 | /** 41 | * One point which is 1/72 of an inch. 42 | * 43 | * MDN 44 | */ 45 | def pt = s"${x}pt" 46 | 47 | /** 48 | * One millimeter. 49 | * 50 | * MDN 51 | */ 52 | def mm = s"${x}mm" 53 | 54 | /** 55 | * One centimeter 10 millimeters. 56 | * 57 | * MDN 58 | */ 59 | def cm = s"${x}cm" 60 | 61 | /** 62 | * One inch 2.54 centimeters. 63 | * 64 | * MDN 65 | */ 66 | def in = s"${x}in" 67 | 68 | /** 69 | * One pica which is 12 points. 70 | * 71 | * MDN 72 | */ 73 | def pc = s"${x}pc" 74 | /** 75 | * This unit represents the calculated font-size of the element. If used on 76 | * the font-size property itself, it represents the inherited font-size 77 | * of the element. 78 | * 79 | * MDN 80 | */ 81 | def em = s"${x}em" 82 | 83 | /** 84 | * This unit represents the width, or more precisely the advance measure, of 85 | * the glyph '0' zero, the Unicode character U+0030 in the element's font. 86 | * 87 | * MDN 88 | */ 89 | def ch = s"${x}ch" 90 | 91 | /** 92 | * This unit represents the x-height of the element's font. On fonts with the 93 | * 'x' letter, this is generally the height of lowercase letters in the font; 94 | * 1ex ≈ 0.5em in many fonts. 95 | * 96 | * MDN 97 | */ 98 | def ex = s"${x}ex" 99 | 100 | /** 101 | * This unit represents the font-size of the root element e.g. the font-size 102 | * of the html element. When used on the font-size on this root element, 103 | * it represents its initial value. 104 | * 105 | * MDN 106 | */ 107 | def rem = s"${x}rem" 108 | 109 | /** 110 | * An angle in degrees. One full circle is 360deg. E.g. 0deg, 90deg, 360deg. 111 | */ 112 | def deg = s"${x}deg" 113 | 114 | /** 115 | * An angle in gradians. One full circle is 400grad. E.g. 0grad, 100grad, 116 | * 400grad. 117 | * 118 | * MDN 119 | */ 120 | def grad = s"${x}grad" 121 | 122 | /** 123 | * An angle in radians. One full circle is 2π radians which approximates 124 | * to 6.2832rad. 1rad is 180/π degrees. E.g. 0rad, 1.0708rad, 6.2832rad. 125 | * 126 | * MDN 127 | */ 128 | def rad = s"${x}rad" 129 | 130 | /** 131 | * The number of turns the angle is. One full circle is 1turn. E.g. 0turn, 132 | * 0.25turn, 1turn. 133 | * 134 | * MDN 135 | */ 136 | def turn = s"${x}turn" 137 | 138 | /** 139 | * A percentage value 140 | */ 141 | def pct = s"${x}%" 142 | } 143 | } 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/Escaping.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | /** 3 | * Utility methods related to validating and escaping XML; used internally but 4 | * potentially useful outside of Scalatags. 5 | */ 6 | object Escaping { 7 | 8 | private[this] val tagRegex = "^[a-z][:\\w0-9-]*$".r 9 | 10 | /** 11 | * Uses a regex to check if something is a valid tag name. 12 | */ 13 | def validTag(s: String) = tagRegex.unapplySeq(s).isDefined 14 | 15 | /** 16 | * Check if 's' is a valid attribute name. 17 | */ 18 | def validAttrName(s: String): Boolean = { 19 | // this is equivalent of the regex but without a huge amount of object creation. 20 | // original regex - ^[a-zA-Z_:][-a-zA-Z0-9_:.]*$ 21 | // n.b. I know its ugly, but its fast 22 | val len = s.length 23 | if(len == 0) 24 | return false 25 | 26 | val sc = s.charAt(0) 27 | val startCharValid = (sc >= 'a' && sc <='z') || (sc >= 'A' && sc <='Z') || sc ==':' 28 | if(!startCharValid) 29 | return false 30 | 31 | var pos = 1 32 | while (pos < len) { 33 | val c = s.charAt(pos) 34 | val valid = (c >= 'a' && c <='z') || (c >= 'A' && c <='Z') || (c >= '0' && c <='9') || 35 | c == '-' || c ==':' || c =='.' || c == '_' 36 | if(!valid) 37 | return false 38 | pos += 1 39 | } 40 | 41 | true 42 | } 43 | 44 | /** 45 | * Code to escape text HTML nodes. Based on code from scala.xml 46 | */ 47 | def escape(text: String, s: java.io.Writer) = { 48 | // Implemented per XML spec: 49 | // http://www.w3.org/International/questions/qa-controls 50 | // Highly imperative code, ~2-3x faster than the previous implementation (2020-06-11) 51 | val charsArray = text.toCharArray 52 | val len = charsArray.size 53 | var pos = 0 54 | var i = 0 55 | while (i < len) { 56 | val c = charsArray(i) 57 | c match { 58 | case '<' => 59 | s.write(charsArray, pos, i - pos) 60 | s.write("<") 61 | pos = i + 1 62 | case '>' => 63 | s.write(charsArray, pos, i - pos) 64 | s.write(">") 65 | pos = i + 1 66 | case '&' => 67 | s.write(charsArray, pos, i - pos) 68 | s.write("&") 69 | pos = i + 1 70 | case '"' => 71 | s.write(charsArray, pos, i - pos) 72 | s.write(""") 73 | pos = i + 1 74 | case '\n' => 75 | case '\r' => 76 | case '\t' => 77 | case c if c < ' ' => 78 | s.write(charsArray, pos, i - pos) 79 | pos = i + 1 80 | case _ => 81 | } 82 | i += 1 83 | } 84 | // Apparently this isn't technically necessary if (len - pos) == 0 as 85 | // it doesn't cause any exception to occur in the JVM. 86 | // The problem is that it isn't documented anywhere so I left this if here 87 | // to make the error clear. 88 | if (pos < len) { 89 | s.write(charsArray, pos, len - pos) 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/Text.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | import java.util.Objects 3 | 4 | import scalatags.generic._ 5 | import scala.annotation.unchecked.uncheckedVariance 6 | import scalatags.stylesheet.{StyleSheetFrag, StyleTree} 7 | import scalatags.text.Builder 8 | 9 | import scala.language.implicitConversions 10 | 11 | /** 12 | * A Scalatags module that works with a text back-end, i.e. it creates HTML 13 | * `String`s. 14 | */ 15 | 16 | 17 | object Text 18 | extends generic.Bundle[text.Builder, String, String] 19 | with Aliases[text.Builder, String, String]{ 20 | object attrs extends Text.Cap with Attrs 21 | object tags extends Text.Cap with text.Tags 22 | object tags2 extends Text.Cap with text.Tags2 23 | object styles extends Text.Cap with Styles 24 | object styles2 extends Text.Cap with Styles2 25 | 26 | object svgTags extends Text.Cap with text.SvgTags 27 | object svgAttrs extends Text.Cap with SvgAttrs 28 | 29 | object implicits extends Aggregate with DataConverters 30 | 31 | object all 32 | extends Cap 33 | with Attrs 34 | with Styles 35 | with text.Tags 36 | with DataConverters 37 | with Aggregate 38 | 39 | object short 40 | extends Cap 41 | with text.Tags 42 | with DataConverters 43 | with Aggregate 44 | with AbstractShort{ 45 | 46 | object * extends Cap with Attrs with Styles 47 | } 48 | 49 | trait Cap extends Util with text.TagFactory{ self => 50 | type ConcreteHtmlTag[T <: String] = TypedTag[T] 51 | type BaseTagType = TypedTag[String] 52 | protected[this] implicit def stringAttrX = new GenericAttr[String] 53 | protected[this] implicit def stringStyleX = new GenericStyle[String] 54 | protected[this] implicit def stringPixelStyleX = new GenericPixelStyle[String](stringStyleX) 55 | implicit def UnitFrag(u: Unit) = new Text.StringFrag("") 56 | def makeAbstractTypedTag[T <: String](tag: String, void: Boolean, namespaceConfig: Namespace): TypedTag[T] = { 57 | TypedTag(tag, Nil, void) 58 | } 59 | implicit class SeqFrag[A](xs: Seq[A])(implicit ev: A => Frag) extends Frag{ 60 | Objects.requireNonNull(xs) 61 | def applyTo(t: text.Builder) = xs.foreach(elem => ev(elem).applyTo(t)) 62 | def render = xs.map(elem => ev(elem).render).mkString 63 | } 64 | implicit class GeneratorFrag[A](xs: geny.Generator[A])(implicit ev: A => Frag) extends Frag{ 65 | Objects.requireNonNull(xs) 66 | def applyTo(t: text.Builder) = xs.foreach(elem => ev(elem).applyTo(t)) 67 | def render = xs.map(elem => ev(elem).render).mkString 68 | } 69 | 70 | case class doctype(s: String)(content: text.Frag) extends geny.Writable{ 71 | override def httpContentType = Some("text/html") 72 | def writeTo(strb: java.io.Writer): Unit = { 73 | strb.write(s"") 74 | content.writeTo(strb) 75 | } 76 | def writeBytesTo(out: java.io.OutputStream): Unit = { 77 | val w = new java.io.OutputStreamWriter(out, java.nio.charset.StandardCharsets.UTF_8) 78 | writeTo(w) 79 | w.flush() 80 | } 81 | def render = { 82 | val strb = new java.io.StringWriter() 83 | writeTo(strb) 84 | strb.toString() 85 | } 86 | } 87 | } 88 | 89 | trait Aggregate extends generic.Aggregate[text.Builder, String, String]{ 90 | implicit def ClsModifier(s: stylesheet.Cls): Modifier = new Modifier with text.Builder.ValueSource{ 91 | def applyTo(t: text.Builder) = t.appendAttr("class",this) 92 | 93 | override def appendAttrValue(sb: java.io.Writer): Unit = { 94 | Escaping.escape(s.name, sb) 95 | } 96 | } 97 | implicit class StyleFrag(s: generic.StylePair[text.Builder, _]) extends StyleSheetFrag{ 98 | def applyTo(c: StyleTree) = { 99 | val b = new Builder() 100 | s.applyTo(b) 101 | val Array(style, value) = b.attrsString(b.attrs(b.attrIndex("style"))._2).split(":", 2) 102 | c.copy(styles = c.styles.updated(style, value)) 103 | } 104 | } 105 | 106 | def genericAttr[T] = new Text.GenericAttr[T] 107 | def genericStyle[T] = new Text.GenericStyle[T] 108 | def genericPixelStyle[T](implicit ev: StyleValue[T]): PixelStyleValue[T] = new Text.GenericPixelStyle[T](ev) 109 | def genericPixelStylePx[T](implicit ev: StyleValue[String]): PixelStyleValue[T] = new Text.GenericPixelStylePx[T](ev) 110 | 111 | implicit def stringFrag(v: String) = new Text.StringFrag(v) 112 | 113 | val RawFrag = Text.RawFrag 114 | val StringFrag = Text.StringFrag 115 | type StringFrag = Text.StringFrag 116 | type RawFrag = Text.RawFrag 117 | def raw(s: String) = RawFrag(s) 118 | 119 | 120 | val Tag = Text.TypedTag 121 | } 122 | 123 | 124 | 125 | case class StringFrag(v: String) extends text.Frag{ 126 | Objects.requireNonNull(v) 127 | def render = { 128 | val strb = new java.io.StringWriter() 129 | writeTo(strb) 130 | strb.toString() 131 | } 132 | def writeTo(strb: java.io.Writer) = Escaping.escape(v, strb) 133 | } 134 | 135 | case class RawFrag(v: String) extends text.Frag{ 136 | Objects.requireNonNull(v) 137 | def render = v 138 | def writeTo(strb: java.io.Writer) = strb.append(v) 139 | } 140 | 141 | class GenericAttr[T] extends AttrValue[T] { 142 | def apply(t: text.Builder, a: Attr, v: T): Unit = { 143 | t.setAttr(a.name, Builder.GenericAttrValueSource(v.toString)) 144 | } 145 | } 146 | 147 | class GenericStyle[T] extends StyleValue[T] { 148 | def apply(t: text.Builder, s: Style, v: T): Unit = { 149 | t.appendAttr("style", Builder.StyleValueSource(s, v.toString)) 150 | } 151 | } 152 | class GenericPixelStyle[T](ev: StyleValue[T]) extends PixelStyleValue[T]{ 153 | def apply(s: Style, v: T) = StylePair(s, v, ev) 154 | } 155 | class GenericPixelStylePx[T](ev: StyleValue[String]) extends PixelStyleValue[T]{ 156 | def apply(s: Style, v: T) = { 157 | StylePair(s, s"${v}px", ev) 158 | } 159 | } 160 | 161 | 162 | 163 | case class TypedTag[+Output <: String](tag: String = "", 164 | modifiers: List[Seq[Modifier]], 165 | void: Boolean = false) 166 | extends generic.TypedTag[text.Builder, Output, String] 167 | with text.Frag with geny.Writable{ 168 | override def httpContentType = Some("text/html") 169 | // unchecked because Scala 2.10.4 seems to not like this, even though 170 | // 2.11.1 works just fine. I trust that 2.11.1 is more correct than 2.10.4 171 | // and so just force this. 172 | protected[this] type Self = TypedTag[Output @uncheckedVariance] 173 | 174 | /** 175 | * Serialize this [[TypedTag]] and all its children out to the given StringBuilder. 176 | * 177 | * Although the external interface is pretty simple, the internals are a huge mess, 178 | * because I've inlined a whole lot of things to improve the performance of this code 179 | * ~4x from what it originally was, which is a pretty nice speedup 180 | */ 181 | def writeTo(strb: java.io.Writer): Unit = { 182 | val builder = new text.Builder() 183 | build(builder) 184 | 185 | // tag 186 | strb.append('<').append(tag) 187 | 188 | // attributes 189 | var i = 0 190 | while (i < builder.attrIndex){ 191 | val pair = builder.attrs(i) 192 | strb.append(' ').append(pair._1).append("=\"") 193 | builder.appendAttrStrings(pair._2,strb) 194 | strb.append('\"') 195 | i += 1 196 | } 197 | 198 | if (builder.childIndex == 0 && void) { 199 | // No children - close tag 200 | strb.append(" />") 201 | } else { 202 | strb.append('>') 203 | // Childrens 204 | var i = 0 205 | while(i < builder.childIndex){ 206 | builder.children(i).writeTo(strb) 207 | i += 1 208 | } 209 | 210 | // Closing tag 211 | strb.append("").append(tag).append('>') 212 | } 213 | } 214 | 215 | def apply(xs: Modifier*): TypedTag[Output] = { 216 | this.copy(tag=tag, void = void, modifiers = xs :: modifiers) 217 | } 218 | 219 | /** 220 | * Converts an ScalaTag fragment into an html string 221 | */ 222 | override def toString = { 223 | val strb = new java.io.StringWriter 224 | writeTo(strb) 225 | strb.toString() 226 | } 227 | def render: Output = this.toString.asInstanceOf[Output] 228 | } 229 | 230 | 231 | } 232 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/VirtualDom.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | 3 | import java.util.Objects 4 | 5 | import scalatags.generic.{Aliases, Namespace, StylePair} 6 | import scalatags.stylesheet.{StyleSheetFrag, StyleTree} 7 | 8 | import scala.annotation.unchecked.uncheckedVariance 9 | import scala.language.implicitConversions 10 | 11 | /** 12 | * A Scalatags module that can be configured to construct arbitrary virtual DOM 13 | * fragments of uniform type 14 | * 15 | * Simply instantiate it with `stringToFrag` and `rawToFrag` factory to construct 16 | * `Frag`, and a `makeBuilder` factory to construct `Tag`s, and you can then use 17 | * it to instantiate any sort of virtual DOM of uniform type: scala.xml trees, 18 | * Preact/React VDOM nodes in the browser, etc. 19 | */ 20 | trait VirtualDom[Output <: FragT, FragT] 21 | extends generic.Bundle[vdom.Builder[Output, FragT], Output, FragT] 22 | with Aliases[vdom.Builder[Output, FragT], Output, FragT]{ 23 | 24 | def stringToFrag(s: String): FragT 25 | def rawToFrag(s: String): FragT 26 | def makeBuilder(tag: String): vdom.Builder[Output, FragT] 27 | object attrs extends Cap with Attrs 28 | object tags extends Cap with vdom.Tags[Output, FragT] 29 | object tags2 extends Cap with vdom.Tags2[Output, FragT] 30 | object styles extends Cap with Styles 31 | object styles2 extends Cap with Styles2 32 | object svgTags extends Cap with vdom.SvgTags[Output, FragT] 33 | object svgAttrs extends Cap with SvgAttrs 34 | 35 | object implicits extends Aggregate with DataConverters 36 | 37 | object all 38 | extends Cap 39 | with Attrs 40 | with Styles 41 | with vdom.Tags[Output, FragT] 42 | with DataConverters 43 | with Aggregate 44 | 45 | object short 46 | extends Cap 47 | with vdom.Tags[Output, FragT] 48 | with DataConverters 49 | with Aggregate 50 | with AbstractShort{ 51 | 52 | object * extends Cap with Attrs with Styles 53 | } 54 | 55 | 56 | trait Aggregate extends generic.Aggregate[vdom.Builder[Output, FragT], Output, FragT]{ 57 | implicit class ApplyTags(e: vdom.Builder[Output, FragT]){ 58 | def applyTags(mods: Modifier*) = mods.foreach(_.applyTo(e)) 59 | } 60 | implicit def ClsModifier(s: stylesheet.Cls): Modifier = new Modifier{ 61 | def applyTo(t: vdom.Builder[Output, FragT]) = { 62 | t.appendClass(s.name) 63 | 64 | } 65 | } 66 | implicit class StyleFrag(s: generic.StylePair[vdom.Builder[Output, FragT], _]) extends StyleSheetFrag{ 67 | def applyTo(c: StyleTree) = { 68 | ??? 69 | // val b = makeBuilder 70 | // s.applyTo(b) 71 | // val Array(style, value) = b.attrs.get("style").map(_.split(":", 2)) 72 | // .getOrElse(throw new IllegalArgumentException(s"Cannot apply style $s. Does it contain a syntax error?")) 73 | // c.copy(styles = c.styles.updated(style, value)) 74 | } 75 | } 76 | 77 | 78 | def genericAttr[T] = new GenericAttr[T] 79 | def genericStyle[T] = new GenericStyle[T] 80 | def genericPixelStyle[T](implicit ev: StyleValue[T]): PixelStyleValue[T] = new GenericPixelStyle[T](ev) 81 | def genericPixelStylePx[T](implicit ev: StyleValue[String]): PixelStyleValue[T] = new GenericPixelStylePx[T](ev) 82 | 83 | implicit def stringFrag(v: String): StringFrag = new VirtualDom.this.StringFrag(v) 84 | 85 | 86 | val RawFrag = VirtualDom.this.RawFrag 87 | val StringFrag = VirtualDom.this.StringFrag 88 | type StringFrag = VirtualDom.this.StringFrag 89 | type RawFrag = VirtualDom.this.RawFrag 90 | def raw(s: String) = RawFrag(s) 91 | 92 | val Tag = TypedTag 93 | } 94 | 95 | trait Cap extends Util with vdom.TagFactory[Output, FragT]{ self => 96 | type ConcreteHtmlTag[T <: Output] = TypedTag[T] 97 | 98 | protected[this] implicit def stringAttrX = new GenericAttr[String] 99 | protected[this] implicit def stringStyleX = new GenericStyle[String] 100 | protected[this] implicit def stringPixelStyleX = new GenericPixelStyle[String](stringStyleX) 101 | implicit def UnitFrag(u: Unit): VirtualDom.this.StringFrag = new VirtualDom.this.StringFrag("") 102 | def makeAbstractTypedTag[T <: Output](tag: String, void: Boolean, namespaceConfig: Namespace): TypedTag[T] = { 103 | TypedTag(tag, Nil, void, namespaceConfig) 104 | } 105 | 106 | implicit class SeqFrag[A](xs: Seq[A])(implicit ev: A => Frag) extends Frag{ 107 | Objects.requireNonNull(xs) 108 | def applyTo(t: vdom.Builder[Output, FragT]): Unit = xs.foreach(elem => ev(elem).applyTo(t)) 109 | def render: FragT = { 110 | throw new Exception("Rendering of bare arrays of nodes is not supported in virtual dom backend") 111 | } 112 | } 113 | implicit class GeneratorFrag[A](xs: geny.Generator[A])(implicit ev: A => Frag) extends Frag{ 114 | Objects.requireNonNull(xs) 115 | def applyTo(t: vdom.Builder[Output, FragT]): Unit = xs.foreach(elem => ev(elem).applyTo(t)) 116 | def render: FragT = { 117 | throw new Exception("Rendering of bare arrays of nodes is not supported in virtual dom backend") 118 | } 119 | } 120 | } 121 | 122 | case class StringFrag(v: String) extends vdom.Frag[Output, FragT]{ 123 | Objects.requireNonNull(v) 124 | def render: FragT = stringToFrag(v) 125 | } 126 | 127 | case class RawFrag(v: String) extends vdom.Frag[Output, FragT]{ 128 | Objects.requireNonNull(v) 129 | def render = rawToFrag(v) 130 | } 131 | 132 | class GenericAttr[T] extends AttrValue[T]{ 133 | def apply(t: vdom.Builder[Output, FragT], a: Attr, v: T): Unit = { 134 | t.setAttr(a.name, v.toString) 135 | } 136 | } 137 | 138 | class GenericStyle[T] extends StyleValue[T]{ 139 | def apply(t: vdom.Builder[Output, FragT], s: Style, v: T): Unit = { 140 | t.appendStyle(s.cssName, v.toString) 141 | } 142 | } 143 | class GenericPixelStyle[T](ev: StyleValue[T]) extends PixelStyleValue[T]{ 144 | def apply(s: Style, v: T) = StylePair(s, v, ev) 145 | } 146 | class GenericPixelStylePx[T](ev: StyleValue[String]) extends PixelStyleValue[T]{ 147 | def apply(s: Style, v: T) = StylePair(s, s"${v}px", ev) 148 | } 149 | case class TypedTag[+O <: Output](tag: String = "", 150 | modifiers: List[Seq[Modifier]], 151 | void: Boolean = false, 152 | namespace: Namespace) 153 | extends generic.TypedTag[vdom.Builder[Output, FragT], O, FragT] 154 | with vdom.Frag[Output, FragT]{ 155 | // unchecked because Scala 2.10.4 seems to not like this, even though 156 | // 2.11.1 works just fine. I trust that 2.11.1 is more correct than 2.10.4 157 | // and so just force this. 158 | protected[this] type Self = TypedTag[O @uncheckedVariance] 159 | 160 | def render: O = { 161 | val builder = makeBuilder(tag) 162 | build(builder) 163 | builder.render().asInstanceOf[O] 164 | } 165 | /** 166 | * Trivial override, not strictly necessary, but it makes IntelliJ happy... 167 | */ 168 | def apply(xs: Modifier*): TypedTag[O] = { 169 | this.copy(tag = tag, void = void, modifiers = xs :: modifiers) 170 | } 171 | } 172 | 173 | } 174 | 175 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/generic/Bundle.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package generic 3 | import scalatags.stylesheet.StyleSheetFrag 4 | import scalatags.text 5 | 6 | import scala.language.implicitConversions 7 | 8 | /** 9 | * An abstract representation of the Scalatags package. This allows you to 10 | * customize Scalatags to work with different backends, by defining your own 11 | * implementation of `Tag`, and specifying how the various [[Attr]]s 12 | * and [[Style]]s contribute to construct the [[Builder]]. Apart from satisfying the 13 | * default String/Boolean/Numeric implementations of [[Attr]] and [[Style]], 14 | * you can also define your own, e.g. ScalaJS ships with an implicit conversion 15 | * from `js.Any` to `Attr`, so that you can attach objects to the resultant 16 | * `dom.Element` without serializing them. 17 | * 18 | * By default, Scalatags ships with [[scalatags.Text]]: `Bundle[StringBuilder]` 19 | * on all platforms, and [[scalatags.JsDom]]: `Bundle[dom.Element]` on ScalaJS. 20 | * 21 | * It is possible to write entirely backend-agnostic Scalatags code by making 22 | * your code parametric on a [[Bundle]] (or some subclass of it), and importing 23 | * from that rather than importing directly from [[scalatags.JsDom]] or 24 | * [[scalatags.Text]]. You will naturally only be able to use functionality 25 | * (e.g. implicit conversions to [[Attr]]s and [[Style]]s which are present 26 | * in the common interface. 27 | * 28 | * @tparam Builder The type to which [[Attr]]s and [[Style]]s are applied to when the 29 | * `Tag` is being rendered to give a final result. 30 | */ 31 | trait Bundle[Builder, Output <: FragT, FragT] extends Aliases[Builder, Output, FragT] { 32 | /** 33 | * Convenience object for importing all of Scalatags' functionality at once 34 | */ 35 | val all: Attrs with Styles with Tags with DataConverters with Util with Aggregate[Builder, Output, FragT] 36 | /** 37 | * Convenience object for importing only Scalatags' tags (e.g. `div`, `p`) 38 | * into the local namespace, while leaving Styles and Attributes accessible 39 | * via the `*` object 40 | */ 41 | val short: AbstractShort with Tags with DataConverters with Aggregate[Builder, Output, FragT] 42 | /** 43 | * Convenience object for only importing Scalatag's implicits, without importing 44 | * any of the tags, styles or attributes themselves. This includes conversions to 45 | * [[Modifier]], typeclass instances for treating strings and numbers as attributes 46 | * or style values, and other things. 47 | */ 48 | val implicits: Aggregate[Builder, Output, FragT] with DataConverters 49 | 50 | type AbstractShort = generic.AbstractShort[Builder, Output, FragT] 51 | 52 | 53 | /** 54 | * Common attributes. 55 | */ 56 | val attrs: Attrs 57 | /** 58 | * Common tags 59 | */ 60 | val tags: Tags 61 | /** 62 | * Less common tags 63 | */ 64 | val tags2: Tags2 65 | /** 66 | * Common styles 67 | */ 68 | val styles: Styles 69 | /** 70 | * Less common styles 71 | */ 72 | val styles2: Styles2 73 | /** 74 | * SVG only tags 75 | */ 76 | val svgTags: SvgTags 77 | 78 | /** 79 | * SVG only attributes 80 | */ 81 | val svgAttrs: SvgAttrs 82 | 83 | 84 | } 85 | 86 | trait Aliases[Builder, Output <: FragT, FragT]{ 87 | type Attrs = generic.Attrs[Builder, Output, FragT] 88 | type Tags = generic.Tags[Builder, Output, FragT] 89 | type Tags2 = generic.Tags2[Builder, Output, FragT] 90 | type Styles = generic.Styles[Builder, Output, FragT] 91 | type Styles2 = generic.Styles2[Builder, Output, FragT] 92 | type SvgTags = generic.SvgTags[Builder, Output, FragT] 93 | type SvgAttrs = generic.SvgAttrs[Builder, Output, FragT] 94 | type Util = generic.Util[Builder, Output, FragT] 95 | type AttrPair = generic.AttrPair[Builder, _] 96 | 97 | type Attr = generic.Attr 98 | type Style = generic.Style 99 | type Modifier = generic.Modifier[Builder] 100 | 101 | type AttrValue[V] = generic.AttrValue[Builder, V] 102 | type StyleValue[V] = generic.StyleValue[Builder, V] 103 | type PixelStyleValue[V] = generic.PixelStyleValue[Builder, V] 104 | 105 | type Tag = generic.TypedTag[Builder, Output, FragT] 106 | 107 | /** 108 | * A [[Modifier]] which contains a String which will not be escaped. 109 | */ 110 | protected[this] type RawFrag <: Modifier 111 | 112 | /** 113 | * A [[Modifier]] which contains a String. 114 | */ 115 | protected[this] type StringFrag <: Modifier 116 | 117 | type Frag = generic.Frag[Builder, FragT] 118 | } 119 | trait Aggregate[Builder, Output <: FragT, FragT] extends Aliases[Builder, Output, FragT]{ 120 | implicit def StyleFrag(s: StylePair[Builder, _]): StyleSheetFrag 121 | implicit def ClsModifier(s: stylesheet.Cls): Modifier 122 | def genericAttr[T]: AttrValue[T] 123 | implicit val stringAttr: AttrValue[String] = genericAttr[String] 124 | implicit val booleanAttr: AttrValue[Boolean] = genericAttr[Boolean] 125 | implicit val byteAttr: AttrValue[Byte] = genericAttr[Byte] 126 | implicit val shortAttr: AttrValue[Short] = genericAttr[Short] 127 | implicit val intAttr: AttrValue[Int] = genericAttr[Int] 128 | implicit val longAttr: AttrValue[Long] = genericAttr[Long] 129 | implicit val floatAttr: AttrValue[Float] = genericAttr[Float] 130 | implicit val doubleAttr: AttrValue[Double] = genericAttr[Double] 131 | 132 | def genericStyle[T]: StyleValue[T] 133 | implicit val stringStyle: StyleValue[String] = genericStyle[String] 134 | implicit val booleanStyle: StyleValue[Boolean] = genericStyle[Boolean] 135 | implicit val byteStyle: StyleValue[Byte] = genericStyle[Byte] 136 | implicit val shortStyle: StyleValue[Short] = genericStyle[Short] 137 | implicit val intStyle: StyleValue[Int] = genericStyle[Int] 138 | implicit val longStyle: StyleValue[Long] = genericStyle[Long] 139 | implicit val floatStyle: StyleValue[Float] = genericStyle[Float] 140 | implicit val doubleStyle: StyleValue[Double] = genericStyle[Double] 141 | 142 | def genericPixelStyle[T](implicit ev: StyleValue[T]): PixelStyleValue[T] 143 | def genericPixelStylePx[T](implicit ev: StyleValue[String]): PixelStyleValue[T] 144 | implicit val stringPixelStyle: PixelStyleValue[String] = genericPixelStyle[String] 145 | implicit val booleanPixelStyle: PixelStyleValue[Boolean] = genericPixelStyle[Boolean] 146 | implicit val bytePixelStyle: PixelStyleValue[Byte] = genericPixelStylePx[Byte] 147 | implicit val shortPixelStyle: PixelStyleValue[Short] = genericPixelStylePx[Short] 148 | implicit val intPixelStyle: PixelStyleValue[Int] = genericPixelStylePx[Int] 149 | implicit val longPixelStyle: PixelStyleValue[Long] = genericPixelStylePx[Long] 150 | implicit val floatPixelStyle: PixelStyleValue[Float] = genericPixelStylePx[Float] 151 | implicit val doublePixelStyle: PixelStyleValue[Double] = genericPixelStylePx[Double] 152 | 153 | implicit def byteFrag(v: Byte): Frag = stringFrag(v.toString) 154 | implicit def shortFrag(v: Short): Frag = stringFrag(v.toString) 155 | implicit def intFrag(v: Int): Frag = stringFrag(v.toString) 156 | implicit def longFrag(v: Long): Frag = stringFrag(v.toString) 157 | implicit def floatFrag(v: Float): Frag = stringFrag(v.toString) 158 | implicit def doubleFrag(v: Double): Frag = stringFrag(v.toString) 159 | implicit def stringFrag(v: String): Frag 160 | 161 | /** 162 | * Delimits a string that should be included in the result as raw, 163 | * un-escaped HTML 164 | */ 165 | def raw(s: String): RawFrag 166 | } 167 | trait AbstractShort[Builder, Output <: FragT, FragT]{ 168 | val `*`: generic.Attrs[Builder, Output, FragT] with generic.Styles[Builder, Output, FragT] 169 | } 170 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/generic/Core.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package generic 3 | 4 | import java.util.Objects.requireNonNull 5 | 6 | import scala.annotation.implicitNotFound 7 | 8 | 9 | /** 10 | * Represents a value that can be nested within a [[scalatags.generic.TypedTag]]. This can be 11 | * another [[scalatags.generic.Modifier]], but can also be a CSS style or HTML attribute binding, 12 | * which will add itself to the node's attributes but not appear in the final 13 | * `children` list. 14 | */ 15 | trait Modifier[Builder] { 16 | /** 17 | * Applies this modifier to the specified [[Builder]], such that when 18 | * rendering is complete the effect of adding this modifier can be seen. 19 | */ 20 | def applyTo(t: Builder): Unit 21 | } 22 | 23 | /** 24 | * Marker sub-type of [[scalatags.generic.Modifier]] which signifies that that type can be 25 | * rendered as a standalone fragment of [[FragT]]. This excludes things 26 | * like [[scalatags.generic.AttrPair]]s or [[scalatags.generic.StylePair]]s which only make sense as part of 27 | * a parent fragment 28 | */ 29 | trait Frag[Builder, +FragT] extends Modifier[Builder]{ 30 | def render: FragT 31 | } 32 | 33 | /** 34 | * A generic representation of a Scalatags tag. 35 | * 36 | * @tparam Output The base type that this tag represents. On Scala-JVM, this is all 37 | * `Nothing`, while on ScalaJS this could be the `dom.XXXElement` 38 | * associated with that tag name. 39 | */ 40 | trait TypedTag[Builder, +Output <: FragT, +FragT] extends Frag[Builder, Output]{ 41 | protected[this] type Self <: TypedTag[Builder, Output, FragT] 42 | def tag: String 43 | 44 | /** 45 | * The modifiers that are applied to a TypedTag are kept in this linked-Seq 46 | * (which are actually WrappedArrays) data-structure in order for maximum 47 | * performance. 48 | */ 49 | def modifiers: List[Seq[Modifier[Builder]]] 50 | 51 | /** 52 | * Walks the [[modifiers]] to apply them to a particular [[Builder]]. 53 | * Super sketchy/procedural for max performance. 54 | */ 55 | def build(b: Builder): Unit = { 56 | var current = modifiers 57 | val arr = new Array[Seq[Modifier[Builder]]](modifiers.length) 58 | 59 | var i = 0 60 | while(current != Nil){ 61 | arr(i) = current.head 62 | current = current.tail 63 | i += 1 64 | } 65 | 66 | var j = arr.length 67 | while (j > 0) { 68 | j -= 1 69 | val frag = arr(j) 70 | var i = 0 71 | while(i < frag.length){ 72 | frag(i).applyTo(b) 73 | i += 1 74 | } 75 | } 76 | } 77 | /** 78 | * Add the given modifications (e.g. additional children, or new attributes) 79 | * to the [[TypedTag]]. 80 | */ 81 | def apply(xs: Modifier[Builder]*): Self 82 | 83 | /** 84 | * Collapses this scalatags tag tree and returns an [[Output]] 85 | */ 86 | def render: Output 87 | } 88 | 89 | /** 90 | * Wraps up a HTML attribute in a value which isn't a string. 91 | * 92 | * @param name the name of this particular attribute 93 | * @param namespace an XML [[Namespace]] that this attribute lives in 94 | * @param raw all [[Attr]]s are checked to fail fast if their names are 95 | * invalid XML attrs; flagging them as [[raw]] disables the checks 96 | * in the few cases you actually want invalid XML attrs 97 | * (e.g. AngularJS) 98 | */ 99 | case class Attr(name: String, namespace: Option[Namespace] = None, raw: Boolean = false) { 100 | 101 | if (!raw && !Escaping.validAttrName(name)) { 102 | throw new IllegalArgumentException( 103 | s"Illegal attribute name: $name is not a valid XML attribute name" 104 | ) 105 | } 106 | /** 107 | * Creates an [[AttrPair]] from an [[Attr]] and a value of type [[T]], if 108 | * there is an [[AttrValue]] of the correct type. 109 | */ 110 | def :=[Builder, T](v: T)(implicit ev: AttrValue[Builder, T]) = { 111 | requireNonNull(v) 112 | AttrPair(this, v, ev) 113 | } 114 | 115 | def empty[Builder](implicit ev: AttrValue[Builder, String]) = this := name 116 | } 117 | 118 | /** 119 | * Wraps up a CSS style in a value. 120 | */ 121 | case class Style(jsName: String, cssName: String) { 122 | /** 123 | * Creates an [[StylePair]] from an [[Style]] and a value of type [[T]], if 124 | * there is an [[StyleValue]] of the correct type. 125 | */ 126 | def :=[Builder, T](v: T)(implicit ev: StyleValue[Builder, T]) = { 127 | requireNonNull(v) 128 | StylePair(this, v, ev) 129 | } 130 | } 131 | /** 132 | * Wraps up a CSS style in a value. 133 | */ 134 | case class PixelStyle(jsName: String, cssName: String) { 135 | val realStyle = Style(jsName, cssName) 136 | /** 137 | * Creates an [[StylePair]] from an [[Style]] and a value of type [[T]], if 138 | * there is an [[StyleValue]] of the correct type. 139 | */ 140 | def :=[Builder, T](v: T)(implicit ev: PixelStyleValue[Builder, T]) = { 141 | requireNonNull(v) 142 | ev(realStyle, v) 143 | } 144 | 145 | } 146 | trait StyleProcessor{ 147 | def apply[T](t: T): String 148 | } 149 | /** 150 | * An [[Attr]], it's associated value, and an [[AttrValue]] of the correct type 151 | */ 152 | case class AttrPair[Builder, T](a: Attr, v: T, ev: AttrValue[Builder, T]) extends Modifier[Builder] { 153 | override def applyTo(t: Builder): Unit = { 154 | ev.apply(t, a, v) 155 | } 156 | def :=[Builder, T](v: T)(implicit ev: AttrValue[Builder, T]) = { 157 | requireNonNull(v) 158 | AttrPair(a, v, ev) 159 | } 160 | } 161 | /** 162 | * Used to specify how to handle a particular type [[T]] when it is used as 163 | * the value of a [[Attr]]. Only types with a specified [[AttrValue]] may 164 | * be used. 165 | */ 166 | @implicitNotFound( 167 | "No AttrValue defined for type ${T}; scalatags does not know how to use ${T} as an attribute" 168 | ) 169 | trait AttrValue[Builder, T]{ 170 | def apply(t: Builder, a: Attr, v: T): Unit 171 | } 172 | 173 | /** 174 | * A [[Style]], it's associated value, and a [[StyleValue]] of the correct type 175 | */ 176 | case class StylePair[Builder, T](s: Style, v: T, ev: StyleValue[Builder, T]) extends Modifier[Builder]{ 177 | override def applyTo(t: Builder): Unit = { 178 | ev.apply(t, s, v) 179 | } 180 | } 181 | 182 | /** 183 | * Used to specify how to handle a particular type [[T]] when it is used as 184 | * the value of a [[Style]]. Only types with a specified [[StyleValue]] may 185 | * be used. 186 | */ 187 | @implicitNotFound( 188 | "No StyleValue defined for type ${T}; scalatags does not know how to use ${T} as an style" 189 | ) 190 | trait StyleValue[Builder, T]{ 191 | def apply(t: Builder, s: Style, v: T): Unit 192 | } 193 | 194 | @implicitNotFound( 195 | "No PixelStyleValue defined for type ${T}; scalatags does not know how to use ${T} as an style" 196 | ) 197 | trait PixelStyleValue[Builder, T]{ 198 | def apply(s: Style, v: T): StylePair[Builder, _] 199 | } 200 | 201 | /** 202 | * Represents a single XML namespace. This is currently ignored in `scalatags.Text`, 203 | * but used to create elements with the correct namespace in `scalatags.JsDom`. A 204 | * [[Namespace]] can be provided implicitly (or explicitly) when creating tags via 205 | * `"".tag`, with a default of "http://www.w3.org/1999/xhtml" if none is found. 206 | */ 207 | trait Namespace { 208 | def uri: String 209 | } 210 | object Namespace{ 211 | implicit val htmlNamespaceConfig: Namespace = new Namespace { 212 | def uri = "http://www.w3.org/1999/xhtml" 213 | } 214 | val svgNamespaceConfig = new Namespace { 215 | def uri = "http://www.w3.org/2000/svg" 216 | } 217 | val svgXlinkNamespaceConfig = new Namespace { 218 | def uri = "http://www.w3.org/1999/xlink" 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/generic/Tags.scala: -------------------------------------------------------------------------------- 1 | package scalatags.generic 2 | 3 | 4 | /** 5 | * Trait that contains the contents of the `Tags` object, so they can be mixed 6 | * in to other objects if needed. 7 | */ 8 | trait Tags[Builder, Output <: FragT, FragT] extends Util[Builder, Output, FragT]{ 9 | 10 | 11 | 12 | // Root Element 13 | /** 14 | * Represents the root of an HTML or XHTML document. All other elements must 15 | * be descendants of this element. 16 | * 17 | * MDN 18 | */ 19 | def html: TypedTag[Builder, Output, FragT] 20 | 21 | // Document Metadata 22 | /** 23 | * Represents a collection of metadata about the document, including links to, 24 | * or definitions of, scripts and style sheets. 25 | * 26 | * MDN 27 | */ 28 | def head: TypedTag[Builder, Output, FragT] 29 | 30 | /** 31 | * Defines the base URL for relative URLs in the page. 32 | * 33 | * MDN 34 | */ 35 | def base: TypedTag[Builder, Output, FragT] 36 | /** 37 | * Used to link JavaScript and external CSS with the current HTML document. 38 | * 39 | * MDN 40 | */ 41 | def link: TypedTag[Builder, Output, FragT] 42 | /** 43 | * Defines metadata that can't be defined using another HTML element. 44 | * 45 | * MDN 46 | */ 47 | def meta: TypedTag[Builder, Output, FragT] 48 | 49 | 50 | // Scripting 51 | /** 52 | * Defines either an internal script or a link to an external script. The 53 | * script language is JavaScript. 54 | * 55 | * MDN 56 | */ 57 | def script: TypedTag[Builder, Output, FragT] 58 | 59 | 60 | // Sections 61 | /** 62 | * Represents the content of an HTML document. There is only one body 63 | * element in a document. 64 | * 65 | * MDN 66 | */ 67 | def body: TypedTag[Builder, Output, FragT] 68 | 69 | /** 70 | * Heading level 1 71 | * 72 | * MDN 73 | */ 74 | def h1: TypedTag[Builder, Output, FragT] 75 | /** 76 | * Heading level 2 77 | * 78 | * MDN 79 | */ 80 | def h2: TypedTag[Builder, Output, FragT] 81 | /** 82 | * Heading level 3 83 | * 84 | * MDN 85 | */ 86 | def h3: TypedTag[Builder, Output, FragT] 87 | /** 88 | * Heading level 4 89 | * 90 | * MDN 91 | */ 92 | def h4: TypedTag[Builder, Output, FragT] 93 | /** 94 | * Heading level 5 95 | * 96 | * MDN 97 | */ 98 | def h5: TypedTag[Builder, Output, FragT] 99 | /** 100 | * Heading level 6 101 | * 102 | * MDN 103 | */ 104 | def h6: TypedTag[Builder, Output, FragT] 105 | /** 106 | * Defines the header of a page or section. It often contains a logo, the 107 | * title of the Web site, and a navigational table of content. 108 | * 109 | * MDN 110 | */ 111 | def header: TypedTag[Builder, Output, FragT] 112 | /** 113 | * Defines the footer for a page or section. It often contains a copyright 114 | * notice, some links to legal information, or addresses to give feedback. 115 | * 116 | * MDN 117 | */ 118 | def footer: TypedTag[Builder, Output, FragT] 119 | 120 | 121 | // Grouping content 122 | /** 123 | * Defines a portion that should be displayed as a paragraph. 124 | * 125 | * MDN 126 | */ 127 | def p: TypedTag[Builder, Output, FragT] 128 | /** 129 | * Represents a thematic break between paragraphs of a section or article or 130 | * any longer content. 131 | * 132 | * MDN 133 | */ 134 | def hr: TypedTag[Builder, Output, FragT] 135 | /** 136 | * Indicates that its content is preformatted and that this format must be 137 | * preserved. 138 | * 139 | * MDN 140 | */ 141 | def pre: TypedTag[Builder, Output, FragT] 142 | /** 143 | * Represents a content that is quoted from another source. 144 | * 145 | * MDN 146 | */ 147 | def blockquote: TypedTag[Builder, Output, FragT] 148 | /** 149 | * Defines an ordered list of items. 150 | * 151 | * MDN 152 | */ 153 | def ol: TypedTag[Builder, Output, FragT] 154 | /** 155 | * Defines an unordered list of items. 156 | * 157 | * MDN 158 | */ 159 | def ul: TypedTag[Builder, Output, FragT] 160 | /** 161 | * Defines an item of an list. 162 | * 163 | * MDN 164 | */ 165 | def li: TypedTag[Builder, Output, FragT] 166 | /** 167 | * Defines a definition list; a list of terms and their associated definitions. 168 | * 169 | * MDN 170 | */ 171 | def dl: TypedTag[Builder, Output, FragT] 172 | /** 173 | * Represents a term defined by the next dd 174 | * 175 | * MDN 176 | */ 177 | def dt: TypedTag[Builder, Output, FragT] 178 | /** 179 | * Represents the definition of the terms immediately listed before it. 180 | * 181 | * MDN 182 | */ 183 | def dd: TypedTag[Builder, Output, FragT] 184 | /** 185 | * Represents a figure illustrated as part of the document. 186 | * 187 | * MDN 188 | */ 189 | def figure: TypedTag[Builder, Output, FragT] 190 | /** 191 | * Represents the legend of a figure. 192 | * 193 | * MDN 194 | */ 195 | def figcaption: TypedTag[Builder, Output, FragT] 196 | /** 197 | * Represents a generic container with no special meaning. 198 | * 199 | * MDN 200 | */ 201 | def div: TypedTag[Builder, Output, FragT] 202 | 203 | // Text-level semantics 204 | /** 205 | * Represents a hyperlink, linking to another resource. 206 | * 207 | * MDN 208 | */ 209 | def a: TypedTag[Builder, Output, FragT] 210 | /** 211 | * Represents emphasized text. 212 | * 213 | * MDN 214 | */ 215 | def em: TypedTag[Builder, Output, FragT] 216 | /** 217 | * Represents especially important text. 218 | * 219 | * MDN 220 | */ 221 | def strong: TypedTag[Builder, Output, FragT] 222 | /** 223 | * Represents a side comment; text like a disclaimer or copyright, which is not 224 | * essential to the comprehension of the document. 225 | * 226 | * MDN 227 | */ 228 | def small: TypedTag[Builder, Output, FragT] 229 | /** 230 | * Strikethrough element, used for that is no longer accurate or relevant. 231 | * 232 | * MDN 233 | */ 234 | def s: TypedTag[Builder, Output, FragT] 235 | /** 236 | * Represents the title of a work being cited. 237 | * 238 | * MDN 239 | */ 240 | def cite: TypedTag[Builder, Output, FragT] 241 | 242 | /** 243 | * Represents computer code. 244 | * 245 | * MDN 246 | */ 247 | def code: TypedTag[Builder, Output, FragT] 248 | 249 | /** 250 | * Subscript tag 251 | * 252 | * MDN 253 | */ 254 | def sub: TypedTag[Builder, Output, FragT] 255 | /** 256 | * Superscript tag. 257 | * 258 | * MDN 259 | */ 260 | def sup: TypedTag[Builder, Output, FragT] 261 | /** 262 | * Italicized text. 263 | * 264 | * MDN 265 | */ 266 | def i: TypedTag[Builder, Output, FragT] 267 | /** 268 | * Bold text. 269 | * 270 | * MDN 271 | */ 272 | def b: TypedTag[Builder, Output, FragT] 273 | /** 274 | * Underlined text. 275 | * 276 | * MDN 277 | */ 278 | def u: TypedTag[Builder, Output, FragT] 279 | 280 | /** 281 | * Represents text with no specific meaning. This has to be used when no other 282 | * text-semantic element conveys an adequate meaning, which, in this case, is 283 | * often brought by global attributes like class, lang, or dir. 284 | * 285 | * MDN 286 | */ 287 | def span: TypedTag[Builder, Output, FragT] 288 | /** 289 | * Represents a line break. 290 | * 291 | * MDN 292 | */ 293 | def br: TypedTag[Builder, Output, FragT] 294 | /** 295 | * Represents a line break opportunity, that is a suggested point for wrapping 296 | * text in order to improve readability of text split on several lines. 297 | * 298 | * MDN 299 | */ 300 | def wbr: TypedTag[Builder, Output, FragT] 301 | 302 | // Edits 303 | /** 304 | * Defines an addition to the document. 305 | * 306 | * MDN 307 | */ 308 | def ins: TypedTag[Builder, Output, FragT] 309 | /** 310 | * Defines a removal from the document. 311 | * 312 | * MDN 313 | */ 314 | def del: TypedTag[Builder, Output, FragT] 315 | 316 | // Embedded content 317 | /** 318 | * Represents an image. 319 | * 320 | * MDN 321 | */ 322 | def img: TypedTag[Builder, Output, FragT] 323 | /** 324 | * Represents a nested browsing context, that is an embedded HTML document. 325 | * 326 | * MDN 327 | */ 328 | def iframe: TypedTag[Builder, Output, FragT] 329 | /** 330 | * Represents a integration point for an external, often non-HTML, application 331 | * or interactive content. 332 | * 333 | * MDN 334 | */ 335 | def embed: TypedTag[Builder, Output, FragT] 336 | /** 337 | * Represents an external resource, which is treated as an image, an HTML 338 | * sub-document, or an external resource to be processed by a plug-in. 339 | * 340 | * MDN 341 | */ 342 | def `object`: TypedTag[Builder, Output, FragT] 343 | /** 344 | * Defines parameters for use by plug-ins invoked by object elements. 345 | * 346 | * MDN 347 | */ 348 | def param: TypedTag[Builder, Output, FragT] 349 | /** 350 | * Represents a video, and its associated audio files and captions, with the 351 | * necessary interface to play it. 352 | * 353 | * MDN 354 | */ 355 | def video: TypedTag[Builder, Output, FragT] 356 | /** 357 | * Represents a sound or an audio stream. 358 | * 359 | * MDN 360 | */ 361 | def audio: TypedTag[Builder, Output, FragT] 362 | /** 363 | * Allows the authors to specify alternate media resources for media elements 364 | * like video or audio 365 | * 366 | * MDN 367 | */ 368 | def source: TypedTag[Builder, Output, FragT] 369 | /** 370 | * Allows authors to specify timed text track for media elements like video or 371 | * audio 372 | * 373 | * MDN 374 | */ 375 | def track: TypedTag[Builder, Output, FragT] 376 | /** 377 | * Represents a bitmap area that scripts can use to render graphics like graphs, 378 | * games or any visual images on the fly. 379 | * 380 | * MDN 381 | */ 382 | def canvas: TypedTag[Builder, Output, FragT] 383 | /** 384 | * In conjunction with area, defines an image map. 385 | * 386 | * MDN 387 | */ 388 | def map: TypedTag[Builder, Output, FragT] 389 | /** 390 | * In conjunction with map, defines an image map 391 | * 392 | * MDN 393 | */ 394 | def area: TypedTag[Builder, Output, FragT] 395 | 396 | 397 | // Tabular data 398 | /** 399 | * Represents data with more than one dimension. 400 | * 401 | * MDN 402 | */ 403 | def table: TypedTag[Builder, Output, FragT] 404 | /** 405 | * The title of a table. 406 | * 407 | * MDN 408 | */ 409 | def caption: TypedTag[Builder, Output, FragT] 410 | /** 411 | * A set of columns. 412 | * 413 | * MDN 414 | */ 415 | def colgroup: TypedTag[Builder, Output, FragT] 416 | /** 417 | * A single column. 418 | * 419 | * MDN 420 | */ 421 | def col: TypedTag[Builder, Output, FragT] 422 | /** 423 | * The table body. 424 | * 425 | * MDN 426 | */ 427 | def tbody: TypedTag[Builder, Output, FragT] 428 | /** 429 | * The table headers. 430 | * 431 | * MDN 432 | */ 433 | def thead: TypedTag[Builder, Output, FragT] 434 | /** 435 | * The table footer. 436 | * 437 | * MDN 438 | */ 439 | def tfoot: TypedTag[Builder, Output, FragT] 440 | /** 441 | * A single row in a table. 442 | * 443 | * MDN 444 | */ 445 | def tr: TypedTag[Builder, Output, FragT] 446 | /** 447 | * A single cell in a table. 448 | * 449 | * MDN 450 | */ 451 | def td: TypedTag[Builder, Output, FragT] 452 | /** 453 | * A header cell in a table. 454 | * 455 | * MDN 456 | */ 457 | def th: TypedTag[Builder, Output, FragT] 458 | 459 | // Forms 460 | /** 461 | * Represents a form, consisting of controls, that can be submitted to a 462 | * server for processing. 463 | * 464 | * MDN 465 | */ 466 | def form: TypedTag[Builder, Output, FragT] 467 | /** 468 | * A set of fields. 469 | * 470 | * MDN 471 | */ 472 | def fieldset: TypedTag[Builder, Output, FragT] 473 | /** 474 | * The caption for a fieldset. 475 | * 476 | * MDN 477 | */ 478 | def legend: TypedTag[Builder, Output, FragT] 479 | /** 480 | * The caption of a single field 481 | * 482 | * MDN 483 | */ 484 | def label: TypedTag[Builder, Output, FragT] 485 | /** 486 | * A typed data field allowing the user to input data. 487 | * 488 | * MDN 489 | */ 490 | def input: TypedTag[Builder, Output, FragT] 491 | /** 492 | * A button 493 | * 494 | * MDN 495 | */ 496 | def button: TypedTag[Builder, Output, FragT] 497 | /** 498 | * A control that allows the user to select one of a set of options. 499 | * 500 | * MDN 501 | */ 502 | def select: TypedTag[Builder, Output, FragT] 503 | /** 504 | * A set of predefined options for other controls. 505 | * 506 | * MDN 507 | */ 508 | def datalist: TypedTag[Builder, Output, FragT] 509 | /** 510 | * A set of options, logically grouped. 511 | * 512 | * MDN 513 | */ 514 | def optgroup: TypedTag[Builder, Output, FragT] 515 | /** 516 | * An option in a select element. 517 | * 518 | * MDN 519 | */ 520 | def option: TypedTag[Builder, Output, FragT] 521 | /** 522 | * A multiline text edit control. 523 | * 524 | * MDN 525 | */ 526 | def textarea: TypedTag[Builder, Output, FragT] 527 | } 528 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/generic/Tags2.scala: -------------------------------------------------------------------------------- 1 | package scalatags.generic 2 | 3 | 4 | /** 5 | * Contains HTML tags which are used less frequently. These are generally 6 | * imported individually as needed. 7 | */ 8 | trait Tags2[Builder, Output <: FragT, FragT] extends Util[Builder, Output, FragT]{ 9 | 10 | // Document Metadata 11 | /** 12 | * Defines the title of the document, shown in a browser's title bar or on the 13 | * page's tab. It can only contain text and any contained tags are not 14 | * interpreted. 15 | * 16 | * MDN 17 | */ 18 | def title: TypedTag[Builder, Output, FragT] 19 | 20 | /** 21 | * Used to write inline CSS. 22 | * 23 | * MDN 24 | */ 25 | def style: TypedTag[Builder, Output, FragT] 26 | // Scripting 27 | /** 28 | * Defines alternative content to display when the browser doesn't support 29 | * scripting. 30 | * 31 | * MDN 32 | */ 33 | def noscript: TypedTag[Builder, Output, FragT] 34 | 35 | // Sections 36 | /** 37 | * Represents a generic section of a document, i.e., a thematic grouping of 38 | * content, typically with a heading. 39 | * 40 | * MDN 41 | */ 42 | def section: TypedTag[Builder, Output, FragT] 43 | /** 44 | * Represents a section of a page that links to other pages or to parts within 45 | * the page: a section with navigation links. 46 | * 47 | * MDN 48 | */ 49 | def nav: TypedTag[Builder, Output, FragT] 50 | /** 51 | * Defines self-contained content that could exist independently of the rest 52 | * of the content. 53 | * 54 | * MDN 55 | */ 56 | def article: TypedTag[Builder, Output, FragT] 57 | /** 58 | * Defines some content loosely related to the page content. If it is removed, 59 | * the remaining content still makes sense. 60 | * 61 | * MDN 62 | */ 63 | def aside: TypedTag[Builder, Output, FragT] 64 | /** 65 | * Defines a section containing contact information. 66 | * 67 | * MDN 68 | */ 69 | def address: TypedTag[Builder, Output, FragT] 70 | 71 | /** 72 | * Defines the main or important content in the document. There is only one 73 | * main element in the document. 74 | * 75 | * MDN 76 | */ 77 | def main: TypedTag[Builder, Output, FragT] 78 | 79 | // Text level semantics 80 | 81 | /** 82 | * An inline quotation. 83 | * 84 | * MDN 85 | */ 86 | def q: TypedTag[Builder, Output, FragT] 87 | /** 88 | * Represents a term whose definition is contained in its nearest ancestor 89 | * content. 90 | * 91 | * MDN 92 | */ 93 | def dfn: TypedTag[Builder, Output, FragT] 94 | /** 95 | * An abbreviation or acronym; the expansion of the abbreviation can be 96 | * represented in the title attribute. 97 | * 98 | * MDN 99 | */ 100 | def abbr: TypedTag[Builder, Output, FragT] 101 | /** 102 | * Associates to its content a machine-readable equivalent. 103 | * 104 | * MDN 105 | */ 106 | def data: TypedTag[Builder, Output, FragT] 107 | /** 108 | * Represents a date and time value; the machine-readable equivalent can be 109 | * represented in the datetime attribetu 110 | * 111 | * MDN 112 | */ 113 | def time: TypedTag[Builder, Output, FragT] 114 | /** 115 | * Represents a variable. 116 | * 117 | * MDN 118 | */ 119 | def `var`: TypedTag[Builder, Output, FragT] 120 | /** 121 | * Represents the output of a program or a computer. 122 | * 123 | * MDN 124 | */ 125 | def samp: TypedTag[Builder, Output, FragT] 126 | /** 127 | * Represents user input, often from a keyboard, but not necessarily. 128 | * 129 | * MDN 130 | */ 131 | def kbd: TypedTag[Builder, Output, FragT] 132 | 133 | /** 134 | * Defines a mathematical formula. 135 | * 136 | * MDN 137 | */ 138 | def math: TypedTag[Builder, Output, FragT] 139 | /** 140 | * Represents text highlighted for reference purposes, that is for its 141 | * relevance in another context. 142 | * 143 | * MDN 144 | */ 145 | def mark: TypedTag[Builder, Output, FragT] 146 | /** 147 | * Represents content to be marked with ruby annotations, short runs of text 148 | * presented alongside the text. This is often used in conjunction with East 149 | * Asian language where the annotations act as a guide for pronunciation, like 150 | * the Japanese furigana . 151 | * 152 | * MDN 153 | */ 154 | def ruby: TypedTag[Builder, Output, FragT] 155 | /** 156 | * Represents the text of a ruby annotation. 157 | * 158 | * MDN 159 | */ 160 | def rt: TypedTag[Builder, Output, FragT] 161 | /** 162 | * Represents parenthesis around a ruby annotation, used to display the 163 | * annotation in an alternate way by browsers not supporting the standard 164 | * display for annotations. 165 | * 166 | * MDN 167 | */ 168 | def rp: TypedTag[Builder, Output, FragT] 169 | /** 170 | * Represents text that must be isolated from its surrounding for bidirectional 171 | * text formatting. It allows embedding a span of text with a different, or 172 | * unknown, directionality. 173 | * 174 | * MDN 175 | */ 176 | def bdi: TypedTag[Builder, Output, FragT] 177 | /** 178 | * Represents the directionality of its children, in order to explicitly 179 | * override the Unicode bidirectional algorithm. 180 | * 181 | * MDN 182 | */ 183 | def bdo: TypedTag[Builder, Output, FragT] 184 | 185 | // Forms 186 | 187 | /** 188 | * A key-pair generator control. 189 | * 190 | * MDN 191 | */ 192 | def keygen: TypedTag[Builder, Output, FragT] 193 | /** 194 | * The result of a calculation 195 | * 196 | * MDN 197 | */ 198 | def output: TypedTag[Builder, Output, FragT] 199 | /** 200 | * A progress completion bar 201 | * 202 | * MDN 203 | */ 204 | def progress: TypedTag[Builder, Output, FragT] 205 | /** 206 | * A scalar measurement within a known range. 207 | * 208 | * MDN 209 | */ 210 | def meter: TypedTag[Builder, Output, FragT] 211 | 212 | 213 | // Interactive elements 214 | /** 215 | * A widget from which the user can obtain additional information 216 | * or controls. 217 | * 218 | * MDN 219 | */ 220 | def details: TypedTag[Builder, Output, FragT] 221 | /** 222 | * A summary, caption, or legend for a given details. 223 | * 224 | * MDN 225 | */ 226 | def summary: TypedTag[Builder, Output, FragT] 227 | /** 228 | * A command that the user can invoke. 229 | * 230 | * MDN 231 | */ 232 | def command: TypedTag[Builder, Output, FragT] 233 | /** 234 | * A list of commands 235 | * 236 | * MDN 237 | */ 238 | def menu: TypedTag[Builder, Output, FragT] 239 | } 240 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/generic/Util.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package generic 3 | import java.util.Objects 4 | 5 | import scala.language.higherKinds 6 | import scala.language.implicitConversions 7 | 8 | /** 9 | * Created by haoyi on 6/2/14. 10 | */ 11 | trait Util[Builder, Output <: FragT, FragT] extends LowPriUtil[Builder, Output, FragT]{ 12 | 13 | type ConcreteHtmlTag[T <: Output] <: TypedTag[Builder, T, FragT] 14 | 15 | def frag(frags: Frag[Builder, FragT]*): Frag[Builder, FragT] = SeqFrag(frags) 16 | def modifier(mods: Modifier[Builder]*): Modifier[Builder] = SeqNode(mods) 17 | 18 | def tag(s: String, void: Boolean = false): TypedTag[Builder, Output, FragT] 19 | def makeAbstractTypedTag[T <: Output](tag: String, void: Boolean, namespaceConfig: Namespace): ConcreteHtmlTag[T] 20 | protected[this] implicit def stringAttrX: AttrValue[Builder, String] 21 | protected[this] implicit def stringStyleX: StyleValue[Builder, String] 22 | protected[this] implicit def stringPixelStyleX: PixelStyleValue[Builder, String] 23 | 24 | /** 25 | * Constructs an [[Attr]] attribute object from a string; can be used inline: 26 | * 27 | * {{{ 28 | * div( 29 | * attr("hello-world-special-attr") := "foo 30 | * ) 31 | * }}} 32 | * 33 | * Or assigned to a name and used later 34 | * 35 | * 36 | * {{{ 37 | * val hello = attr("hello-world-special-attr") 38 | * div( 39 | * hello := "foo 40 | * ) 41 | * }}} 42 | */ 43 | def attr(s: String, ns: Namespace = null, raw: Boolean = false) = Attr(s, Option(ns), raw) 44 | 45 | /** 46 | * Constructs a CSS [[Style]] from a string, can be used inline 47 | * 48 | * {{{ 49 | * div( 50 | * css("-moz-special-style") := "foo" 51 | * ) 52 | * }}} 53 | * 54 | * Or assigned to a name and used later 55 | * 56 | * {{{ 57 | * val mozSpecial := css("-moz-special-style") 58 | * div( 59 | * mozSpecial := "foo" 60 | * ) 61 | * }}} 62 | */ 63 | def css(s: String) = Style(camelCase(s), s) 64 | 65 | 66 | /** 67 | * Allows you to modify a [[ConcreteHtmlTag]] by adding a Seq containing other nest-able 68 | * objects to its list of children. 69 | */ 70 | implicit class SeqNode[A](xs: Seq[A])(implicit ev: A => Modifier[Builder]) extends Modifier[Builder]{ 71 | Objects.requireNonNull(xs) 72 | def applyTo(t: Builder) = xs.foreach(elem => ev(elem).applyTo(t)) 73 | } 74 | 75 | /** 76 | * Allows you to modify a [[ConcreteHtmlTag]] by adding an Option containing other nest-able 77 | * objects to its list of children. 78 | */ 79 | implicit def OptionNode[A](xs: Option[A])(implicit ev: A => Modifier[Builder]): SeqNode[A] = new SeqNode(xs.toSeq) 80 | 81 | /** 82 | * Allows you to modify a [[ConcreteHtmlTag]] by adding an Array containing other nest-able 83 | * objects to its list of children. 84 | */ 85 | implicit def ArrayNode[A](xs: Array[A])(implicit ev: A => Modifier[Builder]): SeqNode[A] = new SeqNode[A](xs.toSeq) 86 | 87 | 88 | } 89 | 90 | trait LowPriUtil[Builder, Output <: FragT, FragT]{ 91 | /** 92 | * Renders an Seq of [[FragT]] into a single [[FragT]] 93 | */ 94 | implicit def SeqFrag[A](xs: Seq[A])(implicit ev: A => Frag[Builder, FragT]): Frag[Builder, FragT] 95 | /** 96 | * Renders an Seq of [[FragT]] into a single [[FragT]] 97 | */ 98 | implicit def GeneratorFrag[A](xs: geny.Generator[A])(implicit ev: A => Frag[Builder, FragT]): Frag[Builder, FragT] 99 | 100 | /** 101 | * Renders an Option of [[FragT]] into a single [[FragT]] 102 | */ 103 | implicit def OptionFrag[A](xs: Option[A])(implicit ev: A => Frag[Builder, FragT]): Frag[Builder, FragT] = SeqFrag(xs.toSeq) 104 | 105 | /** 106 | * Renders an Seq of [[FragT]] into a single [[FragT]] 107 | */ 108 | implicit def ArrayFrag[A](xs: Array[A])(implicit ev: A => Frag[Builder, FragT]): Frag[Builder, FragT] = SeqFrag[A](xs.toSeq) 109 | 110 | /** 111 | * Lets you put Unit into a scalatags tree, as a no-op. 112 | */ 113 | implicit def UnitFrag(u: Unit): Frag[Builder, FragT] 114 | } 115 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/package.scala: -------------------------------------------------------------------------------- 1 | import scala.language.implicitConversions 2 | import scalatags.generic.{Attr, Style} 3 | import language.experimental.macros 4 | /** 5 | * ScalaTags is a small XML/HTML construction library for Scala. See 6 | * [[https://github.com/lihaoyi/scalatags the Github page]] for an introduction 7 | * and documentation. 8 | */ 9 | package object scalatags { 10 | 11 | 12 | private[scalatags] def camelCase(dashedString: String) = { 13 | val first :: rest = dashedString.split("-").toList 14 | 15 | (first :: rest.map(s => s(0).toUpper.toString + s.drop(1))).mkString 16 | } 17 | 18 | implicit object styleOrdering extends Ordering[Style]{ 19 | override def compare(x: Style, y: Style): Int = x.cssName compareTo y.cssName 20 | } 21 | 22 | implicit object attrOrdering extends Ordering[Attr]{ 23 | override def compare(x: Attr, y: Attr): Int = x.name compareTo y.name 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/stylesheet/Core.scala: -------------------------------------------------------------------------------- 1 | package scalatags.stylesheet 2 | 3 | 4 | import scala.collection.immutable.SortedMap 5 | 6 | /** 7 | * A structure representing a set of CSS rules which has not been 8 | * rendered into a [[Cls]]. 9 | * 10 | * e.g. a StyleTree that looks like 11 | * 12 | * .cls1 13 | * .cls2 14 | * :hover 15 | * :hover 16 | * cls2 17 | * 18 | * Flattens out via `stringify` into CSS rules like 19 | * 20 | * .cls1 .cls2:hover 21 | * .cls1:hover .cls2 22 | */ 23 | case class StyleTree(selectors: Seq[String], 24 | styles: SortedMap[String, String], 25 | children: Seq[StyleTree]){ 26 | def stringify(prefix: Seq[String]): String = { 27 | val body = styles.map{case (k, v) => s" $k:$v"}.mkString("\n") 28 | val (first +: rest) = prefix ++ selectors 29 | val all = (first +: rest.map(x => if (x(0) == ':') x else " " + x)).mkString("") 30 | val ours = 31 | if (body == "") "" 32 | else s"$all{\n$body\n}\n" 33 | 34 | (ours +: children.map(_.stringify(prefix ++ selectors))).mkString 35 | } 36 | } 37 | 38 | object StyleTree{ 39 | def build(start: Seq[String], args: Seq[StyleSheetFrag]) = { 40 | args.foldLeft(StyleTree(start, SortedMap.empty, Nil))( 41 | (c, f) => f.applyTo(c) 42 | ) 43 | } 44 | } 45 | 46 | 47 | /** 48 | * Something which can be used as part of a [[StyleSheet]] 49 | */ 50 | trait StyleSheetFrag{ 51 | 52 | def applyTo(c: StyleTree): StyleTree 53 | } 54 | object StyleSheetFrag{ 55 | implicit class StyleTreeFrag(st: StyleTree) extends StyleSheetFrag{ 56 | def applyTo(c: StyleTree) = { 57 | new StyleTree( 58 | c.selectors, 59 | c.styles, 60 | c.children ++ Seq(st) 61 | ) 62 | } 63 | } 64 | 65 | } 66 | 67 | /** 68 | * Provides all the CSS pseudo-selectors as strongly-typed 69 | * properties when mixed in. The only requirement is that you 70 | * define `extend` to tell it what each of these properties 71 | * returns 72 | */ 73 | trait PseudoSelectors[T]{ 74 | 75 | def pseudoExtend(s: String): T 76 | // Pseudo-selectors 77 | // https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes 78 | def active = pseudoExtend("active") 79 | def checked = pseudoExtend("checked") 80 | def default = pseudoExtend("default") 81 | def disabled = pseudoExtend("disabled") 82 | def empty = pseudoExtend("empty") 83 | def enabled = pseudoExtend("enabled") 84 | def first = pseudoExtend("first") 85 | def firstChild = pseudoExtend("first-child") 86 | def firstOfType = pseudoExtend("first-of-type") 87 | def fullscreen = pseudoExtend("fullscreen") 88 | def focus = pseudoExtend("focus") 89 | def hover = pseudoExtend("hover") 90 | def indeterminate = pseudoExtend("indeterminate") 91 | def inRange = pseudoExtend("in-range") 92 | def invalid = pseudoExtend("invalid") 93 | def lastChild = pseudoExtend("last-child") 94 | def lastOfType = pseudoExtend("last-of-type") 95 | def left = pseudoExtend("left") 96 | def link = pseudoExtend("link") 97 | def onlyChild = pseudoExtend("only-child") 98 | def onlyOfType = pseudoExtend("only-of-type") 99 | def optional = pseudoExtend("optional") 100 | def outOfRange = pseudoExtend("out-of-range") 101 | def readOnly = pseudoExtend("read-only") 102 | def readWrite = pseudoExtend("read-write") 103 | def required = pseudoExtend("required") 104 | def right = pseudoExtend("right") 105 | def root = pseudoExtend("root") 106 | def scope = pseudoExtend("scope") 107 | def target = pseudoExtend("target") 108 | def valid = pseudoExtend("valid") 109 | def visited = pseudoExtend("visited") 110 | } 111 | 112 | 113 | /** 114 | * Lets you chain pseudo-selectors e.g. `hover.visited` and have it properly 115 | * translate into `:hover:visited` when rendered. 116 | */ 117 | class Selector(val built: Seq[String] = Nil) extends PseudoSelectors[Selector]{ b => 118 | def pseudoExtend(s: String) = { 119 | if(b.built == Nil) new Selector(Seq(":"+s)) 120 | else new Selector(b.built.init :+ (b.built.last + ":"+s)) 121 | } 122 | 123 | /** 124 | * Builds this selector into a [[StyleTree]] using the given 125 | * [[StyleSheetFrag]]s. This doesn't create a [[Cls]] on its own, 126 | * but can be used as part of the definition of an outer [[Cls]]. 127 | */ 128 | def apply(args: StyleSheetFrag*) = StyleTree.build(built, args) 129 | 130 | /** 131 | * Combine these two selectors, allowing the right-hand-side 132 | * selector to cascade. 133 | */ 134 | def ~(other: Selector) = new Selector(built ++ other.built) 135 | 136 | /** 137 | * Combine these two selectors using the `>` child selector, 138 | * which prevents cascading. 139 | */ 140 | def >(other: Selector) = new Selector(built ++ Seq(">") ++ other.built) 141 | } 142 | 143 | object Selector{ 144 | def apply(s: String) = new Selector(Seq(s)) 145 | } 146 | /** 147 | * Provides a strongly-typed list of all the HTML tags that can be 148 | * used as [[Selector]]s. 149 | */ 150 | trait StyleSheetTags{ 151 | 152 | // Root Element 153 | protected[this] val html = Selector("html") 154 | // Document Metadata 155 | protected[this] val head = Selector("head") 156 | protected[this] val base = Selector("base") 157 | 158 | protected[this] val link = Selector("link") 159 | protected[this] val meta = Selector("meta") 160 | // Scripting 161 | protected[this] val script = Selector("script") 162 | // Sections 163 | protected[this] val body = Selector("body") 164 | protected[this] val h1 = Selector("h1") 165 | protected[this] val h2 = Selector("h2") 166 | protected[this] val h3 = Selector("h3") 167 | protected[this] val h4 = Selector("h4") 168 | protected[this] val h5 = Selector("h5") 169 | protected[this] val h6 = Selector("h6") 170 | protected[this] val header = Selector("header") 171 | protected[this] val footer = Selector("footer") 172 | // Grouping content 173 | protected[this] val p = Selector("p") 174 | protected[this] val hr = Selector("hr") 175 | protected[this] val pre = Selector("pre") 176 | protected[this] val blockquote = Selector("blockquote") 177 | protected[this] val ol = Selector("ol") 178 | protected[this] val ul = Selector("ul") 179 | protected[this] val li = Selector("li") 180 | protected[this] val dl = Selector("dl") 181 | protected[this] val dt = Selector("dt") 182 | protected[this] val dd = Selector("dd") 183 | protected[this] val figure = Selector("figure") 184 | protected[this] val figcaption = Selector("figcaption") 185 | protected[this] val div = Selector("div") 186 | // Text-level semantics 187 | protected[this] val a = Selector("a") 188 | protected[this] val em = Selector("em") 189 | protected[this] val strong = Selector("strong") 190 | protected[this] val small = Selector("small") 191 | protected[this] val s = Selector("s") 192 | protected[this] val cite = Selector("cite") 193 | protected[this] val code = Selector("code") 194 | protected[this] val sub = Selector("sub") 195 | protected[this] val sup = Selector("sup") 196 | protected[this] val i = Selector("i") 197 | protected[this] val b = Selector("b") 198 | protected[this] val u = Selector("u") 199 | protected[this] val span = Selector("span") 200 | protected[this] val br = Selector("br") 201 | protected[this] val wbr = Selector("wbr") 202 | // Edits 203 | protected[this] val ins = Selector("ins") 204 | protected[this] val del = Selector("del") 205 | // Embedded content 206 | protected[this] val img = Selector("img") 207 | protected[this] val iframe = Selector("iframe") 208 | protected[this] val embed = Selector("embed") 209 | protected[this] val `object` = Selector("object") 210 | protected[this] val param = Selector("param") 211 | protected[this] val video = Selector("video") 212 | protected[this] val audio = Selector("audio") 213 | protected[this] val source = Selector("source") 214 | protected[this] val track = Selector("track") 215 | protected[this] val canvas = Selector("canvas") 216 | protected[this] val map = Selector("map") 217 | protected[this] val area = Selector("area") 218 | // Tabular data 219 | protected[this] val table = Selector("table") 220 | protected[this] val caption = Selector("caption") 221 | protected[this] val colgroup = Selector("colgroup") 222 | protected[this] val col = Selector("col") 223 | protected[this] val tbody = Selector("tbody") 224 | protected[this] val thead = Selector("thead") 225 | protected[this] val tfoot = Selector("tfoot") 226 | protected[this] val tr = Selector("tr") 227 | protected[this] val td = Selector("td") 228 | protected[this] val th = Selector("th") 229 | // Forms 230 | protected[this] val form = Selector("form") 231 | protected[this] val fieldset = Selector("fieldset") 232 | protected[this] val legend = Selector("legend") 233 | protected[this] val label = Selector("label") 234 | protected[this] val input = Selector("input") 235 | protected[this] val button = Selector("button") 236 | protected[this] val select = Selector("select") 237 | protected[this] val datalist = Selector("datalist") 238 | protected[this] val optgroup = Selector("optgroup") 239 | protected[this] val option = Selector("option") 240 | protected[this] val textarea = Selector("textarea") 241 | } 242 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/stylesheet/StyleSheet.scala: -------------------------------------------------------------------------------- 1 | package scalatags.stylesheet 2 | 3 | import scala.collection.immutable.SortedMap 4 | import scala.language.implicitConversions 5 | 6 | /** 7 | * A [[StyleSheet]] which lets you define cascading tag/class 8 | * selectors. Separate from [[StyleSheet]] because you almost 9 | * never need these things, so it's good to make it explicit 10 | * when you do to prevent accidental cascading. 11 | */ 12 | abstract class CascadingStyleSheet(implicit sourceName: sourcecode.FullName) extends StyleSheet with StyleSheetTags{ 13 | protected[this] implicit def clsSelector(c: Cls): Selector = new Selector(Seq("." + c.name)) 14 | } 15 | 16 | /** 17 | * Inherit from me to define a stylesheet which you can use to define 18 | * styles which get serialized to a `String`. Does not allow the use 19 | * of cascading tag/class selectors; use [[CascadingStyleSheet]] for that. 20 | */ 21 | abstract class StyleSheet(implicit sourceName: sourcecode.FullName){ 22 | /** 23 | * The name of this CSS stylesheet. Defaults to the name of the trait, 24 | * but you can override 25 | */ 26 | def customSheetName: Option[String] = None 27 | 28 | /** 29 | * Converts the name of the [[StyleSheet]]'s, the name of the member, and 30 | * any applicable pseudo-selectors into the name of the CSS class. 31 | */ 32 | protected[this] def nameFor(memberName: String, pseudoSelectors: String) = { 33 | customSheetName.getOrElse(defaultSheetName.replace(".", "-")) + "-" + memberName + pseudoSelectors 34 | } 35 | 36 | /** 37 | * Namespace that holds all the css pseudo-selectors, to avoid collisions 38 | * with tags and style-names and other things. 39 | */ 40 | protected[this] val & = new Selector 41 | 42 | /** 43 | * `*` in a CSS selector. 44 | */ 45 | protected[this] object * extends Selector(Seq("*")) 46 | 47 | /** 48 | * Used to define a new, uniquely-named class with a set of 49 | * styles associated with it. 50 | */ 51 | protected[this] object cls extends Creator(Nil) 52 | protected[this] class Creator(selectors: Seq[String]) extends PseudoSelectors[Creator]{ 53 | def pseudoExtend(s: String): Creator = new Creator(selectors :+ s) 54 | 55 | /** 56 | * Collapse the tree of [[StyleSheetFrag]]s into a single [[Cls]], 57 | * side-effect all the output into the styleSheetText, and return the 58 | * [[Cls]] 59 | */ 60 | def apply(args: StyleSheetFrag*)(implicit name: sourcecode.Name): Cls = { 61 | Cls(nameFor(name.value, ""), selectors, args) 62 | } 63 | } 64 | 65 | /** 66 | * The default name of a stylesheet, filled in with the [[StyleSheet]] implicit macro 67 | */ 68 | protected[this] def defaultSheetName = sourceName.value.replace(' ', '.').replace('#', '.') 69 | /** 70 | * All classes defined in this stylesheet, filled in with the [[StyleSheet]] implicit macro 71 | */ 72 | protected[this] def initStyleSheet()(implicit sourceClasses: SourceClasses[this.type]) = 73 | allClasses0 = Some(() => sourceClasses.value(this)) 74 | 75 | private[this] var allClasses0: Option[() => Seq[Cls]] = None 76 | def allClasses = allClasses0 match { 77 | case Some(f) => f() 78 | case None => 79 | 80 | throw new Exception( 81 | "No CSS classes found on stylesheet " + this + 82 | ". Did you forget to call `initStyleSheet()` in the body of the style sheet?" 83 | ) 84 | } 85 | 86 | def styleSheetText = allClasses.map(_.structure.stringify(Nil)).mkString("\n") 87 | } 88 | 89 | /** 90 | * A rendered class; both the class `name` (used when injected into Scalatags 91 | * fragments) and the `structure` (used when injected into further class definitions) 92 | */ 93 | case class Cls(name: String, pseudoSelectors: Seq[String], args: Seq[StyleSheetFrag]){ 94 | lazy val structure = args.foldLeft(StyleTree(Seq(s".$name${pseudoSelectors.map(s => s":$s").mkString}"), SortedMap.empty, Nil))( 95 | (c, f) => f.applyTo(c) 96 | ) 97 | def splice = new StyleSheetFrag{ 98 | def applyTo(st: StyleTree) = { 99 | new StyleTree( 100 | st.selectors, 101 | structure.styles ++ st.styles, 102 | structure.children ++ st.children 103 | ) 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/text/Builder.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package text 3 | import java.io.StringWriter 4 | import scala.reflect.ClassTag 5 | import scalatags.generic.Style 6 | 7 | /** 8 | * Object to aggregate the modifiers into one coherent data structure 9 | * so the final HTML string can be properly generated. It's really 10 | * gross internally, but bloody fast. Even using pre-built data structures 11 | * like `mutable.Buffer` slows down the benchmarks considerably. Also 12 | * exposes more of its internals than it probably should for performance, 13 | * so even though the stuff isn't private, don't touch it! 14 | */ 15 | class Builder(var children: Array[Frag] = new Array(4), 16 | var attrs: Array[(String, Builder.ValueSource)] = new Array(4)){ 17 | final var childIndex = 0 18 | final var attrIndex = 0 19 | 20 | private[this] def incrementChidren(arr: Array[Frag], index: Int) = { 21 | if (index >= arr.length){ 22 | val newArr = new Array[Frag](arr.length * 2) 23 | var i = 0 24 | while(i < arr.length){ 25 | newArr(i) = arr(i) 26 | i += 1 27 | } 28 | newArr 29 | }else{ 30 | null 31 | } 32 | } 33 | 34 | private[this] def incrementAttr(arr: Array[(String, Builder.ValueSource)], index: Int) = { 35 | if (index >= arr.length){ 36 | val newArr = new Array[(String, Builder.ValueSource)](arr.length * 2) 37 | var i = 0 38 | while(i < arr.length){ 39 | newArr(i) = arr(i) 40 | i += 1 41 | } 42 | newArr 43 | }else{ 44 | null 45 | } 46 | } 47 | 48 | private[this] def increment[T: ClassTag](arr: Array[T], index: Int) = { 49 | if (index >= arr.length){ 50 | val newArr = new Array[T](arr.length * 2) 51 | var i = 0 52 | while(i < arr.length){ 53 | newArr(i) = arr(i) 54 | i += 1 55 | } 56 | newArr 57 | }else{ 58 | null 59 | } 60 | } 61 | def addChild(c: Frag) = { 62 | val newChildren = incrementChidren(children, childIndex) 63 | if (newChildren != null) children = newChildren 64 | children(childIndex) = c 65 | childIndex += 1 66 | } 67 | def appendAttr(k: String, v: Builder.ValueSource) = { 68 | 69 | attrIndex(k) match{ 70 | case -1 => 71 | val newAttrs = incrementAttr(attrs, attrIndex) 72 | if (newAttrs!= null) attrs = newAttrs 73 | 74 | attrs(attrIndex) = k -> v 75 | attrIndex += 1 76 | case n => 77 | val (oldK, oldV) = attrs(n) 78 | attrs(n) = (oldK, Builder.ChainedAttributeValueSource(oldV, v)) 79 | } 80 | } 81 | def setAttr(k: String, v: Builder.ValueSource) = { 82 | attrIndex(k) match{ 83 | case -1 => 84 | val newAttrs = incrementAttr(attrs, attrIndex) 85 | if (newAttrs!= null) attrs = newAttrs 86 | attrs(attrIndex) = k -> v 87 | attrIndex += 1 88 | case n => 89 | val (oldK, oldV) = attrs(n) 90 | attrs(n) = (oldK, Builder.ChainedAttributeValueSource(oldV, v)) 91 | } 92 | } 93 | 94 | 95 | def appendAttrStrings(v: Builder.ValueSource, sb: java.io.Writer): Unit = { 96 | v.appendAttrValue(sb) 97 | } 98 | 99 | def attrsString(v: Builder.ValueSource): String = { 100 | val sb = new java.io.StringWriter 101 | appendAttrStrings(v, sb) 102 | sb.toString 103 | } 104 | 105 | 106 | 107 | def attrIndex(k: String): Int = { 108 | attrs.indexWhere(x => x != null && x._1 == k) 109 | } 110 | } 111 | object Builder{ 112 | 113 | /** 114 | * More-or-less internal trait, used to package up the parts of a textual 115 | * attribute or style so that we can append the chunks directly to the 116 | * output buffer. Improves perf over immediately combining them into a 117 | * string and storing that, since this avoids allocating that intermediate 118 | * string. 119 | */ 120 | trait ValueSource { 121 | def appendAttrValue(strb: java.io.Writer): Unit 122 | } 123 | case class StyleValueSource(s: Style, v: String) extends ValueSource { 124 | override def appendAttrValue(strb: java.io.Writer): Unit = { 125 | Escaping.escape(s.cssName, strb) 126 | strb.append(": ") 127 | Escaping.escape(v, strb) 128 | strb.append(";") 129 | } 130 | } 131 | 132 | case class GenericAttrValueSource(v: String) extends ValueSource { 133 | override def appendAttrValue(strb: java.io.Writer): Unit = { 134 | Escaping.escape(v, strb) 135 | } 136 | } 137 | 138 | case class ChainedAttributeValueSource(head: ValueSource, tail: ValueSource) extends ValueSource { 139 | override def appendAttrValue(strb: java.io.Writer): Unit = { 140 | head.appendAttrValue(strb) 141 | strb.append(" ") 142 | tail.appendAttrValue(strb) 143 | } 144 | } 145 | } 146 | 147 | trait Frag extends generic.Frag[Builder, String] { 148 | def writeTo(strb: java.io.Writer): Unit 149 | def writeBytesTo(out: java.io.OutputStream): Unit = { 150 | val w = new java.io.OutputStreamWriter(out, java.nio.charset.StandardCharsets.UTF_8) 151 | writeTo(w) 152 | w.flush() 153 | } 154 | def render: String 155 | def applyTo(b: Builder) = b.addChild(this) 156 | } 157 | 158 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/text/SvgTags.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package text 3 | trait SvgTags extends generic.SvgTags[Builder, String, String] 4 | with TagFactory{ 5 | lazy val altGlyph: ConcreteHtmlTag[String] = tag("altGlyph") 6 | lazy val altGlyphDef: ConcreteHtmlTag[String] = tag("altGlyphDef") 7 | lazy val altGlyphItem: ConcreteHtmlTag[String] = tag("altGlyphItem") 8 | lazy val animate: ConcreteHtmlTag[String] = tag("animate") 9 | lazy val animateMotion: ConcreteHtmlTag[String] = tag("animateMotion") 10 | lazy val animateTransform: ConcreteHtmlTag[String] = tag("animateTransform") 11 | lazy val circle: ConcreteHtmlTag[String] = tag("circle") 12 | lazy val clipPath: ConcreteHtmlTag[String] = tag("clipPath") 13 | lazy val `color-profile`: ConcreteHtmlTag[String] = tag("color-profile") 14 | lazy val cursor: ConcreteHtmlTag[String] = tag("cursor") 15 | lazy val defs: ConcreteHtmlTag[String] = tag("defs") 16 | lazy val desc: ConcreteHtmlTag[String] = tag("desc") 17 | lazy val ellipse: ConcreteHtmlTag[String] = tag("ellipse") 18 | lazy val feBlend: ConcreteHtmlTag[String] = tag("feBlend") 19 | lazy val feColorMatrix: ConcreteHtmlTag[String] = tag("feColorMatrix") 20 | lazy val feComponentTransfer: ConcreteHtmlTag[String] = tag("feComponentTransfer") 21 | lazy val feComposite: ConcreteHtmlTag[String] = tag("feComposite") 22 | lazy val feConvolveMatrix: ConcreteHtmlTag[String] = tag("feConvolveMatrix") 23 | lazy val feDiffuseLighting: ConcreteHtmlTag[String] = tag("feDiffuseLighting") 24 | lazy val feDisplacementMap: ConcreteHtmlTag[String] = tag("feDisplacementMap") 25 | lazy val feDistantLighting: ConcreteHtmlTag[String] = tag("feDistantLighting") 26 | lazy val feFlood: ConcreteHtmlTag[String] = tag("feFlood") 27 | lazy val feFuncA: ConcreteHtmlTag[String] = tag("feFuncA") 28 | lazy val feFuncB: ConcreteHtmlTag[String] = tag("feFuncB") 29 | lazy val feFuncG: ConcreteHtmlTag[String] = tag("feFuncG") 30 | lazy val feFuncR: ConcreteHtmlTag[String] = tag("feFuncR") 31 | lazy val feGaussianBlur: ConcreteHtmlTag[String] = tag("feGaussianBlur") 32 | lazy val feImage: ConcreteHtmlTag[String] = tag("feImage") 33 | lazy val feMerge: ConcreteHtmlTag[String] = tag("feMerge") 34 | lazy val feMergeNode: ConcreteHtmlTag[String] = tag("feMergeNode") 35 | lazy val feMorphology: ConcreteHtmlTag[String] = tag("feMorphology") 36 | lazy val feOffset: ConcreteHtmlTag[String] = tag("feOffset") 37 | lazy val fePointLight: ConcreteHtmlTag[String] = tag("fePointLight") 38 | lazy val feSpecularLighting: ConcreteHtmlTag[String] = tag("feSpecularLighting") 39 | lazy val feSpotlight: ConcreteHtmlTag[String] = tag("feSpotlight") 40 | lazy val feTile: ConcreteHtmlTag[String] = tag("feTile") 41 | lazy val feTurbulance: ConcreteHtmlTag[String] = tag("feTurbulance") 42 | lazy val filter: ConcreteHtmlTag[String] = tag("filter") 43 | lazy val font: ConcreteHtmlTag[String] = tag("font") 44 | lazy val `font-face`: ConcreteHtmlTag[String] = tag("font-face") 45 | lazy val `font-face-format`: ConcreteHtmlTag[String] = tag("font-face-format") 46 | lazy val `font-face-name`: ConcreteHtmlTag[String] = tag("font-face-name") 47 | lazy val `font-face-src`: ConcreteHtmlTag[String] = tag("font-face-src") 48 | lazy val `font-face-uri`: ConcreteHtmlTag[String] = tag("font-face-uri") 49 | lazy val foreignObject: ConcreteHtmlTag[String] = tag("foreignObject") 50 | lazy val g: ConcreteHtmlTag[String] = tag("g") 51 | lazy val glyph: ConcreteHtmlTag[String] = tag("glyph") 52 | lazy val glyphRef: ConcreteHtmlTag[String] = tag("glyphRef") 53 | lazy val hkern: ConcreteHtmlTag[String] = tag("hkern") 54 | lazy val image: ConcreteHtmlTag[String] = tag("image") 55 | lazy val line: ConcreteHtmlTag[String] = tag("line") 56 | lazy val linearGradient: ConcreteHtmlTag[String] = tag("linearGradient") 57 | lazy val marker: ConcreteHtmlTag[String] = tag("marker") 58 | lazy val mask: ConcreteHtmlTag[String] = tag("mask") 59 | lazy val metadata: ConcreteHtmlTag[String] = tag("metadata") 60 | lazy val `missing-glyph`: ConcreteHtmlTag[String] = tag("missing-glyph") 61 | lazy val mpath: ConcreteHtmlTag[String] = tag("mpath") 62 | lazy val path: ConcreteHtmlTag[String] = tag("path") 63 | lazy val pattern: ConcreteHtmlTag[String] = tag("pattern") 64 | lazy val polygon: ConcreteHtmlTag[String] = tag("polygon") 65 | lazy val polyline: ConcreteHtmlTag[String] = tag("polyline") 66 | lazy val radialGradient: ConcreteHtmlTag[String] = tag("radialGradient") 67 | lazy val rect: ConcreteHtmlTag[String] = tag("rect") 68 | lazy val set: ConcreteHtmlTag[String] = tag("set") 69 | lazy val stop: ConcreteHtmlTag[String] = tag("stop") 70 | lazy val svg: ConcreteHtmlTag[String] = tag("svg") 71 | lazy val switch: ConcreteHtmlTag[String] = tag("switch") 72 | lazy val symbol: ConcreteHtmlTag[String] = tag("symbol") 73 | lazy val text: ConcreteHtmlTag[String] = tag("text") 74 | lazy val textPath: ConcreteHtmlTag[String] = tag("textPath") 75 | lazy val tref: ConcreteHtmlTag[String] = tag("tref") 76 | lazy val tspan: ConcreteHtmlTag[String] = tag("tspan") 77 | lazy val use: ConcreteHtmlTag[String] = tag("use") 78 | lazy val view: ConcreteHtmlTag[String] = tag("view") 79 | lazy val vkern: ConcreteHtmlTag[String] = tag("vkern") 80 | } 81 | 82 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/text/TagFactory.scala: -------------------------------------------------------------------------------- 1 | package scalatags.text 2 | 3 | import scalatags.Escaping 4 | import scalatags.generic.Namespace 5 | 6 | /** 7 | * Created by haoyi on 7/9/16. 8 | */ 9 | trait TagFactory extends scalatags.generic.Util[Builder, String, String]{ 10 | 11 | def tag(s: String, void: Boolean = false): ConcreteHtmlTag[String] = { 12 | if (!Escaping.validTag(s)) 13 | throw new IllegalArgumentException( 14 | s"Illegal tag name: $s is not a valid XML tag name" 15 | ) 16 | makeAbstractTypedTag[String](s, void, Namespace.htmlNamespaceConfig) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/text/Tags.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package text 3 | trait Tags extends generic.Tags[Builder, String, String] with TagFactory{ 4 | // Root Element 5 | lazy val html: ConcreteHtmlTag[String] = tag("html") 6 | // Document Metadata 7 | lazy val head: ConcreteHtmlTag[String] = tag("head") 8 | lazy val base: ConcreteHtmlTag[String] = tag("base", void = true) 9 | lazy val link: ConcreteHtmlTag[String] = tag("link", void = true) 10 | lazy val meta: ConcreteHtmlTag[String] = tag("meta", void = true) 11 | // Scripting 12 | lazy val script: ConcreteHtmlTag[String] = tag("script") 13 | // Sections 14 | lazy val body: ConcreteHtmlTag[String] = tag("body") 15 | lazy val h1: ConcreteHtmlTag[String] = tag("h1") 16 | lazy val h2: ConcreteHtmlTag[String] = tag("h2") 17 | lazy val h3: ConcreteHtmlTag[String] = tag("h3") 18 | lazy val h4: ConcreteHtmlTag[String] = tag("h4") 19 | lazy val h5: ConcreteHtmlTag[String] = tag("h5") 20 | lazy val h6: ConcreteHtmlTag[String] = tag("h6") 21 | lazy val header: ConcreteHtmlTag[String] = tag("header") 22 | lazy val footer: ConcreteHtmlTag[String] = tag("footer") 23 | // Grouping content 24 | lazy val p: ConcreteHtmlTag[String] = tag("p") 25 | lazy val hr: ConcreteHtmlTag[String] = tag("hr", void = true) 26 | lazy val pre: ConcreteHtmlTag[String] = tag("pre") 27 | lazy val blockquote: ConcreteHtmlTag[String] = tag("blockquote") 28 | lazy val ol: ConcreteHtmlTag[String] = tag("ol") 29 | lazy val ul: ConcreteHtmlTag[String] = tag("ul") 30 | lazy val li: ConcreteHtmlTag[String] = tag("li") 31 | lazy val dl: ConcreteHtmlTag[String] = tag("dl") 32 | lazy val dt: ConcreteHtmlTag[String] = tag("dt") 33 | lazy val dd: ConcreteHtmlTag[String] = tag("dd") 34 | lazy val figure: ConcreteHtmlTag[String] = tag("figure") 35 | lazy val figcaption: ConcreteHtmlTag[String] = tag("figcaption") 36 | lazy val div: ConcreteHtmlTag[String] = tag("div") 37 | // Text-level semantics 38 | lazy val a: ConcreteHtmlTag[String] = tag("a") 39 | lazy val em: ConcreteHtmlTag[String] = tag("em") 40 | lazy val strong: ConcreteHtmlTag[String] = tag("strong") 41 | lazy val small: ConcreteHtmlTag[String] = tag("small") 42 | lazy val s: ConcreteHtmlTag[String] = tag("s") 43 | lazy val cite: ConcreteHtmlTag[String] = tag("cite") 44 | lazy val code: ConcreteHtmlTag[String] = tag("code") 45 | lazy val sub: ConcreteHtmlTag[String] = tag("sub") 46 | lazy val sup: ConcreteHtmlTag[String] = tag("sup") 47 | lazy val i: ConcreteHtmlTag[String] = tag("i") 48 | lazy val b: ConcreteHtmlTag[String] = tag("b") 49 | lazy val u: ConcreteHtmlTag[String] = tag("u") 50 | lazy val span: ConcreteHtmlTag[String] = tag("span") 51 | lazy val br: ConcreteHtmlTag[String] = tag("br", void = true) 52 | lazy val wbr: ConcreteHtmlTag[String] = tag("wbr", void = true) 53 | // Edits 54 | lazy val ins: ConcreteHtmlTag[String] = tag("ins") 55 | lazy val del: ConcreteHtmlTag[String] = tag("del") 56 | // Embedded content 57 | lazy val img: ConcreteHtmlTag[String] = tag("img", void = true) 58 | lazy val iframe: ConcreteHtmlTag[String] = tag("iframe") 59 | lazy val embed: ConcreteHtmlTag[String] = tag("embed", void = true) 60 | lazy val `object`: ConcreteHtmlTag[String] = tag("object") 61 | lazy val param: ConcreteHtmlTag[String] = tag("param", void = true) 62 | lazy val video: ConcreteHtmlTag[String] = tag("video") 63 | lazy val audio: ConcreteHtmlTag[String] = tag("audio") 64 | lazy val source: ConcreteHtmlTag[String] = tag("source", void = true) 65 | lazy val track: ConcreteHtmlTag[String] = tag("track", void = true) 66 | lazy val canvas: ConcreteHtmlTag[String] = tag("canvas") 67 | lazy val map: ConcreteHtmlTag[String] = tag("map") 68 | lazy val area: ConcreteHtmlTag[String] = tag("area", void = true) 69 | // Tabular data 70 | lazy val table: ConcreteHtmlTag[String] = tag("table") 71 | lazy val caption: ConcreteHtmlTag[String] = tag("caption") 72 | lazy val colgroup: ConcreteHtmlTag[String] = tag("colgroup") 73 | lazy val col: ConcreteHtmlTag[String] = tag("col", void = true) 74 | lazy val tbody: ConcreteHtmlTag[String] = tag("tbody") 75 | lazy val thead: ConcreteHtmlTag[String] = tag("thead") 76 | lazy val tfoot: ConcreteHtmlTag[String] = tag("tfoot") 77 | lazy val tr: ConcreteHtmlTag[String] = tag("tr") 78 | lazy val td: ConcreteHtmlTag[String] = tag("td") 79 | lazy val th: ConcreteHtmlTag[String] = tag("th") 80 | // Forms 81 | lazy val form: ConcreteHtmlTag[String] = tag("form") 82 | lazy val fieldset: ConcreteHtmlTag[String] = tag("fieldset") 83 | lazy val legend: ConcreteHtmlTag[String] = tag("legend") 84 | lazy val label: ConcreteHtmlTag[String] = tag("label") 85 | lazy val input: ConcreteHtmlTag[String] = tag("input", void = true) 86 | lazy val button: ConcreteHtmlTag[String] = tag("button") 87 | lazy val select: ConcreteHtmlTag[String] = tag("select") 88 | lazy val datalist: ConcreteHtmlTag[String] = tag("datalist") 89 | lazy val optgroup: ConcreteHtmlTag[String] = tag("optgroup") 90 | lazy val option: ConcreteHtmlTag[String] = tag("option") 91 | lazy val textarea: ConcreteHtmlTag[String] = tag("textarea") 92 | } 93 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/text/Tags2.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package text 3 | trait Tags2 extends generic.Tags2[Builder, String, String] with TagFactory{ 4 | // Document Metadata 5 | lazy val title: ConcreteHtmlTag[String] = tag("title") 6 | lazy val style: ConcreteHtmlTag[String] = tag("style") 7 | // Scripting 8 | lazy val noscript: ConcreteHtmlTag[String] = tag("noscript") 9 | // Sections 10 | lazy val section: ConcreteHtmlTag[String] = tag("section") 11 | lazy val nav: ConcreteHtmlTag[String] = tag("nav") 12 | lazy val article: ConcreteHtmlTag[String] = tag("article") 13 | lazy val aside: ConcreteHtmlTag[String] = tag("aside") 14 | lazy val address: ConcreteHtmlTag[String] = tag("address") 15 | lazy val main: ConcreteHtmlTag[String] = tag("main") 16 | // Text level semantics 17 | lazy val q: ConcreteHtmlTag[String] = tag("q") 18 | lazy val dfn: ConcreteHtmlTag[String] = tag("dfn") 19 | lazy val abbr: ConcreteHtmlTag[String] = tag("abbr") 20 | lazy val data: ConcreteHtmlTag[String] = tag("data") 21 | lazy val time: ConcreteHtmlTag[String] = tag("time") 22 | lazy val `var`: ConcreteHtmlTag[String] = tag("var") 23 | lazy val samp: ConcreteHtmlTag[String] = tag("samp") 24 | lazy val kbd: ConcreteHtmlTag[String] = tag("kbd") 25 | lazy val math: ConcreteHtmlTag[String] = tag("math") 26 | lazy val mark: ConcreteHtmlTag[String] = tag("mark") 27 | lazy val ruby: ConcreteHtmlTag[String] = tag("ruby") 28 | lazy val rt: ConcreteHtmlTag[String] = tag("rt") 29 | lazy val rp: ConcreteHtmlTag[String] = tag("rp") 30 | lazy val bdi: ConcreteHtmlTag[String] = tag("bdi") 31 | lazy val bdo: ConcreteHtmlTag[String] = tag("bdo") 32 | // Forms 33 | lazy val keygen: ConcreteHtmlTag[String] = tag("keygen", void = true) 34 | lazy val output: ConcreteHtmlTag[String] = tag("output") 35 | lazy val progress: ConcreteHtmlTag[String] = tag("progress") 36 | lazy val meter: ConcreteHtmlTag[String] = tag("meter") 37 | // Interactive elements 38 | lazy val details: ConcreteHtmlTag[String] = tag("details") 39 | lazy val summary: ConcreteHtmlTag[String] = tag("summary") 40 | lazy val command: ConcreteHtmlTag[String] = tag("command", void = true) 41 | lazy val menu: ConcreteHtmlTag[String] = tag("menu") 42 | } 43 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/vdom/Builder.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package vdom 3 | trait Builder[Output, FragT]{ 4 | def appendChild(child: FragT): Unit 5 | def appendClass(cls: String): Unit 6 | def appendStyle(cssName: String, value: String): Unit 7 | def setAttr(name: String, value: String): Unit 8 | def render(): Output 9 | } 10 | 11 | trait Frag[Output, FragT] extends scalatags.generic.Frag[Builder[Output, FragT], FragT]{ 12 | def render: FragT 13 | def applyTo(b: Builder[Output, FragT]) = b.appendChild(this.render) 14 | } -------------------------------------------------------------------------------- /scalatags/src/scalatags/vdom/SvgTags.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package vdom 3 | 4 | import scalatags.generic.{Namespace, Util} 5 | 6 | trait SvgTags[Output <: FragT, FragT] 7 | extends generic.SvgTags[Builder[Output, FragT], Output, FragT] with TagFactory[Output, FragT]{ 8 | implicit lazy val svgNamespaceConfig: Namespace = Namespace.svgNamespaceConfig 9 | lazy val altGlyph = tag("altGlyph") 10 | lazy val altGlyphDef = tag("altGlyphDef") 11 | lazy val altGlyphItem = tag("altGlyphItem") 12 | lazy val animate = tag("animate") 13 | lazy val animateMotion = tag("animateMotion") 14 | lazy val animateTransform = tag("animateTransform") 15 | lazy val circle = tag("circle") 16 | lazy val clipPath = tag("clipPath") 17 | lazy val `color-profile` = tag("color-profile") 18 | lazy val cursor = tag("cursor") 19 | lazy val defs = tag("defs") 20 | lazy val desc = tag("desc") 21 | lazy val ellipse = tag("ellipse") 22 | lazy val feBlend = tag("feBlend") 23 | lazy val feColorMatrix = tag("feColorMatrix") 24 | lazy val feComponentTransfer = tag("feComponentTransfer") 25 | lazy val feComposite = tag("feComposite") 26 | lazy val feConvolveMatrix = tag("feConvolveMatrix") 27 | lazy val feDiffuseLighting = tag("feDiffuseLighting") 28 | lazy val feDisplacementMap = tag("feDisplacementMap") 29 | lazy val feDistantLighting = tag("feDistantLighting") 30 | lazy val feFlood = tag("feFlood") 31 | lazy val feFuncA = tag("feFuncA") 32 | lazy val feFuncB = tag("feFuncB") 33 | lazy val feFuncG = tag("feFuncG") 34 | lazy val feFuncR = tag("feFuncR") 35 | lazy val feGaussianBlur = tag("feGaussianBlur") 36 | lazy val feImage = tag("feImage") 37 | lazy val feMerge = tag("feMerge") 38 | lazy val feMergeNode = tag("feMergeNode") 39 | lazy val feMorphology = tag("feMorphology") 40 | lazy val feOffset = tag("feOffset") 41 | lazy val fePointLight = tag("fePointLight") 42 | lazy val feSpecularLighting = tag("feSpecularLighting") 43 | lazy val feSpotlight = tag("feSpotlight") 44 | lazy val feTile = tag("feTile") 45 | lazy val feTurbulance = tag("feTurbulance") 46 | lazy val filter = tag("filter") 47 | lazy val font = tag("font") 48 | lazy val `font-face` = tag("font-face") 49 | lazy val `font-face-format` = tag("font-face-format") 50 | lazy val `font-face-name` = tag("font-face-name") 51 | lazy val `font-face-src` = tag("font-face-src") 52 | lazy val `font-face-uri` = tag("font-face-uri") 53 | lazy val foreignObject = tag("foreignObject") 54 | lazy val g = tag("g") 55 | lazy val glyph = tag("glyph") 56 | lazy val glyphRef = tag("glyphRef") 57 | lazy val hkern = tag("hkern") 58 | lazy val image = tag("image") 59 | lazy val line = tag("line") 60 | lazy val linearGradient = tag("linearGradient") 61 | lazy val marker = tag("marker") 62 | lazy val mask = tag("mask") 63 | lazy val metadata = tag("metadata") 64 | lazy val `missing-glyph` = tag("missing-glyph") 65 | lazy val mpath = tag("mpath") 66 | lazy val path = tag("path") 67 | lazy val pattern = tag("pattern") 68 | lazy val polygon = tag("polygon") 69 | lazy val polyline = tag("polyline") 70 | lazy val radialGradient = tag("radialGradient") 71 | lazy val rect = tag("rect") 72 | lazy val set = tag("set") 73 | lazy val stop = tag("stop") 74 | lazy val svg = tag("svg") 75 | lazy val switch = tag("switch") 76 | lazy val symbol = tag("symbol") 77 | lazy val text = tag("text") 78 | lazy val textPath = tag("textPath") 79 | lazy val tref = tag("tref") 80 | lazy val tspan = tag("tspan") 81 | lazy val use = tag("use") 82 | lazy val view = tag("view") 83 | lazy val vkern = tag("vkern") 84 | } 85 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/vdom/TagFactory.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package vdom 3 | 4 | import scalatags.Escaping 5 | import scalatags.generic.Namespace 6 | 7 | 8 | /** 9 | * Created by haoyi on 7/9/16. 10 | */ 11 | trait TagFactory[Output <: FragT, FragT] extends scalatags.generic.Util[Builder[Output, FragT], Output, FragT]{ 12 | def tag(s: String, void: Boolean = false): ConcreteHtmlTag[Output] = { 13 | if (!Escaping.validTag(s)) 14 | throw new IllegalArgumentException( 15 | s"Illegal tag name: $s is not a valid XML tag name" 16 | ) 17 | makeAbstractTypedTag[Output](s, void, scalatags.generic.Namespace.htmlNamespaceConfig) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/vdom/Tags.scala: -------------------------------------------------------------------------------- 1 | 2 | package scalatags 3 | package vdom 4 | 5 | import scalatags.generic.Util 6 | 7 | trait Tags[Output <: FragT, FragT] 8 | extends generic.Tags[Builder[Output, FragT], Output, FragT] with TagFactory[Output, FragT]{ 9 | // Root Element 10 | lazy val html = tag("html") 11 | // Document Metadata 12 | lazy val head = tag("head") 13 | lazy val base = tag("base", void = true) 14 | lazy val link = tag("link", void = true) 15 | lazy val meta = tag("meta", void = true) 16 | // Scripting 17 | lazy val script = tag("script") 18 | // Sections 19 | lazy val body = tag("body") 20 | lazy val h1 = tag("h1") 21 | lazy val h2 = tag("h2") 22 | lazy val h3 = tag("h3") 23 | lazy val h4 = tag("h4") 24 | lazy val h5 = tag("h5") 25 | lazy val h6 = tag("h6") 26 | lazy val header = tag("header") 27 | lazy val footer = tag("footer") 28 | // Grouping content 29 | lazy val p = tag("p") 30 | lazy val hr = tag("hr", void = true) 31 | lazy val pre = tag("pre") 32 | lazy val blockquote = tag("blockquote") 33 | lazy val ol = tag("ol") 34 | lazy val ul = tag("ul") 35 | lazy val li = tag("li") 36 | lazy val dl = tag("dl") 37 | lazy val dt = tag("dt") 38 | lazy val dd = tag("dd") 39 | lazy val figure = tag("figure") 40 | lazy val figcaption = tag("figcaption") 41 | lazy val div = tag("div") 42 | // Text-level semantics 43 | lazy val a = tag("a") 44 | lazy val em = tag("em") 45 | lazy val strong = tag("strong") 46 | lazy val small = tag("small") 47 | lazy val s = tag("s") 48 | lazy val cite = tag("cite") 49 | lazy val code = tag("code") 50 | lazy val sub = tag("sub") 51 | lazy val sup = tag("sup") 52 | lazy val i = tag("i") 53 | lazy val b = tag("b") 54 | lazy val u = tag("u") 55 | lazy val span = tag("span") 56 | lazy val br = tag("br", void = true) 57 | lazy val wbr = tag("wbr", void = true) 58 | // Edits 59 | lazy val ins = tag("ins") 60 | lazy val del = tag("del") 61 | // Embedded content 62 | lazy val img = tag("img", void = true) 63 | lazy val iframe = tag("iframe") 64 | lazy val embed = tag("embed", void = true) 65 | lazy val `object` = tag("object") 66 | lazy val param = tag("param", void = true) 67 | lazy val video = tag("video") 68 | lazy val audio = tag("audio") 69 | lazy val source = tag("source", void = true) 70 | lazy val track = tag("track", void = true) 71 | lazy val canvas = tag("canvas") 72 | lazy val map = tag("map") 73 | lazy val area = tag("area", void = true) 74 | // Tabular data 75 | lazy val table = tag("table") 76 | lazy val caption = tag("caption") 77 | lazy val colgroup = tag("colgroup") 78 | lazy val col = tag("col", void = true) 79 | lazy val tbody = tag("tbody") 80 | lazy val thead = tag("thead") 81 | lazy val tfoot = tag("tfoot") 82 | lazy val tr = tag("tr") 83 | lazy val td = tag("td") 84 | lazy val th = tag("th") 85 | // Forms 86 | lazy val form = tag("form") 87 | lazy val fieldset = tag("fieldset") 88 | lazy val legend = tag("legend") 89 | lazy val label = tag("label") 90 | lazy val input = tag("input", void = true) 91 | lazy val button = tag("button") 92 | lazy val select = tag("select") 93 | lazy val datalist = tag("datalist") 94 | lazy val optgroup = tag("optgroup") 95 | lazy val option = tag("option") 96 | lazy val textarea = tag("textarea") 97 | } 98 | -------------------------------------------------------------------------------- /scalatags/src/scalatags/vdom/Tags2.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package vdom 3 | import scalatags.generic.Util 4 | 5 | trait Tags2[Output <: FragT, FragT] 6 | extends generic.Tags2[Builder[Output, FragT], Output, FragT] with TagFactory[Output, FragT]{ 7 | // Document Metadata 8 | lazy val title = tag("title") 9 | lazy val style = tag("style") 10 | // Scripting 11 | lazy val noscript = tag("noscript") 12 | // Sections 13 | lazy val section = tag("section") 14 | lazy val nav = tag("nav") 15 | lazy val article = tag("article") 16 | lazy val aside = tag("aside") 17 | lazy val address = tag("address") 18 | lazy val main = tag("main") 19 | // Text level semantics 20 | lazy val q = tag("q") 21 | lazy val dfn = tag("dfn") 22 | lazy val abbr = tag("abbr") 23 | lazy val data = tag("data") 24 | lazy val time = tag("time") 25 | lazy val `var` = tag("var") 26 | lazy val samp = tag("samp") 27 | lazy val kbd = tag("kbd") 28 | lazy val math = tag("math") 29 | lazy val mark = tag("mark") 30 | lazy val ruby = tag("ruby") 31 | lazy val rt = tag("rt") 32 | lazy val rp = tag("rp") 33 | lazy val bdi = tag("bdi") 34 | lazy val bdo = tag("bdo") 35 | // Forms 36 | lazy val keygen = tag("keygen", void = true) 37 | lazy val output = tag("output") 38 | lazy val progress = tag("progress") 39 | lazy val meter = tag("meter") 40 | // Interactive elements 41 | lazy val details = tag("details") 42 | lazy val summary = tag("summary") 43 | lazy val command = tag("command", void = true) 44 | lazy val menu = tag("menu") 45 | } 46 | -------------------------------------------------------------------------------- /scalatags/test/resource/page.jade: -------------------------------------------------------------------------------- 1 | -@ val titleString: String 2 | -@ val contentpara: String 3 | -@ val first: String 4 | -@ val firstParaString: String 5 | -@ val paras: Seq[(Int, String)] 6 | 7 | html 8 | head 9 | script console.log(1) 10 | 11 | body 12 | h1(style="color: red;") 13 | = titleString 14 | div(style="background-color: blue;") 15 | p(class="#{contentpara} #{first}" title="this is paragraph 0") 16 | = firstParaString 17 | 18 | a(href="www.google.com") 19 | p Goooogle 20 | 21 | - paras.foreach{ case (count, color) => 22 | - render("jvm/src/test/resource/para.jade", Map("count" -> count, "color" -> color)) 23 | - } 24 | 25 | 26 | -------------------------------------------------------------------------------- /scalatags/test/resource/page.mustache: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 |{{firstParaString}}
9 | 10 |Goooogle
11 | 12 | {{#paras}} 13 | {{> jvm/src/test/resource/para}} 14 | {{/paras}} 15 |Paragraph {{count}}
-------------------------------------------------------------------------------- /scalatags/test/src-js/scalatags/jsdom/BasicTests.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package jsdom 3 | object BasicTests extends generic.BasicTests(scalatags.JsDom) 4 | -------------------------------------------------------------------------------- /scalatags/test/src-js/scalatags/jsdom/DomTests.scala: -------------------------------------------------------------------------------- 1 | package scalatags 2 | package jsdom 3 | import utest._ 4 | 5 | 6 | 7 | import org.scalajs.dom 8 | import org.scalajs.dom.html.Paragraph 9 | 10 | object DomTests extends TestSuite{ 11 | class SharedTemplates[Builder, Output <: FragT, FragT](val bundle: scalatags.generic.Bundle[Builder, Output, FragT]){ 12 | import bundle.all._ 13 | val widget: Tag = div("hello") 14 | } 15 | def tests = TestSuite{ 16 | test("basic"){ 17 | import scalatags.JsDom.all._ 18 | test("children"){ 19 | val elem = div.render 20 | assert(elem.children.length == 0) 21 | elem.appendChild(p(1, "wtf", "bbq").render) 22 | assert(elem.children.length == 1) 23 | val pElem = elem.children(0).asInstanceOf[Paragraph] 24 | assert(pElem.childNodes.length == 3) 25 | assert(pElem.textContent == "1wtfbbq") 26 | } 27 | 28 | test("attributes"){ 29 | val url = "https://www.google.com/" 30 | val elem = a( 31 | href := url, 32 | "Google" 33 | ).render 34 | 35 | assert(elem.href == url) 36 | assert(elem.children.length == 0) 37 | assert(elem.childNodes.length == 1) 38 | val textNode = elem.childNodes(0).asInstanceOf[dom.Text] 39 | assert(textNode.textContent == "Google") 40 | } 41 | 42 | test("styles"){ 43 | val elem = div( 44 | color := "red", 45 | float.left, 46 | backgroundColor := "yellow" 47 | ).render 48 | assert(elem.style.color == "red") 49 | assert(elem.style.cssFloat == "left") 50 | assert(elem.style.backgroundColor == "yellow") 51 | // styles end up being sorted in alphabetical order 52 | val styleAttr = elem.getAttribute("style") 53 | assert( 54 | styleAttr.trim == "color: red; float: left; background-color: yellow;" 55 | ) 56 | } 57 | } 58 | test("fancy"){ 59 | import scalatags.JsDom.all._ 60 | test("fragSeqsAreFrags"){ 61 | val rendered = Seq( 62 | h1("titless"), 63 | div("lol") 64 | ).render 65 | 66 | val wrapped = div(rendered).toString 67 | assert(wrapped == "i am a cow
i am a cow
Red Text
33 |This is a big paragraph of text
69 |This is my first paragraph
97 |This is my second paragraph
98 |This is my first paragraph
131 |you are the 1023th visitor!
132 |i like pie
174 |pie is evil i hate you
178 |i like pie and pie is evil, i hat myself
182 |No more posts!
184 | 185 | 186 | """ 187 | ) 188 | test("functions") - strCheck( 189 | { 190 | def imgBox(source: String, text: String) = div( 191 | img(src:=source), 192 | div( 193 | p(text) 194 | ) 195 | ) 196 | 197 | html( 198 | head( 199 | script("some script") 200 | ), 201 | body( 202 | h1("This is my title"), 203 | imgBox("www.mysite.com/imageOne.png", "This is the first image displayed on the site"), 204 | div(`class`:="content")( 205 | p("blah blah blah i am text"), 206 | imgBox("www.mysite.com/imageTwo.png", "This image is very interesting") 207 | ) 208 | ) 209 | ) 210 | } 211 | , 212 | """ 213 | 214 | 215 | 216 | 217 | 218 |This is the first image displayed on the site
223 |blah blah blah i am text
227 |This image is very interesting
231 |This is my first paragraph
343 | 344 |Goooogle
345 | 346 |This is my first paragraph
366 | 367 |Goooogle
368 | 369 | 370 |This is my first paragraph
387 | 388 |Goooogle
389 | 390 | 391 |This is my first paragraph
488 |This is my second paragraph
489 |538 | a long paragraph which should not be broken 539 |
540 | 500 Memorial Drive, Cambridge MA 541 | 542 |Hello
601 | 602 | 603 | """ 604 | ) 605 | test("aria") - strCheck( 606 | div( 607 | div(id:="ch1Panel", role:="tabpanel", aria.labelledby:="ch1Tab")( 608 | "Chapter 1 content goes here" 609 | ), 610 | div(id:="ch2Panel", role:="tabpanel", aria.labelledby:="ch2Tab")( 611 | "Chapter 2 content goes here" 612 | ), 613 | div(id:="quizPanel", role:="tabpanel", aria.labelledby:="quizTab")( 614 | "Quiz content goes here" 615 | ) 616 | ) 617 | , 618 | """ 619 |World
685 |This is my first paragraph
58 | 59 |Goooogle
60 | 61 |Paragraph 0
62 |Paragraph 1
63 |Paragraph 2
64 |Paragraph 3
65 |Paragraph 4
66 |This is my first paragraph
19 | 20 |Goooogle
21 | 22 |Paragraph {i}
18 | // } 19 | // 20 | // 21 | // 22 | // 23 | // 24 | //{firstParaString}
27 | // 28 | //Goooogle
29 | // 30 | // {0 until 5 map para} 31 | //@firstParaString
10 | 11 |Goooogle
12 | 13 | @for((i, color) <- paras){ 14 | @para(contentpara, i, color) 15 | } 16 |Paragraph @index
3 | --------------------------------------------------------------------------------