##// END OF EJS Templates
#107 added single line highlight
marcink -
r965:5da1286d beta
parent child Browse files
Show More
@@ -1,528 +1,528 b''
1 1 """Helper functions
2 2
3 3 Consists of functions to typically be used within templates, but also
4 4 available to Controllers. This module is available to both as 'h'.
5 5 """
6 6 import random
7 7 import hashlib
8 8 from pygments.formatters import HtmlFormatter
9 9 from pygments import highlight as code_highlight
10 10 from pylons import url, app_globals as g
11 11 from pylons.i18n.translation import _, ungettext
12 12 from vcs.utils.annotate import annotate_highlight
13 13 from webhelpers.html import literal, HTML, escape
14 14 from webhelpers.html.tools import *
15 15 from webhelpers.html.builder import make_tag
16 16 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
17 17 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
18 18 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
19 19 password, textarea, title, ul, xml_declaration, radio
20 20 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
21 21 mail_to, strip_links, strip_tags, tag_re
22 22 from webhelpers.number import format_byte_size, format_bit_size
23 23 from webhelpers.pylonslib import Flash as _Flash
24 24 from webhelpers.pylonslib.secure_form import secure_form
25 25 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
26 26 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
27 27 replace_whitespace, urlify, truncate, wrap_paragraphs
28 28 from webhelpers.date import time_ago_in_words
29 29
30 30 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
31 31 convert_boolean_attrs, NotGiven
32 32
33 33 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
34 34 """Reset button
35 35 """
36 36 _set_input_attrs(attrs, type, name, value)
37 37 _set_id_attr(attrs, id, name)
38 38 convert_boolean_attrs(attrs, ["disabled"])
39 39 return HTML.input(**attrs)
40 40
41 41 reset = _reset
42 42
43 43
44 44 def get_token():
45 45 """Return the current authentication token, creating one if one doesn't
46 46 already exist.
47 47 """
48 48 token_key = "_authentication_token"
49 49 from pylons import session
50 50 if not token_key in session:
51 51 try:
52 52 token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
53 53 except AttributeError: # Python < 2.4
54 54 token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
55 55 session[token_key] = token
56 56 if hasattr(session, 'save'):
57 57 session.save()
58 58 return session[token_key]
59 59
60 60 class _GetError(object):
61 61 """Get error from form_errors, and represent it as span wrapped error
62 62 message
63 63
64 64 :param field_name: field to fetch errors for
65 65 :param form_errors: form errors dict
66 66 """
67 67
68 68 def __call__(self, field_name, form_errors):
69 69 tmpl = """<span class="error_msg">%s</span>"""
70 70 if form_errors and form_errors.has_key(field_name):
71 71 return literal(tmpl % form_errors.get(field_name))
72 72
73 73 get_error = _GetError()
74 74
75 75 def recursive_replace(str, replace=' '):
76 76 """Recursive replace of given sign to just one instance
77 77
78 78 :param str: given string
79 79 :param replace: char to find and replace multiple instances
80 80
81 81 Examples::
82 82 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
83 83 'Mighty-Mighty-Bo-sstones'
84 84 """
85 85
86 86 if str.find(replace * 2) == -1:
87 87 return str
88 88 else:
89 89 str = str.replace(replace * 2, replace)
90 90 return recursive_replace(str, replace)
91 91
92 92 class _ToolTip(object):
93 93
94 94 def __call__(self, tooltip_title, trim_at=50):
95 95 """Special function just to wrap our text into nice formatted
96 96 autowrapped text
97 97
98 98 :param tooltip_title:
99 99 """
100 100
101 101 return wrap_paragraphs(escape(tooltip_title), trim_at)\
102 102 .replace('\n', '<br/>')
103 103
104 104 def activate(self):
105 105 """Adds tooltip mechanism to the given Html all tooltips have to have
106 106 set class `tooltip` and set attribute `tooltip_title`.
107 107 Then a tooltip will be generated based on that. All with yui js tooltip
108 108 """
109 109
110 110 js = '''
111 111 YAHOO.util.Event.onDOMReady(function(){
112 112 function toolTipsId(){
113 113 var ids = [];
114 114 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
115 115
116 116 for (var i = 0; i < tts.length; i++) {
117 117 //if element doesn't not have and id autogenerate one for tooltip
118 118
119 119 if (!tts[i].id){
120 120 tts[i].id='tt'+i*100;
121 121 }
122 122 ids.push(tts[i].id);
123 123 }
124 124 return ids
125 125 };
126 126 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
127 127 context: toolTipsId(),
128 128 monitorresize:false,
129 129 xyoffset :[0,0],
130 130 autodismissdelay:300000,
131 131 hidedelay:5,
132 132 showdelay:20,
133 133 });
134 134
135 135 // Set the text for the tooltip just before we display it. Lazy method
136 136 myToolTips.contextTriggerEvent.subscribe(
137 137 function(type, args) {
138 138
139 139 var context = args[0];
140 140
141 141 //positioning of tooltip
142 142 var tt_w = this.element.clientWidth;//tooltip width
143 143 var tt_h = this.element.clientHeight;//tooltip height
144 144
145 145 var context_w = context.offsetWidth;
146 146 var context_h = context.offsetHeight;
147 147
148 148 var pos_x = YAHOO.util.Dom.getX(context);
149 149 var pos_y = YAHOO.util.Dom.getY(context);
150 150
151 151 var display_strategy = 'right';
152 152 var xy_pos = [0,0];
153 153 switch (display_strategy){
154 154
155 155 case 'top':
156 156 var cur_x = (pos_x+context_w/2)-(tt_w/2);
157 157 var cur_y = (pos_y-tt_h-4);
158 158 xy_pos = [cur_x,cur_y];
159 159 break;
160 160 case 'bottom':
161 161 var cur_x = (pos_x+context_w/2)-(tt_w/2);
162 162 var cur_y = pos_y+context_h+4;
163 163 xy_pos = [cur_x,cur_y];
164 164 break;
165 165 case 'left':
166 166 var cur_x = (pos_x-tt_w-4);
167 167 var cur_y = pos_y-((tt_h/2)-context_h/2);
168 168 xy_pos = [cur_x,cur_y];
169 169 break;
170 170 case 'right':
171 171 var cur_x = (pos_x+context_w+4);
172 172 var cur_y = pos_y-((tt_h/2)-context_h/2);
173 173 xy_pos = [cur_x,cur_y];
174 174 break;
175 175 default:
176 176 var cur_x = (pos_x+context_w/2)-(tt_w/2);
177 177 var cur_y = pos_y-tt_h-4;
178 178 xy_pos = [cur_x,cur_y];
179 179 break;
180 180
181 181 }
182 182
183 183 this.cfg.setProperty("xy",xy_pos);
184 184
185 185 });
186 186
187 187 //Mouse out
188 188 myToolTips.contextMouseOutEvent.subscribe(
189 189 function(type, args) {
190 190 var context = args[0];
191 191
192 192 });
193 193 });
194 194 '''
195 195 return literal(js)
196 196
197 197 tooltip = _ToolTip()
198 198
199 199 class _FilesBreadCrumbs(object):
200 200
201 201 def __call__(self, repo_name, rev, paths):
202 202 if isinstance(paths, str):
203 203 paths = paths.decode('utf-8')
204 204 url_l = [link_to(repo_name, url('files_home',
205 205 repo_name=repo_name,
206 206 revision=rev, f_path=''))]
207 207 paths_l = paths.split('/')
208 208 for cnt, p in enumerate(paths_l):
209 209 if p != '':
210 210 url_l.append(link_to(p, url('files_home',
211 211 repo_name=repo_name,
212 212 revision=rev,
213 213 f_path='/'.join(paths_l[:cnt + 1]))))
214 214
215 215 return literal('/'.join(url_l))
216 216
217 217 files_breadcrumbs = _FilesBreadCrumbs()
218 218
219 219 class CodeHtmlFormatter(HtmlFormatter):
220 220
221 221 def wrap(self, source, outfile):
222 222 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
223 223
224 224 def _wrap_code(self, source):
225 225 for cnt, it in enumerate(source):
226 226 i, t = it
227 t = '<div id="#S-%s">%s</div>' % (cnt + 1, t)
227 t = '<div id="L-%s">%s</div>' % (cnt + 1, t)
228 228 yield i, t
229 229 def pygmentize(filenode, **kwargs):
230 230 """pygmentize function using pygments
231 231
232 232 :param filenode:
233 233 """
234 234
235 235 return literal(code_highlight(filenode.content,
236 236 filenode.lexer, CodeHtmlFormatter(**kwargs)))
237 237
238 238 def pygmentize_annotation(filenode, **kwargs):
239 239 """pygmentize function for annotation
240 240
241 241 :param filenode:
242 242 """
243 243
244 244 color_dict = {}
245 245 def gen_color(n=10000):
246 246 """generator for getting n of evenly distributed colors using
247 247 hsv color and golden ratio. It always return same order of colors
248 248
249 249 :returns: RGB tuple
250 250 """
251 251 import colorsys
252 252 golden_ratio = 0.618033988749895
253 253 h = 0.22717784590367374
254 254
255 255 for c in xrange(n):
256 256 h += golden_ratio
257 257 h %= 1
258 258 HSV_tuple = [h, 0.95, 0.95]
259 259 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
260 260 yield map(lambda x:str(int(x * 256)), RGB_tuple)
261 261
262 262 cgenerator = gen_color()
263 263
264 264 def get_color_string(cs):
265 265 if color_dict.has_key(cs):
266 266 col = color_dict[cs]
267 267 else:
268 268 col = color_dict[cs] = cgenerator.next()
269 269 return "color: rgb(%s)! important;" % (', '.join(col))
270 270
271 271 def url_func(changeset):
272 272 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
273 273 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
274 274
275 275 tooltip_html = tooltip_html % (changeset.author,
276 276 changeset.date,
277 277 tooltip(changeset.message))
278 278 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
279 279 short_id(changeset.raw_id))
280 280 uri = link_to(
281 281 lnk_format,
282 282 url('changeset_home', repo_name=changeset.repository.name,
283 283 revision=changeset.raw_id),
284 284 style=get_color_string(changeset.raw_id),
285 285 class_='tooltip',
286 286 title=tooltip_html
287 287 )
288 288
289 289 uri += '\n'
290 290 return uri
291 291 return literal(annotate_highlight(filenode, url_func, **kwargs))
292 292
293 293 def repo_name_slug(value):
294 294 """Return slug of name of repository
295 295 This function is called on each creation/modification
296 296 of repository to prevent bad names in repo
297 297 """
298 298
299 299 slug = remove_formatting(value)
300 300 slug = strip_tags(slug)
301 301
302 302 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
303 303 slug = slug.replace(c, '-')
304 304 slug = recursive_replace(slug, '-')
305 305 slug = collapse(slug, '-')
306 306 return slug
307 307
308 308 def get_changeset_safe(repo, rev):
309 309 from vcs.backends.base import BaseRepository
310 310 from vcs.exceptions import RepositoryError
311 311 if not isinstance(repo, BaseRepository):
312 312 raise Exception('You must pass an Repository '
313 313 'object as first argument got %s', type(repo))
314 314
315 315 try:
316 316 cs = repo.get_changeset(rev)
317 317 except RepositoryError:
318 318 from rhodecode.lib.utils import EmptyChangeset
319 319 cs = EmptyChangeset()
320 320 return cs
321 321
322 322
323 323 flash = _Flash()
324 324
325 325
326 326 #==============================================================================
327 327 # MERCURIAL FILTERS available via h.
328 328 #==============================================================================
329 329 from mercurial import util
330 330 from mercurial.templatefilters import person as _person
331 331
332 332 def _age(curdate):
333 333 """turns a datetime into an age string."""
334 334
335 335 if not curdate:
336 336 return ''
337 337
338 338 from datetime import timedelta, datetime
339 339
340 340 agescales = [("year", 3600 * 24 * 365),
341 341 ("month", 3600 * 24 * 30),
342 342 ("day", 3600 * 24),
343 343 ("hour", 3600),
344 344 ("minute", 60),
345 345 ("second", 1), ]
346 346
347 347 age = datetime.now() - curdate
348 348 age_seconds = (age.days * agescales[2][1]) + age.seconds
349 349 pos = 1
350 350 for scale in agescales:
351 351 if scale[1] <= age_seconds:
352 352 if pos == 6:pos = 5
353 353 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
354 354 pos += 1
355 355
356 356 return _('just now')
357 357
358 358 age = lambda x:_age(x)
359 359 capitalize = lambda x: x.capitalize()
360 360 email = util.email
361 361 email_or_none = lambda x: util.email(x) if util.email(x) != x else None
362 362 person = lambda x: _person(x)
363 363 short_id = lambda x: x[:12]
364 364
365 365
366 366 def bool2icon(value):
367 367 """Returns True/False values represented as small html image of true/false
368 368 icons
369 369
370 370 :param value: bool value
371 371 """
372 372
373 373 if value is True:
374 374 return HTML.tag('img', src="/images/icons/accept.png", alt=_('True'))
375 375
376 376 if value is False:
377 377 return HTML.tag('img', src="/images/icons/cancel.png", alt=_('False'))
378 378
379 379 return value
380 380
381 381
382 382 def action_parser(user_log):
383 383 """This helper will map the specified string action into translated
384 384 fancy names with icons and links
385 385
386 386 :param user_log: user log instance
387 387 """
388 388
389 389 action = user_log.action
390 390 action_params = ' '
391 391
392 392 x = action.split(':')
393 393
394 394 if len(x) > 1:
395 395 action, action_params = x
396 396
397 397 def get_cs_links():
398 398 revs_limit = 5 #display this amount always
399 399 revs_top_limit = 50 #show upto this amount of changesets hidden
400 400 revs = action_params.split(',')
401 401 repo_name = user_log.repository.repo_name
402 402 from rhodecode.model.scm import ScmModel
403 403
404 404 message = lambda rev: get_changeset_safe(ScmModel().get(repo_name),
405 405 rev).message
406 406
407 407 cs_links = " " + ', '.join ([link_to(rev,
408 408 url('changeset_home',
409 409 repo_name=repo_name,
410 410 revision=rev), title=tooltip(message(rev)),
411 411 class_='tooltip') for rev in revs[:revs_limit] ])
412 412 if len(revs) > revs_limit:
413 413 uniq_id = revs[0]
414 414 html_tmpl = ('<span> %s '
415 415 '<a class="show_more" id="_%s" href="#">%s</a> '
416 416 '%s</span>')
417 417 cs_links += html_tmpl % (_('and'), uniq_id, _('%s more') \
418 418 % (len(revs) - revs_limit),
419 419 _('revisions'))
420 420
421 421 html_tmpl = '<span id="%s" style="display:none"> %s </span>'
422 422 cs_links += html_tmpl % (uniq_id, ', '.join([link_to(rev,
423 423 url('changeset_home',
424 424 repo_name=repo_name, revision=rev),
425 425 title=message(rev), class_='tooltip')
426 426 for rev in revs[revs_limit:revs_top_limit]]))
427 427
428 428 return cs_links
429 429
430 430 def get_fork_name():
431 431 from rhodecode.model.scm import ScmModel
432 432 repo_name = action_params
433 433 repo = ScmModel().get(repo_name)
434 434 if repo is None:
435 435 return repo_name
436 436 return link_to(action_params, url('summary_home',
437 437 repo_name=repo.name,),
438 438 title=repo.dbrepo.description)
439 439
440 440 map = {'user_deleted_repo':(_('User [deleted] repository'), None),
441 441 'user_created_repo':(_('User [created] repository'), None),
442 442 'user_forked_repo':(_('User [forked] repository as:'), get_fork_name),
443 443 'user_updated_repo':(_('User [updated] repository'), None),
444 444 'admin_deleted_repo':(_('Admin [delete] repository'), None),
445 445 'admin_created_repo':(_('Admin [created] repository'), None),
446 446 'admin_forked_repo':(_('Admin [forked] repository'), None),
447 447 'admin_updated_repo':(_('Admin [updated] repository'), None),
448 448 'push':(_('[Pushed]'), get_cs_links),
449 449 'pull':(_('[Pulled]'), None),
450 450 'started_following_repo':(_('User [started following] repository'), None),
451 451 'stopped_following_repo':(_('User [stopped following] repository'), None),
452 452 }
453 453
454 454 action_str = map.get(action, action)
455 455 action = action_str[0].replace('[', '<span class="journal_highlight">')\
456 456 .replace(']', '</span>')
457 457 if action_str[1] is not None:
458 458 action = action + " " + action_str[1]()
459 459
460 460 return literal(action)
461 461
462 462 def action_parser_icon(user_log):
463 463 action = user_log.action
464 464 action_params = None
465 465 x = action.split(':')
466 466
467 467 if len(x) > 1:
468 468 action, action_params = x
469 469
470 470 tmpl = """<img src="/images/icons/%s" alt="%s"/>"""
471 471 map = {'user_deleted_repo':'database_delete.png',
472 472 'user_created_repo':'database_add.png',
473 473 'user_forked_repo':'arrow_divide.png',
474 474 'user_updated_repo':'database_edit.png',
475 475 'admin_deleted_repo':'database_delete.png',
476 476 'admin_created_repo':'database_add.png',
477 477 'admin_forked_repo':'arrow_divide.png',
478 478 'admin_updated_repo':'database_edit.png',
479 479 'push':'script_add.png',
480 480 'pull':'down_16.png',
481 481 'started_following_repo':'heart_add.png',
482 482 'stopped_following_repo':'heart_delete.png',
483 483 }
484 484 return literal(tmpl % (map.get(action, action), action))
485 485
486 486
487 487 #==============================================================================
488 488 # PERMS
489 489 #==============================================================================
490 490 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
491 491 HasRepoPermissionAny, HasRepoPermissionAll
492 492
493 493 #==============================================================================
494 494 # GRAVATAR URL
495 495 #==============================================================================
496 496 import hashlib
497 497 import urllib
498 498 from pylons import request
499 499
500 500 def gravatar_url(email_address, size=30):
501 501 ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
502 502 default = 'identicon'
503 503 baseurl_nossl = "http://www.gravatar.com/avatar/"
504 504 baseurl_ssl = "https://secure.gravatar.com/avatar/"
505 505 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
506 506
507 507
508 508 # construct the url
509 509 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
510 510 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
511 511
512 512 return gravatar_url
513 513
514 514 def safe_unicode(str):
515 515 """safe unicode function. In case of UnicodeDecode error we try to return
516 516 unicode with errors replace, if this failes we return unicode with
517 517 string_escape decoding """
518 518
519 519 try:
520 520 u_str = unicode(str)
521 521 except UnicodeDecodeError:
522 522 try:
523 523 u_str = unicode(str, 'utf-8', 'replace')
524 524 except UnicodeDecodeError:
525 525 #incase we have a decode error just represent as byte string
526 526 u_str = unicode(str(str).encode('string_escape'))
527 527
528 528 return u_str
@@ -1,119 +1,123 b''
1 1 div.codeblock {
2 2 overflow: auto;
3 3 padding: 0px;
4 4 border: 1px solid #ccc;
5 5 background: #f8f8f8;
6 6 font-size: 100%;
7 7 line-height: 100%;
8 8 /* new */
9 9 line-height: 125%;
10 10 }
11 11 div.codeblock .code-header{
12 12 border-bottom: 1px solid #CCCCCC;
13 13 background: #EEEEEE;
14 14 padding:10px 0 10px 0;
15 15 }
16 16 div.codeblock .code-header .revision{
17 17 margin-left:25px;
18 18 font-weight: bold;
19 19 }
20 20 div.codeblock .code-header .commit{
21 21 margin-left:25px;
22 22 font-weight: normal;
23 23 white-space:pre;
24 24 }
25 25
26 26 div.codeblock .code-body table{
27 27 width: 0 !important;
28 28 }
29 29 div.code-body {
30 30 background-color: #FFFFFF;
31 31 }
32 32 div.code-body pre .match{
33 33 background-color: #FAFFA6;
34 34 }
35 35 div.code-body pre .break{
36 36 background-color: #DDE7EF;
37 37 width: 100%;
38 38 color: #747474;
39 39 display: block;
40 40
41 41 }
42 42 div.annotatediv{
43 43 margin-left:2px;
44 44 margin-right:4px;
45 45 }
46 46 .code-highlight {
47 47 padding: 0px;
48 48 margin-top: 5px;
49 49 margin-bottom: 5px;
50 50 border-left: 2px solid #ccc;
51 51 }
52 52 .code-highlight pre, .linenodiv pre {
53 53 padding: 5px;
54 54 margin: 0;
55 55 }
56 .code-highlight pre div:target {
57 background-color: #FFFFBE !important;
58 }
59
56 60 .linenos a { text-decoration: none; }
57 61
58 62 .code { display: block; }
59 63 .code-highlight .hll { background-color: #ffffcc }
60 64 .code-highlight .c { color: #408080; font-style: italic } /* Comment */
61 65 .code-highlight .err { border: 1px solid #FF0000 } /* Error */
62 66 .code-highlight .k { color: #008000; font-weight: bold } /* Keyword */
63 67 .code-highlight .o { color: #666666 } /* Operator */
64 68 .code-highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
65 69 .code-highlight .cp { color: #BC7A00 } /* Comment.Preproc */
66 70 .code-highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
67 71 .code-highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
68 72 .code-highlight .gd { color: #A00000 } /* Generic.Deleted */
69 73 .code-highlight .ge { font-style: italic } /* Generic.Emph */
70 74 .code-highlight .gr { color: #FF0000 } /* Generic.Error */
71 75 .code-highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
72 76 .code-highlight .gi { color: #00A000 } /* Generic.Inserted */
73 77 .code-highlight .go { color: #808080 } /* Generic.Output */
74 78 .code-highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
75 79 .code-highlight .gs { font-weight: bold } /* Generic.Strong */
76 80 .code-highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
77 81 .code-highlight .gt { color: #0040D0 } /* Generic.Traceback */
78 82 .code-highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
79 83 .code-highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
80 84 .code-highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
81 85 .code-highlight .kp { color: #008000 } /* Keyword.Pseudo */
82 86 .code-highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
83 87 .code-highlight .kt { color: #B00040 } /* Keyword.Type */
84 88 .code-highlight .m { color: #666666 } /* Literal.Number */
85 89 .code-highlight .s { color: #BA2121 } /* Literal.String */
86 90 .code-highlight .na { color: #7D9029 } /* Name.Attribute */
87 91 .code-highlight .nb { color: #008000 } /* Name.Builtin */
88 92 .code-highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
89 93 .code-highlight .no { color: #880000 } /* Name.Constant */
90 94 .code-highlight .nd { color: #AA22FF } /* Name.Decorator */
91 95 .code-highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
92 96 .code-highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
93 97 .code-highlight .nf { color: #0000FF } /* Name.Function */
94 98 .code-highlight .nl { color: #A0A000 } /* Name.Label */
95 99 .code-highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
96 100 .code-highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
97 101 .code-highlight .nv { color: #19177C } /* Name.Variable */
98 102 .code-highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
99 103 .code-highlight .w { color: #bbbbbb } /* Text.Whitespace */
100 104 .code-highlight .mf { color: #666666 } /* Literal.Number.Float */
101 105 .code-highlight .mh { color: #666666 } /* Literal.Number.Hex */
102 106 .code-highlight .mi { color: #666666 } /* Literal.Number.Integer */
103 107 .code-highlight .mo { color: #666666 } /* Literal.Number.Oct */
104 108 .code-highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
105 109 .code-highlight .sc { color: #BA2121 } /* Literal.String.Char */
106 110 .code-highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
107 111 .code-highlight .s2 { color: #BA2121 } /* Literal.String.Double */
108 112 .code-highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
109 113 .code-highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
110 114 .code-highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
111 115 .code-highlight .sx { color: #008000 } /* Literal.String.Other */
112 116 .code-highlight .sr { color: #BB6688 } /* Literal.String.Regex */
113 117 .code-highlight .s1 { color: #BA2121 } /* Literal.String.Single */
114 118 .code-highlight .ss { color: #19177C } /* Literal.String.Symbol */
115 119 .code-highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
116 120 .code-highlight .vc { color: #19177C } /* Name.Variable.Class */
117 121 .code-highlight .vg { color: #19177C } /* Name.Variable.Global */
118 122 .code-highlight .vi { color: #19177C } /* Name.Variable.Instance */
119 123 .code-highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
@@ -1,57 +1,57 b''
1 1 <dl>
2 2 <dt>${_('Revision')}</dt>
3 3 <dd>
4 4 ${h.link_to("r%s:%s" % (c.files_list.last_changeset.revision,h.short_id(c.files_list.last_changeset.raw_id)),
5 5 h.url('changeset_home',repo_name=c.repo_name,revision=c.files_list.last_changeset.raw_id))}
6 6 </dd>
7 7 <dt>${_('Size')}</dt>
8 8 <dd>${h.format_byte_size(c.files_list.size,binary=True)}</dd>
9 9 <dt>${_('Mimetype')}</dt>
10 10 <dd>${c.files_list.mimetype}</dd>
11 11 <dt>${_('Options')}</dt>
12 12 <dd>${h.link_to(_('show annotation'),
13 13 h.url('files_annotate_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
14 14 / ${h.link_to(_('show as raw'),
15 15 h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
16 16 / ${h.link_to(_('download as raw'),
17 17 h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
18 18 </dd>
19 19 <dt>${_('History')}</dt>
20 20 <dd>
21 21 <div>
22 22 ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
23 23 ${h.hidden('diff2',c.files_list.last_changeset.raw_id)}
24 24 ${h.select('diff1',c.files_list.last_changeset.raw_id,c.file_history)}
25 25 ${h.submit('diff','diff to revision',class_="ui-button")}
26 26 ${h.submit('show_rev','show at revision',class_="ui-button")}
27 27 ${h.end_form()}
28 28 </div>
29 29 </dd>
30 30 </dl>
31 31
32 32
33 33 <div id="body" class="codeblock">
34 34 <div class="code-header">
35 35 <div class="revision">${c.files_list.name}@r${c.files_list.last_changeset.revision}:${h.short_id(c.files_list.last_changeset.raw_id)}</div>
36 36 <div class="commit">"${c.files_list.last_changeset.message}"</div>
37 37 </div>
38 38 <div class="code-body">
39 39 % if c.files_list.size < c.cut_off_limit:
40 ${h.pygmentize(c.files_list,linenos=True,anchorlinenos=True,lineanchors='S',cssclass="code-highlight")}
40 ${h.pygmentize(c.files_list,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
41 41 %else:
42 42 ${_('File is to big to display')} ${h.link_to(_('show as raw'),
43 43 h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
44 44 %endif
45 45 </div>
46 46 </div>
47 47
48 48 <script type="text/javascript">
49 49 YAHOO.util.Event.onDOMReady(function(){
50 50 YAHOO.util.Event.addListener('show_rev','click',function(e){
51 51 YAHOO.util.Event.preventDefault(e);
52 52 var cs = YAHOO.util.Dom.get('diff1').value;
53 53 var url = "${h.url('files_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
54 54 window.location = url;
55 55 });
56 56 });
57 57 </script> No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now