Permalink
Browse files

Merge branch 'master' of github.com:twitter/recess

Conflicts:
	package.json
	test/types/lint.js
  • Loading branch information...
2 parents 6971513 + 8c87127 commit 2ec6067080d2e54645791ab233d3dd4dcaf1bf9a @fat fat committed Aug 19, 2012
View
@@ -26,6 +26,7 @@ OPTIONS
- --noOverqualifying - doesn't complain about overqualified selectors (ie: `div#foo.bar`)
- --noUnderscores - doesn't complain about using underscores in your class names
- --noUniversalSelectors - doesn't complain about using the universal `*` selector
+- --prefixWhitespace - adds whitespace prefix to line up vender prefixed properties
- --strictPropertyOrder - doesn't looking into your property ordering
- --zeroUnits - doesn't complain if you add units to values of 0
@@ -54,7 +55,13 @@ $ recess ./bootstrap.less --compress > ./bootstrap-production.css
Watch a directory for changes and auto compile a css file from the changes. *experimental*
```CLI
-$ recess input.less:ouput.css --compile --watch watch/this/dir/for/changes
+$ recess input.less:ouput.css --watch watch/this/dir/for/changes
+```
+
+Watch a single file for changes and auto compile a css file from the changes. *experimental*
+
+```CLI
+$ recess input.less:ouput.css --watch
```
PROGRAMMATIC API
@@ -83,6 +90,7 @@ The following options (and defaults) are available in the programatic api:
- noUniversalSelectors: true
- prefixWhitespace: true
- strictPropertyOrder: true
+- stripColors: false
- zeroUnits: true
The callback is fired when each instance has finished processessing an input. The callback is passed an array of of instances (one for each path). The instances have a bunch of useful things on them like the raw data and an array of output strings.
View
@@ -61,6 +61,9 @@ options.cli = true
// if not watch - run Recess
if (!options.watch) return recess(paths, options)
+// if options watch, but compile isn't set - make it happen
+if (options.watch && !options.compile && !options.compress) options.compile = true;
+
// set CLI to false
options.cli = false
paths = paths[0].split(':')
@@ -74,9 +77,18 @@ writeFile = function () {
})
}
-// create monitor to watch filetree
+// if watch doesn't exist, watch the path
+if (!(fs.existsSync || path.existsSync)(options.watch)) options.watch = path.resolve(paths)
+
+// throw if can't find file to watch
+if (!(fs.existsSync || path.existsSync)(options.watch)) return console.log("can't find file: " + options.watch)
+
+// use fs.watch if watchign single file
+if (path.extname(options.watch)) return fs.watch(options.watch, writeFile)
+
+// create monitor to watch filetree if provided dir
watch.createMonitor(options.watch, function (monitor) {
monitor.on("created", writeFile)
monitor.on("changed", writeFile)
monitor.on("removed", writeFile)
-})
+})
@@ -0,0 +1,46 @@
+// ==========================================
+// RECESS
+// COMPILE: replaces image links with base64 image data
+// ==========================================
+// Copyright 2012 Twitter, Inc
+// Licensed under the Apache License v2.0
+// http://www.apache.org/licenses/LICENSE-2.0
+// ==========================================
+
+'use strict'
+
+var less = require('less')
+ , fs = require('fs')
+ , seperator = (process.platform == 'win32') ? '\\' : '/'
+ , toCSS
+ , path
+
+function compile () {
+ // strip units from 0 values
+ var props = toCSS.apply(this, arguments)
+
+ // do we have a url here?
+ if (/url\(/.test(props)) {
+ var fileName = props.match(/url\((['"]?)(.*)\1\)/)[2]
+ , ext = fileName.match(/[^.]*$/)[0]
+ , mimetype = 'image/' + ext.replace(/jpg/, 'jpeg')
+ , pathParts = path.split(seperator)
+ , filePath = pathParts.slice(0, pathParts.length - 1).join(seperator)
+ , imgBuffer = new Buffer(fs.readFileSync(filePath+seperator+fileName)).toString('base64')
+ , urlData = 'url(data:' + mimetype + ';base64,' + imgBuffer + ')'
+
+ return props.replace(/url\([^\)]*\)/, urlData)
+ }
+
+ return props
+}
+
+module.exports.on = function () {
+ path = this.path
+ toCSS = less.tree.Value.prototype.toCSS
+ less.tree.Value.prototype.toCSS = compile
+}
+
+module.exports.off = function () {
+ less.tree.Value.prototype.toCSS = toCSS
+}
View
@@ -154,7 +154,7 @@ RECESS.prototype = {
Object.keys(this.options).forEach(function (key) {
that.options[key]
&& RECESS.COMPILERS[key]
- && RECESS.COMPILERS[key].on()
+ && RECESS.COMPILERS[key].on.call(that)
})
// iterate over defintions and compress them (join with new lines)
View
@@ -81,6 +81,7 @@ module.exports.DEFAULTS = RECESS.DEFAULTS = {
, stripColors: false
, watch: false
, zeroUnits: true
+, inlineImages: false
}
View
@@ -0,0 +1,60 @@
+// ===================================================
+// RECESS
+// RULE: Linked images should be embeded.
+// ===================================================
+// Copyright 2012 Twitter, Inc
+// Licensed under the Apache License v2.0
+// http://www.apache.org/licenses/LICENSE-2.0
+// ===================================================
+
+'use strict'
+
+var util = require('../util')
+ , RULE = {
+ type: 'inlineImages'
+ , exp: /^url\((?!data:)/
+ , message: 'Linked images should be embeded.'
+ }
+
+// validation method
+module.exports = function (def, data) {
+
+ // default validation to true
+ var isValid = true
+
+ // return if no selector to validate
+ if (!def.rules) return isValid
+
+ // loop over selectors
+ def.rules.forEach(function (rule) {
+ var extract
+
+ // continue to next rule if no url is present
+ if ( !(rule.value
+ && rule.value.is == 'value'
+ && RULE.exp.test(rule.value.toCSS({}))) ) return
+
+ // calculate line number for the extract
+ extract = util.getLine(rule.index, data)
+ extract = util.padLine(extract)
+
+ // highlight invalid 0 units
+ extract += rule.toCSS({}).replace(RULE.exp, function ($1) {
+ return $1.magenta
+ })
+
+ // set invalid flag to false
+ isValid = false
+
+ // set error object on defintion token
+ util.throwError(def, {
+ type: RULE.type
+ , message: RULE.message
+ , extract: extract
+ })
+
+ })
+
+ // return validation state
+ return isValid
+}
@@ -95,6 +95,7 @@ var _ = require('underscore')
, 'list-style-type'
, 'list-style-position'
, 'list-style-image'
+ , 'pointer-events'
, 'cursor'
, 'background'
, 'background-attachment'
@@ -150,19 +151,22 @@ var _ = require('underscore')
, 'box-pack'
, 'box-shadow'
, 'box-sizing'
+ , 'table-layout'
, 'animation'
, 'animation-delay'
, 'animation-duration'
, 'animation-iteration-count'
, 'animation-name'
, 'animation-play-state'
, 'animation-timing-function'
+ , 'animation-fill-mode'
, 'transition'
, 'transition-delay'
, 'transition-duration'
, 'transition-property'
, 'transition-timing-function'
, 'background-clip'
+ , 'backface-visibility'
, 'resize'
, 'appearance'
, 'user-select'
View
@@ -1,6 +1,6 @@
{ "name": "recess"
, "description": "A simple, attractive code quality tool for CSS built on top of LESS"
-, "version": "1.0.5"
+, "version": "1.1.5"
, "author": "Jacob Thornton <jacob@twitter.com> (https://github.com/fat)"
, "keywords": ["css", "lint"]
, "licenses": [ { "type": "Apache-2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0" } ]
View
@@ -1,10 +1,5 @@
/* Fat's blog styles */
-@font-face {
- font-family: "Mistral";
- src: url("/fonts/Mistral.ttf");
-}
-
html,
body {
overflow: auto;

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -1,10 +1,5 @@
/* Fat's blog styles */
-@font-face {
- font-family: "Mistral";
- src: url("/fonts/Mistral.ttf");
-}
-
html,
body {
overflow: auto;
@@ -0,0 +1,12 @@
+.foo {
+ background-image: url("sprite.png");
+}
+.bar {
+ background: url('sprite.png');
+}
+.fat {
+ background: url(sprite.png);
+}
+.woo {
+ background: #fff url(../sprite.png) center center no-repeat;
+}
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
@@ -4,8 +4,12 @@ var fs = require('fs')
, RECESS = require('../../lib')
fs.readdirSync('test/fixtures').forEach(function (file, index) {
+ // Ignore anything not a less/css file.
+ if (file.indexOf('css') === -1 && file.indexOf('less') === -1) {
+ return
+ }
- RECESS('test/fixtures/' + file, { compile: true }, function (err, fat) {
+ RECESS('test/fixtures/' + file, { compile: true, inlineImages: true }, function (err, fat) {
file = file.replace(/less$/, 'css')
assert.ok(err == null)
assert.ok(fat.output[0] == fs.readFileSync('test/compiled/' + file, 'utf-8'))
View
@@ -227,6 +227,33 @@ var assert = require('assert')
Recess.parse()
assert.notEqual(Recess.output[0], '\u001b[31mParse error\u001b[39m: Cannot read property \'red\' of undefined on line 1');
+
+ RECESS.Constructor.prototype.validate = validate
+
+}()
+
+//VALIDATIONS.inlineImage
+!function () {
+
+ var path = 'test/fixtures/inline-images.css'
+ , Recess = new RECESS.Constructor()
+ , validate = RECESS.Constructor.prototype.validate
+ , def
+
+ RECESS.Constructor.prototype.validate = noop
+
+ Recess.data = fs.readFileSync(path, 'utf8')
+
+ Recess.parse()
+
+ def = Recess.definitions[0]
+
+ RECESS.Constructor.RULES.inlineImages(def, Recess.data)
+
+ assert.ok(def.errors)
+ assert.equal(def.errors.length, 1, 'one error found')
+ assert.equal(def.errors[0].type, 'inlineImages')
+
RECESS.Constructor.prototype.validate = validate
}()

0 comments on commit 2ec6067

Please sign in to comment.