|
- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
- # MIT License. See license.txt
-
- from __future__ import unicode_literals
- import frappe, re, os
- from six import iteritems
-
- def delete_page_cache(path):
- cache = frappe.cache()
- cache.delete_value('full_index')
- groups = ("website_page", "page_context")
- if path:
- for name in groups:
- cache.hdel(name, path)
- else:
- for name in groups:
- cache.delete_key(name)
-
- def find_first_image(html):
- m = re.finditer("""<img[^>]*src\s?=\s?['"]([^'"]*)['"]""", html)
- try:
- return m.next().groups()[0]
- except StopIteration:
- return None
-
- def can_cache(no_cache=False):
- if frappe.conf.disable_website_cache or frappe.conf.developer_mode:
- return False
- if getattr(frappe.local, "no_cache", False):
- return False
- return not no_cache
-
- def get_comment_list(doctype, name):
- return frappe.db.sql("""select
- content, sender_full_name, creation, sender
- from `tabCommunication`
- where
- communication_type='Comment'
- and reference_doctype=%s
- and reference_name=%s
- and (comment_type is null or comment_type in ('Comment', 'Communication'))
- and modified >= DATE_SUB(NOW(),INTERVAL 1 YEAR)
- order by creation""", (doctype, name), as_dict=1) or []
-
- def get_home_page():
- if frappe.local.flags.home_page:
- return frappe.local.flags.home_page
-
- def _get_home_page():
- home_page = None
-
- get_website_user_home_page = frappe.get_hooks('get_website_user_home_page')
- if get_website_user_home_page:
- home_page = frappe.get_attr(get_website_user_home_page[-1])(frappe.session.user)
-
- if not home_page:
- role_home_page = frappe.get_hooks("role_home_page")
- if role_home_page:
- for role in frappe.get_roles():
- if role in role_home_page:
- home_page = role_home_page[role][-1]
- break
-
- if not home_page:
- home_page = frappe.get_hooks("home_page")
- if home_page:
- home_page = home_page[-1]
-
- if not home_page:
- home_page = frappe.db.get_value("Website Settings", None, "home_page") or "login"
-
- home_page = home_page.strip('/')
-
- return home_page
-
- return frappe.cache().hget("home_page", frappe.session.user, _get_home_page)
-
- def is_signup_enabled():
- if getattr(frappe.local, "is_signup_enabled", None) is None:
- frappe.local.is_signup_enabled = True
- if frappe.utils.cint(frappe.db.get_value("Website Settings",
- "Website Settings", "disable_signup")):
- frappe.local.is_signup_enabled = False
-
- return frappe.local.is_signup_enabled
-
- def cleanup_page_name(title):
- """make page name from title"""
- if not title:
- return title
-
- name = title.lower()
- name = re.sub('[~!@#$%^&*+()<>,."\'\?]', '', name)
- name = re.sub('[:/]', '-', name)
-
- name = '-'.join(name.split())
-
- # replace repeating hyphens
- name = re.sub(r"(-)\1+", r"\1", name)
-
- return name[:140]
-
-
- def get_shade(color, percent):
- color, color_format = detect_color_format(color)
- r, g, b, a = color
-
- avg = (float(int(r) + int(g) + int(b)) / 3)
- # switch dark and light shades
- if avg > 128:
- percent = -percent
-
- # stronger diff for darker shades
- if percent < 25 and avg < 64:
- percent = percent * 2
-
- new_color = []
- for channel_value in (r, g, b):
- new_color.append(get_shade_for_channel(channel_value, percent))
-
- r, g, b = new_color
-
- return format_color(r, g, b, a, color_format)
-
-
- def detect_color_format(color):
- if color.startswith("rgba"):
- color_format = "rgba"
- color = [c.strip() for c in color[5:-1].split(",")]
-
- elif color.startswith("rgb"):
- color_format = "rgb"
- color = [c.strip() for c in color[4:-1].split(",")] + [1]
-
- else:
- # assume hex
- color_format = "hex"
-
- if color.startswith("#"):
- color = color[1:]
-
- if len(color) == 3:
- # hex in short form like #fff
- color = "{0}{0}{1}{1}{2}{2}".format(*tuple(color))
-
- color = [int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16), 1]
-
- return color, color_format
-
-
- def get_shade_for_channel(channel_value, percent):
- v = int(channel_value) + int(int('ff', 16) * (float(percent)/100))
- if v < 0:
- v=0
- if v > 255:
- v=255
-
- return v
-
-
- def format_color(r, g, b, a, color_format):
- if color_format == "rgba":
- return "rgba({0}, {1}, {2}, {3})".format(r, g, b, a)
-
- elif color_format == "rgb":
- return "rgb({0}, {1}, {2})".format(r, g, b)
-
- else:
- # assume hex
- return "#{0}{1}{2}".format(convert_to_hex(r), convert_to_hex(g), convert_to_hex(b))
-
-
- def convert_to_hex(channel_value):
- h = hex(channel_value)[2:]
-
- if len(h) < 2:
- h = "0" + h
-
- return h
-
- def abs_url(path):
- """Deconstructs and Reconstructs a URL into an absolute URL or a URL relative from root '/'"""
- if not path:
- return
- if path.startswith('http://') or path.startswith('https://'):
- return path
- if not path.startswith("/"):
- path = "/" + path
- return path
-
- def get_toc(route, url_prefix=None, app=None):
- '''Insert full index (table of contents) for {index} tag'''
- from frappe.website.utils import get_full_index
-
- full_index = get_full_index(app=app)
-
- return frappe.get_template("templates/includes/full_index.html").render({
- "full_index": full_index,
- "url_prefix": url_prefix or "/",
- "route": route.rstrip('/')
- })
-
- def get_next_link(route, url_prefix=None, app=None):
- # insert next link
- next_item = None
- route = route.rstrip('/')
- children_map = get_full_index(app=app)
- parent_route = os.path.dirname(route)
- children = children_map[parent_route]
-
- if parent_route and children:
- for i, c in enumerate(children):
- if c.route == route and i < (len(children) - 1):
- next_item = children[i+1]
- next_item.url_prefix = url_prefix or "/"
-
- if next_item:
- if next_item.route and next_item.title:
- html = ('<p class="btn-next-wrapper">' + frappe._("Next")\
- +': <a class="btn-next" href="{url_prefix}{route}">{title}</a></p>').format(**next_item)
-
- return html
-
- return ''
-
- def get_full_index(route=None, app=None):
- """Returns full index of the website for www upto the n-th level"""
- from frappe.website.router import get_pages
-
- if not frappe.local.flags.children_map:
- def _build():
- children_map = {}
- added = []
- pages = get_pages(app=app)
-
- # make children map
- for route, page_info in iteritems(pages):
- parent_route = os.path.dirname(route)
- if parent_route not in added:
- children_map.setdefault(parent_route, []).append(page_info)
-
- # order as per index if present
- for route, children in children_map.items():
- if not route in pages:
- # no parent (?)
- continue
-
- page_info = pages[route]
- if page_info.index or ('index' in page_info.template):
- new_children = []
- page_info.extn = ''
- for name in (page_info.index or []):
- child_route = page_info.route + '/' + name
- if child_route in pages:
- if child_route not in added:
- new_children.append(pages[child_route])
- added.append(child_route)
-
- # add remaining pages not in index.txt
- _children = sorted(children, lambda a, b: cmp(
- os.path.basename(a.route), os.path.basename(b.route)))
-
- for child_route in _children:
- if child_route not in new_children:
- if child_route not in added:
- new_children.append(child_route)
- added.append(child_route)
-
- children_map[route] = new_children
-
- return children_map
-
- children_map = frappe.cache().get_value('website_full_index', _build)
-
- frappe.local.flags.children_map = children_map
-
- return frappe.local.flags.children_map
-
- def extract_title(source, path):
- '''Returns title from `<!-- title -->` or <h1> or path'''
- title = ''
-
- if "<!-- title:" in source:
- title = re.findall('<!-- title:([^>]*) -->', source)[0].strip()
- elif "<h1>" in source:
- match = re.findall('<h1>([^<]*)', source)
- title = match[0].strip()[:300]
- if not title:
- title = os.path.basename(path.rsplit('.', )[0].rstrip('/')).replace('_', ' ').replace('-', ' ').title()
-
- return title
-
- def add_missing_headers():
- '''Walk and add missing headers in docs (to be called from bench execute)'''
- path = frappe.get_app_path('erpnext', 'docs')
- for basepath, folders, files in os.walk(path):
- for fname in files:
- if fname.endswith('.md'):
- with open(os.path.join(basepath, fname), 'r') as f:
- content = frappe.as_unicode(f.read())
-
- if not content.startswith('# ') and not '<h1>' in content:
- with open(os.path.join(basepath, fname), 'w') as f:
- if fname=='index.md':
- fname = os.path.basename(basepath)
- else:
- fname = fname[:-3]
- h = fname.replace('_', ' ').replace('-', ' ').title()
- content = '# {0}\n\n'.format(h) + content
- f.write(content.encode('utf-8'))
|