def test_styleSheet(self): "CSSImportRule.styleSheet" def fetcher(url): if url == "/root/level1/anything.css": return None, '@import "level2/css.css" "title2";' else: return None, 'a { color: red }' parser = cssutils.CSSParser(fetcher=fetcher) sheet = parser.parseString('''@charset "ascii"; @import "level1/anything.css" tv "title";''', href='/root/') self.assertEqual(sheet.href, '/root/') ir = sheet.cssRules[1] self.assertEqual(ir.href, 'level1/anything.css') self.assertEqual(ir.styleSheet.href, '/root/level1/anything.css') # inherits ascii as no self charset is set self.assertEqual(ir.styleSheet.encoding, 'ascii') self.assertEqual(ir.styleSheet.ownerRule, ir) self.assertEqual(ir.styleSheet.media.mediaText, 'tv') self.assertEqual(ir.styleSheet.parentStyleSheet, None) # sheet self.assertEqual(ir.styleSheet.title, 'title') self.assertEqual(ir.styleSheet.cssText, '@charset "ascii";\n@import "level2/css.css" "title2";'.encode()) ir2 = ir.styleSheet.cssRules[1] self.assertEqual(ir2.href, 'level2/css.css') self.assertEqual(ir2.styleSheet.href, '/root/level1/level2/css.css') # inherits ascii as no self charset is set self.assertEqual(ir2.styleSheet.encoding, 'ascii') self.assertEqual(ir2.styleSheet.ownerRule, ir2) self.assertEqual(ir2.styleSheet.media.mediaText, 'all') self.assertEqual(ir2.styleSheet.parentStyleSheet, None) #ir.styleSheet self.assertEqual(ir2.styleSheet.title, 'title2') self.assertEqual(ir2.styleSheet.cssText, '@charset "ascii";\na {\n color: red\n }'.encode()) sheet = cssutils.parseString('@import "CANNOT-FIND.css";') ir = sheet.cssRules[0] self.assertEqual(ir.href, "CANNOT-FIND.css") self.assertEqual(type(ir.styleSheet), cssutils.css.CSSStyleSheet) def fetcher(url): if url.endswith('level1.css'): return None, u'@charset "ascii"; @import "level2.css";'.encode() else: return None, u'a { color: red }'.encode() parser = cssutils.CSSParser(fetcher=fetcher) sheet = parser.parseString('@charset "iso-8859-1";@import "level1.css";') self.assertEqual(sheet.encoding, 'iso-8859-1') sheet = sheet.cssRules[1].styleSheet self.assertEqual(sheet.encoding, 'ascii') sheet = sheet.cssRules[1].styleSheet self.assertEqual(sheet.encoding, 'ascii')
def test_parseComments(self): "cssutils.CSSParser(parseComments=False)" css = u'/*1*/ a { color: /*2*/ red; }' p = cssutils.CSSParser(parseComments=False) self.assertEqual( p.parseString(css).cssText, u'a {\n color: red\n }'.encode()) p = cssutils.CSSParser(parseComments=True) self.assertEqual( p.parseString(css).cssText, u'/*1*/\na {\n color: /*2*/ red\n }'.encode())
def csscombine( path=None, url=None, cssText=None, href=None, sourceencoding=None, targetencoding=None, minify=True, resolveVariables=True, ): """Combine sheets referred to by @import rules in given CSS proxy sheet into a single new sheet. :returns: combined cssText, normal or minified :Parameters: `path` or `url` or `cssText` + `href` path or URL to a CSSStyleSheet or a cssText of a sheet which imports other sheets which are then combined into one sheet. `cssText` normally needs `href` to be able to resolve relative imports. `sourceencoding` = 'utf-8' explicit encoding of the source proxysheet `targetencoding` encoding of the combined stylesheet `minify` = True defines if the combined sheet should be minified, in this case comments are not parsed at all! `resolveVariables` = True defines if variables in combined sheet should be resolved """ cssutils.log.info('Combining files from %r' % url, neverraise=True) if sourceencoding is not None: cssutils.log.info('Using source encoding %r' % sourceencoding, neverraise=True) parser = cssutils.CSSParser(parseComments=not minify) if path and not cssText: src = parser.parseFile(path, encoding=sourceencoding) elif url: src = parser.parseUrl(url, encoding=sourceencoding) elif cssText: src = parser.parseString(cssText, href=href, encoding=sourceencoding) else: sys.exit('Path or URL must be given') result = cssutils.resolveImports(src) result.encoding = targetencoding cssutils.log.info('Using target encoding: %r' % targetencoding, neverraise=True) oldser = cssutils.ser cssutils.setSerializer(cssutils.serialize.CSSSerializer()) if minify: cssutils.ser.prefs.useMinified() cssutils.ser.prefs.resolveVariables = resolveVariables cssText = result.cssText cssutils.setSerializer(oldser) return cssText
def validate_dumb_css(dumb_css): # NOTE: Import here to delay-load because it's a big package. import cssutils # NOTE: Use an array here because setting to a different object # with global does not work, need "nonlocal". fetched = [] def _fetcher(url): fetched.append(url) return (None, u'') p = cssutils.CSSParser(loglevel=logging.CRITICAL, fetcher=_fetcher, raiseExceptions=True) try: sheet = p.parseString(dumb_css) except: raise forms.ValidationError('CSS parsing error: Invalid syntax') if fetched: raise forms.ValidationError( 'CSS parsing error: @import is not allowed') for rule in sheet: _validate_css_rule(rule) # Outputs the parsed/normalized version of the sheet. return sheet.cssText
def __init__(self, ua=None, log=None, defaultloglevel=logging.INFO): """ initialize a new Capture object ua init User-Agent to use for requests log supply a log object which is used instead of the default log which writes to sys.stderr defaultloglevel constant of logging package which defines the level of the default log if no explicit log given """ self._ua = ua if log: self._log = log else: self._log = logging.getLogger('CSSCapture') hdlr = logging.StreamHandler(sys.stderr) formatter = logging.Formatter('%(message)s') hdlr.setFormatter(formatter) self._log.addHandler(hdlr) self._log.setLevel(defaultloglevel) self._log.debug('Using default log') self._htmlparser = CSSCaptureHTMLParser() self._cssparser = cssutils.CSSParser(log=self._log)
def convert_many(files, options): for fname in files: target = fname.rsplit('.', 1)[0] + '.css' if fname == target: sys.stderr.write('Error: same name for ' 'source and target file "%s".' % fname) sys.exit(2) elif options.no_overwrite and os.path.exists(target): sys.stderr.write('File exists (and --no-overwrite was used) "%s".' % target) sys.exit(3) src = open(fname) try: try: converted = clevercss.convert(src.read(), fname=fname) except (ParserError, EvalException) as e: sys.stderr.write('Error in file %s: %s\n' % (fname, e)) sys.exit(1) if options.minified: css = cssutils.CSSParser().parseString(converted) cssutils.ser.prefs.useMinified() converted = css.cssText dst = open(target, 'w') try: print('Writing output to %s...' % target) dst.write(converted) finally: dst.close() finally: src.close()
def process(string, debug=False, minify=False, filt=['webkit', 'moz', 'o', 'ms'], **prefs): loglevel = 'DEBUG' if debug else 'ERROR' parser = cssutils.CSSParser(loglevel=loglevel) if minify: cssutils.ser.prefs.useMinified() else: cssutils.ser.prefs.useDefaults() # use the passed in prefs for key, value in prefs.iteritems(): if hasattr(cssutils.ser.prefs, key): cssutils.ser.prefs.__dict__[key] = value results = [] sheet = parser.parseString(string) for ruleset in sheet.cssRules: cssText = magic(ruleset, debug, minify, filt, parser) if cssText: results.append(cssText) # format with newlines based on minify joinStr = '' if minify else '\n' # Not using sheet.cssText - it's buggy: # it skips some prefixed properties. return joinStr.join(results).rstrip()
def check_css (self): """Check CSS syntax of this page (which is supposed to be CSS) with the local cssutils module.""" if not fileutil.has_module("cssutils"): return self.check_css_w3() import cssutils try: csslog = logging.getLogger('cssutils') csslog.propagate = 0 del csslog.handlers[:] handler = StoringHandler() csslog.addHandler(handler) csslog.setLevel(logging.WARN) cssparser = cssutils.CSSParser(log=csslog) cssparser.parseString(self.get_content(), href=self.url) if handler.storage: for record in handler.storage: self.add_warning(u"cssutils: %s" % record.getMessage()) else: self.add_info(u"cssutils: %s" % _("valid CSS syntax")) except Exception: # catch _all_ exceptions since we dont want third party module # errors to propagate into this library err = str(sys.exc_info()[1]) log.warn(LOG_CHECK, _("cssutils parsing caused error: %(msg)s") % {"msg": err})
def _get_css_imports_cssutils(data, inline=False): """Return all assets that are referenced in the given CSS document. The returned URLs are relative to the stylesheet's URL. Args: data: The content of the stylesheet to scan as string. inline: True if the argument is an inline HTML style attribute. """ try: import cssutils except (ImportError, re.error): # Catching re.error because cssutils in earlier releases (<= 1.0) is # broken on Python 3.5 # See https://bitbucket.org/cthedot/cssutils/issues/52 return None # We don't care about invalid CSS data, this will only litter the log # output with CSS errors parser = cssutils.CSSParser(loglevel=100, fetcher=lambda url: (None, ""), validate=False) if not inline: sheet = parser.parseString(data) return list(cssutils.getUrls(sheet)) else: urls = [] declaration = parser.parseStyle(data) # prop = background, color, margin, ... for prop in declaration: # value = red, 10px, url(foobar), ... for value in prop.propertyValue: if isinstance(value, cssutils.css.URIValue): if value.uri: urls.append(value.uri) return urls
def test_parseUrl(self): "CSSParser.parseUrl()" if mock: # parseUrl(self, href, encoding=None, media=None, title=None): parser = cssutils.CSSParser() mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(None, u'')) sheet = parser.parseUrl('http://example.com', media='tv,print', title='test') restore() #self.assertEqual(sheet, 1) self.assertEqual(sheet.href, 'http://example.com') self.assertEqual(sheet.encoding, 'utf-8') self.assertEqual(sheet.media.mediaText, 'tv, print') self.assertEqual(sheet.title, 'test') # URL and content tests tests = { # (url, content): isSheet, encoding, cssText ('', None): (False, None, None), ('1', None): (False, None, None), ('mailto:[email protected]', None): (False, None, None), ('http://example.com/x.css', None): (False, None, None), ('http://example.com/x.css', ''): (True, u'utf-8', u''), # ('http://example.com/x.css', 'a'): (True, u'utf-8', u''), # ('http://example.com/x.css', 'a {color: red}'): (True, u'utf-8', # u'a {\n color: red\n }'), # ('http://example.com/x.css', 'a {color: red}'): (True, u'utf-8', # u'a {\n color: red\n }'), # ('http://example.com/x.css', '@charset "ascii";a {color: red}'): (True, u'ascii', # u'@charset "ascii";\na {\n color: red\n }'), } override = 'iso-8859-1' overrideprefix = u'@charset "iso-8859-1";' httpencoding = None for (url, content), (isSheet, expencoding, cssText) in tests.items(): mock("cssutils.util._defaultFetcher", mock_obj=self._make_fetcher(httpencoding, content)) #parser.setFetcher(self._make_fetcher(httpencoding, content)) sheet1 = parser.parseUrl(url) sheet2 = parser.parseUrl(url, encoding=override) restore() if isSheet: self.assertEqual(sheet1.encoding, expencoding) self.assertEqual(sheet1.cssText, cssText) self.assertEqual(sheet2.encoding, override) if sheet1.cssText and sheet1.cssText.startswith('@charset'): self.assertEqual(sheet2.cssText, cssText.replace('ascii', override)) elif sheet1.cssText: self.assertEqual(sheet2.cssText, overrideprefix + '\n' + cssText) else: self.assertEqual(sheet2.cssText, overrideprefix + cssText) else: self.assertEqual(sheet1, None) self.assertEqual(sheet2, None) self.assertRaises(ValueError, parser.parseUrl, '../not-valid-in-urllib') self.assertRaises(urllib2.HTTPError, parser.parseUrl, 'http://example.com/not-present.css')
def _get_css_imports_cssutils(data, inline=False): """Return all assets that are referenced in the given CSS document. The returned URLs are relative to the stylesheet's URL. Args: data: The content of the stylesheet to scan as string. inline: True if the argument is a inline HTML style attribute. """ # We don't care about invalid CSS data, this will only litter the log # output with CSS errors parser = cssutils.CSSParser(loglevel=100, fetcher=lambda url: (None, ""), validate=False) if not inline: sheet = parser.parseString(data) return list(cssutils.getUrls(sheet)) else: urls = [] declaration = parser.parseStyle(data) # prop = background, color, margin, ... for prop in declaration: # value = red, 10px, url(foobar), ... for value in prop.propertyValue: if isinstance(value, cssutils.css.URIValue): if value.uri: urls.append(value.uri) return urls
def do_raise_p(self, tests, debug=False, raising=True): # parses with self.p and expects raise p = cssutils.CSSParser(raiseExceptions=raising) for test, expected in list(tests.items()): if debug: print('"%s"' % test) self.assertRaises(expected, p.parseString, test)
def main(): examplecss = """@charset "ascii"; @namespace PREfix "uri"; SOME > WeIrD + selector ~ used here {color: green} PREfix|name {color: green} """ import logging sheet = cssutils.CSSParser(loglevel=logging.DEBUG).parseString(examplecss) print("--- ORIGINAL ---") print(examplecss) print() print( "--- SELECTORS TO LOWER CASE (does not simply work for PREfix|name!) ---" ) sheet.cssRules[2].selectorText = sheet.cssRules[2].selectorText.lower() print( "--- CHANGE PREFIX (prefix is not really part of selectorText, URI is! ---" ) sheet.cssRules[1].prefix = 'lower-case_prefix' print() print(sheet.cssText)
def main(): argparser = argparse.ArgumentParser(description=__doc__) argparser.add_argument("csvfile", metavar="CSV-FILE", nargs=1, help="CSS file to parse") argparser.add_argument("--ignore-comments", dest="comments", action="store_false", default=True, help="Keep comments in generatd output files?") args = argparser.parse_args() style_options = STYLE_OPTIONS style_options["keepComments"] = args.comments stylesheets = [] reader = csv.reader(open(args.csvfile[0])) for line, columns in enumerate(reader): if line == 0: for column in columns: stylesheets.append(Stylesheet(column)) if line == 1: continue for stylen, column in enumerate(columns): stylesheets[stylen].blacklist.add(column) cssparser = cssutils.CSSParser() for stylesheet in stylesheets: print "Working on", stylesheet.uri css = cssparser.parseUrl(stylesheet.uri, validate=False) output = cssutils.css.CSSStyleSheet() for key, value in style_options.iteritems(): output.setSerializerPref(key, value) for rule in css: if rule.type != rule.STYLE_RULE: output.add(rule) continue selectors = cssutils.css.SelectorList( parentRule=rule.selectorList.parentRule) for selector in rule.selectorList: if selector.selectorText in stylesheet.blacklist: print "BLACKLISTED", selector.selectorText continue selectors.appendSelector(selector) if not selectors.length: continue newrule = cssutils.css.CSSStyleRule( style=rule.style, parentRule=rule.parentRule, parentStyleSheet=rule.parentStyleSheet) newrule.selectorList = selectors output.add(newrule) outputfile = os.path.basename(stylesheet.uri) print "Saving stripped stylesheet in", outputfile open(outputfile, "w").write(output.cssText)
def parseCSSfile(): print "Getting data..." parser = cssutils.CSSParser() sheet = parser.parseFile(file, 'utf-8') parseSheet(sheet) colorProcess()
def main(args=None): """ Parses given filename(s) (using optional encoding) and prints the content Redirect stdout to save CSS. Redirect stderr to save parser log infos. """ usage = """usage: %prog [options] filename1.css [filename2.css ...] [>filename_combined.css] [2>parserinfo.log] """ p = optparse.OptionParser(usage=usage) p.add_option('-e', '--encoding', action='store', dest='encoding', help='encoding of the file') p.add_option('-d', '--debug', action='store_true', dest='debug', help='activate debugging output') (options, filenames) = p.parse_args(args) if not filenames: p.error("no filename given") ## newlog = logging.getLogger('CSSPARSER') ## hdlr = logging.FileHandler('CSSPARSER.log', 'w') ## formatter = logging.Formatter('%(levelname)s\t%(message)s') ## hdlr.setFormatter(formatter) ## newlog.addHandler(hdlr) ## newlog.setLevel(logging.DEBUG) ## p = CSSParser(log=newlog, loglevel=logging.DEBUG) if options.debug: p = cssutils.CSSParser(loglevel=logging.DEBUG) else: p = cssutils.CSSParser() for filename in filenames: sys.stderr.write('=== CSS FILE: "%s" ===\n' % filename) sheet = p.parse(filename, encoding=options.encoding) print sheet.cssText print sys.stderr.write('\n')
def check_cssutils(self): """Check the CSS code by parsing it using CSSUtils module.""" if not HAS_CSSUTILS: return with css_report_handler(self, 'pocket-lint') as log: parser = cssutils.CSSParser(log=log, loglevel=logging.INFO, raiseExceptions=False) parser.parseString(self.text)
def main(): parser = OptionParser(usage="usage: %prog [options] css img") parser.add_option("-m", "--minified", action="store_true", dest="minified", help="Minifi the css.") parser.add_option("--sha1", action="store_true", dest="sha1", help=("Use sha1 insted the mtime (Most recent content " "modification)")) parser.add_option("-v", "--version", action="store_true", dest="version", help="show program's version number and exit") (options, args) = parser.parse_args() if options.version: sys.stdout.write("%s\n" % __version__) sys.exit(0) if len(args) == 0: parser.error("You must provide a css file ") elif len(args) == 1: parser.error(("You must provide the relative path between " "the css and the images.")) css_path = os.path.basename(args[0]) img_rel_path = args[1] # Configure the logger log = logging.getLogger('csscache') handler = logging.StreamHandler(sys.stderr) handler.setLevel(logging.ERROR) log.addHandler(handler) if options.minified: cssutils.ser.prefs.useMinified() # Create the parser parser = cssutils.CSSParser(log=log, raiseExceptions=True, parseComments=not options.minified, validate=False) try: # Parse the original file sheet = parser.parseFile(args[0]) except Exception, e: sys.stderr.write('Error: %s %s\n' % (css_path, e.args[0])) sys.exit(1)
def inline(tree): """ Inlines all of the styles within this stylesheet into their matching HTML elements. This modifies the original tree in-place, removing all style tags and updating the nodes. To prevent a ``<style>`` tag from being inlined, add an ``inline="false"`` attribute:: <style type="text/css" inline="false"> /* Any rules contained within this tag will not be inlined. */ </style> """ rules = {} stylesheet_parser = cssutils.CSSParser( log=logging.getLogger('%s.cssutils' % __name__)) # Get all stylesheets from the document. stylesheets = CSSSelector('style')(tree) for stylesheet in stylesheets: if stylesheet.attrib.get('inline') == 'false': del stylesheet.attrib['inline'] continue for rule in ifilter(is_style_rule, stylesheet_parser.parseString(stylesheet.text)): properties = dict([(property.name, property.value) for property in rule.style]) # XXX: This doesn't handle selectors with odd multiple whitespace. for selector in map(text_type.strip, rule.selectorText.split(',')): rule = rules.get(selector, None) if rule is None: rule = rules[selector] = Rule(selector) rule.update(properties) stylesheet.getparent().remove(stylesheet) # Collect all nodes matching our style rules. nodes = defaultdict(list) for rule in rules.values(): for node in rule.selector(tree): nodes[node].append(rule) # Apply all styles to our collected elements. for node, rules in nodes.items(): properties = Rule.combine(rules) # If this node already has a style attribute, we need to apply those # styles on top of the CSS rules from the stylesheet. style_attr = node.attrib.get('style') if style_attr is not None: properties.update(Properties.from_string(style_attr)) node.attrib['style'] = u'%s' % properties
def check_css_parsing(name, raw, line_offset=0, is_declaration=False): log = ErrorHandler(name) parser = cssutils.CSSParser(fetcher=lambda x: (None, None), log=log) if is_declaration: parser.parseStyle(raw, validate=True) else: parser.parseString(raw, validate=True) for err in log.errors: err.line += line_offset return log.errors
def _get_styles(self): """Gets all CSS content from and removes all <link rel="stylesheet"> and <style> tags concatenating into one CSS string which is then parsed with cssutils and the resulting CSSStyleSheet object set to `self.stylesheet`. """ self._get_external_styles() self._get_internal_styles() cssparser = cssutils.CSSParser(log=self.log) self.stylesheet = cssparser.parseString(self.style_string)
def all_selectors(Class, fn): """return a sorted list of selectors that occur in the stylesheet""" selectors = [] cssparser = cssutils.CSSParser(validate=False) css = cssparser.parseFile(fn) for rule in [ r for r in css.cssRules if type(r) == cssutils.css.CSSStyleRule ]: selectors += [sel.selectorText for sel in rule.selectorList] selectors = sorted(list(set(selectors))) return selectors
def parse_string (self, s): """ Parse the CSS in string. """ if self.sheet is not None: return parser = cssutils.CSSParser () self.sheet = parser.parseString (s) self.attribs.mediatype = parsers.ParserAttributes.HeaderElement ('text/css') self.unpack_media_handheld (self.sheet) self.lowercase_selectors (self.sheet)
def test_init(self): "CSSParser.__init__()" self.assertEqual(True, cssutils.log.raiseExceptions) _saved = cssutils.log.raiseExceptions # also the default: cssutils.log.raiseExceptions = True # default non raising parser p = cssutils.CSSParser() s = p.parseString('$') self.assertEqual(s.cssText, '') # explicit raiseExceptions=False p = cssutils.CSSParser(raiseExceptions=False) s = p.parseString('$') self.assertEqual(s.cssText, '') # working with sheet does raise though! self.assertRaises(xml.dom.DOMException, s.__setattr__, 'cssText', '$') # ---- # raiseExceptions=True p = cssutils.CSSParser(raiseExceptions=True) self.assertRaises(xml.dom.SyntaxErr, p.parseString, '$') # working with a sheet does raise too s = cssutils.css.CSSStyleSheet() self.assertRaises(xml.dom.DOMException, s.__setattr__, 'cssText', '$') # RESET cssutils.log.raiseExceptions cssutils.log.raiseExceptions = False s = cssutils.css.CSSStyleSheet() # does not raise! s.__setattr__('cssText', '$') self.assertEqual(s.cssText, '') # RESET cssutils.log.raiseExceptions cssutils.log.raiseExceptions = _saved
def do_equal_p(self, tests, att='cssText', debug=False, raising=True): """ if raising self.p is used for parsing, else self.pf """ p = cssutils.CSSParser(raiseExceptions=raising) # parses with self.p and checks att of result for test, expected in list(tests.items()): if debug: print('"%s"' % test) s = p.parseString(test) if expected is None: expected = test self.assertEqual(expected, str(s.__getattribute__(att), 'utf-8'))
def getStyles(self): """not fully functional""" mediaRule = 0 parser = cssutils.CSSParser() def parseSheet(sheetLocal): styleDictLocal = {} for rule in sheetLocal: if type(rule) is not cssutils.css.CSSStyleRule: continue selector = rule.selectorText styles = rule.style.cssText styleDictLocal[selector.encode('ascii', 'replace')] = styles.encode('ascii', 'replace') return styleDictLocal def expandDict(Dict): for key in Dict: newList = Dict[key].split(";\n") newDict = {} for j in newList: print j try: newKey, value = j.split(": ") except ValueError: # this one indicates some people format using ":" rather than ": " try: newKey, value = j.split(":") except ValueError: # this one indicates that on a higher level of splitting there may be # empty strings left out that can't be split continue newDict[newKey] = value Dict[key] = newDict return Dict styleList = [] for tag in self.bs.find_all('style'): styleList.append(tag.text) for i in range(len(styleList)): sheet = cssutils.parseString(styleList[i]) # try: # try: unFormatted = parseSheet(sheet) # except AttributeError: # unFormatted = parser.parseStyle(parser.cssText) # except AttributeError: # unFormatted = cssutils.css.CSSMediaRule(styleList[i]) styleDict = expandDict(unFormatted) styleList[i] = styleDict return styleList
def add_css_prefixes(css, vendor_prefix_rules): """ Adds the supplied vendor prefix rules to the given CSS """ selectors_with_vendor_prefixes = vendor_prefix_rules.keys() parser = cssutils.CSSParser(validate=False) sheet = parser.parseString(css) for rule in sheet: if not rule.type == rule.STYLE_RULE: continue if rule.selectorText not in selectors_with_vendor_prefixes: continue for property in vendor_prefix_rules[rule.selectorText]: rule.style[property.name] = property.value return sheet.cssText.decode()
def clean(self, value): clean_value = super(CSSValidatorField, self).clean(value) mylog = StringIO.StringIO() h = logging.StreamHandler(mylog) h.setFormatter(logging.Formatter('%(levelname)s %(message)s')) cssutils.log.addHandler(h) cssutils.log.setLevel(logging.INFO) parser = cssutils.CSSParser(raiseExceptions=True) try: value_parse = parser.parseString(clean_value) except SyntaxErr, e: error_message = getattr(e, 'msg', e.message) raise ValidationError( _('Syntax Error %s' % error_message.replace('\\n', '').replace('\\r', '')))
def limit_css_to_lesson_content(css): """ Returns ``css`` limited just to the ``.lesson-content`` element. This doesn't protect against malicious input. """ parser = cssutils.CSSParser(raiseExceptions=True) parsed = parser.parseString(css) for rule in parsed.cssRules: for selector in rule.selectorList: # the space is important - there's a difference between for example # ``.lesson-content:hover`` and ``.lesson-content :hover`` selector.selectorText = ".lesson-content " + selector.selectorText return parsed.cssText.decode("utf-8")
def parseCSS(text): parser = cssutils.CSSParser() css = parser.parseString(text) rules = {} for rule in css.cssRules: commas = rule.selectorText.split(',') for comma in commas: parts = comma.split() c = rules for i, part in enumerate(parts): if part in '>+': parts[i+1] = '&' + part + parts[i+1] continue c = c.setdefault(part, {}) c.setdefault(':rules:', []).append(rule) return rules