=== htdocs/stable-bct-trac_banner.png
==================================================================
Cannot display: file marked as a binary type.
Property changes on: htdocs/stable-bct-trac_banner.png
___________________________________________________________________
Name: svn:executable
+*
Name: svn:mime-type
+image/x-png
=== htdocs/css/trac.css
==================================================================
|
|
|
|
| 240 | 240 | a.missing:link,a.missing:visited { background: #fafaf0; color: #998 } |
| 241 | 241 | a.missing:hover { color: #000; } |
| 242 | 242 | |
| | 243 | a.external:link,a.external:visited { color: #00b } |
| | 244 | |
| 243 | 245 | #content.wiki { line-height: 140% } |
| 244 | 246 | .wikitoolbar { |
| 245 | 247 | border: solid #d7d7d7; |
| … |
… |
|
| 345 | 347 | #content.error pre, div.system-message pre { margin-left: 1em; overflow: auto } |
| 346 | 348 | div.system-message p { margin: 0; } |
| 347 | 349 | div.system-message p.system-message-title { font-weight: bold; } |
| | 350 | div.sidebar, div.contents { |
| | 351 | background: #f7f7f0; |
| | 352 | border: 1px outset #998; |
| | 353 | float: right; |
| | 354 | font-size: 90%; |
| | 355 | padding: .8em; |
| | 356 | margin: 0 1em 1em; |
| | 357 | width: 26em;margin: 0; |
| | 358 | } |
| | 359 | p.sidebar-title, p.topic-title { font-weight: bold; } |
| | 360 | div.note { |
| | 361 | background: #d7d7f0; |
| | 362 | border: 1px outset #998; |
| | 363 | float: left |
| | 364 | font-size: 90%; |
| | 365 | padding: .8em; |
| | 366 | margin: 0 1em 1em; |
| | 367 | width: 26em; |
| | 368 | } |
| | 369 | p.admonition-title { font-weight: bold;text-align: center } |
| 348 | 370 | |
| 349 | 371 | /* Styles for search word highlighting */ |
| 350 | 372 | .searchword0 { background: #ff9 } |
=== htdocs/css/browser.css
==================================================================
|
|
|
|
| 40 | 40 | #chglist td.rev a, #chglist td.chgset a { border-bottom: none } |
| 41 | 41 | #chglist td.summary { width: 100% } |
| 42 | 42 | |
| | 43 | /* Styles for the diff forms inside the log table */ |
| | 44 | #chglist input { |
| | 45 | font-size: 10px; |
| | 46 | margin: 0; |
| | 47 | padding: 0; |
| | 48 | text-align: center; |
| | 49 | vertical-align: middle; |
| | 50 | } |
| | 51 | #chglist form { |
| | 52 | margin: 0; |
| | 53 | padding: 0; |
| | 54 | white-space: nowrap; |
| | 55 | } |
| | 56 | |
| 43 | 57 | /* Styles for the revision info in the file module */ |
| 44 | 58 | #info { |
| 45 | 59 | background: #f7f7f0; |
=== htdocs/css/ticket.css
==================================================================
|
|
|
|
| 21 | 21 | #ticket th { color: #996; font-weight: normal; text-align: left } |
| 22 | 22 | #ticket hr { color: #dd9; border-color: #dd9; border-width: 1px 0 0; height: 1px; margin: .5em 0 0 } |
| 23 | 23 | |
| | 24 | #ticket .category { font-size: 200% } |
| | 25 | |
| 24 | 26 | #attachments { border: 1px outset #996; padding: 1em } |
| 25 | 27 | #attachments .attachments { list-style: square; margin-left: 2em; padding: 0 } |
| 26 | 28 | |
=== htdocs/css/timeline.css
==================================================================
|
|
|
|
| 27 | 27 | dt .time { color: #777 } |
| 28 | 28 | dd { font-size: 80%; margin: 0 0 .5em 5em; padding: 0 } |
| 29 | 29 | |
| | 30 | |
| 30 | 31 | /* Apply icon background-image twice to avoid hover-flicker in IE/Win */ |
| 31 | 32 | dt.changeset, dt.changeset a { background-image: url(../changeset.png) !important } |
| 32 | 33 | dt.newticket, dt.newticket a { background-image: url(../newticket.png) !important } |
| 33 | 34 | dt.closedticket, dt.closedticket a { background-image: url(../closedticket.png) !important } |
| 34 | 35 | dt.wiki, dt.wiki a { background-image: url(../wiki.png) !important } |
| 35 | 36 | dt.milestone, dt.milestone a { background-image: url(../milestone.png) !important } |
| | 37 | dt.ticketcomment a { font-size: 80%; color: #555 } |
| | 38 | dd.ticketcomment { font-size: 70%; color: #555; margin: 0 0 .5em 5em; padding: 0 } |
| 36 | 39 | |
| | 40 | |
| 37 | 41 | .diff-unmod { color: #000 } |
| 38 | 42 | .diff-rem { color: #e00 } |
| 39 | 43 | .diff-add { color: #2e2 } |
=== htdocs/exp-svk-trac_banner.png
==================================================================
Cannot display: file marked as a binary type.
Property changes on: htdocs/exp-svk-trac_banner.png
___________________________________________________________________
Name: svn:mime-type
+image/x-png
=== htdocs/exp-bct-trac_banner.png
==================================================================
Cannot display: file marked as a binary type.
Property changes on: htdocs/exp-bct-trac_banner.png
___________________________________________________________________
Name: svn:executable
+*
Name: svn:mime-type
+image/x-png
=== htdocs/stable-svk-trac_banner.png
==================================================================
Cannot display: file marked as a binary type.
Property changes on: htdocs/stable-svk-trac_banner.png
___________________________________________________________________
Name: svn:mime-type
+image/x-png
=== scripts/trac-admin
==================================================================
|
|
|
|
| 706 | 706 | self._do_wiki_import(filename, page, cursor) |
| 707 | 707 | |
| 708 | 708 | |
| | 709 | ## (Ticket) Category |
| | 710 | _help_category = [('category list', 'Show possible ticket categories'), |
| | 711 | ('category add <value>', 'Add a category value option'), |
| | 712 | ('category change <value> <newvalue>', |
| | 713 | 'Change a category value'), |
| | 714 | ('category remove <value>', 'Remove category value')] |
| | 715 | |
| | 716 | def complete_category (self, text, line, begidx, endidx): |
| | 717 | if begidx == 16: |
| | 718 | comp = self.get_enum_list ('category') |
| | 719 | elif begidx < 15: |
| | 720 | comp = ['list','add','change','remove'] |
| | 721 | return self.word_complete(text, comp) |
| | 722 | |
| | 723 | def do_category(self, line): |
| | 724 | self._do_enum('category', line) |
| | 725 | |
| 709 | 726 | ## (Ticket) Priority |
| 710 | 727 | _help_priority = [('priority list', 'Show possible ticket priorities'), |
| 711 | 728 | ('priority add <value>', 'Add a priority value option'), |
=== README.tracd
==================================================================
|
|
|
|
| | 1 | ======================== |
| 1 | 2 | Trac in stand-alone mode |
| 2 | 3 | ======================== |
| | 4 | |
| 3 | 5 | Trac 0.7 introduces among many other important features, the capability to run |
| 4 | 6 | Trac as a stand-alone server (daemon), without a web server. |
| 5 | 7 | |
| 6 | | *** NOTE: THIS IS STILL AN EXPERIMENTAL FEATURE *** |
| | 8 | .. NOTE:: THIS IS STILL AN EXPERIMENTAL FEATURE |
| 7 | 9 | |
| 8 | 10 | As of writing, tracd is still experimental, but we encourage testing it and |
| 9 | 11 | providing feedback so we can improve it. Tracd supports all features of |
| … |
… |
|
| 12 | 14 | |
| 13 | 15 | Running tracd |
| 14 | 16 | ------------- |
| 15 | | tracd [options] <database> [database] ... |
| | 17 | |
| | 18 | tracd [options] <environment> [environment2 ...] |
| 16 | 19 | Options: |
| | 20 | |
| | 21 | -a, --auth <project,htdigest_file,realm> Use Digest Authentication |
| | 22 | -p, --port <port> Port number to use (default: 80) |
| | 23 | -b, --hostname <hostname> IP to bind to (default: '') |
| 17 | 24 | |
| 18 | | -a --auth [project],[htdigest_file],[realm] |
| 19 | | -p --port [port]\t\tPort number to use (default: 80) |
| 20 | | -b --hostname [hostname]\tIP to bind to (default: '') |
| 21 | 25 | |
| 22 | 26 | |
| 23 | | Example: |
| | 27 | Example 1, without authentication:: |
| 24 | 28 | |
| 25 | 29 | $ tracd -p 9090 /var/trac/myproject |
| 26 | 30 | |
| | 31 | Example 2, with authentication:: |
| 27 | 32 | |
| | 33 | $ TRAC_ENV=/var/trac/myproject |
| | 34 | $ tracd -a `basename $TRAC_ENV`,`dirname $TRAC_ENV`/passwd.digest,REALM \ |
| | 35 | -p 9090 $TRAC_ENV |
| | 36 | |
| | 37 | The file htdigest can be generated using the Apache2 tool htdigest. |
| | 38 | |
| | 39 | |
| 28 | 40 | Feedback and bug reports |
| 29 | 41 | ------------------------ |
| 30 | 42 | Please provide feedback on tracd using the issue tracker or the mailing list. |
=== trac/core.py
==================================================================
|
|
|
|
| 46 | 46 | # name (module_name, class_name, requires_svn) |
| 47 | 47 | 'log' : ('Log', 'Log', 1), |
| 48 | 48 | 'file' : ('File', 'File', 1), |
| 49 | | 'wiki' : ('Wiki', 'WikiModule', 0), |
| | 49 | 'wiki' : ('Wiki', 'WikiModule', 1), # support Svn backend for Wiki pages |
| 50 | 50 | 'about_trac' : ('About', 'About', 0), |
| 51 | 51 | 'search' : ('Search', 'Search', 0), |
| 52 | 52 | 'report' : ('Report', 'Report', 0), |
| … |
… |
|
| 199 | 199 | pass |
| 200 | 200 | |
| 201 | 201 | def populate_hdf(hdf, env, db, req): |
| | 202 | sql_to_hdf(db, "SELECT name FROM enum WHERE type='category' " |
| | 203 | "ORDER BY value", hdf, 'enums.category') |
| 202 | 204 | sql_to_hdf(db, "SELECT name FROM enum WHERE type='priority' " |
| 203 | 205 | "ORDER BY value", hdf, 'enums.priority') |
| 204 | 206 | sql_to_hdf(db, "SELECT name FROM enum WHERE type='severity' " |
=== trac/db_default.py
==================================================================
|
|
|
|
| 21 | 21 | |
| 22 | 22 | |
| 23 | 23 | # Database version identifier. Used for automatic upgrades. |
| 24 | | db_version = 7 |
| | 24 | db_version = 8 |
| 25 | 25 | |
| 26 | 26 | def __mkreports(reps): |
| 27 | 27 | """Utility function used to create report data in same syntax as the |
=== trac/Query.py
==================================================================
|
|
|
|
| 59 | 59 | results.append({ |
| 60 | 60 | 'id': id, |
| 61 | 61 | 'href': self.env.href.ticket(id), |
| | 62 | 'category': row['category'], |
| 62 | 63 | 'summary': util.escape(row['summary'] or '(no summary)'), |
| 63 | 64 | 'status': row['status'] or '', |
| 64 | 65 | 'component': row['component'] or '', |
| … |
… |
|
| 78 | 79 | if self.args.has_key('search'): |
| 79 | 80 | self.req.redirect(self.env.href.query(constraints, order, desc, |
| 80 | 81 | action='view')) |
| | 82 | if self.args.has_key('clear'): |
| | 83 | self.req.redirect(self.env.href.query()) |
| 81 | 84 | |
| 82 | 85 | action = self.args.get('action') |
| 83 | 86 | if not action and not constraints: |
| … |
… |
|
| 91 | 94 | |
| 92 | 95 | def _render_editor(self, constraints, order, desc): |
| 93 | 96 | self.req.hdf.setValue('title', 'Custom Query') |
| | 97 | self.req.hdf.setValue('query.clear_href', self.env.href.query(action='edit')) |
| 94 | 98 | util.add_to_hdf(constraints, self.req.hdf, 'query.constraints') |
| 95 | 99 | self.req.hdf.setValue('query.order', order) |
| 96 | 100 | if desc: self.req.hdf.setValue('query.desc', '1') |
| … |
… |
|
| 112 | 116 | del constraints[field] |
| 113 | 117 | |
| 114 | 118 | cursor = self.db.cursor() |
| | 119 | add_options('category', constraints, 'query.options.', cursor, |
| | 120 | "SELECT name FROM enum WHERE type='category' ORDER BY value") |
| 115 | 121 | add_options('status', constraints, 'query.options.', cursor, |
| 116 | 122 | "SELECT name FROM enum WHERE type='status' ORDER BY value") |
| 117 | 123 | add_options('resolution', constraints, 'query.options.', cursor, |
| … |
… |
|
| 129 | 135 | |
| 130 | 136 | custom_fields = get_custom_fields(self.env) |
| 131 | 137 | for custom in custom_fields: |
| 132 | | if custom['type'] == 'select' or custom['type'] == 'radio': |
| | 138 | if custom['type'] in ['select', 'radio', 'multi']: |
| 133 | 139 | check = constraints.has_key(custom['name']) |
| 134 | 140 | options = filter(None, custom['options']) |
| 135 | 141 | for i in range(len(options)): |
| … |
… |
|
| 146 | 152 | |
| 147 | 153 | # FIXME: the user should be able to configure which columns should |
| 148 | 154 | # be displayed |
| 149 | | headers = [ 'id', 'summary', 'status', 'component', 'owner' ] |
| | 155 | headers = [ 'category', 'id', 'summary', 'status', 'component', 'owner' ] |
| 150 | 156 | cols = headers |
| 151 | 157 | if not 'priority' in cols: |
| 152 | 158 | cols.append('priority') |
| … |
… |
|
| 176 | 182 | "(id=%s.ticket AND %s.name='%s')" |
| 177 | 183 | % (k, k, k, k)) |
| 178 | 184 | |
| 179 | | for col in [c for c in ['status', 'resolution', 'priority', 'severity'] |
| | 185 | for col in [c for c in ['category', 'status', 'resolution', 'priority', 'severity'] |
| 180 | 186 | if c in cols]: |
| 181 | 187 | sql.append(" INNER JOIN (SELECT name AS %s_name, value AS %s_value " \ |
| 182 | 188 | "FROM enum WHERE type='%s')" \ |
| … |
… |
|
| 194 | 200 | if clauses: |
| 195 | 201 | sql.append(" WHERE " + " AND ".join(clauses)) |
| 196 | 202 | |
| 197 | | if order in ['status', 'resolution', 'priority', 'severity']: |
| | 203 | if order in ['category', 'status', 'resolution', 'priority', 'severity']: |
| 198 | 204 | sql.append(" ORDER BY %s_value" % order) |
| 199 | 205 | else: |
| 200 | 206 | sql.append(" ORDER BY " + order) |
=== trac/Timeline.py
==================================================================
|
|
|
|
| 34 | 34 | template_name = 'timeline.cs' |
| 35 | 35 | template_rss_name = 'timeline_rss.cs' |
| 36 | 36 | |
| 37 | | def get_info (self, start, stop, maxrows, tickets, |
| | 37 | def get_info (self, start, stop, maxrows, tickets, ticket_comments, |
| 38 | 38 | changeset, wiki, milestone): |
| 39 | 39 | cursor = self.db.cursor () |
| 40 | 40 | |
| 41 | 41 | tickets = tickets and self.perm.has_permission(perm.TICKET_VIEW) |
| | 42 | ticket_comments = ticket_comments and self.perm.has_permission(perm.TICKET_VIEW) |
| 42 | 43 | changeset = changeset and self.perm.has_permission(perm.CHANGESET_VIEW) |
| 43 | 44 | wiki = wiki and self.perm.has_permission(perm.WIKI_VIEW) |
| 44 | 45 | milestone = milestone and self.perm.has_permission(perm.MILESTONE_VIEW) |
| … |
… |
|
| 52 | 53 | REOPENED_TICKET = 4 |
| 53 | 54 | WIKI = 5 |
| 54 | 55 | MILESTONE = 6 |
| | 56 | TICKET_COMMENT = 7 |
| 55 | 57 | |
| 56 | 58 | q = [] |
| 57 | 59 | if changeset: |
| 58 | 60 | q.append("SELECT time, rev AS idata, '' AS tdata, 1 AS type, " |
| 59 | | " message, author " |
| | 61 | " message, author, '' AS category " |
| 60 | 62 | "FROM revision WHERE time>=%s AND time<=%s" % |
| 61 | 63 | (start, stop)) |
| 62 | 64 | if tickets: |
| 63 | 65 | q.append("SELECT time, id AS idata, '' AS tdata, 2 AS type, " |
| 64 | | "summary AS message, reporter AS author " |
| | 66 | " summary AS message, reporter AS author, category " |
| 65 | 67 | "FROM ticket WHERE time>=%s AND time<=%s" % |
| 66 | 68 | (start, stop)) |
| 67 | | q.append("SELECT time, ticket AS idata, '' AS tdata, 4 AS type, " |
| 68 | | "'' AS message, author " |
| 69 | | "FROM ticket_change WHERE field='status' " |
| 70 | | "AND newvalue='reopened' AND time>=%s AND time<=%s" % |
| | 69 | q.append("SELECT t1.time, t1.ticket AS idata, '' AS tdata, 4 AS type, " |
| | 70 | " '' AS message, t1.author, t0.category AS category " |
| | 71 | "FROM ticket_change t1 " |
| | 72 | " LEFT JOIN ticket t0 ON t0.id = t1.ticket " |
| | 73 | "WHERE t1.field='status' " |
| | 74 | "AND t1.newvalue='reopened' AND t1.time>=%s AND t1.time<=%s" % |
| 71 | 75 | (start, stop)) |
| 72 | 76 | q.append("SELECT t1.time AS time, t1.ticket AS idata," |
| 73 | 77 | " t2.newvalue AS tdata, 3 AS type," |
| 74 | | " t3.newvalue AS message, t1.author AS author" |
| | 78 | " t3.newvalue AS message, t1.author AS author, t0.category AS category" |
| 75 | 79 | " FROM ticket_change t1" |
| | 80 | " LEFT JOIN ticket t0 ON t0.id = t1.ticket" |
| 76 | 81 | " INNER JOIN ticket_change t2 ON t1.ticket = t2.ticket" |
| 77 | 82 | " AND t1.time = t2.time" |
| 78 | 83 | " LEFT OUTER JOIN ticket_change t3 ON t1.time = t3.time" |
| … |
… |
|
| 82 | 87 | " AND t1.time >= %s AND t1.time <= %s" % (start,stop)) |
| 83 | 88 | if wiki: |
| 84 | 89 | q.append("SELECT time, -1 AS idata, name AS tdata, 5 AS type, " |
| 85 | | "comment AS message, author " |
| | 90 | "comment AS message, author, '' AS category " |
| 86 | 91 | "FROM wiki WHERE time>=%s AND time<=%s" % |
| 87 | 92 | (start, stop)) |
| 88 | 93 | if milestone: |
| 89 | 94 | q.append("SELECT time, -1 AS idata, '' AS tdata, 6 AS type, " |
| 90 | | "name AS message, '' AS author " |
| | 95 | "name AS message, '' AS author, '' AS category " |
| 91 | 96 | "FROM milestone WHERE time>=%s AND time<=%s" % |
| 92 | 97 | (start, stop)) |
| 93 | 98 | |
| | 99 | if ticket_comments: |
| | 100 | q.append("SELECT t1.time AS time, t1.ticket AS idata, '' AS tdata, 7 AS type, " |
| | 101 | "t1.newvalue AS message, t1.author AS author, t0.category AS category " |
| | 102 | "FROM ticket_change t1" |
| | 103 | " LEFT JOIN ticket t0 ON t0.id = t1.ticket " |
| | 104 | "WHERE t1.field = 'comment' " |
| | 105 | "AND t1.time>=%s AND t1.time<=%s" % (start, stop)) |
| | 106 | |
| 94 | 107 | q_str = string.join(q, ' UNION ALL ') |
| 95 | 108 | q_str += ' ORDER BY time DESC' |
| 96 | 109 | if maxrows: |
| … |
… |
|
| 100 | 113 | |
| 101 | 114 | # Make the data more HDF-friendly |
| 102 | 115 | info = [] |
| | 116 | tickets = {} |
| 103 | 117 | while 1: |
| 104 | 118 | row = cursor.fetchone() |
| 105 | 119 | if not row: |
| … |
… |
|
| 113 | 127 | 'tdata': row['tdata'], |
| 114 | 128 | 'type': int(row['type']), |
| 115 | 129 | 'message': row['message'] or '', |
| | 130 | 'category': row['category'], |
| 116 | 131 | 'author': util.escape(row['author'] or 'anonymous') |
| 117 | 132 | } |
| 118 | 133 | |
| … |
… |
|
| 168 | 183 | elif item['type'] == MILESTONE: |
| 169 | 184 | item['href'] = self.env.href.milestone(item['message']) |
| 170 | 185 | item['message'] = util.escape(item['message']) |
| 171 | | else: # TICKET |
| | 186 | else: # all the TICKET types |
| 172 | 187 | item['href'] = self.env.href.ticket(item['idata']) |
| | 188 | if item['type'] == TICKET_COMMENT: |
| | 189 | # The following would be ok if there would be a cost effective way |
| | 190 | # to get that change number... |
| | 191 | # item['href'] += '#change_%d' % item['change'] |
| | 192 | pass |
| | 193 | else: |
| | 194 | tickets[(item['idata'], item['time'])] = 1 |
| 173 | 195 | msg = item['message'] |
| 174 | 196 | item['shortmsg'] = util.escape(util.shorten_line(msg)) |
| 175 | 197 | item['message'] = wiki_to_oneliner( |
| … |
… |
|
| 187 | 209 | item['message.rss'] = util.escape(item['message'] or '') |
| 188 | 210 | |
| 189 | 211 | info.append(item) |
| 190 | | return info |
| | 212 | # Ok, the following line is maybe not Python 2.1 friendly, I don't know... |
| | 213 | # return [ i for i in info if i['type'] != 7 or not tickets.has_key((i['idata'], i['time'])) ] |
| | 214 | info2 = [] |
| | 215 | for item in info: |
| | 216 | if item['type'] != 7 or not tickets.has_key((item['idata'], item['time'])): |
| | 217 | info2.append(item) |
| | 218 | return info2 |
| 191 | 219 | |
| 192 | 220 | def render (self): |
| 193 | 221 | self.perm.assert_permission(perm.TIMELINE_VIEW) |
| … |
… |
|
| 221 | 249 | |
| 222 | 250 | wiki = self.args.has_key('wiki') |
| 223 | 251 | ticket = self.args.has_key('ticket') |
| | 252 | ticket_comments = self.args.has_key('ticket_comments') |
| 224 | 253 | changeset = self.args.has_key('changeset') |
| 225 | 254 | milestone = self.args.has_key('milestone') |
| 226 | 255 | if not (wiki or ticket or changeset or milestone): |
| … |
… |
|
| 230 | 259 | self.req.hdf.setValue('timeline.wiki', 'checked') |
| 231 | 260 | if ticket: |
| 232 | 261 | self.req.hdf.setValue('timeline.ticket', 'checked') |
| | 262 | if ticket_comments: |
| | 263 | self.req.hdf.setValue('timeline.ticket_comments', 'checked') |
| 233 | 264 | if changeset: |
| 234 | 265 | self.req.hdf.setValue('timeline.changeset', 'checked') |
| 235 | 266 | if milestone: |
| 236 | 267 | self.req.hdf.setValue('timeline.milestone', 'checked') |
| 237 | 268 | |
| 238 | | info = self.get_info (start, stop, maxrows, ticket, |
| | 269 | info = self.get_info (start, stop, maxrows, ticket, ticket_comments, |
| 239 | 270 | changeset, wiki, milestone) |
| 240 | 271 | util.add_dictlist_to_hdf(info, self.req.hdf, 'timeline.items') |
| 241 | 272 | self.req.hdf.setValue('title', 'Timeline') |
=== trac/tests/wiki-tests.txt
==================================================================
|
|
|
|
| 127 | 127 | ------------------------------ |
| 128 | 128 | <h2>Heading with trailing white-space</h2> |
| 129 | 129 | ============================== |
| | 130 | [[HelloWorld(hej hopp)]] |
| | 131 | ------------------------------ |
| | 132 | <p> |
| | 133 | <pre class="wiki">hej hopp</pre> |
| | 134 | </p> |
| | 135 | ============================== |
| | 136 | [[HelloWorld(hej hopp) ]] # This shouldnt executed as macro since it contain whitespace between ) and ] |
| | 137 | ------------------------------ |
| | 138 | <p> |
| | 139 | [[HelloWorld(hej hopp) ]] # This shouldnt executed as macro since it contain whitespace between ) and ] |
| | 140 | </p> |
| | 141 | ============================== |
| | 142 | [[HelloWorld(hej hopp))]] # Extra right brace and still executed |
| | 143 | ------------------------------ |
| | 144 | <p> |
| | 145 | <pre class="wiki">hej hopp)</pre> # Extra right brace and still executed |
| | 146 | </p> |
| | 147 | ============================== |
| | 148 | [[HelloWorld(hej hopp)]] [[HelloWorld(hej hopp2)]] # Test non greedy match |
| | 149 | ------------------------------ |
| | 150 | <p> |
| | 151 | <pre class="wiki">hej hopp</pre> <pre class="wiki">hej hopp2</pre> # Test non greedy match |
| | 152 | </p> |
| | 153 | ============================== |
| | 154 | Inline [[html(<B> Test </B>)]] text |
| | 155 | ------------------------------ |
| | 156 | <p> |
| | 157 | Inline <B> Test </B> text |
| | 158 | </p> |
| | 159 | ============================== |
| 130 | 160 | A0B1, ST62T53C6, IR32V1H000 |
| 131 | 161 | ------------------------------ |
| 132 | 162 | <p> |
=== trac/tests/wiki.py
==================================================================
|
|
|
|
| 4 | 4 | |
| 5 | 5 | from Wiki import Formatter |
| 6 | 6 | |
| | 7 | |
| 7 | 8 | class WikiTestCase(unittest.TestCase): |
| 8 | 9 | def __init__(self, input, correct): |
| 9 | 10 | unittest.TestCase.__init__(self, 'test') |
| … |
… |
|
| 13 | 14 | def test(self): |
| 14 | 15 | """Testing WikiFormatter""" |
| 15 | 16 | import Href |
| | 17 | import Mimeview |
| 16 | 18 | class Environment: |
| 17 | 19 | def __init__(self): |
| 18 | 20 | self.href = Href.Href('/') |
| 19 | 21 | self._wiki_pages = {} |
| | 22 | self.mimeview = Mimeview.Mimeview(self) |
| 20 | 23 | class Cursor: |
| 21 | 24 | def execute(self, *kwargs): pass |
| 22 | 25 | def fetchone(self): return [] |
| … |
… |
|
| 28 | 31 | out = StringIO.StringIO() |
| 29 | 32 | Formatter(None, Environment(), Connection()).format(self.input, out) |
| 30 | 33 | if out.getvalue() != self.correct: |
| 31 | | print "'%s' != '%s'" % (out.getvalue(), self.correct) |
| | 34 | print "\n'%s' != \n'%s'" % (out.getvalue(), self.correct) |
| 32 | 35 | assert self.correct == out.getvalue() |
| 33 | 36 | |
| 34 | 37 | def suite(): |
=== trac/util.py
==================================================================
|
|
|
|
| 70 | 70 | .replace('>', '>') \ |
| 71 | 71 | .replace('"', '"') |
| 72 | 72 | |
| | 73 | def unescape(text): |
| | 74 | """Reverses Escapes &, <, > and \"""" |
| | 75 | if not text: |
| | 76 | return '' |
| | 77 | if type(text) is StringType: |
| | 78 | text = text.replace('"', '"') \ |
| | 79 | .replace('>', '>') \ |
| | 80 | .replace('<', '<') \ |
| | 81 | .replace('&', '&') |
| | 82 | return text |
| | 83 | |
| 73 | 84 | def get_first_line(text, maxlen): |
| 74 | 85 | """ |
| 75 | 86 | returns the first line of text. If the line is longer then |
=== trac/Log.py
==================================================================
|
|
|
|
| 53 | 53 | 'log.raw' : util.escape(log), |
| 54 | 54 | 'log' : wiki_to_oneliner(util.shorten_line(util.wiki_escape_newline(log)), self.req.hdf, self.env,self.db), |
| 55 | 55 | 'shortlog' : util.escape(shortlog), |
| | 56 | 'original_file_href': self.env.href.browser(self.path, rev), |
| 56 | 57 | 'file_href': self.env.href.browser(self.path, rev), |
| 57 | 58 | 'changeset_href': self.env.href.changeset(rev) |
| 58 | 59 | } |
| … |
… |
|
| 71 | 72 | # Loop through all revisions and update the path |
| 72 | 73 | # after each tag/branch/copy/rename. |
| 73 | 74 | path = self.path |
| | 75 | seq = len(self.log_info) |
| 74 | 76 | for item in self.log_info: |
| | 77 | item['seq'] = seq |
| | 78 | seq -= 1 |
| 75 | 79 | item['file_href'] = self.env.href.browser(path, item['rev']) |
| | 80 | item['intermediate_file_href'] = self.env.href.browser(path, item['rev']) |
| 76 | 81 | if self.branch_info.has_key(item['rev']): |
| 77 | 82 | for info in self.branch_info[item['rev']]: |
| 78 | 83 | if path[:len(info[1])] == info[1]: |
| 79 | 84 | rel_path = path[len(info[1]):] |
| 80 | 85 | path = info[0]+rel_path |
| | 86 | # Add suggested base revision for diffing |
| | 87 | prev = None |
| | 88 | log_info_backward = self.log_info[:] |
| | 89 | log_info_backward.reverse() |
| | 90 | for item in log_info_backward: |
| | 91 | if prev: |
| | 92 | item['diff'] = prev |
| | 93 | prev = item['rev'] |
| 81 | 94 | return self.log_info |
| 82 | 95 | |
| 83 | 96 | def generate_path_links(self, rev, rev_specified): |
=== trac/wikimacros/rst.py
==================================================================
|
|
|
|
| 43 | 43 | raise EnvironmentError, 'Docutils version >= %s required, %s found' % (docutils_required, __version__) |
| 44 | 44 | |
| 45 | 45 | from trac.Href import Href |
| | 46 | from trac.WikiFormatter import WikiProcessor |
| 46 | 47 | |
| 47 | 48 | __docformat__ = 'reStructuredText' |
| 48 | 49 | |
| 49 | | WIKI_LINK = re.compile(r'(?:wiki:)?(?P<w>[A-Za-z][\w\#\?]*[^\w\#\?]*)') # Links must begin with Letters, \# ? so we can link inside pages. |
| 50 | | #WIKI_LINK = re.compile(r'(?:wiki:)?(?P<w>(^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)') |
| | 50 | WIKI_LINK = re.compile(r'(?:wiki:)?(.+)') |
| | 51 | #WIKI_LINK = re.compile(r'(?:wiki:)?(?P<wikilink>[A-Za-z][\w\-]*[^\w\#\?]*)') |
| 51 | 52 | TICKET_LINK = re.compile(r'(?:#(\d+))|(?:ticket:(\d+))') |
| 52 | 53 | REPORT_LINK = re.compile(r'(?:{(\d+)})|(?:report:(\d+))') |
| 53 | 54 | CHANGESET_LINK = re.compile(r'(?:\[(\d+)\])|(?:changeset:(\d+))') |
| 54 | 55 | FILE_LINK = re.compile(r'(?:browser|repos|source):([^#]+)#?(.*)') |
| 55 | 56 | |
| | 57 | #import trac.Logging |
| | 58 | #log = trac.Logging.logger_factory(logtype='file', logfile="/tmp/debug_rst.txt", level='ALL') |
| | 59 | |
| 56 | 60 | def _wikipage(href, args): |
| 57 | 61 | return href.wiki(args[0]) |
| 58 | 62 | |
| … |
… |
|
| 71 | 75 | return href.browser(path, rev) |
| 72 | 76 | |
| 73 | 77 | # TracLink REs and callback functions |
| 74 | | LINKS = [(WIKI_LINK, _wikipage), |
| 75 | | (TICKET_LINK, _ticket), |
| | 78 | LINKS = [(TICKET_LINK, _ticket), |
| 76 | 79 | (REPORT_LINK, _report), |
| 77 | 80 | (CHANGESET_LINK, _changeset), |
| 78 | | (FILE_LINK, _browser)] |
| | 81 | (FILE_LINK, _browser), |
| | 82 | (WIKI_LINK, _wikipage)] |
| 79 | 83 | |
| 80 | 84 | |
| 81 | | def trac_get_reference(env, rawtext, text): |
| | 85 | def trac_get_reference(env, rawtext, link, text): |
| | 86 | |
| 82 | 87 | for (pattern, function) in LINKS: |
| 83 | | m = pattern.match(text) |
| | 88 | m = pattern.match(link) |
| 84 | 89 | if m: |
| 85 | 90 | g = filter(None, m.groups()) |
| 86 | 91 | missing = False |
| | 92 | if not text: |
| | 93 | text = g[0] |
| 87 | 94 | if pattern == WIKI_LINK: |
| 88 | | if not (env._wiki_pages.has_key(g[0])): |
| | 95 | pagename = re.search(r'^[^\#]+',g[0]) |
| | 96 | if not (env._wiki_pages.has_key(pagename.group())): |
| 89 | 97 | missing = True |
| 90 | | text = text + "?" |
| | 98 | text = text + "?" |
| 91 | 99 | uri = function(env.href, g) |
| 92 | 100 | reference = nodes.reference(rawtext, text) |
| 93 | 101 | reference['refuri']= uri |
| 94 | 102 | if missing: |
| 95 | 103 | reference.set_class('missing') |
| 96 | 104 | return reference |
| | 105 | |
| 97 | 106 | return None |
| 98 | 107 | |