def __init__(self, selector): self._path = os.path.join(GLib.get_user_config_dir(), "gtk-3.0", "gtk.css") self.parser = tinycss.make_parser() self.selector = selector self.rule_separator = "/***** %s - cinnamon-settings-generated - do not edit *****/" % self.selector self.my_ruleset = None file = Gio.File.new_for_path(self._path) try: success, content_bytes, tag = file.load_contents(None) self._contents = content_bytes.decode() self.stylesheet = self.parser.parse_stylesheet(self._contents) except GLib.Error as e: if e.code == Gio.IOErrorEnum.NOT_FOUND: self._contents = "" self.stylesheet = tinycss.css21.Stylesheet(rules=[], errors=[], encoding="utf-8") else: raise PermissionError( "Could not load ~/.config/gtk-3.0/gtk.css file, check permissions" )
def get_background_color(): themes = {"default": ("#000000", "#FFFFFF")} p = theme_path() themes_list = list_themes() par = tinycss.make_parser("page3") for file in themes_list: with open("%s/%s" % (p, file), "r") as f: style = par.parse_stylesheet_file(f) i = [str(x) for x in style.rules] index = 0 for x in i: if x.endswith("CodeMirror>"): break else: index += 1 if index < len(style.rules): decs = style.rules[index].declarations background = "" text = "" for dec in decs: if dec.name == "background": background = str(dec.value.as_css()) if dec.name == "color": text = str(dec.value.as_css()) if background == "": background = "#FFFFFF" if text == "": text = "#000000" themes[file.replace(".css", "")] = (background, text) background = "" text = "" return themes
def save_custom_style(): flash(Markup('Styling updated. View your <a href="/">updated shop</a>')) return redirect(url_for('style_shop.style_shop')) # Replace jamla->theme->options->styles with new css rulesets jamla['theme']['options']['styles'] = [] # Clear existing styles css = request.form['css'] parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet(css) # Parse each rule, get its rulesets, declarations and save to jamla styles = [] for ruleSet in stylesheet.rules: selector = ruleSet.selector.as_css() # Add selector to draftJamla rules = [] for rule in ruleSet.declarations: cssProperty = rule.name propertyValue = rule.value.as_css() rules.append({cssProperty: propertyValue}) styles.append({'selector': selector, 'rules': rules}) # Append each style for style in styles: jamla['theme']['options']['styles'].append(style) fp = open(current_app.config["JAMLA_PATH"], "w") yaml.safe_dump(jamla, fp, default_flow_style=False) flash(Markup('Styling updated. View your <a href="/">updated shop</a>')) return redirect(url_for('style_shop.style_shop'))
def genUsedNamesDictionary(data): propCountDictionary={} parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet_bytes(data) for rle in stylesheet.rules: if not hasattr(rle, 'declarations'): continue for prop in rle.declarations: #print prop.name if prop.name in propCountDictionary: propCountDictionary[prop.name] += 1 else: propCountDictionary[prop.name] = 1 valsDict = sorted(propCountDictionary.iteritems(), key=operator.itemgetter(1), reverse=True) sortedVals = [] for k,v in valsDict: #print k sortedVals.append(k) return sortedVals
def _find_css_problems(self, sheets): issues_json = [] try: parser = tinycss.make_parser() for key, value in sheets.iteritems(): parsed_sheet = parser.parse_stylesheet_bytes(value.encode('utf8')) for rule in parsed_sheet.rules: look_for_decl = [] # process_rule will go through rule.declarations and fill look_for_decl with a list of potential problems self._process_rule(rule, look_for_decl) # having gone through all declarations in the rule, we now have a list of # "equivalent" rule names or name:value sets - so we go through the declarations # again - and check if the "equivalents" are present look_for_decl[:] = [x for x in look_for_decl if not self._found_in_rule(rule, x)] # replace list by return of list comprehension # the idea is that if all "problems" had equivalents present, # the look_for_decl list will now be empty for issue in look_for_decl: dec = issue["dec"]; name = dec.name if '-webkit-' in name: name = name[8:] if name in LOG_CSS_PROPS or re.search(LOG_CSS_VALUES, dec.value.as_css()): issues_json.append({"file": key, "selector": issue["sel"], "property":dec.name, "value":dec.value.as_css()}) else: print('ignored %s ' % dec.name) except Exception, e: print e return ["ERROR PARSING CSS"]
def _remove_css_definitions(css, defs): selector_decl_map = {} # Map the selector to the declaration to remove for d in defs: parts = d.split('|') selector_decl_map[parts[0]] = parts[1] parser = tinycss.make_parser('page3') sheet = parser.parse_stylesheet(css) remove_lines = [] for rule in sheet.rules: css_rule = ' '.join(rule.selector.as_css().split('\n')) if not (css_rule in selector_decl_map): continue # Grab the decl to remove remove_decl = selector_decl_map[css_rule] # Grab the decls for this rule decls = rule.declarations for d in decls: if d.name == remove_decl: remove_lines.append(d.line) css_lines = css.splitlines() for line in remove_lines: del css_lines[line-1] return '\n'.join(css_lines)
def parseCSS(file): parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet_file(file); global prefix global fontName first = True content = False for rule in stylesheet.rules: # get raw glyph and name glyph = rule.declarations name = rule.selector.as_css().split(':', 1)[0].replace('.', '') if first == True: fontName = glyph[0].value.as_css().replace('\'', '').replace('"', '') # set fontName first = False else: if prefix == '': # we dont have the prefix yet tmp = rule.selector.as_css().split('-', 1)[0].replace('.', '') if tmp[0] != '[' and tmp != '': prefix = tmp # set the prefix we are looking for if (glyph[0].value.as_css()[1] == '\\'): content = True # font selector with needed content appeared if content == True: glyph = glyph[0].value.as_css().replace('"', '') glyphs.append(glyph.lower()) # set a glyph in glyphs if name[0] != '[': names.append(name.lower()) # set a name in names
def load_module(self, name): if name in sys.modules: return sys.modules[name] mod = imp.new_module(name) mod.__file__ = self.css_path mod.__loader__ = self #decoder = json.JSONDecoder(object_hook=DottedDict) parser = tinycss.make_parser('page3') try: stylesheet = parser.parse_stylesheet_file(self.css_path) except: raise ImportError( 'Could not open file.') b = {} #import pdb; pdb.set_trace() for i in stylesheet.rules: b[i.selector.as_css()] = i.declarations mod.__dict__.update(b) sys.modules[name] = mod return mod
def load_module(self, name): if name in sys.modules: return sys.modules[name] mod = imp.new_module(name) mod.__file__ = self.css_path mod.__loader__ = self #decoder = json.JSONDecoder(object_hook=DottedDict) parser = tinycss.make_parser('page3') try: stylesheet = parser.parse_stylesheet_file(self.css_path) except: raise ImportError('Could not open file.') b = {} #import pdb; pdb.set_trace() for i in stylesheet.rules: b[i.selector.as_css()] = i.declarations mod.__dict__.update(b) sys.modules[name] = mod return mod
def __init__(self, filename, font_class_prefix): import tinycss global icons new_icons = {} parser = tinycss.make_parser("page3") stylesheet = parser.parse_stylesheet_file(filename) is_icon = re.compile(u("\.%s(.*):before,?" % font_class_prefix)) for rule in stylesheet.rules: selector = rule.selector.as_css() for match in is_icon.finditer(selector): name = match.groups()[0] for declaration in rule.declarations: if declaration.name == u"content": val = declaration.value.as_css() if val.startswith('"') and val.endswith('"'): val = val[1:-1] try: new_icons[name] = uchr(int(val[1:], 16)) except UnicodeEncodeError: new_icons[name] = val[1:] except ValueError: new_icons[name] = u(val[1:]) except: pass icons = new_icons
def extract(self, node): textfield = ''.join(map(filter_non_ascii, node.text)) textfield_as_list = textfield.split('\n') ss_offset = 0 # sets textfield to the text in the style tag, if exists and adjusts the offset if BeautifulSoup(textfield).style: ss_offset = textfield.find("<style>") + len("<style>") textfield = ''.join(map(filter_non_ascii, BeautifulSoup(textfield).style.text)) textfield_as_list = textfield.split('\n') # parses textfield as a stylesheet parser = tinycss.make_parser() stylesheet = parser.parse_stylesheet(textfield) valid_regions = [] # calculate the start index of the selector for rule in stylesheet.rules: sel = rule.selector ss_start = ss_offset if sel.line > 1: for l in xrange(sel.line - 1): # add 1 to account for newline characters ss_start += len(textfield_as_list[l]) + 1 ss_start += sel.column - 1 sel = rule.selector.as_css() if rule.declarations: valid_regions.append(Region(node, ss_start, ss_start + len(sel) - 1, sel)) # check if the regions found contain valid selectors for region in valid_regions: if not is_selector(region.string): valid_regions.remove(region) return valid_regions
def retrieve_css_content(css_destination, url_path, destination_dir, base_url): style = css_destination.read_text() stylesheet = tinycss.make_parser().parse_stylesheet(style) # print(stylesheet) for rule in stylesheet.rules: # print(rule, dir(rule)) # print(type(rule)) if isinstance(rule, tinycss.css21.ImportRule): print("TODO ImportRule") print(rule) continue for decl in rule.declarations: # print(dir(decl)) value = decl.value for token in value: # if token.type not in ('IDENT', 'PERCENTAGE', 'DIMENSION', 'S', 'INTEGER', 'HASH', 'STRING', 'DELIM'): if token.type == 'URI': # print(token.type, token) if hasattr(token, 'value'): # print(css_destination) # print(css_destination.parent) # print(token.value) destination = css_destination.parent.joinpath( token.value) #.resolve() zdroj = Path(url_path.lstrip('/')).parent.joinpath( token.value) #.resolve() zdroj = urljoin(base_url, str(zdroj)) # print(zdroj, destination) _retrieve(zdroj, destination)
def _find_css_problems(self, sheets): issues = [] try: parser = tinycss.make_parser() for key, value in sheets.iteritems(): parsed_sheet = parser.parse_stylesheet_bytes(value.encode('utf8')) for rule in parsed_sheet.rules: look_for_decl = [] # process_rule will go through rule.declarations and fill look_for_decl with a list of potential problems self._process_rule(rule, look_for_decl) # having gone through all declarations in the rule, we now have a list of # "equivalent" rule names or name:value sets - so we go through the declarations # again - and check if the "equivalents" are present look_for_decl[:] = [x for x in look_for_decl if not self._found_in_rule(rule, x)] # replace list by return of list comprehension # the idea is that if all "problems" had equivalents present, # the look_for_decl list will now be empty for issue in look_for_decl: dec = issue["dec"]; issues.append(dec.name + ' used without equivalents for '+issue["sel"]+' in ' + key + ':' + str(dec.line) + ':' + str(dec.column) + ', value: ' + dec.value.as_css()) except Exception, e: print e return ["ERROR PARSING CSS"]
def _parse_self(self) -> None: """ Parse this css document and get the colors defined in it. :return: None """ parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet_file(self._file_path) for rule in stylesheet.rules: if rule.selector.as_css().startswith('.'): if len(rule.declarations) == 2: dec_names = [] dec_color = None for declaration in rule.declarations: dec_names.append(declaration.name) if declaration.name == 'color': dec_color = webcolors.hex_to_rgb( declaration.value.as_css()) # This means we have a text color declaration if dec_names == ['color', 'display']: color = Colour(dec_color.red, dec_color.green, dec_color.blue) if color == Colour(0, 0, 255, 255): raise WrongFormatException( Strings.exception_reserved_blue + ': ' + str(color)) self._str_to_color_dict[rule.selector.as_css().lstrip( '.')] = color
def css_parse(text_or_node): parser = tinycss.make_parser('page3') css = parser.parse_stylesheet(html_cast_text(text_or_node)) if len(css.errors) == 0: return (css, tuple()) return (None, ('Line: {:d} Character: {:d} Error: {}'.format( e.line, e.column, e.reason) for e in css.errors))
def rewrite_css(self, base_url, css, append_line=None): _css_base_url = base_url.replace(os.path.basename(base_url), '') parser = tinycss.make_parser() css_columns = css.split("\n") count_replaced = 0 for rule in parser.parse_stylesheet(css).rules: if hasattr(rule, 'uri') and hasattr(rule, 'at_keyword'): if rule.at_keyword == "@import": logging.debug("Found import rule in css %s" % rule.uri) if not rule.uri.startswith('http://') or rule.uri.startswith('https://'): url2 = _css_base_url + rule.uri else: url2 = tok.value if append_line: url2 = append_line + url2 css_columns[rule.line - 1] = css_columns[rule.line - 1].replace(rule.uri, url2) logging.debug("rewrote %r => %r at line %s" % (rule.uri, url2, rule.line)) count_replaced += 1 elif hasattr(rule, 'declarations'): for declaration in rule.declarations: for tok in declaration.value: if tok.type == 'URI' and not tok.value.startswith("data:image"): logging.debug("Found uri rule in css %s" % tok.value) if not tok.value.startswith('http://') or tok.value.startswith('https://'): url2 = urlparse.urljoin(base_url, tok.value) else: url2 = tok.value if append_line: url2 = append_line + url2 css_columns[tok.line - 1] = css_columns[tok.line - 1].replace(tok.value, url2) logging.debug("rewrote %r => %r at line %s" % (tok.value, url2, rule.line)) count_replaced += 1 logging.debug("%s css rules replaced in %s" % (count_replaced, base_url)) return '\n'.join(css_columns)
def parse_bootstrap(bootstrap_url): parser = tinycss.make_parser('page3') global parsed_bootstrap with urllib.request.urlopen(bootstrap_url) as url: parsed_bootstrap = parser.parse_stylesheet_bytes(url.read()) cherrypy.log("parsed bootstrap {} from {}".format( bootstrap_url, str(parsed_bootstrap)))
def parseCSS(file): parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet_file(file) global prefix global fontName first = True content = False for rule in stylesheet.rules: # get raw glyph and name glyph = rule.declarations name = rule.selector.as_css().split(':', 1)[0].replace('.', '') if first == True: fontName = glyph[0].value.as_css().replace('\'', '').replace( '"', '') # set fontName first = False else: if prefix == '': # we dont have the prefix yet tmp = rule.selector.as_css().split('-', 1)[0].replace('.', '') if tmp[0] != '[' and tmp != '': prefix = tmp # set the prefix we are looking for if (glyph[0].value.as_css()[1] == '\\'): content = True # font selector with needed content appeared if content == True: glyph = glyph[0].value.as_css().replace('"', '') glyphs.append(glyph.lower()) # set a glyph in glyphs if name[0] != '[': names.append(name.lower()) # set a name in names
def _remove_css_definitions(css, defs): selector_decl_map = {} # Map the selector to the declaration to remove for d in defs: parts = d.split('|') selector_decl_map[parts[0]] = parts[1] parser = tinycss.make_parser('page3') sheet = parser.parse_stylesheet(css) remove_lines = [] for rule in sheet.rules: css_rule = ' '.join(rule.selector.as_css().split('\n')) if not (css_rule in selector_decl_map): continue # Grab the decl to remove remove_decl = selector_decl_map[css_rule] # Grab the decls for this rule decls = rule.declarations for d in decls: if d.name == remove_decl: remove_lines.append(d.line) css_lines = css.splitlines() for line in remove_lines: del css_lines[line - 1] return '\n'.join(css_lines)
def get_css(self, soup): css_parts = [tag for tag in soup.select('style[type="text/css"]') if isinstance(tag, bs4.Tag)] big_css = max(css_parts, key=lambda x: len(x.text)) style_rules = tinycss.make_parser().parse_stylesheet(big_css.string, encoding="utf8").rules style_dict = OrderedDict(self.css_rule2entry(rule) for rule in style_rules) if None in style_dict: del style_dict[None] return style_dict
def find_hidden_style_element(content, element): """ parse the CSS in style beacons :param content: the content of the style beacon :param element: element need to find in the page :return: list of factors elements find """ visibility = { "display": "none", "visibility": "hidden", "border-style": "none" } position = {"position": "absolute"} location = {"left": "-", "right": "-", "top": "-"} pos = False result = [] json_keys = [] css_dct = {} a = ">" b = "</style>" # remove all occurrences streamed comments (/*COMMENT */) from string content = re.sub(re.compile("/\*.*?\*/", re.DOTALL), "", content) begin = content.find(a) + len(a) end = content.find(b) content_without_style = content[begin:end] stylesheet = tinycss.make_parser().parse_stylesheet(content_without_style) for rule in stylesheet.rules: selector = rule.selector.as_css() dct_style = {} for d in rule.declarations: value = "" for v in d.value: value = value + v.as_css() dct_style[d.name] = value css_dct[selector] = dct_style j = json.dumps(css_dct) json_data = json.loads(j) for json_key, json_val in json_data.items(): json_keys.append(json_key) if element in json_key: for element_key, element_val in visibility.items(): for find_key, find_val in json_data[json_key].items(): if element_key in find_key and element_val in find_val: if json_key not in json_keys: result.append("hidden") for position_key, position_val in position.items(): for find_key, find_val in json_data[json_key].items(): if position_key in find_key and position_val in find_val: pos = True if pos: for element_key, element_val in location.items(): for find_key, find_val in json_data[json_key].items(): if element_key in find_key and element_val in find_val: if json_key not in json_keys: result.append("position") return result
def process_css_file(file_path): parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet_file(file_path) css_blocks = [] for rule in stylesheet.rules: css_block = CSSBlock(rule.selector, rule.declarations) css_blocks.append(css_block) return css_blocks
def get_parsed_sheet(self): source = self.get_latest_source() if not hasattr(self, 'sheet'): if self.inline is True: source = self.extract_inline_source() parser = tinycss.make_parser() sheet = parser.parse_stylesheet(source) self.sheet = sheet return self.sheet
def __init__(self, settings): conn = httplib.HTTPConnection('goodgame.ru') conn.request('GET', '/css/compiled/chat.css') response = conn.getresponse() parser = tinycss.make_parser('page3') self.css = parser.parse_stylesheet(response.read()) self.smiles = {} self.imgs = {}
def css_style(self): ''' `css_style` returns a tinycss's set of tokens based on style text from .design file. ''' if not self._css_style: self._css_style = tinycss.make_parser().parse_stylesheet(self._xml_design_style.text) return self._css_style
def css(self): pq = PyQuery(self.tender_src) for style in pq('link[rel="stylesheet"]'): href = style.get('href') if href and href.startswith('/'): resp = self.client.get(href) if resp.status_code == 200: css = resp.content self.csses.extend(tinycss.make_parser(CSSFontfaceParser).parse_stylesheet(unicode(css)).rules)
def parseFile(self): parser = tinycss.make_parser() stylesheet = parser.parse_stylesheet_file(self.filename) self.basicDict = {rule.selector.as_css():{declaration.name:declaration.value.as_css() for declaration in rule.declarations } for rule in stylesheet.rules} try: self.dict = {removeHashesAndDots(rule.selector.as_css()):{declaration.name:makeFloatsOutOfPercentages(declaration.value.as_css()) for declaration in rule.declarations } for rule in stylesheet.rules} except Exception, e: warn( "problem with submethod, only generating basicDict") raise e
def style_parse(self, response): ''' css parser to extract import css and image ''' url = response.url content = response.text resource = ResourceItem() resource['url'] = url resource['content'] = content resource['rtype'] = 'asset' resource['location'] = self.site_url # resource['encoding'] = response.get('encoding') record = self.get_record(url) should_update = self.should_update(record) if not self.debug and should_update: yield resource print '*' * 40 print '(url,type)', resource['url'], resource['rtype'] # last_update = datetime.date.today() # self.save_record(response.url,{'url':resource['url'],'type':resource['rtype']}) stylesheet = tinycss.make_parser().parse_stylesheet(content) for item in stylesheet.rules: if isinstance(item, tinycss.css21.ImportRule): uri = item.uri http_url = self.gen_http_url(url, uri, None) if http_url: record = self.get_record(http_url) should_crawl = self.should_crawl(record) request = scrapy.Request(http_url, self.style_parse, errback=self.errback_httpbin) if should_crawl: yield request elif hasattr(item, 'declarations'): for decl in getattr(item, 'declarations'): for decl_val in getattr(decl, 'value'): if getattr(decl_val, 'type') == u'URI': uri = getattr(decl_val, 'value') image_url = self.gen_http_url(url, uri, None) if image_url: record = self.get_record(image_url) should_crawl = self.should_crawl(record) request = scrapy.Request( image_url, self.assets_parse, errback=self.errback_httpbin) if should_crawl: yield request
def find_hidden_element(url, element): """ parse the CSS page :param url: url of the css page :param element: element need to find in the page :return: list of factors elements find """ visibility = { "display": "none", "visibility": "hidden", "border-style": "none" } position = {"position": "absolute"} location = {"left": "-", "right": "-", "top": "-"} pos = False result = [] hidden = [] css_dct = {} request = requests.get(url).content.decode("utf-8") stylesheet = tinycss.make_parser().parse_stylesheet(request) for rule in stylesheet.rules: try: selector = rule.selector.as_css() except AttributeError: for i in rule.rules: stylesheet.rules.append(i) selector = None if selector: dct_style = {} for d in rule.declarations: value = "" for v in d.value: value = value + v.as_css() dct_style[d.name] = value css_dct[selector] = dct_style j = json.dumps(css_dct) json_data = json.loads(j) for json_key, json_val in json_data.items(): if element in json_key: for element_key, element_val in visibility.items(): for find_key, find_val in json_data[json_key].items(): if element_key in find_key and element_val in find_val: hidden.append(element_val) for position_key, position_val in position.items(): for find_key, find_val in json_data[json_key].items(): if position_key in find_key and position_val in find_val: pos = True if pos: for element_key, element_val in location.items(): for find_key, find_val in json_data[json_key].items(): if element_key in find_key and element_val in find_val: result.append("position") if hidden: result.append("hidden") return result
def parse_css(): parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet_file(CSS_FILENAME) for rule in stylesheet.rules: if isinstance(rule, tinycss.css21.RuleSet): names = re.findall(r'\.(fa\-[\w\-]+):before\b', rule.selector.as_css()) for decl in rule.declarations: if decl.name == 'content': content_ord = int(decl.value.as_css()[2:-1], 16) for iconname in names: yield iconname, content_ord
def _parseTechFile(self, fileName): """ Reads in a css techfile and builds necessary device map & default styles. Parameters ---------- fileName : string location of techfile Returns ------- out : [defaultAttribs, deviceMap] List of two dictionaries. First describing default attributes, second linking tag names to the function meant to build them. """ cssparser = tinycss.make_parser() stylesheet = cssparser.parse_stylesheet_file(fileName) ## Never modifying globals, just using to link text names to objects globs = globals() deviceMap = {} defaultAttribs = {} for rule in stylesheet.rules: # skip at rules if rule.at_keyword != None: continue # Grab the tag and declarations thisTag = rule.selector[0] thisDecl = self._declaration2dict(rule.declarations) # In the declarations, we require a 'libname' and 'devname' try: thisLib = thisDecl['libname'] thisDev = thisDecl['devname'] except: raise Exception( "FATAL: techfile is malformed at line " + str(rule.line) ) # Use these properties to map the tag to a builder function deviceMap[thisTag.value] = getattr(getattr(self,thisLib),thisDev) thisDecl.pop('libname') thisDecl.pop('devname') # Deal with the other declarations defaultAttribs[thisTag.value] = thisDecl return [defaultAttribs, deviceMap]
def isCSS(txt): # {{{ if isJSON(txt) or isJavaScript(txt) or isFlash(txt) or isHTML(txt): return False try: parser = tinycss.make_parser() res = parser.parse_stylesheet_bytes(txt) if len(res.rules) > len(res.errors) and len(res.rules) > 5: return True except: pass return False
def __init__(self): self._path = os.path.join(GLib.get_user_config_dir(), "gtk-3.0", "gtk.css") self.parser = tinycss.make_parser() try: self.stylesheet = self.parser.parse_stylesheet_file(self._path) except FileNotFoundError: self.stylesheet = tinycss.css21.Stylesheet(rules=[], errors=[], encoding="utf-8")
def find_stylesheets_rules(tree, stylesheet, url): """Find the rules in a stylesheet.""" for rule in stylesheet.rules: if isinstance(rule, tinycss.css21.ImportRule): css_url = parse_url(rule.uri, url) stylesheet = tinycss.make_parser().parse_stylesheet( tree.fetch_url(css_url, 'text/css').decode('utf-8')) for rule in find_stylesheets_rules(tree, stylesheet, css_url.geturl()): yield rule if not rule.at_keyword: yield rule
def find_stylesheets(tree): """Find the stylesheets included in ``tree``.""" # TODO: support contentStyleType on <svg> default_type = "text/css" for element in tree.iter(): # http://www.w3.org/TR/SVG/styling.html#StyleElement if (element.tag == "style" and element.get("type", default_type) == "text/css"): # TODO: pass href for relative URLs # TODO: support media types # TODO: what if <style> has children elements? yield tinycss.make_parser().parse_stylesheet(element.text)
def validateCSS(self, text): ''' # Detect if all texts are CSS ''' try: stylesheet = tinycss.make_parser().parse_stylesheet(text) if len(stylesheet.rules) > 0 and len(stylesheet.errors) == 0: return True except Exception as e: #print('Invalid css. ') pass return False
def test_make_parser(): class MyParser(object): def __init__(self, some_config): self.some_config = some_config parsers = [ make_parser(), make_parser('page3'), make_parser(CSSPage3Parser), make_parser(MyParser, some_config=42), make_parser(CSSPage3Parser, MyParser, some_config=42), make_parser(MyParser, 'page3', some_config=42), ] for parser, exp in zip(parsers, [False, True, True, False, True, True]): assert isinstance(parser, CSSPage3Parser) == exp for parser, exp in zip(parsers, [False, False, False, True, True, True]): assert isinstance(parser, MyParser) == exp for parser in parsers[3:]: assert parser.some_config == 42 # Extra or missing named parameters raises(TypeError, make_parser, some_config=4) raises(TypeError, make_parser, 'page3', some_config=4) raises(TypeError, make_parser, MyParser) raises(TypeError, make_parser, MyParser, some_config=4, other_config=7)
def _parse_css(self, data): cssparser = tinycss.make_parser('page3') css = cssparser.parse_stylesheet(data) if not css: return None re_emote = re.compile( 'a\[href[|^$]?=["\']/([\w:]+)["\']\](:hover)?(\sem|\sstrong)?') emotes_staging = defaultdict(dict) for rule in css.rules: if re_emote.match(rule.selector.as_css()): for match in re_emote.finditer(rule.selector.as_css()): rules = {} for declaration in rule.declarations: if match.group(3): name = match.group( 3).strip() + '-' + declaration.name rules[name] = declaration.value.as_css() emotes_staging[match.group(1)].update(rules) elif declaration.name in [ 'text-align', 'line-height', 'color' ] or declaration.name.startswith( 'font') or declaration.name.startswith('text'): name = 'text-' + declaration.name rules[name] = declaration.value.as_css() emotes_staging[match.group(1)].update(rules) elif declaration.name in [ 'width', 'height', 'background-image', 'background-position', 'background', 'background-size', ]: name = declaration.name if name == 'background-position': val = [ '{}{}'.format(v.value, v.unit if v.unit else '') for v in declaration.value if v.value != ' ' ] else: val = declaration.value[0].value if match.group(2): name = 'hover-' + name rules[name] = val emotes_staging[match.group(1)].update(rules) return emotes_staging
def find_stylesheets(tree, url): """Find the stylesheets included in ``tree``.""" # TODO: support contentStyleType on <svg> default_type = 'text/css' process = tree.getprevious() while process is not None: if (getattr(process, 'target', None) == 'xml-stylesheet' and process.attrib.get('type', default_type) == 'text/css'): href = parse_url(process.attrib.get('href'), url) if href: yield tinycss.make_parser().parse_stylesheet_bytes( read_url(href)) process = process.getprevious() for element in tree.iter(): # http://www.w3.org/TR/SVG/styling.html#StyleElement if (element.tag == 'style' and element.get('type', default_type) == 'text/css' and element.text): # TODO: pass href for relative URLs # TODO: support media types # TODO: what if <style> has children elements? yield tinycss.make_parser().parse_stylesheet(element.text)
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() for style_string in self.extra_style_strings: self.style_string += style_string import tinycss cssparser = tinycss.make_parser() self.stylesheet = cssparser.parse_stylesheet(self.style_string)
def get_image_url_from_style(style: str): css = make_parser() value = None for declaration in css.parse_style_attr(style)[0]: if declaration.name == 'background': for token in declaration.value: if token.type == 'URI': value = token.value break if declaration.name == 'background-image': value = declaration.value[0].value break return value
def parse_style(element): parser = tinycss.make_parser('page3') contents = element.childNodes[0].nodeValue if isinstance(contents, str): contents = contents.encode('utf-8') stylesheet = parser.parse_stylesheet_bytes(contents) rules = {} for rule in stylesheet.rules: _decs = {} for dec in rule.declarations: _decs[dec.name] = dec.value[0].value rules["{}{}".format(*[d.value for d in rule.selector[0:2]])] = _decs return rules
def inline_css(html, css, strip_unsupported_css=True, remove_classes=False, pretty_print=True): """Produces html output with css styles inlined. :param html: the original html :param css: the css rules to apply to the html :param strip_unsupported_css: a flag for stripping invalid email css :param remove_classes: a flag for stripping class attributes from the output :param pretty_print: toggle pretty printing of resulting html """ node_declarations = {} try: dom = etree.fromstring(html) except etree.XMLSyntaxError: # fall back on the soup parser if we don't have valid XML dom = soupparser.fromstring(html) css_rules = tinycss.make_parser().parse_stylesheet(css).rules for rule in css_rules: css_selector = rule.selector.as_css() for node in CSSSelector(css_selector)(dom): for declaration in rule.declarations: if strip_unsupported_css and get_clients_without_support( declaration): # skip invalid rules continue declaration.specificity = _selector_specificity( css_selector, declaration.priority) node_declarations.setdefault(node, {}) active_declaration = node_declarations[node].get( declaration.name) if active_declaration and active_declaration.specificity > declaration.specificity: # skip rules with lower specificity continue node_declarations[node][declaration.name] = declaration for node, declarations in node_declarations.items(): inline_styles = node.get('style', '') inline_css = _get_node_style(declarations, inline_styles) node.set('style', inline_css) if remove_classes and "class" in node.attrib: node.attrib.pop('class') res = etree.tostring(dom, pretty_print=pretty_print) return res.decode("utf-8")
def gen(axure_folder, key, output): if not axure_folder.endswith(path.sep): axure_folder = axure_folder + path.sep css_path = axure_folder + key + "_files/axurerp_pagespecificstyles.css" html_path = axure_folder + key + ".html" parser = tinycss.make_parser('page3') css = parser.parse_stylesheet_file(css_path) rd = get_ruledict(css.rules) soup = BeautifulSoup(open(html_path)) text_dict = {} for i in range(1, len(rd)): node_id = 'u%d' % i nodes = soup.find_all(id = node_id) if len(nodes) == 1: key = nodes[0].get_text().encode("utf-8").strip() key = key.replace(" ", "").replace("*", "").replace("c2a0".decode("hex"), "") if len(key) < 2 or "\n" in key[:-1]: continue text_dict[key] = node_id rows = {} data = {} for text in text_dict.keys(): key = text_dict[text] if rd.has_key(key): size = rd[key] rows[text] = size.top + float(size.left) / (len(str(size.left)) * 10) data[text] = size top = 0 result = "" for w in sorted(rows, key=rows.get): size = data[w] if size.top - top > 10: if top > 0: result += "\n" top = size.top else: result += "\t" result += w f = file(output, "w+") f.write(result) f.close() return result
def getSheetCellStyles(page): parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet_file(page) container_tokens = {} rules = {} edge_code = {'top': 'T', 'right': 'R', 'bottom': 'B', 'left': 'L'} for rule in stylesheet.rules: ident_tokens = [ token for token in rule.selector if token.type == 'IDENT' ] if ident_tokens[0].value == u'tblGenFixed': # print 'Ident {} {}'.format(ident_tokens[0].value, ident_tokens[2].value) got = False rule_id = ident_tokens[2].value temp = {'T': '', 'R': '', 'B': '', 'L': ''} for declaration in rule.declarations: if declaration.name.startswith('border'): style = [ attribute.value for attribute in declaration.value if attribute.type == 'IDENT' ][0] color = [ attribute.value for attribute in declaration.value if attribute.type == 'HASH' ][0] thickness = [ attribute.value for attribute in declaration.value if attribute.type == 'DIMENSION' ][0] # print 'Style {} is {} {} {} {}'.format(rule_id, declaration.name, thickness, style, color) if style != 'solid' or color != '#CCC': got = True edge = edge_code[declaration.name[7:]] temp[edge] = {} temp[edge]['type'] = style temp[edge]['color'] = color temp[edge]['thickness'] = str(thickness) if got: rules[rule_id] = temp # for key, rule in rules.items() : # print 'Rule {} is {}'.format(key, rule) return rules
def find_stylesheets_rules(stylesheet, url): """Find the rules in a stylesheet.""" for rule in stylesheet.rules: if isinstance(rule, tinycss.css21.ImportRule): css_path = os.path.normpath( os.path.join(os.path.dirname(url), rule.uri)) if not os.path.exists(css_path): continue with open(css_path) as f: stylesheet = tinycss.make_parser().parse_stylesheet(f.read()) for rule in find_stylesheets_rules(stylesheet, css_path): yield rule if not rule.at_keyword: yield rule
def load_css(self): """ Creates a dict of all icons available in CSS file, and finds out what's their common prefix. :returns sorted icons dict, common icon prefix """ icons = dict() common_prefix = None parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet_file(self.css_file) is_icon = re.compile("\.(.*):before,?") for rule in stylesheet.rules: selector = rule.selector.as_css() # Skip CSS classes that are not icons if not is_icon.match(selector): continue # Find out what the common prefix is if common_prefix is None: common_prefix = selector[1:] else: common_prefix = os.path.commonprefix( (common_prefix, selector[1:])) for match in is_icon.finditer(selector): name = match.groups()[0] for declaration in rule.declarations: if declaration.name == "content": val = declaration.value.as_css() # Strip quotation marks if re.match("^['\"].*['\"]$", val): val = val[1:-1] icons[name] = unichr(int(val[1:], 16)) common_prefix = common_prefix or '' # Remove common prefix if not self.keep_prefix and len(common_prefix) > 0: non_prefixed_icons = {} for name in icons.keys(): non_prefixed_icons[name[len(common_prefix):]] = icons[name] icons = non_prefixed_icons sorted_icons = OrderedDict(sorted(icons.items(), key=lambda t: t[0])) return sorted_icons, common_prefix
def find_stylesheets_rules(stylesheet, url): """Find the rules in a stylesheet.""" for rule in stylesheet.rules: if isinstance(rule, tinycss.css21.ImportRule): css_path = os.path.normpath( os.path.join(os.path.dirname(url or ''), rule.uri)) if not os.path.exists(css_path): continue with open(css_path) as f: stylesheet = tinycss.make_parser().parse_stylesheet(f.read()) for rule in find_stylesheets_rules(stylesheet, css_path): yield rule if not rule.at_keyword: yield rule
def load_css(self): """ Creates a dict of all icons available in CSS file, and finds out what's their common prefix. :returns sorted icons dict, common icon prefix """ icons = dict() common_prefix = None parser = tinycss.make_parser('page3') stylesheet = parser.parse_stylesheet_file(self.css_file) is_icon = re.compile("\.(.*):before,?") for rule in stylesheet.rules: selector = rule.selector.as_css() # Skip CSS classes that are not icons if not is_icon.match(selector): continue # Find out what the common prefix is if common_prefix is None: common_prefix = selector[1:] else: common_prefix = os.path.commonprefix((common_prefix, selector[1:])) for match in is_icon.finditer(selector): name = match.groups()[0] for declaration in rule.declarations: if declaration.name == "content": val = declaration.value.as_css() # Strip quotation marks if re.match("^['\"].*['\"]$", val): val = val[1:-1] icons[name] = unichr(int(val[1:], 16)) common_prefix = common_prefix or '' # Remove common prefix if not self.keep_prefix and len(common_prefix) > 0: non_prefixed_icons = {} for name in icons.keys(): non_prefixed_icons[name[len(common_prefix):]] = icons[name] icons = non_prefixed_icons sorted_icons = OrderedDict(sorted(icons.items(), key=lambda t: t[0])) return sorted_icons, common_prefix
def _parse_css(self, data): cssparser = tinycss.make_parser("page3") css = cssparser.parse_stylesheet(data) if not css: return None re_emote = re.compile("a\[href[|^$]?=[\"']/([\w:]+)[\"']\](:hover)?(\sem|\sstrong)?") emotes_staging = defaultdict(dict) for rule in css.rules: if re_emote.match(rule.selector.as_css()): for match in re_emote.finditer(rule.selector.as_css()): rules = {} for declaration in rule.declarations: if match.group(3): name = match.group(3).strip() + "-" + declaration.name rules[name] = declaration.value.as_css() emotes_staging[match.group(1)].update(rules) elif ( declaration.name in ["text-align", "line-height", "color"] or declaration.name.startswith("font") or declaration.name.startswith("text") ): name = "text-" + declaration.name rules[name] = declaration.value.as_css() emotes_staging[match.group(1)].update(rules) elif declaration.name in [ "width", "height", "background-image", "background-position", "background", ]: name = declaration.name if name == "background-position": val = [ "{}{}".format(v.value, v.unit if v.unit else "") for v in declaration.value if v.value != " " ] else: val = declaration.value[0].value if match.group(2): name = "hover-" + name rules[name] = val emotes_staging[match.group(1)].update(rules) return emotes_staging
def _load_css(filename): import tinycss new_icons = {} parser = tinycss.make_parser("page3") stylesheet = parser.parse_stylesheet_file(filename) is_icon = re.compile(u("^\.fa-(.*):before$")) for rule in stylesheet.rules: selector = rule.selector.as_css() match = is_icon.match(selector) if match: name = match.groups()[0] for declaration in rule.declarations: if declaration.name == u("content"): new_icons[name] = declaration.value.as_css() return new_icons
def find_stylesheets(tree, url): """Find the stylesheets included in ``tree``.""" # TODO: support contentStyleType on <svg> default_type = "text/css" process = tree.getprevious() while process is not None: if (getattr(process, "target", None) == "xml-stylesheet" and process.attrib.get("type", default_type) == "text/css"): # TODO: handle web URLs filename = process.attrib.get("href") if filename: path = os.path.join(os.path.dirname(url), filename) if os.path.isfile(path): yield tinycss.make_parser().parse_stylesheet_file(path) process = process.getprevious() for element in tree.iter(): # http://www.w3.org/TR/SVG/styling.html#StyleElement if (element.tag == "style" and element.get("type", default_type) == "text/css" and element.text): # TODO: pass href for relative URLs # TODO: support media types # TODO: what if <style> has children elements? yield tinycss.make_parser().parse_stylesheet(element.text)
def parseCSS(self, url): r = requests.get(url) urls = [] parser = tinycss.make_parser('page3') try: stylesheet = parser.parse_stylesheet(r.text) for rule in stylesheet.rules: for dec in rule.declarations: for token in dec.value: if token.type == "URI": # Strip out anything not part of the URL and append it to the list urls.append(token.as_css().replace("url(","").replace(")","").strip('"\'')) except: pass return urls
def parse_backgr_color(self, raw_css): """ :return tuple rgb() for 'html' or 'body', None for no color """ parser = tinycss.make_parser() stylesheet = parser.parse_stylesheet(raw_css) for rule in stylesheet.rules: if rule.selector.as_css() in ['html', 'body']: for declar in rule.declarations: # assert isinstance(declar.value, tinycss.token_data.TokenList) if declar.name == 'background-color': # parse color value to single format as tuple rgb() return tinycss.color3.parse_color(declar.value[0]) # return declar.value.as_css() return None