def get_build_ref_markup(nav_url, jobs, content): '''Return build reference markup expanded by RefHudsonBuild macro. ex1. [[RefHudsonBuild(j3, 1)] >>> str(get_build_ref_markup('http://example.com/hudson/', ['j1','j2'], 'j3,1')) '<a class="ext-link" href="http://example.com/hudson/job/j3/1/"><span class="icon"></span>Hudson: j3#1</a>' ex2. [[RefHudsonBuild(1)] ; jobs = [j1, j2] >>> str(get_build_ref_markup('http://example.com/hudson/', ['j1','j2'], '1')) '<a class="ext-link" href="http://example.com/hudson/job/j1/1/"><span class="icon"></span>Hudson: j1#1</a>' Also, _markup functions must be charcter-escaped. >>> str(get_build_ref_markup('spam/', ['j1','j2'], '><",1')) '<a class="ext-link" href="spam/job/><"/1/"><span class="icon"></span>Hudson: ><"#1</a>' >>> str(get_build_ref_markup('spam/', ['><"','j2'], '1')) '<a class="ext-link" href="spam/job/><"/1/"><span class="icon"></span>Hudson: ><"#1</a>' ''' FORMAT = '<a class="ext-link" href="%sjob/%s/%s/"><span class="icon"></span>Hudson: %s#%s</a>' args = map(lambda x: x.strip(), str(content).split(',')) if len(args) == 1: if len(jobs) == 0: return '' job_name = Markup.escape(jobs[0].strip()) job_no = Markup.escape(args[0]) else: job_name = Markup.escape(args[0]) job_no = Markup.escape(args[1]) return Markup(FORMAT % (nav_url, job_name, job_no, job_name, job_no))
def get_timeline_events(self, req, start, stop, filters): if 'codereview' in filters: crp = CodeReviewPool(self.env) for t, author, text, cr_id, status, version, message in \ crp.get_codereviews_by_time(to_timestamp(start), to_timestamp(stop)): if status == str_status["NoNeedToReview"]: continue elif status == str_status["CompletelyReview"]: title = Markup( 'CodeReview : [ <em title="%s" >%s</em> ] completed by %s' % (message, cr_id, author)) elif version == 1: title = Markup( 'CodeReview : [ <em title="%s" >%s</em> ] created by %s' % (message, cr_id, author)) else: title = Markup( 'CodeReview : [ <em title="%s" >%s</em> ] edited by %s' % (message, cr_id, author)) href = "%s/%s" % (self.env.href.CodeReview(), cr_id) text = wiki_to_oneliner(text, self.env, self.env.get_db_cnx(), shorten=True, req=req) yield 'codereview', href, title, t, author, text
def process_request(self, req): from tractags.macros import TagMacros from trac.web.chrome import add_stylesheet add_stylesheet(req, 'tags/css/tractags.css') req.hdf['trac.href.tags'] = self.env.href.tags() showheadings = self.config.getbool('tags', 'index.showheadings', 'false') and 'true' or 'false' smallest = int(self.config.get('tags', 'index.cloud.smallest', 10)) biggest = int(self.config.get('tags', 'index.cloud.biggest', 30)) if req.path_info == '/tags': index = self.env.config.get('tags', 'index', 'cloud') if index == 'cloud': req.hdf['tag.body'] = Markup( TagMacros(self.env).render_tagcloud(req, smallest=smallest, biggest=biggest)) elif index == 'list': req.hdf['tag.body'] = Markup( TagMacros(self.env).render_listtagged(req, showheadings=showheadings)) else: raise TracError("Invalid index style '%s'" % index) else: tag = req.path_info[6:] req.hdf['tag.name'] = tag req.hdf['tag.body'] = Markup( TagMacros(self.env).render_listtagged( req, tag, showheadings=showheadings)) return 'tags.cs', None
def html_to_printhtml( self, req, html_pages, title='', subject='', version='', date='', ): self.env.log.debug('WikiPrint => Start function html_to_printhtml') page = Markup('<hr>'.join(html_pages)) #TO-DO: Make a nice TOC for HTML printable output page = page.replace('[[pdf-toc]]', '') css_data = '<style type="text/css">%s</style>' % self.get_css(req) page = self.add_headers(req, page, book=False, title=title, subject=subject, version=version, date=date, extra_headers=css_data) page = page.encode(self.default_charset, 'replace') return page
def _acronym_formatter(self, formatter, ns, match): acronym = match.group('acronym') selector = match.group('acronymselector') if acronym not in self.acronyms: return match.group(0) title, href, shref = self.acronyms[acronym] # Perform basic variable substitution title = title.replace('$1', selector).strip() suffix = '' if selector: if shref: href = shref.replace('$1', selector) acronym += ' ' + selector else: suffix = selector # if parsing the href string doesn't return a protocol string, # assume the href string is a reference to a wiki page if href and not urlparse(href).scheme: href = self.env.href.wiki(href) if href: return Markup( '<a class="acronym" href="%s"><acronym title="%s">%s</acronym></a>%s' % (href, title, acronym, suffix)) else: return Markup('<acronym title="%s">%s</acronym>%s' % (title, acronym, suffix))
def get_navi_markup(disp, url, label): """Return the navigation element markup. If nav_url is true, make an element to open other window. >>> str(get_navi_markup(True, 'url', 'label')) '<a class="ext-link" href="url" target="hudson"><span class="icon"></span>label</a>' If nav_url is false, make an element to link only. >>> str(get_navi_markup(False, 'url', 'label')) '<a class="ext-link" href="url" ><span class="icon"></span>label</a>' Also, _markup functions must be charcter-escaped. >>> str(get_navi_markup(False, '"<>', 'label')) '<a class="ext-link" href=""<>" ><span class="icon"></span>label</a>' >>> str(get_navi_markup(False, 'url', '"<>')) '<a class="ext-link" href="url" ><span class="icon"></span>"<></a>' """ FORMAT = '<a class="ext-link" href="%s" %s><span class="icon"></span>%s</a>' escaped_url = Markup.escape(url) escaped_label = Markup.escape(label) if disp: target = 'target="hudson"' else: target = '' return Markup(FORMAT % (escaped_url, target, escaped_label))
def get_navigation_items(self, req): if req.authname and req.authname != 'anonymous': yield 'metanav', 'login', 'logged in as %s' % escape(req.authname) yield 'metanav', 'logout', Markup('<a href="%s">Logout</a>' \ % escape(self.env.href.logout())) else: yield 'metanav', 'login', Markup('<a href="%s">Login</a>' \ % escape(self.env.href.login()))
def get_navigation_items(self, req): if not req.perm.has_permission('WIKI_VIEW'): return yield ('metanav', 'help', Markup('<a href="%s" accesskey="6">Help/Guide</a>', self.env.href.wiki('TracGuide'))) yield ('mainnav', 'wiki', Markup('<a href="%s" accesskey="1">Wiki</a>', self.env.href.wiki()))
def get_navigation_items(self, req): if not self._write_check(): return if req.authname != 'anonymous': yield 'metanav', 'account', Markup('<a href="%s">My Account</a>', (req.href.account())) elif self.reset_password_enabled and not LoginModule(self.env).enabled: yield 'metanav', 'reset_password', Markup( '<a href="%s">Forgot your password?</a>', (req.href.reset_password()))
def process_request(self, req): add_stylesheet(req, 'pydoc/css/pydoc.css') target = req.path_info[7:] req.hdf['trac.href.pydoc'] = self.env.href.pydoc() req.hdf['pydoc.trail'] = [ Markup(x) for x in self.doc._link_components(target)[:-1] ] req.hdf['pydoc.trail_last'] = target.split('.')[-1] req.hdf['pydoc.content'] = Markup(self.generate_help(target)) req.hdf['title'] = target return 'pydoc.cs', None
def get_navigation_items(self, req): items = [] if req.authname == 'anonymous': items.append(('metanav', 'register', Markup('<a href="https://www.djangoproject.com/accounts/register/">Register</a>'))) items.append(('metanav', 'reset_password', Markup('<a href="https://www.djangoproject.com/accounts/password/reset/">Forgot your password?</a>'))) else: items.append(('metanav', 'change_password', Markup('<a href="https://www.djangoproject.com/accounts/password/change/">Change your password</a>'))) items.append(('mainnav', 'custom_reports', Markup('<a href="%s">Reports</a>' % req.href.wiki('Reports')))) return items
def get_navigation_items(self, req): if req.authname and req.authname != 'anonymous': yield 'metanav', 'login', Markup('logged in as <b>%s</b>' \ % req.authname) if self.password_changeable: yield 'metanav', 'password', \ Markup('<a href="%s">Password</a>' \ % req.href.password()) yield 'metanav', 'logout', Markup('<b><a href="%s">Logout</a></b>' \ % req.href.logout()) else: yield 'metanav', 'login', Markup('<b><a href="%s">Login</a></b>' \ % req.href.login())
def execute(hdf, txt, env): out = StringIO() out.write('<ul>\n') for milestone in Milestone.select(env, include_completed=False): if milestone.due > 0: date = format_date(milestone.due) else: date = Markup('<i>(later)</i>') out.write( Markup('<li>%s - <a href="%s">%s</a></li>\n', date, env.href.milestone(milestone.name), milestone.name)) out.write('</ul>\n') return out.getvalue()
def get_timeline_events(self, req, start, stop, filters): format = req.args.get('format') href = format == 'rss' and req.abs_href or req.href # Ticket changes if 'worklog' in filters: add_stylesheet(req, "worklog/worklogplugin.css") db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( """SELECT wl.user,wl.ticket,wl.time,wl.starttime,wl.comment,wl.kind,wl.humankind,t.summary,t.status FROM ( SELECT user, ticket, starttime AS time, starttime, comment, 'workstart' AS kind, 'started' AS humankind FROM work_log UNION SELECT user, ticket, endtime AS time, starttime, comment, 'workstop' AS kind, 'stopped' AS humankind FROM work_log ) AS wl INNER JOIN ticket t ON t.id = wl.ticket AND wl.time>=%s AND wl.time<=%s ORDER BY wl.time""" % (start, stop)) previous_update = None for user, ticket, time, starttime, comment, kind, humankind, summary, status in cursor: summary = Markup.escape(summary) time = float(time) starttime = float(starttime) if format == 'rss': title = Markup('%s %s working on Ticket #%s (%s): %s' % \ (user, humankind, ticket, summary, comment)) else: title = Markup('%s %s working on Ticket <em title="%s">#%s</em>' % \ (user, humankind, summary, ticket)) message = '' if kind == 'workstop': started = datetime.fromtimestamp(starttime) finished = datetime.fromtimestamp(time) if comment: message = wiki_to_oneliner( comment, self.env, db, shorten=True) + Markup( '<br />(Time spent: %s)' % pretty_timedelta(started, finished)) else: message = 'Time spent: %s' % pretty_timedelta( started, finished) yield kind, href.ticket(ticket), title, time, user, message
def _render_filter(self, req, content): buf = StringIO() page = req.args['page'].value href = self.env.href print >> buf, Markup('<a href="%s">[rss]</a><br>', href.changesetrss(page)) idx = page.rstrip('/').rfind('/') if idx != -1: print >> buf, Markup('<a href="%s">[feed list]</a><br>', href.wiki(page[:idx])) print >> buf, Markup( '<h1>Filter Patterns:</h1>' '<pre class="wiki">%s</pre>', content) return buf.getvalue()
def process_request(self, req): req.perm.assert_permission(self.permission) repo = self.env.get_repository(req.authname) add_stylesheet(req, 'wikidoc/css/wikidoc.css') target = req.path_info[9:] req.hdf['trac.href.wikidoc'] = self.env.href.wikidoc() req.hdf['wikidoc.trail'] = [ Markup(x) for x in self._link_components(target)[:-1] ] req.hdf['wikidoc.trail_last'] = target.split('::')[-1] req.hdf['wikidoc.content'] = Markup(self.generate_help(target, repo)) req.hdf['title'] = target return 'wikidoc.cs', None
def html_to_printhtml(self, req, html_pages, title='', subject='', version='', date='', ): self.env.log.debug('WikiPrint => Start function html_to_printhtml') page = Markup('<hr>'.join(html_pages)) #TO-DO: Make a nice TOC for HTML printable output page = page.replace('[[pdf-toc]]','') css_data = '<style type="text/css">%s</style>' % self.get_css(req) page = self.add_headers(req, page, book=False, title=title, subject=subject, version=version, date=date, extra_headers = css_data) page = page.encode(self.default_charset, 'replace') return page
def process_request(self, req): from tractags.macros import TagMacros from tractags.parseargs import parseargs from trac.web.chrome import add_stylesheet add_stylesheet(req, 'tags/css/tractags.css') req.hdf['trac.href.tags'] = self.env.href.tags() def update_from_req(args): for k in req.args.keys(): args[str(k)] = str(req.args.get(k)) if not req.args.has_key('e') and re.match('^/tags/?$', req.path_info): index = self.env.config.get('tags', 'index', 'cloud') index_kwargs = {'smallest': 10, 'biggest': 30} _, config_kwargs = parseargs( self.env.config.get('tags', 'index.args', '')) index_kwargs.update(config_kwargs) update_from_req(index_kwargs) if index == 'cloud': req.hdf['tag.body'] = Markup( TagMacros(self.env).render_tagcloud(req, **index_kwargs)) elif index == 'list': req.hdf['tag.body'] = Markup( TagMacros(self.env).render_listtagged(req, **index_kwargs)) else: raise TracError("Invalid index style '%s'" % index) else: _, args = parseargs(self.env.config.get('tags', 'listing.args', '')) if req.args.has_key('e'): expr = req.args.get('e') else: expr = req.path_info[6:] req.hdf['tag.title'] = Markup( 'Objects matching the expression <i>%s</i>' % expr) req.hdf['tag.expression'] = expr try: Expression(expr) except Exception, e: req.hdf['tag.expression.error'] = str(e).replace( ' (line 1)', '') args['expression'] = expr tags = [] update_from_req(args) req.hdf['tag.body'] = Markup( TagMacros(self.env).render_listtagged(req, *tags, **args))
def get_javascript(self, task_js='', ticket_js='', button_js=''): script = """ <script language=\"javascript\" type=\"text/javascript\"> function wlAddEventListener(elem, evt, func, capture) { capture = capture || false; if (elem.addEventListener) elem.addEventListener(evt, func, capture); else elem.attachEvent('on'+evt, func); return func; } InitWorklog = function() { var x = document.getElementById('ticket').parentNode; var d = document.createElement('fieldset'); d.setAttribute('class', 'workloginfo'); l = document.createElement('legend') l.appendChild(document.createTextNode('Work Log')); d.appendChild(l); """ + button_js + """ ul = document.createElement('ul'); d.appendChild(ul); """ + task_js + ticket_js + """ x.parentNode.insertBefore(d, x); } wlAddEventListener(window, 'load', InitWorklog) </script> """ return Markup(script)
def get_timeline_events(self, req, start, stop, filters): self.log.debug("start: %s, stop: %s, filters: %s" % (start, stop, filters)) if 'downloads' in filters: # Create database context db = self.env.get_db_cnx() cursor = db.cursor() # Get API component. api = self.env[DownloadsApi] format = req.args.get('format') self.log.debug("format: %s" % (format)) # Get message events for download in api.get_new_downloads(req, cursor, start, stop): kind = 'newticket' title = Markup("New download <em>%s</em> created by %s" % (download['file'], download['author'])) time = download['time'] author = download['author'] if format == 'rss': href = req.abs_href.downloads(download['id']) message = wiki_to_html(download['description'], self.env, req) else: href = req.href.downloads(download['id']) message = wiki_to_oneliner(download['description'], self.env) yield kind, href, title, time, author, message
def _replace(m): filepath = posixpath.normpath(m.group('path').replace('\\', '/')) if not cache.get(filepath) is True: parts = filepath.split('/') path = '' for part in parts: path = posixpath.join(path, part) if path not in cache: try: full_path = posixpath.join(config.path, path) full_path = posixpath.normpath(full_path) if full_path.startswith(config.path + "/") \ or full_path == config.path: repos.get_node(full_path, build.rev) cache[path] = True else: cache[path] = False except TracError: cache[path] = False if cache[path] is False: return m.group(0) link = href(config.path, filepath) if m.group('line'): link += '#L' + m.group('line')[1:] return Markup(tag.a(m.group(0), href=link))
def get_build_title_markup(job, build): '''Return build title for timeline. >>> str(get_build_title_markup({'name': 'jobname'}, {'number':1, 'result':'SUCCESS'})) '<img src="chrome/common/extlink.gif">jobname #1 - build-success</a>' Also, _markup functions must be charcter-escaped. >>> str(get_build_title_markup({'name': 'jobname'}, {'number':'><"', 'result':'SUCCESS'})) '<img src="chrome/common/extlink.gif">jobname #><" - build-success</a>' >>> str(get_build_title_markup({'name': '><"'}, {'number':1, 'result':'SUCCESS'})) '<img src="chrome/common/extlink.gif">><" #1 - build-success</a>' ''' FORMAT = '<img src="chrome/common/extlink.gif">%s #%s - %s</a>' build_number = Markup.escape(str(build['number'])) job_name = Markup.escape(job['name']) return Markup(FORMAT % (job_name, build_number, get_build_kind(build)))
def get_navigation_items(self, req): if not (req.perm.has_permission('CODE_REVIEW_DEV') or req.perm.has_permission('CODE_REVIEW_MGR')): return yield ('mainnav', 'peerReviewMain', Markup('<a href="%s">Peer Review</a>', self.env.href.peerReviewMain()))
def expand_macro(self, formatter, name, content): req = formatter.req args, kwargs = parse_args(content) args += [None, None] path, limit, rev = args[:3] limit = kwargs.pop('limit', limit) rev = kwargs.pop('rev', rev) if 'CHANGESET_VIEW' not in req.perm: return Markup('<i>Changelog not available</i>') repo = self.env.get_repository(req.authname) if rev is None: rev = repo.get_youngest_rev() rev = repo.normalize_rev(rev) path = repo.normalize_path(path) if limit is None: limit = 5 else: limit = int(limit) node = repo.get_node(path, rev) out = StringIO() out.write('<div class="changelog">\n') for npath, nrev, nlog in node.get_history(limit): change = repo.get_changeset(nrev) datetime = format_datetime(change.date, '%Y/%m/%d %H:%M:%S', req.tz) out.write( wiki_to_html( "'''[%s] by %s on %s'''\n\n%s" % (nrev, change.author, datetime, change.message), self.env, req)) out.write('</div>\n') return out.getvalue()
def filter_stream(self, req, method, filename, stream, data): try: # get all path patterns path_patterns = TracTweakUIModel.get_path_patterns(self.env) # try to match pattern for path_pattern in path_patterns: if re.match(path_pattern, req.path_info): break else: return stream filter_names = TracTweakUIModel.get_path_filters( self.env, path_pattern) for filter_name in filter_names: self._apply_filter(req, path_pattern, filter_name) js_files = TracTweakUIModel.get_path_scripts( self.env, path_pattern) if js_files: script = ";\n".join(js_files) else: script = "" stream = stream | Transformer('head').append( tag.script(Markup(script), type="text/javascript")()) return stream except: return stream
def get_navigation_items(self, req): move_to = self.env.config.get('navmover', 'move_to') or 'metanav' move_items = self.env.config.get('navmover', 'move_items', ''). \ replace(',', ' ').split() # Ensure sanity if move_to not in ('mainnav', 'metanav'): move_to = 'mainnav' if move_to == 'mainnav': move_from = 'metanav' else: move_from = 'mainnav' # Hide the appropriate nav block add_stylesheet(req, 'navmover/css/hide_%s.css' % move_from) # Find meta nav items meta_items = [] for contributor in self.nav_contributors: if contributor == self: continue for item in contributor.get_navigation_items(req): if (not move_items or item[1] in move_items) and item[0] == move_from \ and unicode(item[2]).startswith('<a '): meta_items.append((move_to, item[1], item[2])) # Add custom items for item, title in [o for o in self.env.config.options('navmover') if '.' not in o[0] and o[0] not in ('move_items', 'move_to')]: url = self.env.config.get('navmover', '%s.url' % item) perm = self.env.config.get('navmover', '%s.permission' % item) if perm and not req.perm.has_permission(perm): continue meta_items.append((move_to, item, Markup('<a href="%s">%s</a>' % (url, title)))) return meta_items
def describeChange(self, file, change, req, db): what = change[2] or 'change' where = 'r%d:%d' % (change[0], change[1]) if (change[0] == -1): if (change[1] == -1): url = None what = "noop" where = None else: #if change[2] == 'add+commits': url = req.href.browser(file, rev=change[1]) # 'add' where = 'r%d' % change[1] what = change[2] elif (change[1] == -1): url = None # deleted what = "deleted" where = None else: url = req.href.changeset(old_path=file, old=change[0], new_path=file, new=change[1]) if url: what = Markup('<a href="%s">%s</a>' % (url, what)) if where: return (what, tag.a(where, href=req.href.search(q=where))) #return (what, where) else: return (what, '')
def post_process_request(self, req, template, content_type): # req.hdf['wiki.page_html'] = str(req.hdf) # return (template, content_type) if not (req.hdf and 'wiki.action' in req.hdf and req.hdf['wiki.action'] == 'view'): return (template, content_type) if not ('wiki.page_name' in req.hdf and 'wiki.page_html' in req.hdf): return (template, content_type) page_name = req.hdf['wiki.page_name'] if not page_name.startswith('Blog'): return (template, content_type) match = h1_match(req.hdf['wiki.page_html']) if not match: return (template, content_type) original = self._get_original_post_info(page_name) title, body = match.groups() title = title.rstrip() body = body.lstrip() permalink = '<a href="%s" title="Permalink" style="%s">#</a>' % ( '/'.join((req.hdf['base_url'], 'wiki', page_name)), 'border-bottom-style: none;') post_info = '<p style="%s">%s | %s | %s</p>' % ( 'font-size: smaller; color: gray; margin: 0 0 0 -18px;', format_datetime(original['time']), original['author'], permalink) req.hdf['wiki.page_html'] = Markup('\n'.join((title, post_info, body))) return (template, content_type)
def get_navigation_items(self, req): """The 'Proj Manager' navigation item is only visible if at least one projmanager page is available and if the user has the permission.""" pages, providers = self._get_pages(req) if req.perm.has_permission('PROJECT_MANAGER') and pages: yield 'mainnav', 'projmanager', Markup('<a href="%s">Proj Management</a>', self.env.href.projmanager())
def get_navigation_items(self, req): # for tickets with only old estimates on them, we would still like to apply style url = req.href.Estimate() #style = req.href.chrome('Estimate/estimate.css') if req.perm.has_permission("TICKET_MODIFY"): yield 'mainnav', "Estimate", \ Markup('<a href="%s">%s</a>' % (url , "Estimate"))
def _make_js(self, req): """Generate the needed Javascript.""" adds = [] for adder in self.ctxtnav_adders: if adder.match_ctxtnav_add(req): for add in adder.get_ctxtnav_adds(req): if isinstance(add, Markup): adds.append(Markup(add.replace("'", "\\'"))) else: href, text = add adds.append( Markup('<a href="%s">%s</a>' % (href, Markup.escape(text, False)))) js = "" for add in adds: js += "add_ctxtnav('%s');\n" % add return """<script type="text/javascript">%s</script>""" % js
def get_navigation_items(self, req): if req.perm.has_permission('DOXYGEN_VIEW'): # Get config variables. title = self.env.config.get('doxygen', 'title', 'Doxygen') # Return mainnav buttons. yield 'mainnav', 'doxygen', Markup('<a href="%s">%s</a>' % \ (self.env.href.doxygen() + '/', title))
def get_navigation_items(self, req): if (not req.perm.has_permission('CODE_REVIEW_VIEW')) and \ (not req.perm.has_permission('CODE_REVIEW_EDIT')) and \ (not req.perm.has_permission('CODE_REVIEW_ADMIN')): return yield ('mainnav', 'CodeReview', Markup('<a href="%s">CodeReview</a>' % self.env.href.CodeReview()))
def get_navigation_items(self, req): nav_bar = bool_val(self.env.config.get('blog', 'nav_bar', True)) if req.perm.has_permission('BLOG_VIEW') and nav_bar: req.hdf['trac.href.blog'] = self.env.href.blog() lname = get_env_val('nav_link', config=self.env.config, section='blog', default='Blog') yield 'mainnav', 'blog', Markup('<a href="%s">%s</a>', self.env.href.blog(), lname)
def process_request(self, req): req.hdf['trac.href.blog'] = req.href.blog() entries = [] for page_name in WikiSystem(self.env).get_pages(prefix='Blog'): page = WikiPage(self.env, page_name) title = page_name text = page.text match = title_split_match(page.text) if match: title = match.group(1) text = match.group(2) comments = text.count('[[SimpleBlogComment(') cutoff = text.find('[[SimpleBlogComment(') if cutoff >= 0: text = text[:cutoff].rstrip() description = wiki_to_html(text, self.env, req) original = self._get_original_post_info(page_name) event = { 'href': self.env.href.wiki(page_name), 'title': title, 'description': description, 'escaped': Markup.escape(unicode(description)), 'date': format_datetime(original['time']), 'rfcdate': http_date(original['time']), 'author': original['author'], 'comment': original['comment'], 'comments': comments, } if page.version > 1: event['updated.version'] = page.version event['updated.date'] = format_datetime(page.time) event['updated.rfcdate'] = http_date(page.time) event['updated.author'] = page.author event['updated.comment'] = page.comment entries.append((original['time'], event)) entries.sort() entries.reverse() max_count = 20 if len(entries) > max_count: entries = entries[:max_count] events = [] for date, event in entries: events.append(event) req.hdf['blog.events'] = events format = req.args.get('format') if format == 'rss': return 'blog_rss.cs', 'application/rss+xml' add_link(req, 'alternate', self.env.href.blog(format='rss'), 'RSS Feed', 'application/rss+xml', 'rss') return 'blog.cs', None
def html_to_pdf(self, req, html_pages, book=True, title='', subject='', version='', date=''): self.env.log.debug('WikiPrint => Start function html_to_pdf') page = Markup('\n<div><pdf:nextpage /></div>'.join(html_pages)) #Replace PageOutline macro with Table of Contents if book: #If book, remove [[TOC]], and add at beginning page = page.replace('[[pdf-toc]]','') page = Markup(self.get_toc()) + Markup(page) else: page = page.replace('[[pdf-toc]]',self.get_toc()) page = self.add_headers(req, page, book, title=title, subject=subject, version=version, date=date) page = page.encode(self.default_charset, 'replace') css_data = self.get_css(req) pdf_file = StringIO.StringIO() auth_cookie = hex_entropy() loader = linkLoader(self.env, req, auth_cookie) #Temporary authentication self.env.log.debug("Storing temporary auth cookie %s for user %s", auth_cookie, req.authname) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (auth_cookie, req.authname, '127.0.0.1', int(time.time()))) db.commit() pdf = pisa.CreatePDF(page, pdf_file, show_errors_as_pdf = True, default_css = css_data, link_callback = loader.getFileName) out = pdf_file.getvalue() pdf_file.close() cursor.execute("DELETE FROM auth_cookie WHERE cookie=%s", (auth_cookie,)) db.commit() self.env.log.debug('WikiPrint => Finish function html_to_pdf') return out
def _process_log(self, req): """Handle AJAX log requests""" try: rev = int(req.args["rev"]) repos = self.env.get_repository(req.authname) chgset = repos.get_changeset(rev) wikimsg = wiki_to_html(chgset.message, self.env, req, None, True, False) # FIXME: check if there is a better way to discard ellipsis # which are not valid in pure XML wikimsg = Markup(wikimsg.replace("...", "")) req.hdf["changeset"] = { "chgset": True, "revision": rev, "time": format_datetime(chgset.date), "age": pretty_timedelta(chgset.date, None, 3600), "author": chgset.author or "anonymous", "message": wikimsg, } return "revtree_log.cs", "application/xhtml+xml" except Exception, e: raise TracError, "Invalid revision log request: %s" % e
def _make_js(self, req): """Generate the needed Javascript.""" adds = [] for adder in self.ctxtnav_adders: if adder.match_ctxtnav_add(req): for add in adder.get_ctxtnav_adds(req): if isinstance(add, Markup): adds.append(Markup(add.replace("'","\\'"))) else: href, text = add adds.append(Markup('<a href="%s">%s</a>'%(href,Markup.escape(text,False)))) js = "" for add in adds: js += "add_ctxtnav('%s');\n"%add return """<script type="text/javascript">%s</script>"""%js
def get_timeline_events(self, req, start, stop, filters): format = req.args.get('format') href = format == 'rss' and req.abs_href or req.href # Ticket changes if 'worklog' in filters: add_stylesheet(req, "worklog/worklogplugin.css") db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("""SELECT wl.user,wl.ticket,wl.time,wl.starttime,wl.comment,wl.kind,wl.humankind,t.summary,t.status FROM ( SELECT user, ticket, starttime AS time, starttime, comment, 'workstart' AS kind, 'started' AS humankind FROM work_log UNION SELECT user, ticket, endtime AS time, starttime, comment, 'workstop' AS kind, 'stopped' AS humankind FROM work_log ) AS wl INNER JOIN ticket t ON t.id = wl.ticket AND wl.time>=%s AND wl.time<=%s ORDER BY wl.time""" % (start, stop)) previous_update = None for user,ticket,time,starttime,comment,kind,humankind,summary,status in cursor: summary = Markup.escape(summary) time = float(time) starttime = float(starttime) if format == 'rss': title = Markup('%s %s working on Ticket #%s (%s): %s' % \ (user, humankind, ticket, summary, comment)) else: title = Markup('%s %s working on Ticket <em title="%s">#%s</em>' % \ (user, humankind, summary, ticket)) message = '' if kind == 'workstop': started = datetime.fromtimestamp(starttime) finished = datetime.fromtimestamp(time) if comment: message = wiki_to_oneliner(comment, self.env, db, shorten=True) + Markup('<br />(Time spent: %s)' % pretty_timedelta(started, finished)) else: message = 'Time spent: %s' % pretty_timedelta(started, finished) yield kind, href.ticket(ticket), title, time, user, message
def _generate_blog(self, req, *args, **kwargs): """Extract the blog pages and fill the HDF. *args is a list of tags to use to limit the blog scope **kwargs are any aditional keyword arguments that are needed """ tallies = {} tags = TagEngine(self.env).tagspace.wiki try: union = kwargs['union'] except KeyError: union = False # Formatting read_post = "[wiki:%s Read Post]" entries = {} if not len(args): tlist = [self.env.config.get('blog', 'default_tag', 'blog')] else: tlist = args if union: blog = tags.get_tagged_names(tlist, operation='union') else: blog = tags.get_tagged_names(tlist, operation='intersection') macropage = req.args.get('page', None) poststart, postend, default_times = self._get_time_range(req, **kwargs) mark_updated = self._choose_value('mark_updated', req, kwargs, convert=bool_val) if not mark_updated and (not isinstance(mark_updated, bool)): mark_updated = bool_val(self.env.config.get('blog', 'mark_updated', True)) macro_bl = self.env.config.get('blog', 'macro_blacklist', '').split(',') macro_bl = [name.strip() for name in macro_bl if name.strip()] macro_bl.append('BlogShow') # Get the email addresses of all known users and validate the "poster" # BlogShow optional argument at the same time (avoids looping the user # list twice). is_poster = None limit_poster = self._choose_value('poster', req, kwargs, convert=None) email_map = {} for username, name, email in self.env.get_known_users(): if email: email_map[username] = email if limit_poster != None: if username == limit_poster: is_poster = username num_posts = self._choose_value('num_posts', req, kwargs, convert=int) if num_posts and default_times: poststart = sys.maxint postend = 0 for blog_entry in blog: if blog_entry == macropage: continue try: page = WikiPage(self.env, version=1, name=blog_entry) version, post_time, author, comment, ipnr = page.get_history( ).next() # if we're limiting by poster, do so now so that the calendar # only shows the number of entries the specific poster made. if is_poster != None: if is_poster != author: continue self._add_to_tallies(tallies, post_time, blog_entry) page = WikiPage(self.env, name=blog_entry) version, modified, author, comment, ipnr = page.get_history( ).next() except: self.log.debug("Error loading wiki page %s" % blog_entry, exc_info=True) continue if poststart >= post_time >= postend: time_format = self.env.config.get('blog', 'date_format') \ or '%x %X' timeStr = format_datetime(post_time, format=time_format) fulltext = page.text # remove comments in blog view: del_comments = re.compile('==== Comment.*\Z', re.DOTALL) fulltext = del_comments.sub('', fulltext) # remove the [[AddComment...]] tag, otherwise it would appeare # more than one and crew up the blog view: del_addcomment = re.compile('\[\[AddComment.*\Z', re.DOTALL) fulltext = del_addcomment.sub('', fulltext) # limit length of preview: post_size = self._choose_value('post_size', req, kwargs, int) if not post_size and (not isinstance(post_size, int)): post_size = int(self.env.config.get('blog', 'post_size', 1024)) text = self._trim_page(fulltext, blog_entry, post_size) pagetags = [x for x in tags.get_name_tags(blog_entry) if x not in tlist] tagtags = [] for i, t in enumerate(pagetags[:3]): d = { 'link' : t, 'name' : t, 'last' : i == (len(pagetags[:3]) - 1), } tagtags.append(d) continue # extract title from text: match = _title_split_match(fulltext) if match: title = match.group(1) fulltext = match.group(2) else: title = blog_entry html_text = wiki_to_html(fulltext, self.env, req) rss_text = Markup.escape(to_unicode(html_text)) data = { 'name' : blog_entry, 'title' : title, 'href' : self.env.href.wiki(blog_entry), 'wiki_link' : wiki_to_oneliner(read_post % blog_entry, self.env), 'time' : timeStr, 'date' : http_date(post_time), # 'date' : http_date(page.time), 'author' : author, 'wiki_text' : wiki_to_nofloat_html(text, self.env, req, macro_blacklist=macro_bl), 'rss_text' : rss_text, 'comment' : wiki_to_oneliner(comment, self.env), 'tags' : { 'present' : len(pagetags), 'tags' : tagtags, 'more' : len(pagetags) > 3 or 0, }, } if author: # For RSS, author must be an email address if author.find('@') != -1: data['author.email'] = author elif email_map.has_key(author): data['author.email'] = email_map[author] if (modified != post_time) and mark_updated: data['modified'] = 1 mod_str = format_datetime(modified, format=time_format) data['mod_time'] = mod_str entries[post_time] = data continue tlist = entries.keys() tlist.sort() tlist.reverse() if num_posts and (num_posts <= len(tlist)): tlist = tlist[:num_posts] if tlist: entries[tlist[-1]]['last'] = 1 req.hdf['blog.entries'] = [entries[x] for x in tlist] bloglink = self.env.config.get('blog', 'new_blog_link', 'New Blog Post') req.hdf['blog.newblog'] = bloglink hidecal = self._choose_value('hidecal', req, kwargs) if not hidecal: self._generate_calendar(req, tallies) req.hdf['blog.hidecal'] = hidecal # Insert /wiki/BlogHeader into /blog. If the page does not exist, # this'll be a no-op blog_header = WikiPage(self.env, name='BlogHeader').text req.hdf['blog.header'] = Mimeview(self.env).render(req, 'text/x-trac-wiki', blog_header)