Skip to content

Commit

Permalink
1.0-M3: Made it so metaClasses are not modified by default but are fo…
Browse files Browse the repository at this point in the history
…r the gradle plugin; also added processors to GroocssExtension and added tests
  • Loading branch information
adamldavis committed Jul 3, 2019
1 parent ab6495f commit 7e541d3
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 10 deletions.
5 changes: 5 additions & 0 deletions groocss-gradle-plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ dependencies {
compile project(':'), {
exclude module: "groovy-all", group: "org.codehaus.groovy"
}
testCompile 'org.spockframework:spock-core:1.1-groovy-2.4', {
exclude module: "groovy-all", group: "org.codehaus.groovy"
}
testRuntime "net.bytebuddy:byte-buddy:1.9.13"
testRuntime "org.objenesis:objenesis:3.0.1"
}

group = 'org.groocss'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.groocss

import org.groocss.proc.Processor

/** Extension to Gradle for configuring GrooCSS. */
class GroocssExtension {

Expand All @@ -18,5 +20,10 @@ class GroocssExtension {
/** Whether or not convert under-scores in CSS classes into dashes (main_content becomes main-content).
* Default is false. */
boolean convertUnderline = false


/** Custom processors/validators to use.
* @see org.groocss.proc.Processor
* @see org.groocss.valid.DefaultValidator
*/
Set<Processor> processors = []
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class GroocssPlugin implements Plugin<Project> {

def convertFile = {File inFile, File out ->
Config config = new Config(extension.properties)
GrooCSS.convert(config, inFile, out)
GrooCSS.convert(config, inFile, out, extension.charset ?: 'UTF-8', true)
}

def convertCss = project.task("convertCss")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.gradle.internal.file.PathToFileResolver
class GroocssTask extends Copy {

Config conf
String charset = 'UTF-8'

@Override
protected CopyAction createCopyAction() {
Expand All @@ -30,6 +31,7 @@ class GroocssTask extends Copy {
throw new InvalidUserDataException("No copy destination directory has been specified, use 'into' to specify a target directory.");
}
def action = new GroocssFileAction(fileLookup.getFileResolver(destinationDir), conf, rootSpec)
action.charset = charset
stream.process(action)
return WorkResults.didWork(action.didWork)
}
Expand All @@ -41,6 +43,7 @@ class GroocssTask extends Copy {

private final PathToFileResolver fileResolver
Config config
String charset = 'UTF-8'
CopySpec copySpec
boolean didWork

Expand All @@ -61,7 +64,8 @@ class GroocssTask extends Copy {

if (copied) {
File newTarget = new File(target.parentFile, GroocssPlugin.toCssName(target.name))
GrooCSS.convert config, target, newTarget

GrooCSS.convert config, target, newTarget, charset, true
target.delete()
didWork = true
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.groocss

import spock.lang.Specification

class GroocssExtensionSpec extends Specification {

def "should have basic properties" () {
expect:
def ext = new GroocssExtension(compress: true, prettyPrint: true)
ext.compress
ext.prettyPrint
ext.addMoz
ext.addMs
ext.addOpera
ext.addWebkit
}

def "should have charset default of null" () {
expect:
def ext = new GroocssExtension()
ext.charset == null
}

def "should have processors which is empty list by default" () {
expect:
def ext = new GroocssExtension()
ext.processors.empty
ext.processors instanceof Set
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.groocss

import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.ExtensionContainer
import org.gradle.api.tasks.TaskContainer
import spock.lang.Specification

class GroocssPluginSpec extends Specification {


def "GroocssPlugin should work as a plugin" () {
given:
def project = Mock(Project.class)
def extensions = Mock(ExtensionContainer)
def files = Mock(NamedDomainObjectContainer)
def tasks = Mock(TaskContainer)
def convertCss = Mock(Task)
when:
def p = new GroocssPlugin()

p.apply(project)
then:
project.getExtensions() >> { extensions }
1 * extensions.create("groocss", GroocssExtension)
project.container(GrooCssFile) >> files
project.getTasks() >> { tasks }
1* tasks.findByName("build")
1* tasks.findByName("processResources")
project.task("convertCss") >> { convertCss }
1* convertCss.doFirst(_)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.groocss

import org.gradle.api.file.CopySpec
import org.gradle.api.file.RelativePath
import org.gradle.api.internal.file.copy.FileCopyDetailsInternal
import org.gradle.internal.file.PathToFileResolver
import spock.lang.Specification
import spock.lang.Unroll

class GroocssTaskSpec extends Specification {

@Unroll
def "should convert regular groocss file #i"() {
given:
def resolver = Mock(PathToFileResolver)
def copySpec = Mock(CopySpec)
def details = Mock(FileCopyDetailsInternal)
def path = Mock(RelativePath)
def config = new Config().noExts().compress()
def target = File.createTempFile("test", ".css.groovy")
File newTarget = new File(target.parentFile, GroocssPlugin.toCssName(target.name))
def testFile = File.createTempFile("input", ".css.groovy")
when:
testFile.text = groocss
new GroocssTask.GroocssFileAction(resolver, config, copySpec).processFile(details)
then:
details.getRelativePath() >> { path }
resolver.resolve(_) >> { target }
details.copyTo(_) >> { target.text = testFile.text }

assert newTarget.isFile()
println(newTarget.text)
assert newTarget.text == css
where:
i || groocss || css
1 | '''import org.groocss.Config
'test'.groocss(new Config().noExts().compress()) {
body { fontSize 2.em color 0.color }
article { padding 2.em }
'thing'.id { fontSize 200.percent }
keyframes('test') {
from { color black } to { color red }
}
}
''' | "body{font-size: 2em;color: #000000;}article{padding: 2em;}#thing{font-size: 200%;}"+
"@keyframes test {from{color: Black;}to{color: Red;}}"
2 | '''
body { fontSize 2.em color 0.color }
article { padding 2.em }
'thing'.id { fontSize 200.percent }
'test'.kf {
from { color black } to { color red }
}
''' | "body{font-size: 2em;color: #000000;}article{padding: 2em;}#thing{font-size: 200%;}"+
"@keyframes test {from{color: Black;}to{color: Red;}}"
3 | 'assert 1.initMetaClassesCalled()' | ''
}

def "should have default charset"() {
given:
def resolver = Mock(PathToFileResolver)
def copySpec = Mock(CopySpec)
def config = new Config()
expect:
def action = new GroocssTask.GroocssFileAction(resolver, config, copySpec)
action.charset == 'UTF-8'
}


}
24 changes: 17 additions & 7 deletions src/main/groovy/org/groocss/GrooCSS.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,12 @@ class GrooCSS extends Script implements CurrentKeyFrameHolder {
* @param conf Optional Config object for configuration.
* @param inf Input file with GrooCSS code.
* @param out Output file of resulting CSS.
* @param charset Charset of file to read (UTF-8 by default).
* @param addMeta Tells GrooCSS to augment String and Integer classes using metaClass (false by default).
*/
static void convert(Config conf = new Config(), File inf, File out) {
convert(conf, inf.newInputStream(), out.newOutputStream())
static void convert(Config conf = new Config(), File inf, File out,
String charset = "UTF-8", boolean addMeta = false) {
convert(conf, inf.newInputStream(), out.newOutputStream(), charset, addMeta)
}

/**
Expand Down Expand Up @@ -90,18 +93,20 @@ class GrooCSS extends Script implements CurrentKeyFrameHolder {

/** Processes a given InputStream and outputs to given OutputStream. */
@TypeChecked
static void convert(Config conf = new Config(), InputStream inf, OutputStream out, String charset1 = "UTF-8") {
static void convert(Config conf = new Config(), InputStream inf, OutputStream out, String charset1 = "UTF-8",
boolean addMeta = false) {
out.withPrintWriter { pw ->
convert conf, new InputStreamReader(inf, charset1), pw
convert conf, new InputStreamReader(inf, charset1), pw, addMeta
}
}

/** Processes a given Reader and outputs to given PrintWriter. */
@TypeChecked
static void convert(Config conf = new Config(), Reader reader, PrintWriter writer) {
static void convert(Config conf = new Config(), Reader reader, PrintWriter writer, boolean addMeta = false) {
reader.withCloseable { input ->
def shell = makeShell()
def script = shell.parse(input)
if (addMeta) script.invokeMethod('initMetaClasses', true)
script.invokeMethod('setConfig', conf)
def result = script.run()
MediaCSS css = (MediaCSS) script.getProperty('css')
Expand Down Expand Up @@ -218,11 +223,16 @@ class GrooCSS extends Script implements CurrentKeyFrameHolder {


GrooCSS() {
addNumberMetaStuff()
addStringMetaStuff()
threadLocalInstance.set(this) // set this instance for the current Thread
}

/** Called when addMeta is true (parameter to "convert") which is used by Gradle plugin. */
void initMetaClasses(boolean addNumberMeta = true, boolean addStringMeta = true) {
if (addNumberMeta) addNumberMetaStuff()
if (addStringMeta) addStringMetaStuff()
Integer.metaClass.initMetaClassesCalled = {return true}
}

private void addStringMetaStuff() {
String.metaClass.groocss = { Config config, Closure closure ->
println "processing $delegate"; GrooCSS.process(config, closure)
Expand Down

0 comments on commit 7e541d3

Please sign in to comment.