# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt from __future__ import unicode_literals import frappe from frappe.utils import strip_html from frappe import _ from jinja2.utils import concat from jinja2 import meta import re def build_template(context): """Returns a dict of block name and its rendered content""" out = {} render_blocks(context["template"], out, context) # set_sidebar(out, context) set_breadcrumbs(out, context) set_title_and_header(out, context) # meta if "meta_block" not in out: out["meta_block"] = frappe.get_template("templates/includes/meta_block.html").render(context) add_index(out, context) # render content_context = {} content_context.update(context) content_context.update(out) out["content"] = frappe.get_template("templates/includes/page_content.html").render(content_context) separate_style_and_script(out, context) add_hero(out, context) return out def render_blocks(template_path, out, context): """Build the template block by block from the main template.""" env = frappe.get_jenv() source = frappe.local.jloader.get_source(frappe.local.jenv, template_path)[0] for referenced_template_path in meta.find_referenced_templates(env.parse(source)): if referenced_template_path: render_blocks(referenced_template_path, out, context) template = frappe.get_template(template_path) for block, render in template.blocks.items(): new_context = template.new_context(context) out[block] = concat(render(new_context)) def separate_style_and_script(out, context): """Extract `style` and `script` tags into separate blocks""" out["style"] = re.sub("]*>", "", out.get("style") or "") out["script"] = re.sub("]*>", "", out.get("script") or "") def set_breadcrumbs(out, context): """Build breadcrumbs template (deprecated)""" out["no_breadcrumbs"] = context.get("no_breadcrumbs", 0) \ or ("" in out.get("content", "")) if out["no_breadcrumbs"]: out["breadcrumbs"] = "" elif "breadcrumbs" not in out: out["breadcrumbs"] = frappe.get_template("templates/includes/breadcrumbs.html").render(context) def set_title_and_header(out, context): """Extract and set title and header from content or context.""" out["no_header"] = context.get("no_header", 0) or ("" in out.get("content", "")) if "', out.get("content"))[0].strip() if "title" not in out: out["title"] = context.get("title") if context.get("page_titles") and context.page_titles.get(context.pathname): out["title"] = context.page_titles.get(context.pathname)[0] # header if out["no_header"]: out["header"] = "" else: if "title" not in out and out.get("header"): out["title"] = out["header"] if not out.get("header") and "", out["header"]): out["header"] = "

" + out["header"] + "

" if not out.get("header"): out["no_header"] = 1 out["title"] = strip_html(out.get("title") or "") def set_sidebar(out, context): """Include sidebar (deprecated)""" out["has_sidebar"] = not (context.get("no_sidebar", 0) or ("" in out.get("content", ""))) if out.get("has_sidebar"): out["sidebar"] = frappe.get_template("templates/includes/sidebar.html").render(context) def add_index(out, context): """Add index, next button if `{index}`, `{next}` is present.""" # table of contents if "{index}" in out.get("content", "") and context.get("children"): html = frappe.get_template("templates/includes/static_index.html").render({ "items": context["children"]}) out["content"] = out["content"].replace("{index}", html) # next and previous if "{next}" in out.get("content", ""): next_item = context.doc.get_next() if next_item: if next_item.name[0]!="/": next_item.name = "/" + next_item.name html = ('

'+_("Next")+': {title}

').format(**next_item) else: html = "" out["content"] = out["content"].replace("{next}", html) def add_hero(out, context): """Add a hero element if specified in content or hooks. Hero elements get full page width.""" out["hero"] = "" if "" in out["content"]: parts1 = out["content"].split("") parts2 = parts1[1].split("") out["content"] = parts1[0] + parts2[1] out["hero"] = parts2[0] elif context.hero and context.hero.get(context.pathname): out["hero"] = frappe.render_template(context.hero[context.pathname][0], context)