postcss-normalize-string
Advanced tools
Comparing version
@@ -1,19 +0,10 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
var _postcss = require('postcss'); | ||
var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser")); | ||
var _postcss2 = _interopRequireDefault(_postcss); | ||
var _postcssValueParser = require('postcss-value-parser'); | ||
var _postcssValueParser2 = _interopRequireDefault(_postcssValueParser); | ||
var _has = require('has'); | ||
var _has2 = _interopRequireDefault(_has); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -24,4 +15,3 @@ | ||
*/ | ||
const SINGLE_QUOTE = '\''.charCodeAt(0); | ||
const SINGLE_QUOTE = "'".charCodeAt(0); | ||
const DOUBLE_QUOTE = '"'.charCodeAt(0); | ||
@@ -34,5 +24,3 @@ const BACKSLASH = '\\'.charCodeAt(0); | ||
const CR = '\r'.charCodeAt(0); | ||
const WORD_END = /[ \n\t\r\f'"\\]/g; | ||
/* | ||
@@ -49,3 +37,2 @@ * Constants (node type strings) | ||
const C_SINGLE = 'single'; | ||
/* | ||
@@ -58,3 +45,2 @@ * Literals | ||
const L_NEWLINE = `\\\n`; | ||
/* | ||
@@ -64,202 +50,233 @@ * Parser nodes | ||
const T_ESCAPED_SINGLE_QUOTE = { type: C_ESCAPED_SINGLE_QUOTE, value: `\\'` }; | ||
const T_ESCAPED_DOUBLE_QUOTE = { type: C_ESCAPED_DOUBLE_QUOTE, value: `\\"` }; | ||
const T_SINGLE_QUOTE = { type: C_SINGLE_QUOTE, value: L_SINGLE_QUOTE }; | ||
const T_DOUBLE_QUOTE = { type: C_DOUBLE_QUOTE, value: L_DOUBLE_QUOTE }; | ||
const T_NEWLINE = { type: C_NEWLINE, value: L_NEWLINE }; | ||
const T_ESCAPED_SINGLE_QUOTE = { | ||
type: C_ESCAPED_SINGLE_QUOTE, | ||
value: `\\'` | ||
}; | ||
const T_ESCAPED_DOUBLE_QUOTE = { | ||
type: C_ESCAPED_DOUBLE_QUOTE, | ||
value: `\\"` | ||
}; | ||
const T_SINGLE_QUOTE = { | ||
type: C_SINGLE_QUOTE, | ||
value: L_SINGLE_QUOTE | ||
}; | ||
const T_DOUBLE_QUOTE = { | ||
type: C_DOUBLE_QUOTE, | ||
value: L_DOUBLE_QUOTE | ||
}; | ||
const T_NEWLINE = { | ||
type: C_NEWLINE, | ||
value: L_NEWLINE | ||
}; | ||
function stringify(ast) { | ||
return ast.nodes.reduce((str, { value }) => { | ||
// Collapse multiple line strings automatically | ||
if (value === L_NEWLINE) { | ||
return str; | ||
} | ||
return ast.nodes.reduce((str, { | ||
value | ||
}) => { | ||
// Collapse multiple line strings automatically | ||
if (value === L_NEWLINE) { | ||
return str; | ||
} | ||
return str + value; | ||
}, ''); | ||
return str + value; | ||
}, ''); | ||
} | ||
function parse(str) { | ||
let code, next, value; | ||
let pos = 0; | ||
let len = str.length; | ||
let code, next, value; | ||
let pos = 0; | ||
let len = str.length; | ||
const ast = { | ||
nodes: [], | ||
types: { | ||
escapedSingleQuote: 0, | ||
escapedDoubleQuote: 0, | ||
singleQuote: 0, | ||
doubleQuote: 0 | ||
}, | ||
quotes: false | ||
}; | ||
const ast = { | ||
nodes: [], | ||
types: { | ||
escapedSingleQuote: 0, | ||
escapedDoubleQuote: 0, | ||
singleQuote: 0, | ||
doubleQuote: 0 | ||
}, | ||
quotes: false | ||
}; | ||
while (pos < len) { | ||
code = str.charCodeAt(pos); | ||
while (pos < len) { | ||
code = str.charCodeAt(pos); | ||
switch (code) { | ||
case SPACE: | ||
case TAB: | ||
case CR: | ||
case FEED: | ||
next = pos; | ||
switch (code) { | ||
case SPACE: | ||
case TAB: | ||
case CR: | ||
case FEED: | ||
next = pos; | ||
do { | ||
next += 1; | ||
code = str.charCodeAt(next); | ||
} while (code === SPACE || code === NEWLINE || code === TAB || code === CR || code === FEED); | ||
do { | ||
next += 1; | ||
code = str.charCodeAt(next); | ||
} while (code === SPACE || code === NEWLINE || code === TAB || code === CR || code === FEED); | ||
ast.nodes.push({ | ||
type: 'space', | ||
value: str.slice(pos, next) | ||
}); | ||
pos = next - 1; | ||
break; | ||
ast.nodes.push({ | ||
type: 'space', | ||
value: str.slice(pos, next) | ||
}); | ||
pos = next - 1; | ||
break; | ||
case SINGLE_QUOTE: | ||
ast.nodes.push(T_SINGLE_QUOTE); | ||
ast.types[C_SINGLE_QUOTE]++; | ||
ast.quotes = true; | ||
break; | ||
case DOUBLE_QUOTE: | ||
ast.nodes.push(T_DOUBLE_QUOTE); | ||
ast.types[C_DOUBLE_QUOTE]++; | ||
ast.quotes = true; | ||
break; | ||
case BACKSLASH: | ||
next = pos + 1; | ||
case SINGLE_QUOTE: | ||
ast.nodes.push(T_SINGLE_QUOTE); | ||
ast.types[C_SINGLE_QUOTE]++; | ||
ast.quotes = true; | ||
break; | ||
if (str.charCodeAt(next) === SINGLE_QUOTE) { | ||
ast.nodes.push(T_ESCAPED_SINGLE_QUOTE); | ||
ast.types[C_ESCAPED_SINGLE_QUOTE]++; | ||
ast.quotes = true; | ||
pos = next; | ||
break; | ||
} else if (str.charCodeAt(next) === DOUBLE_QUOTE) { | ||
ast.nodes.push(T_ESCAPED_DOUBLE_QUOTE); | ||
ast.types[C_ESCAPED_DOUBLE_QUOTE]++; | ||
ast.quotes = true; | ||
pos = next; | ||
break; | ||
} else if (str.charCodeAt(next) === NEWLINE) { | ||
ast.nodes.push(T_NEWLINE); | ||
pos = next; | ||
break; | ||
} | ||
/* | ||
* We need to fall through here to handle the token as | ||
* a whole word. The missing 'break' is intentional. | ||
*/ | ||
default: | ||
WORD_END.lastIndex = pos + 1; | ||
WORD_END.test(str); | ||
case DOUBLE_QUOTE: | ||
ast.nodes.push(T_DOUBLE_QUOTE); | ||
ast.types[C_DOUBLE_QUOTE]++; | ||
ast.quotes = true; | ||
break; | ||
if (WORD_END.lastIndex === 0) { | ||
next = len - 1; | ||
} else { | ||
next = WORD_END.lastIndex - 2; | ||
} | ||
case BACKSLASH: | ||
next = pos + 1; | ||
value = str.slice(pos, next + 1); | ||
if (str.charCodeAt(next) === SINGLE_QUOTE) { | ||
ast.nodes.push(T_ESCAPED_SINGLE_QUOTE); | ||
ast.types[C_ESCAPED_SINGLE_QUOTE]++; | ||
ast.quotes = true; | ||
pos = next; | ||
break; | ||
} else if (str.charCodeAt(next) === DOUBLE_QUOTE) { | ||
ast.nodes.push(T_ESCAPED_DOUBLE_QUOTE); | ||
ast.types[C_ESCAPED_DOUBLE_QUOTE]++; | ||
ast.quotes = true; | ||
pos = next; | ||
break; | ||
} else if (str.charCodeAt(next) === NEWLINE) { | ||
ast.nodes.push(T_NEWLINE); | ||
pos = next; | ||
break; | ||
} | ||
ast.nodes.push({ | ||
type: C_STRING, | ||
value | ||
}); | ||
/* | ||
* We need to fall through here to handle the token as | ||
* a whole word. The missing 'break' is intentional. | ||
*/ | ||
pos = next; | ||
default: | ||
WORD_END.lastIndex = pos + 1; | ||
WORD_END.test(str); | ||
if (WORD_END.lastIndex === 0) { | ||
next = len - 1; | ||
} else { | ||
next = WORD_END.lastIndex - 2; | ||
} | ||
pos++; | ||
value = str.slice(pos, next + 1); | ||
ast.nodes.push({ | ||
type: C_STRING, | ||
value | ||
}); | ||
pos = next; | ||
} | ||
return ast; | ||
pos++; | ||
} | ||
return ast; | ||
} | ||
function changeWrappingQuotes(node, ast) { | ||
const { types } = ast; | ||
const { | ||
types | ||
} = ast; | ||
if (types[C_SINGLE_QUOTE] || types[C_DOUBLE_QUOTE]) { | ||
return; | ||
} | ||
if (types[C_SINGLE_QUOTE] || types[C_DOUBLE_QUOTE]) { | ||
return; | ||
} | ||
if (node.quote === L_SINGLE_QUOTE && types[C_ESCAPED_SINGLE_QUOTE] > 0 && !types[C_ESCAPED_DOUBLE_QUOTE]) { | ||
node.quote = L_DOUBLE_QUOTE; | ||
if (node.quote === L_SINGLE_QUOTE && types[C_ESCAPED_SINGLE_QUOTE] > 0 && !types[C_ESCAPED_DOUBLE_QUOTE]) { | ||
node.quote = L_DOUBLE_QUOTE; | ||
} | ||
if (node.quote === L_DOUBLE_QUOTE && types[C_ESCAPED_DOUBLE_QUOTE] > 0 && !types[C_ESCAPED_SINGLE_QUOTE]) { | ||
node.quote = L_SINGLE_QUOTE; | ||
} | ||
ast.nodes = ast.nodes.reduce((newAst, child) => { | ||
if (child.type === C_ESCAPED_DOUBLE_QUOTE && node.quote === L_SINGLE_QUOTE) { | ||
return [...newAst, T_DOUBLE_QUOTE]; | ||
} | ||
if (node.quote === L_DOUBLE_QUOTE && types[C_ESCAPED_DOUBLE_QUOTE] > 0 && !types[C_ESCAPED_SINGLE_QUOTE]) { | ||
node.quote = L_SINGLE_QUOTE; | ||
if (child.type === C_ESCAPED_SINGLE_QUOTE && node.quote === L_DOUBLE_QUOTE) { | ||
return [...newAst, T_SINGLE_QUOTE]; | ||
} | ||
ast.nodes = ast.nodes.reduce((newAst, child) => { | ||
if (child.type === C_ESCAPED_DOUBLE_QUOTE && node.quote === L_SINGLE_QUOTE) { | ||
return [...newAst, T_DOUBLE_QUOTE]; | ||
} | ||
if (child.type === C_ESCAPED_SINGLE_QUOTE && node.quote === L_DOUBLE_QUOTE) { | ||
return [...newAst, T_SINGLE_QUOTE]; | ||
} | ||
return [...newAst, child]; | ||
}, []); | ||
return [...newAst, child]; | ||
}, []); | ||
} | ||
function normalize(value, preferredQuote) { | ||
if (!value || !value.length) { | ||
return value; | ||
if (!value || !value.length) { | ||
return value; | ||
} | ||
return (0, _postcssValueParser.default)(value).walk(child => { | ||
if (child.type !== C_STRING) { | ||
return; | ||
} | ||
return (0, _postcssValueParser2.default)(value).walk(child => { | ||
if (child.type !== C_STRING) { | ||
return; | ||
} | ||
const ast = parse(child.value); | ||
const ast = parse(child.value); | ||
if (ast.quotes) { | ||
changeWrappingQuotes(child, ast); | ||
} else if (preferredQuote === C_SINGLE) { | ||
child.quote = L_SINGLE_QUOTE; | ||
} else { | ||
child.quote = L_DOUBLE_QUOTE; | ||
} | ||
if (ast.quotes) { | ||
changeWrappingQuotes(child, ast); | ||
} else if (preferredQuote === C_SINGLE) { | ||
child.quote = L_SINGLE_QUOTE; | ||
} else { | ||
child.quote = L_DOUBLE_QUOTE; | ||
} | ||
child.value = stringify(ast); | ||
}).toString(); | ||
child.value = stringify(ast); | ||
}).toString(); | ||
} | ||
const params = { | ||
rule: 'selector', | ||
decl: 'value', | ||
atrule: 'params' | ||
rule: 'selector', | ||
decl: 'value', | ||
atrule: 'params' | ||
}; | ||
exports.default = _postcss2.default.plugin('postcss-normalize-string', opts => { | ||
const { preferredQuote } = Object.assign({}, { | ||
preferredQuote: 'double' | ||
}, opts); | ||
function pluginCreator(opts) { | ||
const { | ||
preferredQuote | ||
} = Object.assign({}, { | ||
preferredQuote: 'double' | ||
}, opts); | ||
return { | ||
postcssPlugin: 'postcss-normalize-string', | ||
return css => { | ||
const cache = {}; | ||
OnceExit(css) { | ||
const cache = {}; | ||
css.walk(node => { | ||
const { | ||
type | ||
} = node; | ||
css.walk(node => { | ||
const { type } = node; | ||
if (Object.prototype.hasOwnProperty.call(params, type)) { | ||
const param = params[type]; | ||
const key = node[param] + '|' + preferredQuote; | ||
if ((0, _has2.default)(params, type)) { | ||
const param = params[type]; | ||
const key = node[param] + '|' + preferredQuote; | ||
if (cache[key]) { | ||
node[param] = cache[key]; | ||
return; | ||
} | ||
if (cache[key]) { | ||
node[param] = cache[key]; | ||
const newValue = normalize(node[param], preferredQuote); | ||
node[param] = newValue; | ||
cache[key] = newValue; | ||
} | ||
}); | ||
} | ||
return; | ||
} | ||
}; | ||
} | ||
const result = normalize(node[param], preferredQuote); | ||
node[param] = result; | ||
cache[key] = result; | ||
} | ||
}); | ||
}; | ||
}); | ||
module.exports = exports['default']; | ||
pluginCreator.postcss = true; | ||
var _default = pluginCreator; | ||
exports.default = _default; | ||
module.exports = exports.default; |
{ | ||
"name": "postcss-normalize-string", | ||
"version": "4.0.2", | ||
"version": "5.0.0-rc.0", | ||
"description": "Normalize wrapping quotes for CSS string literals.", | ||
@@ -11,3 +11,5 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"prepublish": "cross-env BABEL_ENV=publish babel src --out-dir dist --ignore /__tests__/" | ||
"prebuild": "del-cli dist", | ||
"build": "cross-env BABEL_ENV=publish babel src --config-file ../../babel.config.js --out-dir dist --ignore \"**/__tests__/\"", | ||
"prepublish": "yarn build" | ||
}, | ||
@@ -20,6 +22,2 @@ "keywords": [ | ||
"license": "MIT", | ||
"devDependencies": { | ||
"babel-cli": "^6.0.0", | ||
"cross-env": "^5.0.0" | ||
}, | ||
"homepage": "https://github.com/cssnano/cssnano", | ||
@@ -33,5 +31,3 @@ "author": { | ||
"dependencies": { | ||
"has": "^1.0.0", | ||
"postcss": "^7.0.0", | ||
"postcss-value-parser": "^3.0.0" | ||
"postcss-value-parser": "^4.1.0" | ||
}, | ||
@@ -42,4 +38,11 @@ "bugs": { | ||
"engines": { | ||
"node": ">=6.9.0" | ||
} | ||
"node": "^10 || ^12 || >=14.0" | ||
}, | ||
"devDependencies": { | ||
"postcss": "^8.2.1" | ||
}, | ||
"peerDependencies": { | ||
"postcss": "^8.2.1" | ||
}, | ||
"gitHead": "8c16e67a4d24a13ac7e09a36d4faf504196efd0f" | ||
} |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
10874
8.93%2
-33.33%1
-50%5
25%232
12.08%1
Infinity%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated