webentwicklung-frage-antwort-db.com.de

CSS in JavaScript/jQuery analysieren

Ich versuche, das Parsing von CSS in JavaScript zu implementieren, so dass:

a {
  color: red;
}

wird in das Objekt geparst:

{
  'a' {
    'color': 'red'
  }
}

Gibt es eine JavaScript/jQueryBibliothek , die ich verwenden kann?

Meine Implementierung ist ziemlich einfach, daher bin ich mir sicher, dass sie auf keinen Fall narrensicher ist. Zum Beispiel funktioniert es gut für einfaches CSS, aber für eine Eigenschaft des Typs:

background: url(data:image/png;base64, ....);

Es schlägt fehl, weil ich split(';') verwende, um property:value-Paare zu trennen. Hier kommt ; in der value vor, so dass es sich auch an diesem Punkt teilt.

Gibt es einen alternativen Weg, dies zu tun?

Hier ist der Code:

parseCSS: function(css) {
    var rules = {};
    css = this.removeComments(css);
    var blocks = css.split('}');
    blocks.pop();
    var len = blocks.length;
    for (var i = 0; i < len; i++)
    {
        var pair = blocks[i].split('{');
        rules[$.trim(pair[0])] = this.parseCSSBlock(pair[1]);
    }
    return rules;
},

parseCSSBlock: function(css) { 
    var rule = {};
    var declarations = css.split(';');
    declarations.pop();
    var len = declarations.length;
    for (var i = 0; i < len; i++)
    {
        var loc = declarations[i].indexOf(':');
        var property = $.trim(declarations[i].substring(0, loc));
        var value = $.trim(declarations[i].substring(loc + 1));

        if (property != "" && value != "")
            rule[property] = value;
    }
    return rule;
},

removeComments: function(css) {
    return css.replace(/\/\*(\r|\n|.)*\*\//g,"");
}

Vielen Dank!

28
ankit

Es gibt einen in Javascript geschriebenen CSS-Parser mit dem Namen JSCSSP

28
Matthew Manela

Sie können das eigene CSSOM des Browsers problemlos zum Parsen von CSS verwenden:

var rulesForCssText = function (styleContent) {
    var doc = document.implementation.createHTMLDocument(""),
        styleElement = document.createElement("style");

   styleElement.textContent = styleContent;
    // the style will only be parsed once it is added to a document
    doc.body.appendChild(styleElement);

    return styleElement.sheet.cssRules;
};

Für jede zurückgegebene Regel können Sie die Eigenschaften in rule.style anzeigen. Siehe http://jsfiddle.net/v2JsZ/ für ein Beispiel.

59
cburgmer

Um einen möglichst narrensicheren Parser zu schreiben, folgen Sie den genauen Regeln für tokenization und CSS Grammatik , wie in der Spezifikation definiert. Beachten Sie, dass Sie die Spezifikation nicht durch die Tinte implementieren müssen. Sie können mit kleinen Teilen und CSS beginnen, auf die Sie am wahrscheinlichsten stoßen werden, und dann von dort aus erweitern. Besser noch, überspringen Sie den gesamten Prozess und gehen Sie zu @ Matthews Lösung, es sei denn, dies ist eine Lernübung.

Für JavaScript stehen verschiedene lexikalische Scanner und Parser-Generatoren zur Verfügung. Die gesamte Grammatik ist auf der Website von w3 verfügbar. Warum die Überarbeitung, wenn Sie das und die Parser-Generatoren verwenden können, um den Parser in JavaScript zu generieren.

  1. Jison
  2. Peg.js
  3. Cruiser.Parse
  4. McLexer
  5. JS/CC

Die Produktionsregeln für CSS sind unten angegeben.

stylesheet
  : [ CHARSET_SYM STRING ';' ]?
    [S|CDO|CDC]* [ import [ CDO S* | CDC S* ]* ]*
    [ [ ruleset | media | page ] [ CDO S* | CDC S* ]* ]*
  ;
import
  : IMPORT_SYM S*
    [STRING|URI] S* media_list? ';' S*
  ;
media
  : MEDIA_SYM S* media_list LBRACE S* ruleset* '}' S*
  ;
media_list
  : medium [ COMMA S* medium]*
  ;
medium
  : IDENT S*
  ;
page
  : PAGE_SYM S* pseudo_page?
    '{' S* declaration? [ ';' S* declaration? ]* '}' S*
  ;
pseudo_page
  : ':' IDENT S*
  ;
operator
  : '/' S* | ',' S*
  ;
combinator
  : '+' S*
  | '>' S*
  ;
unary_operator
  : '-' | '+'
  ;
property
  : IDENT S*
  ;
ruleset
  : selector [ ',' S* selector ]*
    '{' S* declaration? [ ';' S* declaration? ]* '}' S*
  ;
selector
  : simple_selector [ combinator selector | S+ [ combinator? selector ]? ]?
  ;
simple_selector
  : element_name [ HASH | class | attrib | pseudo ]*
  | [ HASH | class | attrib | pseudo ]+
  ;
class
  : '.' IDENT
  ;
element_name
  : IDENT | '*'
  ;
attrib
  : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
    [ IDENT | STRING ] S* ]? ']'
  ;
pseudo
  : ':' [ IDENT | FUNCTION S* [IDENT S*]? ')' ]
  ;
declaration
  : property ':' S* expr prio?
  ;
prio
  : IMPORTANT_SYM S*
  ;
expr
  : term [ operator? term ]*
  ;
term
  : unary_operator?
    [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
      TIME S* | FREQ S* ]
  | STRING S* | IDENT S* | URI S* | hexcolor | function
  ;
function
  : FUNCTION S* expr ')' S*
  ;
/*
 * There is a constraint on the color that it must
 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
 */
hexcolor
  : HASH S*
  ;
12
Anurag

Einfaches Beispiel, nicht getestet, sollte aber funktionieren, ich verwende in meinem Projekt ähnlich.

var div = jQuery('<div/>');
div[0].style = 'position:absolute;left:5px;top:10px;'; //Css to parse

div.css('left'); // => '5px'
div.css('top'); // => '10px'
div[0].style; // => Object containing all css
0
Olexiy Zamkoviy