backoffice/node_modules/R2/r2.js

215 lines
5.6 KiB
JavaScript

/*!
* R2 - a CSS LTR ∞ RTL converter
* Copyright Dustin Diaz 2012
* https://github.com/ded/r2
* License MIT
*/
var fs = require('fs')
, css = require('css');
function quad(v, m) {
// 1px 2px 3px 4px => 1px 4px 3px 2px
if ((m = v.trim().split(/\s+/)) && m.length == 4) {
return [m[0], m[3], m[2], m[1]].join(' ')
}
return v
}
function quad_radius(v) {
var m = v.trim().split(/\s+/)
// 1px 2px 3px 4px => 1px 2px 4px 3px
// since border-radius: top-left top-right bottom-right bottom-left
// will be border-radius: top-right top-left bottom-left bottom-right
if (m && m.length == 4) {
return [m[1], m[0], m[3], m[2]].join(' ')
} else if (m && m.length == 3) {
// super odd how this works
// 5px 10px 20px => 10px 5px 10px 20px
// yeah it's pretty dumb
return [m[1], m[0], m[1], m[2]].join(' ')
}
return v
}
function direction(v) {
return v.match(/ltr/) ? 'rtl' : v.match(/rtl/) ? 'ltr' : v
}
function rtltr(v) {
if (v.match(/left/)) return 'right'
if (v.match(/right/)) return 'left'
return v
}
function bgPosition(values) {
return values.split(/\s*,\s*/g).map(function (v) {
if (v.match(/\bleft\b/)) {
v = v.replace(/\bleft\b/, 'right')
} else if (v.match(/\bright\b/)) {
v = v.replace(/\bright\b/, 'left')
}
var m = v.trim().split(/\s+/)
if (m && (m.length == 1) && v.match(/(\d+)([a-z]{2}|%)/)) {
v = 'right ' + v
}
if (m && m.length == 2 && m[0].match(/\d+%/)) {
// 30% => 70% (100 - x)
v = (100 - parseInt(m[0], 10)) + '% ' + m[1]
}
return v
}).join(', ')
}
var propertyMap = {
'margin-left': 'margin-right'
, 'margin-right': 'margin-left'
, 'padding-left': 'padding-right'
, 'padding-right': 'padding-left'
, 'border-left': 'border-right'
, 'border-right': 'border-left'
, 'border-left-color': 'border-right-color'
, 'border-right-color': 'border-left-color'
, 'border-left-width': 'border-right-width'
, 'border-right-width': 'border-left-width'
, 'border-radius-bottomleft': 'border-radius-bottomright'
, 'border-radius-bottomright': 'border-radius-bottomleft'
, 'border-bottom-right-radius': 'border-bottom-left-radius'
, 'border-bottom-left-radius': 'border-bottom-right-radius'
, '-webkit-border-bottom-right-radius': '-webkit-border-bottom-left-radius'
, '-webkit-border-bottom-left-radius': '-webkit-border-bottom-right-radius'
, '-moz-border-radius-bottomright': '-moz-border-radius-bottomleft'
, '-moz-border-radius-bottomleft': '-moz-border-radius-bottomright'
, 'border-radius-topleft': 'border-radius-topright'
, 'border-radius-topright': 'border-radius-topleft'
, 'border-top-right-radius': 'border-top-left-radius'
, 'border-top-left-radius': 'border-top-right-radius'
, '-webkit-border-top-right-radius': '-webkit-border-top-left-radius'
, '-webkit-border-top-left-radius': '-webkit-border-top-right-radius'
, '-moz-border-radius-topright': '-moz-border-radius-topleft'
, '-moz-border-radius-topleft': '-moz-border-radius-topright'
, 'left': 'right'
, 'right': 'left'
}
var valueMap = {
'padding': quad,
'margin': quad,
'text-align': rtltr,
'float': rtltr,
'clear': rtltr,
'direction': direction,
'-webkit-border-radius': quad_radius,
'-moz-border-radius': quad_radius,
'border-radius': quad_radius,
'border-color': quad,
'border-width': quad,
'border-style': quad,
'background-position': bgPosition
}
function processRule(rule, idx, list) {
var prev = list[idx-1]
if (prev && prev.type === 'comment' && prev.comment.trim() === '@noflip')
return;
if (rule.declarations)
rule.declarations.forEach(processDeclaration)
else if (rule.rules)
rule.rules.forEach(processRule)
}
function processDeclaration(declaration) {
// Ignore comments in declarations
if (declaration.type !== 'declaration')
return
var prop = declaration.property
, val = declaration.value
, important = /!important/
, isImportant = val.match(important)
, asterisk = prop.match(/^(\*+)(.+)/, '')
if (asterisk) {
prop = asterisk[2]
asterisk = asterisk[1]
} else {
asterisk = ''
}
prop = propertyMap[prop] || prop
val = valueMap[prop] ? valueMap[prop](val) : val
if (!val.match(important) && isImportant) val += '!important'
declaration.property = asterisk + prop;
declaration.value = val;
}
function r2(cssString, options) {
var ast
if (!options)
options = { compress: true }
ast = css.parse(cssString)
ast.stylesheet.rules.forEach(processRule)
return css.stringify(ast, options)
}
module.exports.exec = function (args) {
var out
, read = args[0]
, out = args[1]
, options = { compress: args[2] !== '--no-compress' }
, data
/*
/ If no read arg then read from stdin
/ allows for standard piping and reading in
/ ex: lessc file.less | r2 > file-rtl.css
/ ex: r2 < file.css
*/
if (!read) {
var buffer = ''
process.stdin.resume()
process.stdin.setEncoding('utf8')
process.stdin.on('data', function(chunk) {
buffer += chunk
});
process.stdin.on('end', function() {
if (buffer) {
console.log(r2(buffer, options))
}
});
} else {
/*
/ If reading from a file then print to stdout or out arg
/ To stdout: r2 styles.css
/ To file: r2 styles.cc styles-rtl.css
*/
data = fs.readFileSync(read, 'utf8')
if (out) {
console.log('Swapping ' + read + ' to ' + out + '...')
fs.writeFileSync(out, r2(data, options), 'utf8')
} else {
console.log(r2(data, options))
}
}
}
module.exports.swap = function (cssString, options) {
return r2(cssString, options)
}