Socket
Socket
Sign inDemoInstall

rtlcss

Package Overview
Dependencies
Maintainers
1
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rtlcss - npm Package Compare versions

Comparing version 3.5.0 to 4.0.0

344

bin/rtlcss.js

@@ -29,5 +29,5 @@ #!/usr/bin/env node

let input, output, directory, ext, config, currentErrorcode, arg
let input, output, directory, ext, config
let currentErrorcode = 0
const args = process.argv.slice(2)
let shouldBreak = false

@@ -37,11 +37,11 @@ process.on('exit', () => { process.reallyExit(currentErrorcode) })

function printWarning (...args) {
console.warn(picocolors.yellow(...args))
args.forEach(a => console.warn(picocolors.yellow(a)))
}
function printInfo (...args) {
console.info(picocolors.green(...args))
args.forEach(a => console.info(picocolors.green(a)))
}
function printError (...args) {
console.error(picocolors.red(...args))
args.forEach(a => console.error(picocolors.red(a)))
}

@@ -56,191 +56,185 @@

while ((arg = args.shift())) {
switch (arg) {
case '-h':
case '--help':
printHelp()
shouldBreak = true
break
case '-v':
case '--version':
printInfo(`rtlcss version: ${version}`)
shouldBreak = true
break
case '-c':
case '--config':
arg = args.shift()
try {
config = configLoader.load(path.resolve(arg))
} catch (e) {
printError('rtlcss: invalid config file. ', e)
shouldBreak = true
currentErrorcode = 1
}
break
case '-d':
case '--directory':
directory = true
break
case '-e':
case '--ext':
ext = args.shift()
break
case '-s':
case '--silent':
console.log = console.info = console.warn = () => {}
break
case '-':
case '--stdin':
input = '-'
break
default:
if (arg[0] === '-') {
printError(`rtlcss: unknown option. ${arg}`)
shouldBreak = true
} else if (!input) {
input = path.resolve(arg)
} else if (!output) {
output = path.resolve(arg)
}
break
function processCSSFile (error, data, outputName) {
if (error) {
printError(`rtlcss: ${error.message}`)
return
}
}
if (!shouldBreak) {
if (!directory && !input) {
printError('rtlcss: no input file')
console.log('')
printHelp()
shouldBreak = true
let result
const opt = { map: false }
if (input !== '-') {
opt.from = input
opt.to = output
}
if (!config && input !== '-') {
try {
let cwd = input
if (directory !== true) {
cwd = path.dirname(input)
}
config = configLoader.load(null, cwd)
} catch (e) {
printError('rtlcss: invalid config file. ', e)
currentErrorcode = 1
shouldBreak = true
if (!config) {
printWarning('rtlcss: Warning! No config present, using defaults.')
result = postcss([rtlcss]).process(data, opt)
} else {
if ('map' in config === true && input !== '-') {
opt.map = config.map
}
}
}
if (!shouldBreak) {
if (!output && input !== '-') {
if (directory !== true) {
const extension = path.extname(input)
output = extension ? input.replace(extension, `.rtl${extension}`) : `${input}.rtl`
} else {
output = input
}
result = postcss([rtlcss.configure(config)]).process(data, opt)
}
const processCSSFile = (error, data, outputName) => {
if (error) {
printError(`rtlcss: ${error.message}`)
return
}
if (output) {
const savePath = directory !== true ? output : outputName
printInfo('Saving:', savePath)
let result
const opt = { map: false }
fs.writeFile(savePath, result.css, (err) => {
if (err) printError(err)
})
if (input !== '-') {
opt.from = input
opt.to = output
if (result.map) {
fs.writeFile(`${savePath}.map`, result.map, (err) => {
if (err) printError(err)
})
}
} else {
process.stdout.write(`${result.css}\n`)
}
}
if (!config) {
printWarning('rtlcss: Warning! No config present, using defaults.')
result = postcss([rtlcss]).process(data, opt)
} else {
if ('map' in config === true && input !== '-') {
opt.map = config.map
}
result = postcss([rtlcss.configure(config)]).process(data, opt)
function walk (dir, done) {
fs.readdir(dir, (error, list) => {
if (error) {
return done(error)
}
if (output) {
let savePath = outputName
if (directory !== true) {
savePath = output
let i = 0;
(function next () {
let file = list[i++]
if (!file) {
return done(null)
}
printInfo('Saving:', savePath)
file = path.join(dir, file)
fs.stat(file, (err, stat) => {
if (err) {
printError(err)
} else if (stat && stat.isDirectory()) {
walk(file, (err) => {
if (err) {
printError(err)
} else {
next()
}
})
} else {
// process only *.css files
if (path.extname(file) === '.css') {
// TODO: this could probably be simplified
// compute output directory
const relativePath = path.relative(input, file).split(path.sep)
relativePath.pop()
relativePath.push(path.basename(file).replace('.css', ext || '.rtl.css'))
fs.writeFile(savePath, result.css, (err) => {
if (err) printError(err)
})
// set rtl filename
const rtlFile = path.join(output, relativePath.join(path.sep))
if (result.map) {
fs.writeFile(`${savePath}.map`, result.map, (err) => {
if (err) printError(err)
})
}
} else {
process.stdout.write(`${result.css}\n`)
}
}
// create output directory if it does not exist
const dirName = path.dirname(rtlFile)
if (!fs.existsSync(dirName)) {
fs.mkdirSync(dirName, { recursive: true })
}
const walk = (dir, done) => {
fs.readdir(dir, (error, list) => {
if (error) {
return done(error)
}
// read and process the file.
fs.readFile(file, 'utf8', (e, data) => {
try {
processCSSFile(e, data, rtlFile)
} catch (e) {
printError(`rtlcss: error processing file ${file}`)
printError(e)
}
})
}
let i = 0;
(function next () {
let file = list[i++]
if (!file) {
return done(null)
next()
}
})
})()
})
}
file = dir + path.sep + file
fs.stat(file, (err, stat) => {
if (err) {
printError(err)
} else if (stat && stat.isDirectory()) {
walk(file, (err) => {
if (err) {
printError(err)
} else {
next()
}
})
} else {
// process only *.css files
if (file.endsWith('.css')) {
// compute output directory
const relativePath = path.relative(input, file).split(path.sep)
relativePath.pop()
relativePath.push(path.basename(file).replace('.css', ext || '.rtl.css'))
function main () {
let arg
while ((arg = args.shift())) {
switch (arg) {
case '-h':
case '--help':
printHelp()
return
case '-v':
case '--version':
printInfo(`rtlcss version: ${version}`)
return
case '-c':
case '--config':
arg = args.shift()
try {
config = configLoader.load(path.resolve(arg))
} catch (e) {
printError(`rtlcss: invalid config file. ${e}`)
currentErrorcode = 1
return
}
break
case '-d':
case '--directory':
directory = true
break
case '-e':
case '--ext':
ext = args.shift()
break
case '-s':
case '--silent':
console.log = console.info = console.warn = () => {}
break
case '-':
case '--stdin':
input = '-'
break
default:
if (arg[0] === '-') {
printError(`rtlcss: unknown option. ${arg}`)
currentErrorcode = 1
return
}
// set rtl filename
const rtlFile = path.join(output, relativePath.join(path.sep))
if (!input) {
input = path.resolve(arg)
} else if (!output) {
output = path.resolve(arg)
}
break
}
}
// create output directory if it does not exist
const dirName = path.dirname(rtlFile)
if (!fs.existsSync(dirName)) {
fs.mkdirSync(dirName, { recursive: true })
}
if (!directory && !input) {
printError('rtlcss: no input file\n')
printHelp()
currentErrorcode = 1
return
}
// read and process the file.
fs.readFile(file, 'utf8', (e, data) => {
try {
processCSSFile(e, data, rtlFile)
} catch (e) {
printError('rtlcss: error processing file', file)
printError(e)
}
})
}
if (!config && input !== '-') {
try {
const cwd = directory !== true ? path.dirname(input) : input
config = configLoader.load(null, cwd)
} catch (error) {
printError(`rtlcss: invalid config file. ${error}`)
currentErrorcode = 1
}
}
next()
}
})
})()
})
if (!output && input !== '-') {
if (directory !== true) {
const extension = path.extname(input)
output = extension ? input.replace(extension, `.rtl${extension}`) : `${input}.rtl`
} else {
output = input
}
}

@@ -256,8 +250,8 @@

} else {
fs.readFile(input, 'utf8', (e, data) => {
fs.readFile(input, 'utf8', (err, data) => {
try {
processCSSFile(e, data)
} catch (e) {
printError('rtlcss: error processing file', input)
printError(e)
processCSSFile(err, data)
} catch (err) {
printError(`rtlcss: error processing file ${input}`)
printError(err)
}

@@ -291,1 +285,3 @@ })

}
main()

@@ -1,25 +0,39 @@

# 3.5.0 - 02 Nov. 2021
# RTLCSS Changelog
## 4.0.0 - 09 Aug. 2022
* Update dependencies, Internal code refactoring, cleanup and optimizations. **Thanks @XhmikosR**
* Support flipping `justify-content`, `justify-items` and `justify-self`. **Thanks @mbehzad**
* Support flipping length position without using `calc` option.
## 3.5.0 - 02 Nov. 2021
* Update dependencies. **Thanks @XhmikosR**
* Internal code cleanup/formatting. **Thanks @XhmikosR**
# 3.4.0 - 18 Oct. 2021
## 3.4.0 - 18 Oct. 2021
* Support flipping `object-position`.
* Update dev. dependencies.
# 3.3.0 - 08 Jul. 2021
* Update devDependencies.
## 3.3.0 - 08 Jul. 2021
* Add `processEnv` option to support flipping agent-defined environment variables (`safe-area-inset-left`, `safe-area-inset-right`).
# 3.2.1 - 22 Jun. 2021
## 3.2.1 - 22 Jun. 2021
* Bump [glob-parent](https://github.com/gulpjs/glob-parent) from 5.1.1 to 5.1.2.
# 3.2.0 - 23 May. 2021
## 3.2.0 - 23 May. 2021
* Add `aliases` option to support processing Custom Properties (CSS Variables). **Thanks @elchininet**
# 3.1.2 - 04 Feb. 2021
## 3.1.2 - 04 Feb. 2021
* Update `README.md`.
# 3.1.1 - 02 Feb. 2021
## 3.1.1 - 02 Feb. 2021
* Fixes `TypeError` when placing value directive before `!important`. [#218](https://github.com/MohammadYounes/rtlcss/issues/218)
# 3.1.0 - 30 Jan. 2021
## 3.1.0 - 30 Jan. 2021

@@ -30,8 +44,8 @@ * Use `strict` mode across all files. **Thanks @XhmikosR**

* Allow value directives to be placed any where inside the declaration value.
* Handle value directives placed after `!important`.
* Handle value directives placed after `!important`.
* Fix reading config file sources ([#209](https://github.com/MohammadYounes/rtlcss/issues/209)).
# 3.0.0 - 10 Dec. 2020
## 3.0.0 - 10 Dec. 2020
* Upgrade to [POSTCSS] 8.
* Upgrade to [postcss] 8.
* Dropped **Node.js 6.x, 8.x, 11.x, and 13.x** versions.

@@ -79,3 +93,3 @@

* Support for pre/post hooks.
* Upgrade to [POSTCSS] v6.x
* Upgrade to [postcss] v6.x

@@ -88,3 +102,3 @@ ## 2.1.2 - 31 Dec. 2016

* Fixes a bug in self closing ignore directive (Fixes [#88](https://github.com/MohammadYounes/rtlcss/issues/88)).
* Fixes a bug in self-closing ignore directive (Fixes [#88](https://github.com/MohammadYounes/rtlcss/issues/88)).

@@ -95,36 +109,36 @@ ## 2.1.0 - 30 Nov. 2016

### 2.0.7 - 16 Nov. 2016
## 2.0.7 - 16 Nov. 2016
* Fixes a bug in flipping backgrounds having url placed first (Fixes [#84](https://github.com/MohammadYounes/rtlcss/issues/84)).
* Fixes a bug in flipping backgrounds having URL placed first (Fixes [#84](https://github.com/MohammadYounes/rtlcss/issues/84)).
* Update `node.value` so changes will be picked up by other processors (Closes [#85](https://github.com/MohammadYounes/rtlcss/issues/85)).
### 2.0.6 - 12 Jul. 2016
## 2.0.6 - 12 Jul. 2016
* README updates.
### 2.0.5 - 17 May. 2016
## 2.0.5 - 17 May. 2016
* Fixes a bug in complementing calc values (Fixes [#71](https://github.com/MohammadYounes/rtlcss/issues/71)).
### 2.0.4 - 25 Apr. 2016
* Fixes a bug in complementing `calc` values (Fixes [#71](https://github.com/MohammadYounes/rtlcss/issues/71)).
## 2.0.4 - 25 Apr. 2016
* Fixes a bug in flipping cursor value (Fixes [#68](https://github.com/MohammadYounes/rtlcss/issues/68)).
### 2.0.3 - 23 Mar. 2016
## 2.0.3 - 23 Mar. 2016
* Guard against flipping tokens, e.g: [shadows starting with a color function](https://github.com/MohammadYounes/rtlcss/blob/master/test/data/special.js#L2-L7).
### 2.0.2 - 05 Mar. 2016
## 2.0.2 - 05 Mar. 2016
* Fixes a bug in flipping background with a hex color value (Fixes [#60](https://github.com/MohammadYounes/rtlcss/issues/60)).
### 2.0.1 - 23 Feb. 2016
## 2.0.1 - 23 Feb. 2016
* Fixes a bug when having `decl` nodes inside `atrule`s and `autoRename` enabled.
* Fixes a bug in flipping multi-valued transforms.
# 2.0.0 - 18 Feb. 2016
## 2.0.0 - 18 Feb. 2016
* Support for control directive blocks, e.g. `/*rtl:begin:ignore*/ ... /*rtl:end:ignore*/`.
* Support for strict auto renaming, Which ensures `autoRename` is applied only when a pair exists.
* Support for strict auto renaming, which ensures `autoRename` is applied only when a pair exists.
* New directives:

@@ -137,3 +151,3 @@ * `config`

#### Upgrading from version 1.0
### Upgrading from version 1.0

@@ -153,3 +167,3 @@ Options and config settings have changed. However, you need not to worry about your CSS files as all directives are backward-compatible. This is a summary of what's changed:

* added `exclusive` attribute, which determines if a map execution should stop iterating over other maps.
* dropped 'west-east' map from the default map collection.
* dropped `'west-east'` map from the default map collection.

@@ -165,19 +179,19 @@ * Removed Options:

### v1.7.4 - 23 Feb. 2016
## v1.7.4 - 23 Feb. 2016
* Fixes a bug in flipping multiple transforms.
### v1.7.3 - 30 Jan. 2016
## v1.7.3 - 30 Jan. 2016
* Fixes a bug in flipping N-Values containing comments.
### 1.7.2 - 30 Jan. 2016
## 1.7.2 - 30 Jan. 2016
* Fixes a bug in flipping N-Values containing comments.
### 1.7.2 - 04 Dec. 2015
## 1.7.2 - 04 Dec. 2015
* Fixes a compatibility issue with postcss-js (Fixes [#48](https://github.com/MohammadYounes/rtlcss/issues/48)).
### 1.7.1 - 10 Nov. 2015
## 1.7.1 - 10 Nov. 2015

@@ -192,12 +206,12 @@ * Fixed a bug in flipping backgrounds having functions (Issue [#45](https://github.com/MohammadYounes/rtlcss/issues/45)).

### 1.6.3 - 28 Aug. 2015
## 1.6.3 - 28 Aug. 2015
* CLI: fix source map option (issue #40).
* Upgrade to [POSTCSS] v5.0.x
* Upgrade to [postcss] v5.0.x
### 1.6.2 - 21 Jul. 2015
## 1.6.2 - 21 Jul. 2015
* CLI: fix loading custom configuration file manually via the --config flag. **Thanks @KeyKaKiTO**
### 1.6.1 - 17 Mar. 2015
## 1.6.1 - 17 Mar. 2015

@@ -210,7 +224,7 @@ * Fixed flipping units having more than 1 digit before the decimal point.

### 1.5.2 - 28 Feb. 2015
## 1.5.2 - 28 Feb. 2015
* Fix flipping string maps containing regular expressions special characters (Fixes [#24](https://github.com/MohammadYounes/rtlcss/issues/24)).
### 1.5.1 - 14 Feb. 2015
## 1.5.1 - 14 Feb. 2015

@@ -223,11 +237,11 @@ * Fix flipping multiple shadows when a hex color was used. **Thanks @ocean90**

### 1.4.3 - 24 Jan. 2015
## 1.4.3 - 24 Jan. 2015
* Upgrade to [POSTCSS] v4.0.x **Thanks @necolas**
* Upgrade to [postcss] v4.0.x **Thanks @necolas**
### 1.4.2 - 24 Oct. 2014
## 1.4.2 - 24 Oct. 2014
* CLI: Switch to Unix line endings (Fixes [#14](https://github.com/MohammadYounes/rtlcss/issues/14))
### 1.4.1 - 24 Oct. 2014
## 1.4.1 - 24 Oct. 2014

@@ -238,5 +252,5 @@ * CLI: Print processing errors.

* CLI: Support processing a directory. see [CLI documentation](https://github.com/MohammadYounes/rtlcss/blob/master/CLI.md#directory)
* CLI: Support processing a directory. See [CLI documentation](https://github.com/MohammadYounes/rtlcss/blob/master/docs/CLI.md).
### 1.3.1 - 29 Sep. 2014
## 1.3.1 - 29 Sep. 2014

@@ -256,9 +270,9 @@ * Update README.md (typos).

* Upgrade to [POSTCSS] v2.2.5
* Upgrade to [postcss] v2.2.5
* Support flipping `border-color`, `border-style` and `background-position-x`
# 1.0.0 - 24 Aug. 2014
## 1.0.0 - 24 Aug. 2014
* Upgrade to [POSTCSS] v2.2.1
* Support flipping urls in '@import' rule.
* Upgrade to [postcss] v2.2.1
* Support flipping urls in `@import` rule.
* Fix JSON parse error when configuration file is UTF-8 encoded.

@@ -298,12 +312,12 @@ * Better minification.

* Support flipping rotateZ.
* Fix flipping rotate3d.
* Fix flipping skew, skewX and skewY.
* Fix flipping cursor value.
* Fix flipping translate3d.
* Update flipping background horizontal position to treat 0 as 0%
* Support flipping `rotateZ`.
* Fix flipping `rotate3d`.
* Fix flipping `skew`, `skewX` and `skewY`.
* Fix flipping `cursor` value.
* Fix flipping `translate3d`.
* Update flipping background horizontal position to treat `0` as `0%`
### 0.2.1 - 20 Mar. 2014
## 0.2.1 - 20 Mar. 2014
* Upgrade to [POSTCSS] v0.3.4
* Upgrade to [postcss] v0.3.4

@@ -316,7 +330,7 @@ ## 0.2.0 - 20 Mar. 2014

### 0.1.3 - 7 Mar. 2014
## 0.1.3 - 7 Mar. 2014
* Fix missing include in rules.js
### 0.1.2 - 5 Mar. 2014
## 0.1.2 - 5 Mar. 2014

@@ -326,6 +340,6 @@ * New option: minify output CSS.

### 0.1.1 - 4 Mar. 2014
## 0.1.1 - 4 Mar. 2014
* Initial commit.
[POSTCSS]: https://postcss.org/
[postcss]: https://postcss.org/

@@ -5,3 +5,3 @@ 'use strict'

const path = require('path')
const findUp = require('find-up')
const escalade = require('escalade/sync')
const stripJSONComments = require('strip-json-comments')

@@ -17,6 +17,2 @@

const readConfig = (configFilePath) => {
return JSON.parse(stripJSONComments(fs.readFileSync(configFilePath, 'utf-8').trim()))
}
module.exports.load = (configFilePath, cwd, overrides) => {

@@ -50,21 +46,18 @@ if (configFilePath) {

function readConfig (configFilePath) {
try {
const data = fs.readFileSync(path.normalize(configFilePath), 'utf-8')
return JSON.parse(stripJSONComments(data.trim()))
} catch (error) {
throw new Error(`${error} ${configFilePath}`)
}
}
function loadConfig (cwd) {
for (const source of configSources) {
let foundPath
const foundPath = escalade(cwd, (dir, names) => names.includes(source) && source)
try {
foundPath = findUp.sync(source, { cwd })
} catch (e) {
continue
}
if (foundPath) {
const configFilePath = path.normalize(foundPath)
config = readConfig(foundPath)
try {
config = readConfig(configFilePath)
} catch (e) {
throw new Error(`${e} ${configFilePath}`)
}
if (source === 'package.json') {

@@ -71,0 +64,0 @@ config = config.rtlcssConfig

'use strict'
let options
const config = {}
const corePlugin = require('./plugin.js')
const defaultOptions = {
autoRename: false,
autoRenameStrict: false,
blacklist: {},
clean: true,
greedy: false,
processUrls: false,
stringMap: [],
useCalc: false,
aliases: {},
processEnv: true
}
function sort (arr) {

@@ -11,79 +22,57 @@ return arr.sort((a, b) => a.priority - b.priority)

function optionOrDefault (option, def) {
return option in options ? options[option] : def
}
function setupStringMap (stringMap) {
if (!Array.isArray(stringMap)) {
return
}
function addKey (key, def) {
config[key] = optionOrDefault(key, def)
}
let hasLeftRight = false
let hasLtrRtl = false
function main (opts, plugins, hooks) {
options = opts || {}
hooks = hooks || {}
addKey('autoRename', false)
addKey('autoRenameStrict', false)
addKey('blacklist', {})
addKey('clean', true)
addKey('greedy', false)
addKey('processUrls', false)
addKey('stringMap', [])
addKey('useCalc', false)
addKey('aliases', {})
addKey('processEnv', true)
// default strings map
if (Array.isArray(config.stringMap)) {
let hasLeftRight, hasLtrRtl
for (const map of config.stringMap) {
if (hasLeftRight && hasLtrRtl) {
break
} else if (map.name === 'left-right') {
hasLeftRight = true
} else if (map.name === 'ltr-rtl') {
hasLtrRtl = true
}
for (const map of stringMap) {
if (hasLeftRight && hasLtrRtl) {
break
} else if (map.name === 'left-right') {
hasLeftRight = true
} else if (map.name === 'ltr-rtl') {
hasLtrRtl = true
}
}
if (!hasLeftRight) {
config.stringMap.push({
name: 'left-right',
priority: 100,
exclusive: false,
search: ['left', 'Left', 'LEFT'],
replace: ['right', 'Right', 'RIGHT'],
options: { scope: '*', ignoreCase: false }
})
}
if (!hasLeftRight) {
stringMap.push({
name: 'left-right',
priority: 100,
exclusive: false,
search: ['left', 'Left', 'LEFT'],
replace: ['right', 'Right', 'RIGHT'],
options: { scope: '*', ignoreCase: false }
})
}
if (!hasLtrRtl) {
config.stringMap.push({
name: 'ltr-rtl',
priority: 100,
exclusive: false,
search: ['ltr', 'Ltr', 'LTR'],
replace: ['rtl', 'Rtl', 'RTL'],
options: { scope: '*', ignoreCase: false }
})
}
sort(config.stringMap)
if (!hasLtrRtl) {
stringMap.push({
name: 'ltr-rtl',
priority: 100,
exclusive: false,
search: ['ltr', 'Ltr', 'LTR'],
replace: ['rtl', 'Rtl', 'RTL'],
options: { scope: '*', ignoreCase: false }
})
}
// plugins
config.plugins = []
return sort(stringMap)
}
if (Array.isArray(plugins)) {
if (!plugins.some((plugin) => plugin.name === 'rtlcss')) {
config.plugins.push(corePlugin)
}
function setupPlugins (plugins) {
const newPlugins = []
config.plugins = config.plugins.concat(plugins)
} else if (!plugins || plugins.name !== 'rtlcss') {
config.plugins.push(corePlugin)
if (!plugins || !plugins.some((plugin) => plugin.name === 'rtlcss')) {
newPlugins.push(corePlugin)
}
sort(config.plugins)
return sort([...newPlugins, ...plugins])
}
// hooks
config.hooks = {
function setupHooks (hooks) {
const newHooks = {
pre () {},

@@ -94,12 +83,23 @@ post () {}

if (typeof hooks.pre === 'function') {
config.hooks.pre = hooks.pre
newHooks.pre = hooks.pre
}
if (typeof hooks.post === 'function') {
config.hooks.post = hooks.post
newHooks.post = hooks.post
}
return newHooks
}
module.exports.configure = (opts = {}, plugins = [], hooks = {}) => {
const config = { ...defaultOptions, ...opts }
// string map
config.stringMap = setupStringMap(config.stringMap)
// plugins
config.plugins = setupPlugins(plugins)
// hooks
config.hooks = setupHooks(hooks)
return config
}
module.exports.configure = main
'use strict'
module.exports = (comment) => {
let pos = 0
let value = comment.text
const match = value.match(/^\s*!?\s*rtl:/)
let meta
const match = comment.text.match(/^\s*!?\s*rtl:/)
if (!match) return
if (match) {
meta = {
source: comment,
name: '',
param: '',
begin: true,
end: true,
blacklist: false,
preserve: false
}
value = value.slice(match[0].length)
pos = value.indexOf(':')
let value = comment.text.slice(match[0].length)
let pos = value.indexOf(':')
const meta = {
source: comment,
name: '',
param: '',
begin: true,
end: true,
blacklist: false,
preserve: false
}
if (pos > -1) {
meta.name = value.slice(0, pos)
// begin/end are always true, unless one of them actually exists.
meta.begin = meta.name !== 'end'
meta.end = meta.name !== 'begin'
if (meta.name === 'begin' || meta.name === 'end') {
value = value.slice(meta.name.length + 1)
pos = value.indexOf(':')
if (pos > -1) {
meta.name = value.slice(0, pos)
value = value.slice(pos)
meta.param = value.slice(1)
} else {
meta.name = value
}
if (pos !== -1) {
meta.name = value.slice(0, pos)
// begin/end are always true, unless one of them actually exists.
meta.begin = meta.name !== 'end'
meta.end = meta.name !== 'begin'
if (meta.name === 'begin' || meta.name === 'end') {
value = value.slice(meta.name.length + 1)
pos = value.indexOf(':')
if (pos !== -1) {
meta.name = value.slice(0, pos)
meta.param = value.slice(pos + 1)
} else {
meta.param = value.slice(pos + 1)
meta.name = value
}
} else {
meta.name = value
meta.param = value.slice(pos + 1)
}
} else {
meta.name = value
}

@@ -44,0 +41,0 @@

@@ -15,4 +15,4 @@ 'use strict'

begin (node, metadata, context) {
// find the ending node in case of self closing directive
if (!this.endNode && metadata.begin && metadata.end) {
// find the ending node in case of self-closing directive
if (this.endNode === null && metadata.begin && metadata.end) {
let n = node

@@ -26,8 +26,3 @@ while (n && n.nodes) {

let prevent = true
if (node.type === 'comment' && node.text.match(/^\s*!?\s*rtl:end:ignore/)) {
prevent = false
}
return prevent
return node.type !== 'comment' || !/^\s*!?\s*rtl:end:ignore/.test(node.text)
},

@@ -37,3 +32,3 @@ end (node, metadata, context) {

// 1. block directive and the node is comment
// 2. self closing directive and node is endNode
// 2. self-closing directive and node is endNode
if ((metadata.begin !== metadata.end && node.type === 'comment') || (metadata.begin && metadata.end && node === this.endNode)) {

@@ -183,3 +178,3 @@ // clear ending node

const raw = `${decl.raws.between.substr(1).trim()}${hasRawValue ? decl.raws.value.raw : decl.value}${decl.important ? decl.raws.important.substr(9).trim() : ''}`
const result = raw.replace(expr, (match, value) => hasRawValue ? value + match : value)
const result = raw.replace(expr, (match, value) => value + match)
decl.value = hasRawValue ? (decl.raws.value.raw = result) : result

@@ -223,3 +218,3 @@ return true

action (prop, value, context) {
return { prop: prop.replace(this.expr, () => 'right'), value }
return { prop: prop.replace(this.expr, 'right'), value }
}

@@ -231,3 +226,3 @@ },

action (prop, value, context) {
return { prop: prop.replace(this.expr, () => 'left'), value }
return { prop: prop.replace(this.expr, 'left'), value }
}

@@ -369,25 +364,21 @@ },

flipMatrix (value, context) {
return this.flip(value, (i, num) => {
if (i === 2 || i === 3 || i === 5) {
return context.util.negate(num)
}
return num
}, context)
return this.flip(
value,
(i, num) => i === 2 || i === 3 || i === 5 ? context.util.negate(num) : num,
context
)
},
flipMatrix3D (value, context) {
return this.flip(value, (i, num) => {
if (i === 2 || i === 4 || i === 5 || i === 13) {
return context.util.negate(num)
}
return num
}, context)
return this.flip(
value,
(i, num) => i === 2 || i === 4 || i === 5 || i === 13 ? context.util.negate(num) : num,
context
)
},
flipRotate3D (value, context) {
return this.flip(value, (i, num) => {
if (i === 1 || i === 4) {
return context.util.negate(num)
}
return num
}, context)
return this.flip(
value,
(i, num) => i === 1 || i === 4 ? context.util.negate(num) : num,
context
)
},

@@ -439,3 +430,3 @@ action (prop, value, context) {

cache: null,
flip (value, context) {
flip (value, context, isPositionX) {
const state = util.saveTokens(value, true)

@@ -449,9 +440,18 @@ const parts = state.value.match(this.cache.match)

} else {
parts[0] = parts[0] === '0'
? '100%'
: (parts[0].match(this.cache.percent)
? context.util.complement(parts[0])
: (parts[0].match(this.cache.length)
? context.util.flipLength(parts[0])
: context.util.swapLeftRight(parts[0])))
if (parts[0] === '0') {
parts[0] = '100%'
} else if (parts[0].match(this.cache.percent)) {
parts[0] = context.util.complement(parts[0])
} else if (parts[0].match(this.cache.length)) {
if (isPositionX) {
parts[0] = context.util.flipLength(parts[0])
} else if (parts.length === 1) { // X 50% ==> left X top 50%
parts[0] = `right ${parts[0]} top 50%`
} else if (!keywords && parts.length === 2) { // X Y ==> left X top Y
parts[0] = `right ${parts[0]}`
parts[1] = `top ${parts[1]}`
}
} else {
parts[0] = context.util.swapLeftRight(parts[0])
}
state.value = state.value.replace(this.cache.match, () => parts.shift())

@@ -493,3 +493,3 @@ }

for (let x = 0; x < parts.length; x++) {
parts[x] = this.flip(parts[x], context)
parts[x] = this.flip(parts[x], context, lprop.endsWith('-x'))
}

@@ -508,3 +508,3 @@ }

name: 'keyword',
expr: /float|clear|text-align/i,
expr: /float|clear|text-align|justify-(content|items|self)/i,
action (prop, value, context) {

@@ -519,6 +519,5 @@ return { prop, value: context.util.swapLeftRight(value) }

update (context, value, name) {
if ((context.config.processUrls === true || context.config.processUrls.decl === true) && name.match(this.cache.url)) {
value = context.util.applyStringMap(value, true)
}
return value
return (context.config.processUrls === true || context.config.processUrls.decl === true) && name.match(this.cache.url)
? context.util.applyStringMap(value, true)
: value
},

@@ -525,0 +524,0 @@ flip (value) {

@@ -57,8 +57,8 @@ /**

postcssPlugin: 'rtlcss',
Once (root, { result }) {
Once (root) {
context.config.hooks.pre(root, postcss)
shouldProcess(root, result)
shouldProcess(root)
},
Rule (node, { result }) {
if (shouldProcess(node, result)) {
Rule (node) {
if (shouldProcess(node)) {
// new rule, reset flipped decl count to zero

@@ -68,13 +68,12 @@ flipped = 0

},
AtRule (node, { result }) {
if (shouldProcess(node, result) &&
AtRule (node) {
if (shouldProcess(node) &&
// @rules requires url flipping only
(context.config.processUrls === true || context.config.processUrls.atrule === true)
) {
const params = context.util.applyStringMap(node.params, true)
node.params = params
node.params = context.util.applyStringMap(node.params, true)
}
},
Comment (node, { result }) {
if (shouldProcess(node, result)) {
if (shouldProcess(node)) {
state.parse(node, result, (current) => {

@@ -131,3 +130,3 @@ let push = true

Declaration (node, { result }) {
if (shouldProcess(node, result)) {
if (shouldProcess(node)) {
// if broken by a matching value directive .. break

@@ -138,3 +137,3 @@ if (!context.util.each(context.config.plugins, (plugin) => {

const expr = context.util.regexDirective(directive.name)
if (expr.test(`${node.raws.between}${hasRawValue ? node.raws.value.raw : ''}${node.important && node.raws.important ? node.raws.important : ''}`)) {
if (expr.test(`${node.raws.between}${hasRawValue ? node.raws.value.raw : node.value}${node.important && node.raws.important ? node.raws.important : ''}`)) {
expr.lastIndex = 0

@@ -148,5 +147,5 @@ if (directive.action(node, expr, context)) {

if (hasRawValue) {
node.value = node.raws.value.raw = context.util.trimDirective(node.raws.value.raw)
}
node.value = hasRawValue
? (node.raws.value.raw = context.util.trimDirective(node.raws.value.raw))
: context.util.trimDirective(node.value)
}

@@ -237,5 +236,4 @@

*/
module.exports.configure = function (config) {
config = config || {}
module.exports.configure = function (config = {}) {
return postcss([this(config.options, config.plugins, config.hooks)])
}

@@ -34,3 +34,3 @@ 'use strict'

if (current === undefined) {
lazyResult.warn(`found end "${metadata.name}" without a matching begin.`, { node: node })
lazyResult.warn(`found end "${metadata.name}" without a matching begin.`, { node })
} else if (callback(current)) {

@@ -37,0 +37,0 @@ this.stack.push(current)

@@ -20,3 +20,3 @@ 'use strict'

const REGEX_COMMENT = /\/\*[^]*?\*\//igm // non-greedy
const REGEX_DIRECTIVE = /\/\*\s*(?:!)?\s*rtl:[^]*?\*\//img
const REGEX_DIRECTIVE = /\/\*\s*!?\s*rtl:[^]*?\*\//img
const REGEX_ESCAPE = /[.*+?^${}()|[\]\\]/g

@@ -59,5 +59,4 @@ const REGEX_FUNCTION = /\([^()]+\)/i

},
swap (value, a, b, options) {
swap (value, a, b, options = DEFAULT_STRING_MAP_OPTIONS) {
let expr = `${escapeRegExp(a)}|${escapeRegExp(b)}`
options = options || DEFAULT_STRING_MAP_OPTIONS
const greedy = Object.prototype.hasOwnProperty.call(options, 'greedy') ? options.greedy : config.greedy

@@ -134,3 +133,3 @@ if (!greedy) expr = `\\b(${expr})\\b`

state.value = state.value.replace(what, (c) => {
if (exclude && c.match(exclude)) {
if (exclude && exclude.test(c)) {
return c

@@ -146,5 +145,3 @@ }

let index = 0
const result = state.value.replace(state.restorer, () => {
return state.store[index++]
})
const result = state.value.replace(state.restorer, () => state.store[index++])
state.store.length = 0

@@ -167,3 +164,3 @@ return result

},
guard (what, who, indexed) {
guard (what, who) {
const state = {

@@ -173,16 +170,9 @@ value: who,

offset: tokenId++,
token: CHAR_TOKEN_START + tokenId,
indexed: indexed === true
token: CHAR_TOKEN_START + tokenId
}
if (state.indexed === true) {
while (what.test(state.value)) {
state.value = state.value.replace(what, (m) => {
state.store.push(m)
return `${state.token}:${state.store.length}${CHAR_TOKEN_END}`
})
}
} else {
while (what.test(state.value)) {
state.value = state.value.replace(what, (m) => {
state.store.push(m)
return state.token + CHAR_TOKEN_END
return `${state.token}:${state.store.length}${CHAR_TOKEN_END}`
})

@@ -194,25 +184,16 @@ }

unguard (state, callback) {
if (state.indexed === true) {
const detokenizer = new RegExp('(\\w*?)' + state.token + ':(\\d+)' + CHAR_TOKEN_END, 'i')
while (detokenizer.test(state.value)) {
state.value = state.value.replace(detokenizer, (match, name, index) => {
const value = state.store[index - 1]
return typeof callback === 'function'
? name + callback(value, name)
: name + value
})
}
return state.value
const detokenizer = new RegExp('(\\w*?)' + state.token + ':(\\d+)' + CHAR_TOKEN_END, 'i')
while (detokenizer.test(state.value)) {
state.value = state.value.replace(detokenizer, (match, name, index) => {
const value = state.store[index - 1]
return typeof callback === 'function'
? name + callback(value, name)
: name + value
})
}
return state.value.replace(new RegExp('(\\w*?)' + state.token + CHAR_TOKEN_END, 'i'), (match, name) => {
const value = state.store.shift()
return typeof callback === 'function'
? name + callback(value, name)
: name + value
})
return state.value
},
guardHexColors (value) {
return this.guard(REGEX_HEX_COLOR, value, true)
return this.guard(REGEX_HEX_COLOR, value)
},

@@ -223,3 +204,3 @@ unguardHexColors (state, callback) {

guardFunctions (value) {
return this.guard(REGEX_FUNCTION, value, true)
return this.guard(REGEX_FUNCTION, value)
},

@@ -239,3 +220,2 @@ unguardFunctions (state, callback) {

regex (what, options) {
what = what || []
let expression = ''

@@ -281,13 +261,7 @@

/**
* Simple breakable each: returning false in the callback will break the loop
* returns false if the loop was broken, otherwise true
* Simple breakable each returning false if the callback returns false
* otherwise it returns true
*/
each (array, callback) {
for (const element of array) {
if (callback(element) === false) {
return false
}
}
return true
return !array.some((element) => callback(element) === false)
}

@@ -294,0 +268,0 @@ }

{
"author": "Mohammad Younes",
"name": "rtlcss",
"version": "3.5.0",
"version": "4.0.0",
"description": "Framework for transforming cascading style sheets (CSS) from left-to-right (LTR) to right-to-left (RTL)",

@@ -28,14 +28,23 @@ "homepage": "https://rtlcss.com/",

"bin": {
"rtlcss": "./bin/rtlcss.js"
"rtlcss": "bin/rtlcss.js"
},
"main": "./lib/rtlcss.js",
"files": [
"bin/*.js",
"lib/*.js"
],
"dependencies": {
"find-up": "^5.0.0",
"escalade": "^3.1.1",
"picocolors": "^1.0.0",
"postcss": "^8.3.11",
"postcss": "^8.4.6",
"strip-json-comments": "^3.1.1"
},
"devDependencies": {
"mocha": "^9.1.3",
"c8": "^7.11.0",
"mocha": "^9.2.0",
"standard": "^16.0.4"
},
"engines": {
"node": ">=12.0.0"
},
"scripts": {

@@ -45,11 +54,8 @@ "main": "node ./lib/rtlcss.js",

"lint:fix": "npm run lint -- --fix",
"mocha": "mocha -R spec",
"mocha:special": "npm run mocha -- --fgrep \"# Special\"",
"test": "npm run lint && npm run main && npm run mocha"
},
"main": "./lib/rtlcss.js",
"files": [
"bin/*.js",
"lib/*.js"
]
"mocha": "mocha",
"mocha:special": "mocha --fgrep \"# Special\"",
"test": "npm run lint && npm run main && npm run mocha",
"test:ci": "npm run main && npm run mocha",
"coverage": "c8 npm run mocha"
}
}

@@ -10,3 +10,2 @@ # RTLCSS

[![Build Status](https://img.shields.io/github/workflow/status/MohammadYounes/rtlcss/CI/master?label=CI&logo=github)](https://github.com/MohammadYounes/rtlcss/actions?query=workflow%3ACI+branch%3Amaster)
[![Dependencies](https://img.shields.io/david/MohammadYounes/rtlcss)](https://david-dm.org/MohammadYounes/rtlcss)

@@ -13,0 +12,0 @@ [![js-standard-style](https://img.shields.io/badge/code%20style-standard-blue)](https://standardjs.com/)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc