diff --git a/src/mapcss/__init__.py b/src/mapcss/__init__.py index 169beb1..1259ca6 100644 --- a/src/mapcss/__init__.py +++ b/src/mapcss/__init__.py @@ -41,6 +41,7 @@ CONDITION = re.compile(r'^ \[(.+?)\] \s* ', re.S | re.X) OBJECT = re.compile(r'^ (\*|[\w]+) \s* ', re.S | re.X) DECLARATION = re.compile(r'^ \{(.+?)\} \s* ', re.S | re.X) IMPORT = re.compile(r'^@import\("(.+?)"\); \s* ', re.S | re.X) +VARIABLE_SET = re.compile(r'^@(\w[\w\d]*) \s* : \s* (.+?) \s* ; \s* ', re.S | re.X) UNKNOWN = re.compile(r'^ (\S+) \s* ', re.S | re.X) ZOOM_MINMAX = re.compile(r'^ (\d+)\-(\d+) $', re.S | re.X) @@ -74,6 +75,7 @@ oCONDITION = 4 oOBJECT = 5 oDECLARATION = 6 oSUBPART = 7 +oVARIABLE_SET = 8 DASH = re.compile(r'\-/g') COLOR = re.compile(r'color$/') @@ -84,6 +86,7 @@ CAPS = re.compile(r'^uppercase$/i') CENTER = re.compile(r'^center$/i') HEX = re.compile(r'^#([0-9a-f]+)$/i') +VARIABLE = re.compile(r'@(\w[\w\d]*)') class MapCSS(): def __init__(self, minscale=0, maxscale=19): @@ -96,6 +99,7 @@ class MapCSS(): self.scalepair = (minscale, maxscale) self.choosers = [] self.choosers_by_type = {} + self.variables = {} self.style_loaded = False def parseZoom(self, s): @@ -119,8 +123,9 @@ class MapCSS(): if shash in self.cache["style"]: return deepcopy(self.cache["style"][shash]) style = [] - for chooser in self.choosers_by_type[type]: - style = chooser.updateStyles(style, type, tags, zoom, scale, zscale) + if type in self.choosers_by_type: + for chooser in self.choosers_by_type[type]: + style = chooser.updateStyles(style, type, tags, zoom, scale, zscale) style = [x for x in style if x["object-id"] != "::*"] st = [] for x in style: @@ -168,6 +173,17 @@ class MapCSS(): hints.append(p) return hints + def subst_variables(self, t): + """Expects an array from parseDeclaration.""" + for k in t[0]: + t[0][k] = VARIABLE.sub(self.get_variable, t[0][k]) + return t + + def get_variable(self, m): + name = m.group()[1:] + return self.variables[name] if name in self.variables else m.group() + + def parse(self, css=None, clamp=True, stretch=1000, filename=None): """ Parses MapCSS given as string @@ -256,7 +272,7 @@ class MapCSS(): elif DECLARATION.match(css): decl = DECLARATION.match(css).groups()[0] log.debug("declaration found: %s" % (decl)) - sc.addStyles(parseDeclaration(decl)) + sc.addStyles(self.subst_variables(parseDeclaration(decl))) css = DECLARATION.sub("", css) previous = oDECLARATION @@ -276,6 +292,13 @@ class MapCSS(): except IOError: log.warning("cannot import file %s" % (filename)) + elif VARIABLE_SET.match(css): + name = VARIABLE_SET.match(css).groups()[0] + log.debug("variable set found: %s" % name) + self.variables[name] = VARIABLE_SET.match(css).groups()[1] + css = VARIABLE_SET.sub("", css) + previous = oVARIABLE_SET + # Unknown pattern elif UNKNOWN.match(css): log.warning("unknown thing found on line %s: %s" % (unicode(css_orig[:-len(unicode(css))]).count("\n") + 1, UNKNOWN.match(css).group()))