449 | | === Conversion example |
450 | | |
451 | | Here we detail the conversion process of a sample Genshi template ([source:tags/trac-1.0.9/trac/wiki/templates/wiki_view.html wiki_view.html]) into the corresponding Jinja2 template ([source:cboos.git/trac/wiki/templates/jwiki_view.html jwiki_view.html]). |
452 | | |
453 | | As will become apparent, we mainly use [http://jinja.pocoo.org/docs/dev/templates/#line-statements line statements] for the Jinja2 control structures. |
454 | | Note that we have reformatted the Genshi template to use shorter line widths, so that both columns of the table below stay visible (a wide screen also helps). |
455 | | |
456 | | {{{#!th style="max-width: 200px" |
457 | | wiki_view.html (Genshi template) |
458 | | }}} |
459 | | {{{#!th style="max-width: 200px" |
460 | | jwiki_view.html (Jinja2 template) |
461 | | }}} |
462 | | |------ |
463 | | ||= ||= || |
464 | | {{{#!td |
465 | | {{{#!html+genshi |
466 | | <!--! Copyright (C) 2006-2014 Edgewall Software |
467 | | |
468 | | This software is licensed as described in the file COPYING, which |
469 | | you should have received as part of this distribution. The terms |
470 | | are also available at http://trac.edgewall.com/license.html. |
471 | | |
472 | | This software consists of voluntary contributions made by many |
473 | | individuals. For the exact contribution history, see the revision |
474 | | history and logs, available at http://trac.edgewall.org/. |
475 | | --> |
476 | | }}} |
477 | | }}} |
478 | | {{{#!td |
479 | | {{{#!html+jinja |
480 | | {# Copyright (C) 2006-2014 Edgewall Software |
481 | | |
482 | | This software is licensed as described in the file COPYING, which |
483 | | you should have received as part of this distribution. The terms |
484 | | are also available at http://trac.edgewall.com/license.html. |
485 | | |
486 | | This software consists of voluntary contributions made by many |
487 | | individuals. For the exact contribution history, see the revision |
488 | | history and logs, available at http://trac.edgewall.org/. |
489 | | #} |
490 | | }}} |
491 | | }}} |
492 | | |----------------------------------------------------------------------------- |
493 | | |||| Block comments || |
494 | | |----------------------------------------------------------------------------- |
495 | | {{{#!td |
496 | | {{{#!html+genshi |
497 | | }}} |
498 | | }}} |
499 | | {{{#!td |
500 | | {{{#!html+jinja |
501 | | # extends "jlayout.html" |
502 | | }}} |
503 | | }}} |
504 | | |----------------------------------------------------------------------------- |
505 | | |||| This is the equivalent of Genshi's `<py:include href="layout.html" />`. We have to do the extends before outputing any content on our own, otherwise it would show up in the final result. Once we made the `extends`, only the content written within //blocks// will matter. || |
506 | | |----------------------------------------------------------------------------- |
507 | | {{{#!td |
508 | | {{{#!html+genshi |
509 | | <!DOCTYPE html |
510 | | PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
511 | | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
512 | | }}} |
513 | | }}} |
514 | | {{{#!td |
515 | | {{{#!html+jinja |
516 | | <!DOCTYPE html> |
517 | | }}} |
518 | | }}} |
519 | | |----------------------------------------------------------------------------- |
520 | | |||| Let's directly make the jump to HTML5, while we're at it (I'm not sure what is the current state of the HTML5 support in Genshi, but it no longer matters) || |
521 | | |----------------------------------------------------------------------------- |
522 | | {{{#!td |
523 | | {{{#!html+genshi |
524 | | <html xmlns="http://www.w3.org/1999/xhtml" |
525 | | xmlns:py="http://genshi.edgewall.org/" |
526 | | xmlns:i18n="http://genshi.edgewall.org/i18n" |
527 | | xmlns:xi="http://www.w3.org/2001/XInclude" |
528 | | py:with="modify_perm = 'WIKI_MODIFY' in perm(page.resource); |
529 | | create_perm = 'WIKI_CREATE' in perm(page.resource); |
530 | | admin_perm = 'WIKI_ADMIN' in perm(page.resource); |
531 | | is_not_latest = page.exists and page.version != latest_version"> |
532 | | }}} |
533 | | }}} |
534 | | {{{#!td |
535 | | {{{#!html+jinja |
536 | | <html> |
537 | | |
538 | | }}} |
539 | | }}} |
540 | | |----------------------------------------------------------------------------- |
541 | | {{{#!td |
542 | | No need for exotic namespace declarations. |
543 | | |
544 | | Note that we can't use a `with` declaration that would encompass the ''head'' and ''content'' blocks we'll define in a moment, as this would force the generation of content twice, once by having the with block present in the template, and a second time because of the extends and the call of the blocks. |
545 | | }}} |
546 | | |----------------------------------------------------------------------------- |
547 | | {{{#!td |
548 | | {{{#!html+genshi |
549 | | <xi:include href="layout.html" /> |
550 | | }}} |
551 | | }}} |
552 | | {{{#!td |
553 | | {{{#!html+jinja |
554 | | }}} |
555 | | }}} |
556 | | |----------------------------------------------------------------------------- |
557 | | |||| See above, this will be converted to an initial `extends` statement. || |
558 | | |----------------------------------------------------------------------------- |
559 | | {{{#!td |
560 | | {{{#!html+genshi |
561 | | <head> |
562 | | <title py:if="title">$title</title> |
563 | | }}} |
564 | | }}} |
565 | | {{{#!td |
566 | | {{{#!html+jinja |
567 | | <head> |
568 | | <title> |
569 | | # block title |
570 | | # if title: |
571 | | ${title} ${ super() } |
572 | | # endif |
573 | | # endblock title |
574 | | </title> |
575 | | |
576 | | # block head |
577 | | # set modify_perm = 'WIKI_MODIFY' in perm(page.resource) |
578 | | # set is_not_latest = page.exists and page.version != latest_version |
579 | | |
580 | | ${ super() } |
581 | | }}} |
582 | | }}} |
583 | | |----------------------------------------------------------------------------- |
584 | | {{{#!td colspan=2 |
585 | | The content of the <title> element is placed in the ''title'' block, |
586 | | followed by the content of the parent ''title'' block (`${ super() }`). |
587 | | When closing the block, we reuse the name of the block. |
588 | | |
589 | | Note that while the only thing that really matters in an extending template |
590 | | is the content of the blocks, we try hard to keep a correct HTML structure |
591 | | for the whole template page, so that its HTML content can be validated in a |
592 | | standalone way (cf. [#jinjachecker]). This is why we add the <html>, <head> and |
593 | | <title> tags. |
594 | | |
595 | | We explained earlier why the title block has to be outside of the ''head'' block: |
596 | | to avoid appearing twice, once as part of the head block, and the second time |
597 | | when we call `${ super() }` in order to retrieve the content of the parent ''head'' |
598 | | block. |
599 | | |
600 | | Finally, we define some variables at the beginning of the block (corresponding to |
601 | | some which were part of the `py:with` attribute in the `<html>` tag, in the Genshi |
602 | | template). |
603 | | }}} |
604 | | |----------------------------------------------------------------------------- |
605 | | {{{#!td |
606 | | {{{#!html+genshi |
607 | | <meta py:if="version or page.author == 'trac'" |
608 | | name="ROBOTS" content="NOINDEX, NOFOLLOW" /> |
609 | | <link py:if="modify_perm" rel="alternate" |
610 | | type="application/x-wiki" |
611 | | href="${href.wiki(page.name, action='edit', |
612 | | version=page.version if is_not_latest else None)}" |
613 | | title="${_('Revert page to this version') if |
614 | | is_not_latest else _('Edit this page')}"/> |
615 | | }}} |
616 | | }}} |
617 | | {{{#!td |
618 | | {{{#!html+jinja |
619 | | # if version or page.author == 'trac': |
620 | | <meta name="ROBOTS" content="NOINDEX, NOFOLLOW" /> |
621 | | # endif |
622 | | # if modify_perm: |
623 | | <link rel="alternate" type="application/x-wiki" |
624 | | href="${href.wiki(page.name, action='edit', |
625 | | version=page.version if is_not_latest)}" |
626 | | title="${_("Revert page to this version") if is_not_latest else |
627 | | _("Edit this page")}"/> |
628 | | # endif |
629 | | }}} |
630 | | }}} |
631 | | |----------------------------------------------------------------------------- |
632 | | |||| With Jinja2, the logic is now clearly distinct from the content. || |
633 | | |----------------------------------------------------------------------------- |
634 | | {{{#!td |
635 | | {{{#!html+genshi |
636 | | <script type="text/javascript"> |
637 | | jQuery(document).ready(function($) { |
638 | | $("#content").find("h1,h2,h3,h4,h5,h6") |
639 | | .addAnchor(_("Link to this section")); |
640 | | $("#content").find(".wikianchor").each(function() { |
641 | | $(this).addAnchor(babel.format(_("Link to #%(id)s"), |
642 | | {id: $(this).attr('id')})); |
643 | | }); |
644 | | $(".foldable").enableFolding(true, true); |
645 | | }); |
646 | | </script> |
647 | | }}} |
648 | | }}} |
649 | | {{{#!td |
650 | | {{{#!html+jinja |
651 | | <script type="text/javascript"> |
652 | | jQuery(document).ready(function($) { |
653 | | $("#content").find("h1,h2,h3,h4,h5,h6") |
654 | | .addAnchor(_("Link to this section")); |
655 | | $("#content").find(".wikianchor").each(function() { |
656 | | $(this).addAnchor(babel.format(_("Link to #%(id)s"), { |
657 | | id: $(this).attr('id')})); |
658 | | }); |
659 | | $(".foldable").enableFolding(true, true); |
660 | | }); |
661 | | </script> |
662 | | }}} |
663 | | }}} |
664 | | |----------------------------------------------------------------------------- |
665 | | |||| No changes here, except for some reformatting (we try to stay below 80 chars for nicer future side-by-side diffs). || |
666 | | |----------------------------------------------------------------------------- |
667 | | {{{#!td |
668 | | {{{#!html+genshi |
669 | | </head> |
670 | | |
671 | | }}} |
672 | | }}} |
673 | | {{{#!td |
674 | | {{{#!html+jinja |
675 | | # endblock head |
676 | | </head> |
677 | | |
678 | | }}} |
679 | | }}} |
680 | | |----------------------------------------------------------------------------- |
681 | | |||| We close the ''head'' block. || |
682 | | |----------------------------------------------------------------------------- |
683 | | {{{#!td |
684 | | {{{#!html+genshi |
685 | | <body> |
686 | | <div id="content" class="${classes('wiki', create=not page.exists)}"> |
687 | | |
688 | | }}} |
689 | | }}} |
690 | | {{{#!td |
691 | | {{{#!html+jinja |
692 | | <body> |
693 | | # block content |
694 | | # set modify_perm = 'WIKI_MODIFY' in perm(page.resource) |
695 | | # set create_perm = 'WIKI_CREATE' in perm(page.resource) |
696 | | # set admin_perm = 'WIKI_ADMIN' in perm(page.resource) |
697 | | # set is_not_latest = page.exists and page.version != latest_version |
698 | | |
699 | | <div id="content" class="${classes('wiki', create=not page.exists)}"> |
700 | | |
701 | | }}} |
702 | | }}} |
703 | | |----------------------------------------------------------------------------- |
704 | | |||| We start the ''content'' block. As before with the ''header'' block, we define some variables at the beginning of the block. || |
705 | | |----------------------------------------------------------------------------- |
706 | | {{{#!td |
707 | | {{{#!html+genshi |
708 | | <py:if test="version"> |
709 | | <br /> |
710 | | <table id="info" summary="Revision info"> |
711 | | <tr><th scope="row" i18n:msg="version, author, date"> |
712 | | Version $page.version (modified by ${authorinfo(page.author)}, |
713 | | ${pretty_dateinfo(page.time)}) |
714 | | (<a href="${href.wiki(page.name, action='diff', |
715 | | version=page.version)}">diff</a>) |
716 | | </th></tr> |
717 | | <tr><td class="message" xml:space="preserve"> |
718 | | ${wiki_to_html(context, page.comment or '--')} |
719 | | </td></tr> |
720 | | </table> |
721 | | </py:if> |
722 | | }}} |
723 | | }}} |
724 | | {{{#!td |
725 | | {{{#!html+jinja |
726 | | # if version: |
727 | | <br /> |
728 | | <table id="info" summary="${_("Revision info")}"> |
729 | | <tr><th scope="row"> |
730 | | # with |
731 | | # set version = page.version |
732 | | # set author = authorinfo(page.author) |
733 | | # set date = pretty_dateinfo(page.time) |
734 | | # set hef = href.wiki(page.name, action='diff', version=page.version) |
735 | | # trans version, author, date, href |
736 | | |
737 | | Version ${version} (modified by ${author}, ${date}) |
738 | | (<a href="${href}">diff</a>) |
739 | | |
740 | | # endtrans |
741 | | # endwith |
742 | | </th></tr> |
743 | | <tr><td class="message"> |
744 | | ${wiki_to_html(context, page.comment or '--')} |
745 | | </td></tr> |
746 | | </table> |
747 | | # endif |
748 | | |
749 | | }}} |
750 | | }}} |
751 | | |----------------------------------------------------------------------------- |
752 | | {{{#!td colspan=2 |
753 | | Here we illustrate the i18n changes. |
754 | | |
755 | | First, any sentence that corresponds to visible end-user text that should be |
756 | | translated has to be marked somehow. |
757 | | |
758 | | One way is to use the standard i18n calls, |
759 | | `_`, `ngettext()`, etc. |
760 | | |
761 | | The other way is to use `trans` blocks. |
762 | | There are two big differences with their Genshi i18n equivalent: |
763 | | - variable substitutions can only be those of direct variables, |
764 | | no kind of expression is allowed, even as simple as attribute |
765 | | lookup |
766 | | - Jinja2, markup neutral as it is, will not do any substitutions |
767 | | on the markup found in a trans block; what would have ended |
768 | | in a Genshi bracketed expression `... [1:diff]` in the catalogs |
769 | | will now remain HTML markup: `... <a href="${href}">diff</a>`. |
770 | | Note that one can use a `with` statement for breaking up the |
771 | | assignments needed on multiple separate lines. |
772 | | Smaller lists of variables can be placed on the `trans` line directly. |
773 | | }}} |
774 | | |----------------------------------------------------------------------------- |
775 | | {{{#!td |
776 | | {{{#!html+genshi |
777 | | <div class="wikipage searchable" py:choose="" xml:space="preserve"> |
778 | | <py:when test="page.exists"> |
779 | | <div id="wikipage" class="trac-content" |
780 | | py:content="wiki_to_html(context, text)" /> |
781 | | <?python |
782 | | last_modification = (page.comment and |
783 | | _('Version %(version)s by %(author)s: %(comment)s', |
784 | | version=page.version, author=format_author(page.author), |
785 | | comment=page.comment) or |
786 | | _('Version %(version)s by %(author)s', |
787 | | version=page.version, author=format_author(page.author))) |
788 | | ?> |
789 | | <div py:if="not version" class="trac-modifiedby"> |
790 | | <span i18n:msg="reldate"> |
791 | | <a href="${href.wiki(page.name, action='diff', |
792 | | version=page.version)}" |
793 | | title="$last_modification">Last modified</a> |
794 | | ${pretty_dateinfo(page.time)} |
795 | | </span> |
796 | | <span class="trac-print" i18n:msg="date">Last modified on |
797 | | ${format_datetime(page.time)}</span> |
798 | | </div> |
799 | | </py:when> |
800 | | <py:otherwise> |
801 | | <p i18n:msg="name">The page <strong>${name_of(page.resource)}</strong> |
802 | | does not exist. You can create it here.</p> |
803 | | </py:otherwise> |
804 | | </div> |
805 | | }}} |
806 | | }}} |
807 | | {{{#!td |
808 | | {{{#!html+jinja |
809 | | <div class="wikipage searchable"> |
810 | | # if page.exists: |
811 | | <div id="wikipage" class="trac-content">${ |
812 | | wiki_to_html(context, text) |
813 | | }</div> |
814 | | # set last_modification = (page.comment and |
815 | | _('Version %(version)s by %(author)s: %(comment)s', |
816 | | version=page.version, author=format_author(page.author), |
817 | | comment=page.comment) or |
818 | | _('Version %(version)s by %(author)s', |
819 | | version=page.version, author=format_author(page.author))) |
820 | | # if not version: |
821 | | <div class="trac-modifiedby"> |
822 | | <span> |
823 | | # with |
824 | | # set href = href.wiki(page.name, action='diff', |
825 | | version=page.version), |
826 | | # set date = pretty_dateinfo(page.time) |
827 | | # trans href, last_modification, date |
828 | | |
829 | | <a href="${href}" |
830 | | title="${last_modification}">Last modified</a> ${date} |
831 | | |
832 | | # endtrans |
833 | | # endwith |
834 | | </span> |
835 | | <span class="trac-print"> |
836 | | ${_("Last modified on %(date)s", date=format_datetime(page.time))} |
837 | | </span> |
838 | | </div> |
839 | | # endif |
840 | | # else: |
841 | | <p> |
842 | | # trans name = name_of(page.resource) |
843 | | |
844 | | The page <strong>${name}</strong> does not exist. |
845 | | You can create it here. |
846 | | |
847 | | # endtrans |
848 | | </p> |
849 | | # endif |
850 | | </div> |
851 | | }}} |
852 | | }}} |
853 | | |----------------------------------------------------------------------------- |
854 | | |||| || |
855 | | |----------------------------------------------------------------------------- |
856 | | {{{#!td |
857 | | {{{#!html+genshi |
858 | | <xi:include href="list_of_attachments.html" |
859 | | py:with="alist = attachments; compact = True; |
860 | | foldable = True"/> |
861 | | }}} |
862 | | }}} |
863 | | {{{#!td |
864 | | {{{#!html+jinja |
865 | | # with |
866 | | # set alist = attachments |
867 | | # set compact = True |
868 | | # set foldable = True |
869 | | # include "jlist_of_attachments.html" |
870 | | # endwith |
871 | | }}} |
872 | | }}} |
873 | | |----------------------------------------------------------------------------- |
874 | | |||| Jinja2 includes also know about their context, so that make them kind of parametric. || |
875 | | |----------------------------------------------------------------------------- |
876 | | {{{#!td |
877 | | {{{#!html+genshi |
878 | | <py:with vars="delete_perm = 'WIKI_DELETE' in perm(page.resource); |
879 | | rename_perm = 'WIKI_RENAME' in perm(page.resource)"> |
880 | | <py:if test="modify_perm or create_perm or delete_perm"> |
881 | | <div class="buttons"> |
882 | | <py:if test="modify_perm or create_perm"> |
883 | | }}} |
884 | | }}} |
885 | | {{{#!td |
886 | | {{{#!html+jinja |
887 | | # with |
888 | | # set delete_perm = 'WIKI_DELETE' in perm(page.resource) |
889 | | # set rename_perm = 'WIKI_RENAME' in perm(page.resource) |
890 | | # if modify_perm or create_perm or delete_perm: |
891 | | <div class="buttons"> |
892 | | # if modify_perm or create_perm: |
893 | | }}} |
894 | | }}} |
895 | | |----------------------------------------------------------------------------- |
896 | | |||| Again, even when there's a lot of control lines, it's a bit easier to immediately spot the actual content in Jinja2 templates, due to the clearer syntactic difference. || |
897 | | |----------------------------------------------------------------------------- |
898 | | {{{#!td |
899 | | {{{#!html+genshi |
900 | | <form method="get" action="${href.wiki(page.name)}" id="modifypage"> |
901 | | <div> |
902 | | <input type="hidden" name="action" value="edit" /> |
903 | | <py:choose> |
904 | | <py:when test="is_not_latest and modify_perm"> |
905 | | <input type="hidden" name="version" value="${page.version}"/> |
906 | | <input type="submit" value="${_('Revert to this version')}"/> |
907 | | </py:when> |
908 | | <py:when test="page.exists and modify_perm"> |
909 | | <input type="submit" value="${_('Edit this page')}" |
910 | | accesskey="e" /> |
911 | | </py:when> |
912 | | <py:when test="not page.exists and create_perm"> |
913 | | <input type="submit" value="${_('Create this page')}" |
914 | | accesskey="e" /> |
915 | | <div py:if="templates" id="template"> |
916 | | <label for="template">using the template:</label> |
917 | | <select name="template"> |
918 | | <option selected="${not default_template in templates |
919 | | or None}" |
920 | | value="">(blank page)</option> |
921 | | <option py:for="t in sorted(templates)" value="$t" |
922 | | selected="${t == default_template or None}" |
923 | | >$t</option> |
924 | | </select> |
925 | | </div> |
926 | | </py:when> |
927 | | </py:choose> |
928 | | </div> |
929 | | </form> |
930 | | }}} |
931 | | }}} |
932 | | {{{#!td |
933 | | {{{#!html+jinja |
934 | | <form method="get" action="${href.wiki(page.name)}" id="modifypage"> |
935 | | <div> |
936 | | <input type="hidden" name="action" value="edit" /> |
937 | | # if is_not_latest and modify_perm: |
938 | | <input type="hidden" name="version" value="${page.version}"/> |
939 | | <input type="submit" value="${_('Revert to this version')}"/> |
940 | | # elif page.exists and modify_perm: |
941 | | <input type="submit" value="${_('Edit this page')}" |
942 | | accesskey="e" /> |
943 | | # elif not page.exists and create_perm: |
944 | | <input type="submit" value="${_('Create this page')}" |
945 | | accesskey="e" /> |
946 | | # if templates: |
947 | | <div id="template"> |
948 | | <label for="template">${_("using the template:")}</label> |
949 | | <select name="template"> |
950 | | <option ${{'selected': not default_template in templates |
951 | | }|htmlattr} |
952 | | value="">${_("(blank page)")}</option> |
953 | | # for t in sorted(templates): |
954 | | <option value="${t}" |
955 | | ${{'selected': t == default_template |
956 | | }|htmlattr}>${t}</option> |
957 | | # endfor |
958 | | </select> |
959 | | </div> |
960 | | # endif |
961 | | # endif |
962 | | </div> |
963 | | </form> |
964 | | |
965 | | }}} |
966 | | }}} |
967 | | |----------------------------------------------------------------------------- |
968 | | {{{#!td |
969 | | A `<py:choose>` and its series of `<py:when>` translates very smoothly into a sequence of `if / elif` statements. |
970 | | |
971 | | Special care should be taken when producing attributes dynamically, as it's the |
972 | | case here for `selected`. We use the `htmlattr` filter that takes care of |
973 | | producing the right value for the attribute depending on its content: with |
974 | | a truth value, we'll output `selected="selected"` otherwise we'll just omit |
975 | | the parameter. |
976 | | }}} |
977 | | |----------------------------------------------------------------------------- |
978 | | |||| || |
979 | | |----------------------------------------------------------------------------- |
980 | | {{{#!td |
981 | | {{{#!html+genshi |
982 | | <py:if test="page.exists"> |
983 | | <xi:include href="attach_file_form.html" |
984 | | py:with="alist = attachments"/> |
985 | | </py:if> |
986 | | </py:if> |
987 | | }}} |
988 | | }}} |
989 | | {{{#!td |
990 | | {{{#!html+jinja |
991 | | # if page.exists: |
992 | | # with alist = attachments |
993 | | # include "jattach_file_form.html" |
994 | | # endwith |
995 | | # endif |
996 | | # endif |
997 | | }}} |
998 | | }}} |
999 | | |----------------------------------------------------------------------------- |
1000 | | |||| We pass `attachments` as `alist` to the included template (a `j...` template, obviously). || |
1001 | | |----------------------------------------------------------------------------- |
1002 | | {{{#!td |
1003 | | {{{#!html+genshi |
1004 | | <form method="get" action="${href.wiki(page.name)}" |
1005 | | id="rename" py:if="page.exists and rename_perm"> |
1006 | | <div> |
1007 | | <input type="hidden" name="action" value="rename" /> |
1008 | | <input type="submit" value="${_('Rename page')}" /> |
1009 | | </div> |
1010 | | </form> |
1011 | | <form method="get" action="${href.wiki(page.name)}" |
1012 | | id="delete" py:if="page.exists and delete_perm"> |
1013 | | <div> |
1014 | | <input type="hidden" name="action" value="delete" /> |
1015 | | <input type="hidden" name="version" value="$page.version" /> |
1016 | | <py:if test="page.version == latest_version"> |
1017 | | <input type="submit" name="delete_version" |
1018 | | value="${_('Delete this version')}" /> |
1019 | | </py:if> |
1020 | | <input type="submit" value="${_('Delete page')}" /> |
1021 | | </div> |
1022 | | </form> |
1023 | | </div> |
1024 | | </py:if> |
1025 | | </py:with> |
1026 | | }}} |
1027 | | }}} |
1028 | | {{{#!td |
1029 | | {{{#!html+jinja |
1030 | | # if page.exists and rename_perm: |
1031 | | <form method="get" action="${href.wiki(page.name)}" id="rename"> |
1032 | | <div> |
1033 | | <input type="hidden" name="action" value="rename" /> |
1034 | | <input type="submit" value="${_('Rename page')}" /> |
1035 | | </div> |
1036 | | </form> |
1037 | | # endif |
1038 | | # if page.exists and delete_perm: |
1039 | | <form method="get" action="${href.wiki(page.name)}" id="delete"> |
1040 | | <div> |
1041 | | <input type="hidden" name="action" value="delete" /> |
1042 | | <input type="hidden" name="version" value="${page.version}" /> |
1043 | | # if page.version == latest_version: |
1044 | | <input type="submit" name="delete_version" value="${_('Delete this version')}" /> |
1045 | | # endif |
1046 | | <input type="submit" value="${_('Delete page')}" /> |
1047 | | </div> |
1048 | | </form> |
1049 | | # endif |
1050 | | </div> |
1051 | | # endif |
1052 | | # endwith |
1053 | | |
1054 | | }}} |
1055 | | }}} |
1056 | | |----------------------------------------------------------------------------- |
1057 | | |||| || |
1058 | | |----------------------------------------------------------------------------- |
1059 | | {{{#!td |
1060 | | {{{#!html+genshi |
1061 | | <div class="wikipage searchable" py:if="not page.exists and higher"> |
1062 | | <p>You could also create the same page higher in the hierarchy:</p> |
1063 | | <ul> |
1064 | | <li py:for="markup in higher">${markup}</li> |
1065 | | </ul> |
1066 | | </div> |
1067 | | }}} |
1068 | | }}} |
1069 | | {{{#!td |
1070 | | {{{#!html+jinja |
1071 | | # if not page.exists and higher: |
1072 | | <div class="wikipage searchable"> |
1073 | | <p>You could also create the same page higher in the hierarchy:</p> |
1074 | | <ul> |
1075 | | # for markup in higher: |
1076 | | <li>${markup}</li> |
1077 | | # endfor |
1078 | | </ul> |
1079 | | </div> |
1080 | | # endif |
1081 | | |
1082 | | }}} |
1083 | | }}} |
1084 | | |----------------------------------------------------------------------------- |
1085 | | |||| Here's the first use of the `for` statement. Straightforward. || |
1086 | | |----------------------------------------------------------------------------- |
1087 | | {{{#!td |
1088 | | {{{#!html+genshi |
1089 | | <div class="wikipage searchable" py:if="not page.exists and related"> |
1090 | | <p>The following pages have a name similar to this page, |
1091 | | and may be related:</p> |
1092 | | <ul> |
1093 | | <li py:for="markup in related">${markup}</li> |
1094 | | </ul> |
1095 | | </div> |
1096 | | }}} |
1097 | | }}} |
1098 | | {{{#!td |
1099 | | {{{#!html+jinja |
1100 | | # if not page.exists and related: |
1101 | | <div class="wikipage searchable"> |
1102 | | <p>${_("The following pages have a name similar to this page, and may be related:")}</p> |
1103 | | <ul> |
1104 | | # for markup in related: |
1105 | | <li>${markup}</li> |
1106 | | # endif |
1107 | | </ul> |
1108 | | </div> |
1109 | | # endif |
1110 | | }}} |
1111 | | }}} |
1112 | | |----------------------------------------------------------------------------- |
1113 | | |||| || |
1114 | | |----------------------------------------------------------------------------- |
1115 | | {{{#!td |
1116 | | {{{#!html+genshi |
1117 | | </div> |
1118 | | </body> |
1119 | | </html> |
1120 | | }}} |
1121 | | }}} |
1122 | | {{{#!td |
1123 | | {{{#!html+jinja |
1124 | | </div> |
1125 | | |
1126 | | ${ super() } |
1127 | | |
1128 | | # endblock content |
1129 | | </body> |
1130 | | </html> |
1131 | | }}} |
1132 | | }}} |
1133 | | |----------------------------------------------------------------------------- |
1134 | | |||| Once we're done with the `<div id="content">`, we also call `${ super() }` to re-insert the parent content of the ''content'' block, i.e. the altlinks div and the late_links/late_scripts logic. || |
1135 | | |----------------------------------------------------------------------------- |
| 449 | See also PortingFromGenshiToJinja/Example for a full example presented side-by-side. |