def index_function(self, namespace=None, collapse=True, ignore_empty=True): '''Index function for export template @param namespace: the namespace to include @param collapse: if C{True} only the branch of the current page is shown, if C{False} the whole index is shown @param ignore_empty: if C{True} empty pages (placeholders) are not shown in the index ''' if not self._index_generator: return '' builder = ParseTreeBuilder() builder.start(FORMATTEDTEXT) builder.start(BULLETLIST) if self._index_page: expanded = [self._index_page] + list(self._index_page.parents()) else: expanded = [] stack = [] for path in self._index_generator(namespace): if self._index_page and collapse \ and not path.parent in expanded: continue # skip since it is not part of current path elif ignore_empty and not (path.hascontent or path.haschildren): continue # skip since page is empty if not stack: stack.append(path.parent) elif stack[-1] != path.parent: if path.ischild(stack[-1]): builder.start(BULLETLIST) stack.append(path.parent) else: while stack and stack[-1] != path.parent: builder.end(BULLETLIST) stack.pop() builder.start(LISTITEM) if path == self._index_page: # Current page is marked with the strong style builder.append(STRONG, text=path.basename) else: # links to other pages builder.append(LINK, {'type': 'page', 'href': ':'+path.name}, path.basename) builder.end(LISTITEM) for p in stack: builder.end(BULLETLIST) builder.end(FORMATTEDTEXT) tree = builder.get_parsetree() if not tree: return '' #~ print "!!!", tree.tostring() dumper = self.dumper_factory(None) return ''.join(dumper.dump(tree))
def __call__(self, dict, root=':', collapse=True, ignore_empty=True): builder = ParseTreeBuilder() collapse = bool(collapse) and not collapse == 'False' ignore_empty = bool(ignore_empty) and not ignore_empty == 'False' if isinstance(root, PageProxy): # allow [% menu(page) %] vs [% menu(page.name) %] root = root.name expanded = [self._page] + list(self._page.parents()) def add_namespace(path): builder.start(BULLETLIST) pagelist = self._notebook.index.list_pages(path) for page in pagelist: if ignore_empty and not page.exists(): continue builder.start(LISTITEM) if page == self._page: # Current page is marked with the strong style builder.append(STRONG, text=page.basename) else: # links to other pages builder.append(LINK, {'type': 'page', 'href': ':'+page.name}, page.basename) builder.end(LISTITEM) if page.haschildren: if collapse: # Only recurs into namespaces that are expanded if page in expanded: add_namespace(page) # recurs else: add_namespace(page) # recurs builder.end('ul') builder.start(FORMATTEDTEXT) add_namespace(Path(root)) builder.end(FORMATTEDTEXT) tree = builder.get_parsetree() if not tree: return None #~ print "!!!", tree.tostring() format = self._format linker = self._linker dumper = format.Dumper( linker=linker, template_options=self._options ) return ''.join(dumper.dump(tree))
class HeadingSplitter(Visitor): def __init__(self, max_level=None): self.max_level = max_level or 999 self._builder = ParseTreeBuilder() self.headings = [] def _split(self): self._builder.end(FORMATTEDTEXT) tree = self._builder.get_parsetree() if tree.hascontent: self.headings.append(tree) self._builder = ParseTreeBuilder() self._builder.start(FORMATTEDTEXT) def _close(self): tree = self._builder.get_parsetree() if tree.hascontent: self.headings.append(tree) def start(self, tag, attrib=None): if tag is HEADING and int(attrib['level']) <= self.max_level: self._split() self._builder.start(tag, attrib) def end(self, tag): self._builder.end(tag) if tag == FORMATTEDTEXT: self._close() def text(self, text): self._builder.text(text) def append(self, tag, attrib=None, text=None): if tag is HEADING and int(attrib['level']) <= self.max_level: self._split() self._builder.append(tag, attrib, text)
def _link_tree(links, notebook, path): # Convert a list of links (of any type) into a parsetree #~ print('LINKS: ', links) #~ print('NOTEBOOK and PATH:', notebook, path) builder = ParseTreeBuilder() builder.start(FORMATTEDTEXT) for i in range(len(links)): if i > 0: builder.text(' ') link = links[i] type = link_type(link) isimage = False if type == 'file': try: file = File(link) isimage = file.isimage() except: pass logger.debug('Pasting link: %s (type: %s, isimage: %s)', link, type, isimage) if isimage: src = notebook.relative_filepath(file, path) or file.uri builder.append(IMAGE, {'src': src}) elif link.startswith('@'): # FIXME - is this ever used ?? builder.append(TAG, {'name': links[i][1:]}, links[i]) else: name = None if type == 'page': target = Path(Path.makeValidPageName( link)) # Assume links are always absolute href = notebook.pages.create_link(path, target) link = href.to_wiki_link() if notebook.config['Notebook']['short_relative_links']: name = href.parts()[-1] elif type == 'file': file = File(link) # Assume links are always URIs link = notebook.relative_filepath(file, path) or file.uri builder.append(LINK, {'href': link}, name or link) builder.end(FORMATTEDTEXT) tree = builder.get_parsetree() tree.resolve_images(notebook, path) tree.decode_urls() return tree
def testRoundtrip(self): tree = tests.new_parsetree() #~ print tree tb = TokenBuilder() tree.visit(tb) tokens = tb.tokens #~ import pprint; pprint.pprint(tokens) testTokenStream(tokens) builder = ParseTreeBuilder(_parsetree_roundtrip=True) TokenParser(builder).parse(tokens) newtree = builder.get_parsetree() self.assertEqual(tree.tostring(), newtree.tostring())
def _link_tree(links, notebook, path): # Convert a list of links (of any type) into a parsetree #~ print 'LINKS: ', links #~ print 'NOTEBOOK and PATH:', notebook, path builder = ParseTreeBuilder() builder.start(FORMATTEDTEXT) for i in range(len(links)): if i > 0: builder.text(' ') link = links[i] type = link_type(link) isimage = False if type == 'file': try: file = File(link) isimage = file.isimage() except: pass logger.debug('Pasting link: %s (type: %s, isimage: %s)', link, type, isimage) if isimage: src = notebook.relative_filepath(file, path) or file.uri builder.append(IMAGE, {'src': src}) elif link.startswith('@'): # FIXME - is this ever used ?? builder.append(TAG, {'name': links[i][1:]}, links[i]) else: if type == 'page': href = Path(notebook.cleanup_pathname( link)) # Assume links are always absolute link = notebook.relative_link(path, href) or link elif type == 'file': file = File(link) # Assume links are always URIs link = notebook.relative_filepath(file, path) or file.uri builder.append(LINK, {'href': link}, link) builder.end(FORMATTEDTEXT) tree = builder.get_parsetree() tree.resolve_images(notebook, path) tree.decode_urls() return tree
def _link_tree(links, notebook, path): # Convert a list of links (of any type) into a parsetree #~ print 'LINKS: ', links #~ print 'NOTEBOOK and PATH:', notebook, path builder = ParseTreeBuilder() builder.start(FORMATTEDTEXT) for i in range(len(links)): if i > 0: builder.text(' ') link = links[i] type = link_type(link) isimage = False if type == 'file': try: file = File(link) isimage = file.isimage() except: pass logger.debug('Pasting link: %s (type: %s, isimage: %s)', link, type, isimage) if isimage: src = notebook.relative_filepath(file, path) or file.uri builder.append(IMAGE, {'src': src}) elif link.startswith('@'): # FIXME - is this ever used ?? builder.append(TAG, {'name': links[i][1:]}, links[i]) else: if type == 'page': href = Path(notebook.cleanup_pathname(link)) # Assume links are always absolute link = notebook.relative_link(path, href) or link elif type == 'file': file = File(link) # Assume links are always URIs link = notebook.relative_filepath(file, path) or file.uri builder.append(LINK, {'href': link}, link) builder.end(FORMATTEDTEXT) tree = builder.get_parsetree() tree.resolve_images(notebook, path) tree.decode_urls() return tree
def get_data_as(self, targetid): if targetid == PAGELIST_TARGET_ID: link = "%s?%s" % (self.notebook.interwiki, self.path.name) if self.anchor: link += "#" + self.anchor return pack_urilist((link, )) elif targetid == TEXT_TARGET_ID: link = self.path.name if self.anchor: link += "#" + self.anchor return link elif targetid == PARSETREE_TARGET_ID: link = self.path.name if self.anchor: link += "#" + self.anchor if self.text: text = self.text elif self.notebook.config['Notebook']['short_links']: href = HRef.new_from_wiki_link(link) text = href.parts()[-1] if self.anchor: text += '#' + self.anchor else: text = link # Same logic as set_parsetree_attributes_to_resolve_links() but no need to resolve again builder = ParseTreeBuilder() builder.start(FORMATTEDTEXT) builder.append(LINK, {'href': link, '_href': self.path.name}, text) builder.end(FORMATTEDTEXT) parsetree = builder.get_parsetree() parsetree._set_root_attrib('notebook', self.notebook.interwiki) parsetree._set_root_attrib( 'page', '-') # force resolve on paste also on same page return parsetree.tostring() else: raise ValueError('Unknown target id %i' % targetid)
def parsetree_from_selectiondata(selectiondata, notebook=None, path=None, text_format='plain'): '''Function to get a parsetree based on the selectiondata contents if at all possible. Used by both copy-paste and drag-and-drop methods. The 'notebook' and optional 'path' arguments are used to format links relative to the page which is the target for the pasting or drop operation. For image data, the parameters notebook and page are used to save the image to the correct attachment folder and return a parsetree with the correct image link. @param selectiondata: a C{Gtk.SelectionData} object @param notebook: a L{Notebook} object @param path: a L{Path} object @param text_format: format to parse pasted text, as a special case - "verbatim" will wrap content in VERBARIM_BLOCK or VERBATIM element based on the content - "verbatim-pre" will wrap the content in a VERBATIM_BLOCK element and - "verbatim-code" will wrap the content in a VERBATIM element @returns: a L{ParseTree} or C{None} ''' # TODO: check relative linking for all parsetrees !!! targetname = selectiondata.get_target().name() if targetname == PARSETREE_TARGET_NAME: return ParseTree().fromstring(selectiondata.get_data()) elif targetname in (INTERNAL_PAGELIST_TARGET_NAME, PAGELIST_TARGET_NAME) \ or targetname in URI_TARGET_NAMES: links = selectiondata.get_uris() return _link_tree(links, notebook, path) elif targetname in TEXT_TARGET_NAMES: # plain text parser should highlight urls etc. # FIXME some apps drop text/uri-list as a text/plain mimetype # try to catch this situation by a check here text = selectiondata.get_text() if text: if text_format in ('verbatim', 'verbatim-pre', 'verbatim-code'): if text_format == 'verbatim': tag_name = 'pre' if '\n' in text else 'code' else: tag_name = text_format[9:] builder = ParseTreeBuilder(partial=True) builder.start('zim-tree', {}) builder.start(tag_name, {}) builder.text(text) builder.end(tag_name) builder.end('zim-tree') return builder.get_parsetree() else: return get_format(text_format).Parser().parse(text, partial=True) else: return None elif targetname in IMAGE_TARGET_NAMES: # save image pixbuf = selectiondata.get_pixbuf() if not pixbuf: return None dir = notebook.get_attachments_dir(path) assert isinstance(dir, LocalFolder) or hasattr( dir, '_folder') and isinstance(dir._folder, LocalFolder) # XXX: assert we have local path - HACK to deal with FilesAttachmentFolder if not dir.exists(): logger.debug("Creating attachment dir: %s", dir) dir.touch() format, extension = _get_image_info(targetname) if format is None or format == 'bmp': # default to png format # special casing bmp since many window apps use it internally # but is quite large to store, so compress by using png format, extension = 'png', 'png' file = dir.new_file('pasted_image.%s' % extension) logger.debug("Saving image from clipboard to %s", file) pixbuf.savev(file.path, format, [], []) FS.emit('path-created', file) # notify version control links = [file.uri] return _link_tree(links, notebook, path) else: return None
def emptyParseTree(): b = ParseTreeBuilder() b.start('zim-tree') b.end('zim-tree') return b.get_parsetree()
def index_function(self, namespace=None, collapse=True, ignore_empty=True): '''Index function for export template @param namespace: the namespace to include @param collapse: if C{True} only the branch of the current page is shown, if C{False} the whole index is shown @param ignore_empty: if C{True} empty pages (placeholders) are not shown in the index ''' if not self._index_generator: return '' builder = ParseTreeBuilder() builder.start(FORMATTEDTEXT) if self._index_page: expanded = [self._index_page] + list(self._index_page.parents()) else: expanded = [] stack = [] if isinstance(namespace, PageProxy): namespace = Path(namespace.name) elif isinstance(namespace, str): namespace = Path(namespace) for path in self._index_generator(namespace): logger.info(path) if self._index_page and collapse \ and not path.parent in expanded: continue # skip since it is not part of current path #elif ignore_empty and not (path.hascontent or path.haschildren): - bug, should be page.hascontent, page.haschildren # continue # skip since page is empty if not stack: stack.append(path.parent) builder.start(BULLETLIST) elif stack[-1] != path.parent: if path.ischild(stack[-1]): builder.start(BULLETLIST) stack.append(path.parent) else: while stack and stack[-1] != path.parent: builder.end(BULLETLIST) stack.pop() builder.start(LISTITEM) if path == self._index_page: # Current page is marked with the strong style builder.append(STRONG, text=path.basename) else: # links to other pages builder.append(LINK, {'type': 'page', 'href': ':' + path.name}, path.basename) builder.end(LISTITEM) for p in stack: builder.end(BULLETLIST) builder.end(FORMATTEDTEXT) tree = builder.get_parsetree() if not tree: return '' #~ print("!!!", tree.tostring()) dumper = self.get_dumper(None) return ''.join(dumper.dump(tree))