JAVASCRIPT   19

cssjson js

Guest on 12th August 2022 12:33:30 AM

  1. /**
  2.  * CSS-JSON Converter for JavaScript, v.2.0 By Aram Kocharyan, http://aramk.com/
  3.  * Converts CSS to JSON and back.
  4.  */
  5.  
  6. var CSSJSON = new function() {
  7.  
  8.         var base = this;
  9.  
  10.         base.init = function() {
  11.                 // String functions
  12.                 String.prototype.trim = function() {
  13.                         return this.replace(/^\s+|\s+$/g, '');
  14.                 };
  15.  
  16.                 String.prototype.repeat = function(n) {
  17.                         return new Array(1 + n).join(this);
  18.                 };
  19.         };
  20.         base.init();
  21.  
  22.         var selX = /([^\s\;\{\}][^\;\{\}]*)\{/g;
  23.         var endX = /\}/g;
  24.         var lineX = /([^\;\{\}]*)\;/g;
  25.         var commentX = /\/\*[\s\S]*?\*\//g;
  26.         var lineAttrX = /([^\:]+):([^\;]*);/;
  27.  
  28.         // This is used, a concatenation of all above. We use alternation to
  29.         // capture.
  30.         var altX = /(\/\*[\s\S]*?\*\/)|([^\s\;\{\}][^\;\{\}]*(?=\{))|(\})|([^\;\{\}]+\;(?!\s*\*\/))/gmi;
  31.  
  32.         // Capture groups
  33.         var capComment = 1;
  34.         var capSelector = 2;
  35.         var capEnd = 3;
  36.         var capAttr = 4;
  37.  
  38.         var isEmpty = function(x) {
  39.                 return typeof x == 'undefined' || x.length == 0 || x == null;
  40.         };
  41.  
  42.         /**
  43.          * Input is css string and current pos, returns JSON object
  44.          *
  45.          * @param cssString
  46.          *            The CSS string.
  47.          * @param args
  48.          *            An optional argument object. ordered: Whether order of
  49.          *            comments and other nodes should be kept in the output. This
  50.          *            will return an object where all the keys are numbers and the
  51.          *            values are objects containing "name" and "value" keys for each
  52.          *            node. comments: Whether to capture comments. split: Whether to
  53.          *            split each comma separated list of selectors.
  54.          */
  55.         base.toJSON = function(cssString, args) {
  56.                 var node = {
  57.             children: {},
  58.             attributes: {}
  59.         };
  60.                 var match = null;
  61.                 var count = 0;
  62.  
  63.                 if (typeof args == 'undefined') {
  64.                         var args = {
  65.                                 ordered : false,
  66.                                 comments : false,
  67.                 stripComments : false,
  68.                                 split : false
  69.                         };
  70.                 }
  71.         if (args.stripComments) {
  72.             args.comments = false;
  73.             cssString = cssString.replace(commentX, '');
  74.         }
  75.  
  76.                 while ((match = altX.exec(cssString)) != null) {
  77.                         if (!isEmpty(match[capComment]) && args.comments) {
  78.                                 // Comment
  79.                                 var add = match[capComment].trim();
  80.                                 node[count++] = add;
  81.                         } else if (!isEmpty(match[capSelector])) {
  82.                                 // New node, we recurse
  83.                                 var name = match[capSelector].trim();
  84.                                 // This will return when we encounter a closing brace
  85.                                 var newNode = base.toJSON(cssString, args);
  86.                                 if (args.ordered) {
  87.                                         var obj = {};
  88.                                         obj['name'] = name;
  89.                                         obj['value'] = newNode;
  90.                                         // Since we must use key as index to keep order and not
  91.                                         // name, this will differentiate between a Rule Node and an
  92.                                         // Attribute, since both contain a name and value pair.
  93.                                         obj['type'] = 'rule';
  94.                                         node[count++] = obj;
  95.                                 } else {
  96.                                         if (args.split) {
  97.                                                 var bits = name.split(',');
  98.                                         } else {
  99.                                                 var bits = [name];
  100.                                         }
  101.                     for (i in bits) {
  102.                         var sel = bits[i].trim();
  103.                         if (sel in node.children) {
  104.                             for (var att in newNode.attributes) {
  105.                                 node.children[sel].attributes[att] = newNode.attributes[att];
  106.                             }
  107.                         } else {
  108.                             node.children[sel] = newNode;
  109.                         }
  110.                     }
  111.                                 }
  112.                         } else if (!isEmpty(match[capEnd])) {
  113.                                 // Node has finished
  114.                                 return node;
  115.                         } else if (!isEmpty(match[capAttr])) {
  116.                                 var line = match[capAttr].trim();
  117.                                 var attr = lineAttrX.exec(line);
  118.                                 if (attr) {
  119.                                         // Attribute
  120.                                         var name = attr[1].trim();
  121.                                         var value = attr[2].trim();
  122.                                         if (args.ordered) {
  123.                                                 var obj = {};
  124.                                                 obj['name'] = name;
  125.                                                 obj['value'] = value;
  126.                                                 obj['type'] = 'attr';
  127.                                                 node[count++] = obj;
  128.                                         } else {
  129.                                                 node.attributes[name] = value;
  130.                                         }
  131.                                 } else {
  132.                                         // Semicolon terminated line
  133.                                         node[count++] = line;
  134.                                 }
  135.                         }
  136.                 }
  137.  
  138.                 return node;
  139.         };
  140.  
  141.         /**
  142.          * @param node
  143.          *            A JSON node.
  144.          * @param depth
  145.          *            The depth of the current node; used for indentation and
  146.          *            optional.
  147.          * @param breaks
  148.          *            Whether to add line breaks in the output.
  149.          */
  150.         base.toCSS = function(node, depth, breaks) {
  151.                 var cssString = '';
  152.                 if (typeof depth == 'undefined') {
  153.                         depth = 0;
  154.                 }
  155.                 if (typeof breaks == 'undefined') {
  156.                         breaks = false;
  157.                 }
  158.                 if (node.attributes) {
  159.                         for (i in node.attributes) {
  160.                                 cssString += strAttr(i, node.attributes[i], depth);
  161.                         }
  162.                 }
  163.                 if (node.children) {
  164.                         var first = true;
  165.                         for (i in node.children) {
  166.                                 if (breaks && !first) {
  167.                                         cssString += '\n';
  168.                                 } else {
  169.                                         first = false;
  170.                                 }
  171.                                 cssString += strNode(i, node.children[i], depth);
  172.                         }
  173.                 }
  174.                 return cssString;
  175.         };
  176.  
  177.         // Helpers
  178.  
  179.         var strAttr = function(name, value, depth) {
  180.                 return '\t'.repeat(depth) + name + ': ' + value + ';\n';
  181.         };
  182.  
  183.         var strNode = function(name, value, depth) {
  184.                 var cssString = '\t'.repeat(depth) + name + ' {\n';
  185.                 cssString += base.toCSS(value, depth + 1);
  186.                 cssString += '\t'.repeat(depth) + '}\n';
  187.                 return cssString;
  188.         };
  189.  
  190. };

Raw Paste


Login or Register to edit or fork this paste. It's free.