Ticket #2041: trac-0.9-intertrac.patch
| File trac-0.9-intertrac.patch, 32.5 kB (added by cboos, 3 years ago) |
|---|
-
wiki-default/InterTrac
1 = InterTrac Extension for TracLinks = 2 3 ''This is a proposal for implementing #234''. 4 ''It's candidate for integration in the trunk, after the 0.9 release (see #2041)'' 5 6 == Definitions == 7 8 An InterTrac link is used for referring to a Trac object 9 (Wiki page, changeset, ticket, ...) located in another 10 Trac environment. 11 12 == Link Syntax == 13 14 {{{ 15 <target_environment>:<TracLinks> 16 }}} 17 18 The link is composed by the target environment name, 19 followed by a colon (e.g. `trac:`), 20 followed by a regular TracLinks, of any flavor. 21 22 That target environment name is either the real name of the 23 environment, or an alias for it. 24 The aliases are defined in `trac.ini` (see below). 25 The prefix is case insensitive. 26 27 For convenience, there's also an alternative short-hand form, 28 where one can use an alias as an immediate prefix 29 for the identifier of a ticket, changeset or report: 30 (e.g. `#T234`, `[T1508]`, `[trac 1508]`, ...) 31 32 == Examples == 33 34 Besides the other environments run by the same server process 35 (called ''sibling'' environments), which are automatically detected, 36 (''Note: currently only in `tracd`''), 37 it is necessary to setup a configuration for the InterTrac facility: 38 * in order to refer to a remote Trac 39 * for defining environment aliases 40 41 This is done quite simply in an `[intertrac]` section 42 within the `trac.ini` file. 43 44 Example configuration: 45 {{{ 46 ... 47 [intertrac] 48 ## -- Example of setting up an alias: 49 t = trac 50 51 ## -- Link to an external Trac: 52 trac.title = Edgewall's Trac for Trac 53 trac.url = http://projects.edgewall.com/trac 54 55 #trac.svn = http://repos.edgewall.com/projects/trac 56 # Hint: .svn information could be used in the future to support svn:externals... 57 }}} 58 59 Now, given this configuration, one could create the following links: 60 * to the current InterTrac page: 61 * `trac:wiki:InterTrac` -> 62 [http://projects.edgewall.com/trac/wiki/InterTrac trac:wiki:InterTrac] 63 * `t:wiki:InterTrac` -> 64 [http://projects.edgewall.com/trac/wiki/InterTrac t:wiki:InterTrac] 65 * Keys are case insensitive: `T:wiki:InterTrac` -> 66 [http://projects.edgewall.com/trac/wiki/InterTrac T:wiki:InterTrac] 67 * to the ticket #234: 68 * `trac:ticket:234` -> 69 [http://projects.edgewall.com/trac/ticket/234 trac:ticket:234] 70 * `trac:#234` -> 71 [http://projects.edgewall.com/trac/ticket/234 trac:#234] 72 * `#T234` -> 73 [http://projects.edgewall.com/trac/search?q=#234 #T234] 74 * to the changeset [1912]: 75 * `trac:changeset:1912` -> 76 [http://projects.edgewall.com/trac/changeset/1912 trac:changeset:1912] 77 * `trac:[1912]` -> 78 [http:"//projects.edgewall.com/trac/search?q=[1912]" "trac:[1912]"] 79 * `[T1912]` -> 80 [http://projects.edgewall.com/trac/changeset/1912 "[T1912]"] 81 82 Anything not given as explicit links (intertrac_prefix:module:id) 83 is interpreted by the remote Trac, relying on its quickjump 84 facility. 85 86 87 88 See also: TracLinks, InterWiki 89 90 ---- 91 == Implementation Notes == 92 93 Currently, the `[intertrac]` configuration has to be repeated 94 for each Trac environment, but there's work in progress concerning a 95 [ticket:1051 centralized trac.ini], which would help greatly here. 96 97 This idea was first proposed as a patch for #234, and 98 has been implemented in the following branch: 99 source:branches/cboos-dev/intertrac-branch 100 101 The general idea is that any `[a-zA-Z.+-]+:` prefix, 102 followed by anything which is not a space, has to be interpreted as: 103 1. maybe an alias to something else; if yes, it is dereferenced 104 before going on 105 1. then, it's maybe a link prefix given by an `IWikiSyntaxProvider` component 106 1. if not, it's maybe an environment name (!InterTrac link) 107 1. if not, it's maybe an !InterWiki link 108 1. if not, it is not a link -
wiki-default/InterMapTxt
Property changes on: wiki-default\InterTrac ___________________________________________________________________ Name: svn:mime-type + text/x-trac-wiki
1 = InterMapTxt = 2 == This is the place for defining InterWiki prefixes == 3 4 This page was modelled after the MeatBall:InterMapTxt page. 5 In addition, an optional comment is allowed after the mapping. 6 7 8 This page is interpreted in a special way by Trac, in order to support 9 !InterWiki links in a flexible and dynamic way. 10 11 The code block after the first line separator in this page 12 will be interpreted as a list of !InterWiki specifications: 13 {{{ 14 prefix <space> URL [<space> # comment] 15 }}} 16 17 By using `$1`, `$2`, etc. within the URL, it is possible to create 18 InterWiki links which support multiple arguments, e.g. Trac:ticket:40. 19 The URL itself can be optionally followed by a comment, 20 which will subsequently be used for decorating the links 21 using that prefix. 22 23 New !InterWiki links can be created by adding to that list, in real time. 24 Note however that ''deletions'' are also taken into account immediately, 25 so it may be better to use comments for disabling prefixes. 26 27 Also note that !InterWiki prefixes are case insensitive. 28 29 30 == List of Active Prefixes == 31 32 [[InterWiki]] 33 34 ---- 35 36 == Prefix Definitions == 37 38 {{{ 39 PEP http://www.python.org/peps/pep-$1.html # Python Enhancement Proposal 40 TracML http://thread.gmane.org/gmane.comp.version-control.subversion.trac.general/ # Trac Mailing List 41 42 # 43 # A arbitrary pick of InterWiki prefixes... 44 # 45 Acronym http://www.acronymfinder.com/af-query.asp?String=exact&Acronym= 46 C2find http://c2.com/cgi/wiki?FindPage&value= 47 Cache http://www.google.com/search?q=cache: 48 CPAN http://search.cpan.org/perldoc? 49 DebianBug http://bugs.debian.org/ 50 DebianPackage http://packages.debian.org/ 51 Dictionary http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query= 52 Google http://www.google.com/search?q= 53 GoogleGroups http://groups.google.com/groups?q= 54 JargonFile http://downlode.org/perl/jargon-redirect.cgi?term= 55 MeatBall http://www.usemod.com/cgi-bin/mb.pl? 56 MetaWiki http://sunir.org/apps/meta.pl? 57 MetaWikiPedia http://meta.wikipedia.org/wiki/ 58 MoinMoin http://moinmoin.wikiwikiweb.de/ 59 WhoIs http://www.whois.sc/ 60 Why http://clublet.com/c/c/why? 61 Wiki http://c2.com/cgi/wiki? 62 WikiPedia http://en.wikipedia.org/wiki/ 63 }}} -
wiki-default/WikiStart
Property changes on: wiki-default\InterMapTxt ___________________________________________________________________ Name: svn:mime-type + text/x-trac-wiki
1 = Welcome to Trac 0.9 =1 = Welcome to Trac 0.9-intertrac = 2 2 3 3 Trac is a '''minimalistic''' approach to '''web-based''' management of 4 4 '''software projects'''. Its goal is to simplify effective tracking and handling of software issues, enhancements and overall progress. -
wiki-default/checkwiki.py
15 15 # Pages to include in distribution 16 16 wiki_pages = [ 17 17 "CamelCase", 18 "InterMapTxt", 19 "InterTrac", 20 "InterWiki", 18 21 "RecentChanges", 19 22 "TitleIndex", 20 23 "TracAccessibility", -
wiki-default/InterWiki
1 = Support for InterWiki links = 2 3 ''This is a proposal for implementing #40 and #1414'' 4 ''It's candidate for integration in the trunk, after the 0.9 release (see #2041)'' 5 6 == Definition == 7 8 An InterWiki link can be used for referring to a Wiki page 9 located in another Wiki system, and by extension, to any object 10 located in any other Web application, provided a simple URL 11 mapping can be done. 12 13 == Link Syntax == 14 15 {{{ 16 <target_wiki>(:<identifier>)+ 17 }}} 18 19 The link is composed by the targeted Wiki (or system) name, 20 followed by a column (e.g. {{{MeatBall:}}}), 21 followed by a page specification in the target. 22 Note that, as for InterTrac prefixes, InterWiki prefixes are case insensitive. 23 24 The target Wiki URL is looked up in a the InterMapTxt wiki page, 25 modelled after 26 [http://www.usemod.com/cgi-bin/mb.pl?InterMapTxt MeatBall:InterMapTxt]. 27 28 An addition to traditional InterWiki links, where the target 29 is simply ''appended'' to the URL, 30 Trac supports parametric InterWiki URLs: 31 identifiers `$1`, `$2`, ... in the URL 32 will be replaced by corresponding arguments from a list 33 made up from the page specification split by the ":" token. 34 35 == Examples == 36 37 If the following is an excerpt of the InterMapTxt page: 38 39 {{{ 40 = InterMapTxt = 41 == This is the place for defining InterWiki prefixes == 42 43 Currently active prefixes: [[InterWiki]] 44 45 This page is modelled after the MeatBall:InterMapTxt page. 46 In addition, an optional comment is allowed after the mapping. 47 ---- 48 {{{ 49 PEP http://www.python.org/peps/pep-$1.html # Python Enhancement Proposal 50 TracML http://thread.gmane.org/gmane.comp.version-control.subversion.trac.general/ # Trac Mailing List 51 52 ... 53 MeatBall http://www.usemod.com/cgi-bin/mb.pl? 54 MetaWiki http://sunir.org/apps/meta.pl? 55 MetaWikiPedia http://meta.wikipedia.org/wiki/ 56 MoinMoin http://moinmoin.wikiwikiweb.de/ 57 ... 58 }}} 59 }}} 60 61 Then, 62 * `MoinMoin:InterWikiMap` should be rendered as 63 [http://moinmoin.wikiwikiweb.de/InterWikiMap MoinMoin:InterWikiMap] 64 and the ''title'' for that link would be "!InterWikiMap in !MoinMoin" 65 * {{{TracML:4346}}} should be rendered as 66 [http://thread.gmane.org/gmane.comp.version-control.subversion.trac.general/4346 TracML:4346] 67 and the ''title'' for that link would be "4346 in Trac Mailing List" 68 (idea: I should allow positional parameters in the comment as well) -
trac/env.py
Property changes on: wiki-default\InterWiki ___________________________________________________________________ Name: svn:mime-type + text/x-trac-wiki
74 74 ComponentManager.__init__(self) 75 75 76 76 self.path = path 77 self.siblings = {} 77 78 self.__cnx_pool = None 78 79 if create: 79 80 self.create(db_str) -
trac/ticket/api.py
19 19 from trac import util 20 20 from trac.core import * 21 21 from trac.perm import IPermissionRequestor 22 from trac.wiki import IWikiSyntaxProvider 22 from trac.wiki import IWikiSyntaxProvider, Formatter 23 23 from trac.Search import ISearchSource, query_to_sql, shorten_result 24 24 25 25 … … 140 140 ('ticket', self._format_link)] 141 141 142 142 def get_wiki_syntax(self): 143 yield (r"!?# \d+",144 lambda x, y, z: self._format_link(x, 'ticket', y[1:], y ))143 yield (r"!?#(?P<it_ticket>%s)?\d+" % Formatter.INTERTRAC_SCHEME, 144 lambda x, y, z: self._format_link(x, 'ticket', y[1:], y, z)) 145 145 146 def _format_link(self, formatter, ns, target, label): 146 def _format_link(self, formatter, ns, target, label, fullmatch=None): 147 intertrac = formatter.shorthand_intertrac_helper(ns, target, label, 148 fullmatch) 149 if intertrac: 150 return intertrac 147 151 cursor = formatter.db.cursor() 148 152 cursor.execute("SELECT summary,status FROM ticket WHERE id=%s", 149 153 (target,)) -
trac/ticket/report.py
24 24 from trac.perm import IPermissionRequestor 25 25 from trac.web import IRequestHandler 26 26 from trac.web.chrome import add_link, add_stylesheet, INavigationContributor 27 from trac.wiki import wiki_to_html, IWikiSyntaxProvider 27 from trac.wiki import wiki_to_html, IWikiSyntaxProvider, Formatter 28 28 29 29 30 30 dynvars_re = re.compile('\$([A-Z]+)') … … 510 510 yield ('report', self._format_link) 511 511 512 512 def get_wiki_syntax(self): 513 yield (r"!?\{\d+\}", lambda x, y, z: self._format_link(x, 'report', y[1:-1], y)) 513 yield (r"!?\{(?P<it_report>%s\s*)?\d+\}" % Formatter.INTERTRAC_SCHEME, 514 lambda x, y, z: self._format_link(x, 'report', y[1:-1], y, z)) 514 515 515 def _format_link(self, formatter, ns, target, label): 516 def _format_link(self, formatter, ns, target, label, fullmatch=None): 517 intertrac = formatter.shorthand_intertrac_helper(ns, target, label, 518 fullmatch) 519 if intertrac: 520 return intertrac 516 521 report, args = target, '' 517 522 if '?' in target: 518 523 report, args = target.split('?') -
trac/__init__.py
10 10 """ 11 11 __docformat__ = 'epytext en' 12 12 13 __version__ = '0.9 '13 __version__ = '0.9-intertrac' 14 14 __url__ = 'http://trac.edgewall.com/' 15 15 __copyright__ = '(C) 2003-2005 Edgewall Software' 16 16 __license__ = 'BSD' -
trac/versioncontrol/web_ui/changeset.py
30 30 from trac.versioncontrol.diff import get_diff_options, hdf_diff, unified_diff 31 31 from trac.web import IRequestHandler 32 32 from trac.web.chrome import add_link, add_stylesheet, INavigationContributor 33 from trac.wiki import wiki_to_html, wiki_to_oneliner, IWikiSyntaxProvider 33 from trac.wiki import wiki_to_html, wiki_to_oneliner, IWikiSyntaxProvider, \ 34 Formatter 34 35 35 36 36 37 class ChangesetModule(Component): … … 354 355 # IWikiSyntaxProvider methods 355 356 356 357 def get_wiki_syntax(self): 357 yield (r"!?\[\d+\]|(?:\b|!)r\d+\b(?!:\d)", 358 yield (r"!?\[(?P<it_changeset>%s\s*)?\d+\]|" \ 359 % Formatter.INTERTRAC_SCHEME + # [1], [T1] or [trac 1] 360 r"(?:\b|!)r\d+\b(?!:\d)", # r1 but not r1:2 358 361 lambda x, y, z: self._format_link(x, 'changeset', 359 362 y[0] == 'r' and y[1:] 360 or y[1:-1], y ))363 or y[1:-1], y, z)) 361 364 362 365 def get_link_resolvers(self): 363 366 yield ('changeset', self._format_link) 364 367 365 def _format_link(self, formatter, ns, rev, label): 368 def _format_link(self, formatter, ns, rev, label, fullmatch=None): 369 intertrac = formatter.shorthand_intertrac_helper(ns, rev, label, 370 fullmatch) 371 if intertrac: 372 return intertrac 366 373 cursor = formatter.db.cursor() 367 374 cursor.execute('SELECT message FROM revision WHERE rev=%s', (rev,)) 368 375 row = cursor.fetchone() -
trac/wiki/api.py
214 214 else: 215 215 return '<a class="wiki" href="%s">%s</a>' \ 216 216 % (formatter.href.wiki(page) + anchor, label) 217 -
trac/wiki/tests/wiki-tests.txt
51 51 <a class="ext-link" href="http://www.edgewall.com/"><span class="icon"></span>http://www.edgewall.com/</a> 52 52 ============================== 53 53 #1, [1], r1, {1} 54 #12, [12], r12, {12} 54 55 ------------------------------ 55 56 <p> 56 57 <a class="missing ticket" href="/ticket/1" rel="nofollow">#1</a>, <a class="missing changeset" href="/changeset/1" rel="nofollow">[1]</a>, <a class="missing changeset" href="/changeset/1" rel="nofollow">r1</a>, <a class="report" href="/report/1">{1}</a> 58 <a class="missing ticket" href="/ticket/12" rel="nofollow">#12</a>, <a class="missing changeset" href="/changeset/12" rel="nofollow">[12]</a>, <a class="missing changeset" href="/changeset/12" rel="nofollow">r12</a>, <a class="report" href="/report/12">{12}</a> 57 59 </p> 58 60 ------------------------------ 59 61 ============================== … … 137 139 </p> 138 140 ------------------------------ 139 141 ============================== 140 CamelCase,CamelCase.CamelCase: CamelCase142 CamelCase,CamelCase.CamelCase: CamelCase 141 143 ------------------------------ 142 144 <p> 143 <a class="missing wiki" href="/wiki/CamelCase" rel="nofollow">CamelCase?</a>,<a class="missing wiki" href="/wiki/CamelCase" rel="nofollow">CamelCase?</a>. CamelCase:CamelCase145 <a class="missing wiki" href="/wiki/CamelCase" rel="nofollow">CamelCase?</a>,<a class="missing wiki" href="/wiki/CamelCase" rel="nofollow">CamelCase?</a>.<a class="missing wiki" href="/wiki/CamelCase" rel="nofollow">CamelCase?</a>: <a class="missing wiki" href="/wiki/CamelCase" rel="nofollow">CamelCase?</a> 144 146 </p> 145 147 ------------------------------ 146 148 ============================== … … 855 857 ------------------------------ 856 858 || a || 857 859 || b || 860 ============================== 861 t:wiki:InterTrac 862 trac:wiki:InterTrac 863 [t:wiki:InterTrac intertrac] 864 [trac:wiki:InterTrac intertrac] 865 ------------------------------ 866 <p> 867 <a class="ext-link" href="http://projects.edgewall.com/trac/wiki/InterTrac" title="wiki:InterTrac in Trac's Trac"><span class="icon"></span>t:wiki:InterTrac</a> 868 <a class="ext-link" href="http://projects.edgewall.com/trac/wiki/InterTrac" title="wiki:InterTrac in Trac's Trac"><span class="icon"></span>trac:wiki:InterTrac</a> 869 <a class="ext-link" href="http://projects.edgewall.com/trac/wiki/InterTrac" title="wiki:InterTrac in Trac's Trac"><span class="icon"></span>intertrac</a> 870 <a class="ext-link" href="http://projects.edgewall.com/trac/wiki/InterTrac" title="wiki:InterTrac in Trac's Trac"><span class="icon"></span>intertrac</a> 871 </p> 872 ------------------------------ 873 ============================== 874 trac:ticket:2041 875 [trac:ticket:2041 Trac #2041] 876 #T2041 877 #trac2041 878 ------------------------------ 879 <p> 880 <a class="ext-link" href="http://projects.edgewall.com/trac/ticket/2041" title="ticket:2041 in Trac's Trac"><span class="icon"></span>trac:ticket:2041</a> 881 <a class="ext-link" href="http://projects.edgewall.com/trac/ticket/2041" title="ticket:2041 in Trac's Trac"><span class="icon"></span>Trac #2041</a> 882 <a class="ext-link" href="http://projects.edgewall.com/trac/ticket/2041" title="ticket:2041 in Trac's Trac"><span class="icon"></span>#T2041</a> 883 <a class="ext-link" href="http://projects.edgewall.com/trac/ticket/2041" title="ticket:2041 in Trac's Trac"><span class="icon"></span>#trac2041</a> 884 </p> 885 ------------------------------ 886 ============================== 887 trac:changeset:2081 888 [trac:changeset:2081 Trac r2081] 889 [T2081] 890 [trac2081] 891 [trac 2081] 892 ------------------------------ 893 <p> 894 <a class="ext-link" href="http://projects.edgewall.com/trac/changeset/2081" title="changeset:2081 in Trac's Trac"><span class="icon"></span>trac:changeset:2081</a> 895 <a class="ext-link" href="http://projects.edgewall.com/trac/changeset/2081" title="changeset:2081 in Trac's Trac"><span class="icon"></span>Trac r2081</a> 896 <a class="ext-link" href="http://projects.edgewall.com/trac/changeset/2081" title="changeset:2081 in Trac's Trac"><span class="icon"></span>[T2081]</a> 897 <a class="ext-link" href="http://projects.edgewall.com/trac/changeset/2081" title="changeset:2081 in Trac's Trac"><span class="icon"></span>[trac2081]</a> 898 <a class="ext-link" href="http://projects.edgewall.com/trac/changeset/2081" title="changeset:2081 in Trac's Trac"><span class="icon"></span>[trac 2081]</a> 899 </p> 900 ------------------------------ 901 ============================== 902 trac:report:1 903 [trac:report:1 Trac r1] 904 {T1} 905 {trac1} 906 {trac 1} 907 ------------------------------ 908 <p> 909 <a class="ext-link" href="http://projects.edgewall.com/trac/report/1" title="report:1 in Trac's Trac"><span class="icon"></span>trac:report:1</a> 910 <a class="ext-link" href="http://projects.edgewall.com/trac/report/1" title="report:1 in Trac's Trac"><span class="icon"></span>Trac r1</a> 911 <a class="ext-link" href="http://projects.edgewall.com/trac/report/1" title="report:1 in Trac's Trac"><span class="icon"></span>{T1}</a> 912 <a class="ext-link" href="http://projects.edgewall.com/trac/report/1" title="report:1 in Trac's Trac"><span class="icon"></span>{trac1}</a> 913 <a class="ext-link" href="http://projects.edgewall.com/trac/report/1" title="report:1 in Trac's Trac"><span class="icon"></span>{trac 1}</a> 914 </p> 915 ------------------------------ 916 ============================== 917 t:InterTrac 918 trac:InterTrac 919 [t:InterTrac intertrac] 920 [trac:InterTrac intertrac] 921 T:r2081 922 T:#2041 923 trac:#2041 924 ------------------------------ 925 <p> 926 <a class="ext-link" href="http://projects.edgewall.com/trac/search?q=InterTrac" title="InterTrac in Trac's Trac"><span class="icon"></span>t:InterTrac</a> 927 <a class="ext-link" href="http://projects.edgewall.com/trac/search?q=InterTrac" title="InterTrac in Trac's Trac"><span class="icon"></span>trac:InterTrac</a> 928 <a class="ext-link" href="http://projects.edgewall.com/trac/search?q=InterTrac" title="InterTrac in Trac's Trac"><span class="icon"></span>intertrac</a> 929 <a class="ext-link" href="http://projects.edgewall.com/trac/search?q=InterTrac" title="InterTrac in Trac's Trac"><span class="icon"></span>intertrac</a> 930 <a class="ext-link" href="http://projects.edgewall.com/trac/search?q=r2081" title="r2081 in Trac's Trac"><span class="icon"></span>T:r2081</a> 931 <a class="ext-link" href="http://projects.edgewall.com/trac/search?q=%232041" title="#2041 in Trac's Trac"><span class="icon"></span>T:#2041</a> 932 <a class="ext-link" href="http://projects.edgewall.com/trac/search?q=%232041" title="#2041 in Trac's Trac"><span class="icon"></span>trac:#2041</a> 933 </p> 934 ------------------------------ -
trac/wiki/tests/formatter.py
55 55 self.config = Configuration(None) 56 56 self.href = Href('/') 57 57 self.abs_href = Href('http://www.example.com/') 58 self._wiki_pages = {}59 58 self.path = '' 59 # -- intertrac support 60 self.siblings = {} 61 self.config.set('intertrac', 'trac.title', "Trac's Trac") 62 self.config.set('intertrac', 'trac.url', 63 "http://projects.edgewall.com/trac") 64 self.config.set('intertrac', 't', 'trac') 60 65 def component_activated(self, component): 61 66 component.env = self 62 67 component.config = self.config -
trac/wiki/formatter.py
27 27 from StringIO import StringIO 28 28 29 29 from trac import util 30 from trac.core import * 30 31 from trac.mimeview import * 31 from trac.wiki.api import WikiSystem 32 from trac.wiki.api import WikiSystem, IWikiChangeListener, IWikiMacroProvider 32 33 33 __all__ = ['wiki_to_html', 'wiki_to_oneliner', 'wiki_to_outline' ]34 __all__ = ['wiki_to_html', 'wiki_to_oneliner', 'wiki_to_outline', 'Formatter' ] 34 35 35 36 36 37 def system_message(msg, text): … … 134 135 INLINE_TOKEN = "`" 135 136 136 137 LINK_SCHEME = r"[\w.+-]+" # as per RFC 2396 138 INTERTRAC_SCHEME = r"[a-zA-Z.+-]+?" # no digits (support for shorthand links) 137 139 138 140 QUOTED_STRING = r"'[^']+'|\"[^\"]+\"" 139 141 … … 296 298 return self._make_link(ns, target, match, label) 297 299 298 300 def _make_link(self, ns, target, match, label): 301 # check first for an alias defined in trac.ini 302 ns = self.env.config.get('intertrac', ns.upper(), ns) 299 303 if ns in self.link_resolvers: 300 304 return self.link_resolvers[ns](self, ns, target, label) 301 305 elif target.startswith('//') or ns == "mailto": 302 306 return self._make_ext_link(ns+':'+target, label) 303 307 else: 304 return match 308 intertrac = self._make_intertrac_link(ns, target, label) 309 if intertrac: 310 return intertrac 311 else: 312 interwiki = self._make_interwiki_link(ns, target, label) 313 if interwiki: 314 return interwiki 315 else: 316 return match 305 317 318 def _make_intertrac_link(self, ns, target, label): 319 if self.env.siblings.has_key(ns): 320 sibling = self.env.siblings[ns] 321 if not hasattr(sibling, 'href'): 322 from trac.web.href import Href 323 def xchg_base(base): 324 return '/'.join(base.split('/')[:-1] + [ns]) 325 sibling.href = Href(xchg_base(self.env.href.base)) 326 sibling.abs_href = Href(xchg_base(self.env.abs_href.base)) 327 ref = wiki_to_oneliner(target, sibling) 328 return ref.replace('>%s' % target, '>%s' % label) 329 url = self.env.config.get('intertrac', ns.upper()+'.url') 330 if url: 331 name = self.env.config.get('intertrac', ns.upper()+'.title', 332 'Trac project %s' % ns) 333 sep = target.find(':') 334 if sep != -1: 335 url = '%s/%s/%s' % (url, target[:sep], target[sep+1:]) 336 else: 337 url = '%s/search?q=%s' % (url, urllib.quote_plus(target)) 338 return self._make_ext_link(url, label, '%s in %s' % (target, name)) 339 else: 340 return None 341 342 def shorthand_intertrac_helper(self, ns, target, label, fullmatch): 343 if fullmatch: # short form 344 it_grp = fullmatch.group('it_%s' % ns) 345 if it_grp: 346 alias = it_grp.strip() 347 intertrac = self.env.config.get('intertrac', alias.upper(), 348 alias) 349 target = '%s:%s' % (ns, target[len(it_grp):]) 350 it = self._make_intertrac_link(intertrac, target, label) 351 return it or label 352 return None 353 354 def _make_interwiki_link(self, ns, target, label): 355 interwiki = InterWikiMap(self.env) 356 if interwiki.has_key(ns): 357 url, title = interwiki.url(ns, target) 358 return self._make_ext_link(url, label, '%s in %s' % (target, title)) 359 else: 360 return None 361 306 362 def _make_ext_link(self, url, text, title=''): 307 363 title_attr = title and ' title="%s"' % title or '' 308 364 if Formatter.img_re.search(url) and self.flavor != 'oneliner': … … 762 818 OutlineFormatter(env, absurls, db).format(wikitext, out, max_depth, 763 819 min_depth) 764 820 return out.getvalue() 821 822 823 # -- InterWiki support 824 825 class InterWikiMap(Component): 826 827 implements(IWikiChangeListener, IWikiMacroProvider) 828 829 _page_name = 'InterMapTxt' 830 _interwiki_re = re.compile(r"(\w+)[ \t]+([^ \t]+)(?:[ \t]+#(.*))?", 831 re.UNICODE) 832 _argspec_re = re.compile(r"\$\d") 833 834 def __init__(self): 835 self._interwiki_map = None 836 # This dictionary maps upper-cased namespaces 837 # to (namespace, prefix, title) values 838 839 def has_key(self, ns): 840 if not self._interwiki_map: 841 self._update() 842 return self._interwiki_map.has_key(ns.upper()) 843 844 def url(self, ns, target): 845 ns, url, title = self._interwiki_map[ns.upper()] 846 args = target.split(':') 847 def setarg(match): 848 num = int(match.group()[1:]) 849 return 0 < num <= len(args) and args[num-1] or '' 850 url_with_args = re.sub(InterWikiMap._argspec_re, setarg, url) 851 if url_with_args == url: 852 return url + target, title 853 else: 854 return url_with_args, title 855 856 # IWikiChangeListener methods 857 858 def wiki_page_added(self, page): 859 if page.name == InterWikiMap._page_name: 860 self._update() 861 862 def wiki_page_changed(self, page, version, t, comment, author, ipnr): 863 if page.name == InterWikiMap._page_name: 864 self._update() 865 866 def wiki_page_deleted(self, page): 867 if page.name == InterWikiMap._page_name: 868 self._interwiki_map.clear() 869 870 def _update(self): 871 from trac.wiki.model import WikiPage 872 self._interwiki_map = {} 873 content = WikiPage(self.env, InterWikiMap._page_name).text 874 in_map = False 875 for line in content.split('\n'): 876 if in_map: 877 if line.startswith('----'): 878 in_map = False 879 else: 880 m = re.match(InterWikiMap._interwiki_re, line) 881 if m: 882 prefix, url, title = m.groups() 883 url = url.strip() 884 title = title and title.strip() or prefix 885 self._interwiki_map[prefix.upper()] = (prefix, url, 886 title) 887 elif line.startswith('----'): 888 in_map = True 889 890 # IWikiMacroProvider 891 892 def get_macros(self): 893 yield 'InterWiki' 894 895 def get_macro_description(self, name): 896 return "Provide a description list for the known InterWiki prefixes." 897 898 def render_macro(self, req, name, content): 899 if not self._interwiki_map: 900 self._update() 901 keys = self._interwiki_map.keys() 902 keys.sort() 903 buf = StringIO() 904 buf.write('<table><tr><th>Prefix</th><td>Site</td></tr>\n') 905 for k in keys: 906 prefix, url, title = self._interwiki_map[k] 907 shortened_url = url and url[:-1] 908 description = title == prefix and shortened_url or title 909 buf.write('<tr>\n' + 910 ('<td><a href="%sRecentChanges">%s</a></td>'<
