def lightbox_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ lightbox image directive usage: .. lightbox:: thumb_url img_url Title """ classes = ["lightbox-img"] if 'align' in options: directives.choice(options['align'], align_values) if isinstance(state, states.SubstitutionDef): # Check for align_v_values. if options['align'] not in align_v_values: raise DirectiveError( 3, 'Error in "%s" directive: "%s" is not a valid value ' 'for the "align" option within a substitution ' 'definition. Valid values for "align" are: "%s".' % (name, options['align'], '", "'.join(align_v_values))) elif options['align'] not in align_h_values: raise DirectiveError( 3, 'Error in "%s" directive: "%s" is not a valid value for ' 'the "align" option. Valid values for "align" are: "%s".' % (name, options['align'], '", "'.join(align_h_values))) classes.append('align-%s' % options['align']) thumb_href = arguments[0] img_href = arguments[1] title = u" ".join(content) alt = options.get('alt', '') html = '<a title="%(title)s" rel="lightbox" href="%(img_href)s"><img %(classes)s src="%(thumb_href)s" title="%(title)s" alt="%(alt)s"/></a>' % { "classes": 'class="%s"' % " ".join(classes) if classes else "", "title": title, "img_href": img_href, "thumb_href": thumb_href, "alt": alt, } return [nodes.raw("", html, format="html")]
def run(self): from docutils.parsers.rst.directives.body import CodeBlock, NumberLines if not self.document.settings.file_insertion_enabled: raise DirectiveError(2, 'Directive "{}" disabled.'.format(self.name)) source_dir = Path(self.document["source"]).absolute().parent include_arg = "".join( [s.strip() for s in self.arguments[0].splitlines()]) if include_arg.startswith("<") and include_arg.endswith(">"): # # docutils "standard" includes path = Path(self.klass.standard_include_path).joinpath( include_arg[1:-1]) else: # if using sphinx interpret absolute paths "correctly", # i.e. relative to source directory try: sphinx_env = self.document.settings.env _, include_arg = sphinx_env.relfn2path(self.arguments[0]) sphinx_env.note_included(include_arg) except AttributeError: pass path = Path(include_arg) path = source_dir.joinpath(path) # read file encoding = self.options.get("encoding", self.document.settings.input_encoding) error_handler = self.document.settings.input_encoding_error_handler # tab_width = self.options.get("tab-width", self.document.settings.tab_width) try: file_content = path.read_text(encoding=encoding, errors=error_handler) except Exception as error: raise DirectiveError( 4, 'Directive "{}": error reading file: {}\n{}.'.format( self.name, path, error), ) # get required section of text startline = self.options.get("start-line", None) endline = self.options.get("end-line", None) file_content = "\n".join(file_content.splitlines()[startline:endline]) startline = startline or 0 for split_on_type in ["start-after", "end-before"]: split_on = self.options.get(split_on_type, None) if not split_on: continue split_index = file_content.find(split_on) if split_index < 0: raise DirectiveError( 4, 'Directive "{}"; option "{}": text not found "{}".'.format( self.name, split_on_type, split_on), ) if split_on_type == "start-after": startline += split_index + len(split_on) file_content = file_content[split_index + len(split_on):] else: file_content = file_content[:split_index] if "literal" in self.options: literal_block = nodes.literal_block(file_content, source=str(path), classes=self.options.get( "class", [])) literal_block.line = 1 # TODO don;t think this should be 1? self.add_name(literal_block) if "number-lines" in self.options: try: startline = int(self.options["number-lines"] or 1) except ValueError: raise DirectiveError( 3, ":number-lines: with non-integer " "start value") endline = startline + len(file_content.splitlines()) if file_content.endswith("\n"): file_content = file_content[:-1] tokens = NumberLines([([], file_content)], startline, endline) for classes, value in tokens: if classes: literal_block += nodes.inline(value, value, classes=classes) else: literal_block += nodes.Text(value) else: literal_block += nodes.Text(file_content) return [literal_block] if "code" in self.options: self.options["source"] = str(path) state_machine = MockStateMachine(self.renderer, self.lineno) state = MockState(self.renderer, state_machine, self.lineno) codeblock = CodeBlock( name=self.name, arguments=[self.options.pop("code")], options=self.options, content=file_content.splitlines(), lineno=self.lineno, content_offset=0, block_text=file_content, state=state, state_machine=state_machine, ) return codeblock.run() # Here we perform a nested render, but temporarily setup the document/reporter # with the correct document path and lineno for the included file. source = self.renderer.document["source"] rsource = self.renderer.reporter.source line_func = getattr(self.renderer.reporter, "get_source_and_line", None) try: self.renderer.document["source"] = str(path) self.renderer.reporter.source = str(path) self.renderer.reporter.get_source_and_line = lambda l: (str(path), l) self.renderer.nested_render_text(file_content, startline + 1) finally: self.renderer.document["source"] = source self.renderer.reporter.source = rsource if line_func is not None: self.renderer.reporter.get_source_and_line = line_func else: del self.renderer.reporter.get_source_and_line return []
def run(self, tag_cache={}): if not self.content: return [] if self.arguments: arguments = self.arguments[0].strip().split(',') else: arguments = [] tag_list_id = CURRENT_PLAN_ID or 'list' output = []; add = output.append tag_id = None for tag in arguments: if tag in tag_cache: add(tag_cache[tag]) continue ori_tag = tag tag = tag.strip().rstrip(u',').strip() if not tag: continue if tag.startswith('id:'): tag_id = tag[3:] continue if tag.startswith('@'): tag_class = u'-'.join(tag[1:].lower().split()) tag_type = 'zuser' tag_text = tag elif tag.startswith('#'): tag_class = u'-'.join(tag[1:].lower().split()) tag_type = '2' tag_text = tag elif ':' in tag: tag_split = tag.split(':', 1) if len(tag_split) == 2: tag_type, tag_text = tag_split else: tag_type = tag_split[0] tag_text = u"" tag_type = tag_type.strip().lower() if tag_type == 'dep' and ':' not in tag_text: tag_class = u'dep-%s-%s' % (CURRENT_PLAN_ID, tag_text) else: tag_class = u'-'.join(tag.replace(':', ' ').lower().split()) else: tag_class = u'-'.join(tag.lower().split()) tag_type = '1' tag_text = tag.upper() if ':' in tag: lead = tag.split(':', 1)[0] tag_name = '%s:%s' % (lead.lower(), tag_text) else: tag_name = tag_text tag_span = ( u'<span class="tag tag-type-%s tag-val-%s" tagname="%s" tagnorm="%s">%s</span> ' % (tag_type, tag_class, tag_name, tag.lower(), tag_text) ) tag_cache[ori_tag] = tag_span add(tag_span) output.sort() if not tag_id: global TAG_COUNTER TAG_COUNTER = TAG_COUNTER + 1 tag_id = 'temp-%s' % TAG_COUNTER tag_id = '%s-%s' % (tag_list_id, tag_id) if tag_id in SEEN_TAGS_CACHE: raise DirectiveError(2, "The tag id %r has already been used!" % tag_id) SEEN_TAGS_CACHE.add(tag_id) if not output: pass # add(u'<span class="tag tag-untagged"></span>') output.append(u'<a class="tag-link" href="#tag-ref-%s-main">·</a>' % tag_id) output.insert( 0, (u'<div class="tag-segment" id="tag-ref-%s">' % tag_id) ) add(u'</div>') tag_info = nodes.raw('', u''.join(output), format='html') tag_content_container = nodes.bullet_list( ids=['tag-ref-%s-content' % tag_id] ) tag_content = nodes.list_item() self.state.nested_parse(self.content, self.content_offset, tag_content) tag_content_container += tag_content prefix = nodes.raw('', u'<div id="tag-ref-%s-main" class="tag-content">' % tag_id, format='html') suffix = nodes.raw('', u'</div>', format='html') return [prefix, tag_content_container, tag_info, suffix]
def run( self, tag_cache={}, tag_normalised_cache={}, TODO=u'✗', DONE=u'✓', letters='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -' ): if not self.content: return [] if self.arguments: arguments = self.arguments[0].strip().split(',') else: arguments = [] tag_list_id = CURRENT_PLAN_ID or 'list' output = []; add = output.append implicit_tags = {} tag_id = None def add_tag( ori_tag, tag_span, cache=tag_normalised_cache, add=add, implicit_tags=implicit_tags, done_tags=CURRENT_PLAN_SETTINGS.get('done', []), todo_tags=CURRENT_PLAN_SETTINGS.get('todo', []), ): add(tag_span) norm_tag = cache[ori_tag] if norm_tag in done_tags: implicit_tags['done'] = True if norm_tag in todo_tags: implicit_tags['todo'] = True for tag in arguments: if tag in tag_cache: add_tag(tag, tag_cache[tag]) continue ori_tag = tag tag = tag.strip().rstrip(u',').strip() if not tag: continue if tag.startswith('id:'): tag_id = tag[3:] continue if tag.startswith('@'): tag_class = u'-'.join(tag[1:].lower().split()) tag_type = 'zuser' tag_text = tag elif tag.startswith('#'): tag_class = u'-'.join(tag[1:].lower().split()) tag_type = '2' tag_text = tag elif ':' in tag: tag_split = tag.split(':', 1) if len(tag_split) == 2: tag_type, tag_text = tag_split else: tag_type = tag_split[0] tag_text = u"" tag_type = tag_type.strip().lower() if tag_type == 'dep' and ':' not in tag_text: tag_class = u'dep-%s-%s' % (CURRENT_PLAN_ID, tag_text) else: tag_class = u'-'.join(tag.replace(':', ' ').lower().split()) else: tag_class = u'-'.join(tag.lower().split()) tag_type = '1' tag_text = tag.upper() if ':' in tag: lead = tag.split(':', 1)[0] tag_name = '%s:%s' % (lead.lower(), tag_text) else: tag_name = tag_text tag_span = ( u'<span class="tag tag-type-%s tag-val-%s" tagname="%s" ' 'tagnorm="%s">%s</span> ' % (tag_type, tag_class, tag_name, tag.lower(), tag_text) ) tag_cache[ori_tag] = tag_span tag_normalised_cache[ori_tag] = tag_class add_tag(ori_tag, tag_span) content = u'\n'.join(self.content) if content.startswith(TODO): if self.content: self.content[0] = self.content[0].replace(TODO, u'*%s*' % TODO, 1) if 'todo' not in implicit_tags: add( u'<span class="tag tag-type-1 tag-val-todo" ' 'tagname="TODO" tagnorm="todo">TODO</span> ' ) elif content.startswith(DONE): if self.content: self.content[0] = self.content[0].replace(DONE, u'*%s*' % DONE, 1) if 'done' not in implicit_tags: add( u'<span class="tag tag-type-1 tag-val-done" ' 'tagname="DONE" tagnorm="done">DONE</span> ' ) output.sort() if not tag_id: tag_id = '-'.join(''.join([ char for char in content.split('\n')[0].strip()[1:].strip() if char in letters ]).split()).lower() if not tag_id: global TAG_COUNTER TAG_COUNTER = TAG_COUNTER + 1 tag_id = 'temp-%s' % TAG_COUNTER tag_id = 'planitem-%s' % tag_id if tag_id in SEEN_TAGS_CACHE: raise DirectiveError(2, "The tag id %r has already been used!" % tag_id) SEEN_TAGS_CACHE.add(tag_id) if not output: pass # add(u'<span class="tag tag-untagged"></span>') add(u'<a class="tag-link" href="#%s">#</a>' % tag_id) output.insert( 0, (u'<div class="tag-segment" id="%s-tags">' % tag_id) ) output.append(u'</div>') tag_info = nodes.raw('', u''.join(output), format='html') tag_content_container = nodes.container( ids=['%s-content' % tag_id] ) self.state.nested_parse( self.content, self.content_offset, tag_content_container ) prefix = nodes.raw( '', u'<div id="%s" class="tag-content">' % tag_id, format='html' ) suffix = nodes.raw('', u'</div>', format='html') return [prefix, tag_content_container, tag_info, suffix]