def merge(request, pageTree, removePanelLinks=False, removeLayoutLink=True): """Perform panel merging for the given page. Returns None if the page has no layout. """ # Find layout node layoutHref = utils.xpath1(utils.layoutXPath, pageTree) if layoutHref is None: return None # Resolve layout tree baseURL = request.getURL() if request.getVirtualRoot(): # plone.subrequest deals with VHM requests baseURL = '' layoutHref = parse.urljoin(baseURL, layoutHref) # noqa: turn the link absolute # Pass special ajax_load parameter forward to allow layout indirection # views to select, for example, default AJAX layout instead of full layout. if request.form.get('ajax_load'): parts = list(parse.urlparse(layoutHref)) query = parse.parse_qs(parts[4]) query['ajax_load'] = request.form.get('ajax_load') parts[4] = parse.urlencode(query) layoutHref = parse.urlunparse(parts) layoutTree = utils.resolve(layoutHref) if layoutTree is None: return None # Map page panels onto the layout pagePanels = dict( (node.attrib['data-panel'], node) for node in utils.panelXPath(pageTree) ) layoutPanels = dict( (node.attrib['data-panel'], node) for node in utils.panelXPath(layoutTree) ) # Site layout should always have element with data-panel="content" # Note: This could be more generic, but that would empower editors too much if 'content' in pagePanels and 'content' not in layoutPanels: for node in layoutTree.xpath('//*[@id="content"]'): node.attrib['data-panel'] = 'content' layoutPanels['content'] = node break for panelId, layoutPanelNode in layoutPanels.items(): pagePanelNode = pagePanels.get(panelId, None) if pagePanelNode is not None: utils.replace_content(layoutPanelNode, pagePanelNode) if removePanelLinks: del layoutPanelNode.attrib['data-panel'] if removeLayoutLink: del pageTree.getroot().attrib[utils.layoutAttrib] return layoutTree
def merge(request, pageTree, removePanelLinks=False, removeLayoutLink=True): """Perform panel merging for the given page. Returns None if the page has no layout. """ # Find layout node layoutHref = utils.xpath1(utils.layoutXPath, pageTree) if layoutHref is None: return None # Resolve layout tree baseURL = request.getURL() if request.getVirtualRoot(): # plone.subrequest deals with VHM requests baseURL = '' layoutHref = urljoin(baseURL, layoutHref) # turn the link absolute if request.form.get('ajax_load'): parts = list(urlparse(layoutHref)) query = parse_qs(parts[4]) query['ajax_load'] = request.form.get('ajax_load') parts[4] = urlencode(query) layoutHref = urlunparse(parts) layoutTree = utils.resolve(layoutHref) if layoutTree is None: return None # Map page panels onto the layout pagePanels = dict((node.attrib['data-panel'], node) for node in utils.panelXPath(pageTree)) layoutPanels = dict((node.attrib['data-panel'], node) for node in utils.panelXPath(layoutTree)) # Site layout should always have element with data-panel="content" # Note: This could be more generic, but that would empower editors too much if 'content' in pagePanels and 'content' not in layoutPanels: for node in layoutTree.xpath('//*[@id="content"]'): node.attrib['data-panel'] = 'content' layoutPanels['content'] = node break for panelId, layoutPanelNode in layoutPanels.items(): pagePanelNode = pagePanels.get(panelId, None) if pagePanelNode is not None: utils.replace_content(layoutPanelNode, pagePanelNode) if removePanelLinks: del layoutPanelNode.attrib['data-panel'] if removeLayoutLink: del pageTree.getroot().attrib[utils.layoutAttrib] return layoutTree
def cook_layout(layout): """Return main_template compatible layout""" result = getHTMLSerializer(layout, encoding='utf-8') nsmap = {'metal': 'http://namespaces.zope.org/metal'} # wrap all panels with a metal:fill-slot -tag for layoutPanelNode in panelXPath(result.tree): panelId = layoutPanelNode.attrib['data-panel'] slot = etree.Element('{%s}%s' % (nsmap['metal'], panelId), nsmap=nsmap) slot.attrib['define-slot'] = panelId slot_parent = layoutPanelNode.getparent() slot_parent_index = slot_parent.index(layoutPanelNode) slot.append(layoutPanelNode) slot_parent.insert(slot_parent_index, slot) root = result.tree.getroot() root.attrib['tal:define'] = """\ portal_state python:context.restrictedTraverse('@@plone_portal_state'); context_state python:context.restrictedTraverse('@@plone_context_state'); plone_view python:context.restrictedTraverse('@@plone'); lang portal_state/language; view nocall:view | nocall: plone_view; dummy python: plone_view.mark_view(view); portal_url portal_state/portal_url; checkPermission nocall: context/portal_membership/checkPermission; site_properties nocall:context/portal_properties/site_properties; ajax_load request/ajax_load | nothing; ajax_include_head request/ajax_include_head | nothing; dummy python:request.RESPONSE.setHeader('X-UA-Compatible', 'IE=edge,chrome=1'); dummy python:options.update({'state': options.get('state', request.get('controller_state'))}); """ template = '<metal:page define-macro="master">\n%s\n</metal:page>' metal = 'xmlns:metal="http://namespaces.zope.org/metal"' return (template % ''.join(result)).replace(metal, '')
def item_panels(self): default_view = self.default_view html = default_view() if isinstance(html, six.text_type): html = html.encode('utf-8') serializer = getHTMLSerializer([html], pretty_print=False, encoding='utf-8') panels = dict((node.attrib['data-panel'], node) for node in utils.panelXPath(serializer.tree)) if panels: request = self.request.clone() request.URL = self.content_context.absolute_url() + '/' try: renderTiles(request, serializer.tree) except RuntimeError: # maximum recursion depth exceeded return [] clear = '<div style="clear: both;"></div>' return [ ''.join([ serializer.serializer(child) for child in node.getchildren() ]) for name, node in panels.items() ] + [clear] return []
def merge(request, pageTree, removePanelLinks=False, removeLayoutLink=True): """Perform panel merging for the given page. Returns None if the page has no layout. """ # Find layout node layoutHref = utils.xpath1(utils.layoutXPath, pageTree) if layoutHref is None: return None # Resolve layout tree baseURL = request.getURL() if request.getVirtualRoot(): # plone.subrequest deals with VHM requests baseURL = '' layoutHref = urljoin(baseURL, layoutHref) # turn the link absolute layoutTree = utils.resolve(layoutHref) if layoutTree is None: return None # Map page panels onto the layout pagePanels = dict( (node.attrib['data-panel'], node) for node in utils.panelXPath(pageTree) ) for layoutPanelNode in utils.panelXPath(layoutTree): panelId = layoutPanelNode.attrib['data-panel'] pagePanelNode = pagePanels.get(panelId, None) if pagePanelNode is not None: utils.replace_content(layoutPanelNode, pagePanelNode) if removePanelLinks: del layoutPanelNode.attrib['data-panel'] if removeLayoutLink: del pageTree.getroot().attrib[utils.layoutAttrib] return layoutTree
def merge(request, pageTree, removePanelLinks=False, removeLayoutLink=True): """Perform panel merging for the given page. Returns None if the page has no layout. """ # Find layout node layoutHref = utils.xpath1(utils.layoutXPath, pageTree) if layoutHref is None: return None # Resolve layout tree baseURL = request.getURL() layoutHref = urljoin(baseURL, layoutHref) # turn the link absolute layoutTree = utils.resolve(layoutHref) if layoutTree is None: return None # Map page panels onto the layout pagePanels = dict( (node.attrib['data-panel'], node) for node in utils.panelXPath(pageTree) ) for layoutPanelNode in utils.panelXPath(layoutTree): panelId = layoutPanelNode.attrib['data-panel'] pagePanelNode = pagePanels.get(panelId, None) if pagePanelNode is not None: utils.replace_content(layoutPanelNode, pagePanelNode) if removePanelLinks: del layoutPanelNode.attrib['data-panel'] if removeLayoutLink: del pageTree.getroot().attrib[utils.layoutAttrib] return layoutTree
def tiles_instances(self): tiles = {} baseURL = self.request.getURL() tree = lxml.html.fromstring(self.content) for panelNode in utils.panelXPath(tree): panelName = panelNode.attrib['data-panel'] for tileNode in utils.bodyTileXPath(panelNode): tileName = tileNode.attrib['data-tile'] tileTree = utils.resolve(urljoin(baseURL, tileName)) tile = tileTree.find('body') if panelName not in tiles.keys(): tiles[panelName] = {} tiles[panelName][tileName] = (tile.text or '') + \ ''.join([lxml.html.tostring(child) for child in tile]) return json.dumps(tiles)
def item_panels(self): default_view = self.default_view html = default_view() if isinstance(html, unicode): html = html.encode('utf-8') serializer = getHTMLSerializer([html], pretty_print=False, encoding='utf-8') panels = dict( (node.attrib['data-panel'], node) for node in utils.panelXPath(serializer.tree) ) if panels: request = self.request.clone() request.URL = self.content_context.absolute_url() + '/' try: renderTiles(request, serializer.tree) except RuntimeError: # maximum recursion depth exceeded return [] clear = '<div style="clear: both;"></div>' return [''.join([serializer.serializer(child) for child in node.getchildren()]) for name, node in panels.items()] + [clear] return []