style-to-object
Advanced tools
Comparing version 0.2.2 to 0.2.3
@@ -1,5 +0,26 @@ | ||
# Change Log | ||
# Changelog | ||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. | ||
### [0.2.3](https://github.com/remarkablemark/style-to-object/compare/v0.2.2...v0.2.3) (2019-06-22) | ||
### Build System | ||
* **package:** add field "files" and remove `.npmignore` ([fdf3966](https://github.com/remarkablemark/style-to-object/commit/fdf3966)) | ||
* **package:** update script `build:min` to generate sourcemap ([a13be58](https://github.com/remarkablemark/style-to-object/commit/a13be58)) | ||
* **package:** upgrade devDependencies ([377bb40](https://github.com/remarkablemark/style-to-object/commit/377bb40)) | ||
* **rollup:** remove `uglify-es` from config as it's unneeded ([b0951e0](https://github.com/remarkablemark/style-to-object/commit/b0951e0)) | ||
### Tests | ||
* organize and rename describe blocks ([8d4c004](https://github.com/remarkablemark/style-to-object/commit/8d4c004)) | ||
* organize data (test suites) into cases, errors, and invalids ([513732b](https://github.com/remarkablemark/style-to-object/commit/513732b)) | ||
* rename `test/cases.js` to `test/data.js` ([75d084d](https://github.com/remarkablemark/style-to-object/commit/75d084d)) | ||
* **data:** add more test cases and errors ([c9242c7](https://github.com/remarkablemark/style-to-object/commit/c9242c7)) | ||
* **data:** refactor test data from object to array format ([1a07a38](https://github.com/remarkablemark/style-to-object/commit/1a07a38)) | ||
<a name="0.2.2"></a> | ||
@@ -6,0 +27,0 @@ ## [0.2.2](https://github.com/remarkablemark/style-to-object/compare/v0.2.1...v0.2.2) (2018-09-13) |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global.StyleToObject = factory()); | ||
}(this, (function () { 'use strict'; | ||
(global = global || self, global.StyleToObject = factory()); | ||
}(this, function () { 'use strict'; | ||
// http://www.w3.org/TR/CSS21/grammar.html | ||
// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027 | ||
var commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; | ||
var COMMENT_REGEX = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; | ||
var parse = function(css, options){ | ||
var NEWLINE_REGEX = /\n/g; | ||
var WHITESPACE_REGEX = /^\s*/; | ||
// declaration | ||
var PROPERTY_REGEX = /^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/; | ||
var COLON_REGEX = /^:\s*/; | ||
var VALUE_REGEX = /^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/; | ||
var SEMICOLON_REGEX = /^[;\s]*/; | ||
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill | ||
var TRIM_REGEX = /^\s+|\s+$/g; | ||
// strings | ||
var NEWLINE = '\n'; | ||
var FORWARD_SLASH = '/'; | ||
var ASTERISK = '*'; | ||
var EMPTY_STRING = ''; | ||
// types | ||
var TYPE_COMMENT = 'comment'; | ||
var TYPE_DECLARATION = 'declaration'; | ||
/** | ||
* @param {String} style | ||
* @param {Object} [options] | ||
* @return {Object[]} | ||
* @throws {TypeError} | ||
* @throws {Error} | ||
*/ | ||
var inlineStyleParser = function(style, options) { | ||
if (typeof style !== 'string') { | ||
throw new TypeError('First argument must be a string'); | ||
} | ||
if (!style) return []; | ||
options = options || {}; | ||
@@ -17,3 +52,2 @@ | ||
*/ | ||
var lineno = 1; | ||
@@ -24,8 +58,9 @@ var column = 1; | ||
* Update lineno and column based on `str`. | ||
* | ||
* @param {String} str | ||
*/ | ||
function updatePosition(str) { | ||
var lines = str.match(/\n/g); | ||
var lines = str.match(NEWLINE_REGEX); | ||
if (lines) lineno += lines.length; | ||
var i = str.lastIndexOf('\n'); | ||
var i = str.lastIndexOf(NEWLINE); | ||
column = ~i ? str.length - i : column + str.length; | ||
@@ -36,7 +71,8 @@ } | ||
* Mark position and patch `node.position`. | ||
* | ||
* @return {Function} | ||
*/ | ||
function position() { | ||
var start = { line: lineno, column: column }; | ||
return function(node){ | ||
return function(node) { | ||
node.position = new Position(start); | ||
@@ -49,5 +85,9 @@ whitespace(); | ||
/** | ||
* Store position information for a node | ||
* Store position information for a node. | ||
* | ||
* @constructor | ||
* @property {Object} start | ||
* @property {Object} end | ||
* @property {undefined|String} source | ||
*/ | ||
function Position(start) { | ||
@@ -60,15 +100,16 @@ this.start = start; | ||
/** | ||
* Non-enumerable source string | ||
* Non-enumerable source string. | ||
*/ | ||
Position.prototype.content = style; | ||
Position.prototype.content = css; | ||
/** | ||
* Error `msg`. | ||
* | ||
* @param {String} msg | ||
* @throws {Error} | ||
*/ | ||
var errorsList = []; | ||
function error(msg) { | ||
var err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); | ||
var err = new Error( | ||
options.source + ':' + lineno + ':' + column + ': ' + msg | ||
); | ||
err.reason = msg; | ||
@@ -78,7 +119,5 @@ err.filename = options.source; | ||
err.column = column; | ||
err.source = css; | ||
err.source = style; | ||
if (options.silent) { | ||
errorsList.push(err); | ||
} else { | ||
if (options.silent) ; else { | ||
throw err; | ||
@@ -89,62 +128,13 @@ } | ||
/** | ||
* Parse stylesheet. | ||
*/ | ||
function stylesheet() { | ||
var rulesList = rules(); | ||
return { | ||
type: 'stylesheet', | ||
stylesheet: { | ||
source: options.source, | ||
rules: rulesList, | ||
parsingErrors: errorsList | ||
} | ||
}; | ||
} | ||
/** | ||
* Opening brace. | ||
*/ | ||
function open() { | ||
return match(/^{\s*/); | ||
} | ||
/** | ||
* Closing brace. | ||
*/ | ||
function close() { | ||
return match(/^}/); | ||
} | ||
/** | ||
* Parse ruleset. | ||
*/ | ||
function rules() { | ||
var node; | ||
var rules = []; | ||
whitespace(); | ||
comments(rules); | ||
while (css.length && css.charAt(0) != '}' && (node = atrule() || rule())) { | ||
if (node !== false) { | ||
rules.push(node); | ||
comments(rules); | ||
} | ||
} | ||
return rules; | ||
} | ||
/** | ||
* Match `re` and return captures. | ||
* | ||
* @param {RegExp} re | ||
* @return {undefined|Array} | ||
*/ | ||
function match(re) { | ||
var m = re.exec(css); | ||
var m = re.exec(style); | ||
if (!m) return; | ||
var str = m[0]; | ||
updatePosition(str); | ||
css = css.slice(str.length); | ||
style = style.slice(str.length); | ||
return m; | ||
@@ -156,15 +146,16 @@ } | ||
*/ | ||
function whitespace() { | ||
match(/^\s*/); | ||
match(WHITESPACE_REGEX); | ||
} | ||
/** | ||
* Parse comments; | ||
* Parse comments. | ||
* | ||
* @param {Object[]} [rules] | ||
* @return {Object[]} | ||
*/ | ||
function comments(rules) { | ||
var c; | ||
rules = rules || []; | ||
while (c = comment()) { | ||
while ((c = comment())) { | ||
if (c !== false) { | ||
@@ -179,24 +170,31 @@ rules.push(c); | ||
* Parse comment. | ||
* | ||
* @return {Object} | ||
* @throws {Error} | ||
*/ | ||
function comment() { | ||
var pos = position(); | ||
if ('/' != css.charAt(0) || '*' != css.charAt(1)) return; | ||
if (FORWARD_SLASH != style.charAt(0) || ASTERISK != style.charAt(1)) return; | ||
var i = 2; | ||
while ("" != css.charAt(i) && ('*' != css.charAt(i) || '/' != css.charAt(i + 1))) ++i; | ||
while ( | ||
EMPTY_STRING != style.charAt(i) && | ||
(ASTERISK != style.charAt(i) || FORWARD_SLASH != style.charAt(i + 1)) | ||
) { | ||
++i; | ||
} | ||
i += 2; | ||
if ("" === css.charAt(i-1)) { | ||
if (EMPTY_STRING === style.charAt(i - 1)) { | ||
return error('End of comment missing'); | ||
} | ||
var str = css.slice(2, i - 2); | ||
var str = style.slice(2, i - 2); | ||
column += 2; | ||
updatePosition(str); | ||
css = css.slice(i); | ||
style = style.slice(i); | ||
column += 2; | ||
return pos({ | ||
type: 'comment', | ||
type: TYPE_COMMENT, | ||
comment: str | ||
@@ -207,25 +205,7 @@ }); | ||
/** | ||
* Parse selector. | ||
*/ | ||
function selector() { | ||
var m = match(/^([^{]+)/); | ||
if (!m) return; | ||
/* @fix Remove all comments from selectors | ||
* http://ostermiller.org/findcomment.html */ | ||
return trim(m[0]) | ||
.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '') | ||
.replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function(m) { | ||
return m.replace(/,/g, '\u200C'); | ||
}) | ||
.split(/\s*(?![^(]*\)),\s*/) | ||
.map(function(s) { | ||
return s.replace(/\u200C/g, ','); | ||
}); | ||
} | ||
/** | ||
* Parse declaration. | ||
* | ||
* @return {Object} | ||
* @throws {Error} | ||
*/ | ||
function declaration() { | ||
@@ -235,20 +215,22 @@ var pos = position(); | ||
// prop | ||
var prop = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); | ||
var prop = match(PROPERTY_REGEX); | ||
if (!prop) return; | ||
prop = trim(prop[0]); | ||
comment(); | ||
// : | ||
if (!match(/^:\s*/)) return error("property missing ':'"); | ||
if (!match(COLON_REGEX)) return error("property missing ':'"); | ||
// val | ||
var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); | ||
var val = match(VALUE_REGEX); | ||
var ret = pos({ | ||
type: 'declaration', | ||
property: prop.replace(commentre, ''), | ||
value: val ? trim(val[0]).replace(commentre, '') : '' | ||
type: TYPE_DECLARATION, | ||
property: trim(prop[0].replace(COMMENT_REGEX, EMPTY_STRING)), | ||
value: val | ||
? trim(val[0].replace(COMMENT_REGEX, EMPTY_STRING)) | ||
: EMPTY_STRING | ||
}); | ||
// ; | ||
match(/^[;\s]*/); | ||
match(SEMICOLON_REGEX); | ||
@@ -260,8 +242,8 @@ return ret; | ||
* Parse declarations. | ||
* | ||
* @return {Object[]} | ||
*/ | ||
function declarations() { | ||
var decls = []; | ||
if (!open()) return error("missing '{'"); | ||
comments(decls); | ||
@@ -271,3 +253,3 @@ | ||
var decl; | ||
while (decl = declaration()) { | ||
while ((decl = declaration())) { | ||
if (decl !== false) { | ||
@@ -279,308 +261,7 @@ decls.push(decl); | ||
if (!close()) return error("missing '}'"); | ||
return decls; | ||
} | ||
/** | ||
* Parse keyframe. | ||
*/ | ||
function keyframe() { | ||
var m; | ||
var vals = []; | ||
var pos = position(); | ||
while (m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)) { | ||
vals.push(m[1]); | ||
match(/^,\s*/); | ||
} | ||
if (!vals.length) return; | ||
return pos({ | ||
type: 'keyframe', | ||
values: vals, | ||
declarations: declarations() | ||
}); | ||
} | ||
/** | ||
* Parse keyframes. | ||
*/ | ||
function atkeyframes() { | ||
var pos = position(); | ||
var m = match(/^@([-\w]+)?keyframes\s*/); | ||
if (!m) return; | ||
var vendor = m[1]; | ||
// identifier | ||
var m = match(/^([-\w]+)\s*/); | ||
if (!m) return error("@keyframes missing name"); | ||
var name = m[1]; | ||
if (!open()) return error("@keyframes missing '{'"); | ||
var frame; | ||
var frames = comments(); | ||
while (frame = keyframe()) { | ||
frames.push(frame); | ||
frames = frames.concat(comments()); | ||
} | ||
if (!close()) return error("@keyframes missing '}'"); | ||
return pos({ | ||
type: 'keyframes', | ||
name: name, | ||
vendor: vendor, | ||
keyframes: frames | ||
}); | ||
} | ||
/** | ||
* Parse supports. | ||
*/ | ||
function atsupports() { | ||
var pos = position(); | ||
var m = match(/^@supports *([^{]+)/); | ||
if (!m) return; | ||
var supports = trim(m[1]); | ||
if (!open()) return error("@supports missing '{'"); | ||
var style = comments().concat(rules()); | ||
if (!close()) return error("@supports missing '}'"); | ||
return pos({ | ||
type: 'supports', | ||
supports: supports, | ||
rules: style | ||
}); | ||
} | ||
/** | ||
* Parse host. | ||
*/ | ||
function athost() { | ||
var pos = position(); | ||
var m = match(/^@host\s*/); | ||
if (!m) return; | ||
if (!open()) return error("@host missing '{'"); | ||
var style = comments().concat(rules()); | ||
if (!close()) return error("@host missing '}'"); | ||
return pos({ | ||
type: 'host', | ||
rules: style | ||
}); | ||
} | ||
/** | ||
* Parse media. | ||
*/ | ||
function atmedia() { | ||
var pos = position(); | ||
var m = match(/^@media *([^{]+)/); | ||
if (!m) return; | ||
var media = trim(m[1]); | ||
if (!open()) return error("@media missing '{'"); | ||
var style = comments().concat(rules()); | ||
if (!close()) return error("@media missing '}'"); | ||
return pos({ | ||
type: 'media', | ||
media: media, | ||
rules: style | ||
}); | ||
} | ||
/** | ||
* Parse custom-media. | ||
*/ | ||
function atcustommedia() { | ||
var pos = position(); | ||
var m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); | ||
if (!m) return; | ||
return pos({ | ||
type: 'custom-media', | ||
name: trim(m[1]), | ||
media: trim(m[2]) | ||
}); | ||
} | ||
/** | ||
* Parse paged media. | ||
*/ | ||
function atpage() { | ||
var pos = position(); | ||
var m = match(/^@page */); | ||
if (!m) return; | ||
var sel = selector() || []; | ||
if (!open()) return error("@page missing '{'"); | ||
var decls = comments(); | ||
// declarations | ||
var decl; | ||
while (decl = declaration()) { | ||
decls.push(decl); | ||
decls = decls.concat(comments()); | ||
} | ||
if (!close()) return error("@page missing '}'"); | ||
return pos({ | ||
type: 'page', | ||
selectors: sel, | ||
declarations: decls | ||
}); | ||
} | ||
/** | ||
* Parse document. | ||
*/ | ||
function atdocument() { | ||
var pos = position(); | ||
var m = match(/^@([-\w]+)?document *([^{]+)/); | ||
if (!m) return; | ||
var vendor = trim(m[1]); | ||
var doc = trim(m[2]); | ||
if (!open()) return error("@document missing '{'"); | ||
var style = comments().concat(rules()); | ||
if (!close()) return error("@document missing '}'"); | ||
return pos({ | ||
type: 'document', | ||
document: doc, | ||
vendor: vendor, | ||
rules: style | ||
}); | ||
} | ||
/** | ||
* Parse font-face. | ||
*/ | ||
function atfontface() { | ||
var pos = position(); | ||
var m = match(/^@font-face\s*/); | ||
if (!m) return; | ||
if (!open()) return error("@font-face missing '{'"); | ||
var decls = comments(); | ||
// declarations | ||
var decl; | ||
while (decl = declaration()) { | ||
decls.push(decl); | ||
decls = decls.concat(comments()); | ||
} | ||
if (!close()) return error("@font-face missing '}'"); | ||
return pos({ | ||
type: 'font-face', | ||
declarations: decls | ||
}); | ||
} | ||
/** | ||
* Parse import | ||
*/ | ||
var atimport = _compileAtrule('import'); | ||
/** | ||
* Parse charset | ||
*/ | ||
var atcharset = _compileAtrule('charset'); | ||
/** | ||
* Parse namespace | ||
*/ | ||
var atnamespace = _compileAtrule('namespace'); | ||
/** | ||
* Parse non-block at-rules | ||
*/ | ||
function _compileAtrule(name) { | ||
var re = new RegExp('^@' + name + '\\s*([^;]+);'); | ||
return function() { | ||
var pos = position(); | ||
var m = match(re); | ||
if (!m) return; | ||
var ret = { type: name }; | ||
ret[name] = m[1].trim(); | ||
return pos(ret); | ||
} | ||
} | ||
/** | ||
* Parse at rule. | ||
*/ | ||
function atrule() { | ||
if (css[0] != '@') return; | ||
return atkeyframes() | ||
|| atmedia() | ||
|| atcustommedia() | ||
|| atsupports() | ||
|| atimport() | ||
|| atcharset() | ||
|| atnamespace() | ||
|| atdocument() | ||
|| atpage() | ||
|| athost() | ||
|| atfontface(); | ||
} | ||
/** | ||
* Parse rule. | ||
*/ | ||
function rule() { | ||
var pos = position(); | ||
var sel = selector(); | ||
if (!sel) return error('selector missing'); | ||
comments(); | ||
return pos({ | ||
type: 'rule', | ||
selectors: sel, | ||
declarations: declarations() | ||
}); | ||
} | ||
return addParent(stylesheet()); | ||
whitespace(); | ||
return declarations(); | ||
}; | ||
@@ -590,41 +271,16 @@ | ||
* Trim `str`. | ||
* | ||
* @param {String} str | ||
* @return {String} | ||
*/ | ||
function trim(str) { | ||
return str ? str.replace(/^\s+|\s+$/g, '') : ''; | ||
return str ? str.replace(TRIM_REGEX, EMPTY_STRING) : EMPTY_STRING; | ||
} | ||
/** | ||
* Adds non-enumerable parent node reference to each node. | ||
*/ | ||
function addParent(obj, parent) { | ||
var isNode = obj && typeof obj.type === 'string'; | ||
var childParent = isNode ? obj : parent; | ||
for (var k in obj) { | ||
var value = obj[k]; | ||
if (Array.isArray(value)) { | ||
value.forEach(function(v) { addParent(v, childParent); }); | ||
} else if (value && typeof value === 'object') { | ||
addParent(value, childParent); | ||
} | ||
} | ||
if (isNode) { | ||
Object.defineProperty(obj, 'parent', { | ||
configurable: true, | ||
writable: true, | ||
enumerable: false, | ||
value: parent || null | ||
}); | ||
} | ||
return obj; | ||
} | ||
/** | ||
* Parses inline style. | ||
* Parses inline style to object. | ||
* | ||
* Example: 'color:red' => { color: 'red' } | ||
* @example | ||
* // returns { 'line-height': '42' } | ||
* StyleToObject('line-height: 42;'); | ||
* | ||
@@ -635,11 +291,13 @@ * @param {String} style - The inline style. | ||
*/ | ||
var styleToObject = function parseInlineStyle(style, iterator) { | ||
if (!style || typeof style !== 'string') return null; | ||
function StyleToObject(style, iterator) { | ||
var output = null; | ||
if (!style || typeof style !== 'string') { | ||
return output; | ||
} | ||
// make sure to wrap declarations in placeholder | ||
var declarations = parse('p{' + style + '}').stylesheet.rules[0].declarations; | ||
var declaration, property, value; | ||
var output = null; | ||
var declaration; | ||
var declarations = inlineStyleParser(style); | ||
var hasIterator = typeof iterator === 'function'; | ||
var property; | ||
var value; | ||
@@ -660,6 +318,8 @@ for (var i = 0, len = declarations.length; i < len; i++) { | ||
return output; | ||
}; | ||
} | ||
var styleToObject = StyleToObject; | ||
return styleToObject; | ||
}))); | ||
})); |
@@ -1,1 +0,2 @@ | ||
!function(r,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):r.StyleToObject=e()}(this,function(){"use strict";var z=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//g,f=function(t,n){n=n||{};var i=1,s=1;function a(r){var e=r.match(/\n/g);e&&(i+=e.length);var n=r.lastIndexOf("\n");s=~n?r.length-n:s+r.length}function u(){var e={line:i,column:s};return function(r){return r.position=new o(e),g(),r}}function o(r){this.start=r,this.end={line:i,column:s},this.source=n.source}o.prototype.content=t;var c=[];function f(r){var e=new Error(n.source+":"+i+":"+s+": "+r);if(e.reason=r,e.filename=n.source,e.line=i,e.column=s,e.source=t,!n.silent)throw e;c.push(e)}function p(){return v(/^{\s*/)}function m(){return v(/^}/)}function l(){var r,e=[];for(g(),y(e);t.length&&"}"!=t.charAt(0)&&(r=j()||O());)!1!==r&&(e.push(r),y(e));return e}function v(r){var e=r.exec(t);if(e){var n=e[0];return a(n),t=t.slice(n.length),e}}function g(){v(/^\s*/)}function y(r){var e;for(r=r||[];e=d();)!1!==e&&r.push(e);return r}function d(){var r=u();if("/"==t.charAt(0)&&"*"==t.charAt(1)){for(var e=2;""!=t.charAt(e)&&("*"!=t.charAt(e)||"/"!=t.charAt(e+1));)++e;if(e+=2,""===t.charAt(e-1))return f("End of comment missing");var n=t.slice(2,e-2);return s+=2,a(n),t=t.slice(e),s+=2,r({type:"comment",comment:n})}}function h(){var r=v(/^([^{]+)/);if(r)return C(r[0]).replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g,"").replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g,function(r){return r.replace(/,/g,"")}).split(/\s*(?![^(]*\)),\s*/).map(function(r){return r.replace(/\u200C/g,",")})}function w(){var r=u(),e=v(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/);if(e){if(e=C(e[0]),!v(/^:\s*/))return f("property missing ':'");var n=v(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/),t=r({type:"declaration",property:e.replace(z,""),value:n?C(n[0]).replace(z,""):""});return v(/^[;\s]*/),t}}function A(){var r,e=[];if(!p())return f("missing '{'");for(y(e);r=w();)!1!==r&&(e.push(r),y(e));return m()?e:f("missing '}'")}function b(){for(var r,e=[],n=u();r=v(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/);)e.push(r[1]),v(/^,\s*/);if(e.length)return n({type:"keyframe",values:e,declarations:A()})}var r,e=E("import"),k=E("charset"),x=E("namespace");function E(t){var i=new RegExp("^@"+t+"\\s*([^;]+);");return function(){var r=u(),e=v(i);if(e){var n={type:t};return n[t]=e[1].trim(),r(n)}}}function j(){if("@"==t[0])return function(){var r=u();if(e=v(/^@([-\w]+)?keyframes\s*/)){var e,n=e[1];if(!(e=v(/^([-\w]+)\s*/)))return f("@keyframes missing name");var t,i=e[1];if(!p())return f("@keyframes missing '{'");for(var s=y();t=b();)s.push(t),s=s.concat(y());return m()?r({type:"keyframes",name:i,vendor:n,keyframes:s}):f("@keyframes missing '}'")}}()||function(){var r=u(),e=v(/^@media *([^{]+)/);if(e){var n=C(e[1]);if(!p())return f("@media missing '{'");var t=y().concat(l());return m()?r({type:"media",media:n,rules:t}):f("@media missing '}'")}}()||function(){var r=u(),e=v(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/);if(e)return r({type:"custom-media",name:C(e[1]),media:C(e[2])})}()||function(){var r=u(),e=v(/^@supports *([^{]+)/);if(e){var n=C(e[1]);if(!p())return f("@supports missing '{'");var t=y().concat(l());return m()?r({type:"supports",supports:n,rules:t}):f("@supports missing '}'")}}()||e()||k()||x()||function(){var r=u(),e=v(/^@([-\w]+)?document *([^{]+)/);if(e){var n=C(e[1]),t=C(e[2]);if(!p())return f("@document missing '{'");var i=y().concat(l());return m()?r({type:"document",document:t,vendor:n,rules:i}):f("@document missing '}'")}}()||function(){var r=u();if(v(/^@page */)){var e=h()||[];if(!p())return f("@page missing '{'");for(var n,t=y();n=w();)t.push(n),t=t.concat(y());return m()?r({type:"page",selectors:e,declarations:t}):f("@page missing '}'")}}()||function(){var r=u();if(v(/^@host\s*/)){if(!p())return f("@host missing '{'");var e=y().concat(l());return m()?r({type:"host",rules:e}):f("@host missing '}'")}}()||function(){var r=u();if(v(/^@font-face\s*/)){if(!p())return f("@font-face missing '{'");for(var e,n=y();e=w();)n.push(e),n=n.concat(y());return m()?r({type:"font-face",declarations:n}):f("@font-face missing '}'")}}()}function O(){var r=u(),e=h();return e?(y(),r({type:"rule",selectors:e,declarations:A()})):f("selector missing")}return function e(r,n){var t=r&&"string"==typeof r.type;var i=t?r:n;for(var s in r){var a=r[s];Array.isArray(a)?a.forEach(function(r){e(r,i)}):a&&"object"==typeof a&&e(a,i)}t&&Object.defineProperty(r,"parent",{configurable:!0,writable:!0,enumerable:!1,value:n||null});return r}((r=l(),{type:"stylesheet",stylesheet:{source:n.source,rules:r,parsingErrors:c}}))};function C(r){return r?r.replace(/^\s+|\s+$/g,""):""}return function(r,e){if(!r||"string"!=typeof r)return null;for(var n,t,i,s=f("p{"+r+"}").stylesheet.rules[0].declarations,a=null,u="function"==typeof e,o=0,c=s.length;o<c;o++)t=(n=s[o]).property,i=n.value,u?e(t,i,n):i&&(a||(a={}),a[t]=i);return a}}); | ||
!function(n,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(n=n||self).StyleToObject=r()}(this,function(){"use strict";var m=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//g,g=/\n/g,y=/^\s*/,d=/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/,w=/^:\s*/,A=/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/,x=/^[;\s]*/,r=/^\s+|\s+$/g,b="";function E(n){return n?n.replace(r,b):b}return function(n,r){var t,e=null;if(!n||"string"!=typeof n)return e;for(var o,i,u=function(e,t){if("string"!=typeof e)throw new TypeError("First argument must be a string");if(!e)return[];t=t||{};var o=1,i=1;function u(n){var r=n.match(g);r&&(o+=r.length);var t=n.lastIndexOf("\n");i=~t?n.length-t:i+n.length}function c(){var r={line:o,column:i};return function(n){return n.position=new f(r),l(),n}}function f(n){this.start=n,this.end={line:o,column:i},this.source=t.source}function a(n){var r=new Error(t.source+":"+o+":"+i+": "+n);if(r.reason=n,r.filename=t.source,r.line=o,r.column=i,r.source=e,!t.silent)throw r}function s(n){var r=n.exec(e);if(r){var t=r[0];return u(t),e=e.slice(t.length),r}}function l(){s(y)}function p(n){var r;for(n=n||[];r=h();)!1!==r&&n.push(r);return n}function h(){var n=c();if("/"==e.charAt(0)&&"*"==e.charAt(1)){for(var r=2;b!=e.charAt(r)&&("*"!=e.charAt(r)||"/"!=e.charAt(r+1));)++r;if(r+=2,b===e.charAt(r-1))return a("End of comment missing");var t=e.slice(2,r-2);return i+=2,u(t),e=e.slice(r),i+=2,n({type:"comment",comment:t})}}function v(){var n=c(),r=s(d);if(r){if(h(),!s(w))return a("property missing ':'");var t=s(A),e=n({type:"declaration",property:E(r[0].replace(m,b)),value:t?E(t[0].replace(m,b)):b});return s(x),e}}return f.prototype.content=e,l(),function(){var n,r=[];for(p(r);n=v();)!1!==n&&(r.push(n),p(r));return r}()}(n),c="function"==typeof r,f=0,a=u.length;f<a;f++)o=(t=u[f]).property,i=t.value,c?r(o,i,t):i&&((e=e||{})[o]=i);return e}}); | ||
//# sourceMappingURL=style-to-object.min.js.map |
28
index.js
@@ -1,7 +0,9 @@ | ||
var parse = require('css/lib/parse'); | ||
var parse = require('inline-style-parser'); | ||
/** | ||
* Parses inline style. | ||
* Parses inline style to object. | ||
* | ||
* Example: 'color:red' => { color: 'red' } | ||
* @example | ||
* // returns { 'line-height': '42' } | ||
* StyleToObject('line-height: 42;'); | ||
* | ||
@@ -12,11 +14,13 @@ * @param {String} style - The inline style. | ||
*/ | ||
module.exports = function parseInlineStyle(style, iterator) { | ||
if (!style || typeof style !== 'string') return null; | ||
function StyleToObject(style, iterator) { | ||
var output = null; | ||
if (!style || typeof style !== 'string') { | ||
return output; | ||
} | ||
// make sure to wrap declarations in placeholder | ||
var declarations = parse('p{' + style + '}').stylesheet.rules[0].declarations; | ||
var declaration, property, value; | ||
var output = null; | ||
var declaration; | ||
var declarations = parse(style); | ||
var hasIterator = typeof iterator === 'function'; | ||
var property; | ||
var value; | ||
@@ -37,2 +41,4 @@ for (var i = 0, len = declarations.length; i < len; i++) { | ||
return output; | ||
}; | ||
} | ||
module.exports = StyleToObject; |
{ | ||
"name": "style-to-object", | ||
"version": "0.2.2", | ||
"version": "0.2.3", | ||
"description": "Converts inline style to object.", | ||
@@ -8,12 +8,15 @@ "author": "Mark <mark@remarkablemark.org>", | ||
"scripts": { | ||
"build": "npm run clean && npm run build:min && npm run build:unmin", | ||
"build:min": "NODE_ENV=production rollup --config --file dist/style-to-object.min.js --sourcemap", | ||
"build:unmin": "NODE_ENV=development rollup --config --file dist/style-to-object.js", | ||
"clean": "rm -rf dist", | ||
"coveralls": "nyc report --reporter=text-lcov | coveralls", | ||
"lint": "eslint --ignore-path .gitignore .", | ||
"lint:fix": "npm run lint -- --fix", | ||
"prepublishOnly": "npm run build", | ||
"release": "standard-version", | ||
"release": "standard-version --no-verify", | ||
"test": "mocha", | ||
"lint": "eslint --ignore-path .gitignore .", | ||
"cover": "istanbul cover _mocha -- -R spec \"test/**/*.js\"", | ||
"coveralls": "cat coverage/lcov.info | coveralls", | ||
"clean": "rm -rf dist", | ||
"build": "npm run clean && npm run build:min && npm run build:unmin", | ||
"build:min": "NODE_ENV=production rollup --config --output.file dist/style-to-object.min.js", | ||
"build:unmin": "rollup --config --output.file dist/style-to-object.js" | ||
"test:coverage": "nyc npm test", | ||
"test:coverage:report": "nyc report --reporter=html", | ||
"test:watch": "mocha --watch" | ||
}, | ||
@@ -28,5 +31,7 @@ "repository": { | ||
"keywords": [ | ||
"style-to-object", | ||
"inline", | ||
"style", | ||
"parser", | ||
"css", | ||
"style", | ||
"object", | ||
@@ -36,17 +41,25 @@ "pojo" | ||
"dependencies": { | ||
"css": "2.2.4" | ||
"inline-style-parser": "0.1.1" | ||
}, | ||
"devDependencies": { | ||
"coveralls": "3.0.2", | ||
"eslint": "5.5.0", | ||
"istanbul": "0.4.5", | ||
"mocha": "5.2.0", | ||
"rollup": "0.65.2", | ||
"rollup-plugin-commonjs": "9.1.6", | ||
"rollup-plugin-node-resolve": "3.4.0", | ||
"rollup-plugin-uglify": "5.0.2", | ||
"standard-version": "4.4.0", | ||
"uglify-es": "3.3.9" | ||
"@commitlint/cli": "^8.0.0", | ||
"@commitlint/config-conventional": "^8.0.0", | ||
"coveralls": "^3.0.4", | ||
"eslint": "^6.0.0", | ||
"eslint-plugin-prettier": "^3.1.0", | ||
"husky": "^2.4.1", | ||
"lint-staged": "^8.2.1", | ||
"mocha": "^6.1.4", | ||
"nyc": "^14.1.1", | ||
"prettier": "^1.18.2", | ||
"rollup": "^1.16.2", | ||
"rollup-plugin-commonjs": "^10.0.0", | ||
"rollup-plugin-node-resolve": "^5.0.4", | ||
"rollup-plugin-uglify": "^6.0.2", | ||
"standard-version": "^6.0.1" | ||
}, | ||
"files": [ | ||
"/dist" | ||
], | ||
"license": "MIT" | ||
} |
115
README.md
@@ -9,2 +9,3 @@ # style-to-object | ||
[![Dependency status](https://david-dm.org/remarkablemark/style-to-object.svg)](https://david-dm.org/remarkablemark/style-to-object) | ||
[![NPM downloads](https://img.shields.io/npm/dm/style-to-object.svg?style=flat-square)](https://www.npmjs.com/package/style-to-object) | ||
@@ -16,7 +17,12 @@ Parses inline style to object: | ||
parser('color: #C0FFEE; background: #BADA55;'); | ||
// { color: "#C0FFEE", background: "#BADA55" } | ||
``` | ||
[JSFiddle](https://jsfiddle.net/remarkablemark/ykz2meot/) | [repl.it](https://repl.it/@remarkablemark/style-to-object) | ||
Output: | ||
```js | ||
{ color: '#C0FFEE', background: '#BADA55' } | ||
``` | ||
[JSFiddle](https://jsfiddle.net/remarkablemark/ykz2meot/) | [Repl.it](https://repl.it/@remarkablemark/style-to-object) | [Examples](https://github.com/remarkablemark/style-to-object/tree/master/examples) | ||
## Installation | ||
@@ -27,3 +33,3 @@ | ||
```sh | ||
npm install style-to-object --save | ||
$ npm install style-to-object --save | ||
``` | ||
@@ -34,3 +40,3 @@ | ||
```sh | ||
yarn add style-to-object | ||
$ yarn add style-to-object | ||
``` | ||
@@ -43,3 +49,3 @@ | ||
<script> | ||
var parser = window.StyleToObject; | ||
window.StyleToObject(/* string */); | ||
</script> | ||
@@ -54,6 +60,6 @@ ``` | ||
// CommonJS | ||
const parser = require('style-to-object'); | ||
const parse = require('style-to-object'); | ||
// ES Modules | ||
import parser from 'style-to-object'; | ||
import parse from 'style-to-object'; | ||
``` | ||
@@ -64,8 +70,11 @@ | ||
```js | ||
parse(` | ||
color: #f00 | ||
`); | ||
// { color: '#f00' } | ||
parse('line-height: 42'); | ||
``` | ||
Output: | ||
```js | ||
{ 'line-height': '42' } | ||
``` | ||
Parse multiple declarations: | ||
@@ -75,22 +84,28 @@ | ||
parse(` | ||
color: #f00; | ||
z-index: 42; | ||
border-color: #ACE; | ||
z-index: 1337; | ||
`); | ||
// { color: '#f00', 'z-index': '42' } | ||
``` | ||
Output: | ||
```js | ||
{ 'border-color': '#ACE', 'z-index': '1337' } | ||
``` | ||
Parse unknown declarations: | ||
```js | ||
parse(` | ||
foo: bar; | ||
`); | ||
// { foo: 'bar' } | ||
parse('answer: 42;'); | ||
``` | ||
Invalid declarations: | ||
Output: | ||
```js | ||
parse(1); // null | ||
parse('top:'); // null | ||
{ 'answer': '42' } | ||
``` | ||
Invalid declarations/arguments: | ||
```js | ||
parse(` | ||
@@ -100,3 +115,14 @@ top: ; | ||
`); // { right: '1em' } | ||
parse(); // null | ||
parse(null); // null | ||
parse(1); // null | ||
parse(true); // null | ||
parse('top:'); // null | ||
parse(':12px'); // null | ||
parse(':'); // null | ||
parse(';'); // null | ||
parse('top'); // throws Error | ||
parse('/*'); // throws Error | ||
``` | ||
@@ -109,3 +135,3 @@ | ||
```js | ||
parser('color: #f00', function() {}); // null | ||
parse('color: #f00', function() {}); // null | ||
``` | ||
@@ -127,11 +153,11 @@ | ||
const style = ` | ||
color: #f00; | ||
background: #ba4; | ||
color: red; | ||
background: blue; | ||
`; | ||
const output = []; | ||
const iterator = (name, value) => { | ||
function iterator(name, value) { | ||
output.push([name, value]); | ||
}; | ||
parser(style, iterator); | ||
console.log(output); // [['color', '#f00'], ['background', '#ba4']] | ||
} | ||
parse(style, iterator); | ||
console.log(output); // [['color', 'red'], ['background', 'blue']] | ||
``` | ||
@@ -141,13 +167,40 @@ | ||
Run tests: | ||
```sh | ||
$ npm test | ||
``` | ||
Run tests in watch mode: | ||
```sh | ||
$ npm run test:watch | ||
``` | ||
Run tests with coverage: | ||
```sh | ||
$ npm run test:coverage | ||
# npm run test:coverage:report | ||
``` | ||
Lint files: | ||
```sh | ||
$ npm run lint | ||
``` | ||
Fix lint errors: | ||
```sh | ||
$ npm run lint:fix | ||
``` | ||
## Release | ||
Only collaborators with credentials can release and publish: | ||
```sh | ||
$ npm run release | ||
$ npm publish | ||
$ git push --follow-tags | ||
$ git push --follow-tags && npm publish | ||
``` | ||
@@ -157,3 +210,3 @@ | ||
- [css](https://github.com/reworkcss/css) | ||
- [inline-style-parser](https://github.com/remarkablemark/inline-style-parser) | ||
- [Contributors](https://github.com/remarkablemark/style-to-object/graphs/contributors) | ||
@@ -160,0 +213,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28995
8
204
15
308
1
+ Addedinline-style-parser@0.1.1
+ Addedinline-style-parser@0.1.1(transitive)
- Removedcss@2.2.4
- Removedatob@2.1.2(transitive)
- Removedcss@2.2.4(transitive)
- Removeddecode-uri-component@0.2.2(transitive)
- Removedinherits@2.0.4(transitive)
- Removedresolve-url@0.2.1(transitive)
- Removedsource-map@0.6.1(transitive)
- Removedsource-map-resolve@0.5.3(transitive)
- Removedsource-map-url@0.4.1(transitive)
- Removedurix@0.1.0(transitive)