def render_string_template(self, template: pTemplate) -> pTemplate: """ Render string for markdown rendering. Bold all parameters and perform substitution. Args: template: python Template object Returns: Template with substituted values and all parameters bolded """ if not isinstance(template, (dict, OrderedDict)): return template # replace and render any horizontal lines using *** tag = template.get("tag", None) if tag and tag == "hr": template["template"] = "***" # if there are any groupings of two or more $, we need to double the groupings to account # for template string substitution escaping template["template"] = re.sub(r"\${2,}", lambda m: m.group(0) * 2, template.get("template", "")) # Bold all parameters: base_param_template_string = "**$content**" # Make sure template["params"] is a dict template["params"] = template.get("params", {}) # TODO: Revisit handling of icons in markdown. E.g. inline rendered icons. if "markdown_status_icon" in template["params"]: return template["params"]["markdown_status_icon"] for parameter in template["params"].keys(): if parameter == "html_success_icon": template["params"][parameter] = "" continue # to escape any values that are '*' which, when combined with bold ('**') in markdown, # does not give the output we want. elif template["params"][parameter] == "*": template["params"][parameter] = "\\*" continue template["params"][parameter] = pTemplate( base_param_template_string).safe_substitute({ "content": template["params"][parameter], }) template["template"] = template.get("template", "").replace( "$PARAMETER", "$$PARAMETER") return pTemplate(template.get("template")).safe_substitute( template.get("params", {}))
def render_string_template(template): # NOTE: We should add some kind of type-checking to template if not isinstance(template, (dict, OrderedDict)): return template tag = template.get("tag") base_template_string = "<{tag} $styling>$content</{tag}>".format( tag=tag) if tag else "<span $styling>$content</span>" if "styling" in template: params = template["params"] # Apply default styling if "default" in template["styling"]: default_parameter_styling = template["styling"]["default"] for parameter in template["params"].keys(): # If this param has styling that over-rides the default, skip it here and get it in the next loop. if "params" in template["styling"]: if parameter in template["styling"]["params"]: continue params[parameter] = pTemplate(base_template_string).substitute( { "styling": render_styling(default_parameter_styling), "content": params[parameter], }) # Apply param-specific styling if "params" in template["styling"]: # params = template["params"] for parameter, parameter_styling in template["styling"][ "params"].items(): if parameter not in params: continue params[parameter] = pTemplate(base_template_string).substitute( { "styling": render_styling(parameter_styling), "content": params[parameter], }) string = pTemplate(template["template"]).substitute(params) return string if tag: template_string = "<{tag}>{template}</{tag}>".format( template=template["template"], tag=tag) return pTemplate(template_string).substitute(template["params"]) else: return pTemplate(template["template"]).substitute(template["params"])
def render_styling(styling): """Adds styling information suitable for an html tag styling = { "classes": ["alert", "alert-warning"], "attributes": { "role": "alert", "data-toggle": "popover", }, "styles" : { "padding" : "10px", "border-radius" : "2px", } } returns a string similar to: 'class="alert alert-warning" role="alert" data-toggle="popover" style="padding: 10px; border-radius: 2px"' (Note: `render_styling` makes no guarantees about) "classes", "attributes" and "styles" are all optional parameters. If they aren't present, they simply won't be rendered. Other dictionary keys are also allowed and ignored. This makes it possible for styling objects to be nested, so that different DOM elements # NOTE: We should add some kind of type-checking to styling """ class_list = styling.get("classes", None) if class_list == None: class_str = "" else: if type(class_list) == str: raise TypeError("classes must be a list, not a string.") class_str = 'class="'+' '.join(class_list)+'" ' attribute_dict = styling.get("attributes", None) if attribute_dict == None: attribute_str = "" else: attribute_str = "" for k, v in attribute_dict.items(): attribute_str += k+'="'+v+'" ' style_dict = styling.get("styles", None) if style_dict == None: style_str = "" else: style_str = 'style="' style_str += " ".join([k+':'+v+';' for k, v in style_dict.items()]) style_str += '" ' styling_string = pTemplate('$classes$attributes$style').substitute({ "classes": class_str, "attributes": attribute_str, "style": style_str, }) return styling_string
def render_styling(self, styling): """Adds styling information suitable for an html tag. Example styling block:: styling = { "classes": ["alert", "alert-warning"], "attributes": { "role": "alert", "data-toggle": "popover", }, "styles" : { "padding" : "10px", "border-radius" : "2px", } } The above block returns a string similar to:: 'class="alert alert-warning" role="alert" data-toggle="popover" style="padding: 10px; border-radius: 2px"' "classes", "attributes" and "styles" are all optional parameters. If they aren't present, they simply won't be rendered. Other dictionary keys are also allowed and ignored. """ class_list = styling.get("classes", None) if class_list is None: class_str = "" else: if type(class_list) == str: raise TypeError("classes must be a list, not a string.") class_str = 'class="' + ' '.join(class_list) + '" ' attribute_dict = styling.get("attributes", None) if attribute_dict is None: attribute_str = "" else: attribute_str = "" for k, v in attribute_dict.items(): attribute_str += k + '="' + v + '" ' style_dict = styling.get("styles", None) if style_dict is None: style_str = "" else: style_str = 'style="' style_str += " ".join([k + ':' + v + ';' for k, v in style_dict.items()]) style_str += '" ' styling_string = pTemplate('$classes$attributes$style').substitute({ "classes": class_str, "attributes": attribute_str, "style": style_str, }) return styling_string
def render_string_template(self, template): #NOTE: Using this line for debugging. This should probably be logged...? # print(template) # NOTE: We should add some kind of type-checking to template if not isinstance(template, (dict, OrderedDict)): return template tag = template.get("tag", "span") template["template"] = template.get("template", "").replace("\n", "<br>") if "tooltip" in template: if template.get("styling", {}).get("classes"): classes = template.get("styling", {}).get("classes") classes.append("cooltip") template["styling"]["classes"] = classes elif template.get("styling"): template["styling"]["classes"] = ["cooltip"] else: template["styling"] = {"classes": ["cooltip"]} tooltip_content = template["tooltip"]["content"] tooltip_content.replace("\n", "<br>") placement = template["tooltip"].get("placement", "top") base_template_string = """ <{tag} $styling> $template <span class={placement}> {tooltip_content} </span> </{tag}> """.format(placement=placement, tooltip_content=tooltip_content, tag=tag) else: base_template_string = """ <{tag} $styling> $template </{tag}> """.format(tag=tag) if "styling" in template: params = template.get("params", {}) # Apply default styling if "default" in template["styling"]: default_parameter_styling = template["styling"]["default"] default_param_tag = default_parameter_styling.get( "tag", "span") base_param_template_string = "<{param_tag} $styling>$content</{param_tag}>".format( param_tag=default_param_tag) for parameter in template["params"].keys(): # If this param has styling that over-rides the default, skip it here and get it in the next loop. if "params" in template["styling"]: if parameter in template["styling"]["params"]: continue params[parameter] = pTemplate( base_param_template_string).substitute({ "styling": self.render_styling(default_parameter_styling), "content": params[parameter], }) # Apply param-specific styling if "params" in template["styling"]: # params = template["params"] for parameter, parameter_styling in template["styling"][ "params"].items(): if parameter not in params: continue param_tag = parameter_styling.get("tag", "span") param_template_string = "<{param_tag} $styling>$content</{param_tag}>".format( param_tag=param_tag) params[parameter] = pTemplate( param_template_string).substitute({ "styling": self.render_styling(parameter_styling), "content": params[parameter], }) string = pTemplate( pTemplate(base_template_string).substitute({ "template": template["template"], "styling": self.render_styling(template.get("styling", {})) })).substitute(params) return string return pTemplate( pTemplate(base_template_string).substitute({ "template": template.get("template", ""), "styling": self.render_styling(template.get("styling", {})) })).substitute(template.get("params", {}))
def render_string_template(template): # NOTE: We should add some kind of type-checking to template if not isinstance(template, (dict, OrderedDict)): return template tag = template.get("tag", "span") base_param_template_string = "<{tag} $styling>$content</{tag}>".format(tag=tag) if "tooltip" in template: content = template["tooltip"]["content"] content.replace("\n", "<br>") placement = template["tooltip"].get("placement", "top") base_template_string = """ <{tag} class="cooltip"> $template <span class={placement}> {content} </span> </{tag}> """.format(placement=placement, content=content, tag=tag) else: base_template_string = """ <{tag}> $template </{tag}> """.format(tag=tag) if "styling" in template: params = template["params"] # Apply default styling if "default" in template["styling"]: default_parameter_styling = template["styling"]["default"] for parameter in template["params"].keys(): # If this param has styling that over-rides the default, skip it here and get it in the next loop. if "params" in template["styling"]: if parameter in template["styling"]["params"]: continue params[parameter] = pTemplate(base_param_template_string).substitute({ "styling": render_styling(default_parameter_styling), "content": params[parameter], }) # Apply param-specific styling if "params" in template["styling"]: # params = template["params"] for parameter, parameter_styling in template["styling"]["params"].items(): if parameter not in params: continue params[parameter] = pTemplate(base_param_template_string).substitute({ "styling": render_styling(parameter_styling), "content": params[parameter] }) string = pTemplate( pTemplate(base_template_string).substitute({"template": template["template"]}) ).substitute(params) return string return pTemplate( pTemplate(base_template_string).substitute({"template": template["template"]}) ).substitute(template.get("params", {}))
def __str__(self): string = pTemplate(self.string_template["template"]).safe_substitute( self.string_template["params"]) return string