web-dev-qa-db-fra.com

Analyser CSS en JavaScript/jQuery

J'essaie d'implémenter l'analyse de CSS en JavaScript pour que:

a {
  color: red;
}

est analysé dans l'objet:

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

Tout d’abord, y at-il un JavaScript/jQuery bibliothèque je peux utiliser?

Mon implémentation est assez basique, donc je suis sûr que ce n’est en aucun cas infaillible. Par exemple, cela fonctionne bien pour CSS de base, mais pour une propriété du type:

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

Cela échoue parce que j'utilise split(';') pour séparer les paires property:value. Ici, ; apparaît dans la value, de sorte qu'il se divise également à cet endroit.

Y a-t-il une autre façon de faire cela?

Voici le 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,"");
}

Merci!

28
ankit

Il existe un analyseur CSS écrit en Javascript appelé JSCSSP

28
Matthew Manela

Vous pouvez facilement utiliser le propre CSSOM du navigateur pour analyser CSS:

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;
};

Pour chaque règle renvoyée, vous pouvez consulter les propriétés dans rule.style. Voir http://jsfiddle.net/v2JsZ/ pour un exemple.

59
cburgmer

Pour écrire l'analyseur le plus infaillible, suivez les règles exactes pour tokenization et CSS grammar telles que définies dans la spéc. Notez que vous n'avez pas à implémenter les spécifications à l'encre. Vous pouvez commencer avec les petites pièces et les CSS que vous rencontrerez le plus probablement, puis développer à partir de là. Mieux encore, ignorez tout le processus et utilisez la solution de @ Matthew, à moins qu'il ne s'agisse d'un exercice d'apprentissage.

Il existe différents scanners lexicaux et générateurs d'analyseurs disponibles pour JavaScript. Toute la grammaire est disponible sur le site Web de w3. Pourquoi refaire le travail alors que vous pouvez simplement utiliser cela et les générateurs d’analyseur pour générer l’analyseur en JavaScript.

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

Les règles de production pour CSS sont données ci-dessous.

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

Exemple simple, non testé mais devrait fonctionner, j'utilise similaire dans mon projet.

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