diff --git a/trac/wiki/api.py b/trac/wiki/api.py
|
a
|
b
|
|
| 307 | 307 | if version and query: |
| 308 | 308 | query = '&' + query[1:] |
| 309 | 309 | pagename = pagename.rstrip('/') |
| | 310 | if formatter.resource and formatter.resource.realm == 'wiki' \ |
| | 311 | and not pagename.startswith('/'): |
| | 312 | prefix = formatter.resource.id |
| | 313 | if '/' in prefix: |
| | 314 | while '/' in prefix: |
| | 315 | prefix = prefix.rsplit('/', 1)[0] |
| | 316 | name = prefix + '/' + pagename |
| | 317 | if self.has_page(name): |
| | 318 | pagename = name |
| | 319 | break |
| | 320 | else: |
| | 321 | if not self.has_page(pagename): |
| | 322 | pagename = formatter.resource.id.rsplit('/', 1)[0] \ |
| | 323 | + '/' + pagename |
| | 324 | pagename = pagename.lstrip('/') |
| 310 | 325 | if 'WIKI_VIEW' in formatter.perm('wiki', pagename, version): |
| 311 | 326 | href = formatter.href.wiki(pagename, version=version) + query \ |
| 312 | 327 | + fragment |
diff --git a/trac/wiki/templates/wiki_view.html b/trac/wiki/templates/wiki_view.html
|
a
|
b
|
|
| 44 | 44 | ${wiki_to_html(context, page.text)} |
| 45 | 45 | </py:when> |
| 46 | 46 | <py:otherwise> |
| 47 | | Describe ${name_of(page.resource)} here. |
| | 47 | <p>Describe ${name_of(page.resource)} here.</p> |
| | 48 | <py:if test="'/' in page.name" py:with="parts = page.name.split('/')"> |
| | 49 | <p>Alternatively, you can also create the page higher in the hierarchy:</p> |
| | 50 | <ul> |
| | 51 | <li py:for="i in range(len(parts) - 2, -1, -1)" |
| | 52 | py:with="name = '/'.join(parts[:i] + [parts[-1]]); has_perm = 'WIKI_VIEW' in perm('wiki', name)"> |
| | 53 | <a href="${href.wiki(name)}" class="${has_perm and 'missing' or 'forbidden'} wiki" rel="nofollow" |
| | 54 | title="${not has_perm and _('no permission to view this wiki page') or None}">${name}?</a> |
| | 55 | </li> |
| | 56 | </ul> |
| | 57 | </py:if> |
| 48 | 58 | </py:otherwise> |
| 49 | 59 | </div> |
| 50 | 60 | |
diff --git a/trac/wiki/tests/wikisyntax.py b/trac/wiki/tests/wikisyntax.py
|
a
|
b
|
|
| 319 | 319 | ------------------------------ |
| 320 | 320 | """ # " |
| 321 | 321 | |
| | 322 | SCOPED_LINKS_TESTS=u""" |
| | 323 | ============================== Scoped links for hierarchical pages |
| | 324 | ThirdLevel |
| | 325 | [wiki:ThirdLevel] |
| | 326 | OtherThirdLevel |
| | 327 | [wiki:OtherThirdLevel] |
| | 328 | SecondLevel |
| | 329 | [wiki:SecondLevel] |
| | 330 | FirstLevel |
| | 331 | [wiki:FirstLevel] |
| | 332 | TestPage |
| | 333 | [wiki:TestPage] |
| | 334 | MissingPage |
| | 335 | [wiki:MissingPage] |
| | 336 | ["/OtherThirdLevel"] |
| | 337 | [wiki:/OtherThirdLevel] |
| | 338 | ------------------------------ |
| | 339 | <p> |
| | 340 | <a class="wiki" href="/wiki/FirstLevel/SecondLevel/ThirdLevel">ThirdLevel</a> |
| | 341 | <a class="wiki" href="/wiki/FirstLevel/SecondLevel/ThirdLevel">ThirdLevel</a> |
| | 342 | <a class="wiki" href="/wiki/FirstLevel/SecondLevel/OtherThirdLevel">OtherThirdLevel</a> |
| | 343 | <a class="wiki" href="/wiki/FirstLevel/SecondLevel/OtherThirdLevel">OtherThirdLevel</a> |
| | 344 | <a class="wiki" href="/wiki/FirstLevel/SecondLevel">SecondLevel</a> |
| | 345 | <a class="wiki" href="/wiki/FirstLevel/SecondLevel">SecondLevel</a> |
| | 346 | <a class="wiki" href="/wiki/FirstLevel">FirstLevel</a> |
| | 347 | <a class="wiki" href="/wiki/FirstLevel">FirstLevel</a> |
| | 348 | <a class="wiki" href="/wiki/TestPage">TestPage</a> |
| | 349 | <a class="wiki" href="/wiki/TestPage">TestPage</a> |
| | 350 | <a class="missing wiki" href="/wiki/FirstLevel/SecondLevel/MissingPage" rel="nofollow">MissingPage?</a> |
| | 351 | <a class="missing wiki" href="/wiki/FirstLevel/SecondLevel/MissingPage" rel="nofollow">MissingPage?</a> |
| | 352 | <a class="missing wiki" href="/wiki/OtherThirdLevel" rel="nofollow">/OtherThirdLevel?</a> |
| | 353 | <a class="missing wiki" href="/wiki/OtherThirdLevel" rel="nofollow">/OtherThirdLevel?</a> |
| | 354 | </p> |
| | 355 | ------------------------------ |
| | 356 | """ # " |
| 322 | 357 | |
| 323 | 358 | def wiki_setup(tc): |
| 324 | 359 | now = datetime.now(utc) |
| … |
… |
|
| 354 | 389 | """ |
| 355 | 390 | imt.save('joe', 'test InterWiki links', '::1', now) |
| 356 | 391 | |
| | 392 | w = WikiPage(tc.env) |
| | 393 | w.name = 'FirstLevel' |
| | 394 | w.text = '--' |
| | 395 | w.save('joe', 'first level of hierarchy', '::1', now) |
| | 396 | |
| | 397 | w = WikiPage(tc.env) |
| | 398 | w.name = 'FirstLevel/SecondLevel' |
| | 399 | w.text = '--' |
| | 400 | w.save('joe', 'second level of hierarchy', '::1', now) |
| | 401 | |
| | 402 | w = WikiPage(tc.env) |
| | 403 | w.name = 'FirstLevel/SecondLevel/ThirdLevel' |
| | 404 | w.text = '--' |
| | 405 | w.save('joe', 'third level of hierarchy', '::1', now) |
| | 406 | |
| | 407 | w = WikiPage(tc.env) |
| | 408 | w.name = 'FirstLevel/SecondLevel/OtherThirdLevel' |
| | 409 | w.text = '--' |
| | 410 | w.save('joe', 'other third level of hierarchy', '::1', now) |
| | 411 | |
| 357 | 412 | |
| 358 | 413 | def suite(): |
| 359 | 414 | suite = unittest.TestSuite() |
| 360 | 415 | suite.addTest(formatter.suite(TEST_CASES, wiki_setup, __file__)) |
| 361 | 416 | suite.addTest(formatter.suite(RELATIVE_LINKS_TESTS, wiki_setup, __file__, |
| 362 | 417 | context=('wiki', 'Main/Sub'))) |
| | 418 | suite.addTest(formatter.suite(SCOPED_LINKS_TESTS, wiki_setup, __file__, |
| | 419 | context=('wiki', |
| | 420 | 'FirstLevel/SecondLevel/ThirdLevel'))) |
| 363 | 421 | return suite |
| 364 | 422 | |
| 365 | 423 | if __name__ == '__main__': |